From 76a61ebb3b1a2500b6eb457d6725cc8f4568d2d8 Mon Sep 17 00:00:00 2001 From: "Andrew G. Morgan" Date: Thu, 27 Jun 2002 05:43:28 +0000 Subject: Relevant BUGIDs: 419307 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. --- modules/pam_nologin/pam_nologin.c | 189 ++++++++++++++++++++++++++++---------- 1 file changed, 138 insertions(+), 51 deletions(-) (limited to 'modules/pam_nologin/pam_nologin.c') diff --git a/modules/pam_nologin/pam_nologin.c b/modules/pam_nologin/pam_nologin.c index 708f86de..7b2394af 100644 --- a/modules/pam_nologin/pam_nologin.c +++ b/modules/pam_nologin/pam_nologin.c @@ -27,67 +27,154 @@ #include -/* --- authentication management functions (only) --- */ +#include + +/* + * 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; iretval_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, -- cgit v1.2.3