Coverage Report

Created: 2025-07-11 06:58

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