|
|
1.1 root 1: /* all the permission stuff. */
2: #include "share.h"
3: #include "pwd.h"
4: #include "grp.h"
5:
6: typedef struct {
7: int huid, cuid;
8: } tuid;
9: tuid *t, *g;
10: int tcnt, gcnt;
11: int primes[] = {23, 47, 97, 199, 397, 797, 1597, 3191, 6397, 12799, 31991, 0};
12: int *uhhash, *uchash, uhp, *ghhash, *gchash, ghp;
13: int otherok = 1; /* default policy */
14: int pfd; /* temporary file descriptor */
15: char *exbf, *realexbf; /* exception buffer */
16: char clientname[128] = "\n"; /* the client's name, newline terminated */
17:
18: clientuid() /* from client to host */
19: { int j;
20: if(client.uid < 0)
21: return(-1);
22: for(j = client.uid % uhp; uchash[j] != -1; j++)
23: if(t[uchash[j]].cuid == client.uid)
24: return(t[uchash[j]].huid);
25: return(-1);
26: }
27:
28: clientgid() /* from client to host */
29: { int j;
30: if(client.gid < 0)
31: return(-1);
32: for(j = client.gid % ghp; gchash[j] != -1; j++)
33: if(g[gchash[j]].cuid == client.gid)
34: return(g[gchash[j]].huid);
35: return(-1);
36: }
37:
38: hostuid(n) /* host to client */
39: { int j;
40: if(n < 0)
41: return(-1);
42: for(j = n % uhp; uhhash[j] != -1; j++)
43: if(t[uhhash[j]].huid == n)
44: return(t[uhhash[j]].cuid);
45: return(-1);
46: }
47:
48: hostgid(n) /* host to client */
49: { int j;
50: if(n < 0)
51: return(-1);
52: for(j = n % ghp; ghhash[j] != -1; j++)
53: if(g[ghhash[j]].huid == n)
54: return(g[ghhash[j]].cuid);
55: return(-1);
56: }
57:
58: isowner(p)
59: struct stat *p;
60: {
61: if(clientuid() == p->st_uid)
62: return(1);
63: return(0);
64: }
65:
66: searchperm()
67: { struct stat stb;
68: if(stat(nmbuf, &stb) < 0) {
69: client.errno = errno;
70: return(1);
71: }
72: if(clientuid() == stb.st_uid && (stb.st_mode & 0100))
73: return(0);
74: if(clientgid() == stb.st_gid && (stb.st_mode & 010))
75: return(0);
76: if((stb.st_mode & 1) && (otherok || clientuid() != -1))
77: return(0);
78: return(1);
79: }
80:
81: writeperm()
82: { struct stat stb;
83: if(stat(nmbuf, &stb) < 0) {
84: client.errno = errno;
85: return(1);
86: }
87: if(clientuid() == stb.st_uid && (stb.st_mode & 0200))
88: return(0);
89: if(clientgid() == stb.st_gid && (stb.st_mode & 020))
90: return(0);
91: if((stb.st_mode & 2) && (otherok || clientuid() != -1))
92: return(0);
93: client.errno = EPERM;
94: return(1);
95: }
96:
97: dirwriteperm()
98: { int n;
99: error("dw (%d,%d)\n", clientuid(), clientgid());
100: if(!slash)
101: return(1); /* this can't happen? */
102: if(clientuid() == -1 || clientgid() == -1) {
103: client.errno = EPERM;
104: return(1); /* too bad bozo */
105: }
106: *slash = 0;
107: n = writeperm();
108: *slash = '/';
109: return(n);
110: }
111:
112: /* hostdev translates from host's devs to client's */
113: hostdev(n)
114: { int i;
115: for(i = 0; i < ndev; i++)
116: if(devs[i].hdev == n)
117: return(devs[i].cdev);
118: error("hostdev: 0x%x not found\n", n);
119: client.errno = ENXIO;
120: return(0);
121: }
122:
123: /* clientdev translates from client's to host's */
124: clientdev(n)
125: { int i;
126: for(i = 0; i < ndev; i++)
127: if(devs[i].cdev == n)
128: return(devs[i].hdev);
129: debug("clientdev: 0x%x not found\n", n);
130: client.errno = ENXIO;
131: return(0);
132: }
133:
134: getuids()
135: { int i, j;
136: char msg[16];
137: /* scan host passwd file for count */
138: tcnt = cntpasswd();
139: t = (tuid *) malloc(tcnt * sizeof(tuid));
140: i = xread(cfd, inbuf, inlen);
141: if(i != inlen)
142: fatal("getuids read %d (%d)\n", i, errno);
143: /* decode and ack */
144: msg[0] = 2;
145: if(write(cfd, msg, 1) != 1)
146: fatal("getuid ack failed (%d)\n", errno);
147: /* and match with host passwd */
148: fillpasswd();
149: for(i = 0; primes[i] && primes[i] < 2 * tcnt; i++)
150: ;
151: if(primes[i] == 0)
152: fatal("tcnt %d too big for hashtable %d\n", tcnt, primes[i-1]);
153: uhp = primes[i];
154: uhhash = (int *) malloc((uhp + 4) * sizeof(int));
155: uchash = (int *) malloc((uhp + 4) * sizeof(int));
156: /* what's the chance the last 3 items will fill? */
157: for(i = 0; i < uhp + 4; i++)
158: uhhash[i] = uchash[i] = -1;
159: for(i = 0; i < tcnt; i++) {
160: j = t[i].huid % uhp;
161: while(uhhash[j] != -1)
162: j++;
163: if(j >= uhp + 3) /* guarantee sentinel at end of hash tables */
164: fatal("uhhash overflow!\n");
165: uhhash[j] = i;
166:
167: j = t[i].cuid % uhp;
168: while(uchash[j] != -1)
169: j++;
170: if(j >= uhp + 3)
171: fatal("uchash overflow!\n");
172: uchash[j] = i;
173: }
174: }
175:
176: getgids()
177: { int i, j;
178: char msg[16];
179: /* scan host group file for count */
180: gcnt = cntgroups();
181: g = (tuid *) malloc(gcnt * sizeof(tuid));
182: i = xread(cfd, inbuf, inlen);
183: if(i != inlen)
184: fatal("getgids read %d (%d)\n", i, errno);
185: /* decode and ack */
186: msg[0] = 3;
187: if(write(cfd, msg, 1) != 1)
188: fatal("getgid ack failed (%d)\n", errno);
189: /* and match with host passwd */
190: fillgroups();
191: for(i = 0; primes[i] && primes[i] < 2 * gcnt; i++)
192: ;
193: if(primes[i] == 0)
194: fatal("gcnt %d too big for hashtable %d\n", gcnt, primes[i-1]);
195: ghp = primes[i];
196: ghhash = (int *) malloc((ghp + 4) * sizeof(int));
197: gchash = (int *) malloc((ghp + 4) * sizeof(int));
198: /* what's the chance the last 3 items will fill? */
199: for(i = 0; i < ghp + 4; i++)
200: ghhash[i] = gchash[i] = -1;
201: for(i = 0; i < gcnt; i++) {
202: j = g[i].huid % ghp;
203: while(ghhash[j] != -1)
204: j++;
205: if(j >= ghp + 3) /* guarantee sentinel at end of hash tables */
206: fatal("ghhash overflow!\n");
207: ghhash[j] = i;
208:
209: j = g[i].cuid % ghp;
210: while(gchash[j] != -1)
211: j++;
212: if(j >= ghp + 3)
213: fatal("gchash overflow!\n");
214: gchash[j] = i;
215: }
216: }
217:
218: cntpasswd()
219: { struct passwd *p, *getpwent();
220: int m = 0;
221: while(p = getpwent())
222: m++;
223: setpwent(); /* leave it set for fillpasswd() */
224: return(m);
225: }
226:
227: cntgroups()
228: { struct group *g, *getgrent();
229: int m = 0;
230: while(g = getgrent()) {
231: m++;
232: }
233: setgrent(); /* leave it set for fillgroups() */
234: return(m);
235: }
236:
237: char *
238: clientline(s)
239: char *s;
240: { char *p;
241: if(!s || !*s)
242: return(0);
243: for(p = s; *p; ) {
244: if(strncmp(p, "client ", 7) == 0 || strncmp(p, "client\t", 7) == 0)
245: return(p);
246: while(*p++ != '\n');
247: ;
248: }
249: return(p);
250: }
251:
252: getexcepts()
253: { char *p, *q, *r;
254: struct stat stb;
255: pfd = open("/usr/netb/except", 0);
256: if(pfd < 0 || fstat(pfd, &stb) < 0) {
257: error("danger!!! can't find /usr/netb/except, but proceeding\n");
258: fakeit:
259: exbf = (char *) malloc(1);
260: realexbf = exbf;
261: *exbf = 0;
262: return;
263: }
264: exbf = (char *) malloc(stb.st_size + 1);
265: realexbf = exbf;
266: if(read(pfd, exbf, stb.st_size) != stb.st_size) {
267: error("danger!!! can't read /usr/netb/except, but proceeding\n");
268: free(exbf);
269: goto fakeit;
270: }
271: close(pfd);
272: /* now find the section for this client */
273: for(q = 0, p = clientline(exbf); *p; p = clientline(p)) {
274: if(q) {
275: *p = 0;
276: exbf = q;
277: error("found excepts for client %s");
278: return;
279: }
280: r = p + 6; /* skip across "client " */
281: while(*r == ' ' || *r == '\t')
282: r++;
283: if(strncmp(r, clientname, strlen(clientname)) == 0)
284: q = p;
285: while(*p++ != '\n')
286: ;
287: }
288: error("warning!!! no match for client %s", clientname);
289: /* look for the default client */
290: for(q = 0, p = clientline(exbf); *p && !q; p = clientline(p+1)) {
291: r = p + 6; /* skip across "client " */
292: while(*r == ' ' || *r == '\t')
293: r++;
294: if(*r == '*' && r[1] == '\n')
295: q = p;
296: }
297: if(q) {
298: exbf = q;
299: error("using default client info\n");
300: return;
301: }
302: error("warning!!! no default client info, proceeding anyway\n");
303: }
304:
305: char *
306: findexcept(tag, s)
307: char *tag, *s;
308: { char *p, *q;
309: int n;
310: n = strlen(tag);
311: p = exbf;
312: loop:
313: if(*p == 0)
314: return(s);
315: if(strncmp(tag, p, n) != 0) {
316: eol:
317: while(*p && *p++ != '\n')
318: ;
319: goto loop;
320: }
321: for(p += n; *p == ' ' || *p == '\t'; p++)
322: ; /* skip the tag and whitespace */
323: for(q = s; *p == *q; p++, q++)
324: ;
325: if(*q != 0 || *p != '=')
326: goto eol;
327: if(p[1] == ' ' || p[1] == '\t' || p[1] == '\n')
328: return(0); /* client not allowed */
329: return(p+1);
330: }
331:
332: doneexcepts()
333: { char *s;
334: s = findexcept("param", "otherok");
335: if(s && *s == '0')
336: otherok = 0;
337: error("otherok %d\n", otherok);
338: /* umask could be settable too */
339: umask(0);
340: free(realexbf);
341: realexbf = exbf = (char *) -1; /* dereference that */
342: }
343:
344: char *
345: findid(t, s)
346: char *t, *s;
347: { char *p, *q;
348: s = findexcept(t, s);
349: if(!s)
350: return(0);
351: p = (char *)inbuf;
352: loop:
353: if(*p == 0)
354: return(0);
355: for(q = s; *p == *q; p++, q++)
356: ;
357: if((*q == 0 || *q == ' ' || *q == '\t' || *q == '\n') && *p == ' ')
358: return(p+1);
359: while(*p && *p != '\n')
360: p++;
361: if(*p == '\n')
362: p++;
363: goto loop;
364: }
365:
366: fillpasswd() /* quadratic */
367: { struct passwd *p, *getpwent();
368: char *s;
369: int i = 0;
370: while(p = getpwent()) {
371: s = findid("uid", p->pw_name);
372: if(s == 0)
373: continue;
374: t[i].huid = p->pw_uid;
375: t[i].cuid = atoi(s);
376: i++;
377: }
378: error("matched %d passwds out of %d\n", i, tcnt);
379: tcnt = i;
380: endpwent();
381: }
382:
383: fillgroups() /* quadratic */
384: { struct group *p, *getgrent();
385: char *s;
386: int i = 0;
387: while(p = getgrent()) {
388: s = findid("gid", p->gr_name);
389: if(s == 0)
390: continue;
391: g[i].huid = p->gr_gid;
392: g[i].cuid = atoi(s);
393: i++;
394: }
395: error("matched %d groups out of %d\n", i, gcnt);
396: gcnt = i;
397: endgrent();
398: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.