Annotation of src/usr.bin/sudo/defaults.c, Revision 1.10
1.1 millert 1: /*
1.9 millert 2: * Copyright (c) 1999-2001, 2003 Todd C. Miller <Todd.Miller@courtesan.com>
1.1 millert 3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: *
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: *
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * 3. The name of the author may not be used to endorse or promote products
17: * derived from this software without specific prior written permission.
18: *
19: * 4. Products derived from this software may not be called "Sudo" nor
20: * may "Sudo" appear in their names without specific prior written
21: * permission from the author.
22: *
23: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
26: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.10 ! millert 33: *
! 34: * Sponsored in part by the Defense Advanced Research Projects
! 35: * Agency (DARPA) and Air Force Research Laboratory, Air Force
! 36: * Materiel Command, USAF, under agreement number F39502-99-1-0512.
1.1 millert 37: */
38:
39: #include "config.h"
40:
1.8 millert 41: #include <sys/types.h>
42: #include <sys/param.h>
1.1 millert 43: #include <stdio.h>
44: #ifdef STDC_HEADERS
1.8 millert 45: # include <stdlib.h>
46: # include <stddef.h>
47: #else
48: # ifdef HAVE_STDLIB_H
49: # include <stdlib.h>
50: # endif
1.1 millert 51: #endif /* STDC_HEADERS */
1.8 millert 52: #ifdef HAVE_STRING_H
53: # include <string.h>
54: #else
55: # ifdef HAVE_STRINGS_H
56: # include <strings.h>
57: # endif
58: #endif /* HAVE_STRING_H */
59: # ifdef HAVE_UNISTD_H
1.1 millert 60: #include <unistd.h>
61: #endif /* HAVE_UNISTD_H */
1.9 millert 62: #ifdef HAVE_ERR_H
63: # include <err.h>
64: #else
65: # include "emul/err.h"
66: #endif /* HAVE_ERR_H */
1.8 millert 67: #include <ctype.h>
1.1 millert 68:
69: #include "sudo.h"
70:
71: #ifndef lint
1.10 ! millert 72: static const char rcsid[] = "$Sudo: defaults.c,v 1.40 2003/04/16 00:42:09 millert Exp $";
1.1 millert 73: #endif /* lint */
74:
75: /*
76: * For converting between syslog numbers and strings.
77: */
78: struct strmap {
79: char *name;
80: int num;
81: };
82:
83: #ifdef LOG_NFACILITIES
84: static struct strmap facilities[] = {
85: #ifdef LOG_AUTHPRIV
86: { "authpriv", LOG_AUTHPRIV },
87: #endif
88: { "auth", LOG_AUTH },
89: { "daemon", LOG_DAEMON },
90: { "user", LOG_USER },
91: { "local0", LOG_LOCAL0 },
92: { "local1", LOG_LOCAL1 },
93: { "local2", LOG_LOCAL2 },
94: { "local3", LOG_LOCAL3 },
95: { "local4", LOG_LOCAL4 },
96: { "local5", LOG_LOCAL5 },
97: { "local6", LOG_LOCAL6 },
98: { "local7", LOG_LOCAL7 },
99: { NULL, -1 }
100: };
101: #endif /* LOG_NFACILITIES */
102:
103: static struct strmap priorities[] = {
104: { "alert", LOG_ALERT },
105: { "crit", LOG_CRIT },
106: { "debug", LOG_DEBUG },
107: { "emerg", LOG_EMERG },
108: { "err", LOG_ERR },
109: { "info", LOG_INFO },
110: { "notice", LOG_NOTICE },
111: { "warning", LOG_WARNING },
112: { NULL, -1 }
113: };
114:
115: extern int sudolineno;
116:
117: /*
118: * Local prototypes.
119: */
120: static int store_int __P((char *, struct sudo_defs_types *, int));
1.8 millert 121: static int store_uint __P((char *, struct sudo_defs_types *, int));
1.1 millert 122: static int store_str __P((char *, struct sudo_defs_types *, int));
123: static int store_syslogfac __P((char *, struct sudo_defs_types *, int));
124: static int store_syslogpri __P((char *, struct sudo_defs_types *, int));
125: static int store_mode __P((char *, struct sudo_defs_types *, int));
1.3 millert 126: static int store_pwflag __P((char *, struct sudo_defs_types *, int));
1.8 millert 127: static int store_list __P((char *, struct sudo_defs_types *, int));
128: static void list_op __P((char *, size_t, struct sudo_defs_types *, enum list_ops));
1.1 millert 129:
130: /*
131: * Table describing compile-time and run-time options.
132: */
1.8 millert 133: #include <def_data.c>
1.1 millert 134:
135: /*
136: * Print version and configure info.
137: */
138: void
139: dump_defaults()
140: {
141: struct sudo_defs_types *cur;
1.8 millert 142: struct list_member *item;
1.1 millert 143:
144: for (cur = sudo_defs_table; cur->name; cur++) {
145: if (cur->desc) {
146: switch (cur->type & T_MASK) {
147: case T_FLAG:
148: if (cur->sd_un.flag)
149: puts(cur->desc);
150: break;
151: case T_STR:
152: case T_LOGFAC:
153: case T_LOGPRI:
1.3 millert 154: case T_PWFLAG:
1.1 millert 155: if (cur->sd_un.str) {
156: (void) printf(cur->desc, cur->sd_un.str);
157: putchar('\n');
158: }
159: break;
1.8 millert 160: case T_UINT:
1.1 millert 161: case T_INT:
162: (void) printf(cur->desc, cur->sd_un.ival);
163: putchar('\n');
164: break;
165: case T_MODE:
166: (void) printf(cur->desc, cur->sd_un.mode);
167: putchar('\n');
168: break;
1.8 millert 169: case T_LIST:
170: if (cur->sd_un.list) {
171: puts(cur->desc);
172: for (item = cur->sd_un.list; item; item = item->next)
173: printf("\t%s\n", item->value);
174: }
175: break;
1.1 millert 176: }
177: }
178: }
179: }
180:
181: /*
182: * List each option along with its description.
183: */
184: void
185: list_options()
186: {
187: struct sudo_defs_types *cur;
188: char *p;
189:
190: (void) puts("Available options in a sudoers ``Defaults'' line:\n");
191: for (cur = sudo_defs_table; cur->name; cur++) {
192: if (cur->name && cur->desc) {
193: switch (cur->type & T_MASK) {
194: case T_FLAG:
195: (void) printf("%s: %s\n", cur->name, cur->desc);
196: break;
197: default:
198: p = strrchr(cur->desc, ':');
199: if (p)
1.8 millert 200: (void) printf("%s: %.*s\n", cur->name,
201: (int) (p - cur->desc), cur->desc);
1.1 millert 202: else
203: (void) printf("%s: %s\n", cur->name, cur->desc);
204: break;
205: }
206: }
207: }
208: }
209:
210: /*
211: * Sets/clears an entry in the defaults structure
212: * If a variable that takes a value is used in a boolean
213: * context with op == 0, disable that variable.
214: * Eg. you may want to turn off logging to a file for some hosts.
215: * This is only meaningful for variables that are *optional*.
216: */
217: int
218: set_default(var, val, op)
219: char *var;
220: char *val;
221: int op; /* TRUE or FALSE */
222: {
223: struct sudo_defs_types *cur;
1.2 millert 224: int num;
1.1 millert 225:
1.2 millert 226: for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
1.1 millert 227: if (strcmp(var, cur->name) == 0)
228: break;
229: }
230: if (!cur->name) {
1.9 millert 231: warnx("unknown defaults entry `%s' referenced near line %d",
1.1 millert 232: var, sudolineno);
233: return(FALSE);
234: }
235:
236: switch (cur->type & T_MASK) {
237: case T_LOGFAC:
238: if (!store_syslogfac(val, cur, op)) {
239: if (val)
1.9 millert 240: warnx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 241: else
1.9 millert 242: warnx("no value specified for `%s' on line %d",
1.1 millert 243: var, sudolineno);
244: return(FALSE);
245: }
246: break;
247: case T_LOGPRI:
248: if (!store_syslogpri(val, cur, op)) {
249: if (val)
1.9 millert 250: warnx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 251: else
1.9 millert 252: warnx("no value specified for `%s' on line %d",
1.1 millert 253: var, sudolineno);
254: return(FALSE);
255: }
256: break;
1.3 millert 257: case T_PWFLAG:
258: if (!store_pwflag(val, cur, op)) {
259: if (val)
1.9 millert 260: warnx("value `%s' is invalid for option `%s'", val, var);
1.3 millert 261: else
1.9 millert 262: warnx("no value specified for `%s' on line %d",
1.3 millert 263: var, sudolineno);
264: return(FALSE);
265: }
266: break;
1.1 millert 267: case T_STR:
268: if (!val) {
269: /* Check for bogus boolean usage or lack of a value. */
270: if (!(cur->type & T_BOOL) || op != FALSE) {
1.9 millert 271: warnx("no value specified for `%s' on line %d",
1.1 millert 272: var, sudolineno);
273: return(FALSE);
274: }
275: }
1.7 millert 276: if ((cur->type & T_PATH) && val && *val != '/') {
1.9 millert 277: warnx("values for `%s' must start with a '/'", var);
1.1 millert 278: return(FALSE);
279: }
280: if (!store_str(val, cur, op)) {
1.9 millert 281: warnx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 282: return(FALSE);
283: }
284: break;
285: case T_INT:
286: if (!val) {
287: /* Check for bogus boolean usage or lack of a value. */
288: if (!(cur->type & T_BOOL) || op != FALSE) {
1.9 millert 289: warnx("no value specified for `%s' on line %d",
1.1 millert 290: var, sudolineno);
291: return(FALSE);
292: }
293: }
294: if (!store_int(val, cur, op)) {
1.9 millert 295: warnx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 296: return(FALSE);
297: }
298: break;
1.8 millert 299: case T_UINT:
300: if (!val) {
301: /* Check for bogus boolean usage or lack of a value. */
302: if (!(cur->type & T_BOOL) || op != FALSE) {
1.9 millert 303: warnx("no value specified for `%s' on line %d",
1.8 millert 304: var, sudolineno);
305: return(FALSE);
306: }
307: }
308: if (!store_uint(val, cur, op)) {
1.9 millert 309: warnx("value `%s' is invalid for option `%s'", val, var);
1.8 millert 310: return(FALSE);
311: }
312: break;
1.1 millert 313: case T_MODE:
314: if (!val) {
315: /* Check for bogus boolean usage or lack of a value. */
316: if (!(cur->type & T_BOOL) || op != FALSE) {
1.9 millert 317: warnx("no value specified for `%s' on line %d",
1.1 millert 318: var, sudolineno);
319: return(FALSE);
320: }
321: }
322: if (!store_mode(val, cur, op)) {
1.9 millert 323: warnx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 324: return(FALSE);
325: }
326: break;
327: case T_FLAG:
328: if (val) {
1.9 millert 329: warnx("option `%s' does not take a value on line %d",
330: var, sudolineno);
1.1 millert 331: return(FALSE);
332: }
333: cur->sd_un.flag = op;
1.2 millert 334:
335: /* Special action for I_FQDN. Move to own switch if we get more */
336: if (num == I_FQDN && op)
337: set_fqdn();
1.1 millert 338: break;
1.8 millert 339: case T_LIST:
340: if (!val) {
341: /* Check for bogus boolean usage or lack of a value. */
342: if (!(cur->type & T_BOOL) || op != FALSE) {
1.9 millert 343: warnx("no value specified for `%s' on line %d",
1.8 millert 344: var, sudolineno);
345: return(FALSE);
346: }
347: }
348: if (!store_list(val, cur, op)) {
1.9 millert 349: warnx("value `%s' is invalid for option `%s'", val, var);
1.8 millert 350: return(FALSE);
351: }
1.1 millert 352: }
353:
354: return(TRUE);
355: }
356:
357: /*
358: * Set default options to compiled-in values.
359: * Any of these may be overridden at runtime by a "Defaults" file.
360: */
361: void
362: init_defaults()
363: {
364: static int firsttime = 1;
365: struct sudo_defs_types *def;
366:
367: /* Free any strings that were set. */
368: if (!firsttime) {
369: for (def = sudo_defs_table; def->name; def++)
370: switch (def->type & T_MASK) {
371: case T_STR:
372: case T_LOGFAC:
373: case T_LOGPRI:
1.3 millert 374: case T_PWFLAG:
1.1 millert 375: if (def->sd_un.str) {
376: free(def->sd_un.str);
377: def->sd_un.str = NULL;
378: }
379: break;
1.8 millert 380: case T_LIST:
381: list_op(NULL, 0, def, freeall);
382: break;
1.1 millert 383: }
384: }
385:
386: /* First initialize the flags. */
387: #ifdef LONG_OTP_PROMPT
388: def_flag(I_LONG_OTP_PROMPT) = TRUE;
389: #endif
390: #ifdef IGNORE_DOT_PATH
391: def_flag(I_IGNORE_DOT) = TRUE;
392: #endif
393: #ifdef ALWAYS_SEND_MAIL
394: def_flag(I_MAIL_ALWAYS) = TRUE;
395: #endif
396: #ifdef SEND_MAIL_WHEN_NO_USER
1.8 millert 397: def_flag(I_MAIL_NO_USER) = TRUE;
1.1 millert 398: #endif
399: #ifdef SEND_MAIL_WHEN_NO_HOST
1.8 millert 400: def_flag(I_MAIL_NO_HOST) = TRUE;
1.1 millert 401: #endif
402: #ifdef SEND_MAIL_WHEN_NOT_OK
1.8 millert 403: def_flag(I_MAIL_NO_PERMS) = TRUE;
1.1 millert 404: #endif
405: #ifdef USE_TTY_TICKETS
406: def_flag(I_TTY_TICKETS) = TRUE;
407: #endif
408: #ifndef NO_LECTURE
409: def_flag(I_LECTURE) = TRUE;
410: #endif
411: #ifndef NO_AUTHENTICATION
412: def_flag(I_AUTHENTICATE) = TRUE;
413: #endif
414: #ifndef NO_ROOT_SUDO
415: def_flag(I_ROOT_SUDO) = TRUE;
416: #endif
417: #ifdef HOST_IN_LOG
418: def_flag(I_LOG_HOST) = TRUE;
419: #endif
1.3 millert 420: #ifdef SHELL_IF_NO_ARGS
421: def_flag(I_SHELL_NOARGS) = TRUE;
422: #endif
1.1 millert 423: #ifdef SHELL_SETS_HOME
424: def_flag(I_SET_HOME) = TRUE;
425: #endif
426: #ifndef DONT_LEAK_PATH_INFO
427: def_flag(I_PATH_INFO) = TRUE;
428: #endif
429: #ifdef FQDN
430: def_flag(I_FQDN) = TRUE;
431: #endif
432: #ifdef USE_INSULTS
433: def_flag(I_INSULTS) = TRUE;
434: #endif
1.4 millert 435: #ifdef ENV_EDITOR
436: def_flag(I_ENV_EDITOR) = TRUE;
437: #endif
1.8 millert 438: def_flag(I_SET_LOGNAME) = TRUE;
1.1 millert 439:
440: /* Syslog options need special care since they both strings and ints */
441: #if (LOGGING & SLOG_SYSLOG)
1.8 millert 442: (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG], TRUE);
443: (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI],
444: TRUE);
445: (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI],
446: TRUE);
1.1 millert 447: #endif
448:
1.3 millert 449: /* Password flags also have a string and integer component. */
1.8 millert 450: (void) store_pwflag("any", &sudo_defs_table[I_LISTPW], TRUE);
451: (void) store_pwflag("all", &sudo_defs_table[I_VERIFYPW], TRUE);
1.3 millert 452:
1.1 millert 453: /* Then initialize the int-like things. */
454: #ifdef SUDO_UMASK
455: def_mode(I_UMASK) = SUDO_UMASK;
456: #else
457: def_mode(I_UMASK) = 0777;
458: #endif
1.8 millert 459: def_ival(I_LOGLINELEN) = MAXLOGFILELEN;
460: def_ival(I_TIMESTAMP_TIMEOUT) = TIMEOUT;
461: def_ival(I_PASSWD_TIMEOUT) = PASSWORD_TIMEOUT;
462: def_ival(I_PASSWD_TRIES) = TRIES_FOR_PASSWORD;
1.1 millert 463:
1.8 millert 464: /* Now do the strings */
1.1 millert 465: def_str(I_MAILTO) = estrdup(MAILTO);
466: def_str(I_MAILSUB) = estrdup(MAILSUBJECT);
1.8 millert 467: def_str(I_BADPASS_MESSAGE) = estrdup(INCORRECT_PASSWORD);
1.1 millert 468: def_str(I_TIMESTAMPDIR) = estrdup(_PATH_SUDO_TIMEDIR);
469: def_str(I_PASSPROMPT) = estrdup(PASSPROMPT);
1.8 millert 470: def_str(I_RUNAS_DEFAULT) = estrdup(RUNAS_DEFAULT);
471: #ifdef _PATH_SUDO_SENDMAIL
472: def_str(I_MAILERPATH) = estrdup(_PATH_SUDO_SENDMAIL);
1.1 millert 473: def_str(I_MAILERFLAGS) = estrdup("-t");
474: #endif
475: #if (LOGGING & SLOG_FILE)
476: def_str(I_LOGFILE) = estrdup(_PATH_SUDO_LOGFILE);
477: #endif
478: #ifdef EXEMPTGROUP
1.8 millert 479: def_str(I_EXEMPT_GROUP) = estrdup(EXEMPTGROUP);
1.1 millert 480: #endif
1.4 millert 481: def_str(I_EDITOR) = estrdup(EDITOR);
1.1 millert 482:
1.8 millert 483: /* Finally do the lists (currently just environment tables). */
484: init_envtables();
485:
1.1 millert 486: /*
487: * The following depend on the above values.
488: * We use a pointer to the string so that if its
489: * value changes we get the change.
490: */
491: if (user_runas == NULL)
1.8 millert 492: user_runas = &def_str(I_RUNAS_DEFAULT);
1.1 millert 493:
494: firsttime = 0;
495: }
496:
497: static int
498: store_int(val, def, op)
499: char *val;
500: struct sudo_defs_types *def;
501: int op;
502: {
503: char *endp;
504: long l;
505:
506: if (op == FALSE) {
507: def->sd_un.ival = 0;
508: } else {
509: l = strtol(val, &endp, 10);
1.8 millert 510: if (*endp != '\0')
511: return(FALSE);
512: /* XXX - should check against INT_MAX */
513: def->sd_un.ival = (unsigned int)l;
514: }
515: return(TRUE);
516: }
517:
518: static int
519: store_uint(val, def, op)
520: char *val;
521: struct sudo_defs_types *def;
522: int op;
523: {
524: char *endp;
525: long l;
526:
527: if (op == FALSE) {
528: def->sd_un.ival = 0;
529: } else {
530: l = strtol(val, &endp, 10);
1.1 millert 531: if (*endp != '\0' || l < 0)
532: return(FALSE);
533: /* XXX - should check against INT_MAX */
534: def->sd_un.ival = (unsigned int)l;
535: }
536: return(TRUE);
537: }
538:
539: static int
540: store_str(val, def, op)
541: char *val;
542: struct sudo_defs_types *def;
543: int op;
544: {
545:
546: if (def->sd_un.str)
547: free(def->sd_un.str);
548: if (op == FALSE)
549: def->sd_un.str = NULL;
550: else
551: def->sd_un.str = estrdup(val);
552: return(TRUE);
553: }
554:
555: static int
1.8 millert 556: store_list(str, def, op)
557: char *str;
558: struct sudo_defs_types *def;
559: int op;
560: {
561: char *start, *end;
562:
563: /* Remove all old members. */
564: if (op == FALSE || op == TRUE)
565: list_op(NULL, 0, def, freeall);
566:
567: /* Split str into multiple space-separated words and act on each one. */
568: if (op != FALSE) {
569: end = str;
570: do {
571: /* Remove leading blanks, if nothing but blanks we are done. */
572: for (start = end; isblank(*start); start++)
573: ;
574: if (*start == '\0')
575: break;
576:
577: /* Find end position and perform operation. */
578: for (end = start; *end && !isblank(*end); end++)
579: ;
580: list_op(start, end - start, def, op == '-' ? delete : add);
581: } while (*end++ != '\0');
582: }
583: return(TRUE);
584: }
585:
586: static int
1.1 millert 587: store_syslogfac(val, def, op)
588: char *val;
589: struct sudo_defs_types *def;
590: int op;
591: {
592: struct strmap *fac;
593:
594: if (op == FALSE) {
1.3 millert 595: if (def->sd_un.str) {
596: free(def->sd_un.str);
597: def->sd_un.str = NULL;
598: }
1.1 millert 599: return(TRUE);
600: }
601: #ifdef LOG_NFACILITIES
602: if (!val)
603: return(FALSE);
604: for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
605: ;
606: if (fac->name == NULL)
607: return(FALSE); /* not found */
608:
609: /* Store both name and number. */
1.8 millert 610: if (def->sd_un.str)
1.1 millert 611: free(def->sd_un.str);
612: def->sd_un.str = estrdup(fac->name);
613: sudo_defs_table[I_LOGFAC].sd_un.ival = fac->num;
614: #else
1.8 millert 615: if (def->sd_un.str)
1.1 millert 616: free(def->sd_un.str);
617: def->sd_un.str = estrdup("default");
618: #endif /* LOG_NFACILITIES */
619: return(TRUE);
620: }
621:
622: static int
623: store_syslogpri(val, def, op)
624: char *val;
625: struct sudo_defs_types *def;
626: int op;
627: {
628: struct strmap *pri;
629: struct sudo_defs_types *idef;
630:
631: if (op == FALSE || !val)
632: return(FALSE);
1.8 millert 633: if (def == &sudo_defs_table[I_SYSLOG_GOODPRI])
1.1 millert 634: idef = &sudo_defs_table[I_GOODPRI];
1.8 millert 635: else if (def == &sudo_defs_table[I_SYSLOG_BADPRI])
1.1 millert 636: idef = &sudo_defs_table[I_BADPRI];
637: else
638: return(FALSE);
639:
640: for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
641: ;
642: if (pri->name == NULL)
643: return(FALSE); /* not found */
644:
645: /* Store both name and number. */
646: if (def->sd_un.str)
647: free(def->sd_un.str);
648: def->sd_un.str = estrdup(pri->name);
649: idef->sd_un.ival = pri->num;
650: return(TRUE);
651: }
652:
653: static int
654: store_mode(val, def, op)
655: char *val;
656: struct sudo_defs_types *def;
657: int op;
658: {
659: char *endp;
660: long l;
661:
662: if (op == FALSE) {
663: def->sd_un.mode = (mode_t)0777;
664: } else {
665: l = strtol(val, &endp, 8);
1.5 millert 666: if (*endp != '\0' || l < 0 || l > 0777)
1.1 millert 667: return(FALSE);
668: def->sd_un.mode = (mode_t)l;
669: }
1.3 millert 670: return(TRUE);
671: }
672:
673: static int
674: store_pwflag(val, def, op)
675: char *val;
676: struct sudo_defs_types *def;
677: int op;
678: {
679: int isub, flags;
680:
681: if (strcmp(def->name, "verifypw") == 0)
1.8 millert 682: isub = I_VERIFYPW_I;
1.3 millert 683: else
1.8 millert 684: isub = I_LISTPW_I;
1.3 millert 685:
686: /* Handle !foo. */
687: if (op == FALSE) {
688: if (def->sd_un.str) {
689: free(def->sd_un.str);
690: def->sd_un.str = NULL;
691: }
692: def->sd_un.str = estrdup("never");
693: sudo_defs_table[isub].sd_un.ival = PWCHECK_NEVER;
694: return(TRUE);
695: }
696: if (!val)
697: return(FALSE);
698:
699: /* Convert strings to integer values. */
700: if (strcmp(val, "all") == 0)
701: flags = PWCHECK_ALL;
702: else if (strcmp(val, "any") == 0)
703: flags = PWCHECK_ANY;
704: else if (strcmp(val, "never") == 0)
705: flags = PWCHECK_NEVER;
706: else if (strcmp(val, "always") == 0)
707: flags = PWCHECK_ALWAYS;
708: else
709: return(FALSE);
710:
711: /* Store both name and number. */
712: if (def->sd_un.str)
713: free(def->sd_un.str);
714: def->sd_un.str = estrdup(val);
715: sudo_defs_table[isub].sd_un.ival = flags;
716:
1.1 millert 717: return(TRUE);
1.8 millert 718: }
719:
720: static void
721: list_op(val, len, def, op)
722: char *val;
723: size_t len;
724: struct sudo_defs_types *def;
725: enum list_ops op;
726: {
727: struct list_member *cur, *prev, *tmp;
728:
729: if (op == freeall) {
730: for (cur = def->sd_un.list; cur; ) {
731: tmp = cur;
732: cur = tmp->next;
733: free(tmp->value);
734: free(tmp);
735: }
736: def->sd_un.list = NULL;
737: return;
738: }
739:
740: for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) {
741: if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
742:
743: if (op == add)
744: return; /* already exists */
745:
746: /* Delete node */
747: if (prev != NULL)
748: prev->next = cur->next;
749: else
750: def->sd_un.list = cur->next;
751: free(cur->value);
752: free(cur);
753: break;
754: }
755: }
756:
757: /* Add new node to the head of the list. */
758: if (op == add) {
759: cur = emalloc(sizeof(struct list_member));
760: cur->value = emalloc(len + 1);
761: (void) memcpy(cur->value, val, len);
762: cur->value[len] = '\0';
763: cur->next = def->sd_un.list;
764: def->sd_un.list = cur;
765: }
1.1 millert 766: }