ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/cmd/auth/ai2key.b/
implement Ai2fact;
# authinfo to factotum key set
# intermediate version, for use until revised Inferno authentication is ready
# converts an old authinfo entry in keyring directory to a key for factotum
#
# keys are in proto=infauth, and include the data for the signed certificate, and the diffie-helman parameters
include "sys.m";
sys: Sys;
include "draw.m";
include "keyring.m";
keyring: Keyring;
Certificate, IPint, PK, SK: import keyring;
include "daytime.m";
daytime: Daytime;
include "arg.m";
Ai2fact: module
{
init: fn(nil: ref Draw->Context, nil: list of string);
};
init(nil: ref Draw->Context, args: list of string)
{
sys = load Sys Sys->PATH;
keyring = load Keyring Keyring->PATH;
daytime = load Daytime Daytime->PATH;
arg := load Arg Arg->PATH;
arg->init(args);
arg->setusage("ai2key [-t 'attr=value attr=value ...'] keyfile ...");
tag: string;
while((o := arg->opt()) != 0)
case o {
't' =>
tag = arg->earg();
* =>
arg->usage();
}
args = arg->argv();
if(args == nil)
arg->usage();
arg = nil;
now := daytime->now();
for(; args != nil; args = tl args){
keyfile := hd args;
ai := keyring->readauthinfo(keyfile);
if(ai == nil)
error(sys->sprint("cannot read %s: %r", keyfile));
if(ai.cert.exp != 0 && ai.cert.exp <= now){
sys->fprint(sys->fildes(2), "ai2key: %s: certificate expired -- key ignored\n", keyfile);
continue;
}
if(ai.cert.exp != 0)
expires := sys->sprint(" expires=%ud", ai.cert.exp);
ha := ai.cert.ha;
if(ha == "sha")
ha = "sha1";
if(tag != nil)
tag = " "+tag;
sys->print("key proto=infauth%s %s sigalg=%s-%s user=%q signer=%q pk=%s !sk=%s spk=%s cert=%s dh-alpha=%s dh-p=%s%s\n",
tag, locations(filename(keyfile)), ai.cert.sa.name, ha, ai.mypk.owner, ai.spk.owner, pktostr(ai.mypk), sktostr(ai.mysk),
pktostr(ai.spk), certtostr(ai.cert), ai.alpha.iptostr(16), ai.p.iptostr(16), expires);
}
}
error(e: string)
{
sys->fprint(sys->fildes(2), "ai2key: %s\n", e);
raise "fail:error";
}
filename(s: string): string
{
(nil, fld) := sys->tokenize(s, "/");
for(; fld != nil && tl fld != nil; fld = tl fld){
# skip
}
return hd fld;
}
# guess plausible domain, server and service attributes from the file name
locations(file: string): string
{
if(file == "default")
return "dom=* server=*";
(nf, flds) := sys->tokenize(file, "!");
case nf {
* =>
return sys->sprint("%s", server(file));
2 =>
return sys->sprint("%s", server(hd tl flds));
3 =>
# ignore network component
return sys->sprint("%s service=%q", server(hd tl flds), hd tl tl flds);
}
}
server(name: string): string
{
# if the name contains dot(s), we'll treat it as a domain name
if(sys->tokenize(name, ".").t0 > 1)
return sys->sprint("dom=%q server=%q", name, name);
return sys->sprint("server=%q", name);
}
certtostr(c: ref Certificate): string
{
return dnl(keyring->certtostr(c));
}
pktostr(pk: ref PK): string
{
return dnl(keyring->pktostr(pk));
}
sktostr(sk: ref SK): string
{
return dnl(keyring->sktostr(sk));
}
dnl(s: string): string
{
for(i := 0; i < len s; i++)
if(s[i] == '\n')
s[i] = '^';
while(--i > 0 && s[i] == '^'){
# skip
}
if(i != len s)
return s[0: i+1];
return s;
}