]>
Commit | Line | Data |
---|---|---|
c3a08f59 A |
1 | #ifdef DIRECTORY_SERVICE |
2 | ||
3 | #include "directory_service.h" | |
4 | #include "chpass.h" | |
5 | #include <err.h> | |
2fc1e207 A |
6 | #include <sys/time.h> |
7 | ||
8 | #include <sys/errno.h> | |
9 | extern int errno; | |
c3a08f59 A |
10 | |
11 | #define CONFIGNAMELEN 14 | |
12 | #define GLOBALCONFIGLEN 20 | |
13 | #define LOOKUPORDERLEN 13 | |
14 | #define LINESIZE 128 | |
15 | #define NETINFOROOTLEN 13 | |
16 | #define NLIST 13 | |
17 | #define REMOTEINFOLEN 9 | |
18 | #define USERCONFIGLEN 18 | |
19 | ||
20 | /*--------------------------------------------------------------------------- | |
21 | * Global variables | |
22 | *---------------------------------------------------------------------------*/ | |
2fc1e207 | 23 | char *DSPath = NULL; |
c3a08f59 A |
24 | const char MasterPasswd[] = "/etc/master.passwd"; |
25 | ||
26 | /*--------------------------------------------------------------------------- | |
27 | * Local variables | |
28 | *---------------------------------------------------------------------------*/ | |
29 | static char Agent[] = "Agent"; | |
30 | static char ConfigName[] = "_config_name: "; | |
31 | static char DSFiles[] = "/BSD/local"; | |
32 | static char FFPatFmt[] = "^%s:"; | |
33 | static char GlobalConfig[] = "Global Configuration"; | |
34 | static char LocalNI[] = "/NetInfo/DefaultLocalNode"; | |
35 | static char LookupOrder[] = "LookupOrder: "; | |
36 | static char LookupOrderSep[] = " "; | |
37 | static char NetinfoRoot[] = "/NetInfo/root"; | |
38 | static char NiclPathFmt[] = "/users/%s"; | |
39 | static char NISPatFmt[] = "/usr/bin/ypcat passwd.byname | /usr/bin/grep -q '^%s:'"; | |
40 | static char RemoteNI[] = "/NetInfo/"; | |
c3a08f59 A |
41 | static char UserConfig[] = "User Configuration"; |
42 | static unsigned char RestrictedFFRoot[] = { | |
43 | 0, /*E_LOGIN */ | |
44 | 0, /*E_PASSWD */ | |
45 | 0, /*E_UID */ | |
46 | 0, /*E_GID */ | |
47 | 0, /*E_CHANGE */ | |
48 | 0, /*E_EXPIRE */ | |
49 | 0, /*E_CLASS */ | |
50 | 0, /*E_HOME */ | |
51 | 0, /*E_SHELL */ | |
52 | 0, /*E_NAME */ | |
53 | 1, /*E_LOCATE */ | |
54 | 1, /*E_BPHONE */ | |
55 | 1, /*E_HPHONE */ | |
56 | }; | |
57 | static unsigned char RestrictedFFUser[] = { | |
58 | 1, /*E_LOGIN */ | |
59 | 1, /*E_PASSWD */ | |
60 | 1, /*E_UID */ | |
61 | 1, /*E_GID */ | |
62 | 1, /*E_CHANGE */ | |
63 | 1, /*E_EXPIRE */ | |
64 | 1, /*E_CLASS */ | |
65 | 1, /*E_HOME */ | |
66 | 0, /*E_SHELL */ | |
67 | 0, /*E_NAME */ | |
68 | 1, /*E_LOCATE */ | |
69 | 1, /*E_BPHONE */ | |
70 | 1, /*E_HPHONE */ | |
71 | }; | |
72 | static unsigned char RestrictedLocalNIRoot[] = { | |
73 | 0, /*E_LOGIN */ | |
74 | 1, /*E_PASSWD */ | |
75 | 0, /*E_UID */ | |
76 | 0, /*E_GID */ | |
77 | 0, /*E_CHANGE */ | |
78 | 0, /*E_EXPIRE */ | |
79 | 0, /*E_CLASS */ | |
80 | 0, /*E_HOME */ | |
81 | 0, /*E_SHELL */ | |
82 | 0, /*E_NAME */ | |
83 | 1, /*E_LOCATE */ | |
84 | 1, /*E_BPHONE */ | |
85 | 1, /*E_HPHONE */ | |
86 | }; | |
87 | static unsigned char RestrictedLocalNIUser[] = { | |
88 | 1, /*E_LOGIN */ | |
89 | 1, /*E_PASSWD */ | |
90 | 1, /*E_UID */ | |
91 | 1, /*E_GID */ | |
92 | 1, /*E_CHANGE */ | |
93 | 1, /*E_EXPIRE */ | |
94 | 1, /*E_CLASS */ | |
95 | 1, /*E_HOME */ | |
96 | 0, /*E_SHELL */ | |
97 | 0, /*E_NAME */ | |
98 | 1, /*E_LOCATE */ | |
99 | 1, /*E_BPHONE */ | |
100 | 1, /*E_HPHONE */ | |
101 | }; | |
102 | ||
103 | #define NWHERE 4 | |
104 | ||
105 | typedef int (*wherefunc)(const char *); | |
106 | ||
107 | static int compar(const void *, const void *); | |
108 | static int runnicl(char *name, char *key, char *val); | |
109 | static int whereCache(const char *); | |
110 | static int whereDS(const char *); | |
111 | static int whereFF(const char *); | |
112 | static int whereNI(const char *); | |
113 | static int whereNIL(const char *); | |
114 | static int whereNIS(const char *); | |
115 | ||
116 | /*--------------------------------------------------------------------------- | |
117 | * WhereList determines what functions to call when the LookupOrder is followed | |
118 | *---------------------------------------------------------------------------*/ | |
119 | struct where { | |
120 | char *agent; | |
121 | int len; | |
122 | wherefunc func; | |
123 | } WhereList[] = { | |
124 | {"Cache", 5, whereCache}, | |
125 | {"DS", 2, whereDS}, | |
126 | {"FF", 2, whereFF}, | |
127 | {"NI", 2, whereNI}, | |
128 | {"NIL", 3, whereNIL}, | |
129 | {"NIS", 3, whereNIS}, | |
130 | }; | |
131 | ||
132 | #define PATINDEX 2 | |
133 | static char *Grep[] = { | |
134 | "/usr/bin/grep", | |
135 | "-q", | |
136 | NULL, /* pattern goes here */ | |
137 | (char *)MasterPasswd, | |
138 | NULL | |
139 | }; | |
140 | ||
141 | #define NICLPATHINDEX 3 | |
142 | #define NICLKEYINDEX 4 | |
143 | #define NICLVALUEINDEX 5 | |
144 | static char *Nicl[] = { | |
145 | "/usr/bin/nicl", | |
146 | ".", | |
147 | "-create", | |
148 | NULL, /* path goes here */ | |
149 | NULL, /* key goes here */ | |
150 | NULL, /* value goes here */ | |
151 | NULL | |
152 | }; | |
153 | ||
154 | #define YPCATINDEX 2 | |
155 | static char *Ypcat[] = { | |
156 | "/bin/sh", | |
157 | "-c", | |
158 | NULL, /* ypcat cmd goes here */ | |
159 | NULL | |
160 | }; | |
161 | ||
162 | /*--------------------------------------------------------------------------- | |
163 | * compar - called by bsearch() to search WhereList for an agent | |
164 | *---------------------------------------------------------------------------*/ | |
165 | #define A ((const struct where *)a) | |
166 | #define KEY ((const char *)key) | |
167 | static int | |
168 | compar(const void *key, const void *a) | |
169 | { | |
170 | int result = strncmp(KEY, A->agent, A->len); | |
171 | if(result) | |
172 | return result; | |
173 | if(KEY[A->len] == 0) | |
174 | return 0; | |
175 | return strcmp(KEY + A->len, Agent); | |
176 | } | |
177 | #undef KEY | |
178 | #undef A | |
179 | ||
180 | /*--------------------------------------------------------------------------- | |
181 | * runnicl - run the nicl command to update local netinfo fields | |
182 | *---------------------------------------------------------------------------*/ | |
183 | static int | |
184 | runnicl(char *name, char *key, char *val) | |
185 | { | |
186 | char path[128]; | |
187 | pid_t pid; | |
188 | int estat; | |
189 | int status; | |
190 | ||
191 | IF((pid = fork()) >= 0) { | |
192 | if(pid == 0) { | |
193 | sprintf(path, NiclPathFmt, name); | |
194 | Nicl[NICLPATHINDEX] = path; | |
195 | Nicl[NICLKEYINDEX] = key; | |
196 | Nicl[NICLVALUEINDEX] = val; | |
197 | /*--------------------------------------------------------------- | |
198 | * Become fully root to call nicl | |
199 | *---------------------------------------------------------------*/ | |
200 | setuid(geteuid()); | |
201 | execv(Nicl[0], Nicl); | |
202 | _exit(1); | |
203 | } | |
204 | if(waitpid(pid, &estat, 0) < 0) { | |
205 | status = errno; | |
206 | break; | |
207 | } | |
208 | if(!WIFEXITED(estat)) { | |
209 | status = E_NICLFAILED; | |
210 | break; | |
211 | } | |
212 | status = (WEXITSTATUS(estat) == 0 ? 0 : E_NICLFAILED); | |
213 | } CLEANUP { | |
214 | } ELSE { | |
215 | status = errno; | |
216 | } ENDIF | |
217 | return status; | |
218 | } | |
219 | /*--------------------------------------------------------------------------- | |
220 | * PUBLIC setrestricted - sets the restricted flag | |
221 | *---------------------------------------------------------------------------*/ | |
222 | void | |
223 | setrestricted(int where, struct passwd *pw) | |
224 | { | |
225 | unsigned char *restricted; | |
226 | int i; | |
227 | ENTRY *ep; | |
228 | ||
2fc1e207 A |
229 | switch(where) |
230 | { | |
231 | case WHERE_FILES: | |
232 | restricted = uid ? RestrictedFFUser : RestrictedFFRoot; | |
233 | break; | |
234 | case WHERE_LOCALNI: | |
235 | restricted = uid ? RestrictedLocalNIUser : RestrictedLocalNIRoot; | |
236 | break; | |
237 | default: | |
238 | return; | |
c3a08f59 | 239 | } |
2fc1e207 | 240 | |
c3a08f59 | 241 | for (ep = list, i = NLIST; i > 0; i--) |
2fc1e207 A |
242 | (ep++)->restricted = *restricted++; |
243 | ||
c3a08f59 | 244 | if (uid && !ok_shell(pw->pw_shell)) |
2fc1e207 | 245 | list[E_SHELL].restricted = 1; |
c3a08f59 A |
246 | } |
247 | ||
248 | /*--------------------------------------------------------------------------- | |
249 | * PUBLIC update_local_ni - update local netinfo | |
250 | *---------------------------------------------------------------------------*/ | |
251 | void | |
252 | update_local_ni(struct passwd *pworig, struct passwd *pw) | |
253 | { | |
254 | char buf[64]; | |
255 | char *np, *op, *bp; | |
256 | ||
257 | if(pworig->pw_uid != pw->pw_uid) { | |
258 | sprintf(buf, "%d", pw->pw_uid); | |
259 | runnicl(pworig->pw_name, "uid", buf); | |
260 | } | |
261 | if(pworig->pw_gid != pw->pw_gid) { | |
262 | sprintf(buf, "%d", pw->pw_gid); | |
263 | runnicl(pworig->pw_name, "gid", buf); | |
264 | } | |
265 | if(pworig->pw_change != pw->pw_change) { | |
266 | sprintf(buf, "%lu", pw->pw_change); | |
267 | runnicl(pworig->pw_name, "change", buf); | |
268 | } | |
269 | if(pworig->pw_expire != pw->pw_expire) { | |
270 | sprintf(buf, "%lu", pw->pw_expire); | |
271 | runnicl(pworig->pw_name, "expire", buf); | |
272 | } | |
273 | if(strcmp(pworig->pw_dir, pw->pw_dir) != 0) | |
274 | runnicl(pworig->pw_name, "home", pw->pw_dir); | |
275 | if(strcmp(pworig->pw_shell, pw->pw_shell) != 0) | |
276 | runnicl(pworig->pw_name, "shell", pw->pw_shell); | |
277 | if(strcmp(pworig->pw_class, pw->pw_class) != 0) | |
278 | runnicl(pworig->pw_name, "class", pw->pw_class); | |
279 | ||
280 | bp = pworig->pw_gecos; | |
281 | op = strsep(&bp, ","); | |
282 | if(!op) | |
283 | op = ""; | |
284 | bp = pw->pw_gecos; | |
285 | np = strsep(&bp, ","); | |
286 | if(!np) | |
287 | np = ""; | |
288 | if(strcmp(op, np) != 0) | |
289 | runnicl(pworig->pw_name, "realname", np); | |
290 | ||
291 | if(strcmp(pworig->pw_name, pw->pw_name) != 0) | |
292 | runnicl(pworig->pw_name, "name", pw->pw_name); | |
293 | ||
294 | warnx("netinfo domain \"%s\" updated", DSPath); | |
295 | } | |
296 | ||
297 | /*--------------------------------------------------------------------------- | |
298 | * whereCache - we skip the cache | |
299 | *---------------------------------------------------------------------------*/ | |
300 | static int | |
301 | whereCache(const char *name) | |
302 | { | |
303 | return E_NOTFOUND; | |
304 | } | |
305 | ||
306 | /*--------------------------------------------------------------------------- | |
307 | * whereDS - call DirectoryService. This does both netinfo and other directory | |
308 | * services, so we cache the value so we only process once. | |
309 | *---------------------------------------------------------------------------*/ | |
310 | static int | |
311 | whereDS(const char *name) | |
312 | { | |
313 | tDirReference dsRef; | |
314 | static tDirStatus status; | |
315 | static int dsCached = 0; | |
316 | ||
317 | if(dsCached) | |
318 | return status; | |
319 | dsCached = 1; | |
320 | IF((status = dsOpenDirService(&dsRef)) == eDSNoErr) { | |
321 | tDataBuffer *dataBuff; | |
322 | ||
323 | IF((dataBuff = dsDataBufferAllocate(dsRef, 4096)) != NULL) { | |
324 | tContextData context = NULL; | |
325 | unsigned long nodeCount; | |
326 | ||
327 | /*--------------------------------------------------------------- | |
328 | * Find and open the search node. | |
329 | *---------------------------------------------------------------*/ | |
330 | IF((status = dsFindDirNodes(dsRef, dataBuff, NULL, | |
331 | eDSAuthenticationSearchNodeName, &nodeCount, &context)) | |
2fc1e207 A |
332 | == eDSNoErr) |
333 | { | |
334 | tDataListPtr nodeName; | |
335 | if(nodeCount < 1) { | |
336 | status = eDSNodeNotFound; | |
c3a08f59 | 337 | break; |
2fc1e207 A |
338 | } |
339 | nodeName = NULL; | |
340 | IF((status = dsGetDirNodeName(dsRef, dataBuff, 1, &nodeName)) == eDSNoErr) | |
341 | { | |
342 | tDirNodeReference nodeRef; | |
343 | ||
344 | IF((status = dsOpenDirNode(dsRef, nodeName, &nodeRef)) == eDSNoErr) { | |
345 | tDataListPtr pRecType; | |
346 | tDataListPtr pAttrType; | |
347 | tDataListPtr pPattern; | |
348 | unsigned long recCount; | |
349 | tContextData context2 = NULL; | |
350 | ||
351 | /*--------------------------------------------------- | |
352 | * Now search the search node for the given user name. | |
353 | *---------------------------------------------------*/ | |
354 | pRecType = dsBuildListFromStrings(dsRef, | |
355 | kDSStdRecordTypeUsers, NULL); | |
356 | pAttrType = dsBuildListFromStrings(dsRef, | |
357 | kDSNAttrMetaNodeLocation, NULL); | |
358 | pPattern = dsBuildListFromStrings(dsRef, name, NULL); | |
359 | IF((status = dsGetRecordList(nodeRef, dataBuff, | |
360 | pPattern, eDSExact, pRecType, pAttrType, 0, &recCount, | |
361 | &context2)) == eDSNoErr) { | |
362 | tAttributeListRef attrListRef; | |
363 | tRecordEntry *pRecEntry; | |
364 | ||
365 | if(recCount < 1) { | |
366 | status = E_NOTFOUND; | |
c3a08f59 | 367 | break; |
c3a08f59 | 368 | } |
2fc1e207 A |
369 | /*----------------------------------------------- |
370 | * Get the attributes for the first entry we find | |
371 | *-----------------------------------------------*/ | |
372 | IF((status = dsGetRecordEntry(nodeRef, | |
373 | dataBuff, 1, &attrListRef, &pRecEntry)) == | |
374 | eDSNoErr) { | |
375 | tAttributeValueListRef valueRef; | |
376 | tAttributeEntry *pAttrEntry; | |
377 | ||
378 | /*------------------------------------------- | |
379 | * Get the first (only) attribute | |
380 | *-------------------------------------------*/ | |
381 | IF((status = dsGetAttributeEntry( nodeRef, dataBuff, attrListRef, 1, &valueRef, | |
382 | &pAttrEntry)) == eDSNoErr) | |
383 | { | |
384 | tAttributeValueEntry *pValueEntry; | |
385 | ||
386 | /*--------------------------------------- | |
387 | * Put the attribute values into a data | |
388 | * list. | |
389 | *---------------------------------------*/ | |
390 | ||
391 | status = dsGetAttributeValue(nodeRef, dataBuff, 1, valueRef, &pValueEntry); | |
392 | if ( status == eDSNoErr ) | |
393 | { | |
394 | DSPath = (char *) malloc( pValueEntry->fAttributeValueData.fBufferLength + 1 ); | |
395 | if ( DSPath != NULL ) | |
396 | strlcpy( DSPath, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength + 1 ); | |
397 | ||
398 | dsDeallocAttributeValueEntry(dsRef, pValueEntry); | |
399 | } | |
400 | ||
401 | if(status != eDSNoErr) | |
402 | break; | |
403 | ||
404 | if(strcmp(DSPath, LocalNI) == 0) | |
405 | { | |
406 | status = WHERE_LOCALNI; | |
407 | /*--------------------------- | |
408 | * Translate to netinfo path | |
409 | *---------------------------*/ | |
410 | free((void *)DSPath); | |
411 | DSPath = strdup("."); | |
412 | } | |
413 | else if(strcmp(DSPath, DSFiles) == 0) | |
414 | { | |
415 | status = WHERE_FILES; | |
416 | /*--------------------------- | |
417 | * Translate to master.passwd | |
418 | * path | |
419 | *---------------------------*/ | |
420 | free((void *)DSPath); | |
421 | DSPath = strdup(MasterPasswd); | |
422 | } | |
423 | else if(strncmp(DSPath, RemoteNI, REMOTEINFOLEN) == 0) | |
424 | { | |
425 | status = WHERE_REMOTENI; | |
426 | /*--------------------------- | |
427 | * Translate to netinfo path | |
428 | *---------------------------*/ | |
429 | if(strncmp(DSPath, NetinfoRoot, | |
430 | NETINFOROOTLEN) == 0) { | |
431 | if(DSPath[NETINFOROOTLEN] | |
432 | == 0) { | |
433 | free((void *)DSPath); | |
434 | DSPath = strdup("/"); | |
435 | } else { | |
436 | char *tmp = | |
437 | strdup(DSPath + | |
438 | NETINFOROOTLEN); | |
439 | free((void *)DSPath); | |
440 | DSPath = tmp; | |
441 | } | |
442 | } | |
443 | } | |
444 | else | |
445 | { | |
446 | status = WHERE_DS; | |
447 | } | |
448 | } CLEANUP { | |
449 | dsCloseAttributeValueList(valueRef); | |
450 | dsDeallocAttributeEntry(dsRef, pAttrEntry); | |
451 | } ELSE { | |
452 | } ENDIF | |
453 | } CLEANUP { | |
454 | dsCloseAttributeList(attrListRef); | |
455 | dsDeallocRecordEntry(dsRef, pRecEntry); | |
456 | } ENDIF | |
457 | } CLEANUP { | |
458 | if(context2) | |
459 | dsReleaseContinueData(dsRef, context2); | |
460 | } ENDIF | |
461 | dsDataListDeallocate(dsRef, pRecType); | |
462 | free(pRecType); | |
463 | dsDataListDeallocate(dsRef, pAttrType); | |
464 | free(pAttrType); | |
465 | dsDataListDeallocate(dsRef, pPattern); | |
466 | free(pPattern); | |
c3a08f59 | 467 | } CLEANUP { |
2fc1e207 | 468 | dsCloseDirNode(nodeRef); |
c3a08f59 | 469 | } ENDIF |
c3a08f59 | 470 | } CLEANUP { |
c3a08f59 A |
471 | dsDataListDeallocate(dsRef, nodeName); |
472 | } ENDIF | |
473 | } CLEANUP { | |
474 | if(context) | |
475 | dsReleaseContinueData(dsRef, context); | |
476 | } ENDIF | |
477 | } CLEANUP { | |
478 | dsDataBufferDeAllocate(dsRef, dataBuff); | |
479 | } ELSE { | |
480 | status = eMemoryAllocError; | |
481 | } ENDIF | |
482 | } CLEANUP { | |
483 | dsCloseDirService(dsRef); | |
484 | } ENDIF | |
485 | return status; | |
486 | } | |
487 | ||
488 | /*--------------------------------------------------------------------------- | |
489 | * whereFF - check the flat file (/etc/master.passwd) | |
490 | *---------------------------------------------------------------------------*/ | |
491 | static int | |
492 | whereFF(const char *name) | |
493 | { | |
494 | pid_t pid; | |
495 | int estat; | |
496 | int status; | |
497 | ||
498 | IF((pid = fork()) >= 0) { | |
499 | if(pid == 0) { | |
500 | char pat[64]; | |
501 | ||
502 | sprintf(pat, FFPatFmt, name); | |
503 | Grep[PATINDEX] = pat; | |
504 | /*--------------------------------------------------------------- | |
505 | * Become fully root to read /etc/master.passwd | |
506 | *---------------------------------------------------------------*/ | |
507 | setuid(geteuid()); | |
508 | execv(Grep[0], Grep); | |
509 | _exit(1); | |
510 | } | |
511 | if(waitpid(pid, &estat, 0) < 0) { | |
512 | status = errno; | |
513 | break; | |
514 | } | |
515 | if(!WIFEXITED(estat)) { | |
516 | status = E_CHILDFAILED; | |
517 | break; | |
518 | } | |
519 | status = (WEXITSTATUS(estat) == 0 ? WHERE_FILES : E_NOTFOUND); | |
520 | } CLEANUP { | |
521 | } ELSE { | |
522 | status = errno; | |
523 | } ENDIF | |
524 | return status; | |
525 | } | |
526 | ||
527 | /*--------------------------------------------------------------------------- | |
528 | * whereNI - call whereDS to do the work, then the entry is found in directory | |
529 | * service (and not netinfo), mark as not found. | |
530 | *---------------------------------------------------------------------------*/ | |
531 | static int | |
532 | whereNI(const char *name) | |
533 | { | |
534 | int status = whereDS(name); | |
535 | ||
536 | if(status == WHERE_DS) | |
537 | status = E_NOTFOUND; | |
538 | return status; | |
539 | } | |
540 | ||
541 | /*--------------------------------------------------------------------------- | |
542 | * whereNIL - we skip the NILAgent | |
543 | *---------------------------------------------------------------------------*/ | |
544 | static int | |
545 | whereNIL(const char *name) | |
546 | { | |
547 | return E_NOTFOUND; | |
548 | } | |
549 | ||
550 | /*--------------------------------------------------------------------------- | |
551 | * whereNIS - check NIS passwd.byname | |
552 | *---------------------------------------------------------------------------*/ | |
553 | static int | |
554 | whereNIS(const char *name) | |
555 | { | |
556 | pid_t pid; | |
557 | int estat; | |
558 | int status; | |
559 | ||
560 | IF((pid = fork()) >= 0) { | |
561 | if(pid == 0) { | |
562 | char cmd[256]; | |
563 | ||
564 | sprintf(cmd, NISPatFmt, name); | |
565 | Ypcat[YPCATINDEX] = cmd; | |
566 | execv(Ypcat[0], Ypcat); | |
567 | _exit(1); | |
568 | } | |
569 | if(waitpid(pid, &estat, 0) < 0) { | |
570 | status = errno; | |
571 | break; | |
572 | } | |
573 | if(!WIFEXITED(estat)) { | |
574 | status = E_CHILDFAILED; | |
575 | break; | |
576 | } | |
577 | status = (WEXITSTATUS(estat) == 0 ? WHERE_NIS : E_NOTFOUND); | |
578 | } CLEANUP { | |
579 | } ELSE { | |
580 | status = errno; | |
581 | } ENDIF | |
582 | return status; | |
583 | } | |
584 | ||
585 | /*--------------------------------------------------------------------------- | |
586 | * PUBLIC wherepwent - Given a const char *, determine lookupd's LookupOrder | |
587 | * and then search for the corresponding record for each agent. | |
588 | *---------------------------------------------------------------------------*/ | |
589 | int | |
590 | wherepwent(const char *name) | |
591 | { | |
592 | char user[LINESIZE]; | |
593 | char *cp, *str; | |
594 | struct where *w; | |
2fc1e207 | 595 | FILE *fp = NULL; |
c3a08f59 | 596 | int status = 0; |
2fc1e207 A |
597 | fd_set fdset; |
598 | struct timeval selectTimeout = { 2, 0 }; | |
599 | int result; | |
c3a08f59 | 600 | char order[LINESIZE], line[LINESIZE]; |
2fc1e207 A |
601 | char *task_argv[3] = {NULL}; |
602 | int readPipe = -1; | |
603 | int writePipe = -1; | |
604 | ||
c3a08f59 A |
605 | /*------------------------------------------------------------------- |
606 | * Save the first LookupOrder as the global setting. We make sure | |
607 | * that the first _config_name is Global Configuration. | |
608 | *-------------------------------------------------------------------*/ | |
2fc1e207 A |
609 | |
610 | do | |
611 | { | |
612 | task_argv[0] = "/usr/sbin/lookupd"; | |
613 | task_argv[1] = "-configuration"; | |
614 | task_argv[2] = NULL; | |
615 | ||
616 | if ( LaunchTaskWithPipes(task_argv[0], task_argv, &readPipe, &writePipe) != 0 ) | |
617 | return E_NOTFOUND; | |
618 | ||
619 | // close this pipe now so the forked process quits on completion | |
620 | if ( writePipe != -1 ) | |
621 | close( writePipe ); | |
622 | ||
623 | // wait for data (and skip signals) | |
624 | FD_ZERO( &fdset ); | |
625 | FD_SET( readPipe, &fdset ); | |
626 | do { | |
627 | result = select( FD_SETSIZE, &fdset, NULL, NULL, &selectTimeout ); | |
628 | } | |
629 | while ( result == -1 && errno == EINTR ); | |
630 | if ( result == -1 || result == 0 ) { | |
631 | status = E_NOTFOUND; | |
632 | break; | |
633 | } | |
634 | ||
635 | // now that the descriptor is ready, parse the configuration | |
636 | fp = fdopen(readPipe, "r"); | |
637 | if ( fp == NULL ) { | |
638 | status = E_NOTFOUND; | |
639 | break; | |
640 | } | |
c3a08f59 | 641 | *user = 0; |
2fc1e207 A |
642 | while(fgets(line, LINESIZE, fp)) |
643 | { | |
c3a08f59 | 644 | if(strncasecmp(line, LookupOrder, LOOKUPORDERLEN) == 0) { |
2fc1e207 A |
645 | if((cp = strchr(line, '\n')) != NULL) |
646 | *cp = 0; | |
647 | strcpy(user, line + LOOKUPORDERLEN); | |
648 | continue; | |
c3a08f59 A |
649 | } |
650 | if(strncasecmp(line, ConfigName, CONFIGNAMELEN) == 0) { | |
2fc1e207 A |
651 | if(strncasecmp(line + CONFIGNAMELEN, GlobalConfig, GLOBALCONFIGLEN) != 0) { |
652 | status = E_NOGLOBALCONFIG; | |
653 | } | |
654 | break; | |
c3a08f59 A |
655 | } |
656 | } | |
657 | if(status < 0) | |
658 | break; | |
659 | /*------------------------------------------------------------------- | |
660 | * Save the each LookupOrder and look for _config_name of User | |
661 | * Configuration. If found, replace the global order with this one. | |
662 | *-------------------------------------------------------------------*/ | |
663 | *order = 0; | |
2fc1e207 A |
664 | while(fgets(line, LINESIZE, fp)) |
665 | { | |
c3a08f59 A |
666 | if(strncasecmp(line, LookupOrder, LOOKUPORDERLEN) == 0) { |
667 | if((cp = strchr(line, '\n')) != NULL) | |
668 | *cp = 0; | |
669 | strcpy(order, line + LOOKUPORDERLEN); | |
670 | continue; | |
671 | } | |
672 | if(strncasecmp(line, ConfigName, CONFIGNAMELEN) == 0) { | |
2fc1e207 | 673 | if(strncasecmp(line + CONFIGNAMELEN, UserConfig, USERCONFIGLEN) == 0) { |
c3a08f59 | 674 | if(*order) |
2fc1e207 | 675 | strcpy(user, order); |
c3a08f59 A |
676 | break; |
677 | } | |
678 | *order = 0; | |
679 | } | |
680 | } | |
681 | if(*user == 0) { | |
682 | status = E_NOLOOKUPORDER; | |
683 | break; | |
684 | } | |
2fc1e207 A |
685 | } |
686 | while ( 0 ); | |
687 | ||
688 | if ( fp != NULL ) | |
689 | fclose( fp ); | |
690 | else if ( readPipe != -1 ) | |
691 | close( readPipe ); | |
692 | ||
c3a08f59 A |
693 | if(status < 0) |
694 | return status; | |
2fc1e207 | 695 | |
c3a08f59 A |
696 | /*----------------------------------------------------------------------- |
697 | * Now for each agent, call the corresponding where function. If the | |
698 | * return value is no E_NOTFOUND, then we either have found it or have | |
699 | * detected an error. | |
700 | *-----------------------------------------------------------------------*/ | |
701 | str = user; | |
702 | while((cp = strtok(str, LookupOrderSep)) != NULL) { | |
703 | if((w = bsearch(cp, WhereList, NWHERE, sizeof(struct where), | |
704 | compar)) != NULL) { | |
705 | if((status = w->func(name)) != E_NOTFOUND) | |
706 | return status; | |
707 | } else | |
708 | printf("%s not supported\n", cp); | |
709 | str = NULL; | |
710 | } | |
711 | return E_NOTFOUND; | |
712 | } | |
713 | #endif /* DIRECTORY_SERVICE */ |