]> git.saurik.com Git - apple/system_cmds.git/blob - chkpasswd.tproj/netinfo_passwd.c
system_cmds-279.1.tar.gz
[apple/system_cmds.git] / chkpasswd.tproj / netinfo_passwd.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <sys/param.h>
28 #include <sys/socket.h>
29 #include <net/if.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <sys/ioctl.h>
33 #include <errno.h>
34 #include <pwd.h>
35 #include <netdb.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <netinfo/ni.h>
39
40 extern void checkpasswd(char *, char *);
41
42 static int
43 sys_ismyaddress(unsigned long addr)
44 {
45 struct ifconf ifc;
46 struct ifreq *ifr;
47 char buf[1024]; /* XXX */
48 int offset;
49 int sock;
50 struct sockaddr_in *sin;
51 int i, len;
52
53 if (addr == htonl(INADDR_LOOPBACK)) return 1;
54
55 sock = socket(AF_INET, SOCK_DGRAM, 0);
56
57 if (sock < 0) return 0;
58
59 ifc.ifc_len = sizeof(buf);
60 ifc.ifc_buf = buf;
61
62 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0)
63 {
64 close(sock);
65 return 0;
66 }
67
68 offset = 0;
69
70 while (offset <= ifc.ifc_len)
71 {
72 ifr = (struct ifreq *)(ifc.ifc_buf + offset);
73 offset += IFNAMSIZ + ifr->ifr_addr.sa_len;
74
75 if (ifr->ifr_addr.sa_family != AF_INET) continue;
76 if (ioctl(sock, SIOCGIFFLAGS, ifr) < 0) continue;
77
78 sin = (struct sockaddr_in *)&ifr->ifr_addr;
79 if ((ifr->ifr_flags & IFF_UP) &&
80 (!(ifr->ifr_flags & IFF_LOOPBACK)) &&
81 (sin->sin_addr.s_addr == addr))
82 {
83 close(sock);
84 return 1;
85 }
86 }
87
88 close(sock);
89 return 0;
90 }
91
92 static int
93 is_root_on_master(void *d)
94 {
95 int uid;
96 char myhostname[MAXHOSTNAMELEN + 1];
97 char *p;
98 ni_index where;
99 ni_proplist pl;
100 int status;
101 ni_id dir;
102 struct sockaddr_in addr;
103 char *tag;
104
105 uid = getuid();
106 if (uid != 0) return 0;
107
108 gethostname(myhostname, MAXHOSTNAMELEN);
109 p = strchr(myhostname, '.');
110 if (p != NULL) *p = '\0';
111
112 status = ni_root(d, &dir);
113 if (status != NI_OK) return 0;
114
115 status = ni_read(d, &dir, &pl);
116 if (status != NI_OK) return 0;
117
118 where = ni_proplist_match(pl, "master", NULL);
119 if (where == NI_INDEX_NULL)
120 {
121 ni_proplist_free(&pl);
122 return 0;
123 }
124
125 if (pl.ni_proplist_val[where].nip_val.ni_namelist_len == 0)
126 {
127 ni_proplist_free(&pl);
128 fprintf(stderr, "No value for NetInfo master property\n");
129 return 0;
130 }
131
132 p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '/');
133 if (p != NULL) *p = '\0';
134
135 p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '.');
136 if (p != NULL) *p = '\0';
137
138 if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], myhostname))
139 {
140 ni_proplist_free(&pl);
141 return 1;
142 }
143
144 if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], "localhost"))
145 {
146 ni_proplist_free(&pl);
147 ni_addrtag(d, &addr, &tag);
148 if (sys_ismyaddress(addr.sin_addr.s_addr)) return 1;
149 }
150
151 ni_proplist_free(&pl);
152 return 0;
153 }
154
155 static int
156 secure_passwords()
157 {
158 void *d, *d1;
159 int status;
160 ni_index where;
161 ni_id dir;
162 ni_namelist nl;
163
164 status = ni_open(NULL, ".", &d);
165 while (status == NI_OK)
166 {
167 dir.nii_object = 0;
168 status = ni_lookupprop(d, &dir, "security_options", &nl);
169 if (status == NI_OK)
170 {
171 where = ni_namelist_match(nl, "secure_passwords");
172 if (where != NI_INDEX_NULL)
173 {
174 ni_free(d);
175 return 1;
176 }
177 }
178
179 d1 = d;
180 status = ni_open(d1, "..", &d);
181 ni_free(d1);
182 }
183
184 return 0;
185 }
186
187 static void
188 parse_server_tag(char *str, struct sockaddr_in *server, char **t)
189 {
190 /* utility to parse a server/tag string */
191
192 int len, i;
193 char *host, *tag, *slash;
194 struct hostent *hent;
195
196 len = strlen(str);
197
198 /* find the "/" character */
199 slash = index(str, '/');
200
201 /* check to see if the "/" is missing */
202 if (slash == NULL)
203 {
204 fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
205 exit(1);
206 }
207
208 /* find the location of the '/' */
209 i = slash - str;
210
211 /* check if host string is empty */
212 if (i == 0)
213 {
214 fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
215 fprintf(stderr, "no server name specified\n");
216 exit(1);
217 }
218
219 /* check if tag string is empty */
220 if (i == (len - 1))
221 {
222 fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
223 fprintf(stderr, "no tag specified\n");
224 exit(1);
225 }
226
227 /* allocate some space for the host and tag */
228 host = (char *)malloc(i + 1);
229 *t = (char *)malloc(len - i);
230 tag = *t;
231
232 /* copy out the host */
233 strncpy(host, str, i);
234 host[i] = '\0';
235
236 /* copy out the tag */
237 strcpy(tag, slash + 1);
238
239 /* try interpreting the host portion as an address */
240 server->sin_addr.s_addr = inet_addr(host);
241
242 if (server->sin_addr.s_addr == -1)
243 {
244 /* This isn't a valid address. Is it a known hostname? */
245 hent = gethostbyname(host);
246 if (hent != NULL)
247 {
248 /* found a host with that name */
249 bcopy(hent->h_addr, &server->sin_addr, hent->h_length);
250 }
251 else
252 {
253 fprintf(stderr, "Can't find address for %s\n", host);
254 free(host);
255 free(tag);
256 exit(1);
257 }
258 }
259
260 free(host);
261 }
262
263 static void *
264 domain_for_user(char *uname, char *locn, ni_id *dir)
265 {
266 char *upath;
267 int status;
268 void *d, *d1;
269 struct sockaddr_in server;
270 char *tag;
271 int bytag;
272
273 /*
274 * Find the user in NetInfo.
275 */
276 upath = malloc(8 + strlen(uname));
277 sprintf(upath, "/users/%s", uname);
278
279 if (locn != NULL)
280 {
281 bytag = 1;
282
283 if (locn[0] == '/') bytag = 0;
284 else if (!strncmp(locn, "./", 2)) bytag = 0;
285 else if (!strncmp(locn, "../", 3)) bytag = 0;
286
287 if (bytag == 1)
288 {
289 parse_server_tag(locn, &server, &tag);
290 d = ni_connect(&server, tag);
291 if (d == (void *)NULL) return (void *)NULL;
292 }
293 else status = ni_open(NULL, locn, &d);
294 status = ni_pathsearch(d, dir, upath);
295 free(upath);
296
297 if (status == NI_OK) return d;
298
299 ni_free(d);
300 return (void *)NULL;
301 }
302
303 status = ni_open(NULL, ".", &d);
304 while (status == NI_OK)
305 {
306 status = ni_pathsearch(d, dir, upath);
307 if (status == NI_OK) break;
308 d1 = d;
309 status = ni_open(d1, "..", &d);
310 ni_free(d1);
311 }
312
313 free(upath);
314
315 if (status == NI_OK) return d;
316 return (void *)NULL;
317 }
318
319 int
320 netinfo_check_passwd(char *uname, char *locn)
321 {
322 char *oldpw;
323 void *d;
324 int status;
325 ni_id dir;
326 ni_namelist nl;
327
328 d = domain_for_user(uname, locn, &dir);
329 if (d == (void *)NULL)
330 {
331 fprintf(stderr, "user %s not found in NetInfo\n", uname);
332 exit(1);
333 }
334
335 /*
336 * Read the passwd and uid from NetInfo.
337 */
338 status = ni_lookupprop(d, &dir, "passwd", &nl);
339 if (status == NI_NOPROP) nl.ni_namelist_len = 0;
340 else if (status != NI_OK)
341 {
342 ni_free(d);
343 fprintf(stderr, "NetInfo read failed: %s\n", ni_error(status));
344 exit(1);
345 }
346
347 oldpw = NULL;
348 if (nl.ni_namelist_len > 0) oldpw = nl.ni_namelist_val[0];
349
350 checkpasswd(uname, oldpw);
351 ni_free(d);
352 return (0);
353 }