Coverage Report

Created: 2025-10-10 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/sudo/plugins/sudoers/sudoers_cb.c
Line
Count
Source
1
/*
2
 * SPDX-License-Identifier: ISC
3
 *
4
 * Copyright (c) 2011-2023 Todd C. Miller <Todd.Miller@sudo.ws>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#ifdef __TANDEM
20
# include <floss.h>
21
#endif
22
23
#include <config.h>
24
25
#include <sys/types.h>
26
#include <sys/socket.h>
27
#include <sys/stat.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <errno.h>
32
#include <pwd.h>
33
#include <grp.h>
34
#include <netdb.h>
35
#ifndef HAVE_GETADDRINFO
36
# include <compat/getaddrinfo.h>
37
#endif
38
39
#include <sudoers.h>
40
#include <timestamp.h>
41
#include <sudo_iolog.h>
42
43
#ifndef AI_FQDN
44
27.3k
# define AI_FQDN AI_CANONNAME
45
#endif
46
47
static bool override_umask;
48
49
/*
50
 * Look up the fully qualified domain name of host.
51
 * Use AI_FQDN if available since "canonical" is not always the same as fqdn.
52
 * Returns 0 on success, setting longp and shortp.
53
 * Returns non-zero on failure, longp and shortp are unchanged.
54
 * See gai_strerror() for the list of error return codes.
55
 */
56
static int
57
resolve_host(const char *host, char **longp, char **shortp)
58
27.3k
{
59
27.3k
    struct addrinfo *res0, hint;
60
27.3k
    char *cp, *lname, *sname;
61
27.3k
    int ret;
62
27.3k
    debug_decl(resolve_host, SUDOERS_DEBUG_PLUGIN);
63
64
27.3k
    memset(&hint, 0, sizeof(hint));
65
27.3k
    hint.ai_family = PF_UNSPEC;
66
27.3k
    hint.ai_flags = AI_FQDN;
67
68
27.3k
    if ((ret = getaddrinfo(host, NULL, &hint, &res0)) != 0)
69
0
  debug_return_int(ret);
70
27.3k
    if ((lname = strdup(res0->ai_canonname)) == NULL) {
71
0
  freeaddrinfo(res0);
72
0
  debug_return_int(EAI_MEMORY);
73
0
    }
74
27.3k
    if ((cp = strchr(lname, '.')) != NULL) {
75
0
  sname = strndup(lname, (size_t)(cp - lname));
76
0
  if (sname == NULL) {
77
0
      free(lname);
78
0
      freeaddrinfo(res0);
79
0
      debug_return_int(EAI_MEMORY);
80
0
  }
81
27.3k
    } else {
82
27.3k
  sname = lname;
83
27.3k
    }
84
27.3k
    freeaddrinfo(res0);
85
27.3k
    *longp = lname;
86
27.3k
    *shortp = sname;
87
88
27.3k
    debug_return_int(0);
89
27.3k
}
90
91
/*
92
 * Look up the fully qualified domain name of user and runas hosts.
93
 * Sets ctx->user.host, ctx->user.shost, ctx->runas.host and ctx->runas.shost.
94
 */
95
static bool
96
cb_fqdn(struct sudoers_context *ctx, const char *file,
97
    int line, int column, const union sudo_defs_val *sd_un, int op)
98
26.0k
{
99
26.0k
    bool remote;
100
26.0k
    int rc;
101
26.0k
    char *lhost, *shost;
102
26.0k
    debug_decl(cb_fqdn, SUDOERS_DEBUG_PLUGIN);
103
104
    /* Nothing to do if fqdn flag is disabled. */
105
26.0k
    if (sd_un != NULL && !sd_un->flag)
106
0
  debug_return_bool(true);
107
108
    /* If the -h flag was given we need to resolve both host names. */
109
26.0k
    remote = strcmp(ctx->runas.host, ctx->user.host) != 0;
110
111
    /* First resolve ctx->user.host, setting host and shost. */
112
26.0k
    if (resolve_host(ctx->user.host, &lhost, &shost) != 0) {
113
0
  if ((rc = resolve_host(ctx->runas.host, &lhost, &shost)) != 0) {
114
0
      gai_log_warning(ctx, SLOG_PARSE_ERROR|SLOG_RAW_MSG, rc,
115
0
    N_("unable to resolve host %s"), ctx->user.host);
116
0
      debug_return_bool(false);
117
0
  }
118
0
    }
119
26.0k
    if (ctx->user.shost != ctx->user.host)
120
110
  free(ctx->user.shost);
121
26.0k
    free(ctx->user.host);
122
26.0k
    ctx->user.host = lhost;
123
26.0k
    ctx->user.shost = shost;
124
125
    /* Next resolve ctx->runas.host, setting host and shost in ctx->runas. */
126
26.0k
    lhost = shost = NULL;
127
26.0k
    if (remote) {
128
1.31k
  if ((rc = resolve_host(ctx->runas.host, &lhost, &shost)) != 0) {
129
0
      gai_log_warning(ctx, SLOG_NO_LOG|SLOG_RAW_MSG, rc,
130
0
    N_("unable to resolve host %s"), ctx->runas.host);
131
0
      debug_return_bool(false);
132
0
  }
133
24.7k
    } else {
134
  /* Not remote, just use ctx->user.host. */
135
24.7k
  if ((lhost = strdup(ctx->user.host)) != NULL) {
136
24.7k
      if (ctx->user.shost != ctx->user.host)
137
0
    shost = strdup(ctx->user.shost);
138
24.7k
      else
139
24.7k
    shost = lhost;
140
24.7k
  }
141
24.7k
  if (lhost == NULL || shost == NULL) {
142
0
      free(lhost);
143
0
      if (lhost != shost)
144
0
    free(shost);
145
0
      sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
146
0
      debug_return_bool(false);
147
0
  }
148
24.7k
    }
149
26.0k
    if (lhost != NULL && shost != NULL) {
150
26.0k
  if (ctx->runas.shost != ctx->runas.host)
151
120
      free(ctx->runas.shost);
152
26.0k
  free(ctx->runas.host);
153
26.0k
  ctx->runas.host = lhost;
154
26.0k
  ctx->runas.shost = shost;
155
26.0k
    }
156
157
26.0k
    sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
158
26.0k
  "host %s, shost %s, runas host %s, runas shost %s",
159
26.0k
  ctx->user.host, ctx->user.shost, ctx->runas.host, ctx->runas.shost);
160
26.0k
    debug_return_bool(true);
161
26.0k
}
162
163
static bool
164
cb_tty_tickets(struct sudoers_context *ctx, const char *file,
165
    int line, int column, const union sudo_defs_val *sd_un, int op)
166
26.0k
{
167
26.0k
    debug_decl(cb_tty_tickets, SUDOERS_DEBUG_PLUGIN);
168
169
    /* Convert tty_tickets -> timestamp_type */
170
26.0k
    if (sd_un->flag)
171
26.0k
  def_timestamp_type = tty;
172
0
    else
173
0
  def_timestamp_type = global;
174
26.0k
    debug_return_bool(true);
175
26.0k
}
176
177
static bool
178
cb_umask(struct sudoers_context *ctx, const char *file,
179
    int line, int column, const union sudo_defs_val *sd_un, int op)
180
26.0k
{
181
26.0k
    debug_decl(cb_umask, SUDOERS_DEBUG_PLUGIN);
182
183
    /* Override umask if explicitly set in sudoers. */
184
26.0k
    override_umask = sd_un->mode != ACCESSPERMS;
185
186
26.0k
    debug_return_bool(true);
187
26.0k
}
188
189
static bool
190
cb_runchroot(struct sudoers_context *ctx, const char *file,
191
    int line, int column, const union sudo_defs_val *sd_un, int op)
192
26.0k
{
193
26.0k
    debug_decl(cb_runchroot, SUDOERS_DEBUG_PLUGIN);
194
195
26.0k
    sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
196
26.0k
  "def_runchroot now %s", sd_un->str);
197
26.0k
    if (ctx->user.cmnd != NULL) {
198
  /* Update ctx->user.cmnd and cmnd_status based on the new chroot. */
199
5.94k
  set_cmnd_status(ctx, sd_un->str);
200
5.94k
  sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
201
5.94k
      "ctx->user.cmnd now %s", ctx->user.cmnd);
202
5.94k
    }
203
204
26.0k
    debug_return_bool(true);
205
26.0k
}
206
207
static bool
208
cb_logfile(struct sudoers_context *ctx, const char *file,
209
    int line, int column, const union sudo_defs_val *sd_un, int op)
210
26.0k
{
211
26.0k
    int logtype = def_syslog ? EVLOG_SYSLOG : EVLOG_NONE;
212
26.0k
    debug_decl(cb_logfile, SUDOERS_DEBUG_PLUGIN);
213
214
26.0k
    if (sd_un->str != NULL)
215
26.0k
  SET(logtype, EVLOG_FILE);
216
26.0k
    eventlog_set_type(logtype);
217
26.0k
    eventlog_set_logpath(sd_un->str);
218
219
26.0k
    debug_return_bool(true);
220
26.0k
}
221
222
static bool
223
cb_log_format(struct sudoers_context *ctx, const char *file,
224
    int line, int column, const union sudo_defs_val *sd_un, int op)
225
0
{
226
0
    return sudoers_set_log_format(sd_un->tuple);
227
0
}
228
229
static bool
230
cb_syslog(struct sudoers_context *ctx, const char *file,
231
    int line, int column, const union sudo_defs_val *sd_un, int op)
232
26.0k
{
233
26.0k
    int logtype = def_logfile ? EVLOG_FILE : EVLOG_NONE;
234
26.0k
    debug_decl(cb_syslog, SUDOERS_DEBUG_PLUGIN);
235
236
26.0k
    if (sd_un->str != NULL)
237
26.0k
  SET(logtype, EVLOG_SYSLOG);
238
26.0k
    eventlog_set_type(logtype);
239
240
26.0k
    debug_return_bool(true);
241
26.0k
}
242
243
static bool
244
cb_syslog_goodpri(struct sudoers_context *ctx, const char *file,
245
    int line, int column, const union sudo_defs_val *sd_un, int op)
246
26.0k
{
247
26.0k
    debug_decl(cb_syslog_goodpri, SUDOERS_DEBUG_PLUGIN);
248
249
26.0k
    eventlog_set_syslog_acceptpri(sd_un->ival);
250
251
26.0k
    debug_return_bool(true);
252
26.0k
}
253
254
static bool
255
cb_syslog_badpri(struct sudoers_context *ctx, const char *file,
256
    int line, int column, const union sudo_defs_val *sd_un, int op)
257
26.0k
{
258
26.0k
    debug_decl(cb_syslog_badpri, SUDOERS_DEBUG_PLUGIN);
259
260
26.0k
    eventlog_set_syslog_rejectpri(sd_un->ival);
261
26.0k
    eventlog_set_syslog_alertpri(sd_un->ival);
262
263
26.0k
    debug_return_bool(true);
264
26.0k
}
265
266
static bool
267
cb_syslog_maxlen(struct sudoers_context *ctx, const char *file,
268
    int line, int column, const union sudo_defs_val *sd_un, int op)
269
26.0k
{
270
26.0k
    debug_decl(cb_syslog_maxlen, SUDOERS_DEBUG_PLUGIN);
271
272
26.0k
    eventlog_set_syslog_maxlen((size_t)sd_un->ival);
273
274
26.0k
    debug_return_bool(true);
275
26.0k
}
276
277
static bool
278
cb_loglinelen(struct sudoers_context *ctx, const char *file,
279
    int line, int column, const union sudo_defs_val *sd_un, int op)
280
26.0k
{
281
26.0k
    debug_decl(cb_loglinelen, SUDOERS_DEBUG_PLUGIN);
282
283
26.0k
    eventlog_set_file_maxlen((size_t)sd_un->ival);
284
285
26.0k
    debug_return_bool(true);
286
26.0k
}
287
288
static bool
289
cb_log_year(struct sudoers_context *ctx, const char *file,
290
    int line, int column, const union sudo_defs_val *sd_un, int op)
291
26.0k
{
292
26.0k
    debug_decl(cb_syslog_maxlen, SUDOERS_DEBUG_PLUGIN);
293
294
26.0k
    eventlog_set_time_fmt(sd_un->flag ? "%h %e %T %Y" : "%h %e %T");
295
296
26.0k
    debug_return_bool(true);
297
26.0k
}
298
299
static bool
300
cb_log_host(struct sudoers_context *ctx, const char *file,
301
    int line, int column, const union sudo_defs_val *sd_un, int op)
302
26.0k
{
303
26.0k
    debug_decl(cb_syslog_maxlen, SUDOERS_DEBUG_PLUGIN);
304
305
26.0k
    eventlog_set_omit_hostname(!sd_un->flag);
306
307
26.0k
    debug_return_bool(true);
308
26.0k
}
309
310
static bool
311
cb_mailerpath(struct sudoers_context *ctx, const char *file,
312
    int line, int column, const union sudo_defs_val *sd_un, int op)
313
26.0k
{
314
26.0k
    debug_decl(cb_mailerpath, SUDOERS_DEBUG_PLUGIN);
315
316
26.0k
    eventlog_set_mailerpath(sd_un->str);
317
318
26.0k
    debug_return_bool(true);
319
26.0k
}
320
321
static bool
322
cb_mailerflags(struct sudoers_context *ctx, const char *file,
323
    int line, int column, const union sudo_defs_val *sd_un, int op)
324
26.0k
{
325
26.0k
    debug_decl(cb_mailerflags, SUDOERS_DEBUG_PLUGIN);
326
327
26.0k
    eventlog_set_mailerflags(sd_un->str);
328
329
26.0k
    debug_return_bool(true);
330
26.0k
}
331
332
static bool
333
cb_mailfrom(struct sudoers_context *ctx, const char *file,
334
    int line, int column, const union sudo_defs_val *sd_un, int op)
335
26.0k
{
336
26.0k
    debug_decl(cb_mailfrom, SUDOERS_DEBUG_PLUGIN);
337
338
26.0k
    eventlog_set_mailfrom(sd_un->str);
339
340
26.0k
    debug_return_bool(true);
341
26.0k
}
342
343
static bool
344
cb_mailto(struct sudoers_context *ctx, const char *file,
345
    int line, int column, const union sudo_defs_val *sd_un, int op)
346
26.0k
{
347
26.0k
    debug_decl(cb_mailto, SUDOERS_DEBUG_PLUGIN);
348
349
26.0k
    eventlog_set_mailto(sd_un->str);
350
351
26.0k
    debug_return_bool(true);
352
26.0k
}
353
354
static bool
355
cb_mailsub(struct sudoers_context *ctx, const char *file,
356
    int line, int column, const union sudo_defs_val *sd_un, int op)
357
26.0k
{
358
26.0k
    debug_decl(cb_mailsub, SUDOERS_DEBUG_PLUGIN);
359
360
26.0k
    eventlog_set_mailsub(sd_un->str);
361
362
26.0k
    debug_return_bool(true);
363
26.0k
}
364
365
static bool
366
cb_intercept_type(struct sudoers_context *ctx, const char *file,
367
    int line, int column, const union sudo_defs_val *sd_un, int op)
368
62
{
369
62
    debug_decl(cb_intercept_type, SUDOERS_DEBUG_PLUGIN);
370
371
62
    if (op != -1) {
372
  /* Set explicitly in sudoers. */
373
0
  if (sd_un->tuple == dso) {
374
      /* Reset intercept_allow_setid default value. */
375
0
      if (!ISSET(ctx->settings.flags, USER_INTERCEPT_SETID))
376
0
    def_intercept_allow_setid = false;
377
0
  }
378
0
    }
379
380
62
    debug_return_bool(true);
381
62
}
382
383
static bool
384
cb_intercept_allow_setid(struct sudoers_context *ctx, const char *file,
385
    int line, int column, const union sudo_defs_val *sd_un, int op)
386
59
{
387
59
    debug_decl(cb_intercept_allow_setid, SUDOERS_DEBUG_PLUGIN);
388
389
    /* Operator will be -1 if set by front-end. */
390
59
    if (op != -1) {
391
  /* Set explicitly in sudoers. */
392
0
  SET(ctx->settings.flags, USER_INTERCEPT_SETID);
393
0
    }
394
395
59
    debug_return_bool(true);
396
59
}
397
398
bool
399
cb_log_input(struct sudoers_context *ctx, const char *file,
400
    int line, int column, const union sudo_defs_val *sd_un, int op)
401
26.0k
{
402
26.0k
    debug_decl(cb_log_input, SUDOERS_DEBUG_PLUGIN);
403
404
26.0k
    def_log_stdin = op;
405
26.0k
    def_log_ttyin = op;
406
407
26.0k
    debug_return_bool(true);
408
26.0k
}
409
410
bool
411
cb_log_output(struct sudoers_context *ctx, const char *file,
412
    int line, int column, const union sudo_defs_val *sd_un, int op)
413
26.0k
{
414
26.0k
    debug_decl(cb_log_output, SUDOERS_DEBUG_PLUGIN);
415
416
26.0k
    def_log_stdout = op;
417
26.0k
    def_log_stderr = op;
418
26.0k
    def_log_ttyout = op;
419
420
26.0k
    debug_return_bool(true);
421
26.0k
}
422
423
/*
424
 * Set parser Defaults callbacks.
425
 * We do this here instead in def_data.in so we don't have to
426
 * stub out the callbacks for visudo and testsudoers.
427
 */
428
void
429
set_callbacks(void)
430
20.4k
{
431
20.4k
    debug_decl(set_callbacks, SUDOERS_DEBUG_PLUGIN);
432
433
    /* Set fqdn callback. */
434
20.4k
    sudo_defs_table[I_FQDN].callback = cb_fqdn;
435
436
    /* Set group_plugin callback. */
437
20.4k
    sudo_defs_table[I_GROUP_PLUGIN].callback = cb_group_plugin;
438
439
    /* Set runas callback. */
440
20.4k
    sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default;
441
442
    /* Set locale callback. */
443
20.4k
    sudo_defs_table[I_SUDOERS_LOCALE].callback = sudoers_locale_callback;
444
445
20.4k
#ifdef SESSID_MAX
446
    /* Set maxseq callback. */
447
20.4k
    sudo_defs_table[I_MAXSEQ].callback = cb_maxseq;
448
449
    /* Set iolog_user callback. */
450
20.4k
    sudo_defs_table[I_IOLOG_USER].callback = cb_iolog_user;
451
452
    /* Set iolog_group callback. */
453
20.4k
    sudo_defs_table[I_IOLOG_GROUP].callback = cb_iolog_group;
454
455
    /* Set iolog_mode callback. */
456
20.4k
    sudo_defs_table[I_IOLOG_MODE].callback = cb_iolog_mode;
457
20.4k
#endif /* SESSID_MAX */
458
459
    /* Set timestampowner callback. */
460
20.4k
    sudo_defs_table[I_TIMESTAMPOWNER].callback = cb_timestampowner;
461
462
    /* Set tty_tickets callback. */
463
20.4k
    sudo_defs_table[I_TTY_TICKETS].callback = cb_tty_tickets;
464
465
    /* Set umask callback. */
466
20.4k
    sudo_defs_table[I_UMASK].callback = cb_umask;
467
468
    /* Set runchroot callback. */
469
20.4k
    sudo_defs_table[I_RUNCHROOT].callback = cb_runchroot;
470
471
    /* eventlog callbacks */
472
20.4k
    sudo_defs_table[I_SYSLOG].callback = cb_syslog;
473
20.4k
    sudo_defs_table[I_SYSLOG_GOODPRI].callback = cb_syslog_goodpri;
474
20.4k
    sudo_defs_table[I_SYSLOG_BADPRI].callback = cb_syslog_badpri;
475
20.4k
    sudo_defs_table[I_SYSLOG_MAXLEN].callback = cb_syslog_maxlen;
476
20.4k
    sudo_defs_table[I_LOGLINELEN].callback = cb_loglinelen;
477
20.4k
    sudo_defs_table[I_LOG_HOST].callback = cb_log_host;
478
20.4k
    sudo_defs_table[I_LOGFILE].callback = cb_logfile;
479
20.4k
    sudo_defs_table[I_LOG_FORMAT].callback = cb_log_format;
480
20.4k
    sudo_defs_table[I_LOG_YEAR].callback = cb_log_year;
481
20.4k
    sudo_defs_table[I_MAILERPATH].callback = cb_mailerpath;
482
20.4k
    sudo_defs_table[I_MAILERFLAGS].callback = cb_mailerflags;
483
20.4k
    sudo_defs_table[I_MAILFROM].callback = cb_mailfrom;
484
20.4k
    sudo_defs_table[I_MAILTO].callback = cb_mailto;
485
20.4k
    sudo_defs_table[I_MAILSUB].callback = cb_mailsub;
486
20.4k
    sudo_defs_table[I_PASSPROMPT_REGEX].callback = cb_passprompt_regex;
487
20.4k
    sudo_defs_table[I_INTERCEPT_TYPE].callback = cb_intercept_type;
488
20.4k
    sudo_defs_table[I_INTERCEPT_ALLOW_SETID].callback = cb_intercept_allow_setid;
489
20.4k
    sudo_defs_table[I_LOG_INPUT].callback = cb_log_input;
490
20.4k
    sudo_defs_table[I_LOG_OUTPUT].callback = cb_log_output;
491
492
20.4k
    debug_return;
493
20.4k
}
494
495
bool
496
sudoers_override_umask(void)
497
13.3k
{
498
13.3k
    return override_umask;
499
13.3k
}