137da2899SCharles.Forsythimplement P9export; 237da2899SCharles.Forsyth 337da2899SCharles.Forsythinclude "sys.m"; 437da2899SCharles.Forsyth sys: Sys; 537da2899SCharles.Forsyth 637da2899SCharles.Forsythinclude "draw.m"; 737da2899SCharles.Forsythinclude "keyring.m"; 837da2899SCharles.Forsythinclude "security.m"; 937da2899SCharles.Forsythinclude "factotum.m"; 1037da2899SCharles.Forsythinclude "encoding.m"; 1137da2899SCharles.Forsythinclude "arg.m"; 1237da2899SCharles.Forsyth 1337da2899SCharles.ForsythP9export: module 1437da2899SCharles.Forsyth{ 1537da2899SCharles.Forsyth init: fn(nil: ref Draw->Context, nil: list of string); 1637da2899SCharles.Forsyth}; 1737da2899SCharles.Forsyth 1837da2899SCharles.Forsythfactotumfile := "/mnt/factotum/rpc"; 1937da2899SCharles.Forsyth 2037da2899SCharles.Forsythfail(status, msg: string) 2137da2899SCharles.Forsyth{ 2237da2899SCharles.Forsyth sys->fprint(sys->fildes(2), "9export: %s\n", msg); 2337da2899SCharles.Forsyth raise "fail:"+status; 2437da2899SCharles.Forsyth} 2537da2899SCharles.Forsyth 2637da2899SCharles.Forsythnomod(mod: string) 2737da2899SCharles.Forsyth{ 2837da2899SCharles.Forsyth fail("load", sys->sprint("can't load %s: %r", mod)); 2937da2899SCharles.Forsyth} 3037da2899SCharles.Forsyth 3137da2899SCharles.Forsythinit(nil: ref Draw->Context, args: list of string) 3237da2899SCharles.Forsyth{ 3337da2899SCharles.Forsyth sys = load Sys Sys->PATH; 3437da2899SCharles.Forsyth 3537da2899SCharles.Forsyth arg := load Arg Arg->PATH; 3637da2899SCharles.Forsyth if(arg == nil) 3737da2899SCharles.Forsyth nomod(Arg->PATH); 3837da2899SCharles.Forsyth 3937da2899SCharles.Forsyth arg->init(args); 4037da2899SCharles.Forsyth arg->setusage("9export [-aA9] [-k keyspec] [-e enc digest]"); 4137da2899SCharles.Forsyth cryptalg := ""; # will be rc4_256 sha1 4237da2899SCharles.Forsyth keyspec := ""; 4337da2899SCharles.Forsyth noauth := 0; 4437da2899SCharles.Forsyth xflag := Sys->EXPWAIT; 4537da2899SCharles.Forsyth while((o := arg->opt()) != 0) 4637da2899SCharles.Forsyth case o { 4737da2899SCharles.Forsyth 'a' => 4837da2899SCharles.Forsyth xflag = Sys->EXPASYNC; 4937da2899SCharles.Forsyth 'A' => 5037da2899SCharles.Forsyth noauth = 1; 5137da2899SCharles.Forsyth 'e' => 5237da2899SCharles.Forsyth cryptalg = arg->earg(); 5337da2899SCharles.Forsyth if(cryptalg == "clear") 5437da2899SCharles.Forsyth cryptalg = nil; 5537da2899SCharles.Forsyth 'k' => 5637da2899SCharles.Forsyth keyspec = arg->earg(); 5737da2899SCharles.Forsyth '9' => 5837da2899SCharles.Forsyth ; 5937da2899SCharles.Forsyth * => 6037da2899SCharles.Forsyth arg->usage(); 6137da2899SCharles.Forsyth } 6237da2899SCharles.Forsyth args = arg->argv(); 6337da2899SCharles.Forsyth arg = nil; 6437da2899SCharles.Forsyth 6537da2899SCharles.Forsyth sys->pctl(Sys->FORKFD|Sys->FORKNS, nil); 6637da2899SCharles.Forsyth 6737da2899SCharles.Forsyth fd := sys->fildes(0); 6837da2899SCharles.Forsyth 6937da2899SCharles.Forsyth secret: array of byte; 7037da2899SCharles.Forsyth if(noauth == 0){ 7137da2899SCharles.Forsyth factotum := load Factotum Factotum->PATH; 7237da2899SCharles.Forsyth if(factotum == nil) 7337da2899SCharles.Forsyth nomod(Factotum->PATH); 7437da2899SCharles.Forsyth factotum->init(); 7537da2899SCharles.Forsyth facfd := sys->open(factotumfile, Sys->ORDWR); 7637da2899SCharles.Forsyth if(facfd == nil) 7737da2899SCharles.Forsyth fail("factotum", sys->sprint("can't open %s: %r", factotumfile)); 7837da2899SCharles.Forsyth ai := factotum->proxy(fd, facfd, "proto=p9any role=server "+keyspec); 7937da2899SCharles.Forsyth if(ai == nil) 8037da2899SCharles.Forsyth fail("auth", sys->sprint("can't authenticate 9export: %r")); 8137da2899SCharles.Forsyth secret = ai.secret; 8237da2899SCharles.Forsyth } 8337da2899SCharles.Forsyth 8437da2899SCharles.Forsyth # read tree; it's a Plan 9 bug that there's no reliable delimiter 8537da2899SCharles.Forsyth btree := array[2048] of byte; 8637da2899SCharles.Forsyth n := sys->read(fd, btree, len btree); 8737da2899SCharles.Forsyth if(n <= 0) 8837da2899SCharles.Forsyth fail("tree", sys->sprint("can't read tree: %r")); 8937da2899SCharles.Forsyth tree := string btree[0:n]; 9037da2899SCharles.Forsyth if(sys->chdir(tree) < 0){ 9137da2899SCharles.Forsyth sys->fprint(fd, "chdir(%d:\"%s\"): %r", n, tree); 9237da2899SCharles.Forsyth fail("tree", sys->sprint("bad tree: %s", tree)); 9337da2899SCharles.Forsyth } 9437da2899SCharles.Forsyth if(sys->write(fd, array of byte "OK", 2) != 2) 9537da2899SCharles.Forsyth fail("tree", sys->sprint("can't OK tree: %r")); 9637da2899SCharles.Forsyth impo := array[2048] of byte; 9737da2899SCharles.Forsyth for(n = 0; n < len impo; n++) 9837da2899SCharles.Forsyth if(sys->read(fd, impo[n:], 1) != 1) 9937da2899SCharles.Forsyth fail("impo", sys->sprint("can't read impo: %r")); 10037da2899SCharles.Forsyth else if(impo[n] == byte 0 || impo[n] == byte '\n') 10137da2899SCharles.Forsyth break; 10237da2899SCharles.Forsyth if(n < 4 || string impo[0:4] != "impo") 10337da2899SCharles.Forsyth fail("impo", "wasn't impo: possibly old import/cpu"); 10437da2899SCharles.Forsyth if(noauth == 0 && cryptalg != nil){ 10537da2899SCharles.Forsyth if(secret == nil) 10637da2899SCharles.Forsyth fail("import", "didn't establish shared secret"); 10737da2899SCharles.Forsyth random := load Random Random->PATH; 10837da2899SCharles.Forsyth if(random == nil) 10937da2899SCharles.Forsyth nomod(Random->PATH); 11037da2899SCharles.Forsyth kr := load Keyring Keyring->PATH; 11137da2899SCharles.Forsyth if(kr == nil) 11237da2899SCharles.Forsyth nomod(Keyring->PATH); 11337da2899SCharles.Forsyth ssl := load SSL SSL->PATH; 11437da2899SCharles.Forsyth if(ssl == nil) 11537da2899SCharles.Forsyth nomod(SSL->PATH); 11637da2899SCharles.Forsyth base64 := load Encoding Encoding->BASE64PATH; 11737da2899SCharles.Forsyth if(base64 == nil) 11837da2899SCharles.Forsyth nomod(Encoding->BASE64PATH); 11937da2899SCharles.Forsyth key := array[16] of byte; # myrand[4] secret[8] hisrand[4] 12037da2899SCharles.Forsyth key[0:] = random->randombuf(Random->ReallyRandom, 4); 12137da2899SCharles.Forsyth ns := len secret; 12237da2899SCharles.Forsyth if(ns > 8) 12337da2899SCharles.Forsyth ns = 8; 12437da2899SCharles.Forsyth key[12:] = secret[0:ns]; 12537da2899SCharles.Forsyth if(sys->write(fd, key[12:], 4) != 4) 12637da2899SCharles.Forsyth fail("import", sys->sprint("can't write key to remote: %r")); 127*a6011949SCharles.Forsyth if(sys->readn(fd, key, 4) != 4) 12837da2899SCharles.Forsyth fail("import", sys->sprint("can't read remote key: %r")); 12937da2899SCharles.Forsyth digest := array[Keyring->SHA1dlen] of byte; 13037da2899SCharles.Forsyth kr->sha1(key, len key, digest, nil); 13137da2899SCharles.Forsyth err: string; 13237da2899SCharles.Forsyth (fd, err) = pushssl(fd, base64->dec(S(digest[10:20])), base64->dec(S(digest[0:10])), cryptalg); 13337da2899SCharles.Forsyth if(err != nil) 13437da2899SCharles.Forsyth fail("import", sys->sprint("can't push security layer: %s", err)); 13537da2899SCharles.Forsyth } 13637da2899SCharles.Forsyth if(sys->export(fd, ".", xflag) < 0) 13737da2899SCharles.Forsyth fail("export", sys->sprint("can't export %s: %r", tree)); 13837da2899SCharles.Forsyth} 13937da2899SCharles.Forsyth 14037da2899SCharles.ForsythS(a: array of byte): string 14137da2899SCharles.Forsyth{ 14237da2899SCharles.Forsyth s := ""; 14337da2899SCharles.Forsyth for(i:=0; i<len a; i++) 14437da2899SCharles.Forsyth s += sys->sprint("%.2ux", int a[i]); 14537da2899SCharles.Forsyth return s; 14637da2899SCharles.Forsyth} 14737da2899SCharles.Forsyth 14837da2899SCharles.Forsythpushssl(fd: ref Sys->FD, secretin, secretout: array of byte, alg: string): (ref Sys->FD, string) 14937da2899SCharles.Forsyth{ 15037da2899SCharles.Forsyth ssl := load SSL SSL->PATH; 15137da2899SCharles.Forsyth if(ssl == nil) 15237da2899SCharles.Forsyth nomod(SSL->PATH); 15337da2899SCharles.Forsyth 15437da2899SCharles.Forsyth (err, c) := ssl->connect(fd); 15537da2899SCharles.Forsyth if(err != nil) 15637da2899SCharles.Forsyth return (nil, "can't connect ssl: " + err); 15737da2899SCharles.Forsyth 15837da2899SCharles.Forsyth err = ssl->secret(c, secretin, secretout); 15937da2899SCharles.Forsyth if(err != nil) 16037da2899SCharles.Forsyth return (nil, "can't write secret: " + err); 16137da2899SCharles.Forsyth if(sys->fprint(c.cfd, "alg %s", alg) < 0) 16237da2899SCharles.Forsyth return (nil, sys->sprint("can't push algorithm %s: %r", alg)); 16337da2899SCharles.Forsyth 16437da2899SCharles.Forsyth return (c.dfd, nil); 16537da2899SCharles.Forsyth} 166