xref: /plan9-contrib/sys/src/libauth/newns.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <auth.h>
5 
6 enum
7 {
8 	NARG	= 15,		/* max number of arguments */
9 	MAXARG	= 10*NAMELEN,	/* max length of an argument */
10 };
11 
12 static int	setenv(char*, char*);
13 static char	*expandarg(char*, char*);
14 static int	splitargs(char*, char*[], char*, int);
15 static void	nsop(int, char*[], int);
16 static int	callexport(char*, char*);
17 static int	catch(void*, char*);
18 
19 int
20 newns(char *user, char *file)
21 {
22 	Biobuf *spec;
23 	char home[2*NAMELEN], *cmd;
24 	char *argv[NARG], argbuf[MAXARG*NARG];
25 	int argc;
26 	int afd;
27 
28 	/* try for authentication server now because later is impossible */
29 	if(strcmp(user, "none") == 0)
30 		afd = -1;
31 	else
32 		afd = authdial();
33 	if(!file)
34 		file = "/lib/namespace";
35 	spec = Bopen(file, OREAD);
36 	if(spec == 0){
37 		werrstr("can't open %s: %r", file);
38 		close(afd);
39 		return -1;
40 	}
41 	rfork(RFENVG|RFCNAMEG);
42 	setenv("user", user);
43 	sprint(home, "/usr/%s", user);
44 	setenv("home", home);
45 
46 	atnotify(catch, 1);
47 	while(cmd = Brdline(spec, '\n')){
48 		cmd[Blinelen(spec)-1] = '\0';
49 		while(*cmd==' ' || *cmd=='\t')
50 			cmd++;
51 		if(*cmd == 0 || *cmd == '#')
52 			continue;
53 		argc = splitargs(cmd, argv, argbuf, NARG);
54 		if(argc)
55 			nsop(argc, argv, afd);
56 	}
57 	atnotify(catch, 0);
58 	Bterm(spec);
59 	close(afd);
60 	return 0;
61 }
62 
63 static void
64 nsop(int argc, char *argv[], int afd)
65 {
66 	char *argv0;
67 	ulong flags;
68 	int fd;
69 
70 	flags = 0;
71 	argv0 = 0;
72 	ARGBEGIN{
73 	case 'a':
74 		flags |= MAFTER;
75 		break;
76 	case 'b':
77 		flags |= MBEFORE;
78 		break;
79 	case 'c':
80 		flags |= MCREATE;
81 		break;
82 	}ARGEND
83 
84 	if(!(flags & (MAFTER|MBEFORE)))
85 		flags |= MREPL;
86 
87 	if(strcmp(argv0, "bind") == 0 && argc == 2)
88 		bind(argv[0], argv[1], flags);
89 	if(strcmp(argv0, "mount") == 0){
90 		fd = open(argv[0], ORDWR);
91 		authenticate(fd, afd);
92 		if(argc == 2){
93 			mount(fd, argv[1], flags, "");
94 		}else if(argc == 3){
95 			mount(fd, argv[1], flags, argv[2]);
96 		}
97 		close(fd);
98 	}
99 	if(strcmp(argv0, "import") == 0){
100 		fd = callexport(argv[0], argv[1]);
101 		authenticate(fd, afd);
102 		if(argc == 2)
103 			mount(fd, argv[1], flags, "");
104 		else if(argc == 3)
105 			mount(fd, argv[2], flags, "");
106 		close(fd);
107 	}
108 	if(strcmp(argv0, "cd") == 0 && argc == 1)
109 		chdir(argv[0]);
110 }
111 
112 char *wocp = "sys: write on closed pipe";
113 
114 static int
115 catch(void *x, char *m)
116 {
117 	USED(x);
118 	return strncmp(m, wocp, strlen(wocp)) == 0;
119 }
120 
121 static int
122 callexport(char *sys, char *tree)
123 {
124 	char *na, buf[3];
125 	int fd;
126 
127 	na = netmkaddr(sys, 0, "exportfs");
128 	if((fd = dial(na, 0, 0, 0)) < 0)
129 		return -1;
130 	if(auth(fd) < 0 || write(fd, tree, strlen(tree)) < 0
131 	|| read(fd, buf, 3) != 2 || buf[0]!='O' || buf[1]!= 'K'){
132 		close(fd);
133 		return -1;
134 	}
135 	return fd;
136 }
137 
138 static int
139 splitargs(char *p, char *argv[], char *argbuf, int maxargs)
140 {
141 	char *q;
142 	int i;
143 
144 	i = 0;
145 	while(i < maxargs){
146 		while(*p==' ' || *p=='\t')
147 			p++;
148 		if(!*p)
149 			return i;
150 		q = p;
151 		while(*p && *p!=' ' && *p!='\t')
152 			p++;
153 		if(*p)
154 			*p++ = '\0';
155 		argv[i++] = argbuf;
156 		argbuf = expandarg(q, argbuf);
157 		if(!argbuf)
158 			return 0;
159 	}
160 	return 0;
161 }
162 
163 /*
164  * copy the arg into the buffer,
165  * expanding any environment variables.
166  * environment variables are assumed to be
167  * names (ie. < NAMELEN long)
168  * the entire argument is expanded to be at
169  * most MAXARG long and null terminated
170  * the address of the byte after the terminating null is returned
171  * any problems cause a 0 return;
172  */
173 static char *
174 expandarg(char *arg, char *buf)
175 {
176 	char env[3+NAMELEN], *p, *q;
177 	int fd, n, len;
178 
179 	n = 0;
180 	while(p = utfrune(arg, L'$')){
181 		len = p - arg;
182 		if(n + len + NAMELEN >= MAXARG-1)
183 			return 0;
184 		memmove(&buf[n], arg, len);
185 		n += len;
186 		p++;
187 		arg = utfrune(p, L'\0');
188 		q = utfrune(p, L'/');
189 		if(q && q < arg)
190 			arg = q;
191 		q = utfrune(p, L'$');
192 		if(q && q < arg)
193 			arg = q;
194 		len = arg - p;
195 		if(len >= NAMELEN)
196 			continue;
197 		strcpy(env, "#e/");
198 		strncpy(env+3, p, len);
199 		env[3+len] = '\0';
200 		fd = open(env, OREAD);
201 		if(fd >= 0){
202 			len = read(fd, &buf[n], NAMELEN - 1);
203 			if(len > 0)
204 				n += len;
205 			close(fd);
206 		}
207 	}
208 	len = strlen(arg);
209 	if(n + len >= MAXARG - 1)
210 		return 0;
211 	strcpy(&buf[n], arg);
212 	return &buf[n+len+1];
213 }
214 
215 static int
216 setenv(char *name, char *val)
217 {
218 	int f;
219 	char ename[NAMELEN+6];
220 	long s;
221 
222 	sprint(ename, "#e/%s", name);
223 	f = create(ename, OWRITE, 0664);
224 	if(f < 0)
225 		return -1;
226 	s = strlen(val);
227 	if(write(f, val, s) != s){
228 		close(f);
229 		return -1;
230 	}
231 	close(f);
232 	return 0;
233 }
234