]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libauth/newns.c
remove debugging
[plan9front.git] / sys / src / libauth / newns.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <auth.h>
5 #include <authsrv.h>
6 #include "authlocal.h"
7
8 enum
9 {
10         NARG    = 15,           /* max number of arguments */
11         MAXARG  = 10*ANAMELEN,  /* max length of an argument */
12 };
13
14 static int      setenv(char*, char*);
15 static char     *expandarg(char*, char*);
16 static int      splitargs(char*, char*[], char*, int);
17 static int      nsfile(char*, Biobuf *, AuthRpc *);
18 static int      nsop(char*, int, char*[], AuthRpc*);
19 static int      callexport(char*, char*);
20 static int      catch(void*, char*);
21
22 int newnsdebug;
23
24 static int
25 freecloserpc(AuthRpc *rpc)
26 {
27         if(rpc){
28                 close(rpc->afd);
29                 auth_freerpc(rpc);
30         }
31         return -1;
32 }
33
34 static int
35 buildns(int newns, char *user, char *file)
36 {
37         Biobuf *b;
38         char home[4*ANAMELEN];
39         int afd, cdroot;
40         char *path;
41         AuthRpc *rpc;
42
43         rpc = nil;
44         /* try for factotum now because later is impossible */
45         afd = open("/mnt/factotum/rpc", ORDWR);
46         if(afd < 0 && newnsdebug)
47                 fprint(2, "open /mnt/factotum/rpc: %r\n");
48         if(afd >= 0){
49                 rpc = auth_allocrpc(afd);
50                 if(rpc == nil)
51                         close(afd);
52         }
53         /* rpc != nil iff afd >= 0 */
54
55         if(file == nil){
56                 if(!newns){
57                         werrstr("no namespace file specified");
58                         return freecloserpc(rpc);
59                 }
60                 file = "/lib/namespace";
61         }
62         b = Bopen(file, OREAD);
63         if(b == 0){
64                 werrstr("can't open %s: %r", file);
65                 return freecloserpc(rpc);
66         }
67         if(newns){
68                 rfork(RFENVG|RFCNAMEG);
69                 setenv("user", user);
70                 snprint(home, sizeof home, "/usr/%s", user);
71                 setenv("home", home);
72         }
73
74         cdroot = nsfile(newns ? "newns" : "addns", b, rpc);
75         Bterm(b);
76         freecloserpc(rpc);
77
78         /* make sure we managed to cd into the new name space */
79         if(newns && !cdroot){
80                 path = malloc(1024);
81                 if(path == nil || getwd(path, 1024) == 0 || chdir(path) < 0)
82                         chdir("/");
83                 if(path != nil)
84                         free(path);
85         }
86
87         return 0;
88 }
89
90 static int
91 nsfile(char *fn, Biobuf *b, AuthRpc *rpc)
92 {
93         int argc;
94         char *cmd, *argv[NARG+1], argbuf[MAXARG*NARG];
95         int cdroot;
96
97         cdroot = 0;
98         atnotify(catch, 1);
99         while(cmd = Brdline(b, '\n')){
100                 cmd[Blinelen(b)-1] = '\0';
101                 while(*cmd==' ' || *cmd=='\t')
102                         cmd++;
103                 if(*cmd == '#')
104                         continue;
105                 argc = splitargs(cmd, argv, argbuf, NARG);
106                 if(argc)
107                         cdroot |= nsop(fn, argc, argv, rpc);
108         }
109         atnotify(catch, 0);
110         return cdroot;
111 }
112
113 int
114 newns(char *user, char *file)
115 {
116         return buildns(1, user, file);
117 }
118
119 int
120 addns(char *user, char *file)
121 {
122         return buildns(0, user, file);
123 }
124
125 static int
126 famount(int fd, AuthRpc *rpc, char *mntpt, int flags, char *aname)
127 {
128         int afd;
129         AuthInfo *ai;
130         int ret;
131
132         afd = fauth(fd, aname);
133         if(afd >= 0){
134                 ai = fauth_proxy(afd, rpc, amount_getkey, "proto=p9any role=client");
135                 if(ai != nil)
136                         auth_freeAI(ai);
137         }
138         ret = mount(fd, afd, mntpt, flags, aname);
139         if(afd >= 0)
140                 close(afd);
141         return ret;
142 }
143
144 static int
145 nsop(char *fn, int argc, char *argv[], AuthRpc *rpc)
146 {
147         char *argv0;
148         ulong flags;
149         int fd, i;
150         Biobuf *b;
151         int cdroot;
152
153         cdroot = 0;
154         flags = 0;
155         argv0 = 0;
156         if (newnsdebug){
157                 for (i = 0; i < argc; i++)
158                         fprint(2, "%s ", argv[i]);
159                 fprint(2, "\n");
160         }
161         ARGBEGIN{
162         case 'a':
163                 flags |= MAFTER;
164                 break;
165         case 'b':
166                 flags |= MBEFORE;
167                 break;
168         case 'c':
169                 flags |= MCREATE;
170                 break;
171         case 'C':
172                 flags |= MCACHE;
173                 break;
174         }ARGEND
175
176         if(!(flags & (MAFTER|MBEFORE)))
177                 flags |= MREPL;
178
179         if(strcmp(argv0, ".") == 0 && argc == 1){
180                 b = Bopen(argv[0], OREAD);
181                 if(b == nil)
182                         return 0;
183                 cdroot |= nsfile(fn, b, rpc);
184                 Bterm(b);
185         }else if(strcmp(argv0, "clear") == 0 && argc == 0)
186                 rfork(RFCNAMEG);
187         else if(strcmp(argv0, "bind") == 0 && argc == 2){
188                 if(bind(argv[0], argv[1], flags) < 0 && newnsdebug)
189                         fprint(2, "%s: bind: %s %s: %r\n", fn, argv[0], argv[1]);
190         }else if(strcmp(argv0, "unmount") == 0){
191                 if(argc == 1)
192                         unmount(nil, argv[0]);
193                 else if(argc == 2)
194                         unmount(argv[0], argv[1]);
195         }else if(strcmp(argv0, "mount") == 0){
196                 fd = open(argv[0], ORDWR);
197                 if(argc == 2){
198                         if(famount(fd, rpc, argv[1], flags, "") < 0 && newnsdebug)
199                                 fprint(2, "%s: mount: %s %s: %r\n", fn, argv[0], argv[1]);
200                 }else if(argc == 3){
201                         if(famount(fd, rpc, argv[1], flags, argv[2]) < 0 && newnsdebug)
202                                 fprint(2, "%s: mount: %s %s %s: %r\n", fn, argv[0], argv[1], argv[2]);
203                 }
204                 close(fd);
205         }else if(strcmp(argv0, "import") == 0){
206                 fd = callexport(argv[0], argv[1]);
207                 if(argc == 2)
208                         famount(fd, rpc, argv[1], flags, "");
209                 else if(argc == 3)
210                         famount(fd, rpc, argv[2], flags, "");
211                 close(fd);
212         }else if(strcmp(argv0, "cd") == 0 && argc == 1){
213                 if(chdir(argv[0]) == 0 && *argv[0] == '/')
214                         cdroot = 1;
215         }
216         return cdroot;
217 }
218
219 static char *wocp = "sys: write on closed pipe";
220
221 static int
222 catch(void *x, char *m)
223 {
224         USED(x);
225         return strncmp(m, wocp, strlen(wocp)) == 0;
226 }
227
228 static int
229 callexport(char *sys, char *tree)
230 {
231         char *na, buf[3];
232         int fd;
233         AuthInfo *ai;
234
235         na = netmkaddr(sys, 0, "exportfs");
236         if((fd = dial(na, 0, 0, 0)) < 0)
237                 return -1;
238         if((ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client")) == nil
239         || write(fd, tree, strlen(tree)) < 0
240         || read(fd, buf, 3) != 2 || buf[0]!='O' || buf[1]!= 'K'){
241                 close(fd);
242                 auth_freeAI(ai);
243                 return -1;
244         }
245         auth_freeAI(ai);
246         return fd;
247 }
248
249 static char*
250 unquote(char *s)
251 {
252         char *r, *w;
253         int inquote;
254         
255         inquote = 0;
256         for(r=w=s; *r; r++){
257                 if(*r != '\''){
258                         *w++ = *r;
259                         continue;
260                 }
261                 if(inquote){
262                         if(*(r+1) == '\''){
263                                 *w++ = '\'';
264                                 r++;
265                         }else
266                                 inquote = 0;
267                 }else
268                         inquote = 1;
269         }
270         *w = 0;
271         return s;
272 }
273
274 static int
275 splitargs(char *p, char *argv[], char *argbuf, int nargv)
276 {
277         char *q;
278         int i, n;
279
280         n = gettokens(p, argv, nargv, " \t\r");
281         if(n == nargv)
282                 return 0;
283         for(i = 0; i < n; i++){
284                 q = argv[i];
285                 argv[i] = argbuf;
286                 argbuf = expandarg(q, argbuf);
287                 if(argbuf == nil)
288                         return 0;
289                 unquote(argv[i]);
290         }
291         return n;
292 }
293
294 static char*
295 nextdollar(char *arg)
296 {
297         char *p;
298         int inquote;
299         
300         inquote = 0;
301         for(p=arg; *p; p++){
302                 if(*p == '\'')
303                         inquote = !inquote;
304                 if(*p == '$' && !inquote)
305                         return p;
306         }
307         return nil;
308 }
309
310 /*
311  * copy the arg into the buffer,
312  * expanding any environment variables.
313  * environment variables are assumed to be
314  * names (ie. < ANAMELEN long)
315  * the entire argument is expanded to be at
316  * most MAXARG long and null terminated
317  * the address of the byte after the terminating null is returned
318  * any problems cause a 0 return;
319  */
320 static char *
321 expandarg(char *arg, char *buf)
322 {
323         char env[3+ANAMELEN], *p, *x;
324         int fd, n, len;
325
326         n = 0;
327         while(p = nextdollar(arg)){
328                 len = p - arg;
329                 if(n + len + ANAMELEN >= MAXARG-1)
330                         return 0;
331                 memmove(&buf[n], arg, len);
332                 n += len;
333                 p++;
334                 arg = strpbrk(p, "/.!'$");
335                 if(arg == nil)
336                         arg = p+strlen(p);
337                 len = arg - p;
338                 if(len == 0 || len >= ANAMELEN)
339                         continue;
340                 strcpy(env, "#e/");
341                 strncpy(env+3, p, len);
342                 env[3+len] = '\0';
343                 fd = open(env, OREAD);
344                 if(fd >= 0){
345                         len = read(fd, &buf[n], ANAMELEN - 1);
346                         /* some singleton environment variables have trailing NULs */
347                         /* lists separate entries with NULs; we arbitrarily take the first element */
348                         if(len > 0){
349                                 x = memchr(&buf[n], 0, len);
350                                 if(x != nil)
351                                         len = x - &buf[n];
352                                 n += len;
353                         }
354                         close(fd);
355                 }
356         }
357         len = strlen(arg);
358         if(n + len >= MAXARG - 1)
359                 return 0;
360         strcpy(&buf[n], arg);
361         return &buf[n+len+1];
362 }
363
364 static int
365 setenv(char *name, char *val)
366 {
367         int f;
368         char ename[ANAMELEN+6];
369         long s;
370
371         sprint(ename, "#e/%s", name);
372         f = create(ename, OWRITE, 0664);
373         if(f < 0)
374                 return -1;
375         s = strlen(val);
376         if(write(f, val, s) != s){
377                 close(f);
378                 return -1;
379         }
380         close(f);
381         return 0;
382 }