libpam: make use of secure memory erasure

Non trivial changes:

  - erase responses in pam_get_authtok_internal() on error branch
This commit is contained in:
Christian Göttsche 2023-01-30 17:55:27 +01:00
parent 19a2926817
commit e2d01a42c1
7 changed files with 48 additions and 41 deletions

View File

@ -161,7 +161,7 @@ pam_read_passwords(int fd, int npass, char **passwords)
if (npass > 0) {
memcpy(passwords[i], pptr, rbytes);
}
memset(pptr, '\0', rbytes);
pam_overwrite_n(pptr, rbytes);
}
}
offset += rbytes;
@ -169,7 +169,7 @@ pam_read_passwords(int fd, int npass, char **passwords)
/* clear up */
if (offset > 0 && npass > 0) {
memset(passwords[i], '\0', offset);
pam_overwrite_n(passwords[i], offset);
}
return i;

View File

@ -5,6 +5,7 @@
*/
#include "pam_private.h"
#include "pam_inline.h"
#include <stdlib.h>
@ -41,34 +42,34 @@ int pam_end(pam_handle_t *pamh, int pam_status)
_pam_drop_env(pamh); /* purge the environment */
_pam_overwrite(pamh->authtok); /* blank out old token */
pam_overwrite_string(pamh->authtok); /* blank out old token */
_pam_drop(pamh->authtok);
_pam_overwrite(pamh->oldauthtok); /* blank out old token */
pam_overwrite_string(pamh->oldauthtok); /* blank out old token */
_pam_drop(pamh->oldauthtok);
_pam_overwrite(pamh->former.prompt);
pam_overwrite_string(pamh->former.prompt);
_pam_drop(pamh->former.prompt); /* drop saved prompt */
_pam_overwrite(pamh->service_name);
pam_overwrite_string(pamh->service_name);
_pam_drop(pamh->service_name);
_pam_overwrite(pamh->user);
pam_overwrite_string(pamh->user);
_pam_drop(pamh->user);
_pam_overwrite(pamh->confdir);
pam_overwrite_string(pamh->confdir);
_pam_drop(pamh->confdir);
_pam_overwrite(pamh->prompt);
pam_overwrite_string(pamh->prompt);
_pam_drop(pamh->prompt); /* prompt for pam_get_user() */
_pam_overwrite(pamh->tty);
pam_overwrite_string(pamh->tty);
_pam_drop(pamh->tty);
_pam_overwrite(pamh->rhost);
pam_overwrite_string(pamh->rhost);
_pam_drop(pamh->rhost);
_pam_overwrite(pamh->ruser);
pam_overwrite_string(pamh->ruser);
_pam_drop(pamh->ruser);
_pam_drop(pamh->pam_conversation);
@ -76,16 +77,16 @@ int pam_end(pam_handle_t *pamh, int pam_status)
_pam_drop(pamh->former.substates);
_pam_overwrite(pamh->xdisplay);
pam_overwrite_string(pamh->xdisplay);
_pam_drop(pamh->xdisplay);
_pam_overwrite(pamh->xauth.name);
pam_overwrite_string(pamh->xauth.name);
_pam_drop(pamh->xauth.name);
_pam_overwrite_n(pamh->xauth.data, (unsigned int)pamh->xauth.datalen);
pam_overwrite_n(pamh->xauth.data, (unsigned int)pamh->xauth.datalen);
_pam_drop(pamh->xauth.data);
_pam_overwrite_n((char *)&pamh->xauth, sizeof(pamh->xauth));
pam_overwrite_object(&pamh->xauth);
_pam_overwrite(pamh->authtok_type);
pam_overwrite_string(pamh->authtok_type);
_pam_drop(pamh->authtok_type);
/* and finally liberate the memory for the pam_handle structure */

View File

@ -11,6 +11,7 @@
*/
#include "pam_private.h"
#include "pam_inline.h"
#include <string.h>
#include <stdlib.h>
@ -100,7 +101,7 @@ void _pam_drop_env(pam_handle_t *pamh)
for (i=pamh->env->requested-1; i-- > 0; ) {
D(("dropping #%3d>%s<", i, pamh->env->list[i]));
_pam_overwrite(pamh->env->list[i]); /* clean */
pam_overwrite_string(pamh->env->list[i]); /* clean */
_pam_drop(pamh->env->list[i]); /* forget */
}
pamh->env->requested = 0;
@ -227,7 +228,7 @@ int pam_putenv(pam_handle_t *pamh, const char *name_value)
} else { /* replace old */
D(("replacing item: %s\n with: %s"
, pamh->env->list[item], name_value));
_pam_overwrite(pamh->env->list[item]);
pam_overwrite_string(pamh->env->list[item]);
_pam_drop(pamh->env->list[item]);
}
@ -261,7 +262,7 @@ int pam_putenv(pam_handle_t *pamh, const char *name_value)
*/
D(("deleting: env#%3d:[%s]", item, pamh->env->list[item]));
_pam_overwrite(pamh->env->list[item]);
pam_overwrite_string(pamh->env->list[item]);
_pam_drop(pamh->env->list[item]);
--(pamh->env->requested);
D(("mmove: item[%d]+%d -> item[%d]"
@ -341,7 +342,7 @@ static char **_copy_env(pam_handle_t *pamh)
/* out of memory */
while (dump[++i]) {
_pam_overwrite(dump[i]);
pam_overwrite_string(dump[i]);
_pam_drop(dump[i]);
}
_pam_drop(dump);

View File

@ -33,6 +33,7 @@
#include "config.h"
#include "pam_private.h"
#include "pam_inline.h"
#include <security/pam_ext.h>
@ -174,6 +175,10 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item,
(chpass > 1 && resp[1] == NULL))
{
/* We want to abort */
pam_overwrite_string (resp[0]);
_pam_drop (resp[0]);
pam_overwrite_string (resp[1]);
_pam_drop (resp[1]);
if (chpass)
pam_error (pamh, _("Password change has been aborted."));
return PAM_AUTHTOK_ERR;
@ -182,18 +187,18 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item,
if (chpass > 1 && strcmp (resp[0], resp[1]) != 0)
{
pam_error (pamh, MISTYPED_PASS);
_pam_overwrite (resp[0]);
pam_overwrite_string (resp[0]);
_pam_drop (resp[0]);
_pam_overwrite (resp[1]);
pam_overwrite_string (resp[1]);
_pam_drop (resp[1]);
return PAM_TRY_AGAIN;
}
_pam_overwrite (resp[1]);
pam_overwrite_string (resp[1]);
_pam_drop (resp[1]);
retval = pam_set_item (pamh, item, resp[0]);
_pam_overwrite (resp[0]);
pam_overwrite_string (resp[0]);
_pam_drop (resp[0]);
if (retval != PAM_SUCCESS)
return retval;
@ -263,13 +268,13 @@ pam_get_authtok_verify (pam_handle_t *pamh, const char **authtok,
{
pam_set_item (pamh, PAM_AUTHTOK, NULL);
pam_error (pamh, MISTYPED_PASS);
_pam_overwrite (resp);
pam_overwrite_string (resp);
_pam_drop (resp);
return PAM_TRY_AGAIN;
}
retval = pam_set_item (pamh, PAM_AUTHTOK, resp);
_pam_overwrite (resp);
pam_overwrite_string (resp);
_pam_drop (resp);
if (retval != PAM_SUCCESS)
return retval;

View File

@ -1033,7 +1033,7 @@ void _pam_free_handlers_aux(struct handler **hp)
_pam_drop(h->argv); /* This is all allocated in a single chunk */
_pam_drop(h->mod_name);
h = h->next;
memset(last, 0, sizeof(*last));
pam_overwrite_object(last);
free(last);
}

View File

@ -5,6 +5,7 @@
*/
#include "pam_private.h"
#include "pam_inline.h"
#include <ctype.h>
#include <stdlib.h>
@ -79,7 +80,7 @@ int pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
*/
if (__PAM_FROM_MODULE(pamh)) {
if (pamh->authtok != item) {
_pam_overwrite(pamh->authtok);
pam_overwrite_string(pamh->authtok);
TRY_SET(pamh->authtok, item);
}
} else {
@ -95,7 +96,7 @@ int pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
*/
if (__PAM_FROM_MODULE(pamh)) {
if (pamh->oldauthtok != item) {
_pam_overwrite(pamh->oldauthtok);
pam_overwrite_string(pamh->oldauthtok);
TRY_SET(pamh->oldauthtok, item);
}
} else {
@ -139,24 +140,23 @@ int pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
if (&pamh->xauth == item)
break;
if (pamh->xauth.namelen) {
_pam_overwrite(pamh->xauth.name);
pam_overwrite_string(pamh->xauth.name);
free(pamh->xauth.name);
}
if (pamh->xauth.datalen) {
_pam_overwrite_n(pamh->xauth.data,
(unsigned int) pamh->xauth.datalen);
pam_overwrite_n(pamh->xauth.data, (unsigned int) pamh->xauth.datalen);
free(pamh->xauth.data);
}
pamh->xauth = *((const struct pam_xauth_data *) item);
if ((pamh->xauth.name=_pam_strdup(pamh->xauth.name)) == NULL) {
memset(&pamh->xauth, '\0', sizeof(pamh->xauth));
pam_overwrite_object(&pamh->xauth);
return PAM_BUF_ERR;
}
if ((pamh->xauth.data=_pam_memdup(pamh->xauth.data,
pamh->xauth.datalen)) == NULL) {
_pam_overwrite(pamh->xauth.name);
pam_overwrite_string(pamh->xauth.name);
free(pamh->xauth.name);
memset(&pamh->xauth, '\0', sizeof(pamh->xauth));
pam_overwrite_object(&pamh->xauth);
return PAM_BUF_ERR;
}
break;
@ -330,7 +330,7 @@ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt)
/* ok, we can resume where we left off last time */
pamh->former.want_user = PAM_FALSE;
_pam_overwrite(pamh->former.prompt);
pam_overwrite_string(pamh->former.prompt);
_pam_drop(pamh->former.prompt);
}
@ -388,7 +388,7 @@ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt)
* note 'resp' is allocated by the application and is
* correctly free()'d here
*/
_pam_drop_reply(resp, 1);
pam_drop_response(resp, 1);
}
D(("completed"));

View File

@ -40,10 +40,10 @@
#include <errno.h>
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <security/pam_ext.h>
#include "pam_private.h"
#include "pam_inline.h"
int
pam_vprompt (pam_handle_t *pamh, int style, char **response,
@ -88,10 +88,10 @@ pam_vprompt (pam_handle_t *pamh, int style, char **response,
*response = pam_resp == NULL ? NULL : pam_resp->resp;
else if (pam_resp && pam_resp->resp)
{
_pam_overwrite (pam_resp->resp);
pam_overwrite_string (pam_resp->resp);
_pam_drop (pam_resp->resp);
}
_pam_overwrite (msgbuf);
pam_overwrite_string (msgbuf);
_pam_drop (pam_resp);
free (msgbuf);
if (retval != PAM_SUCCESS)