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/pam_unix | |
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/pam_unix')
-rw-r--r-- | modules/pam_unix/bigcrypt.c | 13 | ||||
-rw-r--r-- | modules/pam_unix/md5.c | 4 | ||||
-rw-r--r-- | modules/pam_unix/md5_crypt.c | 4 | ||||
-rw-r--r-- | modules/pam_unix/pam_unix_passwd.c | 1 | ||||
-rw-r--r-- | modules/pam_unix/passverify.c | 19 | ||||
-rw-r--r-- | modules/pam_unix/support.c | 2 | ||||
-rw-r--r-- | modules/pam_unix/support.h | 8 | ||||
-rw-r--r-- | modules/pam_unix/unix_chkpwd.c | 2 | ||||
-rw-r--r-- | modules/pam_unix/unix_update.c | 11 |
9 files changed, 38 insertions, 26 deletions
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(); |