Annotation of src/usr.bin/sudo/defaults.c, Revision 1.15
1.1 millert 1: /*
1.14 millert 2: * Copyright (c) 1999-2005, 2007-2008
3: * Todd C. Miller <Todd.Miller@courtesan.com>
1.1 millert 4: *
1.11 millert 5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
1.1 millert 8: *
1.11 millert 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.10 millert 16: *
17: * Sponsored in part by the Defense Advanced Research Projects
18: * Agency (DARPA) and Air Force Research Laboratory, Air Force
19: * Materiel Command, USAF, under agreement number F39502-99-1-0512.
1.1 millert 20: */
21:
1.13 millert 22: #include <config.h>
1.1 millert 23:
1.8 millert 24: #include <sys/types.h>
25: #include <sys/param.h>
1.1 millert 26: #include <stdio.h>
27: #ifdef STDC_HEADERS
1.8 millert 28: # include <stdlib.h>
29: # include <stddef.h>
30: #else
31: # ifdef HAVE_STDLIB_H
32: # include <stdlib.h>
33: # endif
1.1 millert 34: #endif /* STDC_HEADERS */
1.8 millert 35: #ifdef HAVE_STRING_H
36: # include <string.h>
37: #else
38: # ifdef HAVE_STRINGS_H
39: # include <strings.h>
40: # endif
41: #endif /* HAVE_STRING_H */
42: # ifdef HAVE_UNISTD_H
1.1 millert 43: #include <unistd.h>
44: #endif /* HAVE_UNISTD_H */
1.11 millert 45: #include <pwd.h>
1.8 millert 46: #include <ctype.h>
1.1 millert 47:
48: #include "sudo.h"
1.14 millert 49: #include "parse.h"
50: #include <gram.h>
1.1 millert 51:
52: /*
53: * For converting between syslog numbers and strings.
54: */
55: struct strmap {
56: char *name;
57: int num;
58: };
59:
60: #ifdef LOG_NFACILITIES
61: static struct strmap facilities[] = {
62: #ifdef LOG_AUTHPRIV
63: { "authpriv", LOG_AUTHPRIV },
64: #endif
65: { "auth", LOG_AUTH },
66: { "daemon", LOG_DAEMON },
67: { "user", LOG_USER },
68: { "local0", LOG_LOCAL0 },
69: { "local1", LOG_LOCAL1 },
70: { "local2", LOG_LOCAL2 },
71: { "local3", LOG_LOCAL3 },
72: { "local4", LOG_LOCAL4 },
73: { "local5", LOG_LOCAL5 },
74: { "local6", LOG_LOCAL6 },
75: { "local7", LOG_LOCAL7 },
76: { NULL, -1 }
77: };
78: #endif /* LOG_NFACILITIES */
79:
80: static struct strmap priorities[] = {
81: { "alert", LOG_ALERT },
82: { "crit", LOG_CRIT },
83: { "debug", LOG_DEBUG },
84: { "emerg", LOG_EMERG },
85: { "err", LOG_ERR },
86: { "info", LOG_INFO },
87: { "notice", LOG_NOTICE },
88: { "warning", LOG_WARNING },
89: { NULL, -1 }
90: };
91:
92: /*
93: * Local prototypes.
94: */
95: static int store_int __P((char *, struct sudo_defs_types *, int));
1.11 millert 96: static int store_list __P((char *, struct sudo_defs_types *, int));
97: static int store_mode __P((char *, struct sudo_defs_types *, int));
1.1 millert 98: static int store_str __P((char *, struct sudo_defs_types *, int));
99: static int store_syslogfac __P((char *, struct sudo_defs_types *, int));
100: static int store_syslogpri __P((char *, struct sudo_defs_types *, int));
1.11 millert 101: static int store_tuple __P((char *, struct sudo_defs_types *, int));
102: static int store_uint __P((char *, struct sudo_defs_types *, int));
1.8 millert 103: static void list_op __P((char *, size_t, struct sudo_defs_types *, enum list_ops));
1.11 millert 104: static const char *logfac2str __P((int));
105: static const char *logpri2str __P((int));
1.1 millert 106:
107: /*
108: * Table describing compile-time and run-time options.
109: */
1.8 millert 110: #include <def_data.c>
1.1 millert 111:
112: /*
113: * Print version and configure info.
114: */
115: void
116: dump_defaults()
117: {
118: struct sudo_defs_types *cur;
1.8 millert 119: struct list_member *item;
1.11 millert 120: struct def_values *def;
1.1 millert 121:
122: for (cur = sudo_defs_table; cur->name; cur++) {
123: if (cur->desc) {
124: switch (cur->type & T_MASK) {
125: case T_FLAG:
126: if (cur->sd_un.flag)
127: puts(cur->desc);
128: break;
129: case T_STR:
1.11 millert 130: if (cur->sd_un.str) {
131: (void) printf(cur->desc, cur->sd_un.str);
132: putchar('\n');
133: }
134: break;
1.1 millert 135: case T_LOGFAC:
1.11 millert 136: if (cur->sd_un.ival) {
137: (void) printf(cur->desc, logfac2str(cur->sd_un.ival));
138: putchar('\n');
139: }
140: break;
1.1 millert 141: case T_LOGPRI:
1.11 millert 142: if (cur->sd_un.ival) {
143: (void) printf(cur->desc, logpri2str(cur->sd_un.ival));
1.1 millert 144: putchar('\n');
145: }
146: break;
1.8 millert 147: case T_UINT:
1.1 millert 148: case T_INT:
149: (void) printf(cur->desc, cur->sd_un.ival);
150: putchar('\n');
151: break;
152: case T_MODE:
153: (void) printf(cur->desc, cur->sd_un.mode);
154: putchar('\n');
155: break;
1.8 millert 156: case T_LIST:
157: if (cur->sd_un.list) {
158: puts(cur->desc);
159: for (item = cur->sd_un.list; item; item = item->next)
160: printf("\t%s\n", item->value);
161: }
162: break;
1.11 millert 163: case T_TUPLE:
164: for (def = cur->values; def->sval; def++) {
165: if (cur->sd_un.ival == def->ival) {
166: (void) printf(cur->desc, def->sval);
167: break;
168: }
169: }
170: putchar('\n');
171: break;
1.1 millert 172: }
173: }
174: }
175: }
176:
177: /*
178: * List each option along with its description.
179: */
180: void
181: list_options()
182: {
183: struct sudo_defs_types *cur;
184: char *p;
185:
186: (void) puts("Available options in a sudoers ``Defaults'' line:\n");
187: for (cur = sudo_defs_table; cur->name; cur++) {
188: if (cur->name && cur->desc) {
189: switch (cur->type & T_MASK) {
190: case T_FLAG:
191: (void) printf("%s: %s\n", cur->name, cur->desc);
192: break;
193: default:
194: p = strrchr(cur->desc, ':');
195: if (p)
1.8 millert 196: (void) printf("%s: %.*s\n", cur->name,
197: (int) (p - cur->desc), cur->desc);
1.1 millert 198: else
199: (void) printf("%s: %s\n", cur->name, cur->desc);
200: break;
201: }
202: }
203: }
204: }
205:
206: /*
207: * Sets/clears an entry in the defaults structure
208: * If a variable that takes a value is used in a boolean
209: * context with op == 0, disable that variable.
210: * Eg. you may want to turn off logging to a file for some hosts.
211: * This is only meaningful for variables that are *optional*.
212: */
213: int
214: set_default(var, val, op)
215: char *var;
216: char *val;
217: int op; /* TRUE or FALSE */
218: {
219: struct sudo_defs_types *cur;
1.2 millert 220: int num;
1.1 millert 221:
1.2 millert 222: for (cur = sudo_defs_table, num = 0; cur->name; cur++, num++) {
1.1 millert 223: if (strcmp(var, cur->name) == 0)
224: break;
225: }
226: if (!cur->name) {
1.14 millert 227: warningx("unknown defaults entry `%s'", var);
1.1 millert 228: return(FALSE);
229: }
230:
231: switch (cur->type & T_MASK) {
232: case T_LOGFAC:
233: if (!store_syslogfac(val, cur, op)) {
234: if (val)
1.14 millert 235: warningx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 236: else
1.14 millert 237: warningx("no value specified for `%s'", var);
1.1 millert 238: return(FALSE);
239: }
240: break;
241: case T_LOGPRI:
242: if (!store_syslogpri(val, cur, op)) {
243: if (val)
1.14 millert 244: warningx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 245: else
1.14 millert 246: warningx("no value specified for `%s'", var);
1.1 millert 247: return(FALSE);
248: }
249: break;
250: case T_STR:
251: if (!val) {
252: /* Check for bogus boolean usage or lack of a value. */
1.11 millert 253: if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.14 millert 254: warningx("no value specified for `%s'", var);
1.1 millert 255: return(FALSE);
256: }
257: }
1.11 millert 258: if (ISSET(cur->type, T_PATH) && val && *val != '/') {
1.14 millert 259: warningx("values for `%s' must start with a '/'", var);
1.1 millert 260: return(FALSE);
261: }
262: if (!store_str(val, cur, op)) {
1.14 millert 263: warningx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 264: return(FALSE);
265: }
266: break;
267: case T_INT:
268: if (!val) {
269: /* Check for bogus boolean usage or lack of a value. */
1.11 millert 270: if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.14 millert 271: warningx("no value specified for `%s'", var);
1.1 millert 272: return(FALSE);
273: }
274: }
275: if (!store_int(val, cur, op)) {
1.14 millert 276: warningx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 277: return(FALSE);
278: }
279: break;
1.8 millert 280: case T_UINT:
281: if (!val) {
282: /* Check for bogus boolean usage or lack of a value. */
1.11 millert 283: if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.14 millert 284: warningx("no value specified for `%s'", var);
1.8 millert 285: return(FALSE);
286: }
287: }
288: if (!store_uint(val, cur, op)) {
1.14 millert 289: warningx("value `%s' is invalid for option `%s'", val, var);
1.8 millert 290: return(FALSE);
291: }
292: break;
1.1 millert 293: case T_MODE:
294: if (!val) {
295: /* Check for bogus boolean usage or lack of a value. */
1.11 millert 296: if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.14 millert 297: warningx("no value specified for `%s'", var);
1.1 millert 298: return(FALSE);
299: }
300: }
301: if (!store_mode(val, cur, op)) {
1.14 millert 302: warningx("value `%s' is invalid for option `%s'", val, var);
1.1 millert 303: return(FALSE);
304: }
305: break;
306: case T_FLAG:
307: if (val) {
1.14 millert 308: warningx("option `%s' does not take a value", var);
1.1 millert 309: return(FALSE);
310: }
311: cur->sd_un.flag = op;
1.2 millert 312:
313: /* Special action for I_FQDN. Move to own switch if we get more */
314: if (num == I_FQDN && op)
315: set_fqdn();
1.1 millert 316: break;
1.8 millert 317: case T_LIST:
318: if (!val) {
319: /* Check for bogus boolean usage or lack of a value. */
1.11 millert 320: if (!ISSET(cur->type, T_BOOL) || op != FALSE) {
1.14 millert 321: warningx("no value specified for `%s'", var);
1.8 millert 322: return(FALSE);
323: }
324: }
325: if (!store_list(val, cur, op)) {
1.14 millert 326: warningx("value `%s' is invalid for option `%s'", val, var);
1.8 millert 327: return(FALSE);
328: }
1.11 millert 329: break;
330: case T_TUPLE:
1.12 millert 331: if (!val && !ISSET(cur->type, T_BOOL)) {
1.14 millert 332: warningx("no value specified for `%s'", var);
1.12 millert 333: return(FALSE);
1.11 millert 334: }
335: if (!store_tuple(val, cur, op)) {
1.14 millert 336: warningx("value `%s' is invalid for option `%s'", val, var);
1.11 millert 337: return(FALSE);
338: }
339: break;
1.1 millert 340: }
341:
342: return(TRUE);
343: }
344:
345: /*
346: * Set default options to compiled-in values.
347: * Any of these may be overridden at runtime by a "Defaults" file.
348: */
349: void
350: init_defaults()
351: {
352: static int firsttime = 1;
353: struct sudo_defs_types *def;
354:
1.14 millert 355: /* Clear any old settings. */
1.1 millert 356: if (!firsttime) {
1.14 millert 357: for (def = sudo_defs_table; def->name; def++) {
1.1 millert 358: switch (def->type & T_MASK) {
359: case T_STR:
1.13 millert 360: efree(def->sd_un.str);
361: def->sd_un.str = NULL;
1.1 millert 362: break;
1.8 millert 363: case T_LIST:
364: list_op(NULL, 0, def, freeall);
365: break;
1.1 millert 366: }
1.14 millert 367: zero_bytes(&def->sd_un, sizeof(def->sd_un));
368: }
1.1 millert 369: }
370:
371: /* First initialize the flags. */
372: #ifdef LONG_OTP_PROMPT
1.11 millert 373: def_long_otp_prompt = TRUE;
1.1 millert 374: #endif
375: #ifdef IGNORE_DOT_PATH
1.11 millert 376: def_ignore_dot = TRUE;
1.1 millert 377: #endif
378: #ifdef ALWAYS_SEND_MAIL
1.11 millert 379: def_mail_always = TRUE;
1.1 millert 380: #endif
381: #ifdef SEND_MAIL_WHEN_NO_USER
1.11 millert 382: def_mail_no_user = TRUE;
1.1 millert 383: #endif
384: #ifdef SEND_MAIL_WHEN_NO_HOST
1.11 millert 385: def_mail_no_host = TRUE;
1.1 millert 386: #endif
387: #ifdef SEND_MAIL_WHEN_NOT_OK
1.11 millert 388: def_mail_no_perms = TRUE;
1.1 millert 389: #endif
390: #ifdef USE_TTY_TICKETS
1.11 millert 391: def_tty_tickets = TRUE;
1.1 millert 392: #endif
393: #ifndef NO_LECTURE
1.11 millert 394: def_lecture = once;
1.1 millert 395: #endif
396: #ifndef NO_AUTHENTICATION
1.11 millert 397: def_authenticate = TRUE;
1.1 millert 398: #endif
399: #ifndef NO_ROOT_SUDO
1.11 millert 400: def_root_sudo = TRUE;
1.1 millert 401: #endif
402: #ifdef HOST_IN_LOG
1.11 millert 403: def_log_host = TRUE;
1.1 millert 404: #endif
1.3 millert 405: #ifdef SHELL_IF_NO_ARGS
1.11 millert 406: def_shell_noargs = TRUE;
1.3 millert 407: #endif
1.1 millert 408: #ifdef SHELL_SETS_HOME
1.11 millert 409: def_set_home = TRUE;
1.1 millert 410: #endif
411: #ifndef DONT_LEAK_PATH_INFO
1.11 millert 412: def_path_info = TRUE;
1.1 millert 413: #endif
414: #ifdef FQDN
1.11 millert 415: def_fqdn = TRUE;
1.1 millert 416: #endif
417: #ifdef USE_INSULTS
1.11 millert 418: def_insults = TRUE;
1.1 millert 419: #endif
1.4 millert 420: #ifdef ENV_EDITOR
1.11 millert 421: def_env_editor = TRUE;
1.4 millert 422: #endif
1.14 millert 423: #ifdef _PATH_SUDO_ASKPASS
424: def_askpass = estrdup(_PATH_SUDO_ASKPASS);
425: #endif
426: def_sudoers_locale = estrdup("C");
1.13 millert 427: def_env_reset = TRUE;
1.11 millert 428: def_set_logname = TRUE;
1.14 millert 429: def_closefrom = STDERR_FILENO + 1;
1.1 millert 430:
431: /* Syslog options need special care since they both strings and ints */
432: #if (LOGGING & SLOG_SYSLOG)
1.8 millert 433: (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG], TRUE);
434: (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI],
435: TRUE);
436: (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI],
437: TRUE);
1.1 millert 438: #endif
439:
1.3 millert 440: /* Password flags also have a string and integer component. */
1.11 millert 441: (void) store_tuple("any", &sudo_defs_table[I_LISTPW], TRUE);
442: (void) store_tuple("all", &sudo_defs_table[I_VERIFYPW], TRUE);
1.3 millert 443:
1.1 millert 444: /* Then initialize the int-like things. */
445: #ifdef SUDO_UMASK
1.11 millert 446: def_umask = SUDO_UMASK;
1.1 millert 447: #else
1.11 millert 448: def_umask = 0777;
1.1 millert 449: #endif
1.11 millert 450: def_loglinelen = MAXLOGFILELEN;
451: def_timestamp_timeout = TIMEOUT;
452: def_passwd_timeout = PASSWORD_TIMEOUT;
453: def_passwd_tries = TRIES_FOR_PASSWORD;
1.1 millert 454:
1.8 millert 455: /* Now do the strings */
1.11 millert 456: def_mailto = estrdup(MAILTO);
457: def_mailsub = estrdup(MAILSUBJECT);
458: def_badpass_message = estrdup(INCORRECT_PASSWORD);
459: def_timestampdir = estrdup(_PATH_SUDO_TIMEDIR);
460: def_passprompt = estrdup(PASSPROMPT);
461: def_runas_default = estrdup(RUNAS_DEFAULT);
1.8 millert 462: #ifdef _PATH_SUDO_SENDMAIL
1.11 millert 463: def_mailerpath = estrdup(_PATH_SUDO_SENDMAIL);
464: def_mailerflags = estrdup("-t");
1.1 millert 465: #endif
466: #if (LOGGING & SLOG_FILE)
1.11 millert 467: def_logfile = estrdup(_PATH_SUDO_LOGFILE);
1.1 millert 468: #endif
469: #ifdef EXEMPTGROUP
1.11 millert 470: def_exempt_group = estrdup(EXEMPTGROUP);
471: #endif
1.14 millert 472: #ifdef SECURE_PATH
473: def_secure_path = estrdup(SECURE_PATH);
474: #endif
1.11 millert 475: def_editor = estrdup(EDITOR);
476: #ifdef _PATH_SUDO_NOEXEC
477: def_noexec_file = estrdup(_PATH_SUDO_NOEXEC);
1.1 millert 478: #endif
479:
1.8 millert 480: /* Finally do the lists (currently just environment tables). */
481: init_envtables();
482:
1.14 millert 483: firsttime = 0;
484: }
485:
486: /*
487: * Update the defaults based on what was set by sudoers.
488: * Pass in a an OR'd list of which default types to update.
489: */
490: int
491: update_defaults(what)
492: int what;
493: {
494: struct defaults *def;
1.1 millert 495:
1.14 millert 496: tq_foreach_fwd(&defaults, def) {
497: switch (def->type) {
498: case DEFAULTS:
499: if (ISSET(what, SETDEF_GENERIC) &&
500: !set_default(def->var, def->val, def->op))
501: return(FALSE);
502: break;
503: case DEFAULTS_USER:
504: if (ISSET(what, SETDEF_USER) &&
505: userlist_matches(sudo_user.pw, &def->binding) == ALLOW &&
506: !set_default(def->var, def->val, def->op))
507: return(FALSE);
508: break;
509: case DEFAULTS_RUNAS:
510: if (ISSET(what, SETDEF_RUNAS) &&
511: runaslist_matches(&def->binding, NULL) == ALLOW &&
512: !set_default(def->var, def->val, def->op))
513: return(FALSE);
514: break;
515: case DEFAULTS_HOST:
516: if (ISSET(what, SETDEF_HOST) &&
517: hostlist_matches(&def->binding) == ALLOW &&
518: !set_default(def->var, def->val, def->op))
519: return(FALSE);
520: break;
521: case DEFAULTS_CMND:
522: if (ISSET(what, SETDEF_CMND) &&
523: cmndlist_matches(&def->binding) == ALLOW &&
524: !set_default(def->var, def->val, def->op))
525: return(FALSE);
526: break;
527: }
528: }
529: return(TRUE);
1.1 millert 530: }
531:
532: static int
533: store_int(val, def, op)
534: char *val;
535: struct sudo_defs_types *def;
536: int op;
537: {
538: char *endp;
539: long l;
540:
541: if (op == FALSE) {
542: def->sd_un.ival = 0;
543: } else {
544: l = strtol(val, &endp, 10);
1.8 millert 545: if (*endp != '\0')
546: return(FALSE);
547: /* XXX - should check against INT_MAX */
548: def->sd_un.ival = (unsigned int)l;
549: }
1.11 millert 550: if (def->callback)
551: return(def->callback(val));
1.8 millert 552: return(TRUE);
553: }
554:
555: static int
556: store_uint(val, def, op)
557: char *val;
558: struct sudo_defs_types *def;
559: int op;
560: {
561: char *endp;
562: long l;
563:
564: if (op == FALSE) {
565: def->sd_un.ival = 0;
566: } else {
567: l = strtol(val, &endp, 10);
1.1 millert 568: if (*endp != '\0' || l < 0)
569: return(FALSE);
570: /* XXX - should check against INT_MAX */
571: def->sd_un.ival = (unsigned int)l;
572: }
1.11 millert 573: if (def->callback)
574: return(def->callback(val));
575: return(TRUE);
576: }
577:
578: static int
579: store_tuple(val, def, op)
580: char *val;
581: struct sudo_defs_types *def;
582: int op;
583: {
584: struct def_values *v;
585:
586: /*
587: * Since enums are really just ints we store the value as an ival.
588: * In the future, there may be multiple enums for different tuple
589: * types we want to avoid and special knowledge of the tuple type.
590: * This does assume that the first entry in the tuple enum will
591: * be the equivalent to a boolean "false".
592: */
1.12 millert 593: if (!val) {
594: def->sd_un.ival = (op == FALSE) ? 0 : 1;
1.11 millert 595: } else {
1.12 millert 596: for (v = def->values; v->sval != NULL; v++) {
1.11 millert 597: if (strcmp(v->sval, val) == 0) {
598: def->sd_un.ival = v->ival;
599: break;
600: }
601: }
1.12 millert 602: if (v->sval == NULL)
1.11 millert 603: return(FALSE);
604: }
605: if (def->callback)
606: return(def->callback(val));
1.1 millert 607: return(TRUE);
608: }
609:
610: static int
611: store_str(val, def, op)
612: char *val;
613: struct sudo_defs_types *def;
614: int op;
615: {
616:
1.13 millert 617: efree(def->sd_un.str);
1.1 millert 618: if (op == FALSE)
619: def->sd_un.str = NULL;
620: else
621: def->sd_un.str = estrdup(val);
1.11 millert 622: if (def->callback)
623: return(def->callback(val));
1.1 millert 624: return(TRUE);
625: }
626:
627: static int
1.8 millert 628: store_list(str, def, op)
629: char *str;
630: struct sudo_defs_types *def;
631: int op;
632: {
633: char *start, *end;
634:
635: /* Remove all old members. */
636: if (op == FALSE || op == TRUE)
637: list_op(NULL, 0, def, freeall);
638:
639: /* Split str into multiple space-separated words and act on each one. */
640: if (op != FALSE) {
641: end = str;
642: do {
643: /* Remove leading blanks, if nothing but blanks we are done. */
644: for (start = end; isblank(*start); start++)
645: ;
646: if (*start == '\0')
647: break;
648:
649: /* Find end position and perform operation. */
1.11 millert 650: for (end = start; *end && !isblank(*end); end++)
1.8 millert 651: ;
652: list_op(start, end - start, def, op == '-' ? delete : add);
653: } while (*end++ != '\0');
654: }
655: return(TRUE);
656: }
657:
658: static int
1.1 millert 659: store_syslogfac(val, def, op)
660: char *val;
661: struct sudo_defs_types *def;
662: int op;
663: {
664: struct strmap *fac;
665:
666: if (op == FALSE) {
1.11 millert 667: def->sd_un.ival = FALSE;
1.1 millert 668: return(TRUE);
669: }
670: #ifdef LOG_NFACILITIES
671: if (!val)
672: return(FALSE);
673: for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
674: ;
675: if (fac->name == NULL)
676: return(FALSE); /* not found */
677:
1.11 millert 678: def->sd_un.ival = fac->num;
1.1 millert 679: #else
1.11 millert 680: def->sd_un.ival = -1;
1.1 millert 681: #endif /* LOG_NFACILITIES */
682: return(TRUE);
683: }
684:
1.11 millert 685: static const char *
686: logfac2str(n)
687: int n;
688: {
689: #ifdef LOG_NFACILITIES
690: struct strmap *fac;
691:
692: for (fac = facilities; fac->name && fac->num != n; fac++)
693: ;
1.14 millert 694: return(fac->name);
1.11 millert 695: #else
1.14 millert 696: return("default");
1.11 millert 697: #endif /* LOG_NFACILITIES */
698: }
699:
1.1 millert 700: static int
701: store_syslogpri(val, def, op)
702: char *val;
703: struct sudo_defs_types *def;
704: int op;
705: {
706: struct strmap *pri;
707:
708: if (op == FALSE || !val)
709: return(FALSE);
710:
711: for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
712: ;
713: if (pri->name == NULL)
714: return(FALSE); /* not found */
715:
1.11 millert 716: def->sd_un.ival = pri->num;
1.1 millert 717: return(TRUE);
718: }
719:
1.11 millert 720: static const char *
721: logpri2str(n)
722: int n;
723: {
724: struct strmap *pri;
725:
726: for (pri = priorities; pri->name && pri->num != n; pri++)
727: ;
1.14 millert 728: return(pri->name);
1.11 millert 729: }
730:
1.1 millert 731: static int
732: store_mode(val, def, op)
733: char *val;
734: struct sudo_defs_types *def;
735: int op;
736: {
737: char *endp;
738: long l;
739:
740: if (op == FALSE) {
741: def->sd_un.mode = (mode_t)0777;
742: } else {
743: l = strtol(val, &endp, 8);
1.5 millert 744: if (*endp != '\0' || l < 0 || l > 0777)
1.1 millert 745: return(FALSE);
746: def->sd_un.mode = (mode_t)l;
747: }
1.11 millert 748: if (def->callback)
749: return(def->callback(val));
1.1 millert 750: return(TRUE);
1.8 millert 751: }
752:
753: static void
754: list_op(val, len, def, op)
755: char *val;
756: size_t len;
757: struct sudo_defs_types *def;
758: enum list_ops op;
759: {
760: struct list_member *cur, *prev, *tmp;
761:
762: if (op == freeall) {
763: for (cur = def->sd_un.list; cur; ) {
764: tmp = cur;
765: cur = tmp->next;
1.13 millert 766: efree(tmp->value);
767: efree(tmp);
1.8 millert 768: }
769: def->sd_un.list = NULL;
770: return;
771: }
772:
773: for (cur = def->sd_un.list, prev = NULL; cur; prev = cur, cur = cur->next) {
774: if ((strncmp(cur->value, val, len) == 0 && cur->value[len] == '\0')) {
775:
776: if (op == add)
777: return; /* already exists */
778:
779: /* Delete node */
780: if (prev != NULL)
781: prev->next = cur->next;
782: else
783: def->sd_un.list = cur->next;
1.13 millert 784: efree(cur->value);
785: efree(cur);
1.8 millert 786: break;
787: }
788: }
789:
790: /* Add new node to the head of the list. */
791: if (op == add) {
792: cur = emalloc(sizeof(struct list_member));
793: cur->value = emalloc(len + 1);
794: (void) memcpy(cur->value, val, len);
795: cur->value[len] = '\0';
796: cur->next = def->sd_un.list;
797: def->sd_un.list = cur;
798: }
1.1 millert 799: }