xref: /inferno-os/appl/cmd/9export.b (revision a6011949be081a8fe1bec0713ce60c36beb3a351)
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