xref: /csrg-svn/usr.bin/uucp/libuu/chkpth.c (revision 18616)
113638Ssam #ifndef lint
2*18616Sralph static char sccsid[] = "@(#)chkpth.c	5.3 (Berkeley) 04/10/85";
313638Ssam #endif
413638Ssam 
513638Ssam #include "uucp.h"
613638Ssam #include <sys/stat.h>
713638Ssam 
813638Ssam struct userpath {
913638Ssam 	char *us_lname;
1013638Ssam 	char *us_mname;
1113638Ssam 	char us_callback;
1213638Ssam 	char **us_path;
1313638Ssam 	struct userpath *unext;
1413638Ssam };
1513638Ssam struct userpath *Uhead = NULL;
1613638Ssam struct userpath *Mchdef = NULL, *Logdef = NULL;
1713638Ssam int Uptfirst = 1;
1813638Ssam 
1913638Ssam /*******
2013638Ssam  *	chkpth(logname, mchname, path)
2113638Ssam  *	char *path, *logname, *mchname;
2213638Ssam  *
2313638Ssam  *	chkpth  -  this routine will check the path table for the
2413638Ssam  *	machine or log name (non-null parameter) to see if the
2513638Ssam  *	input path (path)
2613638Ssam  *	starts with an acceptable prefix.
2713638Ssam  *
2813638Ssam  *	return codes:  0  |  FAIL
2913638Ssam  */
3013638Ssam 
3113638Ssam chkpth(logname, mchname, path)
3213638Ssam char *path, *logname, *mchname;
3313638Ssam {
3413638Ssam 	register struct userpath *u;
3513638Ssam 	extern char *lastpart();
3613638Ssam 	register char **p, *s;
3713638Ssam 
3813638Ssam 	/* Allow only rooted pathnames.  Security wish.  rti!trt */
39*18616Sralph 	if (*path != '/') {
40*18616Sralph 		DEBUG(4, "filename doesn't begin with /\n", CNULL);
4117767Sralph 		return FAIL;
42*18616Sralph 	}
4313638Ssam 
4413638Ssam 	if (Uptfirst) {
4513638Ssam 		rdpth();
4617767Sralph 		ASSERT(Uhead != NULL, "INIT USERFILE, No entrys!", CNULL, 0);
4713638Ssam 		Uptfirst = 0;
4813638Ssam 	}
4913638Ssam 	for (u = Uhead; u != NULL; ) {
5013638Ssam 		if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME)
5113638Ssam 			break;
5213638Ssam 		if (*mchname != '\0' && strncmp(mchname, u->us_mname, 7) == SAME)
5313638Ssam 			break;
5413638Ssam 		u = u->unext;
5513638Ssam 	}
5613638Ssam 	if (u == NULL) {
5713638Ssam 		if (*logname == '\0')
5813638Ssam 			u = Mchdef;
5913638Ssam 		else
6013638Ssam 			u = Logdef;
6113638Ssam 		if (u == NULL)
6217767Sralph 			return FAIL;
6313638Ssam 	}
6413638Ssam 
6513638Ssam 	/*  check for /../ in path name  */
6613638Ssam 	for (s = path; *s != '\0'; s++) {
67*18616Sralph 		if (prefix("/../",s)) {
68*18616Sralph 			DEBUG(4, "filename has /../ in it\n", CNULL);
6917767Sralph 			return FAIL;
70*18616Sralph 		}
7113638Ssam 	}
7213638Ssam 
7313638Ssam 	/* Check for access permission */
7413638Ssam 	for (p = u->us_path; *p != NULL; p++)
7513638Ssam 		if (prefix(*p, path))
7617767Sralph 			return SUCCESS;
77*18616Sralph 	DEBUG(4, "filename not in list\n", CNULL);
7813638Ssam 
7913638Ssam 	/* path name not valid */
8017767Sralph 	return FAIL;
8113638Ssam }
8213638Ssam 
8313638Ssam 
8413638Ssam /***
8513638Ssam  *	rdpth()
8613638Ssam  *
8713638Ssam  *	rdpth  -  this routine will read the USERFILE and
8813638Ssam  *	construct the userpath structure pointed to by (u);
8913638Ssam  *
9013638Ssam  */
9113638Ssam 
9213638Ssam rdpth()
9313638Ssam {
9413638Ssam 	char buf[100 + 1], *pbuf[50 + 1];
9513638Ssam 	register struct userpath *u;
9613638Ssam 	register char *pc, **cp;
9713638Ssam 	FILE *uf;
9813638Ssam 
9913638Ssam 	if ((uf = fopen(USERFILE, "r")) == NULL) {
10013638Ssam 		/* can not open file */
10113638Ssam 		return;
10213638Ssam 	}
10313638Ssam 
10413638Ssam 	while (cfgets(buf, sizeof(buf), uf) != NULL) {
10513638Ssam 		int nargs, i;
10613638Ssam 
10717767Sralph 		u = (struct userpath *)malloc(sizeof (struct userpath));
10817767Sralph 		if (u == NULL) {
10913638Ssam 			DEBUG (1, "*** Userpath malloc failed\n", 0);
11013638Ssam 			fclose (uf);
11113638Ssam 			return;
11213638Ssam 		}
11313638Ssam 		if ((pc = calloc((unsigned)strlen(buf) + 1, sizeof (char)))
11413638Ssam 			== NULL) {
11513638Ssam 			/* can not allocate space */
11613638Ssam 			DEBUG (1, "Userpath calloc 1 failed\n", 0);
11713638Ssam 			fclose(uf);
11813638Ssam 			return;
11913638Ssam 		}
12013638Ssam 
12113638Ssam 		strcpy(pc, buf);
12217767Sralph 		nargs = getargs(pc, pbuf, 50);
12313638Ssam 		u->us_lname = pbuf[0];
12413638Ssam 		pc = index(u->us_lname, ',');
12513638Ssam 		if (pc != NULL)
12613638Ssam 			*pc++ = '\0';
12713638Ssam 		else
12813638Ssam 			pc = u->us_lname + strlen(u->us_lname);
12913638Ssam 		u->us_mname = pc;
13013638Ssam 		if (strlen(u->us_mname) > 7)
13113638Ssam 			u->us_mname[7] = '\0';
13213638Ssam 		if (*u->us_lname == '\0' && Logdef == NULL)
13313638Ssam 			Logdef = u;
13417767Sralph 		if (*u->us_mname == '\0' && Mchdef == NULL)
13513638Ssam 			Mchdef = u;
13613638Ssam 		i = 1;
13713638Ssam 		if (strcmp(pbuf[1], "c") == SAME) {
13813638Ssam 			u->us_callback = 1;
13913638Ssam 			i++;
14013638Ssam 		}
14113638Ssam 		else
14213638Ssam 			u->us_callback = 0;
14317767Sralph 		cp = (char **)calloc((unsigned)(nargs-i+1), sizeof(char *));
14417767Sralph 		if (cp == NULL) {
14513638Ssam 			/*  can not allocate space */
14613638Ssam 			DEBUG (1, "Userpath calloc 2 failed!\n", 0);
14713638Ssam 			fclose(uf);
14813638Ssam 			return;
14913638Ssam 		}
15017767Sralph 		u->us_path = cp;
15113638Ssam 
15213638Ssam 		while (i < nargs)
15313638Ssam 			*cp++ = pbuf[i++];
15413638Ssam 		*cp = NULL;
15513638Ssam 		u->unext = Uhead;
15613638Ssam 		Uhead = u;
15713638Ssam 	}
15813638Ssam 
15913638Ssam 	fclose(uf);
16013638Ssam 	return;
16113638Ssam }
16213638Ssam 
16313638Ssam /***
16413638Ssam  *	callback(name)	check for callback
16513638Ssam  *	char *name;
16613638Ssam  *
16713638Ssam  *	return codes:
16813638Ssam  *		0  -  no call back
16913638Ssam  *		1  -  call back
17013638Ssam  */
17113638Ssam 
17213638Ssam callback(name)
17313638Ssam register char *name;
17413638Ssam {
17513638Ssam 	register struct userpath *u;
17613638Ssam 
17713638Ssam 	if (Uptfirst) {
17813638Ssam 		rdpth();
17917767Sralph 		ASSERT(Uhead != NULL, "INIT USERFILE, No Users!", CNULL, 0);
18013638Ssam 		Uptfirst = 0;
18113638Ssam 	}
18213638Ssam 
18313638Ssam 	for (u = Uhead; u != NULL; ) {
18413638Ssam 		if (strcmp(u->us_lname, name) == SAME)
18513638Ssam 			/* found user name */
18617767Sralph 			return u->us_callback;
18713638Ssam 		u = u->unext;
18813638Ssam 	}
18913638Ssam 
19013638Ssam 	/* userid not found */
19117767Sralph 	return 0;
19213638Ssam }
19313638Ssam 
19413638Ssam 
19513638Ssam /***
19613638Ssam  *	chkperm(file, mopt)	check write permission of file
19713638Ssam  *	char *mopt;		none NULL - create directories
19813638Ssam  *
19913638Ssam  *	if mopt != NULL and permissions are ok,
20013638Ssam  *	a side effect of this routine is to make
20113638Ssam  *	directories up to the last part of the
20213638Ssam  *	filename (if they do not exist).
20313638Ssam  *
20417767Sralph  *	return SUCCESS | FAIL
20513638Ssam  */
20613638Ssam 
20713638Ssam chkperm(file, mopt)
20813638Ssam char *file, *mopt;
20913638Ssam {
21013638Ssam 	struct stat s;
21113638Ssam 	int ret;
21213638Ssam 	char dir[MAXFULLNAME];
21313638Ssam 	extern char *lastpart();
21413638Ssam 
21513638Ssam 	if (stat(subfile(file), &s) == 0) {
216*18616Sralph 		if ((s.st_mode & ANYWRITE) == 0) {
217*18616Sralph 			DEBUG(4,"file is not writable: mode %o\n", s.st_mode);
21817767Sralph 			return FAIL;
219*18616Sralph 		}
22017767Sralph 		return SUCCESS;
22113638Ssam 	}
22213638Ssam 
22313638Ssam 	strcpy(dir, file);
22413638Ssam 	*lastpart(dir) = '\0';
225*18616Sralph 	if ((ret = stat(subfile(dir), &s)) == -1 && mopt == NULL) {
226*18616Sralph 		DEBUG(4, "can't stat directory %s\n", subfile(dir));
22717767Sralph 		return FAIL;
228*18616Sralph 	}
22913638Ssam 
23013638Ssam 	if (ret != -1) {
23113638Ssam 		if ((s.st_mode & ANYWRITE) == 0)
23217767Sralph 			return FAIL;
23313638Ssam 		else
23417767Sralph 			return SUCCESS;
23513638Ssam 	}
23613638Ssam 
23713638Ssam 	/*  make directories  */
23817767Sralph 	return mkdirs(file);
23913638Ssam }
24013638Ssam 
24113638Ssam /*
24213638Ssam  * Check for sufficient privilege to request debugging.
24313638Ssam  */
24417767Sralph chkdebug()
24513638Ssam {
24617767Sralph 	if (access(SYSFILE, 04) < 0) {
24717767Sralph 		fprintf(stderr, "Sorry, you must be able to read L.sys for debugging\n");
24813638Ssam 		cleanup(1);
24913638Ssam 		exit(1);	/* Just in case */
25013638Ssam 	}
25113638Ssam }
252