diff options
Diffstat (limited to 'appl/cmd/auth/convpasswd.b')
| -rw-r--r-- | appl/cmd/auth/convpasswd.b | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/appl/cmd/auth/convpasswd.b b/appl/cmd/auth/convpasswd.b new file mode 100644 index 00000000..8463b0fb --- /dev/null +++ b/appl/cmd/auth/convpasswd.b @@ -0,0 +1,120 @@ +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; +} |
