]> granicus.if.org Git - linux-pam/blobdiff - modules/pam_unix/support.c
Relevant BUGIDs: none
[linux-pam] / modules / pam_unix / support.c
index cf01e3c21c39dcd1e293cecb106fde40176a43fc..fc7fc2b337a41272310e44946ddc41c125b39376 100644 (file)
@@ -1,10 +1,10 @@
-/* 
+/*
  * $Id$
  *
  * Copyright information at end of file.
  */
 
-#define _BSD_SOURCE
+#include "config.h"
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <ctype.h>
+#include <sys/resource.h>
 #include <rpcsvc/ypclnt.h>
 
 #include <security/_pam_macros.h>
 
 #include "md5.h"
 #include "support.h"
-
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#define SELINUX_ENABLED is_selinux_enabled()>0
+#else
+#define SELINUX_ENABLED 0
+#endif
 extern char *crypt(const char *key, const char *salt);
 extern char *bigcrypt(const char *key, const char *salt);
 
@@ -35,11 +41,11 @@ extern char *bigcrypt(const char *key, const char *salt);
 
 void _log_err(int err, pam_handle_t *pamh, const char *format,...)
 {
-       char *service = NULL;
+       const void *service = NULL;
        char logname[256];
        va_list args;
 
-       pam_get_item(pamh, PAM_SERVICE, (const void **) &service);
+       pam_get_item(pamh, PAM_SERVICE, &service);
        if (service) {
                strncpy(logname, service, sizeof(logname));
                logname[sizeof(logname) - 1 - strlen("(pam_unix)")] = '\0';
@@ -62,11 +68,13 @@ static int converse(pam_handle_t * pamh, int ctrl, int nargs
                    ,struct pam_response **response)
 {
        int retval;
-       struct pam_conv *conv;
+       const void *void_conv;
+       const struct pam_conv *conv;
 
        D(("begin to converse"));
 
-       retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
+       retval = pam_get_item(pamh, PAM_CONV, &void_conv);
+       conv = void_conv;
        if (retval == PAM_SUCCESS) {
 
                retval = conv->conv(nargs, (const struct pam_message **) message
@@ -225,10 +233,10 @@ struct _pam_failed_auth {
 static void _cleanup_failures(pam_handle_t * pamh, void *fl, int err)
 {
        int quiet;
-       const char *service = NULL;
-       const char *ruser = NULL;
-       const char *rhost = NULL;
-       const char *tty = NULL;
+       const void *service = NULL;
+       const void *ruser = NULL;
+       const void *rhost = NULL;
+       const void *tty = NULL;
        struct _pam_failed_auth *failure;
 
        D(("called"));
@@ -244,13 +252,13 @@ static void _cleanup_failures(pam_handle_t * pamh, void *fl, int err)
                        /* log the number of authentication failures */
                        if (failure->count > 1) {
                                (void) pam_get_item(pamh, PAM_SERVICE,
-                                                   (const void **)&service);
+                                                   &service);
                                (void) pam_get_item(pamh, PAM_RUSER,
-                                                   (const void **)&ruser);
+                                                   &ruser);
                                (void) pam_get_item(pamh, PAM_RHOST,
-                                                   (const void **)&rhost);
+                                                   &rhost);
                                (void) pam_get_item(pamh, PAM_TTY,
-                                                   (const void **)&tty);
+                                                   &tty);
                                _log_err(LOG_NOTICE, pamh,
                                         "%d more authentication failure%s; "
                                         "logname=%s uid=%d euid=%d "
@@ -471,9 +479,9 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
 
        if (pwd != NULL) {
                if (strcmp( pwd->pw_passwd, "*NP*" ) == 0)
-               { /* NIS+ */                 
+               { /* NIS+ */
                        uid_t save_euid, save_uid;
-       
+
                        save_euid = geteuid();
                        save_uid = getuid();
                        if (save_uid == pwd->pw_uid)
@@ -488,7 +496,7 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
                                                return 0;
                                }
                        }
-       
+
                        spwdent = _pammodutil_getspnam (pamh, name);
                        if (save_uid == pwd->pw_uid)
                                setreuid( save_uid, save_euid );
@@ -562,18 +570,32 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
     /* fork */
     child = fork();
     if (child == 0) {
+        int i=0;
+        struct rlimit rlim;
        static char *envp[] = { NULL };
-       char *args[] = { NULL, NULL, NULL };
+       char *args[] = { NULL, NULL, NULL, NULL };
 
        /* XXX - should really tidy up PAM here too */
 
+       close(0); close(1);
        /* reopen stdin as pipe */
        close(fds[1]);
        dup2(fds[0], STDIN_FILENO);
 
+       if (getrlimit(RLIMIT_NOFILE,&rlim)==0) {
+         for (i=2; i < rlim.rlim_max; i++) {
+               if (fds[0] != i)
+                  close(i);
+         }
+       }
        /* exec binary helper */
        args[0] = x_strdup(CHKPWD_HELPER);
        args[1] = x_strdup(user);
+       if (off(UNIX__NONULL, ctrl)) {  /* this means we've succeeded */
+         args[2]=x_strdup("nullok");
+       } else {
+         args[2]=x_strdup("nonull");
+       }
 
        execve(CHKPWD_HELPER, args, envp);
 
@@ -583,11 +605,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
     } else if (child > 0) {
        /* wait for child */
        /* if the stored password is NULL */
-       if (off(UNIX__NONULL, ctrl)) {  /* this means we've succeeded */
-           write(fds[1], "nullok\0\0", 8);
-       } else {
-           write(fds[1], "nonull\0\0", 8);
-       }
+        int rc=0;
        if (passwd != NULL) {            /* send the password to the child */
            write(fds[1], passwd, strlen(passwd)+1);
            passwd = NULL;
@@ -596,10 +614,17 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
        }
        close(fds[0]);       /* close here to avoid possible SIGPIPE above */
        close(fds[1]);
-       (void) waitpid(child, &retval, 0);  /* wait for helper to complete */
-       retval = (retval == 0) ? PAM_SUCCESS:PAM_AUTH_ERR;
+       rc=waitpid(child, &retval, 0);  /* wait for helper to complete */
+       if (rc<0) {
+         _log_err(LOG_ERR, pamh, "unix_chkpwd waitpid returned %d: %s", rc, strerror(errno));
+         retval = PAM_AUTH_ERR;
+       } else {
+         retval = WEXITSTATUS(retval);
+       }
     } else {
        D(("fork failed"));
+       close(fds[0]);
+       close(fds[1]);
        retval = PAM_AUTH_ERR;
     }
 
@@ -621,6 +646,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
        char *data_name;
        int retval;
 
+
        D(("called"));
 
 #ifdef HAVE_PAM_FAIL_DELAY
@@ -639,9 +665,9 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
 
        if (pwd != NULL) {
                if (strcmp( pwd->pw_passwd, "*NP*" ) == 0)
-               { /* NIS+ */                 
+               { /* NIS+ */
                        uid_t save_euid, save_uid;
-       
+
                        save_euid = geteuid();
                        save_uid = getuid();
                        if (save_uid == pwd->pw_uid)
@@ -655,7 +681,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
                                                return PAM_CRED_INSUFFICIENT;
                                }
                        }
-       
+
                        spwdent = _pammodutil_getspnam (pamh, name);
                        if (save_uid == pwd->pw_uid)
                                setreuid( save_uid, save_euid );
@@ -687,19 +713,18 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
 
        retval = PAM_SUCCESS;
        if (pwd == NULL || salt == NULL || !strcmp(salt, "x") || ((salt[0] == '#') && (salt[1] == '#') && !strcmp(salt + 2, name))) {
-               if (geteuid()) {
+
+               if (pwd != NULL && (geteuid() || SELINUX_ENABLED)) {
                        /* we are not root perhaps this is the reason? Run helper */
                        D(("running helper binary"));
                        retval = _unix_run_helper_binary(pamh, p, ctrl, name);
-                       if (pwd == NULL && !on(UNIX_AUDIT,ctrl)
-                           && retval != PAM_SUCCESS)
-                       {
-                               name = NULL;
-                       }
                } else {
                        D(("user's record unavailable"));
                        p = NULL;
-                       retval = PAM_AUTHINFO_UNAVAIL;
+                       if (pwd == NULL)
+                               retval = PAM_USER_UNKNOWN;
+                       else
+                               retval = PAM_AUTHINFO_UNAVAIL;
                        if (on(UNIX_AUDIT, ctrl)) {
                                /* this might be a typo and the user has given a password
                                   instead of a username. Careful with this. */
@@ -777,6 +802,8 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
                        if (new != NULL) {
 
                            const char *login_name;
+                           const void *void_old;
+
 
                            login_name = _pammodutil_getlogin(pamh);
                            if (login_name == NULL) {
@@ -789,7 +816,11 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
                                new->name = x_strdup(login_name);
 
                                /* any previous failures for this user ? */
-                               pam_get_data(pamh, data_name, (const void **) &old);
+                               if (pam_get_data(pamh, data_name, &void_old)
+                                   == PAM_SUCCESS)
+                                       old = void_old;
+                               else
+                                       old = NULL;
 
                                if (old != NULL) {
                                        new->count = old->count + 1;
@@ -797,19 +828,19 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
                                                retval = PAM_MAXTRIES;
                                        }
                                } else {
-                                       const char *service=NULL;
-                                       const char *ruser=NULL;
-                                       const char *rhost=NULL;
-                                       const char *tty=NULL;
+                                       const void *service=NULL;
+                                       const void *ruser=NULL;
+                                       const void *rhost=NULL;
+                                       const void *tty=NULL;
 
                                        (void) pam_get_item(pamh, PAM_SERVICE,
-                                                           (const void **)&service);
+                                                           &service);
                                        (void) pam_get_item(pamh, PAM_RUSER,
-                                                           (const void **)&ruser);
+                                                           &ruser);
                                        (void) pam_get_item(pamh, PAM_RHOST,
-                                                           (const void **)&rhost);
+                                                           &rhost);
                                        (void) pam_get_item(pamh, PAM_TTY,
-                                                           (const void **)&tty);
+                                                           &tty);
 
                                        _log_err(LOG_NOTICE, pamh,
                                                 "authentication failure; "
@@ -859,7 +890,7 @@ int _unix_read_password(pam_handle_t * pamh
                        ,const char *prompt1
                        ,const char *prompt2
                        ,const char *data_name
-                       ,const char **pass)
+                       ,const void **pass)
 {
        int authtok_flag;
        int retval;
@@ -884,7 +915,7 @@ int _unix_read_password(pam_handle_t * pamh
         */
 
        if (on(UNIX_TRY_FIRST_PASS, ctrl) || on(UNIX_USE_FIRST_PASS, ctrl)) {
-               retval = pam_get_item(pamh, authtok_flag, (const void **) pass);
+               retval = pam_get_item(pamh, authtok_flag, pass);
                if (retval != PAM_SUCCESS) {
                        /* very strange. */
                        _log_err(LOG_ALERT, pamh
@@ -897,7 +928,7 @@ int _unix_read_password(pam_handle_t * pamh
                        return PAM_AUTHTOK_RECOVER_ERR;         /* didn't work */
                } else if (on(UNIX_USE_AUTHTOK, ctrl)
                           && off(UNIX__OLD_PASSWD, ctrl)) {
-                       return PAM_AUTHTOK_RECOVER_ERR;
+                       return PAM_AUTHTOK_ERR;
                }
        }
        /*
@@ -989,8 +1020,7 @@ int _unix_read_password(pam_handle_t * pamh
                retval = pam_set_item(pamh, authtok_flag, token);
                _pam_delete(token);     /* clean it up */
                if (retval != PAM_SUCCESS
-                   || (retval = pam_get_item(pamh, authtok_flag
-                                             ,(const void **) pass))
+                   || (retval = pam_get_item(pamh, authtok_flag, pass))
                    != PAM_SUCCESS) {
 
                        *pass = NULL;
@@ -1052,13 +1082,13 @@ int _unix_shadowed(const struct passwd *pwd)
  * 3. The name of the author may not be used to endorse or promote
  *    products derived from this software without specific prior
  *    written permission.
- * 
+ *
  * ALTERNATIVELY, this product may be distributed under the terms of
  * the GNU Public License, in which case the provisions of the GPL are
  * required INSTEAD OF the above restrictions.  (This clause is
  * necessary due to a potential bad interaction between the GPL and
  * the restrictions contained in a BSD-style copyright.)
- * 
+ *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE