From caf6fbd81a21a5bd5fac57a0163582bbc8968920 Mon Sep 17 00:00:00 2001 From: Will Andrews Date: Tue, 27 Aug 2013 15:50:26 +0000 Subject: [PATCH] Make the PAM password strength checking module WARNS=2 safe. lib/libpam/modules/pam_passwdqc/Makefile: Bump WARNS to 2. contrib/pam_modules/pam_passwdqc/pam_passwdqc.c: Bump _XOPEN_SOURCE and _XOPEN_VERSION from 500 to 600 so that vsnprint() is declared. Use the two new union types (pam_conv_item_t and pam_text_item_t) to resolve strict aliasing violations caused by casts to comply with the pam_get_item() API taking a "const void **" for all item types. Warnings are generated for casts that create "type puns" (pointers of conflicting sized types that are set to access the same memory location) since these pointers may be used in ways that violate C's strict aliasing rules. Casts to a new type must be performed through a union in order to be compliant, and access must be performed through only one of the union's data types during the lifetime of the union instance. Handle strict-aliasing warnings through pointer assignments, which drastically simplifies this change. Correct a CLANG "printf-like function with more arguments than format" error. Submitted by: gibbs Sponsored by: Spectra Logic --- .../pam_modules/pam_passwdqc/pam_passwdqc.c | 41 +++++++++++-------- lib/libpam/modules/pam_passwdqc/Makefile | 2 +- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/contrib/pam_modules/pam_passwdqc/pam_passwdqc.c b/contrib/pam_modules/pam_passwdqc/pam_passwdqc.c index 7c3973105cd2..e12d0b4f9109 100644 --- a/contrib/pam_modules/pam_passwdqc/pam_passwdqc.c +++ b/contrib/pam_modules/pam_passwdqc/pam_passwdqc.c @@ -2,9 +2,9 @@ * Copyright (c) 2000-2002 by Solar Designer. See LICENSE. */ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 600 #define _XOPEN_SOURCE_EXTENDED -#define _XOPEN_VERSION 500 +#define _XOPEN_VERSION 600 #include #include #include @@ -132,17 +132,19 @@ static params_t defaults = { static int converse(pam_handle_t *pamh, int style, lo_const char *text, struct pam_response **resp) { - struct pam_conv *conv; + pam_item_t item; + lo_const struct pam_conv *conv; struct pam_message msg, *pmsg; int status; - status = pam_get_item(pamh, PAM_CONV, (pam_item_t *)&conv); + status = pam_get_item(pamh, PAM_CONV, &item); if (status != PAM_SUCCESS) return status; + conv = item; pmsg = &msg; msg.msg_style = style; - msg.msg = text; + msg.msg = (char *)text; *resp = NULL; return conv->conv(1, (lo_const struct pam_message **)&pmsg, resp, @@ -294,8 +296,11 @@ static int parse(params_t *params, pam_handle_t *pamh, } if (argc) { - say(pamh, PAM_ERROR_MSG, getuid() != 0 ? - MESSAGE_MISCONFIGURED : MESSAGE_INVALID_OPTION, *argv); + if (getuid() != 0) { + say(pamh, PAM_ERROR_MSG, MESSAGE_MISCONFIGURED); + } else { + say(pamh, PAM_ERROR_MSG, MESSAGE_INVALID_OPTION, *argv); + } return PAM_ABORT; } @@ -311,7 +316,9 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, #ifdef HAVE_SHADOW struct spwd *spw; #endif - char *user, *oldpass, *newpass, *randompass; + pam_item_t item; + lo_const char *user, *oldpass, *curpass; + char *newpass, *randompass; const char *reason; int ask_oldauthtok; int randomonly, enforce, retries_left, retry_wanted; @@ -353,17 +360,19 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (flags & PAM_PRELIM_CHECK) return status; - status = pam_get_item(pamh, PAM_USER, (pam_item_t *)&user); + status = pam_get_item(pamh, PAM_USER, &item); if (status != PAM_SUCCESS) return status; + user = item; - status = pam_get_item(pamh, PAM_OLDAUTHTOK, (pam_item_t *)&oldpass); + status = pam_get_item(pamh, PAM_OLDAUTHTOK, &item); if (status != PAM_SUCCESS) return status; + oldpass = item; if (params.flags & F_NON_UNIX) { pw = &fake_pw; - pw->pw_name = user; + pw->pw_name = (char *)user; pw->pw_gecos = ""; } else { pw = getpwnam(user); @@ -405,13 +414,13 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, enforce = params.flags & F_ENFORCE_ROOT; if (params.flags & F_USE_AUTHTOK) { - status = pam_get_item(pamh, PAM_AUTHTOK, - (pam_item_t *)&newpass); + status = pam_get_item(pamh, PAM_AUTHTOK, &item); if (status != PAM_SUCCESS) return status; - if (!newpass || (check_max(¶ms, pamh, newpass) && enforce)) + curpass = item; + if (!curpass || (check_max(¶ms, pamh, curpass) && enforce)) return PAM_AUTHTOK_ERR; - reason = _passwdqc_check(¶ms.qc, newpass, oldpass, pw); + reason = _passwdqc_check(¶ms.qc, curpass, oldpass, pw); if (reason) { say(pamh, PAM_ERROR_MSG, MESSAGE_WEAKPASS, reason); if (enforce) @@ -487,7 +496,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (!newpass) { if (randompass) _pam_overwrite(randompass); - return PAM_AUTHTOK_ERR; + return status; } if (check_max(¶ms, pamh, newpass) && enforce) { diff --git a/lib/libpam/modules/pam_passwdqc/Makefile b/lib/libpam/modules/pam_passwdqc/Makefile index 905afe1c7eb6..c9cc30e52342 100644 --- a/lib/libpam/modules/pam_passwdqc/Makefile +++ b/lib/libpam/modules/pam_passwdqc/Makefile @@ -7,7 +7,7 @@ LIB= pam_passwdqc SRCS= pam_passwdqc.c passwdqc_check.c passwdqc_random.c wordset_4k.c MAN= pam_passwdqc.8 -WARNS?= 0 +WARNS?= 2 CFLAGS+= -I${SRCDIR} DPADD= ${LIBCRYPT}