Общие подкаталоги: sudo-1.6.7p2.orig/auth и sudo-1.6.7p2/auth diff -upk.orig sudo-1.6.7p2.orig/configure sudo-1.6.7p2/configure --- sudo-1.6.7p2.orig/configure 2003-04-02 23:03:19 +0400 +++ sudo-1.6.7p2/configure 2003-04-09 16:30:12 +0400 @@ -1413,6 +1413,7 @@ PROGS="sudo visudo" test -n "$MANTYPE" || MANTYPE="man" test -n "$mansrcdir" || mansrcdir="." test -n "$SUDOERS_MODE" || SUDOERS_MODE=0440 +test -n "$SUDOERS_DIR_MODE" || SUDOERS_DIR_MODE=0700 test -n "$SUDOERS_UID" || SUDOERS_UID=0 test -n "$SUDOERS_GID" || SUDOERS_GID=0 DEV="#" @@ -14627,6 +14628,7 @@ s,@AUTH_OBJS@,$AUTH_OBJS,;t t s,@MANTYPE@,$MANTYPE,;t t s,@MAN_POSTINSTALL@,$MAN_POSTINSTALL,;t t s,@SUDOERS_MODE@,$SUDOERS_MODE,;t t +s,@SUDOERS_DIR_MODE@,$SUDOERS_DIR_MODE,;t t s,@SUDOERS_UID@,$SUDOERS_UID,;t t s,@SUDOERS_GID@,$SUDOERS_GID,;t t s,@DEV@,$DEV,;t t diff -upk.orig sudo-1.6.7p2.orig/configure.in sudo-1.6.7p2/configure.in --- sudo-1.6.7p2.orig/configure.in 2003-04-09 16:29:49 +0400 +++ sudo-1.6.7p2/configure.in 2003-04-09 16:30:12 +0400 @@ -27,6 +27,7 @@ AC_SUBST(AUTH_OBJS)dnl AC_SUBST(MANTYPE)dnl AC_SUBST(MAN_POSTINSTALL)dnl AC_SUBST(SUDOERS_MODE)dnl +AC_SUBST(SUDOERS_DIR_MODE)dnl AC_SUBST(SUDOERS_UID)dnl AC_SUBST(SUDOERS_GID)dnl AC_SUBST(DEV) @@ -94,6 +95,7 @@ PROGS="sudo visudo" test -n "$MANTYPE" || MANTYPE="man" test -n "$mansrcdir" || mansrcdir="." test -n "$SUDOERS_MODE" || SUDOERS_MODE=0440 +test -n "$SUDOERS_DIR_MODE" || SUDOERS_DIR_MODE=0700 test -n "$SUDOERS_UID" || SUDOERS_UID=0 test -n "$SUDOERS_GID" || SUDOERS_GID=0 DEV="" @@ -660,6 +662,20 @@ AC_ARG_WITH(sudoers-mode, [ --with-sudo ;; 0*) SUDOERS_MODE=$with_sudoers_mode ;; + *) AC_MSG_ERROR(["you must use a numeric uid, not a name."]) + ;; +esac]) + +AC_ARG_WITH(sudoers-dir-mode, [ --with-sudoers-dir-mode mode of sudoers directory (defaults to 0700)], +[case $with_sudoers_dir_mode in + yes) AC_MSG_ERROR(["must give --with-sudoers-dir-mode an argument."]) + ;; + no) AC_MSG_ERROR(["--without-sudoers-dir-mode not supported."]) + ;; + [[1-9]]*) SUDOERS_DIR_MODE=0${with_sudoers_dir_mode} + ;; + 0*) SUDOERS_DIR_MODE=$with_sudoers_dir_mode + ;; *) AC_MSG_ERROR(["you must use an octal mode, not a name."]) ;; esac]) Общие подкаталоги: sudo-1.6.7p2.orig/emul и sudo-1.6.7p2/emul diff -upk.orig sudo-1.6.7p2.orig/Makefile.in sudo-1.6.7p2/Makefile.in --- sudo-1.6.7p2.orig/Makefile.in 2003-04-02 23:05:47 +0400 +++ sudo-1.6.7p2/Makefile.in 2003-04-09 16:30:12 +0400 @@ -99,9 +99,10 @@ install_gid = 0 sudoers_uid = @SUDOERS_UID@ sudoers_gid = @SUDOERS_GID@ sudoers_mode = @SUDOERS_MODE@ +sudoers_dir_mode = @SUDOERS_DIR_MODE@ # Pass in paths and uid/gid + OS dependent defined -DEFS = @OSDEFS@ -D_PATH_SUDOERS=\"$(sudoersdir)/sudoers\" -D_PATH_SUDOERS_TMP=\"$(sudoersdir)/sudoers.tmp\" -DSUDOERS_UID=$(sudoers_uid) -DSUDOERS_GID=$(sudoers_gid) -DSUDOERS_MODE=$(sudoers_mode) +DEFS = @OSDEFS@ -D_PATH_SUDOERS=\"$(sudoersdir)/sudoers\" -D_PATH_SUDOERS_TMP=\"$(sudoersdir)/sudoers.tmp\" -DSUDOERS_UID=$(sudoers_uid) -DSUDOERS_GID=$(sudoers_gid) -DSUDOERS_MODE=$(sudoers_mode) -DSUDOERS_DIR_MODE=$(sudoers_dir_mode) #### End of system configuration section. #### diff -upk.orig sudo-1.6.7p2.orig/parse.c sudo-1.6.7p2/parse.c --- sudo-1.6.7p2.orig/parse.c 2003-03-15 23:31:02 +0300 +++ sudo-1.6.7p2/parse.c 2003-04-09 16:35:40 +0400 @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -104,40 +105,129 @@ static const char rcsid[] = "$Sudo: pars */ int parse_error = FALSE; extern int keepall; +extern int errorlineno; extern FILE *yyin, *yyout; +static FILE *sudoers_fp = NULL; /* * Prototypes */ static int has_meta __P((char *)); void init_parser __P((void)); + void reset_parser __P((void)); + +static int +skip_sudoers(const char *s) +{ + char allowed[] = "_-"; + + for ( ; *s; ++s ) { + if (!isalnum(*s) && !strchr(allowed, *s)) + return 1; + } + + return 0; +} /* - * Look up the user in the sudoers file and check to see if they are - * allowed to run the specified command on this host as the target user. + * Sanity check sudoers mode/owner/type. + * Leaves a file pointer to the sudoers file open in ``sudoers_fp''. */ -int -sudoers_lookup(pwflag) - int pwflag; +static void +check_sudoers(const char *path) { - int error; - int pwcheck; - int nopass; + struct stat statbuf; + int rootstat, i; + char c; + + /* Need to be root to fix permissions. */ + set_perms(PERM_ROOT); + + /* + * Fix the mode and group on sudoers file from old default. + * Only works if filesystem is readable/writable by root. + */ + if ((rootstat = stat_sudoers(path, &statbuf)) == 0 && + SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 && + (statbuf.st_mode & 07777) == 0400) { + + if (chmod(path, SUDOERS_MODE) == 0) { + (void) fprintf(stderr, "%s: fixed mode on %s\n", + __progname, path); + statbuf.st_mode |= SUDOERS_MODE; + if (statbuf.st_gid != SUDOERS_GID) { + if (!chown(path,(uid_t) -1,SUDOERS_GID)) { + (void) fprintf(stderr, "%s: set group on %s\n", + __progname, path); + statbuf.st_gid = SUDOERS_GID; + } else { + (void) fprintf(stderr,"%s: Unable to set group on %s: %s\n", + __progname, path, strerror(errno)); + } + } + } else { + (void) fprintf(stderr, "%s: Unable to fix mode on %s: %s\n", + __progname, path, strerror(errno)); + } + } - /* Become sudoers file owner */ + /* + * Sanity checks on sudoers file. Must be done as sudoers + * file owner. We already did a stat as root, so use that + * data if we can't stat as sudoers file owner. + */ set_perms(PERM_SUDOERS); - /* We opened _PATH_SUDOERS in check_sudoers() so just rewind it. */ + if (rootstat != 0 && stat_sudoers(path, &statbuf) != 0) + log_error(USE_ERRNO, "can't stat %s", path); + else if (!S_ISREG(statbuf.st_mode)) + log_error(0, "%s is not a regular file", path); + else if (statbuf.st_size == 0) + log_error(0, "%s is zero length", path); + else if ((statbuf.st_mode & 07777) != SUDOERS_MODE) + log_error(0, "%s is mode 0%o, should be 0%o", path, + (statbuf.st_mode & 07777), SUDOERS_MODE); + else if (statbuf.st_uid != SUDOERS_UID) + log_error(0, "%s is owned by uid %ld, should be %d", path, + (long) statbuf.st_uid, SUDOERS_UID); + else if (statbuf.st_gid != SUDOERS_GID) + log_error(0, "%s is owned by gid %ld, should be %d", path, + (long) statbuf.st_gid, SUDOERS_GID); + else { + /* Solaris sometimes returns EAGAIN so try 10 times */ + for (i = 0; i < 10 ; i++) { + errno = 0; + if ((sudoers_fp = fopen(path, "r")) == NULL || + fread(&c, sizeof(c), 1, sudoers_fp) != 1) { + sudoers_fp = NULL; + if (errno != EAGAIN && errno != EWOULDBLOCK) + break; + } else + break; + sleep(1); + } + if (sudoers_fp == NULL) + log_error(USE_ERRNO, "can't open %s", path); + } +} + +/* + * Load sudoers file. + */ +static void +load_sudoers(const char *path) +{ + int error; + + check_sudoers(path); /* check mode/owner on _PATH_SUDOERS */ + + /* We opened ``path'' in check_sudoers() so just rewind it. */ rewind(sudoers_fp); yyin = sudoers_fp; yyout = stdout; - /* Allocate space for data structures in the parser. */ - init_parser(); - - /* If pwcheck *could* be PWCHECK_ALL or PWCHECK_ANY, keep more state. */ - if (pwflag > 0) - keepall = TRUE; + /* Reset data structures in the parser. */ + reset_parser(); /* Need to be root while stat'ing things in the parser. */ set_perms(PERM_ROOT); @@ -148,7 +238,93 @@ sudoers_lookup(pwflag) sudoers_fp = NULL; if (error || parse_error) - return(VALIDATE_ERROR); + log_error(0, "parse error in %s near line %d", path, errorlineno); +} + +/* + * Load all sudoers files. + */ +static void +load_all_sudoers(void) +{ + struct stat statbuf; + + /* check mode/owner and parse */ + load_sudoers(_PATH_SUDOERS); + + /* + * Sanity checks on sudoers file. Must be done as sudoers + * file owner. We already did a stat as root, so use that + * data if we can't stat as sudoers file owner. + */ + set_perms(PERM_SUDOERS); + + if (stat_sudoers(_PATH_SUDOERS_DIR, &statbuf) != 0) { + if (ENOENT == errno) + return; /* do not fail if sudoers directory is missing */ + log_error(USE_ERRNO, "can't stat %s", _PATH_SUDOERS_DIR); + } + else if (!S_ISDIR(statbuf.st_mode)) + log_error(0, "%s is not a directory", _PATH_SUDOERS_DIR); + else if ((statbuf.st_mode & 07777) != SUDOERS_DIR_MODE) + log_error(0, "%s is mode 0%o, should be 0%o", _PATH_SUDOERS_DIR, + (statbuf.st_mode & 07777), SUDOERS_DIR_MODE); + else if (statbuf.st_uid != SUDOERS_UID) + log_error(0, "%s is owned by uid %lu, should be %lu", _PATH_SUDOERS_DIR, + (unsigned long) statbuf.st_uid, SUDOERS_UID); + else if (statbuf.st_gid != SUDOERS_GID) + log_error(0, "%s is owned by gid %lu, should be %lu", _PATH_SUDOERS_DIR, + (unsigned long) statbuf.st_gid, SUDOERS_GID); + else { + DIR *dirp; + struct dirent *dent; + unsigned dir_len; + + if (!(dirp = opendir(_PATH_SUDOERS_DIR))) + log_error(USE_ERRNO, "can't open %s", _PATH_SUDOERS_DIR); + + dir_len = strlen(_PATH_SUDOERS_DIR) + 1; + while ((dent = readdir(dirp))) { + char *fname; + + if (skip_sudoers(dent->d_name)) + continue; + + easprintf(&fname, "%s/%s", _PATH_SUDOERS_DIR, dent->d_name); + load_sudoers(fname); + free(fname); + + /* Become sudoers file owner again */ + set_perms(PERM_SUDOERS); + } + + closedir( dirp ); + } + + set_perms(PERM_ROOT); /* change back to root */ +} + +/* + * Look up the user in the sudoers file and check to see if they are + * allowed to run the specified command on this host as the target user. + */ +int +sudoers_lookup(pwflag) + int pwflag; +{ + int error = 0; + int pwcheck; + int nopass; + + /* Allocate space for data structures in the parser. */ + init_parser(); + + /* If pwcheck *could* be PWCHECK_ALL or PWCHECK_ANY, keep more state. */ + if (pwflag > 0) + keepall = TRUE; + + /* check mode/owner and parse all sudoers files */ + load_all_sudoers(); /* * The pw options may have changed during sudoers parse so we diff -upk.orig sudo-1.6.7p2.orig/parse.yacc sudo-1.6.7p2/parse.yacc --- sudo-1.6.7p2.orig/parse.yacc 2003-03-15 23:31:02 +0300 +++ sudo-1.6.7p2/parse.yacc 2003-04-09 16:30:12 +0400 @@ -1211,3 +1211,15 @@ init_parser() if (printmatches == TRUE) expand_match_list(); } + +/* + * Resets data structures used by a previous parser run. + */ +void +reset_parser() +{ + /* Reset data structures if we run the parser more than once. */ + parse_error = FALSE; + errorlineno = -1; + sudolineno = 1; +} diff -upk.orig sudo-1.6.7p2.orig/pathnames.h.in sudo-1.6.7p2/pathnames.h.in --- sudo-1.6.7p2.orig/pathnames.h.in 2001-12-14 22:54:56 +0300 +++ sudo-1.6.7p2/pathnames.h.in 2003-04-09 16:30:12 +0400 @@ -71,6 +71,13 @@ #endif /* _PATH_SUDOERS_TMP */ /* + * NOTE: _PATH_SUDOERS_DIR is usually overriden by the Makefile. + */ +#ifndef _PATH_SUDOERS_DIR +#define _PATH_SUDOERS_DIR "/etc/sudo.d" +#endif /* _PATH_SUDOERS_DIR */ + +/* * The following paths are controlled via the configure script. */ diff -upk.orig sudo-1.6.7p2.orig/sudo.c sudo-1.6.7p2/sudo.c --- sudo-1.6.7p2.orig/sudo.c 2003-04-09 16:29:49 +0400 +++ sudo-1.6.7p2/sudo.c 2003-04-09 16:31:41 +0400 @@ -106,7 +106,6 @@ static const char rcsid[] = "$Sudo: sudo */ static int init_vars __P((int)); static int parse_args __P((void)); -static void check_sudoers __P((void)); static void initial_setup __P((void)); static void set_loginclass __P((struct passwd *)); static void usage __P((int)); @@ -127,12 +126,10 @@ int NewArgc = 0; char **NewArgv = NULL; struct sudo_user sudo_user; struct passwd *auth_pw; -FILE *sudoers_fp = NULL; struct interface *interfaces; int num_interfaces; int tgetpass_flags; uid_t timestamp_uid; -extern int errorlineno; #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) static struct rlimit corelimit; #endif /* RLIMIT_CORE */ @@ -257,8 +254,6 @@ main(argc, argv, envp) cmnd_status = init_vars(sudo_mode); - check_sudoers(); /* check mode/owner on _PATH_SUDOERS */ - /* Validate the user but don't search for pseudo-commands. */ validated = sudoers_lookup(pwflag); @@ -317,10 +312,6 @@ main(argc, argv, envp) exit(0); } - if (validated & VALIDATE_ERROR) - log_error(0, "parse error in %s near line %d", _PATH_SUDOERS, - errorlineno); - /* Is root even allowed to run sudo? */ if (user_uid == 0 && !def_flag(I_ROOT_SUDO)) { (void) fprintf(stderr, @@ -792,87 +783,6 @@ parse_args() } /* - * Sanity check sudoers mode/owner/type. - * Leaves a file pointer to the sudoers file open in ``fp''. - */ -static void -check_sudoers() -{ - struct stat statbuf; - int rootstat, i; - char c; - - /* - * Fix the mode and group on sudoers file from old default. - * Only works if filesystem is readable/writable by root. - */ - if ((rootstat = stat_sudoers(_PATH_SUDOERS, &statbuf)) == 0 && - SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 && - (statbuf.st_mode & 0007777) == 0400) { - - if (chmod(_PATH_SUDOERS, SUDOERS_MODE) == 0) { - (void) fprintf(stderr, "%s: fixed mode on %s\n", - __progname, _PATH_SUDOERS); - statbuf.st_mode |= SUDOERS_MODE; - if (statbuf.st_gid != SUDOERS_GID) { - if (!chown(_PATH_SUDOERS,(uid_t) -1,SUDOERS_GID)) { - (void) fprintf(stderr, "%s: set group on %s\n", - __progname, _PATH_SUDOERS); - statbuf.st_gid = SUDOERS_GID; - } else { - (void) fprintf(stderr,"%s: Unable to set group on %s: %s\n", - __progname, _PATH_SUDOERS, strerror(errno)); - } - } - } else { - (void) fprintf(stderr, "%s: Unable to fix mode on %s: %s\n", - __progname, _PATH_SUDOERS, strerror(errno)); - } - } - - /* - * Sanity checks on sudoers file. Must be done as sudoers - * file owner. We already did a stat as root, so use that - * data if we can't stat as sudoers file owner. - */ - set_perms(PERM_SUDOERS); - - if (rootstat != 0 && stat_sudoers(_PATH_SUDOERS, &statbuf) != 0) - log_error(USE_ERRNO, "can't stat %s", _PATH_SUDOERS); - else if (!S_ISREG(statbuf.st_mode)) - log_error(0, "%s is not a regular file", _PATH_SUDOERS); - else if (statbuf.st_size == 0) - log_error(0, "%s is zero length", _PATH_SUDOERS); - else if ((statbuf.st_mode & 07777) != SUDOERS_MODE) - log_error(0, "%s is mode 0%o, should be 0%o", _PATH_SUDOERS, - (statbuf.st_mode & 07777), SUDOERS_MODE); - else if (statbuf.st_uid != SUDOERS_UID) - log_error(0, "%s is owned by uid %lu, should be %lu", _PATH_SUDOERS, - (unsigned long) statbuf.st_uid, SUDOERS_UID); - else if (statbuf.st_gid != SUDOERS_GID) - log_error(0, "%s is owned by gid %lu, should be %lu", _PATH_SUDOERS, - (unsigned long) statbuf.st_gid, SUDOERS_GID); - else { - /* Solaris sometimes returns EAGAIN so try 10 times */ - for (i = 0; i < 10 ; i++) { - errno = 0; - if ((sudoers_fp = fopen(_PATH_SUDOERS, "r")) == NULL || - fread(&c, sizeof(c), 1, sudoers_fp) != 1) { - sudoers_fp = NULL; - if (errno != EAGAIN && errno != EWOULDBLOCK) - break; - } else - break; - sleep(1); - } - if (sudoers_fp == NULL) - log_error(USE_ERRNO, "can't open %s", _PATH_SUDOERS); - } - - set_perms(PERM_ROOT); /* change back to root */ -} - -/* * Close all open files (except std*) and turn off core dumps. * Also sets the set_perms() pointer to the correct function. */ diff -upk.orig sudo-1.6.7p2.orig/sudoers.pod sudo-1.6.7p2/sudoers.pod --- sudo-1.6.7p2.orig/sudoers.pod 2003-03-15 23:31:02 +0300 +++ sudo-1.6.7p2/sudoers.pod 2003-04-09 16:30:12 +0400 @@ -1078,7 +1078,8 @@ I. =head1 FILES - @sysconfdir@/sudoers List of who can run what + @sysconfdir@/sudoers, + @sysconfdir@/sudo.d/* List of who can run what /etc/group Local groups file /etc/netgroup List of network groups diff -upk.orig sudo-1.6.7p2.orig/sudo.h sudo-1.6.7p2/sudo.h --- sudo-1.6.7p2.orig/sudo.h 2003-04-09 16:29:49 +0400 +++ sudo-1.6.7p2/sudo.h 2003-04-09 16:30:12 +0400 @@ -242,7 +242,6 @@ extern struct passwd *auth_pw; extern int Argc; extern char **Argv; -extern FILE *sudoers_fp; extern int tgetpass_flags; extern uid_t timestamp_uid; diff -upk.orig sudo-1.6.7p2.orig/sudo.pod sudo-1.6.7p2/sudo.pod --- sudo-1.6.7p2.orig/sudo.pod 2003-03-15 23:31:02 +0300 +++ sudo-1.6.7p2/sudo.pod 2003-04-09 16:30:12 +0400 @@ -49,7 +49,7 @@ B B<-V> | B<-h> | B<-l> | B<-L> | =head1 DESCRIPTION B allows a permitted user to execute a I as the -superuser or another user, as specified in the I file. +superuser or another user, as specified in the I files. The real and effective uid and gid are set to match those of the target user as specified in the passwd file (the group vector is also initialized when the target user is not root). By default, @@ -60,15 +60,16 @@ user may then use sudo without a passwor time (C<@timeout@> minutes unless overridden in I). B determines who is an authorized user by consulting the file -F<@sysconfdir@/sudoers>. By giving B the B<-v> flag a user +F<@sysconfdir@/sudoers> and all files with valid names from +F<@sysconfdir@/sudo.d> directory. By giving B the B<-v> flag a user can update the time stamp without running a I The password prompt itself will also time out if the user's password is not entered within C<@password_timeout@> minutes (unless overridden via I). -If a user who is not listed in the I file tries to run a +If a user who is not listed in the I files tries to run a command via B, mail is sent to the proper authorities, as -defined at configure time or the I file (defaults to root). +defined at configure time or the I files (defaults to root). Note that the mail will not be sent if an unauthorized user tries to run sudo with the B<-l> or B<-v> flags. This allows users to determine for themselves whether or not they are allowed to use @@ -77,7 +78,7 @@ B. B can log both successful and unsuccessful attempts (as well as errors) to syslog(3), a log file, or both. By default B will log via syslog(3) but this is changeable at configure time -or via the I file. +or via the I files. =head1 OPTIONS @@ -355,7 +356,8 @@ B utilizes the following environme =head1 FILES - @sysconfdir@/sudoers List of who can run what + @sysconfdir@/sudoers, + @sysconfdir@/sudo.d/* List of who can run what @timedir@ Directory containing timestamps =head1 AUTHORS diff -upk.orig sudo-1.6.7p2.orig/visudo.pod sudo-1.6.7p2/visudo.pod --- sudo-1.6.7p2.orig/visudo.pod 2003-03-15 23:31:02 +0300 +++ sudo-1.6.7p2/visudo.pod 2003-04-09 16:30:12 +0400 @@ -157,7 +157,8 @@ was configured with the I<--with-env-edi =head1 FILES - @sysconfdir@/sudoers List of who can run what + @sysconfdir@/sudoers, + @sysconfdir@/sudo.d/* List of who can run what @sysconfdir@/sudoers.tmp Lock file for visudo =head1 AUTHOR