]> git.saurik.com Git - apple/system_cmds.git/blame - chkpasswd.tproj/netinfo_passwd.c
system_cmds-279.tar.gz
[apple/system_cmds.git] / chkpasswd.tproj / netinfo_passwd.c
CommitLineData
1815bff5
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
c3a08f59
A
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
1815bff5
A
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
c3a08f59
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1815bff5
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25#include <stdio.h>
26#include <unistd.h>
27#include <stdlib.h>
28#include <sys/param.h>
29#include <sys/socket.h>
30#include <net/if.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
33#include <sys/ioctl.h>
34#include <errno.h>
35#include <pwd.h>
36#include <netdb.h>
37#include <ctype.h>
38#include <string.h>
39#include <netinfo/ni.h>
40
41extern void checkpasswd(char *, char *);
42
43static int
44sys_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 int i, len;
53
54 if (addr == htonl(INADDR_LOOPBACK)) return 1;
55
56 sock = socket(AF_INET, SOCK_DGRAM, 0);
57
58 if (sock < 0) return 0;
59
60 ifc.ifc_len = sizeof(buf);
61 ifc.ifc_buf = buf;
62
63 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0)
64 {
65 close(sock);
66 return 0;
67 }
68
69 offset = 0;
70
71 while (offset <= ifc.ifc_len)
72 {
73 ifr = (struct ifreq *)(ifc.ifc_buf + offset);
74 offset += IFNAMSIZ + ifr->ifr_addr.sa_len;
75
76 if (ifr->ifr_addr.sa_family != AF_INET) continue;
77 if (ioctl(sock, SIOCGIFFLAGS, ifr) < 0) continue;
78
79 sin = (struct sockaddr_in *)&ifr->ifr_addr;
80 if ((ifr->ifr_flags & IFF_UP) &&
81 (!(ifr->ifr_flags & IFF_LOOPBACK)) &&
82 (sin->sin_addr.s_addr == addr))
83 {
84 close(sock);
85 return 1;
86 }
87 }
88
89 close(sock);
90 return 0;
91}
92
93static int
94is_root_on_master(void *d)
95{
96 int uid;
97 char myhostname[MAXHOSTNAMELEN + 1];
98 char *p;
99 ni_index where;
100 ni_proplist pl;
101 int status;
102 ni_id dir;
103 struct sockaddr_in addr;
104 char *tag;
105
106 uid = getuid();
107 if (uid != 0) return 0;
108
109 gethostname(myhostname, MAXHOSTNAMELEN);
110 p = strchr(myhostname, '.');
111 if (p != NULL) *p = '\0';
112
113 status = ni_root(d, &dir);
114 if (status != NI_OK) return 0;
115
116 status = ni_read(d, &dir, &pl);
117 if (status != NI_OK) return 0;
118
119 where = ni_proplist_match(pl, "master", NULL);
120 if (where == NI_INDEX_NULL)
121 {
122 ni_proplist_free(&pl);
123 return 0;
124 }
125
126 if (pl.ni_proplist_val[where].nip_val.ni_namelist_len == 0)
127 {
128 ni_proplist_free(&pl);
129 fprintf(stderr, "No value for NetInfo master property\n");
130 return 0;
131 }
132
133 p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '/');
134 if (p != NULL) *p = '\0';
135
136 p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '.');
137 if (p != NULL) *p = '\0';
138
139 if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], myhostname))
140 {
141 ni_proplist_free(&pl);
142 return 1;
143 }
144
145 if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], "localhost"))
146 {
147 ni_proplist_free(&pl);
148 ni_addrtag(d, &addr, &tag);
149 if (sys_ismyaddress(addr.sin_addr.s_addr)) return 1;
150 }
151
152 ni_proplist_free(&pl);
153 return 0;
154}
155
156static int
157secure_passwords()
158{
159 void *d, *d1;
160 int status;
161 ni_index where;
162 ni_id dir;
163 ni_namelist nl;
164
165 status = ni_open(NULL, ".", &d);
166 while (status == NI_OK)
167 {
168 dir.nii_object = 0;
169 status = ni_lookupprop(d, &dir, "security_options", &nl);
170 if (status == NI_OK)
171 {
172 where = ni_namelist_match(nl, "secure_passwords");
173 if (where != NI_INDEX_NULL)
174 {
175 ni_free(d);
176 return 1;
177 }
178 }
179
180 d1 = d;
181 status = ni_open(d1, "..", &d);
182 ni_free(d1);
183 }
184
185 return 0;
186}
187
188static void
189parse_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
264static void *
265domain_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
320int
321netinfo_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}