~ubuntu-branches/ubuntu/quantal/sudo/quantal

« back to all changes in this revision

Viewing changes to .pc/enable_badpass.patch/plugins/sudoers/defaults.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2011-11-20 12:07:45 UTC
  • mfrom: (1.3.17 sid)
  • Revision ID: package-import@ubuntu.com-20111120120745-o3qpklobmygytndc
Tags: 1.8.3p1-1ubuntu1
* Merge from debian/testing, remaining changes:
  - debian/patches/keep_home_by_default.patch:
    + Set HOME in initial_keepenv_table. (rebased for 1.8.3p1)
  - debian/patches/enable_badpass.patch: turn on "mail_badpass" by default:
    + attempting sudo without knowing a login password is as bad as not
      being listed in the sudoers file, especially if getting the password
      wrong means doing the access-check-email-notification never happens
      (rebased for 1.8.3p1)
  - debian/rules:
    + compile with --without-lecture --with-tty-tickets (Ubuntu specific)
    + install man/man8/sudo_root.8 (Ubuntu specific)
    + install apport hooks
    + The ubuntu-sudo-as-admin-successful.patch was taken upstream by
      Debian however it requires a --enable-admin-flag configure flag to
      actually enable it.
  - debian/sudoers: 
    + grant admin group sudo access
  - debian/sudo-ldap.dirs, debian/sudo.dirs: 
    + add usr/share/apport/package-hooks
  - debian/sudo.preinst:
    + avoid conffile prompt by checking for known default /etc/sudoers
      and if found installing the correct default /etc/sudoers file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}