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 namelocations(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;}
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;
}