]> git.saurik.com Git - apple/system_cmds.git/blob - chkpasswd.tproj/netinfo_passwd.c
system_cmds-433.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 #if 0
43 static int
44 sys_ismyaddress(unsigned long addr)
45 {
46 struct ifconf ifc;
47 struct ifreq *ifr;
48 char buf[1024]; /* XXX */
49 int offset;
50 int sock;
51 struct sockaddr_in *sin;
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 #endif /* 0 */
187
188 static void
189 parse_server_tag(char *str, struct sockaddr_in *server, char **t)
190 {
191 /* utility to parse a server/tag string */
192
193 int len, i;
194 char *host, *tag, *slash;
195 struct hostent *hent;
196
197 len = strlen(str);
198
199 /* find the "/" character */
200 slash = index(str, '/');
201
202 /* check to see if the "/" is missing */
203 if (slash == NULL)
204 {
205 fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
206 exit(1);
207 }
208
209 /* find the location of the '/' */
210 i = slash - str;
211
212 /* check if host string is empty */
213 if (i == 0)
214 {
215 fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
216 fprintf(stderr, "no server name specified\n");
217 exit(1);
218 }
219
220 /* check if tag string is empty */
221 if (i == (len - 1))
222 {
223 fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
224 fprintf(stderr, "no tag specified\n");
225 exit(1);
226 }
227
228 /* allocate some space for the host and tag */
229 host = (char *)malloc(i + 1);
230 *t = (char *)malloc(len - i);
231 tag = *t;
232
233 /* copy out the host */
234 strncpy(host, str, i);
235 host[i] = '\0';
236
237 /* copy out the tag */
238 strcpy(tag, slash + 1);
239
240 /* try interpreting the host portion as an address */
241 server->sin_addr.s_addr = inet_addr(host);
242
243 if (server->sin_addr.s_addr == -1)
244 {
245 /* This isn't a valid address. Is it a known hostname? */
246 hent = gethostbyname(host);
247 if (hent != NULL)
248 {
249 /* found a host with that name */
250 bcopy(hent->h_addr, &server->sin_addr, hent->h_length);
251 }
252 else
253 {
254 fprintf(stderr, "Can't find address for %s\n", host);
255 free(host);
256 free(tag);
257 exit(1);
258 }
259 }
260
261 free(host);
262 }
263
264 static void *
265 domain_for_user(char *uname, char *locn, ni_id *dir)
266 {
267 char *upath;
268 int status;
269 void *d, *d1;
270 struct sockaddr_in server;
271 char *tag;
272 int bytag;
273
274 /*
275 * Find the user in NetInfo.
276 */
277 upath = malloc(8 + strlen(uname));
278 sprintf(upath, "/users/%s", uname);
279
280 if (locn != NULL)
281 {
282 bytag = 1;
283
284 if (locn[0] == '/') bytag = 0;
285 else if (!strncmp(locn, "./", 2)) bytag = 0;
286 else if (!strncmp(locn, "../", 3)) bytag = 0;
287
288 if (bytag == 1)
289 {
290 parse_server_tag(locn, &server, &tag);
291 d = ni_connect(&server, tag);
292 if (d == (void *)NULL) return (void *)NULL;
293 }
294 else status = ni_open(NULL, locn, &d);
295 status = ni_pathsearch(d, dir, upath);
296 free(upath);
297
298 if (status == NI_OK) return d;
299
300 ni_free(d);
301 return (void *)NULL;
302 }
303
304 status = ni_open(NULL, ".", &d);
305 while (status == NI_OK)
306 {
307 status = ni_pathsearch(d, dir, upath);
308 if (status == NI_OK) break;
309 d1 = d;
310 status = ni_open(d1, "..", &d);
311 ni_free(d1);
312 }
313
314 free(upath);
315
316 if (status == NI_OK) return d;
317 return (void *)NULL;
318 }
319
320 int
321 netinfo_check_passwd(char *uname, char *locn)
322 {
323 char *oldpw;
324 void *d;
325 int status;
326 ni_id dir;
327 ni_namelist nl;
328
329 d = domain_for_user(uname, locn, &dir);
330 if (d == (void *)NULL)
331 {
332 fprintf(stderr, "user %s not found in NetInfo\n", uname);
333 exit(1);
334 }
335
336 /*
337 * Read the passwd and uid from NetInfo.
338 */
339 status = ni_lookupprop(d, &dir, "passwd", &nl);
340 if (status == NI_NOPROP) nl.ni_namelist_len = 0;
341 else if (status != NI_OK)
342 {
343 ni_free(d);
344 fprintf(stderr, "NetInfo read failed: %s\n", ni_error(status));
345 exit(1);
346 }
347
348 oldpw = NULL;
349 if (nl.ni_namelist_len > 0) oldpw = nl.ni_namelist_val[0];
350
351 checkpasswd(uname, oldpw);
352 ni_free(d);
353 return (0);
354 }