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.