rsc | 57fcfc2 | 2005-02-13 18:04:20 +0000 | [diff] [blame] | 1 | #include <u.h> |
| 2 | #include <libc.h> |
| 3 | #include <libsec.h> |
| 4 | #include <authsrv.h> |
| 5 | |
| 6 | static char *pbmsg = "AS protocol botch"; |
| 7 | |
| 8 | int |
| 9 | asrdresp(int fd, char *buf, int len) |
| 10 | { |
| 11 | char error[AERRLEN]; |
| 12 | |
| 13 | if(read(fd, buf, 1) != 1){ |
| 14 | werrstr(pbmsg); |
| 15 | return -1; |
| 16 | } |
| 17 | |
| 18 | switch(buf[0]){ |
| 19 | case AuthOK: |
| 20 | if(readn(fd, buf, len) < 0){ |
| 21 | werrstr(pbmsg); |
| 22 | return -1; |
| 23 | } |
| 24 | break; |
| 25 | case AuthErr: |
| 26 | if(readn(fd, error, AERRLEN) < 0){ |
| 27 | werrstr(pbmsg); |
| 28 | return -1; |
| 29 | } |
| 30 | error[AERRLEN-1] = 0; |
| 31 | werrstr(error); |
| 32 | return -1; |
| 33 | default: |
| 34 | werrstr(pbmsg); |
| 35 | return -1; |
| 36 | } |
| 37 | return 0; |
| 38 | } |
| 39 | |
| 40 | void |
| 41 | readln(char *prompt, char *buf, int nbuf, int secret) |
| 42 | { |
| 43 | char *p; |
| 44 | |
| 45 | p = readcons(prompt, nil, secret); |
| 46 | if(p == nil) |
| 47 | sysfatal("user terminated input"); |
| 48 | if(strlen(p) >= nbuf) |
| 49 | sysfatal("too long"); |
| 50 | strcpy(buf, p); |
| 51 | memset(p, 0, strlen(p)); |
| 52 | free(p); |
| 53 | } |
| 54 | |
| 55 | void |
| 56 | main(int argc, char **argv) |
| 57 | { |
| 58 | int fd; |
| 59 | Ticketreq tr; |
| 60 | Ticket t; |
| 61 | Passwordreq pr; |
| 62 | char tbuf[TICKETLEN]; |
| 63 | char key[DESKEYLEN]; |
| 64 | char buf[512]; |
| 65 | char *s, *user; |
| 66 | |
| 67 | user = getuser(); |
| 68 | |
| 69 | ARGBEGIN{ |
| 70 | }ARGEND |
| 71 | |
| 72 | s = nil; |
| 73 | if(argc > 0){ |
| 74 | user = argv[0]; |
| 75 | s = strchr(user, '@'); |
| 76 | if(s != nil) |
| 77 | *s++ = 0; |
| 78 | if(*user == 0) |
| 79 | user = getuser(); |
| 80 | } |
| 81 | |
| 82 | fd = authdial(nil, s); |
| 83 | if(fd < 0) |
| 84 | sysfatal("protocol botch: %r"); |
| 85 | |
| 86 | /* send ticket request to AS */ |
| 87 | memset(&tr, 0, sizeof(tr)); |
| 88 | strcpy(tr.uid, user); |
| 89 | tr.type = AuthPass; |
| 90 | convTR2M(&tr, buf); |
| 91 | if(write(fd, buf, TICKREQLEN) != TICKREQLEN) |
| 92 | sysfatal("protocol botch: %r"); |
| 93 | if(asrdresp(fd, buf, TICKETLEN) < 0) |
| 94 | sysfatal("%r"); |
| 95 | memmove(tbuf, buf, TICKETLEN); |
| 96 | |
| 97 | /* |
| 98 | * get a password from the user and try to decrypt the |
| 99 | * ticket. If it doesn't work we've got a bad password, |
| 100 | * give up. |
| 101 | */ |
| 102 | readln("Plan 9 Password", pr.old, sizeof pr.old, 1); |
| 103 | passtokey(key, pr.old); |
| 104 | convM2T(tbuf, &t, key); |
| 105 | if(t.num != AuthTp || strcmp(t.cuid, tr.uid)) |
| 106 | sysfatal("bad password"); |
| 107 | |
| 108 | /* loop trying new passwords */ |
| 109 | for(;;){ |
| 110 | pr.changesecret = 0; |
| 111 | *pr.new = 0; |
| 112 | readln("change Plan 9 Password? (y/n)", buf, sizeof buf, 0); |
| 113 | if(*buf == 'y' || *buf == 'Y'){ |
| 114 | readln("Password(8 to 31 characters)", pr.new, |
| 115 | sizeof pr.new, 1); |
| 116 | readln("Confirm", buf, sizeof buf, 1); |
| 117 | if(strcmp(pr.new, buf)){ |
| 118 | print("!mismatch\n"); |
| 119 | continue; |
| 120 | } |
| 121 | } |
| 122 | readln("change Inferno/POP password? (y/n)", buf, sizeof buf, 0); |
| 123 | if(*buf == 'y' || *buf == 'Y'){ |
| 124 | pr.changesecret = 1; |
| 125 | readln("make it the same as your plan 9 password? (y/n)", |
| 126 | buf, sizeof buf, 0); |
| 127 | if(*buf == 'y' || *buf == 'Y'){ |
| 128 | if(*pr.new == 0) |
| 129 | strcpy(pr.secret, pr.old); |
| 130 | else |
| 131 | strcpy(pr.secret, pr.new); |
| 132 | } else { |
| 133 | readln("Secret(0 to 256 characters)", pr.secret, |
| 134 | sizeof pr.secret, 1); |
| 135 | readln("Confirm", buf, sizeof buf, 1); |
| 136 | if(strcmp(pr.secret, buf)){ |
| 137 | print("!mismatch\n"); |
| 138 | continue; |
| 139 | } |
| 140 | } |
| 141 | } |
| 142 | pr.num = AuthPass; |
| 143 | convPR2M(&pr, buf, t.key); |
| 144 | if(write(fd, buf, PASSREQLEN) != PASSREQLEN) |
| 145 | sysfatal("AS protocol botch: %r"); |
| 146 | if(asrdresp(fd, buf, 0) == 0) |
| 147 | break; |
| 148 | fprint(2, "refused: %r\n"); |
| 149 | } |
| 150 | close(fd); |
| 151 | |
| 152 | exits(0); |
| 153 | } |