shithub: purgatorio

ref: 94443daf8e248e65afc8d3f17f26efea22748b51
dir: /appl/cmd/auth/createsignerkey.b/

View raw version
implement Createsignerkey;

include "sys.m";
	sys: Sys;

include "draw.m";

include "daytime.m";

include "ipints.m";
include "crypt.m";
	crypt: Crypt;

include "oldauth.m";
	oldauth: Oldauth;

include "arg.m";

# signer key never expires
SKexpire:       con 0;

# size in bits of modulus for public keys
PKmodlen:		con 1024;

# size in bits of modulus for diffie hellman
DHmodlen:		con 1024;

algs := array[] of {"rsa", "elgamal"};	# first entry is default

Createsignerkey: module
{
	init:	fn(nil: ref Draw->Context, nil: list of string);
};

init(nil: ref Draw->Context, args: list of string)
{
	err: string;

	sys = load Sys Sys->PATH;
	crypt = load Crypt Crypt->PATH;
	oldauth = load Oldauth Oldauth->PATH;
	oldauth->init();
	arg := load Arg Arg->PATH;

	arg->init(args);
	arg->setusage("createsignerkey [-a algorithm] [-f keyfile] [-e ddmmyyyy] [-b size-in-bits] name-of-owner");
	alg := algs[0];
	filename := "/keydb/signerkey";
	expire := SKexpire;
	bits := PKmodlen;
	while((c := arg->opt()) != 0){
		case c {
		'a' =>
			alg = arg->arg();
			if(alg == nil)
				arg->usage();
			for(i:=0;; i++){
				if(i >= len algs)
					error(sys->sprint("unknown algorithm: %s", alg));
				else if(alg == algs[i])
					break;
			}
		'f' or 'k' =>
			filename = arg->earg();
		'e' =>
			s := arg->earg();
			(err, expire) = checkdate(s);
			if(err != nil)
				error(err);
		'b' =>
			s := arg->earg();
			bits = int s;
			if(bits < 32 || bits > 4096)
				error("modulus must be in the range of 32 to 4096 bits");
		* =>
			arg->usage();
		}
	}
	args = arg->argv();
	if(args == nil)
		arg->usage();
	arg = nil;

	owner := hd args;

	# generate a local key, self-signed
	info := ref Oldauth->Authinfo;
	info.mysk = crypt->genSK(alg, bits);
	if(info.mysk == nil)
		error(sys->sprint("algorithm %s not configured in system", alg));
	info.owner = owner;
	info.mypk = crypt->sktopk(info.mysk);
	info.spk = crypt->sktopk(info.mysk);
	myPKbuf := array of byte oldauth->pktostr(info.mypk, owner);
	state := crypt->sha1(myPKbuf, len myPKbuf, nil, nil);
	info.cert = oldauth->sign(info.mysk, owner, expire, state, "sha1");
	(info.alpha, info.p) = crypt->dhparams(DHmodlen);

	if(oldauth->writeauthinfo(filename, info) < 0)
		error(sys->sprint("can't write signerkey file %s: %r", filename));
}

error(s: string)
{
	sys->fprint(sys->fildes(2), "createsignerkey: %s\n", s);
	raise "fail:error";
}

checkdate(word: string): (string, int)
{
	if(len word != 8)
		return ("!date must be in form ddmmyyyy", 0);

	daytime := load Daytime Daytime->PATH;

	now := daytime->now();

	tm := daytime->local(now);
	tm.sec = 59;
	tm.min = 59;
	tm.hour = 24;

	tm.mday = int word[0:2];
	if(tm.mday > 31 || tm.mday < 1)
		return ("!bad day of month", 0);

	tm.mon = int word[2:4] - 1;
	if(tm.mon > 11 || tm.mday < 0)
		return ("!bad month", 0);

	tm.year = int word[4:8] - 1900;
	if(tm.year < 70)
		return ("!bad year", 0);

	newdate := daytime->tm2epoch(tm);
	if(newdate < now)
		return ("!expiration date must be in the future", 0);

	return (nil, newdate);
}