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
chkpth(logname,mchname,path)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
rdpth()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
callback(name)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
chkperm(file,mopt)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 */
chkdebug()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