mrapple@quack.sac.ca.us (Nick Sayer) (10/15/90)
Posting-number: Volume 15, Issue 48 Submitted-by: mrapple@quack.sac.ca.us (Nick Sayer) Archive-name: sec/part01 [Uses syslog and is otherwise BSD-specific; however, it should not be too difficult to convert to System V. I must admit that giving each user who is permitted to use root a password that only works for that user is an improvement over the standard "su" model, and certainly over a program that was in use on ncoast some years ago. But remember that giving *anyone* other than the system administrator the ability to access root is a potential security hole; as always, consider carefully before allowing someone root access. ++bsa] I'm not quite sure what to call this, but I call it "sec." Anyway, I've had a couple requests for it, so I thought I'd pass it along. #!/bin/sh # This is a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 10/08/1990 19:39 UTC by nsayer@uop # Source directory /files/users/staff-uop/nsayer/sec # # existing files will NOT be overwritten unless -c is specified # # # # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 1315 -rw-r--r-- sec.c # 1672 -rw-r--r-- secpw.c # 737 -rw-r--r-- Makefile # 1803 -rw-r--r-- README # 796 -rw-r--r-- config.h # if test -r _shar_seq_.tmp; then echo 'Must unpack archives in sequence!' echo Please unpack part `cat _shar_seq_.tmp` next exit 1 fi # ============= sec.c ============== if test -f 'sec.c' -a X"$1" != X"-c"; then echo 'x - skipping sec.c (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting sec.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'sec.c' && /* X * X * sec.c X * X * Grudgingly give out root shells to authorized users. X * X * Usage: sec X * X */ X #include <stdio.h> #include <syslog.h> #include <strings.h> #include "config.h" X int getline(file,s) FILE *file; char *s; { X while (((*s=getc(file))!=EOF) && (*s!='\n')) s++; X if ((*s)==EOF) return 0; X *s=0; X return 1; } X extern char *crypt(); X char ckpw(b) char *b; { X char *a,*encr,input[10]; X int f; X X if (!strlen(b)) X { X printf("Null PW. Please use 'secpw' and add one.\n"); X return 1; X } X strcpy(input,getpass("Password:")); X encr=crypt(input,b); X return(!strcmp(encr,b)); } X main() { X FILE* f; X char str[80],ok=0; X X f=fopen(FILENAME,"r"); X if (f!=NULL) X { X while(getline(f,str)) X { X char b[16],*c; X c=index(str,':'); X if (c==NULL) continue; X strcpy(b,c+1); X *c='\0'; X if (!strcmp(str,getlogin())) X if (ckpw(b)) X ok=1; X } X fclose(f); X } X else X { X printf("Error reading file.\n"); X exit(1); X } X X openlog("sec",0,LOG_FACILITY); X X if (ok) X { X syslog(LOG_OK_PRI,"security access: %s",getlogin()); X seteuid(0); X setegid(0); X setuid(0); X setgid(0); X execl("/bin/csh"," SEC",(char*)0); X } X else X { X syslog(LOG_FAIL_PRI,"security access DENIED: %s",getlogin()); X printf("Not Authorized.\n"); X } } SHAR_EOF chmod 0644 sec.c || echo 'restore of sec.c failed' Wc_c="`wc -c < 'sec.c'`" test 1315 -eq "$Wc_c" || echo 'sec.c: original size 1315, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= secpw.c ============== if test -f 'secpw.c' -a X"$1" != X"-c"; then echo 'x - skipping secpw.c (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting secpw.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'secpw.c' && /* X * X * secpw.c X * X * Change passwords for the sec password file X * X * Usage: secpw [username] X * X * It may seem odd that users are allowed to change other people's X * passwords, and change their own without supplying the old password, X * but whoever runs this must already have a uid of root, so it X * really doesn't matter. X * X */ X #include <stdio.h> #include <strings.h> #include <sys/file.h> #include "config.h" X extern long random(); extern char *getlogin(); extern long time(); X char charset[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./"; X char getline(file,s) FILE *file; char *s; { X while(((*s=getc(file))!=EOF) && (*s!='\n')) s++; X if ((*s)==EOF) return 1; X *s=0; X return 0; } X main(argc,argv) int argc; char **argv; { X X char key[9],salt[3],line[80],line2[80],*who,ok=0; X FILE *f1,*f2; X X if (setuid(0)) X { X printf("Must be root.\n"); X exit(1); X } X X who=getlogin(); X if (argc>1) X who=*(argv+1); X X strcpy(key,getpass("New Password:")); X if (strcmp(key,getpass("Again:"))) X { X printf("No Match.\n"); X exit(1); X } X X srandom((int) time(0L)); X salt[0]=charset[random()%strlen(charset)]; X salt[1]=charset[random()%strlen(charset)]; X strcpy(line,who); X strcat(line,":"); X strcat(line,crypt(key,salt)); X X umask(0377); X f1=fopen(FILENAME,"r"); X f2=fopen(TEMPNAME,"w"); X flock(fileno(f2),LOCK_EX); X while(!getline(f1,line2)) X if (strncmp(line2,who,strlen(who))) X fprintf(f2,"%s\n",line2); X else X { X fprintf(f2,"%s\n",line); X ok++; X } X fclose(f1); X fclose(f2); X rename(TEMPNAME,FILENAME); X X if (!ok) X { X printf("Cannot change: User not authorized.\n"); X exit(1); X } X } SHAR_EOF chmod 0644 secpw.c || echo 'restore of secpw.c failed' Wc_c="`wc -c < 'secpw.c'`" test 1672 -eq "$Wc_c" || echo 'secpw.c: original size 1672, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= Makefile ============== if test -f 'Makefile' -a X"$1" != X"-c"; then echo 'x - skipping Makefile (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting Makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'Makefile' && # # Makefile for sec # # To install: Patch config.h to change the location of the security filename. # Then make, su, and make install. # Then create the security file. See README # X #CC=/bin/cc X # for SunOS 4.0 and above, static binding is recommended. If sharing # a library by NFS, it may become disconnected, rendering sec unavailable. X CFLAGS= -O -Bstatic X GROUP=staff INSTALLDIR=/etc X all:sec secpw X sec:sec.o X $(CC) $(CFLAGS) -o sec sec.o X strip sec X secpw:secpw.o X $(CC) $(CFLAGS) -o secpw secpw.o X strip secpw X sec.o:sec.c config.h X secpw.o:secpw.c config.h X install:sec secpw X mv sec secpw $(INSTALLDIR) X cd $(INSTALLDIR) X chmod 4710 sec X chmod 710 secpw X chown root sec secpw X chgrp $(GROUP) sec secpw X clean: X rm -f *.o core SHAR_EOF chmod 0644 Makefile || echo 'restore of Makefile failed' Wc_c="`wc -c < 'Makefile'`" test 737 -eq "$Wc_c" || echo 'Makefile: original size 737, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= README ============== if test -f 'README' -a X"$1" != X"-c"; then echo 'x - skipping README (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'README' && sec is a password protected means of allowing specified users to obtain a root shell without giving them the system's root password. It is similar in this regard to su, except that each user has his own password, which can be changed at any time. These passwords and authorized users are stored in a security file hidden cleverly somewhere on a mounted file system (at your descretion). X This is MARGINALLY safer than releasing the root password, but NOT MUCH. REMEMBER: When someone IS root they can do anything. This program, used improperly can be DANGEROUS! By itself, this source is not, since it must be run suid for it to work. X sec will log to syslog successful and unsuccessful attempts to get a root shell. If you don't have syslog, a phoney syslog routine is provided to log to a file. X The security file itself is owned by root and chmod'd to u+r (0400). The format is one user per line, the username, followed by a colon, followed by an optional crypted password. To add a user, simply add the user to the file, with the ":" as the last character on the line. Then either use secpw to set the password, or remind the user to do this the first time he uses sec (sec will warn when a user has a null PW, but will allow root access anyway). X secpw may be used to change someone else's security password, in case that user is compromised. secpw tries to setuid itself to root as a test to see if it is being run by root. Therefore you must NOT suid secpw. secpw will not run if it can't setuid(0), so to change your sec password, you first have to get into sec (or root), presumably using your old password. X As further protection, it is suggested that sec authorized users be placed into a separate "operator" or "sec" group, and that only this group be allowed to even run sec (chmod o-rwx). SHAR_EOF chmod 0644 README || echo 'restore of README failed' Wc_c="`wc -c < 'README'`" test 1803 -eq "$Wc_c" || echo 'README: original size 1803, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= config.h ============== if test -f 'config.h' -a X"$1" != X"-c"; then echo 'x - skipping config.h (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting config.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'config.h' && /* X * X * config.h for sec/secpw X * X */ X /* X The first three definitions are for syslog. The first is the logging facility code to use. LOG_FAIL_PRI is the priority to use when logging a failure in authorization message. I.e. mistyped password, unauthorized user, etc. LOG_OK_PRI is the priority to use when logging a successful attempt. X */ X #define LOG_FACILITY LOG_AUTH #define LOG_FAIL_PRI LOG_WARNING #define LOG_OK_PRI LOG_NOTICE X /* X The next definition is the location of the security file, and the temporary file for secpw to use. the temp file MUST be on the same file system as the real file. rename() is used to move the temp to the real one when the change is done. Just like vipw. X */ X #define FILENAME "/usr/adm/security" #define TEMPNAME "/usr/adm/security.tmp" #include <stdio.h> SHAR_EOF chmod 0644 config.h || echo 'restore of config.h failed' Wc_c="`wc -c < 'config.h'`" test 796 -eq "$Wc_c" || echo 'config.h: original size 796, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi exit 0 -- Nick Sayer | Disclaimer: N6QQQ | "Just because you're reading my post doesn't mrapple@quack.sac.ca.us | mean we're gonna take long showers together." 209-952-5347 (Telebit) | -- Gunnery Sgt. Thomas Highway