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