xref: /plan9/sys/src/cmd/disk/kfs/uid.c (revision a84536681645e23c630ce4ef2e5c3b284d4c590b)
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 	if(con_clone(FID1, FID2))
155 		goto ainitu;
156 	if(con_path(FID2, "/adm/users"))
157 		goto ainitu;
158 	if(con_open(FID2, 0)){
159 		goto ainitu;
160 	}
161 
162 	wlock(&uidgc.uidlock);
163 	uidgc.uidbuf = malloc(MAXDAT);
164 
165 	memset(uid, 0, conf.nuid * sizeof(*uid));
166 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
167 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
168 
169 	uidgc.flen = 0;
170 	uidgc.find = 0;
171 	cons.offset = 0;
172 	u = 0;
173 	o = conf.uidspace;
174 
175 ul1:
176 	c = fname(name);
177 	if(c != ':')
178 		goto uskip;
179 	n = atol(name);
180 	if(n == 0)
181 		goto uskip;
182 	c = fname(name);
183 	if(c != ':')
184 		goto uskip;
185 	o -= strlen(name)+1;
186 	if(o < 0) {
187 		cprint("conf.uidspace(%ld) too small\n", conf.uidspace);
188 		goto initu;
189 	}
190 	strcpy(uidspace+o, name);
191 	uid[u].uid = n;
192 	uid[u].offset = o;
193 	u++;
194 	if(u >= conf.nuid) {
195 		cprint("conf.nuid(%ld) too small\n", conf.nuid);
196 		goto initu;
197 	}
198 
199 uskip:
200 	if(c == '\n')
201 		goto ul1;
202 	if(c) {
203 		c = fname(name);
204 		goto uskip;
205 	}
206 /*	cprint("%d uids read\n", u);/**/
207 	qsort(uid, u, sizeof(uid[0]), byuid);
208 	for(c=u-1; c>0; c--)
209 		if(uid[c].uid == uid[c-1].uid) {
210 			cprint("duplicate uids: %d\n", uid[c].uid);
211 			cprint("	%s", uidspace+uid[c].offset);
212 			cprint(" %s\n", uidspace+uid[c-1].offset);
213 		}
214 	qsort(uid, u, sizeof(uid[0]), byname);
215 	for(c=u-1; c>0; c--)
216 		if(!strcmp(uidspace+uid[c].offset,
217 		   uidspace+uid[c-1].offset)) {
218 			cprint("kfs: duplicate names: %s\n", uidspace+uid[c].offset);
219 			cprint("	%d", uid[c].uid);
220 			cprint(" %d\n", uid[c-1].uid);
221 		}
222 	if(cons.flags & Fuid)
223 		for(c=0; c<u; c++)
224 			cprint("%6d %s\n", uid[c].uid, uidspace+uid[c].offset);
225 
226 	uidgc.flen = 0;
227 	uidgc.find = 0;
228 	cons.offset = 0;
229 	g = 0;
230 
231 gl1:
232 	c = fname(name);
233 	if(c != ':')
234 		goto gskip;
235 	n = atol(name);		/* number */
236 	if(n == 0)
237 		goto gskip;
238 	c = fname(name);	/* name */
239 	if(c != ':')
240 		goto gskip;
241 	c = fname(name);	/* leader */
242 	if(c != ':')
243 		goto gskip;
244 	o = strtouid1(name);
245 	if(o == 0 && strcmp(name, "") != 0)
246 		o = n;
247 	for(c=0; c<u; c++)
248 		if(uid[c].uid == n) {
249 			uid[c].lead = o;
250 			break;
251 		}
252 	c = fname(name);	/* list of members */
253 	if(c != ',' && c != '\n')
254 		goto gskip;
255 	if(!name[0])
256 		goto gskip;
257 	gidspace[g++] = n;
258 gl2:
259 	n = strtouid1(name);
260 	if(n)
261 		gidspace[g++] = n;
262 	if(g >= conf.gidspace-2) {
263 		cprint("conf.gidspace(%ld) too small\n", conf.gidspace);
264 		goto initu;
265 	}
266 	if(c == '\n')
267 		goto gl3;
268 	c = fname(name);
269 	if(c == ',' || c == '\n')
270 		goto gl2;
271 	cprint("gid truncated\n");
272 
273 gl3:
274 	gidspace[g++] = 0;
275 
276 gskip:
277 	if(c == '\n')
278 		goto gl1;
279 	if(c) {
280 		c = fname(name);
281 		goto gskip;
282 	}
283 	if(cons.flags & Fuid) {
284 		o = 0;
285 		for(c=0; c<g; c++) {
286 			n = gidspace[c];
287 			if(n == 0) {
288 				o = 0;
289 				continue;
290 			}
291 			uidtostr1(name, n);
292 			if(o) {
293 				if(o > 6) {
294 					cprint("\n       %s", name);
295 					o = 1;
296 				} else
297 					cprint(" %s", name);
298 			} else
299 				cprint("\n%6s", name);
300 			o++;
301 		}
302 		cprint("\n");
303 	}
304 	goto out;
305 
306 ainitu:
307 	wlock(&uidgc.uidlock);
308 	uidgc.uidbuf = malloc(MAXDAT);
309 
310 initu:
311 	cprint("initializing minimal user table\n");
312 	memset(uid, 0, conf.nuid * sizeof(*uid));
313 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
314 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
315 	o = conf.uidspace;
316 	u = 0;
317 
318 	for(i=0; admusers[i].name; i++){
319 		o -= strlen(admusers[i].name)+1;
320 		strcpy(uidspace+o, admusers[i].name);
321 		uid[u].uid = admusers[i].uid;
322 		uid[u].lead = admusers[i].leader;
323 		uid[u].offset = o;
324 		u++;
325 	}
326 
327 out:
328 	free(uidgc.uidbuf);
329 	writegroup = strtouid1("write");
330 	wunlock(&uidgc.uidlock);
331 
332 }
333 
334 void
335 uidtostr(char *name, int id)
336 {
337 	rlock(&uidgc.uidlock);
338 	uidtostr1(name, id);
339 	runlock(&uidgc.uidlock);
340 }
341 
342 void
343 uidtostr1(char *name, int id)
344 {
345 	Uid *u;
346 	int i;
347 
348 	if(id == 0){
349 		strncpy(name, "none", NAMELEN);
350 		return;
351 	}
352 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
353 		if(u->uid == id) {
354 			strncpy(name, uidspace+u->offset, NAMELEN);
355 			return;
356 		}
357 	}
358 	strncpy(name, "none", NAMELEN);
359 }
360 
361 int
362 strtouid(char *s)
363 {
364 	int i;
365 
366 	rlock(&uidgc.uidlock);
367 	i = strtouid1(s);
368 	runlock(&uidgc.uidlock);
369 	return i;
370 }
371 
372 int
373 strtouid1(char *s)
374 {
375 	Uid *u;
376 	int i;
377 
378 	for(i=0, u=uid; i<conf.nuid; i++,u++)
379 		if(!strcmp(s, uidspace+u->offset))
380 			return u->uid;
381 	return 0;
382 }
383 
384 int
385 ingroup(int u, int g)
386 {
387 	short *p;
388 
389 	if(u == g)
390 		return 1;
391 	rlock(&uidgc.uidlock);
392 	for(p=gidspace; *p;) {
393 		if(*p != g) {
394 			for(p++; *p++;)
395 				;
396 			continue;
397 		}
398 		for(p++; *p; p++)
399 			if(*p == u) {
400 				runlock(&uidgc.uidlock);
401 				return 1;
402 			}
403 	}
404 	runlock(&uidgc.uidlock);
405 	return 0;
406 }
407 
408 int
409 leadgroup(int ui, int gi)
410 {
411 	Uid *u;
412 	int i;
413 
414 	rlock(&uidgc.uidlock);
415 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
416 		if(u->uid == gi) {
417 			i = u->lead;
418 			runlock(&uidgc.uidlock);
419 			if(i == ui)
420 				return 1;
421 			if(i == 0)
422 				return ingroup(ui, gi);
423 			return 0;
424 		}
425 	}
426 	runlock(&uidgc.uidlock);
427 	return 0;
428 }
429