c4f2d992 |
1 | /* -*-c-*- |
2 | * |
e171c3bf |
3 | * $Id: userdb.c,v 1.8 1998/06/08 11:21:22 mdw Exp $ |
c4f2d992 |
4 | * |
5 | * User database management |
6 | * |
c758e654 |
7 | * (c) 1998 EBI |
c4f2d992 |
8 | */ |
9 | |
03f996bd |
10 | /*----- Licensing notice --------------------------------------------------* |
c4f2d992 |
11 | * |
12 | * This file is part of `become' |
13 | * |
14 | * `Become' is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by |
16 | * the Free Software Foundation; either version 2 of the License, or |
17 | * (at your option) any later version. |
18 | * |
19 | * `Become' is distributed in the hope that it will be useful, |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | * GNU General Public License for more details. |
23 | * |
24 | * You should have received a copy of the GNU General Public License |
03f996bd |
25 | * along with `become'; if not, write to the Free Software Foundation, |
26 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
c4f2d992 |
27 | */ |
28 | |
29 | /*----- Revision history --------------------------------------------------* |
30 | * |
31 | * $Log: userdb.c,v $ |
e171c3bf |
32 | * Revision 1.8 1998/06/08 11:21:22 mdw |
33 | * Fixed bug in password and group file reading: strtok doesn't handle |
34 | * double colons nicely. |
35 | * |
a340752b |
36 | * Revision 1.7 1998/04/23 13:27:46 mdw |
37 | * Switch to using the ypstuff interface to YP server. |
38 | * |
c758e654 |
39 | * Revision 1.6 1998/01/12 16:46:33 mdw |
40 | * Fix copyright date. |
41 | * |
42 | * Revision 1.5 1997/09/17 10:24:08 mdw |
d8cd61fe |
43 | * Use `uid_t' instead of `int' for uids and gids. Not quite sure why I |
44 | * didn't do this before. |
45 | * |
46 | * Revision 1.4 1997/08/20 16:24:58 mdw |
46cc26eb |
47 | * Patch memory leak. Rename `userdb_reinit' to `userdb_end' for more |
48 | * sensible restart. |
49 | * |
e893b83f |
50 | * Revision 1.3 1997/08/07 09:44:29 mdw |
51 | * Read NIS-based passwords from the YP server directly, rather than using |
52 | * `popen(ypcat)', which is probably both slower and less secure. |
53 | * |
03f996bd |
54 | * Revision 1.2 1997/08/04 10:24:26 mdw |
55 | * Sources placed under CVS control. |
56 | * |
57 | * Revision 1.1 1997/07/21 13:47:43 mdw |
c4f2d992 |
58 | * Initial revision |
59 | * |
60 | */ |
61 | |
62 | /*----- Header files ------------------------------------------------------*/ |
63 | |
64 | /* --- ANSI headers --- */ |
65 | |
66 | #include <ctype.h> |
67 | #include <errno.h> |
68 | #include <stdio.h> |
69 | #include <stdlib.h> |
70 | #include <string.h> |
71 | |
72 | /* --- Unix headers --- */ |
73 | |
03f996bd |
74 | #include "config.h" |
75 | |
c4f2d992 |
76 | #include <sys/types.h> |
77 | |
78 | #include <grp.h> |
79 | #include <pwd.h> |
80 | #include <unistd.h> |
81 | |
82 | /* --- Local headers --- */ |
83 | |
e893b83f |
84 | #include "become.h" |
c4f2d992 |
85 | #include "sym.h" |
86 | #include "userdb.h" |
87 | #include "utils.h" |
a340752b |
88 | #include "ypstuff.h" |
c4f2d992 |
89 | |
90 | /*----- Type definitions --------------------------------------------------*/ |
91 | |
92 | /* --- A map link --- */ |
93 | |
94 | typedef struct userdb__node { |
95 | struct userdb__node *next; |
96 | void *rec; |
97 | } userdb__node; |
98 | |
99 | /* --- A reference to a real record --- */ |
100 | |
101 | typedef struct userdb__sym { |
102 | sym_base _base; |
103 | void *rec; |
104 | } userdb__sym; |
105 | |
106 | /* --- A name- and number-mapping --- */ |
107 | |
108 | typedef struct userdb__map { |
109 | sym_table nmap; |
110 | sym_table idmap; |
111 | userdb__node *list; |
112 | } userdb__map; |
113 | |
114 | /*----- Static variables --------------------------------------------------*/ |
115 | |
116 | static userdb__map userdb__users; /* Map of user info blocks */ |
117 | static sym_iter userdb__useri; /* Iterator for users */ |
118 | static userdb__map userdb__groups; /* Map of group info blocks */ |
119 | static sym_iter userdb__groupi; /* Iterator for groups */ |
120 | |
121 | /*----- Map management functions ------------------------------------------*/ |
122 | |
123 | /* --- @userdb__createMap@ --- * |
124 | * |
125 | * Arguments: @userdb__map *m@ = pointer to a map block |
126 | * |
127 | * Returns: --- |
128 | * |
129 | * Use: Initialises a map table. |
130 | */ |
131 | |
132 | static void userdb__createMap(userdb__map *m) |
133 | { |
134 | sym_createTable(&m->nmap); |
135 | sym_createTable(&m->idmap); |
136 | m->list = 0; |
137 | } |
138 | |
139 | /* --- @userdb__addToMap@ --- * |
140 | * |
141 | * Arguments: @userdb__map *m@ = pointer to the map block |
142 | * @const char *name@ = pointer to the item's name |
d8cd61fe |
143 | * @uid_t id@ = the item's id number |
c4f2d992 |
144 | * @void *rec@ = pointer to the actual record |
145 | * |
146 | * Returns: --- |
147 | * |
148 | * Use: Adds an item to the given map. |
149 | */ |
150 | |
151 | static void userdb__addToMap(userdb__map *m, |
152 | const char *name, |
d8cd61fe |
153 | uid_t id, void *rec) |
c4f2d992 |
154 | { |
155 | unsigned f; |
156 | userdb__sym *s; |
157 | userdb__node *n; |
158 | |
159 | s = sym_find(&m->nmap, name, -1, sizeof(*s), &f); |
160 | if (!f) |
161 | s->rec = rec; |
162 | |
163 | s = sym_find(&m->idmap, (char *)&id, sizeof(id), sizeof(*s), &f); |
164 | if (!f) |
165 | s->rec = rec; |
166 | |
167 | n = xmalloc(sizeof(*n)); |
168 | n->rec = rec; |
169 | n->next = m->list; |
170 | m->list = n; |
171 | } |
172 | |
173 | /* --- @userdb__byName@ --- * |
174 | * |
175 | * Arguments: @userdb__map *m@ = pointer to a map block |
176 | * @const char *name@ = name to look up |
177 | * |
178 | * Returns: A pointer to the appropriate block, or zero if not found. |
179 | * |
180 | * Use: Looks up a name in a mapping and returns the result. |
181 | */ |
182 | |
183 | static void *userdb__byName(userdb__map *m, const char *name) |
184 | { |
185 | userdb__sym *s = sym_find(&m->nmap, name, -1, 0, 0); |
186 | return (s ? s->rec : 0); |
187 | } |
188 | |
189 | /* --- @userdb__byId@ --- * |
190 | * |
191 | * Arguments: @userdb__map *m@ = pointer to a map block |
d8cd61fe |
192 | * @uid_t id@ = id number to find |
c4f2d992 |
193 | * |
194 | * Returns: A pointer to the appropriate block, or zero if not found. |
195 | * |
196 | * Use: Looks up an ID in a mapping, and returns the result. |
197 | */ |
198 | |
d8cd61fe |
199 | static void *userdb__byId(userdb__map *m, uid_t id) |
c4f2d992 |
200 | { |
201 | userdb__sym *s = sym_find(&m->idmap, (char *)&id, sizeof(id), 0, 0); |
202 | return (s ? s->rec : 0); |
203 | } |
204 | |
205 | /* --- @userdb__clearMap@ --- * |
206 | * |
207 | * Arguments: @userdb__map *m@ = pointer to a map block |
208 | * @void (*freerec)(void *rec)@ = pointer to a free-record proc |
209 | * |
210 | * Returns: --- |
211 | * |
212 | * Use: Clears a map, emptying it and releasing the memory it |
213 | * occupied. |
214 | */ |
215 | |
216 | static void userdb__clearMap(userdb__map *m, void (*freerec)(void *rec)) |
217 | { |
218 | userdb__node *n, *t; |
219 | |
220 | sym_destroyTable(&m->nmap); |
221 | sym_destroyTable(&m->idmap); |
222 | |
223 | for (n = m->list; n; n = t) { |
224 | t = n->next; |
225 | freerec(n->rec); |
226 | free(n); |
227 | } |
228 | } |
229 | |
230 | /*----- User and group block management -----------------------------------*/ |
231 | |
232 | /* --- @userdb__dumpUser@ --- * |
233 | * |
234 | * Arguments: @const struct passwd *pw@ = pointer to a user block |
c4f2d992 |
235 | * |
236 | * Returns: --- |
237 | * |
238 | * Use: Writes a user's informationt to a stream. |
239 | */ |
240 | |
e893b83f |
241 | #ifdef TRACING |
c4f2d992 |
242 | |
e893b83f |
243 | static void userdb__dumpUser(const struct passwd *pw) |
c4f2d992 |
244 | { |
e893b83f |
245 | trace(TRACE_DEBUG, |
246 | "debug: name `%s' passwd `%s' uid %i gid %i", |
247 | pw->pw_name, pw->pw_passwd, (int)pw->pw_uid, (int)pw->pw_gid); |
248 | trace(TRACE_DEBUG, |
249 | "debug: ... gecos `%s' home `%s' shell `%s'", |
250 | pw->pw_gecos, pw->pw_dir, pw->pw_shell); |
c4f2d992 |
251 | } |
252 | |
c4f2d992 |
253 | #endif |
254 | |
e171c3bf |
255 | /* --- @userdb__split@ --- * |
256 | * |
257 | * Arguments: @char *p@ = pointer to string |
258 | * @char **v@ = pointer to vector to fill in |
259 | * @int sz@ = maximum number of fields to split |
260 | * |
261 | * Returns: Number of fields extracted. |
262 | * |
263 | * Use: Splits a string into fields at colon characters. |
264 | */ |
265 | |
266 | static int userdb__split(char *p, char **v, int sz) |
267 | { |
268 | int count = 0; |
269 | |
270 | *v++ = p; sz--; count++; |
271 | if (!sz) |
272 | goto done; |
273 | while (*p) { |
274 | if (*p++ == ':') { |
275 | p[-1] = 0; |
276 | *v++ = p; sz--; count++; |
277 | if (!sz) |
278 | goto done; |
279 | } |
280 | } |
281 | while (sz--) |
282 | *v++ = 0; |
283 | |
284 | done: |
285 | return (count); |
286 | } |
287 | |
c4f2d992 |
288 | /* --- @userdb_copyUser@ --- * |
289 | * |
290 | * Arguments: @struct passwd *pw@ = pointer to block to copy |
291 | * |
292 | * Returns: Pointer to the copy. |
293 | * |
294 | * Use: Copies a user block. The copy is `deep' so all the strings |
295 | * are copied too. Free the copy with @userdb_freeUser@ when |
296 | * you don't want it any more. |
297 | */ |
298 | |
299 | struct passwd *userdb_copyUser(struct passwd *pw) |
300 | { |
301 | struct passwd *npw; |
302 | |
303 | if (!pw) |
304 | return (0); |
305 | |
306 | npw = xmalloc(sizeof(*npw)); |
307 | |
308 | npw->pw_name = xstrdup(pw->pw_name); |
309 | npw->pw_passwd = xstrdup(pw->pw_passwd); |
310 | npw->pw_uid = pw->pw_uid; |
311 | npw->pw_gid = pw->pw_gid; |
312 | npw->pw_gecos = xstrdup(pw->pw_gecos); |
313 | npw->pw_dir = xstrdup(pw->pw_dir); |
314 | npw->pw_shell = xstrdup(pw->pw_shell); |
315 | |
316 | return (npw); |
317 | } |
318 | |
319 | /* --- @userdb__buildUser@ --- * |
320 | * |
321 | * Arguments: @char *s@ = pointer to user string |
322 | * |
323 | * Returns: Pointer to a user block. |
324 | * |
325 | * Use: Converts a line from a user file into a password entry. |
326 | * Note that the string is corrupted by @strtok@ while it gets |
327 | * parsed. |
328 | */ |
329 | |
330 | static struct passwd *userdb__buildUser(char *s) |
331 | { |
332 | struct passwd *pw = xmalloc(sizeof(*pw)); |
e171c3bf |
333 | char *v[7]; |
c4f2d992 |
334 | |
e171c3bf |
335 | if (userdb__split(s, v, 7) < 7) { |
336 | free(pw); |
337 | return (0); |
338 | } |
c4f2d992 |
339 | |
e171c3bf |
340 | pw->pw_name = xstrdup(v[0]); |
341 | pw->pw_passwd = xstrdup(v[1]); |
342 | pw->pw_uid = (uid_t)atol(v[2]); |
343 | pw->pw_gid = (gid_t)atol(v[3]); |
344 | pw->pw_gecos = xstrdup(v[4]); |
345 | pw->pw_dir = xstrdup(v[5]); |
346 | pw->pw_shell = xstrdup(v[6]); |
347 | return (pw); |
c4f2d992 |
348 | } |
349 | |
350 | /* --- @userdb_freeUser@ --- * |
351 | * |
352 | * Arguments: @void *rec@ = pointer to a user record |
353 | * |
354 | * Returns: --- |
355 | * |
356 | * Use: Frees a user record. |
357 | */ |
358 | |
359 | void userdb_freeUser(void *rec) |
360 | { |
361 | struct passwd *pw; |
362 | |
363 | if (!rec) |
364 | return; |
365 | |
366 | pw = rec; |
367 | free(pw->pw_name); |
368 | free(pw->pw_passwd); |
369 | free(pw->pw_gecos); |
370 | free(pw->pw_dir); |
371 | free(pw->pw_shell); |
372 | free(pw); |
373 | } |
374 | |
375 | /* --- @userdb__dumpGroup@ --- * |
376 | * |
377 | * Arguments: @const struct group *gr@ = pointer to a group block |
378 | * @FILE *fp@ = pointer to stream to write on |
379 | * |
380 | * Returns: --- |
381 | * |
382 | * Use: Writes a group's information to a stream. |
383 | */ |
384 | |
e893b83f |
385 | #ifdef TRACING |
c4f2d992 |
386 | |
e893b83f |
387 | static void userdb__dumpGroup(const struct group *gr) |
c4f2d992 |
388 | { |
389 | char *const *p; |
390 | |
e893b83f |
391 | trace(TRACE_DEBUG, |
392 | "debug: name `%s' passwd `%s' gid %i", |
c4f2d992 |
393 | gr->gr_name, gr->gr_passwd, (int)gr->gr_gid); |
394 | for (p = gr->gr_mem; *p; p++) |
e893b83f |
395 | trace(TRACE_DEBUG,"debug: ... `%s'", *p); |
c4f2d992 |
396 | } |
397 | |
c4f2d992 |
398 | #endif |
399 | |
400 | /* --- @userdb_copyGroup@ --- * |
401 | * |
402 | * Arguments: @struct group *gr@ = pointer to group block |
403 | * |
404 | * Returns: Pointer to copied block |
405 | * |
406 | * Use: Copies a group block. The copy is `deep' so all the strings |
407 | * are copied too. Free the copy with @userdb_freeGroup@ when |
408 | * you don't want it any more. |
409 | */ |
410 | |
411 | struct group *userdb_copyGroup(struct group *gr) |
412 | { |
413 | struct group *ngr; |
414 | int i, max; |
415 | |
416 | if (!gr) |
417 | return (0); |
418 | |
419 | ngr = xmalloc(sizeof(*ngr)); |
420 | |
421 | ngr->gr_name = xstrdup(gr->gr_name); |
422 | ngr->gr_passwd = xstrdup(gr->gr_passwd); |
423 | ngr->gr_gid = gr->gr_gid; |
424 | |
425 | for (max = 0; gr->gr_mem[max]; max++) |
426 | ; |
427 | ngr->gr_mem = xmalloc((max + 1) * sizeof(char *)); |
428 | for (i = 0; i < max; i++) |
429 | ngr->gr_mem[i] = xstrdup(gr->gr_mem[i]); |
430 | ngr->gr_mem[max] = 0; |
431 | |
432 | return (ngr); |
433 | } |
434 | |
435 | /* --- @userdb__buildGroup@ --- * |
436 | * |
437 | * Arguments: @char *s@ = pointer to group line string |
438 | * |
439 | * Returns: Pointer to a group block |
440 | * |
441 | * Use: Parses an entry in the groups file. The string is garbled |
442 | * by @strtok@ as we go. |
443 | */ |
444 | |
445 | static struct group *userdb__buildGroup(char *s) |
446 | { |
447 | struct group *gr = xmalloc(sizeof(*gr)); |
e171c3bf |
448 | char *v[4]; |
c4f2d992 |
449 | int i; |
450 | |
451 | /* --- Do the easy bits --- */ |
452 | |
e171c3bf |
453 | if (userdb__split(s, v, 4) < 3) { |
454 | free(gr); |
455 | return (0); |
456 | } |
457 | gr->gr_name = xstrdup(v[0]); |
458 | gr->gr_passwd = xstrdup(v[1]); |
459 | gr->gr_gid = (gid_t)atol(v[2]); |
c4f2d992 |
460 | |
461 | /* --- Count the number of members --- */ |
462 | |
e171c3bf |
463 | s = v[3]; |
c4f2d992 |
464 | i = 0; |
e171c3bf |
465 | if (s && s[0]) { |
466 | for (;;) { |
467 | i++; |
468 | if ((s = strpbrk(s, ",")) == 0) |
469 | break; |
470 | s++; |
471 | } |
c4f2d992 |
472 | } |
473 | |
474 | /* --- Allocate the block and fill it --- */ |
475 | |
476 | gr->gr_mem = xmalloc((i + 1) * sizeof(char *)); |
477 | i = 0; |
e171c3bf |
478 | if (v[3]) { |
479 | s = strtok(v[3], ","); |
480 | while (s) { |
481 | gr->gr_mem[i++] = xstrdup(s); |
482 | s = strtok(0, ","); |
483 | } |
484 | } |
c4f2d992 |
485 | gr->gr_mem[i] = 0; |
486 | |
487 | return (gr); |
c4f2d992 |
488 | } |
489 | |
490 | /* --- @userdb_freeGroup@ --- * |
491 | * |
492 | * Arguments: @void *rec@ = pointer to a group record |
493 | * |
494 | * Returns: --- |
495 | * |
496 | * Use: Frees a group record. |
497 | */ |
498 | |
499 | void userdb_freeGroup(void *rec) |
500 | { |
501 | struct group *gr; |
502 | char **p; |
503 | |
504 | if (!rec) |
505 | return; |
506 | |
507 | gr = rec; |
508 | free(gr->gr_name); |
509 | free(gr->gr_passwd); |
510 | for (p = gr->gr_mem; *p; p++) |
511 | free(*p); |
512 | free(gr->gr_mem); |
513 | free(gr); |
514 | } |
515 | |
03f996bd |
516 | /*----- Answering queries -------------------------------------------------*/ |
c4f2d992 |
517 | |
518 | /* --- @userdb_userByName@, @userdb_userById@ --- * |
519 | * |
520 | * Arguments: @const char *name@ = pointer to user's name |
521 | * @uid_t id@ = user id to find |
522 | * |
523 | * Returns: Pointer to user block, or zero if not found. |
524 | * |
525 | * Use: Looks up a user by name or id. |
526 | */ |
527 | |
528 | struct passwd *userdb_userByName(const char *name) |
529 | { return (userdb__byName(&userdb__users, name)); } |
530 | |
531 | struct passwd *userdb_userById(uid_t id) |
532 | { return (userdb__byId(&userdb__users, id)); } |
533 | |
534 | /* --- @userdb_iterateUsers@, @userdb_iterateUsers_r@ --- * |
535 | * |
536 | * Arguments: @userdb_iter *i@ = pointer to a symbol table iterator object |
537 | * |
538 | * Returns: --- |
539 | * |
540 | * Use: Initialises an iteration for the user database. |
541 | */ |
542 | |
543 | void userdb_iterateUsers(void) |
544 | { userdb_iterateUsers_r(&userdb__useri); } |
545 | |
546 | void userdb_iterateUsers_r(userdb_iter *i) |
547 | { sym_createIter(i, &userdb__users.nmap); } |
548 | |
549 | /* --- @userdb_nextUser@, @userdb_nextUser_r@ --- * |
550 | * |
551 | * Arguments: @userdb_iter *i@ = pointer to a symbol table iterator oject |
552 | * |
553 | * Returns: Pointer to the next user block, or null. |
554 | * |
555 | * Use: Returns another user block. |
556 | */ |
557 | |
558 | struct passwd *userdb_nextUser(void) |
559 | { return (userdb_nextUser_r(&userdb__useri)); } |
560 | |
561 | struct passwd *userdb_nextUser_r(userdb_iter *i) |
562 | { |
563 | userdb__sym *s = sym_next(i); |
564 | return (s ? s->rec : 0); |
565 | } |
566 | |
567 | /* --- @userdb_groupByName@, @userdb_groupById@ --- * |
568 | * |
569 | * Arguments: @const char *name@ = pointer to group's name |
570 | * @gid_t id@ = group id to find |
571 | * |
572 | * Returns: Pointer to group block, or zero if not found. |
573 | * |
574 | * Use: Looks up a group by name or id. |
575 | */ |
576 | |
577 | struct group *userdb_groupByName(const char *name) |
578 | { return (userdb__byName(&userdb__groups, name)); } |
579 | |
580 | struct group *userdb_groupById(gid_t id) |
581 | { return (userdb__byId(&userdb__groups, id)); } |
582 | |
583 | /* --- @userdb_iterateGroups@, @userdb_iterateGroups_r@ --- * |
584 | * |
585 | * Arguments: @userdb_iter *i@ = pointer to a symbol table iterator object |
586 | * |
587 | * Returns: --- |
588 | * |
589 | * Use: Initialises an iteration for the group database. |
590 | */ |
591 | |
592 | void userdb_iterateGroups(void) |
593 | { userdb_iterateGroups_r(&userdb__groupi); } |
594 | |
595 | void userdb_iterateGroups_r(userdb_iter *i) |
596 | { sym_createIter(i, &userdb__groups.nmap); } |
597 | |
598 | /* --- @userdb_nextGroup@, @userdb_nextGroup_r@ --- * |
599 | * |
600 | * Arguments: @userdb_iter *i@ = pointer to a symbol table iterator oject |
601 | * |
602 | * Returns: Pointer to the next group block, or null. |
603 | * |
604 | * Use: Returns another group block. |
605 | */ |
606 | |
607 | struct group *userdb_nextGroup(void) |
608 | { return (userdb_nextGroup_r(&userdb__groupi)); } |
609 | |
610 | struct group *userdb_nextGroup_r(userdb_iter *i) |
611 | { |
612 | userdb__sym *s = sym_next(i); |
613 | return (s ? s->rec : 0); |
614 | } |
615 | |
03f996bd |
616 | /*----- Yellow pages support ----------------------------------------------*/ |
617 | |
618 | #ifdef HAVE_YP |
619 | |
620 | /* --- @userdb__foreachUser@ --- * |
621 | * |
622 | * Arguments: @int st@ = YP protocol-level status code |
623 | * @char *k@ = address of the key for this record |
624 | * @int ksz@ = size of the key |
625 | * @char *v@ = address of the value for this record |
626 | * @int vsz@ = size of the value |
627 | * @char *data@ = pointer to some data passed to me |
628 | * |
629 | * Returns: Zero to be called again, nonzero to end the enumeration. |
630 | * |
631 | * Use: Handles an incoming user record. |
632 | */ |
633 | |
634 | static int userdb__foreachUser(int st, char *k, int ksz, |
635 | char *v, int vsz, char *data) |
636 | { |
637 | char *cv; |
638 | struct passwd *pw; |
639 | |
640 | if (st != YP_TRUE) |
641 | return (-1); |
642 | cv = xmalloc(vsz + 1); |
643 | memcpy(cv, v, vsz); |
644 | cv[vsz] = 0; |
e893b83f |
645 | T( trace(TRACE_DEBUG, "debug: nis string: `%s'", cv); ) |
03f996bd |
646 | pw = userdb__buildUser(cv); |
e893b83f |
647 | if (pw && !userdb__byName(&userdb__users, pw->pw_name)) { |
648 | IF_TRACING(TRACE_DEBUG, userdb__dumpUser(pw); ) |
03f996bd |
649 | userdb__addToMap(&userdb__users, pw->pw_name, pw->pw_uid, pw); |
46cc26eb |
650 | } else |
651 | userdb_freeUser(pw); |
03f996bd |
652 | free(cv); |
653 | return (0); |
654 | } |
655 | |
656 | /* --- @userdb__foreachGroup@ --- * |
657 | * |
658 | * Arguments: @int st@ = YP protocol-level status code |
659 | * @char *k@ = address of the key for this record |
660 | * @int ksz@ = size of the key |
661 | * @char *v@ = address of the value for this record |
662 | * @int vsz@ = size of the value |
663 | * @char *data@ = pointer to some data passed to me |
664 | * |
665 | * Returns: Zero to be called again, nonzero to end the enumeration. |
666 | * |
667 | * Use: Handles an incoming user record. |
668 | */ |
669 | |
670 | static int userdb__foreachGroup(int st, char *k, int ksz, |
671 | char *v, int vsz, char *data) |
672 | { |
673 | char *cv; |
674 | struct group *gr; |
675 | |
676 | if (st != YP_TRUE) |
677 | return (-1); |
678 | cv = xmalloc(vsz + 1); |
679 | memcpy(cv, v, vsz); |
680 | cv[vsz] = 0; |
e893b83f |
681 | T( trace(TRACE_DEBUG, "debug: nis string: `%s'", cv); ) |
03f996bd |
682 | gr = userdb__buildGroup(cv); |
e893b83f |
683 | if (gr && !userdb__byName(&userdb__groups, gr->gr_name)) { |
684 | IF_TRACING(TRACE_DEBUG, userdb__dumpGroup(gr); ) |
03f996bd |
685 | userdb__addToMap(&userdb__groups, gr->gr_name, gr->gr_gid, gr); |
46cc26eb |
686 | } else |
687 | userdb_freeGroup(gr); |
03f996bd |
688 | free(cv); |
689 | return (0); |
690 | } |
691 | |
692 | /* --- @userdb_yp@ --- * |
693 | * |
694 | * Arguments: --- |
695 | * |
696 | * Returns: --- |
697 | * |
698 | * Use: Fetches the YP database of users. |
699 | */ |
700 | |
701 | void userdb_yp(void) |
702 | { |
03f996bd |
703 | /* --- Bind to a server --- */ |
704 | |
a340752b |
705 | ypstuff_bind(); |
706 | if (!yp_domain) |
03f996bd |
707 | return; |
708 | |
e893b83f |
709 | T( trace(TRACE_DEBUG, "debug: adding NIS users"); ) |
710 | |
03f996bd |
711 | /* --- Fetch the users map --- */ |
712 | |
713 | { |
714 | static struct ypall_callback ucb = { userdb__foreachUser, 0 }; |
a340752b |
715 | yp_all(yp_domain, "passwd.byuid", &ucb); |
03f996bd |
716 | } |
717 | |
718 | /* --- Fetch the groups map --- */ |
719 | |
720 | { |
721 | static struct ypall_callback gcb = { userdb__foreachGroup, 0 }; |
a340752b |
722 | yp_all(yp_domain, "group.bygid", &gcb); |
03f996bd |
723 | } |
03f996bd |
724 | } |
725 | |
726 | #else |
727 | |
728 | void userdb_yp(void) { ; } |
729 | |
730 | #endif |
731 | |
732 | /*----- Building the databases --------------------------------------------*/ |
733 | |
734 | /* --- @userdb_local@ --- * |
735 | * |
736 | * Arguments: --- |
737 | * |
738 | * Returns: --- |
739 | * |
740 | * Use: Reads the local list of users into the maps. |
741 | */ |
742 | |
743 | void userdb_local(void) |
744 | { |
e893b83f |
745 | T( trace(TRACE_DEBUG, "debug: adding local users"); ) |
03f996bd |
746 | |
747 | /* --- Fetch users first --- */ |
748 | |
749 | { |
750 | struct passwd *pw; |
751 | |
752 | setpwent(); |
753 | while ((pw = getpwent()) != 0) { |
e893b83f |
754 | IF_TRACING(TRACE_DEBUG, userdb__dumpUser(pw); ) |
03f996bd |
755 | if (!userdb__byName(&userdb__users, pw->pw_name)) |
756 | userdb__addToMap(&userdb__users, pw->pw_name, pw->pw_uid, |
757 | userdb_copyUser(pw)); |
758 | } |
759 | endpwent(); |
760 | } |
761 | |
762 | /* --- Then fetch groups --- */ |
763 | |
764 | { |
765 | struct group *gr; |
766 | |
767 | setgrent(); |
768 | while ((gr = getgrent()) != 0) { |
e893b83f |
769 | IF_TRACING(TRACE_DEBUG, userdb__dumpGroup(gr); ) |
03f996bd |
770 | if (!userdb__byName(&userdb__groups, gr->gr_name)) |
771 | userdb__addToMap(&userdb__groups, gr->gr_name, gr->gr_gid, |
772 | userdb_copyGroup(gr)); |
773 | } |
774 | endgrent(); |
775 | } |
776 | } |
777 | |
c4f2d992 |
778 | /* --- @userdb_init@ --- * |
779 | * |
780 | * Arguments: --- |
781 | * |
782 | * Returns: --- |
783 | * |
784 | * Use: Initialises the user database. |
785 | */ |
786 | |
787 | void userdb_init(void) |
788 | { |
789 | userdb__createMap(&userdb__users); |
790 | userdb__createMap(&userdb__groups); |
791 | } |
792 | |
46cc26eb |
793 | /* --- @userdb_end@ --- * |
c4f2d992 |
794 | * |
795 | * Arguments: --- |
796 | * |
797 | * Returns: --- |
798 | * |
46cc26eb |
799 | * Use: Closes down the user database. |
c4f2d992 |
800 | */ |
801 | |
46cc26eb |
802 | void userdb_end(void) |
c4f2d992 |
803 | { |
804 | userdb__clearMap(&userdb__users, userdb_freeUser); |
805 | userdb__clearMap(&userdb__groups, userdb_freeGroup); |
c4f2d992 |
806 | } |
807 | |
808 | /*----- Test rig ----------------------------------------------------------*/ |
809 | |
810 | #ifdef TEST_RIG |
811 | |
812 | void dumpit(const char *msg) |
813 | { |
e893b83f |
814 | trace(TRACE_DEBUG, "debug: %s", msg); |
c4f2d992 |
815 | |
816 | { |
817 | struct passwd *pw; |
818 | for (userdb_iterateUsers(); (pw = userdb_nextUser()) != 0; ) |
e893b83f |
819 | userdb__dumpUser(pw); |
c4f2d992 |
820 | } |
821 | |
822 | { |
823 | struct group *gr; |
824 | for (userdb_iterateGroups(); (gr = userdb_nextGroup()) != 0; ) |
e893b83f |
825 | userdb__dumpGroup(gr); |
c4f2d992 |
826 | } |
827 | } |
828 | |
829 | int main(void) |
830 | { |
e893b83f |
831 | ego("userdb-test"); |
a340752b |
832 | traceon(stdout, TRACE_ALL); |
c4f2d992 |
833 | userdb_init(); |
e893b83f |
834 | userdb_local(); |
46cc26eb |
835 | userdb_yp(); |
a340752b |
836 | dumpit("spong"); |
837 | /* printf("loaded (%lu)\n", track_memused()); */ |
46cc26eb |
838 | getchar(); |
839 | for (;;) { |
840 | userdb_end(); |
a340752b |
841 | /* printf("cleared (%lu)\n", track_memused()); */ |
46cc26eb |
842 | /* track_memlist(); */ |
843 | userdb_init(); |
844 | userdb_local(); |
845 | userdb_yp(); |
a340752b |
846 | /* printf("reloaded (%lu)\n", track_memused()); */ |
46cc26eb |
847 | getchar(); |
848 | } |
c4f2d992 |
849 | return (0); |
850 | } |
851 | |
852 | #endif |
853 | |
854 | /*----- That's all, folks -------------------------------------------------*/ |