summaryrefslogtreecommitdiff
path: root/appl/cmd/auth/passwd.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/auth/passwd.b')
-rw-r--r--appl/cmd/auth/passwd.b290
1 files changed, 290 insertions, 0 deletions
diff --git a/appl/cmd/auth/passwd.b b/appl/cmd/auth/passwd.b
new file mode 100644
index 00000000..d10b5c95
--- /dev/null
+++ b/appl/cmd/auth/passwd.b
@@ -0,0 +1,290 @@
+implement Passwd;
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "keyring.m";
+ kr: Keyring;
+
+include "security.m";
+ auth: Auth;
+
+include "arg.m";
+
+Passwd: module
+{
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+stderr, stdin, stdout: ref Sys->FD;
+keysrv := "/mnt/keysrv";
+signer := "$SIGNER";
+
+usage()
+{
+ sys->fprint(sys->fildes(2), "usage: passwd [-u user] [-s signer] [keyfile]\n");
+ raise "fail:usage";
+}
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+
+ stdin = sys->fildes(0);
+ stdout = sys->fildes(1);
+ stderr = sys->fildes(2);
+
+ kr = load Keyring Keyring->PATH;
+ if(kr == nil)
+ noload(Keyring->PATH);
+ auth = load Auth Auth->PATH;
+ if(auth == nil)
+ noload(Auth->PATH);
+ auth->init();
+
+ keyfile, id: string;
+ arg := load Arg Arg->PATH;
+ if(arg == nil)
+ noload(Arg->PATH);
+ arg->init(args);
+ while((o := arg->opt()) != 0)
+ case o {
+ 's' =>
+ signer = arg->arg();
+ 'u' =>
+ id = arg->arg();
+ * =>
+ usage();
+ }
+ args = arg->argv();
+ arg = nil;
+
+ if(args == nil)
+ args = "default" :: nil;
+
+ if(id == nil)
+ id= user();
+
+ if(args != nil)
+ keyfile = hd args;
+ else
+ keyfile = "default";
+ if(len keyfile > 0 && keyfile[0] != '/')
+ keyfile = "/usr/" + id + "/keyring/" + keyfile;
+
+ ai := kr->readauthinfo(keyfile);
+ if(ai == nil)
+ err(sys->sprint("can't read certificate from %s: %r", keyfile));
+sys->print("key owner: %s\n", ai.mypk.owner);
+
+ sys->pctl(Sys->FORKNS|Sys->FORKFD, nil);
+ remid := mountsrv(ai);
+
+ # get password
+ ok: int;
+ secret: array of byte;
+ oldhash: array of byte;
+ word: string;
+ for(;;){
+ sys->print("Inferno secret: ");
+ (ok, word) = readline(stdin, "rawon");
+ if(!ok || word == nil)
+ exit;
+ secret = array of byte word;
+ (nil, s) := hashkey(secret);
+ for(i := 0; i < len word; i++)
+ word[i] = ' ';
+ oldhash = array of byte s;
+ e := putsecret(oldhash, nil);
+ if(e != "wrong secret"){
+ if(e == nil)
+ break;
+ err(e);
+ }
+ sys->fprint(stderr, "!wrong secret\n");
+ }
+ newsecret: array of byte;
+ for(;;){
+ for(;;){
+ sys->print("new secret [default = don't change]: ");
+ (ok, word) = readline(stdin, "rawon");
+ if(!ok)
+ exit;
+ if(word == "" && secret != nil)
+ break;
+ if(len word >= 8)
+ break;
+ sys->print("!secret must be at least 8 characters\n");
+ }
+ if(word != ""){
+ # confirm password change
+ word1 := word;
+ sys->print("confirm: ");
+ (ok, word) = readline(stdin, "rawon");
+ if(!ok || word != word1){
+ sys->fprint(stderr, "!entries didn't match\n");
+ continue;
+ }
+ # TO DO...
+ #pwbuf := array of byte word;
+ #newsecret = array[Keyring->SHA1dlen] of byte;
+ #kr->sha1(pwbuf, len pwbuf, newsecret, nil);
+ newsecret = array of byte word;
+ }
+ if(!eq(newsecret, secret)){
+ if((e := putsecret(oldhash, newsecret)) != nil){
+ sys->fprint(stderr, "passwd: can't update secret for %s: %s\n", id, e);
+ continue;
+ }
+ }
+ break;
+ }
+}
+
+noload(s: string)
+{
+ err(sys->sprint("can't load %s: %r", s));
+}
+
+err(s: string)
+{
+ sys->fprint(sys->fildes(2), "passwd: %s\n", s);
+ raise "fail:error";
+}
+
+mountsrv(ai: ref Keyring->Authinfo): string
+{
+ (rc, c) := sys->dial(netmkaddr(signer, "net", "infkey"), nil);
+ if(rc < 0)
+ err(sys->sprint("can't dial %s: %r", signer));
+ (fd, id_or_err) := auth->client("sha1/rc4_256", ai, c.dfd);
+ if(fd == nil)
+ err(sys->sprint("can't authenticate with %s: %r", signer));
+ if(sys->mount(fd, nil, keysrv, Sys->MREPL, nil) < 0)
+ err(sys->sprint("can't mount %s on %s: %r", signer, keysrv));
+ return id_or_err;
+}
+
+user(): string
+{
+ fd := sys->open("/dev/user", Sys->OREAD);
+ if(fd == nil)
+ err(sys->sprint("can't open /dev/user: %r"));
+
+ buf := array[Sys->NAMEMAX] of byte;
+ n := sys->read(fd, buf, len buf);
+ if(n < 0)
+ err(sys->sprint("error reading /dev/user: %r"));
+
+ return string buf[0:n];
+}
+
+eq(a, b: array of byte): int
+{
+ if(len a != len b)
+ return 0;
+ for(i := 0; i < len a; i++)
+ if(a[i] != b[i])
+ return 0;
+ return 1;
+}
+
+hashkey(a: array of byte): (array of byte, string)
+{
+ hash := array[Keyring->SHA1dlen] of byte;
+ kr->sha1(a, len a, hash, nil);
+ s := "";
+ for(i := 0; i < len hash; i++)
+ s += sys->sprint("%2.2ux", int hash[i]);
+ return (hash, s);
+}
+
+putsecret(oldhash: array of byte, secret: array of byte): string
+{
+ fd := sys->create(keysrv+"/secret", Sys->OWRITE, 8r600);
+ if(fd == nil)
+ return sys->sprint("%r");
+ n := len oldhash;
+ if(secret != nil)
+ n += 1 + len secret;
+ buf := array[n] of byte;
+ buf[0:] = oldhash;
+ if(secret != nil){
+ buf[len oldhash] = byte ' ';
+ buf[len oldhash+1:] = secret;
+ }
+ if(sys->write(fd, buf, len buf) < 0)
+ return sys->sprint("%r");
+ return nil;
+}
+
+netmkaddr(addr, net, svc: string): string
+{
+ if(net == nil)
+ net = "net";
+ (n, l) := 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);
+}
+
+readline(io: ref Sys->FD, mode: string): (int, string)
+{
+ r : int;
+ line : string;
+ buf := array[8192] of byte;
+ fdctl : ref Sys->FD;
+ rawoff := array of byte "rawoff";
+
+ if(mode == "rawon"){
+ fdctl = sys->open("/dev/consctl", sys->OWRITE);
+ if(fdctl == nil || sys->write(fdctl,array of byte mode,len mode) != len mode){
+ sys->fprint(stderr, "unable to change console mode");
+ return (0,nil);
+ }
+ }
+
+ line = "";
+ for(;;) {
+ r = sys->read(io, buf, len buf);
+ if(r <= 0){
+ sys->fprint(stderr, "error read from console mode");
+ if(mode == "rawon")
+ sys->write(fdctl,rawoff,6);
+ return (0, nil);
+ }
+
+ line += string buf[0:r];
+ if ((len line >= 1) && (line[(len line)-1] == '\n')){
+ if(mode == "rawon"){
+ r = sys->write(stdout,array of byte "\n",1);
+ if(r <= 0) {
+ sys->write(fdctl,rawoff,6);
+ return (0, nil);
+ }
+ }
+ break;
+ }
+ else {
+ if(mode == "rawon"){
+ #r = sys->write(stdout, array of byte "*",1);
+ if(r <= 0) {
+ sys->write(fdctl,rawoff,6);
+ return (0, nil);
+ }
+ }
+ }
+ }
+
+ if(mode == "rawon")
+ sys->write(fdctl,rawoff,6);
+
+ return (1, line[0:len line - 1]);
+}