Unified · Split
| @@ -0,0 +1,204 @@ | ||
| 1 | +implement Authproto; | |
| 2 | +include "sys.m"; | |
| 3 | + sys: Sys; | |
| 4 | + Rread, Rwrite: import Sys; | |
| 5 | +include "draw.m"; | |
| 6 | +include "keyring.m"; | |
| 7 | +include "bufio.m"; | |
| 8 | +include "sexprs.m"; | |
| 9 | + sexprs: Sexprs; | |
| 10 | + Sexp: import sexprs; | |
| 11 | +include "spki.m"; | |
| 12 | + spki: SPKI; | |
| 13 | +include "../authio.m"; | |
| 14 | + authio: Authio; | |
| 15 | + Aattr, Aval, Aquery: import Authio; | |
| 16 | + Attr, IO, Key, Authinfo: import authio; | |
| 17 | + | |
| 18 | +# queries to handle: | |
| 19 | +# are you a member of group X? | |
| 20 | +# are you group leader of group X? | |
| 21 | + | |
| 22 | +Debug: con 0; | |
| 23 | + | |
| 24 | +# init, addkey, closekey, write, read, close, keyprompt | |
| 25 | + | |
| 26 | +Query: adt { | |
| 27 | + e: ref Sexp; | |
| 28 | + certs: list of ref Sexp; | |
| 29 | + gotcerts: list of ref Sexp; | |
| 30 | + | |
| 31 | + parse: fn(se: ref Sexp): (ref Query, string); | |
| 32 | + neededcert: fn(q: self ref Query): ref Sexp; | |
| 33 | + addcert: fn(q: self ref Query, cert: ref Sexp): string; | |
| 34 | + result: fn(q: self ref Query): ref Sexp; | |
| 35 | +}; | |
| 36 | + | |
| 37 | +Read: adt { | |
| 38 | + buf: array of byte; | |
| 39 | + ptr: int; | |
| 40 | + off: int; | |
| 41 | + io: ref IO; | |
| 42 | + | |
| 43 | + new: fn(io: ref IO): ref Read; | |
| 44 | + getb: fn(r: self ref Read): int; | |
| 45 | + ungetb: fn(r: self ref Read): int; | |
| 46 | + offset: fn(r: self ref Read): big; | |
| 47 | +}; | |
| 48 | + | |
| 49 | + | |
| 50 | +Maxmsg: con 4000; | |
| 51 | + | |
| 52 | +init(f: Authio): string | |
| 53 | +{ | |
| 54 | + authio = f; | |
| 55 | + sys = load Sys Sys->PATH; | |
| 56 | + spki = load SPKI SPKI->PATH; | |
| 57 | + spki->init(); | |
| 58 | + sexprs = load Sexprs Sexprs->PATH; | |
| 59 | + sexprs->init(); | |
| 60 | + return nil; | |
| 61 | +} | |
| 62 | + | |
| 63 | +interaction(attrs: list of ref Attr, io: ref IO): string | |
| 64 | +{ | |
| 65 | + case authio->lookattrval(attrs, "role") { | |
| 66 | + "client" => | |
| 67 | + return client(attrs, io); | |
| 68 | + "server" => | |
| 69 | + return server(attrs, io); | |
| 70 | + * => | |
| 71 | + return "unknown role"; | |
| 72 | + } | |
| 73 | +} | |
| 74 | + | |
| 75 | +client(attrs: list of ref Attr, io: ref IO): string | |
| 76 | +{ | |
| 77 | + (sexp, nil, err) := Sexp.parse(authio->lookattrval(attrs, "query")); | |
| 78 | + if(sexp == nil || err != nil) | |
| 79 | + raise sys->sprint("bad or empty query %q: %s", authio->lookattrval(attrs, "query"), err); | |
| 80 | + for(;;){ | |
| 81 | + write(io, sexp.pack()); | |
| 82 | + (sexp, err) = Sexp.read(Read.new(io)); | |
| 83 | + if(err != nil) | |
| 84 | + return "authquery: bad query: "+err; | |
| 85 | + if(sexp == nil) | |
| 86 | + return "authquery: no result"; | |
| 87 | + if(sexp.op() != "needcert"){ | |
| 88 | + io.done(ref Authinfo(nil, nil, nil, sexp.pack())); # XXX use something other than secret | |
| 89 | + return nil; | |
| 90 | + } | |
| 91 | + (sexp, err) = needcert(io, sexp); | |
| 92 | + if(sexp == nil) | |
| 93 | + return "authquery: no cert: "+err; | |
| 94 | + } | |
| 95 | +} | |
| 96 | + | |
| 97 | +server(nil: list of ref Attr, io: ref IO): string | |
| 98 | +{ | |
| 99 | + (sexp, err) := Sexp.read(Read.new(io)); | |
| 100 | + if(err != nil) | |
| 101 | + return "authquery: bad query sexp: "+err; | |
| 102 | + q: ref Query; | |
| 103 | + (q, err) = Query.parse(sexp); | |
| 104 | + if(q == nil) | |
| 105 | + return "authquery: bad query: "+err; | |
| 106 | + while((sexp = q.neededcert()) != nil){ | |
| 107 | + write(io, sexp.pack()); | |
| 108 | + (sexp, err) = Sexp.read(Read.new(io)); | |
| 109 | + if(err != nil) | |
| 110 | + return "authquery: bad cert sexp: "+err; | |
| 111 | + if((err = q.addcert(sexp)) != nil) | |
| 112 | + return "authquery: bad certificate received: "+err; | |
| 113 | + } | |
| 114 | + write(io, q.result().pack()); | |
| 115 | + io.done(ref Authinfo); | |
| 116 | + return nil; | |
| 117 | +} | |
| 118 | + | |
| 119 | +mkop(op: string, els: list of ref Sexp): ref Sexp | |
| 120 | +{ | |
| 121 | + return ref Sexp.List(ref Sexp.String(op, nil) :: els); | |
| 122 | +} | |
| 123 | + | |
| 124 | +needcert(nil: ref IO, se: ref Sexp): (ref Sexp, string) | |
| 125 | +{ | |
| 126 | + return (mkop("cert", se :: nil), nil); | |
| 127 | +# (key, err) := io.findkey( | |
| 128 | +} | |
| 129 | + | |
| 130 | +write(io: ref IO, buf: array of byte) | |
| 131 | +{ | |
| 132 | + while(len buf > Maxmsg){ | |
| 133 | + io.write(buf[0:Maxmsg], Maxmsg); | |
| 134 | + buf = buf[Maxmsg:]; | |
| 135 | + } | |
| 136 | + io.write(buf, len buf); | |
| 137 | +} | |
| 138 | + | |
| 139 | +Query.parse(sexp: ref Sexp): (ref Query, string) | |
| 140 | +{ | |
| 141 | + if(!sexp.islist()) | |
| 142 | + return (nil, "query must be a list"); | |
| 143 | + return (ref Query(sexp, sexp.els(), nil), nil); | |
| 144 | +} | |
| 145 | + | |
| 146 | +Query.neededcert(q: self ref Query): ref Sexp | |
| 147 | +{ | |
| 148 | + if(q.certs == nil) | |
| 149 | + return nil; | |
| 150 | + c := hd q.certs; | |
| 151 | + q.certs = tl q.certs; | |
| 152 | + if(c.op() != "cert") | |
| 153 | + return nil; | |
| 154 | + for(a := c.args(); a != nil; a = tl a) | |
| 155 | + if((hd a).op() == "delay" && (hd a).args() != nil) | |
| 156 | + sys->sleep(int (hd (hd a).args()).astext()); | |
| 157 | + return mkop("needcert", c :: nil); | |
| 158 | +} | |
| 159 | + | |
| 160 | +Query.addcert(q: self ref Query, cert: ref Sexp): string | |
| 161 | +{ | |
| 162 | + q.gotcerts = cert :: q.gotcerts; | |
| 163 | + return nil; | |
| 164 | +} | |
| 165 | + | |
| 166 | +Query.result(q: self ref Query): ref Sexp | |
| 167 | +{ | |
| 168 | + return mkop("result", q.gotcerts); | |
| 169 | +} | |
| 170 | + | |
| 171 | +Read.new(io: ref IO): ref Read | |
| 172 | +{ | |
| 173 | + return ref Read(nil, 0, 0, io); | |
| 174 | +} | |
| 175 | + | |
| 176 | +Read.getb(r: self ref Read): int | |
| 177 | +{ | |
| 178 | + if(r.ptr >= len r.buf){ | |
| 179 | + while((buf := r.io.read()) == nil || len buf == 0) | |
| 180 | + r.io.toosmall(Maxmsg); | |
| 181 | + r.buf = buf; | |
| 182 | + r.ptr = 0; | |
| 183 | + } | |
| 184 | + r.off++; | |
| 185 | + return int r.buf[r.ptr++]; | |
| 186 | +} | |
| 187 | + | |
| 188 | +Read.ungetb(r: self ref Read): int | |
| 189 | +{ | |
| 190 | + if(r.buf == nil || r.ptr == 0) | |
| 191 | + return -1; | |
| 192 | + r.off--; | |
| 193 | + return int r.buf[--r.ptr]; | |
| 194 | +} | |
| 195 | + | |
| 196 | +Read.offset(r: self ref Read): big | |
| 197 | +{ | |
| 198 | + return big r.off; | |
| 199 | +} | |
| 200 | + | |
| 201 | +keycheck(nil: ref Authio->Key): string | |
| 202 | +{ | |
| 203 | + return nil; | |
| 204 | +} | |
Binary file not shown.