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; }