]> granicus.if.org Git - linux-pam/commitdiff
pam_succeed_if: Request user data only when needed
authorOlaf Mandel <o.mandel@menlosystems.com>
Thu, 23 May 2019 16:09:44 +0000 (16:09 +0000)
committerTomáš Mráz <t8m@users.noreply.github.com>
Thu, 23 May 2019 17:48:24 +0000 (19:48 +0200)
Allow for conditions that just check the user field to also work for
users not known to the system. Before this caused a PAM_USER_UNKNOWN
even if no extra data for an existing user was needed. E.g.

    auth sufficient pam_succeed_if.so user = NotKnownToSystem

modules/pam_succeed_if/pam_succeed_if.c (evaluate): Change the pwd
parameter to an input/output parameter. Lazily request pwd with
pam_modutil_getpwnam() if needed and return PAM_USER_UNKNOWN on failure.

modules/pam_succeed_if/pam_succeed_if.c (pam_sm_authenticate): Don't
request the pwd if !use_uid anymore and shift the output from audit to
after the evaluate() call. Also make sure not to give the normal failure
message if the lazy pwd loading failed.

modules/pam_succeed_if/pam_succeed_if.c

index aac3eeb07108aa4dc97cbc9a90323b3942886ff0..afa61b3ef70c994ebd3095dfccf17da97464bb7f 100644 (file)
@@ -259,7 +259,7 @@ evaluate_notinnetgr(const pam_handle_t* pamh, const char *host, const char *user
 static int
 evaluate(pam_handle_t *pamh, int debug,
         const char *left, const char *qual, const char *right,
-        struct passwd *pwd, const char *user)
+        struct passwd **pwd, const char *user)
 {
        char buf[LINE_MAX] = "";
        const char *attribute = left;
@@ -270,22 +270,35 @@ evaluate(pam_handle_t *pamh, int debug,
                snprintf(buf, sizeof(buf), "%s", user);
                left = buf;
        }
+       /* Get information about the user if needed. */
+       if ((*pwd == NULL) &&
+           ((strcasecmp(left, "uid") == 0) ||
+            (strcasecmp(left, "gid") == 0) ||
+            (strcasecmp(left, "shell") == 0) ||
+            (strcasecmp(left, "home") == 0) ||
+            (strcasecmp(left, "dir") == 0) ||
+            (strcasecmp(left, "homedir") == 0))) {
+               *pwd = pam_modutil_getpwnam(pamh, user);
+               if (*pwd == NULL) {
+                       return PAM_USER_UNKNOWN;
+               }
+       }
        if (strcasecmp(left, "uid") == 0) {
-               snprintf(buf, sizeof(buf), "%lu", (unsigned long) pwd->pw_uid);
+               snprintf(buf, sizeof(buf), "%lu", (unsigned long) (*pwd)->pw_uid);
                left = buf;
        }
        if (strcasecmp(left, "gid") == 0) {
-               snprintf(buf, sizeof(buf), "%lu", (unsigned long) pwd->pw_gid);
+               snprintf(buf, sizeof(buf), "%lu", (unsigned long) (*pwd)->pw_gid);
                left = buf;
        }
        if (strcasecmp(left, "shell") == 0) {
-               snprintf(buf, sizeof(buf), "%s", pwd->pw_shell);
+               snprintf(buf, sizeof(buf), "%s", (*pwd)->pw_shell);
                left = buf;
        }
        if ((strcasecmp(left, "home") == 0) ||
            (strcasecmp(left, "dir") == 0) ||
            (strcasecmp(left, "homedir") == 0)) {
-               snprintf(buf, sizeof(buf), "%s", pwd->pw_dir);
+               snprintf(buf, sizeof(buf), "%s", (*pwd)->pw_dir);
                left = buf;
        }
        if (strcasecmp(left, "service") == 0) {
@@ -415,7 +428,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
 {
        const void *prompt;
        const char *user;
-       struct passwd *pwd;
+       struct passwd *pwd = NULL;
        int ret, i, count, use_uid, debug;
        const char *left, *right, *qual;
        int quiet_fail, quiet_succ, audit;
@@ -471,15 +484,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
                        return ret;
                }
 
-               /* Get information about the user. */
-               pwd = pam_modutil_getpwnam(pamh, user);
-               if (pwd == NULL) {
-                       if(audit)
-                               pam_syslog(pamh, LOG_NOTICE,
-                                          "error retrieving information about user %s",
-                                          user);
-                       return PAM_USER_UNKNOWN;
-               }
+               /* Postpone requesting password data until it is needed */
        }
 
        /* Walk the argument list. */
@@ -520,9 +525,13 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
                        count++;
                        ret = evaluate(pamh, debug,
                                       left, qual, right,
-                                      pwd, user);
+                                      &pwd, user);
+                       if (ret == PAM_USER_UNKNOWN && audit)
+                               pam_syslog(pamh, LOG_NOTICE,
+                                          "error retrieving information about user %s",
+                                          user);
                        if (ret != PAM_SUCCESS) {
-                               if(!quiet_fail)
+                               if(!quiet_fail && ret != PAM_USER_UNKNOWN)
                                        pam_syslog(pamh, LOG_INFO,
                                                   "requirement \"%s %s %s\" "
                                                   "not met by user \"%s\"",