xref: /netbsd-src/usr.bin/chpass/pw_yp.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
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[] = "@(#)pw_yp.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 extern char *progname;
53 
54 static char *domain;
55 
56 pw_yp(pw, uid)
57         struct passwd *pw;
58         uid_t uid;
59 {
60         char *master;
61         char *pp;
62         int r, rpcport, status;
63         struct yppasswd yppasswd;
64 	struct timeval tv;
65 	CLIENT *client;
66         extern char *getpass();
67 
68         /*
69          * Get local domain
70          */
71         if (!domain && (r = yp_get_default_domain(&domain))) {
72                 (void)fprintf(stderr, "%s: can't get local NIS domain. Reason: %s\n", progname, yperr_string(r));
73                 return(0);
74         }
75 
76         /*
77          * Find the host for the passwd map; it should be running
78          * the daemon.
79          */
80         if ((r = yp_master(domain, "passwd.byname", &master)) != 0) {
81                 (void)fprintf(stderr, "%s: can't find the master NIS server. Reason: %s\n", progname, yperr_string(r));
82                 return(0);
83         }
84 
85         /*
86          * Ask the portmapper for the port of the daemon.
87          */
88         if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) {
89                 (void)fprintf(stderr, "%s: master NIS server not running yppasswd daemon.\n\tCan't change password.\n", progname);
90                 return(0);
91         }
92 
93         /*
94          * Be sure the port is priviledged
95          */
96         if (rpcport >= IPPORT_RESERVED) {
97                 (void)fprintf(stderr, "%s: yppasswd daemon running on an invalid port.\n", progname);
98                 return(0);
99         }
100 
101         /* prompt for old password */
102         yppasswd.oldpass = "none";
103         if (uid)
104                 yppasswd.oldpass = getpass("Old password:");
105         if (!yppasswd.oldpass) {
106                 (void)fprintf(stderr, "Cancelled.\n");
107                 return(0);
108         }
109 
110         /* tell rpc.yppasswdd */
111         yppasswd.newpw.pw_name	= pw->pw_name;
112         yppasswd.newpw.pw_passwd= pw->pw_passwd;
113         yppasswd.newpw.pw_uid 	= pw->pw_uid;
114         yppasswd.newpw.pw_gid	= pw->pw_gid;
115         yppasswd.newpw.pw_gecos = pw->pw_gecos;
116         yppasswd.newpw.pw_dir	= pw->pw_dir;
117         yppasswd.newpw.pw_shell	= pw->pw_shell;
118 
119         client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
120         if (client==NULL) {
121                 fprintf(stderr, "can't contact yppasswdd on %s: Reason: %s\n",
122                         master, yperr_string(YPERR_YPBIND));
123                 return(0);
124         }
125         client->cl_auth = authunix_create_default();
126         tv.tv_sec = 2;
127         tv.tv_usec = 0;
128         r = clnt_call(client, YPPASSWDPROC_UPDATE,
129                       xdr_yppasswd, &yppasswd, xdr_int, &status, tv);
130         if (r) {
131                 fprintf(stderr, "%s: rpc to yppasswdd failed.\n");
132                 return(0);
133         }
134         else if (status) {
135                 printf("Couldn't change NIS password information.\n");
136                 return(0);
137         }
138         else
139                 printf("The NIS password information has been changed on %s, the master NIS passwd server.\n", master);
140 
141         return(1);
142 }
143 
144 static char *
145 pwskip(register char *p)
146 {
147 	while (*p && *p != ':' && *p != '\n')
148 		++p;
149 	if (*p)
150 		*p++ = 0;
151 	return (p);
152 }
153 
154 static struct passwd *
155 interpret(struct passwd *pwent, char *line)
156 {
157 	register char	*p = line;
158 	register int	c;
159 
160         pwent->pw_passwd = "*";
161         pwent->pw_uid = 0;
162         pwent->pw_gid = 0;
163         pwent->pw_gecos = "";
164         pwent->pw_dir = "";
165         pwent->pw_shell = "";
166 	pwent->pw_change = 0;
167 	pwent->pw_expire = 0;
168 	pwent->pw_class = "";
169 
170         /* line without colon separators is no good, so ignore it */
171         if(!strchr(p,':'))
172                 return(NULL);
173 
174 	pwent->pw_name = p;
175 	p = pwskip(p);
176 	pwent->pw_passwd = p;
177 	p = pwskip(p);
178 	pwent->pw_uid = (uid_t)strtoul(p, NULL, 10);
179 	p = pwskip(p);
180 	pwent->pw_gid = (gid_t)strtoul(p, NULL, 10);
181 	p = pwskip(p);
182 	pwent->pw_gecos = p;
183 	p = pwskip(p);
184 	pwent->pw_dir = p;
185 	p = pwskip(p);
186 	pwent->pw_shell = p;
187 	while (*p && *p != '\n')
188 		p++;
189 	*p = '\0';
190 	return (pwent);
191 }
192 
193 struct passwd *
194 ypgetpwnam(nam)
195         char *nam;
196 {
197         static struct passwd pwent;
198         static char line[1024];
199         char *val;
200         int reason, vallen;
201 
202         /*
203          * Get local domain
204          */
205         if (!domain && (reason = yp_get_default_domain(&domain))) {
206                 (void)fprintf(stderr, "%s: can't get local NIS domain. Reason: %s\n", progname, yperr_string(reason));
207                 exit(1);
208         }
209 
210         reason = yp_match(domain, "passwd.byname", nam, strlen(nam),
211                           &val, &vallen);
212         switch(reason) {
213         case 0:
214                 break;
215         default:
216                 return (NULL);
217                 break;
218         }
219         val[vallen] = '\0';
220         strcpy(line, val);
221         free(val);
222 
223         return(interpret(&pwent, line));
224 }
225 
226 struct passwd *
227 ypgetpwuid(uid)
228         uid_t uid;
229 {
230         static struct passwd pwent;
231         static char line[1024];
232         char *val;
233         int reason, vallen;
234         char namebuf[16];
235 
236         if (!domain && (reason = yp_get_default_domain(&domain))) {
237                 (void)fprintf(stderr, "%s: can't get local NIS domain. Reason: %s\n", progname, yperr_string(reason));
238                 exit(1);
239         }
240 
241         sprintf(namebuf, "%d", uid);
242         reason = yp_match(domain, "passwd.byuid", namebuf, strlen(namebuf),
243                           &val, &vallen);
244         switch(reason) {
245         case 0:
246                 break;
247         default:
248                 return (NULL);
249                 break;
250         }
251         val[vallen] = '\0';
252         strcpy(line, val);
253         free(val);
254 
255         return(interpret(&pwent, line));
256 }
257 
258 #endif	/* YP */
259