diff --git a/ChangeLog b/ChangeLog index a4b697a..cd934c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -117,3 +117,14 @@ Fixed a bug when setting the GID explicitly. ================== The xauth directive can now be given a target user, into whose environment the X authentication information is imported. + +07/04/05 - op 1.26 +================== +op will now read all config files in /etc/op.d with a .conf extension. This is +a clean way of adding extra commands without having to manipulate op.conf. +op.conf does not have to be present at all. Useful for dropping in op config +with other packages or when adding config to systems in bulk. Thanks to Kyle +Hyland for this idea. + +Also made error reporting a bit smarter when config files are missing or have +incorrect permissions. diff --git a/Makefile b/Makefile index 0c0da00..f40712a 100644 --- a/Makefile +++ b/Makefile @@ -3,28 +3,42 @@ # CC=gcc INC= -I. -Wall -LIBS= -ll -L/lib -lpam -lcrypt +LIBS= -ll -L/lib -lcrypt DESTDIR= PREFIX=/usr +CONFDIR= $(DESTDIR)/etc/op.d BINDIR= $(DESTDIR)$(PREFIX)/bin BINOWN= root BINGRP= bin BINMODE= 4755 -INSTALL =install -o $(BINOWN) -g $(BINGRP) -m $(BINMODE) op $(BINDIR) MANOWN= bin MANGRP= bin MANMODE= 444 MANEXT=1 MANDIR= $(DESTDIR)$(PREFIX)/share/man/man$(MANEXT) +# Command to install binary and man page +INSTALL =install -o $(BINOWN) -g $(BINGRP) -m $(BINMODE) op $(BINDIR) INSTALL-MAN =install -o $(MANOWN) -g $(MANGRP) -m $(MANMODE) op.$(MANEXT) $(MANDIR) -#GLOBALOPTS=-DDEBUG -# -# Linux 2.0.30 -# -#OPTS= -DUSE_SHADOW -g -OPTS= -DXAUTH=\"/usr/X11R6/bin/xauth\" -DUSE_PAM -DHAVE_SNPRINTF -g -LDFLAGS = -g -# + +######################### USER CONFIGURABLE SECTION ########################### +# Enable debugging +OPTS += -g -DDEBUG +LDFLAGS += -g + +# Enable PAM support +#OPTS += -DUSE_PAM +#LDFLAGS += -lpam + +# Enable shadow support (generally not used in conjunction with PAM) +OPTS += -DUSE_SHADOW + +# Enable XAUTH support +OPTS += -DXAUTH=\"/usr/X11R6/bin/xauth\" + +# We have snprintf(3) +OPTS += -DHAVE_SNPRINTF + +############################ LEGACY CONFIG #################################### # # Solaris 2.x - SunPro c compiler # @@ -74,19 +88,18 @@ OBJ = lex.o main.o atov.o $(REG) op: $(OBJ) op.list $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(LDFLAGS) $(SECURIDLIBDIR) $(OBJ) $(SECURIDLIB) $(LIBS) clean: - rm -f $(OBJ) op core* lex.c \#* *~ -op.list: op.list.in + rm -f $(OBJ) op.list op core* lex.c \#* *~ +op.list: defs.h op.list.in sed -e "s/@VERSION@/`grep VERSION defs.h | cut -d\\\" -f2`/" < op.list.in > op.list -install: install-prog install-man -install-prog: +install: op mkdir -p $(BINDIR) $(INSTALL) -install-man: mkdir -p $(MANDIR) $(INSTALL-MAN) + mkdir -p $(CONFDIR) pkg: op (umask 022; mkdir -p pkg/usr/bin pkg/usr/share/man/man1; mv op pkg/usr/bin; cp op.1 pkg/usr/share/man/man1; strip pkg/usr/bin/op; chown -R root:root pkg; chmod 4755 pkg/usr/bin/op; chmod 644 pkg/usr/share/man/man1/op.1) dist: clean - (V=`grep VERSION defs.h | cut -d\" -f2`; rm -rf pkg; rm -f op-$$V.tar.gz; cd .. && mv op op-$$V && tar --exclude '.*.swp' --exclude '.svn' -czv -f op-$$V.tar.gz op-$$V && mv op-$$V op && mv op-$$V.tar.gz op) + (V=`grep VERSION defs.h | cut -d\" -f2`; rm -rf pkg; rm -f op-$$V.tar.gz; cd .. && mv op op-$$V && tar --exclude 'op.list' --exclude '.*.swp' --exclude '.svn' -czv -f op-$$V.tar.gz op-$$V && mv op-$$V op && mv op-$$V.tar.gz op) diff --git a/defs.h b/defs.h index 30df864..bea8bef 100644 --- a/defs.h +++ b/defs.h @@ -31,12 +31,14 @@ void fatal(int logit, const char *format, ...); int logger(unsigned flags, const char *format, ...); int ReadFile(char *file); +int ReadDir(char *dir); int CountArgs(cmd_t *cmd); int atov(char *str, int type); #define MAXSTRLEN 2048 #define OP_ACCESS "/etc/op.conf" -#define VERSION "1.25" +#define OP_ACCESS_DIR "/etc/op.d" +#define VERSION "1.26" #define VAR_EXPAND_LEN 8192 #define VAR_NAME_LEN 64 diff --git a/lex.l b/lex.l index 6f45b4a..e28f57c 100644 --- a/lex.l +++ b/lex.l @@ -13,6 +13,7 @@ #include #include #include +#include #include "defs.h" static cmd_t *newcmd(); @@ -267,19 +268,20 @@ char *file; struct stat statbuf; FILE *fd; - if ((stat(file, &statbuf) < 0) || - (statbuf.st_uid != 0) || /* Owned by root */ - ((statbuf.st_mode & 0077) != 0)) { /* SD - no perm */ - fatal(1, "Permission problems on %s", file); - } - if ((fd = fopen(file,"r")) == NULL) { - fatal(1, "Couldn't open %s", file); + if ((stat(file, &statbuf) < 0)) + return 0; + if ((statbuf.st_uid != 0) || /* Owned by root */ + ((statbuf.st_mode & 0077) != 0)) { /* SD - no perm */ + logger(LOG_ERR, "Permission problems on %s", file); + return 0; } + if ((fd = fopen(file,"r")) == NULL) + return 0; yyin = fd; yylex(); - return 0; + return 1; } int CountArgs(cmd) diff --git a/main.c b/main.c index b0b7e91..3804ea1 100644 --- a/main.c +++ b/main.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "defs.h" #include "regexp.h" @@ -88,6 +89,35 @@ void Usage() gargv[0], gargv[0]); } +int ReadDir( char *dir ) +{ +DIR *d; + + if ((d = opendir(dir)) != NULL) + { + struct dirent *f; + int successes = 0; + + while ((f = readdir(d))) + { + char full_path[PATH_MAX]; + + if (f->d_name[0] == '.' || (strlen(f->d_name) > 5 && strcmp(f->d_name + strlen(f->d_name) - 5, ".conf"))) + continue; +#ifdef HAVE_SNPRINTF + snprintf(full_path, PATH_MAX, "%s/%s", OP_ACCESS_DIR, f->d_name); +#else + sprintf(full_path, "%s/%s", OP_ACCESS_DIR, f->d_name); +#endif + if (ReadFile(full_path)) + ++successes; + } + closedir(d); + return successes; + } + return 0; +} + int main(argc, argv) int argc; char **argv; @@ -96,7 +126,7 @@ char **argv; char user[MAXSTRLEN]; cmd_t *cmd, *def, *new; struct passwd *pw; - int hflag = 0; + int hflag = 0, read_conf = 0, read_conf_dir = 0; char *uptr = NULL; char cmd_s[MAXSTRLEN]; char *pcmd_s; @@ -160,7 +190,11 @@ char **argv; if (openlog("op", LOG_PID | LOG_CONS, LOG_AUTH) < 0) fatal(0, "openlog failed"); #endif - ReadFile( OP_ACCESS ); + read_conf = ReadFile( OP_ACCESS ); + read_conf_dir = ReadDir( OP_ACCESS_DIR ); + + if (!read_conf && !read_conf_dir) + fatal(1, "Could not open %s or any configuration files in %s", OP_ACCESS, OP_ACCESS_DIR); if (hflag) { if (uptr != NULL) { diff --git a/op.1 b/op.1 index 7c1a62a..2402f5d 100644 --- a/op.1 +++ b/op.1 @@ -15,17 +15,29 @@ operations without having to give them full superuser privileges. Different sets of users may access different operations, and the security-related aspects of environment of each operation can be carefully controlled. +.PP +Configuration entries are read from +.B /etc/op.conf +and all files in +.B /etc/op.d +with the extension +.B .conf. +Files must be owned by +.I root +and not have +.I group +or +.I other +permissions set. .PP -The fields of the entries in -.I op.conf -are separated by white space. Each entry may span several lines and -continues until the next alphanumeric string is found at the beginning of -a lines (which is taken to be the next +The fields of the entries in the configuration files are separated by white +space. Each entry may span several lines and continues until the next +alphanumeric string is found at the beginning of a lines (which is taken to be +the next .I mnemonic or variable definition, and thus the beginning of a new entry). Comments may be embedded -beginning with a # character. Each entry in op -.I op.conf -has the following form: +beginning with a # character. Each entry in the configuration files has the +following form: .RS .DT .PP @@ -314,10 +326,14 @@ inetd /bin/sh -c ' .PP .SH FILES -.DT -/etc/op.conf access control description +.TP +.B /etc/op.conf +Access control description file. +.TP +.B /etc/op.d/*.conf +Access control description files. .SH "SEE ALSO" -su(1), chroot(2), egrep(1) +sudo(1), su(1), chroot(2), egrep(1) .SH CREDIT .B "Op: A flexible Tool for Restricted Superuser Access", originally by @@ -330,7 +346,7 @@ Further changes by .I "Alec Thomas". . .SH BUG REPORTS TO -alec@korn.ch +alec@swapoff.org .SH COPYRIGHTS \fB\(co\fR\s12 Copyright 1991 by David Koblas \fB\(co\fR\s12 Copyright 2002 by Alec Thomas diff --git a/op.conf b/op.conf index ca105b6..c02794f 100644 --- a/op.conf +++ b/op.conf @@ -1,83 +1,18 @@ -# Host definitions -SWAPOFF_ORG=(blink|iris|seraph|cavern) -FAILOVER_ORG=(thoth|ash|oak|widow) -SELLICK_ID_AU=(beholder|kraken) -ASN=(SWAPOFF_ORG|FAILOVER_ORG|SELLICK_ID_AU) - -# User definitions -SWAPOFF_ORG_USERS=(athomas) -SELLICK_ID_AU_USERS=(psellick) -FAILOVER_ORG_USERS=(dcooper) -ASN_USERS=(SWAPOFF_ORG_USERS|SELLICK_ID_AU_USERS|FAILOVER_ORG_USERS) - -# ACL definitions -FAILOVER_ORG_ACL=FAILOVER_ORG_USERS@FAILOVER_ORG -SWAPOFF_ORG_ACL=SWAPOFF_ORG_USERS@SWAPOFF_ORG -SELLICK_ID_AU_ACL=SELLICK_ID_AU_USERS@SELLICK_ID_AU -ASN_ACL=root|FAILOVER_ORG_ACL|SWAPOFF_ORG_ACL|SELLICK_ID_AU_ACL - -# Group definitions -ASN_GROUPS=asn - -# Actions requiring authentication -shell /bin/su -; users=ASN_ACL environment password -sh /bin/su -; users=ASN_ACL environment password -vi /usr/bin/vi $*; users=ASN_ACL password -reboot /sbin/reboot; users=ASN_ACL environment password - -# Password-less commands -shutdown /sbin/shutdown -h $1; users=ASN_ACL environment - $1=now|[0-1]?[0-9]:[0-9][0-9]|2[0-3]:[0-5][0-9]|\+[0-9]+ -ethereal /usr/bin/ethereal $*; users=ASN_ACL environment -nomad /usr/bin/nomad $*; users=ASN_ACL environment -tcpdump /usr/sbin/tcpdump $*; users=ASN_ACL environment -nmap /usr/bin/nmap $*; users=ASN_ACL environment -updatedb /usr/bin/updatedb; users=ASN_ACL environment -makewhatis /bin/sh -c ' - /usr/sbin/makewhatis & - echo makewhatis running in the background - '; - users=ASN_ACL environment -cdrom /sbin/mount /mnt/cdrom; users=ASN_ACL -eject /usr/bin/eject; users=ASN_ACL -nmap /usr/bin/nmap $*; users=ASN_ACL environment -grip /bin/sh -c '/usr/bin/nice -n 19 /usr/bin/grip &'; - users=ASN_ACL - user=athomas - group=audio - umask=007 - environment - -# Cavern local commands -gtkam /usr/bin/gtkam; users=athomas environment $DISPLAY $GTKRC=/home/athomas/.gtkrc -drip /usr/bin/drip; users=athomas environment $DISPLAY $GTKRC=/home/athomas/.gtkrc -evms /bin/sh -c 'PATH=/sbin:/usr/sbin:$PATH /sbin/evmsgui &'; users=athomas environment $DISPLAY $GTKRC=/home/athomas/.gtkrc -xine /usr/bin/xine; users=athomas environment $DISPLAY - -# An example of how to use -mount /bin/sh -c ' - case $1 in - cdrom) /bin/mount /mnt/cdrom ;; - dvd) /bin/mount -o ro /dev/dvd /mnt/dvd ;; - burner) /bin/mount -o ro /dev/burner /mnt/burner ;; - *) echo "op: you do not have permission to mount \'$1\'" ;; - esac - '; - users=athomas environment - -apache /usr/sbin/apachectl $1; - users=athomas - environment - $1=start|stop|restart - -umount /bin/sh -c ' - case $1 in - cdrom) /bin/umount /mnt/cdrom ;; - dvd) /bin/umount /mnt/dvd ;; - burner) /bin/umount /mnt/burner ;; - *) echo "op: you do not have permission to unmount \'$1\'" ;; - esac - '; - users=athomas environment - -tail /usr/bin/tail -f $1; users=athomas +# +# A simple example config for op(1). See the man page for more information or +# op.conf.complex for a complex multi-user/multi-system configuration. +# + +## List of privileged users +#PRIVILEGED= +# +#shell /bin/su -; +# users=PRIVILEGED +# password +# environment +# +#shutdown /sbin/shutdown -h now; +# users=PRIVILEGED +# +#reboot /sbin/shutdown -h now; +# users=PRIVILEGED diff --git a/op.conf.complex b/op.conf.complex new file mode 100644 index 0000000..ca105b6 --- /dev/null +++ b/op.conf.complex @@ -0,0 +1,83 @@ +# Host definitions +SWAPOFF_ORG=(blink|iris|seraph|cavern) +FAILOVER_ORG=(thoth|ash|oak|widow) +SELLICK_ID_AU=(beholder|kraken) +ASN=(SWAPOFF_ORG|FAILOVER_ORG|SELLICK_ID_AU) + +# User definitions +SWAPOFF_ORG_USERS=(athomas) +SELLICK_ID_AU_USERS=(psellick) +FAILOVER_ORG_USERS=(dcooper) +ASN_USERS=(SWAPOFF_ORG_USERS|SELLICK_ID_AU_USERS|FAILOVER_ORG_USERS) + +# ACL definitions +FAILOVER_ORG_ACL=FAILOVER_ORG_USERS@FAILOVER_ORG +SWAPOFF_ORG_ACL=SWAPOFF_ORG_USERS@SWAPOFF_ORG +SELLICK_ID_AU_ACL=SELLICK_ID_AU_USERS@SELLICK_ID_AU +ASN_ACL=root|FAILOVER_ORG_ACL|SWAPOFF_ORG_ACL|SELLICK_ID_AU_ACL + +# Group definitions +ASN_GROUPS=asn + +# Actions requiring authentication +shell /bin/su -; users=ASN_ACL environment password +sh /bin/su -; users=ASN_ACL environment password +vi /usr/bin/vi $*; users=ASN_ACL password +reboot /sbin/reboot; users=ASN_ACL environment password + +# Password-less commands +shutdown /sbin/shutdown -h $1; users=ASN_ACL environment + $1=now|[0-1]?[0-9]:[0-9][0-9]|2[0-3]:[0-5][0-9]|\+[0-9]+ +ethereal /usr/bin/ethereal $*; users=ASN_ACL environment +nomad /usr/bin/nomad $*; users=ASN_ACL environment +tcpdump /usr/sbin/tcpdump $*; users=ASN_ACL environment +nmap /usr/bin/nmap $*; users=ASN_ACL environment +updatedb /usr/bin/updatedb; users=ASN_ACL environment +makewhatis /bin/sh -c ' + /usr/sbin/makewhatis & + echo makewhatis running in the background + '; + users=ASN_ACL environment +cdrom /sbin/mount /mnt/cdrom; users=ASN_ACL +eject /usr/bin/eject; users=ASN_ACL +nmap /usr/bin/nmap $*; users=ASN_ACL environment +grip /bin/sh -c '/usr/bin/nice -n 19 /usr/bin/grip &'; + users=ASN_ACL + user=athomas + group=audio + umask=007 + environment + +# Cavern local commands +gtkam /usr/bin/gtkam; users=athomas environment $DISPLAY $GTKRC=/home/athomas/.gtkrc +drip /usr/bin/drip; users=athomas environment $DISPLAY $GTKRC=/home/athomas/.gtkrc +evms /bin/sh -c 'PATH=/sbin:/usr/sbin:$PATH /sbin/evmsgui &'; users=athomas environment $DISPLAY $GTKRC=/home/athomas/.gtkrc +xine /usr/bin/xine; users=athomas environment $DISPLAY + +# An example of how to use +mount /bin/sh -c ' + case $1 in + cdrom) /bin/mount /mnt/cdrom ;; + dvd) /bin/mount -o ro /dev/dvd /mnt/dvd ;; + burner) /bin/mount -o ro /dev/burner /mnt/burner ;; + *) echo "op: you do not have permission to mount \'$1\'" ;; + esac + '; + users=athomas environment + +apache /usr/sbin/apachectl $1; + users=athomas + environment + $1=start|stop|restart + +umount /bin/sh -c ' + case $1 in + cdrom) /bin/umount /mnt/cdrom ;; + dvd) /bin/umount /mnt/dvd ;; + burner) /bin/umount /mnt/burner ;; + *) echo "op: you do not have permission to unmount \'$1\'" ;; + esac + '; + users=athomas environment + +tail /usr/bin/tail -f $1; users=athomas diff --git a/op.list b/op.list deleted file mode 100644 index 2ead6eb..0000000 --- a/op.list +++ /dev/null @@ -1,24 +0,0 @@ -%readme README -%version 1.24 -%product Operator Escalation -%copyright David Koblas, Howard Owen, Alec Thomas -%license COPYING -%vendor N/A - - -# Directories... -$prefix=/usr -$exec_prefix=${prefix} -$bindir=${exec_prefix}/bin -$mandir=${prefix}/share/man -$datadir=${prefix}/share - -d 755 root sys ${bindir} - -f 4755 root sys ${bindir}/op op - -d 755 root sys /etc - -c 600 root sys /etc/op.conf op.conf - -d 755 root sys ${mandir} - -d 755 root sys ${mandir}/man1 - -f 644 root sys ${mandir}/man1/op.1 op.1 diff --git a/op.list.in b/op.list.in index 4d74820..440ae2d 100644 --- a/op.list.in +++ b/op.list.in @@ -17,6 +17,7 @@ d 755 root sys ${bindir} - f 4755 root sys ${bindir}/op op d 755 root sys /etc - +d 755 root sys /etc/op.d - c 600 root sys /etc/op.conf op.conf d 755 root sys ${mandir} -