From 6e99aa00d23a68650fdd4fae01aab812dcfe10eb Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 22 Sep 2004 09:37:46 +0000 Subject: Relevant BUGIDs: Purpose of commit: Commit summary: --------------- bugfix: Add rest of Steve Grubb's resource leak and other fixes --- modules/pam_filter/pam_filter.c | 13 +++- modules/pam_filter/upperLOWER/Makefile | 7 ++- modules/pam_filter/upperLOWER/upperLOWER.c | 15 +++-- modules/pam_ftp/pam_ftp.c | 4 +- modules/pam_group/pam_group.c | 8 +++ modules/pam_issue/pam_issue.c | 29 +++++++-- modules/pam_lastlog/pam_lastlog.c | 8 ++- modules/pam_limits/pam_limits.c | 48 ++++++++------- modules/pam_mail/pam_mail.c | 18 +++--- modules/pam_mkhomedir/pam_mkhomedir.c | 38 +++++++++--- modules/pam_motd/pam_motd.c | 38 +++++++----- modules/pam_nologin/pam_nologin.c | 35 +++++++---- modules/pam_permit/pam_permit.c | 4 +- modules/pam_shells/pam_shells.c | 11 +++- modules/pam_stress/pam_stress.c | 71 +++++++++++----------- modules/pam_tally/pam_tally.c | 9 ++- modules/pam_time/pam_time.c | 4 +- modules/pam_unix/pam_unix_auth.c | 11 ++-- modules/pam_wheel/pam_wheel.c | 2 +- modules/pammodutil/Makefile | 2 +- modules/pammodutil/include/security/_pam_modutil.h | 4 ++ modules/pammodutil/modutil_ioloop.c | 50 +++++++++++++++ 22 files changed, 296 insertions(+), 133 deletions(-) create mode 100644 modules/pammodutil/modutil_ioloop.c (limited to 'modules') diff --git a/modules/pam_filter/pam_filter.c b/modules/pam_filter/pam_filter.c index 9a6fc8c5..e9a0494b 100644 --- a/modules/pam_filter/pam_filter.c +++ b/modules/pam_filter/pam_filter.c @@ -131,7 +131,7 @@ static int process_args(pam_handle_t *pamh } else { char **levp; const char *tmp; - int i,size; + int i,size, retval; *filtername = *++argv; if (ctrl & FILTER_DEBUG) { @@ -177,7 +177,15 @@ static int process_args(pam_handle_t *pamh #define SERVICE_OFFSET 8 /* sizeof('SERVICE='); */ #define SERVICE_NAME "SERVICE=" - pam_get_item(pamh, PAM_SERVICE, (const void **)&tmp); + retval = pam_get_item(pamh, PAM_SERVICE, (const void **)&tmp); + if (retval != PAM_SUCCESS || tmp == NULL) { + _pam_log(LOG_CRIT,"service name not found"); + if (levp) { + free(levp[0]); + free(levp); + } + return -1; + } size = SERVICE_OFFSET+strlen(tmp); levp[1] = (char *) malloc(size+1); @@ -199,6 +207,7 @@ static int process_args(pam_handle_t *pamh #define USER_OFFSET 5 /* sizeof('USER='); */ #define USER_NAME "USER=" + tmp = NULL; pam_get_user(pamh, &tmp, NULL); if (tmp == NULL) { tmp = ""; diff --git a/modules/pam_filter/upperLOWER/Makefile b/modules/pam_filter/upperLOWER/Makefile index 77bc4102..60c6d08c 100644 --- a/modules/pam_filter/upperLOWER/Makefile +++ b/modules/pam_filter/upperLOWER/Makefile @@ -12,16 +12,19 @@ TITLE=upperLOWER # -CFLAGS += -I../include +CFLAGS += -I../include -I../../pammodutil/include OBJS = $(TITLE).o +LIBS += $(GLIB_LIBS) -L../../pammodutil -lpammodutil +LDFLAGS = $(LIBS) + ####################### don't edit below ####################### all: $(TITLE) $(TITLE): $(OBJS) - $(CC) $(CFLAGS) -o $(TITLE) $(OBJS) + $(CC) $(CFLAGS) -o $(TITLE) $(OBJS) $(LDFLAGS) $(STRIP) $(TITLE) install: diff --git a/modules/pam_filter/upperLOWER/upperLOWER.c b/modules/pam_filter/upperLOWER/upperLOWER.c index e750e877..72f9dab5 100644 --- a/modules/pam_filter/upperLOWER/upperLOWER.c +++ b/modules/pam_filter/upperLOWER/upperLOWER.c @@ -21,6 +21,9 @@ #include #include +#include +#include +#include /* ---------------------------------------------------------------- */ @@ -109,27 +112,27 @@ int main(int argc, char **argv) /* application errors */ if ( FD_ISSET(APPERR_FILENO,&readers) ) { - int got = read(APPERR_FILENO, buffer, BUFSIZ); + int got = _pammodutil_read(APPERR_FILENO, buffer, BUFSIZ); if (got <= 0) { break; } else { /* translate to give to real terminal */ if (before_user != NULL) before_user(buffer, got); - if ( write(STDERR_FILENO, buffer, got) != got ) { + if (_pammodutil_write(STDERR_FILENO, buffer, got) != got ) { log_this(LOG_WARNING,"couldn't write %d bytes?!",got); break; } } } else if ( FD_ISSET(APPOUT_FILENO,&readers) ) { /* app output */ - int got = read(APPOUT_FILENO, buffer, BUFSIZ); + int got = _pammodutil_read(APPOUT_FILENO, buffer, BUFSIZ); if (got <= 0) { break; } else { /* translate to give to real terminal */ if (before_user != NULL) before_user(buffer, got); - if ( write(STDOUT_FILENO, buffer, got) != got ) { + if (_pammodutil_write(STDOUT_FILENO, buffer, got) != got ) { log_this(LOG_WARNING,"couldn't write %d bytes!?",got); break; } @@ -137,7 +140,7 @@ int main(int argc, char **argv) } if ( FD_ISSET(STDIN_FILENO, &readers) ) { /* user input */ - int got = read(STDIN_FILENO, buffer, BUFSIZ); + int got = _pammodutil_read(STDIN_FILENO, buffer, BUFSIZ); if (got < 0) { log_this(LOG_WARNING,"user input junked"); break; @@ -145,7 +148,7 @@ int main(int argc, char **argv) /* translate to give to application */ if (before_app != NULL) before_app(buffer, got); - if ( write(APPIN_FILENO, buffer, got) != got ) { + if (_pammodutil_write(APPIN_FILENO, buffer, got) != got ) { log_this(LOG_WARNING,"couldn't pass %d bytes!?",got); break; } diff --git a/modules/pam_ftp/pam_ftp.c b/modules/pam_ftp/pam_ftp.c index bebcd2b2..e95b7d78 100644 --- a/modules/pam_ftp/pam_ftp.c +++ b/modules/pam_ftp/pam_ftp.c @@ -58,7 +58,7 @@ static int converse(pam_handle_t *pamh, int nargs D(("begin to converse\n")); retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ; - if ( retval == PAM_SUCCESS ) { + if ( retval == PAM_SUCCESS && conv ) { retval = conv->conv(nargs, ( const struct pam_message ** ) message , response, conv->appdata_ptr); @@ -73,6 +73,8 @@ static int converse(pam_handle_t *pamh, int nargs } else { _pam_log(LOG_ERR, "couldn't obtain coversation function [%s]" , pam_strerror(pamh, retval)); + if (retval == PAM_SUCCESS) + retval = PAM_BAD_ITEM; /* conv was NULL */ } D(("ready to return from module conversation\n")); diff --git a/modules/pam_group/pam_group.c b/modules/pam_group/pam_group.c index 77c909d0..4b42506c 100644 --- a/modules/pam_group/pam_group.c +++ b/modules/pam_group/pam_group.c @@ -79,6 +79,12 @@ static void shift_bytes(char *mem, int from, int by) } } +/* This function should initially be called with buf = NULL. If + * an error occurs, the file descriptor is closed. Subsequent + * calls with a closed descriptor will cause buf to be deallocated. + * Therefore, always check buf after calling this to see if an error + * occurred. + */ static int read_field(int fd, char **buf, int *from, int *to) { /* is buf set ? */ @@ -126,6 +132,7 @@ static int read_field(int fd, char **buf, int *from, int *to) i = read(fd, *to + *buf, PAM_GROUP_BUFLEN - *to); if (i < 0) { _log_err("error reading " PAM_GROUP_CONF); + close(fd); return -1; } else if (!i) { close(fd); @@ -165,6 +172,7 @@ static int read_field(int fd, char **buf, int *from, int *to) } else { _log_err("internal error in " __FILE__ " at line %d", __LINE__ ); + close(fd); return -1; } break; diff --git a/modules/pam_issue/pam_issue.c b/modules/pam_issue/pam_issue.c index 985bfebc..5665966e 100644 --- a/modules/pam_issue/pam_issue.c +++ b/modules/pam_issue/pam_issue.c @@ -84,12 +84,19 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, if ((fd = fopen(issue_file, "r")) != NULL) { int tot_size = 0; - if (fstat(fileno(fd), &st) < 0) + if (fstat(fileno(fd), &st) < 0) { + fclose(fd); + if (issue_file) + free(issue_file); return PAM_IGNORE; + } retval = pam_get_item(pamh, PAM_USER_PROMPT, (const void **) &cur_prompt); if (retval != PAM_SUCCESS) { + fclose(fd); + if (issue_file) + free(issue_file); return PAM_IGNORE; } if (cur_prompt == NULL) { @@ -101,6 +108,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, if (parse_esc) { prompt_tmp = do_prompt(fd); if (prompt_tmp == NULL) { + fclose(fd); + if (issue_file) + free(issue_file); return PAM_IGNORE; } } else { @@ -108,13 +118,17 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, prompt_tmp = malloc(st.st_size + 1); if (prompt_tmp == NULL) { + fclose(fd); + if (issue_file) + free(issue_file); return PAM_IGNORE; } memset (prompt_tmp, '\0', st.st_size + 1); count = fread(prompt_tmp, 1, st.st_size, fd); if (count != st.st_size) { - free(prompt_tmp); - return PAM_IGNORE; + fclose(fd); + retval = PAM_IGNORE; + goto cleanup; } prompt_tmp[st.st_size] = '\0'; } @@ -151,6 +165,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, } else { D(("could not open issue_file: %s", issue_file)); + free(issue_file); return PAM_IGNORE; } @@ -167,11 +182,15 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, static char *do_prompt(FILE *fd) { int c, size = 1024; - char *issue = (char *)malloc(size); + char *issue; char buf[1024]; struct utsname uts; - if (issue == NULL || fd == NULL) + if (fd == NULL) + return NULL; + + issue = (char *)malloc(size); + if (issue == NULL) return NULL; issue[0] = '\0'; /* zero this, for strcat to work on first buf */ diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c index f9a730bf..1e7a3b4f 100644 --- a/modules/pam_lastlog/pam_lastlog.c +++ b/modules/pam_lastlog/pam_lastlog.c @@ -149,7 +149,7 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs D(("begin to converse")); retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ; - if ( retval == PAM_SUCCESS ) { + if ( retval == PAM_SUCCESS && conv) { retval = conv->conv(nargs, ( const struct pam_message ** ) message , response, conv->appdata_ptr); @@ -164,6 +164,8 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs } else { _log_err(LOG_ERR, "couldn't obtain coversation function [%s]" , pam_strerror(pamh, retval)); + if (retval == PAM_SUCCESS) + retval = PAM_BAD_ITEM; /* conv was NULL */ } D(("ready to return from module conversation")); @@ -235,7 +237,7 @@ static int last_login_date(pam_handle_t *pamh, int announce, uid_t uid) sleep(LASTLOG_IGNORE_LOCK_TIME); } - win = ( read(last_fd, &last_login, sizeof(last_login)) + win = ( _pammodutil_read(last_fd, &last_login, sizeof(last_login)) == sizeof(last_login) ); last_lock.l_type = F_UNLCK; @@ -376,7 +378,7 @@ static int last_login_date(pam_handle_t *pamh, int announce, uid_t uid) } D(("writing to the last_log file")); - (void) write(last_fd, &last_login, sizeof(last_login)); + (void) _pammodutil_write(last_fd, &last_login, sizeof(last_login)); last_lock.l_type = F_UNLCK; (void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */ diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c index 6837fdef..0d7f2185 100644 --- a/modules/pam_limits/pam_limits.c +++ b/modules/pam_limits/pam_limits.c @@ -1,13 +1,13 @@ /* * pam_limits - impose resource limits when opening a user session * - * 1.6 - modified for PLD (added process priority settings) + * 1.6 - modified for PLD (added process priority settings) * by Marcin Korzonek * 1.5 - Elliot Lee's "max system logins patch" * 1.4 - addressed bug in configuration file parser * 1.3 - modified the configuration file format * 1.2 - added 'debug' and 'conf=' arguments - * 1.1 - added @group support + * 1.1 - added @group support * 1.0 - initial release - Linux ONLY * * See end for Copyright information @@ -15,7 +15,7 @@ #if !(defined(linux)) #error THIS CODE IS KNOWN TO WORK ONLY ON LINUX !!! -#endif +#endif #include @@ -54,6 +54,8 @@ static const char *limits_def_names[] = { "GROUP", "DEFAULT", "NONE", + "ALL", + "ALLGROUP", NULL, }; @@ -165,7 +167,7 @@ static int is_in_group(const char *user_name, const char *group_name) struct passwd *pwd; struct group *grp, *pgrp; char uname[LINE_LENGTH], gname[LINE_LENGTH]; - + if (!user_name || !strlen(user_name)) return 0; if (!group_name || !strlen(group_name)) @@ -174,7 +176,7 @@ static int is_in_group(const char *user_name, const char *group_name) strncpy(uname, user_name, sizeof(uname)-1); memset(gname, 0, sizeof(gname)); strncpy(gname, group_name, sizeof(gname)-1); - + pwd = getpwnam(uname); if (!pwd) return 0; @@ -183,7 +185,7 @@ static int is_in_group(const char *user_name, const char *group_name) grp = getgrnam(gname); if (!grp) return 0; - + /* first check: is a member of the group_name group ? */ if (is_on_list(grp->gr_mem, uname)) return 1; @@ -194,10 +196,10 @@ static int is_in_group(const char *user_name, const char *group_name) return 0; if (!strcmp(pgrp->gr_name, gname)) return 1; - + return 0; } - + /* Counts the number of user logins and check against the limit*/ static int check_logins(const char *name, int limit, int ctrl, struct pam_limit_s *pl) @@ -228,7 +230,7 @@ static int check_logins(const char *name, int limit, int ctrl, standard for this, since if a module wants to actually map a username then any early utmp entry will be for the unmapped name = broken.) */ - + if (ctrl & PAM_UTMP_EARLY) { count = 0; } else { @@ -300,7 +302,7 @@ static int init_limits(struct pam_limit_s *pl) pl->login_limit_def = LIMITS_DEF_NONE; return retval; -} +} static void process_limit(int source, const char *lim_type, const char *lim_item, const char *lim_value, @@ -311,7 +313,7 @@ static void process_limit(int source, const char *lim_type, long limit_value; const char **endptr = &lim_value; const char *value_orig = lim_value; - + if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_DEBUG, "%s: processing %s %s %s for %s\n", __FUNCTION__,lim_type,lim_item,lim_value, @@ -451,7 +453,7 @@ static int parse_config_file(const char *uname, int ctrl, { FILE *fil; char buf[LINE_LENGTH]; - + #define CONF_FILE (pl->conf_file[0])?pl->conf_file:LIMITS_FILE /* check for the LIMITS_FILE */ if (ctrl & PAM_DEBUG_ARG) @@ -462,7 +464,7 @@ static int parse_config_file(const char *uname, int ctrl, return PAM_SERVICE_ERR; } #undef CONF_FILE - + /* init things */ memset(buf, 0, sizeof(buf)); /* start the show */ @@ -473,14 +475,14 @@ static int parse_config_file(const char *uname, int ctrl, char value[LINE_LENGTH]; int i,j; char *tptr; - + tptr = buf; /* skip the leading white space */ while (*tptr && isspace(*tptr)) tptr++; strncpy(buf, tptr, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; - + /* Rip off the comments */ tptr = strchr(buf,'#'); if (tptr) @@ -499,7 +501,7 @@ static int parse_config_file(const char *uname, int ctrl, memset(ltype, 0, sizeof(ltype)); memset(item, 0, sizeof(item)); memset(value, 0, sizeof(value)); - + i = sscanf(buf,"%s%s%s%s", domain, ltype, item, value); D(("scanned line[%d]: domain[%s], ltype[%s], item[%s], value[%s]", i, domain, ltype, item, value)); @@ -558,7 +560,7 @@ static int parse_config_file(const char *uname, int ctrl, } } fclose(fil); - return PAM_SUCCESS; + return PAM_SUCCESS; } static int setup_limits(const char * uname, uid_t uid, int ctrl, @@ -588,7 +590,7 @@ static int setup_limits(const char * uname, uid_t uid, int ctrl, } status |= setrlimit(i, &pl->limits[i].limit); } - + if (status) { retval = LIMIT_ERR; } @@ -610,7 +612,7 @@ static int setup_limits(const char * uname, uid_t uid, int ctrl, return retval; } - + /* now the session stuff */ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) @@ -631,7 +633,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, _pam_log(LOG_CRIT, "open_session - error recovering username"); return PAM_SESSION_ERR; } - + pwd = getpwnam(user_name); if (!pwd) { if (ctrl & PAM_DEBUG_ARG) @@ -639,7 +641,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, user_name); return PAM_SESSION_ERR; } - + retval = init_limits(&pl); if (retval != PAM_SUCCESS) { _pam_log(LOG_WARNING, "cannot initialize"); @@ -705,13 +707,13 @@ struct pam_module _pam_limits_modstruct = { * 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 diff --git a/modules/pam_mail/pam_mail.c b/modules/pam_mail/pam_mail.c index 35a6b9f2..4888a1a5 100644 --- a/modules/pam_mail/pam_mail.c +++ b/modules/pam_mail/pam_mail.c @@ -32,7 +32,7 @@ #define MAIL_ENV_FORMAT MAIL_ENV_NAME "=%s" #define YOUR_MAIL_VERBOSE_FORMAT "You have %s mail in %s." #define YOUR_MAIL_STANDARD_FORMAT "You have %smail." -#define NO_MAIL_STANDARD_FORMAT "No mail." +#define NO_MAIL_STANDARD_FORMAT "No mail." /* * here, we make a definition for the externally accessible function @@ -142,8 +142,8 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs D(("begin to converse")); - retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ; - if ( retval == PAM_SUCCESS ) { + retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ; + if ( retval == PAM_SUCCESS && conv ) { retval = conv->conv(nargs, ( const struct pam_message ** ) message , response, conv->appdata_ptr); @@ -158,6 +158,8 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs } else { _log_err(LOG_ERR, "couldn't obtain coversation function [%s]" , pam_strerror(pamh, retval)); + if (retval == PAM_SUCCESS) + retval = PAM_BAD_ITEM; /* conv was NULL */ } D(("ready to return from module conversation")); @@ -234,7 +236,9 @@ static int get_folder(pam_handle_t *pamh, int ctrl, _pam_overwrite(hash); _pam_drop(hash); } else { - sprintf(folder, "error"); + _pam_drop(folder); + _log_err(LOG_CRIT, "out of memory for mail folder"); + return PAM_BUF_ERR; } } D(("folder =[%s]", folder)); @@ -386,7 +390,7 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc ,const char **argv) { - return _do_mail(pamh,flags,argc,argv,0);; + return _do_mail(pamh,flags,argc,argv,0); } /* Checking mail as part of the session management */ @@ -467,8 +471,8 @@ static int _do_mail(pam_handle_t *pamh, int flags, int argc, type = NULL; } } - - /* Delete environment variable? */ + + /* Delete environment variable? */ if (!est) (void) pam_putenv(pamh, MAIL_ENV_NAME); diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index c6d49301..342637c1 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -111,7 +111,7 @@ static int converse(pam_handle_t * pamh, int ctrl, int nargs D(("begin to converse")); retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv); - if (retval == PAM_SUCCESS) + if (retval == PAM_SUCCESS && conv) { retval = conv->conv(nargs, (const struct pam_message **) message @@ -130,6 +130,8 @@ static int converse(pam_handle_t * pamh, int ctrl, int nargs { _log_err(LOG_ERR, "couldn't obtain coversation function [%s]" ,pam_strerror(pamh, retval)); + if (retval == PAM_SUCCESS) + retval = PAM_BAD_ITEM; /* conv was NULL */ } D(("ready to return from module conversation")); @@ -235,7 +237,11 @@ static int create_homedir(pam_handle_t * pamh, int ctrl, /* If it's a directory, recurse. */ if (S_ISDIR(St.st_mode)) { - create_homedir(pamh, ctrl, pwd, newsource, newdest); + int retval = create_homedir(pamh, ctrl, pwd, newsource, newdest); + if (retval != PAM_SUCCESS) { + closedir(D); + return retval; + } continue; } @@ -250,6 +256,7 @@ static int create_homedir(pam_handle_t * pamh, int ctrl, { if (lchown(newdest,pwd->pw_uid,pwd->pw_gid) != 0) { + closedir(D); _log_err(LOG_DEBUG, "unable to chang perms on link %s", newdest); return PAM_PERM_DENIED; @@ -269,6 +276,7 @@ static int create_homedir(pam_handle_t * pamh, int ctrl, /* Open the source file */ if ((SrcFd = open(newsource,O_RDONLY)) < 0 || fstat(SrcFd,&St) != 0) { + closedir(D); _log_err(LOG_DEBUG, "unable to open src file %s",newsource); return PAM_PERM_DENIED; } @@ -278,6 +286,7 @@ static int create_homedir(pam_handle_t * pamh, int ctrl, if ((DestFd = open(newdest,O_WRONLY | O_TRUNC | O_CREAT,0600)) < 0) { close(SrcFd); + closedir(D); _log_err(LOG_DEBUG, "unable to open dest file %s",newdest); return PAM_PERM_DENIED; } @@ -290,6 +299,7 @@ static int create_homedir(pam_handle_t * pamh, int ctrl, { close(SrcFd); close(DestFd); + closedir(D); _log_err(LOG_DEBUG, "unable to chang perms on copy %s",newdest); return PAM_PERM_DENIED; } @@ -297,19 +307,29 @@ static int create_homedir(pam_handle_t * pamh, int ctrl, /* Copy the file */ do { - Res = read(SrcFd,remark,sizeof(remark)); - if (Res < 0 || write(DestFd,remark,Res) != Res) - { - close(SrcFd); - close(DestFd); - _log_err(LOG_DEBUG, "unable to perform IO"); - return PAM_PERM_DENIED; + Res = _pammodutil_read(SrcFd,remark,sizeof(remark)); + + if (Res == 0) + continue; + + if (Res > 0) { + if (_pammodutil_write(DestFd,remark,Res) == Res) + continue; } + + /* If we get here, pammodutil_read returned a -1 or + _pammodutil_write returned something unexpected. */ + close(SrcFd); + close(DestFd); + closedir(D); + _log_err(LOG_DEBUG, "unable to perform IO"); + return PAM_PERM_DENIED; } while (Res != 0); close(SrcFd); close(DestFd); } + closedir(D); return PAM_SUCCESS; } diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c index 759cc017..b1d9c9d9 100644 --- a/modules/pam_motd/pam_motd.c +++ b/modules/pam_motd/pam_motd.c @@ -33,6 +33,7 @@ #define DEFAULT_MOTD "/etc/motd" #include +#include /* --- session management functions (only) --- */ @@ -80,24 +81,33 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, if ((fd = open(motd_path, O_RDONLY, 0)) >= 0) { /* fill in message buffer with contents of motd */ - if ((fstat(fd, &st) < 0) || !st.st_size) + if ((fstat(fd, &st) < 0) || !st.st_size) { + close(fd); return retval; + } message.msg = mtmp = malloc(st.st_size+1); /* if malloc failed... */ - if (!message.msg) return retval; - read(fd, mtmp, st.st_size); - if (mtmp[st.st_size-1] == '\n') - mtmp[st.st_size-1] = '\0'; - else - mtmp[st.st_size] = '\0'; - close(fd); - /* Use conversation function to give user contents of motd */ - pam_get_item(pamh, PAM_CONV, (const void **)&conversation); - conversation->conv(1, (const struct pam_message **)&pmessage, - &resp, conversation->appdata_ptr); + if (!message.msg) { + close(fd); + return retval; + } + if (_pammodutil_read(fd, mtmp, st.st_size) == st.st_size) { + if (mtmp[st.st_size-1] == '\n') + mtmp[st.st_size-1] = '\0'; + else + mtmp[st.st_size] = '\0'; + close(fd); + + /* Use conversation function to give user contents of motd */ + if (pam_get_item(pamh, PAM_CONV, (const void **)&conversation) == + PAM_SUCCESS && conversation) { + conversation->conv(1, (const struct pam_message **)&pmessage, + &resp, conversation->appdata_ptr); + if (resp) + _pam_drop_reply(resp, 1); + } + } free(mtmp); - if (resp) - _pam_drop_reply(resp, 1); } return retval; diff --git a/modules/pam_nologin/pam_nologin.c b/modules/pam_nologin/pam_nologin.c index 6916a7b4..433d2e11 100644 --- a/modules/pam_nologin/pam_nologin.c +++ b/modules/pam_nologin/pam_nologin.c @@ -117,22 +117,31 @@ static int perform_check(pam_handle_t *pamh, struct opt_s *opts) 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 - */ + if (_pammodutil_read(fd, mtmp, st.st_size) == st.st_size) { + mtmp[st.st_size] = '\000'; + + /* + * Use conversation function to give user contents + * of /etc/nologin + */ + + retval = pam_get_item(pamh, PAM_CONV, + (const void **)&conversation); + if ((retval == PAM_SUCCESS) && (conversation)) { + (void) conversation->conv(1, + (const struct pam_message **)&pmessage, + &resp, conversation->appdata_ptr); + + if (resp) { + _pam_drop_reply(resp, 1); + } + } + } + else + retval = PAM_SYSTEM_ERR; - 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); diff --git a/modules/pam_permit/pam_permit.c b/modules/pam_permit/pam_permit.c index ea23b312..9eee5611 100644 --- a/modules/pam_permit/pam_permit.c +++ b/modules/pam_permit/pam_permit.c @@ -45,7 +45,9 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc } if (user == NULL || *user == '\0') { D(("username not known")); - pam_set_item(pamh, PAM_USER, (const void *) DEFAULT_USER); + retval = pam_set_item(pamh, PAM_USER, (const void *) DEFAULT_USER); + if (retval != PAM_SUCCESS) + return PAM_USER_UNKNOWN; } user = NULL; /* clean up */ diff --git a/modules/pam_shells/pam_shells.c b/modules/pam_shells/pam_shells.c index 37d740dc..c9e2ed6c 100644 --- a/modules/pam_shells/pam_shells.c +++ b/modules/pam_shells/pam_shells.c @@ -59,11 +59,16 @@ static int perform_check(pam_handle_t *pamh, int flags) return PAM_SERVICE_ERR; } - if (!userName || (strlen(userName) <= 0)) { + if (!userName || (userName[0] == '\0')) { + /* Don't let them use a NULL username... */ - pam_get_user(pamh,&userName,NULL); + retval = pam_get_user(pamh,&userName,NULL); if (retval != PAM_SUCCESS) return PAM_SERVICE_ERR; + + /* It could still be NULL the second time. */ + if (!userName || (userName[0] == '\0')) + return PAM_SERVICE_ERR; } pw = getpwnam(userName); @@ -93,7 +98,7 @@ static int perform_check(pam_handle_t *pamh, int flags) retval = 1; - while((fgets(shellFileLine, 255, shellFile) != NULL) && retval) { + while(retval && (fgets(shellFileLine, 255, shellFile) != NULL)) { if (shellFileLine[strlen(shellFileLine) - 1] == '\n') shellFileLine[strlen(shellFileLine) - 1] = '\0'; retval = strcmp(shellFileLine, userShell); diff --git a/modules/pam_stress/pam_stress.c b/modules/pam_stress/pam_stress.c index 7828f421..d45ad300 100644 --- a/modules/pam_stress/pam_stress.c +++ b/modules/pam_stress/pam_stress.c @@ -31,13 +31,6 @@ #include #include -static char *_strdup(const char *x) -{ - char *new; - new = malloc(strlen(x)+1); - strcpy(new,x); - return new; -} /* log errors */ @@ -141,8 +134,8 @@ static int converse(pam_handle_t *pamh, int nargs int retval; struct pam_conv *conv; - if ((retval = pam_get_item(pamh,PAM_CONV,(const void **)&conv)) - == PAM_SUCCESS) { + retval = pam_get_item(pamh,PAM_CONV,(const void **)&conv); + if (retval == PAM_SUCCESS && conv) { retval = conv->conv(nargs, (const struct pam_message **) message , response, conv->appdata_ptr); if (retval != PAM_SUCCESS) { @@ -151,6 +144,8 @@ static int converse(pam_handle_t *pamh, int nargs } } else { _pam_log(LOG_ERR,"(pam_stress) converse failed to get pam_conv"); + if (retval == PAM_SUCCESS) + retval = PAM_BAD_ITEM; /* conv was null */ } return retval; @@ -167,7 +162,8 @@ static int stress_get_password(pam_handle_t *pamh, int flags && (pam_get_item(pamh,PAM_AUTHTOK,(const void **)&pass) == PAM_SUCCESS) && (pass != NULL) ) { - pass = _strdup(pass); + if ((pass = strdup(pass)) == NULL) + return PAM_BUF_ERR; } else if ((ctrl & PAM_ST_USE_PASS1)) { _pam_log(LOG_WARNING, "pam_stress: no forwarded password"); return PAM_PERM_DENIED; @@ -206,7 +202,8 @@ static int stress_get_password(pam_handle_t *pamh, int flags _pam_log(LOG_DEBUG,"getting password, but NULL returned!?"); return PAM_CONV_ERR; } - free(resp); + if (resp) + free(resp); } *password = pass; /* this *MUST* be free()'d by this module */ @@ -238,12 +235,15 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* try to get the username */ retval = pam_get_user(pamh, &username, "username: "); - if ((ctrl & PAM_ST_DEBUG) && (retval == PAM_SUCCESS)) { - _pam_log(LOG_DEBUG, "pam_sm_authenticate: username = %s", username); - } else if (retval != PAM_SUCCESS) { + if (retval != PAM_SUCCESS || !username) { _pam_log(LOG_WARNING, "pam_sm_authenticate: failed to get username"); + if (retval == PAM_SUCCESS) + retval = PAM_USER_UNKNOWN; /* username was null */ return retval; } + else if ((ctrl & PAM_ST_DEBUG) && (retval == PAM_SUCCESS)) { + _pam_log(LOG_DEBUG, "pam_sm_authenticate: username = %s", username); + } /* now get the password */ @@ -257,20 +257,15 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* try to set password item */ retval = pam_set_item(pamh,PAM_AUTHTOK,pass); + _pam_overwrite(pass); /* clean up local copy of password */ + free(pass); + pass = NULL; if (retval != PAM_SUCCESS) { _pam_log(LOG_WARNING, "pam_sm_authenticate: " "failed to store new password"); - _pam_overwrite(pass); - free(pass); return retval; } - /* clean up local copy of password */ - - _pam_overwrite(pass); - free(pass); - pass = NULL; - /* if we are debugging then we print the password */ if (ctrl & PAM_ST_DEBUG) { @@ -319,9 +314,18 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, if (ctrl & PAM_ST_FAIL_1) return PAM_PERM_DENIED; else if (ctrl & PAM_ST_EXPIRED) { - void *text = malloc(sizeof("yes")+1); - strcpy(text,"yes"); - pam_set_data(pamh,"stress_new_pwd",text,wipe_up); + int retval; + void *text = strdup("yes"); + if (!text) + return PAM_BUF_ERR; + retval = pam_set_data(pamh,"stress_new_pwd",text,wipe_up); + if (retval != PAM_SUCCESS) { + _pam_log(LOG_DEBUG, + "pam_sm_acct_mgmt: failed setting stress_new_pwd"); + free(text); + return retval; + } + if (ctrl & PAM_ST_DEBUG) { _pam_log(LOG_DEBUG,"pam_sm_acct_mgmt: need a new password"); } @@ -343,9 +347,9 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, _pam_report(ctrl,"pam_sm_open_session", flags, argc, argv); if ((pam_get_item(pamh, PAM_USER, (const void **) &username) - != PAM_SUCCESS) + != PAM_SUCCESS || !username) || (pam_get_item(pamh, PAM_SERVICE, (const void **) &service) - != PAM_SUCCESS)) { + != PAM_SUCCESS || !service)) { _pam_log(LOG_WARNING,"pam_sm_open_session: for whom?"); return PAM_SESSION_ERR; } @@ -371,9 +375,9 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, _pam_report(ctrl,"pam_sm_close_session", flags, argc, argv); if ((pam_get_item(pamh, PAM_USER, (const void **)&username) - != PAM_SUCCESS) + != PAM_SUCCESS || !username) || (pam_get_item(pamh, PAM_SERVICE, (const void **)&service) - != PAM_SUCCESS)) { + != PAM_SUCCESS || !service)) { _pam_log(LOG_WARNING,"pam_sm_close_session: for whom?"); return PAM_SESSION_ERR; } @@ -447,15 +451,14 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, return retval; } retval = pam_set_item(pamh, PAM_OLDAUTHTOK, pass); + _pam_overwrite(pass); + free(pass); + pass = NULL; if (retval != PAM_SUCCESS) { _pam_log(LOG_DEBUG ,"pam_sm_chauthtok: could not set OLDAUTHTOK"); - _pam_overwrite(pass); - free(pass); return retval; } - _pam_overwrite(pass); - free(pass); } /* set up for conversation */ @@ -516,7 +519,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, pmsg[0] = &msg[0]; msg[0].msg_style = PAM_ERROR_MSG; msg[0].msg = "Verification mis-typed; " - "password unchaged"; + "password unchanged"; resp = NULL; (void) converse(pamh,1,pmsg,&resp); if (resp) { diff --git a/modules/pam_tally/pam_tally.c b/modules/pam_tally/pam_tally.c index 3da37f40..27fe0b37 100644 --- a/modules/pam_tally/pam_tally.c +++ b/modules/pam_tally/pam_tally.c @@ -109,7 +109,7 @@ static char *cline_user=0; /* cline_user is used in the administration prog */ static int pam_get_uid( pam_handle_t *pamh, uid_t *uid, const char **userp ) { - const char *user; + const char *user = NULL; struct passwd *pw; #ifdef MAIN @@ -189,7 +189,8 @@ static int get_tally( tally_t *tally, if ( fseek( *TALLY, uid * sizeof(struct faillog), SEEK_SET ) ) { _pam_log(LOG_ALERT, "fseek failed %s", filename); - return PAM_AUTH_ERR; + fclose(*TALLY); + return PAM_AUTH_ERR; } if ( fileinfo.st_size <= uid * sizeof(struct faillog) ) { @@ -527,6 +528,8 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { user,uid, fsp->fs_fail_time+fsp->fs_faillog.fail_locktime -time(NULL)); + if (TALLY) + fclose(TALLY); return PAM_AUTH_ERR; } } @@ -537,6 +540,8 @@ PAM_FUNCTION( pam_sm_acct_mgmt ) { ) { _pam_log(LOG_NOTICE,"user %s ("UID_FMT") tally "TALLY_FMT", deny "TALLY_FMT, user, uid, tally, deny); + if (TALLY) + fclose(TALLY); return PAM_AUTH_ERR; /* Only unconditional failure */ } diff --git a/modules/pam_time/pam_time.c b/modules/pam_time/pam_time.c index 9cf68280..9858307e 100644 --- a/modules/pam_time/pam_time.c +++ b/modules/pam_time/pam_time.c @@ -8,7 +8,7 @@ * shadow-960129) */ -const static char rcsid[] = +static const char rcsid[] = "$Id$;\n" "\t\tVersion 0.22 for Linux-PAM\n" "Copyright (C) Andrew G. Morgan 1996 \n"; @@ -127,6 +127,7 @@ static int read_field(int fd, char **buf, int *from, int *to) i = read(fd, *to + *buf, PAM_TIME_BUFLEN - *to); if (i < 0) { _log_err("error reading " PAM_TIME_CONF); + close(fd); return -1; } else if (!i) { close(fd); @@ -166,6 +167,7 @@ static int read_field(int fd, char **buf, int *from, int *to) } else { _log_err("internal error in " __FILE__ " at line %d", __LINE__ ); + close(fd); return -1; } break; diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c index 67497e06..a0c1da81 100644 --- a/modules/pam_unix/pam_unix_auth.c +++ b/modules/pam_unix/pam_unix_auth.c @@ -15,13 +15,13 @@ * 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 @@ -88,7 +88,8 @@ do { \ *ret_data = retval; \ pam_set_data(pamh, "unix_setcred_return", \ (void *) ret_data, setcred_free); \ - } \ + } else if (ret_data) \ + free (ret_data); \ D(("done. [%s]", pam_strerror(pamh, retval))); \ return retval; \ } while (0) @@ -183,7 +184,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags } -/* +/* * The only thing _pam_set_credentials_unix() does is initialization of * UNIX group IDs. * @@ -203,7 +204,7 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags retval = PAM_SUCCESS; D(("recovering return code from auth call")); - /* We will only find something here if UNIX_LIKE_AUTH is set -- + /* We will only find something here if UNIX_LIKE_AUTH is set -- don't worry about an explicit check of argv. */ pam_get_data(pamh, "unix_setcred_return", (const void **) &pretval); if(pretval) { diff --git a/modules/pam_wheel/pam_wheel.c b/modules/pam_wheel/pam_wheel.c index 2ac1eecb..9545231b 100644 --- a/modules/pam_wheel/pam_wheel.c +++ b/modules/pam_wheel/pam_wheel.c @@ -112,7 +112,7 @@ static int perform_check(pam_handle_t *pamh, int flags, int ctrl, { const char *username = NULL; const char *fromsu; - struct passwd *pwd, *tpwd; + struct passwd *pwd, *tpwd = NULL; struct group *grp; int retval = PAM_AUTH_ERR; diff --git a/modules/pammodutil/Makefile b/modules/pammodutil/Makefile index b4868528..c1f1b9a7 100644 --- a/modules/pammodutil/Makefile +++ b/modules/pammodutil/Makefile @@ -19,7 +19,7 @@ CFLAGS += $(PIC) $(STATIC) $(MOREFLAGS) \ # all the object files we care about LIBOBJECTS = modutil_cleanup.o modutil_getpwnam.o modutil_getpwuid.o \ - modutil_getlogin.o + modutil_getlogin.o modutil_ioloop.o # static library name LIBSTATIC = $(LIBNAME).a diff --git a/modules/pammodutil/include/security/_pam_modutil.h b/modules/pammodutil/include/security/_pam_modutil.h index 5e063651..5b95e279 100644 --- a/modules/pammodutil/include/security/_pam_modutil.h +++ b/modules/pammodutil/include/security/_pam_modutil.h @@ -32,4 +32,8 @@ extern void _pammodutil_cleanup(pam_handle_t *pamh, void *data, extern const char *_pammodutil_getlogin(pam_handle_t *pamh); +extern int _pammodutil_read(int fd, char *buffer, int count); + +extern int _pammodutil_write(int fd, const char *buffer, int count); + #endif /* _PAM_MODUTIL_H */ diff --git a/modules/pammodutil/modutil_ioloop.c b/modules/pammodutil/modutil_ioloop.c new file mode 100644 index 00000000..4176b658 --- /dev/null +++ b/modules/pammodutil/modutil_ioloop.c @@ -0,0 +1,50 @@ +/* + * $Id$ + * + * These functions provides common methods for ensure a complete read or + * write occurs. It handles EINTR and partial read/write returns. + */ + +#include +#include + +int _pammodutil_read(int fd, char *buffer, int count) +{ + int block, offset = 0; + + while (count > 0) { + block = read(fd, &buffer[offset], count); + + if (block < 0) { + if (errno == EINTR) continue; + return block; + } + if (block == 0) return offset; + + offset += block; + count -= block; + } + + return offset; +} + +int _pammodutil_write(int fd, const char *buffer, int count) +{ + int block, offset = 0; + + while (count > 0) { + block = write(fd, &buffer[offset], count); + + if (block < 0) { + if (errno == EINTR) continue; + return block; + } + if (block == 0) return offset; + + offset += block; + count -= block; + } + + return offset; +} + -- cgit v1.2.3