shithub: purgatorio

ref: 54bac038f411c10a596adf84c06df32f8c7c4c53
dir: /appl/lib/keyset.b/

View raw version
implement Keyset;

include "sys.m";
	sys: Sys;
include "keyring.m";
	keyring: Keyring;
include "daytime.m";
	daytime: Daytime;
include "readdir.m";

include "keyset.m";

PKHASHLEN: con Keyring->SHA1dlen * 2;

init(): string
{
	sys = load Sys Sys->PATH;
	keyring = load Keyring Keyring->PATH;
	if(keyring == nil)
		return cant(Keyring->PATH);
	daytime = load Daytime Daytime->PATH;
	if(daytime == nil)
		return cant(Daytime->PATH);
	return nil;
}

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

pkhash(pk: string): string
{
	d := array of byte pk;
	digest := array[Keyring->SHA1dlen] of byte;
	keyring->sha1(d, len d, digest, nil);
	s := "";
	for(i := 0; i < len digest; i++)
		s += sys->sprint("%2.2ux", int digest[i]);
	return s;
}

keysforsigner(signername: string, spkhash: string, user: string, dir: string): (list of (string, string, string), string)
{
	if(spkhash != nil && len spkhash != PKHASHLEN)
		return (nil, "invalid hash string");
	if(dir == nil){
		if(user == nil)
			user = readname("/dev/user");
		if(user == nil)
			dir = "/lib/keyring";
		else
			dir = "/usr/" + user + "/keyring";
	}
	readdir := load Readdir Readdir->PATH;
	if(readdir == nil)
		return (nil, sys->sprint("can't load Readdir: %r"));
	now := daytime->now();
	(a, ok) := readdir->init(dir, Readdir->COMPACT|Readdir->MTIME);
	if(ok < 0)
		return (nil, sys->sprint("can't open %s: %r", dir));
	keys: list of (string, string, string);
	for(i := 0; i < len a; i++){
		if(a[i].mode & Sys->DMDIR)
			continue;
		f := dir + "/" + a[i].name;
		info := keyring->readauthinfo(f);
		if(info == nil || info.cert == nil || info.cert.exp != 0 && info.cert.exp < now)
			continue;
		if(signername != nil && info.cert.signer != signername)
			continue;
		if(spkhash != nil && pkhash(keyring->pktostr(info.spk)) != spkhash)
			continue;
		keys = (f, info.mypk.owner, info.cert.signer) :: keys;
	}
	return (keys, nil);
}

readname(f: string): string
{
	fd := sys->open(f, Sys->OREAD);
	if(fd == nil)
		return nil;
	buf := array[Sys->NAMEMAX] of byte;
	n := sys->read(fd, buf, len buf);
	if(n <= 0)
		return nil;
	return string buf[0:n];
}