]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/9nfs/unixnames.c
dc: fix off by one in stack overflow check (thanks BurnZeZ)
[plan9front.git] / sys / src / cmd / 9nfs / unixnames.c
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 *
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
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
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
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
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 *
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
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 *
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 }