Imported Upstream version 1.8.7
[debian/sudo] / plugins / sudoers / testsudoers.c
index d63ca9230600e94b888aa2f2ed8cf75a8032957c..00c71c5a5a2ab05499650ecbf3e729829e0c8710 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 1998-2005, 2007-2012
+ * Copyright (c) 1996, 1998-2005, 2007-2013
  *     Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -25,7 +25,6 @@
 
 #include <config.h>
 
-#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <errno.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <netdb.h>
-#ifdef HAVE_SETLOCALE
-# include <locale.h>
-#endif
 
 #include "tsgetgrpw.h"
 #include "sudoers.h"
 #include "interfaces.h"
 #include "parse.h"
 #include "sudo_conf.h"
+#include "secure_path.h"
 #include <gram.h>
 
 /*
@@ -80,11 +76,9 @@ void print_defaults(void);
 void print_privilege(struct privilege *);
 void print_userspecs(void);
 void usage(void) __attribute__((__noreturn__));
-void cleanup(int);
 static void set_runaspw(const char *);
 static void set_runasgr(const char *);
 static int cb_runas_default(const char *);
-static int testsudoers_printf(int msg_type, const char *fmt, ...);
 static int testsudoers_print(const char *msg);
 
 extern void setgrfile(const char *);
@@ -105,15 +99,12 @@ extern int (*trace_print)(const char *msg);
 /*
  * Globals
  */
-struct interface *interfaces;
 struct sudo_user sudo_user;
 struct passwd *list_pw;
 static char *runas_group, *runas_user;
 extern int errorlineno;
 extern bool parse_error;
 extern char *errorfile;
-sudo_printf_t sudo_printf = testsudoers_printf;
-sudo_conv_t sudo_conv; /* NULL in non-plugin */
 
 /* For getopt(3) */
 extern char *optarg;
@@ -123,9 +114,11 @@ extern int optind;
 extern char *malloc_options;
 #endif
 #ifdef YYDEBUG
-extern int yydebug;
+extern int sudoersdebug;
 #endif
 
+__dso_public int main(int argc, char *argv[]);
+
 int
 main(int argc, char *argv[])
 {
@@ -133,7 +126,7 @@ main(int argc, char *argv[])
     struct privilege *priv;
     struct userspec *us;
     char *p, *grfile, *pwfile;
-    char hbuf[MAXHOSTNAMELEN + 1];
+    char hbuf[HOST_NAME_MAX + 1];
     int match, host_match, runas_match, cmnd_match;
     int ch, dflag, exitcode = 0;
     debug_decl(main, SUDO_DEBUG_MAIN)
@@ -142,25 +135,23 @@ main(int argc, char *argv[])
     malloc_options = "AFGJPR";
 #endif
 #ifdef YYDEBUG
-    yydebug = 1;
+    sudoersdebug = 1;
 #endif
 
 #if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME)
     setprogname(argc > 0 ? argv[0] : "testsudoers");
 #endif
 
-#ifdef HAVE_SETLOCALE 
-    setlocale(LC_ALL, "");
-#endif
+    sudoers_setlocale(SUDOERS_LOCALE_USER, NULL);
     bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have own domain */
     textdomain("sudoers");
 
     /* Read sudo.conf. */
-    sudo_conf_read();
+    sudo_conf_read(NULL);
 
     dflag = 0;
     grfile = pwfile = NULL;
-    while ((ch = getopt(argc, argv, "dg:G:h:p:tu:")) != -1) {
+    while ((ch = getopt(argc, argv, "dg:G:h:P:p:tu:U:")) != -1) {
        switch (ch) {
            case 'd':
                dflag = 1;
@@ -169,7 +160,7 @@ main(int argc, char *argv[])
                user_host = optarg;
                break;
            case 'G':
-               grfile = optarg;
+               sudoers_gid = (gid_t)atoi(optarg);
                break;
            case 'g':
                runas_group = optarg;
@@ -177,9 +168,15 @@ main(int argc, char *argv[])
            case 'p':
                pwfile = optarg;
                break;
+           case 'P':
+               grfile = optarg;
+               break;
            case 't':
                trace_print = testsudoers_print;
                break;
+           case 'U':
+               sudoers_uid = (uid_t)atoi(optarg);
+               break;
            case 'u':
                runas_user = optarg;
                break;
@@ -215,11 +212,11 @@ main(int argc, char *argv[])
        argc -= 2;
     }
     if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL)
-       errorx(1, _("unknown user: %s"), user_name);
+       fatalx(_("unknown user: %s"), user_name);
 
     if (user_host == NULL) {
        if (gethostname(hbuf, sizeof(hbuf)) != 0)
-           error(1, "gethostname");
+           fatal("gethostname");
        hbuf[sizeof(hbuf) - 1] = '\0';
        user_host = hbuf;
     }
@@ -243,7 +240,7 @@ main(int argc, char *argv[])
        for (to = user_args, from = argv; *from; from++) {
            n = strlcpy(to, *from, size - (to - user_args));
            if (n >= size - (to - user_args))
-                   errorx(1, _("internal error, init_vars() overflow"));
+               fatalx(_("internal error, %s overflow"), "init_vars()");
            to += n;
            *to++ = ' ';
        }
@@ -261,9 +258,9 @@ main(int argc, char *argv[])
        set_interfaces(p);
 
     /* Allocate space for data structures in the parser. */
-    init_parser("sudoers", 0);
+    init_parser("sudoers", false);
 
-    if (yyparse() != 0 || parse_error) {
+    if (sudoersparse() != 0 || parse_error) {
        parse_error = true;
        if (errorlineno != -1)
            (void) printf("Parse error in %s near line %d",
@@ -317,7 +314,7 @@ main(int argc, char *argv[])
                puts("\thost  matched");
                tq_foreach_rev(&priv->cmndlist, cs) {
                    runas_match = runaslist_matches(&cs->runasuserlist,
-                       &cs->runasgrouplist);
+                       &cs->runasgrouplist, NULL, NULL);
                    if (runas_match == ALLOW) {
                        puts("\trunas matched");
                        cmnd_match = cmnd_matches(cs->cmnd);
@@ -353,13 +350,13 @@ set_runaspw(const char *user)
     debug_decl(main, SUDO_DEBUG_UTIL)
 
     if (runas_pw != NULL)
-       pw_delref(runas_pw);
+       sudo_pw_delref(runas_pw);
     if (*user == '#') {
        if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
            runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0);
     } else {
        if ((runas_pw = sudo_getpwnam(user)) == NULL)
-           errorx(1, _("unknown user: %s"), user);
+           fatalx(_("unknown user: %s"), user);
     }
 
     debug_return;
@@ -371,13 +368,13 @@ set_runasgr(const char *group)
     debug_decl(main, SUDO_DEBUG_UTIL)
 
     if (runas_gr != NULL)
-       gr_delref(runas_gr);
+       sudo_gr_delref(runas_gr);
     if (*group == '#') {
        if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
            runas_gr = sudo_fakegrnam(group);
     } else {
        if ((runas_gr = sudo_getgrnam(group)) == NULL)
-           errorx(1, _("unknown group: %s"), group);
+           fatalx(_("unknown group: %s"), group);
     }
 
     debug_return;
@@ -407,18 +404,45 @@ sudo_endspent(void)
     return;
 }
 
-void
-set_fqdn(void)
-{
-    return;
-}
-
 FILE *
-open_sudoers(const char *path, bool doedit, bool *keepopen)
+open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
 {
+    struct stat sb;
+    FILE *fp = NULL;
+    char *sudoers_base;
     debug_decl(open_sudoers, SUDO_DEBUG_UTIL)
 
-    debug_return_ptr(fopen(path, "r"));
+    sudoers_base = strrchr(sudoers, '/');
+    if (sudoers_base != NULL)
+       sudoers_base++;
+
+    switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) {
+       case SUDO_PATH_SECURE:
+           fp = fopen(sudoers, "r");
+           break;
+       case SUDO_PATH_MISSING:
+           warning("unable to stat %s", sudoers_base);
+           break;
+       case SUDO_PATH_BAD_TYPE:
+           warningx("%s is not a regular file", sudoers_base);
+           break;
+       case SUDO_PATH_WRONG_OWNER:
+           warningx("%s should be owned by uid %u",
+               sudoers_base, (unsigned int) sudoers_uid);
+           break;
+       case SUDO_PATH_WORLD_WRITABLE:
+           warningx("%s is world writable", sudoers_base);
+           break;
+       case SUDO_PATH_GROUP_WRITABLE:
+           warningx("%s should be owned by gid %u",
+               sudoers_base, (unsigned int) sudoers_gid);
+           break;
+       default:
+           /* NOTREACHED */
+           break;
+    }
+
+    debug_return_ptr(fp);
 }
 
 void
@@ -438,15 +462,6 @@ restore_perms(void)
 {
 }
 
-void
-cleanup(int gotsignal)
-{
-    if (!gotsignal) {
-       sudo_endpwent();
-       sudo_endgrent();
-    }
-}
-
 void
 print_member(struct member *m)
 {
@@ -563,7 +578,8 @@ print_privilege(struct privilege *priv)
            print_member(m);
        }
        fputs(" = ", stdout);
-       tags.nopasswd = tags.noexec = UNSPEC;
+       tags.nopasswd = UNSPEC;
+       tags.noexec = UNSPEC;
        tq_foreach_fwd(&p->cmndlist, cs) {
            if (cs != tq_first(&p->cmndlist))
                fputs(", ", stdout);
@@ -596,6 +612,12 @@ print_privilege(struct privilege *priv)
            if (cs->type)
                printf("TYPE=%s ", cs->type);
 #endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+           if (cs->privs)
+               printf("PRIVS=%s ", cs->privs);
+           if (cs->limitprivs)
+               printf("LIMITPRIVS=%s ", cs->limitprivs);
+#endif /* HAVE_PRIV_SET */
            if (cs->tags.nopasswd != UNSPEC && cs->tags.nopasswd != tags.nopasswd)
                printf("%sPASSWD: ", cs->tags.nopasswd ? "NO" : "");
            if (cs->tags.noexec != UNSPEC && cs->tags.noexec != tags.noexec)
@@ -627,32 +649,6 @@ print_userspecs(void)
     debug_return;
 }
 
-static int
-testsudoers_printf(int msg_type, const char *fmt, ...)
-{
-    va_list ap;
-    FILE *fp;
-    debug_decl(testsudoers_printf, SUDO_DEBUG_UTIL)
-            
-    switch (msg_type) {
-    case SUDO_CONV_INFO_MSG:
-       fp = stdout;
-       break;
-    case SUDO_CONV_ERROR_MSG:
-       fp = stderr;
-       break;
-    default:
-       errno = EINVAL;
-       debug_return_int(-1);
-    }
-   
-    va_start(ap, fmt);
-    vfprintf(fp, fmt, ap);
-    va_end(ap);
-   
-    debug_return_int(0);
-}
-
 void
 dump_sudoers(void)
 {
@@ -677,6 +673,6 @@ static int testsudoers_print(const char *msg)
 void
 usage(void)
 {
-    (void) fprintf(stderr, "usage: %s [-dt] [-G grfile] [-g group] [-h host] [-p pwfile] [-u user] <user> <command> [args]\n", getprogname());
+    (void) fprintf(stderr, "usage: %s [-dt] [-G sudoers_gid] [-g group] [-h host] [-p grfile] [-p pwfile] [-U sudoers_uid] [-u user] <user> <command> [args]\n", getprogname());
     exit(1);
 }