1 /* $NetBSD: yp_passwd.c,v 1.35 2010/09/08 13:58:46 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.35 2010/09/08 13:58:46 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
)
171 int reason
, vallen
, namlen
= (int)strlen(nam
);
177 reason
= yp_match(domain
, "master.passwd.byname", nam
, namlen
,
179 if (reason
== YPERR_MAP
) {
180 reason
= yp_match(domain
, "passwd.byname", nam
, namlen
,
182 flags
= _PASSWORD_OLDFMT
;
187 if (pw_scan(val
, pwd
, &flags
) == 0)
191 val
= NULL
; /* Don't free the memory, it is still in use */
201 pwyp_usage(const char *prefix
)
204 (void)fprintf(stderr
, "%s %s [-d nis | -y] [user]\n",
205 prefix
, getprogname());
209 pwyp_argv0_usage(const char *prefix
)
212 (void)fprintf(stderr
, "%s %s [user]\n",
213 prefix
, getprogname());
217 pwyp_process(const char *username
, int argc
, char **argv
)
220 int ch
, r
, rpcport
, status
;
223 struct passwd pwb
, pwb2
, *pw
;
228 while ((ch
= getopt(argc
, argv
, "y")) != -1) {
232 * Abosrb the -y that may have gotten us here.
247 /* username already provided */
257 if (_yp_check(NULL
) == 0) {
259 errx(EXIT_FAILURE
, "NIS not in use.");
267 if ((r
= yp_get_default_domain(&domain
)) != 0)
268 errx(EXIT_FAILURE
, "Can't get local NIS domain (%s)",
272 * Find the host for the passwd map; it should be running
275 if ((r
= yp_master(domain
, "passwd.byname", &master
)) != 0)
276 errx(EXIT_FAILURE
, "Can't find the master NIS server (%s)",
280 * Ask the portmapper for the port of the daemon.
282 if ((rpcport
= getrpcport(master
, YPPASSWDPROG
,
283 YPPASSWDPROC_UPDATE
, IPPROTO_UDP
)) == 0)
284 errx(EXIT_FAILURE
, "Master NIS server not running yppasswd "
288 * Be sure the port is privileged
290 if (rpcport
>= IPPORT_RESERVED
)
291 errx(EXIT_FAILURE
, "Yppasswd daemon is on an invalid port");
293 /* Bail out if this is a local (non-yp) user, */
294 /* then get user's login identity */
295 if (!ypgetpwnam(username
, &pwb
) ||
296 getpwnam_r(username
, &pwb2
, pwbuf
, sizeof(pwbuf
), &pw
) ||
298 errx(EXIT_FAILURE
, "NIS unknown user %s", username
);
300 if (uid
&& uid
!= pwb
.pw_uid
) {
302 err(EXIT_FAILURE
, "You may only change your own password");
307 client
= clnt_create(master
, YPPASSWDPROG
, YPPASSWDVERS
, "udp");
309 errx(EXIT_FAILURE
, "Cannot contact yppasswdd on %s (%s)",
310 master
, yperr_string(YPERR_YPBIND
));
312 client
->cl_auth
= authunix_create_default();
315 yr
= clnt_call(client
, YPPASSWDPROC_UPDATE
,
316 xdr_yppasswd
, &ypp
, xdr_int
, &status
, tv
);
317 if (yr
!= RPC_SUCCESS
)
318 errx(EXIT_FAILURE
, "RPC to yppasswdd failed (%s)",
321 printf("Couldn't change NIS password.\n");
323 printf("The NIS password has been changed on %s, %s\n",
324 master
, "the master NIS passwd server.");
327 #else /* ! USE_PAM */
333 const char *progname
;
337 if (strcmp(progname
, "yppasswd") == 0) {
342 if (_yp_check(NULL
) == 0) {
345 errx(EXIT_FAILURE
, "NIS not in use");
352 yp_arg(char ch
, const char *arg
)
379 yp_chpw(const char *username
)
382 int r
, rpcport
, status
;
385 struct passwd
*pw
, pwb
;
395 if ((r
= yp_get_default_domain(&domain
)) != 0)
396 errx(EXIT_FAILURE
, "can't get local NIS domain. Reason: %s",
400 * Find the host for the passwd map; it should be running
403 if ((r
= yp_master(domain
, "passwd.byname", &master
)) != 0) {
404 warnx("can't find the master NIS server. Reason: %s",
411 * Ask the portmapper for the port of the daemon.
413 if ((rpcport
= getrpcport(master
, YPPASSWDPROG
,
414 YPPASSWDPROC_UPDATE
, IPPROTO_UDP
)) == 0) {
415 warnx("Master NIS server not running yppasswd daemon");
421 * Be sure the port is privileged
423 if (rpcport
>= IPPORT_RESERVED
)
424 errx(EXIT_FAILURE
, "Yppasswd daemon is on an invalid port");
426 /* Bail out if this is a local (non-yp) user, */
427 /* then get user's login identity */
428 if (!ypgetpwnam(username
, pw
= &pwb
) ||
429 getpwnam_r(username
, &pwb
, pwbuf
, sizeof(pwbuf
), &pw
) ||
431 warnx("NIS unknown user %s", username
);
436 if (uid
&& uid
!= pw
->pw_uid
) {
438 err(EXIT_FAILURE
, "You may only change your own password");
443 client
= clnt_create(master
, YPPASSWDPROG
, YPPASSWDVERS
, "udp");
444 if (client
== NULL
) {
445 warnx("Cannot contact yppasswdd on %s (%s)",
446 master
, yperr_string(YPERR_YPBIND
));
450 client
->cl_auth
= authunix_create_default();
453 yr
= clnt_call(client
, YPPASSWDPROC_UPDATE
,
454 xdr_yppasswd
, &ypp
, xdr_int
, &status
, tv
);
455 if (yr
!= RPC_SUCCESS
)
456 errx(EXIT_FAILURE
, "RPC to yppasswdd failed (%s)",
459 printf("Couldn't change NIS password.\n");
461 printf("The NIS password has been changed on %s, %s\n",
462 master
, "the master NIS passwd server.");