2 * Copyright (c) 2009-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.
23 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <sys/resource.h>
37 #endif /* STDC_HEADERS */
39 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
43 #endif /* HAVE_STRING_H */
46 #endif /* HAVE_STRINGS_H */
49 #endif /* HAVE_UNISTD_H */
57 #if TIME_WITH_SYS_TIME
60 #ifdef HAVE_LOGIN_CAP_H
61 # include <login_cap.h>
63 # define LOGIN_SETENV 0
68 # include <sys/task.h>
71 # include <selinux/selinux.h>
75 #endif /* HAVE_SETAUTHDB */
76 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
79 # include <hpsecurity.h>
81 # include <sys/security.h>
84 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
87 #include "sudo_plugin.h"
88 #include "sudo_plugin_int.h"
89 #include "sudo_usage.h"
94 struct plugin_container policy_plugin;
95 struct plugin_container_list io_plugins;
96 struct user_details user_details;
97 const char *list_user, *runas_user, *runas_group; /* extern for parse_args.c */
98 static struct command_details command_details;
104 static void fix_fds(void);
105 static void disable_coredumps(void);
106 static void sudo_check_suid(const char *path);
107 static char **get_user_info(struct user_details *);
108 static void command_info_to_details(char * const info[],
109 struct command_details *details);
111 /* Policy plugin convenience functions. */
112 static int policy_open(struct plugin_container *plugin, char * const settings[],
113 char * const user_info[], char * const user_env[]);
114 static void policy_close(struct plugin_container *plugin, int exit_status,
116 static int policy_show_version(struct plugin_container *plugin, int verbose);
117 static int policy_check(struct plugin_container *plugin, int argc,
118 char * const argv[], char *env_add[], char **command_info[],
119 char **argv_out[], char **user_env_out[]);
120 static int policy_list(struct plugin_container *plugin, int argc,
121 char * const argv[], int verbose, const char *list_user);
122 static int policy_validate(struct plugin_container *plugin);
123 static void policy_invalidate(struct plugin_container *plugin, int remove);
125 /* I/O log plugin convenience functions. */
126 static int iolog_open(struct plugin_container *plugin, char * const settings[],
127 char * const user_info[], char * const command_details[],
128 int argc, char * const argv[], char * const user_env[]);
129 static void iolog_close(struct plugin_container *plugin, int exit_status,
131 static int iolog_show_version(struct plugin_container *plugin, int verbose);
132 static void iolog_unlink(struct plugin_container *plugin);
135 static struct rlimit corelimit;
136 #endif /* RLIMIT_CORE */
137 #if defined(__linux__)
138 static struct rlimit nproclimit;
141 __dso_public int main(int argc, char *argv[], char *envp[]);
144 main(int argc, char *argv[], char *envp[])
146 int nargc, ok, exitcode = 0;
147 char **nargv, **settings, **env_add;
148 char **user_info, **command_info, **argv_out, **user_env_out;
149 struct plugin_container *plugin, *next;
151 debug_decl(main, SUDO_DEBUG_MAIN)
153 os_init(argc, argv, envp);
155 setlocale(LC_ALL, "");
156 bindtextdomain(PACKAGE_NAME, LOCALEDIR);
157 textdomain(PACKAGE_NAME);
161 #endif /* HAVE_TZSET */
163 /* Must be done before we do any password lookups */
164 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
165 (void) set_auth_parameters(argc, argv);
166 # ifdef HAVE_INITPRIVS
169 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
171 /* Make sure we are setuid root. */
172 sudo_check_suid(argv[0]);
174 /* Reset signal mask, save signal state and make sure fds 0-2 are open. */
175 (void) sigemptyset(&mask);
176 (void) sigprocmask(SIG_SETMASK, &mask, NULL);
180 /* Read sudo.conf. */
181 sudo_conf_read(NULL);
183 /* Fill in user_info with user name, uid, cwd, etc. */
184 memset(&user_details, 0, sizeof(user_details));
185 user_info = get_user_info(&user_details);
187 /* Disable core dumps if not enabled in sudo.conf. */
190 /* Parse command line arguments. */
191 sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);
192 sudo_debug_printf(SUDO_DEBUG_DEBUG, "sudo_mode %d", sudo_mode);
194 /* Print sudo version early, in case of plugin init failure. */
195 if (ISSET(sudo_mode, MODE_VERSION)) {
196 printf(_("Sudo version %s\n"), PACKAGE_VERSION);
197 if (user_details.uid == ROOT_UID)
198 (void) printf(_("Configure options: %s\n"), CONFIGURE_ARGS);
202 if (!sudo_load_plugins(&policy_plugin, &io_plugins))
203 fatalx(_("fatal error, unable to load plugins"));
205 /* Open policy plugin. */
206 ok = policy_open(&policy_plugin, settings, user_info, envp);
211 fatalx(_("unable to initialize policy plugin"));
216 switch (sudo_mode & MODE_MASK) {
218 policy_show_version(&policy_plugin, !user_details.uid);
219 tq_foreach_fwd(&io_plugins, plugin) {
220 ok = iolog_open(plugin, settings, user_info, NULL,
223 iolog_show_version(plugin, !user_details.uid);
227 case MODE_VALIDATE|MODE_INVALIDATE:
228 ok = policy_validate(&policy_plugin);
231 case MODE_INVALIDATE:
232 policy_invalidate(&policy_plugin, sudo_mode == MODE_KILL);
236 case MODE_CHECK|MODE_INVALIDATE:
238 case MODE_LIST|MODE_INVALIDATE:
239 ok = policy_list(&policy_plugin, nargc, nargv,
240 ISSET(sudo_mode, MODE_LONG_LIST), list_user);
244 ok = policy_check(&policy_plugin, nargc, nargv, env_add,
245 &command_info, &argv_out, &user_env_out);
246 sudo_debug_printf(SUDO_DEBUG_INFO, "policy plugin returns %d", ok);
250 exit(1); /* plugin printed error message */
252 /* Open I/O plugins once policy plugin succeeds. */
253 for (plugin = io_plugins.first; plugin != NULL; plugin = next) {
255 ok = iolog_open(plugin, settings, user_info,
256 command_info, nargc, nargv, envp);
261 /* I/O plugin asked to be disabled, remove and free. */
262 iolog_unlink(plugin);
268 fatalx(_("error initializing I/O plugin %s"),
272 /* Setup command details and run command/edit. */
273 command_info_to_details(command_info, &command_details);
274 command_details.argv = argv_out;
275 command_details.envp = user_env_out;
276 if (ISSET(sudo_mode, MODE_BACKGROUND))
277 SET(command_details.flags, CD_BACKGROUND);
278 /* Become full root (not just setuid) so user cannot kill us. */
279 if (setuid(ROOT_UID) == -1)
280 warning("setuid(%d)", ROOT_UID);
281 /* Restore coredumpsize resource limit before running. */
283 if (sudo_conf_disable_coredump())
284 (void) setrlimit(RLIMIT_CORE, &corelimit);
285 #endif /* RLIMIT_CORE */
286 if (ISSET(command_details.flags, CD_SUDOEDIT)) {
287 exitcode = sudo_edit(&command_details);
289 exitcode = run_command(&command_details);
291 /* The close method was called by sudo_edit/run_command. */
294 fatalx(_("unexpected sudo mode 0x%x"), sudo_mode);
296 sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);
301 os_init_common(int argc, char *argv[], char *envp[])
303 #if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME)
305 setprogname(argv[0]);
311 * Ensure that stdin, stdout and stderr are open; set to /dev/null if not.
312 * Some operating systems do this automatically in the kernel or libc.
317 int miss[3], devnull = -1;
318 debug_decl(fix_fds, SUDO_DEBUG_UTIL)
321 * stdin, stdout and stderr must be open; set them to /dev/null
322 * if they are closed.
324 miss[STDIN_FILENO] = fcntl(STDIN_FILENO, F_GETFL, 0) == -1;
325 miss[STDOUT_FILENO] = fcntl(STDOUT_FILENO, F_GETFL, 0) == -1;
326 miss[STDERR_FILENO] = fcntl(STDERR_FILENO, F_GETFL, 0) == -1;
327 if (miss[STDIN_FILENO] || miss[STDOUT_FILENO] || miss[STDERR_FILENO]) {
328 if ((devnull = open(_PATH_DEVNULL, O_RDWR, 0644)) == -1)
329 fatal(_("unable to open %s"), _PATH_DEVNULL);
330 if (miss[STDIN_FILENO] && dup2(devnull, STDIN_FILENO) == -1)
332 if (miss[STDOUT_FILENO] && dup2(devnull, STDOUT_FILENO) == -1)
334 if (miss[STDERR_FILENO] && dup2(devnull, STDERR_FILENO) == -1)
336 if (devnull > STDERR_FILENO)
343 * Allocate space for groups and fill in using getgrouplist()
344 * for when we cannot (or don't want to) use getgroups().
347 fill_group_list(struct user_details *ud, int system_maxgroups)
349 int tries, rval = -1;
350 debug_decl(fill_group_list, SUDO_DEBUG_UTIL)
353 * If user specified a max number of groups, use it, otherwise keep
354 * trying getgrouplist() until we have enough room in the array.
356 ud->ngroups = sudo_conf_max_groups();
357 if (ud->ngroups != -1) {
358 ud->groups = emalloc2(ud->ngroups, sizeof(GETGROUPS_T));
359 /* No error on insufficient space if user specified max_groups. */
360 (void)getgrouplist(ud->username, ud->gid, ud->groups, &ud->ngroups);
364 * It is possible to belong to more groups in the group database
365 * than NGROUPS_MAX. We start off with NGROUPS_MAX * 4 entries
366 * and double this as needed.
369 ud->ngroups = system_maxgroups << 1;
370 for (tries = 0; tries < 10 && rval == -1; tries++) {
373 ud->groups = emalloc2(ud->ngroups, sizeof(GETGROUPS_T));
374 rval = getgrouplist(ud->username, ud->gid, ud->groups, &ud->ngroups);
377 debug_return_int(rval);
381 get_user_groups(struct user_details *ud)
383 char *cp, *gid_list = NULL;
385 int i, len, maxgroups, group_source;
386 debug_decl(get_user_groups, SUDO_DEBUG_UTIL)
388 #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
389 maxgroups = (int)sysconf(_SC_NGROUPS_MAX);
392 maxgroups = NGROUPS_MAX;
395 group_source = sudo_conf_group_source();
396 if (group_source != GROUP_SOURCE_DYNAMIC) {
397 if ((ud->ngroups = getgroups(0, NULL)) > 0) {
398 /* Use groups from kernel if not too many or source is static. */
399 if (ud->ngroups < maxgroups || group_source == GROUP_SOURCE_STATIC) {
400 ud->groups = emalloc2(ud->ngroups, sizeof(GETGROUPS_T));
401 if (getgroups(ud->ngroups, ud->groups) < 0) {
408 if (ud->groups == NULL) {
410 * Query group database if kernel list is too small or disabled.
411 * Typically, this is because NFS can only support up to 16 groups.
413 if (fill_group_list(ud, maxgroups) == -1)
414 fatal(_("unable to get group vector"));
418 * Format group list as a comma-separated string of gids.
420 glsize = sizeof("groups=") - 1 + (ud->ngroups * (MAX_UID_T_LEN + 1));
421 gid_list = emalloc(glsize);
422 memcpy(gid_list, "groups=", sizeof("groups=") - 1);
423 cp = gid_list + sizeof("groups=") - 1;
424 for (i = 0; i < ud->ngroups; i++) {
425 /* XXX - check rval */
426 len = snprintf(cp, glsize - (cp - gid_list), "%s%u",
427 i ? "," : "", (unsigned int)ud->groups[i]);
430 debug_return_str(gid_list);
434 * Return user information as an array of name=value pairs.
435 * and fill in struct user_details (which shares the same strings).
438 get_user_info(struct user_details *ud)
440 char *cp, **user_info, cwd[PATH_MAX], host[HOST_NAME_MAX + 1];
443 debug_decl(get_user_info, SUDO_DEBUG_UTIL)
445 /* XXX - bound check number of entries */
446 user_info = emalloc2(32, sizeof(char *));
449 ud->ppid = getppid();
450 ud->pgid = getpgid(0);
451 ud->tcpgid = (pid_t)-1;
452 fd = open(_PATH_TTY, O_RDWR|O_NOCTTY|O_NONBLOCK, 0);
454 ud->tcpgid = tcgetpgrp(fd);
460 ud->euid = geteuid();
462 ud->egid = getegid();
464 pw = getpwuid(ud->uid);
466 fatalx(_("unknown uid %u: who are you?"), (unsigned int)ud->uid);
468 user_info[i] = fmt_string("user", pw->pw_name);
469 if (user_info[i] == NULL)
471 ud->username = user_info[i] + sizeof("user=") - 1;
473 /* Stash user's shell for use with the -s flag; don't pass to plugin. */
474 if ((ud->shell = getenv("SHELL")) == NULL || ud->shell[0] == '\0') {
475 ud->shell = pw->pw_shell[0] ? pw->pw_shell : _PATH_BSHELL;
477 ud->shell = estrdup(ud->shell);
479 easprintf(&user_info[++i], "pid=%d", (int)ud->pid);
480 easprintf(&user_info[++i], "ppid=%d", (int)ud->ppid);
481 easprintf(&user_info[++i], "pgid=%d", (int)ud->pgid);
482 easprintf(&user_info[++i], "tcpgid=%d", (int)ud->tcpgid);
483 easprintf(&user_info[++i], "sid=%d", (int)ud->sid);
485 easprintf(&user_info[++i], "uid=%u", (unsigned int)ud->uid);
486 easprintf(&user_info[++i], "euid=%u", (unsigned int)ud->euid);
487 easprintf(&user_info[++i], "gid=%u", (unsigned int)ud->gid);
488 easprintf(&user_info[++i], "egid=%u", (unsigned int)ud->egid);
490 if ((cp = get_user_groups(ud)) != NULL)
493 if (getcwd(cwd, sizeof(cwd)) != NULL) {
494 user_info[++i] = fmt_string("cwd", cwd);
495 if (user_info[i] == NULL)
497 ud->cwd = user_info[i] + sizeof("cwd=") - 1;
500 if ((cp = get_process_ttyname()) != NULL) {
501 user_info[++i] = fmt_string("tty", cp);
502 if (user_info[i] == NULL)
504 ud->tty = user_info[i] + sizeof("tty=") - 1;
508 if (gethostname(host, sizeof(host)) == 0)
509 host[sizeof(host) - 1] = '\0';
511 strlcpy(host, "localhost", sizeof(host));
512 user_info[++i] = fmt_string("host", host);
513 if (user_info[i] == NULL)
515 ud->host = user_info[i] + sizeof("host=") - 1;
517 get_ttysize(&ud->ts_lines, &ud->ts_cols);
518 easprintf(&user_info[++i], "lines=%d", ud->ts_lines);
519 easprintf(&user_info[++i], "cols=%d", ud->ts_cols);
521 user_info[++i] = NULL;
523 debug_return_ptr(user_info);
527 * Convert a command_info array into a command_details structure.
530 command_info_to_details(char * const info[], struct command_details *details)
536 debug_decl(command_info_to_details, SUDO_DEBUG_PCOMM)
538 memset(details, 0, sizeof(*details));
539 details->closefrom = -1;
541 #define SET_STRING(s, n) \
542 if (strncmp(s, info[i], sizeof(s) - 1) == 0 && info[i][sizeof(s) - 1]) { \
543 details->n = info[i] + sizeof(s) - 1; \
547 sudo_debug_printf(SUDO_DEBUG_INFO, "command info from plugin:");
548 for (i = 0; info[i] != NULL; i++) {
549 sudo_debug_printf(SUDO_DEBUG_INFO, " %d: %s", i, info[i]);
550 switch (info[i][0]) {
552 SET_STRING("chroot=", chroot)
553 SET_STRING("command=", command)
554 SET_STRING("cwd=", cwd)
555 if (strncmp("closefrom=", info[i], sizeof("closefrom=") - 1) == 0) {
556 cp = info[i] + sizeof("closefrom=") - 1;
560 lval = strtol(cp, &ep, 0);
561 if (*cp != '\0' && *ep == '\0' &&
563 (lval == LONG_MAX || lval == LONG_MIN)) &&
564 lval < INT_MAX && lval > INT_MIN) {
565 details->closefrom = (int)lval;
571 if (strncmp("exec_background=", info[i], sizeof("exec_background=") - 1) == 0) {
572 if (atobool(info[i] + sizeof("exec_background=") - 1) == true)
573 SET(details->flags, CD_EXEC_BG);
578 SET_STRING("login_class=", login_class)
581 /* XXX - bounds check -NZERO to NZERO (inclusive). */
582 if (strncmp("nice=", info[i], sizeof("nice=") - 1) == 0) {
583 cp = info[i] + sizeof("nice=") - 1;
587 lval = strtol(cp, &ep, 0);
588 if (*cp != '\0' && *ep == '\0' &&
590 (lval == LONG_MAX || lval == LONG_MIN)) &&
591 lval < INT_MAX && lval > INT_MIN) {
592 details->priority = (int)lval;
593 SET(details->flags, CD_SET_PRIORITY);
597 if (strncmp("noexec=", info[i], sizeof("noexec=") - 1) == 0) {
598 if (atobool(info[i] + sizeof("noexec=") - 1) == true)
599 SET(details->flags, CD_NOEXEC);
604 if (strncmp("preserve_groups=", info[i], sizeof("preserve_groups=") - 1) == 0) {
605 if (atobool(info[i] + sizeof("preserve_groups=") - 1) == true)
606 SET(details->flags, CD_PRESERVE_GROUPS);
611 if (strncmp("runas_egid=", info[i], sizeof("runas_egid=") - 1) == 0) {
612 cp = info[i] + sizeof("runas_egid=") - 1;
616 ulval = strtoul(cp, &ep, 0);
617 if (*cp != '\0' && *ep == '\0' &&
618 (errno != ERANGE || ulval != ULONG_MAX)) {
619 details->egid = (gid_t)ulval;
620 SET(details->flags, CD_SET_EGID);
624 if (strncmp("runas_euid=", info[i], sizeof("runas_euid=") - 1) == 0) {
625 cp = info[i] + sizeof("runas_euid=") - 1;
629 ulval = strtoul(cp, &ep, 0);
630 if (*cp != '\0' && *ep == '\0' &&
631 (errno != ERANGE || ulval != ULONG_MAX)) {
632 details->euid = (uid_t)ulval;
633 SET(details->flags, CD_SET_EUID);
637 if (strncmp("runas_gid=", info[i], sizeof("runas_gid=") - 1) == 0) {
638 cp = info[i] + sizeof("runas_gid=") - 1;
642 ulval = strtoul(cp, &ep, 0);
643 if (*cp != '\0' && *ep == '\0' &&
644 (errno != ERANGE || ulval != ULONG_MAX)) {
645 details->gid = (gid_t)ulval;
646 SET(details->flags, CD_SET_GID);
650 if (strncmp("runas_groups=", info[i], sizeof("runas_groups=") - 1) == 0) {
653 /* count groups, alloc and fill in */
654 cp = info[i] + sizeof("runas_groups=") - 1;
659 if ((cp = strchr(cp, ',')) == NULL)
663 if (details->ngroups != 0) {
665 emalloc2(details->ngroups, sizeof(GETGROUPS_T));
666 cp = info[i] + sizeof("runas_groups=") - 1;
667 for (j = 0; j < details->ngroups;) {
669 ulval = strtoul(cp, &ep, 0);
670 if (*cp == '\0' || (*ep != ',' && *ep != '\0') ||
671 (ulval == ULONG_MAX && errno == ERANGE)) {
674 details->groups[j++] = (gid_t)ulval;
677 details->ngroups = j;
681 if (strncmp("runas_uid=", info[i], sizeof("runas_uid=") - 1) == 0) {
682 cp = info[i] + sizeof("runas_uid=") - 1;
686 ulval = strtoul(cp, &ep, 0);
687 if (*cp != '\0' && *ep == '\0' &&
688 (errno != ERANGE || ulval != ULONG_MAX)) {
689 details->uid = (uid_t)ulval;
690 SET(details->flags, CD_SET_UID);
695 if (strncmp("runas_privs=", info[i], sizeof("runas_privs=") - 1) == 0) {
697 cp = info[i] + sizeof("runas_privs=") - 1;
701 details->privs = priv_str_to_set(cp, ",", &endp);
702 if (details->privs == NULL)
703 warning("invalid runas_privs %s", endp);
705 if (strncmp("runas_limitprivs=", info[i], sizeof("runas_limitprivs=") - 1) == 0) {
707 cp = info[i] + sizeof("runas_limitprivs=") - 1;
711 details->limitprivs = priv_str_to_set(cp, ",", &endp);
712 if (details->limitprivs == NULL)
713 warning("invalid runas_limitprivs %s", endp);
715 #endif /* HAVE_PRIV_SET */
718 SET_STRING("selinux_role=", selinux_role)
719 SET_STRING("selinux_type=", selinux_type)
720 if (strncmp("set_utmp=", info[i], sizeof("set_utmp=") - 1) == 0) {
721 if (atobool(info[i] + sizeof("set_utmp=") - 1) == true)
722 SET(details->flags, CD_SET_UTMP);
725 if (strncmp("sudoedit=", info[i], sizeof("sudoedit=") - 1) == 0) {
726 if (atobool(info[i] + sizeof("sudoedit=") - 1) == true)
727 SET(details->flags, CD_SUDOEDIT);
732 if (strncmp("timeout=", info[i], sizeof("timeout=") - 1) == 0) {
733 cp = info[i] + sizeof("timeout=") - 1;
737 lval = strtol(cp, &ep, 0);
738 if (*cp != '\0' && *ep == '\0' &&
740 (lval == LONG_MAX || lval == LONG_MIN)) &&
741 lval <= INT_MAX && lval >= 0) {
742 details->timeout = (int)lval;
743 SET(details->flags, CD_SET_TIMEOUT);
749 if (strncmp("umask=", info[i], sizeof("umask=") - 1) == 0) {
750 cp = info[i] + sizeof("umask=") - 1;
754 ulval = strtoul(cp, &ep, 8);
755 if (*cp != '\0' && *ep == '\0' &&
756 (errno != ERANGE || ulval != ULONG_MAX)) {
757 details->umask = (uid_t)ulval;
758 SET(details->flags, CD_SET_UMASK);
762 if (strncmp("use_pty=", info[i], sizeof("use_pty=") - 1) == 0) {
763 if (atobool(info[i] + sizeof("use_pty=") - 1) == true)
764 SET(details->flags, CD_USE_PTY);
767 SET_STRING("utmp_user=", utmp_user)
772 if (!ISSET(details->flags, CD_SET_EUID))
773 details->euid = details->uid;
775 #ifdef HAVE_SETAUTHDB
776 aix_setauthdb(IDtouser(details->euid));
778 details->pw = getpwuid(details->euid);
779 if (details->pw != NULL && (details->pw = pw_dup(details->pw)) == NULL)
781 #ifdef HAVE_SETAUTHDB
786 if (details->selinux_role != NULL && is_selinux_enabled() > 0)
787 SET(details->flags, CD_RBAC_ENABLED);
793 sudo_check_suid(const char *path)
796 debug_decl(sudo_check_suid, SUDO_DEBUG_PCOMM)
798 if (geteuid() != 0) {
799 if (strchr(path, '/') != NULL && stat(path, &sb) == 0) {
800 /* Try to determine why sudo was not running as root. */
801 if (sb.st_uid != ROOT_UID || !ISSET(sb.st_mode, S_ISUID)) {
803 _("%s must be owned by uid %d and have the setuid bit set"),
806 fatalx(_("effective uid is not %d, is %s on a file system "
807 "with the 'nosuid' option set or an NFS file system without"
808 " root privileges?"), ROOT_UID, path);
812 _("effective uid is not %d, is sudo installed setuid root?"),
820 * Disable core dumps to avoid dropping a core with user password in it.
821 * We will reset this limit before executing the command.
822 * Not all operating systems disable core dumps for setuid processes.
825 disable_coredumps(void)
827 #if defined(__linux__) || defined(RLIMIT_CORE)
830 debug_decl(disable_coredumps, SUDO_DEBUG_UTIL)
832 #if defined(__linux__)
834 * Unlimit the number of processes since Linux's setuid() will
835 * apply resource limits when changing uid and return EAGAIN if
836 * nproc would be violated by the uid switch.
838 (void) getrlimit(RLIMIT_NPROC, &nproclimit);
839 rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
840 if (setrlimit(RLIMIT_NPROC, &rl)) {
841 memcpy(&rl, &nproclimit, sizeof(struct rlimit));
842 rl.rlim_cur = rl.rlim_max;
843 (void)setrlimit(RLIMIT_NPROC, &rl);
845 #endif /* __linux__ */
848 * Turn off core dumps?
850 if (sudo_conf_disable_coredump()) {
851 (void) getrlimit(RLIMIT_CORE, &corelimit);
852 memcpy(&rl, &corelimit, sizeof(struct rlimit));
854 (void) setrlimit(RLIMIT_CORE, &rl);
856 #endif /* RLIMIT_CORE */
861 * Setup the execution environment immediately prior to the call to execve()
862 * Returns true on success and false on failure.
865 exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
868 debug_decl(exec_setup, SUDO_DEBUG_EXEC)
871 if (ISSET(details->flags, CD_RBAC_ENABLED)) {
872 if (selinux_setup(details->selinux_role, details->selinux_type,
873 ptyname ? ptyname : user_details.tty, ptyfd) == -1)
878 if (details->pw != NULL) {
879 #ifdef HAVE_PROJECT_H
880 set_project(details->pw);
883 if (details->privs != NULL) {
884 if (setppriv(PRIV_SET, PRIV_INHERITABLE, details->privs) != 0) {
885 warning("unable to set privileges");
889 if (details->limitprivs != NULL) {
890 if (setppriv(PRIV_SET, PRIV_LIMIT, details->limitprivs) != 0) {
891 warning("unable to set limit privileges");
894 } else if (details->privs != NULL) {
895 if (setppriv(PRIV_SET, PRIV_LIMIT, details->privs) != 0) {
896 warning("unable to set limit privileges");
900 #endif /* HAVE_PRIV_SET */
902 #ifdef HAVE_GETUSERATTR
903 aix_prep_user(details->pw->pw_name, ptyname ? ptyname : user_details.tty);
905 #ifdef HAVE_LOGIN_CAP_H
906 if (details->login_class) {
911 * We only use setusercontext() to set the nice value and rlimits
912 * unless this is a login shell (sudo -i).
914 lc = login_getclass((char *)details->login_class);
916 warningx(_("unknown login class %s"), details->login_class);
920 if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
921 /* Set everything except user, group and login name. */
922 flags = LOGIN_SETALL;
923 CLR(flags, LOGIN_SETGROUP|LOGIN_SETLOGIN|LOGIN_SETUSER|LOGIN_SETENV|LOGIN_SETPATH);
924 CLR(details->flags, CD_SET_UMASK); /* LOGIN_UMASK instead */
926 flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
928 if (setusercontext(lc, details->pw, details->pw->pw_uid, flags)) {
929 if (details->pw->pw_uid != ROOT_UID) {
930 warning(_("unable to set user context"));
933 warning(_("unable to set user context"));
936 #endif /* HAVE_LOGIN_CAP_H */
940 * Set groups, including supplementary group vector.
942 if (!ISSET(details->flags, CD_PRESERVE_GROUPS)) {
943 if (details->ngroups >= 0) {
944 if (sudo_setgroups(details->ngroups, details->groups) < 0) {
945 warning(_("unable to set supplementary group IDs"));
951 if (ISSET(details->flags, CD_SET_EGID) && setegid(details->egid)) {
952 warning(_("unable to set effective gid to runas gid %u"),
953 (unsigned int)details->egid);
957 if (ISSET(details->flags, CD_SET_GID) && setgid(details->gid)) {
958 warning(_("unable to set gid to runas gid %u"),
959 (unsigned int)details->gid);
963 if (ISSET(details->flags, CD_SET_PRIORITY)) {
964 if (setpriority(PRIO_PROCESS, 0, details->priority) != 0) {
965 warning(_("unable to set process priority"));
969 if (ISSET(details->flags, CD_SET_UMASK))
970 (void) umask(details->umask);
971 if (details->chroot) {
972 if (chroot(details->chroot) != 0 || chdir("/") != 0) {
973 warning(_("unable to change root to %s"), details->chroot);
978 #ifdef HAVE_SETRESUID
979 if (setresuid(details->uid, details->euid, details->euid) != 0) {
980 warning(_("unable to change to runas uid (%u, %u)"), details->uid,
985 if (setreuid(details->uid, details->euid) != 0) {
986 warning(_("unable to change to runas uid (%u, %u)"),
987 (unsigned int)details->uid, (unsigned int)details->euid);
991 if (seteuid(details->euid) != 0 || setuid(details->euid) != 0) {
992 warning(_("unable to change to runas uid (%u, %u)"), details->uid,
996 #endif /* !HAVE_SETRESUID && !HAVE_SETREUID */
999 * Only change cwd if we have chroot()ed or the policy modules
1000 * specifies a different cwd. Must be done after uid change.
1003 if (details->chroot || strcmp(details->cwd, user_details.cwd) != 0) {
1004 /* Note: cwd is relative to the new root, if any. */
1005 if (chdir(details->cwd) != 0) {
1006 warning(_("unable to change directory to %s"), details->cwd);
1013 * SuSE Enterprise Linux uses RLIMIT_NPROC and _SC_CHILD_MAX
1014 * interchangably. This causes problems when setting RLIMIT_NPROC
1015 * to RLIM_INFINITY due to a bug in bash where bash tries to honor
1016 * the value of _SC_CHILD_MAX but treats a value of -1 as an error,
1017 * and uses a default value of 32 instead.
1019 * To work around this problem, we restore the nproc resource limit
1020 * if sysconf(_SC_CHILD_MAX) is negative. In most cases, pam_limits
1021 * will set RLIMIT_NPROC for us.
1023 * We must do this *after* the uid change to avoid potential EAGAIN
1026 #if defined(__linux__) && defined(_SC_CHILD_MAX)
1031 l = sysconf(_SC_CHILD_MAX);
1032 if (l == -1 && errno == 0 && getrlimit(RLIMIT_NPROC, &rl) == 0) {
1033 if (rl.rlim_cur == RLIM_INFINITY && rl.rlim_max == RLIM_INFINITY)
1034 (void) setrlimit(RLIMIT_NPROC, &nproclimit);
1042 debug_return_bool(rval);
1046 * Run the command and wait for it to complete.
1049 run_command(struct command_details *details)
1051 struct plugin_container *plugin;
1052 struct command_status cstat;
1054 debug_decl(run_command, SUDO_DEBUG_EXEC)
1056 cstat.type = CMD_INVALID;
1059 sudo_execute(details, &cstat);
1061 switch (cstat.type) {
1063 /* exec_setup() or execve() returned an error. */
1064 sudo_debug_printf(SUDO_DEBUG_DEBUG,
1065 "calling policy close with errno %d", cstat.val);
1066 policy_close(&policy_plugin, 0, cstat.val);
1067 tq_foreach_fwd(&io_plugins, plugin) {
1068 sudo_debug_printf(SUDO_DEBUG_DEBUG,
1069 "calling I/O close with errno %d", cstat.val);
1070 iolog_close(plugin, 0, cstat.val);
1075 /* Command ran, exited or was killed. */
1076 sudo_debug_printf(SUDO_DEBUG_DEBUG,
1077 "calling policy close with wait status %d", cstat.val);
1078 policy_close(&policy_plugin, cstat.val, 0);
1079 tq_foreach_fwd(&io_plugins, plugin) {
1080 sudo_debug_printf(SUDO_DEBUG_DEBUG,
1081 "calling I/O close with wait status %d", cstat.val);
1082 iolog_close(plugin, cstat.val, 0);
1084 if (WIFEXITED(cstat.val))
1085 exitcode = WEXITSTATUS(cstat.val);
1086 else if (WIFSIGNALED(cstat.val))
1087 exitcode = WTERMSIG(cstat.val) | 128;
1090 warningx(_("unexpected child termination condition: %d"), cstat.type);
1093 debug_return_int(exitcode);
1097 policy_open(struct plugin_container *plugin, char * const settings[],
1098 char * const user_info[], char * const user_env[])
1101 debug_decl(policy_open, SUDO_DEBUG_PCOMM)
1104 * Backwards compatibility for older API versions
1106 switch (plugin->u.generic->version) {
1107 case SUDO_API_MKVERSION(1, 0):
1108 case SUDO_API_MKVERSION(1, 1):
1109 rval = plugin->u.policy_1_0->open(plugin->u.io_1_0->version,
1110 sudo_conversation, _sudo_printf, settings, user_info, user_env);
1113 rval = plugin->u.policy->open(SUDO_API_VERSION, sudo_conversation,
1114 _sudo_printf, settings, user_info, user_env, plugin->options);
1117 debug_return_bool(rval);
1121 policy_close(struct plugin_container *plugin, int exit_status, int error)
1123 debug_decl(policy_close, SUDO_DEBUG_PCOMM)
1124 if (plugin->u.policy->close != NULL)
1125 plugin->u.policy->close(exit_status, error);
1127 warning(_("unable to execute %s"), command_details.command);
1132 policy_show_version(struct plugin_container *plugin, int verbose)
1134 debug_decl(policy_show_version, SUDO_DEBUG_PCOMM)
1135 if (plugin->u.policy->show_version == NULL)
1136 debug_return_bool(true);
1137 debug_return_bool(plugin->u.policy->show_version(verbose));
1141 policy_check(struct plugin_container *plugin, int argc, char * const argv[],
1142 char *env_add[], char **command_info[], char **argv_out[],
1143 char **user_env_out[])
1145 debug_decl(policy_check, SUDO_DEBUG_PCOMM)
1146 if (plugin->u.policy->check_policy == NULL) {
1147 fatalx(_("policy plugin %s is missing the `check_policy' method"),
1150 debug_return_bool(plugin->u.policy->check_policy(argc, argv, env_add,
1151 command_info, argv_out, user_env_out));
1155 policy_list(struct plugin_container *plugin, int argc, char * const argv[],
1156 int verbose, const char *list_user)
1158 debug_decl(policy_list, SUDO_DEBUG_PCOMM)
1159 if (plugin->u.policy->list == NULL) {
1160 warningx(_("policy plugin %s does not support listing privileges"),
1162 debug_return_bool(false);
1164 debug_return_bool(plugin->u.policy->list(argc, argv, verbose, list_user));
1168 policy_validate(struct plugin_container *plugin)
1170 debug_decl(policy_validate, SUDO_DEBUG_PCOMM)
1171 if (plugin->u.policy->validate == NULL) {
1172 warningx(_("policy plugin %s does not support the -v option"),
1174 debug_return_bool(false);
1176 debug_return_bool(plugin->u.policy->validate());
1180 policy_invalidate(struct plugin_container *plugin, int remove)
1182 debug_decl(policy_invalidate, SUDO_DEBUG_PCOMM)
1183 if (plugin->u.policy->invalidate == NULL) {
1184 fatalx(_("policy plugin %s does not support the -k/-K options"),
1187 plugin->u.policy->invalidate(remove);
1192 policy_init_session(struct command_details *details)
1195 debug_decl(policy_init_session, SUDO_DEBUG_PCOMM)
1197 if (policy_plugin.u.policy->init_session) {
1199 * Backwards compatibility for older API versions
1201 switch (policy_plugin.u.generic->version) {
1202 case SUDO_API_MKVERSION(1, 0):
1203 case SUDO_API_MKVERSION(1, 1):
1204 rval = policy_plugin.u.policy_1_0->init_session(details->pw);
1207 rval = policy_plugin.u.policy->init_session(details->pw,
1211 debug_return_bool(rval);
1215 iolog_open(struct plugin_container *plugin, char * const settings[],
1216 char * const user_info[], char * const command_info[],
1217 int argc, char * const argv[], char * const user_env[])
1220 debug_decl(iolog_open, SUDO_DEBUG_PCOMM)
1223 * Backwards compatibility for older API versions
1225 switch (plugin->u.generic->version) {
1226 case SUDO_API_MKVERSION(1, 0):
1227 rval = plugin->u.io_1_0->open(plugin->u.io_1_0->version,
1228 sudo_conversation, _sudo_printf, settings, user_info, argc, argv,
1231 case SUDO_API_MKVERSION(1, 1):
1232 rval = plugin->u.io_1_1->open(plugin->u.io_1_1->version,
1233 sudo_conversation, _sudo_printf, settings, user_info,
1234 command_info, argc, argv, user_env);
1237 rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
1238 _sudo_printf, settings, user_info, command_info,
1239 argc, argv, user_env, plugin->options);
1241 debug_return_bool(rval);
1245 iolog_close(struct plugin_container *plugin, int exit_status, int error)
1247 debug_decl(iolog_close, SUDO_DEBUG_PCOMM)
1248 if (plugin->u.io->close != NULL)
1249 plugin->u.io->close(exit_status, error);
1254 iolog_show_version(struct plugin_container *plugin, int verbose)
1256 debug_decl(iolog_show_version, SUDO_DEBUG_PCOMM)
1257 if (plugin->u.io->show_version == NULL)
1258 debug_return_bool(true);
1259 debug_return_bool(plugin->u.io->show_version(verbose));
1263 * Remove the specified I/O logging plugin from the io_plugins list.
1264 * Deregisters any hooks before unlinking, then frees the container.
1267 iolog_unlink(struct plugin_container *plugin)
1269 debug_decl(iolog_unlink, SUDO_DEBUG_PCOMM)
1271 /* Deregister hooks, if any. */
1272 if (plugin->u.io->version >= SUDO_API_MKVERSION(1, 2)) {
1273 if (plugin->u.io->deregister_hooks != NULL)
1274 plugin->u.io->deregister_hooks(SUDO_HOOK_VERSION,
1277 /* Remove from io_plugins list and free. */
1278 tq_remove(&io_plugins, plugin);