4 * This file contains the routines to update the passwd databases.
9 static int unix_update_db(pam_handle_t *pamh, int ctrl, const char *user,
10 const char *pass_old, const char *pass_new)
12 const struct pwdb *pw=NULL;
13 const struct pwdb_entry *pwe=NULL;
19 /* obtain default user record */
21 retval = pwdb_locate("user", PWDB_DEFAULT, user, PWDB_ID_UNKNOWN, &pw);
22 if (retval == PWDB_PASS_PHRASE_REQD) {
23 retval = pwdb_set_entry(pw, "pass_phrase"
24 , pass_old, 1+strlen(pass_old)
26 if (retval == PWDB_SUCCESS)
27 retval = pwdb_locate("user", pw->source, user
28 , PWDB_ID_UNKNOWN, &pw);
32 if ( retval != PWDB_SUCCESS ) {
33 _log_err(LOG_ALERT, "cannot identify user %s (uid=%d)"
37 (void) pwdb_delete(&pw);
38 return PAM_USER_UNKNOWN;
41 /* check that we can update all of the default databases */
43 retval = pwdb_flags("user", pw->source, &flag);
45 if ( retval != PWDB_SUCCESS || ( pwdb_on(flag,PWDB_F_NOUPDATE) ) ) {
46 _log_err(LOG_ERR, "cannot update default database for user %s"
50 (void) pwdb_delete(&pw);
51 return PAM_PERM_DENIED;
54 /* If there was one, we delete the "last_change" entry */
55 retval = pwdb_get_entry(pw, "last_change", &pwe);
56 if (retval == PWDB_SUCCESS) {
57 (void) pwdb_entry_delete(&pwe);
58 pwdb_set_entry(pw, "last_change", NULL, -1, NULL, NULL, 0);
62 * next check for pam.conf specified databases: shadow etc... [In
63 * other words, pam.conf indicates which database the password is
64 * to be subsequently placed in: this is password migration].
67 if ( on(UNIX__SET_DB, ctrl) ) {
69 pwdb_type pt = _PWDB_MAX_TYPES;
71 if ( on(UNIX_UNIX, ctrl) ) {
72 db_token = "U"; /* XXX - should be macro */
74 } else if ( on(UNIX_SHADOW, ctrl) ) {
75 db_token = "x"; /* XXX - should be macro */
77 } else if ( on(UNIX_RADIUS, ctrl) ) {
78 db_token = "R"; /* XXX - is this ok? */
82 , "cannot determine database to use for authtok");
85 (void) pwdb_delete(&pw);
86 return PAM_ABORT; /* we're in trouble */
90 * Attempt to update the indicated database (only)
96 tpt[1] = _PWDB_MAX_TYPES;
98 /* Can we set entry in database? */
99 retval = pwdb_flags("user", tpt, &flag);
100 if (retval == PWDB_SUCCESS && !pwdb_on(flag,PWDB_F_NOUPDATE)) {
101 /* YES. This database is available.. */
103 /* Only update if it is not already in the default list */
104 for (i=0; pw->source[i] != _PWDB_MAX_TYPES
105 && pw->source[i] != pt ; ++i);
106 if (pw->source[i] == _PWDB_MAX_TYPES) {
107 const struct pwdb *tpw=NULL;
109 /* copy database entry */
110 if ((retval = pwdb_new(&tpw, 10)) != PWDB_SUCCESS
111 || (retval = pwdb_merge(tpw, pw, PWDB_TRUE))
113 _log_err(LOG_CRIT, "failed to obtain new pwdb: %s"
114 , pwdb_strerror(retval));
117 retval = PAM_SUCCESS;
120 if (retval == PAM_SUCCESS) {
121 retval = pwdb_set_entry(tpw, "defer_pass", db_token
124 if (retval != PWDB_SUCCESS) {
125 _log_err(LOG_ALERT, "set defer_pass -> %s"
126 , pwdb_strerror(retval));
127 retval = PAM_PERM_DENIED;
129 retval = PAM_SUCCESS;
132 /* update specific database */
133 if (retval == PAM_SUCCESS) {
134 retval = pwdb_replace("user", tpt
135 , user, PWDB_ID_UNKNOWN, &tpw);
136 if (retval != PWDB_SUCCESS) {
137 const char *service=NULL;
138 (void) pam_get_item(pamh, PAM_SERVICE
139 , (const void **)&service);
141 , "(%s) specified database failed: %s"
143 , pwdb_strerror(retval));
144 retval = PAM_PERM_DENIED;
146 retval = PAM_SUCCESS;
150 /* clean up temporary pwdb */
152 (void) pwdb_delete(&tpw);
155 /* we can properly adopt new defer_pass */
156 if (retval == PAM_SUCCESS) {
157 /* failing here will mean we go back to former
159 (void) pwdb_set_entry(pw, "defer_pass", db_token
160 , 1+strlen(db_token), NULL, NULL, 0);
167 * the password will now be placed in appropriate (perhaps original) db
170 retval = pwdb_get_entry(pw, "uid", &pwe);
171 if (retval != PWDB_SUCCESS) {
172 _log_err(LOG_ALERT, "no uid!? (%s); %s", user, pwdb_strerror(retval));
175 (void) pwdb_delete(&pw);
176 return PAM_USER_UNKNOWN;
179 /* insert the passwd into the 'pw' structure */
181 retval = pwdb_set_entry(pw, "passwd", pass_new, 1+strlen(pass_new)
184 if (retval != PWDB_SUCCESS) {
185 _log_err(LOG_ALERT, "set2 failed; %s", pwdb_strerror(retval));
187 (void) pwdb_delete(&pw);
188 return PAM_AUTHTOK_LOCK_BUSY;
191 retval = pwdb_replace("user", pw->source, user
192 , *((uid_t *)pwe->value), &pw);
193 if (retval != PWDB_SUCCESS) {
194 _log_err(LOG_ALERT, "user (%s/%d) update failed; %s"
195 , user, *((uid_t *)pwe->value), pwdb_strerror(retval));
197 (void) pwdb_delete(&pw);
198 (void) pwdb_entry_delete(&pwe);
202 if (retval != PWDB_SUCCESS) {
204 _log_err(LOG_ALERT, "user (%s/%d) update failed; %s"
205 , user, *((uid_t *)pwe->value), pwdb_strerror(retval));
209 /* password updated */
211 _log_err(LOG_INFO, "password for (%s/%d) changed by (%s/%d)"
212 , user, *((uid_t *)pwe->value), getlogin(), getuid());
213 retval = PAM_SUCCESS;
218 (void) pwdb_entry_delete(&pwe);
220 (void) pwdb_delete(&pw);
225 /* ******************************************************************
226 * Copyright (c) Andrew Morgan <morgan@parc.power.net> 1996,1997.
227 * Copyright (c) Cristian Gafton, <gafton@redhat.com> 1996, 1997.
228 * All rights reserved
230 * Redistribution and use in source and binary forms, with or without
231 * modification, are permitted provided that the following conditions
233 * 1. Redistributions of source code must retain the above copyright
234 * notice, and the entire permission notice in its entirety,
235 * including the disclaimer of warranties.
236 * 2. Redistributions in binary form must reproduce the above copyright
237 * notice, this list of conditions and the following disclaimer in the
238 * documentation and/or other materials provided with the distribution.
239 * 3. The name of the author may not be used to endorse or promote
240 * products derived from this software without specific prior
241 * written permission.
243 * ALTERNATIVELY, this product may be distributed under the terms of
244 * the GNU Public License, in which case the provisions of the GPL are
245 * required INSTEAD OF the above restrictions. (This clause is
246 * necessary due to a potential bad interaction between the GPL and
247 * the restrictions contained in a BSD-style copyright.)
249 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
250 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
251 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
252 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
253 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
254 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
255 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
256 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
257 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
258 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
259 * OF THE POSSIBILITY OF SUCH DAMAGE.