diff --git a/contrib/openpam/include/security/openpam.h b/contrib/openpam/include/security/openpam.h index eb12730345a..b001398e90e 100644 --- a/contrib/openpam/include/security/openpam.h +++ b/contrib/openpam/include/security/openpam.h @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/openpam/include/security/openpam.h#12 $ + * $P4: //depot/projects/openpam/include/security/openpam.h#14 $ */ #ifndef _SECURITY_OPENPAM_H_INCLUDED @@ -65,6 +65,7 @@ pam_error(pam_handle_t *_pamh, int pam_get_authtok(pam_handle_t *_pamh, + int _item, const char **_authtok, const char *_prompt); @@ -116,19 +117,26 @@ enum { /* * Log to syslog */ -void _openpam_log(int _level, +void +_openpam_log(int _level, const char *_func, const char *_fmt, ...); -#if defined(__STDC__) && (__STDC_VERSION__ > 199901L) +#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L) #define openpam_log(lvl, fmt, ...) \ _openpam_log((lvl), __func__, fmt, __VA_ARGS__) -#elif defined(__GNUC__) +#elif defined(__GNUC__) && (__GNUC__ >= 2) && (__GNUC_MINOR__ >= 95) +#define openpam_log(lvl, fmt, ...) \ + _openpam_log((lvl), __func__, fmt, ##fmt) +#elif defined(__GNUC__) && defined(__FUNCTION__) #define openpam_log(lvl, fmt...) \ - _openpam_log((lvl), __func__, ##fmt) + _openpam_log((lvl), __FUNCTION__, ##fmt) #else -extern openpam_log(int _level, const char *_format, ...); +void +openpam_log(int _level, + const char *_format, + ...); #endif /* @@ -189,12 +197,14 @@ struct pam_module { * Infrastructure for static modules using GCC linker sets. * You are not expected to understand this. */ -#if defined(__GNUC__) && !defined(__PIC__) #if defined(__FreeBSD__) #define PAM_SOEXT ".so" #else -#error Static linking is not supported on your platform +#ifndef NO_STATIC_MODULES +#define NO_STATIC_MODULES #endif +#endif +#if defined(__GNUC__) && !defined(__PIC__) && !defined(NO_STATIC_MODULES) /* gcc, static linking */ #include #include diff --git a/contrib/openpam/include/security/pam_constants.h b/contrib/openpam/include/security/pam_constants.h index 986b4d08cb3..5cb0b409455 100644 --- a/contrib/openpam/include/security/pam_constants.h +++ b/contrib/openpam/include/security/pam_constants.h @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/openpam/include/security/pam_constants.h#12 $ + * $P4: //depot/projects/openpam/include/security/pam_constants.h#13 $ */ #ifndef _PAM_CONSTANTS_H_INCLUDED @@ -119,6 +119,7 @@ enum { PAM_RUSER = 8, PAM_USER_PROMPT = 9, PAM_AUTHTOK_PROMPT = 10, /* OpenPAM extension */ + PAM_OLDAUTHTOK_PROMPT = 11, /* OpenPAM extension */ PAM_NUM_ITEMS /* OpenPAM extension */ }; diff --git a/contrib/openpam/lib/pam_authenticate.c b/contrib/openpam/lib/pam_authenticate.c index ff70fb66794..20c656e11ea 100644 --- a/contrib/openpam/lib/pam_authenticate.c +++ b/contrib/openpam/lib/pam_authenticate.c @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/openpam/lib/pam_authenticate.c#8 $ + * $P4: //depot/projects/openpam/lib/pam_authenticate.c#9 $ */ #include @@ -53,6 +53,8 @@ pam_authenticate(pam_handle_t *pamh, { int pam_err; + if (flags & ~(PAM_SILENT|PAM_DISALLOW_NULL_AUTHTOK)) + return (PAM_SYMBOL_ERR); pam_err = openpam_dispatch(pamh, PAM_SM_AUTHENTICATE, flags); pam_set_item(pamh, PAM_AUTHTOK, NULL); return (pam_err); @@ -65,3 +67,20 @@ pam_authenticate(pam_handle_t *pamh, * =pam_sm_authenticate * !PAM_IGNORE */ + +/** + * The =pam_authenticate function attempts to authenticate the user + * associated with the pam context specified by the =pamh argument. + * + * The application is free to call =pam_authenticate as many times as it + * wishes, but some modules may maintain an internal retry counter and + * return =PAM_MAXTRIES when it exceeds some preset or hardcoded limit. + * + * The =flags argument is the binary or of zero or more of the following + * values: + * + * =PAM_SILENT + * Do not emit any messages. + * =PAM_DISALLOW_NULL_AUTHTOK + * Fail if the user's authentication token is null. + */ diff --git a/contrib/openpam/lib/pam_chauthtok.c b/contrib/openpam/lib/pam_chauthtok.c index 2699fdef2ce..bf56a130e80 100644 --- a/contrib/openpam/lib/pam_chauthtok.c +++ b/contrib/openpam/lib/pam_chauthtok.c @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/openpam/lib/pam_chauthtok.c#9 $ + * $P4: //depot/projects/openpam/lib/pam_chauthtok.c#10 $ */ #include @@ -53,7 +53,7 @@ pam_chauthtok(pam_handle_t *pamh, { int pam_err; - if (flags & PAM_PRELIM_CHECK || flags & PAM_UPDATE_AUTHTOK) + if (flags & ~(PAM_SILENT|PAM_CHANGE_EXPIRED_AUTHTOK)) return (PAM_SYMBOL_ERR); pam_err = openpam_dispatch(pamh, PAM_SM_CHAUTHTOK, flags | PAM_PRELIM_CHECK); @@ -73,3 +73,17 @@ pam_chauthtok(pam_handle_t *pamh, * !PAM_IGNORE * PAM_SYMBOL_ERR */ + +/** + * The =pam_chauthtok function attempts to change the authentication token + * for the user associated with the pam context specified by the =pamh + * argument. + * + * The =flags argument is the binary or of zero or more of the following + * values: + * + * =PAM_SILENT + * Do not emit any messages. + * =PAM_CHANGE_EXPIRED_AUTHTOK + * Change only those authentication tokens that have expired. + */ diff --git a/contrib/openpam/lib/pam_get_authtok.c b/contrib/openpam/lib/pam_get_authtok.c index e7edc66db9c..8dd82389aa3 100644 --- a/contrib/openpam/lib/pam_get_authtok.c +++ b/contrib/openpam/lib/pam_get_authtok.c @@ -31,16 +31,22 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/openpam/lib/pam_get_authtok.c#12 $ + * $P4: //depot/projects/openpam/lib/pam_get_authtok.c#15 $ */ #include +#include + #include #include #include "openpam_impl.h" +const char authtok_prompt[] = "Password:"; +const char oldauthtok_prompt[] = "Old Password:"; +const char newauthtok_prompt[] = "New Password:"; + /* * OpenPAM extension * @@ -49,34 +55,76 @@ int pam_get_authtok(pam_handle_t *pamh, + int item, const char **authtok, const char *prompt) { - char *p, *resp; - int r, style; + const void *oldauthtok; + const char *default_prompt; + char *resp, *resp2; + int pitem, r, style, twice; if (pamh == NULL || authtok == NULL) return (PAM_SYSTEM_ERR); + *authtok = NULL; + twice = 0; + switch (item) { + case PAM_AUTHTOK: + pitem = PAM_AUTHTOK_PROMPT; + default_prompt = authtok_prompt; + r = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldauthtok); + if (r == PAM_SUCCESS && oldauthtok != NULL) { + default_prompt = newauthtok_prompt; + twice = 1; + } + break; + case PAM_OLDAUTHTOK: + pitem = PAM_OLDAUTHTOK_PROMPT; + default_prompt = oldauthtok_prompt; + twice = 0; + break; + default: + return (PAM_SYMBOL_ERR); + } + if (openpam_get_option(pamh, "try_first_pass") || openpam_get_option(pamh, "use_first_pass")) { - r = pam_get_item(pamh, PAM_AUTHTOK, (const void **)authtok); + r = pam_get_item(pamh, item, (const void **)authtok); if (r == PAM_SUCCESS && *authtok != NULL) return (PAM_SUCCESS); else if (openpam_get_option(pamh, "use_first_pass")) return (r == PAM_SUCCESS ? PAM_AUTH_ERR : r); } - if (pam_get_item(pamh, PAM_AUTHTOK_PROMPT, - (const void **)&p) != PAM_SUCCESS || p == NULL) - if (prompt == NULL) - prompt = "Password:"; + if (prompt == NULL) { + r = pam_get_item(pamh, pitem, (const void **)&prompt); + if (r != PAM_SUCCESS || prompt == NULL) + prompt = default_prompt; + } style = openpam_get_option(pamh, "echo_pass") ? PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF; - r = pam_prompt(pamh, style, &resp, "%s", p ? p : prompt); + r = pam_prompt(pamh, style, &resp, "%s", prompt); if (r != PAM_SUCCESS) return (r); - *authtok = resp; - return (pam_set_item(pamh, PAM_AUTHTOK, *authtok)); + if (twice) { + r = pam_prompt(pamh, style, &resp2, "Retype %s", prompt); + if (r != PAM_SUCCESS) { + free(resp); + return (r); + } + if (strcmp(resp, resp2) != 0) { + free(resp); + resp = NULL; + } + free(resp2); + } + if (resp == NULL) + return (PAM_TRY_AGAIN); + r = pam_set_item(pamh, pitem, resp); + free(resp); + if (r != PAM_SUCCESS) + return (r); + return (pam_get_item(pamh, pitem, (const void **)authtok)); } /* @@ -86,4 +134,34 @@ pam_get_authtok(pam_handle_t *pamh, * =pam_prompt * =pam_set_item * !PAM_SYMBOL_ERR + * PAM_TRY_AGAIN + */ + +/** + * The =pam_get_authtok function returns the cached authentication token, + * or prompts the user if no token is currently cached. Either way, a + * pointer to the authentication token is stored in the location pointed + * to by the =authtok argument. + * + * The =item argument must have one of the following values: + * + * =PAM_AUTHTOK + * Returns the current authentication token, or the new token + * when changing authentication tokens. + * =PAM_OLDAUTHTOK + * Returns the previous authentication token when changing + * authentication tokens. + * + * The =prompt argument specifies a prompt to use if no token is cached. + * If it is =NULL, the =PAM_AUTHTOK_PROMPT or =PAM_OLDAUTHTOK_PROMPT item, + * as appropriate, will be used. If that item is also =NULL, a hardcoded + * default prompt will be used. + * + * If =item is set to =PAM_AUTHTOK and there is a non-null =PAM_OLDAUTHTOK + * item, =pam_get_authtok will ask the user to confirm the new token by + * retyping it. If there is a mismatch, =pam_get_authtok will return + * =PAM_TRY_AGAIN. + * + * >pam_get_item + * >pam_get_user */ diff --git a/contrib/openpam/lib/pam_get_item.c b/contrib/openpam/lib/pam_get_item.c index a3b01e5c8d4..55879f45718 100644 --- a/contrib/openpam/lib/pam_get_item.c +++ b/contrib/openpam/lib/pam_get_item.c @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/openpam/lib/pam_get_item.c#10 $ + * $P4: //depot/projects/openpam/lib/pam_get_item.c#11 $ */ #include @@ -66,6 +66,7 @@ pam_get_item(pam_handle_t *pamh, case PAM_CONV: case PAM_USER_PROMPT: case PAM_AUTHTOK_PROMPT: + case PAM_OLDAUTHTOK_PROMPT: *item = pamh->item[item_type]; return (PAM_SUCCESS); default: @@ -112,6 +113,9 @@ pam_get_item(pam_handle_t *pamh, * =PAM_AUTHTOK_PROMPT: * The prompt to use when asking the applicant for an * authentication token. + * =PAM_OLDAUTHTOK_PROMPT: + * The prompt to use when asking the applicant for an + * expired authentication token prior to changing it. * * See =pam_start for a description of =struct pam_conv. * diff --git a/contrib/openpam/lib/pam_get_user.c b/contrib/openpam/lib/pam_get_user.c index 5e10f3052c7..608614ab0f9 100644 --- a/contrib/openpam/lib/pam_get_user.c +++ b/contrib/openpam/lib/pam_get_user.c @@ -31,16 +31,20 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/openpam/lib/pam_get_user.c#10 $ + * $P4: //depot/projects/openpam/lib/pam_get_user.c#11 $ */ #include +#include + #include #include #include "openpam_impl.h" +const char user_prompt[] = "Login:"; + /* * XSSO 4.2.1 * XSSO 6 page 52 @@ -53,7 +57,7 @@ pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) { - char *p, *resp; + char *resp; int r; if (pamh == NULL || user == NULL) @@ -63,16 +67,18 @@ pam_get_user(pam_handle_t *pamh, if (r == PAM_SUCCESS) return (PAM_SUCCESS); if (prompt == NULL) { - if (pam_get_item(pamh, PAM_USER_PROMPT, - (const void **)&p) != PAM_SUCCESS || p == NULL) - prompt = "Login: "; + r = pam_get_item(pamh, PAM_USER_PROMPT, (const void **)&prompt); + if (r != PAM_SUCCESS || prompt == NULL) + prompt = user_prompt; } - r = pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &resp, - "%s", prompt ? prompt : p); + r = pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &resp, "%s", prompt); if (r != PAM_SUCCESS) return (r); - *user = resp; - return (pam_set_item(pamh, PAM_USER, *user)); + r = pam_set_item(pamh, PAM_USER, resp); + free(resp); + if (r != PAM_SUCCESS) + return (r); + return (pam_get_item(pamh, PAM_USER, (const void **)user)); } /* @@ -83,3 +89,18 @@ pam_get_user(pam_handle_t *pamh, * =pam_set_item * !PAM_SYMBOL_ERR */ + +/** + * The =pam_get_user function returns the name of the target user, as + * specified to =pam_start. If no user was specified, nor set using + * =pam_set_item, =pam_get_user will prompt for a user name. Either way, + * a pointer to the user name is stored in the location pointed to by the + * =user argument. + + * The =prompt argument specifies a prompt to use if no user name is + * cached. If it is =NULL, the =PAM_USER_PROMPT will be used. If that + * item is also =NULL, a hardcoded default prompt will be used. + * + * >pam_get_item + * >pam_get_authtok + */ diff --git a/contrib/openpam/lib/pam_set_item.c b/contrib/openpam/lib/pam_set_item.c index 2491fee6901..f5d953b6017 100644 --- a/contrib/openpam/lib/pam_set_item.c +++ b/contrib/openpam/lib/pam_set_item.c @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/openpam/lib/pam_set_item.c#12 $ + * $P4: //depot/projects/openpam/lib/pam_set_item.c#13 $ */ #include @@ -73,6 +73,7 @@ pam_set_item(pam_handle_t *pamh, case PAM_RUSER: case PAM_USER_PROMPT: case PAM_AUTHTOK_PROMPT: + case PAM_OLDAUTHTOK_PROMPT: if (*slot != NULL) size = strlen(*slot) + 1; if (item != NULL)