diff options
| author | forsyth <forsyth@vitanuova.com> | 2011-01-17 11:10:35 +0000 |
|---|---|---|
| committer | forsyth <forsyth@vitanuova.com> | 2011-01-17 11:10:35 +0000 |
| commit | d6b4eae8eb0a5ca3119414005e483fedd63a62d6 (patch) | |
| tree | 4959b04b1ae02ce5ccb4b3c0a8c459ff46587eb7 /appl/cmd | |
| parent | 9e6910dc0c747c8f30b87f6482f4eadb48ad6654 (diff) | |
20110117-1110
Diffstat (limited to 'appl/cmd')
| -rw-r--r-- | appl/cmd/auth/dsagen.b | 14 | ||||
| -rw-r--r-- | appl/cmd/auth/factotum/proto/rsa.b | 64 | ||||
| -rw-r--r-- | appl/cmd/auth/getpk.b | 32 | ||||
| -rw-r--r-- | appl/cmd/auth/rsagen.b | 44 | ||||
| -rw-r--r-- | appl/cmd/auth/signer.b | 83 | ||||
| -rw-r--r-- | appl/cmd/auth/verify.b | 13 | ||||
| -rw-r--r-- | appl/cmd/cpu.b | 27 | ||||
| -rw-r--r-- | appl/cmd/dial.b | 12 | ||||
| -rw-r--r-- | appl/cmd/listen.b | 33 | ||||
| -rw-r--r-- | appl/cmd/sh/mpexpr.b | 10 | ||||
| -rw-r--r-- | appl/cmd/spki/verify.b | 10 | ||||
| -rw-r--r-- | appl/cmd/ssh/authpassword.b | 68 | ||||
| -rw-r--r-- | appl/cmd/ssh/authrsa.b | 188 | ||||
| -rw-r--r-- | appl/cmd/ssh/authtis.b | 119 | ||||
| -rw-r--r-- | appl/cmd/ssh/cipher3des.b | 51 | ||||
| -rw-r--r-- | appl/cmd/ssh/cipherblowfish.b | 43 | ||||
| -rw-r--r-- | appl/cmd/ssh/cipherdes.b | 43 | ||||
| -rw-r--r-- | appl/cmd/ssh/ciphernone.b | 28 | ||||
| -rw-r--r-- | appl/cmd/ssh/cipherrc4.b | 46 | ||||
| -rw-r--r-- | appl/cmd/ssh/mkfile | 29 | ||||
| -rw-r--r-- | appl/cmd/ssh/sshio.b | 586 | ||||
| -rw-r--r-- | appl/cmd/ssh/sshio.m | 194 | ||||
| -rw-r--r-- | appl/cmd/ssh/sshserve.b | 495 | ||||
| -rw-r--r-- | appl/cmd/styxlisten.b | 34 |
24 files changed, 172 insertions, 2094 deletions
diff --git a/appl/cmd/auth/dsagen.b b/appl/cmd/auth/dsagen.b index 51b50a12..3e24df2f 100644 --- a/appl/cmd/auth/dsagen.b +++ b/appl/cmd/auth/dsagen.b @@ -5,12 +5,9 @@ include "sys.m"; include "draw.m"; -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; +include "keyring.m"; + kr: Keyring; + IPint, DSAsk, DSApk, DSAsig: import kr; include "arg.m"; @@ -22,8 +19,7 @@ Dsagen: module init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; + kr = load Keyring Keyring->PATH; arg := load Arg Arg->PATH; arg->init(args); @@ -41,7 +37,7 @@ init(nil: ref Draw->Context, args: list of string) arg->usage(); arg = nil; - sk := crypt->dsagen(nil); + sk := DSAsk.gen(nil); if(tag != nil) tag = " "+tag; s := add("p", sk.pk.p); diff --git a/appl/cmd/auth/factotum/proto/rsa.b b/appl/cmd/auth/factotum/proto/rsa.b index 8af64578..24dcef43 100644 --- a/appl/cmd/auth/factotum/proto/rsa.b +++ b/appl/cmd/auth/factotum/proto/rsa.b @@ -1,10 +1,6 @@ implement Authproto; -# SSH RSA authentication -# -# this version is compatible with Plan 9 factotum -# Plan 9 port's factotum works differently, and eventually -# we'll support both (the role= attribute distinguishes the cases), but not today +# SSH RSA authentication. # # Client protocol: # read public key @@ -20,38 +16,35 @@ include "sys.m"; include "draw.m"; -include "ipints.m"; - ipints: IPints; - IPint: import ipints; -include "crypt.m"; - crypt: Crypt; - SK, PK: import crypt; +include "keyring.m"; + kr: Keyring; + IPint, RSAsk, RSApk: import kr; include "../authio.m"; authio: Authio; Aattr, Aval, Aquery: import Authio; - Attr, IO, Key: import authio; + Attr, IO, Key, Authinfo: import authio; eqbytes, memrandom: import authio; - findattrval: import authio; + lookattrval: import authio; init(f: Authio): string { authio = f; sys = load Sys Sys->PATH; - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; + kr = load Keyring Keyring->PATH; +# base16 = load Encoding Encoding->BASE16PATH; return nil; } interaction(attrs: list of ref Attr, io: ref IO): string { - role := findattrval(attrs, "role"); + role := lookattrval(attrs, "role"); if(role == nil) return "role not specified"; if(role != "client") return "only client role supported"; - sk: ref SK.RSA; + sk: ref RSAsk; keys: list of ref Key; err: string; for(;;){ @@ -74,7 +67,7 @@ interaction(attrs: list of ref Attr, io: ref IO): string io.error("invalid challenge value"); continue; } - m := crypt->rsadecrypt(sk, chal); + m := sk.decrypt(chal); b := array of byte m.iptostr(16); io.write(b, len b); io.done(nil); @@ -96,33 +89,30 @@ waitread(io: ref IO) Badkey: exception(string); -kv(key: ref Key, name: string): ref IPint raises Badkey +ipint(attrs: list of ref Attr, name: string): ref IPint raises Badkey { - if(name[0] == '!') - a := authio->findattrval(key.secrets, name); - else - a = authio->findattrval(key.attrs, name); - if(a == nil) + s := lookattrval(attrs, name); + if(s == nil) raise Badkey("missing attribute "+name); - m := IPint.strtoip(a, 16); + m := IPint.strtoip(s, 16); if(m == nil) - raise Badkey("bad value for "+name); + raise Badkey("invalid value for "+name); return m; } -keytorsa(k: ref Key): (ref SK.RSA, string) +keytorsa(k: ref Key): (ref RSAsk, string) { - sk := ref SK.RSA; - sk.pk = ref PK.RSA; + sk := ref RSAsk; + sk.pk = ref RSApk; { - sk.pk.ek = kv(k, "ek"); - sk.pk.n = kv(k, "n"); - sk.dk = kv(k, "!dk"); - sk.p = kv(k, "!p"); - sk.q = kv(k, "!q"); - sk.kp = kv(k, "!kp"); - sk.kq = kv(k, "!kq"); - sk.c2 = kv(k, "!c2"); + sk.pk.ek = ipint(k.attrs, "ek"); + sk.pk.n = ipint(k.attrs, "n"); + sk.dk = ipint(k.secrets, "!dk"); + sk.p = ipint(k.secrets, "!p"); + sk.q = ipint(k.secrets, "!q"); + sk.kp = ipint(k.secrets, "!kp"); + sk.kq = ipint(k.secrets, "!kq"); + sk.c2 = ipint(k.secrets, "!c2"); }exception e{ Badkey => return (nil, "rsa key "+e); diff --git a/appl/cmd/auth/getpk.b b/appl/cmd/auth/getpk.b index e2273d17..24283340 100644 --- a/appl/cmd/auth/getpk.b +++ b/appl/cmd/auth/getpk.b @@ -3,14 +3,10 @@ include "sys.m"; sys: Sys; include "draw.m"; include "arg.m"; -include "ipints.m"; -include "crypt.m"; - crypt: Crypt; -include "oldauth.m"; - oldauth: Oldauth; +include "keyring.m"; + keyring: Keyring; -Getpk: module -{ +Getpk: module { init: fn(nil: ref Draw->Context, argv: list of string); }; @@ -23,18 +19,14 @@ badmodule(p: string) init(nil: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; - crypt = load Crypt Crypt->PATH; - if(crypt == nil) - badmodule(Crypt->PATH); - oldauth = load Oldauth Oldauth->PATH; - if(oldauth == nil) - badmodule(Oldauth->PATH); - oldauth->init(); + keyring = load Keyring Keyring->PATH; + if(keyring == nil) + badmodule(Keyring->PATH); arg := load Arg Arg->PATH; if(arg == nil) badmodule(Arg->PATH); arg->init(argv); - arg->setusage("getpk [-asu] file..."); + arg->setusage("usage: getpk [-asu] file..."); aflag := 0; sflag := 0; uflag := 0; @@ -55,7 +47,7 @@ init(nil: ref Draw->Context, argv: list of string) arg->usage(); multi := len argv > 1; for(; argv != nil; argv = tl argv){ - info := oldauth->readauthinfo(hd argv); + info := keyring->readauthinfo(hd argv); if(info == nil){ sys->fprint(sys->fildes(2), "getpk: cannot read %s: %r\n", hd argv); continue; @@ -63,13 +55,13 @@ init(nil: ref Draw->Context, argv: list of string) pk := info.mypk; if(sflag) pk = info.spk; - s := oldauth->pktostr(pk, info.owner); + s := keyring->pktostr(pk); if(!aflag) s = hex(hash(s)); if(multi) s = hd argv + ": " + s; if(uflag) - s += " " + info.owner; + s += " " + pk.owner; sys->print("%s\n", s); } } @@ -77,8 +69,8 @@ init(nil: ref Draw->Context, argv: list of string) hash(s: string): array of byte { d := array of byte s; - digest := array[Crypt->SHA1dlen] of byte; - crypt->sha1(d, len d, digest, nil); + digest := array[Keyring->SHA1dlen] of byte; + keyring->sha1(d, len d, digest, nil); return digest; } diff --git a/appl/cmd/auth/rsagen.b b/appl/cmd/auth/rsagen.b index 48fcba6d..a1a4477c 100644 --- a/appl/cmd/auth/rsagen.b +++ b/appl/cmd/auth/rsagen.b @@ -5,12 +5,8 @@ include "sys.m"; include "draw.m"; -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; +include "keyring.m"; + kr: Keyring; include "arg.m"; @@ -22,8 +18,7 @@ Rsagen: module init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; + kr = load Keyring Keyring->PATH; arg := load Arg Arg->PATH; arg->init(args); @@ -48,31 +43,34 @@ init(nil: ref Draw->Context, args: list of string) arg->usage(); arg = nil; - sk := crypt->rsagen(nbits, 6, 0); + sk := kr->genSK("rsa", "", nbits); if(sk == nil) error("unable to generate key"); + s := kr->sktoattr(sk); + # need to fix the attr interface so the following isn't needed: + s = skip(s, "alg"); + s = skip(s, "owner"); if(tag != nil) tag = " "+tag; - s := add("ek", sk.pk.ek); - s += add("n", sk.pk.n); - s += add("!dk", sk.dk); - s += add("!p", sk.p); - s += add("!q", sk.q); - s += add("!kp", sk.kp); - s += add("!kq", sk.kq); - s += add("!c2", sk.c2); - a := sys->aprint("key proto=rsa%s size=%d%s\n", tag, sk.pk.n.bits(), s); + a := sys->aprint("key proto=rsa%s size=%d %s\n", tag, nbits, s); if(sys->write(sys->fildes(1), a, len a) != len a) error(sys->sprint("error writing key: %r")); } -error(s: string) +skip(s: string, attr: string): string { - sys->fprint(sys->fildes(2), "rsagen: %s\n", s); - raise "fail:error"; + for(i := 0; i < len s && s[i] != ' '; i++) + {} + if(i >= len s) + return s; + (nf, fld) := sys->tokenize(s[0:i], "="); + if(nf == 2 && hd fld == attr) + s = s[i+1:]; + return s; } -add(name: string, b: ref IPint): string +error(s: string) { - return " "+name+"="+b.iptostr(16); + sys->fprint(sys->fildes(2), "rsagen: %s\n", s); + raise "fail:error"; } diff --git a/appl/cmd/auth/signer.b b/appl/cmd/auth/signer.b index b27a719c..b3f4669d 100644 --- a/appl/cmd/auth/signer.b +++ b/appl/cmd/auth/signer.b @@ -5,20 +5,10 @@ include "sys.m"; include "draw.m"; -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; - -include "oldauth.m"; - oldauth: Oldauth; - -include "msgio.m"; - msgio: Msgio; - include "keyring.m"; + kr: Keyring; + IPint: import kr; + include "security.m"; random: Random; @@ -39,12 +29,7 @@ init(nil: ref Draw->Context, nil: list of string) { sys = load Sys Sys->PATH; random = load Random Random->PATH; - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; - oldauth = load Oldauth Oldauth->PATH; - oldauth->init(); - msgio = load Msgio Msgio->PATH; - msgio->init(); + kr = load Keyring Keyring->PATH; stdin = sys->fildes(0); stdout = sys->fildes(1); @@ -70,75 +55,75 @@ sign(): string return "can't read key"; # send public part to client - mypkbuf := array of byte oldauth->pktostr(crypt->sktopk(info.mysk), info.owner); - msgio->sendmsg(stdout, mypkbuf, len mypkbuf); + mypkbuf := array of byte kr->pktostr(kr->sktopk(info.mysk)); + kr->sendmsg(stdout, mypkbuf, len mypkbuf); alphabuf := array of byte info.alpha.iptob64(); - msgio->sendmsg(stdout, alphabuf, len alphabuf); + kr->sendmsg(stdout, alphabuf, len alphabuf); pbuf := array of byte info.p.iptob64(); - msgio->sendmsg(stdout, pbuf, len pbuf); + kr->sendmsg(stdout, pbuf, len pbuf); # get client's public key - hisPKbuf := msgio->getmsg(stdin); + hisPKbuf := kr->getmsg(stdin); if(hisPKbuf == nil) return "caller hung up"; - (hisPK, hisname) := oldauth->strtopk(string hisPKbuf); + hisPK := kr->strtopk(string hisPKbuf); if(hisPK == nil) return "illegal caller PK"; # hash, sign, and blind - state := crypt->sha1(hisPKbuf, len hisPKbuf, nil, nil); - cert := oldauth->sign(info.mysk, info.owner, 0, state, "sha1"); + state := kr->sha1(hisPKbuf, len hisPKbuf, nil, nil); + cert := kr->sign(info.mysk, 0, state, "sha1"); # sanity clause - state = crypt->sha1(hisPKbuf, len hisPKbuf, nil, nil); - if(oldauth->verify(info.mypk, cert, state) == 0) + state = kr->sha1(hisPKbuf, len hisPKbuf, nil, nil); + if(kr->verify(info.mypk, cert, state) == 0) return "bad signer certificate"; - certbuf := array of byte oldauth->certtostr(cert); + certbuf := array of byte kr->certtostr(cert); blind := random->randombuf(random->ReallyRandom, len certbuf); for(i := 0; i < len blind; i++) certbuf[i] = certbuf[i] ^ blind[i]; # sum PKs and blinded certificate - state = crypt->md5(mypkbuf, len mypkbuf, nil, nil); - crypt->md5(hisPKbuf, len hisPKbuf, nil, state); + state = kr->md5(mypkbuf, len mypkbuf, nil, nil); + kr->md5(hisPKbuf, len hisPKbuf, nil, state); digest := array[Keyring->MD5dlen] of byte; - crypt->md5(certbuf, len certbuf, digest, state); + kr->md5(certbuf, len certbuf, digest, state); # save sum and blinded cert in a file - file := "signed/"+hisname; + file := "signed/"+hisPK.owner; fd := sys->create(file, Sys->OWRITE, 8r600); if(fd == nil) return "can't create "+file+sys->sprint(": %r"); - if(msgio->sendmsg(fd, blind, len blind) < 0 || - msgio->sendmsg(fd, digest, len digest) < 0){ + if(kr->sendmsg(fd, blind, len blind) < 0 || + kr->sendmsg(fd, digest, len digest) < 0){ sys->remove(file); return "can't write "+file+sys->sprint(": %r"); } # send blinded cert to client - msgio->sendmsg(stdout, certbuf, len certbuf); + kr->sendmsg(stdout, certbuf, len certbuf); return nil; } -signerkey(filename: string): ref Oldauth->Authinfo +signerkey(filename: string): ref Keyring->Authinfo { - info := oldauth->readauthinfo(filename); + info := kr->readauthinfo(filename); if(info != nil) return info; # generate a local key - info = ref Oldauth->Authinfo; - info.mysk = crypt->genSK("elgamal", PKmodlen); - info.mypk = crypt->sktopk(info.mysk); - info.spk = crypt->sktopk(info.mysk); - myPKbuf := array of byte oldauth->pktostr(info.mypk, "*"); - state := crypt->sha1(myPKbuf, len myPKbuf, nil, nil); - info.cert = oldauth->sign(info.mysk, "*", 0, state, "sha1"); - (info.alpha, info.p) = crypt->dhparams(DHmodlen); - - if(oldauth->writeauthinfo(filename, info) < 0){ + info = ref Keyring->Authinfo; + info.mysk = kr->genSK("elgamal", "*", PKmodlen); + info.mypk = kr->sktopk(info.mysk); + info.spk = kr->sktopk(info.mysk); + myPKbuf := array of byte kr->pktostr(info.mypk); + state := kr->sha1(myPKbuf, len myPKbuf, nil, nil); + info.cert = kr->sign(info.mysk, 0, state, "sha1"); + (info.alpha, info.p) = kr->dhparams(DHmodlen); + + if(kr->writeauthinfo(filename, info) < 0){ sys->fprint(stderr, "can't write signerkey file: %r\n"); return nil; } diff --git a/appl/cmd/auth/verify.b b/appl/cmd/auth/verify.b index 91fe1a86..d829a76c 100644 --- a/appl/cmd/auth/verify.b +++ b/appl/cmd/auth/verify.b @@ -3,8 +3,8 @@ implement Verify; include "sys.m"; sys: Sys; -include "msgio.m"; - msgio: Msgio; +include "keyring.m"; + kr: Keyring; include "draw.m"; @@ -25,8 +25,7 @@ pro := array[] of { init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; - msgio = load Msgio Msgio->PATH; - msgio->init(); + kr = load Keyring Keyring->PATH; stdin = sys->fildes(0); stderr = sys->fildes(2); @@ -51,8 +50,8 @@ init(nil: ref Draw->Context, args: list of string) sys->fprint(stderr, "signer: can't open %s: %r\n", file); raise "fail:no certificate"; } - certbuf := msgio->getmsg(fd); - digest := msgio->getmsg(fd); + certbuf := kr->getmsg(fd); + digest := kr->getmsg(fd); if(digest == nil || certbuf == nil){ sys->fprint(stderr, "signer: can't read %s: %r\n", file); raise "fail:bad certificate"; @@ -79,7 +78,7 @@ init(nil: ref Draw->Context, args: list of string) sys->fprint(stderr, "signer: can't create %s: %r\n", nfile); raise "fail:create"; } - if(msgio->sendmsg(fd, certbuf, len certbuf) < 0){ + if(kr->sendmsg(fd, certbuf, len certbuf) < 0){ sys->fprint(stderr, "signer: can't write %s: %r\n", nfile); raise "fail:write"; } diff --git a/appl/cmd/cpu.b b/appl/cmd/cpu.b index 8acab430..75728e57 100644 --- a/appl/cmd/cpu.b +++ b/appl/cmd/cpu.b @@ -5,9 +5,6 @@ include "sys.m"; stderr: ref Sys->FD; include "draw.m"; Context: import Draw; - -include "dial.m"; - include "string.m"; str: String; include "arg.m"; @@ -53,9 +50,6 @@ init(nil: ref Context, argv: list of string) kr := load Keyring Keyring->PATH; if (kr == nil) badmodule(Keyring->PATH); - dial := load Dial Dial->PATH; - if(dial == nil) badmodule(Dial->PATH); - arg->init(argv); alg := ""; while ((opt := arg->opt()) != 0) { @@ -85,7 +79,7 @@ init(nil: ref Context, argv: list of string) user := getuser(); kd := "/usr/" + user + "/keyring/"; - cert := kd + dial->netmkaddr(mach, "tcp", ""); + cert := kd + netmkaddr(mach, "tcp", ""); if (!exists(cert)) { cert = kd + "default"; if (!exists(cert)) { @@ -98,8 +92,8 @@ init(nil: ref Context, argv: list of string) if(!exists("/dev/draw/new")) sys->bind("#d", "/dev", Sys->MBEFORE); - c := dial->dial(dial->netmkaddr(mach, "net", "rstyx"), nil); - if(c == nil){ + (ok, c) := sys->dial(netmkaddr(mach, "net", "rstyx"), nil); + if(ok < 0){ sys->fprint(stderr, "Error: cpu: dial: %r\n"); return; } @@ -157,3 +151,18 @@ getuser(): string return string buf[0:n]; } + +netmkaddr(addr, net, svc: string): string +{ + if(net == nil) + net = "net"; + (n, nil) := sys->tokenize(addr, "!"); + if(n <= 1){ + if(svc== nil) + return sys->sprint("%s!%s", net, addr); + return sys->sprint("%s!%s!%s", net, addr, svc); + } + if(svc == nil || n > 2) + return addr; + return sys->sprint("%s!%s", addr, svc); +} diff --git a/appl/cmd/dial.b b/appl/cmd/dial.b index 8821b49a..c562a570 100644 --- a/appl/cmd/dial.b +++ b/appl/cmd/dial.b @@ -1,4 +1,4 @@ -implement Dialcmd; +implement Dial; include "sys.m"; sys: Sys; include "draw.m"; @@ -7,12 +7,11 @@ include "keyring.m"; keyring: Keyring; include "security.m"; auth: Auth; -include "dial.m"; include "sh.m"; sh: Sh; Context: import sh; -Dialcmd: module { +Dial: module { init: fn(nil: ref Draw->Context, argv: list of string); }; @@ -36,9 +35,6 @@ init(drawctxt: ref Draw->Context, argv: list of string) arg := load Arg Arg->PATH; if (arg == nil) badmodule(Arg->PATH); - dial := load Dial Dial->PATH; - if(dial == nil) - badmodule(Dial->PATH); sh = load Sh Sh->PATH; if (sh == nil) badmodule(Sh->PATH); @@ -91,8 +87,8 @@ init(drawctxt: ref Draw->Context, argv: list of string) } } - c := dial->dial(addr, nil); - if (c == nil) { + (ok, c) := sys->dial(addr, nil); + if (ok == -1) { sys->fprint(stderr(), "dial: cannot dial %s:: %r\n", addr); raise "fail:errors"; } diff --git a/appl/cmd/listen.b b/appl/cmd/listen.b index 5a06892d..25869223 100644 --- a/appl/cmd/listen.b +++ b/appl/cmd/listen.b @@ -7,8 +7,6 @@ include "keyring.m"; keyring: Keyring; include "security.m"; auth: Auth; -include "dial.m"; - dial: Dial; include "sh.m"; sh: Sh; Context: import sh; @@ -33,9 +31,6 @@ init(drawctxt: ref Draw->Context, argv: list of string) auth = load Auth Auth->PATH; if (auth == nil) badmodule(Auth->PATH); - dial = load Dial Dial->PATH; - if (dial == nil) - badmodule(Dial->PATH); sh = load Sh Sh->PATH; if (sh == nil) badmodule(Sh->PATH); @@ -125,8 +120,8 @@ listen1(drawctxt: ref Draw->Context, addr: string, argv: list of string, sys->pctl(Sys->FORKFD, nil); ctxt := Context.new(drawctxt); - acon := dial->announce(addr); - if (acon == nil) { + (ok, acon) := sys->announce(addr); + if (ok == -1) { sys->fprint(stderr(), "listen: failed to announce on '%s': %r\n", addr); sync <-= "cannot announce"; exit; @@ -151,15 +146,15 @@ listen1(drawctxt: ref Draw->Context, addr: string, argv: list of string, } sync <-= nil; - listench := chan of ref Dial->Connection; - authch := chan of (string, ref Dial->Connection); + listench := chan of (int, Sys->Connection); + authch := chan of (string, Sys->Connection); spawn listener(listench, acon, addr); for (;;) { user := ""; - ccon: ref Dial->Connection; + ccon: Sys->Connection; alt { - c := <-listench => - if (c == nil){ + (lok, c) := <-listench => + if (lok == -1){ sync <-= "listen"; exit; } @@ -187,13 +182,13 @@ listen1(drawctxt: ref Draw->Context, addr: string, argv: list of string, } } -listener(listench: chan of ref Dial->Connection, c: ref Dial->Connection, addr: string) +listener(listench: chan of (int, Sys->Connection), c: Sys->Connection, addr: string) { for (;;) { - nc := dial->listen(c); - if (nc == nil) { + (ok, nc) := sys->listen(c); + if (ok == -1) { sys->fprint(stderr(), "listen: listen error on '%s': %r\n", addr); - listench <-= nc; + listench <-= (-1, nc); exit; } if (verbose) @@ -205,13 +200,13 @@ listener(listench: chan of ref Dial->Connection, c: ref Dial->Connection, addr: else{ if(nc.cfd != nil) sys->fprint(nc.cfd, "keepalive"); - listench <-= nc; + listench <-= (ok, nc); } } } -authenticator(authch: chan of (string, ref Dial->Connection), - c: ref Dial->Connection, algs: list of string, addr: string) +authenticator(authch: chan of (string, Sys->Connection), + c: Sys->Connection, algs: list of string, addr: string) { err: string; (c.dfd, err) = auth->server(algs, serverkey, c.dfd, 0); diff --git a/appl/cmd/sh/mpexpr.b b/appl/cmd/sh/mpexpr.b index 0aaf6cda..682c01e8 100644 --- a/appl/cmd/sh/mpexpr.b +++ b/appl/cmd/sh/mpexpr.b @@ -3,9 +3,9 @@ implement Shellbuiltin; include "sys.m"; sys: Sys; include "draw.m"; -include "ipints.m"; - ipints: IPints; - IPint: import ipints; +include "keyring.m"; + keyring: Keyring; + IPint: import keyring; include "sh.m"; sh: Sh; Listnode, Context: import sh; @@ -17,7 +17,7 @@ One: Big; initbuiltin(ctxt: ref Context, shmod: Sh): string { sys = load Sys Sys->PATH; - ipints = load IPints IPints->PATH; + keyring = load Keyring Keyring->PATH; sh = shmod; myself = load Shellbuiltin "$self"; if (myself == nil) @@ -233,7 +233,7 @@ oper(ctxt: ref Context, args: list of Big, op, lastop, lastn: int, BITS => r = mki(n1.bits()); EXPMOD => r = n1.expmod(n2, n3); EXP => r = n1.expmod(n2, nil); - RAND => r = IPint.random(n1.iptoint()); + RAND => r = IPint.random(0, n1.iptoint()); INVERT => r = n1.invert(n2); } return r :: stk; diff --git a/appl/cmd/spki/verify.b b/appl/cmd/spki/verify.b index daf563ac..9eab6b41 100644 --- a/appl/cmd/spki/verify.b +++ b/appl/cmd/spki/verify.b @@ -11,11 +11,9 @@ include "sys.m"; include "draw.m"; -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; +include "keyring.m"; + kr: Keyring; + IPint: import kr; include "bufio.m"; bufio: Bufio; @@ -46,7 +44,7 @@ debug := 0; init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; - ipints = load IPints IPints->PATH; + kr = load Keyring Keyring->PATH; bufio = load Bufio Bufio->PATH; sexprs = load Sexprs Sexprs->PATH; spki = load SPKI SPKI->PATH; diff --git a/appl/cmd/ssh/authpassword.b b/appl/cmd/ssh/authpassword.b deleted file mode 100644 index 1a149117..00000000 --- a/appl/cmd/ssh/authpassword.b +++ /dev/null @@ -1,68 +0,0 @@ -implement Auth; - -include "sys.m"; - sys: Sys; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; # TO DO: needed to avoid compiler error - -include "factotum.m"; - factotum: Factotum; - -include "sshio.m"; - sshio: Sshio; - Conn, Msg: import sshio; - -id(): int -{ - return SSH_AUTH_PASSWORD; -} - -init(mod: Sshio) -{ - sys = load Sys Sys->PATH; - sshio = mod; -} - -firstmsg(): int -{ - return SSH_CMSG_AUTH_PASSWORD; -} - -authsrv(c: ref Conn, m: ref Msg): ref AuthInfo -{ - pass := m.getstring(); -# return auth_userpasswd(c.user, pass); - return ref AuthInfo(c.user, nil); # TO DO: -} - -auth(c: ref Conn): int -{ - if(factotum == nil) - factotum = load Factotum Factotum->PATH; - (user, pass) := factotum->getuserpasswd(sys->sprint("proto=pass service=ssh server=%q user=%q", c.host, c.user)); - if(user == nil){ - sshio->debug(DBG_AUTH, "getuserpasswd failed"); - return -1; - } - - sshio->debug(DBG_AUTH, "try using password from factotum\n"); - m := Msg.mk(SSH_CMSG_AUTH_PASSWORD, 4+Sys->UTFmax*len pass); - m.putstring(pass); - c.out <-= m; - - m = sshio->recvmsg(c, -1); - case m.mtype { - SSH_SMSG_SUCCESS => - return 0; - SSH_SMSG_FAILURE => - return -1; - * => - sshio->badmsg(m, 0, nil); - return -1; - } -} diff --git a/appl/cmd/ssh/authrsa.b b/appl/cmd/ssh/authrsa.b deleted file mode 100644 index 427355d5..00000000 --- a/appl/cmd/ssh/authrsa.b +++ /dev/null @@ -1,188 +0,0 @@ -implement Auth; - -include "sys.m"; - sys: Sys; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; - PK, SK: import crypt; - -include "factotum.m"; - factotum: Factotum; - Attr: import factotum; - findattrval: import factotum; - -include "sshio.m"; - sshio: Sshio; - Conn, Msg: import sshio; - debug: import sshio; - -id(): int -{ - return SSH_AUTH_RSA; -} - -init(mod: Sshio) -{ - sshio = mod; - sys = load Sys Sys->PATH; - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; - factotum = load Factotum Factotum->PATH; - factotum->init(); -} - -firstmsg(): int -{ - return SSH_CMSG_AUTH_RSA; -} - -authsrv(c: ref Conn, m: ref Msg): ref AuthInfo -{ - # TO DO: use factotum - hismod := m.getipint(); - if(hismod.bits() < 512){ - debug(DBG_AUTH, sys->sprint("rsa key for %s < 512 bits\n", c.user)); - return nil; - } - hispk := readpk("/keydb/ssh/"+c.user); - if(hispk == nil){ - debug(DBG_AUTH, sys->sprint("no ssh/rsa key for %s: %r\n", c.user)); - return nil; - } - if(!hispk.n.eq(hismod)){ - debug(DBG_AUTH, sys->sprint("%s rsa key doesn't match modulus\n", c.user)); - return nil; - } - # encrypt a challenge with his pk -# chal := IPint.random(256).expmod(IPint.inttoip(1), hismod); - chal := IPint.random(256); - echal := crypt->rsaencrypt(hispk, x := sshio->rsapad(chal, (hispk.n.bits()+7)/8)); -debug(DBG_AUTH, sys->sprint("padded %s\nrsa chal %s\n", x.iptostr(16), echal.iptostr(16))); - m = Msg.mk(SSH_SMSG_AUTH_RSA_CHALLENGE, 2048); - m.putipint(echal); - c.out <-= m; - - m = sshio->recvmsg(c, SSH_CMSG_AUTH_RSA_RESPONSE); - response := m.getbytes(Crypt->MD5dlen); - chalbuf := array[32+SESSIDLEN] of byte; - sshio->iptorjustbe(chal, chalbuf, 32); - debug(DBG_AUTH, sys->sprint("\trjusted %s\n", sshio->hex(chalbuf[0:32]))); - chalbuf[32:] = c.sessid[0: SESSIDLEN]; - debug(DBG_AUTH, sys->sprint("\tappend sessid %s\n", sshio->hex(chalbuf))); - expected := array[Crypt->MD5dlen] of byte; - crypt->md5(chalbuf, 32+SESSIDLEN, expected, nil); - if(sshio->eqbytes(expected, response, len expected)) - return ref AuthInfo(c.user, nil); - return nil; -} - -readpk(file: string): ref PK.RSA -{ - fd := sys->open(file, Sys->OREAD); - if(fd == nil) - return nil; - buf := array[8192] of byte; - nr := sys->readn(fd, buf, len buf); - if(nr < 0) - return nil; - attrs := factotum->parseattrs(string buf[0: nr]); - if(findattrval(attrs, "proto") != "rsa" || - (ns := findattrval(attrs, "n")) == nil || - (eks := findattrval(attrs, "ek")) == nil){ - sys->werrstr("missing rsa key attributes"); - return nil; - } - n := IPint.strtoip(ns, 16); - ek := IPint.strtoip(eks, 16); - if(n == nil || ek == nil){ - sys->werrstr("invalid rsa key values"); - return nil; - } - return ref PK.RSA(n, ek); -} - -auth(c: ref Conn): int -{ - chalbuf := array[32+SESSIDLEN] of byte; - response := array[Crypt->MD5dlen] of byte; - - debug(DBG_AUTH, "authrsa\n"); - - afd := sys->open("/mnt/factotum/rpc", Sys->ORDWR); - if(afd == nil){ - debug(DBG_AUTH, sys->sprint("open /mnt/factotum/rpc: %r\n")); - return -1; - } - s := "proto=rsa role=client"; - if(factotum->rpc(afd, "start", array of byte s).t0 != "ok"){ - debug(DBG_AUTH, sys->sprint("auth_rpc start %s failed: %r\n", s)); - return -1; - } - - debug(DBG_AUTH, "trying factotum rsa keys\n"); - for(;;){ - (tag, value) := factotum->rpc(afd, "read", nil); - if(tag != "ok") - break; - textkey := string value; - sshio->debug(DBG_AUTH, sys->sprint("try %q\n", textkey)); - mod := IPint.strtoip(textkey, 16); - m := Msg.mk(SSH_CMSG_AUTH_RSA, 16+(mod.bits()+7/8)); - m.putipint(mod); - c.out <-= m; - - m = sshio->recvmsg(c, -1); - case m.mtype { - SSH_SMSG_FAILURE => - debug(DBG_AUTH, "\tnot accepted\n"); - continue; - SSH_SMSG_AUTH_RSA_CHALLENGE => - ; - * => - sshio->badmsg(m, 0, nil); - } - chal := m.getipint(); - p := chal.iptostr(16); - debug(DBG_AUTH, sys->sprint("\tgot challenge %s\n", p)); - unpad: ref IPint; - if(factotum->rpc(afd, "write", array of byte p).t0 == "ok" && - ((tag, value) = factotum->rpc(afd, "read", nil)).t0 == "ok"){ - debug(DBG_AUTH, sys->sprint("\tfactotum said %q\n", string value)); - decr := IPint.strtoip(string value, 16); - if(decr != nil){ - debug(DBG_AUTH, sys->sprint("\tdecrypted %s\n", decr.iptostr(16))); - unpad = sshio->rsaunpad(decr); - }else - unpad = IPint.inttoip(0); - }else{ - debug(DBG_AUTH, sys->sprint("\tauth_rpc write or read failed: %r\n")); - unpad = IPint.inttoip(0); # it will fail, we'll go round again - } - debug(DBG_AUTH, sys->sprint("\tunpadded %s\n", unpad.iptostr(16))); - sshio->iptorjustbe(unpad, chalbuf, 32); -# debug(DBG_AUTH, sys->sprint("\trjusted %.*H\n", 32, chalbuf)); - chalbuf[32:] = c.sessid[0: SESSIDLEN]; -# debug(DBG_AUTH, sys->sprint("\tappend sesskey %.*H\n", 32, chalbuf)); - crypt->md5(chalbuf, 32+SESSIDLEN, response, nil); - - m = Msg.mk(SSH_CMSG_AUTH_RSA_RESPONSE, Crypt->MD5dlen); - m.putbytes(response, Crypt->MD5dlen); - c.out <-= m; - - m = sshio->recvmsg(c, -1); - case m.mtype { - SSH_SMSG_FAILURE => - ; # retry - SSH_SMSG_SUCCESS => - return 0; - * => - sshio->badmsg(m, 0, nil); - } - } - return -1; -} diff --git a/appl/cmd/ssh/authtis.b b/appl/cmd/ssh/authtis.b deleted file mode 100644 index 0fd5edd6..00000000 --- a/appl/cmd/ssh/authtis.b +++ /dev/null @@ -1,119 +0,0 @@ -implement Auth; - -# TO DO: add chal/resp to Factotum - -include "sys.m"; - sys: Sys; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; # avoid compiler error - -include "factotum.m"; - factotum: Factotum; - Attr: import factotum; - findattrval: import factotum; - -include "sshio.m"; - sshio: Sshio; - Conn, Msg: import sshio; - debug: import sshio; - -id(): int -{ - return SSH_AUTH_TIS; -} - -init(mod: Sshio) -{ - sshio = mod; - sys = load Sys Sys->PATH; - ipints = load IPints IPints->PATH; - factotum = load Factotum Factotum->PATH; - factotum->init(); -} - -firstmsg(): int -{ - return SSH_CMSG_AUTH_TIS; -} - -authsrv(conn: ref Conn, nil: ref Msg): ref AuthInfo -{ - if((c := factotum->challenge(sys->sprint("proto=p9cr user=%q role=server", conn.user))) == nil){ -# sshlog("auth_challenge failed for %s", conn.user); - return nil; - } - s := sys->sprint("Challenge: %s\nResponse: ", c.chal); - m := Msg.mk(SSH_SMSG_AUTH_TIS_CHALLENGE, 4+len s); - m.putstring(s); - conn.out <-= m; - - m = sshio->recvmsg(conn, 0); - if(m == nil) - return nil; - if(m.mtype != SSH_CMSG_AUTH_TIS_RESPONSE){ - # - # apparently you can just give up on - # this protocol and start a new one. - # - sshio->unrecvmsg(conn, m); - return nil; - } - - ai := factotum->response(c, m.getstring()); - if(ai == nil){ - debug(DBG_AUTH, sys->sprint("response rejected: %r\n")); - return nil; - } - return ref AuthInfo(ai.cuid, ai.cap); -} - -auth(c: ref Conn): int -{ - if(!c.interactive) - return -1; - - debug(DBG_AUTH, "try TIS\n"); - c.out <-= Msg.mk(SSH_CMSG_AUTH_TIS, 0); - - m := sshio->recvmsg(c, -1); - case m.mtype { - SSH_SMSG_FAILURE => - return -1; - SSH_SMSG_AUTH_TIS_CHALLENGE => - ; - * => - sshio->badmsg(m, SSH_SMSG_AUTH_TIS_CHALLENGE, nil); - } - - chal := m.getstring(); - - if((fd := sys->open("/dev/cons", Sys->ORDWR)) == nil) - sshio->error(sys->sprint("can't open /dev/cons: %r")); - - sys->fprint(fd, "TIS Authentication\n%s", chal); - resp := array[256] of byte; - n := sys->read(fd, resp, len resp); - if(n <= 0 || resp[0] == byte '\n') - return -1; - - m = Msg.mk(SSH_CMSG_AUTH_TIS_RESPONSE, 4+n); - m.put4(len resp); - m.putbytes(resp, n); - c.out <-= m; - - m = sshio->recvmsg(c, -1); - case m.mtype { - SSH_SMSG_SUCCESS => - return 0; - SSH_SMSG_FAILURE => - return -1; - * => - sshio->badmsg(m, 0, nil); - return -1; - } -} diff --git a/appl/cmd/ssh/cipher3des.b b/appl/cmd/ssh/cipher3des.b deleted file mode 100644 index e6f347f1..00000000 --- a/appl/cmd/ssh/cipher3des.b +++ /dev/null @@ -1,51 +0,0 @@ -implement Cipher; - -include "sys.m"; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; - DESstate: import crypt; - -include "sshio.m"; - -Cipherstate: adt -{ - enc: array of ref DESstate; - dec: array of ref DESstate; -}; - -cs: ref Cipherstate; - -id(): int -{ - return SSH_CIPHER_3DES; -} - -init(key: array of byte, nil: int) -{ - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; - cs = ref Cipherstate(array[3] of ref DESstate, array[3] of ref DESstate); - for(i := 0; i < 3; i++){ - cs.enc[i] = crypt->dessetup(key[i*8:], nil); - cs.dec[i] = crypt->dessetup(key[i*8:], nil); - } -} - -encrypt(buf: array of byte, nbuf: int) -{ - crypt->descbc(cs.enc[0], buf, nbuf, Crypt->Encrypt); - crypt->descbc(cs.enc[1], buf, nbuf, Crypt->Decrypt); - crypt->descbc(cs.enc[2], buf, nbuf, Crypt->Encrypt); -} - -decrypt(buf: array of byte, nbuf: int) -{ - crypt->descbc(cs.dec[2], buf, nbuf, Crypt->Decrypt); - crypt->descbc(cs.dec[1], buf, nbuf, Crypt->Encrypt); - crypt->descbc(cs.dec[0], buf, nbuf, Crypt->Decrypt); -} diff --git a/appl/cmd/ssh/cipherblowfish.b b/appl/cmd/ssh/cipherblowfish.b deleted file mode 100644 index 8d3b0c31..00000000 --- a/appl/cmd/ssh/cipherblowfish.b +++ /dev/null @@ -1,43 +0,0 @@ -implement Cipher; - -include "sys.m"; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; - BFstate: import crypt; - -include "sshio.m"; - -Cipherstate: adt -{ - enc: ref BFstate; - dec: ref BFstate; -}; - -cs: ref Cipherstate; - -id(): int -{ - return SSH_CIPHER_BLOWFISH; -} - -init(key: array of byte, nil: int) -{ - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; - cs = ref Cipherstate(crypt->blowfishsetup(key, nil), crypt->blowfishsetup(key, nil)); -} - -encrypt(buf: array of byte, nbuf: int) -{ - crypt->blowfishcbc(cs.enc, buf, nbuf, Crypt->Encrypt); -} - -decrypt(buf: array of byte, nbuf: int) -{ - crypt->blowfishcbc(cs.dec, buf, nbuf, Crypt->Decrypt); -} diff --git a/appl/cmd/ssh/cipherdes.b b/appl/cmd/ssh/cipherdes.b deleted file mode 100644 index 7de0a7ca..00000000 --- a/appl/cmd/ssh/cipherdes.b +++ /dev/null @@ -1,43 +0,0 @@ -implement Cipher; - -include "sys.m"; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; - DESstate: import crypt; - -include "sshio.m"; - -Cipherstate: adt -{ - enc: ref DESstate; - dec: ref DESstate; -}; - -cs: ref Cipherstate; - -id(): int -{ - return SSH_CIPHER_DES; -} - -init(key: array of byte, nil: int) -{ - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; - cs = ref Cipherstate(crypt->dessetup(key, nil), crypt->dessetup(key, nil)); -} - -encrypt(buf: array of byte, nbuf: int) -{ - crypt->descbc(cs.enc, buf, nbuf, Crypt->Encrypt); -} - -decrypt(buf: array of byte, nbuf: int) -{ - crypt->descbc(cs.dec, buf, nbuf, Crypt->Decrypt); -} diff --git a/appl/cmd/ssh/ciphernone.b b/appl/cmd/ssh/ciphernone.b deleted file mode 100644 index 01a7a1f3..00000000 --- a/appl/cmd/ssh/ciphernone.b +++ /dev/null @@ -1,28 +0,0 @@ -implement Cipher; - -include "sys.m"; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - -include "sshio.m"; - -id(): int -{ - return SSH_CIPHER_NONE; -} - -init(nil: array of byte, nil: int) -{ -} - -encrypt(nil: array of byte, nil: int) -{ -} - -decrypt(nil: array of byte, nil: int) -{ -} diff --git a/appl/cmd/ssh/cipherrc4.b b/appl/cmd/ssh/cipherrc4.b deleted file mode 100644 index f43f9c8d..00000000 --- a/appl/cmd/ssh/cipherrc4.b +++ /dev/null @@ -1,46 +0,0 @@ -implement Cipher; - -include "sys.m"; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; - RC4state: import crypt; - -include "sshio.m"; - -Cipherstate: adt -{ - enc: ref RC4state; - dec: ref RC4state; -}; - -cs: ref Cipherstate; - -id(): int -{ - return SSH_CIPHER_RC4; -} - -init(key: array of byte, isserver: int) -{ - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; - if(isserver) - cs = ref Cipherstate(crypt->rc4setup(key[0:16]), crypt->rc4setup(key[16:32])); - else - cs = ref Cipherstate(crypt->rc4setup(key[16:32]), crypt->rc4setup(key[0:16])); -} - -encrypt(buf: array of byte, nbuf: int) -{ - crypt->rc4(cs.enc, buf, nbuf); -} - -decrypt(buf: array of byte, nbuf: int) -{ - crypt->rc4(cs.dec, buf, nbuf); -} diff --git a/appl/cmd/ssh/mkfile b/appl/cmd/ssh/mkfile deleted file mode 100644 index afb4c903..00000000 --- a/appl/cmd/ssh/mkfile +++ /dev/null @@ -1,29 +0,0 @@ -<../../../mkconfig - -TARG=\ - authpassword.dis\ - authrsa.dis\ - authtis.dis\ - cipher3des.dis\ - cipherblowfish.dis\ - cipherdes.dis\ - ciphernone.dis\ - cipherrc4.dis\ - sshio.dis\ - sshserve.dis\ -# ssh.dis\ - -SYSMODULES=\ - arg.m\ - keyring.m\ - security.m\ - rand.m\ - sys.m\ - draw.m\ - -MODULES=\ - sshio.m\ - -DISBIN=$ROOT/dis/ssh - -<$ROOT/mkfiles/mkdis diff --git a/appl/cmd/ssh/sshio.b b/appl/cmd/ssh/sshio.b deleted file mode 100644 index 942b06df..00000000 --- a/appl/cmd/ssh/sshio.b +++ /dev/null @@ -1,586 +0,0 @@ -implement Sshio; - -include "sys.m"; - sys: Sys; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; - PK, SK: import crypt; - -include "sshio.m"; - -include "rand.m"; - rand: Rand; - -init() -{ - sys = load Sys Sys->PATH; - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; - rand = load Rand Rand->PATH; - rand->init(sys->millisec()); -} - -msgnames := array[45] of { - "SSH_MSG_NONE", # 0 - "SSH_MSG_DISCONNECT", - "SSH_SMSG_PUBLIC_KEY", - "SSH_CMSG_SESSION_KEY", - "SSH_CMSG_USER", - "SSH_CMSG_AUTH_RHOSTS", - "SSH_CMSG_AUTH_RSA", - "SSH_SMSG_AUTH_RSA_CHALLENGE", - "SSH_CMSG_AUTH_RSA_RESPONSE", - "SSH_CMSG_AUTH_PASSWORD", - "SSH_CMSG_REQUEST_PTY", # 10 - "SSH_CMSG_WINDOW_SIZE", - "SSH_CMSG_EXEC_SHELL", - "SSH_CMSG_EXEC_CMD", - "SSH_SMSG_SUCCESS", - "SSH_SMSG_FAILURE", - "SSH_CMSG_STDIN_DATA", - "SSH_SMSG_STDOUT_DATA", - "SSH_SMSG_STDERR_DATA", - "SSH_CMSG_EOF", - "SSH_SMSG_EXITSTATUS", # 20 - "SSH_MSG_CHANNEL_OPEN_CONFIRMATION", - "SSH_MSG_CHANNEL_OPEN_FAILURE", - "SSH_MSG_CHANNEL_DATA", - "SSH_MSG_CHANNEL_INPUT_EOF", - "SSH_MSG_CHANNEL_OUTPUT_CLOSED", - "SSH_MSG_UNIX_DOMAIN_X11_FORWARDING (obsolete)", - "SSH_SMSG_X11_OPEN", - "SSH_CMSG_PORT_FORWARD_REQUEST", - "SSH_MSG_PORT_OPEN", - "SSH_CMSG_AGENT_REQUEST_FORWARDING", # 30 - "SSH_SMSG_AGENT_OPEN", - "SSH_MSG_IGNORE", - "SSH_CMSG_EXIT_CONFIRMATION", - "SSH_CMSG_X11_REQUEST_FORWARDING", - "SSH_CMSG_AUTH_RHOSTS_RSA", - "SSH_MSG_DEBUG", - "SSH_CMSG_REQUEST_COMPRESSION", - "SSH_CMSG_MAX_PACKET_SIZE", - "SSH_CMSG_AUTH_TIS", - "SSH_SMSG_AUTH_TIS_CHALLENGE", # 40 - "SSH_CMSG_AUTH_TIS_RESPONSE", - "SSH_CMSG_AUTH_KERBEROS", - "SSH_SMSG_AUTH_KERBEROS_RESPONSE", - "SSH_CMSG_HAVE_KERBEROS_TGT", -}; - -Conn.mk(host: string, fd: ref Sys->FD): ref Conn -{ - c := ref Conn; - c.host = host; - c.sesskey = array[SESSKEYLEN] of byte; - c.sessid = array[SESSIDLEN] of byte; - c.in = chan of (ref Msg, string); - c.out = chan of ref Msg; - c.flags = 0; - c.interactive = 0; - sync := chan of int; - spawn msgreader(c, fd, sync); - <-sync; - spawn msgwriter(c, fd, sync); - <-sync; - return c; -} - -Conn.setkey(c: self ref Conn, key: ref PK.RSA) -{ - c.hostkey = key; -} - -msgreader(c: ref Conn, fd: ref Sys->FD, sync: chan of int) -{ - sys->pctl(Sys->NEWFD, 2 :: fd.fd :: nil); - sync <-= 1; - fd = sys->fildes(fd.fd); - for(;;){ - m := readmsg(c, fd); - if(m == nil){ - c.in <-= (nil, sys->sprint("%r")); - break; - } - debug(DBG_PROTO, sys->sprint("<-[%d] %s\n", m.ep-m.rp, m.fulltext())); - case m.mtype { - SSH_MSG_IGNORE => - ; - SSH_MSG_DEBUG => - debug(DBG_PROTO, sys->sprint("remote DEBUG: %s\n", m.getstring())); - * => - c.in <-= (m, nil); - } - } -} - -msgwriter(c: ref Conn, fd: ref Sys->FD, sync: chan of int) -{ - sys->pctl(Sys->NEWFD, 2 :: fd.fd :: nil); - sync <-= 1; - fd = sys->fildes(fd.fd); - while((m := <-c.out) != nil) - if(writemsg(c, m, fd) < 0){ - while(<-c.out != nil) - {} # flush - exit; - } -} - -# -# read initial SSH-m.n-comment line -# -readversion(fd: ref Sys->FD): (int, int, string) -{ - buf := array[128] of byte; - if((n := readstrnl(fd, buf, len buf)) < 0) - return (-1, -1, sys->sprint("error reading version: %r")); - # id string is "SSH-m.n-comment". We need m=1, n>=5. - s := string buf[0: n]; - (nf, fld) := sys->tokenize(s, "-\r\n"); - if(nf < 3 || hd fld != "SSH") - return (-1, -1, sys->sprint("unexpected protocol reply: %s", s)); - (nf, fld) = sys->tokenize(hd tl fld, "."); - if(nf < 2) - return (-1, -1, "invalid SSH version string in "+s); - return (1, int hd tl fld, s); -} - -calcsessid(hostmod: ref IPint, servermod: ref IPint, cookie: array of byte): array of byte -{ - b1 := hostmod.iptobebytes(); - b2 := servermod.iptobebytes(); - buf := array[len b1+len b2+COOKIELEN] of byte; - buf[0:] = b1; - buf[len b1:] = b2; - buf[len b1+len b2:] = cookie[0: COOKIELEN]; - sessid := array[Crypt->MD5dlen] of byte; - crypt->md5(buf, len buf, sessid, nil); - return sessid; -} - -Msg.text(m: self ref Msg): string -{ - if(0 <= m.mtype && m.mtype < len msgnames) - return msgnames[m.mtype]; - return sys->sprint("<unknown type %d>", m.mtype); -} - -Msg.fulltext(m: self ref Msg): string -{ - s := m.text(); - n := m.ep; - if(n > 64) - n = 64; - for(i := 0; i < n; i++) - s += sys->sprint(" %.2ux", int m.data[i]); - if(n != m.ep) - s += " ..."; - return s; -} - -badmsg(m: ref Msg, want: int, errmsg: string) -{ - if(m == nil) - s := sys->sprint("<early eof: %s>", errmsg); - else - s = m.text(); - if(want) - error(sys->sprint("got %s message expecting %s", s, msgnames[want])); - error(sys->sprint("got unexpected %s message", s)); -} - -Msg.mk(mtype: int, length: int): ref Msg -{ - if(length > 256*1024) - raise "message too large"; - return ref Msg(mtype, array[4+8+1+length+4] of byte, 0, 0, length); -} - -# used by auth tis -unrecvmsg(c: ref Conn, m: ref Msg) -{ - debug(DBG_PROTO, sys->sprint("unreceived %s len %d\n", msgnames[m.mtype], m.ep-m.rp)); - c.unget = m; -} - -readmsg(c: ref Conn, fd: ref Sys->FD): ref Msg -{ - if(c.unget != nil){ # TO DO: assumes state of processes ensures exclusive access - m := c.unget; - c.unget = nil; - return m; - } - buf := array[4] of byte; - if((n := sys->readn(fd, buf, len buf)) != len buf){ - if(n < 0) - sys->werrstr("short net read: %r"); - else - sys->werrstr("short net read"); - return nil; - } - length := get4(buf, 0); - if(length < 5 || length > 256*1024){ - sys->werrstr(sys->sprint("implausible packet length: %.8ux", length)); - return nil; - } - pad := 8-length%8; - m := ref Msg(0, array[pad+length] of byte, pad, 0, pad+length-4); - if(sys->readn(fd, m.data, len m.data) != len m.data){ - sys->werrstr(sys->sprint("short net read: %r")); - return nil; - } - if(c.cipher != nil) - c.cipher->decrypt(m.data, length+pad); - crc := sum32(0, m.data, m.ep); - crc0 := get4(m.data, m.ep); - if(crc != crc0){ - sys->werrstr(sys->sprint("bad crc %#ux != %#ux (packet length %ud)", crc, crc0, length)); - return nil; - } - m.mtype = int m.data[m.rp++]; - return m; -} - -recvmsg(c: ref Conn, mtype: int): ref Msg -{ - (m, errmsg) := <-c.in; - if(mtype == 0){ - # no checking - }else if(mtype == -1){ - # must not be nil - if(m == nil) - error(Ehangup); - }else if(m == nil || m.mtype != mtype) # must be given type - badmsg(m, mtype, errmsg); - return m; -} - -writemsg(c: ref Conn, m: ref Msg, fd: ref Sys->FD): int -{ - datalen := m.wp; - length := datalen+1+4; # will add type and crc - pad := 8-length%8; - debug(DBG_PROTO, sys->sprint("->[%d] %s\n", datalen, m.fulltext())); - m.data[4+pad+1:] = m.data[0: datalen]; # slide data to correct position (is this guaranteed?) TO DO - put4(m.data, 0, length); - p := 4; - if(c.cipher != nil) - for(i := 0; i < pad; i++) - m.data[p++] = byte fastrand(); - else{ - for(i = 0; i < pad; i++) - m.data[p++] = byte 0; - } - m.data[p++] = byte m.mtype; - # data already in position - p += datalen; - crc := sum32(0, m.data[4:], pad+1+datalen); - put4(m.data, p, crc); - p += 4; - if(c.cipher != nil) - c.cipher->encrypt(m.data[4:], length+pad); - if(sys->write(fd, m.data, p) != p) - return -1; - return 0; -} - -Msg.get1(m: self ref Msg): int -{ - if(m.rp >= m.ep) - raise Edecode; - return int m.data[m.rp++]; -} - -Msg.get2(m: self ref Msg): int -{ - if(m.rp+2 > m.ep) - raise Edecode; - x := (int m.data[m.rp+0]<<8) | int m.data[m.rp+1]; - m.rp += 2; - return x; -} - -Msg.get4(m: self ref Msg): int -{ - if(m.rp+4 > m.ep) - raise Edecode; - x := int m.data[m.rp+0]<<24|int m.data[m.rp+1]<<16|int m.data[m.rp+2]<<8|int m.data[m.rp+3]; - m.rp += 4; - return x; -} - -Msg.getarray(m: self ref Msg): array of byte -{ - length := m.get4(); - if(m.rp+length > m.ep) - raise Edecode; - p := m.data[m.rp: m.rp+length]; - m.rp += length; - return p; -} - -Msg.getstring(m: self ref Msg): string -{ - return string m.getarray(); -} - -Msg.getbytes(m: self ref Msg, n: int): array of byte -{ - if(m.rp+n > m.ep) - raise Edecode; - p := m.data[m.rp: m.rp+n]; - m.rp += n; - return p; -} - -Msg.getipint(m: self ref Msg): ref IPint -{ - n := (m.get2()+7)/8; # get2 returns # bits - return IPint.bebytestoip(m.getbytes(n)); -} - -Msg.getpk(m: self ref Msg): ref PK.RSA -{ - m.get4(); - ek := m.getipint(); - n := m.getipint(); - return ref PK.RSA(n, ek); -} - -Msg.put1(m: self ref Msg, x: int) -{ - if(m.wp >= m.ep) - raise Eencode; - m.data[m.wp++] = byte x; -} - -Msg.put2(m: self ref Msg, x: int) -{ - if(m.wp+2 > m.ep) - raise Eencode; - (m.data[m.wp+0], m.data[m.wp+1]) = (byte (x>>8), byte x); - m.wp += 2; -} - -Msg.put4(m: self ref Msg, x: int) -{ - if(m.wp+4 > m.ep) - raise Eencode; - (m.data[m.wp+0], m.data[m.wp+1], m.data[m.wp+2], m.data[m.wp+3]) = (byte (x>>24), byte (x>>16), byte (x>>8), byte x); - m.wp += 4; -} - -Msg.putstring(m: self ref Msg, s: string) -{ - b := array of byte s; - m.put4(len b); - m.putbytes(b, len b); -} - -Msg.putbytes(m: self ref Msg, a: array of byte, n: int) -{ - if(m.wp+n > m.ep) - raise Eencode; - m.data[m.wp:] = a[0: n]; - m.wp += n; -} - -Msg.putipint(m: self ref Msg, b: ref IPint) -{ - bits := b.bits(); - m.put2(bits); -# n := (bits+7)/8; - ba := b.iptobebytes(); - n := len ba; - if(m.wp+n > m.ep) - raise Eencode; - m.data[m.wp:] = ba; - m.wp += n; -} - -Msg.putpk(m: self ref Msg, key: ref PK.RSA) -{ - m.put4(key.n.bits()); - m.putipint(key.ek); - m.putipint(key.n); -} - -crctab := array[256] of int; - -initsum32() -{ - poly := int 16redb88320; - for(i := 0; i < 256; i++){ - crc := i; - for(j := 0; j < 8; j++) - if(crc&1) - crc = ((crc>>1) & int ~16r80000000)^poly; # need unsigned shift - else - crc = (crc>>1) & int ~16r80000000; - crctab[i] = crc; - } -} - -first_38: int = 1; - -sum32(lcrc: int, buf: array of byte, n: int): int -{ - crc := lcrc; - if(first_38){ - first_38 = 0; - initsum32(); - } - s := 0; - while(n-- > 0) - crc = crctab[(crc^int buf[s++])&16rff]^((crc>>8)&int ~16rFF000000); - return crc; -} - -erase(b: array of byte) -{ - for(i := 0; i < len b; i++) - b[i] = byte 0; -} - -# -# PKCS#1 padding -# -rsapad(b: ref IPint, n: int): ref IPint -{ - a := b.iptobebytes(); - pad := n - len a - 3; - if(pad < 0) - error("value too large to pad"); # can't happen if keys are required size - buf := array[n] of byte; - buf[0] = byte 0; - buf[1] = byte 2; - for(i := 2; --pad >= 0; i++) - buf[i] = byte (1+fastrand()%255); - buf[i++] = byte 0; - buf[i:] = a; - c := IPint.bebytestoip(buf); - erase(buf); - erase(a); - return c; -} - -rsaunpad(b: ref IPint): ref IPint -{ - buf := b.iptobebytes(); - i := 0; - if(buf[0] == byte 0) - i++; - if(buf[i] != byte 2) - error("bad data in rsaunpad"); - for(; i < len buf; i++) - if(buf[i] == byte 0) - break; - c := IPint.bebytestoip(buf[i:]); - erase(buf); - return c; -} - -rsaencryptbuf(key: ref PK.RSA, buf: array of byte, nbuf: int): ref IPint -{ - n := (key.n.bits()+7)/8; - a := IPint.bebytestoip(buf[0: nbuf]); - b := rsapad(a, n); - return crypt->rsaencrypt(key, b); -} - -iptorjustbe(b: ref IPint, buf: array of byte, length: int) -{ - a := b.iptobebytes(); - if(len a < length){ - length -= len a; - erase(buf[0: length]); - buf[length:] = a; - }else - buf[0:] = a[0: length]; - erase(a); -} - -hex(a: array of byte): string -{ - s := ""; - for(i := 0; i < len a; i++) - s += sys->sprint("%.2ux", int a[i]); - return s; -} - -debug(n: int, s: string) -{ - sys->fprint(sys->fildes(2), "debug: %s", s); -} - -error(s: string) -{ - sys->fprint(sys->fildes(2), "error: %s\n", s); - raise "error"; -} - -rsagen(bits: int): ref SK.RSA -{ - return crypt->rsagen(bits, 6, 0); -} - -rsaencrypt(key: ref PK.RSA, b: ref IPint): ref IPint -{ - return crypt->rsaencrypt(key, b); -} - -rsadecrypt(key: ref SK.RSA, b: ref IPint): ref IPint -{ - return crypt->rsadecrypt(key, b); -} - -fastrand(): int -{ - return int rand->bigrand(4294967295); -} - -readstrnl(fd: ref Sys->FD, buf: array of byte, nbuf: int): int -{ - for(i := 0; i < nbuf; i++) - case sys->read(fd, buf[i:], 1) { - -1 => - return -1; - 0 => - sys->werrstr("unexpected EOF"); - return -1; - * => - if(buf[i] == byte '\n') - return i; - } - sys->werrstr("line too long"); - return -1; -} - -eqbytes(a: array of byte, b: array of byte, n: int): int -{ - if(len a > n || len b > n) - return 0; - for(i := 0; i < n; i++) - if(a[i] != b[i]) - return 0; - return 1; -} - -get4(a: array of byte, o: int): int -{ - return int a[o+0]<<24 | int a[o+1]<<16 | int a[o+2]<<8 | int a[o+3]; -} - -put4(a: array of byte, o: int, v: int) -{ - a[o+0] = byte (v>>24); - a[o+1] = byte (v>>16); - a[o+2] = byte (v>>8); - a[o+3] = byte v; -} diff --git a/appl/cmd/ssh/sshio.m b/appl/cmd/ssh/sshio.m deleted file mode 100644 index 6c186e63..00000000 --- a/appl/cmd/ssh/sshio.m +++ /dev/null @@ -1,194 +0,0 @@ - - # internal debugging flags - DBG, DBG_CRYPTO, DBG_PACKET, DBG_AUTH, DBG_PROC, DBG_PROTO, DBG_IO, DBG_SCP: con 1<<iota; - - # protocol packet types - SSH_MSG_NONE, # 0 - SSH_MSG_DISCONNECT, - SSH_SMSG_PUBLIC_KEY, - SSH_CMSG_SESSION_KEY, - SSH_CMSG_USER, - SSH_CMSG_AUTH_RHOSTS, - SSH_CMSG_AUTH_RSA, - SSH_SMSG_AUTH_RSA_CHALLENGE, - SSH_CMSG_AUTH_RSA_RESPONSE, - SSH_CMSG_AUTH_PASSWORD, # 10 - SSH_CMSG_REQUEST_PTY, - SSH_CMSG_WINDOW_SIZE, - SSH_CMSG_EXEC_SHELL, - SSH_CMSG_EXEC_CMD, - SSH_SMSG_SUCCESS, - SSH_SMSG_FAILURE, - SSH_CMSG_STDIN_DATA, - SSH_SMSG_STDOUT_DATA, - SSH_SMSG_STDERR_DATA, - SSH_CMSG_EOF, # 20 - SSH_SMSG_EXITSTATUS, - SSH_MSG_CHANNEL_OPEN_CONFIRMATION, - SSH_MSG_CHANNEL_OPEN_FAILURE, - SSH_MSG_CHANNEL_DATA, - SSH_MSG_CHANNEL_INPUT_EOF, - SSH_MSG_CHANNEL_OUTPUT_CLOSED, - SSH_MSG_UNIX_DOMAIN_X11_FORWARDING, # obsolete - SSH_SMSG_X11_OPEN, - SSH_CMSG_PORT_FORWARD_REQUEST, - SSH_MSG_PORT_OPEN, # 30 - SSH_CMSG_AGENT_REQUEST_FORWARDING, - SSH_SMSG_AGENT_OPEN, - SSH_MSG_IGNORE, - SSH_CMSG_EXIT_CONFIRMATION, - SSH_CMSG_X11_REQUEST_FORWARDING, - SSH_CMSG_AUTH_RHOSTS_RSA, - SSH_MSG_DEBUG, - SSH_CMSG_REQUEST_COMPRESSION, - SSH_CMSG_MAX_PACKET_SIZE, - SSH_CMSG_AUTH_TIS, # 40 - SSH_SMSG_AUTH_TIS_CHALLENGE, - SSH_CMSG_AUTH_TIS_RESPONSE, - SSH_CMSG_AUTH_KERBEROS, - SSH_SMSG_AUTH_KERBEROS_RESPONSE, - SSH_CMSG_HAVE_KERBEROS_TGT: con iota; - - SSH_MSG_ERROR: con -1; - - # protocol flags - SSH_PROTOFLAG_SCREEN_NUMBER: con 1<<0; - SSH_PROTOFLAG_HOST_IN_FWD_OPEN: con 1<<1; - - # agent protocol packet types - SSH_AGENTC_NONE, - SSH_AGENTC_REQUEST_RSA_IDENTITIES, - SSH_AGENT_RSA_IDENTITIES_ANSWER, - SSH_AGENTC_RSA_CHALLENGE, - SSH_AGENT_RSA_RESPONSE, - SSH_AGENT_FAILURE, - SSH_AGENT_SUCCESS, - SSH_AGENTC_ADD_RSA_IDENTITY, - SSH_AGENTC_REMOVE_RSA_IDENTITY: con iota; - - # protocol constants - SSH_MAX_DATA: con 256*1024; - SSH_MAX_MSG: con SSH_MAX_DATA+4; - SESSKEYLEN: con 32; - SESSIDLEN: con 16; - COOKIELEN: con 8; - - # crypto ids - SSH_CIPHER_NONE, - SSH_CIPHER_IDEA, - SSH_CIPHER_DES, - SSH_CIPHER_3DES, - SSH_CIPHER_TSS, - SSH_CIPHER_RC4, - SSH_CIPHER_BLOWFISH: con iota; - - # auth method ids - SSH_AUTH_RHOSTS, - SSH_AUTH_RSA, - SSH_AUTH_PASSWORD, - SSH_AUTH_RHOSTS_RSA, - SSH_AUTH_TIS, - SSH_AUTH_USER_RSA: con 1+iota; - -Edecode: con "error decoding input packet"; -Eencode: con "out of space encoding output packet (BUG)"; -Ehangup: con "hungup connection"; -Ememory: con "out of memory"; - -Cipher: module -{ - id: fn(): int; - init: fn(key: array of byte, isserver: int); - encrypt: fn(a: array of byte, n: int); - decrypt: fn(a: array of byte, n: int); -}; - -Auth: module -{ - AuthInfo: adt{ - user: string; - cap: string; - }; - - id: fn(): int; - firstmsg: fn(): int; - init: fn(nil: Sshio); - authsrv: fn(nil: ref Sshio->Conn, nil: ref Sshio->Msg): ref AuthInfo; - auth: fn(nil: ref Sshio->Conn): int; -}; - -Sshio: module -{ - PATH: con "sshio.dis"; - - Conn: adt{ - in: chan of (ref Msg, string); - out: chan of ref Msg; - - sessid: array of byte; - sesskey: array of byte; - hostkey: ref Crypt->PK.RSA; - flags: int; - cipher: Cipher; # chosen cipher - user: string; - host: string; - interactive: int; - unget: ref Msg; - - mk: fn(host: string, fd: ref Sys->FD): ref Conn; - setkey: fn(c: self ref Conn, key: ref Crypt->PK.RSA); - }; - - Msg: adt{ - mtype: int; - data: array of byte; - rp: int; # read pointer - wp: int; # write pointer - ep: int; # byte just beyond message data - - mk: fn(mtype: int, length: int): ref Msg; - text: fn(m: self ref Msg): string; - fulltext: fn(m: self ref Msg): string; - - get1: fn(m: self ref Msg): int; - get2: fn(m: self ref Msg): int; - get4: fn(m: self ref Msg): int; - getstring: fn(m: self ref Msg): string; - getbytes: fn(m: self ref Msg, n: int): array of byte; - getarray: fn(m: self ref Msg): array of byte; - getipint: fn(m: self ref Msg): ref IPints->IPint; - getpk: fn(m: self ref Msg): ref Crypt->PK.RSA; - - put1: fn(m: self ref Msg, nil: int); - put2: fn(m: self ref Msg, nil: int); - put4: fn(m: self ref Msg, nil: int); - putstring: fn(m: self ref Msg, s: string); - putbytes: fn(m: self ref Msg, a: array of byte, n: int); - putipint: fn(m: self ref Msg, mp: ref IPints->IPint); - putpk: fn(m: self ref Msg, pk: ref Crypt->PK.RSA); - }; - - init: fn(); - - badmsg: fn(nil: ref Msg, nil: int, err: string); - recvmsg: fn(nil: ref Conn, nil: int): ref Msg; - unrecvmsg: fn(nil: ref Conn, nil: ref Msg); - rsapad: fn(nil: ref IPints->IPint, nil: int): ref IPints->IPint; - rsaunpad: fn(nil: ref IPints->IPint): ref IPints->IPint; - iptorjustbe: fn(nil: ref IPints->IPint, nil: array of byte, nil: int); - rsaencryptbuf: fn(nil: ref Crypt->PK.RSA, nil: array of byte, nil: int): ref IPints->IPint; - rsagen: fn(nbits: int): ref Crypt->SK.RSA; - rsaencrypt: fn(key: ref Crypt->PK.RSA, b: ref IPints->IPint): ref IPints->IPint; - rsadecrypt: fn(key: ref Crypt->SK.RSA, b: ref IPints->IPint): ref IPints->IPint; - - debug: fn(nil: int, nil: string); - error: fn(nil: string); - readstrnl: fn(fd: ref Sys->FD, buf: array of byte, nbytes: int): int; - calcsessid: fn(hostmod: ref IPints->IPint, servermod: ref IPints->IPint, cookie: array of byte): array of byte; -# sshlog: fn(nil: array of byte); # TBA was ... - - fastrand: fn(): int; - eqbytes: fn(a: array of byte, b: array of byte, n: int): int; - readversion: fn(fd: ref Sys->FD): (int, int, string); - hex: fn(a: array of byte): string; -}; diff --git a/appl/cmd/ssh/sshserve.b b/appl/cmd/ssh/sshserve.b deleted file mode 100644 index dc8bbd31..00000000 --- a/appl/cmd/ssh/sshserve.b +++ /dev/null @@ -1,495 +0,0 @@ -implement Sshserve; - -include "sys.m"; - sys: Sys; - -include "draw.m"; - -include "ipints.m"; - ipints: IPints; - IPint: import ipints; - -include "crypt.m"; - crypt: Crypt; - PK, SK: import crypt; - -include "env.m"; - env: Env; - -include "sh.m"; - sh: Sh; - -include "wait.m"; - wait: Wait; - -include "arg.m"; - -include "sshio.m"; - sshio: Sshio; - Conn, Msg: import sshio; - recvmsg: import sshio; - error, debug: import sshio; - -Sshserve: module -{ - init: fn(nil: ref Draw->Context, argl: list of string); -}; - -AuthRpc: adt {}; -debuglevel := 0; - -cipherlist := "blowfish rc4 3des"; -ciphers: list of Cipher; - -authlist := "rsa password tis"; -authsrvs: list of Auth; - -maxmsg := 256*1024; - -serverpriv: ref SK.RSA; -serverkey: ref PK.RSA; -hostpriv: ref SK.RSA; - -init(nil: ref Draw->Context, args: list of string) -{ - sys = load Sys Sys->PATH; - ipints = load IPints IPints->PATH; - crypt = load Crypt Crypt->PATH; - env = load Env Env->PATH; - sh = load Sh Sh->PATH; - sshio = load Sshio Sshio->PATH; - sshio->init(); - wait = load Wait Wait->PATH; - wait->init(); -# fmtinstall('B', mpfmt); -# fmtinstall('H', encodefmt); - sys->pctl(Sys->NEWPGRP|Sys->FORKFD|Sys->FORKNS|Sys->FORKENV, nil); - keyfile: string; - arg := load Arg Arg->PATH; - arg->setusage("sshserve [-A authlist] [-c cipherlist] [-k keyfile] client-ip-address"); - arg->init(args); - while((o := arg->opt()) != 0){ - case o { - 'D' => - debuglevel = int arg->earg(); - 'A' => - authlist = arg->earg(); - 'c' => - cipherlist = arg->earg(); - 'k' => - keyfile = arg->earg(); - * => - arg->usage(); - } - } - args = arg->argv(); - if(len args != 1) - arg->usage(); - arg = nil; - - sys->dup(2, 1); -# if(keyfile != nil) -# ; # read hostpriv from file -# sshlog("connect from %s", c.host); - authsrvs = loadlist("auth", authlist, authload); - ciphers = loadlist("cipher", cipherlist, cipherload); - hostpriv = crypt->rsagen(1024, 6, 0); - serverpriv = crypt->rsagen(768, 6, 0); - serverkey = serverpriv.pk; - { - versioning(sys->fildes(0)); - c := Conn.mk(hd args, sys->fildes(0)); - c.setkey(hostpriv.pk); - authenticate(c); - comms(c); - }exception e{ - "fail:*" => - raise e; - "error*" => - notegrp(sys->pctl(0, nil), "error"); - raise "fail:"+e; - } -} - -authload(f: string): Auth -{ - return load Auth f; -} - -cipherload(f: string): Cipher -{ - return load Cipher f; -} - -loadlist[T](sort: string, set: string, loadf: ref fn(f: string): T): list of T -{ - l: list of T; - (nil, fld) := sys->tokenize(set, " \t,"); - for(; fld != nil; fld = tl fld){ - f := "/dis/ssh/"+sort+hd fld+".dis"; - m := loadf(f); - if(m == nil) - error(sys->sprint("unknown %s scheme %s (%s)", sort, hd fld, f)); - l = m :: l; - } - return l; -} - -comms(c: ref Conn) -{ - (kidpid, infd, waiting) := prelude(c); -Work: - for(;;)alt{ - (m, nil) := <-c.in => - if(m == nil){ - notegrp(kidpid, "hungup"); - exit; - } - case m.mtype { - * => - sshio->badmsg(m, 0, nil); - SSH_MSG_DISCONNECT => - notegrp(kidpid, "hungup"); - sysfatal("client disconnected"); - SSH_CMSG_STDIN_DATA => - if(infd != nil){ - n := m.get4(); - sys->write(infd, m.getbytes(n), n); - } - SSH_CMSG_EOF => - infd = nil; - SSH_CMSG_EXIT_CONFIRMATION => - # sent by some clients as dying breath - notegrp(kidpid, "hungup"); - break Work; - SSH_CMSG_WINDOW_SIZE => - ; # we don't care - } - (pid, nil, status) := <-waiting => - if(pid == kidpid){ - if(status != "" && status != "0"){ - m := Msg.mk(SSH_MSG_DISCONNECT, 4+Sys->UTFmax*len status); - m.putstring(status); - sendmsg(c, m); - }else{ - m := Msg.mk(SSH_SMSG_EXITSTATUS, 4); - m.put4(0); - sendmsg(c, m); - } - sendmsg(c, nil); - break Work; - } - } - notegrp(sys->pctl(0, nil), "done"); -} - -prelude(c: ref Conn): (int, ref Sys->FD, chan of (int, string, string)) -{ - for(;;){ - m := recvmsg(c, -1); - if(m == nil) - return (-1, nil, nil); - case m.mtype { - * => - sendmsg(c, Msg.mk(SSH_SMSG_FAILURE, 0)); - SSH_MSG_DISCONNECT => - sysfatal("client disconnected"); - SSH_CMSG_REQUEST_PTY => - sendmsg(c, Msg.mk(SSH_SMSG_SUCCESS, 0)); - SSH_CMSG_MAX_PACKET_SIZE => - n := m.get4(); - if(n >= 32 && n <= SSH_MAX_MSG){ - maxmsg = n; - sendmsg(c, Msg.mk(SSH_SMSG_SUCCESS, 0)); - }else - sendmsg(c, Msg.mk(SSH_SMSG_FAILURE, 0)); - SSH_CMSG_EXEC_SHELL => - return startcmd(c, nil); - SSH_CMSG_EXEC_CMD => - cmd := m.getstring(); - return startcmd(c, cmd); - } - } -} - -copyout(c: ref Conn, fd: ref Sys->FD, mtype: int) -{ - buf := array[8192] of byte; - max := len buf; - if(max > maxmsg-32) # 32 is an overestimate of packet overhead - max = maxmsg-32; - if(max <= 0) - sysfatal("maximum message size too small"); - while((n := sys->read(fd, buf, max)) > 0){ - m := Msg.mk(mtype, 4+n); - m.put4(n); - m.putbytes(buf, n); - sendmsg(c, m); - } -} - -send_ssh_smsg_public_key(c: ref Conn, cookie: array of byte) -{ - m := Msg.mk(SSH_SMSG_PUBLIC_KEY, 2048); - m.putbytes(cookie, COOKIELEN); - m.putpk(serverkey); - m.putpk(c.hostkey); - m.put4(c.flags); - ciphermask := 0; - for(l1 := ciphers; l1 != nil; l1 = tl l1) - ciphermask |= 1<<(hd l1)->id(); - m.put4(ciphermask); - authmask := 0; - for(l2 := authsrvs; l2 != nil; l2 = tl l2) - authmask |= 1<<(hd l2)->id(); - m.put4(authmask); - sendmsg(c, m); -} - -rpcdecrypt(rpc: ref AuthRpc, b: ref IPint): ref IPint -{ - raise "rpcdecrypt"; -# p := array of byte b.iptostr(16); -# if(auth_rpc(rpc, "write", p, len p) != ARok) -# sysfatal("factotum rsa write: %r"); -# if(auth_rpc(rpc, "read", nil, 0) != ARok) -# sysfatal("factotum rsa read: %r"); -# return strtomp(rpc.arg, nil, 16, nil); -} - -recv_ssh_cmsg_session_key(c: ref Conn, rpc: ref AuthRpc, cookie: array of byte) -{ - m := recvmsg(c, SSH_CMSG_SESSION_KEY); - id := m.get1(); - c.cipher = nil; - for(l := ciphers; l != nil; l = tl l) - if((hd l)->id() == id){ - c.cipher = hd l; - break; - } - if(c.cipher == nil) - sysfatal(sys->sprint("invalid cipher %d selected", id)); - if(!sshio->eqbytes(m.getbytes(COOKIELEN), cookie, len cookie)) - sysfatal("bad cookie"); - serverkeylen := serverkey.n.bits(); - hostkeylen := c.hostkey.n.bits(); - ksmall, kbig: ref SK.RSA; - if(serverkeylen+128 <= hostkeylen){ - ksmall = serverpriv; - kbig = nil; - }else if(hostkeylen+128 <= serverkeylen){ - ksmall = nil; - kbig = serverpriv; - }else - sysfatal("server session and host keys do not differ by at least 128 bits"); - b := m.getipint(); - debug(DBG_CRYPTO, sys->sprint("encrypted with kbig is %s\n", b.iptostr(16))); - if(kbig != nil) - b = sshio->rsadecrypt(kbig, b); - else -# b = rpcdecrypt(rpc, b); - b = sshio->rsadecrypt(hostpriv, b); - b = sshio->rsaunpad(b); - sshio->debug(DBG_CRYPTO, sys->sprint("encrypted with ksmall is %s\n", b.iptostr(16))); - if(ksmall != nil) - b = sshio->rsadecrypt(ksmall, b); - else -# b = rpcdecrypt(rpc, b); - b = sshio->rsadecrypt(hostpriv, b); - b = sshio->rsaunpad(b); - debug(DBG_CRYPTO, sys->sprint("munged is %s\n", b.iptostr(16))); - n := (b.bits()+7)/8; - if(n < SESSKEYLEN) - sysfatal("client sent short session key"); - buf := array[SESSKEYLEN] of byte; - sshio->iptorjustbe(b, buf, SESSKEYLEN); - for(i := 0; i < SESSIDLEN; i++) - buf[i] ^= c.sessid[i]; - c.sesskey[0: ] = buf[0: SESSKEYLEN]; - debug(DBG_CRYPTO, sys->sprint("unmunged is %.*s\n", SESSKEYLEN*2, sshio->hex(buf))); - c.flags = m.get4(); -} - -authsrvuser(c: ref Conn) -{ - m := recvmsg(c, SSH_CMSG_USER); - user := m.getstring(); - c.user = user; - inited := 0; - ai: ref Auth->AuthInfo; - while(authsrvs != nil && ai == nil){ -# # -# # * clumsy: if the client aborted the auth_tis early -# # * we don't send a new failure. we check this by -# # * looking at c->unget, which is only used in that -# # * case. -# # - if(c.unget == nil) - sendmsg(c, Msg.mk(SSH_SMSG_FAILURE, 0)); - m = recvmsg(c, -1); - for(l := authsrvs; l != nil; l = tl l) - if((hd l)->firstmsg() == m.mtype){ - bit := 1 << (hd l)->id(); - if((inited & bit) == 0){ - (hd l)->init(sshio); - inited |= bit; - } - ai = (hd l)->authsrv(c, m); - break; - } - if(l == nil) - sshio->badmsg(m, 0, nil); - } - sendmsg(c, Msg.mk(SSH_SMSG_SUCCESS, 0)); -# if(noworld(ai.cuid)) -# ns := "/lib/namespace.noworld"; -# else -# ns = nil; -# if(auth_chuid(ai, ns) < 0){ -# sshlog("auth_chuid to %s: %r", ai.cuid); -# sysfatal("auth_chuid: %r"); -# } -# sshlog("logged in as %q", ai.user); - if(ai != nil) - sys->print("logged in as %q\n", ai.user); -} - -keyjunk() -{ - p: array of byte; - m: ref IPint; - rpc: ref AuthRpc; - key: ref PK.RSA; - -# # -# # BUG: should use `attr' to get the key attributes -# # after the read, but that's not implemented yet. -# # -# if((b = Bopen("/mnt/factotum/ctl", OREAD)) == nil) -# sysfatal("open /mnt/factotum/ctl: %r"); -# while((p = Brdline(b, '\n')) != nil){ -# if(strstr(p, " proto=rsa ") != nil && strstr(p, " service=sshserve ") != nil) -# break; -# } -# if(p == nil) -# sysfatal("no sshserve keys found in /mnt/factotum/ctl"); -# a = _parseattr(p); -# Bterm(b); -# key = rsaprivalloc(); -# if((p = _strfindattr(a, "n")) == nil) -# sysfatal("no n in sshserve key"); -# if((key.n = IPint.strtoip(p, 16)) == nil) -# sysfatal("bad n in sshserve key"); -# if((p = _strfindattr(a, "ek")) == nil) -# sysfatal("no ek in sshserve key"); -# if((key.ek = IPint.strtoip(p, 16)) == nil) -# sysfatal("bad ek in sshserve key"); -# _freeattr(a); -# if((afd = sys->open("/mnt/factotum/rpc", ORDWR)) == nil) -# sysfatal("open /mnt/factotum/rpc: %r"); -# if((rpc = auth_allocrpc(afd)) == nil) -# sysfatal("auth_allocrpc: %r"); -# p = "proto=rsa role=client service=sshserve"; -# if(auth_rpc(rpc, "start", p, len p) != ARok) -# sysfatal("auth_rpc start %s: %r", p); -# if(auth_rpc(rpc, "read", nil, 0) != ARok) -# sysfatal("auth_rpc read: %r"); -# m = strtomp(rpc.arg, nil, 16, nil); -# if(mpcmp(m, key.n) != 0) -# sysfatal("key in /mnt/factotum/ctl does not match rpc key"); -# mpfree(m); -# c.hostkey = key; -} - -versioning(fd: ref Sys->FD) -{ - sys->fprint(fd, "SSH-1.5-Inferno\n"); - (maj, min, err_or_id) := sshio->readversion(fd); - if(maj < 0) - sysfatal(err_or_id); - if(maj != 1 || min < 5) - sysfatal(sys->sprint("protocol mismatch; got %s, need SSH-1.x for x >= 5", err_or_id)); -} - -authenticate(c: ref Conn) -{ - rpc: ref AuthRpc; - - cookie := array[COOKIELEN] of {* => byte sshio->fastrand()}; - c.sessid = sshio->calcsessid(c.hostkey.n, serverkey.n, cookie); - send_ssh_smsg_public_key(c, cookie); - recv_ssh_cmsg_session_key(c, rpc, cookie); -# afd = nil; - c.cipher->init(c.sesskey, 1); # turns on encryption - sendmsg(c, Msg.mk(SSH_SMSG_SUCCESS, 0)); - authsrvuser(c); -} - -startcmd(c: ref Conn, cmd: string): (int, ref Sys->FD, chan of (int, string, string)) -{ - pfd := array[3] of {* => array[2] of ref Sys->FD}; - for(i := 0; i < 3; i++) - if(sys->pipe(pfd[i]) < 0) - sysfatal(sys->sprint("pipe: %r")); - wfd := sys->open("#p/"+string sys->pctl(0, nil)+"/wait", Sys->OREAD); - if(wfd == nil) - sysfatal(sys->sprint("open wait: %r")); - pidc := chan of int; - spawn startcmd1(c, cmd, pfd, pidc); - kidpid := <-pidc; - (nil, waited) := wait->monitor(wfd); - spawn copyout(c, pfd[1][0], SSH_SMSG_STDOUT_DATA); - pfd[1][0] = nil; - spawn copyout(c, pfd[2][0], SSH_SMSG_STDERR_DATA); - pfd[2][0] = nil; - return (kidpid, pfd[0][0], waited); -} - -startcmd1(c: ref Conn, cmd: string, pfd: array of array of ref Sys->FD, pidc: chan of int) -{ - sysname := env->getenv("sysname"); - tz := env->getenv("timezone"); - sys->pctl(Sys->FORKFD, nil); - for(i := 0; i < len pfd; i++) - if(sys->dup(pfd[i][1].fd, i) < 0) - sysfatal(sys->sprint("dup: %r")); - pfd = nil; - sys->pctl(Sys->NEWPGRP|Sys->FORKNS|Sys->FORKENV|Sys->NEWFD, 0::1::2::nil); - pidc <-= sys->pctl(0, nil); - env->setenv("user", c.user); - if(sysname != nil) - env->setenv("sysname", sysname); - if(tz != nil) - env->setenv("tz", tz); - if(sys->chdir("/usr/"+c.user) < 0) - sys->chdir("/"); - if(cmd != nil){ - env->setenv("service", "rx"); - status := sh->run(nil, list of {"/dis/sh.dis", "-lc", cmd}); - if(status != nil) - raise "fail:"+status; - }else{ - env->setenv("service", "con"); - #execl("/bin/ip/telnetd", "telnetd", "-tn", nil); # TO DO: just for echo and line editing - sys->fprint(sys->fildes(2), "sshserve: cannot run /dis/ip/telnetd: %r"); - } -} - -sysfatal(s: string) -{ - sys->print("sysfatal: %s\n", s); - notegrp(sys->pctl(0, nil), "zap"); - exit; -} - -notegrp(pid: int, nil: string) -{ - fd := sys->open("#p/"+string pid+"/ctl", Sys->OWRITE); - if(fd != nil) - sys->fprint(fd, "killgrp"); -} - -sendmsg(c: ref Conn, m: ref Msg) -{ - c.out <-= m; -} diff --git a/appl/cmd/styxlisten.b b/appl/cmd/styxlisten.b index 4c8bcc94..df136e47 100644 --- a/appl/cmd/styxlisten.b +++ b/appl/cmd/styxlisten.b @@ -1,8 +1,6 @@ implement Styxlisten; include "sys.m"; sys: Sys; -include "dial.m"; - dial: Dial; include "draw.m"; include "keyring.m"; keyring: Keyring; @@ -30,9 +28,6 @@ init(ctxt: ref Draw->Context, argv: list of string) auth = load Auth Auth->PATH; if (auth == nil) badmodule(Auth->PATH); - dial = load Dial Dial->PATH; - if (dial == nil) - badmodule(Dial->PATH); if ((e := auth->init()) != nil) error("auth init failed: " + e); keyring = load Keyring Keyring->PATH; @@ -81,7 +76,7 @@ init(ctxt: ref Draw->Context, argv: list of string) arg = nil; if (doauth && algs == nil) algs = getalgs(); - addr := dial->netmkaddr(hd argv, "tcp", "styx"); + addr := netmkaddr(hd argv, "tcp", "styx"); cmd := tl argv; authinfo: ref Keyring->Authinfo; @@ -93,8 +88,8 @@ init(ctxt: ref Draw->Context, argv: list of string) error(sys->sprint("cannot read %s: %r", keyfile)); } - c := dial->announce(addr); - if (c == nil) + (ok, c) := sys->announce(addr); + if (ok == -1) error(sys->sprint("cannot announce on %s: %r", addr)); if(!trusted){ sys->unmount(nil, "/mnt/keys"); # should do for now @@ -108,17 +103,17 @@ init(ctxt: ref Draw->Context, argv: list of string) spawn listener(c, popen(ctxt, cmd, lsync), authinfo, algs, lsync); } -listener(c: ref Dial->Connection, mfd: ref Sys->FD, authinfo: ref Keyring->Authinfo, algs: list of string, lsync: chan of int) +listener(c: Sys->Connection, mfd: ref Sys->FD, authinfo: ref Keyring->Authinfo, algs: list of string, lsync: chan of int) { lsync <-= sys->pctl(0, nil); for (;;) { - nc := dial->listen(c); - if (nc == nil) + (n, nc) := sys->listen(c); + if (n == -1) error(sys->sprint("listen failed: %r")); if (verbose) sys->fprint(stderr(), "styxlisten: got connection from %s", readfile(nc.dir + "/remote")); - dfd := dial->accept(nc); + dfd := sys->open(nc.dir + "/data", Sys->ORDWR); if (dfd != nil) { if(nc.cfd != nil) sys->fprint(nc.cfd, "keepalive"); @@ -250,3 +245,18 @@ stderr(): ref Sys->FD { return sys->fildes(2); } + +netmkaddr(addr, net, svc: string): string +{ + if(net == nil) + net = "net"; + (n, nil) := sys->tokenize(addr, "!"); + if(n <= 1){ + if(svc== nil) + return sys->sprint("%s!%s", net, addr); + return sys->sprint("%s!%s!%s", net, addr, svc); + } + if(svc == nil || n > 2) + return addr; + return sys->sprint("%s!%s", addr, svc); +} |
