From: Nick Porter Date: Fri, 8 Mar 2024 13:53:05 +0000 (+0000) Subject: Use linelog for auth logging in TACACS X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d55a660b2ce4b863979a520170440ffd27488513;p=thirdparty%2Ffreeradius-server.git Use linelog for auth logging in TACACS --- diff --git a/doc/antora/modules/raddb/pages/sites-available/tacacs.adoc b/doc/antora/modules/raddb/pages/sites-available/tacacs.adoc index d4110efabdb..cd9d28a3c6f 100644 --- a/doc/antora/modules/raddb/pages/sites-available/tacacs.adoc +++ b/doc/antora/modules/raddb/pages/sites-available/tacacs.adoc @@ -33,54 +33,6 @@ packets. At this time, there is no configuration needed for other packet types. -log:: Logging configuration for TACACS+ authentication - - -stripped_names:: Log the full -`link:https://freeradius.org/rfc/rfc2865.html#User-Name[User-Name]` attribute, as it was -found in the request. - -allowed values: {no, yes} - - - -auth:: Log authentication requests -to the log file. - -allowed values: {no, yes} - - - -auth_goodpass:: Log "good" -passwords with the authentication -requests. - -allowed values: {no, yes} - - - -auth_badpass:: Log "bad" -passwords with the authentication -requests. - -allowed values: {no, yes} - - - -msg_goodpass:: -msg_badpass:: - -Log additional text at the end of the "Login OK" messages. -for these to work, the "auth" and "auth_goodpass" or "auth_badpass" -configurations above have to be set to "yes". - -The strings below are dynamically expanded, which means that -you can put anything you want in them. However, note that -this expansion can be slow, and can negatively impact server -performance. - - - session:: Controls how ongoing (multi-round) sessions are handled @@ -331,14 +283,6 @@ server tacacs { namespace = tacacs tacacs { Authentication { - log { - stripped_names = no - auth = no - auth_goodpass = no - auth_badpass = no -# msg_goodpass = "" -# msg_badpass = "" - } session { # max = 4096 max_rounds = 4 diff --git a/raddb/mods-available/linelog b/raddb/mods-available/linelog index 453427db1f0..e28a70d50e7 100644 --- a/raddb/mods-available/linelog +++ b/raddb/mods-available/linelog @@ -452,3 +452,30 @@ linelog log_auth_access_reject { format = "Login incorrect (%{Module-Failure-Message}): [%{User-Name}] (from %client(shortname) port %{NAS-Port} cli %{Calling-Station-Id})" } + +linelog log_auth_authentication_pass { + destination = ${log.destination} + file { + filename = ${log.file} + } + syslog { + facility = ${log.syslog_facility} + severity = notice + } + + format = "Login OK: [%{User-Name}] (from client %client(shortname))" +} + + +linelog log_auth_authentication_fail { + destination = ${log.destination} + file { + filename = ${log.file} + } + syslog { + facility = ${log.syslog_facility} + severity = notice + } + + format = "Login incorrect (%{Module-Failure-Message}): [%{User-Name}] (from %client(shortname))" +} diff --git a/raddb/sites-available/tacacs b/raddb/sites-available/tacacs index b1ea4cd8d96..a0da50e22d2 100644 --- a/raddb/sites-available/tacacs +++ b/raddb/sites-available/tacacs @@ -42,62 +42,6 @@ server tacacs { # needed for other packet types. # Authentication { - # - # log:: Logging configuration for TACACS+ authentication - # - log { - # - # stripped_names:: Log the full - # `User-Name` attribute, as it was - # found in the request. - # - # allowed values: {no, yes} - # - stripped_names = no - - # - # auth:: Log authentication requests - # to the log file. - # - # allowed values: {no, yes} - # - auth = no - - # - # auth_goodpass:: Log "good" - # passwords with the authentication - # requests. - # - # allowed values: {no, yes} - # - auth_goodpass = no - - # - # auth_badpass:: Log "bad" - # passwords with the authentication - # requests. - # - # allowed values: {no, yes} - # - auth_badpass = no - - # - # msg_goodpass:: - # msg_badpass:: - # - # Log additional text at the end of the "Login OK" messages. - # for these to work, the "auth" and "auth_goodpass" or "auth_badpass" - # configurations above have to be set to "yes". - # - # The strings below are dynamically expanded, which means that - # you can put anything you want in them. However, note that - # this expansion can be slow, and can negatively impact server - # performance. - # -# msg_goodpass = "" -# msg_badpass = "" - } - # # session:: Controls how ongoing # (multi-round) sessions are handled @@ -332,10 +276,24 @@ server tacacs { # send Authentication-Pass { &reply.Server-Message := "Hello %{User-Name}" + + # + # Call an instance of `linelog` to log the authentication success + # - equivalent to the previous log `auth = yes` option in v3. + # See `mods-enabled/linelog` for message formats and destinations. + # +# log_auth_authentication_pass } send Authentication-Fail { &reply.Server-Message := "Failed login!" + + # + # Call an instance of `linelog` to log the authentication failure + # - equivalent to the previous log `auth = yes` option in v3. + # See `mods-enabled/linelog` for message formats and destinations. + # +# log_auth_authentication_fail } # diff --git a/src/process/tacacs/base.c b/src/process/tacacs/base.c index 4345951aca0..12a4b61e8ff 100644 --- a/src/process/tacacs/base.c +++ b/src/process/tacacs/base.c @@ -158,13 +158,6 @@ typedef struct { } process_tacacs_sections_t; typedef struct { - bool log_stripped_names; - bool log_auth; //!< Log authentication attempts. - bool log_auth_badpass; //!< Log failed authentications. - bool log_auth_goodpass; //!< Log successful authentications. - char const *auth_badpass_msg; //!< Additional text to append to failed auth messages. - char const *auth_goodpass_msg; //!< Additional text to append to successful auth messages. - fr_time_delta_t session_timeout; //!< Maximum time between the last response and next request. uint32_t max_session; //!< Maximum ongoing session allowed. @@ -212,20 +205,7 @@ static const conf_parser_t session_config[] = { CONF_PARSER_TERMINATOR }; -static const conf_parser_t log_config[] = { - { FR_CONF_OFFSET("stripped_names", process_tacacs_auth_t, log_stripped_names), .dflt = "no" }, - { FR_CONF_OFFSET("auth", process_tacacs_auth_t, log_auth), .dflt = "no" }, - { FR_CONF_OFFSET("auth_badpass", process_tacacs_auth_t, log_auth_badpass), .dflt = "no" }, - { FR_CONF_OFFSET("auth_goodpass", process_tacacs_auth_t, log_auth_goodpass), .dflt = "no" }, - { FR_CONF_OFFSET("msg_badpass", process_tacacs_auth_t, auth_badpass_msg) }, - { FR_CONF_OFFSET("msg_goodpass", process_tacacs_auth_t, auth_goodpass_msg) }, - - CONF_PARSER_TERMINATOR -}; - static const conf_parser_t auth_config[] = { - { FR_CONF_POINTER("log", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) log_config }, - { FR_CONF_POINTER("session", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) session_config }, CONF_PARSER_TERMINATOR @@ -241,116 +221,6 @@ static const conf_parser_t config[] = { #define RAUTH(fmt, ...) log_request(L_AUTH, L_DBG_LVL_OFF, request, __FILE__, __LINE__, fmt, ## __VA_ARGS__) -/* - * Return a short string showing the terminal server, port - * and calling station ID. - */ -static char *auth_name(char *buf, size_t buflen, request_t *request) -{ - char const *tls = ""; - fr_client_t *client = client_from_request(request); - - if (request->packet->socket.inet.dst_port == 0) tls = " via proxy to virtual server"; - - snprintf(buf, buflen, "from client %.128s%s", - client ? client->shortname : "", tls); - - return buf; -} - - -/* - * Make sure user/pass are clean and then create an attribute - * which contains the log message. - */ -static void CC_HINT(format (printf, 4, 5)) auth_message(process_tacacs_auth_t const *inst, - request_t *request, bool goodpass, char const *fmt, ...) -{ - va_list ap; - - bool logit; - char const *extra_msg = NULL; - - char password_buff[256]; - char const *password_str = NULL; - - char buf[1024]; - char extra[1024]; - char *p; - char *msg; - fr_pair_t *username = NULL; - fr_pair_t *password = NULL; - - /* - * No logs? Then no logs. - */ - if (!inst->log_auth) return; - - /* - * Get the correct username based on the configured value - */ - if (!inst->log_stripped_names) { - username = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_name); - } else { - username = fr_pair_find_by_da(&request->request_pairs, NULL, attr_stripped_user_name); - if (!username) username = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_name); - } - - /* - * Clean up the password - */ - if (inst->log_auth_badpass || inst->log_auth_goodpass) { - password = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_password); - if (!password) { - fr_pair_t *auth_type; - - auth_type = fr_pair_find_by_da(&request->control_pairs, NULL, attr_auth_type); - if (auth_type) { - snprintf(password_buff, sizeof(password_buff), "", - fr_dict_enum_name_by_value(auth_type->da, &auth_type->data)); - password_str = password_buff; - } else { - password_str = ""; - } - } else if (fr_pair_find_by_da(&request->request_pairs, NULL, attr_chap_password)) { - password_str = ""; - } - } - - if (goodpass) { - logit = inst->log_auth_goodpass; - extra_msg = inst->auth_goodpass_msg; - } else { - logit = inst->log_auth_badpass; - extra_msg = inst->auth_badpass_msg; - } - - if (extra_msg) { - extra[0] = ' '; - p = extra + 1; - if (xlat_eval(p, sizeof(extra) - 1, request, extra_msg, NULL, NULL) < 0) return; - } else { - *extra = '\0'; - } - - /* - * Expand the input message - */ - va_start(ap, fmt); - msg = fr_vasprintf(request, fmt, ap); - va_end(ap); - - RAUTH("%s: [%pV%s%pV] (%s)%s", - msg, - username ? &username->data : fr_box_strvalue(""), - logit ? "/" : "", - logit ? (password_str ? fr_box_strvalue(password_str) : &password->data) : fr_box_strvalue(""), - auth_name(buf, sizeof(buf), request), - extra); - - talloc_free(msg); -} - /* * Synthesize a State attribute from connection && session information. */ @@ -761,18 +631,10 @@ RESUME(auth_type) RESUME(auth_pass) { - fr_pair_t *vp; process_tacacs_t const *inst = talloc_get_type_abort_const(mctx->inst->data, process_tacacs_t); PROCESS_TRACE; - vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_module_success_message); - if (vp) { - auth_message(&inst->auth, request, true, "Login OK (%pV)", &vp->data); - } else { - auth_message(&inst->auth, request, true, "Login OK"); - } - // @todo - worry about user identity existing? fr_state_discard(inst->auth.state_tree, request); @@ -781,18 +643,10 @@ RESUME(auth_pass) RESUME(auth_fail) { - fr_pair_t *vp; process_tacacs_t const *inst = talloc_get_type_abort_const(mctx->inst->data, process_tacacs_t); PROCESS_TRACE; - vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_module_failure_message); - if (vp) { - auth_message(&inst->auth, request, false, "Login incorrect (%pV)", &vp->data); - } else { - auth_message(&inst->auth, request, false, "Login incorrect"); - } - // @todo - insert server message saying "failed" // and also for FAIL