xref: /plan9/sys/src/cmd/disk/kfs/uid.c (revision b85a83648eec38fe82b6f00adfd7828ceec5ee8d)
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
byuid(void * a1,void * a2)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
byname(void * a1,void * a2)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
fchar(void)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
fname(char * name)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 }
66 
67 #ifdef sometime
68 /*
69  * file format is
70  * uid:name:lead:member,member,...\n
71  */
72 void
read_user(void)73 read_user(void)
74 {
75 	int c;
76 
77 	if((c=fname(ustr))!=':' || (c=fname(name))!=':' || (c=fname(lead))!=':')
78 		goto skipline;
79 	n = atol(ustr);
80 	if(n == 0)
81 		goto skipline;
82 	if(readu){
83 		o -= strlen(name)+1;
84 		if(o < 0) {
85 			cprint("conf.uidspace(%ld) too small\n", conf.uidspace);
86 			return -1;
87 		}
88 		strcpy(uidspace+o, name);
89 		uid[u].uid = n;
90 		uid[u].offset = o;
91 		u++;
92 		if(u >= conf.nuid) {
93 			cprint("conf.nuid(%ld) too small\n", conf.nuid);
94 			goto initu;
95 		}
96 	}else{
97 		o = strtouid1(name);
98 		if(o == 0 && strcmp(name, "") != 0)
99 			o = n;
100 		for(c=0; c<u; c++)
101 			if(uid[c].uid == n) {
102 				uid[c].lead = o;
103 				break;
104 			}
105 		while(((c=fname(name))==',' || c=='\n') && name[0]){
106 work here
107 			if(c=='\n')
108 				break;
109 		}
110 	}
111 
112 skipline:
113 	while(c != '\n')
114 		fname(ustr);
115 }
116 #endif
117 
118 /*
119 	-1:adm:adm:
120 	0:none:adm:
121 	1:tor:tor:
122 	10000:sys::
123 	10001:map:map:
124 	10002:doc::
125 	10003:upas:upas:
126 	10004:font::
127 	10005:bootes:bootes:
128 */
129 
130 struct {
131 	int	uid;
132 	char	*name;
133 	int	leader;
134 }
135 admusers[] = {
136 	-1,	"adm",	-1,
137 	 0,	"none",	-1,
138 	 1,	"tor",	1,
139 	 2,	"glenda",	2,
140 	10000,	"sys",	0,
141 	10001,	"upas",	10001,
142 	10002,	"bootes",	10002,
143 	0,	0,	0,
144 };
145 
146 
147 void
cmd_user(void)148 cmd_user(void)
149 {
150 	int c, n, o, u, g, i;
151 	char name[NAMELEN];
152 
153 	if(con_clone(FID1, FID2))
154 		goto ainitu;
155 	if(con_path(FID2, "/adm/users"))
156 		goto ainitu;
157 	if(con_open(FID2, 0)){
158 		goto ainitu;
159 	}
160 
161 	wlock(&uidgc.uidlock);
162 	uidgc.uidbuf = malloc(MAXDAT);
163 
164 	memset(uid, 0, conf.nuid * sizeof(*uid));
165 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
166 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
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 ainitu:
306 	wlock(&uidgc.uidlock);
307 	uidgc.uidbuf = malloc(MAXDAT);
308 
309 initu:
310 	cprint("initializing minimal user table\n");
311 	memset(uid, 0, conf.nuid * sizeof(*uid));
312 	memset(uidspace, 0, conf.uidspace * sizeof(*uidspace));
313 	memset(gidspace, 0, conf.gidspace * sizeof(*gidspace));
314 	o = conf.uidspace;
315 	u = 0;
316 
317 	for(i=0; admusers[i].name; i++){
318 		o -= strlen(admusers[i].name)+1;
319 		strcpy(uidspace+o, admusers[i].name);
320 		uid[u].uid = admusers[i].uid;
321 		uid[u].lead = admusers[i].leader;
322 		uid[u].offset = o;
323 		u++;
324 	}
325 
326 out:
327 	free(uidgc.uidbuf);
328 	writegroup = strtouid1("write");
329 	wunlock(&uidgc.uidlock);
330 
331 }
332 
333 void
uidtostr(char * name,int id)334 uidtostr(char *name, int id)
335 {
336 	rlock(&uidgc.uidlock);
337 	uidtostr1(name, id);
338 	runlock(&uidgc.uidlock);
339 }
340 
341 void
uidtostr1(char * name,int id)342 uidtostr1(char *name, int id)
343 {
344 	Uid *u;
345 	int i;
346 
347 	if(id == 0){
348 		strncpy(name, "none", NAMELEN);
349 		return;
350 	}
351 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
352 		if(u->uid == id) {
353 			strncpy(name, uidspace+u->offset, NAMELEN);
354 			return;
355 		}
356 	}
357 	strncpy(name, "none", NAMELEN);
358 }
359 
360 int
strtouid(char * s)361 strtouid(char *s)
362 {
363 	int i;
364 
365 	rlock(&uidgc.uidlock);
366 	i = strtouid1(s);
367 	runlock(&uidgc.uidlock);
368 	return i;
369 }
370 
371 int
strtouid1(char * s)372 strtouid1(char *s)
373 {
374 	Uid *u;
375 	int i;
376 
377 	for(i=0, u=uid; i<conf.nuid; i++,u++)
378 		if(!strcmp(s, uidspace+u->offset))
379 			return u->uid;
380 	return 0;
381 }
382 
383 int
ingroup(int u,int g)384 ingroup(int u, int g)
385 {
386 	short *p;
387 
388 	if(u == g)
389 		return 1;
390 	rlock(&uidgc.uidlock);
391 	for(p=gidspace; *p;) {
392 		if(*p != g) {
393 			for(p++; *p++;)
394 				;
395 			continue;
396 		}
397 		for(p++; *p; p++)
398 			if(*p == u) {
399 				runlock(&uidgc.uidlock);
400 				return 1;
401 			}
402 	}
403 	runlock(&uidgc.uidlock);
404 	return 0;
405 }
406 
407 int
leadgroup(int ui,int gi)408 leadgroup(int ui, int gi)
409 {
410 	Uid *u;
411 	int i;
412 
413 	rlock(&uidgc.uidlock);
414 	for(i=0, u=uid; i<conf.nuid; i++,u++) {
415 		if(u->uid == gi) {
416 			i = u->lead;
417 			runlock(&uidgc.uidlock);
418 			if(i == ui)
419 				return 1;
420 			if(i == 0)
421 				return ingroup(ui, gi);
422 			return 0;
423 		}
424 	}
425 	runlock(&uidgc.uidlock);
426 	return 0;
427 }
428