Light fixes for strange building.
[become] / src / name.c
CommitLineData
c4f2d992 1/* -*-c-*-
2 *
8bdddfb7 3 * $Id: name.c,v 1.9 2003/10/12 00:39:16 mdw Exp $
c4f2d992 4 *
5 * Looking up of names in symbol tables
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: name.c,v $
8bdddfb7 32 * Revision 1.9 2003/10/12 00:39:16 mdw
33 * Light fixes for strange building.
34 *
f60a3434 35 * Revision 1.8 2003/10/12 00:14:55 mdw
36 * Major overhaul. Now uses DSA signatures rather than the bogus symmetric
37 * encrypt-and-hope thing. Integrated with mLib and Catacomb.
38 *
8cdc1da9 39 * Revision 1.7 1998/04/23 13:23:56 mdw
40 * Fix bugs involving empty classes.
41 *
c758e654 42 * Revision 1.6 1998/01/12 16:46:14 mdw
43 * Fix copyright date.
44 *
45 * Revision 1.5 1997/09/17 10:26:11 mdw
2e11036b 46 * Use rewritten class handler. Support `none' class.
47 *
48 * Revision 1.4 1997/08/20 16:17:59 mdw
e6677daf 49 * Replace `name_reinit' by `name_end' for more sensible restart.
50 *
607937a4 51 * Revision 1.3 1997/08/07 09:49:39 mdw
52 * Extensive modifications to handle netgroups. Also sanitise user and group
53 * names before adding them to the symbol table.
54 *
03f996bd 55 * Revision 1.2 1997/08/04 10:24:24 mdw
56 * Sources placed under CVS control.
57 *
58 * Revision 1.1 1997/07/21 13:47:46 mdw
c4f2d992 59 * Initial revision
60 *
61 */
62
63/*----- Header files ------------------------------------------------------*/
64
65/* --- ANSI headers --- */
66
607937a4 67#include <ctype.h>
c4f2d992 68#include <stdio.h>
69#include <stdlib.h>
70#include <string.h>
71
72/* --- Unix headers --- */
73
607937a4 74#include <sys/types.h>
75#include <sys/socket.h>
03f996bd 76
607937a4 77#include <netinet/in.h>
03f996bd 78
607937a4 79#include <arpa/inet.h>
80
81#include <netdb.h>
c4f2d992 82#include <grp.h>
83#include <pwd.h>
84
f60a3434 85/* --- mLib headers --- */
86
87#include <mLib/alloc.h>
88#include <mLib/sym.h>
89
c4f2d992 90/* --- Local headers --- */
91
607937a4 92#include "config.h"
93
03f996bd 94#include "become.h"
c4f2d992 95#include "class.h"
96#include "name.h"
607937a4 97#include "netg.h"
c4f2d992 98#include "userdb.h"
c4f2d992 99
100/*----- Static variables --------------------------------------------------*/
101
102static sym_table name__table; /* Symbol table for everything */
103
104/*----- Main code ---------------------------------------------------------*/
105
607937a4 106/* --- @name__get@ --- *
107 *
108 * Arguments: @const char *p@ = pointer to the name we want
109 * @unsigned type@ = type of class it should have
110 *
111 * Returns: A pointer to a name ready to use, or zero if there's a type
112 * conflict.
113 *
114 * Use: Creates a name of the appropriate type all ready to use.
115 */
116
117static name *name__get(const char *p, unsigned type)
118{
119 unsigned f;
120 name *n = sym_find(&name__table, p, -1, sizeof(*n), &f);
2e11036b 121 if (!f)
122 n->c = 0;
123 return ((n->c && !(n->c->type & type)) ? 0 : n);
607937a4 124}
125
126/* --- @name__sanitise@ --- *
127 *
128 * Arguments: @const char *n@ = pointer to a name
129 * @char *buf@ = pointer to a buffer of space
130 * @size_t sz@ = size of the buffer
131 *
132 * Returns: A pointer to the transformed name in the buffer, or null
133 * if there wasn't enough space.
134 *
135 * Use: Transforms a name so that it only contains nice characters.
136 */
137
138static char *name__sanitise(const char *n, char *buf, size_t sz)
139{
140 char *p = buf;
141
142 if (strlen(n) + 1 > sz)
143 return (0);
144
145 while (*n) {
146 if (isalnum((unsigned char)*n))
147 *p++ = *n;
148 else
149 *p++ = '_';
150 n++;
151 }
152 *p++ = 0;
153 return (buf);
154}
155
03f996bd 156/* --- @name__users@ --- *
c4f2d992 157 *
158 * Arguments: ---
159 *
160 * Returns: ---
161 *
03f996bd 162 * Use: Adds all of the users registered with the user database to
163 * the name table. Also adds the users' primary groups.
c4f2d992 164 */
165
03f996bd 166static void name__users(void)
c4f2d992 167{
03f996bd 168 struct passwd *pw;
169 struct group *gr;
607937a4 170 char buf[32];
c4f2d992 171
03f996bd 172 userdb_iterateUsers();
173 while ((pw = userdb_nextUser()) != 0) {
03f996bd 174 name *n;
2e11036b 175 uid_t u = pw->pw_uid;
607937a4 176
03f996bd 177 /* --- First, add the user to the table --- */
c4f2d992 178
607937a4 179 if (name__sanitise(pw->pw_name, buf, sizeof(buf)) &&
180 (n = name__get(buf, clType_user)) != 0)
2e11036b 181 n->c = class_addUser(n->c, u);
c4f2d992 182
03f996bd 183 /* --- Now handle the user's default group --- */
c4f2d992 184
607937a4 185 if ((gr = userdb_groupById(pw->pw_gid)) != 0 &&
186 name__sanitise(gr->gr_name, buf, sizeof(buf)) &&
187 (n = name__get(buf, clType_user)) != 0)
2e11036b 188 n->c = class_addUser(n->c, u);
03f996bd 189 }
190}
c4f2d992 191
03f996bd 192/* --- @name__groups@ --- *
193 *
194 * Arguments: ---
195 *
196 * Returns: ---
197 *
198 * Use: Adds users into all of their supplementary groups.
199 */
200
201static void name__groups(void)
202{
203 struct group *gr;
204 struct passwd *pw;
205 char **p;
607937a4 206 char buf[32];
03f996bd 207
208 userdb_iterateGroups();
209 while ((gr = userdb_nextGroup()) != 0) {
03f996bd 210 name *n;
c4f2d992 211
607937a4 212 if (name__sanitise(gr->gr_name, buf, sizeof(buf)) &&
213 (n = name__get(buf, clType_user)) != 0) {
03f996bd 214
607937a4 215 /* --- Now add all of the members --- */
216
217 for (p = gr->gr_mem; *p; p++) {
2e11036b 218 if ((pw = userdb_userByName(*p)) != 0)
219 n->c = class_addUser(n->c, pw->pw_uid);
607937a4 220 }
8cdc1da9 221 if (!n->c)
222 n->c = class_none;
03f996bd 223 }
607937a4 224 }
225}
03f996bd 226
607937a4 227/* --- @name__scan@ --- *
228 *
229 * Arguments: @netg *n@ = the netgroup handle we're scanning
230 * @const char *host@ = the host name
231 * @const char *user@ = the user name
232 * @const char *domain@ = the (NIS?) domain name
233 * @void *ctx@ = some context pointer
234 *
235 * Returns: Zero to continue scanning.
236 *
237 * Use: Scans a netgroup, adding items to the name table.
238 */
239
240/* --- A data type --- */
241
242typedef struct name__scanctx {
243 char *name; /* Netgroup name prefixed with `?_'*/
244 unsigned f; /* Various interesting flags */
245 name *h; /* Name entry for hosts */
246 name *u; /* Name entry for users */
247} name__scanctx;
248
249enum { f_host = 1, f_user = 2 };
250
251/* --- And now for the real code --- */
252
253static int name__scan(netg *n, const char *host, const char *user,
254 const char *domain, void *ctx)
255{
256 name__scanctx *sc = ctx;
257
258 /* --- Add the host to the hosts class --- */
259
260 if (sc->f & f_host && host) {
261 struct hostent *h;
262 struct in_addr in;
263 const char *a;
264
265 /* --- First ensure that I have a host class --- */
266
267 if (!sc->h) {
268 sc->name[0] = 'h';
269 sc->h = name__get(sc->name, clType_host);
270 if (!sc->h) {
271 sc->f &= ~f_host;
272 goto done_host;
273 }
274 }
275
276 /* --- Now that I've done that, try to add the host --- *
277 *
278 * I'll turn it into an IP address. There's less chance of confusion
279 * that way.
280 */
281
282 if ((h = gethostbyname(host)) == 0)
283 goto done_host;
284 memcpy(&in, h->h_addr, sizeof(in));
285 if ((a = inet_ntoa(in)) == 0)
286 goto done_host;
2e11036b 287 sc->h->c = class_addString(sc->h->c, a);
607937a4 288 done_host:;
289 }
290
291 /* --- Add the user to the users class --- */
03f996bd 292
607937a4 293 if (sc->f & f_user && user) {
294 struct passwd *pw;
607937a4 295
296 /* --- First ensure that I have a user class --- */
297
298 if (!sc->u) {
299 sc->name[0] = 'u';
300 sc->u = name__get(sc->name, clType_user);
301 if (!sc->u) {
302 sc->f &= ~f_user;
303 goto done_user;
c4f2d992 304 }
305 }
607937a4 306
307 /* --- Add the user to the list --- */
308
309 if ((pw = userdb_userByName(user)) == 0)
310 goto done_user;
2e11036b 311 sc->u->c = class_addUser(sc->u->c, pw->pw_uid);
607937a4 312 done_user:;
313 }
314
315 return (0);
316}
317
318/* --- @name__netgroups@ --- *
319 *
320 * Arguments: ---
321 *
322 * Returns: ---
323 *
324 * Use: Populates the name table with netgroup information.
325 */
326
327void name__netgroups(void)
328{
329 netg *n;
330 char buf[32];
331 const char *p;
332 name__scanctx sc;
333
334 netg_iterate();
335 buf[1] = '_';
336 while ((n = netg_next()) != 0) {
337 p = netg_name(n);
338 if (name__sanitise(p, buf + 2, sizeof(buf) - 2) == 0)
339 continue;
340 sc.name = buf;
341 sc.u = sc.h = 0;
342 sc.f = f_host | f_user;
343 netg_scan(n, name__scan, &sc);
c4f2d992 344 }
03f996bd 345}
c4f2d992 346
03f996bd 347/* --- @name_init@ --- *
348 *
349 * Arguments: ---
350 *
351 * Returns: ---
352 *
353 * Use: Initialises the name table. Requires the user database to
607937a4 354 * be populated (see @userdb_local@ and @userdb_yp@, and
355 * @netg_init@).
03f996bd 356 */
c4f2d992 357
03f996bd 358void name_init(void)
359{
360 /* --- Initialise the name table --- */
c4f2d992 361
f60a3434 362 sym_create(&name__table);
c4f2d992 363
03f996bd 364 /* --- Add everyone into the table --- */
c4f2d992 365
03f996bd 366 name__users();
367 name__groups();
607937a4 368 name__netgroups();
c4f2d992 369
2e11036b 370 /* --- Finally add in the `all' and `none' classes --- *
c4f2d992 371 *
2e11036b 372 * Do that now, to prevent them being overwritten by the above.
c4f2d992 373 */
374
375 {
376 name *n;
377 unsigned f;
378
379 n = sym_find(&name__table, "all", -1, sizeof(name), &f);
380 if (f)
381 class_dec(n->c);
382 n->c = class_all;
2e11036b 383
384 n = sym_find(&name__table, "none", -1, sizeof(name), &f);
385 if (f)
386 class_dec(n->c);
387 n->c = class_none;
c4f2d992 388 }
389}
390
e6677daf 391/* --- @name_end@ --- *
c4f2d992 392 *
393 * Arguments: ---
394 *
395 * Returns: ---
396 *
e6677daf 397 * Use: Closes down the name database, so that it can be
398 * reinitialised.
c4f2d992 399 */
400
e6677daf 401void name_end(void)
c4f2d992 402{
403 /* --- Empty the symbol table --- */
404
405 {
406 sym_iter i;
407 name *n;
408
f60a3434 409 for (sym_mkiter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
c4f2d992 410 if (n->c)
411 class_dec(n->c);
412 }
413 }
414
415 /* --- Destroy and recreate the table --- */
416
f60a3434 417 sym_destroy(&name__table);
c4f2d992 418}
419
420/* --- @name_find@ --- *
421 *
422 * Arguments: @const char *p@ = pointer to name to look up
423 * @unsigned create@ = whether to create the item
424 * @unsigned *f@ = whether the item was created
425 *
426 * Returns: Pointer to a @name@ block containing the symbol, or
427 * zero if it wasn't found and we didn't want to create a
428 * new one.
429 *
430 * Use: Looks up a name in the symbol table and returns the
431 * item so located.
432 */
433
434name *name_find(const char *p, unsigned create, unsigned *f)
435{
436 /* --- This is a trivial veneer onto @sym_find@ --- */
437
438 return (sym_find(&name__table, p, -1, create ? sizeof(name) : 0, f));
439}
440
441/* --- @name_dump@ --- *
442 *
03f996bd 443 * Arguments: ---
c4f2d992 444 *
445 * Returns: ---
446 *
447 * Use: Dumps a complete listing of the symbol table.
448 */
449
03f996bd 450void name_dump(void)
c4f2d992 451{
e6677daf 452#ifdef TRACING
c4f2d992 453 sym_iter i;
454 name *n;
455
03f996bd 456 trace(TRACE_DEBUG, "name: dumping names");
f60a3434 457 for (sym_mkiter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
03f996bd 458 trace(TRACE_DEBUG, "name: dumping `%s'", n->base.name);
8cdc1da9 459 if (!n->c)
460 trace(TRACE_DEBUG, "name: <empty>");
461 else
462 class_dump(n->c, 1);
c4f2d992 463 }
e6677daf 464#endif
c4f2d992 465}
466
467/*----- Test driver -------------------------------------------------------*/
468
469#ifdef TEST_RIG
470
471int main(void)
472{
607937a4 473 ego("name-test");
8bdddfb7 474 trace_on(stdout, TRACE_ALL);
c4f2d992 475 userdb_init();
476 userdb_local();
477 userdb_yp();
607937a4 478 netg_init();
c4f2d992 479 name_init();
8cdc1da9 480 /* printf("loaded (%lu)\n", track_memused()); */
481#ifdef notdef
e6677daf 482 getchar();
483 for (;;) {
484 name_end();
485 netg_end();
486 userdb_end();
8cdc1da9 487 /* printf("cleared (%lu)\n", track_memused()); */
488 /* track_memlist(); */
e6677daf 489 userdb_init();
490 userdb_local();
491 userdb_yp();
492 netg_init();
493 name_init();
8cdc1da9 494 /* printf("reloaded (%lu)\n", track_memused()); */
e6677daf 495 getchar();
496 }
8cdc1da9 497#else
498 name_dump();
499#endif
c4f2d992 500 return (0);
501}
502
503#endif