xref: /csrg-svn/usr.bin/uucp/libuu/chkpth.c (revision 13638)
1*13638Ssam #ifndef lint
2*13638Ssam static char sccsid[] = "@(#)chkpth.c	5.1 (Berkeley) 07/02/83";
3*13638Ssam #endif
4*13638Ssam 
5*13638Ssam /*
6*13638Ssam  * Doug Kingston, 30 July 82 to fix handling of the "userpath" structures.
7*13638Ssam  * (brl-bmd)
8*13638Ssam  * rti!trt: the code here is bizarre.  There must be a zillion holes.
9*13638Ssam  * chkpth should not be called for implied Spool requests .
10*13638Ssam  * But explicit requests (foo!/usr/spoo/uucp/*) should use chkpth.
11*13638Ssam  */
12*13638Ssam #include "uucp.h"
13*13638Ssam #include <sys/types.h>
14*13638Ssam #include <sys/stat.h>
15*13638Ssam 
16*13638Ssam 
17*13638Ssam struct userpath {
18*13638Ssam 	char *us_lname;
19*13638Ssam 	char *us_mname;
20*13638Ssam 	char us_callback;
21*13638Ssam 	char **us_path;
22*13638Ssam 	struct userpath *unext;
23*13638Ssam };
24*13638Ssam struct userpath *Uhead = NULL;
25*13638Ssam struct userpath *Mchdef = NULL, *Logdef = NULL;
26*13638Ssam int Uptfirst = 1;
27*13638Ssam 
28*13638Ssam 
29*13638Ssam /*******
30*13638Ssam  *	chkpth(logname, mchname, path)
31*13638Ssam  *	char *path, *logname, *mchname;
32*13638Ssam  *
33*13638Ssam  *	chkpth  -  this routine will check the path table for the
34*13638Ssam  *	machine or log name (non-null parameter) to see if the
35*13638Ssam  *	input path (path)
36*13638Ssam  *	starts with an acceptable prefix.
37*13638Ssam  *
38*13638Ssam  *	return codes:  0  |  FAIL
39*13638Ssam  */
40*13638Ssam 
41*13638Ssam chkpth(logname, mchname, path)
42*13638Ssam char *path, *logname, *mchname;
43*13638Ssam {
44*13638Ssam 	register struct userpath *u;
45*13638Ssam 	extern char *lastpart();
46*13638Ssam 	register char **p, *s;
47*13638Ssam 
48*13638Ssam 	/* Allow only rooted pathnames.  Security wish.  rti!trt */
49*13638Ssam 	if (*path != '/')
50*13638Ssam 		return(FAIL);
51*13638Ssam 
52*13638Ssam 	if (Uptfirst) {
53*13638Ssam 		rdpth();
54*13638Ssam 		ASSERT(Uhead != NULL, "INIT USERFILE, No entrys!", "", 0);
55*13638Ssam 		Uptfirst = 0;
56*13638Ssam 	}
57*13638Ssam 	for (u = Uhead; u != NULL; ) {
58*13638Ssam 		if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME)
59*13638Ssam 			break;
60*13638Ssam 		if (*mchname != '\0' && strncmp(mchname, u->us_mname, 7) == SAME)
61*13638Ssam 			break;
62*13638Ssam 		u = u->unext;
63*13638Ssam 	}
64*13638Ssam 	if (u == NULL) {
65*13638Ssam 		if (*logname == '\0')
66*13638Ssam 			u = Mchdef;
67*13638Ssam 		else
68*13638Ssam 			u = Logdef;
69*13638Ssam 		if (u == NULL)
70*13638Ssam 			return(FAIL);
71*13638Ssam 	}
72*13638Ssam 	/* found user name */
73*13638Ssam 	p = u->us_path;
74*13638Ssam 
75*13638Ssam 	/*  check for /../ in path name  */
76*13638Ssam 	for (s = path; *s != '\0'; s++) {
77*13638Ssam 		if (prefix("/../",s))
78*13638Ssam 			return(FAIL);
79*13638Ssam 	}
80*13638Ssam 
81*13638Ssam 	/* Check for access permission */
82*13638Ssam 	for (p = u->us_path; *p != NULL; p++)
83*13638Ssam 		if (prefix(*p, path))
84*13638Ssam 			return(0);
85*13638Ssam 
86*13638Ssam 	/* path name not valid */
87*13638Ssam 	return(FAIL);
88*13638Ssam }
89*13638Ssam 
90*13638Ssam 
91*13638Ssam /***
92*13638Ssam  *	rdpth()
93*13638Ssam  *
94*13638Ssam  *	rdpth  -  this routine will read the USERFILE and
95*13638Ssam  *	construct the userpath structure pointed to by (u);
96*13638Ssam  *
97*13638Ssam  *	return codes:  0  |  FAIL
98*13638Ssam  *
99*13638Ssam  * 5/3/81 - changed to enforce the uucp-wide convention that system
100*13638Ssam  *	    names be 7 chars or less in length
101*13638Ssam  */
102*13638Ssam 
103*13638Ssam rdpth()
104*13638Ssam {
105*13638Ssam 	char buf[100 + 1], *pbuf[50 + 1];
106*13638Ssam 	register struct userpath *u;
107*13638Ssam 	register char *pc, **cp;
108*13638Ssam 	FILE *uf;
109*13638Ssam 
110*13638Ssam 	if ((uf = fopen(USERFILE, "r")) == NULL) {
111*13638Ssam 		/* can not open file */
112*13638Ssam 		return;
113*13638Ssam 	}
114*13638Ssam 
115*13638Ssam 	while (cfgets(buf, sizeof(buf), uf) != NULL) {
116*13638Ssam 		int nargs, i;
117*13638Ssam 
118*13638Ssam 		if ((u = (struct userpath *)malloc(sizeof (struct userpath))) == NULL) {
119*13638Ssam 			DEBUG (1, "*** Userpath malloc failed\n", 0);
120*13638Ssam 			fclose (uf);
121*13638Ssam 			return;
122*13638Ssam 		}
123*13638Ssam 		if ((pc = calloc((unsigned)strlen(buf) + 1, sizeof (char)))
124*13638Ssam 			== NULL) {
125*13638Ssam 			/* can not allocate space */
126*13638Ssam 			DEBUG (1, "Userpath calloc 1 failed\n", 0);
127*13638Ssam 			fclose(uf);
128*13638Ssam 			return;
129*13638Ssam 		}
130*13638Ssam 
131*13638Ssam 		strcpy(pc, buf);
132*13638Ssam 		nargs = getargs(pc, pbuf);
133*13638Ssam 		u->us_lname = pbuf[0];
134*13638Ssam 		pc = index(u->us_lname, ',');
135*13638Ssam 		if (pc != NULL)
136*13638Ssam 			*pc++ = '\0';
137*13638Ssam 		else
138*13638Ssam 			pc = u->us_lname + strlen(u->us_lname);
139*13638Ssam 		u->us_mname = pc;
140*13638Ssam 		if (strlen(u->us_mname) > 7)
141*13638Ssam 			u->us_mname[7] = '\0';
142*13638Ssam 		if (*u->us_lname == '\0' && Logdef == NULL)
143*13638Ssam 			Logdef = u;
144*13638Ssam 		/* rti!trt: commented following else so
145*13638Ssam 		 * chkpth("","",file) works okay.
146*13638Ssam 		 * I don't understand this, though.
147*13638Ssam 		 */
148*13638Ssam 		/*else*/ if (*u->us_mname == '\0' && Mchdef == NULL)
149*13638Ssam 			Mchdef = u;
150*13638Ssam 		i = 1;
151*13638Ssam 		if (strcmp(pbuf[1], "c") == SAME) {
152*13638Ssam 			u->us_callback = 1;
153*13638Ssam 			i++;
154*13638Ssam 		}
155*13638Ssam 		else
156*13638Ssam 			u->us_callback = 0;
157*13638Ssam 		if ((cp = u->us_path =
158*13638Ssam 		  (char **)calloc((unsigned)(nargs-i+1), sizeof(char *))) == NULL) {
159*13638Ssam 			/*  can not allocate space */
160*13638Ssam 			DEBUG (1, "Userpath calloc 2 failed!\n", 0);
161*13638Ssam 			fclose(uf);
162*13638Ssam 			return;
163*13638Ssam 		}
164*13638Ssam 
165*13638Ssam 		while (i < nargs)
166*13638Ssam 			*cp++ = pbuf[i++];
167*13638Ssam 		*cp = NULL;
168*13638Ssam 		u->unext = Uhead;
169*13638Ssam 		Uhead = u;
170*13638Ssam 	}
171*13638Ssam 
172*13638Ssam 	fclose(uf);
173*13638Ssam 	return;
174*13638Ssam }
175*13638Ssam 
176*13638Ssam /***
177*13638Ssam  *	callback(name)	check for callback
178*13638Ssam  *	char *name;
179*13638Ssam  *
180*13638Ssam  *	return codes:
181*13638Ssam  *		0  -  no call back
182*13638Ssam  *		1  -  call back
183*13638Ssam  */
184*13638Ssam 
185*13638Ssam callback(name)
186*13638Ssam register char *name;
187*13638Ssam {
188*13638Ssam 	register struct userpath *u;
189*13638Ssam 
190*13638Ssam 	if (Uptfirst) {
191*13638Ssam 		rdpth();
192*13638Ssam 		ASSERT(Uhead != NULL, "INIT USERFILE, No Users!", "", 0);
193*13638Ssam 		Uptfirst = 0;
194*13638Ssam 	}
195*13638Ssam 
196*13638Ssam 	for (u = Uhead; u != NULL; ) {
197*13638Ssam 		if (strcmp(u->us_lname, name) == SAME)
198*13638Ssam 			/* found user name */
199*13638Ssam 			return(u->us_callback);
200*13638Ssam 		u = u->unext;
201*13638Ssam 	}
202*13638Ssam 
203*13638Ssam 	/* userid not found */
204*13638Ssam 	return(0);
205*13638Ssam }
206*13638Ssam 
207*13638Ssam 
208*13638Ssam /***
209*13638Ssam  *	chkperm(file, mopt)	check write permission of file
210*13638Ssam  *	char *mopt;		none NULL - create directories
211*13638Ssam  *
212*13638Ssam  *	if mopt != NULL and permissions are ok,
213*13638Ssam  *	a side effect of this routine is to make
214*13638Ssam  *	directories up to the last part of the
215*13638Ssam  *	filename (if they do not exist).
216*13638Ssam  *
217*13638Ssam  *	return 0 | FAIL
218*13638Ssam  */
219*13638Ssam 
220*13638Ssam chkperm(file, mopt)
221*13638Ssam char *file, *mopt;
222*13638Ssam {
223*13638Ssam 	struct stat s;
224*13638Ssam 	int ret;
225*13638Ssam 	char dir[MAXFULLNAME];
226*13638Ssam 	extern char *lastpart();
227*13638Ssam 
228*13638Ssam 	if (stat(subfile(file), &s) == 0) {
229*13638Ssam 		/* Forbid scribbling on a not-generally-writable file */
230*13638Ssam 		/* rti!trt */
231*13638Ssam 		if ((s.st_mode & ANYWRITE) == 0)
232*13638Ssam 			return(FAIL);
233*13638Ssam 		return(0);
234*13638Ssam 	}
235*13638Ssam 
236*13638Ssam 	strcpy(dir, file);
237*13638Ssam 	*lastpart(dir) = '\0';
238*13638Ssam 	if ((ret = stat(subfile(dir), &s)) == -1
239*13638Ssam 	  && mopt == NULL)
240*13638Ssam 		return(FAIL);
241*13638Ssam 
242*13638Ssam 	if (ret != -1) {
243*13638Ssam 		if ((s.st_mode & ANYWRITE) == 0)
244*13638Ssam 			return(FAIL);
245*13638Ssam 		else
246*13638Ssam 			return(0);
247*13638Ssam 	}
248*13638Ssam 
249*13638Ssam 	/*  make directories  */
250*13638Ssam 	return(mkdirs(file));
251*13638Ssam }
252*13638Ssam 
253*13638Ssam /*
254*13638Ssam  * Check for sufficient privilege to request debugging.
255*13638Ssam  * Suggested by seismo!stewart, John Stewart.
256*13638Ssam  */
257*13638Ssam chkdebug(uid)
258*13638Ssam int uid;
259*13638Ssam {
260*13638Ssam 	if (uid > PRIV_UIDS) {
261*13638Ssam 		fprintf(stderr, "Sorry, uid must be <= %d for debugging\n",
262*13638Ssam 			PRIV_UIDS);
263*13638Ssam 		cleanup(1);
264*13638Ssam 		exit(1);	/* Just in case */
265*13638Ssam 	}
266*13638Ssam }
267