summaryrefslogtreecommitdiff
path: root/appl/cmd/auth/factotum/factotum.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/auth/factotum/factotum.b')
-rw-r--r--appl/cmd/auth/factotum/factotum.b128
1 files changed, 108 insertions, 20 deletions
diff --git a/appl/cmd/auth/factotum/factotum.b b/appl/cmd/auth/factotum/factotum.b
index 07169747..0baf9c0c 100644
--- a/appl/cmd/auth/factotum/factotum.b
+++ b/appl/cmd/auth/factotum/factotum.b
@@ -19,6 +19,8 @@ include "authio.m";
include "arg.m";
+include "readdir.m";
+
Factotum: module
{
init: fn(nil: ref Draw->Context, nil: list of string);
@@ -39,7 +41,7 @@ debug := Debug;
files: Files;
authio: Authio;
-keymanc: chan of (list of ref Attr, int, chan of (ref Key, string));
+keymanc: chan of (list of ref Attr, int, chan of (list of ref Key, string));
init(nil: ref Draw->Context, args: list of string)
{
@@ -55,7 +57,7 @@ init(nil: ref Draw->Context, args: list of string)
arg->setusage("auth/factotum [-d] [-m /mnt/factotum] [-s factotum]");
while((o := arg->opt()) != 0)
case o {
- 'd' => debug = 1;
+ 'd' => debug++;
'm' => mntpt = arg->earg();
's' => svcname = "#s"+arg->earg();
* => arg->usage();
@@ -74,7 +76,7 @@ init(nil: ref Draw->Context, args: list of string)
files.needkey = sys->file2chan(mntpt, "needkey");
if(files.ctl == nil || files.rpc == nil || files.proto == nil || files.needkey == nil)
err(sys->sprint("can't create %s/*: %r", mntpt));
- keymanc = chan of (list of ref Attr, int, chan of (ref Key, string));
+ keymanc = chan of (list of ref Attr, int, chan of (list of ref Key, string));
spawn factotumsrv();
}
@@ -101,14 +103,14 @@ rlist: list of ref Fid;
factotumsrv()
{
sys->pctl(Sys->NEWPGRP|Sys->FORKFD|Sys->FORKENV, nil);
- if(!Debug)
+ if(debug == 0)
privacy();
allkeys := array[0] of ref Key;
pidc := chan of int;
donec := chan of ref Fid;
# keyc := chan of (list of ref Attr, chan of (ref Key, string));
needfid := -1;
- needed, needy: list of (int, list of ref Attr, chan of (ref Key, string));
+ needed, needy: list of (int, list of ref Attr, chan of (list of ref Key, string));
needread: Sys->Rread;
needtag := 0;
for(;;) X: alt{
@@ -216,7 +218,7 @@ factotumsrv()
(off, nbytes, nil, rc) := <-files.proto.read =>
if(rc == nil)
break;
- rc <-= reads("pass\np9any\n", off, nbytes); # TO DO
+ rc <-= reads(readprotos(), off, nbytes);
(nil, nil, nil, wc) := <-files.proto.write =>
if(wc != nil)
wc <-= (0, "illegal operation");
@@ -260,7 +262,7 @@ factotumsrv()
break;
}
tag := int t;
- nl: list of (int, list of ref Attr, chan of (ref Key, string));
+ nl: list of (int, list of ref Attr, chan of (list of ref Key, string));
found := 0;
for(l := needed; l != nil; l = tl l){
(ntag, attrs, kc) := hd l;
@@ -268,7 +270,7 @@ factotumsrv()
found = 1;
k := findkey(allkeys, attrs);
if(k != nil)
- kc <-= (k, nil);
+ kc <-= (k :: nil, nil);
else
kc <-= (nil, "needkey "+attrtext(attrs));
while((l = tl l) != nil)
@@ -284,9 +286,9 @@ factotumsrv()
(attrs, required, kc) := <-keymanc =>
# look for key and reply
- k := findkey(allkeys, attrs);
- if(k != nil){
- kc <-= (k, nil);
+ kl := findkeys(allkeys, attrs);
+ if(kl != nil){
+ kc <-= (kl, nil);
break;
}else if(!required || needfid == -1){
kc <-= (nil, "needkey "+attrtext(attrs));
@@ -353,6 +355,21 @@ reads(str: string, off, nbytes: int): (array of byte, string)
return (bstr[off:off+nbytes], nil);
}
+readprotos(): string
+{
+ readdir := load Readdir Readdir->PATH;
+ if(readdir == nil)
+ return "unknown\n";
+ (dirs, nil) := readdir->init("/dis/auth/proto", Readdir->NAME|Readdir->COMPACT);
+ s := "";
+ for(i := 0; i < len dirs; i++){
+ n := dirs[i].name;
+ if(len n > 4 && n[len n-4:] == ".dis")
+ s += n[0: len n-4]+"\n";
+ }
+ return s;
+}
+
Ogok, Ostart, Oread, Owrite, Oauthinfo, Oattr: con iota;
ops := array[] of {
@@ -406,19 +423,19 @@ request(r: ref Fid, pidc: chan of int, donec: chan of ref Fid)
startproto(request: string): (Authproto, list of ref Attr, string)
{
attrs := parseline(request);
- if(Debug)
+ if(debug > 1)
sys->print("-> %s <-\n", attrtext(attrs));
p := lookattrval(attrs, "proto");
if(p == nil)
return (nil, nil, "did not specify protocol");
- if(Debug)
+ if(debug > 1)
sys->print("proto=%s\n", p);
if(any(p, "./")) # avoid unpleasantness
return (nil, nil, "illegal protocol: "+p);
proto := load Authproto "/dis/auth/proto/"+p+".dis";
if(proto == nil)
return (nil, nil, sys->sprint("protocol %s: %r", p));
- if(Debug)
+ if(debug)
sys->print("start %s\n", p);
e: string;
{
@@ -708,9 +725,15 @@ delattrs(lv: list of ref Attr, rv: list of ref Attr): list of ref Attr
return reverse(nl);
}
+ignored(s: string): int
+{
+ return s == "role" || s == "disabled";
+}
+
matchattr(attrs: list of ref Attr, pat: ref Attr): int
{
- return (b := lookattr(attrs, pat.name)) != nil && (pat.tag == Aquery || b.val == pat.val);
+ return (b := lookattr(attrs, pat.name)) != nil && (pat.tag == Aquery || b.val == pat.val) ||
+ ignored(pat.name);
}
matchattrs(pub: list of ref Attr, secret: list of ref Attr, pats: list of ref Attr): int
@@ -756,7 +779,7 @@ shellsort(a: array of ref Attr)
findkey(keys: array of ref Key, attrs: list of ref Attr): ref Key
{
- if(Debug)
+ if(debug)
sys->print("findkey %q\n", attrtext(attrs));
for(i := 0; i < len keys; i++)
if((k := keys[i]) != nil && matchattrs(k.attrs, k.secrets, attrs))
@@ -764,6 +787,17 @@ findkey(keys: array of ref Key, attrs: list of ref Attr): ref Key
return nil;
}
+findkeys(keys: array of ref Key, attrs: list of ref Attr): list of ref Key
+{
+ if(debug)
+ sys->print("findkey %q\n", attrtext(attrs));
+ kl: list of ref Key;
+ for(i := 0; i < len keys; i++)
+ if((k := keys[i]) != nil && matchattrs(k.attrs, k.secrets, attrs))
+ kl = k :: kl;
+ return reverse(kl);
+}
+
delkey(keys: array of ref Key, attrs: list of ref Attr): int
{
nk := 0;
@@ -835,12 +869,20 @@ any(s: string, t: string): int
return 0;
}
-IO.findkey(nil: self ref IO, attrs: list of ref Attr, extra: string): (ref Key, string)
+IO.findkey(io: self ref IO, attrs: list of ref Attr, extra: string): (ref Key, string)
+{
+ (kl, err) := io.findkeys(attrs, extra);
+ if(kl != nil)
+ return (hd kl, err);
+ return (nil, err);
+}
+
+IO.findkeys(nil: self ref IO, attrs: list of ref Attr, extra: string): (list of ref Key, string)
{
ea := parseline(extra);
for(; ea != nil; ea = tl ea)
attrs = hd ea :: attrs;
- kc := chan of (ref Key, string);
+ kc := chan of (list of ref Key, string);
keymanc <-= (attrs, 1, kc); # TO DO: 1 => 0 for not needed
return <-kc;
}
@@ -850,9 +892,12 @@ IO.needkey(nil: self ref IO, attrs: list of ref Attr, extra: string): (ref Key,
ea := parseline(extra);
for(; ea != nil; ea = tl ea)
attrs = hd ea :: attrs;
- kc := chan of (ref Key, string);
+ kc := chan of (list of ref Key, string);
keymanc <-= (attrs, 1, kc);
- return <-kc;
+ (kl, err) := <-kc;
+ if(kl != nil)
+ return (hd kl, err);
+ return (nil, err);
}
IO.read(io: self ref IO): array of byte
@@ -890,6 +935,7 @@ IO.write(io: self ref IO, buf: array of byte, n: int): int
okdata(rpc, buf[0:n]);
return n;
}
+ io.rpc = rpc;
io.toosmall(n+3);
Oauthinfo =>
reply(rpc, "error authentication unfinished");
@@ -899,6 +945,48 @@ IO.write(io: self ref IO, buf: array of byte, n: int): int
exit;
}
+IO.rdwr(io: self ref IO): array of byte
+{
+ io.ok();
+ while((rpc := rio(io.f)) != nil)
+ case rpc.cmd {
+ Oread =>
+ io.rpc = rpc;
+ if(rpc.nbytes >= 3)
+ return nil;
+ io.toosmall(128+3); # make them read something
+ Owrite =>
+ io.rpc = rpc;
+ if(rpc.arg == nil)
+ rpc.arg = array[0] of byte;
+ return rpc.arg;
+ Oauthinfo =>
+ reply(rpc, "error authentication unfinished");
+ * =>
+ phase(rpc, "protocol phase error");
+ }
+ exit;
+}
+
+IO.reply2read(io: self ref IO, buf: array of byte, n: int): int
+{
+ if(io.rpc == nil)
+ return 0;
+ rpc := io.rpc;
+ if(rpc.cmd != Oread){
+ io.rpc = nil;
+ phase(rpc, "internal phase error");
+ return 0;
+ }
+ if(rpc.nbytes-3 < n){
+ io.toosmall(n+3);
+ return 0;
+ }
+ io.rpc = nil;
+ okdata(rpc, buf[0:n]);
+ return 1;
+}
+
IO.ok(io: self ref IO)
{
if(io.rpc != nil){