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