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