Annotation of src/usr.bin/chpass/pw_yp.c, Revision 1.23
1.23 ! deraadt 1: /* $OpenBSD: pw_yp.c,v 1.22 2009/02/15 21:43:40 deraadt Exp $ */
1.1 deraadt 2: /* $NetBSD: pw_yp.c,v 1.5 1995/03/26 04:55:33 glass Exp $ */
3:
4: /*
5: * Copyright (c) 1988 The Regents of the University of California.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.18 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifdef YP
34:
35: #include <stdio.h>
36: #include <string.h>
37: #include <netdb.h>
38: #include <time.h>
39: #include <pwd.h>
1.8 deraadt 40: #include <err.h>
1.1 deraadt 41: #include <errno.h>
1.16 deraadt 42: #include <unistd.h>
1.7 niklas 43: #include <stdlib.h>
1.1 deraadt 44: #include <rpc/rpc.h>
45: #include <rpcsvc/yp_prot.h>
46: #include <rpcsvc/ypclnt.h>
47: #define passwd yp_passwd_rec
48: #include <rpcsvc/yppasswd.h>
49: #undef passwd
1.19 deraadt 50: #include "chpass.h"
1.1 deraadt 51:
1.9 millert 52: extern char *__progname;
1.1 deraadt 53:
54: static char *domain;
55:
1.8 deraadt 56: int
1.16 deraadt 57: pw_yp(struct passwd *pw, uid_t uid)
1.1 deraadt 58: {
1.20 deraadt 59: char uidbuf[20], gidbuf[20], *master, *p;
1.5 deraadt 60: int r, rpcport, status, alen;
1.1 deraadt 61: struct yppasswd yppasswd;
62: struct timeval tv;
63: CLIENT *client;
1.16 deraadt 64:
1.1 deraadt 65: /*
66: * Get local domain
67: */
68: if (!domain && (r = yp_get_default_domain(&domain))) {
69: fprintf(stderr, "%s: can't get local YP domain. Reason: %s\n",
1.9 millert 70: __progname, yperr_string(r));
1.1 deraadt 71: return(0);
72: }
73:
74: /*
75: * Find the host for the passwd map; it should be running
76: * the daemon.
77: */
78: if ((r = yp_master(domain, "passwd.byname", &master)) != 0) {
79: fprintf(stderr,
80: "%s: can't find the master YP server. Reason: %s\n",
1.9 millert 81: __progname, yperr_string(r));
1.1 deraadt 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,
89: IPPROTO_UDP)) == 0) {
90: fprintf(stderr,
91: "%s: master YP server not running yppasswd daemon.\n",
1.9 millert 92: __progname);
1.1 deraadt 93: fprintf(stderr, "\tCan't change password.\n");
94: return(0);
95: }
96:
97: /*
1.15 deraadt 98: * Be sure the port is privileged
1.1 deraadt 99: */
100: if (rpcport >= IPPORT_RESERVED) {
101: (void)fprintf(stderr,
102: "%s: yppasswd daemon running on an invalid port.\n",
1.9 millert 103: __progname);
1.1 deraadt 104: return(0);
105: }
106:
107: /* prompt for old password */
108: bzero(&yppasswd, sizeof yppasswd);
109: yppasswd.oldpass = "none";
110: yppasswd.oldpass = getpass("Old password:");
111: if (!yppasswd.oldpass) {
112: (void)fprintf(stderr, "Cancelled.\n");
113: return(0);
114: }
1.16 deraadt 115:
1.5 deraadt 116: for (alen = 0, p = pw->pw_gecos; *p; p++)
117: if (*p == '&')
118: alen = alen + strlen(pw->pw_name) - 1;
1.20 deraadt 119: (void)snprintf(uidbuf, sizeof uidbuf, "%u", pw->pw_uid);
120: (void)snprintf(gidbuf, sizeof gidbuf, "%u", pw->pw_gid);
121:
1.5 deraadt 122: if (strlen(pw->pw_name) + 1 + strlen(pw->pw_passwd) + 1 +
1.20 deraadt 123: strlen(uidbuf) + 1 + strlen(gidbuf) + 1 +
1.5 deraadt 124: strlen(pw->pw_gecos) + alen + 1 + strlen(pw->pw_dir) + 1 +
125: strlen(pw->pw_shell) >= 1023) {
126: warnx("entries too long");
127: return (0);
128: }
129:
1.1 deraadt 130: /* tell rpc.yppasswdd */
131: yppasswd.newpw.pw_name = pw->pw_name;
132: yppasswd.newpw.pw_passwd= pw->pw_passwd;
1.16 deraadt 133: yppasswd.newpw.pw_uid = pw->pw_uid;
1.1 deraadt 134: yppasswd.newpw.pw_gid = pw->pw_gid;
135: yppasswd.newpw.pw_gecos = pw->pw_gecos;
136: yppasswd.newpw.pw_dir = pw->pw_dir;
137: yppasswd.newpw.pw_shell = pw->pw_shell;
1.5 deraadt 138:
1.1 deraadt 139: client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
140: if (client==NULL) {
141: fprintf(stderr, "can't contact yppasswdd on %s: Reason: %s\n",
142: master, yperr_string(YPERR_YPBIND));
1.6 deraadt 143: return(1);
1.1 deraadt 144: }
145: client->cl_auth = authunix_create_default();
146: tv.tv_sec = 5;
147: tv.tv_usec = 0;
148: r = clnt_call(client, YPPASSWDPROC_UPDATE,
149: xdr_yppasswd, &yppasswd, xdr_int, &status, tv);
150: if (r) {
1.9 millert 151: fprintf(stderr, "%s: rpc to yppasswdd failed. %d\n",
152: __progname, r);
1.4 deraadt 153: clnt_destroy(client);
1.6 deraadt 154: return(1);
1.1 deraadt 155: } else if (status) {
156: printf("Couldn't change YP password information.\n");
1.4 deraadt 157: clnt_destroy(client);
1.6 deraadt 158: return(1);
1.1 deraadt 159: }
160: printf("The YP password information has been changed on %s, the master YP passwd server.\n", master);
161:
1.4 deraadt 162: clnt_destroy(client);
1.6 deraadt 163: return(0);
1.1 deraadt 164: }
165:
166: static char *
1.16 deraadt 167: pwskip(char *p)
1.1 deraadt 168: {
169: while (*p && *p != ':' && *p != '\n')
170: ++p;
171: if (*p)
172: *p++ = 0;
173: return (p);
174: }
175:
176: static struct passwd *
1.22 deraadt 177: interpret(struct passwd *pwent, char *line, const int secure)
1.1 deraadt 178: {
1.13 mpech 179: char *p = line;
1.1 deraadt 180:
181: pwent->pw_passwd = "*";
182: pwent->pw_uid = 0;
183: pwent->pw_gid = 0;
184: pwent->pw_gecos = "";
185: pwent->pw_dir = "";
186: pwent->pw_shell = "";
187: pwent->pw_change = 0;
188: pwent->pw_expire = 0;
189: pwent->pw_class = "";
1.16 deraadt 190:
1.1 deraadt 191: /* line without colon separators is no good, so ignore it */
1.22 deraadt 192: if (!strchr(p,':'))
1.1 deraadt 193: return(NULL);
194:
195: pwent->pw_name = p;
196: p = pwskip(p);
197: pwent->pw_passwd = p;
198: p = pwskip(p);
199: pwent->pw_uid = (uid_t)strtoul(p, NULL, 10);
200: p = pwskip(p);
201: pwent->pw_gid = (gid_t)strtoul(p, NULL, 10);
202: p = pwskip(p);
1.22 deraadt 203: if (secure == 1) {
204: pwent->pw_class = p;
205: p = pwskip(p);
206: pwent->pw_change = (time_t)strtoul(p, NULL, 10);
207: p = pwskip(p);
208: pwent->pw_expire = (time_t)strtoul(p, NULL, 10);
209: p = pwskip(p);
210: }
1.1 deraadt 211: pwent->pw_gecos = p;
212: p = pwskip(p);
213: pwent->pw_dir = p;
214: p = pwskip(p);
215: pwent->pw_shell = p;
216: while (*p && *p != '\n')
217: p++;
218: *p = '\0';
219: return (pwent);
220: }
221:
1.3 deraadt 222: static char *__yplin;
223:
1.1 deraadt 224: struct passwd *
1.16 deraadt 225: ypgetpwnam(char *nam)
1.1 deraadt 226: {
227: static struct passwd pwent;
1.22 deraadt 228: int reason, vallen, secure = 0;
1.1 deraadt 229: char *val;
1.16 deraadt 230:
1.1 deraadt 231: /*
232: * Get local domain
233: */
234: if (!domain && (reason = yp_get_default_domain(&domain))) {
235: fprintf(stderr, "%s: can't get local YP domain. Reason: %s\n",
1.9 millert 236: __progname, yperr_string(reason));
1.1 deraadt 237: exit(1);
238: }
239:
1.22 deraadt 240: if (!yp_match(domain, "master.passwd.byname", nam, strlen(nam),
241: &val, &vallen))
242: secure = 1;
243: else if (yp_match(domain, "passwd.byname", nam, strlen(nam),
244: &val, &vallen))
1.1 deraadt 245: return (NULL);
1.22 deraadt 246:
1.1 deraadt 247: val[vallen] = '\0';
1.3 deraadt 248: if (__yplin)
249: free(__yplin);
1.21 deraadt 250: if (!(__yplin = malloc(vallen + 1)))
1.11 alex 251: err(1, NULL);
1.16 deraadt 252: strlcpy(__yplin, val, vallen + 1);
1.1 deraadt 253: free(val);
254:
1.22 deraadt 255: return(interpret(&pwent, __yplin, secure));
1.1 deraadt 256: }
257:
258: struct passwd *
1.16 deraadt 259: ypgetpwuid(uid_t uid)
1.1 deraadt 260: {
261: static struct passwd pwent;
1.22 deraadt 262: int reason, vallen, secure = 0;
1.16 deraadt 263: char namebuf[16], *val;
264:
1.1 deraadt 265: if (!domain && (reason = yp_get_default_domain(&domain))) {
266: fprintf(stderr, "%s: can't get local YP domain. Reason: %s\n",
1.9 millert 267: __progname, yperr_string(reason));
1.1 deraadt 268: exit(1);
269: }
270:
1.16 deraadt 271: snprintf(namebuf, sizeof namebuf, "%u", (u_int)uid);
1.22 deraadt 272: if (!yp_match(domain, "master.passwd.byuid", namebuf, strlen(namebuf),
273: &val, &vallen))
274: secure = 1;
275: else if (yp_match(domain, "passwd.byuid", namebuf, strlen(namebuf),
276: &val, &vallen))
1.1 deraadt 277: return (NULL);
1.22 deraadt 278:
1.1 deraadt 279: val[vallen] = '\0';
1.3 deraadt 280: if (__yplin)
281: free(__yplin);
1.21 deraadt 282: if (!(__yplin = malloc(vallen + 1)))
1.11 alex 283: err(1, NULL);
1.16 deraadt 284: strlcpy(__yplin, val, vallen + 1);
1.1 deraadt 285: free(val);
286:
1.22 deraadt 287: return(interpret(&pwent, __yplin, secure));
1.1 deraadt 288: }
289:
290: #endif /* YP */