implement Iauth;
include "sys.m";
sys: Sys;
include "draw.m";
include "keyring.m";
include "security.m";
ssl: SSL;
include "factotum.m";
factotum: Factotum;
include "sexprs.m";
sexprs: Sexprs;
Sexp: import sexprs;
include "styx.m";
include "iauth.m";
init()
{
sys = load Sys Sys->PATH;
sexprs = load Sexprs Sexprs->PATH;
sexprs->init();
factotum = load Factotum Factotum->PATH;
factotum->init();
ssl = load SSL SSL->PATH;
}
auth(keyspec: string, fd: ref Sys->FD, setid: int): (ref Sys->FD, string)
{
info := factotum->proxy(fd, sys->open("/mnt/factotum/rpc", Sys->ORDWR), "proto=infauth "+keyspec);
if(info == nil)
return (nil, sys->sprint("factotum auth failed: %r"));
(se, nil, err) := Sexp.unpack(info.secret);
if(se == nil)
return (nil, "bad authinfo: "+err);
if(setid){
if(info.cap == nil)
return (nil, "no capability to set user id");
cfd := sys->open("#¤/capuse", Sys->OWRITE);
if(cfd == nil)
return (nil, sys->sprint("cannot open #¤/capuse: %r"));
if(sys->fprint(cfd, "%s", info.cap) == -1)
return (nil, sys->sprint("cannot use capability: %r"));
}
secret: array of byte;
alg: string;
for(l := se.els(); l != nil; l = tl l){
case (hd l).op() {
"secret" =>
secret = onearg(hd l).asdata();
"alg" =>
alg = onearg(hd l).astext();
}
}
if(alg == "none" || alg == nil)
return (fd, info.suid);
return (pushssl(fd, secret, alg), info.suid);
}
mount(addr, old: string, flag: int, aname: string, keyspec: string): (int, string)
{
# if(sys->stat(old).t0 == -1)
# return (-1, sys->sprint("cannot stat mountpoint %q: %r", old));
addr = netmkaddr(addr, "net", "styx");
(ok, c) := sys->dial(addr, nil);
if(ok == -1)
return (-1, sys->sprint("cannot dial %q: %r", addr));
user := "none";
if((flag & MNOAUTH) == 0){
(c.dfd, user) = auth("role=client "+keyspec, c.dfd, 0);
if(c.dfd == nil)
return (-1, user);
}
flag &= ~MNOAUTH;
if(sys->mount(c.dfd, nil, old, flag, aname) == -1)
return (-1, sys->sprint("mount failed: %r"));
return (0, user);
}
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);
}
pushssl(fd: ref Sys->FD, secret: array of byte, alg: string): ref Sys->FD
{
(err, c) := ssl->connect(fd);
if(err != nil){
sys->werrstr("ssl connect failed: "+err);
return nil;
}
err = ssl->secret(c, secret, secret);
if(err != nil){
sys->werrstr("ssl set secret failed: "+err);
return nil;
}
if(sys->fprint(c.cfd, "alg %s", alg) < 0){
sys->werrstr(sys->sprint("ssl set algorithm failed: %r"));
return nil;
}
return c.dfd;
}
onearg(se: ref Sexp): ref Sexp
{
a := se.args();
if(a != nil)
return hd a;
return nil;
}
|