summaryrefslogtreecommitdiff
path: root/modules/pam_tty_audit/pam_tty_audit.c
diff options
context:
space:
mode:
authorTomas Mraz <tmraz@fedoraproject.org>2017-06-28 15:52:16 +0200
committerTomas Mraz <tmraz@fedoraproject.org>2017-06-28 15:52:16 +0200
commit62058c50abd7df7769fd4e152488197b7e4e2054 (patch)
tree88ad63a03d3114086a403721900a15ed65613222 /modules/pam_tty_audit/pam_tty_audit.c
parent7d0c508a52ebc9c702e1b6e66f46e4a6dc028c4a (diff)
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.
Diffstat (limited to 'modules/pam_tty_audit/pam_tty_audit.c')
-rw-r--r--modules/pam_tty_audit/pam_tty_audit.c85
1 files changed, 81 insertions, 4 deletions
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);