c2a452
diff -up Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.c.uid-range Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.c
c2a452
--- Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.c.uid-range	2017-09-08 14:46:58.869496414 +0200
c2a452
+++ Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.c	2017-10-09 17:42:13.947599041 +0200
c2a452
@@ -198,6 +198,54 @@ cleanup_old_status (pam_handle_t *pamh,
c2a452
   free (data);
c2a452
 }
c2a452
 
c2a452
+enum uid_range { UID_RANGE_NONE, UID_RANGE_MM, UID_RANGE_MIN,
c2a452
+    UID_RANGE_ONE, UID_RANGE_ERR };
c2a452
+
c2a452
+static enum uid_range
c2a452
+parse_uid_range(pam_handle_t *pamh, const char *s,
c2a452
+                uid_t *min_uid, uid_t *max_uid)
c2a452
+{
c2a452
+    const char *range = s;
c2a452
+    const char *pmax;
c2a452
+    char *endptr;
c2a452
+    enum uid_range rv = UID_RANGE_MM;
c2a452
+
c2a452
+    if ((pmax=strchr(range, ':')) == NULL)
c2a452
+        return UID_RANGE_NONE;
c2a452
+    ++pmax;
c2a452
+
c2a452
+    if (range[0] == ':')
c2a452
+        rv = UID_RANGE_ONE;
c2a452
+    else {
c2a452
+            errno = 0;
c2a452
+            *min_uid = strtoul (range, &endptr, 10);
c2a452
+            if (errno != 0 || (range == endptr) || *endptr != ':') {
c2a452
+                pam_syslog(pamh, LOG_DEBUG,
c2a452
+                           "wrong min_uid value in '%s'", s);
c2a452
+                return UID_RANGE_ERR;
c2a452
+            }
c2a452
+    }
c2a452
+
c2a452
+    if (*pmax == '\0') {
c2a452
+        if (rv == UID_RANGE_ONE)
c2a452
+            return UID_RANGE_ERR;
c2a452
+
c2a452
+        return UID_RANGE_MIN;
c2a452
+    }
c2a452
+
c2a452
+    errno = 0;
c2a452
+    *max_uid = strtoul (pmax, &endptr, 10);
c2a452
+    if (errno != 0 || (pmax == endptr) || *endptr != '\0') {
c2a452
+        pam_syslog(pamh, LOG_DEBUG,
c2a452
+                   "wrong max_uid value in '%s'", s);
c2a452
+        return UID_RANGE_ERR;
c2a452
+    }
c2a452
+
c2a452
+    if (rv == UID_RANGE_ONE)
c2a452
+        *min_uid = *max_uid;
c2a452
+    return rv;
c2a452
+}
c2a452
+
c2a452
 int
c2a452
 pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv)
c2a452
 {
c2a452
@@ -207,6 +255,7 @@ pam_sm_open_session (pam_handle_t *pamh,
c2a452
   struct audit_tty_status *old_status, new_status;
c2a452
   const char *user;
c2a452
   int i, fd, open_only;
c2a452
+  struct passwd *pwd;
c2a452
 #ifdef HAVE_STRUCT_AUDIT_TTY_STATUS_LOG_PASSWD
c2a452
   int log_passwd;
c2a452
 #endif /* HAVE_STRUCT_AUDIT_TTY_STATUS_LOG_PASSWD */
c2a452
@@ -219,6 +268,14 @@ pam_sm_open_session (pam_handle_t *pamh,
c2a452
       return PAM_SESSION_ERR;
c2a452
     }
c2a452
 
c2a452
+  pwd = pam_modutil_getpwnam(pamh, user);
c2a452
+  if (pwd == NULL)
c2a452
+    {
c2a452
+      pam_syslog(pamh, LOG_WARNING,
c2a452
+                 "open_session unknown user '%s'", user);
c2a452
+      return PAM_SESSION_ERR;
c2a452
+    }
c2a452
+
c2a452
   command = CMD_NONE;
c2a452
   open_only = 0;
c2a452
 #ifdef HAVE_STRUCT_AUDIT_TTY_STATUS_LOG_PASSWD
c2a452
@@ -236,13 +293,31 @@ pam_sm_open_session (pam_handle_t *pamh,
c2a452
 	  copy = strdup (strchr (argv[i], '=') + 1);
c2a452
 	  if (copy == NULL)
c2a452
 	    return PAM_SESSION_ERR;
c2a452
-	  for (tok = strtok_r (copy, ",", &tok_data); tok != NULL;
c2a452
+	  for (tok = strtok_r (copy, ",", &tok_data);
c2a452
+	       tok != NULL && command != this_command;
c2a452
 	       tok = strtok_r (NULL, ",", &tok_data))
c2a452
 	    {
c2a452
-	      if (fnmatch (tok, user, 0) == 0)
c2a452
+	      uid_t min_uid = 0, max_uid = 0;
c2a452
+	      switch (parse_uid_range(pamh, tok, &min_uid, &max_uid))
c2a452
 		{
c2a452
-		  command = this_command;
c2a452
-		  break;
c2a452
+		case UID_RANGE_NONE:
c2a452
+		    if (fnmatch (tok, user, 0) == 0)
c2a452
+			command = this_command;
c2a452
+		    break;
c2a452
+		case UID_RANGE_MM:
c2a452
+		    if (pwd->pw_uid >= min_uid && pwd->pw_uid <= max_uid)
c2a452
+			command = this_command;
c2a452
+		    break;
c2a452
+		case UID_RANGE_MIN:
c2a452
+		    if (pwd->pw_uid >= min_uid)
c2a452
+			command = this_command;
c2a452
+		    break;
c2a452
+		case UID_RANGE_ONE:
c2a452
+		    if (pwd->pw_uid == max_uid)
c2a452
+			command = this_command;
c2a452
+		    break;
c2a452
+		case UID_RANGE_ERR:
c2a452
+		    break;
c2a452
 		}
c2a452
 	    }
c2a452
 	  free (copy);
c2a452
diff -up Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.8.xml.uid-range Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.8.xml
c2a452
--- Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.8.xml.uid-range	2013-08-28 10:53:40.000000000 +0200
c2a452
+++ Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.8.xml	2017-09-08 14:46:58.895497022 +0200
c2a452
@@ -44,10 +44,10 @@
c2a452
         </term>
c2a452
         <listitem>
c2a452
           <para>
c2a452
-	    For each user matching one of comma-separated glob
c2a452
-	    <option><replaceable>patterns</replaceable></option>, disable
c2a452
-	    TTY auditing.  This overrides any previous <option>enable</option>
c2a452
-	    option matching the same user name on the command line.
c2a452
+	    For each user matching <option><replaceable>patterns</replaceable></option>,
c2a452
+	    disable TTY auditing.  This overrides any previous <option>enable</option>
c2a452
+	    option matching the same user name on the command line. See NOTES
c2a452
+	    for further description of <option><replaceable>patterns</replaceable></option>.
c2a452
           </para>
c2a452
         </listitem>
c2a452
       </varlistentry>
c2a452
@@ -57,10 +57,10 @@
c2a452
         </term>
c2a452
         <listitem>
c2a452
           <para>
c2a452
-	    For each user matching one of comma-separated glob
c2a452
-	    <option><replaceable>patterns</replaceable></option>, enable
c2a452
-	    TTY auditing.  This overrides any previous <option>disable</option>
c2a452
-	    option matching the same user name on the command line.
c2a452
+	    For each user matching <option><replaceable>patterns</replaceable></option>,
c2a452
+	    enable TTY auditing.  This overrides any previous <option>disable</option>
c2a452
+	    option matching the same user name on the command line. See NOTES
c2a452
+	    for further description of <option><replaceable>patterns</replaceable></option>.
c2a452
           </para>
c2a452
         </listitem>
c2a452
       </varlistentry>
c2a452
@@ -139,6 +139,16 @@
c2a452
       To view the data that was logged by the kernel to audit use
c2a452
       the command <command>aureport --tty</command>.
c2a452
     </para>
c2a452
+    <para>
c2a452
+      The <option><replaceable>patterns</replaceable></option> are comma separated
c2a452
+      lists of glob patterns or ranges of uids. A range is specified as
c2a452
+      <replaceable>min_uid</replaceable>:<replaceable>max_uid</replaceable> where
c2a452
+      one of these values can be empty. If <replaceable>min_uid</replaceable> is
c2a452
+      empty only user with the uid <replaceable>max_uid</replaceable> will be
c2a452
+      matched. If <replaceable>max_uid</replaceable> is empty users with the uid
c2a452
+      greater than or equal to <replaceable>min_uid</replaceable> will be
c2a452
+      matched.
c2a452
+    </para>
c2a452
   </refsect1>
c2a452
 
c2a452
   <refsect1 id='pam_tty_audit-examples'>