Imported Upstream version 1.7.4p6
[debian/sudo] / sudo.c
1 /*
2  * Copyright (c) 1993-1996, 1998-2010 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/wait.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #ifdef HAVE_SETRLIMIT
38 # include <sys/time.h>
39 # include <sys/resource.h>
40 #endif
41 #include <stdio.h>
42 #ifdef STDC_HEADERS
43 # include <stdlib.h>
44 # include <stddef.h>
45 #else
46 # ifdef HAVE_STDLIB_H
47 #  include <stdlib.h>
48 # endif
49 #endif /* STDC_HEADERS */
50 #ifdef HAVE_STRING_H
51 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
52 #  include <memory.h>
53 # endif
54 # include <string.h>
55 #endif /* HAVE_STRING_H */
56 #ifdef HAVE_STRINGS_H
57 # include <strings.h>
58 #endif /* HAVE_STRINGS_H */
59 #ifdef HAVE_UNISTD_H
60 # include <unistd.h>
61 #endif /* HAVE_UNISTD_H */
62 #include <pwd.h>
63 #include <ctype.h>
64 #include <errno.h>
65 #include <fcntl.h>
66 #include <signal.h>
67 #include <grp.h>
68 #if TIME_WITH_SYS_TIME
69 # include <time.h>
70 #endif
71 #ifdef HAVE_SETLOCALE
72 # include <locale.h>
73 #endif
74 #include <netinet/in.h>
75 #include <netdb.h>
76 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
77 # ifdef __hpux
78 #  undef MAXINT
79 #  include <hpsecurity.h>
80 # else
81 #  include <sys/security.h>
82 # endif /* __hpux */
83 # include <prot.h>
84 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
85 #ifdef HAVE_LOGIN_CAP_H
86 # include <login_cap.h>
87 # ifndef LOGIN_DEFROOTCLASS
88 #  define LOGIN_DEFROOTCLASS    "daemon"
89 # endif
90 #endif
91 #ifdef HAVE_MBR_CHECK_MEMBERSHIP
92 # include <membership.h>
93 #endif
94
95 #include "sudo.h"
96 #include "lbuf.h"
97 #include "interfaces.h"
98 #include <sudo_usage.h>
99
100 #ifdef USING_NONUNIX_GROUPS
101 # include "nonunix.h"
102 #endif
103
104 #if defined(HAVE_PAM) && !defined(NO_PAM_SESSION)
105 # define CMND_WAIT      TRUE
106 #else
107 # define CMND_WAIT      FALSE
108 #endif
109
110 /*
111  * Prototypes
112  */
113 static void init_vars                   __P((char **));
114 static int set_cmnd                     __P((int));
115 static void initial_setup               __P((void));
116 static void set_loginclass              __P((struct passwd *));
117 static void set_runasgr                 __P((char *));
118 static void set_runaspw                 __P((char *));
119 static void show_version                __P((void));
120 static struct passwd *get_authpw        __P((void));
121 static void create_admin_success_flag   __P((void));
122 extern int sudo_edit                    __P((int, char **, char **));
123 int run_command __P((const char *path, char *argv[], char *envp[], uid_t uid, int dowait)); /* XXX should be in sudo.h */
124
125 /*
126  * Globals
127  */
128 int Argc, NewArgc;
129 char **Argv, **NewArgv;
130 char *prev_user;
131 int user_closefrom = -1;
132 struct sudo_user sudo_user;
133 struct passwd *auth_pw, *list_pw;
134 struct interface *interfaces;
135 int num_interfaces;
136 int tgetpass_flags;
137 int long_list;
138 uid_t timestamp_uid;
139 extern int errorlineno;
140 extern int parse_error;
141 extern char *errorfile;
142 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
143 static struct rlimit corelimit;
144 #endif /* RLIMIT_CORE && !SUDO_DEVEL */
145 #if defined(__linux__)
146 static struct rlimit nproclimit;
147 #endif
148 #ifdef HAVE_LOGIN_CAP_H
149 login_cap_t *lc;
150 #endif /* HAVE_LOGIN_CAP_H */
151 sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp;
152 char *runas_user;
153 char *runas_group;
154 static struct sudo_nss_list *snl;
155 int sudo_mode;
156
157 /* For getopt(3) */
158 extern char *optarg;
159 extern int optind;
160
161 int
162 main(argc, argv, envp)
163     int argc;
164     char *argv[];
165     char *envp[];
166 {
167     int sources = 0, validated;
168     int fd, cmnd_status, pwflag, rc = 0;
169     sigaction_t sa;
170     struct sudo_nss *nss;
171 #if defined(SUDO_DEVEL) && defined(__OpenBSD__)
172     extern char *malloc_options;
173     malloc_options = "AFGJPR";
174 #endif
175
176 #ifdef HAVE_SETLOCALE
177     setlocale(LC_ALL, "");
178 #endif
179
180     Argv = argv;
181     if ((Argc = argc) < 1)
182         usage(1);
183
184     /* Must be done as the first thing... */
185 #if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
186     (void) set_auth_parameters(Argc, Argv);
187 # ifdef HAVE_INITPRIVS
188     initprivs();
189 # endif
190 #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
191
192     if (geteuid() != 0)
193         errorx(1, "must be setuid root");
194
195     /*
196      * Signal setup:
197      *  Ignore keyboard-generated signals so the user cannot interrupt
198      *  us at some point and avoid the logging.
199      *  Install handler to wait for children when they exit.
200      */
201     zero_bytes(&sa, sizeof(sa));
202     sigemptyset(&sa.sa_mask);
203     sa.sa_flags = SA_RESTART;
204     sa.sa_handler = SIG_IGN;
205     (void) sigaction(SIGINT, &sa, &saved_sa_int);
206     (void) sigaction(SIGQUIT, &sa, &saved_sa_quit);
207     (void) sigaction(SIGTSTP, &sa, &saved_sa_tstp);
208
209     /* Initialize environment functions (including replacements). */
210     env_init(FALSE);
211
212     /*
213      * Turn off core dumps and make sure fds 0-2 are open.
214      */
215     initial_setup();
216     sudo_setpwent();
217     sudo_setgrent();
218
219     /* Parse our arguments. */
220     sudo_mode = parse_args(Argc, Argv);
221
222     /* Setup defaults data structures. */
223     init_defaults();
224
225     /* Load the list of local ip addresses and netmasks.  */
226     load_interfaces();
227
228     pwflag = 0;
229     if (ISSET(sudo_mode, MODE_SHELL))
230         user_cmnd = "shell";
231     else if (ISSET(sudo_mode, MODE_EDIT))
232         user_cmnd = "sudoedit";
233     else {
234         switch (sudo_mode) {
235             case MODE_VERSION:
236                 show_version();
237                 break;
238             case MODE_HELP:
239                 usage(0);
240                 break;
241             case MODE_VALIDATE:
242             case MODE_VALIDATE|MODE_INVALIDATE:
243                 user_cmnd = "validate";
244                 pwflag = I_VERIFYPW;
245                 break;
246             case MODE_KILL:
247             case MODE_INVALIDATE:
248                 user_cmnd = "kill";
249                 pwflag = -1;
250                 break;
251             case MODE_LISTDEFS:
252                 list_options();
253                 exit(0);
254                 break;
255             case MODE_LIST:
256             case MODE_LIST|MODE_INVALIDATE:
257                 user_cmnd = "list";
258                 pwflag = I_LISTPW;
259                 break;
260             case MODE_CHECK:
261             case MODE_CHECK|MODE_INVALIDATE:
262                 pwflag = I_LISTPW;
263                 break;
264         }
265     }
266
267     /* Must have a command to run... */
268     if (user_cmnd == NULL && NewArgc == 0)
269         usage(1);
270
271     init_vars(envp);                    /* XXX - move this later? */
272
273 #ifdef USING_NONUNIX_GROUPS
274     sudo_nonunix_groupcheck_init();     /* initialise nonunix groups impl */
275 #endif /* USING_NONUNIX_GROUPS */
276
277     /* Parse nsswitch.conf for sudoers order. */
278     snl = sudo_read_nss();
279
280     /* Open and parse sudoers, set global defaults */
281     tq_foreach_fwd(snl, nss) {
282         if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
283             sources++;
284             if (nss->setdefs(nss) != 0)
285                 log_error(NO_STDERR|NO_EXIT, "problem with defaults entries");
286         }
287     }
288     if (sources == 0)
289         log_error(0, "no valid sudoers sources found, quitting");
290
291     /* XXX - collect post-sudoers parse settings into a function */
292
293     /*
294      * Set runas passwd/group entries based on command line or sudoers.
295      * Note that if runas_group was specified without runas_user we
296      * defer setting runas_pw so the match routines know to ignore it.
297      */
298     if (runas_group != NULL) {
299         set_runasgr(runas_group);
300         if (runas_user != NULL)
301             set_runaspw(runas_user);
302     } else
303         set_runaspw(runas_user ? runas_user : def_runas_default);
304
305     if (!update_defaults(SETDEF_RUNAS))
306         log_error(NO_STDERR|NO_EXIT, "problem with defaults entries");
307
308     if (def_fqdn)
309         set_fqdn();     /* deferred until after sudoers is parsed */
310
311     /* Set login class if applicable. */
312     set_loginclass(sudo_user.pw);
313
314     /* Update initial shell now that runas is set. */
315     if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
316         NewArgv[0] = runas_pw->pw_shell;
317
318     /* This goes after sudoers is parsed since it may have timestamp options. */
319     if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) {
320         remove_timestamp((sudo_mode == MODE_KILL));
321         cleanup(0);
322         exit(0);
323     }
324
325     /* Is root even allowed to run sudo? */
326     if (user_uid == 0 && !def_root_sudo) {
327         (void) fprintf(stderr,
328             "Sorry, %s has been configured to not allow root to run it.\n",
329             getprogname());
330         exit(1);
331     }
332
333     /* Check for -C overriding def_closefrom. */
334     if (user_closefrom >= 0 && user_closefrom != def_closefrom) {
335         if (!def_closefrom_override)
336             errorx(1, "you are not permitted to use the -C option");
337         else
338             def_closefrom = user_closefrom;
339     }
340
341     cmnd_status = set_cmnd(sudo_mode);
342
343 #ifdef HAVE_SETLOCALE
344     if (!setlocale(LC_ALL, def_sudoers_locale)) {
345         warningx("unable to set locale to \"%s\", using \"C\"",
346             def_sudoers_locale);
347         setlocale(LC_ALL, "C");
348     }
349 #endif
350
351     validated = FLAG_NO_USER | FLAG_NO_HOST;
352     tq_foreach_fwd(snl, nss) {
353         validated = nss->lookup(nss, validated, pwflag);
354
355         if (ISSET(validated, VALIDATE_OK)) {
356             /* Handle "= auth" in netsvc.conf */
357             if (nss->ret_if_found)
358                 break;
359         } else {
360             /* Handle [NOTFOUND=return] */
361             if (nss->ret_if_notfound)
362                 break;
363         }
364     }
365
366     if (safe_cmnd == NULL)
367         safe_cmnd = estrdup(user_cmnd);
368
369 #ifdef HAVE_SETLOCALE
370     setlocale(LC_ALL, "");
371 #endif
372
373     /* If only a group was specified, set runas_pw based on invoking user. */
374     if (runas_pw == NULL)
375         set_runaspw(user_name);
376
377     /*
378      * Look up the timestamp dir owner if one is specified.
379      */
380     if (def_timestampowner) {
381         struct passwd *pw;
382
383         if (*def_timestampowner == '#')
384             pw = sudo_getpwuid(atoi(def_timestampowner + 1));
385         else
386             pw = sudo_getpwnam(def_timestampowner);
387         if (!pw)
388             log_error(0, "timestamp owner (%s): No such user",
389                 def_timestampowner);
390         timestamp_uid = pw->pw_uid;
391     }
392
393     /* If given the -P option, set the "preserve_groups" flag. */
394     if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS))
395         def_preserve_groups = TRUE;
396
397     /* If no command line args and "set_home" is not set, error out. */
398     if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs)
399         usage(1);
400
401     /* Bail if a tty is required and we don't have one.  */
402     if (def_requiretty) {
403         if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) {
404             audit_failure(NewArgv, "no tty");
405             log_error(NO_MAIL, "sorry, you must have a tty to run sudo");
406         } else
407             (void) close(fd);
408     }
409
410     /* Use askpass value from sudoers unless user specified their own. */
411     if (def_askpass && !user_askpass)
412         user_askpass = def_askpass;
413
414     /*
415      * We don't reset the environment for sudoedit or if the user
416      * specified the -E command line flag and they have setenv privs.
417      */
418     if (ISSET(sudo_mode, MODE_EDIT) ||
419         (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv))
420         def_env_reset = FALSE;
421
422     /* Build a new environment that avoids any nasty bits. */
423     rebuild_env(def_noexec);
424
425     /* Fill in passwd struct based on user we are authenticating as.  */
426     auth_pw = get_authpw();
427
428     /* Require a password if sudoers says so.  */
429     if (def_authenticate)
430         check_user(validated, sudo_mode);
431
432     /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */
433     /* XXX - causes confusion when root is not listed in sudoers */
434     if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) {
435         if (user_uid == 0 && strcmp(prev_user, "root") != 0) {
436             struct passwd *pw;
437
438             if ((pw = sudo_getpwnam(prev_user)) != NULL) {
439                     sudo_user.pw = pw;
440 #ifdef HAVE_MBR_CHECK_MEMBERSHIP
441                     mbr_uid_to_uuid(user_uid, user_uuid);
442 #endif
443             }
444         }
445     }
446
447     if (ISSET(validated, VALIDATE_OK)) {
448         /* Create Ubuntu-style dot file to indicate sudo was successful. */
449         create_admin_success_flag();
450
451         /* Finally tell the user if the command did not exist. */
452         if (cmnd_status == NOT_FOUND_DOT) {
453             audit_failure(NewArgv, "command in current directory");
454             errorx(1, "ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd);
455         } else if (cmnd_status == NOT_FOUND) {
456             audit_failure(NewArgv, "%s: command not found", user_cmnd);
457             errorx(1, "%s: command not found", user_cmnd);
458         }
459
460         /* If user specified env vars make sure sudoers allows it. */
461         if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) {
462             if (ISSET(sudo_mode, MODE_PRESERVE_ENV))
463                 log_error(NO_MAIL,
464                     "sorry, you are not allowed to preserve the environment");
465             else
466                 validate_env_vars(sudo_user.env_vars);
467         }
468
469 #ifdef _PATH_SUDO_IO_LOGDIR
470         /* Get next session ID so we can log it. */
471         if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && (def_log_input || def_log_output))
472             io_nextid();
473 #endif
474         log_allowed(validated);
475         if (ISSET(sudo_mode, MODE_CHECK))
476             rc = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
477         else if (ISSET(sudo_mode, MODE_LIST))
478             display_privs(snl, list_pw ? list_pw : sudo_user.pw);
479
480         /* Cleanup sudoers sources */
481         tq_foreach_fwd(snl, nss)
482             nss->close(nss);
483
484 #ifdef USING_NONUNIX_GROUPS
485         /* Finished with the groupcheck code */
486         sudo_nonunix_groupcheck_cleanup();
487 #endif
488
489         /* Deferred exit due to sudo_ldap_close() */
490         if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST)))
491             exit(rc);
492
493         /* Must audit before uid change. */
494         audit_success(NewArgv);
495
496         if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
497             char *p;
498
499             /* Convert /bin/sh -> -sh so shell knows it is a login shell */
500             if ((p = strrchr(NewArgv[0], '/')) == NULL)
501                 p = NewArgv[0];
502             *p = '-';
503             NewArgv[0] = p;
504
505 #if defined(__linux__) || defined(_AIX)
506             /* Insert system-wide environment variables. */
507             read_env_file(_PATH_ENVIRONMENT, TRUE);
508 #endif
509         }
510
511         if (ISSET(sudo_mode, MODE_RUN)) {
512             /* Insert system-wide environment variables. */
513             if (def_env_file)
514                 read_env_file(def_env_file, FALSE);
515
516             /* Insert user-specified environment variables. */
517             insert_env_vars(sudo_user.env_vars);
518         }
519
520         /* Restore signal handlers before we exec. */
521         (void) sigaction(SIGINT, &saved_sa_int, NULL);
522         (void) sigaction(SIGQUIT, &saved_sa_quit, NULL);
523         (void) sigaction(SIGTSTP, &saved_sa_tstp, NULL);
524
525         if (ISSET(sudo_mode, MODE_EDIT)) {
526             exit(sudo_edit(NewArgc, NewArgv, envp));
527         } else {
528             exit(run_command(safe_cmnd, NewArgv, env_get(), runas_pw->pw_uid,
529                 CMND_WAIT));
530         }
531     } else if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) {
532         audit_failure(NewArgv, "No user or host");
533         log_denial(validated, 1);
534         exit(1);
535     } else {
536         if (def_path_info) {
537             /*
538              * We'd like to not leak path info at all here, but that can
539              * *really* confuse the users.  To really close the leak we'd
540              * have to say "not allowed to run foo" even when the problem
541              * is just "no foo in path" since the user can trivially set
542              * their path to just contain a single dir.
543              */
544             log_denial(validated,
545                 !(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND));
546             if (cmnd_status == NOT_FOUND)
547                 warningx("%s: command not found", user_cmnd);
548             else if (cmnd_status == NOT_FOUND_DOT)
549                 warningx("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd);
550         } else {
551             /* Just tell the user they are not allowed to run foo. */
552             log_denial(validated, 1);
553         }
554         audit_failure(NewArgv, "validation failure");
555         exit(1);
556     }
557     exit(0);    /* not reached */
558 }
559
560 /*
561  * Initialize timezone, set umask, fill in ``sudo_user'' struct and
562  * load the ``interfaces'' array.
563  */
564 static void
565 init_vars(envp)
566     char **envp;
567 {
568     char *p, **ep, thost[MAXHOSTNAMELEN + 1];
569     int nohostname;
570
571     /* Sanity check command from user. */
572     if (user_cmnd == NULL && strlen(NewArgv[0]) >= PATH_MAX)
573         errorx(1, "%s: File name too long", NewArgv[0]);
574
575 #ifdef HAVE_TZSET
576     (void) tzset();             /* set the timezone if applicable */
577 #endif /* HAVE_TZSET */
578
579     /* Default value for cmnd and cwd, overridden later. */
580     if (user_cmnd == NULL)
581         user_cmnd = NewArgv[0];
582     (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd));
583
584     /*
585      * We avoid gethostbyname() if possible since we don't want
586      * sudo to block if DNS or NIS is hosed.
587      * "host" is the (possibly fully-qualified) hostname and
588      * "shost" is the unqualified form of the hostname.
589      */
590     nohostname = gethostname(thost, sizeof(thost));
591     if (nohostname) {
592         user_host = user_shost = "localhost";
593     } else {
594         thost[sizeof(thost) - 1] = '\0';
595         user_host = estrdup(thost);
596         if ((p = strchr(user_host, '.'))) {
597             *p = '\0';
598             user_shost = estrdup(user_host);
599             *p = '.';
600         } else {
601             user_shost = user_host;
602         }
603     }
604
605     if ((p = ttyname(STDIN_FILENO)) || (p = ttyname(STDOUT_FILENO)) ||
606         (p = ttyname(STDERR_FILENO))) {
607         user_tty = user_ttypath = estrdup(p);
608         if (strncmp(user_tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
609             user_tty += sizeof(_PATH_DEV) - 1;
610     } else
611         user_tty = "unknown";
612
613     for (ep = envp; *ep; ep++) {
614         /* XXX - don't fill in if empty string */
615         switch (**ep) {
616             case 'D':
617                 if (strncmp("DISPLAY=", *ep, 8) == 0)
618                     user_display = *ep + 8;
619                 break;
620             case 'K':
621                 if (strncmp("KRB5CCNAME=", *ep, 11) == 0)
622                     user_ccname = *ep + 11;
623                 break;
624             case 'P':
625                 if (strncmp("PATH=", *ep, 5) == 0)
626                     user_path = *ep + 5;
627                 break;
628             case 'S':
629                 if (strncmp("SHELL=", *ep, 6) == 0)
630                     user_shell = *ep + 6;
631                 else if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)
632                     user_prompt = *ep + 12;
633                 else if (strncmp("SUDO_USER=", *ep, 10) == 0)
634                     prev_user = *ep + 10;
635                 else if (strncmp("SUDO_ASKPASS=", *ep, 13) == 0)
636                     user_askpass = *ep + 13;
637                 break;
638             }
639     }
640
641     /*
642      * Get a local copy of the user's struct passwd with the shadow password
643      * if necessary.  It is assumed that euid is 0 at this point so we
644      * can read the shadow passwd file if necessary.
645      */
646     if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) {
647         /* Need to make a fake struct passwd for logging to work. */
648         struct passwd pw;
649         char pw_name[MAX_UID_T_LEN + 1];
650
651         pw.pw_uid = getuid();
652         (void) snprintf(pw_name, sizeof(pw_name), "%lu",
653             (unsigned long) pw.pw_uid);
654         pw.pw_name = pw_name;
655         sudo_user.pw = &pw;
656
657         /*
658          * If we are in -k/-K mode, just spew to stderr.  It is not unusual for
659          * users to place "sudo -k" in a .logout file which can cause sudo to
660          * be run during reboot after the YP/NIS/NIS+/LDAP/etc daemon has died.
661          */
662         if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE)
663             errorx(1, "unknown uid: %s", pw_name);
664         log_error(0, "unknown uid: %s", pw_name);
665     }
666 #ifdef HAVE_MBR_CHECK_MEMBERSHIP
667     mbr_uid_to_uuid(user_uid, user_uuid);
668 #endif
669     if (user_shell == NULL || *user_shell == '\0')
670         user_shell = estrdup(sudo_user.pw->pw_shell);
671
672     /* It is now safe to use log_error() and set_perms() */
673
674 #ifdef HAVE_GETGROUPS
675     if ((user_ngroups = getgroups(0, NULL)) > 0) {
676         user_groups = emalloc2(user_ngroups, sizeof(GETGROUPS_T));
677         if (getgroups(user_ngroups, user_groups) < 0)
678             log_error(USE_ERRNO|MSG_ONLY, "can't get group vector");
679     }
680 #endif
681
682     if (nohostname)
683         log_error(USE_ERRNO|MSG_ONLY, "can't get hostname");
684
685     /*
686      * Get current working directory.  Try as user, fall back to root.
687      */
688     set_perms(PERM_USER);
689     if (!getcwd(user_cwd, sizeof(user_cwd))) {
690         set_perms(PERM_ROOT);
691         if (!getcwd(user_cwd, sizeof(user_cwd))) {
692             warningx("cannot get working directory");
693             (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd));
694         }
695     } else
696         set_perms(PERM_ROOT);
697
698     /*
699      * If in shell or edit mode, or if running a pseudo-command
700      * such as "list", we need to redo NewArgv and NewArgc.
701      */
702     if (ISSET(sudo_mode, MODE_SHELL)) {
703         char **av;
704
705         /* Allocate an extra slot for execve() failure (ENOEXEC). */
706         av = (char **) emalloc2(5, sizeof(char *));
707         av++;
708
709         av[0] = user_shell;     /* may be updated later */
710         if (NewArgc > 0) {
711             size_t cmnd_size = 1024;
712             char *cmnd, *src, *dst, **ap;
713
714             cmnd = dst = emalloc(cmnd_size);
715             for (ap = NewArgv; *ap != NULL; ap++) {
716                 for (src = *ap; *src != '\0'; src++) {
717                     /* reserve room for an escaped char + space */
718                     if (cmnd_size < (dst - cmnd) + 3) {
719                         char *new_cmnd;
720                         cmnd_size <<= 1;
721                         new_cmnd = erealloc(cmnd, cmnd_size);
722                         dst = new_cmnd + (dst - cmnd);
723                         cmnd = new_cmnd;
724                     }
725                     if (isalnum((unsigned char)*src) || *src == '_' || *src == '-') {
726                         *dst++ = *src;
727                     } else {
728                         /* quote potential meta character */
729                         *dst++ = '\\';
730                         *dst++ = *src;
731                     }
732                 }
733                 *dst++ = ' ';
734             }
735             if (cmnd != dst)
736                 dst--;  /* replace last space with a NUL */
737             *dst = '\0';
738             av[1] = "-c";
739             av[2] = cmnd;
740             NewArgc = 2;
741         }
742         av[++NewArgc] = NULL;
743         NewArgv = av;
744     } else if (ISSET(sudo_mode, MODE_EDIT) || NewArgc == 0) {
745         NewArgv--;
746         NewArgc++;
747         NewArgv[0] = user_cmnd;
748     }
749 }
750
751 /*
752  * Fill in user_cmnd, user_args, user_base and user_stat variables
753  * and apply any command-specific defaults entries.
754  */
755 static int
756 set_cmnd(sudo_mode)
757     int sudo_mode;
758 {
759     int rval;
760     char *path = user_path;
761
762     /* Resolve the path and return. */
763     rval = FOUND;
764     user_stat = emalloc(sizeof(struct stat));
765     if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) {
766         if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) {
767             if (def_secure_path && !user_is_exempt())
768                 path = def_secure_path;
769             set_perms(PERM_RUNAS);
770             rval = find_path(NewArgv[0], &user_cmnd, user_stat, path,
771                 def_ignore_dot);
772             set_perms(PERM_ROOT);
773             if (rval != FOUND) {
774                 /* Failed as root, try as invoking user. */
775                 set_perms(PERM_USER);
776                 rval = find_path(NewArgv[0], &user_cmnd, user_stat, path,
777                     def_ignore_dot);
778                 set_perms(PERM_ROOT);
779             }
780         }
781
782         /* set user_args */
783         if (NewArgc > 1) {
784             char *to, **from;
785             size_t size, n;
786
787             /* If we didn't realloc NewArgv it is contiguous so just count. */
788             if (!ISSET(sudo_mode, MODE_SHELL)) {
789                 size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) +
790                         strlen(NewArgv[NewArgc-1]) + 1;
791             } else {
792                 for (size = 0, from = NewArgv + 1; *from; from++)
793                     size += strlen(*from) + 1;
794             }
795
796             /* Alloc and build up user_args. */
797             user_args = (char *) emalloc(size);
798             for (to = user_args, from = NewArgv + 1; *from; from++) {
799                 n = strlcpy(to, *from, size - (to - user_args));
800                 if (n >= size - (to - user_args))
801                     errorx(1, "internal error, init_vars() overflow");
802                 to += n;
803                 *to++ = ' ';
804             }
805             *--to = '\0';
806         }
807     }
808     if ((user_base = strrchr(user_cmnd, '/')) != NULL)
809         user_base++;
810     else
811         user_base = user_cmnd;
812
813     if (!update_defaults(SETDEF_CMND))
814         log_error(NO_STDERR|NO_EXIT, "problem with defaults entries");
815
816     if (!runas_user && !runas_group)
817         set_runaspw(def_runas_default); /* may have been updated above */
818
819     return(rval);
820 }
821
822 /*
823  * Setup the execution environment immediately prior to the call to execve()
824  * Returns TRUE on success and FALSE on failure.
825  */
826 int
827 exec_setup(rbac_enabled, ttyname, ttyfd)
828     int rbac_enabled;
829     const char *ttyname;
830     int ttyfd;
831 {
832     int rval = FALSE;
833
834 #ifdef HAVE_SELINUX
835     if (rbac_enabled) {
836        if (selinux_setup(user_role, user_type, ttyname, ttyfd) == -1)
837            goto done;
838     }
839 #endif
840
841     /* Close the password and group files and free up memory. */
842     sudo_endpwent();
843     sudo_endgrent();
844
845     /*
846      * For sudoedit, the command runas a the user with no additional setup.
847      */
848     if (ISSET(sudo_mode, MODE_EDIT)) {
849         set_perms(PERM_FULL_USER);
850         rval = TRUE;
851         goto done;
852     }
853
854     /*
855      * Set umask based on sudoers.
856      * If user's umask is more restrictive, OR in those bits too
857      * unless umask_override is set.
858      */
859     if (def_umask != 0777) {
860         if (def_umask_override) {
861             umask(def_umask);
862         } else {
863             mode_t mask = umask(def_umask);
864             mask |= def_umask;
865             if (mask != def_umask)
866                 umask(mask);
867         }
868     }
869
870     /* Restore coredumpsize resource limit. */
871 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
872     (void) setrlimit(RLIMIT_CORE, &corelimit);
873 #endif /* RLIMIT_CORE && !SUDO_DEVEL */
874
875     if (ISSET(sudo_mode, MODE_RUN))
876         set_perms(PERM_FULL_RUNAS);
877
878     if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
879         /* Change to target user's homedir. */
880         if (chdir(runas_pw->pw_dir) == -1) {
881             warning("unable to change directory to %s", runas_pw->pw_dir);
882             goto done;
883         }
884     }
885
886     /*
887      * Restore nproc resource limit if pam_limits didn't do it for us.
888      * We must do this *after* the uid change to avoid potential EAGAIN
889      * from setuid().
890      */
891 #if defined(__linux__)
892     {
893         struct rlimit rl;
894         if (getrlimit(RLIMIT_NPROC, &rl) == 0) {
895             if (rl.rlim_cur == RLIM_INFINITY && rl.rlim_max == RLIM_INFINITY)
896                 (void) setrlimit(RLIMIT_NPROC, &nproclimit);
897         }
898     }
899 #endif
900
901     rval = TRUE;
902
903 done:
904     return(rval);
905 }
906
907 /*
908  * Run the command and wait for it to complete.
909  */
910 int
911 run_command(path, argv, envp, uid, dowait)
912     const char *path;
913     char *argv[];
914     char *envp[];
915     uid_t uid;
916     int dowait;
917 {
918     struct command_status cstat;
919     int exitcode = 1;
920
921 #ifdef PROFILING
922     exit(0);
923 #endif
924
925     cstat.type = CMD_INVALID;
926     cstat.val = 0;
927
928     sudo_execve(path, argv, envp, uid, &cstat, dowait,
929         ISSET(sudo_mode, MODE_BACKGROUND));
930
931     switch (cstat.type) {
932     case CMD_ERRNO:
933         /* exec_setup() or execve() returned an error. */
934         warningx("unable to execute %s: %s", path, strerror(cstat.val));
935         exitcode = 127;
936         break;
937     case CMD_WSTATUS:
938         /* Command ran, exited or was killed. */
939         if (WIFEXITED(cstat.val))
940             exitcode = WEXITSTATUS(cstat.val);
941         else if (WIFSIGNALED(cstat.val))
942             exitcode = WTERMSIG(cstat.val) | 128;
943         break;
944     default:
945         warningx("unexpected child termination condition: %d", cstat.type);
946         break;
947     }
948 #ifdef HAVE_PAM
949     pam_end_session();
950 #endif /* HAVE_PAM */
951 #ifdef _PATH_SUDO_IO_LOGDIR
952     io_log_close();
953 #endif
954     return(exitcode);
955 }
956
957 /*
958  * Open sudoers and sanity check mode/owner/type.
959  * Returns a handle to the sudoers file or NULL on error.
960  */
961 FILE *
962 open_sudoers(sudoers, doedit, keepopen)
963     const char *sudoers;
964     int doedit;
965     int *keepopen;
966 {
967     struct stat statbuf;
968     FILE *fp = NULL;
969     int rootstat;
970
971     /*
972      * Fix the mode and group on sudoers file from old default.
973      * Only works if file system is readable/writable by root.
974      */
975     if ((rootstat = stat_sudoers(sudoers, &statbuf)) == 0 &&
976         SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 &&
977         (statbuf.st_mode & 0007777) == 0400) {
978
979         if (chmod(sudoers, SUDOERS_MODE) == 0) {
980             warningx("fixed mode on %s", sudoers);
981             SET(statbuf.st_mode, SUDOERS_MODE);
982             if (statbuf.st_gid != SUDOERS_GID) {
983                 if (chown(sudoers, (uid_t) -1, SUDOERS_GID) == 0) {
984                     warningx("set group on %s", sudoers);
985                     statbuf.st_gid = SUDOERS_GID;
986                 } else
987                     warning("unable to set group on %s", sudoers);
988             }
989         } else
990             warning("unable to fix mode on %s", sudoers);
991     }
992
993     /*
994      * Sanity checks on sudoers file.  Must be done as sudoers
995      * file owner.  We already did a stat as root, so use that
996      * data if we can't stat as sudoers file owner.
997      */
998     set_perms(PERM_SUDOERS);
999
1000     if (rootstat != 0 && stat_sudoers(sudoers, &statbuf) != 0)
1001         log_error(USE_ERRNO|NO_EXIT, "can't stat %s", sudoers);
1002     else if (!S_ISREG(statbuf.st_mode))
1003         log_error(NO_EXIT, "%s is not a regular file", sudoers);
1004     else if ((statbuf.st_mode & 07777) != SUDOERS_MODE)
1005         log_error(NO_EXIT, "%s is mode 0%o, should be 0%o", sudoers,
1006             (unsigned int) (statbuf.st_mode & 07777),
1007             (unsigned int) SUDOERS_MODE);
1008     else if (statbuf.st_uid != SUDOERS_UID)
1009         log_error(NO_EXIT, "%s is owned by uid %lu, should be %lu", sudoers,
1010             (unsigned long) statbuf.st_uid, (unsigned long) SUDOERS_UID);
1011     else if (statbuf.st_gid != SUDOERS_GID)
1012         log_error(NO_EXIT, "%s is owned by gid %lu, should be %lu", sudoers,
1013             (unsigned long) statbuf.st_gid, (unsigned long) SUDOERS_GID);
1014     else if ((fp = fopen(sudoers, "r")) == NULL)
1015         log_error(USE_ERRNO|NO_EXIT, "can't open %s", sudoers);
1016     else {
1017         /*
1018          * Make sure we can actually read sudoers so we can present the
1019          * user with a reasonable error message (unlike the lexer).
1020          */
1021         if (statbuf.st_size != 0 && fgetc(fp) == EOF) {
1022             log_error(USE_ERRNO|NO_EXIT, "can't read %s", sudoers);
1023             fclose(fp);
1024             fp = NULL;
1025         }
1026     }
1027
1028     if (fp != NULL) {
1029         rewind(fp);
1030         (void) fcntl(fileno(fp), F_SETFD, 1);
1031     }
1032
1033     set_perms(PERM_ROOT);               /* change back to root */
1034     return(fp);
1035 }
1036
1037 /*
1038  * Close all open files (except std*) and turn off core dumps.
1039  * Also sets the set_perms() pointer to the correct function.
1040  */
1041 static void
1042 initial_setup()
1043 {
1044     int miss[3], devnull = -1;
1045 #if defined(__linux__) || (defined(RLIMIT_CORE) && !defined(SUDO_DEVEL))
1046     struct rlimit rl;
1047 #endif
1048
1049 #if defined(__linux__)
1050     /*
1051      * Unlimit the number of processes since Linux's setuid() will
1052      * apply resource limits when changing uid and return EAGAIN if
1053      * nproc would be violated by the uid switch.
1054      */
1055     (void) getrlimit(RLIMIT_NPROC, &nproclimit);
1056     rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
1057     if (setrlimit(RLIMIT_NPROC, &rl)) {
1058         memcpy(&rl, &nproclimit, sizeof(struct rlimit));
1059         rl.rlim_cur = rl.rlim_max;
1060         (void)setrlimit(RLIMIT_NPROC, &rl);
1061     }
1062 #endif /* __linux__ */
1063 #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)
1064     /*
1065      * Turn off core dumps.
1066      */
1067     (void) getrlimit(RLIMIT_CORE, &corelimit);
1068     memcpy(&rl, &corelimit, sizeof(struct rlimit));
1069     rl.rlim_cur = 0;
1070     (void) setrlimit(RLIMIT_CORE, &rl);
1071 #endif /* RLIMIT_CORE && !SUDO_DEVEL */
1072
1073     /*
1074      * stdin, stdout and stderr must be open; set them to /dev/null
1075      * if they are closed and close all other fds.
1076      */
1077     miss[STDIN_FILENO] = fcntl(STDIN_FILENO, F_GETFL, 0) == -1;
1078     miss[STDOUT_FILENO] = fcntl(STDOUT_FILENO, F_GETFL, 0) == -1;
1079     miss[STDERR_FILENO] = fcntl(STDERR_FILENO, F_GETFL, 0) == -1;
1080     if (miss[STDIN_FILENO] || miss[STDOUT_FILENO] || miss[STDERR_FILENO]) {
1081         if ((devnull = open(_PATH_DEVNULL, O_RDWR, 0644)) == -1)
1082             error(1, "unable to open %s", _PATH_DEVNULL);
1083         if (miss[STDIN_FILENO] && dup2(devnull, STDIN_FILENO) == -1)
1084             error(1, "dup2");
1085         if (miss[STDOUT_FILENO] && dup2(devnull, STDOUT_FILENO) == -1)
1086             error(1, "dup2");
1087         if (miss[STDERR_FILENO] && dup2(devnull, STDERR_FILENO) == -1)
1088             error(1, "dup2");
1089         if (devnull > STDERR_FILENO)
1090             close(devnull);
1091     }
1092 }
1093
1094 #ifdef HAVE_LOGIN_CAP_H
1095 static void
1096 set_loginclass(pw)
1097     struct passwd *pw;
1098 {
1099     int errflags;
1100
1101     /*
1102      * Don't make it a fatal error if the user didn't specify the login
1103      * class themselves.  We do this because if login.conf gets
1104      * corrupted we want the admin to be able to use sudo to fix it.
1105      */
1106     if (login_class)
1107         errflags = NO_MAIL|MSG_ONLY;
1108     else
1109         errflags = NO_MAIL|MSG_ONLY|NO_EXIT;
1110
1111     if (login_class && strcmp(login_class, "-") != 0) {
1112         if (user_uid != 0 &&
1113             strcmp(runas_user ? runas_user : def_runas_default, "root") != 0)
1114             errorx(1, "only root can use -c %s", login_class);
1115     } else {
1116         login_class = pw->pw_class;
1117         if (!login_class || !*login_class)
1118             login_class =
1119                 (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
1120     }
1121
1122     lc = login_getclass(login_class);
1123     if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) {
1124         log_error(errflags, "unknown login class: %s", login_class);
1125         if (!lc)
1126             lc = login_getclass(NULL);  /* needed for login_getstyle() later */
1127     }
1128 }
1129 #else
1130 static void
1131 set_loginclass(pw)
1132     struct passwd *pw;
1133 {
1134 }
1135 #endif /* HAVE_LOGIN_CAP_H */
1136
1137 /*
1138  * Look up the fully qualified domain name and set user_host and user_shost.
1139  */
1140 void
1141 set_fqdn()
1142 {
1143 #ifdef HAVE_GETADDRINFO
1144     struct addrinfo *res0, hint;
1145 #else
1146     struct hostent *hp;
1147 #endif
1148     char *p;
1149
1150 #ifdef HAVE_GETADDRINFO
1151     zero_bytes(&hint, sizeof(hint));
1152     hint.ai_family = PF_UNSPEC;
1153     hint.ai_flags = AI_CANONNAME;
1154     if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) {
1155 #else
1156     if (!(hp = gethostbyname(user_host))) {
1157 #endif
1158         log_error(MSG_ONLY|NO_EXIT,
1159             "unable to resolve host %s", user_host);
1160     } else {
1161         if (user_shost != user_host)
1162             efree(user_shost);
1163         efree(user_host);
1164 #ifdef HAVE_GETADDRINFO
1165         user_host = estrdup(res0->ai_canonname);
1166         freeaddrinfo(res0);
1167 #else
1168         user_host = estrdup(hp->h_name);
1169 #endif
1170     }
1171     if ((p = strchr(user_host, '.'))) {
1172         *p = '\0';
1173         user_shost = estrdup(user_host);
1174         *p = '.';
1175     } else {
1176         user_shost = user_host;
1177     }
1178 }
1179
1180 /*
1181  * Get passwd entry for the user we are going to run commands as.
1182  * By default, this is "root".  Updates runas_pw as a side effect.
1183  */
1184 static void
1185 set_runaspw(user)
1186     char *user;
1187 {
1188     if (*user == '#') {
1189         if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
1190             runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
1191     } else {
1192         if ((runas_pw = sudo_getpwnam(user)) == NULL) {
1193             audit_failure(NewArgv, "unknown user: %s", user);
1194             log_error(NO_MAIL|MSG_ONLY, "unknown user: %s", user);
1195         }
1196     }
1197 }
1198
1199 /*
1200  * Get group entry for the group we are going to run commands as.
1201  * Updates runas_pw as a side effect.
1202  */
1203 static void
1204 set_runasgr(group)
1205     char *group;
1206 {
1207     if (*group == '#') {
1208         if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
1209             runas_gr = sudo_fakegrnam(group);
1210     } else {
1211         if ((runas_gr = sudo_getgrnam(group)) == NULL)
1212             log_error(NO_MAIL|MSG_ONLY, "unknown group: %s", group);
1213     }
1214 }
1215
1216 /*
1217  * Get passwd entry for the user we are going to authenticate as.
1218  * By default, this is the user invoking sudo.  In the most common
1219  * case, this matches sudo_user.pw or runas_pw.
1220  */
1221 static struct passwd *
1222 get_authpw()
1223 {
1224     struct passwd *pw;
1225
1226     if (def_rootpw) {
1227         if ((pw = sudo_getpwuid(0)) == NULL)
1228             log_error(0, "unknown uid: 0");
1229     } else if (def_runaspw) {
1230         if ((pw = sudo_getpwnam(def_runas_default)) == NULL)
1231             log_error(0, "unknown user: %s", def_runas_default);
1232     } else if (def_targetpw) {
1233         if (runas_pw->pw_name == NULL)
1234             log_error(NO_MAIL|MSG_ONLY, "unknown uid: %lu",
1235                 (unsigned long) runas_pw->pw_uid);
1236         pw = runas_pw;
1237     } else
1238         pw = sudo_user.pw;
1239
1240     return(pw);
1241 }
1242
1243 /*
1244  * Cleanup hook for error()/errorx()
1245  */
1246 void
1247 cleanup(gotsignal)
1248     int gotsignal;
1249 {
1250     struct sudo_nss *nss;
1251
1252     if (!gotsignal) {
1253         if (snl != NULL) {
1254             tq_foreach_fwd(snl, nss)
1255                 nss->close(nss);
1256         }
1257 #ifdef USING_NONUNIX_GROUPS
1258         sudo_nonunix_groupcheck_cleanup();
1259 #endif
1260         sudo_endpwent();
1261         sudo_endgrent();
1262 #ifdef _PATH_SUDO_IO_LOGDIR
1263         io_log_close();
1264 #endif
1265     }
1266     term_restore(STDIN_FILENO, 0);
1267 #ifdef HAVE_SELINUX
1268     selinux_restore_tty();
1269 #endif
1270 }
1271
1272 static void
1273 show_version()
1274 {
1275     (void) printf("Sudo version %s\n", PACKAGE_VERSION);
1276     if (getuid() == 0) {
1277         putchar('\n');
1278         (void) printf("Configure args: %s\n", CONFIGURE_ARGS);
1279         (void) printf("Sudoers path: %s\n", _PATH_SUDOERS);
1280 #ifdef HAVE_LDAP
1281 # ifdef _PATH_NSSWITCH_CONF
1282         (void) printf("nsswitch path: %s\n", _PATH_NSSWITCH_CONF);
1283 # endif
1284         (void) printf("ldap.conf path: %s\n", _PATH_LDAP_CONF);
1285         (void) printf("ldap.secret path: %s\n", _PATH_LDAP_SECRET);
1286 #endif
1287         dump_auth_methods();
1288         dump_defaults();
1289         dump_interfaces();
1290     }
1291     exit(0);
1292 }
1293
1294 #ifdef USE_ADMIN_FLAG
1295 static void
1296 create_admin_success_flag()
1297 {
1298     struct stat statbuf;
1299     char flagfile[PATH_MAX];
1300     int fd, n;
1301
1302     /* Check whether the user is in the admin group. */
1303     if (!user_in_group(sudo_user.pw, "admin"))
1304         return;
1305
1306     /* Build path to flag file. */
1307     n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful",
1308         user_dir);
1309     if (n <= 0 || n >= sizeof(flagfile))
1310         return;
1311
1312     /* Create admin flag file if it doesn't already exist. */
1313     set_perms(PERM_USER);
1314     if (stat(flagfile, &statbuf) == 0) {
1315         set_perms(PERM_ROOT);
1316         return;
1317     }
1318
1319     fd = open(flagfile, O_CREAT|O_WRONLY|O_EXCL, 0644);
1320     close(fd);
1321     set_perms(PERM_ROOT);
1322 }
1323 #else /* !USE_ADMIN_FLAG */
1324 static void
1325 create_admin_success_flag()
1326 {
1327     /* STUB */
1328 }
1329 #endif /* USE_ADMIN_FLAG */