DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T i

⟦667a4b863⟧ TextFile

    Length: 5750 (0x1676)
    Types: TextFile
    Names: »is_able.c«

Derivation

└─⟦4f9d7c866⟧ Bits:30007245 EUUGD6: Sikkerheds distributionen
    └─⟦3da311d67⟧ »./cops/1.04/cops_104.tar.Z« 
        └─⟦6a2577110⟧ 
└─⟦4f9d7c866⟧ Bits:30007245 EUUGD6: Sikkerheds distributionen
    └─⟦6a2577110⟧ »./cops/1.04/cops_104.tar« 
            └─⟦this⟧ »cops_104/src/is_able.c« 

TextFile

/*
    Usage:

 is_able filename {w|g|s|S}       {r|w|B|b|s}
         (world/group/SUID/SGID   read/write/{read&write}/{suid&write}/s[ug]id)

    The second arg of {r|w} determines whether a file is (group or world
  depending on the first arg of {w|g}) writable/readable, or if it is
  SUID/SGID (first arg, either s or S, respectively), and prints out a
  short message to that effect.

 So:
    is_able w w		# checks if world writable
    is_able g r		# checks if group readable
    is_able s s		# checks if SUID
    is_able S b		# checks if world writable and SGID

  	Permissions bits:		  vvv--- Permission bits
   	        1 = execute		00000
   	        2 = writable		 ^
   	        4 = readable		 + Setuid bits

  	Setuid bits:
   	        1 = sticky
   	        2 = set group id
   	        4 = set user od

    Pete Shipley (shipley@mica.berkeley.edu) gutted my original code,
  made in cleaner and smarter, and combined everything into one compact
  file.  What a deal, huh?  Then I came along and beat up his code and
  made it look ugly again (I changed the is_writeable option to return
  true if _any_ parent directories are writable, not just the target.  So
  you can blame me if you want.  Better yet, just send me a patch if I
  blew it.)

*/

#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <stdio.h>

#define G_READ_TEST 00044	/* group (or world) readable */
#define W_READ_TEST 00004	/* world readable */
#define G_READ_STRING	"Warning!  %s is group readable!\n"
#define W_READ_STRING	"Warning!  %s is _World_ readable!\n"

#define G_WRITE_TEST 00022	/* group (or world) writable */
#define W_WRITE_TEST 00002	/* world writable */
#define G_WRITE_STRING	"Warning!  %s is group writable!\n"
#define G_WRITE_TREE	"Warning!  %s is group writable! (*)\n"
#define W_WRITE_STRING	"Warning!  %s is _World_ writable!\n"
#define W_WRITE_TREE	"Warning!  %s is _World_ writable! (*)\n"

#define SGID_TEST 02000		/* set group id */
#define SUID_TEST 04000		/* set user id */
#define SUID_STRING	"Warning!  %s is SUID!\n"
#define SGID_STRING	"Warning!  %s is SGID!\n"

char usage[]="Usage: is_able file {w|g|S|s} {r|w|B|b|}\n";

main(argc,argv)
int argc;
char **argv;
{
char file[256],wg,rwb,gstring[35],wstring[35],wstring_tree[50],
	gstring_tree[50], suidstring[35];
register int group, read, write, both, suid, sgid, verbose, xmode;
static struct stat statb;

group=read=write=suid=sgid=both=verbose=xmode=0;

/* check out arguments */
if (argc != 4) {
	fprintf(stderr, usage);
	exit(1);
	}

/* parse arguments */
strcpy(file, argv[1]);

/* get stats on file in question -- if doesn't exist, exit */
if (stat(file,&statb) < 0) {
	fprintf(stderr, file);
	exit(2);
	}

wg   = argv[2][0];		/* world or group */
rwb  = argv[3][0];		/* read/write/both */

/* set the report string and some flags */
if (wg == 'g') group = 1;
else if (wg == 's') suid = 1;
else if (wg == 'S') sgid = 1;

if (rwb == 'r') {
	if (group) strcpy(gstring, G_READ_STRING);
	else strcpy(wstring, W_READ_STRING);
	read = 1;
	}
else if (rwb == 's')
	(suid?strcpy(suidstring,SUID_STRING):strcpy(suidstring,SGID_STRING));

else if (rwb == 'w') {
	if (group) {
		strcpy(gstring, G_WRITE_STRING);
		strcpy(gstring_tree, G_WRITE_TREE);
		}
	else {
		strcpy(wstring, W_WRITE_STRING);
		strcpy(wstring_tree, W_WRITE_TREE);
		}
	write = 1;
	}
else if (rwb == 'b') {
	/* do the write first, then read check */
	if (group) strcpy(gstring, G_WRITE_STRING);
	else strcpy(wstring, W_WRITE_STRING);
	if (suid) strcpy(suidstring,SUID_STRING);
	both = read = write = 1;
	}
else if (rwb == 'B') {
	/* do the write first, then s[ug]id check */
	if (suid) strcpy(suidstring, SUID_STRING);
	else if (sgid) strcpy(suidstring, SGID_STRING);
	else {
		fprintf(stderr, usage);
		exit(1);
		}
	both = write = 1;
	}
else {
	fprintf(stderr, usage);
	exit(1);
	}

/*
 *         the write stuff, so to speak...
 *   What I'm doing in this mess is to parse the file in question, check out
 * whole path; 'cause if anything is world writable, you can compromise.
 * For instance, if /usr is world writable, then /usr/spool/mail is
 * compromisable, no matter what its permissions are.
 *
*/
if (write) {
	/* 256 levels of dirs, max len each 256 chars */
	char foo_dirs[256][256];
	char *foo_file;
	int i = 0, j;

	foo_file = file;
	strcpy(foo_dirs[i++], foo_file);

	j=strlen(foo_file) - 1;
	do {
		if (foo_file[j] == '/')
			strncpy(foo_dirs[i++], foo_file, j);
	} while (--j > 0);

	for (j = 0; j < i; j++) {
		if (stat(foo_dirs[j],&statb) < 0)
			continue;
		xmode=statb.st_mode;
		if (!group) {
			if (xmode & W_WRITE_TEST) {
				/* want to distinguish between file being
				   writable and directory tree being
				   writable; j==0 means actual file */
				if (!j) printf( wstring, file);
				else printf( wstring_tree, file);
				if (both) goto bboth;
				exit(!xmode);
				}
			}
		else if (xmode & G_WRITE_TEST) {
			if (!j) printf( gstring, file);
			else printf( gstring_tree, file);
			if (both) goto bboth;
			exit(!xmode);
			}
		}

if (!both) exit(!xmode);
}

bboth:
if (both) if (stat(file,&statb) < 0) {
		fprintf(stderr, file);
		exit(2);
		}

/* find premissions on file in question */
if (group)
	xmode = statb.st_mode & G_READ_TEST;
else
	xmode = statb.st_mode & W_READ_TEST;

if (wg == 's') {
	/* check SUID */
	xmode = statb.st_mode & SUID_TEST;
	if (xmode) printf( suidstring, file);
	exit (!xmode);
	}
if (wg == 'S') {
	/* check SGID */
	xmode = statb.st_mode & SGID_TEST;
	if (xmode) printf( suidstring, file);
	exit (!xmode);
	}

if (rwb == 'b') {
	/* do the read now */
	if (group) strcpy(gstring, G_READ_STRING);
	else strcpy(wstring, W_READ_STRING);
	}

/* report finding */
if (xmode) printf( (group ? gstring : wstring), file);

exit(!xmode);
}