Imported Upstream version 1.8.5
[debian/sudo] / plugins / sudoers / sudoers.c
1 /*
2  * Copyright (c) 1993-1996, 1998-2011 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
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.
7  *
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.
15  *
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.
19  *
20  * For a brief history of sudo, please see the HISTORY file included
21  * with this distribution.
22  */
23
24 #define _SUDO_MAIN
25
26 #ifdef __TANDEM
27 # include <floss.h>
28 #endif
29
30 #include <config.h>
31
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/param.h>
35 #include <sys/socket.h>
36 #include <stdio.h>
37 #ifdef STDC_HEADERS
38 # include <stdlib.h>
39 # include <stddef.h>
40 #else
41 # ifdef HAVE_STDLIB_H
42 #  include <stdlib.h>
43 # endif
44 #endif /* STDC_HEADERS */
45 #ifdef HAVE_STRING_H
46 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
47 #  include <memory.h>
48 # endif
49 # include <string.h>
50 #endif /* HAVE_STRING_H */
51 #ifdef HAVE_STRINGS_H
52 # include <strings.h>
53 #endif /* HAVE_STRINGS_H */
54 #ifdef HAVE_UNISTD_H
55 # include <unistd.h>
56 #endif /* HAVE_UNISTD_H */
57 #include <pwd.h>
58 #include <errno.h>
59 #include <fcntl.h>
60 #include <signal.h>
61 #include <grp.h>
62 #include <time.h>
63 #ifdef HAVE_SETLOCALE
64 # include <locale.h>
65 #endif
66 #include <netinet/in.h>
67 #include <netdb.h>
68 #ifdef HAVE_LOGIN_CAP_H
69 # include <login_cap.h>
70 # ifndef LOGIN_DEFROOTCLASS
71 #  define LOGIN_DEFROOTCLASS    "daemon"
72 # endif
73 # ifndef LOGIN_SETENV
74 #  define LOGIN_SETENV  0
75 # endif
76 #endif
77 #ifdef HAVE_SELINUX
78 # include <selinux/selinux.h>
79 #endif
80 #include <ctype.h>
81 #include <setjmp.h>
82 #ifndef HAVE_GETADDRINFO
83 # include "compat/getaddrinfo.h"
84 #endif
85
86 #include "sudoers.h"
87 #include "interfaces.h"
88 #include "sudoers_version.h"
89 #include "auth/sudo_auth.h"
90 #include "secure_path.h"
91
92 /*
93  * Prototypes
94  */
95 static void init_vars(char * const *);
96 static int set_cmnd(void);
97 static void set_loginclass(struct passwd *);
98 static void set_runaspw(const char *);
99 static void set_runasgr(const char *);
100 static int cb_runas_default(const char *);
101 static int sudoers_policy_version(int verbose);
102 static int deserialize_info(char * const args[], char * const settings[],
103     char * const user_info[]);
104 static char *find_editor(int nfiles, char **files, char ***argv_out);
105 static void create_admin_success_flag(void);
106
107 /*
108  * Globals
109  */
110 struct sudo_user sudo_user;
111 struct passwd *list_pw;
112 struct interface *interfaces;
113 int long_list;
114 uid_t timestamp_uid;
115 extern int errorlineno;
116 extern bool parse_error;
117 extern char *errorfile;
118 #ifdef HAVE_BSD_AUTH_H
119 char *login_style;
120 #endif /* HAVE_BSD_AUTH_H */
121 sudo_conv_t sudo_conv;
122 sudo_printf_t sudo_printf;
123 int sudo_mode;
124
125 static int sudo_version;
126 static char *prev_user;
127 static char *runas_user;
128 static char *runas_group;
129 static struct sudo_nss_list *snl;
130 static const char *interfaces_string;
131 static sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp;
132
133 /* XXX - must be extern for audit bits of sudo_auth.c */
134 int NewArgc;
135 char **NewArgv;
136
137 /* Declared here instead of plugin_error.c for static sudo builds. */
138 sigjmp_buf error_jmp;
139
140 static int
141 sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
142     sudo_printf_t plugin_printf, char * const settings[],
143     char * const user_info[], char * const envp[], char * const args[])
144 {
145     volatile int sources = 0;
146     sigaction_t sa;
147     struct sudo_nss *nss;
148     debug_decl(sudoers_policy_open, SUDO_DEBUG_PLUGIN)
149
150     sudo_version = version;
151     if (!sudo_conv)
152         sudo_conv = conversation;
153     if (!sudo_printf)
154         sudo_printf = plugin_printf;
155
156     /* Plugin args are only specified for API version 1.2 and higher. */
157     if (sudo_version < SUDO_API_MKVERSION(1, 2))
158         args = NULL;
159
160     if (sigsetjmp(error_jmp, 1)) {
161         /* called via error(), errorx() or log_fatal() */
162         rewind_perms();
163         debug_return_bool(-1);
164     }
165
166     bindtextdomain("sudoers", LOCALEDIR);
167
168     /*
169      * Signal setup:
170      *  Ignore keyboard-generated signals so the user cannot interrupt
171      *  us at some point and avoid the logging.
172      *  Install handler to wait for children when they exit.
173      */
174     zero_bytes(&sa, sizeof(sa));
175     sigemptyset(&sa.sa_mask);
176     sa.sa_flags = SA_RESTART;
177     sa.sa_handler = SIG_IGN;
178     (void) sigaction(SIGINT, &sa, &saved_sa_int);
179     (void) sigaction(SIGQUIT, &sa, &saved_sa_quit);
180     (void) sigaction(SIGTSTP, &sa, &saved_sa_tstp);
181
182     sudo_setpwent();
183     sudo_setgrent();
184
185     /* Initialize environment functions (including replacements). */
186     env_init(envp);
187
188     /* Setup defaults data structures. */
189     init_defaults();
190
191     /* Parse args, settings and user_info */
192     sudo_mode = deserialize_info(args, settings, user_info);
193
194     init_vars(envp);            /* XXX - move this later? */
195
196     /* Parse nsswitch.conf for sudoers order. */
197     snl = sudo_read_nss();
198
199     /* LDAP or NSS may modify the euid so we need to be root for the open. */
200     set_perms(PERM_INITIAL);
201     set_perms(PERM_ROOT);
202
203     /* Open and parse sudoers, set global defaults */
204     tq_foreach_fwd(snl, nss) {
205         if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
206             sources++;
207             if (nss->setdefs(nss) != 0)
208                 log_error(NO_STDERR, _("problem with defaults entries"));
209         }
210     }
211     if (sources == 0) {
212         warningx(_("no valid sudoers sources found, quitting"));
213         debug_return_bool(-1);
214     }
215
216     /* XXX - collect post-sudoers parse settings into a function */
217
218     /*
219      * Initialize external group plugin, if any.
220      */
221     if (def_group_plugin) {
222         if (group_plugin_load(def_group_plugin) != true)
223             def_group_plugin = NULL;
224     }
225
226     /*
227      * Set runas passwd/group entries based on command line or sudoers.
228      * Note that if runas_group was specified without runas_user we
229      * defer setting runas_pw so the match routines know to ignore it.
230      */
231     if (runas_group != NULL) {
232         set_runasgr(runas_group);
233         if (runas_user != NULL)
234             set_runaspw(runas_user);
235     } else
236         set_runaspw(runas_user ? runas_user : def_runas_default);
237
238     if (!update_defaults(SETDEF_RUNAS))
239         log_error(NO_STDERR, _("problem with defaults entries"));
240
241     if (def_fqdn)
242         set_fqdn();     /* deferred until after sudoers is parsed */
243
244     /* Set login class if applicable. */
245     set_loginclass(runas_pw ? runas_pw : sudo_user.pw);
246
247     restore_perms();
248
249     debug_return_bool(true);
250 }
251
252 static void
253 sudoers_policy_close(int exit_status, int error_code)
254 {
255     debug_decl(sudoers_policy_close, SUDO_DEBUG_PLUGIN)
256
257     if (sigsetjmp(error_jmp, 1)) {
258         /* called via error(), errorx() or log_fatal() */
259         debug_return;
260     }
261
262     /* We do not currently log the exit status. */
263     if (error_code)
264         warningx(_("unable to execute %s: %s"), safe_cmnd, strerror(error_code));
265
266     /* Close the session we opened in sudoers_policy_init_session(). */
267     if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT))
268         (void)sudo_auth_end_session(runas_pw);
269
270     /* Free remaining references to password and group entries. */
271     pw_delref(sudo_user.pw);
272     pw_delref(runas_pw);
273     if (runas_gr != NULL)
274         gr_delref(runas_gr);
275     if (user_group_list != NULL)
276         grlist_delref(user_group_list);
277
278     debug_return;
279 }
280
281 /*
282  * The init_session function is called before executing the command
283  * and before uid/gid changes occur.
284  */
285 static int
286 sudoers_policy_init_session(struct passwd *pwd, char **user_env[])
287 {
288     debug_decl(sudoers_policy_init, SUDO_DEBUG_PLUGIN)
289
290     /* user_env is only specified for API version 1.2 and higher. */
291     if (sudo_version < SUDO_API_MKVERSION(1, 2))
292         user_env = NULL;
293
294     if (sigsetjmp(error_jmp, 1)) {
295         /* called via error(), errorx() or log_fatal() */
296         return -1;
297     }
298
299     debug_return_bool(sudo_auth_begin_session(pwd, user_env));
300 }
301
302 static int
303 sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
304     char **command_infop[], char **argv_out[], char **user_env_out[])
305 {
306     static char *command_info[32]; /* XXX */
307     char **edit_argv = NULL;
308     struct sudo_nss *nss;
309     int cmnd_status = -1, validated;
310     volatile int info_len = 0;
311     volatile int rval = true;
312     debug_decl(sudoers_policy_main, SUDO_DEBUG_PLUGIN)
313
314     if (sigsetjmp(error_jmp, 1)) {
315         /* error recovery via error(), errorx() or log_fatal() */
316         rval = -1;
317         goto done;
318     }
319
320     /* Is root even allowed to run sudo? */
321     if (user_uid == 0 && !def_root_sudo) {
322         warningx(_("sudoers specifies that root is not allowed to sudo"));
323         goto bad;
324     }    
325
326     /* Check for -C overriding def_closefrom. */
327     if (user_closefrom >= 0 && user_closefrom != def_closefrom) {
328         if (!def_closefrom_override) {
329             warningx(_("you are not permitted to use the -C option"));
330             goto bad;
331         }
332         def_closefrom = user_closefrom;
333     }
334
335     set_perms(PERM_INITIAL);
336
337     /* Environment variables specified on the command line. */
338     if (env_add != NULL && env_add[0] != NULL)
339         sudo_user.env_vars = env_add;
340
341     /*
342      * Make a local copy of argc/argv, with special handling
343      * for pseudo-commands and the '-i' option.
344      */
345     if (argc == 0) {
346         NewArgc = 1;
347         NewArgv = emalloc2(NewArgc + 1, sizeof(char *));
348         NewArgv[0] = user_cmnd;
349         NewArgv[1] = NULL;
350     } else {
351         /* Must leave an extra slot before NewArgv for bash's --login */
352         NewArgc = argc;
353         NewArgv = emalloc2(NewArgc + 2, sizeof(char *));
354         memcpy(++NewArgv, argv, argc * sizeof(char *));
355         NewArgv[NewArgc] = NULL;
356         if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && runas_pw != NULL)
357             NewArgv[0] = estrdup(runas_pw->pw_shell);
358     }
359
360     /* If given the -P option, set the "preserve_groups" flag. */
361     if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
362         def_preserve_groups = true;
363
364     /* Find command in path */
365     cmnd_status = set_cmnd();
366     if (cmnd_status == -1) {
367         rval = -1;
368         goto done;
369     }
370
371 #ifdef HAVE_SETLOCALE
372     if (!setlocale(LC_ALL, def_sudoers_locale)) {
373         warningx(_("unable to set locale to \"%s\", using \"C\""),
374             def_sudoers_locale);
375         setlocale(LC_ALL, "C");
376     }
377 #endif
378
379     /*
380      * Check sudoers sources.
381      */
382     validated = FLAG_NO_USER | FLAG_NO_HOST;
383     tq_foreach_fwd(snl, nss) {
384         validated = nss->lookup(nss, validated, pwflag);
385
386         if (ISSET(validated, VALIDATE_OK)) {
387             /* Handle "= auth" in netsvc.conf */
388             if (nss->ret_if_found)
389                 break;
390         } else {
391             /* Handle [NOTFOUND=return] */
392             if (nss->ret_if_notfound)
393                 break;
394         }
395     }
396
397     if (safe_cmnd == NULL)
398         safe_cmnd = estrdup(user_cmnd);
399
400 #ifdef HAVE_SETLOCALE
401     setlocale(LC_ALL, "");
402 #endif
403
404     /* If only a group was specified, set runas_pw based on invoking user. */
405     if (runas_pw == NULL)
406         set_runaspw(user_name);
407
408     /*
409      * Look up the timestamp dir owner if one is specified.
410      */
411     if (def_timestampowner) {
412         struct passwd *pw;
413
414         if (*def_timestampowner == '#')
415             pw = sudo_getpwuid(atoi(def_timestampowner + 1));
416         else
417             pw = sudo_getpwnam(def_timestampowner);
418         if (pw != NULL) {
419             timestamp_uid = pw->pw_uid;
420             pw_delref(pw);
421         } else {
422             log_error(0, _("timestamp owner (%s): No such user"),
423                 def_timestampowner);
424             timestamp_uid = ROOT_UID;
425         }
426     }
427
428     /* If no command line args and "shell_noargs" is not set, error out. */
429     if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) {
430         rval = -2; /* usage error */
431         goto done;
432     }
433
434     /* Bail if a tty is required and we don't have one.  */
435     if (def_requiretty) {
436         int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY);
437         if (fd == -1) {
438             audit_failure(NewArgv, _("no tty"));
439             warningx(_("sorry, you must have a tty to run sudo"));
440             goto bad;
441         } else
442             (void) close(fd);
443     }
444
445     /*
446      * We don't reset the environment for sudoedit or if the user
447      * specified the -E command line flag and they have setenv privs.
448      */
449     if (ISSET(sudo_mode, MODE_EDIT) ||
450         (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv))
451         def_env_reset = false;
452
453     /* Build a new environment that avoids any nasty bits. */
454     rebuild_env();
455
456     /* Require a password if sudoers says so.  */
457     rval = check_user(validated, sudo_mode);
458     if (rval != true)
459         goto done;
460
461     /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
462     /* XXX - causes confusion when root is not listed in sudoers */
463     if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) {
464         if (user_uid == 0 && strcmp(prev_user, "root") != 0) {
465             struct passwd *pw;
466
467             if ((pw = sudo_getpwnam(prev_user)) != NULL) {
468                     if (sudo_user.pw != NULL)
469                         pw_delref(sudo_user.pw);
470                     sudo_user.pw = pw;
471             }
472         }
473     }
474
475     /* If the user was not allowed to run the command we are done. */
476     if (!ISSET(validated, VALIDATE_OK)) {
477         if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) {
478             audit_failure(NewArgv, _("No user or host"));
479             log_denial(validated, 1);
480         } else {
481             if (def_path_info) {
482                 /*
483                  * We'd like to not leak path info at all here, but that can
484                  * *really* confuse the users.  To really close the leak we'd
485                  * have to say "not allowed to run foo" even when the problem
486                  * is just "no foo in path" since the user can trivially set
487                  * their path to just contain a single dir.
488                  */
489                 log_denial(validated,
490                     !(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND));
491                 if (cmnd_status == NOT_FOUND)
492                     warningx(_("%s: command not found"), user_cmnd);
493                 else if (cmnd_status == NOT_FOUND_DOT)
494                     warningx(_("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run."), user_cmnd, user_cmnd, user_cmnd);
495             } else {
496                 /* Just tell the user they are not allowed to run foo. */
497                 log_denial(validated, 1);
498             }
499             audit_failure(NewArgv, _("validation failure"));
500         }
501         goto bad;
502     }
503
504     /* Create Ubuntu-style dot file to indicate sudo was successful. */
505     create_admin_success_flag();
506
507     /* Finally tell the user if the command did not exist. */
508     if (cmnd_status == NOT_FOUND_DOT) {
509         audit_failure(NewArgv, _("command in current directory"));
510         warningx(_("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run."), user_cmnd, user_cmnd, user_cmnd);
511         goto bad;
512     } else if (cmnd_status == NOT_FOUND) {
513         audit_failure(NewArgv, _("%s: command not found"), user_cmnd);
514         warningx(_("%s: command not found"), user_cmnd);
515         goto bad;
516     }
517
518     /* If user specified env vars make sure sudoers allows it. */
519     if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) {
520         if (ISSET(sudo_mode, MODE_PRESERVE_ENV)) {
521             warningx(_("sorry, you are not allowed to preserve the environment"));
522             goto bad;
523         } else
524             validate_env_vars(sudo_user.env_vars);
525     }
526
527     if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && (def_log_input || def_log_output)) {
528         if (def_iolog_file && def_iolog_dir) {
529             command_info[info_len++] = expand_iolog_path("iolog_path=",
530                 def_iolog_dir, def_iolog_file, &sudo_user.iolog_file);
531             sudo_user.iolog_file++;
532         }
533         if (def_log_input) {
534             command_info[info_len++] = estrdup("iolog_stdin=true");
535             command_info[info_len++] = estrdup("iolog_ttyin=true");
536         }
537         if (def_log_output) {
538             command_info[info_len++] = estrdup("iolog_stdout=true");
539             command_info[info_len++] = estrdup("iolog_stderr=true");
540             command_info[info_len++] = estrdup("iolog_ttyout=true");
541         }
542         if (def_compress_io)
543             command_info[info_len++] = estrdup("iolog_compress=true");
544     }
545
546     log_allowed(validated);
547     if (ISSET(sudo_mode, MODE_CHECK))
548         rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
549     else if (ISSET(sudo_mode, MODE_LIST))
550         display_privs(snl, list_pw ? list_pw : sudo_user.pw); /* XXX - return val */
551
552     /* Cleanup sudoers sources */
553     tq_foreach_fwd(snl, nss) {
554         nss->close(nss);
555     }
556     if (def_group_plugin)
557         group_plugin_unload();
558
559     if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) {
560         /* rval already set appropriately */
561         goto done;
562     }
563
564     /*
565      * Set umask based on sudoers.
566      * If user's umask is more restrictive, OR in those bits too
567      * unless umask_override is set.
568      */
569     if (def_umask != 0777) {
570         mode_t mask = def_umask;
571         if (!def_umask_override) {
572             mode_t omask = umask(mask);
573             mask |= omask;
574             umask(omask);
575         }
576         easprintf(&command_info[info_len++], "umask=0%o", (unsigned int)mask);
577     }
578
579     if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
580         char *p;
581
582         /* Convert /bin/sh -> -sh so shell knows it is a login shell */
583         if ((p = strrchr(NewArgv[0], '/')) == NULL)
584             p = NewArgv[0];
585         *p = '-';
586         NewArgv[0] = p;
587
588         /* Set cwd to run user's homedir. */
589         command_info[info_len++] = fmt_string("cwd", runas_pw->pw_dir);
590
591         /*
592          * Newer versions of bash require the --login option to be used
593          * in conjunction with the -c option even if the shell name starts
594          * with a '-'.  Unfortunately, bash 1.x uses -login, not --login
595          * so this will cause an error for that.
596          */
597         if (NewArgc > 1 && strcmp(NewArgv[0], "-bash") == 0 &&
598             strcmp(NewArgv[1], "-c") == 0) {
599             /* Use the extra slot before NewArgv so we can store --login. */
600             NewArgv--;
601             NewArgc++;
602             NewArgv[0] = NewArgv[1];
603             NewArgv[1] = "--login";
604         }
605
606 #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM))
607         /* Insert system-wide environment variables. */
608         read_env_file(_PATH_ENVIRONMENT, true);
609 #endif
610 #ifdef HAVE_LOGIN_CAP_H
611         /* Set environment based on login class. */
612         if (login_class) {
613             login_cap_t *lc = login_getclass(login_class);
614             if (lc != NULL) {
615                 setusercontext(lc, runas_pw, runas_pw->pw_uid, LOGIN_SETPATH|LOGIN_SETENV);
616                 login_close(lc);
617             }
618         }
619 #endif /* HAVE_LOGIN_CAP_H */
620     }
621
622     /* Insert system-wide environment variables. */
623     if (def_env_file)
624         read_env_file(def_env_file, false);
625
626     /* Insert user-specified environment variables. */
627     insert_env_vars(sudo_user.env_vars);
628
629     /* Restore signal handlers before we exec. */
630     (void) sigaction(SIGINT, &saved_sa_int, NULL);
631     (void) sigaction(SIGQUIT, &saved_sa_quit, NULL);
632     (void) sigaction(SIGTSTP, &saved_sa_tstp, NULL);
633
634     if (ISSET(sudo_mode, MODE_EDIT)) {
635         char *editor = find_editor(NewArgc - 1, NewArgv + 1, &edit_argv);
636         if (editor == NULL)
637             goto bad;
638         command_info[info_len++] = fmt_string("command", editor);
639         command_info[info_len++] = estrdup("sudoedit=true");
640     } else {
641         command_info[info_len++] = fmt_string("command", safe_cmnd);
642     }
643     if (def_stay_setuid) {
644         easprintf(&command_info[info_len++], "runas_uid=%u",
645             (unsigned int)user_uid);
646         easprintf(&command_info[info_len++], "runas_gid=%u",
647             (unsigned int)user_gid);
648         easprintf(&command_info[info_len++], "runas_euid=%u",
649             (unsigned int)runas_pw->pw_uid);
650         easprintf(&command_info[info_len++], "runas_egid=%u",
651             runas_gr ? (unsigned int)runas_gr->gr_gid :
652             (unsigned int)runas_pw->pw_gid);
653     } else {
654         easprintf(&command_info[info_len++], "runas_uid=%u",
655             (unsigned int)runas_pw->pw_uid);
656         easprintf(&command_info[info_len++], "runas_gid=%u",
657             runas_gr ? (unsigned int)runas_gr->gr_gid :
658             (unsigned int)runas_pw->pw_gid);
659     }
660     if (def_preserve_groups) {
661         command_info[info_len++] = "preserve_groups=true";
662     } else {
663         int i, len;
664         gid_t egid;
665         size_t glsize;
666         char *cp, *gid_list;
667         struct group_list *grlist = get_group_list(runas_pw);
668
669         /* We reserve an extra spot in the list for the effective gid. */
670         glsize = sizeof("runas_groups=") - 1 +
671             ((grlist->ngids + 1) * (MAX_UID_T_LEN + 1));
672         gid_list = emalloc(glsize);
673         memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1);
674         cp = gid_list + sizeof("runas_groups=") - 1;
675
676         /* On BSD systems the effective gid is the first group in the list. */
677         egid = runas_gr ? (unsigned int)runas_gr->gr_gid :
678             (unsigned int)runas_pw->pw_gid;
679         len = snprintf(cp, glsize - (cp - gid_list), "%u", egid);
680         if (len < 0 || len >= glsize - (cp - gid_list))
681             errorx(1, _("internal error, runas_groups overflow"));
682         cp += len;
683         for (i = 0; i < grlist->ngids; i++) {
684             if (grlist->gids[i] != egid) {
685                 len = snprintf(cp, glsize - (cp - gid_list), ",%u",
686                      (unsigned int) grlist->gids[i]);
687                 if (len < 0 || len >= glsize - (cp - gid_list))
688                     errorx(1, _("internal error, runas_groups overflow"));
689                 cp += len;
690             }
691         }
692         command_info[info_len++] = gid_list;
693         grlist_delref(grlist);
694     }
695     if (def_closefrom >= 0)
696         easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom);
697     if (def_noexec)
698         command_info[info_len++] = estrdup("noexec=true");
699     if (def_set_utmp)
700         command_info[info_len++] = estrdup("set_utmp=true");
701     if (def_use_pty)
702         command_info[info_len++] = estrdup("use_pty=true");
703     if (def_utmp_runas)
704         command_info[info_len++] = fmt_string("utmp_user", runas_pw->pw_name);
705 #ifdef HAVE_LOGIN_CAP_H
706     if (def_use_loginclass)
707         command_info[info_len++] = fmt_string("login_class", login_class);
708 #endif /* HAVE_LOGIN_CAP_H */
709 #ifdef HAVE_SELINUX
710     if (user_role != NULL)
711         command_info[info_len++] = fmt_string("selinux_role", user_role);
712     if (user_type != NULL)
713         command_info[info_len++] = fmt_string("selinux_type", user_type);
714 #endif /* HAVE_SELINUX */
715
716     /* Must audit before uid change. */
717     audit_success(NewArgv);
718
719     *command_infop = command_info;
720
721     *argv_out = edit_argv ? edit_argv : NewArgv;
722
723     /* Get private version of the environment and zero out stashed copy. */
724     *user_env_out = env_get();
725     env_init(NULL);
726
727     goto done;
728
729 bad:
730     rval = false;
731
732 done:
733     rewind_perms();
734
735     /* Close the password and group files and free up memory. */
736     sudo_endpwent();
737     sudo_endgrent();
738
739     debug_return_bool(rval);
740 }
741
742 static int
743 sudoers_policy_check(int argc, char * const argv[], char *env_add[],
744     char **command_infop[], char **argv_out[], char **user_env_out[])
745 {
746     debug_decl(sudoers_policy_check, SUDO_DEBUG_PLUGIN)
747
748     if (!ISSET(sudo_mode, MODE_EDIT))
749         SET(sudo_mode, MODE_RUN);
750
751     debug_return_bool(sudoers_policy_main(argc, argv, 0, env_add, command_infop,
752         argv_out, user_env_out));
753 }
754
755 static int
756 sudoers_policy_validate(void)
757 {
758     debug_decl(sudoers_policy_validate, SUDO_DEBUG_PLUGIN)
759
760     user_cmnd = "validate";
761     SET(sudo_mode, MODE_VALIDATE);
762
763     debug_return_bool(sudoers_policy_main(0, NULL, I_VERIFYPW, NULL, NULL, NULL, NULL));
764 }
765
766 static void
767 sudoers_policy_invalidate(int remove)
768 {
769     debug_decl(sudoers_policy_invalidate, SUDO_DEBUG_PLUGIN)
770
771     user_cmnd = "kill";
772     if (sigsetjmp(error_jmp, 1) == 0) {
773         remove_timestamp(remove);
774         plugin_cleanup(0);
775     }
776
777     debug_return;
778 }
779
780 static int
781 sudoers_policy_list(int argc, char * const argv[], int verbose,
782     const char *list_user)
783 {
784     int rval;
785     debug_decl(sudoers_policy_list, SUDO_DEBUG_PLUGIN)
786
787     user_cmnd = "list";
788     if (argc)
789         SET(sudo_mode, MODE_CHECK);
790     else
791         SET(sudo_mode, MODE_LIST);
792     if (verbose)
793         long_list = 1;
794     if (list_user) {
795         list_pw = sudo_getpwnam(list_user);
796         if (list_pw == NULL) {
797             warningx(_("unknown user: %s"), list_user);
798             debug_return_bool(-1);
799         }
800     }
801     rval = sudoers_policy_main(argc, argv, I_LISTPW, NULL, NULL, NULL, NULL);
802     if (list_user) {
803         pw_delref(list_pw);
804         list_pw = NULL;
805     }
806
807     debug_return_bool(rval);
808 }
809
810 /*
811  * Initialize timezone, set umask, fill in ``sudo_user'' struct and
812  * load the ``interfaces'' array.
813  */
814 static void
815 init_vars(char * const envp[])
816 {
817     char * const * ep;
818     debug_decl(init_vars, SUDO_DEBUG_PLUGIN)
819
820 #ifdef HAVE_TZSET
821     (void) tzset();             /* set the timezone if applicable */
822 #endif /* HAVE_TZSET */
823
824     for (ep = envp; *ep; ep++) {
825         /* XXX - don't fill in if empty string */
826         switch (**ep) {
827             case 'K':
828                 if (strncmp("KRB5CCNAME=", *ep, 11) == 0)
829                     user_ccname = *ep + 11;
830                 break;
831             case 'P':
832                 if (strncmp("PATH=", *ep, 5) == 0)
833                     user_path = *ep + 5;
834                 break;
835             case 'S':
836                 if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
837                     user_prompt = *ep + 12;
838                 else if (strncmp("SUDO_USER=", *ep, 10) == 0)
839                     prev_user = *ep + 10;
840                 break;
841             }
842     }
843
844     /*
845      * Get a local copy of the user's struct passwd with the shadow password
846      * if necessary.  It is assumed that euid is 0 at this point so we
847      * can read the shadow passwd file if necessary.
848      */
849     if ((sudo_user.pw = sudo_getpwuid(user_uid)) == NULL) {
850         /*
851          * It is not unusual for users to place "sudo -k" in a .logout
852          * file which can cause sudo to be run during reboot after the
853          * YP/NIS/NIS+/LDAP/etc daemon has died.
854          */
855         if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE)
856             errorx(1, _("unknown uid: %u"), (unsigned int) user_uid);
857
858         /* Need to make a fake struct passwd for the call to log_fatal(). */
859         sudo_user.pw = sudo_fakepwnamid(user_name, user_uid, user_gid);
860         log_fatal(0, _("unknown uid: %u"), (unsigned int) user_uid);
861         /* NOTREACHED */
862     }
863
864     /*
865      * Get group list.
866      */
867     if (user_group_list == NULL)
868         user_group_list = get_group_list(sudo_user.pw);
869
870     /* Set runas callback. */
871     sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default;
872
873     /* It is now safe to use log_fatal() and set_perms() */
874     debug_return;
875 }
876
877 /*
878  * Fill in user_cmnd, user_args, user_base and user_stat variables
879  * and apply any command-specific defaults entries.
880  */
881 static int
882 set_cmnd(void)
883 {
884     int rval;
885     char *path = user_path;
886     debug_decl(set_cmnd, SUDO_DEBUG_PLUGIN)
887
888     /* Resolve the path and return. */
889     rval = FOUND;
890     user_stat = ecalloc(1, sizeof(struct stat));
891
892     /* Default value for cmnd, overridden below. */
893     if (user_cmnd == NULL)
894         user_cmnd = NewArgv[0];
895
896     if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
897         if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
898             if (def_secure_path && !user_is_exempt())
899                 path = def_secure_path;
900             set_perms(PERM_RUNAS);
901             rval = find_path(NewArgv[0], &user_cmnd, user_stat, path,
902                 def_ignore_dot);
903             restore_perms();
904             if (rval != FOUND) {
905                 /* Failed as root, try as invoking user. */
906                 set_perms(PERM_USER);
907                 rval = find_path(NewArgv[0], &user_cmnd, user_stat, path,
908                     def_ignore_dot);
909                 restore_perms();
910             }
911         }
912
913         /* set user_args */
914         if (NewArgc > 1) {
915             char *to, *from, **av;
916             size_t size, n;
917
918             /* Alloc and build up user_args. */
919             for (size = 0, av = NewArgv + 1; *av; av++)
920                 size += strlen(*av) + 1;
921             user_args = emalloc(size);
922             if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
923                 /*
924                  * When running a command via a shell, the sudo front-end
925                  * escapes potential meta chars.  We unescape non-spaces
926                  * for sudoers matching and logging purposes.
927                  */
928                 for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
929                     while (*from) {
930                         if (from[0] == '\\' && !isspace((unsigned char)from[1]))
931                             from++;
932                         *to++ = *from++;
933                     }
934                     *to++ = ' ';
935                 }
936                 *--to = '\0';
937             } else {
938                 for (to = user_args, av = NewArgv + 1; *av; av++) {
939                     n = strlcpy(to, *av, size - (to - user_args));
940                     if (n >= size - (to - user_args))
941                         errorx(1, _("internal error, set_cmnd() overflow"));
942                     to += n;
943                     *to++ = ' ';
944                 }
945                 *--to = '\0';
946             }
947         }
948     }
949     if (strlen(user_cmnd) >= PATH_MAX)
950         errorx(1, _("%s: %s"), user_cmnd, strerror(ENAMETOOLONG));
951
952     if ((user_base = strrchr(user_cmnd, '/')) != NULL)
953         user_base++;
954     else
955         user_base = user_cmnd;
956
957     if (!update_defaults(SETDEF_CMND))
958         log_error(NO_STDERR, _("problem with defaults entries"));
959
960     debug_return_int(rval);
961 }
962
963 /*
964  * Open sudoers and sanity check mode/owner/type.
965  * Returns a handle to the sudoers file or NULL on error.
966  */
967 FILE *
968 open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
969 {
970     struct stat sb;
971     FILE *fp = NULL;
972     debug_decl(open_sudoers, SUDO_DEBUG_PLUGIN)
973
974     set_perms(PERM_SUDOERS);
975
976     switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) {
977         case SUDO_PATH_SECURE:
978             if ((fp = fopen(sudoers, "r")) == NULL) {
979                 log_error(USE_ERRNO, _("unable to open %s"), sudoers);
980             } else {
981                 /*
982                  * Make sure we can actually read sudoers so we can present the
983                  * user with a reasonable error message (unlike the lexer).
984                  */
985                 if (sb.st_size != 0 && fgetc(fp) == EOF) {
986                     log_error(USE_ERRNO, _("unable to read %s"),
987                         sudoers);
988                     fclose(fp);
989                     fp = NULL;
990                 } else {
991                     /* Rewind fp and set close on exec flag. */
992                     rewind(fp);
993                     (void) fcntl(fileno(fp), F_SETFD, 1);
994                 }
995             }
996             break;
997         case SUDO_PATH_MISSING:
998             log_error(USE_ERRNO, _("unable to stat %s"), sudoers);
999             break;
1000         case SUDO_PATH_BAD_TYPE:
1001             log_error(0, _("%s is not a regular file"), sudoers);
1002             break;
1003         case SUDO_PATH_WRONG_OWNER:
1004             log_error(0, _("%s is owned by uid %u, should be %u"),
1005                 sudoers, (unsigned int) sb.st_uid, (unsigned int) sudoers_uid);
1006             break;
1007         case SUDO_PATH_WORLD_WRITABLE:
1008             log_error(0, _("%s is world writable"), sudoers);
1009             break;
1010         case SUDO_PATH_GROUP_WRITABLE:
1011             log_error(0, _("%s is owned by gid %u, should be %u"),
1012                 sudoers, (unsigned int) sb.st_gid, (unsigned int) sudoers_gid);
1013             break;
1014         default:
1015             /* NOTREACHED */
1016             break;
1017     }
1018
1019     restore_perms();            /* change back to root */
1020
1021     debug_return_ptr(fp);
1022 }
1023
1024 #ifdef HAVE_LOGIN_CAP_H
1025 static void
1026 set_loginclass(struct passwd *pw)
1027 {
1028     const int errflags = NO_MAIL|MSG_ONLY;
1029     login_cap_t *lc;
1030     debug_decl(set_loginclass, SUDO_DEBUG_PLUGIN)
1031
1032     if (!def_use_loginclass)
1033         debug_return;
1034
1035     if (login_class && strcmp(login_class, "-") != 0) {
1036         if (user_uid != 0 &&
1037             strcmp(runas_user ? runas_user : def_runas_default, "root") != 0)
1038             errorx(1, _("only root can use `-c %s'"), login_class);
1039     } else {
1040         login_class = pw->pw_class;
1041         if (!login_class || !*login_class)
1042             login_class =
1043                 (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
1044     }
1045
1046     /* Make sure specified login class is valid. */
1047     lc = login_getclass(login_class);
1048     if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
1049         /*
1050          * Don't make it a fatal error if the user didn't specify the login
1051          * class themselves.  We do this because if login.conf gets
1052          * corrupted we want the admin to be able to use sudo to fix it.
1053          */
1054         if (login_class)
1055             log_fatal(errflags, _("unknown login class: %s"), login_class);
1056         else
1057             log_error(errflags, _("unknown login class: %s"), login_class);
1058         def_use_loginclass = false;
1059     }
1060     login_close(lc);
1061     debug_return;
1062 }
1063 #else
1064 static void
1065 set_loginclass(struct passwd *pw)
1066 {
1067 }
1068 #endif /* HAVE_LOGIN_CAP_H */
1069
1070 /*
1071  * Look up the fully qualified domain name and set user_host and user_shost.
1072  */
1073 void
1074 set_fqdn(void)
1075 {
1076     struct addrinfo *res0, hint;
1077     char *p;
1078     debug_decl(set_fqdn, SUDO_DEBUG_PLUGIN)
1079
1080     zero_bytes(&hint, sizeof(hint));
1081     hint.ai_family = PF_UNSPEC;
1082     hint.ai_flags = AI_CANONNAME;
1083     if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) {
1084         log_error(MSG_ONLY, _("unable to resolve host %s"), user_host);
1085     } else {
1086         if (user_shost != user_host)
1087             efree(user_shost);
1088         efree(user_host);
1089         user_host = estrdup(res0->ai_canonname);
1090         freeaddrinfo(res0);
1091     }
1092     if ((p = strchr(user_host, '.')) != NULL)
1093         user_shost = estrndup(user_host, (size_t)(p - user_host));
1094     else
1095         user_shost = user_host;
1096     debug_return;
1097 }
1098
1099 /*
1100  * Get passwd entry for the user we are going to run commands as
1101  * and store it in runas_pw.  By default, commands run as "root".
1102  */
1103 static void
1104 set_runaspw(const char *user)
1105 {
1106     debug_decl(set_runaspw, SUDO_DEBUG_PLUGIN)
1107
1108     if (runas_pw != NULL)
1109         pw_delref(runas_pw);
1110     if (*user == '#') {
1111         if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
1112             runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
1113     } else {
1114         if ((runas_pw = sudo_getpwnam(user)) == NULL)
1115             log_fatal(NO_MAIL|MSG_ONLY, _("unknown user: %s"), user);
1116     }
1117     debug_return;
1118 }
1119
1120 /*
1121  * Get group entry for the group we are going to run commands as
1122  * and store it in runas_gr.
1123  */
1124 static void
1125 set_runasgr(const char *group)
1126 {
1127     debug_decl(set_runasgr, SUDO_DEBUG_PLUGIN)
1128
1129     if (runas_gr != NULL)
1130         gr_delref(runas_gr);
1131     if (*group == '#') {
1132         if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
1133             runas_gr = sudo_fakegrnam(group);
1134     } else {
1135         if ((runas_gr = sudo_getgrnam(group)) == NULL)
1136             log_fatal(NO_MAIL|MSG_ONLY, _("unknown group: %s"), group);
1137     }
1138     debug_return;
1139 }
1140
1141 /*
1142  * Callback for runas_default sudoers setting.
1143  */
1144 static int
1145 cb_runas_default(const char *user)
1146 {
1147     /* Only reset runaspw if user didn't specify one. */
1148     if (!runas_user && !runas_group)
1149         set_runaspw(user);
1150     return true;
1151 }
1152
1153 /*
1154  * Cleanup hook for error()/errorx()
1155  */
1156 void
1157 plugin_cleanup(int gotsignal)
1158 {
1159     struct sudo_nss *nss;
1160
1161     if (!gotsignal) {
1162         debug_decl(plugin_cleanup, SUDO_DEBUG_PLUGIN)
1163         if (snl != NULL) {
1164             tq_foreach_fwd(snl, nss)
1165                 nss->close(nss);
1166         }
1167         if (def_group_plugin)
1168             group_plugin_unload();
1169         sudo_endpwent();
1170         sudo_endgrent();
1171         debug_return;
1172     }
1173 }
1174
1175 static int
1176 sudoers_policy_version(int verbose)
1177 {
1178     debug_decl(sudoers_policy_version, SUDO_DEBUG_PLUGIN)
1179
1180     if (sigsetjmp(error_jmp, 1)) {
1181         /* error recovery via error(), errorx() or log_fatal() */
1182         debug_return_bool(-1);
1183     }
1184
1185     sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers policy plugin version %s\n"),
1186         PACKAGE_VERSION);
1187     sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers file grammar version %d\n"),
1188         SUDOERS_GRAMMAR_VERSION);
1189
1190     if (verbose) {
1191         sudo_printf(SUDO_CONV_INFO_MSG, _("\nSudoers path: %s\n"), sudoers_file);
1192 #ifdef HAVE_LDAP
1193 # ifdef _PATH_NSSWITCH_CONF
1194         sudo_printf(SUDO_CONV_INFO_MSG, _("nsswitch path: %s\n"), _PATH_NSSWITCH_CONF);
1195 # endif
1196         sudo_printf(SUDO_CONV_INFO_MSG, _("ldap.conf path: %s\n"), _PATH_LDAP_CONF);
1197         sudo_printf(SUDO_CONV_INFO_MSG, _("ldap.secret path: %s\n"), _PATH_LDAP_SECRET);
1198 #endif
1199         dump_auth_methods();
1200         dump_defaults();
1201         sudo_printf(SUDO_CONV_INFO_MSG, "\n");
1202         if (interfaces_string != NULL) {
1203             dump_interfaces(interfaces_string);
1204             sudo_printf(SUDO_CONV_INFO_MSG, "\n");
1205         }
1206     }
1207     debug_return_bool(true);
1208 }
1209
1210 static int
1211 deserialize_info(char * const args[], char * const settings[], char * const user_info[])
1212 {
1213     char * const *cur;
1214     const char *p, *groups = NULL;
1215     const char *debug_flags = NULL;
1216     int flags = 0;
1217     debug_decl(deserialize_info, SUDO_DEBUG_PLUGIN)
1218
1219 #define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0)
1220
1221     /* Parse sudo.conf plugin args. */
1222     if (args != NULL) {
1223         for (cur = args; *cur != NULL; cur++) {
1224             if (MATCHES(*cur, "sudoers_file=")) {
1225                 sudoers_file = *cur + sizeof("sudoers_file=") - 1;
1226                 continue;
1227             }
1228             if (MATCHES(*cur, "sudoers_uid=")) {
1229                 sudoers_uid = (uid_t) atoi(*cur + sizeof("sudoers_uid=") - 1);
1230                 continue;
1231             }
1232             if (MATCHES(*cur, "sudoers_gid=")) {
1233                 sudoers_gid = (gid_t) atoi(*cur + sizeof("sudoers_gid=") - 1);
1234                 continue;
1235             }
1236             if (MATCHES(*cur, "sudoers_mode=")) {
1237                 sudoers_mode = (mode_t) strtol(*cur + sizeof("sudoers_mode=") - 1,
1238                     NULL, 8);
1239                 continue;
1240             }
1241         }
1242     }
1243
1244     /* Parse command line settings. */
1245     user_closefrom = -1;
1246     for (cur = settings; *cur != NULL; cur++) {
1247         if (MATCHES(*cur, "closefrom=")) {
1248             user_closefrom = atoi(*cur + sizeof("closefrom=") - 1);
1249             continue;
1250         }
1251         if (MATCHES(*cur, "debug_flags=")) {
1252             debug_flags = *cur + sizeof("debug_flags=") - 1;
1253             continue;
1254         }
1255         if (MATCHES(*cur, "runas_user=")) {
1256             runas_user = *cur + sizeof("runas_user=") - 1;
1257             continue;
1258         }
1259         if (MATCHES(*cur, "runas_group=")) {
1260             runas_group = *cur + sizeof("runas_group=") - 1;
1261             continue;
1262         }
1263         if (MATCHES(*cur, "prompt=")) {
1264             user_prompt = *cur + sizeof("prompt=") - 1;
1265             def_passprompt_override = true;
1266             continue;
1267         }
1268         if (MATCHES(*cur, "set_home=")) {
1269             if (atobool(*cur + sizeof("set_home=") - 1) == true)
1270                 SET(flags, MODE_RESET_HOME);
1271             continue;
1272         }
1273         if (MATCHES(*cur, "preserve_environment=")) {
1274             if (atobool(*cur + sizeof("preserve_environment=") - 1) == true)
1275                 SET(flags, MODE_PRESERVE_ENV);
1276             continue;
1277         }
1278         if (MATCHES(*cur, "run_shell=")) {
1279             if (atobool(*cur + sizeof("run_shell=") - 1) == true)
1280                 SET(flags, MODE_SHELL);
1281             continue;
1282         }
1283         if (MATCHES(*cur, "login_shell=")) {
1284             if (atobool(*cur + sizeof("login_shell=") - 1) == true) {
1285                 SET(flags, MODE_LOGIN_SHELL);
1286                 def_env_reset = true;
1287             }
1288             continue;
1289         }
1290         if (MATCHES(*cur, "implied_shell=")) {
1291             if (atobool(*cur + sizeof("implied_shell=") - 1) == true)
1292                 SET(flags, MODE_IMPLIED_SHELL);
1293             continue;
1294         }
1295         if (MATCHES(*cur, "preserve_groups=")) {
1296             if (atobool(*cur + sizeof("preserve_groups=") - 1) == true)
1297                 SET(flags, MODE_PRESERVE_GROUPS);
1298             continue;
1299         }
1300         if (MATCHES(*cur, "ignore_ticket=")) {
1301             if (atobool(*cur + sizeof("ignore_ticket=") - 1) == true)
1302                 SET(flags, MODE_IGNORE_TICKET);
1303             continue;
1304         }
1305         if (MATCHES(*cur, "noninteractive=")) {
1306             if (atobool(*cur + sizeof("noninteractive=") - 1) == true)
1307                 SET(flags, MODE_NONINTERACTIVE);
1308             continue;
1309         }
1310         if (MATCHES(*cur, "sudoedit=")) {
1311             if (atobool(*cur + sizeof("sudoedit=") - 1) == true)
1312                 SET(flags, MODE_EDIT);
1313             continue;
1314         }
1315         if (MATCHES(*cur, "login_class=")) {
1316             login_class = *cur + sizeof("login_class=") - 1;
1317             def_use_loginclass = true;
1318             continue;
1319         }
1320 #ifdef HAVE_SELINUX
1321         if (MATCHES(*cur, "selinux_role=")) {
1322             user_role = *cur + sizeof("selinux_role=") - 1;
1323             continue;
1324         }
1325         if (MATCHES(*cur, "selinux_type=")) {
1326             user_type = *cur + sizeof("selinux_type=") - 1;
1327             continue;
1328         }
1329 #endif /* HAVE_SELINUX */
1330 #ifdef HAVE_BSD_AUTH_H
1331         if (MATCHES(*cur, "bsdauth_type=")) {
1332             login_style = *cur + sizeof("bsdauth_type=") - 1;
1333             continue;
1334         }
1335 #endif /* HAVE_BSD_AUTH_H */
1336 #if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME)
1337         if (MATCHES(*cur, "progname=")) {
1338             setprogname(*cur + sizeof("progname=") - 1);
1339             continue;
1340         }
1341 #endif
1342         if (MATCHES(*cur, "network_addrs=")) {
1343             interfaces_string = *cur + sizeof("network_addrs=") - 1;
1344             set_interfaces(interfaces_string);
1345             continue;
1346         }
1347     }
1348
1349     for (cur = user_info; *cur != NULL; cur++) {
1350         if (MATCHES(*cur, "user=")) {
1351             user_name = estrdup(*cur + sizeof("user=") - 1);
1352             continue;
1353         }
1354         if (MATCHES(*cur, "uid=")) {
1355             user_uid = (uid_t) atoi(*cur + sizeof("uid=") - 1);
1356             continue;
1357         }
1358         if (MATCHES(*cur, "gid=")) {
1359             p = *cur + sizeof("gid=") - 1;
1360             user_gid = (gid_t) atoi(p);
1361             continue;
1362         }
1363         if (MATCHES(*cur, "groups=")) {
1364             groups = *cur + sizeof("groups=") - 1;
1365             continue;
1366         }
1367         if (MATCHES(*cur, "cwd=")) {
1368             user_cwd = estrdup(*cur + sizeof("cwd=") - 1);
1369             continue;
1370         }
1371         if (MATCHES(*cur, "tty=")) {
1372             user_tty = user_ttypath = estrdup(*cur + sizeof("tty=") - 1);
1373             if (strncmp(user_tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
1374                 user_tty += sizeof(_PATH_DEV) - 1;
1375             continue;
1376         }
1377         if (MATCHES(*cur, "host=")) {
1378             user_host = user_shost = estrdup(*cur + sizeof("host=") - 1);
1379             if ((p = strchr(user_host, '.')))
1380                 user_shost = estrndup(user_host, (size_t)(p - user_host));
1381             continue;
1382         }
1383         if (MATCHES(*cur, "lines=")) {
1384             sudo_user.lines = atoi(*cur + sizeof("lines=") - 1);
1385             continue;
1386         }
1387         if (MATCHES(*cur, "cols=")) {
1388             sudo_user.cols = atoi(*cur + sizeof("cols=") - 1);
1389             continue;
1390         }
1391     }
1392     if (user_cwd == NULL)
1393         user_cwd = "unknown";
1394     if (user_tty == NULL)
1395         user_tty = "unknown"; /* user_ttypath remains NULL */
1396
1397     if (groups != NULL && groups[0] != '\0') {
1398         const char *cp;
1399         GETGROUPS_T *gids;
1400         int ngids;
1401
1402         /* Count number of groups, including passwd gid. */
1403         ngids = 2;
1404         for (cp = groups; *cp != '\0'; cp++) {
1405             if (*cp == ',')
1406                 ngids++;
1407         }
1408
1409         /* The first gid in the list is the passwd group gid. */
1410         gids = emalloc2(ngids, sizeof(GETGROUPS_T));
1411         gids[0] = user_gid;
1412         ngids = 1;
1413         cp = groups;
1414         for (;;) {
1415             gids[ngids] = atoi(cp);
1416             if (gids[0] != gids[ngids])
1417                 ngids++;
1418             cp = strchr(cp, ',');
1419             if (cp == NULL)
1420                 break;
1421             cp++; /* skip over comma */
1422         }
1423         set_group_list(user_name, gids, ngids);
1424         efree(gids);
1425     }
1426
1427     /* Setup debugging if indicated. */
1428     if (debug_flags != NULL) {
1429         sudo_debug_init(NULL, debug_flags);
1430         for (cur = settings; *cur != NULL; cur++)
1431             sudo_debug_printf(SUDO_DEBUG_INFO, "settings: %s", *cur);
1432         for (cur = user_info; *cur != NULL; cur++)
1433             sudo_debug_printf(SUDO_DEBUG_INFO, "user_info: %s", *cur);
1434     }
1435
1436 #undef MATCHES
1437     debug_return_int(flags);
1438 }
1439
1440 static char *
1441 resolve_editor(char *editor, int nfiles, char **files, char ***argv_out)
1442 {
1443     char *cp, **nargv, *editor_path = NULL;
1444     int ac, i, nargc;
1445     bool wasblank;
1446     debug_decl(resolve_editor, SUDO_DEBUG_PLUGIN)
1447
1448     editor = estrdup(editor); /* becomes part of argv_out */
1449
1450     /*
1451      * Split editor into an argument vector; editor is reused (do not free).
1452      * The EDITOR and VISUAL environment variables may contain command
1453      * line args so look for those and alloc space for them too.
1454      */
1455     nargc = 1;
1456     for (wasblank = false, cp = editor; *cp != '\0'; cp++) {
1457         if (isblank((unsigned char) *cp))
1458             wasblank = true;
1459         else if (wasblank) {
1460             wasblank = false;
1461             nargc++;
1462         }
1463     }
1464     /* If we can't find the editor in the user's PATH, give up. */
1465     cp = strtok(editor, " \t");
1466     if (cp == NULL ||
1467         find_path(cp, &editor_path, NULL, getenv("PATH"), 0) != FOUND) {
1468         efree(editor);
1469         debug_return_str(NULL);
1470     }
1471     nargv = (char **) emalloc2(nargc + 1 + nfiles + 1, sizeof(char *));
1472     for (ac = 0; cp != NULL && ac < nargc; ac++) {
1473         nargv[ac] = cp;
1474         cp = strtok(NULL, " \t");
1475     }
1476     nargv[ac++] = "--";
1477     for (i = 0; i < nfiles; )
1478         nargv[ac++] = files[i++];
1479     nargv[ac] = NULL;
1480
1481     *argv_out = nargv;
1482     debug_return_str(editor_path);
1483 }
1484
1485 /*
1486  * Determine which editor to use.  We don't need to worry about restricting
1487  * this to a "safe" editor since it runs with the uid of the invoking user,
1488  * not the runas (privileged) user.
1489  */
1490 static char *
1491 find_editor(int nfiles, char **files, char ***argv_out)
1492 {
1493     char *cp, *editor, *editor_path = NULL, **ev, *ev0[4];
1494     debug_decl(find_editor, SUDO_DEBUG_PLUGIN)
1495
1496     /*
1497      * If any of SUDO_EDITOR, VISUAL or EDITOR are set, choose the first one.
1498      */
1499     ev0[0] = "SUDO_EDITOR";
1500     ev0[1] = "VISUAL";
1501     ev0[2] = "EDITOR";
1502     ev0[3] = NULL;
1503     for (ev = ev0; *ev != NULL; ev++) {
1504         if ((editor = getenv(*ev)) != NULL && *editor != '\0') {
1505             editor_path = resolve_editor(editor, nfiles, files, argv_out);
1506             if (editor_path != NULL)
1507                 break;
1508         }
1509     }
1510     if (editor_path == NULL) {
1511         /* def_editor could be a path, split it up */
1512         editor = estrdup(def_editor);
1513         cp = strtok(editor, ":");
1514         while (cp != NULL && editor_path == NULL) {
1515             editor_path = resolve_editor(cp, nfiles, files, argv_out);
1516             cp = strtok(NULL, ":");
1517         }
1518         if (editor_path)
1519             efree(editor);
1520     }
1521     if (!editor_path) {
1522         audit_failure(NewArgv, _("%s: command not found"), editor);
1523         warningx(_("%s: command not found"), editor);
1524     }
1525     debug_return_str(editor_path);
1526 }
1527
1528 #ifdef USE_ADMIN_FLAG
1529 static void
1530 create_admin_success_flag(void)
1531 {
1532     struct stat statbuf;
1533     char flagfile[PATH_MAX];
1534     int fd, n;
1535     debug_decl(create_admin_success_flag, SUDO_DEBUG_PLUGIN)
1536
1537     /* Check whether the user is in the admin group. */
1538     if (!user_in_group(sudo_user.pw, "admin"))
1539         debug_return;
1540
1541     /* Build path to flag file. */
1542     n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful",
1543         user_dir);
1544     if (n <= 0 || n >= sizeof(flagfile))
1545         debug_return;
1546
1547     /* Create admin flag file if it doesn't already exist. */
1548     set_perms(PERM_USER);
1549     if (stat(flagfile, &statbuf) != 0) {
1550         fd = open(flagfile, O_CREAT|O_WRONLY|O_EXCL, 0644);
1551         close(fd);
1552     }
1553     restore_perms();
1554     debug_return;
1555 }
1556 #else /* !USE_ADMIN_FLAG */
1557 static void
1558 create_admin_success_flag(void)
1559 {
1560     /* STUB */
1561 }
1562 #endif /* USE_ADMIN_FLAG */
1563
1564 static void
1565 sudoers_policy_register_hooks(int version, int (*register_hook)(struct sudo_hook *hook))
1566 {
1567     struct sudo_hook hook;
1568
1569     memset(&hook, 0, sizeof(hook));
1570     hook.hook_version = SUDO_HOOK_VERSION;
1571
1572     hook.hook_type = SUDO_HOOK_SETENV;
1573     hook.hook_fn = sudoers_hook_setenv;
1574     register_hook(&hook);
1575
1576     hook.hook_type = SUDO_HOOK_UNSETENV;
1577     hook.hook_fn = sudoers_hook_unsetenv;
1578     register_hook(&hook);
1579
1580     hook.hook_type = SUDO_HOOK_GETENV;
1581     hook.hook_fn = sudoers_hook_getenv;
1582     register_hook(&hook);
1583
1584     hook.hook_type = SUDO_HOOK_PUTENV;
1585     hook.hook_fn = sudoers_hook_putenv;
1586     register_hook(&hook);
1587 }
1588
1589 struct policy_plugin sudoers_policy = {
1590     SUDO_POLICY_PLUGIN,
1591     SUDO_API_VERSION,
1592     sudoers_policy_open,
1593     sudoers_policy_close,
1594     sudoers_policy_version,
1595     sudoers_policy_check,
1596     sudoers_policy_list,
1597     sudoers_policy_validate,
1598     sudoers_policy_invalidate,
1599     sudoers_policy_init_session,
1600     sudoers_policy_register_hooks
1601 };