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