xref: /csrg-svn/usr.bin/uucp/libuu/chkpth.c (revision 33944)
113638Ssam #ifndef lint
2*33944Srick static char sccsid[] = "@(#)chkpth.c	5.5	(Berkeley) 04/05/88";
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 };
15*33944Srick 
1613638Ssam struct userpath *Uhead = NULL;
1713638Ssam struct userpath *Mchdef = NULL, *Logdef = NULL;
1813638Ssam int Uptfirst = 1;
1913638Ssam 
2023588Sbloom /*LINTLIBRARY*/
2123588Sbloom 
2223588Sbloom /*
2323588Sbloom  *	this routine will check the path table for the
2413638Ssam  *	machine or log name (non-null parameter) to see if the
2523588Sbloom  *	input path (path) starts with an acceptable prefix.
2613638Ssam  *
2713638Ssam  *	return codes:  0  |  FAIL
2813638Ssam  */
2913638Ssam 
3013638Ssam chkpth(logname, mchname, path)
3113638Ssam char *path, *logname, *mchname;
3213638Ssam {
3313638Ssam 	register struct userpath *u;
3413638Ssam 	extern char *lastpart();
3513638Ssam 	register char **p, *s;
3613638Ssam 
3713638Ssam 	/* Allow only rooted pathnames.  Security wish.  rti!trt */
3818616Sralph 	if (*path != '/') {
3918616Sralph 		DEBUG(4, "filename doesn't begin with /\n", CNULL);
4017767Sralph 		return FAIL;
4118616Sralph 	}
4213638Ssam 
4313638Ssam 	if (Uptfirst) {
4413638Ssam 		rdpth();
45*33944Srick 		if (Uhead == NULL) {
46*33944Srick 			syslog(LOG_ERR, "USERFILE empty!");
47*33944Srick 			cleanup(FAIL);
48*33944Srick 		}
4913638Ssam 		Uptfirst = 0;
5013638Ssam 	}
5113638Ssam 	for (u = Uhead; u != NULL; ) {
5213638Ssam 		if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME)
5313638Ssam 			break;
5423588Sbloom 		if (*mchname != '\0' && strncmp(mchname, u->us_mname, MAXBASENAME) == SAME)
5513638Ssam 			break;
5613638Ssam 		u = u->unext;
5713638Ssam 	}
5813638Ssam 	if (u == NULL) {
5913638Ssam 		if (*logname == '\0')
6013638Ssam 			u = Mchdef;
6113638Ssam 		else
6213638Ssam 			u = Logdef;
6313638Ssam 		if (u == NULL)
6417767Sralph 			return FAIL;
6513638Ssam 	}
6613638Ssam 
6713638Ssam 	/*  check for /../ in path name  */
6813638Ssam 	for (s = path; *s != '\0'; s++) {
6918616Sralph 		if (prefix("/../",s)) {
7018616Sralph 			DEBUG(4, "filename has /../ in it\n", CNULL);
7117767Sralph 			return FAIL;
7218616Sralph 		}
7313638Ssam 	}
7413638Ssam 
7513638Ssam 	/* Check for access permission */
7613638Ssam 	for (p = u->us_path; *p != NULL; p++)
7713638Ssam 		if (prefix(*p, path))
7817767Sralph 			return SUCCESS;
7918616Sralph 	DEBUG(4, "filename not in list\n", CNULL);
8013638Ssam 
8113638Ssam 	/* path name not valid */
8217767Sralph 	return FAIL;
8313638Ssam }
8413638Ssam 
8513638Ssam 
8613638Ssam /***
8713638Ssam  *	rdpth()
8813638Ssam  *
8913638Ssam  *	rdpth  -  this routine will read the USERFILE and
9013638Ssam  *	construct the userpath structure pointed to by (u);
9113638Ssam  *
9213638Ssam  */
9313638Ssam 
9413638Ssam rdpth()
9513638Ssam {
9613638Ssam 	char buf[100 + 1], *pbuf[50 + 1];
9713638Ssam 	register struct userpath *u;
9813638Ssam 	register char *pc, **cp;
9913638Ssam 	FILE *uf;
10013638Ssam 
10113638Ssam 	if ((uf = fopen(USERFILE, "r")) == NULL) {
10213638Ssam 		/* can not open file */
10313638Ssam 		return;
10413638Ssam 	}
10513638Ssam 
10613638Ssam 	while (cfgets(buf, sizeof(buf), uf) != NULL) {
10713638Ssam 		int nargs, i;
10813638Ssam 
10917767Sralph 		u = (struct userpath *)malloc(sizeof (struct userpath));
11017767Sralph 		if (u == NULL) {
11113638Ssam 			DEBUG (1, "*** Userpath malloc failed\n", 0);
11213638Ssam 			fclose (uf);
11313638Ssam 			return;
11413638Ssam 		}
11513638Ssam 		if ((pc = calloc((unsigned)strlen(buf) + 1, sizeof (char)))
11613638Ssam 			== NULL) {
11713638Ssam 			/* can not allocate space */
11813638Ssam 			DEBUG (1, "Userpath calloc 1 failed\n", 0);
11913638Ssam 			fclose(uf);
12013638Ssam 			return;
12113638Ssam 		}
12213638Ssam 
12313638Ssam 		strcpy(pc, buf);
12417767Sralph 		nargs = getargs(pc, pbuf, 50);
12513638Ssam 		u->us_lname = pbuf[0];
12613638Ssam 		pc = index(u->us_lname, ',');
12713638Ssam 		if (pc != NULL)
12813638Ssam 			*pc++ = '\0';
12913638Ssam 		else
13013638Ssam 			pc = u->us_lname + strlen(u->us_lname);
13113638Ssam 		u->us_mname = pc;
13223588Sbloom 		if (strlen(u->us_mname) > MAXBASENAME)
13323588Sbloom 			u->us_mname[MAXBASENAME] = '\0';
13413638Ssam 		if (*u->us_lname == '\0' && Logdef == NULL)
13513638Ssam 			Logdef = u;
13617767Sralph 		if (*u->us_mname == '\0' && Mchdef == NULL)
13713638Ssam 			Mchdef = u;
13813638Ssam 		i = 1;
13913638Ssam 		if (strcmp(pbuf[1], "c") == SAME) {
14013638Ssam 			u->us_callback = 1;
14113638Ssam 			i++;
14213638Ssam 		}
14313638Ssam 		else
14413638Ssam 			u->us_callback = 0;
14517767Sralph 		cp = (char **)calloc((unsigned)(nargs-i+1), sizeof(char *));
14617767Sralph 		if (cp == NULL) {
14713638Ssam 			/*  can not allocate space */
14813638Ssam 			DEBUG (1, "Userpath calloc 2 failed!\n", 0);
14913638Ssam 			fclose(uf);
15013638Ssam 			return;
15113638Ssam 		}
15217767Sralph 		u->us_path = cp;
15313638Ssam 
15413638Ssam 		while (i < nargs)
15513638Ssam 			*cp++ = pbuf[i++];
15613638Ssam 		*cp = NULL;
15713638Ssam 		u->unext = Uhead;
15813638Ssam 		Uhead = u;
15913638Ssam 	}
16013638Ssam 
16113638Ssam 	fclose(uf);
16213638Ssam 	return;
16313638Ssam }
16413638Ssam 
16513638Ssam /***
16613638Ssam  *	callback(name)	check for callback
16713638Ssam  *	char *name;
16813638Ssam  *
16913638Ssam  *	return codes:
17013638Ssam  *		0  -  no call back
17113638Ssam  *		1  -  call back
17213638Ssam  */
17313638Ssam 
17413638Ssam callback(name)
17513638Ssam register char *name;
17613638Ssam {
17713638Ssam 	register struct userpath *u;
17813638Ssam 
17913638Ssam 	if (Uptfirst) {
18013638Ssam 		rdpth();
181*33944Srick 		if (Uhead == NULL) {
182*33944Srick 			syslog(LOG_ERR, "USERFILE empty!");
183*33944Srick 			cleanup(FAIL);
184*33944Srick 		}
18513638Ssam 		Uptfirst = 0;
18613638Ssam 	}
18713638Ssam 
18813638Ssam 	for (u = Uhead; u != NULL; ) {
18913638Ssam 		if (strcmp(u->us_lname, name) == SAME)
19013638Ssam 			/* found user name */
19117767Sralph 			return u->us_callback;
19213638Ssam 		u = u->unext;
19313638Ssam 	}
19413638Ssam 
19513638Ssam 	/* userid not found */
19617767Sralph 	return 0;
19713638Ssam }
19813638Ssam 
19913638Ssam 
20013638Ssam /***
20113638Ssam  *	chkperm(file, mopt)	check write permission of file
20213638Ssam  *	char *mopt;		none NULL - create directories
20313638Ssam  *
20413638Ssam  *	if mopt != NULL and permissions are ok,
20513638Ssam  *	a side effect of this routine is to make
20613638Ssam  *	directories up to the last part of the
20713638Ssam  *	filename (if they do not exist).
20813638Ssam  *
20917767Sralph  *	return SUCCESS | FAIL
21013638Ssam  */
21113638Ssam 
21213638Ssam chkperm(file, mopt)
21313638Ssam char *file, *mopt;
21413638Ssam {
21513638Ssam 	struct stat s;
21613638Ssam 	int ret;
21713638Ssam 	char dir[MAXFULLNAME];
21813638Ssam 	extern char *lastpart();
21913638Ssam 
22013638Ssam 	if (stat(subfile(file), &s) == 0) {
22118616Sralph 		if ((s.st_mode & ANYWRITE) == 0) {
22218616Sralph 			DEBUG(4,"file is not writable: mode %o\n", s.st_mode);
22317767Sralph 			return FAIL;
22418616Sralph 		}
22517767Sralph 		return SUCCESS;
22613638Ssam 	}
22713638Ssam 
22813638Ssam 	strcpy(dir, file);
22913638Ssam 	*lastpart(dir) = '\0';
23018616Sralph 	if ((ret = stat(subfile(dir), &s)) == -1 && mopt == NULL) {
23118616Sralph 		DEBUG(4, "can't stat directory %s\n", subfile(dir));
23217767Sralph 		return FAIL;
23318616Sralph 	}
23413638Ssam 
23513638Ssam 	if (ret != -1) {
23613638Ssam 		if ((s.st_mode & ANYWRITE) == 0)
23717767Sralph 			return FAIL;
23813638Ssam 		else
23917767Sralph 			return SUCCESS;
24013638Ssam 	}
24113638Ssam 
24213638Ssam 	/*  make directories  */
24317767Sralph 	return mkdirs(file);
24413638Ssam }
24513638Ssam 
24613638Ssam /*
24713638Ssam  * Check for sufficient privilege to request debugging.
24813638Ssam  */
24917767Sralph chkdebug()
25013638Ssam {
25117767Sralph 	if (access(SYSFILE, 04) < 0) {
25217767Sralph 		fprintf(stderr, "Sorry, you must be able to read L.sys for debugging\n");
25313638Ssam 		cleanup(1);
25413638Ssam 		exit(1);	/* Just in case */
25513638Ssam 	}
25613638Ssam }
257