diff options
author | Thorsten Kukuk <kukuk@thkukuk.de> | 2008-12-03 14:16:33 +0000 |
---|---|---|
committer | Thorsten Kukuk <kukuk@thkukuk.de> | 2008-12-03 14:16:33 +0000 |
commit | f326d04ccd16631d57134487e56bb73074f0dd0e (patch) | |
tree | be55fce45e805e98057c1920a5f0ebaffa2b6650 /libpam | |
parent | de63f0160c57494553e400aca215ffe316e946b7 (diff) | |
download | pam-f326d04ccd16631d57134487e56bb73074f0dd0e.tar.gz pam-f326d04ccd16631d57134487e56bb73074f0dd0e.tar.bz2 pam-f326d04ccd16631d57134487e56bb73074f0dd0e.zip |
Relevant BUGIDs:
Purpose of commit: new feature
Commit summary:
---------------
2008-12-03 Thorsten Kukuk <kukuk@suse.de>
* doc/man/Makefile.am: Add pam_get_authtok.3.xml.
* doc/man/pam_get_authtok.3.xml: New.
* libpam/Makefile.am: Add pam_get_authtok.c.
* libpam/libpam.map: Export pam_get_authtok.
* libpam/pam_get_authtok.c: New.
* libpam/pam_private.h: Add mod_argc and mod_argv to pam_handle.
* libpam_include/security/pam_ext.h: Add pam_get_authtok
prototype.
* modules/pam_cracklib/pam_cracklib.c: Use pam_get_authtok.
* modules/pam_pwhistory/pam_pwhistory.c: Likewise.
* po/POTFILES.in: Add libpam/pam_get_authtok.c.
* xtests/tst-pam_cracklib1.c: Adjust error codes.
* modules/pam_timestamp/Makefile.am: Remove hmactest.c from
EXTRA_DIST.
* po/*.po: Regenerated.
Diffstat (limited to 'libpam')
-rw-r--r-- | libpam/Makefile.am | 5 | ||||
-rw-r--r-- | libpam/include/security/pam_ext.h | 5 | ||||
-rw-r--r-- | libpam/libpam.map | 5 | ||||
-rw-r--r-- | libpam/pam_dispatch.c | 8 | ||||
-rw-r--r-- | libpam/pam_get_authtok.c | 166 | ||||
-rw-r--r-- | libpam/pam_private.h | 2 |
6 files changed, 186 insertions, 5 deletions
diff --git a/libpam/Makefile.am b/libpam/Makefile.am index 75e55954..70a11133 100644 --- a/libpam/Makefile.am +++ b/libpam/Makefile.am @@ -20,7 +20,7 @@ include_HEADERS = include/security/_pam_compat.h \ noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \ pam_modutil_private.h pam_static_modules.h -libpam_la_LDFLAGS = -no-undefined -version-info 81:11:81 +libpam_la_LDFLAGS = -no-undefined -version-info 82:0:82 libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@ if STATIC_MODULES @@ -34,7 +34,8 @@ endif lib_LTLIBRARIES = libpam.la libpam_la_SOURCES = pam_account.c pam_auth.c pam_data.c pam_delay.c \ - pam_dispatch.c pam_end.c pam_env.c pam_handlers.c pam_item.c \ + pam_dispatch.c pam_end.c pam_env.c pam_get_authtok.c \ + pam_handlers.c pam_item.c \ pam_misc.c pam_password.c pam_prelude.c \ pam_session.c pam_start.c pam_static.c pam_strerror.c \ pam_vprompt.c pam_syslog.c pam_dynamic.c pam_audit.c \ diff --git a/libpam/include/security/pam_ext.h b/libpam/include/security/pam_ext.h index 111dd633..26f7156c 100644 --- a/libpam/include/security/pam_ext.h +++ b/libpam/include/security/pam_ext.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006 Thorsten Kukuk. + * Copyright (C) 2005, 2006, 2008 Thorsten Kukuk. * * <security/pam_ext.h> * @@ -74,6 +74,9 @@ pam_prompt (pam_handle_t *pamh, int style, char **response, #define pam_info(pamh, fmt...) pam_prompt(pamh, PAM_TEXT_INFO, NULL, fmt) #define pam_vinfo(pamh, fmt, args) pam_vprompt(pamh, PAM_TEXT_INFO, NULL, fmt, args) +extern int PAM_NONNULL((1,3)) +pam_get_authtok (pam_handle_t *pamh, int item, const char **authtok, + const char *prompt); #ifdef __cplusplus } #endif diff --git a/libpam/libpam.map b/libpam/libpam.map index e37fc356..227e8372 100644 --- a/libpam/libpam.map +++ b/libpam/libpam.map @@ -30,6 +30,11 @@ LIBPAM_EXTENSION_1.0 { pam_vsyslog; }; +LIBPAM_EXTENSION_1.1 { + global: + pam_get_authtok; +} LIBPAM_EXTENSION_1.0; + LIBPAM_MODUTIL_1.0 { global: pam_modutil_getpwnam; diff --git a/libpam/pam_dispatch.c b/libpam/pam_dispatch.c index fa4e5ed4..42482573 100644 --- a/libpam/pam_dispatch.c +++ b/libpam/pam_dispatch.c @@ -87,7 +87,7 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, } /* remember state if we are entering a substack */ - if (prev_level < stack_level) { + if (prev_level < stack_level) { substates[stack_level].impression = impression; substates[stack_level].status = status; } @@ -105,8 +105,12 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, } else { D(("passing control to module...")); pamh->mod_name=h->mod_name; + pamh->mod_argc = h->argc; + pamh->mod_argv = h->argv; retval = h->func(pamh, flags, h->argc, h->argv); pamh->mod_name=NULL; + pamh->mod_argc = 0; + pamh->mod_argv = NULL; D(("module returned: %s", pam_strerror(pamh, retval))); } @@ -286,7 +290,7 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, } } continue; - + decision_made: /* by getting here we have made a decision */ while (h->next != NULL && h->next->stack_level >= stack_level) { h = h->next; diff --git a/libpam/pam_get_authtok.c b/libpam/pam_get_authtok.c new file mode 100644 index 00000000..83b3f530 --- /dev/null +++ b/libpam/pam_get_authtok.c @@ -0,0 +1,166 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "pam_private.h" + +#include <security/pam_ext.h> + +#define PROMPT _("Password: ") +/* For Translators: "%s%s" could be replaced with "<service> " or "". */ +#define PROMPT1 _("New %s%spassword: ") +/* For Translators: "%s%s" could be replaced with "<service> " or "". */ +#define PROMPT2 _("Retype new %s%spassword: ") +#define MISTYPED_PASS _("Sorry, passwords do not match.") + +static const char * +get_option (pam_handle_t *pamh, const char *option) +{ + int i; + size_t len; + + + if (option == NULL || pamh == NULL || + pamh->mod_argc == 0 || pamh->mod_argv == NULL) + return NULL; + + len = strlen (option); + + for (i = 0; i < pamh->mod_argc; i++) + { + if (strncmp (option, pamh->mod_argv[i], len) == 0) + { + if (pamh->mod_argv[i][len] == '=') + return &(pamh->mod_argv[i][len+1]); + else if (pamh->mod_argv[i][len] == '\0') + return ""; + } + } + return NULL; +} + + +int +pam_get_authtok (pam_handle_t *pamh, int item, const char **authtok, + const char *prompt) + +{ + char *resp[2] = {NULL, NULL}; + const void* prevauthtok; + const char *type = ""; + int ask_twice = 0; /* Password change, ask twice for it */ + int retval; + + if (authtok == NULL) + return PAM_SYSTEM_ERR; + + /* PAM_AUTHTOK in password stack returns new password, + which needs to be verified. */ + if (item == PAM_AUTHTOK && pamh->choice == PAM_CHAUTHTOK) + { + ask_twice = 1; + type = get_option (pamh, "type"); + if (type == NULL) + type = ""; + } + + retval = pam_get_item (pamh, item, &prevauthtok); + if (retval == PAM_SUCCESS && prevauthtok != NULL) + { + *authtok = prevauthtok; + return PAM_SUCCESS; + } + else if (get_option (pamh, "use_first_pass") || + (ask_twice && get_option (pamh, "use_authtok"))) + { + if (prevauthtok == NULL) + { + if (ask_twice) + return PAM_AUTHTOK_ERR; + else + return PAM_AUTH_ERR; + } + else + return retval; + } + + if (prompt != NULL) + { + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], + "%s", prompt); + if (retval == PAM_SUCCESS && ask_twice && resp[0] != NULL) + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[1], + _("Retype %s"), prompt); + } + else if (ask_twice) + { + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], + PROMPT1, type, + strlen (type) > 0?" ":""); + if (retval == PAM_SUCCESS && ask_twice && resp[0] != NULL) + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[1], + PROMPT2, type, + strlen (type) > 0?" ":""); + } + else + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], "%s", + PROMPT); + + if (resp[0] == NULL || (ask_twice && resp[1] == NULL)) + { + /* We want to abort the password change */ + pam_error (pamh, _("Password change aborted.")); + return PAM_AUTHTOK_ERR; + } + + if (ask_twice && strcmp (resp[0], resp[1]) != 0) + { + pam_error (pamh, MISTYPED_PASS); + _pam_overwrite (resp[0]); + _pam_drop (resp[0]); + _pam_overwrite (resp[1]); + _pam_drop (resp[1]); + return PAM_TRY_AGAIN; + } + + _pam_overwrite (resp[1]); + _pam_drop (resp[1]); + + retval = pam_set_item (pamh, item, resp[0]); + _pam_overwrite (resp[0]); + _pam_drop (resp[0]); + if (retval != PAM_SUCCESS) + return retval; + + return pam_get_item(pamh, item, (const void **)authtok); +} diff --git a/libpam/pam_private.h b/libpam/pam_private.h index 62756ad4..777fd2d7 100644 --- a/libpam/pam_private.h +++ b/libpam/pam_private.h @@ -162,6 +162,8 @@ struct pam_handle { struct _pam_former_state former; /* library state - support for event driven applications */ const char *mod_name; /* Name of the module currently executed */ + int mod_argc; /* Number of module arguments */ + char **mod_argv; /* module arguments */ int choice; /* Which function we call from the module */ #ifdef HAVE_LIBAUDIT |