forsyth20121205-174063a80cc13 years agoHistory
290 lines · 5.9 KB · Brainfuck
RawDownload
implement Passwd; include "sys.m";	sys: Sys; include "draw.m"; include "keyring.m";	kr: Keyring; include "security.m";	auth: Auth; include "arg.m"; Passwd: module{	init:	fn(ctxt: ref Draw->Context, argv: list of string);}; stderr, stdin, stdout: ref Sys->FD;keysrv := "/mnt/keysrv";signer := "$SIGNER"; usage(){	sys->fprint(sys->fildes(2), "usage: passwd [-u user] [-s signer] [keyfile]\n");	raise "fail:usage";} init(nil: ref Draw->Context, args: list of string){	sys = load Sys Sys->PATH; 	stdin = sys->fildes(0);	stdout = sys->fildes(1);	stderr = sys->fildes(2); 	kr = load Keyring Keyring->PATH;	if(kr == nil)		noload(Keyring->PATH);	auth = load Auth Auth->PATH;	if(auth == nil)		noload(Auth->PATH);	auth->init(); 	keyfile, id: string;	arg := load Arg Arg->PATH;	if(arg == nil)		noload(Arg->PATH);	arg->init(args);	while((o := arg->opt()) != 0)		case o {		's' =>			signer = arg->arg();		'u' =>			id = arg->arg();		* =>			usage();		}	args = arg->argv();	arg = nil; 	if(args == nil)		args = "default" :: nil; 	if(id == nil)		id= user(); 	if(args != nil)		keyfile = hd args;	else		keyfile = "default";	if(len keyfile > 0 && keyfile[0] != '/')		keyfile = "/usr/" + id + "/keyring/" + keyfile; 	ai := kr->readauthinfo(keyfile);	if(ai == nil)		err(sys->sprint("can't read certificate from %s: %r", keyfile));sys->print("key owner: %s\n", ai.mypk.owner); 	sys->pctl(Sys->FORKNS|Sys->FORKFD, nil);	mountsrv(ai); 	# get password	ok: int;	secret: array of byte;	oldhash: array of byte;	word: string;	for(;;){		sys->print("Inferno secret: ");		(ok, word) = readline(stdin, "rawon");		if(!ok || word == nil)			exit;		secret = array of byte word;		(nil, s) := hashkey(secret);		for(i := 0; i < len word; i++)			word[i] = ' ';		oldhash = array of byte s;		e := putsecret(oldhash, nil);		if(e != "wrong secret"){			if(e == nil)				break;			err(e);		}		sys->fprint(stderr, "!wrong secret\n");	}	newsecret: array of byte;	for(;;){		for(;;){			sys->print("new secret [default = don't change]: ");			(ok, word) = readline(stdin, "rawon");			if(!ok)				exit;			if(word == "" && secret != nil)				break;			if(len word >= 8)				break;			sys->print("!secret must be at least 8 characters\n");		}		if(word != ""){			# confirm password change			word1 := word;			sys->print("confirm: ");			(ok, word) = readline(stdin, "rawon");			if(!ok || word != word1){				sys->fprint(stderr, "!entries didn't match\n");				continue;			}			# TO DO...			#pwbuf := array of byte word;			#newsecret = array[Keyring->SHA1dlen] of byte;			#kr->sha1(pwbuf, len pwbuf, newsecret, nil);			newsecret = array of byte word;		}		if(!eq(newsecret, secret)){			if((e := putsecret(oldhash, newsecret)) != nil){				sys->fprint(stderr, "passwd: can't update secret for %s: %s\n", id, e);				continue;			}		}		break;	}} noload(s: string){	err(sys->sprint("can't load %s: %r", s));} err(s: string){	sys->fprint(sys->fildes(2), "passwd: %s\n", s);	raise "fail:error";} mountsrv(ai: ref Keyring->Authinfo): string{	(rc, c) := sys->dial(netmkaddr(signer, "net", "infkey"), nil);	if(rc < 0)		err(sys->sprint("can't dial %s: %r", signer));	(fd, id_or_err) := auth->client("sha1/rc4_256", ai, c.dfd);	if(fd == nil)		err(sys->sprint("can't authenticate with %s: %r", signer));	if(sys->mount(fd, nil, keysrv, Sys->MREPL, nil) < 0)		err(sys->sprint("can't mount %s on %s: %r", signer, keysrv));	return id_or_err;} user(): string{	fd := sys->open("/dev/user", Sys->OREAD);	if(fd == nil)		err(sys->sprint("can't open /dev/user: %r")); 	buf := array[Sys->NAMEMAX] of byte;	n := sys->read(fd, buf, len buf);	if(n < 0)		err(sys->sprint("error reading /dev/user: %r")); 	return string buf[0:n];	} eq(a, b: array of byte): int{	if(len a != len b)		return 0;	for(i := 0; i < len a; i++)		if(a[i] != b[i])			return 0;	return 1;} hashkey(a: array of byte): (array of byte, string){	hash := array[Keyring->SHA1dlen] of byte;	kr->sha1(a, len a, hash, nil);	s := "";	for(i := 0; i < len hash; i++)		s += sys->sprint("%2.2ux", int hash[i]);	return (hash, s);} putsecret(oldhash: array of byte, secret: array of byte): string{	fd := sys->create(keysrv+"/secret", Sys->OWRITE, 8r600);	if(fd == nil)		return sys->sprint("%r");	n := len oldhash;	if(secret != nil)		n += 1 + len secret;	buf := array[n] of byte;	buf[0:] = oldhash;	if(secret != nil){		buf[len oldhash] = byte ' ';		buf[len oldhash+1:] = secret;	}	if(sys->write(fd, buf, len buf) < 0)		return sys->sprint("%r");	return nil;} netmkaddr(addr, net, svc: string): string{	if(net == nil)		net = "net";	(n, nil) := sys->tokenize(addr, "!");	if(n <= 1){		if(svc== nil)			return sys->sprint("%s!%s", net, addr);		return sys->sprint("%s!%s!%s", net, addr, svc);	}	if(svc == nil || n > 2)		return addr;	return sys->sprint("%s!%s", addr, svc);} readline(io: ref Sys->FD, mode: string): (int, string){	r : int;	line : string;	buf := array[8192] of byte;	fdctl : ref Sys->FD;	rawoff := array of byte "rawoff"; 	if(mode == "rawon"){		fdctl = sys->open("/dev/consctl", sys->OWRITE);		if(fdctl == nil || sys->write(fdctl,array of byte mode,len mode) != len mode){			sys->fprint(stderr, "unable to change console mode");			return (0,nil);		}	} 	line = "";	for(;;) {		r = sys->read(io, buf, len buf);		if(r <= 0){			sys->fprint(stderr, "error read from console mode");			if(mode == "rawon")				sys->write(fdctl,rawoff,6);			return (0, nil);		} 		line += string buf[0:r];		if ((len line >= 1) && (line[(len line)-1] == '\n')){			if(mode == "rawon"){				r = sys->write(stdout,array of byte "\n",1);				if(r <= 0) {					sys->write(fdctl,rawoff,6);					return (0, nil);				}			}			break;		}		else {			if(mode == "rawon"){				#r = sys->write(stdout, array of byte "*",1);				if(r <= 0) {					sys->write(fdctl,rawoff,6);					return (0, nil);				}			}		}	} 	if(mode == "rawon")		sys->write(fdctl,rawoff,6); 	return (1, line[0:len line - 1]);}