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