yp_passwd.c revision 1.1 1 /*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33 #ifndef lint
34 static char sccsid[] = "@(#)nis_passwd.c 1.0 2/2/93";
35 #endif /* not lint */
36
37 #ifdef YP
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <netdb.h>
42 #include <time.h>
43 #include <pwd.h>
44 #include <errno.h>
45 #include <rpc/rpc.h>
46 #include <rpcsvc/yp_prot.h>
47 #include <rpcsvc/ypclnt.h>
48 #define passwd yp_passwd_rec
49 #include <rpcsvc/yppasswd.h>
50 #undef passwd
51
52 #ifndef _PASSWORD_LEN
53 #define _PASSWORD_LEN PASS_MAX
54 #endif
55
56 extern char *progname;
57 static char *getnewpasswd();
58 static struct passwd *ypgetpwnam();
59
60 static uid_t uid;
61 char *domain;
62
63 nis_passwd(uname)
64 char *uname;
65 {
66 char *master;
67 char *pp;
68 int r, rpcport, status;
69 struct yppasswd yppasswd;
70 struct passwd *pw;
71 struct timeval tv;
72 CLIENT *client;
73
74 uid = getuid();
75
76 /*
77 * Get local domain
78 */
79 if (r = yp_get_default_domain(&domain)) {
80 (void)fprintf(stderr, "%s: can't get local NIS domain. Reason: %s\n", progname, yperr_string(r));
81 exit(1);
82 }
83
84 /*
85 * Find the host for the passwd map; it should be running
86 * the daemon.
87 */
88 if ((r = yp_master(domain, "passwd.byname", &master)) != 0) {
89 (void)fprintf(stderr, "%s: can't find the master NIS server. Reason: %s\n", progname, yperr_string(r));
90 exit(1);
91 }
92
93 /*
94 * Ask the portmapper for the port of the daemon.
95 */
96 if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) {
97 (void)fprintf(stderr, "%s: master NIS server not running yppasswd daemon.\n\tCan't change password.\n", progname);
98 exit(1);
99 }
100
101 /*
102 * Be sure the port is priviledged
103 */
104 if (rpcport >= IPPORT_RESERVED) {
105 (void)fprintf(stderr, "%s: yppasswd daemon running on an invalid port.\n", progname);
106 exit(1);
107 }
108
109 /* Get user's login identity */
110 if (!(pw = ypgetpwnam(uname))) {
111 (void)fprintf(stderr, "%s: unknown user %s.\n", progname, uname);
112 exit(1);
113 }
114
115 if (uid && uid != pw->pw_uid) {
116 (void)fprintf(stderr, "%s: you are only allowed to change your own password: %s\n", progname, strerror(EACCES));
117 exit(1);
118 }
119
120 /* prompt for new password */
121 yppasswd.newpw.pw_passwd = getnewpasswd(pw, &yppasswd.oldpass);
122
123 /* tell rpc.yppasswdd */
124 yppasswd.newpw.pw_name = pw->pw_name;
125 yppasswd.newpw.pw_uid = pw->pw_uid;
126 yppasswd.newpw.pw_gid = pw->pw_gid;
127 yppasswd.newpw.pw_gecos = pw->pw_gecos;
128 yppasswd.newpw.pw_dir = pw->pw_dir;
129 yppasswd.newpw.pw_shell = pw->pw_shell;
130
131 client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
132 if (client==NULL) {
133 fprintf(stderr, "can't contact yppasswdd on %s: Reason: %s\n",
134 master, yperr_string(YPERR_YPBIND));
135 return(YPERR_YPBIND);
136 }
137 client->cl_auth = authunix_create_default();
138 tv.tv_sec = 2;
139 tv.tv_usec = 0;
140 r = clnt_call(client, YPPASSWDPROC_UPDATE,
141 xdr_yppasswd, &yppasswd, xdr_int, &status, tv);
142 if (r)
143 fprintf(stderr, "%s: rpc to yppasswdd failed.\n");
144 else if (status)
145 printf("Couldn't change NIS password.\n");
146 else
147 printf("The NIS password has been changed on %s, the master NIS passwd server.\n", master);
148
149 exit(0);
150 }
151
152 static char *
153 getnewpasswd(pw, old_pass)
154 register struct passwd *pw;
155 char **old_pass;
156 {
157 static char buf[_PASSWORD_LEN+1];
158 register char *p, *t;
159 int tries;
160 char salt[9], *crypt(), *getpass();
161
162 (void)printf("Changing NIS password for %s.\n", pw->pw_name);
163
164 if (uid && old_pass) {
165 *old_pass = NULL;
166
167 if (pw->pw_passwd &&
168 #ifdef DES
169 strcmp(crypt(p = getpass("Old password:"), pw->pw_passwd),
170 pw->pw_passwd)) {
171 #else
172 strcmp(p = getpass("Old password:"), pw->pw_passwd)) {
173 #endif
174 errno = EACCES;
175 pw_error(NULL, 1, 1);
176 }
177 *old_pass = strdup(p);
178 }
179 for (buf[0] = '\0', tries = 0;;) {
180 p = getpass("New password:");
181 if (!*p) {
182 (void)printf("Password unchanged.\n");
183 pw_error(NULL, 0, 0);
184 }
185 if (strlen(p) <= 5 && (uid != 0 || ++tries < 2)) {
186 (void)printf("Please enter a longer password.\n");
187 continue;
188 }
189 for (t = p; *t && islower(*t); ++t);
190 if (!*t && (uid != 0 || ++tries < 2)) {
191 (void)printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n");
192 continue;
193 }
194 (void)strcpy(buf, p);
195 if (!strcmp(buf, getpass("Retype new password:")))
196 break;
197 (void)printf("Mismatch; try again, EOF to quit.\n");
198 }
199 /* grab a random printable character that isn't a colon */
200 (void)srandom((int)time((time_t *)NULL));
201 #ifdef NEWSALT
202 salt[0] = _PASSWORD_EFMT1;
203 to64(&salt[1], (long)(29 * 25), 4);
204 to64(&salt[5], random(), 4);
205 #else
206 to64(&salt[0], random(), 2);
207 #endif
208 #ifdef DES
209 return(strdup(crypt(buf, salt)));
210 #else
211 return(buf);
212 #endif
213 }
214
215 static char *
216 pwskip(register char *p)
217 {
218 while (*p && *p != ':' && *p != '\n')
219 ++p;
220 if (*p)
221 *p++ = 0;
222 return (p);
223 }
224
225 struct passwd *
226 interpret(struct passwd *pwent, char *line)
227 {
228 register char *p = line;
229 register int c;
230
231 pwent->pw_passwd = "*";
232 pwent->pw_uid = 0;
233 pwent->pw_gid = 0;
234 pwent->pw_gecos = "";
235 pwent->pw_dir = "";
236 pwent->pw_shell = "";
237 pwent->pw_change = 0;
238 pwent->pw_expire = 0;
239 pwent->pw_class = "";
240
241 /* line without colon separators is no good, so ignore it */
242 if(!strchr(p,':'))
243 return(NULL);
244
245 pwent->pw_name = p;
246 p = pwskip(p);
247 pwent->pw_passwd = p;
248 p = pwskip(p);
249 pwent->pw_uid = (uid_t)strtoul(p, NULL, 10);
250 p = pwskip(p);
251 pwent->pw_gid = (gid_t)strtoul(p, NULL, 10);
252 p = pwskip(p);
253 pwent->pw_gecos = p;
254 p = pwskip(p);
255 pwent->pw_dir = p;
256 p = pwskip(p);
257 pwent->pw_shell = p;
258 while (*p && *p != '\n')
259 p++;
260 *p = '\0';
261 return (pwent);
262 }
263
264 static struct passwd *
265 ypgetpwnam(nam)
266 char *nam;
267 {
268 static struct passwd pwent;
269 static char line[1024];
270 char *val;
271 int reason, vallen;
272
273 reason = yp_match(domain, "passwd.byname", nam, strlen(nam),
274 &val, &vallen);
275 switch(reason) {
276 case 0:
277 break;
278 default:
279 return (NULL);
280 break;
281 }
282 val[vallen] = '\0';
283 strcpy(line, val);
284 free(val);
285
286 return(interpret(&pwent, line));
287 }
288
289 #endif /* YP */
290