summaryrefslogtreecommitdiffstats
path: root/lib/libpam
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2001-08-26 17:41:13 +0000
committermarkm <markm@FreeBSD.org>2001-08-26 17:41:13 +0000
commit67fcc4111ae36921c649ec85c8cab3bbf50fd738 (patch)
tree3cf7d6b063084a826d4901572e4ab8447645201d /lib/libpam
parente52902c064d70be6f3fbee06988b2b991e62bd23 (diff)
downloadFreeBSD-src-67fcc4111ae36921c649ec85c8cab3bbf50fd738.zip
FreeBSD-src-67fcc4111ae36921c649ec85c8cab3bbf50fd738.tar.gz
Big module makeover; improve logging, standardise variable names,
introduce ability to change passwords for both "usual" Unix methods and NIS.
Diffstat (limited to 'lib/libpam')
-rw-r--r--lib/libpam/modules/pam_ssh/pam_ssh.830
-rw-r--r--lib/libpam/modules/pam_unix/Makefile50
-rw-r--r--lib/libpam/modules/pam_unix/pam_unix.830
-rw-r--r--lib/libpam/modules/pam_unix/pam_unix.c479
4 files changed, 567 insertions, 22 deletions
diff --git a/lib/libpam/modules/pam_ssh/pam_ssh.8 b/lib/libpam/modules/pam_ssh/pam_ssh.8
index 93b0fa7..64be97a 100644
--- a/lib/libpam/modules/pam_ssh/pam_ssh.8
+++ b/lib/libpam/modules/pam_ssh/pam_ssh.8
@@ -131,6 +131,36 @@ debugging information at
.Dv LOG_DEBUG
level.
.El
+.Ss Ux Ss Password Management Module
+The
+.Ux
+password management component
+provides a function to perform account management,
+.Fn pam_sm_chauthtok .
+The function changes
+the user's password.
+.Pp
+The following options may be passed to the password module:
+.Bl -tag -width ".Cm use_first_pass"
+.It Cm debug
+.Xr syslog 3
+debugging information at
+.Dv LOG_DEBUG
+level.
+.It Cm no_warn
+suppress warning messages to the user.
+These messages include
+reasons why the user's
+authentication attempt was declined.
+.It Cm local_pass
+forces the password module
+to change a local password
+in favour of a NIS one.
+.It Cm nis_pass
+forces the password module
+to change a NIS password
+in favour of a local one.
+.El
.Sh FILES
.Bl -tag -width ".Pa /etc/master.passwd" -compact
.It Pa /etc/master.passwd
diff --git a/lib/libpam/modules/pam_unix/Makefile b/lib/libpam/modules/pam_unix/Makefile
index b2d928c..8365ab5 100644
--- a/lib/libpam/modules/pam_unix/Makefile
+++ b/lib/libpam/modules/pam_unix/Makefile
@@ -26,9 +26,53 @@
LIB= pam_unix
SHLIB_NAME= pam_unix.so
-SRCS= pam_unix.c
-DPADD= ${LIBUTIL} ${LIBCRYPT}
-LDADD= -lutil -lcrypt
+SRCS= pam_unix.c pw_copy.c pw_yp.c pw_util.c ypxfr_misc.c ${GENSRCS}
+CFLAGS= -DYP -Dyp_error=warnx \
+ -I${.OBJDIR} \
+ -I${.CURDIR}/../../../../libexec/ypxfr \
+ -I${.CURDIR}/../../../../usr.sbin/vipw \
+ -I${.CURDIR}/../../../../usr.bin/chpass
+DPADD= ${LIBUTIL} ${LIBCRYPT} ${LIBRPCSVC}
+LDADD= -lutil -lcrypt -lrpcsvc
MAN= pam_unix.8
+GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_clnt.c \
+ yppasswd_private.h yppasswd_private_clnt.c yppasswd_private_xdr.c
+
+RPCGEN= rpcgen -C
+RPCSRC= ${DESTDIR}/usr/include/rpcsvc/yp.x
+RPCSRC_PW= ${DESTDIR}/usr/include/rpcsvc/yppasswd.x
+RPCSRC_PRIV= ${.CURDIR}/../../../../usr.sbin/rpc.yppasswdd/yppasswd_private.x
+
+yp.h: ${RPCSRC}
+ ${RPCGEN} -h -o ${.TARGET} ${RPCSRC}
+
+yp_clnt.c: ${RPCSRC} yp.h
+ ${RPCGEN} -l -o ${.TARGET} ${RPCSRC}
+
+yppasswd.h: ${RPCSRC_PW}
+ ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PW}
+
+yppasswd_clnt.c: ${RPCSRC_PW}
+ ${RPCGEN} -l -o ${.TARGET} ${RPCSRC_PW}
+
+yppasswd_private.h: ${RPCSRC_PRIV}
+ ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PRIV}
+
+yppasswd_private_xdr.c: ${RPCSRC_PRIV}
+ ${RPCGEN} -c -o ${.TARGET} ${RPCSRC_PRIV}
+
+yppasswd_private_clnt.c: ${RPCSRC_PRIV}
+ ${RPCGEN} -l -o ${.TARGET} ${RPCSRC_PRIV}
+
+
+yppasswd_private.h: ${RPCSRC_PRIV}
+ ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PRIV}
+
+CLEANFILES= ${GENSRCS}
+
.include <bsd.lib.mk>
+
+.PATH: ${.CURDIR}/../../../../usr.bin/chpass
+.PATH: ${.CURDIR}/../../../../usr.sbin/vipw
+.PATH: ${.CURDIR}/../../../../libexec/ypxfr
diff --git a/lib/libpam/modules/pam_unix/pam_unix.8 b/lib/libpam/modules/pam_unix/pam_unix.8
index 93b0fa7..64be97a 100644
--- a/lib/libpam/modules/pam_unix/pam_unix.8
+++ b/lib/libpam/modules/pam_unix/pam_unix.8
@@ -131,6 +131,36 @@ debugging information at
.Dv LOG_DEBUG
level.
.El
+.Ss Ux Ss Password Management Module
+The
+.Ux
+password management component
+provides a function to perform account management,
+.Fn pam_sm_chauthtok .
+The function changes
+the user's password.
+.Pp
+The following options may be passed to the password module:
+.Bl -tag -width ".Cm use_first_pass"
+.It Cm debug
+.Xr syslog 3
+debugging information at
+.Dv LOG_DEBUG
+level.
+.It Cm no_warn
+suppress warning messages to the user.
+These messages include
+reasons why the user's
+authentication attempt was declined.
+.It Cm local_pass
+forces the password module
+to change a local password
+in favour of a NIS one.
+.It Cm nis_pass
+forces the password module
+to change a NIS password
+in favour of a local one.
+.El
.Sh FILES
.Bl -tag -width ".Pa /etc/master.passwd" -compact
.It Pa /etc/master.passwd
diff --git a/lib/libpam/modules/pam_unix/pam_unix.c b/lib/libpam/modules/pam_unix/pam_unix.c
index 61c462c..f63acc0 100644
--- a/lib/libpam/modules/pam_unix/pam_unix.c
+++ b/lib/libpam/modules/pam_unix/pam_unix.c
@@ -28,6 +28,12 @@
#include <sys/types.h>
#include <sys/time.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+#endif
#include <login_cap.h>
#include <pwd.h>
#include <stdlib.h>
@@ -35,42 +41,72 @@
#include <stdio.h>
#include <unistd.h>
+#include <pw_copy.h>
+#include <pw_util.h>
+
+#ifdef YP
+#include <pw_yp.h>
+#include "yppasswd_private.h"
+#endif
+
#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
+#define PAM_SM_SESSION
+#define PAM_SM_PASSWORD
+
#include <security/pam_modules.h>
#include "pam_mod_misc.h"
-#define PASSWORD_PROMPT "Password:"
-#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
+#define USER_PROMPT "Username: "
+#define PASSWORD_PROMPT "Password: "
+#define PASSWORD_PROMPT_EXPIRED "\nPassword expired\nOld Password: "
+#define NEW_PASSWORD_PROMPT_1 "New Password: "
+#define NEW_PASSWORD_PROMPT_2 "New Password (again): "
+#define PASSWORD_HASH "md5"
+#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
+#define MAX_TRIES 3
-enum { PAM_OPT_AUTH_AS_SELF=PAM_OPT_STD_MAX, PAM_OPT_NULLOK };
+enum { PAM_OPT_AUTH_AS_SELF=PAM_OPT_STD_MAX, PAM_OPT_NULLOK, PAM_OPT_LOCAL_PASS, PAM_OPT_NIS_PASS };
static struct opttab other_options[] = {
{ "auth_as_self", PAM_OPT_AUTH_AS_SELF },
{ "nullok", PAM_OPT_NULLOK },
+ { "local_pass", PAM_OPT_LOCAL_PASS },
+ { "nis_pass", PAM_OPT_NIS_PASS },
{ NULL, 0 }
};
+#ifdef YP
+int pam_use_yp = 0;
+int yp_errno = YP_TRUE;
+#endif
+
+char *tempname = NULL;
+static int local_passwd(const char *user, const char *pass);
+#ifdef YP
+static int yp_passwd(const char *user, const char *pass);
+#endif
+
/*
* authentication management
*/
-
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
+ login_cap_t *lc;
struct options options;
struct passwd *pwd;
int retval;
- const char *password, *user;
- char *encrypted;
+ const char *pass, *user;
+ char *encrypted, *password_prompt;
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());
+ pwd = getpwnam(getlogin());
else {
retval = pam_get_user(pamh, &user, NULL);
if (retval != PAM_SUCCESS)
@@ -80,6 +116,12 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
PAM_LOG("Got user: %s", user);
+ lc = login_getclass(NULL);
+ password_prompt = login_getcapstr(lc, "passwd_prompt",
+ PASSWORD_PROMPT, PASSWORD_PROMPT);
+ login_close(lc);
+ lc = NULL;
+
if (pwd != NULL) {
PAM_LOG("Doing real authentication");
@@ -94,18 +136,18 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
PAM_RETURN(PAM_SUCCESS);
}
else {
- retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT,
+ retval = pam_get_pass(pamh, &pass, 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 = crypt(pass, pwd->pw_passwd);
+ if (pass[0] == '\0' && pwd->pw_passwd[0] != '\0')
encrypted = ":";
- PAM_LOG("Encrypted passwords are: %s & %s", encrypted,
- pwd->pw_passwd);
+ PAM_LOG("Encrypted password 1 is: %s", encrypted);
+ PAM_LOG("Encrypted password 2 is: %s", pwd->pw_passwd);
retval = strcmp(encrypted, pwd->pw_passwd) == 0 ?
PAM_SUCCESS : PAM_AUTH_ERR;
@@ -118,12 +160,12 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
* User unknown.
* Encrypt a dummy password so as to not give away too much.
*/
- retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT,
+ retval = pam_get_pass(pamh, &pass, password_prompt,
&options);
if (retval != PAM_SUCCESS)
PAM_RETURN(retval);
PAM_LOG("Got password");
- crypt(password, "xx");
+ crypt(pass, "xx");
retval = PAM_AUTH_ERR;
}
@@ -131,22 +173,29 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
* The PAM infrastructure will obliterate the cleartext
* password before returning to the application.
*/
+ if (retval != PAM_SUCCESS)
+ PAM_VERBOSE_ERROR("UNIX authentication refused");
+
PAM_RETURN(retval);
}
PAM_EXTERN int
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
- return PAM_SUCCESS;
+ struct options options;
+
+ pam_std_option(&options, other_options, argc, argv);
+
+ PAM_LOG("Options processed");
+
+ PAM_RETURN(PAM_SUCCESS);
}
/*
* account management
- *
- * 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)
+PAM_EXTERN int
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
struct options options;
struct passwd *pw;
@@ -214,4 +263,396 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
PAM_RETURN(retval);
}
+/*
+ * session management
+ *
+ * logging only
+ */
+PAM_EXTERN int
+pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ struct options options;
+
+ pam_std_option(&options, other_options, argc, argv);
+
+ PAM_LOG("Options processed");
+
+ PAM_RETURN(PAM_SUCCESS);
+}
+
+PAM_EXTERN int
+pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ struct options options;
+
+ pam_std_option(&options, other_options, argc, argv);
+
+ PAM_LOG("Options processed");
+
+ PAM_RETURN(PAM_SUCCESS);
+}
+
+/*
+ * password management
+ *
+ * standard Unix and NIS password changing
+ */
+PAM_EXTERN int
+pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ struct options options;
+ struct passwd *pwd;
+ int retval, retry, res, got;
+ const char *user, *pass;
+ char *new_pass, *new_pass_, *encrypted;
+
+ pam_std_option(&options, other_options, argc, argv);
+
+ PAM_LOG("Options processed");
+
+ if (pam_test_option(&options, PAM_OPT_AUTH_AS_SELF, NULL))
+ pwd = getpwnam(getlogin());
+ else {
+ retval = pam_get_user(pamh, &user, NULL);
+ if (retval != PAM_SUCCESS)
+ PAM_RETURN(retval);
+ pwd = getpwnam(user);
+ }
+
+ PAM_LOG("Got user: %s", user);
+
+ if (flags & PAM_PRELIM_CHECK) {
+
+ PAM_LOG("PRELIM round; checking user password");
+
+ 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?
+ */
+ PAM_LOG("No password, and null password OK");
+ PAM_RETURN(PAM_SUCCESS);
+ }
+ else {
+ retval = pam_get_pass(pamh, &pass,
+ PASSWORD_PROMPT_EXPIRED, &options);
+ if (retval != PAM_SUCCESS)
+ PAM_RETURN(retval);
+ PAM_LOG("Got password: %s", pass);
+ }
+ encrypted = crypt(pass, pwd->pw_passwd);
+ if (pass[0] == '\0' && pwd->pw_passwd[0] != '\0')
+ encrypted = ":";
+
+ PAM_LOG("Encrypted password 1 is: %s", encrypted);
+ PAM_LOG("Encrypted password 2 is: %s", pwd->pw_passwd);
+
+ if (strcmp(encrypted, pwd->pw_passwd) != 0)
+ PAM_RETURN(PAM_AUTH_ERR);
+
+ retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *)pass);
+ pass = NULL;
+ if (retval != PAM_SUCCESS)
+ PAM_RETURN(retval);
+
+ PAM_LOG("Stashed old password");
+
+ retval = pam_set_item(pamh, PAM_AUTHTOK, (const void *)pass);
+ if (retval != PAM_SUCCESS)
+ PAM_RETURN(retval);
+
+ PAM_LOG("Voided old password");
+
+ PAM_RETURN(PAM_SUCCESS);
+ }
+ else if (flags & PAM_UPDATE_AUTHTOK) {
+ PAM_LOG("UPDATE round; checking user password");
+
+ retval = pam_get_item(pamh, PAM_OLDAUTHTOK,
+ (const void **)&pass);
+ if (retval != PAM_SUCCESS)
+ PAM_RETURN(retval);
+
+ PAM_LOG("Got old password: %s", pass);
+
+ got = 0;
+ retry = 0;
+ while (retry++ < MAX_TRIES) {
+ new_pass = NULL;
+ retval = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF,
+ NEW_PASSWORD_PROMPT_1, &new_pass);
+
+ if (new_pass == NULL)
+ new_pass = "";
+
+ if (retval == PAM_SUCCESS) {
+ new_pass_ = NULL;
+ retval = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF,
+ NEW_PASSWORD_PROMPT_2, &new_pass_);
+
+ if (new_pass_ == NULL)
+ new_pass_ = "";
+
+ if (retval == PAM_SUCCESS) {
+ if (strcmp(new_pass, new_pass_) == 0) {
+ got = 1;
+ break;
+ }
+ else
+ PAM_VERBOSE_ERROR("Password mismatch");
+ }
+ }
+ }
+
+ if (!got) {
+ PAM_VERBOSE_ERROR("Unable to get valid password");
+ PAM_RETURN(PAM_PERM_DENIED);
+ }
+
+ PAM_LOG("Got new password: %s", new_pass);
+
+#ifdef YP
+ /* If NIS is set in the passwd database, use it */
+ res = use_yp((char *)user, 0, 0);
+ if (res == USER_YP_ONLY) {
+ if (!pam_test_option(&options, PAM_OPT_LOCAL_PASS,
+ NULL))
+ retval = yp_passwd(user, new_pass);
+ else {
+ /* Reject 'local' flag if NIS is on and the user
+ * is not local
+ */
+ retval = PAM_PERM_DENIED;
+ PAM_LOG("Unknown local user: %s", user);
+ }
+ }
+ else if (res == USER_LOCAL_ONLY) {
+ if (!pam_test_option(&options, PAM_OPT_NIS_PASS, NULL))
+ retval = local_passwd(user, new_pass);
+ else {
+ /* Reject 'nis' flag if user is only local */
+ retval = PAM_PERM_DENIED;
+ PAM_LOG("Unknown NIS user: %s", user);
+ }
+ }
+ else if (res == USER_YP_AND_LOCAL) {
+ if (pam_test_option(&options, PAM_OPT_NIS_PASS, NULL))
+ retval = yp_passwd(user, new_pass);
+ else
+ retval = local_passwd(user, new_pass);
+ }
+ else
+ retval = PAM_ABORT; /* Bad juju */
+#else
+ retval = local_passwd(user, new_pass);
+#endif
+
+ /* XXX wipe the mem as well */
+ pass = NULL;
+ new_pass = NULL;
+ }
+ else {
+ /* Very bad juju */
+ retval = PAM_ABORT;
+ PAM_LOG("Illegal 'flags'");
+ }
+
+ PAM_RETURN(retval);
+}
+
+/* Mostly stolen from passwd(1)'s local_passwd.c - markm */
+
+static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void
+to64(char *s, long v, int n)
+{
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+static int
+local_passwd(const char *user, const char *pass)
+{
+ login_cap_t * lc;
+ struct passwd *pwd;
+ struct timeval tv;
+ int pfd, tfd;
+ char *crypt_type, salt[32];
+
+ pwd = getpwnam(user);
+ if (pwd == NULL)
+ return(PAM_ABORT); /* Really bad things */
+
+#ifdef YP
+ pwd = (struct passwd *)&local_password;
+#endif
+ pw_init();
+
+ pwd->pw_change = 0;
+ lc = login_getclass(NULL);
+ crypt_type = login_getcapstr(lc, "passwd_format",
+ PASSWORD_HASH, PASSWORD_HASH);
+ if (login_setcryptfmt(lc, crypt_type, NULL) == NULL)
+ syslog(LOG_ERR, "cannot set password cipher");
+ login_close(lc);
+ /* Salt suitable for anything */
+ srandomdev();
+ gettimeofday(&tv, 0);
+ to64(&salt[0], random(), 3);
+ to64(&salt[3], tv.tv_usec, 3);
+ to64(&salt[6], tv.tv_sec, 2);
+ to64(&salt[8], random(), 5);
+ to64(&salt[13], random(), 5);
+ to64(&salt[17], random(), 5);
+ to64(&salt[22], random(), 5);
+ salt[27] = '\0';
+
+ pwd->pw_passwd = crypt(pass, salt);
+
+ pfd = pw_lock();
+ tfd = pw_tmp();
+ pw_copy(pfd, tfd, pwd);
+
+ if (!pw_mkdb((char *)user))
+ pw_error((char *)NULL, 0, 1);
+
+ return PAM_SUCCESS;
+}
+
+#ifdef YP
+/* Stolen from src/usr.bin/passwd/yp_passwd.c, carrying copyrights of:
+ * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+ * Copyright (c) 1994 Olaf Kirch <okir@monad.swb.de>
+ * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>
+ */
+int
+yp_passwd(const char *user, const char *pass)
+{
+ struct master_yppasswd master_yppasswd;
+ struct passwd *pwd;
+ struct rpc_err err;
+ struct timeval tv;
+ struct yppasswd yppasswd;
+ CLIENT *clnt;
+ login_cap_t *lc;
+ int *status;
+ uid_t uid;
+ char *master, *sockname = YP_SOCKNAME, salt[32];
+
+ _use_yp = 1;
+
+ uid = getuid();
+
+ master = get_yp_master(1);
+ if (master == NULL)
+ return PAM_ABORT; /* Major disaster */
+
+ /*
+ * It is presumed that by the time we get here, use_yp()
+ * has been called and that we have verified that the user
+ * actually exists. This being the case, the yp_password
+ * stucture has already been filled in for us.
+ */
+
+ /* Use the correct password */
+ pwd = (struct passwd *)&yp_password;
+
+ pwd->pw_change = 0;
+
+ /* Initialize password information */
+ if (suser_override) {
+ master_yppasswd.newpw.pw_passwd = strdup(pwd->pw_passwd);
+ master_yppasswd.newpw.pw_name = strdup(pwd->pw_name);
+ master_yppasswd.newpw.pw_uid = pwd->pw_uid;
+ master_yppasswd.newpw.pw_gid = pwd->pw_gid;
+ master_yppasswd.newpw.pw_expire = pwd->pw_expire;
+ master_yppasswd.newpw.pw_change = pwd->pw_change;
+ master_yppasswd.newpw.pw_fields = pwd->pw_fields;
+ master_yppasswd.newpw.pw_gecos = strdup(pwd->pw_gecos);
+ master_yppasswd.newpw.pw_dir = strdup(pwd->pw_dir);
+ master_yppasswd.newpw.pw_shell = strdup(pwd->pw_shell);
+ master_yppasswd.newpw.pw_class = pwd->pw_class != NULL ?
+ strdup(pwd->pw_class) : "";
+ master_yppasswd.oldpass = "";
+ master_yppasswd.domain = yp_domain;
+ } else {
+ yppasswd.newpw.pw_passwd = strdup(pwd->pw_passwd);
+ yppasswd.newpw.pw_name = strdup(pwd->pw_name);
+ yppasswd.newpw.pw_uid = pwd->pw_uid;
+ yppasswd.newpw.pw_gid = pwd->pw_gid;
+ yppasswd.newpw.pw_gecos = strdup(pwd->pw_gecos);
+ yppasswd.newpw.pw_dir = strdup(pwd->pw_dir);
+ yppasswd.newpw.pw_shell = strdup(pwd->pw_shell);
+ yppasswd.oldpass = "";
+ }
+
+ if (login_setcryptfmt(lc, "md5", NULL) == NULL)
+ syslog(LOG_ERR, "cannot set password cipher");
+ login_close(lc);
+ /* Salt suitable for anything */
+ srandomdev();
+ gettimeofday(&tv, 0);
+ to64(&salt[0], random(), 3);
+ to64(&salt[3], tv.tv_usec, 3);
+ to64(&salt[6], tv.tv_sec, 2);
+ to64(&salt[8], random(), 5);
+ to64(&salt[13], random(), 5);
+ to64(&salt[17], random(), 5);
+ to64(&salt[22], random(), 5);
+ salt[27] = '\0';
+
+ if (suser_override)
+ master_yppasswd.newpw.pw_passwd = crypt(pass, salt);
+ else
+ yppasswd.newpw.pw_passwd = crypt(pass, salt);
+
+ if (suser_override) {
+ if ((clnt = clnt_create(sockname, MASTER_YPPASSWDPROG,
+ MASTER_YPPASSWDVERS, "unix")) == NULL) {
+ syslog(LOG_ERR,
+ "Cannot contact rpc.yppasswdd on host %s: %s",
+ master, clnt_spcreateerror(""));
+ return PAM_ABORT;
+ }
+ }
+ else {
+ if ((clnt = clnt_create(master, YPPASSWDPROG,
+ YPPASSWDVERS, "udp")) == NULL) {
+ syslog(LOG_ERR,
+ "Cannot contact rpc.yppasswdd on host %s: %s",
+ master, clnt_spcreateerror(""));
+ return PAM_ABORT;
+ }
+ }
+ /*
+ * The yppasswd.x file said `unix authentication required',
+ * so I added it. This is the only reason it is in here.
+ * My yppasswdd doesn't use it, but maybe some others out there
+ * do. --okir
+ */
+ clnt->cl_auth = authunix_create_default();
+
+ if (suser_override)
+ status = yppasswdproc_update_master_1(&master_yppasswd, clnt);
+ else
+ status = yppasswdproc_update_1(&yppasswd, clnt);
+
+ clnt_geterr(clnt, &err);
+
+ auth_destroy(clnt->cl_auth);
+ clnt_destroy(clnt);
+
+ if (err.re_status != RPC_SUCCESS || status == NULL || *status)
+ return PAM_ABORT;
+
+ return (err.re_status || status == NULL || *status)
+ ? PAM_ABORT : PAM_SUCCESS;
+}
+#endif /* YP */
+
PAM_MODULE_ENTRY("pam_unix");
OpenPOWER on IntegriCloud