URI:
       tsecuser.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tsecuser.c (5194B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <mp.h>
            4 #include <libsec.h>
            5 #include "SConn.h"
            6 #include "secstore.h"
            7 
            8 int verbose;
            9 
           10 static void userinput(char *, int);
           11 char *SECSTORE_DIR;
           12 
           13 static void
           14 ensure_exists(char *f, ulong perm)
           15 {
           16         int fd;
           17 
           18         if(access(f, AEXIST) >= 0)
           19                 return;
           20         if(verbose)
           21                 fprint(2,"first time setup for secstore: create %s %lo\n", f, perm);
           22         fd = create(f, OREAD, perm);
           23         if(fd < 0){
           24                 fprint(2, "unable to create %s\n", f);
           25                 exits("secstored directories");
           26         }
           27         close(fd);
           28 }
           29 
           30 
           31 int
           32 main(int argc, char **argv)
           33 {
           34         int isnew;
           35         char *id, buf[Maxmsg], home[Maxmsg], prompt[100], *hexHi;
           36         char *pass, *passck;
           37         long expsecs;
           38         mpint *H = mpnew(0), *Hi = mpnew(0);
           39         PW *pw;
           40         Tm *tm;
           41 
           42         SECSTORE_DIR = unsharp("#9/secstore");
           43 
           44         ARGBEGIN{
           45         case 'v':
           46                 verbose++;
           47                 break;
           48         }ARGEND;
           49         if(argc!=1){
           50                 print("usage: secuser [-v] <user>\n");
           51                 exits("usage");
           52         }
           53 
           54         ensure_exists(SECSTORE_DIR, DMDIR|0755L);
           55         snprint(home, sizeof(home), "%s/who", SECSTORE_DIR);
           56         ensure_exists(home, DMDIR|0755L);
           57         snprint(home, sizeof(home), "%s/store", SECSTORE_DIR);
           58         ensure_exists(home, DMDIR|0700L);
           59 
           60         id = argv[0];
           61         if(verbose)
           62                 fprint(2,"secuser %s\n", id);
           63         if((pw = getPW(id,1)) == nil){
           64                 isnew = 1;
           65                 print("new account (because %s/%s %r)\n", SECSTORE_DIR, id);
           66                 pw = emalloc(sizeof(*pw));
           67                 pw->id = estrdup(id);
           68                 snprint(home, sizeof(home), "%s/store/%s", SECSTORE_DIR, id);
           69                 if(access(home, AEXIST) == 0){
           70                         print("new user, but directory %s already exists\n", home);
           71                         exits(home);
           72                 }
           73         }else{
           74                 isnew = 0;
           75         }
           76 
           77         /* get main password for id */
           78         for(;;){
           79                 if(isnew)
           80                         snprint(prompt, sizeof(prompt), "%s password", id);
           81                 else
           82                         snprint(prompt, sizeof(prompt), "%s password [default = don't change]", id);
           83                 pass = readcons(prompt, nil, 1);
           84                 if(pass == nil){
           85                         print("getpass failed\n");
           86                         exits("getpass failed");
           87                 }
           88                 if(verbose)
           89                         print("%ld characters\n", strlen(pass));
           90                 if(pass[0] == '\0' && isnew == 0)
           91                         break;
           92                 if(strlen(pass) >= 7)
           93                         break;
           94                 print("password must be at least 7 characters\n");
           95         }
           96 
           97         if(pass[0] != '\0'){
           98                 snprint(prompt, sizeof(prompt), "retype password");
           99                 if(verbose)
          100                         print("confirming...\n");
          101                 passck = readcons(prompt, nil, 1);
          102                 if(passck == nil){
          103                         print("getpass failed\n");
          104                         exits("getpass failed");
          105                 }
          106                 if(strcmp(pass, passck) != 0){
          107                         print("passwords didn't match\n");
          108                         exits("no match");
          109                 }
          110                 memset(passck, 0, strlen(passck));
          111                 free(passck);
          112                 hexHi = PAK_Hi(id, pass, H, Hi);
          113                 memset(pass, 0, strlen(pass));
          114                 free(pass);
          115                 free(hexHi);
          116                 mpfree(H);
          117                 pw->Hi = Hi;
          118         }
          119 
          120         /* get expiration time (midnight of date specified) */
          121         if(isnew)
          122                 expsecs = time(0) + 365*24*60*60;
          123         else
          124                 expsecs = pw->expire;
          125 
          126         for(;;){
          127                 tm = localtime(expsecs);
          128                 print("expires [DDMMYYYY, default = %2.2d%2.2d%4.4d]: ",
          129                                 tm->mday, tm->mon, tm->year+1900);
          130                 userinput(buf, sizeof(buf));
          131                 if(strlen(buf) == 0)
          132                         break;
          133                 if(strlen(buf) != 8){
          134                         print("!bad date format: %s\n", buf);
          135                         continue;
          136                 }
          137                 tm->mday = (buf[0]-'0')*10 + (buf[1]-'0');
          138                 if(tm->mday > 31 || tm->mday < 1){
          139                         print("!bad day of month: %d\n", tm->mday);
          140                         continue;
          141                 }
          142                 tm->mon = (buf[2]-'0')*10 + (buf[3]-'0') - 1;
          143                 if(tm->mon > 11 || tm->mday < 0){
          144                         print("!bad month: %d\n", tm->mon + 1);
          145                         continue;
          146                 }
          147                 tm->year = atoi(buf+4) - 1900;
          148                 if(tm->year < 70){
          149                         print("!bad year: %d\n", tm->year + 1900);
          150                         continue;
          151                 }
          152                 tm->sec = 59;
          153                 tm->min = 59;
          154                 tm->hour = 23;
          155                 tm->yday = 0;
          156                 expsecs = tm2sec(tm);
          157                 break;
          158         }
          159         pw->expire = expsecs;
          160 
          161         /* failed logins */
          162         if(pw->failed != 0 )
          163                 print("clearing %d failed login attempts\n", pw->failed);
          164         pw->failed = 0;
          165 
          166         /* status bits */
          167         if(isnew)
          168                 pw->status = Enabled;
          169         for(;;){
          170                 print("Enabled or Disabled [default %s]: ",
          171                         (pw->status & Enabled) ? "Enabled" : "Disabled" );
          172                 userinput(buf, sizeof(buf));
          173                 if(strlen(buf) == 0)
          174                         break;
          175                 if(buf[0]=='E' || buf[0]=='e'){
          176                         pw->status |= Enabled;
          177                         break;
          178                 }
          179                 if(buf[0]=='D' || buf[0]=='d'){
          180                         pw->status = pw->status & ~Enabled;
          181                         break;
          182                 }
          183         }
          184         for(;;){
          185                 print("require STA? [default %s]: ",
          186                         (pw->status & STA) ? "yes" : "no" );
          187                 userinput(buf, sizeof(buf));
          188                 if(strlen(buf) == 0)
          189                         break;
          190                 if(buf[0]=='Y' || buf[0]=='y'){
          191                         pw->status |= STA;
          192                         break;
          193                 }
          194                 if(buf[0]=='N' || buf[0]=='n'){
          195                         pw->status = pw->status & ~STA;
          196                         break;
          197                 }
          198         }
          199 
          200         /* free form field */
          201         if(isnew)
          202                 pw->other = nil;
          203         print("comments [default = %s]: ", (pw->other == nil) ? "" : pw->other);
          204         userinput(buf, 72);  /* 72 comes from password.h */
          205         if(buf[0])
          206                 if((pw->other = strdup(buf)) == nil)
          207                         sysfatal("strdup");
          208 
          209         syslog(0, LOG, "CHANGELOGIN for '%s'", pw->id);
          210         if(putPW(pw) < 0){
          211                 print("error writing entry: %r\n");
          212                 exits("can't write password file");
          213         }else{
          214                 print("change written\n");
          215                 if(isnew && create(home, OREAD, DMDIR | 0775L) < 0){
          216                         print("unable to create %s: %r\n", home);
          217                         exits(home);
          218                 }
          219         }
          220 
          221         exits("");
          222         return 1;  /* keep  other compilers happy */
          223 }
          224 
          225 
          226 static void
          227 userinput(char *buf, int blen)
          228 {
          229         int n;
          230 
          231         while(1){
          232                 n = read(0, buf, blen);
          233                 if(n<=0)
          234                         exits("read error");
          235                 if(buf[n-1]=='\n'){
          236                         buf[n-1] = '\0';
          237                         return;
          238                 }
          239                 buf += n;  blen -= n;
          240                 if(blen<=0)
          241                         exits("input too large");
          242         }
          243 }