1*219b2ee8SDavid du Colombier #include <u.h> 2*219b2ee8SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <auth.h> 4*219b2ee8SDavid du Colombier #include <ctype.h> 5*219b2ee8SDavid du Colombier #include "authsrv.h" 6*219b2ee8SDavid du Colombier 7*219b2ee8SDavid du Colombier 8*219b2ee8SDavid du Colombier void install(char*, char*, char*, long, int); 9*219b2ee8SDavid du Colombier int exists (char*, char*); 10*219b2ee8SDavid du Colombier long getexpiration(char *db, char *u); 11*219b2ee8SDavid du Colombier Tm getdate(char*); 12*219b2ee8SDavid du Colombier 13*219b2ee8SDavid du Colombier void 14*219b2ee8SDavid du Colombier usage(void) 15*219b2ee8SDavid du Colombier { 16*219b2ee8SDavid du Colombier fprint(2, "usage: changeuser [-hpn] user\n"); 17*219b2ee8SDavid du Colombier exits("usage"); 18*219b2ee8SDavid du Colombier } 19*219b2ee8SDavid du Colombier 20*219b2ee8SDavid du Colombier void 21*219b2ee8SDavid du Colombier main(int argc, char *argv[]) 22*219b2ee8SDavid du Colombier { 23*219b2ee8SDavid du Colombier char *u, key[DESKEYLEN], answer[32]; 24*219b2ee8SDavid du Colombier int which, i, newkey, newbio; 25*219b2ee8SDavid du Colombier long t; 26*219b2ee8SDavid du Colombier Acctbio a; 27*219b2ee8SDavid du Colombier Fs *f; 28*219b2ee8SDavid du Colombier 29*219b2ee8SDavid du Colombier srand(getpid()*time(0)); 30*219b2ee8SDavid du Colombier fmtinstall('K', keyconv); 31*219b2ee8SDavid du Colombier 32*219b2ee8SDavid du Colombier which = 0; 33*219b2ee8SDavid du Colombier ARGBEGIN{ 34*219b2ee8SDavid du Colombier case 'p': 35*219b2ee8SDavid du Colombier which |= Plan9; 36*219b2ee8SDavid du Colombier break; 37*219b2ee8SDavid du Colombier case 'n': 38*219b2ee8SDavid du Colombier which |= Securenet; 39*219b2ee8SDavid du Colombier break; 40*219b2ee8SDavid du Colombier default: 41*219b2ee8SDavid du Colombier usage(); 42*219b2ee8SDavid du Colombier }ARGEND 43*219b2ee8SDavid du Colombier argv0 = "changeuser"; 44*219b2ee8SDavid du Colombier 45*219b2ee8SDavid du Colombier if(argc != 1) 46*219b2ee8SDavid du Colombier usage(); 47*219b2ee8SDavid du Colombier u = *argv; 48*219b2ee8SDavid du Colombier if(memchr(u, '\0', NAMELEN) == 0) 49*219b2ee8SDavid du Colombier error("bad user name"); 50*219b2ee8SDavid du Colombier 51*219b2ee8SDavid du Colombier if(!which) 52*219b2ee8SDavid du Colombier which = Plan9; 53*219b2ee8SDavid du Colombier 54*219b2ee8SDavid du Colombier newbio = 0; 55*219b2ee8SDavid du Colombier t = 0; 56*219b2ee8SDavid du Colombier a.user = 0; 57*219b2ee8SDavid du Colombier if(which & Plan9){ 58*219b2ee8SDavid du Colombier f = &fs[Plan9]; 59*219b2ee8SDavid du Colombier newkey = 1; 60*219b2ee8SDavid du Colombier if(exists(f->keys, u)){ 61*219b2ee8SDavid du Colombier readln("assign new password? [y/n]: ", answer, sizeof answer, 0); 62*219b2ee8SDavid du Colombier if(answer[0] != 'y' && answer[0] != 'Y') 63*219b2ee8SDavid du Colombier newkey = 0; 64*219b2ee8SDavid du Colombier } 65*219b2ee8SDavid du Colombier if(newkey) 66*219b2ee8SDavid du Colombier getpass(key, 1); 67*219b2ee8SDavid du Colombier t = getexpiration(f->keys, u); 68*219b2ee8SDavid du Colombier install(f->keys, u, key, t, newkey); 69*219b2ee8SDavid du Colombier newbio = querybio(f->who, u, &a); 70*219b2ee8SDavid du Colombier if(newbio) 71*219b2ee8SDavid du Colombier wrbio(f->who, &a); 72*219b2ee8SDavid du Colombier print("user %s installed for Plan 9\n", u); 73*219b2ee8SDavid du Colombier syslog(0, AUTHLOG, "user %s installed for plan 9", u); 74*219b2ee8SDavid du Colombier } 75*219b2ee8SDavid du Colombier if(which & Securenet){ 76*219b2ee8SDavid du Colombier f = &fs[Securenet]; 77*219b2ee8SDavid du Colombier newkey = 1; 78*219b2ee8SDavid du Colombier if(exists(f->keys, u)){ 79*219b2ee8SDavid du Colombier readln("assign new key? [y/n]: ", answer, sizeof answer, 0); 80*219b2ee8SDavid du Colombier if(answer[0] != 'y' && answer[0] != 'Y') 81*219b2ee8SDavid du Colombier newkey = 0; 82*219b2ee8SDavid du Colombier } 83*219b2ee8SDavid du Colombier if(newkey) 84*219b2ee8SDavid du Colombier for(i=0; i<DESKEYLEN; i++) 85*219b2ee8SDavid du Colombier key[i] = nrand(256); 86*219b2ee8SDavid du Colombier if(a.user == 0){ 87*219b2ee8SDavid du Colombier t = getexpiration(f->keys, u); 88*219b2ee8SDavid du Colombier newbio = querybio(f->who, u, &a); 89*219b2ee8SDavid du Colombier } 90*219b2ee8SDavid du Colombier install(f->keys, u, key, t, newkey); 91*219b2ee8SDavid du Colombier if(newbio) 92*219b2ee8SDavid du Colombier wrbio(f->who, &a); 93*219b2ee8SDavid du Colombier findkey(f->keys, u, key); 94*219b2ee8SDavid du Colombier print("user %s: SecureNet key: %K\n", u, key); 95*219b2ee8SDavid du Colombier checksum(key, answer); 96*219b2ee8SDavid du Colombier print("verify with checksum %s\n", answer); 97*219b2ee8SDavid du Colombier print("user %s installed for SecureNet\n", u); 98*219b2ee8SDavid du Colombier syslog(0, AUTHLOG, "user %s installed for securenet", u); 99*219b2ee8SDavid du Colombier } 100*219b2ee8SDavid du Colombier exits(0); 101*219b2ee8SDavid du Colombier } 102*219b2ee8SDavid du Colombier 103*219b2ee8SDavid du Colombier void 104*219b2ee8SDavid du Colombier install(char *db, char *u, char *key, long t, int newkey) 105*219b2ee8SDavid du Colombier { 106*219b2ee8SDavid du Colombier char buf[KEYDBBUF+NAMELEN+6]; 107*219b2ee8SDavid du Colombier int fd; 108*219b2ee8SDavid du Colombier 109*219b2ee8SDavid du Colombier if(!exists(db, u)){ 110*219b2ee8SDavid du Colombier sprint(buf, "%s/%s", db, u); 111*219b2ee8SDavid du Colombier fd = create(buf, OREAD, 0777|CHDIR); 112*219b2ee8SDavid du Colombier if(fd < 0) 113*219b2ee8SDavid du Colombier error("can't create user %s: %r", u); 114*219b2ee8SDavid du Colombier close(fd); 115*219b2ee8SDavid du Colombier } 116*219b2ee8SDavid du Colombier 117*219b2ee8SDavid du Colombier if(newkey){ 118*219b2ee8SDavid du Colombier sprint(buf, "%s/%s/key", db, u); 119*219b2ee8SDavid du Colombier fd = open(buf, OWRITE); 120*219b2ee8SDavid du Colombier if(fd < 0 || write(fd, key, DESKEYLEN) != DESKEYLEN) 121*219b2ee8SDavid du Colombier error("can't set key: %r"); 122*219b2ee8SDavid du Colombier close(fd); 123*219b2ee8SDavid du Colombier } 124*219b2ee8SDavid du Colombier 125*219b2ee8SDavid du Colombier if(t == 0) 126*219b2ee8SDavid du Colombier return; 127*219b2ee8SDavid du Colombier sprint(buf, "%s/%s/expire", db, u); 128*219b2ee8SDavid du Colombier fd = open(buf, OWRITE); 129*219b2ee8SDavid du Colombier if(fd < 0 || fprint(fd, "%d", t) < 0) 130*219b2ee8SDavid du Colombier error("can't write expiration time"); 131*219b2ee8SDavid du Colombier close(fd); 132*219b2ee8SDavid du Colombier } 133*219b2ee8SDavid du Colombier 134*219b2ee8SDavid du Colombier int 135*219b2ee8SDavid du Colombier exists(char *db, char *u) 136*219b2ee8SDavid du Colombier { 137*219b2ee8SDavid du Colombier char buf[KEYDBBUF+NAMELEN+6]; 138*219b2ee8SDavid du Colombier 139*219b2ee8SDavid du Colombier sprint(buf, "%s/%s/expire", db, u); 140*219b2ee8SDavid du Colombier if(access(buf, OREAD) < 0) 141*219b2ee8SDavid du Colombier return 0; 142*219b2ee8SDavid du Colombier return 1; 143*219b2ee8SDavid du Colombier } 144*219b2ee8SDavid du Colombier 145*219b2ee8SDavid du Colombier /* 146*219b2ee8SDavid du Colombier * get the date in the format yyyymmdd 147*219b2ee8SDavid du Colombier */ 148*219b2ee8SDavid du Colombier Tm 149*219b2ee8SDavid du Colombier getdate(char *d) 150*219b2ee8SDavid du Colombier { 151*219b2ee8SDavid du Colombier Tm date; 152*219b2ee8SDavid du Colombier int i; 153*219b2ee8SDavid du Colombier 154*219b2ee8SDavid du Colombier date.year = date.mon = date.mday = 0; 155*219b2ee8SDavid du Colombier date.hour = date.min = date.sec = 0; 156*219b2ee8SDavid du Colombier for(i = 0; i < 8; i++) 157*219b2ee8SDavid du Colombier if(!isdigit(d[i])) 158*219b2ee8SDavid du Colombier return date; 159*219b2ee8SDavid du Colombier date.year = (d[0]-'0')*1000 + (d[1]-'0')*100 + (d[2]-'0')*10 + d[3]-'0'; 160*219b2ee8SDavid du Colombier date.year -= 1900; 161*219b2ee8SDavid du Colombier d += 4; 162*219b2ee8SDavid du Colombier date.mon = (d[0]-'0')*10 + d[1]-'0'; 163*219b2ee8SDavid du Colombier d += 2; 164*219b2ee8SDavid du Colombier date.mday = (d[0]-'0')*10 + d[1]-'0'; 165*219b2ee8SDavid du Colombier return date; 166*219b2ee8SDavid du Colombier } 167*219b2ee8SDavid du Colombier 168*219b2ee8SDavid du Colombier long 169*219b2ee8SDavid du Colombier getexpiration(char *db, char *u) 170*219b2ee8SDavid du Colombier { 171*219b2ee8SDavid du Colombier char buf[32]; 172*219b2ee8SDavid du Colombier char prompt[128]; 173*219b2ee8SDavid du Colombier char cdate[32]; 174*219b2ee8SDavid du Colombier Tm date; 175*219b2ee8SDavid du Colombier ulong secs, now, fd; 176*219b2ee8SDavid du Colombier int n; 177*219b2ee8SDavid du Colombier 178*219b2ee8SDavid du Colombier /* read current expiration (if any) */ 179*219b2ee8SDavid du Colombier sprint(buf, "%s/%s/expire", db, u); 180*219b2ee8SDavid du Colombier fd = open(buf, OREAD); 181*219b2ee8SDavid du Colombier buf[0] = 0; 182*219b2ee8SDavid du Colombier if(fd >= 0){ 183*219b2ee8SDavid du Colombier n = read(fd, buf, sizeof(buf)-1); 184*219b2ee8SDavid du Colombier if(n > 0) 185*219b2ee8SDavid du Colombier buf[n-1] = 0; 186*219b2ee8SDavid du Colombier close(fd); 187*219b2ee8SDavid du Colombier } 188*219b2ee8SDavid du Colombier secs = 0; 189*219b2ee8SDavid du Colombier if(buf[0]){ 190*219b2ee8SDavid du Colombier if(strncmp(buf, "never", 5)){ 191*219b2ee8SDavid du Colombier secs = atoi(buf); 192*219b2ee8SDavid du Colombier memmove(&date, localtime(secs), sizeof(date)); 193*219b2ee8SDavid du Colombier sprint(buf, "%4.4d%2.2d%2.2d", date.year+1900, date.mon, date.mday); 194*219b2ee8SDavid du Colombier } else 195*219b2ee8SDavid du Colombier buf[5] = 0; 196*219b2ee8SDavid du Colombier } else 197*219b2ee8SDavid du Colombier strcpy(buf, "never"); 198*219b2ee8SDavid du Colombier sprint(prompt, "Expiration date (YYYYMMDD or never)[return = %s]: ", buf); 199*219b2ee8SDavid du Colombier 200*219b2ee8SDavid du Colombier now = time(0); 201*219b2ee8SDavid du Colombier for(;;){ 202*219b2ee8SDavid du Colombier readln(prompt, cdate, sizeof cdate, 0); 203*219b2ee8SDavid du Colombier if(*cdate == 0) 204*219b2ee8SDavid du Colombier return secs; 205*219b2ee8SDavid du Colombier if(strcmp(cdate, "never") == 0) 206*219b2ee8SDavid du Colombier return 0; 207*219b2ee8SDavid du Colombier date = getdate(cdate); 208*219b2ee8SDavid du Colombier secs = tm2sec(date); 209*219b2ee8SDavid du Colombier if(secs > now && secs < now + 2*365*24*60*60) 210*219b2ee8SDavid du Colombier break; 211*219b2ee8SDavid du Colombier print("expiration time must fall between now and 2 years from now\n"); 212*219b2ee8SDavid du Colombier } 213*219b2ee8SDavid du Colombier return secs; 214*219b2ee8SDavid du Colombier } 215