diff options
Diffstat (limited to 'usr.bin/sudo/testsudoers.c')
-rw-r--r-- | usr.bin/sudo/testsudoers.c | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/usr.bin/sudo/testsudoers.c b/usr.bin/sudo/testsudoers.c new file mode 100644 index 00000000000..ee4d2fe1c39 --- /dev/null +++ b/usr.bin/sudo/testsudoers.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 1996, 1998, 1999 Todd C. Miller <Todd.Miller@courtesan.com> + * All rights reserved. + * + * This code is derived from software contributed by Chris Jepeway + * <jepeway@cs.utk.edu>. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. Products derived from this software may not be called "Sudo" nor + * may "Sudo" appear in their names without specific prior written + * permission from the author. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include <stdio.h> +#ifdef STDC_HEADERS +# include <stdlib.h> +#endif /* STDC_HEADERS */ +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_STRING_H +# include <string.h> +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif /* HAVE_STRINGS_H */ +#if defined(HAVE_FNMATCH) && defined(HAVE_FNMATCH_H) +# include <fnmatch.h> +#endif /* HAVE_FNMATCH_H */ +#ifdef HAVE_NETGROUP_H +# include <netgroup.h> +#endif /* HAVE_NETGROUP_H */ +#include <ctype.h> +#include <pwd.h> +#include <grp.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/stat.h> +#include <dirent.h> + +#include "sudo.h" +#include "parse.h" +#include "interfaces.h" + +#ifndef HAVE_FNMATCH +# include "emul/fnmatch.h" +#endif /* HAVE_FNMATCH */ + +#ifndef lint +static const char rcsid[] = "$Sudo: testsudoers.c,v 1.64 1999/09/08 08:06:19 millert Exp $"; +#endif /* lint */ + +/* + * Globals + */ +char **Argv, **NewArgv; +int Argc, NewArgc; +int parse_error = FALSE; +int num_interfaces; +struct interface *interfaces; +struct sudo_user sudo_user; +extern int clearaliases; +extern int pedantic; + +/* + * Prototypes for external functions + */ +void init_parser __P((void)); +void dumpaliases __P((void)); + +/* + * Returns TRUE if "s" has shell meta characters in it, + * else returns FALSE. + */ +int +has_meta(s) + char *s; +{ + register char *t; + + for (t = s; *t; t++) { + if (*t == '\\' || *t == '?' || *t == '*' || *t == '[' || *t == ']') + return(TRUE); + } + return(FALSE); +} + +/* + * Returns TRUE if cmnd matches, in the sudo sense, + * the pathname in path; otherwise, return FALSE + */ +int +command_matches(cmnd, cmnd_args, path, sudoers_args) + char *cmnd; + char *cmnd_args; + char *path; + char *sudoers_args; +{ + int clen, plen; + char *args; + + if (cmnd == NULL) + return(FALSE); + + if ((args = strchr(path, ' '))) + *args++ = '\0'; + + if (has_meta(path)) { + if (fnmatch(path, cmnd, FNM_PATHNAME)) + return(FALSE); + if (!sudoers_args) + return(TRUE); + else if (!cmnd_args && sudoers_args && !strcmp("\"\"", sudoers_args)) + return(TRUE); + else if (sudoers_args) + return((fnmatch(sudoers_args, cmnd_args ? cmnd_args : "", 0) == 0)); + else + return(FALSE); + } else { + plen = strlen(path); + if (path[plen - 1] != '/') { + if (strcmp(cmnd, path)) + return(FALSE); + if (!sudoers_args) + return(TRUE); + else if (!cmnd_args && sudoers_args && !strcmp("\"\"", sudoers_args)) + return(TRUE); + else if (sudoers_args) + return((fnmatch(sudoers_args, cmnd_args ? cmnd_args : "", 0) == 0)); + else + return(FALSE); + } + + clen = strlen(cmnd); + if (clen < plen + 1) + /* path cannot be the parent dir of cmnd */ + return(FALSE); + + if (strchr(cmnd + plen + 1, '/') != NULL) + /* path could only be an anscestor of cmnd -- */ + /* ignoring, of course, things like // & /./ */ + return(FALSE); + + /* see whether path is the prefix of cmnd */ + return((strncmp(cmnd, path, plen) == 0)); + } +} + +int +addr_matches(n) + char *n; +{ + int i; + char *m; + struct in_addr addr, mask; + + /* If there's an explicit netmask, use it. */ + if ((m = strchr(n, '/'))) { + *m++ = '\0'; + addr.s_addr = inet_addr(n); + if (strchr(m, '.')) + mask.s_addr = inet_addr(m); + else + mask.s_addr = (1 << atoi(m)) - 1; /* XXX - better way? */ + *(m - 1) = '/'; + + for (i = 0; i < num_interfaces; i++) + if ((interfaces[i].addr.s_addr & mask.s_addr) == addr.s_addr) + return(TRUE); + } else { + addr.s_addr = inet_addr(n); + + for (i = 0; i < num_interfaces; i++) + if (interfaces[i].addr.s_addr == addr.s_addr || + (interfaces[i].addr.s_addr & interfaces[i].netmask.s_addr) + == addr.s_addr) + return(TRUE); + } + + return(FALSE); +} + +int +usergr_matches(group, user) + char *group; + char *user; +{ + struct group *grp; + char **cur; + + /* Make sure we have a valid usergroup, sudo style. */ + if (*group++ != '%') + return(FALSE); + + if ((grp = getgrnam(group)) == NULL) + return(FALSE); + + /* + * Check against user's real gid as well as group's user list + */ + if (getgid() == grp->gr_gid) + return(TRUE); + + for (cur=grp->gr_mem; *cur; cur++) { + if (strcmp(*cur, user) == 0) + return(TRUE); + } + + return(FALSE); +} + +int +netgr_matches(netgr, host, user) + char *netgr; + char *host; + char *user; +{ +#ifdef HAVE_GETDOMAINNAME + static char *domain = (char *) -1; +#else + static char *domain = NULL; +#endif /* HAVE_GETDOMAINNAME */ + + /* Make sure we have a valid netgroup, sudo style. */ + if (*netgr++ != '+') + return(FALSE); + +#ifdef HAVE_GETDOMAINNAME + /* Get the domain name (if any). */ + if (domain == (char *) -1) { + domain = (char *) emalloc(MAXHOSTNAMELEN); + + if (getdomainname(domain, MAXHOSTNAMELEN) != 0 || *domain == '\0') { + free(domain); + domain = NULL; + } + } +#endif /* HAVE_GETDOMAINNAME */ + +#ifdef HAVE_INNETGR + return(innetgr(netgr, host, user, domain)); +#else + return(FALSE); +#endif /* HAVE_INNETGR */ +} + +void +set_perms(i, j) + int i, j; +{ + return; +} + +int +main(argc, argv) + int argc; + char **argv; +{ + struct passwd pw; + char *p; +#ifdef YYDEBUG + extern int yydebug; + yydebug = 1; +#endif + + Argv = argv; + Argc = argc; + + if (Argc >= 6 && strcmp(Argv[1], "-u") == 0) { + user_runas = &Argv[2]; + pw.pw_name = Argv[3]; + user_host = Argv[4]; + user_cmnd = Argv[5]; + + NewArgv = &Argv[5]; + NewArgc = Argc - 5; + } else if (Argc >= 4) { + pw.pw_name = Argv[1]; + user_host = Argv[2]; + user_cmnd = Argv[3]; + + NewArgv = &Argv[3]; + NewArgc = Argc - 3; + } else { + (void) fprintf(stderr, + "usage: %s [-u user] <user> <host> <command> [args]\n", Argv[0]); + exit(1); + } + + sudo_user.pw = &pw; /* user_name needs to be defined */ + + if ((p = strchr(user_host, '.'))) { + *p = '\0'; + user_shost = estrdup(user_host); + *p = '.'; + } else { + user_shost = user_host; + } + + /* Fill in cmnd_args from NewArgv. */ + if (NewArgc > 1) { + size_t size; + char *to, **from; + + size = (size_t) NewArgv[NewArgc-1] + strlen(NewArgv[NewArgc-1]) - + (size_t) NewArgv[1] + 1; + user_args = (char *) emalloc(size); + for (to = user_args, from = &NewArgv[1]; *from; from++) { + *to++ = ' '; + (void) strcpy(to, *from); + to += strlen(*from); + } + } + + /* Initialize default values. */ + init_defaults(); + + /* Warn about aliases that are used before being defined. */ + pedantic = TRUE; + + /* Need to keep aliases around for dumpaliases(). */ + clearaliases = FALSE; + + /* Load ip addr/mask for each interface. */ + load_interfaces(); + + /* Allocate space for data structures in the parser. */ + init_parser(); + + if (yyparse() || parse_error) { + (void) printf("doesn't parse.\n"); + } else { + (void) printf("parses OK.\n\n"); + if (top == 0) + (void) printf("User %s not found\n", pw.pw_name); + else while (top) { + (void) printf("[%d]\n", top-1); + (void) printf("user_match : %d\n", user_matches); + (void) printf("host_match : %d\n", host_matches); + (void) printf("cmnd_match : %d\n", cmnd_matches); + (void) printf("no_passwd : %d\n", no_passwd); + (void) printf("runas_match: %d\n", runas_matches); + (void) printf("runas : %s\n", *user_runas); + top--; + } + } + + /* Dump aliases. */ + (void) printf("Matching Aliases --\n"); + dumpaliases(); + + exit(0); +} |