2 * Copyright (c) 1993-1996, 1998-2013 Todd C. Miller <Todd.Miller@courtesan.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 * Sponsored in part by the Defense Advanced Research Projects
17 * Agency (DARPA) and Air Force Research Laboratory, Air Force
18 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
29 #include <sys/types.h>
31 #include <sys/socket.h>
40 #endif /* STDC_HEADERS */
42 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
46 #endif /* HAVE_STRING_H */
49 #endif /* HAVE_STRINGS_H */
52 #endif /* HAVE_UNISTD_H */
60 #ifdef HAVE_LOGIN_CAP_H
61 # include <login_cap.h>
62 # ifndef LOGIN_DEFROOTCLASS
63 # define LOGIN_DEFROOTCLASS "daemon"
66 # define LOGIN_SETENV 0
70 # include <selinux/selinux.h>
73 #ifndef HAVE_GETADDRINFO
74 # include "compat/getaddrinfo.h"
78 #include "auth/sudo_auth.h"
79 #include "secure_path.h"
84 static char *find_editor(int nfiles, char **files, char ***argv_out);
85 static int cb_runas_default(const char *);
86 static int cb_sudoers_locale(const char *);
87 static int set_cmnd(void);
88 static void create_admin_success_flag(void);
89 static void init_vars(char * const *);
90 static void set_fqdn(void);
91 static void set_loginclass(struct passwd *);
92 static void set_runasgr(const char *);
93 static void set_runaspw(const char *);
94 static bool tty_present(void);
99 struct sudo_user sudo_user;
100 struct passwd *list_pw;
103 extern int errorlineno;
104 extern bool parse_error;
105 extern char *errorfile;
106 #ifdef HAVE_BSD_AUTH_H
108 #endif /* HAVE_BSD_AUTH_H */
111 static char *prev_user;
112 static char *runas_user;
113 static char *runas_group;
114 static struct sudo_nss_list *snl;
116 /* XXX - must be extern for audit bits of sudo_auth.c */
121 sudoers_policy_init(void *info, char * const envp[])
123 volatile int sources = 0;
124 struct sudo_nss *nss, *nss_next;
125 debug_decl(sudoers_policy_init, SUDO_DEBUG_PLUGIN)
127 bindtextdomain("sudoers", LOCALEDIR);
132 /* Register fatal/fatalx callback. */
133 fatal_callback_register(sudoers_cleanup);
135 /* Initialize environment functions (including replacements). */
138 /* Setup defaults data structures. */
141 /* Parse info from front-end. */
142 sudo_mode = sudoers_policy_deserialize_info(info, &runas_user, &runas_group);
144 init_vars(envp); /* XXX - move this later? */
146 /* Parse nsswitch.conf for sudoers order. */
147 snl = sudo_read_nss();
149 /* LDAP or NSS may modify the euid so we need to be root for the open. */
150 set_perms(PERM_INITIAL);
151 set_perms(PERM_ROOT);
153 /* Open and parse sudoers, set global defaults */
154 for (nss = snl->first; nss != NULL; nss = nss_next) {
155 nss_next = nss->next;
156 if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
158 if (nss->setdefs(nss) != 0)
159 log_warning(NO_STDERR, N_("problem with defaults entries"));
165 warningx(_("no valid sudoers sources found, quitting"));
166 debug_return_bool(-1);
169 /* XXX - collect post-sudoers parse settings into a function */
172 * Initialize external group plugin, if any.
174 if (def_group_plugin) {
175 if (group_plugin_load(def_group_plugin) != true)
176 def_group_plugin = NULL;
180 * Set runas passwd/group entries based on command line or sudoers.
181 * Note that if runas_group was specified without runas_user we
182 * defer setting runas_pw so the match routines know to ignore it.
184 /* XXX - qpm4u does more here as it may have already set runas_pw */
185 if (runas_group != NULL) {
186 set_runasgr(runas_group);
187 if (runas_user != NULL)
188 set_runaspw(runas_user);
190 set_runaspw(runas_user ? runas_user : def_runas_default);
192 if (!update_defaults(SETDEF_RUNAS))
193 log_warning(NO_STDERR, N_("problem with defaults entries"));
196 set_fqdn(); /* deferred until after sudoers is parsed */
198 /* Set login class if applicable. */
199 set_loginclass(runas_pw ? runas_pw : sudo_user.pw);
203 debug_return_bool(true);
207 sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
210 char **edit_argv = NULL;
211 char *iolog_path = NULL;
212 mode_t cmnd_umask = 0777;
213 struct sudo_nss *nss;
214 int cmnd_status = -1, oldlocale, validated;
215 volatile int rval = true;
216 debug_decl(sudoers_policy_main, SUDO_DEBUG_PLUGIN)
218 /* XXX - would like to move this to policy.c but need the cleanup. */
219 if (fatal_setjmp() != 0) {
220 /* error recovery via fatal(), fatalx() or log_fatal() */
225 /* Is root even allowed to run sudo? */
226 if (user_uid == 0 && !def_root_sudo) {
227 warningx(_("sudoers specifies that root is not allowed to sudo"));
231 /* Check for -C overriding def_closefrom. */
232 if (user_closefrom >= 0 && user_closefrom != def_closefrom) {
233 if (!def_closefrom_override) {
234 warningx(_("you are not permitted to use the -C option"));
237 def_closefrom = user_closefrom;
240 set_perms(PERM_INITIAL);
242 /* Environment variables specified on the command line. */
243 if (env_add != NULL && env_add[0] != NULL)
244 sudo_user.env_vars = env_add;
247 * Make a local copy of argc/argv, with special handling
248 * for pseudo-commands and the '-i' option.
252 NewArgv = emalloc2(NewArgc + 1, sizeof(char *));
253 NewArgv[0] = user_cmnd;
256 /* Must leave an extra slot before NewArgv for bash's --login */
258 NewArgv = emalloc2(NewArgc + 2, sizeof(char *));
259 memcpy(++NewArgv, argv, argc * sizeof(char *));
260 NewArgv[NewArgc] = NULL;
261 if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && runas_pw != NULL)
262 NewArgv[0] = estrdup(runas_pw->pw_shell);
265 /* If given the -P option, set the "preserve_groups" flag. */
266 if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
267 def_preserve_groups = true;
269 /* Find command in path */
270 cmnd_status = set_cmnd();
273 * Check sudoers sources, using the locale specified in sudoers.
275 sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
276 validated = FLAG_NO_USER | FLAG_NO_HOST;
277 tq_foreach_fwd(snl, nss) {
278 validated = nss->lookup(nss, validated, pwflag);
280 if (ISSET(validated, VALIDATE_OK)) {
281 /* Handle [SUCCESS=return] */
282 if (nss->ret_if_found)
285 /* Handle [NOTFOUND=return] */
286 if (nss->ret_if_notfound)
291 /* Restore user's locale. */
292 sudoers_setlocale(oldlocale, NULL);
294 if (safe_cmnd == NULL)
295 safe_cmnd = estrdup(user_cmnd);
297 /* If only a group was specified, set runas_pw based on invoking user. */
298 if (runas_pw == NULL)
299 set_runaspw(user_name);
302 * Look up the timestamp dir owner if one is specified.
304 if (def_timestampowner) {
307 if (*def_timestampowner == '#')
308 pw = sudo_getpwuid(atoi(def_timestampowner + 1));
310 pw = sudo_getpwnam(def_timestampowner);
312 timestamp_uid = pw->pw_uid;
315 log_warning(0, N_("timestamp owner (%s): No such user"),
317 timestamp_uid = ROOT_UID;
321 /* If no command line args and "shell_noargs" is not set, error out. */
322 if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) {
323 rval = -2; /* usage error */
327 /* Bail if a tty is required and we don't have one. */
328 if (def_requiretty && !tty_present()) {
329 audit_failure(NewArgv, N_("no tty"));
330 warningx(_("sorry, you must have a tty to run sudo"));
335 * We don't reset the environment for sudoedit or if the user
336 * specified the -E command line flag and they have setenv privs.
338 if (ISSET(sudo_mode, MODE_EDIT) ||
339 (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv))
340 def_env_reset = false;
342 /* Build a new environment that avoids any nasty bits. */
345 /* Require a password if sudoers says so. */
346 rval = check_user(validated, sudo_mode);
348 if (!ISSET(validated, VALIDATE_OK))
349 log_denial(validated, false);
353 /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
354 /* XXX - causes confusion when root is not listed in sudoers */
355 if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) {
356 if (user_uid == 0 && strcmp(prev_user, "root") != 0) {
359 if ((pw = sudo_getpwnam(prev_user)) != NULL) {
360 if (sudo_user.pw != NULL)
361 sudo_pw_delref(sudo_user.pw);
367 /* If the user was not allowed to run the command we are done. */
368 if (!ISSET(validated, VALIDATE_OK)) {
369 log_failure(validated, cmnd_status);
373 /* Create Ubuntu-style dot file to indicate sudo was successful. */
374 create_admin_success_flag();
376 /* Finally tell the user if the command did not exist. */
377 if (cmnd_status == NOT_FOUND_DOT) {
378 audit_failure(NewArgv, N_("command in current directory"));
379 warningx(_("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run."), user_cmnd, user_cmnd, user_cmnd);
381 } else if (cmnd_status == NOT_FOUND) {
382 if (ISSET(sudo_mode, MODE_CHECK)) {
383 audit_failure(NewArgv, N_("%s: command not found"), NewArgv[0]);
384 warningx(_("%s: command not found"), NewArgv[0]);
386 audit_failure(NewArgv, N_("%s: command not found"), user_cmnd);
387 warningx(_("%s: command not found"), user_cmnd);
392 /* If user specified env vars make sure sudoers allows it. */
393 if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) {
394 if (ISSET(sudo_mode, MODE_PRESERVE_ENV)) {
395 warningx(_("sorry, you are not allowed to preserve the environment"));
398 validate_env_vars(sudo_user.env_vars);
401 if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT))) {
402 if ((def_log_input || def_log_output) && def_iolog_file && def_iolog_dir) {
403 const char prefix[] = "iolog_path=";
404 iolog_path = expand_iolog_path(prefix, def_iolog_dir,
405 def_iolog_file, &sudo_user.iolog_file);
406 sudo_user.iolog_file++;
410 log_allowed(validated);
411 if (ISSET(sudo_mode, MODE_CHECK))
412 rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
413 else if (ISSET(sudo_mode, MODE_LIST))
414 display_privs(snl, list_pw ? list_pw : sudo_user.pw); /* XXX - return val */
416 /* Cleanup sudoers sources */
417 tq_foreach_fwd(snl, nss) {
420 if (def_group_plugin)
421 group_plugin_unload();
423 if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) {
424 /* rval already set appropriately */
429 * Set umask based on sudoers.
430 * If user's umask is more restrictive, OR in those bits too
431 * unless umask_override is set.
433 if (def_umask != 0777) {
434 cmnd_umask = def_umask;
435 if (!def_umask_override)
436 cmnd_umask |= user_umask;
439 if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
442 /* Convert /bin/sh -> -sh so shell knows it is a login shell */
443 if ((p = strrchr(NewArgv[0], '/')) == NULL)
449 * Newer versions of bash require the --login option to be used
450 * in conjunction with the -c option even if the shell name starts
451 * with a '-'. Unfortunately, bash 1.x uses -login, not --login
452 * so this will cause an error for that.
454 if (NewArgc > 1 && strcmp(NewArgv[0], "-bash") == 0 &&
455 strcmp(NewArgv[1], "-c") == 0) {
456 /* Use the extra slot before NewArgv so we can store --login. */
459 NewArgv[0] = NewArgv[1];
460 NewArgv[1] = "--login";
463 #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM))
464 /* Insert system-wide environment variables. */
465 read_env_file(_PATH_ENVIRONMENT, true);
467 #ifdef HAVE_LOGIN_CAP_H
468 /* Set environment based on login class. */
470 login_cap_t *lc = login_getclass(login_class);
472 setusercontext(lc, runas_pw, runas_pw->pw_uid, LOGIN_SETPATH|LOGIN_SETENV);
476 #endif /* HAVE_LOGIN_CAP_H */
479 /* Insert system-wide environment variables. */
481 read_env_file(def_env_file, false);
483 /* Insert user-specified environment variables. */
484 insert_env_vars(sudo_user.env_vars);
486 if (ISSET(sudo_mode, MODE_EDIT)) {
488 safe_cmnd = find_editor(NewArgc - 1, NewArgv + 1, &edit_argv);
489 if (safe_cmnd == NULL)
493 /* Must audit before uid change. */
494 audit_success(NewArgv);
496 /* Setup execution environment to pass back to front-end. */
497 rval = sudoers_policy_exec_setup(edit_argv ? edit_argv : NewArgv,
498 env_get(), cmnd_umask, iolog_path, closure);
500 /* Zero out stashed copy of environment, it is owned by the front-end. */
509 fatal_disable_setjmp();
512 /* Close the password and group files and free up memory. */
516 debug_return_bool(rval);
520 * Initialize timezone and fill in ``sudo_user'' struct.
523 init_vars(char * const envp[])
526 debug_decl(init_vars, SUDO_DEBUG_PLUGIN)
528 sudoers_initlocale(setlocale(LC_ALL, NULL), def_sudoers_locale);
530 for (ep = envp; *ep; ep++) {
531 /* XXX - don't fill in if empty string */
534 if (strncmp("KRB5CCNAME=", *ep, 11) == 0)
535 user_ccname = *ep + 11;
538 if (strncmp("PATH=", *ep, 5) == 0)
542 if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
543 user_prompt = *ep + 12;
544 else if (strncmp("SUDO_USER=", *ep, 10) == 0)
545 prev_user = *ep + 10;
551 * Get a local copy of the user's struct passwd if we don't already
554 if (sudo_user.pw == NULL) {
555 if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL) {
557 * It is not unusual for users to place "sudo -k" in a .logout
558 * file which can cause sudo to be run during reboot after the
559 * YP/NIS/NIS+/LDAP/etc daemon has died.
561 if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE)
562 fatalx(_("unknown uid: %u"), (unsigned int) user_uid);
564 /* Need to make a fake struct passwd for the call to log_fatal(). */
565 sudo_user.pw = sudo_mkpwent(user_name, user_uid, user_gid, NULL, NULL);
566 log_fatal(0, N_("unknown uid: %u"), (unsigned int) user_uid);
574 if (user_group_list == NULL)
575 user_group_list = sudo_get_grlist(sudo_user.pw);
577 /* Set runas callback. */
578 sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default;
580 /* Set locale callback. */
581 sudo_defs_table[I_SUDOERS_LOCALE].callback = cb_sudoers_locale;
583 /* Set maxseq callback. */
584 sudo_defs_table[I_MAXSEQ].callback = io_set_max_sessid;
586 /* It is now safe to use log_fatal() and set_perms() */
591 * Fill in user_cmnd, user_args, user_base and user_stat variables
592 * and apply any command-specific defaults entries.
598 char *path = user_path;
599 debug_decl(set_cmnd, SUDO_DEBUG_PLUGIN)
601 /* Resolve the path and return. */
603 user_stat = ecalloc(1, sizeof(struct stat));
605 /* Default value for cmnd, overridden below. */
606 if (user_cmnd == NULL)
607 user_cmnd = NewArgv[0];
609 if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
610 if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
611 if (def_secure_path && !user_is_exempt())
612 path = def_secure_path;
613 set_perms(PERM_RUNAS);
614 rval = find_path(NewArgv[0], &user_cmnd, user_stat, path,
618 /* Failed as root, try as invoking user. */
619 set_perms(PERM_USER);
620 rval = find_path(NewArgv[0], &user_cmnd, user_stat, path,
628 char *to, *from, **av;
631 /* Alloc and build up user_args. */
632 for (size = 0, av = NewArgv + 1; *av; av++)
633 size += strlen(*av) + 1;
634 user_args = emalloc(size);
635 if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
637 * When running a command via a shell, the sudo front-end
638 * escapes potential meta chars. We unescape non-spaces
639 * for sudoers matching and logging purposes.
641 for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
643 if (from[0] == '\\' && !isspace((unsigned char)from[1]))
651 for (to = user_args, av = NewArgv + 1; *av; av++) {
652 n = strlcpy(to, *av, size - (to - user_args));
653 if (n >= size - (to - user_args))
654 fatalx(_("internal error, %s overflow"), "set_cmnd()");
662 if (strlen(user_cmnd) >= PATH_MAX) {
663 errno = ENAMETOOLONG;
664 fatal("%s", user_cmnd);
667 if ((user_base = strrchr(user_cmnd, '/')) != NULL)
670 user_base = user_cmnd;
672 if (!update_defaults(SETDEF_CMND))
673 log_warning(NO_STDERR, N_("problem with defaults entries"));
675 debug_return_int(rval);
679 * Open sudoers and sanity check mode/owner/type.
680 * Returns a handle to the sudoers file or NULL on error.
683 open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
687 debug_decl(open_sudoers, SUDO_DEBUG_PLUGIN)
689 set_perms(PERM_SUDOERS);
691 switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) {
692 case SUDO_PATH_SECURE:
694 * If we are expecting sudoers to be group readable but
695 * it is not, we must open the file as root, not uid 1.
697 if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP)) {
698 if ((sb.st_mode & S_IRGRP) == 0) {
700 set_perms(PERM_ROOT);
704 * Open sudoers and make sure we can read it so we can present
705 * the user with a reasonable error message (unlike the lexer).
707 if ((fp = fopen(sudoers, "r")) == NULL) {
708 log_warning(USE_ERRNO, N_("unable to open %s"), sudoers);
710 if (sb.st_size != 0 && fgetc(fp) == EOF) {
711 log_warning(USE_ERRNO, N_("unable to read %s"),
716 /* Rewind fp and set close on exec flag. */
718 (void) fcntl(fileno(fp), F_SETFD, 1);
722 case SUDO_PATH_MISSING:
723 log_warning(USE_ERRNO, N_("unable to stat %s"), sudoers);
725 case SUDO_PATH_BAD_TYPE:
726 log_warning(0, N_("%s is not a regular file"), sudoers);
728 case SUDO_PATH_WRONG_OWNER:
729 log_warning(0, N_("%s is owned by uid %u, should be %u"),
730 sudoers, (unsigned int) sb.st_uid, (unsigned int) sudoers_uid);
732 case SUDO_PATH_WORLD_WRITABLE:
733 log_warning(0, N_("%s is world writable"), sudoers);
735 case SUDO_PATH_GROUP_WRITABLE:
736 log_warning(0, N_("%s is owned by gid %u, should be %u"),
737 sudoers, (unsigned int) sb.st_gid, (unsigned int) sudoers_gid);
744 restore_perms(); /* change back to root */
746 debug_return_ptr(fp);
749 #ifdef HAVE_LOGIN_CAP_H
751 set_loginclass(struct passwd *pw)
753 const int errflags = NO_MAIL|MSG_ONLY;
755 debug_decl(set_loginclass, SUDO_DEBUG_PLUGIN)
757 if (!def_use_loginclass)
760 if (login_class && strcmp(login_class, "-") != 0) {
762 strcmp(runas_user ? runas_user : def_runas_default, "root") != 0)
763 fatalx(_("only root can use `-c %s'"), login_class);
765 login_class = pw->pw_class;
766 if (!login_class || !*login_class)
768 (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
771 /* Make sure specified login class is valid. */
772 lc = login_getclass(login_class);
773 if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
775 * Don't make it a fatal error if the user didn't specify the login
776 * class themselves. We do this because if login.conf gets
777 * corrupted we want the admin to be able to use sudo to fix it.
780 log_fatal(errflags, N_("unknown login class: %s"), login_class);
782 log_warning(errflags, N_("unknown login class: %s"), login_class);
783 def_use_loginclass = false;
790 set_loginclass(struct passwd *pw)
793 #endif /* HAVE_LOGIN_CAP_H */
796 # define AI_FQDN AI_CANONNAME
800 * Look up the fully qualified domain name and set user_host and user_shost.
801 * Use AI_FQDN if available since "canonical" is not always the same as fqdn.
806 struct addrinfo *res0, hint;
808 debug_decl(set_fqdn, SUDO_DEBUG_PLUGIN)
810 zero_bytes(&hint, sizeof(hint));
811 hint.ai_family = PF_UNSPEC;
812 hint.ai_flags = AI_FQDN;
813 if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) {
814 log_warning(MSG_ONLY, N_("unable to resolve host %s"), user_host);
816 if (user_shost != user_host)
819 user_host = estrdup(res0->ai_canonname);
821 if ((p = strchr(user_host, '.')) != NULL)
822 user_shost = estrndup(user_host, (size_t)(p - user_host));
824 user_shost = user_host;
830 * Get passwd entry for the user we are going to run commands as
831 * and store it in runas_pw. By default, commands run as "root".
834 set_runaspw(const char *user)
836 debug_decl(set_runaspw, SUDO_DEBUG_PLUGIN)
838 if (runas_pw != NULL)
839 sudo_pw_delref(runas_pw);
841 if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
842 runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
844 if ((runas_pw = sudo_getpwnam(user)) == NULL)
845 log_fatal(NO_MAIL|MSG_ONLY, N_("unknown user: %s"), user);
851 * Get group entry for the group we are going to run commands as
852 * and store it in runas_gr.
855 set_runasgr(const char *group)
857 debug_decl(set_runasgr, SUDO_DEBUG_PLUGIN)
859 if (runas_gr != NULL)
860 sudo_gr_delref(runas_gr);
862 if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
863 runas_gr = sudo_fakegrnam(group);
865 if ((runas_gr = sudo_getgrnam(group)) == NULL)
866 log_fatal(NO_MAIL|MSG_ONLY, N_("unknown group: %s"), group);
872 * Callback for runas_default sudoers setting.
875 cb_runas_default(const char *user)
877 /* Only reset runaspw if user didn't specify one. */
878 if (!runas_user && !runas_group)
884 * Callback for sudoers_locale sudoers setting.
887 cb_sudoers_locale(const char *locale)
889 sudoers_initlocale(NULL, locale);
894 * Cleanup hook for fatal()/fatalx()
897 sudoers_cleanup(void)
899 struct sudo_nss *nss;
900 debug_decl(sudoers_cleanup, SUDO_DEBUG_PLUGIN)
903 tq_foreach_fwd(snl, nss)
906 if (def_group_plugin)
907 group_plugin_unload();
915 resolve_editor(const char *ed, size_t edlen, int nfiles, char **files, char ***argv_out)
917 char *cp, **nargv, *editor, *editor_path = NULL;
920 debug_decl(resolve_editor, SUDO_DEBUG_PLUGIN)
922 /* Note: editor becomes part of argv_out and is not freed. */
923 editor = emalloc(edlen + 1);
924 memcpy(editor, ed, edlen);
925 editor[edlen] = '\0';
928 * Split editor into an argument vector; editor is reused (do not free).
929 * The EDITOR and VISUAL environment variables may contain command
930 * line args so look for those and alloc space for them too.
933 for (wasblank = false, cp = editor; *cp != '\0'; cp++) {
934 if (isblank((unsigned char) *cp))
941 /* If we can't find the editor in the user's PATH, give up. */
942 cp = strtok(editor, " \t");
944 find_path(cp, &editor_path, NULL, getenv("PATH"), 0) != FOUND) {
946 debug_return_str(NULL);
948 nargv = (char **) emalloc2(nargc + 1 + nfiles + 1, sizeof(char *));
949 for (ac = 0; cp != NULL && ac < nargc; ac++) {
951 cp = strtok(NULL, " \t");
954 for (i = 0; i < nfiles; )
955 nargv[ac++] = files[i++];
959 debug_return_str(editor_path);
963 * Determine which editor to use. We don't need to worry about restricting
964 * this to a "safe" editor since it runs with the uid of the invoking user,
965 * not the runas (privileged) user.
968 find_editor(int nfiles, char **files, char ***argv_out)
970 const char *cp, *ep, *editor;
971 char *editor_path = NULL, **ev, *ev0[4];
973 debug_decl(find_editor, SUDO_DEBUG_PLUGIN)
976 * If any of SUDO_EDITOR, VISUAL or EDITOR are set, choose the first one.
978 ev0[0] = "SUDO_EDITOR";
982 for (ev = ev0; editor_path == NULL && *ev != NULL; ev++) {
983 if ((editor = getenv(*ev)) != NULL && *editor != '\0') {
984 editor_path = resolve_editor(editor, strlen(editor), nfiles,
988 if (editor_path == NULL) {
989 /* def_editor could be a path, split it up, avoiding strtok() */
990 cp = editor = def_editor;
992 if ((ep = strchr(cp, ':')) != NULL)
996 editor_path = resolve_editor(cp, len, nfiles, files, argv_out);
998 } while (ep != NULL && editor_path == NULL);
1001 audit_failure(NewArgv, N_("%s: command not found"), editor);
1002 warningx(_("%s: command not found"), editor);
1004 debug_return_str(editor_path);
1007 #ifdef USE_ADMIN_FLAG
1009 create_admin_success_flag(void)
1011 struct stat statbuf;
1012 char flagfile[PATH_MAX];
1014 debug_decl(create_admin_success_flag, SUDO_DEBUG_PLUGIN)
1016 /* Check whether the user is in the admin group. */
1017 if (!user_in_group(sudo_user.pw, "admin"))
1020 /* Build path to flag file. */
1021 n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful",
1023 if (n <= 0 || n >= sizeof(flagfile))
1026 /* Create admin flag file if it doesn't already exist. */
1027 set_perms(PERM_USER);
1028 if (stat(flagfile, &statbuf) != 0) {
1029 fd = open(flagfile, O_CREAT|O_WRONLY|O_EXCL, 0644);
1035 #else /* !USE_ADMIN_FLAG */
1037 create_admin_success_flag(void)
1041 #endif /* USE_ADMIN_FLAG */
1046 #if defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV) || defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV) || defined(HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV) || defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || defined(HAVE_PSTAT_GETPROC) || defined(__linux__)
1047 return user_ttypath != NULL;
1049 int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY);