summaryrefslogtreecommitdiff
path: root/Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c
diff options
context:
space:
mode:
Diffstat (limited to 'Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c')
-rw-r--r--Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c260
1 files changed, 260 insertions, 0 deletions
diff --git a/Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c b/Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c
new file mode 100644
index 00000000..adb286e2
--- /dev/null
+++ b/Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c
@@ -0,0 +1,260 @@
+/*
+ * $Id: pam_unix_pwupd.-c,v 1.1.1.1 2001/04/29 04:17:29 hartmans Exp $
+ *
+ * This file contains the routines to update the passwd databases.
+ */
+
+/* Implementation */
+
+static int unix_update_db(pam_handle_t *pamh, int ctrl, const char *user,
+ const char *pass_old, const char *pass_new)
+{
+ const struct pwdb *pw=NULL;
+ const struct pwdb_entry *pwe=NULL;
+ pwdb_flag flag;
+ int retval, i;
+
+ D(("called."));
+
+ /* obtain default user record */
+
+ retval = pwdb_locate("user", PWDB_DEFAULT, user, PWDB_ID_UNKNOWN, &pw);
+ if (retval == PWDB_PASS_PHRASE_REQD) {
+ retval = pwdb_set_entry(pw, "pass_phrase"
+ , pass_old, 1+strlen(pass_old)
+ , NULL, NULL, 0);
+ if (retval == PWDB_SUCCESS)
+ retval = pwdb_locate("user", pw->source, user
+ , PWDB_ID_UNKNOWN, &pw);
+ }
+ pass_old = NULL;
+
+ if ( retval != PWDB_SUCCESS ) {
+ _log_err(LOG_ALERT, "cannot identify user %s (uid=%d)"
+ , user, getuid() );
+ pass_new = NULL;
+ if (pw)
+ (void) pwdb_delete(&pw);
+ return PAM_USER_UNKNOWN;
+ }
+
+ /* check that we can update all of the default databases */
+
+ retval = pwdb_flags("user", pw->source, &flag);
+
+ if ( retval != PWDB_SUCCESS || ( pwdb_on(flag,PWDB_F_NOUPDATE) ) ) {
+ _log_err(LOG_ERR, "cannot update default database for user %s"
+ , user );
+ pass_new = NULL;
+ if (pw)
+ (void) pwdb_delete(&pw);
+ return PAM_PERM_DENIED;
+ }
+
+ /* If there was one, we delete the "last_change" entry */
+ retval = pwdb_get_entry(pw, "last_change", &pwe);
+ if (retval == PWDB_SUCCESS) {
+ (void) pwdb_entry_delete(&pwe);
+ pwdb_set_entry(pw, "last_change", NULL, -1, NULL, NULL, 0);
+ }
+
+ /*
+ * next check for pam.conf specified databases: shadow etc... [In
+ * other words, pam.conf indicates which database the password is
+ * to be subsequently placed in: this is password migration].
+ */
+
+ if ( on(UNIX__SET_DB, ctrl) ) {
+ const char *db_token;
+ pwdb_type pt = _PWDB_MAX_TYPES;
+
+ if ( on(UNIX_UNIX, ctrl) ) {
+ db_token = "U"; /* XXX - should be macro */
+ pt = PWDB_UNIX;
+ } else if ( on(UNIX_SHADOW, ctrl) ) {
+ db_token = "x"; /* XXX - should be macro */
+ pt = PWDB_SHADOW;
+ } else if ( on(UNIX_RADIUS, ctrl) ) {
+ db_token = "R"; /* XXX - is this ok? */
+ pt = PWDB_RADIUS;
+ } else {
+ _log_err(LOG_ALERT
+ , "cannot determine database to use for authtok");
+ pass_new = NULL;
+ if (pw)
+ (void) pwdb_delete(&pw);
+ return PAM_ABORT; /* we're in trouble */
+ }
+
+ /*
+ * Attempt to update the indicated database (only)
+ */
+
+ {
+ pwdb_type tpt[2];
+ tpt[0] = pt;
+ tpt[1] = _PWDB_MAX_TYPES;
+
+ /* Can we set entry in database? */
+ retval = pwdb_flags("user", tpt, &flag);
+ if (retval == PWDB_SUCCESS && !pwdb_on(flag,PWDB_F_NOUPDATE)) {
+ /* YES. This database is available.. */
+
+ /* Only update if it is not already in the default list */
+ for (i=0; pw->source[i] != _PWDB_MAX_TYPES
+ && pw->source[i] != pt ; ++i);
+ if (pw->source[i] == _PWDB_MAX_TYPES) {
+ const struct pwdb *tpw=NULL;
+
+ /* copy database entry */
+ if ((retval = pwdb_new(&tpw, 10)) != PWDB_SUCCESS
+ || (retval = pwdb_merge(tpw, pw, PWDB_TRUE))
+ != PWDB_SUCCESS) {
+ _log_err(LOG_CRIT, "failed to obtain new pwdb: %s"
+ , pwdb_strerror(retval));
+ retval = PAM_ABORT;
+ } else
+ retval = PAM_SUCCESS;
+
+ /* set db_token */
+ if (retval == PAM_SUCCESS) {
+ retval = pwdb_set_entry(tpw, "defer_pass", db_token
+ , 1+strlen(db_token)
+ , NULL, NULL, 0);
+ if (retval != PWDB_SUCCESS) {
+ _log_err(LOG_ALERT, "set defer_pass -> %s"
+ , pwdb_strerror(retval));
+ retval = PAM_PERM_DENIED;
+ } else
+ retval = PAM_SUCCESS;
+ }
+
+ /* update specific database */
+ if (retval == PAM_SUCCESS) {
+ retval = pwdb_replace("user", tpt
+ , user, PWDB_ID_UNKNOWN, &tpw);
+ if (retval != PWDB_SUCCESS) {
+ const char *service=NULL;
+ (void) pam_get_item(pamh, PAM_SERVICE
+ , (const void **)&service);
+ _log_err(LOG_ALERT
+ , "(%s) specified database failed: %s"
+ , service
+ , pwdb_strerror(retval));
+ retval = PAM_PERM_DENIED;
+ } else {
+ retval = PAM_SUCCESS;
+ }
+ }
+
+ /* clean up temporary pwdb */
+ if (tpw)
+ (void) pwdb_delete(&tpw);
+ }
+
+ /* we can properly adopt new defer_pass */
+ if (retval == PAM_SUCCESS) {
+ /* failing here will mean we go back to former
+ password location */
+ (void) pwdb_set_entry(pw, "defer_pass", db_token
+ , 1+strlen(db_token), NULL, NULL, 0);
+ }
+ }
+ }
+ }
+
+ /*
+ * the password will now be placed in appropriate (perhaps original) db
+ */
+
+ retval = pwdb_get_entry(pw, "uid", &pwe);
+ if (retval != PWDB_SUCCESS) {
+ _log_err(LOG_ALERT, "no uid!? (%s); %s", user, pwdb_strerror(retval));
+ pass_new = NULL;
+ if (pw)
+ (void) pwdb_delete(&pw);
+ return PAM_USER_UNKNOWN;
+ }
+
+ /* insert the passwd into the 'pw' structure */
+
+ retval = pwdb_set_entry(pw, "passwd", pass_new, 1+strlen(pass_new)
+ , NULL, NULL, 0);
+ pass_new = NULL;
+ if (retval != PWDB_SUCCESS) {
+ _log_err(LOG_ALERT, "set2 failed; %s", pwdb_strerror(retval));
+ if (pw)
+ (void) pwdb_delete(&pw);
+ return PAM_AUTHTOK_LOCK_BUSY;
+ }
+
+ retval = pwdb_replace("user", pw->source, user
+ , *((uid_t *)pwe->value), &pw);
+ if (retval != PWDB_SUCCESS) {
+ _log_err(LOG_ALERT, "user (%s/%d) update failed; %s"
+ , user, *((uid_t *)pwe->value), pwdb_strerror(retval));
+ if (pw)
+ (void) pwdb_delete(&pw);
+ (void) pwdb_entry_delete(&pwe);
+ return PAM_ABORT;
+ }
+
+ if (retval != PWDB_SUCCESS) {
+
+ _log_err(LOG_ALERT, "user (%s/%d) update failed; %s"
+ , user, *((uid_t *)pwe->value), pwdb_strerror(retval));
+ retval = PAM_ABORT;
+
+ } else {
+ /* password updated */
+
+ _log_err(LOG_INFO, "password for (%s/%d) changed by (%s/%d)"
+ , user, *((uid_t *)pwe->value), getlogin(), getuid());
+ retval = PAM_SUCCESS;
+ }
+
+ /* tidy up */
+
+ (void) pwdb_entry_delete(&pwe);
+ if (pw)
+ (void) pwdb_delete(&pw);
+
+ return retval;
+}
+
+/* ******************************************************************
+ * Copyright (c) Andrew Morgan <morgan@parc.power.net> 1996,1997.
+ * Copyright (c) Cristian Gafton, <gafton@redhat.com> 1996, 1997.
+ * 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, 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.
+ */