--- embedaddon/sudo/plugins/sudoers/testsudoers.c 2012/05/29 12:26:49 1.1.1.2 +++ embedaddon/sudo/plugins/sudoers/testsudoers.c 2014/06/15 16:12:54 1.1.1.6 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2012 + * Copyright (c) 1996, 1998-2005, 2007-2013 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -25,7 +25,6 @@ #include -#include #include #include #include @@ -59,16 +58,13 @@ #include #include #include -#include -#ifdef HAVE_SETLOCALE -# include -#endif #include "tsgetgrpw.h" #include "sudoers.h" #include "interfaces.h" #include "parse.h" #include "sudo_conf.h" +#include "secure_path.h" #include /* @@ -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,27 +99,19 @@ 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; -extern int optind; - #if defined(SUDO_DEVEL) && defined(__OpenBSD__) 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 +119,8 @@ 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]; + const char *errstr; int match, host_match, runas_match, cmnd_match; int ch, dflag, exitcode = 0; debug_decl(main, SUDO_DEBUG_MAIN) @@ -142,25 +129,21 @@ 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 + initprogname(argc > 0 ? argv[0] : "testsudoers"); -#ifdef HAVE_SETLOCALE - setlocale(LC_ALL, ""); -#endif + sudoers_initlocale(setlocale(LC_ALL, ""), def_sudoers_locale); 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 +152,9 @@ main(int argc, char *argv[]) user_host = optarg; break; case 'G': - grfile = optarg; + sudoers_gid = (gid_t)atoid(optarg, NULL, NULL, &errstr); + if (errstr != NULL) + fatalx("group ID %s: %s", optarg, errstr); break; case 'g': runas_group = optarg; @@ -177,9 +162,17 @@ 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)atoid(optarg, NULL, NULL, &errstr); + if (errstr != NULL) + fatalx("user ID %s: %s", optarg, errstr); + break; case 'u': runas_user = optarg; break; @@ -215,11 +208,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(U_("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; } @@ -230,6 +223,8 @@ main(int argc, char *argv[]) } else { user_shost = user_host; } + user_runhost = user_host; + user_srunhost = user_shost; /* Fill in user_args from argv. */ if (argc > 0) { @@ -243,7 +238,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(U_("internal error, %s overflow"), "init_vars()"); to += n; *to++ = ' '; } @@ -261,9 +256,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", @@ -305,19 +300,19 @@ main(int argc, char *argv[]) /* This loop must match the one in sudo_file_lookup() */ printf("\nEntries for user %s:\n", user_name); match = UNSPEC; - tq_foreach_rev(&userspecs, us) { + TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) { if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) continue; - tq_foreach_rev(&us->privileges, priv) { + TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) { putchar('\n'); - print_privilege(priv); /* XXX */ + print_privilege(priv); putchar('\n'); host_match = hostlist_matches(&priv->hostlist); if (host_match == ALLOW) { puts("\thost matched"); - tq_foreach_rev(&priv->cmndlist, cs) { - runas_match = runaslist_matches(&cs->runasuserlist, - &cs->runasgrouplist); + TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) { + runas_match = runaslist_matches(cs->runasuserlist, + cs->runasgrouplist, NULL, NULL); if (runas_match == ALLOW) { puts("\trunas matched"); cmnd_match = cmnd_matches(cs->cmnd); @@ -343,6 +338,8 @@ main(int argc, char *argv[]) */ exitcode = parse_error ? 1 : (match == ALLOW ? 0 : match + 3); done: + sudo_endpwent(); + sudo_endgrent(); sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode); exit(exitcode); } @@ -350,36 +347,48 @@ done: static void set_runaspw(const char *user) { - debug_decl(main, SUDO_DEBUG_UTIL) + struct passwd *pw = NULL; + debug_decl(set_runaspw, SUDO_DEBUG_UTIL) - if (runas_pw != NULL) - 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); + const char *errstr; + uid_t uid = atoid(user + 1, NULL, NULL, &errstr); + if (errstr == NULL) { + if ((pw = sudo_getpwuid(uid)) == NULL) + pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0); + } } - + if (pw == NULL) { + if ((pw = sudo_getpwnam(user)) == NULL) + fatalx(U_("unknown user: %s"), user); + } + if (runas_pw != NULL) + sudo_pw_delref(runas_pw); + runas_pw = pw; debug_return; } static void set_runasgr(const char *group) { - debug_decl(main, SUDO_DEBUG_UTIL) + struct group *gr = NULL; + debug_decl(set_runasgr, SUDO_DEBUG_UTIL) - if (runas_gr != NULL) - 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); + const char *errstr; + gid_t gid = atoid(group + 1, NULL, NULL, &errstr); + if (errstr == NULL) { + if ((gr = sudo_getgrgid(gid)) == NULL) + gr = sudo_fakegrnam(group); + } } - + if (gr == NULL) { + if ((gr = sudo_getgrnam(group)) == NULL) + fatalx(U_("unknown group: %s"), group); + } + if (runas_gr != NULL) + sudo_gr_delref(runas_gr); + runas_gr = gr; debug_return; } @@ -407,18 +416,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 @@ -439,15 +475,6 @@ restore_perms(void) } void -cleanup(int gotsignal) -{ - if (!gotsignal) { - sudo_endpwent(); - sudo_endgrent(); - } -} - -void print_member(struct member *m) { struct sudo_command *c; @@ -473,9 +500,9 @@ print_defaults(void) { struct defaults *d; struct member *m; - debug_decl(print_member, SUDO_DEBUG_UTIL) + debug_decl(print_defaults, SUDO_DEBUG_UTIL) - tq_foreach_fwd(&defaults, d) { + TAILQ_FOREACH(d, &defaults, entries) { (void) fputs("Defaults", stdout); switch (d->type) { case DEFAULTS_HOST: @@ -491,8 +518,8 @@ print_defaults(void) putchar('!'); break; } - tq_foreach_fwd(&d->binding, m) { - if (m != tq_first(&d->binding)) + TAILQ_FOREACH(m, d->binding, entries) { + if (m != TAILQ_FIRST(d->binding)) putchar(','); print_member(m); } @@ -528,8 +555,8 @@ print_alias(void *v1, void *v2) (void) printf("Runas_Alias\t%s = ", a->name); break; } - tq_foreach_fwd(&a->members, m) { - if (m != tq_first(&a->members)) + TAILQ_FOREACH(m, &a->members, entries) { + if (m != TAILQ_FIRST(&a->members)) fputs(", ", stdout); if (m->type == COMMAND) { c = (struct sudo_command *) m->name; @@ -550,59 +577,61 @@ print_privilege(struct privilege *priv) { struct cmndspec *cs; struct member *m; - struct privilege *p; struct cmndtag tags; debug_decl(print_privilege, SUDO_DEBUG_UTIL) - for (p = priv; p != NULL; p = p->next) { - if (p != priv) - fputs(" : ", stdout); - tq_foreach_fwd(&p->hostlist, m) { - if (m != tq_first(&p->hostlist)) - fputs(", ", stdout); - print_member(m); - } - fputs(" = ", stdout); - tags.nopasswd = tags.noexec = UNSPEC; - tq_foreach_fwd(&p->cmndlist, cs) { - if (cs != tq_first(&p->cmndlist)) - fputs(", ", stdout); - if (!tq_empty(&cs->runasuserlist) || !tq_empty(&cs->runasgrouplist)) { - fputs("(", stdout); - if (!tq_empty(&cs->runasuserlist)) { - tq_foreach_fwd(&cs->runasuserlist, m) { - if (m != tq_first(&cs->runasuserlist)) - fputs(", ", stdout); - print_member(m); - } - } else if (tq_empty(&cs->runasgrouplist)) { - fputs(def_runas_default, stdout); - } else { - fputs(sudo_user.pw->pw_name, stdout); + TAILQ_FOREACH(m, &priv->hostlist, entries) { + if (m != TAILQ_FIRST(&priv->hostlist)) + fputs(", ", stdout); + print_member(m); + } + fputs(" = ", stdout); + tags.nopasswd = UNSPEC; + tags.noexec = UNSPEC; + TAILQ_FOREACH(cs, &priv->cmndlist, entries) { + if (cs != TAILQ_FIRST(&priv->cmndlist)) + fputs(", ", stdout); + if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL) { + fputs("(", stdout); + if (cs->runasuserlist != NULL) { + TAILQ_FOREACH(m, cs->runasuserlist, entries) { + if (m != TAILQ_FIRST(cs->runasuserlist)) + fputs(", ", stdout); + print_member(m); + } + } else if (cs->runasgrouplist == NULL) { + fputs(def_runas_default, stdout); + } else { + fputs(sudo_user.pw->pw_name, stdout); + } + if (cs->runasgrouplist != NULL) { + fputs(" : ", stdout); + TAILQ_FOREACH(m, cs->runasgrouplist, entries) { + if (m != TAILQ_FIRST(cs->runasgrouplist)) + fputs(", ", stdout); + print_member(m); } - if (!tq_empty(&cs->runasgrouplist)) { - fputs(" : ", stdout); - tq_foreach_fwd(&cs->runasgrouplist, m) { - if (m != tq_first(&cs->runasgrouplist)) - fputs(", ", stdout); - print_member(m); - } - } - fputs(") ", stdout); } + fputs(") ", stdout); + } #ifdef HAVE_SELINUX - if (cs->role) - printf("ROLE=%s ", cs->role); - if (cs->type) - printf("TYPE=%s ", cs->type); + if (cs->role) + printf("ROLE=%s ", cs->role); + if (cs->type) + printf("TYPE=%s ", cs->type); #endif /* HAVE_SELINUX */ - 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) - printf("%sEXEC: ", cs->tags.noexec ? "NO" : ""); - print_member(cs->cmnd); - memcpy(&tags, &cs->tags, sizeof(tags)); - } +#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) + printf("%sEXEC: ", cs->tags.noexec ? "NO" : ""); + print_member(cs->cmnd); + memcpy(&tags, &cs->tags, sizeof(tags)); } debug_return; } @@ -612,47 +641,26 @@ print_userspecs(void) { struct member *m; struct userspec *us; + struct privilege *priv; debug_decl(print_userspecs, SUDO_DEBUG_UTIL) - tq_foreach_fwd(&userspecs, us) { - tq_foreach_fwd(&us->users, m) { - if (m != tq_first(&us->users)) + TAILQ_FOREACH(us, &userspecs, entries) { + TAILQ_FOREACH(m, &us->users, entries) { + if (m != TAILQ_FIRST(&us->users)) fputs(", ", stdout); print_member(m); } putchar('\t'); - print_privilege(us->privileges.first); /* XXX */ + TAILQ_FOREACH(priv, &us->privileges, entries) { + if (priv != TAILQ_FIRST(&us->privileges)) + fputs(" : ", stdout); + print_privilege(priv); + } putchar('\n'); } 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 +685,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] [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] [args]\n", getprogname()); exit(1); }