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