From 62058c50abd7df7769fd4e152488197b7e4e2054 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 28 Jun 2017 15:52:16 +0200 Subject: pam_tty_audit: Support matching users by uid range. * modules/pam_tty_audit/pam_tty_audit.c (parse_uid_range): New function to parse the uid range. (pam_sm_open_session): Call parse_uid_range() and behave according to its result. * modules/pam_tty_audit/pam_tty_audit.8.xml: Document the uid range matching. --- modules/pam_tty_audit/pam_tty_audit.c | 85 +++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) (limited to 'modules/pam_tty_audit/pam_tty_audit.c') diff --git a/modules/pam_tty_audit/pam_tty_audit.c b/modules/pam_tty_audit/pam_tty_audit.c index bce3ab77..c76026a0 100644 --- a/modules/pam_tty_audit/pam_tty_audit.c +++ b/modules/pam_tty_audit/pam_tty_audit.c @@ -199,6 +199,57 @@ cleanup_old_status (pam_handle_t *pamh, void *data, int error_status) free (data); } +enum uid_range { UID_RANGE_NONE, UID_RANGE_MM, UID_RANGE_MIN, + UID_RANGE_ONE, UID_RANGE_ERR }; + +static enum uid_range +parse_uid_range(pam_handle_t *pamh, const char *s, + uid_t *min_uid, uid_t *max_uid) +{ + const char *range = s; + char *pmax; + char *endptr; + enum uid_range rv = UID_RANGE_MM; + + if ((pmax=strchr(range, ':')) == NULL) + return UID_RANGE_NONE; + ++pmax; + + if (range[0] == '@' || range[0] == '%') + ++range; + + if (range[0] == ':') + rv = UID_RANGE_ONE; + else { + errno = 0; + *min_uid = strtoul (range, &endptr, 10); + if (errno != 0 || (range == endptr) || *endptr != ':') { + pam_syslog(pamh, LOG_DEBUG, + "wrong min_uid value in '%s'", s); + return UID_RANGE_ERR; + } + } + + if (*pmax == '\0') { + if (rv == UID_RANGE_ONE) + return UID_RANGE_ERR; + + return UID_RANGE_MIN; + } + + errno = 0; + *max_uid = strtoul (pmax, &endptr, 10); + if (errno != 0 || (pmax == endptr) || *endptr != '\0') { + pam_syslog(pamh, LOG_DEBUG, + "wrong max_uid value in '%s'", s); + return UID_RANGE_ERR; + } + + if (rv == UID_RANGE_ONE) + *min_uid = *max_uid; + return rv; +} + int pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) { @@ -208,6 +259,7 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) struct audit_tty_status *old_status, new_status; const char *user; int i, fd, open_only; + struct passwd *pwd; #ifdef HAVE_STRUCT_AUDIT_TTY_STATUS_LOG_PASSWD int log_passwd; #endif /* HAVE_STRUCT_AUDIT_TTY_STATUS_LOG_PASSWD */ @@ -220,6 +272,14 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) return PAM_SESSION_ERR; } + pwd = pam_modutil_getpwnam(pamh, user); + if (pwd == NULL) + { + pam_syslog(pamh, LOG_WARNING, + "open_session unknown user '%s'", user); + return PAM_SESSION_ERR; + } + command = CMD_NONE; open_only = 0; #ifdef HAVE_STRUCT_AUDIT_TTY_STATUS_LOG_PASSWD @@ -237,13 +297,30 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) copy = strdup (strchr (argv[i], '=') + 1); if (copy == NULL) return PAM_SESSION_ERR; - for (tok = strtok_r (copy, ",", &tok_data); tok != NULL; + for (tok = strtok_r (copy, ",", &tok_data); + tok != NULL && command == CMD_NONE; tok = strtok_r (NULL, ",", &tok_data)) { - if (fnmatch (tok, user, 0) == 0) + uid_t min_uid = 0, max_uid = 0; + switch (parse_uid_range(pamh, tok, &min_uid, &max_uid)) { - command = this_command; - break; + case UID_RANGE_NONE: + if (fnmatch (tok, user, 0) == 0) + command = this_command; + break; + case UID_RANGE_MM: + if (pwd->pw_uid >= min_uid && pwd->pw_uid <= max_uid) + command = this_command; + break; + case UID_RANGE_MIN: + if (pwd->pw_uid >= min_uid) + command = this_command; + break; + case UID_RANGE_ONE: + if (pwd->pw_uid == max_uid) + command = this_command; + case UID_RANGE_ERR: + break; } } free (copy); -- cgit v1.2.3