Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/plugins/sudoers/defaults.c
1532 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 1999-2005, 2007-2023
5
* Todd C. Miller <[email protected]>
6
*
7
* Permission to use, copy, modify, and distribute this software for any
8
* purpose with or without fee is hereby granted, provided that the above
9
* copyright notice and this permission notice appear in all copies.
10
*
11
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
*
19
* Sponsored in part by the Defense Advanced Research Projects
20
* Agency (DARPA) and Air Force Research Laboratory, Air Force
21
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
22
*/
23
24
#include <config.h>
25
26
#include <sys/stat.h>
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
#include <unistd.h>
31
#include <ctype.h>
32
#include <errno.h>
33
#include <limits.h>
34
#include <syslog.h>
35
36
#include <sudoers.h>
37
#include <sudo_eventlog.h>
38
#include <sudo_iolog.h>
39
#include <gram.h>
40
41
static struct early_default early_defaults[] = {
42
{ I_IGNORE_UNKNOWN_DEFAULTS },
43
#ifdef FQDN
44
{ I_FQDN, true },
45
#else
46
{ I_FQDN },
47
#endif
48
{ I_MATCH_GROUP_BY_GID },
49
{ I_GROUP_PLUGIN },
50
{ I_RUNAS_DEFAULT },
51
{ I_SUDOERS_LOCALE },
52
{ -1 }
53
};
54
55
/*
56
* Local prototypes.
57
*/
58
static bool store_int(const char *str, struct sudo_defs_types *def);
59
static bool store_list(const char *str, struct sudo_defs_types *def, int op);
60
static bool store_mode(const char *str, struct sudo_defs_types *def);
61
static int store_str(const char *str, struct sudo_defs_types *def);
62
static bool store_syslogfac(const char *str, struct sudo_defs_types *def);
63
static bool store_syslogpri(const char *str, struct sudo_defs_types *def);
64
static bool store_timeout(const char *str, struct sudo_defs_types *def);
65
static bool store_tuple(const char *str, struct sudo_defs_types *def, int op);
66
static bool store_uint(const char *str, struct sudo_defs_types *def);
67
static bool store_timespec(const char *str, struct sudo_defs_types *def);
68
static bool store_rlimit(const char *str, struct sudo_defs_types *def);
69
static bool store_plugin(const char *str, struct sudo_defs_types *def, int op);
70
static bool list_op(const char *str, size_t, struct list_members *list, enum list_ops op);
71
static bool valid_path(const struct sudoers_context *ctx, const struct sudo_defs_types *def, const char *val, const char *file, int line, int column, bool quiet);
72
73
/*
74
* Table describing compile-time and run-time options.
75
*/
76
#include <def_data.c>
77
78
/*
79
* Print version and configure info.
80
*/
81
void
82
dump_defaults(void)
83
{
84
const struct sudo_defs_types *cur;
85
const struct list_member *item;
86
const struct def_values *def;
87
const char *desc;
88
debug_decl(dump_defaults, SUDOERS_DEBUG_DEFAULTS);
89
90
for (cur = sudo_defs_table; cur->name; cur++) {
91
if (cur->desc) {
92
desc = _(cur->desc);
93
switch (cur->type & T_MASK) {
94
case T_FLAG:
95
if (cur->sd_un.flag)
96
sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
97
break;
98
case T_STR:
99
case T_RLIMIT:
100
if (cur->sd_un.str) {
101
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.str);
102
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
103
}
104
break;
105
case T_LOGFAC:
106
if (cur->sd_un.ival) {
107
sudo_printf(SUDO_CONV_INFO_MSG, desc,
108
sudo_logfac2str(cur->sd_un.ival));
109
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
110
}
111
break;
112
case T_LOGPRI:
113
if (cur->sd_un.ival) {
114
sudo_printf(SUDO_CONV_INFO_MSG, desc,
115
sudo_logpri2str(cur->sd_un.ival));
116
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
117
}
118
break;
119
case T_INT:
120
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.ival);
121
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
122
break;
123
case T_UINT:
124
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.uival);
125
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
126
break;
127
case T_TIMESPEC: {
128
/* display timespec in minutes and 10ths of a minute */
129
const int min = cur->sd_un.tspec.tv_sec / 60;
130
int decimin =
131
(((cur->sd_un.tspec.tv_sec % 60) * 10) + 30) / 60;
132
decimin += cur->sd_un.tspec.tv_nsec / 100000000;
133
sudo_printf(SUDO_CONV_INFO_MSG, desc, min, decimin);
134
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
135
break;
136
}
137
case T_MODE:
138
sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.mode);
139
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
140
break;
141
case T_LIST:
142
if (!SLIST_EMPTY(&cur->sd_un.list)) {
143
sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
144
SLIST_FOREACH(item, &cur->sd_un.list, entries) {
145
sudo_printf(SUDO_CONV_INFO_MSG,
146
"\t%s\n", item->value);
147
}
148
}
149
break;
150
case T_TIMEOUT:
151
if (cur->sd_un.ival) {
152
sudo_printf(SUDO_CONV_INFO_MSG, desc,
153
cur->sd_un.ival);
154
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
155
}
156
break;
157
case T_TUPLE:
158
for (def = cur->values; def->sval; def++) {
159
if (cur->sd_un.tuple == def->nval) {
160
sudo_printf(SUDO_CONV_INFO_MSG, desc, def->sval);
161
break;
162
}
163
}
164
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
165
break;
166
}
167
}
168
}
169
debug_return;
170
}
171
172
static bool
173
defaults_warnx(const struct sudoers_context *ctx, const char *file, int line,
174
int column, bool quiet, const char * restrict fmt, ...)
175
{
176
va_list ap;
177
bool ret;
178
debug_decl(defaults_warnx, SUDOERS_DEBUG_DEFAULTS);
179
180
va_start(ap, fmt);
181
ret = parser_vwarnx(ctx, file, line, column, true, quiet, fmt, ap);
182
va_end(ap);
183
184
debug_return_bool(ret);
185
}
186
187
/*
188
* Find the index of the specified Defaults name in sudo_defs_table[]
189
* On success, returns the matching index or -1 on failure.
190
*/
191
static int
192
find_default(const struct sudoers_context *ctx, const char *name,
193
const char *file, int line, int column, bool quiet)
194
{
195
int i;
196
debug_decl(find_default, SUDOERS_DEBUG_DEFAULTS);
197
198
for (i = 0; sudo_defs_table[i].name != NULL; i++) {
199
if (strcmp(name, sudo_defs_table[i].name) == 0)
200
debug_return_int(i);
201
}
202
if (!def_ignore_unknown_defaults) {
203
defaults_warnx(ctx, file, line, column, quiet,
204
N_("unknown defaults entry \"%s\""), name);
205
}
206
debug_return_int(-1);
207
}
208
209
/*
210
* Parse a defaults entry, storing the parsed entry in sd_un.
211
* Returns true on success or false on failure.
212
*/
213
static bool
214
parse_default_entry(const struct sudoers_context *ctx,
215
struct sudo_defs_types *def, const char *val, int op,
216
const char *file, int line, int column, bool quiet)
217
{
218
int rc;
219
debug_decl(parse_default_entry, SUDOERS_DEBUG_DEFAULTS);
220
221
if (file == NULL)
222
file = "front-end";
223
224
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %s:%d:%d: %s=%s op=%d",
225
__func__, file, line, column, def->name, val ? val : "", op);
226
227
/*
228
* If no value specified, the boolean flag must be set for non-flags.
229
* Only flags and tuples support boolean "true".
230
*/
231
if (val == NULL) {
232
switch (def->type & T_MASK) {
233
case T_LOGFAC:
234
if (op == true) {
235
/* Use default syslog facility if none specified. */
236
val = LOGFAC;
237
}
238
break;
239
case T_FLAG:
240
break;
241
case T_TUPLE:
242
if (ISSET(def->type, T_BOOL))
243
break;
244
FALLTHROUGH;
245
default:
246
if (!ISSET(def->type, T_BOOL) || op != false) {
247
defaults_warnx(ctx, file, line, column, quiet,
248
N_("no value specified for \"%s\""), def->name);
249
debug_return_bool(false);
250
}
251
}
252
}
253
254
/* Only lists support append/remove. */
255
if ((op == '+' || op == '-') && (def->type & T_MASK) != T_LIST) {
256
defaults_warnx(ctx, file, line, column, quiet,
257
N_("invalid operator \"%c=\" for \"%s\""), op, def->name);
258
debug_return_bool(false);
259
}
260
261
switch (def->type & T_MASK) {
262
case T_LOGFAC:
263
rc = store_syslogfac(val, def);
264
break;
265
case T_LOGPRI:
266
rc = store_syslogpri(val, def);
267
break;
268
case T_STR:
269
if (val != NULL && ISSET(def->type, T_PATH|T_CHPATH)) {
270
if (!valid_path(ctx, def, val, file, line, column, quiet)) {
271
rc = -1;
272
break;
273
}
274
}
275
rc = store_str(val, def);
276
break;
277
case T_INT:
278
rc = store_int(val, def);
279
break;
280
case T_UINT:
281
rc = store_uint(val, def);
282
break;
283
case T_MODE:
284
rc = store_mode(val, def);
285
break;
286
case T_FLAG:
287
if (val != NULL) {
288
defaults_warnx(ctx, file, line, column, quiet,
289
N_("option \"%s\" does not take a value"), def->name);
290
rc = -1;
291
break;
292
}
293
def->sd_un.flag = (bool)op;
294
rc = true;
295
break;
296
case T_LIST:
297
rc = store_list(val, def, op);
298
break;
299
case T_TIMEOUT:
300
rc = store_timeout(val, def);
301
break;
302
case T_TUPLE:
303
rc = store_tuple(val, def, op);
304
break;
305
case T_TIMESPEC:
306
rc = store_timespec(val, def);
307
break;
308
case T_PLUGIN:
309
rc = store_plugin(val, def, op);
310
break;
311
case T_RLIMIT:
312
rc = store_rlimit(val, def);
313
break;
314
default:
315
defaults_warnx(ctx, file, line, column, quiet,
316
N_("invalid Defaults type 0x%x for option \"%s\""),
317
def->type, def->name);
318
rc = -1;
319
break;
320
}
321
if (rc == false) {
322
defaults_warnx(ctx, file, line, column, quiet,
323
N_("value \"%s\" is invalid for option \"%s\""), val, def->name);
324
}
325
326
debug_return_bool(rc == true);
327
}
328
329
static struct early_default *
330
is_early_default(const char *name)
331
{
332
struct early_default *early;
333
debug_decl(is_early_default, SUDOERS_DEBUG_DEFAULTS);
334
335
for (early = early_defaults; early->idx != -1; early++) {
336
if (strcmp(name, sudo_defs_table[early->idx].name) == 0)
337
debug_return_ptr(early);
338
}
339
debug_return_ptr(NULL);
340
}
341
342
static bool
343
run_callback(struct sudoers_context *ctx, const char *file, int line,
344
int column, struct sudo_defs_types *def, int op)
345
{
346
debug_decl(run_callback, SUDOERS_DEBUG_DEFAULTS);
347
348
if (def->callback == NULL)
349
debug_return_bool(true);
350
debug_return_bool(def->callback(ctx, file, line, column, &def->sd_un, op));
351
}
352
353
/*
354
* Sets/clears an entry in the defaults structure.
355
* Runs the callback if present on success.
356
*/
357
bool
358
set_default(struct sudoers_context *ctx, const char *var, const char *val,
359
int op, const char *file, int line, int column, bool quiet)
360
{
361
int idx;
362
debug_decl(set_default, SUDOERS_DEBUG_DEFAULTS);
363
364
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
365
"%s: setting Defaults %s -> %s", __func__, var, val ? val : "false");
366
367
idx = find_default(ctx, var, file, line, column, quiet);
368
if (idx != -1) {
369
/* Set parsed value in sudo_defs_table and run callback (if any). */
370
struct sudo_defs_types *def = &sudo_defs_table[idx];
371
if (parse_default_entry(ctx, def, val, op, file, line, column, quiet))
372
debug_return_bool(run_callback(ctx, file, line, column, def, op));
373
}
374
debug_return_bool(false);
375
}
376
377
/*
378
* Like set_default() but stores the matching default value
379
* and does not run callbacks.
380
*/
381
static bool
382
set_early_default(const struct sudoers_context *ctx, const char *var,
383
const char *val, int op, const char *file, int line, int column,
384
bool quiet, struct early_default *early)
385
{
386
int idx;
387
debug_decl(set_early_default, SUDOERS_DEBUG_DEFAULTS);
388
389
idx = find_default(ctx, var, file, line, column, quiet);
390
if (idx != -1) {
391
/* Set parsed value in sudo_defs_table but defer callback (if any). */
392
struct sudo_defs_types *def = &sudo_defs_table[idx];
393
if (parse_default_entry(ctx, def, val, op, file, line, column, quiet)) {
394
if (early->file != NULL)
395
sudo_rcstr_delref(early->file);
396
early->file = sudo_rcstr_addref(file);
397
early->line = line;
398
early->column = column;
399
early->run_callback = true;
400
debug_return_bool(true);
401
}
402
}
403
debug_return_bool(false);
404
}
405
406
/*
407
* Run callbacks for early defaults.
408
*/
409
static bool
410
run_early_defaults(struct sudoers_context *ctx)
411
{
412
struct early_default *early;
413
bool ret = true;
414
debug_decl(run_early_defaults, SUDOERS_DEBUG_DEFAULTS);
415
416
for (early = early_defaults; early->idx != -1; early++) {
417
if (early->run_callback) {
418
if (!run_callback(ctx, early->file, early->line, early->column,
419
&sudo_defs_table[early->idx], true))
420
ret = false;
421
early->run_callback = false;
422
}
423
}
424
debug_return_bool(ret);
425
}
426
427
static void
428
free_defs_val(int type, union sudo_defs_val *sd_un)
429
{
430
switch (type & T_MASK) {
431
case T_STR:
432
case T_RLIMIT:
433
free(sd_un->str);
434
break;
435
case T_LIST:
436
(void)list_op(NULL, 0, &sd_un->list, freeall);
437
break;
438
}
439
memset(sd_un, 0, sizeof(*sd_un));
440
}
441
442
static bool
443
init_passprompt_regex(void)
444
{
445
struct list_member *lm;
446
debug_decl(init_passprompt_regex, SUDOERS_DEBUG_DEFAULTS);
447
448
/* Add initial defaults setting. */
449
lm = calloc(1, sizeof(struct list_member));
450
if (lm == NULL || (lm->value = strdup(PASSPROMPT_REGEX)) == NULL) {
451
free(lm);
452
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
453
debug_return_bool(false);
454
}
455
SLIST_INSERT_HEAD(&def_passprompt_regex, lm, entries);
456
457
debug_return_bool(true);
458
}
459
460
/*
461
* Set default options to compiled-in values.
462
* Any of these may be overridden at runtime by a "Defaults" file.
463
*/
464
bool
465
init_defaults(void)
466
{
467
static bool firsttime = true;
468
struct sudo_defs_types *def;
469
debug_decl(init_defaults, SUDOERS_DEBUG_DEFAULTS);
470
471
/* Clear any old settings. */
472
if (!firsttime) {
473
for (def = sudo_defs_table; def->name != NULL; def++)
474
free_defs_val(def->type, &def->sd_un);
475
}
476
477
/* First initialize the flags. */
478
#ifdef LONG_OTP_PROMPT
479
def_long_otp_prompt = true;
480
#endif
481
#ifndef ALLOW_DOT_PATH
482
def_ignore_dot = true;
483
#endif
484
#ifdef ALWAYS_SEND_MAIL
485
def_mail_always = true;
486
#endif
487
#ifdef SEND_MAIL_WHEN_NO_USER
488
def_mail_no_user = true;
489
#endif
490
#ifdef SEND_MAIL_WHEN_NO_HOST
491
def_mail_no_host = true;
492
#endif
493
#ifdef SEND_MAIL_WHEN_NOT_OK
494
def_mail_no_perms = true;
495
#endif
496
#ifndef NO_LECTURE
497
def_lecture = once;
498
#endif
499
#ifndef NO_AUTHENTICATION
500
def_authenticate = true;
501
#endif
502
#ifndef NO_ROOT_SUDO
503
def_root_sudo = true;
504
#endif
505
#ifdef HOST_IN_LOG
506
def_log_host = true;
507
#endif
508
#ifdef SHELL_IF_NO_ARGS
509
def_shell_noargs = true;
510
#endif
511
#ifdef SHELL_SETS_HOME
512
def_set_home = true;
513
#endif
514
#ifndef DONT_LEAK_PATH_INFO
515
def_path_info = true;
516
#endif
517
#ifdef USE_INSULTS
518
def_insults = true;
519
#endif
520
#ifdef FQDN
521
def_fqdn = true;
522
#endif
523
#ifdef ENV_EDITOR
524
def_env_editor = true;
525
#endif
526
#ifdef UMASK_OVERRIDE
527
def_umask_override = true;
528
#endif
529
#ifdef SUDOERS_NAME_MATCH
530
def_fast_glob = true;
531
def_fdexec = never;
532
#else
533
def_fdexec = digest_only;
534
#endif
535
def_timestamp_type = TIMESTAMP_TYPE;
536
if ((def_iolog_file = strdup(IOLOG_FILE)) == NULL)
537
goto oom;
538
if ((def_iolog_dir = strdup(_PATH_SUDO_IO_LOGDIR)) == NULL)
539
goto oom;
540
if ((def_sudoers_locale = strdup("C")) == NULL)
541
goto oom;
542
def_env_reset = ENV_RESET;
543
def_set_logname = true;
544
def_closefrom = STDERR_FILENO + 1;
545
def_pam_ruser = true;
546
#ifdef __sun__
547
def_pam_rhost = true;
548
#endif
549
if ((def_pam_service = strdup("sudo")) == NULL)
550
goto oom;
551
#ifdef HAVE_PAM_LOGIN
552
if ((def_pam_login_service = strdup("sudo-i")) == NULL)
553
goto oom;
554
#else
555
if ((def_pam_login_service = strdup("sudo")) == NULL)
556
goto oom;
557
#endif
558
#ifdef NO_PAM_SESSION
559
def_pam_session = false;
560
#else
561
def_pam_session = true;
562
#endif
563
#ifdef HAVE_SELINUX
564
def_selinux = true;
565
#endif
566
#ifdef _PATH_SUDO_ADMIN_FLAG
567
if ((def_admin_flag = strdup(_PATH_SUDO_ADMIN_FLAG)) == NULL)
568
goto oom;
569
#endif
570
if ((def_rlimit_core = strdup("0,0")) == NULL)
571
goto oom;
572
def_intercept_type = dso;
573
def_intercept_verify = true;
574
def_use_netgroups = true;
575
def_netgroup_tuple = false;
576
def_sudoedit_checkdir = true;
577
def_iolog_mode = S_IRUSR|S_IWUSR;
578
def_log_allowed = true;
579
def_log_denied = true;
580
def_log_format = sudo;
581
def_runas_allow_unknown_id = false;
582
def_noninteractive_auth = false;
583
def_use_pty = true;
584
585
/* Syslog options need special care since they both strings and ints */
586
#if (LOGGING & SLOG_SYSLOG)
587
(void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG]);
588
(void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI]);
589
(void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI]);
590
#endif
591
592
/* Password flags also have a string and integer component. */
593
(void) store_tuple("any", &sudo_defs_table[I_LISTPW], 0);
594
(void) store_tuple("all", &sudo_defs_table[I_VERIFYPW], 0);
595
596
/* Then initialize the int-like things. */
597
#ifdef SUDO_UMASK
598
def_umask = SUDO_UMASK;
599
#else
600
def_umask = ACCESSPERMS;
601
#endif
602
def_loglinelen = MAXLOGFILELEN;
603
def_timestamp_timeout.tv_sec = TIMEOUT * 60;
604
def_passwd_timeout.tv_sec = PASSWORD_TIMEOUT * 60;
605
def_passwd_tries = TRIES_FOR_PASSWORD;
606
#ifdef HAVE_ZLIB_H
607
def_compress_io = true;
608
#endif
609
def_ignore_audit_errors = true;
610
def_ignore_iolog_errors = false;
611
def_ignore_logfile_errors = true;
612
def_log_passwords = false;
613
#ifdef SUDOERS_LOG_CLIENT
614
def_log_server_timeout = 30;
615
def_log_server_verify = true;
616
def_log_server_keepalive = true;
617
#endif
618
619
/* Now do the strings */
620
if ((def_mailto = strdup(MAILTO)) == NULL)
621
goto oom;
622
if ((def_mailsub = strdup(N_(MAILSUBJECT))) == NULL)
623
goto oom;
624
if ((def_badpass_message = strdup(_(INCORRECT_PASSWORD))) == NULL)
625
goto oom;
626
#ifdef _PATH_SUDO_LECTURE_DIR
627
if ((def_lecture_status_dir = strdup(_PATH_SUDO_LECTURE_DIR)) == NULL)
628
goto oom;
629
#endif
630
#ifdef _PATH_SUDO_TIMEDIR
631
if ((def_timestampdir = strdup(_PATH_SUDO_TIMEDIR)) == NULL)
632
goto oom;
633
#endif
634
if ((def_passprompt = strdup(_(PASSPROMPT))) == NULL)
635
goto oom;
636
if ((def_runas_default = strdup(RUNAS_DEFAULT)) == NULL)
637
goto oom;
638
#ifdef _PATH_SUDO_SENDMAIL
639
if ((def_mailerpath = strdup(_PATH_SUDO_SENDMAIL)) == NULL)
640
goto oom;
641
#endif
642
if ((def_mailerflags = strdup("-t")) == NULL)
643
goto oom;
644
#if (LOGGING & SLOG_FILE)
645
if ((def_logfile = strdup(_PATH_SUDO_LOGFILE)) == NULL)
646
goto oom;
647
#endif
648
#ifdef EXEMPTGROUP
649
if ((def_exempt_group = strdup(EXEMPTGROUP)) == NULL)
650
goto oom;
651
#endif
652
#ifdef SECURE_PATH
653
if ((def_secure_path = strdup(SECURE_PATH)) == NULL)
654
goto oom;
655
#endif
656
if ((def_editor = strdup(EDITOR)) == NULL)
657
goto oom;
658
def_set_utmp = true;
659
def_pam_acct_mgmt = true;
660
def_pam_setcred = true;
661
def_pam_silent = true;
662
def_syslog_maxlen = MAXSYSLOGLEN;
663
def_case_insensitive_user = true;
664
def_case_insensitive_group = true;
665
666
/* Reset the locale. */
667
if (!firsttime) {
668
if (!sudoers_initlocale(NULL, def_sudoers_locale))
669
goto oom;
670
}
671
672
/* Finally do the lists (currently just environment tables). */
673
if (!init_envtables())
674
goto oom;
675
676
/* Init eventlog config. */
677
init_eventlog_config();
678
679
/* Initial iolog password prompt regex. */
680
if (!init_passprompt_regex())
681
debug_return_bool(false);
682
683
firsttime = false;
684
685
debug_return_bool(true);
686
oom:
687
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
688
debug_return_bool(false);
689
}
690
691
/*
692
* Check whether a defaults entry matches the specified type.
693
* Returns true if it matches, else false.
694
*/
695
static bool
696
default_type_matches(const struct defaults *d, int what)
697
{
698
debug_decl(default_type_matches, SUDOERS_DEBUG_DEFAULTS);
699
700
switch (d->type) {
701
case DEFAULTS:
702
if (ISSET(what, SETDEF_GENERIC))
703
debug_return_bool(true);
704
break;
705
case DEFAULTS_USER:
706
if (ISSET(what, SETDEF_USER))
707
debug_return_bool(true);
708
break;
709
case DEFAULTS_RUNAS:
710
if (ISSET(what, SETDEF_RUNAS))
711
debug_return_bool(true);
712
break;
713
case DEFAULTS_HOST:
714
if (ISSET(what, SETDEF_HOST))
715
debug_return_bool(true);
716
break;
717
case DEFAULTS_CMND:
718
if (ISSET(what, SETDEF_CMND))
719
debug_return_bool(true);
720
break;
721
}
722
debug_return_bool(false);
723
}
724
725
/*
726
* Check whether a defaults entry's binding matches.
727
* Returns true if it matches, else false.
728
*/
729
static bool
730
default_binding_matches(const struct sudoers_context *ctx,
731
struct sudoers_parse_tree *parse_tree, const struct defaults *d, int what)
732
{
733
debug_decl(default_binding_matches, SUDOERS_DEBUG_DEFAULTS);
734
735
switch (d->type) {
736
case DEFAULTS:
737
debug_return_bool(true);
738
case DEFAULTS_USER:
739
if (userlist_matches(parse_tree, ctx->user.pw, &d->binding->members) == ALLOW)
740
debug_return_bool(true);
741
break;
742
case DEFAULTS_RUNAS:
743
if (runaslist_matches(parse_tree, &d->binding->members, NULL) == ALLOW)
744
debug_return_bool(true);
745
break;
746
case DEFAULTS_HOST:
747
if (hostlist_matches(parse_tree, ctx->user.pw, &d->binding->members) == ALLOW)
748
debug_return_bool(true);
749
break;
750
case DEFAULTS_CMND:
751
if (cmndlist_matches(parse_tree, &d->binding->members, NULL, NULL) == ALLOW)
752
debug_return_bool(true);
753
break;
754
}
755
debug_return_bool(false);
756
}
757
758
/*
759
* Update the global defaults based on the given defaults list.
760
* Pass in an OR'd list of which default types to update.
761
*/
762
bool
763
update_defaults(struct sudoers_context *ctx,
764
struct sudoers_parse_tree *parse_tree,
765
const struct defaults_list *defs, int what, bool quiet)
766
{
767
const struct defaults *d;
768
bool global_defaults = false;
769
bool ret = true;
770
debug_decl(update_defaults, SUDOERS_DEBUG_DEFAULTS);
771
772
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
773
"what: 0x%02x", what);
774
775
/* If no defaults list specified, use the global one in the parse tree. */
776
if (defs == NULL) {
777
defs = &parse_tree->defaults;
778
global_defaults = true;
779
}
780
781
/*
782
* If using the global defaults list, apply Defaults values marked as early.
783
*/
784
if (global_defaults) {
785
TAILQ_FOREACH(d, defs, entries) {
786
struct early_default *early = is_early_default(d->var);
787
if (early == NULL)
788
continue;
789
790
/* Defaults type and binding must match. */
791
if (!default_type_matches(d, what) ||
792
!default_binding_matches(ctx, parse_tree, d, what))
793
continue;
794
795
/* Copy the value to sudo_defs_table and mark as early. */
796
if (!set_early_default(ctx, d->var, d->val, d->op, d->file, d->line,
797
d->column, quiet, early))
798
ret = false;
799
}
800
801
/* Run callbacks for early defaults (if any) */
802
if (!run_early_defaults(ctx))
803
ret = false;
804
}
805
806
/*
807
* Set the rest of the defaults and run their callbacks, if any.
808
*/
809
TAILQ_FOREACH(d, defs, entries) {
810
if (global_defaults) {
811
/* Skip Defaults marked as early, we already did them. */
812
if (is_early_default(d->var))
813
continue;
814
}
815
816
/* Defaults type and binding must match. */
817
if (!default_type_matches(d, what) ||
818
!default_binding_matches(ctx, parse_tree, d, what))
819
continue;
820
821
/* Copy the value to sudo_defs_table and run callback (if any) */
822
if (!set_default(ctx, d->var, d->val, d->op, d->file, d->line, d->column, quiet))
823
ret = false;
824
}
825
826
debug_return_bool(ret);
827
}
828
829
/*
830
* Check all defaults entries without actually setting them.
831
*/
832
bool
833
check_defaults(const struct sudoers_parse_tree *parse_tree, bool quiet)
834
{
835
const struct defaults *d;
836
bool ret = true;
837
int idx;
838
debug_decl(check_defaults, SUDOERS_DEBUG_DEFAULTS);
839
840
TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
841
idx = find_default(parse_tree->ctx, d->var, d->file, d->line,
842
d->column, quiet);
843
if (idx != -1) {
844
struct sudo_defs_types def = sudo_defs_table[idx];
845
memset(&def.sd_un, 0, sizeof(def.sd_un));
846
if (parse_default_entry(parse_tree->ctx, &def, d->val, d->op,
847
d->file, d->line, d->column, quiet)) {
848
free_defs_val(def.type, &def.sd_un);
849
continue;
850
}
851
}
852
/* There was an error in the entry. */
853
ret = false;
854
}
855
debug_return_bool(ret);
856
}
857
858
static bool
859
store_int(const char *str, struct sudo_defs_types *def)
860
{
861
const char *errstr;
862
int i;
863
debug_decl(store_int, SUDOERS_DEBUG_DEFAULTS);
864
865
if (str == NULL) {
866
def->sd_un.ival = 0;
867
} else {
868
i = (int)sudo_strtonum(str, INT_MIN, INT_MAX, &errstr);
869
if (errstr != NULL) {
870
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
871
"%s: %s", str, errstr);
872
debug_return_bool(false);
873
}
874
def->sd_un.ival = i;
875
}
876
debug_return_bool(true);
877
}
878
879
static bool
880
store_uint(const char *str, struct sudo_defs_types *def)
881
{
882
const char *errstr;
883
unsigned int u;
884
debug_decl(store_uint, SUDOERS_DEBUG_DEFAULTS);
885
886
if (str == NULL) {
887
def->sd_un.uival = 0;
888
} else {
889
u = (unsigned int)sudo_strtonum(str, 0, UINT_MAX, &errstr);
890
if (errstr != NULL) {
891
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
892
"%s: %s", str, errstr);
893
debug_return_bool(false);
894
}
895
def->sd_un.uival = u;
896
}
897
debug_return_bool(true);
898
}
899
900
/* Check resource limit syntax, does not save as rlim_t. */
901
static bool
902
check_rlimit(const char *str, bool soft)
903
{
904
const size_t inflen = sizeof("infinity") - 1;
905
debug_decl(check_rlimit, SUDOERS_DEBUG_DEFAULTS);
906
907
if (isdigit((unsigned char)*str)) {
908
unsigned long long ullval;
909
char *ep;
910
911
errno = 0;
912
#ifdef HAVE_STRTOULL
913
ullval = strtoull(str, &ep, 10);
914
if (str == ep || (errno == ERANGE && ullval == ULLONG_MAX))
915
debug_return_bool(false);
916
#else
917
ullval = strtoul(str, &ep, 10);
918
if (str == ep || (errno == ERANGE && ullval == ULONG_MAX))
919
debug_return_bool(false);
920
#endif
921
if (*ep == '\0' || (soft && *ep == ','))
922
debug_return_bool(true);
923
debug_return_bool(false);
924
}
925
if (strncmp(str, "infinity", inflen) == 0) {
926
if (str[inflen] == '\0' || (soft && str[inflen] == ','))
927
debug_return_bool(true);
928
}
929
debug_return_bool(false);
930
}
931
932
static bool
933
store_rlimit(const char *str, struct sudo_defs_types *def)
934
{
935
debug_decl(store_rlimit, SUDOERS_DEBUG_DEFAULTS);
936
937
/* The special values "user" and "default" are not compound. */
938
if (str != NULL && strcmp(str, "user") != 0 && strcmp(str, "default") != 0) {
939
const char *hard, *soft = str;
940
/*
941
* Expect a limit in the form "soft,hard" or "limit" (both soft+hard).
942
*/
943
hard = strchr(str, ',');
944
if (hard != NULL)
945
hard++;
946
else
947
hard = soft;
948
949
if (!check_rlimit(soft, true))
950
debug_return_bool(false);
951
if (!check_rlimit(hard, false))
952
debug_return_bool(false);
953
}
954
955
/* Store as string, front-end will parse it as a limit. */
956
debug_return_bool(store_str(str, def));
957
}
958
959
static bool
960
store_timespec(const char *str, struct sudo_defs_types *def)
961
{
962
struct timespec ts;
963
char sign = '+';
964
long i;
965
debug_decl(store_timespec, SUDOERS_DEBUG_DEFAULTS);
966
967
sudo_timespecclear(&ts);
968
if (str != NULL) {
969
/* Convert from minutes to seconds. */
970
if (*str == '+' || *str == '-')
971
sign = *str++;
972
while (*str != '\0' && *str != '.') {
973
if (!isdigit((unsigned char)*str))
974
debug_return_bool(false); /* invalid number */
975
976
/* Verify (ts.tv_sec * 10) + (digit * 60) <= TIME_T_MAX. */
977
i = (*str++ - '0') * 60L;
978
if (ts.tv_sec > (TIME_T_MAX - i) / 10)
979
debug_return_bool(false); /* overflow */
980
ts.tv_sec *= 10;
981
ts.tv_sec += i;
982
}
983
if (*str++ == '.') {
984
long long nsec = 0;
985
986
/* Convert optional fractional component to seconds and nanosecs. */
987
for (i = 100000000; i > 0; i /= 10) {
988
if (*str == '\0')
989
break;
990
if (!isdigit((unsigned char)*str))
991
debug_return_bool(false); /* invalid number */
992
nsec += i * (*str++ - '0') * 60LL;
993
}
994
while (nsec >= 1000000000) {
995
if (ts.tv_sec == TIME_T_MAX)
996
debug_return_bool(false); /* overflow */
997
ts.tv_sec++;
998
nsec -= 1000000000;
999
}
1000
ts.tv_nsec = (long)nsec;
1001
}
1002
}
1003
if (sign == '-') {
1004
def->sd_un.tspec.tv_sec = -ts.tv_sec;
1005
def->sd_un.tspec.tv_nsec = -ts.tv_nsec;
1006
} else {
1007
def->sd_un.tspec.tv_sec = ts.tv_sec;
1008
def->sd_un.tspec.tv_nsec = ts.tv_nsec;
1009
}
1010
debug_return_bool(true);
1011
}
1012
1013
static bool
1014
store_tuple(const char *str, struct sudo_defs_types *def, int op)
1015
{
1016
const struct def_values *v;
1017
debug_decl(store_tuple, SUDOERS_DEBUG_DEFAULTS);
1018
1019
/*
1020
* Look up tuple value by name to find enum def_tuple value.
1021
* A tuple must have at least two possible values.
1022
*/
1023
if (str == NULL) {
1024
/*
1025
* Boolean context: true maps to values[1], false maps to values[0].
1026
*/
1027
if (op == true) {
1028
v = &def->values[1];
1029
def->sd_un.ival = v->nval;
1030
} else if (op == false) {
1031
v = &def->values[0];
1032
def->sd_un.ival = v->nval;
1033
} else {
1034
debug_return_bool(false);
1035
}
1036
} else {
1037
for (v = def->values; v->sval != NULL; v++) {
1038
if (strcmp(v->sval, str) == 0) {
1039
def->sd_un.tuple = v->nval;
1040
break;
1041
}
1042
}
1043
if (v->sval == NULL)
1044
debug_return_bool(false);
1045
}
1046
debug_return_bool(true);
1047
}
1048
1049
static int
1050
store_str(const char *str, struct sudo_defs_types *def)
1051
{
1052
debug_decl(store_str, SUDOERS_DEBUG_DEFAULTS);
1053
1054
free(def->sd_un.str);
1055
if (str == NULL) {
1056
def->sd_un.str = NULL;
1057
} else {
1058
if ((def->sd_un.str = strdup(str)) == NULL) {
1059
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
1060
debug_return_int(-1);
1061
}
1062
}
1063
debug_return_int(true);
1064
}
1065
1066
static bool
1067
store_list(const char *str, struct sudo_defs_types *def, int op)
1068
{
1069
debug_decl(store_list, SUDOERS_DEBUG_DEFAULTS);
1070
1071
/* Remove all old members. */
1072
if (op == false || op == true)
1073
(void)list_op(NULL, 0, &def->sd_un.list, freeall);
1074
1075
/* Split str into multiple space-separated words and act on each one. */
1076
if (str != NULL) {
1077
const char *cp, *ep;
1078
const char *end = str + strlen(str);
1079
const enum list_ops lop = op == '-' ? delete : add;
1080
1081
if (ISSET(def->type, T_SPACE)) {
1082
if (!list_op(str, strlen(str), &def->sd_un.list, lop))
1083
debug_return_bool(false);
1084
} else {
1085
for (cp = sudo_strsplit(str, end, " \t", &ep); cp != NULL;
1086
cp = sudo_strsplit(NULL, end, " \t", &ep)) {
1087
if (!list_op(cp, (size_t)(ep - cp), &def->sd_un.list, lop))
1088
debug_return_bool(false);
1089
}
1090
}
1091
}
1092
debug_return_bool(true);
1093
}
1094
1095
static bool
1096
store_plugin(const char *str, struct sudo_defs_types *def, int op)
1097
{
1098
const enum list_ops lop = op == '-' ? delete : add;
1099
debug_decl(store_plugin, SUDOERS_DEBUG_DEFAULTS);
1100
1101
/* Remove all old members. */
1102
if (op == false || op == true)
1103
(void)list_op(NULL, 0, &def->sd_un.list, freeall);
1104
1105
if (str != NULL) {
1106
if (!list_op(str, strlen(str), &def->sd_un.list, lop))
1107
debug_return_bool(false);
1108
}
1109
1110
debug_return_bool(true);
1111
}
1112
1113
static bool
1114
store_syslogfac(const char *str, struct sudo_defs_types *def)
1115
{
1116
debug_decl(store_syslogfac, SUDOERS_DEBUG_DEFAULTS);
1117
1118
if (str == NULL) {
1119
def->sd_un.ival = false;
1120
debug_return_bool(true);
1121
}
1122
debug_return_bool(sudo_str2logfac(str, &def->sd_un.ival));
1123
}
1124
1125
static bool
1126
store_syslogpri(const char *str, struct sudo_defs_types *def)
1127
{
1128
debug_decl(store_syslogpri, SUDOERS_DEBUG_DEFAULTS);
1129
1130
if (str == NULL) {
1131
def->sd_un.ival = -1;
1132
debug_return_bool(true);
1133
}
1134
debug_return_bool(sudo_str2logpri(str, &def->sd_un.ival));
1135
}
1136
1137
static bool
1138
store_mode(const char *str, struct sudo_defs_types *def)
1139
{
1140
mode_t mode;
1141
const char *errstr;
1142
debug_decl(store_mode, SUDOERS_DEBUG_DEFAULTS);
1143
1144
if (str == NULL) {
1145
def->sd_un.mode = ACCESSPERMS;
1146
} else {
1147
mode = sudo_strtomode(str, &errstr);
1148
if (errstr != NULL) {
1149
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
1150
"%s is %s", str, errstr);
1151
debug_return_bool(false);
1152
}
1153
def->sd_un.mode = mode;
1154
}
1155
debug_return_bool(true);
1156
}
1157
1158
static bool
1159
store_timeout(const char *str, struct sudo_defs_types *def)
1160
{
1161
debug_decl(store_mode, SUDOERS_DEBUG_DEFAULTS);
1162
1163
if (str == NULL) {
1164
def->sd_un.ival = 0;
1165
} else {
1166
int seconds = parse_timeout(str);
1167
if (seconds == -1) {
1168
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
1169
"%s", str);
1170
debug_return_bool(false);
1171
}
1172
def->sd_un.ival = seconds;
1173
}
1174
debug_return_bool(true);
1175
}
1176
1177
static bool
1178
valid_path(const struct sudoers_context *ctx, const struct sudo_defs_types *def,
1179
const char *val, const char *file, int line, int column, bool quiet)
1180
{
1181
bool ret = true;
1182
debug_decl(valid_path, SUDOERS_DEBUG_DEFAULTS);
1183
1184
if (strlen(val) >= PATH_MAX) {
1185
defaults_warnx(ctx, file, line, column, quiet,
1186
N_("path name for \"%s\" too long"), def->name);
1187
ret = false;
1188
}
1189
if (ISSET(def->type, T_CHPATH)) {
1190
if (val[0] != '/' && val[0] != '~' && (val[0] != '*' || val[1] != '\0')) {
1191
defaults_warnx(ctx, file, line, column, quiet,
1192
N_("values for \"%s\" must start with a '/', '~', or '*'"),
1193
def->name);
1194
ret = false;
1195
}
1196
} else {
1197
if (val[0] != '/') {
1198
defaults_warnx(ctx, file, line, column, quiet,
1199
N_("values for \"%s\" must start with a '/'"), def->name);
1200
ret = false;
1201
}
1202
1203
}
1204
debug_return_bool(ret);
1205
}
1206
1207
static bool
1208
list_op(const char *str, size_t len, struct list_members *list,
1209
enum list_ops op)
1210
{
1211
struct list_member *cur, *prev = NULL;
1212
debug_decl(list_op, SUDOERS_DEBUG_DEFAULTS);
1213
1214
if (op == freeall) {
1215
while ((cur = SLIST_FIRST(list)) != NULL) {
1216
SLIST_REMOVE_HEAD(list, entries);
1217
free(cur->value);
1218
free(cur);
1219
}
1220
debug_return_bool(true);
1221
}
1222
1223
SLIST_FOREACH(cur, list, entries) {
1224
if ((strncmp(cur->value, str, len) == 0 && cur->value[len] == '\0')) {
1225
1226
if (op == add)
1227
debug_return_bool(true); /* already exists */
1228
1229
/* Delete node */
1230
if (prev == NULL)
1231
SLIST_REMOVE_HEAD(list, entries);
1232
else
1233
SLIST_REMOVE_AFTER(prev, entries);
1234
free(cur->value);
1235
free(cur);
1236
break;
1237
}
1238
prev = cur;
1239
}
1240
1241
/* Add new node to the head of the list. */
1242
if (op == add) {
1243
cur = calloc(1, sizeof(struct list_member));
1244
if (cur == NULL || (cur->value = strndup(str, len)) == NULL) {
1245
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
1246
free(cur);
1247
debug_return_bool(false);
1248
}
1249
SLIST_INSERT_HEAD(list, cur, entries);
1250
}
1251
debug_return_bool(true);
1252
}
1253
1254
bool
1255
append_default(const char *var, const char *val, int op,
1256
char *source, struct defaults_list *defs)
1257
{
1258
struct defaults *def;
1259
debug_decl(append_default, SUDOERS_DEBUG_DEFAULTS);
1260
1261
if ((def = calloc(1, sizeof(*def))) == NULL)
1262
goto oom;
1263
1264
def->type = DEFAULTS;
1265
def->op = op;
1266
if ((def->var = strdup(var)) == NULL) {
1267
goto oom;
1268
}
1269
if (val != NULL) {
1270
if ((def->val = strdup(val)) == NULL)
1271
goto oom;
1272
}
1273
def->file = source;
1274
sudo_rcstr_addref(source);
1275
TAILQ_INSERT_TAIL(defs, def, entries);
1276
debug_return_bool(true);
1277
1278
oom:
1279
if (def != NULL) {
1280
free(def->var);
1281
free(def->val);
1282
free(def);
1283
}
1284
debug_return_bool(false);
1285
}
1286
1287
bool
1288
cb_passprompt_regex(struct sudoers_context *ctx, const char *file,
1289
int line, int column, const union sudo_defs_val *sd_un, int op)
1290
{
1291
struct list_member *lm;
1292
const char *errstr;
1293
debug_decl(cb_passprompt_regex, SUDOERS_DEBUG_DEFAULTS);
1294
1295
/* If adding one or more regexps, make sure they are valid. */
1296
if (op == '+' || op == true) {
1297
SLIST_FOREACH(lm, &sd_un->list, entries) {
1298
if (!sudo_regex_compile(NULL, lm->value, &errstr)) {
1299
defaults_warnx(ctx, file, line, column, false,
1300
U_("invalid regular expression \"%s\": %s"),
1301
lm->value, U_(errstr));
1302
debug_return_bool(false);
1303
}
1304
}
1305
}
1306
1307
debug_return_bool(true);
1308
}
1309
1310