Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!rutgers!husc6!cmcl2!brl-adm!brl-smoke!gwyn From: gwyn@brl-smoke.UUCP Newsgroups: comp.unix.questions Subject: Re: Usage of SCCS Message-ID: <6507@brl-smoke.ARPA> Date: Sat, 3-Oct-87 20:58:28 EDT Article-I.D.: brl-smok.6507 Posted: Sat Oct 3 20:58:28 1987 Date-Received: Sun, 4-Oct-87 07:01:00 EDT References: <9597@brl-adm.ARPA> Reply-To: gwyn@brl.arpa (Doug Gwyn (VLD/VMB) ) Organization: Ballistic Research Lab (BRL), APG, MD. Lines: 170 In article <9597@brl-adm.ARPA> MIKEY%FLOPN2%eg.ti.com@RELAY. (Mike McIntyre -- (214) 575-2983) writes: >The discussion in Volume V of the Unix Programmers Manual makes mention of this >interface program, but never really goes into enough detail on just exactly >what it does or how it does it. What I really need to see is any examples that >anyone might have of this interface routine. The following relies on the fact that the SCCS utilities use the System V setuid() facilities to revert to the real UID. The SCCS utilities do not do this properly on Berkeley kernels (e.g. under the BRL UNIX System V emulation). /* SCCS -- provide controlled access to SCCS archives last edit: 83/09/14 D A Gwyn Installation: All SCCS archives and their directories belonging to the project administrator optionally may be readable by authorized editors but should not be writable by them. The archives must have all authorized editors other than the administrator added to their user lists via "admin -a". The "SCCS" program must be executable by authorized editors but not writable by them; it must be owned by the project administrator and set-UID to its owner. System SCCS utility binaries must be safe from unauthorized tampering. Use: Authorized editors may invoke SCCS utilities by appending the appropriate command as arguments to "SCCS", as in $ SCCS get -e s.archive */ static char sccsid[] = "@(#)SCCS.c 1.2"; #include #include #include #include #include extern void exit(); extern char *malloc(); extern int close(), execve(), fstat(), open(); #define DEVNULL "/dev/null" /* black hole pathname */ #define MAXFD 19 /* maximum file descriptor */ #define SCCSBIN "/usr/bin/" /* where SCCS commands reside -- important! note the slash */ typedef int bool; /* Boolean data */ #define false 0 #define true 1 static char *argv0 = NULL; /* "SCCS" program name */ static void DoCmd(), Fatal(); static bool CheckFDs(); static char *GetCmd(); main( argc, argv ) int argc; register char **argv; { register char *path; /* SCCS command pathname */ if ( !CheckFDs() ) /* check file descriptors */ exit( 10 ); /* something is wrong! */ if ( argc <= 1 ) /* check argument count */ { argv0 = "SCCS"; /* for Fatal() */ Fatal( "Usage: SCCS sccs_command arg ..." ); } argv0 = *argv++; /* remember invocation */ /* argv is now the user SCCS command argument list */ if ( (path = GetCmd( argv )) == NULL ) Fatal( "Not a controlled command" ); DoCmd( path, argv ); /* exec */ /*NOTREACHED*/ } static bool CheckFDs() /* check file descriptors */ { struct stat sbuf; /* dummy for fstat() */ register int fd; /* file descriptor */ for ( fd = 0; fd <= MAXFD; ++fd ) if ( fd > 2 ) (void)close( fd ); /* for safety */ else /* fd 0, 1, or 2 */ if ( fstat( fd, &sbuf ) != 0 && open( DEVNULL, fd == 0 ? O_RDONLY : O_WRONLY ) != fd /* forestall fraud */ ) return false; /* we tried! */ return true; /* okay */ } static char * GetCmd( argv ) /* return SCCS command */ register char **argv; /* user argument list */ { static char dir[] = SCCSBIN;/* where SCCS commands reside */ static char *ok_cmd[] = /* controlled commands */ { "cdc", "delta", "get", "prs", "rmdel", "sact", "unget", NULL }; register char **okp; /* -> ok_cmd[] */ for ( okp = ok_cmd; *okp != NULL; ++okp ) if ( strcmp( *okp, *argv ) == 0 ) { /* controlled command */ register char *path; /* command pathname */ if ( (path = malloc( sizeof dir + (unsigned)strlen( *okp ) ) ) == NULL ) Fatal( "Out of space" ); (void) strcat( strcpy( path, dir ), *okp ); return path; } return NULL; /* command not found */ } static void DoCmd( path, argv ) /* execute SCCS command */ char *path; /* command pathname */ char **argv; /* user argument list */ { static char *envp[] = { NULL }; /* empty environment */ (void) execve( path, argv, envp ); Fatal( "Can't execute command" ); } static void Fatal( message ) /* print message then quit */ char *message; /* error message */ { (void) fputs( argv0, stderr ); (void) fputs( ": ", stderr ); (void) fputs( message, stderr ); (void) putc( '\n', stderr ); exit( 1 ); }