diff options
Diffstat (limited to 'lib/libpam/modules/pam_unix')
-rw-r--r-- | lib/libpam/modules/pam_unix/Makefile | 1 | ||||
-rw-r--r-- | lib/libpam/modules/pam_unix/pam_unix.8 | 148 | ||||
-rw-r--r-- | lib/libpam/modules/pam_unix/pam_unix.c | 106 |
3 files changed, 222 insertions, 33 deletions
diff --git a/lib/libpam/modules/pam_unix/Makefile b/lib/libpam/modules/pam_unix/Makefile index 048fade..b2d928c 100644 --- a/lib/libpam/modules/pam_unix/Makefile +++ b/lib/libpam/modules/pam_unix/Makefile @@ -29,5 +29,6 @@ SHLIB_NAME= pam_unix.so SRCS= pam_unix.c DPADD= ${LIBUTIL} ${LIBCRYPT} LDADD= -lutil -lcrypt +MAN= pam_unix.8 .include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_unix/pam_unix.8 b/lib/libpam/modules/pam_unix/pam_unix.8 new file mode 100644 index 0000000..ad4323c --- /dev/null +++ b/lib/libpam/modules/pam_unix/pam_unix.8 @@ -0,0 +1,148 @@ +.\" Copyright (c) 2001 Mark R V Murray +.\" All rights reserved. +.\" +.\" 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, this list of conditions and the following disclaimer. +.\" 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. +.\" +.\" $FreeBSD$ +.\" +.Dd July 7, 2001 +.Dt PAM_UNIX 8 +.Os +.Sh NAME +.Nm pam_unix +.Nd UNIX PAM module +.Sh SYNOPSIS +.Op Ar service-name +.Ar module-type +.Ar control-flag +.Pa pam_unix +.Op Ar options +.Sh DESCRIPTION +The +.Ux +authentication service module for PAM, +.Nm +provides functionality for two PAM categories: +authentication +and account management. +In terms of the +.Ar module-type +parameter, they are the +.Dv auth +and +.Dv account +features. +It also provides a null function for session management. +.Ss Ux Authentication Module +The +.Ux +authentication component +provides functions to verify the identity of a user +.Pq Fn pam_sm_authenticate , +which obtains the relevant +.Xr passwd 5 +entry. +It prompts the user for a password +and verifies that this is correct with +.Xr crypt 3 . +.Pp +The following options may be passed to the authentication module: +.Bl -tag -xwidth ".Cm use_first_pass" +.It Cm debug +.Xr syslog 3 +debugging information at +.Dv LOG_DEBUG +level. +.It Cm use_first_pass +If the authentication module +is not the first in the stack, +and a previous module +obtained the user's password, +that password is used +to authenticate the user. +If this fails, +the authentication module returns failure +without prompting the user for a password. +This option has no effect +if the authentication module +is the first in the stack, +or if no previous modules +obtained the user's password. +.It Cm try_first_pass +This option is similar to the +.Cm use_first_pass +option, +except that if the previously obtained password fails, +the user is prompted for another password. +.It Cm auth_as_self +This option will require the user +to authenticate themself as the user +given by +.Fn getuid 2 , +not as the account they are attempting to access. +This is primarily for services like +.Xr su 1 , +where the user's ability to retype +their own password +might be deemed sufficient. +.It Cm nullok +If the password database +has no password +for the entity being authenticated, +then this option +will forgo password prompting, +and silently allow authentication to succeed. +.El +.Ss Ux Account Management Module +The +.Ux +account management component +provides a function to perform account management, +.Fn pam_sm_acct_mgmt . +The function verifies +that the authenticated user +is allowed to login to the local user account +by checking the password expiry date. +.Pp +The following options may be passed to the management module: +.Bl -tag -xwidth ".Cm use_first_pass" +.It Cm debug +.Xr syslog 3 +debugging information at +.Dv LOG_DEBUG +level. +.El +.Sh FILES +.Bl -tag -xwidth ".Pa /etc/master.passwd" -compact +.It Pa /etc/master.passwd +default +.Ux +password database. +.El +.Sh SEE ALSO +.Xr passwd 1 , +.Xr getuid 2 , +.Xr crypt 3 , +.Xr passwd 5 , +.Xr syslog 3 , +.Xr pam.conf 5 , +.Xr pam 8 diff --git a/lib/libpam/modules/pam_unix/pam_unix.c b/lib/libpam/modules/pam_unix/pam_unix.c index cc97ad9..61c462c 100644 --- a/lib/libpam/modules/pam_unix/pam_unix.c +++ b/lib/libpam/modules/pam_unix/pam_unix.c @@ -42,64 +42,96 @@ #include "pam_mod_misc.h" #define PASSWORD_PROMPT "Password:" +#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ + +enum { PAM_OPT_AUTH_AS_SELF=PAM_OPT_STD_MAX, PAM_OPT_NULLOK }; + +static struct opttab other_options[] = { + { "auth_as_self", PAM_OPT_AUTH_AS_SELF }, + { "nullok", PAM_OPT_NULLOK }, + { NULL, 0 } +}; /* * authentication management */ PAM_EXTERN int -pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, - const char **argv) +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { - int retval; - const char *user; - const char *password; + struct options options; struct passwd *pwd; + int retval; + const char *password, *user; char *encrypted; - int options; - int i; - options = 0; - for (i = 0; i < argc; i++) - pam_std_option(&options, argv[i]); - if (options & PAM_OPT_AUTH_AS_SELF) + pam_std_option(&options, other_options, argc, argv); + + PAM_LOG("Options processed"); + + if (pam_test_option(&options, PAM_OPT_AUTH_AS_SELF, NULL)) pwd = getpwuid(getuid()); else { - if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) - return retval; + retval = pam_get_user(pamh, &user, NULL); + if (retval != PAM_SUCCESS) + PAM_RETURN(retval); pwd = getpwnam(user); } + + PAM_LOG("Got user: %s", user); + if (pwd != NULL) { - if (pwd->pw_passwd[0] == '\0' && (options & PAM_OPT_NULLOK)) + + PAM_LOG("Doing real authentication"); + + if (pwd->pw_passwd[0] == '\0' + && pam_test_option(&options, PAM_OPT_NULLOK, NULL)) { /* * No password case. XXX Are we giving too much away * by not prompting for a password? */ - return PAM_SUCCESS; + PAM_LOG("No password, and null password OK"); + PAM_RETURN(PAM_SUCCESS); + } else { - if ((retval = pam_get_pass(pamh, &password, - PASSWORD_PROMPT, options)) != PAM_SUCCESS) - return retval; + retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT, + &options); + if (retval != PAM_SUCCESS) + PAM_RETURN(retval); + PAM_LOG("Got password"); } encrypted = crypt(password, pwd->pw_passwd); if (password[0] == '\0' && pwd->pw_passwd[0] != '\0') encrypted = ":"; + PAM_LOG("Encrypted passwords are: %s & %s", encrypted, + pwd->pw_passwd); + retval = strcmp(encrypted, pwd->pw_passwd) == 0 ? PAM_SUCCESS : PAM_AUTH_ERR; - } else { + } + else { + + PAM_LOG("Doing dummy authentication"); + /* - * User unknown. Encrypt anyway so that it takes the - * same amount of time. + * User unknown. + * Encrypt a dummy password so as to not give away too much. */ + retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT, + &options); + if (retval != PAM_SUCCESS) + PAM_RETURN(retval); + PAM_LOG("Got password"); crypt(password, "xx"); retval = PAM_AUTH_ERR; } + /* * The PAM infrastructure will obliterate the cleartext * password before returning to the application. */ - return retval; + PAM_RETURN(retval); } PAM_EXTERN int @@ -114,24 +146,31 @@ pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) * check pw_change and pw_expire fields */ PAM_EXTERN -int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, - int argc, const char **argv) +int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { - const char *user; + struct options options; struct passwd *pw; struct timeval tp; + login_cap_t *lc; time_t warntime; - login_cap_t *lc = NULL; - char buf[128]; int retval; + const char *user; + char buf[128]; + + pam_std_option(&options, other_options, argc, argv); + + PAM_LOG("Options processed"); retval = pam_get_item(pamh, PAM_USER, (const void **)&user); if (retval != PAM_SUCCESS || user == NULL) /* some implementations return PAM_SUCCESS here */ - return PAM_USER_UNKNOWN; + PAM_RETURN(PAM_USER_UNKNOWN); - if ((pw = getpwnam(user)) == NULL) - return PAM_USER_UNKNOWN; + pw = getpwnam(user); + if (pw == NULL) + PAM_RETURN(PAM_USER_UNKNOWN); + + PAM_LOG("Got user: %s", user); retval = PAM_SUCCESS; lc = login_getpwclass(pw); @@ -139,11 +178,11 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, if (pw->pw_change || pw->pw_expire) gettimeofday(&tp, NULL); -#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ - warntime = login_getcaptime(lc, "warnpassword", DEFAULT_WARN, DEFAULT_WARN); + PAM_LOG("Got login_cap"); + if (pw->pw_change) { if (tp.tv_sec >= pw->pw_change) /* some implementations return PAM_AUTHTOK_EXPIRED */ @@ -171,7 +210,8 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, } login_close(lc); - return retval; + + PAM_RETURN(retval); } PAM_MODULE_ENTRY("pam_unix"); |