diff options
author | rsc <devnull@localhost> | 2005-02-13 18:04:20 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-02-13 18:04:20 +0000 |
commit | 57fcfc2a0b8ecd266ce130dab9a29b7ceb558d64 (patch) | |
tree | 2d7dc505e9bda2e49efdc13ed459d7e2fad5f579 /src/cmd/auth/passwd.c | |
parent | ce94dbe662155bd60d6839b5e8c82ad708667bcd (diff) | |
download | plan9port-57fcfc2a0b8ecd266ce130dab9a29b7ceb558d64.tar.gz plan9port-57fcfc2a0b8ecd266ce130dab9a29b7ceb558d64.tar.bz2 plan9port-57fcfc2a0b8ecd266ce130dab9a29b7ceb558d64.zip |
add others
Diffstat (limited to 'src/cmd/auth/passwd.c')
-rw-r--r-- | src/cmd/auth/passwd.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/cmd/auth/passwd.c b/src/cmd/auth/passwd.c new file mode 100644 index 00000000..da23638f --- /dev/null +++ b/src/cmd/auth/passwd.c @@ -0,0 +1,153 @@ +#include <u.h> +#include <libc.h> +#include <libsec.h> +#include <authsrv.h> + +static char *pbmsg = "AS protocol botch"; + +int +asrdresp(int fd, char *buf, int len) +{ + char error[AERRLEN]; + + if(read(fd, buf, 1) != 1){ + werrstr(pbmsg); + return -1; + } + + switch(buf[0]){ + case AuthOK: + if(readn(fd, buf, len) < 0){ + werrstr(pbmsg); + return -1; + } + break; + case AuthErr: + if(readn(fd, error, AERRLEN) < 0){ + werrstr(pbmsg); + return -1; + } + error[AERRLEN-1] = 0; + werrstr(error); + return -1; + default: + werrstr(pbmsg); + return -1; + } + return 0; +} + +void +readln(char *prompt, char *buf, int nbuf, int secret) +{ + char *p; + + p = readcons(prompt, nil, secret); + if(p == nil) + sysfatal("user terminated input"); + if(strlen(p) >= nbuf) + sysfatal("too long"); + strcpy(buf, p); + memset(p, 0, strlen(p)); + free(p); +} + +void +main(int argc, char **argv) +{ + int fd; + Ticketreq tr; + Ticket t; + Passwordreq pr; + char tbuf[TICKETLEN]; + char key[DESKEYLEN]; + char buf[512]; + char *s, *user; + + user = getuser(); + + ARGBEGIN{ + }ARGEND + + s = nil; + if(argc > 0){ + user = argv[0]; + s = strchr(user, '@'); + if(s != nil) + *s++ = 0; + if(*user == 0) + user = getuser(); + } + + fd = authdial(nil, s); + if(fd < 0) + sysfatal("protocol botch: %r"); + + /* send ticket request to AS */ + memset(&tr, 0, sizeof(tr)); + strcpy(tr.uid, user); + tr.type = AuthPass; + convTR2M(&tr, buf); + if(write(fd, buf, TICKREQLEN) != TICKREQLEN) + sysfatal("protocol botch: %r"); + if(asrdresp(fd, buf, TICKETLEN) < 0) + sysfatal("%r"); + memmove(tbuf, buf, TICKETLEN); + + /* + * get a password from the user and try to decrypt the + * ticket. If it doesn't work we've got a bad password, + * give up. + */ + readln("Plan 9 Password", pr.old, sizeof pr.old, 1); + passtokey(key, pr.old); + convM2T(tbuf, &t, key); + if(t.num != AuthTp || strcmp(t.cuid, tr.uid)) + sysfatal("bad password"); + + /* loop trying new passwords */ + for(;;){ + pr.changesecret = 0; + *pr.new = 0; + readln("change Plan 9 Password? (y/n)", buf, sizeof buf, 0); + if(*buf == 'y' || *buf == 'Y'){ + readln("Password(8 to 31 characters)", pr.new, + sizeof pr.new, 1); + readln("Confirm", buf, sizeof buf, 1); + if(strcmp(pr.new, buf)){ + print("!mismatch\n"); + continue; + } + } + readln("change Inferno/POP password? (y/n)", buf, sizeof buf, 0); + if(*buf == 'y' || *buf == 'Y'){ + pr.changesecret = 1; + readln("make it the same as your plan 9 password? (y/n)", + buf, sizeof buf, 0); + if(*buf == 'y' || *buf == 'Y'){ + if(*pr.new == 0) + strcpy(pr.secret, pr.old); + else + strcpy(pr.secret, pr.new); + } else { + readln("Secret(0 to 256 characters)", pr.secret, + sizeof pr.secret, 1); + readln("Confirm", buf, sizeof buf, 1); + if(strcmp(pr.secret, buf)){ + print("!mismatch\n"); + continue; + } + } + } + pr.num = AuthPass; + convPR2M(&pr, buf, t.key); + if(write(fd, buf, PASSREQLEN) != PASSREQLEN) + sysfatal("AS protocol botch: %r"); + if(asrdresp(fd, buf, 0) == 0) + break; + fprint(2, "refused: %r\n"); + } + close(fd); + + exits(0); +} |