ref: d0ab3a0dd8f6355b3603d0fb04043a9ae867639b
dir: /appl/cmd/auth/convpasswd.b/
implement Convpasswd;
include "sys.m";
sys: Sys;
include "draw.m";
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "keyring.m";
keyring: Keyring;
IPint: import keyring;
include "security.m";
include "arg.m";
Convpasswd: module
{
init: fn(nil: ref Draw->Context, nil: list of string);
};
PW: adt {
id: string; # user id
pw: array of byte; # password hashed by SHA
expire: int; # expiration time (epoch seconds)
other: string; # about the account
};
mntpt := "/mnt/keys";
init(nil: ref Draw->Context, args: list of string)
{
sys = load Sys Sys->PATH;
keyring = load Keyring Keyring->PATH;
bufio = load Bufio Bufio->PATH;
if(bufio == nil)
noload(Arg->PATH);
arg := load Arg Arg->PATH;
if(arg == nil)
noload(Arg->PATH);
force := 0;
verbose := 0;
arg->init(args);
arg->setusage("convpasswd [-f] [-v] [-m /mnt/keys] [passwordfile]");
while((o := arg->opt()) != 0)
case o {
'f' => force = 1;
'm' => mntpt = arg->earg();
'v' => verbose = 1;
* => arg->usage();
}
args = arg->argv();
arg = nil;
f := "/keydb/password";
if(args != nil)
f = hd args;
iob := bufio->open(f, Bufio->OREAD);
if(iob == nil)
error(sys->sprint("%s: %r", f));
for(line := 1; (s := iob.gets('\n')) != nil; line++) {
(n, tokl) := sys->tokenize(s, ":\n");
if (n < 3){
sys->fprint(sys->fildes(2), "convpasswd: %s:%d: invalid format\n", f, line);
continue;
}
pw := ref PW;
pw.id = hd tokl;
pw.pw = IPint.b64toip(hd tl tokl).iptobytes();
pw.expire = int hd tl tl tokl;
if (n==3)
pw.other = nil;
else
pw.other = hd tl tl tl tokl;
err := writekey(pw, force);
if(err != nil)
error(sys->sprint("error writing /mnt/keys entry for %s: %s", pw.id, err));
if(verbose)
sys->print("%s\n", pw.id);
}
}
noload(p: string)
{
error(sys->sprint("can't load %s: %r", p));
}
error(s: string)
{
sys->fprint(sys->fildes(2), "convpasswd: %s\n", s);
raise "fail:error";
}
writekey(pw: ref PW, force: int): string
{
dir := mntpt+"/"+pw.id;
if(sys->open(dir, Sys->OREAD) == nil){
# make it
d := sys->create(dir, Sys->OREAD, Sys->DMDIR|8r600);
if(d == nil)
return sys->sprint("can't create %s: %r", dir);
}else if(!force)
return nil; # leave existing entry alone
secret := dir+"/secret";
fd := sys->open(secret, Sys->OWRITE);
if(fd == nil)
return sys->sprint("can't open %s: %r", secret);
if(sys->write(fd, pw.pw, len pw.pw) != len pw.pw)
return sys->sprint("error writing %s: %r", secret);
expire := dir+"/expire";
fd = sys->open(expire, Sys->OWRITE);
if(fd == nil)
return sys->sprint("can't open %s: %r", expire);
if(sys->fprint(fd, "%d", pw.expire) < 0)
return sys->sprint("error writing %s: %r", expire);
# no equivalent of `other'
return nil;
}