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