diff options
author | Christian Göttsche <cgzones@googlemail.com> | 2023-01-30 17:56:58 +0100 |
---|---|---|
committer | Christian Göttsche <cgzones@googlemail.com> | 2023-02-28 15:13:15 +0100 |
commit | bcba17939e1b1a568cd4a764534cde74d37078cc (patch) | |
tree | 4f3630f53cd52c2afa59435f5d36db260c1bf4a1 /modules | |
parent | 87ff7a12a55c38873905636eb8d29b4542d828f5 (diff) | |
download | pam-bcba17939e1b1a568cd4a764534cde74d37078cc.tar.gz pam-bcba17939e1b1a568cd4a764534cde74d37078cc.tar.bz2 pam-bcba17939e1b1a568cd4a764534cde74d37078cc.zip |
modules: make use of secure memory erasure
Use empty initialization of structs to minimize the memset() usage, to
reduce the amount of calls which are not sensitive.
Non trivial changes:
- pam_env:
* erase environment variables where possible
- pam_exec:
* erase responce on error
* erase auth token
- pam_pwhistory:
* erase buffers containing old passwords
- pam_selinux: skip overwriting data structure consisting of only
pointers to insensitive data, which also gets free'd afterwards (so
it currently does not protect against double-free or use-after-free on
the member pointers)
- pam_unix: erase cipher data in more places
- pam_userdb: erase password hashes
Diffstat (limited to 'modules')
28 files changed, 140 insertions, 96 deletions
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c index f7b47227..f70b7e49 100644 --- a/modules/pam_access/pam_access.c +++ b/modules/pam_access/pam_access.c @@ -663,7 +663,7 @@ static int group_match (pam_handle_t *pamh, const char *tok, const char* usr, int debug) { - char grptok[BUFSIZ]; + char grptok[BUFSIZ] = {}; if (debug) pam_syslog (pamh, LOG_DEBUG, @@ -673,7 +673,6 @@ group_match (pam_handle_t *pamh, const char *tok, const char* usr, return NO; /* token is received under the format '(...)' */ - memset(grptok, 0, BUFSIZ); strncpy(grptok, tok + 1, strlen(tok) - 2); if (pam_modutil_user_in_group_nam_nam(pamh, usr, grptok)) diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c index 42842308..d2b4cb10 100644 --- a/modules/pam_env/pam_env.c +++ b/modules/pam_env/pam_env.c @@ -70,6 +70,7 @@ static void free_string_array(char **array) if (array == NULL) return; for (char **entry = array; *entry != NULL; ++entry) { + pam_overwrite_string(*entry); free(*entry); } free(array); @@ -402,6 +403,7 @@ static int read_file(const pam_handle_t *pamh, const char*filename, char ***line pam_syslog(pamh, LOG_ERR, "Cannot allocate memory."); (void) fclose(conf); free_string_array(*lines); + pam_overwrite_array(buffer); return PAM_BUF_ERR; } *lines = tmp; @@ -410,12 +412,14 @@ static int read_file(const pam_handle_t *pamh, const char*filename, char ***line pam_syslog(pamh, LOG_ERR, "Cannot allocate memory."); (void) fclose(conf); free_string_array(*lines); + pam_overwrite_array(buffer); return PAM_BUF_ERR; } (*lines)[i] = 0; } (void) fclose(conf); + pam_overwrite_array(buffer); return PAM_SUCCESS; } #endif @@ -580,12 +584,8 @@ _expand_arg(pam_handle_t *pamh, char **value) char type, tmpval[BUF_SIZE]; /* I know this shouldn't be hard-coded but it's so much easier this way */ - char tmp[MAX_ENV]; - size_t idx; - - D(("Remember to initialize tmp!")); - memset(tmp, 0, MAX_ENV); - idx = 0; + char tmp[MAX_ENV] = {}; + size_t idx = 0; /* * (possibly non-existent) environment variables can be used as values @@ -610,7 +610,7 @@ _expand_arg(pam_handle_t *pamh, char **value) D(("Variable buffer overflow: <%s> + <%s>", tmp, tmpptr)); pam_syslog (pamh, LOG_ERR, "Variable buffer overflow: <%s> + <%s>", tmp, tmpptr); - return PAM_BUF_ERR; + goto buf_err; } continue; } @@ -635,7 +635,7 @@ _expand_arg(pam_handle_t *pamh, char **value) D(("Unterminated expandable variable: <%s>", orig-2)); pam_syslog(pamh, LOG_ERR, "Unterminated expandable variable: <%s>", orig-2); - return PAM_ABORT; + goto abort_err; } strncpy(tmpval, orig, sizeof(tmpval)); tmpval[sizeof(tmpval)-1] = '\0'; @@ -661,7 +661,7 @@ _expand_arg(pam_handle_t *pamh, char **value) default: D(("Impossible error, type == <%c>", type)); pam_syslog(pamh, LOG_CRIT, "Impossible error, type == <%c>", type); - return PAM_ABORT; + goto abort_err; } /* switch */ if (tmpptr) { @@ -674,7 +674,7 @@ _expand_arg(pam_handle_t *pamh, char **value) D(("Variable buffer overflow: <%s> + <%s>", tmp, tmpptr)); pam_syslog (pamh, LOG_ERR, "Variable buffer overflow: <%s> + <%s>", tmp, tmpptr); - return PAM_BUF_ERR; + goto buf_err; } } } /* if ('{' != *orig++) */ @@ -686,7 +686,7 @@ _expand_arg(pam_handle_t *pamh, char **value) D(("Variable buffer overflow: <%s> + <%s>", tmp, tmpptr)); pam_syslog(pamh, LOG_ERR, "Variable buffer overflow: <%s> + <%s>", tmp, tmpptr); - return PAM_BUF_ERR; + goto buf_err; } } } /* for (;*orig;) */ @@ -697,14 +697,23 @@ _expand_arg(pam_handle_t *pamh, char **value) D(("Couldn't malloc %d bytes for expanded var", idx + 1)); pam_syslog (pamh, LOG_CRIT, "Couldn't malloc %lu bytes for expanded var", (unsigned long)idx+1); - return PAM_BUF_ERR; + goto buf_err; } } strcpy(*value, tmp); - memset(tmp, '\0', sizeof(tmp)); + pam_overwrite_array(tmp); + pam_overwrite_array(tmpval); D(("Exit.")); return PAM_SUCCESS; +buf_err: + pam_overwrite_array(tmp); + pam_overwrite_array(tmpval); + return PAM_BUF_ERR; +abort_err: + pam_overwrite_array(tmp); + pam_overwrite_array(tmpval); + return PAM_ABORT; } static int @@ -780,12 +789,15 @@ static void _clean_var(VAR *var) { if (var->name) { + pam_overwrite_string(var->name); free(var->name); } if (var->defval && ("e != var->defval)) { + pam_overwrite_string(var->defval); free(var->defval); } if (var->override && ("e != var->override)) { + pam_overwrite_string(var->override); free(var->override); } var->name = NULL; diff --git a/modules/pam_exec/pam_exec.c b/modules/pam_exec/pam_exec.c index aeb98cdc..9d2145dc 100644 --- a/modules/pam_exec/pam_exec.c +++ b/modules/pam_exec/pam_exec.c @@ -184,6 +184,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, if (retval != PAM_SUCCESS) { + pam_overwrite_string (resp); _pam_drop (resp); if (retval == PAM_CONV_AGAIN) retval = PAM_INCOMPLETE; @@ -194,6 +195,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, { pam_set_item (pamh, PAM_AUTHTOK, resp); strncpy (authtok, resp, sizeof(authtok) - 1); + pam_overwrite_string (resp); _pam_drop (resp); } } @@ -202,6 +204,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, if (pipe(fds) != 0) { + pam_overwrite_array(authtok); pam_syslog (pamh, LOG_ERR, "Could not create pipe: %m"); return PAM_SYSTEM_ERR; } @@ -212,18 +215,21 @@ call_exec (const char *pam_type, pam_handle_t *pamh, { if (pipe(stdout_fds) != 0) { + pam_overwrite_array(authtok); pam_syslog (pamh, LOG_ERR, "Could not create pipe: %m"); return PAM_SYSTEM_ERR; } stdout_file = fdopen(stdout_fds[0], "r"); if (!stdout_file) { + pam_overwrite_array(authtok); pam_syslog (pamh, LOG_ERR, "Could not fdopen pipe: %m"); return PAM_SYSTEM_ERR; } } if (optargc >= argc) { + pam_overwrite_array(authtok); pam_syslog (pamh, LOG_ERR, "No path given as argument"); return PAM_SERVICE_ERR; } @@ -231,13 +237,16 @@ call_exec (const char *pam_type, pam_handle_t *pamh, memset(&newsa, '\0', sizeof(newsa)); newsa.sa_handler = SIG_DFL; if (sigaction(SIGCHLD, &newsa, &oldsa) == -1) { + pam_overwrite_array(authtok); pam_syslog(pamh, LOG_ERR, "failed to reset SIGCHLD handler: %m"); return PAM_SYSTEM_ERR; } pid = fork(); - if (pid == -1) + if (pid == -1) { + pam_overwrite_array(authtok); return PAM_SYSTEM_ERR; + } if (pid > 0) /* parent */ { int status = 0; @@ -255,6 +264,8 @@ call_exec (const char *pam_type, pam_handle_t *pamh, close(fds[1]); } + pam_overwrite_array(authtok); + if (use_stdout) { char buf[4096]; @@ -325,6 +336,8 @@ call_exec (const char *pam_type, pam_handle_t *pamh, enum pam_modutil_redirect_fd redirect_stdout = (use_stdout || logfile) ? PAM_MODUTIL_IGNORE_FD : PAM_MODUTIL_NULL_FD; + pam_overwrite_array(authtok); + /* First, move all the pipes off of stdin, stdout, and stderr, to ensure * that calls to dup2 won't close them. */ diff --git a/modules/pam_ftp/pam_ftp.c b/modules/pam_ftp/pam_ftp.c index 441f2bba..41fb9f48 100644 --- a/modules/pam_ftp/pam_ftp.c +++ b/modules/pam_ftp/pam_ftp.c @@ -157,7 +157,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, GUEST_LOGIN_PROMPT); if (retval != PAM_SUCCESS) { - _pam_overwrite (resp); + pam_overwrite_string (resp); _pam_drop (resp); return ((retval == PAM_CONV_AGAIN) ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL); @@ -196,7 +196,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, } /* clean up */ - _pam_overwrite(resp); + pam_overwrite_string(resp); _pam_drop(resp); /* success or failure */ diff --git a/modules/pam_group/pam_group.c b/modules/pam_group/pam_group.c index c49358a1..6877849e 100644 --- a/modules/pam_group/pam_group.c +++ b/modules/pam_group/pam_group.c @@ -44,6 +44,7 @@ typedef enum { AND, OR } operator; #include <security/_pam_macros.h> #include <security/pam_modutil.h> #include <security/pam_ext.h> +#include "pam_inline.h" /* --- static functions for checking whether the user should be let in --- */ @@ -53,7 +54,7 @@ shift_buf(char *mem, int from) char *start = mem; while ((*mem = mem[from]) != '\0') ++mem; - memset(mem, '\0', PAM_GROUP_BUFLEN - (mem - start)); + pam_overwrite_n(mem, PAM_GROUP_BUFLEN - (mem - start)); return mem; } @@ -114,7 +115,7 @@ read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state, if (i < 0) { pam_syslog(pamh, LOG_ERR, "error reading %s: %m", conf_filename); close(fd); - memset(*buf, 0, PAM_GROUP_BUFLEN); + pam_overwrite_n(*buf, PAM_GROUP_BUFLEN); _pam_drop(*buf); *state = STATE_EOF; return -1; @@ -133,7 +134,7 @@ read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state, return -1; } - memset(to, '\0', PAM_GROUP_BUFLEN - (to - *buf)); + pam_overwrite_n(to, PAM_GROUP_BUFLEN - (to - *buf)); to = *buf; onspace = 1; /* delete any leading spaces */ @@ -744,7 +745,7 @@ static int check_account(pam_handle_t *pamh, const char *service, } if (grps) { /* tidy up */ - memset(grps, 0, sizeof(gid_t) * blk_size(no_grps)); + pam_overwrite_n(grps, sizeof(gid_t) * blk_size(no_grps)); _pam_drop(grps); no_grps = 0; } diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c index 797a61ce..ec515f56 100644 --- a/modules/pam_lastlog/pam_lastlog.c +++ b/modules/pam_lastlog/pam_lastlog.c @@ -366,11 +366,11 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid, time_t /* cleanup */ cleanup: - memset(&last_login, 0, sizeof(last_login)); - _pam_overwrite(date); - _pam_overwrite(host); + pam_overwrite_object(&last_login); + pam_overwrite_string(date); + pam_overwrite_string(host); _pam_drop(host); - _pam_overwrite(line); + pam_overwrite_string(line); _pam_drop(line); return retval; @@ -502,7 +502,7 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd, } /* cleanup */ - memset(&last_login, 0, sizeof(last_login)); + pam_overwrite_object(&last_login); return retval; } diff --git a/modules/pam_mail/pam_mail.c b/modules/pam_mail/pam_mail.c index 7eb94fc7..2b77e560 100644 --- a/modules/pam_mail/pam_mail.c +++ b/modules/pam_mail/pam_mail.c @@ -169,7 +169,7 @@ get_folder(pam_handle_t *pamh, int ctrl, hash[2 * i] = '\0'; rc = asprintf(&folder, MAIL_FILE_FORMAT, path, hash, pwd->pw_name); - _pam_overwrite(hash); + pam_overwrite_string(hash); _pam_drop(hash); if (rc < 0) goto get_folder_cleanup; @@ -211,7 +211,7 @@ get_mail_status(pam_handle_t *pamh, int ctrl, const char *folder) } i = scandir(dir, &namelist, 0, alphasort); save_errno = errno; - _pam_overwrite(dir); + pam_overwrite_string(dir); _pam_drop(dir); if (i < 0) { type = 0; @@ -232,7 +232,7 @@ get_mail_status(pam_handle_t *pamh, int ctrl, const char *folder) } i = scandir(dir, &namelist, 0, alphasort); save_errno = errno; - _pam_overwrite(dir); + pam_overwrite_string(dir); _pam_drop(dir); if (i < 0) { type = 0; @@ -264,7 +264,7 @@ get_mail_status(pam_handle_t *pamh, int ctrl, const char *folder) } get_mail_status_cleanup: - memset(&mail_st, 0, sizeof(mail_st)); + pam_overwrite_object(&mail_st); D(("user has %d mail in %s folder", type, folder)); return type; } @@ -415,7 +415,7 @@ static int _do_mail(pam_handle_t *pamh, int flags, int argc, } D(("setting env: %s", tmp)); retval = pam_putenv(pamh, tmp); - _pam_overwrite(tmp); + pam_overwrite_string(tmp); _pam_drop(tmp); if (retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_CRIT, @@ -457,7 +457,7 @@ static int _do_mail(pam_handle_t *pamh, int flags, int argc, (void) pam_putenv(pamh, MAIL_ENV_NAME); do_mail_cleanup: - _pam_overwrite(folder); + pam_overwrite_string(folder); _pam_drop(folder); /* indicate success or failure */ diff --git a/modules/pam_mkhomedir/mkhomedir_helper.c b/modules/pam_mkhomedir/mkhomedir_helper.c index 582fecce..3213f028 100644 --- a/modules/pam_mkhomedir/mkhomedir_helper.c +++ b/modules/pam_mkhomedir/mkhomedir_helper.c @@ -184,8 +184,7 @@ create_homedir(const struct passwd *pwd, else pointed[pointedlen] = 0; #else - char pointed[PATH_MAX]; - memset(pointed, 0, sizeof(pointed)); + char pointed[PATH_MAX] = {}; pointedlen = readlink(newsource, pointed, sizeof(pointed) - 1); #endif diff --git a/modules/pam_namespace/md5.c b/modules/pam_namespace/md5.c index 22e41ee0..07ad9a02 100644 --- a/modules/pam_namespace/md5.c +++ b/modules/pam_namespace/md5.c @@ -21,6 +21,8 @@ #include "md5.h" #include <string.h> +#include "pam_inline.h" + #define MD5Name(x) x #ifdef WORDS_BIGENDIAN @@ -149,7 +151,7 @@ void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i); byteReverse(ctx->buf.c, 4); memcpy(digest, ctx->buf.c, 16); - memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ + pam_overwrite_object(ctx); /* In case it's sensitive */ } /* The four core functions - F1 is optimized somewhat */ diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c index 1d3242ca..859b3da4 100644 --- a/modules/pam_pwhistory/opasswd.c +++ b/modules/pam_pwhistory/opasswd.c @@ -68,6 +68,7 @@ #include <security/pam_ext.h> #endif #include <security/pam_modules.h> +#include "pam_inline.h" #include "opasswd.h" @@ -129,6 +130,7 @@ compare_password(const char *newpass, const char *oldpass) char *outval; #ifdef HAVE_CRYPT_R struct crypt_data output; + int retval; output.initialized = 0; @@ -137,7 +139,9 @@ compare_password(const char *newpass, const char *oldpass) outval = crypt (newpass, oldpass); #endif - return outval != NULL && strcmp(outval, oldpass) == 0; + retval = outval != NULL && strcmp(outval, oldpass) == 0; + pam_overwrite_string(outval); + return retval; } /* Check, if the new password is already in the opasswd file. */ @@ -238,8 +242,8 @@ check_old_pass, const char *user, const char *newpass, const char *filename, int } while (oldpass != NULL); } - if (buf) - free (buf); + pam_overwrite_n(buf, buflen); + free (buf); return retval; } @@ -519,6 +523,7 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN } if (fputs (out, newpf) < 0) { + pam_overwrite_string(out); free (out); retval = PAM_AUTHTOK_ERR; if (oldpf) @@ -526,6 +531,7 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN fclose (newpf); goto error_opasswd; } + pam_overwrite_string(out); free (out); } @@ -571,6 +577,7 @@ save_old_pass, const char *user, int howmany, const char *filename, int debug UN rename (opasswd_tmp, opasswd_file); error_opasswd: unlink (opasswd_tmp); + pam_overwrite_n(buf, buflen); free (buf); return retval; diff --git a/modules/pam_pwhistory/pwhistory_helper.c b/modules/pam_pwhistory/pwhistory_helper.c index 7a61ae53..469d95fa 100644 --- a/modules/pam_pwhistory/pwhistory_helper.c +++ b/modules/pam_pwhistory/pwhistory_helper.c @@ -70,7 +70,7 @@ check_history(const char *user, const char *filename, const char *debug) retval = check_old_pass(user, pass, filename, dbg); - memset(pass, '\0', PAM_MAX_RESP_SIZE); /* clear memory of the password */ + pam_overwrite_array(pass); /* clear memory of the password */ return retval; } diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c index bf605c8b..e52e0fc4 100644 --- a/modules/pam_selinux/pam_selinux.c +++ b/modules/pam_selinux/pam_selinux.c @@ -393,7 +393,6 @@ free_module_data(module_data_t *data) freecon(data->prev_exec_context); if (data->exec_context != data->default_user_context) freecon(data->exec_context); - memset(data, 0, sizeof(*data)); free(data); } diff --git a/modules/pam_stress/pam_stress.c b/modules/pam_stress/pam_stress.c index 6c7a6251..b2c55586 100644 --- a/modules/pam_stress/pam_stress.c +++ b/modules/pam_stress/pam_stress.c @@ -18,6 +18,7 @@ #include <security/pam_modules.h> #include <security/_pam_macros.h> #include <security/pam_ext.h> +#include "pam_inline.h" /* ---------- */ @@ -240,7 +241,7 @@ 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 */ + pam_overwrite_string(pass); /* clean up local copy of password */ free(pass); pass = NULL; if (retval != PAM_SUCCESS) { @@ -432,7 +433,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, return retval; } retval = pam_set_item(pamh, PAM_OLDAUTHTOK, pass); - _pam_overwrite(pass); + pam_overwrite_string(pass); free(pass); pass = NULL; if (retval != PAM_SUCCESS) { @@ -495,7 +496,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (strcmp(resp[i-2].resp,resp[i-1].resp)) { /* passwords are not the same; forget and return error */ - _pam_drop_reply(resp, i); + pam_drop_response(resp, i); if (!(flags & PAM_SILENT) && !(ctrl & PAM_ST_NO_WARN)) { pmsg[0] = &msg[0]; @@ -505,7 +506,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, resp = NULL; (void) converse(pamh,1,pmsg,&resp); if (resp) { - _pam_drop_reply(resp, 1); + pam_drop_response(resp, 1); } } return PAM_AUTHTOK_ERR; @@ -523,7 +524,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, retval = PAM_SYSTEM_ERR; } - _pam_drop_reply(resp, i); /* clean up the passwords */ + pam_drop_response(resp, i); /* clean up the passwords */ } else { pam_syslog(pamh, LOG_ERR, "pam_sm_chauthtok: this must be a Linux-PAM error"); diff --git a/modules/pam_time/pam_time.c b/modules/pam_time/pam_time.c index 9092597a..6b7adefc 100644 --- a/modules/pam_time/pam_time.c +++ b/modules/pam_time/pam_time.c @@ -107,7 +107,7 @@ shift_buf(char *mem, int from) char *start = mem; while ((*mem = mem[from]) != '\0') ++mem; - memset(mem, '\0', PAM_TIME_BUFLEN - (mem - start)); + pam_overwrite_n(mem, PAM_TIME_BUFLEN - (mem - start)); return mem; } @@ -168,7 +168,7 @@ read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state, if (i < 0) { pam_syslog(pamh, LOG_ERR, "error reading %s: %m", file); close(fd); - memset(*buf, 0, PAM_TIME_BUFLEN); + pam_overwrite_n(*buf, PAM_TIME_BUFLEN); _pam_drop(*buf); *state = STATE_EOF; return -1; @@ -187,7 +187,7 @@ read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state, return -1; } - memset(to, '\0', PAM_TIME_BUFLEN - (to - *buf)); + pam_overwrite_n(to, PAM_TIME_BUFLEN - (to - *buf)); to = *buf; onspace = 1; /* delete any leading spaces */ diff --git a/modules/pam_timestamp/hmac_openssl_wrapper.c b/modules/pam_timestamp/hmac_openssl_wrapper.c index 926c2fb9..df772d60 100644 --- a/modules/pam_timestamp/hmac_openssl_wrapper.c +++ b/modules/pam_timestamp/hmac_openssl_wrapper.c @@ -144,7 +144,7 @@ read_file(pam_handle_t *pamh, int fd, char **text, size_t *text_length) if (bytes_read < (size_t)st.st_size) { pam_syslog(pamh, LOG_ERR, "Short read on key file"); - memset(tmp, 0, st.st_size); + pam_overwrite_n(tmp, st.st_size); free(tmp); return PAM_AUTH_ERR; } @@ -167,14 +167,14 @@ write_file(pam_handle_t *pamh, const char *file_name, char *text, S_IRUSR | S_IWUSR); if (fd == -1) { pam_syslog(pamh, LOG_ERR, "Unable to open [%s]: %m", file_name); - memset(text, 0, text_length); + pam_overwrite_n(text, text_length); free(text); return PAM_AUTH_ERR; } if (fchown(fd, owner, group) == -1) { pam_syslog(pamh, LOG_ERR, "Unable to change ownership [%s]: %m", file_name); - memset(text, 0, text_length); + pam_overwrite_n(text, text_length); free(text); close(fd); return PAM_AUTH_ERR; @@ -294,7 +294,7 @@ done: free(hmac_message); } if (key != NULL) { - memset(key, 0, key_length); + pam_overwrite_n(key, key_length); free(key); } if (ctx != NULL) { diff --git a/modules/pam_timestamp/hmacsha1.c b/modules/pam_timestamp/hmacsha1.c index 45a3cac2..384ccde8 100644 --- a/modules/pam_timestamp/hmacsha1.c +++ b/modules/pam_timestamp/hmacsha1.c @@ -48,6 +48,7 @@ #include <unistd.h> #include <syslog.h> #include <security/pam_ext.h> +#include "pam_inline.h" #include "hmacsha1.h" #include "sha1.h" @@ -107,7 +108,7 @@ hmac_key_create(pam_handle_t *pamh, const char *filename, size_t key_size, /* If we didn't get enough, stop here. */ if (count < key_size) { pam_syslog(pamh, LOG_ERR, "Short read on random device"); - memset(key, 0, key_size); + pam_overwrite_n(key, key_size); free(key); close(keyfd); return; @@ -122,7 +123,7 @@ hmac_key_create(pam_handle_t *pamh, const char *filename, size_t key_size, } count += i; } - memset(key, 0, key_size); + pam_overwrite_n(key, key_size); free(key); close(keyfd); } @@ -180,7 +181,7 @@ hmac_key_read(pam_handle_t *pamh, const char *filename, size_t default_key_size, /* Require that we got the expected amount of data. */ if (count < st.st_size) { - memset(tmp, 0, st.st_size); + pam_overwrite_n(tmp, st.st_size); free(tmp); return; } @@ -204,7 +205,7 @@ hmac_sha1_generate(void **mac, size_t *mac_length, const void *raw_key, size_t raw_key_size, const void *text, size_t text_length) { - unsigned char key[MAXIMUM_KEY_SIZE], tmp_key[MAXIMUM_KEY_SIZE]; + unsigned char key[MAXIMUM_KEY_SIZE] = {}, tmp_key[MAXIMUM_KEY_SIZE]; size_t maximum_key_size = SHA1_BLOCK_SIZE, minimum_key_size = SHA1_OUTPUT_SIZE; const unsigned char ipad = 0x36, opad = 0x5c; @@ -223,7 +224,6 @@ hmac_sha1_generate(void **mac, size_t *mac_length, /* If the key is too long, "compress" it, else copy it and pad it * out with zero bytes. */ - memset(key, 0, sizeof(key)); if (raw_key_size > maximum_key_size) { sha1_init(&sha1); sha1_update(&sha1, raw_key, raw_key_size); @@ -251,8 +251,8 @@ hmac_sha1_generate(void **mac, size_t *mac_length, sha1_output(&sha1, outer); /* We don't need any of the keys any more. */ - memset(key, 0, sizeof(key)); - memset(tmp_key, 0, sizeof(tmp_key)); + pam_overwrite_array(key); + pam_overwrite_array(tmp_key); /* Allocate space to store the output. */ *mac_length = sizeof(outer); @@ -284,7 +284,7 @@ hmac_sha1_generate_file(pam_handle_t *pamh, void **mac, size_t *mac_length, hmac_sha1_generate(mac, mac_length, key, key_length, text, text_length); - memset(key, 0, key_length); + pam_overwrite_n(key, key_length); free(key); } diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c index 572d9ff2..c5fa6dfc 100644 --- a/modules/pam_timestamp/pam_timestamp.c +++ b/modules/pam_timestamp/pam_timestamp.c @@ -95,7 +95,7 @@ static int check_dir_perms(pam_handle_t *pamh, const char *tdir) { - char scratch[BUFLEN]; + char scratch[BUFLEN] = {}; struct stat st; int i; /* Check that the directory is "safe". */ @@ -103,7 +103,6 @@ check_dir_perms(pam_handle_t *pamh, const char *tdir) return PAM_AUTH_ERR; } /* Iterate over the path, checking intermediate directories. */ - memset(scratch, 0, sizeof(scratch)); for (i = 0; (tdir[i] != '\0') && (i < (int)sizeof(scratch)); i++) { scratch[i] = tdir[i]; if ((scratch[i] == '/') || (tdir[i + 1] == '\0')) { diff --git a/modules/pam_unix/bigcrypt.c b/modules/pam_unix/bigcrypt.c index d8d61a4b..c1028668 100644 --- a/modules/pam_unix/bigcrypt.c +++ b/modules/pam_unix/bigcrypt.c @@ -29,6 +29,7 @@ #include <string.h> #include <stdlib.h> #include <security/_pam_macros.h> +#include "pam_inline.h" #ifdef HAVE_CRYPT_H #include <crypt.h> #endif @@ -56,12 +57,12 @@ char *bigcrypt(const char *key, const char *salt) #endif unsigned long int keylen, n_seg, j; char *cipher_ptr, *plaintext_ptr, *tmp_ptr, *salt_ptr; - char keybuf[KEYBUF_SIZE + 1]; + char keybuf[KEYBUF_SIZE + 1] = {}; D(("called with key='%s', salt='%s'.", key, salt)); /* reset arrays */ - dec_c2_cryptbuf = malloc(CBUF_SIZE); + dec_c2_cryptbuf = calloc(1, CBUF_SIZE); if (!dec_c2_cryptbuf) { return NULL; } @@ -73,8 +74,6 @@ char *bigcrypt(const char *key, const char *salt) } cdata->initialized = 0; #endif - memset(keybuf, 0, KEYBUF_SIZE + 1); - memset(dec_c2_cryptbuf, 0, CBUF_SIZE); /* fill KEYBUF_SIZE with key */ strncpy(keybuf, key, KEYBUF_SIZE); @@ -116,6 +115,7 @@ char *bigcrypt(const char *key, const char *salt) } /* and place in the static area */ strncpy(cipher_ptr, tmp_ptr, 13); + pam_overwrite_string(tmp_ptr); cipher_ptr += ESEGMENT_SIZE + SALT_SIZE; plaintext_ptr += SEGMENT_SIZE; /* first block of SEGMENT_SIZE */ @@ -136,9 +136,10 @@ char *bigcrypt(const char *key, const char *salt) tmp_ptr = crypt(plaintext_ptr, salt_ptr); #endif if (tmp_ptr == NULL) { - _pam_overwrite(dec_c2_cryptbuf); + pam_overwrite_string(dec_c2_cryptbuf); free(dec_c2_cryptbuf); #ifdef HAVE_CRYPT_R + pam_overwrite_object(cdata); free(cdata); #endif return NULL; @@ -146,6 +147,7 @@ char *bigcrypt(const char *key, const char *salt) /* skip the salt for seg!=0 */ strncpy(cipher_ptr, (tmp_ptr + SALT_SIZE), ESEGMENT_SIZE); + pam_overwrite_string(tmp_ptr); cipher_ptr += ESEGMENT_SIZE; plaintext_ptr += SEGMENT_SIZE; @@ -155,6 +157,7 @@ char *bigcrypt(const char *key, const char *salt) D(("key=|%s|, salt=|%s|\nbuf=|%s|\n", key, salt, dec_c2_cryptbuf)); #ifdef HAVE_CRYPT_R + pam_overwrite_object(cdata); free(cdata); #endif diff --git a/modules/pam_unix/md5.c b/modules/pam_unix/md5.c index 229112cf..95b8de4c 100644 --- a/modules/pam_unix/md5.c +++ b/modules/pam_unix/md5.c @@ -21,6 +21,8 @@ #include <string.h> #include "md5.h" +#include "pam_inline.h" + #ifndef HIGHFIRST #define byteReverse(buf, len) /* Nothing */ #else @@ -149,7 +151,7 @@ void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) MD5Name(MD5Transform)(ctx->buf.i, ctx->in.i); byteReverse(ctx->buf.i, 4); memcpy(digest, ctx->buf.c, 16); - memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ + pam_overwrite_object(ctx); /* In case it's sensitive */ } #ifndef ASM_MD5 diff --git a/modules/pam_unix/md5_crypt.c b/modules/pam_unix/md5_crypt.c index 94f7b434..ed5ecda4 100644 --- a/modules/pam_unix/md5_crypt.c +++ b/modules/pam_unix/md5_crypt.c @@ -87,7 +87,7 @@ char *MD5Name(crypt_md5)(const char *pw, const char *salt) MD5Name(MD5Update)(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl); /* Don't leave anything around in vm they could use. */ - memset(final, 0, sizeof final); + pam_overwrite_array(final); /* Then something really weird... */ for (j = 0, i = strlen(pw); i; i >>= 1) @@ -151,7 +151,7 @@ char *MD5Name(crypt_md5)(const char *pw, const char *salt) *p = '\0'; /* Don't leave anything around in vm they could use. */ - memset(final, 0, sizeof final); + pam_overwrite_array(final); return passwd; } diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 857ddd45..d5f5e51f 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -66,6 +66,7 @@ #include <security/pam_ext.h> #include <security/pam_modutil.h> +#include "pam_inline.h" #include "pam_cc_compat.h" #include "md5.h" #include "support.h" diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index c8ab49f3..81b10d88 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -96,7 +96,7 @@ PAMH_ARG_DECL(int verify_pwd_hash, } else if (*hash != '$' && hash_len >= 13) { pp = bigcrypt(p, hash); if (pp && hash_len == 13 && strlen(pp) > hash_len) { - _pam_overwrite(pp + hash_len); + pam_overwrite_string(pp + hash_len); } } else { /* @@ -147,7 +147,7 @@ PAMH_ARG_DECL(int verify_pwd_hash, if (cdata != NULL) { cdata->initialized = 0; pp = x_strdup(crypt_r(p, hash, cdata)); - memset(cdata, '\0', sizeof(*cdata)); + pam_overwrite_object(cdata); free(cdata); } #else @@ -427,7 +427,7 @@ PAMH_ARG_DECL(char * create_password_hash, #else char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */ #endif - char *sp; + char *sp, *ret; #ifdef HAVE_CRYPT_R struct crypt_data *cdata = NULL; #endif @@ -456,7 +456,7 @@ PAMH_ARG_DECL(char * create_password_hash, password = tmppass; } hashed = bigcrypt(password, salt); - memset(tmppass, '\0', sizeof(tmppass)); + pam_overwrite_array(tmppass); password = NULL; return hashed; } @@ -494,18 +494,21 @@ PAMH_ARG_DECL(char * create_password_hash, on(UNIX_SHA256_PASS, ctrl) ? "sha256" : on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid); if(sp) { - memset(sp, '\0', strlen(sp)); + pam_overwrite_string(sp); } #ifdef HAVE_CRYPT_R + pam_overwrite_object(cdata); free(cdata); #endif return NULL; } - sp = x_strdup(sp); + ret = strdup(sp); + pam_overwrite_string(sp); #ifdef HAVE_CRYPT_R + pam_overwrite_object(cdata); free(cdata); #endif - return sp; + return ret; } #ifdef WITH_SELINUX @@ -1090,7 +1093,7 @@ helper_verify_password(const char *name, const char *p, int nullok) } if (hash) { - _pam_overwrite(hash); + pam_overwrite_string(hash); _pam_drop(hash); } diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 27ca7127..23a30498 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -805,7 +805,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name } cleanup: - memset(pw, 0, sizeof(pw)); /* clear memory of the password */ + pam_overwrite_array(pw); /* clear memory of the password */ if (data_name) _pam_delete(data_name); if (salt) diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h index 19754dc1..81054002 100644 --- a/modules/pam_unix/support.h +++ b/modules/pam_unix/support.h @@ -151,10 +151,10 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = /* use this to free strings. ESPECIALLY password strings */ -#define _pam_delete(xx) \ -{ \ - _pam_overwrite(xx); \ - _pam_drop(xx); \ +#define _pam_delete(xx) \ +{ \ + pam_overwrite_string(xx); \ + _pam_drop(xx); \ } extern int _make_remark(pam_handle_t * pamh, unsigned long long ctrl, diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c index 3931bab2..556a2e2c 100644 --- a/modules/pam_unix/unix_chkpwd.c +++ b/modules/pam_unix/unix_chkpwd.c @@ -176,7 +176,7 @@ int main(int argc, char *argv[]) retval = helper_verify_password(user, pass, nullok); - memset(pass, '\0', PAM_MAX_RESP_SIZE); /* clear memory of the password */ + pam_overwrite_array(pass); /* clear memory of the password */ /* return pass or fail */ diff --git a/modules/pam_unix/unix_update.c b/modules/pam_unix/unix_update.c index 3559972b..49a70ff3 100644 --- a/modules/pam_unix/unix_update.c +++ b/modules/pam_unix/unix_update.c @@ -55,15 +55,18 @@ set_password(const char *forwho, const char *shadow, const char *remember) if (npass != 2) { /* is it a valid password? */ if (npass == 1) { helper_log_err(LOG_DEBUG, "no new password supplied"); - memset(pass, '\0', PAM_MAX_RESP_SIZE); + pam_overwrite_array(pass); } else { helper_log_err(LOG_DEBUG, "no valid passwords supplied"); } return PAM_AUTHTOK_ERR; } - if (lock_pwdf() != PAM_SUCCESS) + if (lock_pwdf() != PAM_SUCCESS) { + pam_overwrite_array(pass); + pam_overwrite_array(towhat); return PAM_AUTHTOK_LOCK_BUSY; + } pwd = getpwnam(forwho); @@ -98,8 +101,8 @@ set_password(const char *forwho, const char *shadow, const char *remember) } done: - memset(pass, '\0', PAM_MAX_RESP_SIZE); - memset(towhat, '\0', PAM_MAX_RESP_SIZE); + pam_overwrite_array(pass); + pam_overwrite_array(towhat); unlock_pwdf(); diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c index f467ea4c..297403b0 100644 --- a/modules/pam_userdb/pam_userdb.c +++ b/modules/pam_userdb/pam_userdb.c @@ -62,7 +62,7 @@ obtain_authtok(pam_handle_t *pamh) retval = pam_set_item(pamh, PAM_AUTHTOK, resp); /* clean it up */ - _pam_overwrite(resp); + pam_overwrite_string(resp); _pam_drop(resp); if ( (retval != PAM_SUCCESS) || @@ -181,7 +181,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, if (key.dptr) { data = dbm_fetch(dbm, key); - memset(key.dptr, 0, key.dsize); + pam_overwrite_n(key.dptr, key.dsize); free(key.dptr); } @@ -247,8 +247,11 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, free(cdata); #endif } + pam_overwrite_string(pwhash); free(pwhash); } + + pam_overwrite_string(cryptpw); } else { /* Unknown password encryption method - diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c index bbb7743b..f3e2a40d 100644 --- a/modules/pam_xauth/pam_xauth.c +++ b/modules/pam_xauth/pam_xauth.c @@ -141,7 +141,7 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output, if (child == 0) { /* We're the child. */ size_t j; - const char *args[10]; + const char *args[10] = {}; /* Drop privileges. */ if (setgid(gid) == -1) { @@ -181,8 +181,6 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output, PAM_MODUTIL_NULL_FD) < 0) { _exit(1); } - /* Initialize the argument list. */ - memset(args, 0, sizeof(args)); /* Convert the varargs list into a regular array of strings. */ va_start(ap, command); args[0] = command; @@ -564,9 +562,8 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, } /* Allocate enough space to hold an adjusted name. */ tlen = strlen(display) + LINE_MAX + 1; - t = malloc(tlen); + t = calloc(1, tlen); if (t != NULL) { - memset(t, 0, tlen); if (gethostname(t, tlen - 1) != -1) { /* Append the protocol and then the * screen number. */ |