1 /* $NetBSD: yp_passwd.c,v 1.32 2008/01/25 19:36:12 christos Exp $ */
4 * Copyright (c) 1988, 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: yp_passwd.c,v 1.32 2008/01/25 19:36:12 christos Exp $");
57 #include <rpcsvc/yp_prot.h>
58 #include <rpcsvc/ypclnt.h>
62 #define passwd yp_passwd_rec
63 #include <rpcsvc/yppasswd.h>
67 #define _PASSWORD_LEN PASS_MAX
74 pwerror(const char *name
, int show_err
, int eval
)
79 errx(eval
, "NIS passwd database unchanged");
83 getnewpasswd(struct passwd
*pw
, char **old_pass
)
88 static char buf
[_PASSWORD_LEN
+1];
89 char salt
[_PASSWORD_LEN
+1];
90 char option
[LINE_MAX
], *key
, *opt
;
92 (void)printf("Changing NIS password for %s.\n", pw
->pw_name
);
97 if (pw
->pw_passwd
[0]) {
98 if (strcmp(crypt(p
= getpass("Old password:"),
99 pw
->pw_passwd
), pw
->pw_passwd
)) {
100 (void)printf("Sorry.\n");
107 *old_pass
= strdup(p
);
109 (void)printf("not enough core.\n");
113 for (buf
[0] = '\0', tries
= 0;;) {
114 p
= getpass("New password:");
116 (void)printf("Password unchanged.\n");
119 if (strlen(p
) <= 5 && ++tries
< 2) {
120 (void)printf("Please enter a longer password.\n");
123 for (t
= p
; *t
&& islower((unsigned char)*t
); ++t
);
124 if (!*t
&& ++tries
< 2) {
125 (void)printf("Please don't use an all-lower case "
126 "password.\nUnusual capitalization, "
127 "control characters or digits are "
131 (void)strlcpy(buf
, p
, sizeof(buf
));
132 if (!strcmp(buf
, getpass("Retype new password:")))
134 (void)printf("Mismatch; try again, EOF to quit.\n");
137 pw_getpwconf(option
, sizeof(option
), pw
, "ypcipher");
139 key
= strsep(&opt
, ",");
140 if (pw_gensalt(salt
, _PASSWORD_LEN
, key
, opt
) == -1) {
141 warn("Couldn't generate salt");
144 result
= strdup(crypt(buf
, salt
));
146 (void)printf("not enough core.\n");
153 makeypp(struct yppasswd
*ypp
, struct passwd
*pw
)
155 /* prompt for new password */
156 ypp
->newpw
.pw_passwd
= getnewpasswd(pw
, &ypp
->oldpass
);
158 /* tell rpc.yppasswdd */
159 ypp
->newpw
.pw_name
= estrdup(pw
->pw_name
);
160 ypp
->newpw
.pw_uid
= pw
->pw_uid
;
161 ypp
->newpw
.pw_gid
= pw
->pw_gid
;
162 ypp
->newpw
.pw_gecos
= estrdup(pw
->pw_gecos
);
163 ypp
->newpw
.pw_dir
= estrdup(pw
->pw_dir
);
164 ypp
->newpw
.pw_shell
= estrdup(pw
->pw_shell
);
168 ypgetpwnam(const char *nam
, struct passwd
*pwd
)
176 reason
= yp_match(domain
, "passwd.byname", nam
, (int)strlen(nam
),
181 flags
= _PASSWORD_OLDFMT
;
182 if (pw_scan(val
, pwd
, &flags
) == 0)
195 pwyp_usage(const char *prefix
)
198 (void) fprintf(stderr
, "%s %s [-d nis | -y] [user]\n",
199 prefix
, getprogname());
203 pwyp_argv0_usage(const char *prefix
)
206 (void) fprintf(stderr
, "%s %s [user]\n",
207 prefix
, getprogname());
211 pwyp_process(const char *username
, int argc
, char **argv
)
214 int ch
, r
, rpcport
, status
;
216 struct passwd pwb
, *pw
;
221 while ((ch
= getopt(argc
, argv
, "y")) != -1) {
225 * Abosrb the -y that may have gotten us here.
240 /* username already provided */
250 if (_yp_check(NULL
) == 0) {
252 errx(1, "NIS not in use.");
260 if ((r
= yp_get_default_domain(&domain
)) != 0)
261 errx(1, "can't get local NIS domain. Reason: %s",
265 * Find the host for the passwd map; it should be running
268 if ((r
= yp_master(domain
, "passwd.byname", &master
)) != 0)
269 errx(1, "can't find the master NIS server. Reason: %s",
273 * Ask the portmapper for the port of the daemon.
275 if ((rpcport
= getrpcport(master
, YPPASSWDPROG
,
276 YPPASSWDPROC_UPDATE
, IPPROTO_UDP
)) == 0)
277 errx(1, "master NIS server not running yppasswd daemon.\n\t%s\n",
278 "Can't change NIS password.");
281 * Be sure the port is privileged
283 if (rpcport
>= IPPORT_RESERVED
)
284 errx(1, "yppasswd daemon is on an invalid port.");
286 /* Bail out if this is a local (non-yp) user, */
287 /* then get user's login identity */
288 if (!ypgetpwnam(username
, pw
= &pwb
) ||
289 getpwnam_r(username
, &pwb
, pwbuf
, sizeof(pwbuf
), &pw
) ||
291 errx(1, "NIS unknown user %s", username
);
293 if (uid
&& uid
!= pw
->pw_uid
)
294 errx(1, "you may only change your own password: %s",
299 client
= clnt_create(master
, YPPASSWDPROG
, YPPASSWDVERS
, "udp");
301 errx(1, "cannot contact yppasswdd on %s: Reason: %s",
302 master
, yperr_string(YPERR_YPBIND
));
304 client
->cl_auth
= authunix_create_default();
307 r
= clnt_call(client
, YPPASSWDPROC_UPDATE
,
308 xdr_yppasswd
, &ypp
, xdr_int
, &status
, tv
);
310 errx(1, "rpc to yppasswdd failed.");
312 printf("Couldn't change NIS password.\n");
314 printf("The NIS password has been changed on %s, %s\n",
315 master
, "the master NIS passwd server.");
318 #else /* ! USE_PAM */
324 const char *progname
;
328 if (strcmp(progname
, "yppasswd") == 0) {
333 if (_yp_check(NULL
) == 0) {
336 errx(1, "NIS not in use.");
361 return (PW_USE_FORCE
);
373 const char *username
;
376 int r
, rpcport
, status
;
378 struct passwd
*pw
, pwb
;
388 if ((r
= yp_get_default_domain(&domain
)) != 0)
389 errx(1, "can't get local NIS domain. Reason: %s",
393 * Find the host for the passwd map; it should be running
396 if ((r
= yp_master(domain
, "passwd.byname", &master
)) != 0) {
397 warnx("can't find the master NIS server. Reason: %s",
404 * Ask the portmapper for the port of the daemon.
406 if ((rpcport
= getrpcport(master
, YPPASSWDPROG
,
407 YPPASSWDPROC_UPDATE
, IPPROTO_UDP
)) == 0) {
408 warnx("master NIS server not running yppasswd daemon.\n\t%s\n",
409 "Can't change NIS password.");
415 * Be sure the port is privileged
417 if (rpcport
>= IPPORT_RESERVED
)
418 errx(1, "yppasswd daemon is on an invalid port.");
420 /* Bail out if this is a local (non-yp) user, */
421 /* then get user's login identity */
422 if (!ypgetpwnam(username
, pw
= &pwb
) ||
423 getpwnam_r(username
, &pwb
, pwbuf
, sizeof(pwbuf
), &pw
) ||
425 warnx("NIS unknown user %s", username
);
430 if (uid
&& uid
!= pw
->pw_uid
)
431 errx(1, "you may only change your own password: %s",
436 client
= clnt_create(master
, YPPASSWDPROG
, YPPASSWDVERS
, "udp");
437 if (client
== NULL
) {
438 warnx("cannot contact yppasswdd on %s: Reason: %s",
439 master
, yperr_string(YPERR_YPBIND
));
440 return (YPERR_YPBIND
);
443 client
->cl_auth
= authunix_create_default();
446 r
= clnt_call(client
, YPPASSWDPROC_UPDATE
,
447 xdr_yppasswd
, &ypp
, xdr_int
, &status
, tv
);
449 errx(1, "rpc to yppasswdd failed.");
451 printf("Couldn't change NIS password.\n");
453 printf("The NIS password has been changed on %s, %s\n",
454 master
, "the master NIS passwd server.");