xref: /plan9/sys/src/cmd/disk/kfs/uid.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
1 #include "all.h"
2 
3 struct
4 {
5 	RWLock	uidlock;
6 	char*	uidbuf;
7 	int	flen;
8 	int	find;
9 } uidgc;
10 
11 int
12 byuid(void *a1, void *a2)
13 {
14 	Uid *u1, *u2;
15 
16 	u1 = a1;
17 	u2 = a2;
18 	return u2->uid - u1->uid;
19 }
20 
21 int
22 byname(void *a1, void *a2)
23 {
24 	Uid *u1, *u2;
25 
26 	u1 = a1;
27 	u2 = a2;
28 	return strcmp(uidspace+u2->offset, uidspace+u1->offset);
29 }
30 
31 int
32 fchar(void)
33 {
34 
35 	if(uidgc.find >= uidgc.flen) {
36 		uidgc.find = 0;
37 		uidgc.flen = con_read(FID2, uidgc.uidbuf, cons.offset, MAXDAT);
38 		if(uidgc.flen <= 0)
39 			return 0;
40 		cons.offset += uidgc.flen;
41 	}
42 	return uidgc.uidbuf[uidgc.find++];
43 }
44 
45 int
46 fname(char *name)
47 {
48 	int i, c;
49 
50 	memset(name, 0, NAMELEN);
51 	for(i=0;; i++) {
52 		c = fchar();
53 		switch(c) {
54 		case ':':
55 		case '\n':
56 		case ',':
57 		case ' ':
58 		case '#':
59 		case 0:
60 			return c;
61 		}
62 		if(i < NAMELEN-1)
63 			name[i] = c;
64 	}
65 	return -1;
66 }
67 
68 #ifdef sometime
69 /*
70  * file format is
71  * uid:name:lead:member,member,...\n
72  */
73 void
74 read_user(void)
75 {
76 	int c;
77 
78 	if((c=fname(ustr))!=':' || (c=fname(name))!=':' || (c=fname(lead))!=':')
79 		goto skipline;
80 	n = atol(ustr);
81 	if(n == 0)
82 		goto skipline;
83 	if(readu){
84 		o -= strlen(name)+1;
85 		if(o < 0) {
86 			cprint("conf.uidspace(%ld) too small\n", conf.uidspace);
87 			return -1;
88 		}
89 		strcpy(uidspace+o, name);
90 		uid[u].uid = n;
91 		uid[u].offset = o;
92 		u++;
93 		if(u >= conf.nuid) {
94 			cprint("conf.nuid(%ld) too small\n", conf.nuid);
95 			goto initu;
96 		}
97 	}else{
98 		o = strtouid1(name);
99 		if(o == 0 && strcmp(name, "") != 0)
100 			o = n;
101 		for(c=0; c<u; c++)
102 			if(uid[c].uid == n) {
103 				uid[c].lead = o;
104 				break;
105 			}
106 		while(((c=fname(name))==',' || c=='\n') && name[0]){
107 work here
108 			if(c=='\n')
109 				break;
110 		}
111 	}
112 
113 skipline:
114 	while(c != '\n')
115 		fname(ustr);
116 }
117 #endif
118 
119 /*
120 	-1:adm:adm:
121 	0:none:adm:
122 	1:tor:tor:
123 	10000:sys::
124 	10001:map:map:
125 	10002:doc::
126 	10003:upas:upas:
127 	10004:font::
128 	10005:bootes:bootes:
129 */
130 
131 struct {
132 	int	uid;
133 	char	*name;
134 	int	leader;
135 }
136 admusers[] = {
137 	-1,	"adm",	-1,
138 	 0,	"none",	-1,
139 	 1,	"tor",	1,
140 	 2,	"glenda",	2,
141 	10000,	"sys",	0,
142 	10001,	"upas",	10001,
143 	10002,	"bootes",	10002,
144 	0,	0,	0,
145 };
146 
147 
148 void
149 cmd_user(void)
150 {
151 	int c, n, o, u, g, i;
152 	char name[NAMELEN];
153 
154 	wlock(&uidgc.uidlock);
155 	uidgc.uidbuf = malloc(MAXDAT);
156 
157 	memset(uid, 0, conf.nuid * sizeof(*uid));
158 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
159 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
160 
161 	if(con_clone(FID1, FID2))
162 		goto initu;
163 	if(con_path(FID2, "/adm/users"))
164 		goto initu;
165 	if(con_open(FID2, 0))
166 		goto initu;
167 
168 	uidgc.flen = 0;
169 	uidgc.find = 0;
170 	cons.offset = 0;
171 	u = 0;
172 	o = conf.uidspace;
173 
174 ul1:
175 	c = fname(name);
176 	if(c != ':')
177 		goto uskip;
178 	n = atol(name);
179 	if(n == 0)
180 		goto uskip;
181 	c = fname(name);
182 	if(c != ':')
183 		goto uskip;
184 	o -= strlen(name)+1;
185 	if(o < 0) {
186 		cprint("conf.uidspace(%ld) too small\n", conf.uidspace);
187 		goto initu;
188 	}
189 	strcpy(uidspace+o, name);
190 	uid[u].uid = n;
191 	uid[u].offset = o;
192 	u++;
193 	if(u >= conf.nuid) {
194 		cprint("conf.nuid(%ld) too small\n", conf.nuid);
195 		goto initu;
196 	}
197 
198 uskip:
199 	if(c == '\n')
200 		goto ul1;
201 	if(c) {
202 		c = fname(name);
203 		goto uskip;
204 	}
205 /*	cprint("%d uids read\n", u);/**/
206 	qsort(uid, u, sizeof(uid[0]), byuid);
207 	for(c=u-1; c>0; c--)
208 		if(uid[c].uid == uid[c-1].uid) {
209 			cprint("duplicate uids: %d\n", uid[c].uid);
210 			cprint("	%s", uidspace+uid[c].offset);
211 			cprint(" %s\n", uidspace+uid[c-1].offset);
212 		}
213 	qsort(uid, u, sizeof(uid[0]), byname);
214 	for(c=u-1; c>0; c--)
215 		if(!strcmp(uidspace+uid[c].offset,
216 		   uidspace+uid[c-1].offset)) {
217 			cprint("kfs: duplicate names: %s\n", uidspace+uid[c].offset);
218 			cprint("	%d", uid[c].uid);
219 			cprint(" %d\n", uid[c-1].uid);
220 		}
221 	if(cons.flags & Fuid)
222 		for(c=0; c<u; c++)
223 			cprint("%6d %s\n", uid[c].uid, uidspace+uid[c].offset);
224 
225 	uidgc.flen = 0;
226 	uidgc.find = 0;
227 	cons.offset = 0;
228 	g = 0;
229 
230 gl1:
231 	c = fname(name);
232 	if(c != ':')
233 		goto gskip;
234 	n = atol(name);		/* number */
235 	if(n == 0)
236 		goto gskip;
237 	c = fname(name);	/* name */
238 	if(c != ':')
239 		goto gskip;
240 	c = fname(name);	/* leader */
241 	if(c != ':')
242 		goto gskip;
243 	o = strtouid1(name);
244 	if(o == 0 && strcmp(name, "") != 0)
245 		o = n;
246 	for(c=0; c<u; c++)
247 		if(uid[c].uid == n) {
248 			uid[c].lead = o;
249 			break;
250 		}
251 	c = fname(name);	/* list of members */
252 	if(c != ',' && c != '\n')
253 		goto gskip;
254 	if(!name[0])
255 		goto gskip;
256 	gidspace[g++] = n;
257 gl2:
258 	n = strtouid1(name);
259 	if(n)
260 		gidspace[g++] = n;
261 	if(g >= conf.gidspace-2) {
262 		cprint("conf.gidspace(%ld) too small\n", conf.gidspace);
263 		goto initu;
264 	}
265 	if(c == '\n')
266 		goto gl3;
267 	c = fname(name);
268 	if(c == ',' || c == '\n')
269 		goto gl2;
270 	cprint("gid truncated\n");
271 
272 gl3:
273 	gidspace[g++] = 0;
274 
275 gskip:
276 	if(c == '\n')
277 		goto gl1;
278 	if(c) {
279 		c = fname(name);
280 		goto gskip;
281 	}
282 	if(cons.flags & Fuid) {
283 		o = 0;
284 		for(c=0; c<g; c++) {
285 			n = gidspace[c];
286 			if(n == 0) {
287 				o = 0;
288 				continue;
289 			}
290 			uidtostr1(name, n);
291 			if(o) {
292 				if(o > 6) {
293 					cprint("\n       %s", name);
294 					o = 1;
295 				} else
296 					cprint(" %s", name);
297 			} else
298 				cprint("\n%6s", name);
299 			o++;
300 		}
301 		cprint("\n");
302 	}
303 	goto out;
304 
305 initu:
306 	cprint("initializing minimal user table\n");
307 	memset(uid, 0, conf.nuid * sizeof(*uid));
308 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
309 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
310 	o = conf.uidspace;
311 	u = 0;
312 
313 	for(i=0; admusers[i].name; i++){
314 		o -= strlen(admusers[i].name)+1;
315 		strcpy(uidspace+o, admusers[i].name);
316 		uid[u].uid = admusers[i].uid;
317 		uid[u].lead = admusers[i].leader;
318 		uid[u].offset = o;
319 		u++;
320 	}
321 
322 out:
323 	free(uidgc.uidbuf);
324 	writegroup = strtouid1("write");
325 	wunlock(&uidgc.uidlock);
326 
327 }
328 
329 void
330 uidtostr(char *name, int id)
331 {
332 	rlock(&uidgc.uidlock);
333 	uidtostr1(name, id);
334 	runlock(&uidgc.uidlock);
335 }
336 
337 void
338 uidtostr1(char *name, int id)
339 {
340 	Uid *u;
341 	int i;
342 
343 	if(id == 0){
344 		strncpy(name, "none", NAMELEN);
345 		return;
346 	}
347 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
348 		if(u->uid == id) {
349 			strncpy(name, uidspace+u->offset, NAMELEN);
350 			return;
351 		}
352 	}
353 	strncpy(name, "none", NAMELEN);
354 }
355 
356 int
357 strtouid(char *s)
358 {
359 	int i;
360 
361 	rlock(&uidgc.uidlock);
362 	i = strtouid1(s);
363 	runlock(&uidgc.uidlock);
364 	return i;
365 }
366 
367 int
368 strtouid1(char *s)
369 {
370 	Uid *u;
371 	int i;
372 
373 	for(i=0, u=uid; i<conf.nuid; i++,u++)
374 		if(!strcmp(s, uidspace+u->offset))
375 			return u->uid;
376 	return 0;
377 }
378 
379 int
380 ingroup(int u, int g)
381 {
382 	short *p;
383 
384 	if(u == g)
385 		return 1;
386 	rlock(&uidgc.uidlock);
387 	for(p=gidspace; *p;) {
388 		if(*p != g) {
389 			for(p++; *p++;)
390 				;
391 			continue;
392 		}
393 		for(p++; *p; p++)
394 			if(*p == u) {
395 				runlock(&uidgc.uidlock);
396 				return 1;
397 			}
398 	}
399 	runlock(&uidgc.uidlock);
400 	return 0;
401 }
402 
403 int
404 leadgroup(int ui, int gi)
405 {
406 	Uid *u;
407 	int i;
408 
409 	rlock(&uidgc.uidlock);
410 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
411 		if(u->uid == gi) {
412 			i = u->lead;
413 			runlock(&uidgc.uidlock);
414 			if(i == ui)
415 				return 1;
416 			if(i == 0)
417 				return ingroup(ui, gi);
418 			return 0;
419 		}
420 	}
421 	runlock(&uidgc.uidlock);
422 	return 0;
423 }
424