newns.c 7.1 KB

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