summaryrefslogtreecommitdiff
path: root/appl/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd')
-rw-r--r--appl/cmd/auth/factotum/authio.m5
-rw-r--r--appl/cmd/auth/factotum/factotum.b128
-rw-r--r--appl/cmd/auth/factotum/proto/infauth.b5
-rw-r--r--appl/cmd/auth/factotum/proto/p9any.b5
-rw-r--r--appl/cmd/auth/factotum/proto/pass.b5
-rw-r--r--appl/cmd/auth/factotum/proto/rsa.b126
-rw-r--r--appl/cmd/auth/factotum/rpc.b2
-rw-r--r--appl/cmd/diff.b10
8 files changed, 258 insertions, 28 deletions
diff --git a/appl/cmd/auth/factotum/authio.m b/appl/cmd/auth/factotum/authio.m
index 7c0565b5..a156daba 100644
--- a/appl/cmd/auth/factotum/authio.m
+++ b/appl/cmd/auth/factotum/authio.m
@@ -47,12 +47,15 @@ Authio: module
rpc: ref Rpc;
findkey: fn(io: self ref IO, attrs: list of ref Attr, extra: string): (ref Key, string);
+ findkeys: fn(io: self ref IO, attrs: list of ref Attr, extra: string): (list of ref Key, string);
needkey: fn(io: self ref IO, attrs: list of ref Attr, extra: string): (ref Key, string);
read: fn(io: self ref IO): array of byte;
readn: fn(io: self ref IO, n: int): array of byte;
write: fn(io: self ref IO, buf: array of byte, n: int): int;
toosmall: fn(io: self ref IO, n: int);
error: fn(io: self ref IO, s: string);
+ rdwr: fn(io: self ref IO): array of byte;
+ reply2read: fn(io: self ref IO, a: array of byte, n: int): int;
ok: fn(io: self ref IO);
done: fn(io: self ref IO, ai: ref Authinfo);
};
@@ -71,10 +74,12 @@ Authio: module
user: fn(): string;
lookattrval: fn(a: list of ref Attr, n: string): string;
parseline: fn(s: string): list of ref Attr;
+ attrtext: fn(a: list of ref Attr): string;
};
Authproto: module
{
init: fn(f: Authio): string;
interaction: fn(attrs: list of ref Authio->Attr, io: ref Authio->IO): string;
+ keycheck: fn(k: ref Authio->Key): string;
};
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){
diff --git a/appl/cmd/auth/factotum/proto/infauth.b b/appl/cmd/auth/factotum/proto/infauth.b
index 0b3505d6..cfc847eb 100644
--- a/appl/cmd/auth/factotum/proto/infauth.b
+++ b/appl/cmd/auth/factotum/proto/infauth.b
@@ -382,3 +382,8 @@ sl(l: list of ref Sexp): ref Sexp
{
return ref Sexp.List(l);
}
+
+keycheck(nil: ref Authio->Key): string
+{
+ return nil;
+}
diff --git a/appl/cmd/auth/factotum/proto/p9any.b b/appl/cmd/auth/factotum/proto/p9any.b
index 1668a701..3d0b0d12 100644
--- a/appl/cmd/auth/factotum/proto/p9any.b
+++ b/appl/cmd/auth/factotum/proto/p9any.b
@@ -230,3 +230,8 @@ authdial(netroot: string, dom: string): ref Sys->FD
(nil, conn) := sys->dial(netmkaddr(p, netroot, "ticket"), nil);
return conn.dfd;
}
+
+keycheck(nil: ref Authio->Key): string
+{
+ return nil;
+}
diff --git a/appl/cmd/auth/factotum/proto/pass.b b/appl/cmd/auth/factotum/proto/pass.b
index 9c4462b3..aea5b00e 100644
--- a/appl/cmd/auth/factotum/proto/pass.b
+++ b/appl/cmd/auth/factotum/proto/pass.b
@@ -27,3 +27,8 @@ interaction(attrs: list of ref Attr, io: ref Authio->IO): string
io.write(a, len a);
return nil;
}
+
+keycheck(nil: ref Authio->Key): string
+{
+ return nil;
+}
diff --git a/appl/cmd/auth/factotum/proto/rsa.b b/appl/cmd/auth/factotum/proto/rsa.b
new file mode 100644
index 00000000..24dcef43
--- /dev/null
+++ b/appl/cmd/auth/factotum/proto/rsa.b
@@ -0,0 +1,126 @@
+implement Authproto;
+
+# SSH RSA authentication.
+#
+# Client protocol:
+# read public key
+# if you don't like it, read another, repeat
+# write challenge
+# read response
+# all numbers are hexadecimal biginits parsable with strtomp.
+#
+
+include "sys.m";
+ sys: Sys;
+ Rread, Rwrite: import Sys;
+
+include "draw.m";
+
+include "keyring.m";
+ kr: Keyring;
+ IPint, RSAsk, RSApk: import kr;
+
+include "../authio.m";
+ authio: Authio;
+ Aattr, Aval, Aquery: import Authio;
+ Attr, IO, Key, Authinfo: import authio;
+ eqbytes, memrandom: import authio;
+ lookattrval: import authio;
+
+
+init(f: Authio): string
+{
+ authio = f;
+ sys = load Sys Sys->PATH;
+ kr = load Keyring Keyring->PATH;
+# base16 = load Encoding Encoding->BASE16PATH;
+ return nil;
+}
+
+interaction(attrs: list of ref Attr, io: ref IO): string
+{
+ role := lookattrval(attrs, "role");
+ if(role == nil)
+ return "role not specified";
+ if(role != "client")
+ return "only client role supported";
+ sk: ref RSAsk;
+ keys: list of ref Key;
+ err: string;
+ for(;;){
+ waitread(io);
+ (keys, err) = io.findkeys(attrs, "");
+ if(keys != nil)
+ break;
+ io.error(err);
+ }
+ for(; keys != nil; keys = tl keys){
+ (sk, err) = keytorsa(hd keys);
+ if(sk != nil){
+ r := array of byte sk.pk.n.iptostr(16);
+ while(!io.reply2read(r, len r))
+ waitread(io);
+ data := io.rdwr();
+ if(data != nil){
+ chal := IPint.strtoip(string data, 16);
+ if(chal == nil){
+ io.error("invalid challenge value");
+ continue;
+ }
+ m := sk.decrypt(chal);
+ b := array of byte m.iptostr(16);
+ io.write(b, len b);
+ io.done(nil);
+ return nil;
+ }
+ }
+ }
+ for(;;){
+ io.error("no key matches "+authio->attrtext(attrs));
+ waitread(io);
+ }
+}
+
+waitread(io: ref IO)
+{
+ while(io.rdwr() != nil)
+ io.error("no current key");
+}
+
+Badkey: exception(string);
+
+ipint(attrs: list of ref Attr, name: string): ref IPint raises Badkey
+{
+ s := lookattrval(attrs, name);
+ if(s == nil)
+ raise Badkey("missing attribute "+name);
+ m := IPint.strtoip(s, 16);
+ if(m == nil)
+ raise Badkey("invalid value for "+name);
+ return m;
+}
+
+keytorsa(k: ref Key): (ref RSAsk, string)
+{
+ sk := ref RSAsk;
+ sk.pk = ref RSApk;
+ {
+ 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);
+ }
+ return (sk, nil);
+}
+
+keycheck(k: ref Authio->Key): string
+{
+ return keytorsa(k).t1;
+}
diff --git a/appl/cmd/auth/factotum/rpc.b b/appl/cmd/auth/factotum/rpc.b
index 220980a8..5d76c2be 100644
--- a/appl/cmd/auth/factotum/rpc.b
+++ b/appl/cmd/auth/factotum/rpc.b
@@ -58,7 +58,7 @@ rpc(f: ref Sys->FD, addr: string)
b := array of byte addr;
if(sys->write(f, b, len b) > 0){
sys->seek(f, big 0, Sys->SEEKSTART);
- buf := array[256] of byte;
+ buf := array[4096+3] of byte;
if((n := sys->read(f, buf, len buf)) > 0)
sys->print("%s\n", string buf[0:n]);
if(n >= 0)
diff --git a/appl/cmd/diff.b b/appl/cmd/diff.b
index 4ef3ab32..3847e9e9 100644
--- a/appl/cmd/diff.b
+++ b/appl/cmd/diff.b
@@ -203,7 +203,6 @@ init(nil: ref Draw->Context, args: list of string)
sort(a : array of line, n : int)
{
w : line;
- j1:=0;
m := 0;
for (i := 1; i <= n; i *= 2)
m = 2*i - 1;
@@ -791,12 +790,9 @@ statfile(file : string) : (string,Sys->Dir)
{
(ret,sb):=sys->stat(file);
if (ret==-1) {
- if (file == "-") {
- (ret,sb)= sys->fstat(sys->fildes(0));
- if (ret == -1) {
- error(sys->sprint("cannot stat %s: %r", file));
- return (nil,sb);
- }
+ if (file != "-" || sys->fstat(sys->fildes(0)).t0 == -1){
+ error(sys->sprint("cannot stat %s: %r", file));
+ return (nil,sb);
}
(file, sb) = mktmpfile(sys->fildes(0));
}