#define SC_CONTINUE 1 #define SC_END_CLASS 2 #define SC_END_SCAN 3 static int scan_class_line(char *l, int(*fn)(const char *, const char *)) { char *spc; char *c; int fr; c = l; spc = index(l,' '); if (! spc) return(0); *spc = '\0'; while (1) { l = spc + 1; spc = index(l,' '); if (! spc) { fr = (*fn)(c,l); switch (fr) { case SC_CONTINUE: case SC_END_CLASS: return(0); case SC_END_SCAN: return(1); default: abort(); break; } } if (spc > l) { *spc = '\0'; fr = (*fn)(c,l); switch (fr) { case SC_CONTINUE: break; case SC_END_CLASS: return(0); case SC_END_SCAN: return(1); default: abort(); break; } } } } static void scan_class(int (*get)(void), int (*fn)(const char *, const char *)) { void *ls; ls = ls_init(); while (ls_readline(ls,get)) { if (scan_class_line(ls_line(ls),fn)) break; } ls_done(ls); } static void scan_class_file(CLASS *cl, int (*fn)(const char *, const char *)) { FILE *f; static int get(void) { return(getc(f)); } f = fopen_decrypt_path(cl->filename); if (! f) { if (errno == ENOENT) exit(0); fprintf(stderr,"%s: %s: %s\n",__progname,cl->filename,pse(errno)); exit(1); } scan_class(&get,fn); fclose(f); } static void hash_password(const char *pw, const char *salt, char *hash) { void *sha; unsigned char saltbuf[64]; int pwlen; const char *t; int tlen; int i; int c; char I[PWHASHRL10+1]; do <"salt"> { do <"nosalt"> { if (salt) { if (strlen(salt) == PWHASHLEN) { bzero(&saltbuf[0],64); for (i=0;i= PWHASHC0+PWHASHBASE)) break <"nosalt">; mult94_add(&saltbuf[0],c-PWHASHC0); } break <"salt">; } } } while (0); random_data(&saltbuf[0],32); } while (0); pwlen = strlen(pw); t = pw; tlen = pwlen; for (i=1;i<=PWHASHROUNDS;i++) { sprintf(&I[0],"%d",i); sha = sha256_init(); sha256_process_bytes(sha,&saltbuf[0],32); sha256_process_bytes(sha,&I[0],strlen(&I[0])); sha256_process_bytes(sha,&saltbuf[0],32); sha256_process_bytes(sha,pw,pwlen); sha256_process_bytes(sha,&saltbuf[0],32); sha256_process_bytes(sha,t,tlen); sha256_process_bytes(sha,&saltbuf[0],32); sha256_result(sha,&saltbuf[32]); t = (void *) &saltbuf[32]; tlen = 32; } hash[PWHASHLEN] = '\0'; for (i=PWHASHLEN-1;i>=0;i--) hash[i] = PWHASHC0 + div94_rem(&saltbuf[0]); } static FILE *fopen_decrypt_path(const char *path) { int fd; FILE *f; void *buf; int len; int e; fd = open_in_datadir(path,O_RDONLY|O_SHLOCK,0); if (load_fd_to_buf(fd,&buf,&len) < 0) { e = errno; close(fd); errno = e; return(0); } close(fd); f = fopen_decrypt(buf,len); if (! f) { e = errno; close(fd); free(buf); errno = e; return(0); } return(f); } static void class_addsub(CLASS *cl, int ac, char **av) { char *class; const char *why; int i; int j; int thisclass; int lineopen; int found; static void print_member(FILE *f, const char *m) { if (! lineopen) { fprintf(f,"%s",class); lineopen = 1; } fprintf(f," %s",m); } static void closeline(FILE *f) { int x; if (thisclass) { for (x=1;x=1;j--) { if (av[j] == 0) continue; if (!strcmp(av[i]+1,av[j]+1)) av[j] = 0; } } j = 1; for (i=1;ibadmember)(&av[i][1]); if (why) { fprintf(stderr,"%s: %s: %s\n",__progname,av[i],why); exit(1); } } class = strdup(""); thisclass = 0; found = 0; lineopen = 0; rewrite_file(cl->filename,&line,&post); free(class); } static void pw_challenge(void) { int fd; FILE *f; void *ls; char *u; char *p; char pwhash[PWHASHBUF]; static int r(void *cookie __attribute__((__unused__)), char *buf, int len) { return(read(fd,buf,len)); } static int get(void) { return(getc(f)); } do <"notfound"> { f = fopen_decrypt_path(&pw_file_name[0]); if (! f) { if (errno == ENOENT) break <"notfound">; fprintf(stderr,"%s: %s: %s\n",__progname,&pw_file_name[0],pse(errno)); exit(1); } ls = ls_init(); while (ls_readline(ls,&get)) { u = ls_line(ls); p = index(u,' '); if (! p) continue; *p++ = '\0'; if (strcmp(u,whoami)) continue; if (! get_hashed_pw_noecho("Your pwdb password",&pwhash[0],p)) exit(1); if (strcmp(&pwhash[0],p)) { fprintf(stderr,"Sorry.\n"); exit(1); } ls_done(ls); fclose(f); return; } ls_done(ls); } while (0); if (! get_hashed_pw_noecho("Your pwdb password",&pwhash[0],&bogus_salt[0])) exit(1); fprintf(stderr,"Sorry.\n"); exit(1); } static void cmd_pw(int, char **) __attribute__((__noreturn__)); static void cmd_pw(int ac, char **av) { char pwhash[PWHASHBUF]; char pwhash2[PWHASHBUF]; char *user; static int line(char *l, FILE *f) { char *p; p = index(l,' '); if (! p) return(0); *p++ = '\0'; if (! strcmp(l,user)) return(0); fprintf(f,"%s %s\n",l,p); return(0); } static void post(FILE *f) { fprintf(f,"%s %s\n",user,&pwhash[0]); } while (1) { if (priv) { char *p; if (ac != 1) { fprintf(stderr,"Usage: %s pw USER\n",__progname); exit(1); } user = av[0]; asprintf(&p,"%s's new pwdb password",user); if (! get_hashed_pw_noecho(p,&pwhash[0],0)) exit(1); } else { if (ac != 0) { fprintf(stderr,"Usage: %s pw\n",__progname); exit(1); } user = whoami; if (! get_hashed_pw_noecho("Your new pwdb password",&pwhash[0],0)) exit(1); } if (! get_hashed_pw_noecho("Again, to verify",&pwhash2[0],&pwhash[0])) exit(1); if (! strcmp(&pwhash[0],&pwhash2[0])) break; printf("Mismatch. Try again.\n"); } rewrite_file(&pw_file_name[0],&line,&post); printf("Done.\n"); exit(0); } static void cmd_pwdel(int, char **) __attribute__((__noreturn__)); static void cmd_pwdel(int ac, char **av) { static int line(char *l, FILE *f) { char *p; p = index(l,' '); if (! p) return(0); *p++ = '\0'; if (! strcmp(l,av[0])) return(0); fprintf(f,"%s %s\n",l,p); return(0); } if (ac != 1) { fprintf(stderr,"Usage: %s pw USER\n",__progname); exit(1); } rewrite_file(&pw_file_name[0],&line,0); printf("Removed.\n"); exit(0); } static unsigned int div94_rem(unsigned char *v, int len) { int r; int i; r = 0; for (i=0;(i= len) return(B94BASE); for (;i