xref: /plan9/sys/src/libauth/newns.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <auth.h>
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier enum
73e12c5d1SDavid du Colombier {
83e12c5d1SDavid du Colombier 	NARG	= 15,		/* max number of arguments */
93e12c5d1SDavid du Colombier 	MAXARG	= 10*NAMELEN,	/* max length of an argument */
103e12c5d1SDavid du Colombier };
113e12c5d1SDavid du Colombier 
123e12c5d1SDavid du Colombier static int	setenv(char*, char*);
133e12c5d1SDavid du Colombier static char	*expandarg(char*, char*);
143e12c5d1SDavid du Colombier static int	splitargs(char*, char*[], char*, int);
15*219b2ee8SDavid du Colombier static void	nsop(int, char*[], int);
163e12c5d1SDavid du Colombier static int	callexport(char*, char*);
173e12c5d1SDavid du Colombier static int	catch(void*, char*);
183e12c5d1SDavid du Colombier 
19*219b2ee8SDavid du Colombier int
203e12c5d1SDavid du Colombier newns(char *user, char *file)
213e12c5d1SDavid du Colombier {
223e12c5d1SDavid du Colombier 	Biobuf *spec;
233e12c5d1SDavid du Colombier 	char home[2*NAMELEN], *cmd;
243e12c5d1SDavid du Colombier 	char *argv[NARG], argbuf[MAXARG*NARG];
253e12c5d1SDavid du Colombier 	int argc;
26*219b2ee8SDavid du Colombier 	int afd;
273e12c5d1SDavid du Colombier 
28*219b2ee8SDavid du Colombier 	/* try for authentication server now because later is impossible */
29*219b2ee8SDavid du Colombier 	if(strcmp(user, "none") == 0)
30*219b2ee8SDavid du Colombier 		afd = -1;
31*219b2ee8SDavid du Colombier 	else
32*219b2ee8SDavid du Colombier 		afd = authdial();
333e12c5d1SDavid du Colombier 	if(!file)
343e12c5d1SDavid du Colombier 		file = "/lib/namespace";
353e12c5d1SDavid du Colombier 	spec = Bopen(file, OREAD);
36*219b2ee8SDavid du Colombier 	if(spec == 0){
37*219b2ee8SDavid du Colombier 		werrstr("can't open %s: %r", file);
38*219b2ee8SDavid du Colombier 		close(afd);
39*219b2ee8SDavid du Colombier 		return -1;
40*219b2ee8SDavid du Colombier 	}
413e12c5d1SDavid du Colombier 	rfork(RFENVG|RFCNAMEG);
423e12c5d1SDavid du Colombier 	setenv("user", user);
433e12c5d1SDavid du Colombier 	sprint(home, "/usr/%s", user);
443e12c5d1SDavid du Colombier 	setenv("home", home);
453e12c5d1SDavid du Colombier 
463e12c5d1SDavid du Colombier 	atnotify(catch, 1);
473e12c5d1SDavid du Colombier 	while(cmd = Brdline(spec, '\n')){
483e12c5d1SDavid du Colombier 		cmd[Blinelen(spec)-1] = '\0';
493e12c5d1SDavid du Colombier 		while(*cmd==' ' || *cmd=='\t')
503e12c5d1SDavid du Colombier 			cmd++;
51*219b2ee8SDavid du Colombier 		if(*cmd == 0 || *cmd == '#')
523e12c5d1SDavid du Colombier 			continue;
533e12c5d1SDavid du Colombier 		argc = splitargs(cmd, argv, argbuf, NARG);
54*219b2ee8SDavid du Colombier 		if(argc)
55*219b2ee8SDavid du Colombier 			nsop(argc, argv, afd);
563e12c5d1SDavid du Colombier 	}
573e12c5d1SDavid du Colombier 	atnotify(catch, 0);
58*219b2ee8SDavid du Colombier 	Bterm(spec);
59*219b2ee8SDavid du Colombier 	close(afd);
603e12c5d1SDavid du Colombier 	return 0;
613e12c5d1SDavid du Colombier }
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier static void
64*219b2ee8SDavid du Colombier nsop(int argc, char *argv[], int afd)
653e12c5d1SDavid du Colombier {
66*219b2ee8SDavid du Colombier 	char *argv0;
673e12c5d1SDavid du Colombier 	ulong flags;
683e12c5d1SDavid du Colombier 	int fd;
693e12c5d1SDavid du Colombier 
703e12c5d1SDavid du Colombier 	flags = 0;
713e12c5d1SDavid du Colombier 	argv0 = 0;
723e12c5d1SDavid du Colombier 	ARGBEGIN{
733e12c5d1SDavid du Colombier 	case 'a':
743e12c5d1SDavid du Colombier 		flags |= MAFTER;
753e12c5d1SDavid du Colombier 		break;
763e12c5d1SDavid du Colombier 	case 'b':
773e12c5d1SDavid du Colombier 		flags |= MBEFORE;
783e12c5d1SDavid du Colombier 		break;
793e12c5d1SDavid du Colombier 	case 'c':
803e12c5d1SDavid du Colombier 		flags |= MCREATE;
813e12c5d1SDavid du Colombier 		break;
823e12c5d1SDavid du Colombier 	}ARGEND
833e12c5d1SDavid du Colombier 
843e12c5d1SDavid du Colombier 	if(!(flags & (MAFTER|MBEFORE)))
853e12c5d1SDavid du Colombier 		flags |= MREPL;
863e12c5d1SDavid du Colombier 
873e12c5d1SDavid du Colombier 	if(strcmp(argv0, "bind") == 0 && argc == 2)
883e12c5d1SDavid du Colombier 		bind(argv[0], argv[1], flags);
893e12c5d1SDavid du Colombier 	if(strcmp(argv0, "mount") == 0){
903e12c5d1SDavid du Colombier 		fd = open(argv[0], ORDWR);
91*219b2ee8SDavid du Colombier 		authenticate(fd, afd);
92*219b2ee8SDavid du Colombier 		if(argc == 2){
93*219b2ee8SDavid du Colombier 			mount(fd, argv[1], flags, "");
94*219b2ee8SDavid du Colombier 		}else if(argc == 3){
95*219b2ee8SDavid du Colombier 			mount(fd, argv[1], flags, argv[2]);
96*219b2ee8SDavid du Colombier 		}
973e12c5d1SDavid du Colombier 		close(fd);
983e12c5d1SDavid du Colombier 	}
993e12c5d1SDavid du Colombier 	if(strcmp(argv0, "import") == 0){
1003e12c5d1SDavid du Colombier 		fd = callexport(argv[0], argv[1]);
101*219b2ee8SDavid du Colombier 		authenticate(fd, afd);
1023e12c5d1SDavid du Colombier 		if(argc == 2)
103*219b2ee8SDavid du Colombier 			mount(fd, argv[1], flags, "");
1043e12c5d1SDavid du Colombier 		else if(argc == 3)
105*219b2ee8SDavid du Colombier 			mount(fd, argv[2], flags, "");
1063e12c5d1SDavid du Colombier 		close(fd);
1073e12c5d1SDavid du Colombier 	}
1083e12c5d1SDavid du Colombier 	if(strcmp(argv0, "cd") == 0 && argc == 1)
1093e12c5d1SDavid du Colombier 		chdir(argv[0]);
1103e12c5d1SDavid du Colombier }
1113e12c5d1SDavid du Colombier 
1123e12c5d1SDavid du Colombier char *wocp = "sys: write on closed pipe";
1133e12c5d1SDavid du Colombier 
1143e12c5d1SDavid du Colombier static int
1153e12c5d1SDavid du Colombier catch(void *x, char *m)
1163e12c5d1SDavid du Colombier {
1173e12c5d1SDavid du Colombier 	USED(x);
1183e12c5d1SDavid du Colombier 	return strncmp(m, wocp, strlen(wocp)) == 0;
1193e12c5d1SDavid du Colombier }
1203e12c5d1SDavid du Colombier 
1213e12c5d1SDavid du Colombier static int
1223e12c5d1SDavid du Colombier callexport(char *sys, char *tree)
1233e12c5d1SDavid du Colombier {
1243e12c5d1SDavid du Colombier 	char *na, buf[3];
1253e12c5d1SDavid du Colombier 	int fd;
1263e12c5d1SDavid du Colombier 
1273e12c5d1SDavid du Colombier 	na = netmkaddr(sys, 0, "exportfs");
1283e12c5d1SDavid du Colombier 	if((fd = dial(na, 0, 0, 0)) < 0)
1293e12c5d1SDavid du Colombier 		return -1;
130*219b2ee8SDavid du Colombier 	if(auth(fd) < 0 || write(fd, tree, strlen(tree)) < 0
1313e12c5d1SDavid du Colombier 	|| read(fd, buf, 3) != 2 || buf[0]!='O' || buf[1]!= 'K'){
1323e12c5d1SDavid du Colombier 		close(fd);
1333e12c5d1SDavid du Colombier 		return -1;
1343e12c5d1SDavid du Colombier 	}
1353e12c5d1SDavid du Colombier 	return fd;
1363e12c5d1SDavid du Colombier }
1373e12c5d1SDavid du Colombier 
1383e12c5d1SDavid du Colombier static int
1393e12c5d1SDavid du Colombier splitargs(char *p, char *argv[], char *argbuf, int maxargs)
1403e12c5d1SDavid du Colombier {
1413e12c5d1SDavid du Colombier 	char *q;
1423e12c5d1SDavid du Colombier 	int i;
1433e12c5d1SDavid du Colombier 
1443e12c5d1SDavid du Colombier 	i = 0;
1453e12c5d1SDavid du Colombier 	while(i < maxargs){
1463e12c5d1SDavid du Colombier 		while(*p==' ' || *p=='\t')
1473e12c5d1SDavid du Colombier 			p++;
1483e12c5d1SDavid du Colombier 		if(!*p)
1493e12c5d1SDavid du Colombier 			return i;
1503e12c5d1SDavid du Colombier 		q = p;
1513e12c5d1SDavid du Colombier 		while(*p && *p!=' ' && *p!='\t')
1523e12c5d1SDavid du Colombier 			p++;
1533e12c5d1SDavid du Colombier 		if(*p)
1543e12c5d1SDavid du Colombier 			*p++ = '\0';
1553e12c5d1SDavid du Colombier 		argv[i++] = argbuf;
1563e12c5d1SDavid du Colombier 		argbuf = expandarg(q, argbuf);
1573e12c5d1SDavid du Colombier 		if(!argbuf)
1583e12c5d1SDavid du Colombier 			return 0;
1593e12c5d1SDavid du Colombier 	}
1603e12c5d1SDavid du Colombier 	return 0;
1613e12c5d1SDavid du Colombier }
1623e12c5d1SDavid du Colombier 
1633e12c5d1SDavid du Colombier /*
1643e12c5d1SDavid du Colombier  * copy the arg into the buffer,
1653e12c5d1SDavid du Colombier  * expanding any environment variables.
1663e12c5d1SDavid du Colombier  * environment variables are assumed to be
1673e12c5d1SDavid du Colombier  * names (ie. < NAMELEN long)
1683e12c5d1SDavid du Colombier  * the entire argument is expanded to be at
1693e12c5d1SDavid du Colombier  * most MAXARG long and null terminated
1703e12c5d1SDavid du Colombier  * the address of the byte after the terminating null is returned
1713e12c5d1SDavid du Colombier  * any problems cause a 0 return;
1723e12c5d1SDavid du Colombier  */
1733e12c5d1SDavid du Colombier static char *
1743e12c5d1SDavid du Colombier expandarg(char *arg, char *buf)
1753e12c5d1SDavid du Colombier {
1763e12c5d1SDavid du Colombier 	char env[3+NAMELEN], *p, *q;
1773e12c5d1SDavid du Colombier 	int fd, n, len;
1783e12c5d1SDavid du Colombier 
1793e12c5d1SDavid du Colombier 	n = 0;
1803e12c5d1SDavid du Colombier 	while(p = utfrune(arg, L'$')){
1813e12c5d1SDavid du Colombier 		len = p - arg;
1823e12c5d1SDavid du Colombier 		if(n + len + NAMELEN >= MAXARG-1)
1833e12c5d1SDavid du Colombier 			return 0;
1843e12c5d1SDavid du Colombier 		memmove(&buf[n], arg, len);
1853e12c5d1SDavid du Colombier 		n += len;
1863e12c5d1SDavid du Colombier 		p++;
1873e12c5d1SDavid du Colombier 		arg = utfrune(p, L'\0');
1883e12c5d1SDavid du Colombier 		q = utfrune(p, L'/');
1893e12c5d1SDavid du Colombier 		if(q && q < arg)
1903e12c5d1SDavid du Colombier 			arg = q;
1913e12c5d1SDavid du Colombier 		q = utfrune(p, L'$');
1923e12c5d1SDavid du Colombier 		if(q && q < arg)
1933e12c5d1SDavid du Colombier 			arg = q;
1943e12c5d1SDavid du Colombier 		len = arg - p;
1953e12c5d1SDavid du Colombier 		if(len >= NAMELEN)
1963e12c5d1SDavid du Colombier 			continue;
1973e12c5d1SDavid du Colombier 		strcpy(env, "#e/");
1983e12c5d1SDavid du Colombier 		strncpy(env+3, p, len);
1993e12c5d1SDavid du Colombier 		env[3+len] = '\0';
2003e12c5d1SDavid du Colombier 		fd = open(env, OREAD);
2013e12c5d1SDavid du Colombier 		if(fd >= 0){
2023e12c5d1SDavid du Colombier 			len = read(fd, &buf[n], NAMELEN - 1);
2033e12c5d1SDavid du Colombier 			if(len > 0)
2043e12c5d1SDavid du Colombier 				n += len;
2053e12c5d1SDavid du Colombier 			close(fd);
2063e12c5d1SDavid du Colombier 		}
2073e12c5d1SDavid du Colombier 	}
2083e12c5d1SDavid du Colombier 	len = strlen(arg);
2093e12c5d1SDavid du Colombier 	if(n + len >= MAXARG - 1)
2103e12c5d1SDavid du Colombier 		return 0;
2113e12c5d1SDavid du Colombier 	strcpy(&buf[n], arg);
2123e12c5d1SDavid du Colombier 	return &buf[n+len+1];
2133e12c5d1SDavid du Colombier }
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier static int
2163e12c5d1SDavid du Colombier setenv(char *name, char *val)
2173e12c5d1SDavid du Colombier {
2183e12c5d1SDavid du Colombier 	int f;
2193e12c5d1SDavid du Colombier 	char ename[NAMELEN+6];
2203e12c5d1SDavid du Colombier 	long s;
2213e12c5d1SDavid du Colombier 
2223e12c5d1SDavid du Colombier 	sprint(ename, "#e/%s", name);
2233e12c5d1SDavid du Colombier 	f = create(ename, OWRITE, 0664);
2243e12c5d1SDavid du Colombier 	if(f < 0)
2253e12c5d1SDavid du Colombier 		return -1;
2263e12c5d1SDavid du Colombier 	s = strlen(val);
2273e12c5d1SDavid du Colombier 	if(write(f, val, s) != s){
2283e12c5d1SDavid du Colombier 		close(f);
2293e12c5d1SDavid du Colombier 		return -1;
2303e12c5d1SDavid du Colombier 	}
2313e12c5d1SDavid du Colombier 	close(f);
2323e12c5d1SDavid du Colombier 	return 0;
2333e12c5d1SDavid du Colombier }
234