Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}