]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs: 419307
authorAndrew G. Morgan <morgan@kernel.org>
Thu, 27 Jun 2002 05:43:28 +0000 (05:43 +0000)
committerAndrew G. Morgan <morgan@kernel.org>
Thu, 27 Jun 2002 05:43:28 +0000 (05:43 +0000)
Purpose of commit: new feature/cleanup

Commit summary:
---------------
made pam_nologin more secure by changing the default behavior and
adding some more features. General code clean up in the process.

CHANGELOG
doc/modules/pam_nologin.sgml
doc/pam_source.sgml
modules/pam_nologin/README
modules/pam_nologin/pam_nologin.c

index de60ed1ec1a264986f81bb176195a8e428c461d5..4e2eae941e656d38c651db4a4a8f15b622a983b7 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -55,6 +55,9 @@ bug report - outstanding bugs are listed here:
 0.76: please submit patches for this section with actual code/doc
       patches!
 
+* make pam_nologin more secure by default, added two new module
+  arguments etc. - acting on suggestion from Nico (Bug 419307 -
+  agmorgan)
 * link in libpam to libpam_misc - since the latter uses functions in
   the former it makes some sort of sense to do this (although, in the
   static library case, I remain to be convinced). (Bug 565470 -
index b1aa664b1474219b38bdf931babbf98ccddfee91..52cf02a5b4903171e88b57b56bf4ad87caabcb57 100644 (file)
 
 <tag><bf>Author:</bf></tag>
 Written by Michael K. Johnson &lt;johnsonm@redhat.com&gt;<newline>
-(based on code taken from a module written by Andrew G. Morgan
-&lt;morgan@kernel.org&gt;).
 
 <tag><bf>Maintainer:</bf></tag>
-Michael K. Johnson &lt;johnsonm@redhat.com&gt;
 
 <tag><bf>Management groups provided:</bf></tag>
-authentication
+account; authentication
 
 <tag><bf>Cryptographically sensitive:</bf></tag>
        
 <tag><bf>Security rating:</bf></tag>
 
 <tag><bf>Clean code base:</bf></tag>
-1 warning about dropping const
 
 <tag><bf>System dependencies:</bf></tag>
 
@@ -49,24 +45,34 @@ Provides standard Unix <em/nologin/ authentication.
 <descrip>
 
 <tag><bf>Recognized arguments:</bf></tag>
+successok, file=&lt;<em/filename/&gt;
 
 <tag><bf>Description:</bf></tag>
 
 Provides standard Unix <em/nologin/ authentication.  If the file
 <tt>/etc/nologin</tt> exists, only root is allowed to log in; other
-users are turned away with an error message.  All users (root or
+users are turned away with an error message (and the module returns
+<tt/PAM_AUTH_ERR/ or <tt/PAM_USER_UNKNOWN/).  All users (root or
 otherwise) are shown the contents of <tt>/etc/nologin</tt>.
 
 <p>
-If the file <tt>/etc/nologin</tt> does not exist, this module succeeds
-silently.
+If the file <tt>/etc/nologin</tt> does not exist, this module defaults
+to returning <tt/PAM_IGNORE/, but the <tt/successok/ module argument
+causes it to return <tt/PAM_SUCCESS/ in this case.
+
+<p>
+The administrator can override the default nologin file with the
+<tt/file=/<em/pathname/ module argument.
 
 <tag><bf>Examples/suggested usage:</bf></tag>
 
-In order to make this module effective, all login methods should
-be secured by it.  It should be used as a <tt>required</tt>
-method listed before any <tt>sufficient</tt> methods in order to
-get standard Unix nologin semantics.
+In order to make this module effective, all login methods should be
+secured by it.  It should be used as a <tt>required</tt> method listed
+before any <tt>sufficient</tt> methods in order to get standard Unix
+nologin semantics. Note, the use of <tt/successok/ module argument
+causes the module to return <tt/PAM_SUCCESS/ and as such would break
+such a configuration - failing <tt/sufficient/ modules would lead to a
+successful login because the nologin module <em/succeeded/.
 
 </descrip>
 
index f2545e6f34bffd8d5b59ea63828315df763331d1..2dd5783e3fd8e8c06339f2a0e4a8e222e418de19 100644 (file)
@@ -46,7 +46,7 @@ DAMAGE.
 
 <title>The Linux-PAM System Administrators' Guide
 <author>Andrew G. Morgan, <tt>morgan@kernel.org</tt>
-<date>DRAFT v0.76 2002/05/27
+<date>DRAFT v0.76 2002/06/26
 <abstract>
 This manual documents what a system-administrator needs to know about
 the <bf>Linux-PAM</bf> library. It covers the correct syntax of the
index 0586de6669ff5d418855e23319a663a091f6fc57..11dc7635b80b4a2c8d380a34727d90ce0b0da9f2 100644 (file)
@@ -5,8 +5,19 @@ This module always lets root in; it lets other users in only if the file
 /etc/nologin doesn't exist.  In any case, if /etc/nologin exists, it's
 contents are displayed to the user.
 
+The default return value for this module is PAM_IGNORE, you can
+override this with the successok module argument.
+
 module services provided:
 
-       auth            _authentication and _setcred (blank)
+       auth            _authenticate and _setcred
+       account         _acct_mgmt
+
+optional arguments:
+
+       file=<alternative-nologin-pathname>  - choose a different file
+       successok                            - return PAM_SUCCESS if no file
+
+[Original README by Michael K. Johnson]
+
 
-Michael K. Johnson
index 708f86ded4d3d35268d90befa87f43c7de46106a..7b2394af97dcd4cfe106ff13faaf321455da5a87 100644 (file)
 
 #include <security/pam_modules.h>
 
-/* --- authentication management functions (only) --- */
+#include <security/_pam_modutil.h>
+
+/*
+ * parse some command line options
+ */
+struct opt_s {
+    int retval_when_nofile;
+    const char *nologin_file;
+};
+
+static void parse_args(pam_handle_t *pamh, int argc, const char **argv,
+                      struct opt_s *opts)
+{
+    int i;
+
+    memset(opts, 0, sizeof(*opts));
+
+    opts->retval_when_nofile = PAM_IGNORE;
+    opts->nologin_file = "/etc/nologin";
+
+    for (i=0; i<argc; ++i) {
+       if (!strcmp("successok", argv[i])) {
+           opts->retval_when_nofile = PAM_SUCCESS;
+       } else if (!memcmp("file=", argv[i], 5)) {
+           opts->nologin_file = argv[i] + 5;
+       } else {
+           /* XXX - ignore for now. Later, we'll use the logging
+               function in pammodutils */
+       }
+    }
+}
+
+/*
+ * do the meat of the work for this module
+ */
+
+static int perform_check(pam_handle_t *pamh, struct opt_s *opts)
+{
+    const char *username;
+    int retval = PAM_SUCCESS;
+    int fd;
+
+    retval = opts->retval_when_nofile;
+
+    if ((pam_get_user(pamh, &username, NULL) != PAM_SUCCESS) || !username) {
+       return PAM_USER_UNKNOWN;
+    }
+
+    if ((fd = open(opts->nologin_file, O_RDONLY, 0)) >= 0) {
+
+       char *mtmp=NULL;
+       struct passwd *user_pwd;
+       struct pam_conv *conversation;
+       struct pam_message message;
+       struct pam_message *pmessage = &message;
+       struct pam_response *resp = NULL;
+       struct stat st;
+
+       user_pwd = _pammodutil_getpwnam(pamh, username);
+       if (user_pwd == NULL) {
+
+           retval = PAM_USER_UNKNOWN;
+           message.msg_style = PAM_ERROR_MSG;
+
+       } else if (user_pwd->pw_uid) {
+
+           retval = PAM_AUTH_ERR;
+           message.msg_style = PAM_ERROR_MSG;
+
+       } else {
+
+           /* root can still log in; lusers cannot */
+           message.msg_style = PAM_TEXT_INFO;
+
+       }
+
+       /* fill in message buffer with contents of /etc/nologin */
+       if (fstat(fd, &st) < 0)  {
+           /* give up trying to display message */
+           goto clean_up_fd;
+       }
+
+       message.msg = mtmp = malloc(st.st_size+1);
+       if (!message.msg) {
+           /* if malloc failed... */
+           retval = PAM_BUF_ERR;
+           goto clean_up_fd;
+       }
+
+       read(fd, mtmp, st.st_size);
+       mtmp[st.st_size] = '\000';
+
+       /*
+        * Use conversation function to give user contents of /etc/nologin
+        */
+
+       pam_get_item(pamh, PAM_CONV, (const void **)&conversation);
+       (void) conversation->conv(1, (const struct pam_message **)&pmessage,
+                                 &resp, conversation->appdata_ptr);
+       free(mtmp);
+
+       if (resp) {
+           _pam_drop_reply(resp, 1);
+       }
+
+    clean_up_fd:
+
+       close(fd);
+    }
+
+    return retval;
+}
+
+/* --- authentication management functions --- */
 
 PAM_EXTERN
 int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
                         const char **argv)
 {
-     int retval = PAM_SUCCESS;
-     int fd;
-     const char *username;
-     char *mtmp=NULL;
-     struct passwd *user_pwd;
-     struct pam_conv *conversation;
-     struct pam_message message;
-     struct pam_message *pmessage = &message;
-     struct pam_response *resp = NULL;
-     struct stat st;
-
-     if ((fd = open("/etc/nologin", O_RDONLY, 0)) >= 0) {
-       /* root can still log in; lusers cannot */
-       if ((pam_get_user(pamh, &username, NULL) != PAM_SUCCESS)
-           || !username) {
-         return PAM_SERVICE_ERR;
-       }
-       user_pwd = getpwnam(username);
-       if (user_pwd && user_pwd->pw_uid == 0) {
-         message.msg_style = PAM_TEXT_INFO;
-       } else {
-          if (!user_pwd) {
-              retval = PAM_USER_UNKNOWN;
-          } else {
-              retval = PAM_AUTH_ERR;
-          }
-          message.msg_style = PAM_ERROR_MSG;
-       }
-
-       /* fill in message buffer with contents of /etc/nologin */
-       if (fstat(fd, &st) < 0) /* give up trying to display message */
-         return retval;
-       message.msg = mtmp = malloc(st.st_size+1);
-       /* if malloc failed... */
-       if (!message.msg) return retval;
-       read(fd, mtmp, st.st_size);
-       mtmp[st.st_size] = '\000';
-
-       /* Use conversation function to give user contents of /etc/nologin */
-       pam_get_item(pamh, PAM_CONV, (const void **)&conversation);
-       conversation->conv(1, (const struct pam_message **)&pmessage,
-                         &resp, conversation->appdata_ptr);
-       free(mtmp);
-       if (resp)
-          _pam_drop_reply(resp, 1);
-     }
-
-     return retval;
+    struct opt_s opts;
+
+    parse_args(pamh, argc, argv, &opts);
+
+    return perform_check(pamh, &opts);
 }
 
 PAM_EXTERN
 int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
                    const char **argv)
 {
-     return PAM_SUCCESS;
+    struct opt_s opts;
+
+    parse_args(pamh, argc, argv, &opts);
+
+    return opts.retval_when_nofile;
+}
+
+/* --- account management function --- */
+
+PAM_EXTERN
+int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
+                    const char **argv)
+{
+    struct opt_s opts;
+
+    parse_args(pamh, argc, argv, &opts);
+
+    return perform_check(pamh, &opts);
 }
 
 
@@ -99,7 +186,7 @@ struct pam_module _pam_nologin_modstruct = {
      "pam_nologin",
      pam_sm_authenticate,
      pam_sm_setcred,
-     NULL,
+     pam_sm_acct_mgmt,
      NULL,
      NULL,
      NULL,