summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2008-01-16 14:00:01 +0000
committerCharles.Forsyth <devnull@localhost>2008-01-16 14:00:01 +0000
commitcbcf843ad68398691ae1268652eeea7ca96b376b (patch)
tree85182a19e4c6c069063454aa240ca820112fbd1f
parent85cef7b8460d7280ed0d574689ca8b0d38b21721 (diff)
20080116-1406
-rw-r--r--appl/cmd/auth/factotum/proto/authquery.b204
-rw-r--r--dis/auth/proto/authquery.disbin2943 -> 2987 bytes
2 files changed, 204 insertions, 0 deletions
diff --git a/appl/cmd/auth/factotum/proto/authquery.b b/appl/cmd/auth/factotum/proto/authquery.b
new file mode 100644
index 00000000..c21a7c58
--- /dev/null
+++ b/appl/cmd/auth/factotum/proto/authquery.b
@@ -0,0 +1,204 @@
+implement Authproto;
+include "sys.m";
+ sys: Sys;
+ Rread, Rwrite: import Sys;
+include "draw.m";
+include "keyring.m";
+include "bufio.m";
+include "sexprs.m";
+ sexprs: Sexprs;
+ Sexp: import sexprs;
+include "spki.m";
+ spki: SPKI;
+include "../authio.m";
+ authio: Authio;
+ Aattr, Aval, Aquery: import Authio;
+ Attr, IO, Key, Authinfo: import authio;
+
+# queries to handle:
+# are you a member of group X?
+# are you group leader of group X?
+
+Debug: con 0;
+
+# init, addkey, closekey, write, read, close, keyprompt
+
+Query: adt {
+ e: ref Sexp;
+ certs: list of ref Sexp;
+ gotcerts: list of ref Sexp;
+
+ parse: fn(se: ref Sexp): (ref Query, string);
+ neededcert: fn(q: self ref Query): ref Sexp;
+ addcert: fn(q: self ref Query, cert: ref Sexp): string;
+ result: fn(q: self ref Query): ref Sexp;
+};
+
+Read: adt {
+ buf: array of byte;
+ ptr: int;
+ off: int;
+ io: ref IO;
+
+ new: fn(io: ref IO): ref Read;
+ getb: fn(r: self ref Read): int;
+ ungetb: fn(r: self ref Read): int;
+ offset: fn(r: self ref Read): big;
+};
+
+
+Maxmsg: con 4000;
+
+init(f: Authio): string
+{
+ authio = f;
+ sys = load Sys Sys->PATH;
+ spki = load SPKI SPKI->PATH;
+ spki->init();
+ sexprs = load Sexprs Sexprs->PATH;
+ sexprs->init();
+ return nil;
+}
+
+interaction(attrs: list of ref Attr, io: ref IO): string
+{
+ case authio->lookattrval(attrs, "role") {
+ "client" =>
+ return client(attrs, io);
+ "server" =>
+ return server(attrs, io);
+ * =>
+ return "unknown role";
+ }
+}
+
+client(attrs: list of ref Attr, io: ref IO): string
+{
+ (sexp, nil, err) := Sexp.parse(authio->lookattrval(attrs, "query"));
+ if(sexp == nil || err != nil)
+ raise sys->sprint("bad or empty query %q: %s", authio->lookattrval(attrs, "query"), err);
+ for(;;){
+ write(io, sexp.pack());
+ (sexp, err) = Sexp.read(Read.new(io));
+ if(err != nil)
+ return "authquery: bad query: "+err;
+ if(sexp == nil)
+ return "authquery: no result";
+ if(sexp.op() != "needcert"){
+ io.done(ref Authinfo(nil, nil, nil, sexp.pack())); # XXX use something other than secret
+ return nil;
+ }
+ (sexp, err) = needcert(io, sexp);
+ if(sexp == nil)
+ return "authquery: no cert: "+err;
+ }
+}
+
+server(nil: list of ref Attr, io: ref IO): string
+{
+ (sexp, err) := Sexp.read(Read.new(io));
+ if(err != nil)
+ return "authquery: bad query sexp: "+err;
+ q: ref Query;
+ (q, err) = Query.parse(sexp);
+ if(q == nil)
+ return "authquery: bad query: "+err;
+ while((sexp = q.neededcert()) != nil){
+ write(io, sexp.pack());
+ (sexp, err) = Sexp.read(Read.new(io));
+ if(err != nil)
+ return "authquery: bad cert sexp: "+err;
+ if((err = q.addcert(sexp)) != nil)
+ return "authquery: bad certificate received: "+err;
+ }
+ write(io, q.result().pack());
+ io.done(ref Authinfo);
+ return nil;
+}
+
+mkop(op: string, els: list of ref Sexp): ref Sexp
+{
+ return ref Sexp.List(ref Sexp.String(op, nil) :: els);
+}
+
+needcert(nil: ref IO, se: ref Sexp): (ref Sexp, string)
+{
+ return (mkop("cert", se :: nil), nil);
+# (key, err) := io.findkey(
+}
+
+write(io: ref IO, buf: array of byte)
+{
+ while(len buf > Maxmsg){
+ io.write(buf[0:Maxmsg], Maxmsg);
+ buf = buf[Maxmsg:];
+ }
+ io.write(buf, len buf);
+}
+
+Query.parse(sexp: ref Sexp): (ref Query, string)
+{
+ if(!sexp.islist())
+ return (nil, "query must be a list");
+ return (ref Query(sexp, sexp.els(), nil), nil);
+}
+
+Query.neededcert(q: self ref Query): ref Sexp
+{
+ if(q.certs == nil)
+ return nil;
+ c := hd q.certs;
+ q.certs = tl q.certs;
+ if(c.op() != "cert")
+ return nil;
+ for(a := c.args(); a != nil; a = tl a)
+ if((hd a).op() == "delay" && (hd a).args() != nil)
+ sys->sleep(int (hd (hd a).args()).astext());
+ return mkop("needcert", c :: nil);
+}
+
+Query.addcert(q: self ref Query, cert: ref Sexp): string
+{
+ q.gotcerts = cert :: q.gotcerts;
+ return nil;
+}
+
+Query.result(q: self ref Query): ref Sexp
+{
+ return mkop("result", q.gotcerts);
+}
+
+Read.new(io: ref IO): ref Read
+{
+ return ref Read(nil, 0, 0, io);
+}
+
+Read.getb(r: self ref Read): int
+{
+ if(r.ptr >= len r.buf){
+ while((buf := r.io.read()) == nil || len buf == 0)
+ r.io.toosmall(Maxmsg);
+ r.buf = buf;
+ r.ptr = 0;
+ }
+ r.off++;
+ return int r.buf[r.ptr++];
+}
+
+Read.ungetb(r: self ref Read): int
+{
+ if(r.buf == nil || r.ptr == 0)
+ return -1;
+ r.off--;
+ return int r.buf[--r.ptr];
+}
+
+Read.offset(r: self ref Read): big
+{
+ return big r.off;
+}
+
+keycheck(nil: ref Authio->Key): string
+{
+ return nil;
+}
diff --git a/dis/auth/proto/authquery.dis b/dis/auth/proto/authquery.dis
index 2139897a..a5f563b9 100644
--- a/dis/auth/proto/authquery.dis
+++ b/dis/auth/proto/authquery.dis
Binary files differ