]> granicus.if.org Git - sudo/blob - plugins/sudoers/sudoers.c
Add SPDX-License-Identifier to files.
[sudo] / plugins / sudoers / sudoers.c
1 /*
2  * SPDX-License-Identifier: ISC
3  *
4  * Copyright (c) 1993-1996, 1998-2019 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  * Sponsored in part by the Defense Advanced Research Projects
19  * Agency (DARPA) and Air Force Research Laboratory, Air Force
20  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
21  */
22
23 /*
24  * This is an open source non-commercial project. Dear PVS-Studio, please check it.
25  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
26  */
27
28 #ifdef __TANDEM
29 # include <floss.h>
30 #endif
31
32 #include <config.h>
33
34 #include <sys/types.h>
35 #include <sys/resource.h>
36 #include <sys/stat.h>
37 #include <sys/socket.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #ifdef HAVE_STRING_H
41 # include <string.h>
42 #endif /* HAVE_STRING_H */
43 #ifdef HAVE_STRINGS_H
44 # include <strings.h>
45 #endif /* HAVE_STRINGS_H */
46 #include <unistd.h>
47 #include <pwd.h>
48 #include <errno.h>
49 #include <fcntl.h>
50 #include <signal.h>
51 #include <grp.h>
52 #include <time.h>
53 #include <netdb.h>
54 #ifdef HAVE_LOGIN_CAP_H
55 # include <login_cap.h>
56 # ifndef LOGIN_DEFROOTCLASS
57 #  define LOGIN_DEFROOTCLASS    "daemon"
58 # endif
59 # ifndef LOGIN_SETENV
60 #  define LOGIN_SETENV  0
61 # endif
62 #endif
63 #ifdef HAVE_SELINUX
64 # include <selinux/selinux.h>
65 #endif
66 #include <ctype.h>
67
68 #include "sudoers.h"
69 #include "parse.h"
70 #include "auth/sudo_auth.h"
71
72 #ifndef HAVE_GETADDRINFO
73 # include "compat/getaddrinfo.h"
74 #endif
75
76 /*
77  * Prototypes
78  */
79 static bool cb_fqdn(const union sudo_defs_val *);
80 static bool cb_runas_default(const union sudo_defs_val *);
81 static bool cb_tty_tickets(const union sudo_defs_val *);
82 static int set_cmnd(void);
83 static int create_admin_success_flag(void);
84 static bool init_vars(char * const *);
85 static bool set_loginclass(struct passwd *);
86 static bool set_runasgr(const char *, bool);
87 static bool set_runaspw(const char *, bool);
88 static bool tty_present(void);
89
90 /*
91  * Globals
92  */
93 struct sudo_user sudo_user;
94 struct passwd *list_pw;
95 uid_t timestamp_uid;
96 gid_t timestamp_gid;
97 #ifdef HAVE_BSD_AUTH_H
98 char *login_style;
99 #endif /* HAVE_BSD_AUTH_H */
100 int sudo_mode;
101
102 static char *prev_user;
103 static char *runas_user;
104 static char *runas_group;
105 static struct sudo_nss_list *snl;
106
107 #ifdef __linux__
108 static struct rlimit nproclimit;
109 #endif
110
111 /* XXX - must be extern for audit bits of sudo_auth.c */
112 int NewArgc;
113 char **NewArgv;
114
115 /*
116  * Unlimit the number of processes since Linux's setuid() will
117  * apply resource limits when changing uid and return EAGAIN if
118  * nproc would be exceeded by the uid switch.
119  */
120 static void
121 unlimit_nproc(void)
122 {
123 #ifdef __linux__
124     struct rlimit rl;
125     debug_decl(unlimit_nproc, SUDOERS_DEBUG_UTIL)
126
127     if (getrlimit(RLIMIT_NPROC, &nproclimit) != 0)
128             sudo_warn("getrlimit");
129     rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
130     if (setrlimit(RLIMIT_NPROC, &rl) != 0) {
131         rl.rlim_cur = rl.rlim_max = nproclimit.rlim_max;
132         if (setrlimit(RLIMIT_NPROC, &rl) != 0)
133             sudo_warn("setrlimit");
134     }
135     debug_return;
136 #endif /* __linux__ */
137 }
138
139 /*
140  * Restore saved value of RLIMIT_NPROC.
141  */
142 static void
143 restore_nproc(void)
144 {
145 #ifdef __linux__
146     debug_decl(restore_nproc, SUDOERS_DEBUG_UTIL)
147
148     if (setrlimit(RLIMIT_NPROC, &nproclimit) != 0)
149         sudo_warn("setrlimit");
150
151     debug_return;
152 #endif /* __linux__ */
153 }
154
155 int
156 sudoers_policy_init(void *info, char * const envp[])
157 {
158     struct sudo_nss *nss, *nss_next;
159     int oldlocale, sources = 0;
160     int ret = -1;
161     debug_decl(sudoers_policy_init, SUDOERS_DEBUG_PLUGIN)
162
163     bindtextdomain("sudoers", LOCALEDIR);
164
165     /* Register fatal/fatalx callback. */
166     sudo_fatal_callback_register(sudoers_cleanup);
167
168     /* Initialize environment functions (including replacements). */
169     if (!env_init(envp))
170         debug_return_int(-1);
171
172     /* Setup defaults data structures. */
173     if (!init_defaults()) {
174         sudo_warnx(U_("unable to initialize sudoers default values"));
175         debug_return_int(-1);
176     }
177
178     /* Parse info from front-end. */
179     sudo_mode = sudoers_policy_deserialize_info(info, &runas_user, &runas_group);
180     if (ISSET(sudo_mode, MODE_ERROR))
181         debug_return_int(-1);
182
183     if (!init_vars(envp))
184         debug_return_int(-1);
185
186     /* Parse nsswitch.conf for sudoers order. */
187     snl = sudo_read_nss();
188
189     /* LDAP or NSS may modify the euid so we need to be root for the open. */
190     if (!set_perms(PERM_ROOT))
191         debug_return_int(-1);
192
193     /*
194      * Open and parse sudoers, set global defaults.
195      * Uses the C locale unless another is specified in sudoers.
196      */
197     sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
198     sudo_warn_set_locale_func(sudoers_warn_setlocale);
199     init_parser(sudoers_file, false);
200     TAILQ_FOREACH_SAFE(nss, snl, entries, nss_next) {
201         if (nss->open(nss) == -1 || (nss->parse_tree = nss->parse(nss)) == NULL) {
202             TAILQ_REMOVE(snl, nss, entries);
203             continue;
204         }
205
206         sources++;
207         if (nss->getdefs(nss) == -1 || !update_defaults(nss->parse_tree, NULL,
208             SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER|SETDEF_RUNAS, false)) {
209             log_warningx(SLOG_SEND_MAIL|SLOG_NO_STDERR,
210                 N_("problem with defaults entries"));
211         }
212     }
213     if (sources == 0) {
214         sudo_warnx(U_("no valid sudoers sources found, quitting"));
215         goto cleanup;
216     }
217
218     /* Set login class if applicable (after sudoers is parsed). */
219     if (set_loginclass(runas_pw ? runas_pw : sudo_user.pw))
220         ret = true;
221
222 cleanup:
223     if (!restore_perms())
224         ret = -1;
225
226     /* Restore user's locale. */
227     sudo_warn_set_locale_func(NULL);
228     sudoers_setlocale(oldlocale, NULL);
229
230     debug_return_int(ret);
231 }
232
233 int
234 sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
235     bool verbose, void *closure)
236 {
237     char **edit_argv = NULL;
238     char *iolog_path = NULL;
239     mode_t cmnd_umask = ACCESSPERMS;
240     struct sudo_nss *nss;
241     int cmnd_status = -1, oldlocale, validated;
242     int ret = -1;
243     debug_decl(sudoers_policy_main, SUDOERS_DEBUG_PLUGIN)
244
245     sudo_warn_set_locale_func(sudoers_warn_setlocale);
246
247     unlimit_nproc();
248
249     /* Is root even allowed to run sudo? */
250     if (user_uid == 0 && !def_root_sudo) {
251         /* Not an audit event. */
252         sudo_warnx(U_("sudoers specifies that root is not allowed to sudo"));
253         goto bad;
254     }    
255
256     if (!set_perms(PERM_INITIAL))
257         goto bad;
258
259     /* Environment variables specified on the command line. */
260     if (env_add != NULL && env_add[0] != NULL)
261         sudo_user.env_vars = env_add;
262
263     /*
264      * Make a local copy of argc/argv, with special handling
265      * for pseudo-commands and the '-i' option.
266      */
267     if (argc == 0) {
268         NewArgc = 1;
269         NewArgv = reallocarray(NULL, NewArgc + 1, sizeof(char *));
270         if (NewArgv == NULL) {
271             sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
272             goto done;
273         }
274         NewArgv[0] = user_cmnd;
275         NewArgv[1] = NULL;
276     } else {
277         /* Must leave an extra slot before NewArgv for bash's --login */
278         NewArgc = argc;
279         NewArgv = reallocarray(NULL, NewArgc + 2, sizeof(char *));
280         if (NewArgv == NULL) {
281             sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
282             goto done;
283         }
284         NewArgv++;      /* reserve an extra slot for --login */
285         memcpy(NewArgv, argv, argc * sizeof(char *));
286         NewArgv[NewArgc] = NULL;
287         if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && runas_pw != NULL) {
288             NewArgv[0] = strdup(runas_pw->pw_shell);
289             if (NewArgv[0] == NULL) {
290                 sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
291                 free(NewArgv);
292                 goto done;
293             }
294         }
295     }
296
297     /* If given the -P option, set the "preserve_groups" flag. */
298     if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
299         def_preserve_groups = true;
300
301     /* Find command in path and apply per-command Defaults. */
302     cmnd_status = set_cmnd();
303     if (cmnd_status == NOT_FOUND_ERROR)
304         goto done;
305
306     /* Check for -C overriding def_closefrom. */
307     if (user_closefrom >= 0 && user_closefrom != def_closefrom) {
308         if (!def_closefrom_override) {
309             /* XXX - audit? */
310             sudo_warnx(U_("you are not permitted to use the -C option"));
311             goto bad;
312         }
313         def_closefrom = user_closefrom;
314     }
315
316     /*
317      * Check sudoers sources, using the locale specified in sudoers.
318      */
319     sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
320     validated = sudoers_lookup(snl, sudo_user.pw, FLAG_NO_USER | FLAG_NO_HOST,
321         pwflag);
322     if (ISSET(validated, VALIDATE_ERROR)) {
323         /* The lookup function should have printed an error. */
324         goto done;
325     }
326
327     /* Restore user's locale. */
328     sudoers_setlocale(oldlocale, NULL);
329
330     if (safe_cmnd == NULL) {
331         if ((safe_cmnd = strdup(user_cmnd)) == NULL) {
332             sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
333             goto done;
334         }
335     }
336
337     /*
338      * Look up the timestamp dir owner if one is specified.
339      */
340     if (def_timestampowner) {
341         struct passwd *pw = NULL;
342
343         if (*def_timestampowner == '#') {
344             const char *errstr;
345             uid_t uid = sudo_strtoid(def_timestampowner + 1, NULL, NULL, &errstr);
346             if (errstr == NULL)
347                 pw = sudo_getpwuid(uid);
348         }
349         if (pw == NULL)
350             pw = sudo_getpwnam(def_timestampowner);
351         if (pw != NULL) {
352             timestamp_uid = pw->pw_uid;
353             timestamp_gid = pw->pw_gid;
354             sudo_pw_delref(pw);
355         } else {
356             log_warningx(SLOG_SEND_MAIL,
357                 N_("timestamp owner (%s): No such user"), def_timestampowner);
358             timestamp_uid = ROOT_UID;
359             timestamp_gid = ROOT_GID;
360         }
361     }
362
363     /* If no command line args and "shell_noargs" is not set, error out. */
364     if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) {
365         /* Not an audit event. */
366         ret = -2; /* usage error */
367         goto done;
368     }
369
370     /* Bail if a tty is required and we don't have one.  */
371     if (def_requiretty && !tty_present()) {
372         audit_failure(NewArgc, NewArgv, N_("no tty"));
373         sudo_warnx(U_("sorry, you must have a tty to run sudo"));
374         goto bad;
375     }
376
377     /*
378      * We don't reset the environment for sudoedit or if the user
379      * specified the -E command line flag and they have setenv privs.
380      */
381     if (ISSET(sudo_mode, MODE_EDIT) ||
382         (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv))
383         def_env_reset = false;
384
385     /* Build a new environment that avoids any nasty bits. */
386     if (!rebuild_env())
387         goto bad;
388
389     /* Require a password if sudoers says so.  */
390     switch (check_user(validated, sudo_mode)) {
391     case true:
392         /* user authenticated successfully. */
393         break;
394     case false:
395         /* Note: log_denial() calls audit for us. */
396         if (!ISSET(validated, VALIDATE_SUCCESS)) {
397             /* Only display a denial message if no password was read. */
398             if (!log_denial(validated, def_passwd_tries <= 0))
399                 goto done;
400         }
401         goto bad;
402     default:
403         /* some other error, ret is -1. */
404         goto done;
405     }
406
407     /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
408     /* XXX - causes confusion when root is not listed in sudoers */
409     if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) {
410         if (user_uid == 0 && strcmp(prev_user, "root") != 0) {
411             struct passwd *pw;
412
413             if ((pw = sudo_getpwnam(prev_user)) != NULL) {
414                     if (sudo_user.pw != NULL)
415                         sudo_pw_delref(sudo_user.pw);
416                     sudo_user.pw = pw;
417             }
418         }
419     }
420
421     /* If the user was not allowed to run the command we are done. */
422     if (!ISSET(validated, VALIDATE_SUCCESS)) {
423         /* Note: log_failure() calls audit for us. */
424         if (!log_failure(validated, cmnd_status))
425             goto done;
426         goto bad;
427     }
428
429     /* Create Ubuntu-style dot file to indicate sudo was successful. */
430     if (create_admin_success_flag() == -1)
431         goto done;
432
433     /* Finally tell the user if the command did not exist. */
434     if (cmnd_status == NOT_FOUND_DOT) {
435         audit_failure(NewArgc, NewArgv, N_("command in current directory"));
436         sudo_warnx(U_("ignoring \"%s\" found in '.'\nUse \"sudo ./%s\" if this is the \"%s\" you wish to run."), user_cmnd, user_cmnd, user_cmnd);
437         goto bad;
438     } else if (cmnd_status == NOT_FOUND) {
439         if (ISSET(sudo_mode, MODE_CHECK)) {
440             audit_failure(NewArgc, NewArgv, N_("%s: command not found"),
441                 NewArgv[0]);
442             sudo_warnx(U_("%s: command not found"), NewArgv[0]);
443         } else {
444             audit_failure(NewArgc, NewArgv, N_("%s: command not found"),
445                 user_cmnd);
446             sudo_warnx(U_("%s: command not found"), user_cmnd);
447         }
448         goto bad;
449     }
450
451     /* If user specified a timeout make sure sudoers allows it. */
452     if (!def_user_command_timeouts && user_timeout > 0) {
453         /* XXX - audit/log? */
454         sudo_warnx(U_("sorry, you are not allowed set a command timeout"));
455         goto bad;
456     }
457
458     /* If user specified env vars make sure sudoers allows it. */
459     if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) {
460         if (ISSET(sudo_mode, MODE_PRESERVE_ENV)) {
461             /* XXX - audit/log? */
462             sudo_warnx(U_("sorry, you are not allowed to preserve the environment"));
463             goto bad;
464         } else {
465             if (!validate_env_vars(sudo_user.env_vars))
466                 goto bad;
467         }
468     }
469
470     if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT))) {
471         if ((def_log_input || def_log_output) && def_iolog_file && def_iolog_dir) {
472             const char prefix[] = "iolog_path=";
473             iolog_path = expand_iolog_path(prefix, def_iolog_dir,
474                 def_iolog_file, &sudo_user.iolog_file);
475             if (iolog_path == NULL) {
476                 if (!def_ignore_iolog_errors)
477                     goto done;
478                 /* Unable to expand I/O log path, disable I/O logging. */
479                 def_log_input = false;
480                 def_log_output = false;
481             } else {
482                 sudo_user.iolog_file++;
483             }
484         }
485     }
486
487     if (!log_allowed(validated) && !def_ignore_logfile_errors)
488         goto bad;
489
490     switch (sudo_mode & MODE_MASK) {
491         case MODE_CHECK:
492             ret = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
493             break;
494         case MODE_LIST:
495             ret = display_privs(snl, list_pw ? list_pw : sudo_user.pw, verbose);
496             break;
497         case MODE_VALIDATE:
498             /* Nothing to do. */
499             ret = true;
500             break;
501         case MODE_RUN:
502         case MODE_EDIT:
503             /* ret set by sudoers_policy_exec_setup() below. */
504             break;
505         default:
506             /* Should not happen. */
507             sudo_warnx("internal error, unexpected sudo mode 0x%x", sudo_mode);
508             goto done;
509     }
510
511     /* Cleanup sudoers sources */
512     TAILQ_FOREACH(nss, snl, entries) {
513         nss->close(nss);
514     }
515     if (def_group_plugin)
516         group_plugin_unload();
517     init_parser(NULL, false);
518
519     if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) {
520         /* ret already set appropriately */
521         goto done;
522     }
523
524     /*
525      * Set umask based on sudoers.
526      * If user's umask is more restrictive, OR in those bits too
527      * unless umask_override is set.
528      */
529     if (def_umask != ACCESSPERMS) {
530         cmnd_umask = def_umask;
531         if (!def_umask_override)
532             cmnd_umask |= user_umask;
533     }
534
535     if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
536         char *p;
537
538         /* Convert /bin/sh -> -sh so shell knows it is a login shell */
539         if ((p = strrchr(NewArgv[0], '/')) == NULL)
540             p = NewArgv[0];
541         *p = '-';
542         NewArgv[0] = p;
543
544         /*
545          * Newer versions of bash require the --login option to be used
546          * in conjunction with the -c option even if the shell name starts
547          * with a '-'.  Unfortunately, bash 1.x uses -login, not --login
548          * so this will cause an error for that.
549          */
550         if (NewArgc > 1 && strcmp(NewArgv[0], "-bash") == 0 &&
551             strcmp(NewArgv[1], "-c") == 0) {
552             /* Use the extra slot before NewArgv so we can store --login. */
553             NewArgv--;
554             NewArgc++;
555             NewArgv[0] = NewArgv[1];
556             NewArgv[1] = "--login";
557         }
558
559 #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM))
560         /* Insert system-wide environment variables. */
561         if (!read_env_file(_PATH_ENVIRONMENT, true, false))
562             sudo_warn("%s", _PATH_ENVIRONMENT);
563 #endif
564 #ifdef HAVE_LOGIN_CAP_H
565         /* Set environment based on login class. */
566         if (login_class) {
567             login_cap_t *lc = login_getclass(login_class);
568             if (lc != NULL) {
569                 setusercontext(lc, runas_pw, runas_pw->pw_uid, LOGIN_SETPATH|LOGIN_SETENV);
570                 login_close(lc);
571             }
572         }
573 #endif /* HAVE_LOGIN_CAP_H */
574     }
575
576     /* Insert system-wide environment variables. */
577     if (def_restricted_env_file) {
578         if (!read_env_file(def_restricted_env_file, false, true))
579             sudo_warn("%s", def_restricted_env_file);
580     }
581     if (def_env_file) {
582         if (!read_env_file(def_env_file, false, false))
583             sudo_warn("%s", def_env_file);
584     }
585
586     /* Insert user-specified environment variables. */
587     if (!insert_env_vars(sudo_user.env_vars))
588         goto done;
589
590     /* Note: must call audit before uid change. */
591     if (ISSET(sudo_mode, MODE_EDIT)) {
592         int edit_argc;
593         const char *env_editor;
594
595         free(safe_cmnd);
596         safe_cmnd = find_editor(NewArgc - 1, NewArgv + 1, &edit_argc,
597             &edit_argv, NULL, &env_editor, false);
598         if (safe_cmnd == NULL) {
599             if (errno != ENOENT)
600                 goto done;
601             audit_failure(NewArgc, NewArgv, N_("%s: command not found"),
602                 env_editor ? env_editor : def_editor);
603             sudo_warnx(U_("%s: command not found"),
604                 env_editor ? env_editor : def_editor);
605             goto bad;
606         }
607         if (audit_success(edit_argc, edit_argv) != 0 && !def_ignore_audit_errors)
608             goto done;
609
610         /* We want to run the editor with the unmodified environment. */
611         env_swap_old();
612     } else {
613         if (audit_success(NewArgc, NewArgv) != 0 && !def_ignore_audit_errors)
614             goto done;
615     }
616
617     /* Setup execution environment to pass back to front-end. */
618     ret = sudoers_policy_exec_setup(edit_argv ? edit_argv : NewArgv,
619         env_get(), cmnd_umask, iolog_path, closure);
620
621     /* Zero out stashed copy of environment, it is owned by the front-end. */
622     (void)env_init(NULL);
623
624     goto done;
625
626 bad:
627     ret = false;
628
629 done:
630     if (!rewind_perms())
631         ret = -1;
632
633     restore_nproc();
634
635     /* Destroy the password and group caches and free the contents. */
636     sudo_freepwcache();
637     sudo_freegrcache();
638
639     sudo_warn_set_locale_func(NULL);
640
641     debug_return_int(ret);
642 }
643
644 /*
645  * Initialize timezone and fill in sudo_user struct.
646  */
647 static bool
648 init_vars(char * const envp[])
649 {
650     char * const * ep;
651     bool unknown_user = false;
652     debug_decl(init_vars, SUDOERS_DEBUG_PLUGIN)
653
654     if (!sudoers_initlocale(setlocale(LC_ALL, NULL), def_sudoers_locale)) {
655         sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
656         debug_return_bool(false);
657     }
658
659 #define MATCHES(s, v)   \
660     (strncmp((s), (v), sizeof(v) - 1) == 0 && (s)[sizeof(v) - 1] != '\0')
661
662     for (ep = envp; *ep; ep++) {
663         switch (**ep) {
664             case 'K':
665                 if (MATCHES(*ep, "KRB5CCNAME="))
666                     user_ccname = *ep + sizeof("KRB5CCNAME=") - 1;
667                 break;
668             case 'P':
669                 if (MATCHES(*ep, "PATH="))
670                     user_path = *ep + sizeof("PATH=") - 1;
671                 break;
672             case 'S':
673                 if (MATCHES(*ep, "SUDO_PROMPT=")) {
674                     /* Don't override "sudo -p prompt" */
675                     if (user_prompt == NULL)
676                         user_prompt = *ep + sizeof("SUDO_PROMPT=") - 1;
677                     break;
678                 }
679                 if (MATCHES(*ep, "SUDO_USER="))
680                     prev_user = *ep + sizeof("SUDO_USER=") - 1;
681                 break;
682             }
683     }
684 #undef MATCHES
685
686     /*
687      * Get a local copy of the user's passwd struct and group list if we
688      * don't already have them.
689      */
690     if (sudo_user.pw == NULL) {
691         if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL) {
692             /*
693              * It is not unusual for users to place "sudo -k" in a .logout
694              * file which can cause sudo to be run during reboot after the
695              * YP/NIS/NIS+/LDAP/etc daemon has died.
696              */
697             if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) {
698                 sudo_warnx(U_("unknown uid: %u"), (unsigned int) user_uid);
699                 debug_return_bool(false);
700             }
701
702             /* Need to make a fake struct passwd for the call to log_warningx(). */
703             sudo_user.pw = sudo_mkpwent(user_name, user_uid, user_gid, NULL, NULL);
704             unknown_user = true;
705         }
706     }
707     if (user_gid_list == NULL)
708         user_gid_list = sudo_get_gidlist(sudo_user.pw, ENTRY_TYPE_ANY);
709
710     /* Store initialize permissions so we can restore them later. */
711     if (!set_perms(PERM_INITIAL))
712         debug_return_bool(false);
713
714     /* Set fqdn callback. */
715     sudo_defs_table[I_FQDN].callback = cb_fqdn;
716
717     /* Set group_plugin callback. */
718     sudo_defs_table[I_GROUP_PLUGIN].callback = cb_group_plugin;
719
720     /* Set runas callback. */
721     sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default;
722
723     /* Set locale callback. */
724     sudo_defs_table[I_SUDOERS_LOCALE].callback = sudoers_locale_callback;
725
726     /* Set maxseq callback. */
727     sudo_defs_table[I_MAXSEQ].callback = cb_maxseq;
728
729     /* Set iolog_user callback. */
730     sudo_defs_table[I_IOLOG_USER].callback = cb_iolog_user;
731
732     /* Set iolog_group callback. */
733     sudo_defs_table[I_IOLOG_GROUP].callback = cb_iolog_group;
734
735     /* Set iolog_mode callback. */
736     sudo_defs_table[I_IOLOG_MODE].callback = cb_iolog_mode;
737
738     /* Set tty_tickets callback. */
739     sudo_defs_table[I_TTY_TICKETS].callback = cb_tty_tickets;
740
741     /* It is now safe to use log_warningx() and set_perms() */
742     if (unknown_user) {
743         log_warningx(SLOG_SEND_MAIL, N_("unknown uid: %u"),
744             (unsigned int) user_uid);
745         debug_return_bool(false);
746     }
747
748     /*
749      * Set runas passwd/group entries based on command line or sudoers.
750      * Note that if runas_group was specified without runas_user we
751      * run the command as the invoking user.
752      */
753     if (runas_group != NULL) {
754         if (!set_runasgr(runas_group, false))
755             debug_return_bool(false);
756         if (!set_runaspw(runas_user ? runas_user : user_name, false))
757             debug_return_bool(false);
758     } else {
759         if (!set_runaspw(runas_user ? runas_user : def_runas_default, false))
760             debug_return_bool(false);
761     }
762
763     debug_return_bool(true);
764 }
765
766 /*
767  * Fill in user_cmnd, user_args, user_base and user_stat variables
768  * and apply any command-specific defaults entries.
769  */
770 static int
771 set_cmnd(void)
772 {
773     struct sudo_nss *nss;
774     char *path = user_path;
775     int ret = FOUND;
776     debug_decl(set_cmnd, SUDOERS_DEBUG_PLUGIN)
777
778     /* Allocate user_stat for find_path() and match functions. */
779     user_stat = calloc(1, sizeof(struct stat));
780     if (user_stat == NULL) {
781         sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
782         debug_return_int(NOT_FOUND_ERROR);
783     }
784
785     /* Default value for cmnd, overridden below. */
786     if (user_cmnd == NULL)
787         user_cmnd = NewArgv[0];
788
789     if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
790         if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
791             if (def_secure_path && !user_is_exempt())
792                 path = def_secure_path;
793             if (!set_perms(PERM_RUNAS))
794                 debug_return_int(-1);
795             ret = find_path(NewArgv[0], &user_cmnd, user_stat, path,
796                 def_ignore_dot, NULL);
797             if (!restore_perms())
798                 debug_return_int(-1);
799             if (ret == NOT_FOUND) {
800                 /* Failed as root, try as invoking user. */
801                 if (!set_perms(PERM_USER))
802                     debug_return_int(-1);
803                 ret = find_path(NewArgv[0], &user_cmnd, user_stat, path,
804                     def_ignore_dot, NULL);
805                 if (!restore_perms())
806                     debug_return_int(-1);
807             }
808             if (ret == NOT_FOUND_ERROR) {
809                 if (errno == ENAMETOOLONG)
810                     audit_failure(NewArgc, NewArgv, N_("command too long"));
811                 log_warning(0, "%s", NewArgv[0]);
812                 debug_return_int(ret);
813             }
814         }
815
816         /* set user_args */
817         if (NewArgc > 1) {
818             char *to, *from, **av;
819             size_t size, n;
820
821             /* Alloc and build up user_args. */
822             for (size = 0, av = NewArgv + 1; *av; av++)
823                 size += strlen(*av) + 1;
824             if (size == 0 || (user_args = malloc(size)) == NULL) {
825                 sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
826                 debug_return_int(-1);
827             }
828             if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
829                 /*
830                  * When running a command via a shell, the sudo front-end
831                  * escapes potential meta chars.  We unescape non-spaces
832                  * for sudoers matching and logging purposes.
833                  */
834                 for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
835                     while (*from) {
836                         if (from[0] == '\\' && !isspace((unsigned char)from[1]))
837                             from++;
838                         *to++ = *from++;
839                     }
840                     *to++ = ' ';
841                 }
842                 *--to = '\0';
843             } else {
844                 for (to = user_args, av = NewArgv + 1; *av; av++) {
845                     n = strlcpy(to, *av, size - (to - user_args));
846                     if (n >= size - (to - user_args)) {
847                         sudo_warnx(U_("internal error, %s overflow"), __func__);
848                         debug_return_int(-1);
849                     }
850                     to += n;
851                     *to++ = ' ';
852                 }
853                 *--to = '\0';
854             }
855         }
856     }
857
858     if ((user_base = strrchr(user_cmnd, '/')) != NULL)
859         user_base++;
860     else
861         user_base = user_cmnd;
862
863     TAILQ_FOREACH(nss, snl, entries) {
864         if (!update_defaults(nss->parse_tree, NULL, SETDEF_CMND, false)) {
865             log_warningx(SLOG_SEND_MAIL|SLOG_NO_STDERR,
866                 N_("problem with defaults entries"));
867         }
868     }
869
870     debug_return_int(ret);
871 }
872
873 /*
874  * Open sudoers and sanity check mode/owner/type.
875  * Returns a handle to the sudoers file or NULL on error.
876  */
877 FILE *
878 open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
879 {
880     struct stat sb;
881     FILE *fp = NULL;
882     debug_decl(open_sudoers, SUDOERS_DEBUG_PLUGIN)
883
884     if (!set_perms(PERM_SUDOERS))
885         debug_return_ptr(NULL);
886
887     switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) {
888         case SUDO_PATH_SECURE:
889             /*
890              * If we are expecting sudoers to be group readable by
891              * SUDOERS_GID but it is not, we must open the file as root,
892              * not uid 1.
893              */
894             if (sudoers_uid == ROOT_UID && ISSET(sudoers_mode, S_IRGRP)) {
895                 if (!ISSET(sb.st_mode, S_IRGRP) || sb.st_gid != SUDOERS_GID) {
896                     if (!restore_perms() || !set_perms(PERM_ROOT))
897                         debug_return_ptr(NULL);
898                 }
899             }
900             /*
901              * Open sudoers and make sure we can read it so we can present
902              * the user with a reasonable error message (unlike the lexer).
903              */
904             if ((fp = fopen(sudoers, "r")) == NULL) {
905                 log_warning(SLOG_SEND_MAIL, N_("unable to open %s"), sudoers);
906             } else {
907                 if (sb.st_size != 0 && fgetc(fp) == EOF) {
908                     log_warning(SLOG_SEND_MAIL,
909                         N_("unable to read %s"), sudoers);
910                     fclose(fp);
911                     fp = NULL;
912                 } else {
913                     /* Rewind fp and set close on exec flag. */
914                     rewind(fp);
915                     (void) fcntl(fileno(fp), F_SETFD, 1);
916                 }
917             }
918             break;
919         case SUDO_PATH_MISSING:
920             log_warning(SLOG_SEND_MAIL, N_("unable to stat %s"), sudoers);
921             break;
922         case SUDO_PATH_BAD_TYPE:
923             log_warningx(SLOG_SEND_MAIL,
924                 N_("%s is not a regular file"), sudoers);
925             break;
926         case SUDO_PATH_WRONG_OWNER:
927             log_warningx(SLOG_SEND_MAIL,
928                 N_("%s is owned by uid %u, should be %u"), sudoers,
929                 (unsigned int) sb.st_uid, (unsigned int) sudoers_uid);
930             break;
931         case SUDO_PATH_WORLD_WRITABLE:
932             log_warningx(SLOG_SEND_MAIL, N_("%s is world writable"), sudoers);
933             break;
934         case SUDO_PATH_GROUP_WRITABLE:
935             log_warningx(SLOG_SEND_MAIL,
936                 N_("%s is owned by gid %u, should be %u"), sudoers,
937                 (unsigned int) sb.st_gid, (unsigned int) sudoers_gid);
938             break;
939         default:
940             /* NOTREACHED */
941             break;
942     }
943
944     if (!restore_perms()) {
945         /* unable to change back to root */
946         if (fp != NULL) {
947             fclose(fp);
948             fp = NULL;
949         }
950     }
951
952     debug_return_ptr(fp);
953 }
954
955 #ifdef HAVE_LOGIN_CAP_H
956 static bool
957 set_loginclass(struct passwd *pw)
958 {
959     const int errflags = SLOG_RAW_MSG;
960     login_cap_t *lc;
961     bool ret = true;
962     debug_decl(set_loginclass, SUDOERS_DEBUG_PLUGIN)
963
964     if (!def_use_loginclass)
965         goto done;
966
967     if (login_class && strcmp(login_class, "-") != 0) {
968         if (user_uid != 0 && pw->pw_uid != 0) {
969             sudo_warnx(U_("only root can use \"-c %s\""), login_class);
970             ret = false;
971             goto done;
972         }
973     } else {
974         login_class = pw->pw_class;
975         if (!login_class || !*login_class)
976             login_class =
977                 (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
978     }
979
980     /* Make sure specified login class is valid. */
981     lc = login_getclass(login_class);
982     if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
983         /*
984          * Don't make it an error if the user didn't specify the login
985          * class themselves.  We do this because if login.conf gets
986          * corrupted we want the admin to be able to use sudo to fix it.
987          */
988         log_warningx(errflags, N_("unknown login class: %s"), login_class);
989         def_use_loginclass = false;
990         if (login_class)
991             ret = false;
992     }
993     login_close(lc);
994 done:
995     debug_return_bool(ret);
996 }
997 #else
998 static bool
999 set_loginclass(struct passwd *pw)
1000 {
1001     return true;
1002 }
1003 #endif /* HAVE_LOGIN_CAP_H */
1004
1005 #ifndef AI_FQDN
1006 # define AI_FQDN AI_CANONNAME
1007 #endif
1008
1009 /*
1010  * Look up the fully qualified domain name of host.
1011  * Use AI_FQDN if available since "canonical" is not always the same as fqdn.
1012  * Returns true on success, setting longp and shortp.
1013  * Returns false on failure, longp and shortp are unchanged.
1014  */
1015 static int
1016 resolve_host(const char *host, char **longp, char **shortp)
1017 {
1018     struct addrinfo *res0, hint;
1019     char *cp, *lname, *sname;
1020     int ret;
1021     debug_decl(resolve_host, SUDOERS_DEBUG_PLUGIN)
1022
1023     memset(&hint, 0, sizeof(hint));
1024     hint.ai_family = PF_UNSPEC;
1025     hint.ai_flags = AI_FQDN;
1026
1027     if ((ret = getaddrinfo(host, NULL, &hint, &res0)) != 0)
1028         debug_return_int(ret);
1029     if ((lname = strdup(res0->ai_canonname)) == NULL) {
1030         freeaddrinfo(res0);
1031         debug_return_int(EAI_MEMORY);
1032     }
1033     if ((cp = strchr(lname, '.')) != NULL) {
1034         sname = strndup(lname, (size_t)(cp - lname));
1035         if (sname == NULL) {
1036             free(lname);
1037             freeaddrinfo(res0);
1038             debug_return_int(EAI_MEMORY);
1039         }
1040     } else {
1041         sname = lname;
1042     }
1043     freeaddrinfo(res0);
1044     *longp = lname;
1045     *shortp = sname;
1046
1047     debug_return_int(0);
1048 }
1049
1050 /*
1051  * Look up the fully qualified domain name of user_host and user_runhost.
1052  * Sets user_host, user_shost, user_runhost and user_srunhost.
1053  */
1054 static bool
1055 cb_fqdn(const union sudo_defs_val *sd_un)
1056 {
1057     bool remote;
1058     char *lhost, *shost;
1059     debug_decl(cb_fqdn, SUDOERS_DEBUG_PLUGIN)
1060
1061     /* Nothing to do if fqdn flag is disabled. */
1062     if (sd_un != NULL && !sd_un->flag)
1063         debug_return_bool(true);
1064
1065     /* If the -h flag was given we need to resolve both host and runhost. */
1066     remote = strcmp(user_runhost, user_host) != 0;
1067
1068     /* First resolve user_host, setting user_host and user_shost. */
1069     if (resolve_host(user_host, &lhost, &shost) != 0) {
1070         int rc = resolve_host(user_runhost, &lhost, &shost);
1071         if (rc != 0) {
1072             gai_log_warning(SLOG_SEND_MAIL|SLOG_RAW_MSG, rc,
1073                 N_("unable to resolve host %s"), user_host);
1074             debug_return_bool(false);
1075         }
1076     }
1077     if (user_shost != user_host)
1078         free(user_shost);
1079     free(user_host);
1080     user_host = lhost;
1081     user_shost = shost;
1082
1083     /* Next resolve user_runhost, setting user_runhost and user_srunhost. */
1084     lhost = shost = NULL;
1085     if (remote) {
1086         if (!resolve_host(user_runhost, &lhost, &shost)) {
1087             sudo_warnx(U_("unable to resolve host %s"), user_runhost);
1088         }
1089     } else {
1090         /* Not remote, just use user_host. */
1091         if ((lhost = strdup(user_host)) != NULL) {
1092             if (user_shost != user_host)
1093                 shost = strdup(user_shost);
1094             else
1095                 shost = lhost;
1096         }
1097         if (lhost == NULL || shost == NULL) {
1098             free(lhost);
1099             if (lhost != shost)
1100                 free(shost);
1101             sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
1102             debug_return_bool(false);
1103         }
1104     }
1105     if (lhost != NULL && shost != NULL) {
1106         if (user_srunhost != user_runhost)
1107             free(user_srunhost);
1108         free(user_runhost);
1109         user_runhost = lhost;
1110         user_srunhost = shost;
1111     }
1112
1113     sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
1114         "host %s, shost %s, runhost %s, srunhost %s",
1115         user_host, user_shost, user_runhost, user_srunhost);
1116     debug_return_bool(true);
1117 }
1118
1119 /*
1120  * Get passwd entry for the user we are going to run commands as
1121  * and store it in runas_pw.  By default, commands run as "root".
1122  */
1123 static bool
1124 set_runaspw(const char *user, bool quiet)
1125 {
1126     struct passwd *pw = NULL;
1127     debug_decl(set_runaspw, SUDOERS_DEBUG_PLUGIN)
1128
1129     if (*user == '#') {
1130         const char *errstr;
1131         uid_t uid = sudo_strtoid(user + 1, NULL, NULL, &errstr);
1132         if (errstr == NULL) {
1133             if ((pw = sudo_getpwuid(uid)) == NULL)
1134                 pw = sudo_fakepwnam(user, user_gid);
1135         }
1136     }
1137     if (pw == NULL) {
1138         if ((pw = sudo_getpwnam(user)) == NULL) {
1139             if (!quiet)
1140                 log_warningx(SLOG_RAW_MSG, N_("unknown user: %s"), user);
1141             debug_return_bool(false);
1142         }
1143     }
1144     if (runas_pw != NULL)
1145         sudo_pw_delref(runas_pw);
1146     runas_pw = pw;
1147     debug_return_bool(true);
1148 }
1149
1150 /*
1151  * Get group entry for the group we are going to run commands as
1152  * and store it in runas_gr.
1153  */
1154 static bool
1155 set_runasgr(const char *group, bool quiet)
1156 {
1157     struct group *gr = NULL;
1158     debug_decl(set_runasgr, SUDOERS_DEBUG_PLUGIN)
1159
1160     if (*group == '#') {
1161         const char *errstr;
1162         gid_t gid = sudo_strtoid(group + 1, NULL, NULL, &errstr);
1163         if (errstr == NULL) {
1164             if ((gr = sudo_getgrgid(gid)) == NULL)
1165                 gr = sudo_fakegrnam(group);
1166         }
1167     }
1168     if (gr == NULL) {
1169         if ((gr = sudo_getgrnam(group)) == NULL) {
1170             if (!quiet)
1171                 log_warningx(SLOG_RAW_MSG, N_("unknown group: %s"), group);
1172             debug_return_bool(false);
1173         }
1174     }
1175     if (runas_gr != NULL)
1176         sudo_gr_delref(runas_gr);
1177     runas_gr = gr;
1178     debug_return_bool(true);
1179 }
1180
1181 /*
1182  * Callback for runas_default sudoers setting.
1183  */
1184 static bool
1185 cb_runas_default(const union sudo_defs_val *sd_un)
1186 {
1187     debug_decl(cb_runas_default, SUDOERS_DEBUG_PLUGIN)
1188
1189     /* Only reset runaspw if user didn't specify one. */
1190     if (!runas_user && !runas_group)
1191         debug_return_bool(set_runaspw(sd_un->str, true));
1192     debug_return_bool(true);
1193 }
1194
1195 /*
1196  * Callback for runas_default sudoers setting.
1197  */
1198 static bool
1199 cb_tty_tickets(const union sudo_defs_val *sd_un)
1200 {
1201     debug_decl(cb_tty_tickets, SUDOERS_DEBUG_PLUGIN)
1202
1203     /* Convert tty_tickets -> timestamp_type */
1204     if (sd_un->flag)
1205         def_timestamp_type = tty;
1206     else
1207         def_timestamp_type = global;
1208     debug_return_bool(true);
1209 }
1210
1211 /*
1212  * Cleanup hook for sudo_fatal()/sudo_fatalx()
1213  */
1214 void
1215 sudoers_cleanup(void)
1216 {
1217     struct sudo_nss *nss;
1218     debug_decl(sudoers_cleanup, SUDOERS_DEBUG_PLUGIN)
1219
1220     if (snl != NULL) {
1221         TAILQ_FOREACH(nss, snl, entries) {
1222             nss->close(nss);
1223         }
1224     }
1225     if (def_group_plugin)
1226         group_plugin_unload();
1227     sudo_freepwcache();
1228     sudo_freegrcache();
1229
1230     debug_return;
1231 }
1232
1233 #ifdef USE_ADMIN_FLAG
1234 static int
1235 create_admin_success_flag(void)
1236 {
1237     char flagfile[PATH_MAX];
1238     int len, ret = -1;
1239     debug_decl(create_admin_success_flag, SUDOERS_DEBUG_PLUGIN)
1240
1241     /* Check whether the user is in the sudo or admin group. */
1242     if (!user_in_group(sudo_user.pw, "sudo") &&
1243         !user_in_group(sudo_user.pw, "admin"))
1244         debug_return_int(true);
1245
1246     /* Build path to flag file. */
1247     len = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful",
1248         user_dir);
1249     if (len <= 0 || len >= (int)sizeof(flagfile))
1250         debug_return_int(false);
1251
1252     /* Create admin flag file if it doesn't already exist. */
1253     if (set_perms(PERM_USER)) {
1254         int fd = open(flagfile, O_CREAT|O_WRONLY|O_NONBLOCK|O_EXCL, 0644);
1255         ret = fd != -1 || errno == EEXIST;
1256         if (fd != -1)
1257             close(fd);
1258         if (!restore_perms())
1259             ret = -1;
1260     }
1261     debug_return_int(ret);
1262 }
1263 #else /* !USE_ADMIN_FLAG */
1264 static int
1265 create_admin_success_flag(void)
1266 {
1267     /* STUB */
1268     return true;
1269 }
1270 #endif /* USE_ADMIN_FLAG */
1271
1272 static bool
1273 tty_present(void)
1274 {
1275 #if defined(HAVE_KINFO_PROC2_NETBSD) || defined(HAVE_KINFO_PROC_OPENBSD) || defined(HAVE_KINFO_PROC_FREEBSD) || defined(HAVE_KINFO_PROC_44BSD) || defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || defined(HAVE_PSTAT_GETPROC) || defined(__linux__)
1276     return user_ttypath != NULL;
1277 #else
1278     int fd = open(_PATH_TTY, O_RDWR);
1279     if (fd != -1)
1280         close(fd);
1281     return fd != -1;
1282 #endif
1283 }