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