summaryrefslogtreecommitdiff
path: root/appl
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2008-10-21 21:53:53 +0000
committerCharles.Forsyth <devnull@localhost>2008-10-21 21:53:53 +0000
commitbb0454063029bcd36bb713dc95bbce4c4fa43510 (patch)
tree4dbf3828724c2b3a43af70f855dd04ad726a3706 /appl
parent7bd3b6e428a8af0be5091e7ff22b07481debdf97 (diff)
20081021-2253
Diffstat (limited to 'appl')
-rw-r--r--appl/cmd/auth/ai2key.b144
-rw-r--r--appl/cmd/auth/factotum/proto/infauth.b66
-rw-r--r--appl/cmd/auth/mkfile1
3 files changed, 199 insertions, 12 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;
+}
diff --git a/appl/cmd/auth/factotum/proto/infauth.b b/appl/cmd/auth/factotum/proto/infauth.b
index cfc847eb..e9b87553 100644
--- a/appl/cmd/auth/factotum/proto/infauth.b
+++ b/appl/cmd/auth/factotum/proto/infauth.b
@@ -139,9 +139,8 @@ interaction(attrs: list of ref Attr, io: ref IO): string
senderr(io, e);
break;
Error1 =>
- senderr(io, "missing your authentication data");
- x: string = e;
- return "remote: "+x;
+ senderr(io, "failed"); # acknowledge error
+ return remote(e);
}
{
@@ -151,8 +150,7 @@ interaction(attrs: list of ref Attr, io: ref IO): string
Error0 =>
return e;
Error1 =>
- x: string = e;
- return "remote: "+x;
+ return remote(e);
}
if(err != nil)
return err;
@@ -160,13 +158,26 @@ interaction(attrs: list of ref Attr, io: ref IO): string
return negotiatecrypto(io, key, ai, rattrs);
}
+remote(s: string): string
+{
+ # account for strange earlier interface
+ if(len s < 6 || s[0: 6] != "remote")
+ return "remote: "+s;
+ return s;
+}
+
+# TO DO: exchange attr/value pairs, covered by hmac (use part of secret up to hmac block size of 64 bytes)
+# the old scheme can be distinguished either by a prefix "attrs " or simply because the string contains "=",
+# and the server side can then reply. the hmac is to prevent tampering.
negotiatecrypto(io: ref IO, key: ref Key, ai: ref Authinfo, attrs: list of ref Sexp): string
{
role := authio->lookattrval(key.attrs, "role");
alg: string;
{
if(role == "client"){
- alg = authio->lookattrval(key.attrs, "alg");
+ alg = authio->lookattrval(key.attrs, ":alg");
+ if(alg == nil)
+ alg = authio->lookattrval(key.attrs, "alg"); # old way
if(alg == nil)
alg = "md5/rc4_256";
sendmsg(io, array of byte alg);
@@ -297,7 +308,8 @@ getmsg(io: ref IO): array of byte raises (Error0, Error1)
if(len buf != m)
raise Error0("io error: (impossible?) msg length " + string m);
if(h[0] == '!'){
-sys->print("got remote error: %s, len %d\n", string buf, len string buf);
+ if(0)
+ sys->print("got remote error: %q, len %d\n", string buf, len string buf);
raise Error1(string buf);
}
return buf;
@@ -318,16 +330,46 @@ senderr(io: ref IO, e: string)
io.write(buf, len buf);
}
+# both the s-expression and k=v form are interim, until all
+# the factotum implementations can manage public keys
+# the s-expression form was the original one used by Inferno factotum
+# the form in which Authinfo components are separate attributes is the
+# one now used by Plan 9 and Plan 9 Ports factotum implementations
keytoauthinfo(key:ref Key): (ref Keyring->Authinfo, string)
{
- if((s := authio->lookattrval(key.secrets, "!authinfo")) == nil){
- # XXX could look up authinfo by hash at this point
- return (nil, "no authinfo attribute");
- }
+ if((s := authio->lookattrval(key.secrets, "!authinfo")) != nil)
+ return strtoauthinfo(s);
+ # TO DO: could look up authinfo by hash
+ ai := ref Keyring->Authinfo;
+ if((s = kv(key.secrets, "!sk")) == nil || (ai.mysk = keyring->strtosk(s)) == nil)
+ return (nil, "bad secret key");
+ if((s = kv(key.attrs, "pk")) == nil || (ai.mypk = keyring->strtopk(s)) == nil)
+ return (nil, "bad public key");
+ if((s = kv(key.attrs, "cert")) == nil || (ai.cert = keyring->strtocert(s)) == nil)
+ return (nil, "bad certificate");
+ if((s = kv(key.attrs, "spk")) == nil || (ai.spk = keyring->strtopk(s)) == nil)
+ return (nil, "bad signer public key");
+ if((s = kv(key.attrs, "dh-alpha")) == nil || (ai.alpha = IPint.strtoip(s, 16)) == nil)
+ return (nil, "bad value for alpha");
+ if((s = kv(key.attrs, "dh-p")) == nil || (ai.p = IPint.strtoip(s, 16)) == nil)
+ return (nil, "bad value for p");
+ return (ai, nil);
+}
- return strtoauthinfo(s);
+kv(a: list of ref Attr, name: string): string
+{
+ return rnl(authio->lookattrval(a, name));
+}
+
+rnl(s: string): string
+{
+ for(i := 0; i < len s; i++)
+ if(s[i] == '^')
+ s[i] = '\n';
+ return s;
}
+# s-expression form
strtoauthinfo(s: string): (ref Keyring->Authinfo, string)
{
(se, err, nil) := Sexp.parse(s);
diff --git a/appl/cmd/auth/mkfile b/appl/cmd/auth/mkfile
index 5782599e..71d31533 100644
--- a/appl/cmd/auth/mkfile
+++ b/appl/cmd/auth/mkfile
@@ -5,6 +5,7 @@ DIRS=\
TARG=\
aescbc.dis\
+ ai2key.dis\
changelogin.dis\
countersigner.dis\
convpasswd.dis\