xref: /plan9/sys/src/cmd/9nfs/unixnames.c (revision 4fc7c3569bd2d80cd473f6db4bc2d3605434c9fb)
1 #include "all.h"
2 
3 static void	uxfree(Unixid*);
4 
5 static Unixid *	xfree;
6 
7 Unixidmap *idhead, *idtail;
8 
9 Unixscmap *scmap;
10 
11 #define	UNUSED	0x7FFFFFFF
12 
13 /*
14  * Sadly we have to use the IP address, since some systems (FreeBSD in particular)
15  * do not believe it to be safe to depend on the hostname and so refuse to send it.
16  * I dislike making this IP-centric, but so be it.
17  * We keep a cache of host names in getdom.
18  */
19 Unixidmap *
pair2idmap(char * server,ulong clientip)20 pair2idmap(char *server, ulong clientip)
21 {
22 	Resub match;
23 	Unixscmap *m, *mp;
24 	Unixidmap *r;
25 	char dom[256];
26 
27 	for(mp=0,m=scmap; m; mp=m,m=m->next){
28 		if(m->server[0] != server[0])
29 			continue;
30 		if(strcmp(m->server, server))
31 			continue;
32 		if(m->clientip != clientip)
33 			continue;
34 		if(mp){
35 			mp->next = m->next;
36 			m->next = scmap;
37 			scmap = m;
38 		}
39 		r = m->map;
40 		if(r->u.timestamp != 0 && r->g.timestamp != 0)
41 			return r;
42 		scmap = m->next;
43 		free(m);
44 		break;
45 	}
46 	if(rpcdebug)
47 		fprint(2, "looking for %lux\n", clientip);
48 	if(getdom(clientip, dom, sizeof dom)<0){
49 		clog("auth: unknown ip address");
50 		return nil;
51 	}
52 	if(rpcdebug)
53 		fprint(2, "dom is %s\n", dom);
54 	for(r=idhead; r; r=r->next){
55 		if(r->u.timestamp == 0 || r->g.timestamp == 0)
56 			continue;
57 		match.sp = match.ep = 0;
58 		if(regexec(r->sexp, server, &match, 1) == 0)
59 			continue;
60 		if(match.sp != server || match.ep <= match.sp || *match.ep)
61 			continue;
62 		match.sp = match.ep = 0;
63 		if(regexec(r->cexp, dom, &match, 1) == 0)
64 			continue;
65 		if(match.sp != dom || match.ep <= match.sp || *match.ep)
66 			continue;
67 		m = malloc(sizeof(Unixscmap));
68 		m->next = scmap;
69 		scmap = m;
70 		m->server = strstore(server);
71 		m->clientip = clientip;
72 		m->map = r;
73 		break;
74 	}
75 	return r;
76 }
77 
78 int
readunixidmaps(char * file)79 readunixidmaps(char *file)
80 {
81 	Waitmsg *w;
82 	Biobuf *in;
83 	Unixidmap *m;
84 	int i, arc; char *arv[16], buf[256];
85 	char *l;
86 // 	long savalarm;
87 
88 // 	savalarm = alarm(0);
89 	in = Bopen(file, OREAD);
90 	if(in == 0){
91 		clog("readunixidmaps can't open %s: %r\n", file);
92 //		alarm(savalarm);
93 		return -1;
94 	}
95 	for(m=idhead; m; m=m->next)
96 		m->flag = 0;
97 	while(l = Brdline(in, '\n')){	/* assign = */
98 		l[Blinelen(in)-1] = 0;
99 		arc = strparse(l, nelem(arv), arv);
100 		if(arc > 0 && arv[0][0] == '!'){
101 			++arv[0];
102 			snprint(buf, sizeof buf, "/bin/%s", arv[0]);
103 			if(chatty){
104 				chat("!");
105 				for(i=0; i<arc; i++)
106 					chat(" %s", arv[i]);
107 				chat("...");
108 			}
109 			w = system(buf, arv);
110 			if(w == nil)
111 				chat("err: %r\n");
112 			else if(w->msg && w->msg[0])
113 				chat("status: %s\n", w->msg);
114 			else
115 				chat("OK\n");
116 			free(w);
117 			continue;
118 		}
119 		if(arc != 4)
120 			continue;
121 		for(m=idhead; m; m=m->next)
122 			if(strcmp(arv[0], m->server) == 0 &&
123 			   strcmp(arv[1], m->client) == 0)
124 				break;
125 		if(m == 0){
126 			m = malloc(sizeof(Unixidmap));
127 			if(idtail)
128 				idtail->next = m;
129 			else
130 				idhead = m;
131 			idtail = m;
132 			m->next = 0;
133 			m->server = strstore(arv[0]);
134 			m->client = strstore(arv[1]);
135 			m->sexp = regcomp(m->server);
136 			m->cexp = regcomp(m->client);
137 			m->u.file = strstore(arv[2]);
138 			m->u.style = 'u';
139 			m->u.timestamp = 0;
140 			m->u.ids = 0;
141 			m->g.file = strstore(arv[3]);
142 			m->g.style = 'u';
143 			m->g.timestamp = 0;
144 			m->g.ids = 0;
145 		}else{
146 			if(!m->u.file || strcmp(m->u.file, arv[2]) != 0){
147 				m->u.file = strstore(arv[2]);
148 				m->u.timestamp = 0;
149 			}
150 			if(!m->g.file || strcmp(m->g.file, arv[3]) != 0){
151 				m->g.file = strstore(arv[3]);
152 				m->g.timestamp = 0;
153 			}
154 		}
155 		m->flag = 1;
156 		checkunixmap(&m->u);
157 		checkunixmap(&m->g);
158 	}
159 	Bterm(in);
160 	for(m=idhead; m; m=m->next)
161 		if(m->flag == 0){
162 			m->u.file = 0;
163 			m->u.timestamp = 0;
164 			uxfree(m->u.ids);
165 			m->u.ids = 0;
166 			m->g.file = 0;
167 			m->g.timestamp = 0;
168 			uxfree(m->g.ids);
169 			m->g.ids = 0;
170 		}
171 // 	alarm(savalarm);
172 	return 0;
173 }
174 
175 static void
uxfree(Unixid * x)176 uxfree(Unixid *x)
177 {
178 	Unixid *tail;
179 	int count=0;
180 
181 	if(x){
182 		tail = x;
183 		if(tail->id < 0)
184 			abort();
185 		tail->id = UNUSED;
186 		while(tail->next){
187 			tail = tail->next;
188 			++count;
189 			if(tail->id == UNUSED)
190 				abort();
191 			tail->id = UNUSED;
192 		}
193 		tail->next = xfree;
194 		xfree = x;
195 	}
196 }
197 
198 int
checkunixmap(Unixmap * u)199 checkunixmap(Unixmap *u)
200 {
201 	Dir *dir;
202 
203 	dir = dirstat(u->file);
204 	if(dir == nil){
205 		clog("checkunixmap can't stat %s: %r\n", u->file);
206 		return -1;
207 	}
208 	if(u->timestamp > dir->mtime){
209 		free(dir);
210 		return 0;
211 	}
212 	uxfree(u->ids);
213 	u->ids = readunixids(u->file, u->style);
214 	u->timestamp = time(0);
215 	free(dir);
216 	return 1;
217 }
218 
219 int
name2id(Unixid ** list,char * name)220 name2id(Unixid **list, char *name)
221 {
222 	Unixid *x, *xp;
223 
224 	for(xp=0,x=*list; x; xp=x,x=x->next){
225 		if(x->name[0] == name[0] && strcmp(x->name, name) == 0){
226 			if(xp){
227 				xp->next = x->next;
228 				x->next = *list;
229 				*list = x;
230 			}
231 			return x->id;
232 		}
233 	}
234 	return -1;
235 }
236 
237 char *
id2name(Unixid ** list,int id)238 id2name(Unixid **list, int id)
239 {
240 	Unixid *x, *xp;
241 
242 	for(xp=0,x=*list; x; xp=x,x=x->next){
243 		if(x->id == id){
244 			if(xp){
245 				xp->next = x->next;
246 				x->next = *list;
247 				*list = x;
248 			}
249 			return x->name;
250 		}
251 	}
252 	return "none";
253 }
254 
255 void
idprint(int fd,Unixid * xp)256 idprint(int fd, Unixid *xp)
257 {
258 	while(xp){
259 		fprint(fd, "%d\t%s\n", xp->id, xp->name);
260 		xp = xp->next;
261 	}
262 }
263 
264 /*
265  *	style '9': 3:tom:tom:
266  *	style 'u': sysadm:*:0:0:System-Administrator:/usr/admin:/bin/sh
267  */
268 
269 Unixid *
readunixids(char * file,int style)270 readunixids(char *file, int style)
271 {
272 	Biobuf *in;
273 	char *l, *name = 0;
274 	Unixid *x, *xp = 0;
275 	int id = 0;
276 
277 	in = Bopen(file, OREAD);
278 	if(in == 0){
279 		clog("readunixids can't open %s: %r\n", file);
280 		return 0;
281 	}
282 	while(l = Brdline(in, '\n')){	/* assign = */
283 		l[Blinelen(in)-1] = 0;
284 		switch(style){
285 		case '9':
286 			id = strtol(l, &l, 10);
287 			if(*l != ':')
288 				continue;
289 			name = ++l;
290 			l = strchr(l, ':');
291 			if(l == 0)
292 				continue;
293 			*l = 0;
294 			break;
295 		case 'u':
296 			name = l;
297 			l = strchr(l, ':');
298 			if(l == 0)
299 				continue;
300 			*l++ = 0;
301 			/* skip password */
302 			l = strchr(l, ':');
303 			if(l == 0)
304 				continue;
305 			id = strtol(l+1, 0, 10);
306 			break;
307 		default:
308 			panic("unknown unixid style %d\n", style);
309 		}
310 		if(id == UNUSED)
311 			id = -1;	/* any value will do */
312 		if(!(x = xfree))	/* assign = */
313 			x = listalloc(1024/sizeof(Unixid), sizeof(Unixid));
314 		xfree = x->next;
315 		x->id = id;
316 		x->name = strstore(name);
317 		x->next = xp;
318 		xp = x;
319 	}
320 	Bterm(in);
321 	return xp;
322 }
323