1 /* $NetBSD: local_passwd.c,v 1.32 2009/04/12 23:59:37 lukem Exp $ */
4 * Copyright (c) 1990, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "from: @(#)local_passwd.c 8.3 (Berkeley) 4/2/94";
37 __RCSID("$NetBSD: local_passwd.c,v 1.32 2009/04/12 23:59:37 lukem Exp $");
41 #include <sys/types.h>
55 #include <login_cap.h>
62 getnewpasswd(struct passwd
*pw
, int min_pw_len
)
66 char buf
[_PASSWORD_LEN
+1], salt
[_PASSWORD_LEN
+1];
67 char option
[LINE_MAX
], *key
, *opt
;
69 (void)printf("Changing local password for %s.\n", pw
->pw_name
);
71 if (uid
&& pw
->pw_passwd
[0] &&
72 strcmp(crypt(getpass("Old password:"), pw
->pw_passwd
),
78 for (buf
[0] = '\0', tries
= 0;;) {
79 p
= getpass("New password:");
81 (void)printf("Password unchanged.\n");
84 if (min_pw_len
> 0 && (int)strlen(p
) < min_pw_len
) {
85 (void) printf("Password is too short.\n");
88 if (strlen(p
) <= 5 && ++tries
< 2) {
89 (void)printf("Please enter a longer password.\n");
92 for (t
= p
; *t
&& islower((unsigned char)*t
); ++t
);
93 if (!*t
&& ++tries
< 2) {
94 (void)printf("Please don't use an all-lower case "
95 "password.\nUnusual capitalization, "
96 "control characters or digits are "
100 (void)strlcpy(buf
, p
, sizeof(buf
));
101 if (!strcmp(buf
, getpass("Retype new password:")))
103 (void)printf("Mismatch; try again, EOF to quit.\n");
106 pw_getpwconf(option
, sizeof(option
), pw
, "localcipher");
108 key
= strsep(&opt
, ",");
109 if(pw_gensalt(salt
, _PASSWORD_LEN
, key
, opt
) == -1) {
110 warn("Couldn't generate salt");
111 pw_error(NULL
, 0, 0);
113 return(crypt(buf
, salt
));
119 pwlocal_usage(const char *prefix
)
122 (void) fprintf(stderr
, "%s %s [-d files | -l] [user]\n",
123 prefix
, getprogname());
127 pwlocal_process(const char *username
, int argc
, char **argv
)
130 struct passwd old_pw
;
140 while ((ch
= getopt(argc
, argv
, "l")) != -1) {
144 * Aborb the -l that may have gotten us here.
159 /* username already provided */
169 if (!(pw
= getpwnam(username
)))
170 errx(1, "unknown user %s", username
);
173 if (uid
&& uid
!= pw
->pw_uid
)
174 errx(1, "%s", strerror(EACCES
));
176 /* Save the old pw information for comparing on pw_copy(). */
180 * Get class restrictions for this user, then get the new password.
183 if((lc
= login_getclass(pw
->pw_class
)) != NULL
) {
184 min_pw_len
= (int) login_getcapnum(lc
, "minpasswordlen", 0, 0);
185 pw_expiry
= (int) login_getcaptime(lc
, "passwordtime", 0, 0);
190 pw
->pw_passwd
= getnewpasswd(pw
, min_pw_len
);
191 old_change
= pw
->pw_change
;
192 pw
->pw_change
= pw_expiry
? pw_expiry
+ time(NULL
) : 0;
195 * Now that the user has given us a new password, let us
196 * change the database.
201 warnx ("The passwd file is busy, waiting...");
204 errx(1, "The passwd file is still busy, "
208 pfd
= open(_PATH_MASTERPASSWD
, O_RDONLY
, 0);
210 pw_error(_PATH_MASTERPASSWD
, 1, 1);
212 pw_copy(pfd
, tfd
, pw
, &old_pw
);
214 if (pw_mkdb(username
, old_change
== pw
->pw_change
) < 0)
215 pw_error((char *)NULL
, 0, 1);
218 #else /* ! USE_PAM */
220 static int force_local
;
224 const char *progname
;
231 local_arg(char ch
, const char *arg
)
247 return(PW_USE_FORCE
);
262 struct passwd old_pw
;
271 if (!(pw
= getpwnam(uname
))) {
272 warnx("unknown user %s", uname
);
277 if (uid
&& uid
!= pw
->pw_uid
) {
278 warnx("%s", strerror(EACCES
));
282 /* Save the old pw information for comparing on pw_copy(). */
286 * Get class restrictions for this user, then get the new password.
289 if((lc
= login_getclass(pw
->pw_class
))) {
290 min_pw_len
= (int) login_getcapnum(lc
, "minpasswordlen", 0, 0);
291 pw_expiry
= (int) login_getcaptime(lc
, "passwordtime", 0, 0);
296 pw
->pw_passwd
= getnewpasswd(pw
, min_pw_len
);
297 old_change
= pw
->pw_change
;
298 pw
->pw_change
= pw_expiry
? pw_expiry
+ time(NULL
) : 0;
301 * Now that the user has given us a new password, let us
302 * change the database.
307 warnx ("The passwd file is busy, waiting...");
310 errx(1, "The passwd file is still busy, "
314 pfd
= open(_PATH_MASTERPASSWD
, O_RDONLY
, 0);
316 pw_error(_PATH_MASTERPASSWD
, 1, 1);
318 pw_copy(pfd
, tfd
, pw
, &old_pw
);
320 if (pw_mkdb(uname
, old_change
== pw
->pw_change
) < 0)
321 pw_error((char *)NULL
, 0, 1);