summaryrefslogtreecommitdiff
path: root/appl/cmd/auth/ai2key.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/auth/ai2key.b')
-rw-r--r--appl/cmd/auth/ai2key.b144
1 files changed, 144 insertions, 0 deletions
diff --git a/appl/cmd/auth/ai2key.b b/appl/cmd/auth/ai2key.b
new file mode 100644
index 00000000..aff86d57
--- /dev/null
+++ b/appl/cmd/auth/ai2key.b
@@ -0,0 +1,144 @@
+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;
+}