code: 9ferno

ref: 6d69f6fba35087686f79adb2ea0d67944a62ca7b
dir: /appl/cmd/auth/mkauthinfo.b/

View raw version
implement Mkauthinfo;

#
#  sign a new key to produce a certificate
#

include "sys.m";
	sys: Sys;

include "draw.m";

include "keyring.m";
	kr: Keyring;
	IPint: import kr;

include "security.m";
	auth: Auth;

include "daytime.m";
	daytime: Daytime;

include "arg.m";

Mkauthinfo: module{
	init:	fn(ctxt: ref Draw->Context, argv: list of string);
};

stderr: ref Sys->FD;

init(nil: ref Draw->Context, args: list of string)
{
	sys = load Sys Sys->PATH;
	stderr = sys->open("/dev/cons", sys->OWRITE);

	kr = load Keyring Keyring->PATH;

	auth = load Auth Auth->PATH;
	if(auth == nil)
		nomod(Auth->PATH);

	daytime = load Daytime Daytime->PATH;
	if(daytime == nil) 
		nomod(Daytime->PATH);

	arg := load Arg Arg->PATH;
	if(arg == nil)
		nomod(Arg->PATH);
	arg->init(args);
	arg->setusage("auth/mkauthinfo [-k keyspec] [-e ddmmyyyy] user [keyfile]");
	keyspec := "key=default";
	expiry := 0;
	while((o := arg->opt()) != 0)
		case o {
		'k' =>
			keyspec = arg->earg();
		'e' =>
			expiry = parsedate(arg->earg());
		* =>
			arg->usage();
		}
	args = arg->argv();
	if(args == nil)
		arg->usage();
	user := hd args;
	args = tl args;
	dstfile := "/fd/1";
	if(args != nil)
		dstfile = hd args;
	arg = nil;

	sai := auth->key(keyspec);
	if(sai == nil){
		sys->fprint(stderr, "sign: can't find key matching %q: %r\n", keyspec);
		raise "fail:no key";
	}

	info := ref Keyring->Authinfo;
	info.alpha = sai.alpha;
	info.p = sai.p;
	info.mysk = kr->genSKfromPK(sai.spk, user);
	info.mypk = kr->sktopk(info.mysk);
	info.spk = sai.mypk;
	pkbuf := array of byte kr->pktostr(info.mypk);
	state := kr->sha1(pkbuf, len pkbuf, nil, nil);
	info.cert = kr->sign(sai.mysk, expiry, state, "sha1");
	if(kr->writeauthinfo("/fd/1", info) < 0){
		sys->fprint(stderr, "sign: error writing certificate: %r\n");
		raise "fail:write error";
	}
}

parsedate(s: string): int
{
	now := daytime->now();
	tm := daytime->local(now);
	if(s == "permanent")
		return 0;
	if(len s != 8)
		fatal("bad date format "+s+" (expected DDMMYYYY)");
	tm.mday = int s[0:2];
	if(tm.mday > 31 || tm.mday < 1)
		fatal(sys->sprint("bad day of month %d", tm.mday));
	tm.mon = int s[2:4] - 1;
	if(tm.mon > 11 || tm.mday < 0)
		fatal(sys->sprint("bad month %d\n", tm.mon + 1));
	tm.year = int s[4:8] - 1900;
	if(tm.year < 70)
		fatal(sys->sprint("bad year %d (year may be no earlier than 1970)", tm.year + 1900));
	expiry := daytime->tm2epoch(tm);
	expiry += 60;
	if(expiry <= now)
		fatal("expiry date has already passed");
	return expiry;
}

nomod(mod: string)
{
	fatal(sys->sprint("can't load %s: %r",mod));
}

fatal(msg: string)
{
	sys->fprint(stderr, "mkauthinfo: %s\n", msg);
	raise "fail:error";
}