From 096ff3e14a188992d2dfe59c7fd3f5d6da791331 Mon Sep 17 00:00:00 2001 From: rsc Date: Fri, 11 Feb 2005 19:39:51 +0000 Subject: add secstored; use readcons --- src/cmd/secstore/secuser.c | 244 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 src/cmd/secstore/secuser.c (limited to 'src/cmd/secstore/secuser.c') diff --git a/src/cmd/secstore/secuser.c b/src/cmd/secstore/secuser.c new file mode 100644 index 00000000..31ba184b --- /dev/null +++ b/src/cmd/secstore/secuser.c @@ -0,0 +1,244 @@ +#include +#include +#include +#include +#include "SConn.h" +#include "secstore.h" + +int verbose; + +static void userinput(char *, int); +char *SECSTORE_DIR; + +static void +ensure_exists(char *f, ulong perm) +{ + int fd; + + if(access(f, AEXIST) >= 0) + return; + if(verbose) + fprint(2,"first time setup for secstore: create %s %lo\n", f, perm); + fd = create(f, OREAD, perm); + if(fd < 0){ + fprint(2, "unable to create %s\n", f); + exits("secstored directories"); + } + close(fd); +} + + +int +main(int argc, char **argv) +{ + int isnew; + char *id, buf[Maxmsg], home[Maxmsg], prompt[100], *hexHi; + char *pass, *passck; + long expsecs; + mpint *H = mpnew(0), *Hi = mpnew(0); + PW *pw; + Tm *tm; + + SECSTORE_DIR = unsharp("#9/secstore"); + + ARGBEGIN{ + case 'v': + verbose++; + break; + }ARGEND; + if(argc!=1){ + print("usage: secuser [-v] \n"); + exits("usage"); + } + + ensure_exists(SECSTORE_DIR, DMDIR|0755L); + snprint(home, sizeof(home), "%s/who", SECSTORE_DIR); + ensure_exists(home, DMDIR|0755L); + snprint(home, sizeof(home), "%s/store", SECSTORE_DIR); + ensure_exists(home, DMDIR|0700L); + + id = argv[0]; + if(verbose) + fprint(2,"secuser %s\n", id); + if((pw = getPW(id,1)) == nil){ + isnew = 1; + print("new account (because %s/%s %r)\n", SECSTORE_DIR, id); + pw = emalloc(sizeof(*pw)); + pw->id = estrdup(id); + snprint(home, sizeof(home), "%s/store/%s", SECSTORE_DIR, id); + if(access(home, AEXIST) == 0){ + print("new user, but directory %s already exists\n", home); + exits(home); + } + }else{ + isnew = 0; + } + + /* get main password for id */ + for(;;){ + if(isnew) + snprint(prompt, sizeof(prompt), "%s password", id); + else + snprint(prompt, sizeof(prompt), "%s password [default = don't change]", id); + pass = readcons(prompt, nil, 1); + if(pass == nil){ + print("getpass failed\n"); + exits("getpass failed"); + } + if(verbose) + print("%ld characters\n", strlen(pass)); + if(pass[0] == '\0' && isnew == 0) + break; + if(strlen(pass) >= 7) + break; + print("password must be at least 7 characters\n"); + } + + if(pass[0] != '\0'){ + snprint(prompt, sizeof(prompt), "retype password"); + if(verbose) + print("confirming...\n"); + passck = readcons(prompt, nil, 1); + if(passck == nil){ + print("getpass failed\n"); + exits("getpass failed"); + } + if(strcmp(pass, passck) != 0){ + print("passwords didn't match\n"); + exits("no match"); + } + memset(passck, 0, strlen(passck)); + free(passck); + hexHi = PAK_Hi(id, pass, H, Hi); + memset(pass, 0, strlen(pass)); + free(pass); + free(hexHi); + mpfree(H); + pw->Hi = Hi; + } + + /* get expiration time (midnight of date specified) */ + if(isnew) + expsecs = time(0) + 365*24*60*60; + else + expsecs = pw->expire; + + for(;;){ + tm = localtime(expsecs); + print("expires [DDMMYYYY, default = %2.2d%2.2d%4.4d]: ", + tm->mday, tm->mon, tm->year+1900); + userinput(buf, sizeof(buf)); + if(strlen(buf) == 0) + break; + if(strlen(buf) != 8){ + print("!bad date format: %s\n", buf); + continue; + } + tm->mday = (buf[0]-'0')*10 + (buf[1]-'0'); + if(tm->mday > 31 || tm->mday < 1){ + print("!bad day of month: %d\n", tm->mday); + continue; + } + tm->mon = (buf[2]-'0')*10 + (buf[3]-'0') - 1; + if(tm->mon > 11 || tm->mday < 0){ + print("!bad month: %d\n", tm->mon + 1); + continue; + } + tm->year = atoi(buf+4) - 1900; + if(tm->year < 70){ + print("!bad year: %d\n", tm->year + 1900); + continue; + } + tm->sec = 59; + tm->min = 59; + tm->hour = 23; + tm->yday = 0; + expsecs = tm2sec(tm); + break; + } + pw->expire = expsecs; + + /* failed logins */ + if(pw->failed != 0 ) + print("clearing %d failed login attempts\n", pw->failed); + pw->failed = 0; + + /* status bits */ + if(isnew) + pw->status = Enabled; + for(;;){ + print("Enabled or Disabled [default %s]: ", + (pw->status & Enabled) ? "Enabled" : "Disabled" ); + userinput(buf, sizeof(buf)); + if(strlen(buf) == 0) + break; + if(buf[0]=='E' || buf[0]=='e'){ + pw->status |= Enabled; + break; + } + if(buf[0]=='D' || buf[0]=='d'){ + pw->status = pw->status & ~Enabled; + break; + } + } + for(;;){ + print("require STA? [default %s]: ", + (pw->status & STA) ? "yes" : "no" ); + userinput(buf, sizeof(buf)); + if(strlen(buf) == 0) + break; + if(buf[0]=='Y' || buf[0]=='y'){ + pw->status |= STA; + break; + } + if(buf[0]=='N' || buf[0]=='n'){ + pw->status = pw->status & ~STA; + break; + } + } + + /* free form field */ + if(isnew) + pw->other = nil; + print("comments [default = %s]: ", (pw->other == nil) ? "" : pw->other); + userinput(buf, 72); /* 72 comes from password.h */ + if(buf[0]) + if((pw->other = strdup(buf)) == nil) + sysfatal("strdup"); + + syslog(0, LOG, "CHANGELOGIN for '%s'", pw->id); + if(putPW(pw) < 0){ + print("error writing entry: %r\n"); + exits("can't write password file"); + }else{ + print("change written\n"); + if(isnew && create(home, OREAD, DMDIR | 0775L) < 0){ + print("unable to create %s: %r\n", home); + exits(home); + } + } + + exits(""); + return 1; /* keep other compilers happy */ +} + + +static void +userinput(char *buf, int blen) +{ + int n; + + while(1){ + n = read(0, buf, blen); + if(n<=0) + exits("read error"); + if(buf[n-1]=='\n'){ + buf[n-1] = '\0'; + return; + } + buf += n; blen -= n; + if(blen<=0) + exits("input too large"); + } +} + -- cgit v1.2.3