Charles.Forsyth20070714-11427a6ecc419 years agoHistory
165 lines · 4.1 KB · Brainfuck
RawDownload
implement P9export; include "sys.m";	sys: Sys; include "draw.m";include "keyring.m";include "security.m";include "factotum.m";include "encoding.m";include "arg.m"; P9export: module{	init:	 fn(nil: ref Draw->Context, nil: list of string);}; factotumfile := "/mnt/factotum/rpc"; fail(status, msg: string){	sys->fprint(sys->fildes(2), "9export: %s\n", msg);	raise "fail:"+status;} nomod(mod: string){	fail("load", sys->sprint("can't load %s: %r", mod));} init(nil: ref Draw->Context, args: list of string){	sys = load Sys Sys->PATH; 	arg := load Arg Arg->PATH;	if(arg == nil)		nomod(Arg->PATH); 	arg->init(args);	arg->setusage("9export [-aA9] [-k keyspec] [-e enc digest]");	cryptalg := "";	# will be rc4_256 sha1	keyspec := "";	noauth := 0;	xflag := Sys->EXPWAIT;	while((o := arg->opt()) != 0)		case o {		'a' =>			xflag = Sys->EXPASYNC;		'A' =>			noauth = 1;		'e' =>			cryptalg = arg->earg();			if(cryptalg == "clear")				cryptalg = nil;		'k' =>			keyspec = arg->earg();		'9' =>			;		*   =>			arg->usage();		}	args = arg->argv();	arg = nil; 	sys->pctl(Sys->FORKFD|Sys->FORKNS, nil); 	fd := sys->fildes(0); 	secret: array of byte;	if(noauth == 0){		factotum := load Factotum Factotum->PATH;		if(factotum == nil)			nomod(Factotum->PATH);		factotum->init();		facfd := sys->open(factotumfile, Sys->ORDWR);		if(facfd == nil)			fail("factotum", sys->sprint("can't open %s: %r", factotumfile));		ai := factotum->proxy(fd, facfd, "proto=p9any role=server "+keyspec);		if(ai == nil)			fail("auth", sys->sprint("can't authenticate 9export: %r"));		secret = ai.secret;	} 	# read tree; it's a Plan 9 bug that there's no reliable delimiter	btree := array[2048] of byte;	n := sys->read(fd, btree, len btree);	if(n <= 0)		fail("tree", sys->sprint("can't read tree: %r"));	tree := string btree[0:n];	if(sys->chdir(tree) < 0){		sys->fprint(fd, "chdir(%d:\"%s\"): %r", n, tree);		fail("tree", sys->sprint("bad tree: %s", tree));	}	if(sys->write(fd, array of byte "OK", 2) != 2)		fail("tree", sys->sprint("can't OK tree: %r"));	impo := array[2048] of byte;	for(n = 0; n < len impo; n++)		if(sys->read(fd, impo[n:], 1) != 1)			fail("impo", sys->sprint("can't read impo: %r"));		else if(impo[n] == byte 0 || impo[n] == byte '\n')			break;	if(n < 4 || string impo[0:4] != "impo")		fail("impo", "wasn't impo: possibly old import/cpu");	if(noauth == 0 && cryptalg != nil){		if(secret == nil)			fail("import", "didn't establish shared secret");		random := load Random Random->PATH;		if(random == nil)			nomod(Random->PATH);		kr := load Keyring Keyring->PATH;		if(kr == nil)			nomod(Keyring->PATH);		ssl := load SSL SSL->PATH;		if(ssl == nil)			nomod(SSL->PATH);		base64 := load Encoding Encoding->BASE64PATH;		if(base64 == nil)			nomod(Encoding->BASE64PATH);		key := array[16] of byte;	# myrand[4] secret[8] hisrand[4]		key[0:] = random->randombuf(Random->ReallyRandom, 4);		ns := len secret;		if(ns > 8)			ns = 8;		key[12:] = secret[0:ns];		if(sys->write(fd, key[12:], 4) != 4)			fail("import", sys->sprint("can't write key to remote: %r"));		if(sys->readn(fd, key, 4) != 4)			fail("import", sys->sprint("can't read remote key: %r"));		digest := array[Keyring->SHA1dlen] of byte;		kr->sha1(key, len key, digest, nil);		err: string;		(fd, err) = pushssl(fd, base64->dec(S(digest[10:20])), base64->dec(S(digest[0:10])), cryptalg);		if(err != nil)			fail("import", sys->sprint("can't push security layer: %s", err));	}	if(sys->export(fd, ".", xflag) < 0)		fail("export", sys->sprint("can't export %s: %r", tree));} S(a: array of byte): string{	s := "";	for(i:=0; i<len a; i++)		s += sys->sprint("%.2ux", int a[i]);	return s;} pushssl(fd: ref Sys->FD, secretin, secretout: array of byte, alg: string): (ref Sys->FD, string){	ssl := load SSL SSL->PATH;	if(ssl == nil)		nomod(SSL->PATH); 	(err, c) := ssl->connect(fd);	if(err != nil)		return (nil, "can't connect ssl: " + err); 	err = ssl->secret(c, secretin, secretout);	if(err != nil)		return (nil, "can't write secret: " + err);	if(sys->fprint(c.cfd, "alg %s", alg) < 0)		return (nil, sys->sprint("can't push algorithm %s: %r", alg)); 	return (c.dfd, nil);}