Differences From
Artifact [9379e84c9e]:
25 25 * interface. this is unlikely to cause problems,
26 26 * but should be kept in mind.
27 27 *
28 28 * TODO prevent pw reads from going off the edge of
29 29 * the screen and fucking up all the shit
30 30 */
31 31
32 +#define _DEFAULT_SOURCE
33 +
32 34 #include <unistd.h>
33 35 #include <sys/random.h>
34 36 #include <sys/syscall.h>
35 37 #include <sys/shm.h>
36 38 #include <stddef.h>
37 39 #include <stdint.h>
38 40 #include <stdlib.h>
................................................................................
51 53 # include <pwd.h>
52 54 # include <stdlib.h>
53 55 #else
54 56 # define copy(str,len)
55 57 #endif
56 58
57 59 enum /* constants */ {
58 - null = 0, true = 1, false = 0,
60 + /* nullptr = 0, true = 1, false = 0, */
59 61 kpw_shm_key = 0x3CC215A,
60 62 };
61 63
62 64 #include "err.inc"
63 65
64 66 enum /* db format constants */ {
65 67 db_pubkey_len = crypto_box_PUBLICKEYBYTES,
66 68 db_privkey_len = crypto_box_SECRETKEYBYTES,
67 69 kpw_db_pw_max = 64,
68 70 default_pw_len = 32,
69 71 };
70 72
71 -typedef _Bool bool;
73 +/* typedef _Bool bool; */
72 74 typedef unsigned long long iaia_word_type;
73 75 typedef bad iaia_error_type;
74 76 enum /* iaia errors */ {
75 77 iaia_e_ok = ok,
76 78 iaia_e_base = fail,
77 79 iaia_e_domain = fail,
78 80 iaia_e_overflow = fail,
................................................................................
149 151 #ifdef _CLIPBOARD
150 152 char* const*
151 153 cbd_cmds[] = {
152 154 /* NOTE: these commands must be specified in order of
153 155 * most- to least-specific. more than one utility may
154 156 * be present on a given system, so we need to make sure
155 157 * the right one is called. */
156 - (char* const[]){"termux-clipboard-set", null},
157 - (char* const[]){"xsel", "-bi", null},
158 + (char* const[]){"termux-clipboard-set", nullptr},
159 + (char* const[]){"xsel", "-bi", nullptr},
158 160 /* TODO: allow command to be specified by env var */
159 - null
161 + nullptr
160 162 };
161 163
162 164
163 165 enum bad
164 166 copy(const char* str, size_t len) {
165 167 alert(a_debug, "copying password to clipboard");
166 168 if (geteuid() == 0) {
167 169 /* on a sane system, what we'd do is hike up the process
168 170 * tree til we found a non-root user. alas, this is UNIX. */
169 171 const char* realuser = getenv("SUDO_USER");
170 - if (realuser == null) realuser = "nobody";
172 + if (realuser == nullptr) realuser = "nobody";
171 173
172 174 alert(a_warn, "running as root! dropping privileges to prevent malicious use of copy functionality");
173 175 setenv("USER", realuser, true);
174 176
175 177 struct passwd* nobody = getpwnam(realuser);
176 - if (nobody == null) {
178 + if (nobody == nullptr) {
177 179 alert(a_fatal | bad_user, "could not get UID to drop privileges; bailing");
178 180 return bad_user;
179 181 } else {
180 182 setenv("HOME", nobody -> pw_dir, true);
181 183 setenv("SHELL", "/dev/null", true);
182 184 setuid(nobody -> pw_uid);
183 185 if (geteuid() == 0)
................................................................................
189 191 char* const clipboard_env_arg = getenv("mkpw_clipboard_setter_arg");
190 192 // FIXME: allow multiple args
191 193 int fds[2];
192 194 if (pipe(fds) != 0) return bad_pipe;
193 195 if (!fork()) {
194 196 close(fds[1]);
195 197 dup2(fds[0], 0);
196 - if (clipboard_env != null) {
198 + if (clipboard_env != nullptr) {
197 199 execvp(clipboard_env, (char* const[]){
198 - clipboard_env, clipboard_env_arg, null});
200 + clipboard_env, clipboard_env_arg, nullptr});
199 201 return bad_copy;
200 - } else for(char* const** cmd = cbd_cmds; *cmd != null; ++cmd) {
202 + } else for(char* const** cmd = cbd_cmds; *cmd != nullptr; ++cmd) {
201 203 execvp((*cmd)[0], *cmd);
202 204 }
203 205 return bad_copy;
204 206 } else {
205 207 close(fds[0]);
206 208 write(fds[1], str, len);
207 209 write(fds[1], "\n", 1);
................................................................................
259 261 hexdump(byte* bytes, size_t sz) {
260 262 if(!_g_debug_msgs) return;
261 263 alert(a_debug, "printing hex dump");
262 264 byte* st = bytes;
263 265 write(2, _str("\t\x1b[94m"));
264 266 for (size_t i = 0; i < sz; ++i) {
265 267 char hex[5] = " ";
266 - kitoa(16, bytes[i], hex, hex + 2, NULL, true);
268 + kitoa(16, bytes[i], hex, hex + 2, nullptr, true);
267 269 write(2, hex, 4);
268 270 if(!((i+1)%8)) {
269 271 write(2, _str("\x1b[;1m│\x1b[m "));
270 272 bytedump(st, 8);
271 273 write(2, "\n\t\x1b[94m", (i == sz - 1 ? 1 : 7));
272 274 st += 8;
273 275 } else if (i == sz - 1) {
................................................................................
387 389 /* either EOF or an error - either way,
388 390 * we're finished here */
389 391 break;
390 392 }
391 393 } while(1);
392 394 end_read_loop: term_clear(tty, term_clear_line);
393 395 *p = 0;
394 - if (out_len!=NULL) *out_len = p - dest;
396 + if (out_len!=nullptr) *out_len = p - dest;
395 397
396 398 /* return the terminal to normal */
397 399 tcsetattr(tty, TCSANOW, &initial);
398 400
399 401 if (tty != 1) close(tty);
400 402 } else {
401 403 alert(a_warn, "reading pw from standard input");
................................................................................
405 407 return ok;
406 408 }
407 409
408 410 int
409 411 dbopen(int flags) {
410 412 const char* dbpath = getenv("kpw_db");
411 413 int db;
412 - if (dbpath == NULL) {
414 + if (dbpath == nullptr) {
413 415 const char* cfg = getenv("XDG_CONFIG_HOME");
414 - if (cfg == NULL) {
416 + if (cfg == nullptr) {
415 417 const char* home = getenv("HOME");
416 - if (home == NULL) exit(bad_insane);
418 + if (home == nullptr) exit(bad_insane);
417 419
418 420 size_t homelen = strlen(home);
419 421 pstr path[] = { {homelen, home}, _p("/.config/kpw.db") };
420 422 char buf[homelen + path[1].len + 1];
421 423 bzero(buf, sz(buf));
422 - impose(path, sz(path), NULL, buf);
424 + impose(path, sz(path), nullptr, buf);
423 425
424 426 db = open(buf, flags, 0600);
425 427 } else {
426 428 size_t cfglen = strlen(cfg);
427 429 pstr path[] = { {cfglen, cfg}, _p("/kpw.db") };
428 430 char buf[cfglen + path[1].len + 1];
429 431 bzero(buf, sz(buf));
430 - impose(path, sz(path), NULL, buf);
432 + impose(path, sz(path), nullptr, buf);
431 433
432 434 db = open(buf, flags, 0600);
433 435 }
434 436 } else {
435 437 db = open(dbpath, flags, 0600);
436 438 }
437 439
................................................................................
484 486 alert(a_debug, "deriving secret");
485 487 if(crypto_pwhash(key, sz(key), dbpw, pwlen, salt,
486 488 crypto_pwhash_OPSLIMIT_INTERACTIVE,
487 489 crypto_pwhash_MEMLIMIT_INTERACTIVE,
488 490 crypto_pwhash_ALG_DEFAULT) != 0) {
489 491 return bad_mem;
490 492 }
493 + memset(&dbpw, 0, (sizeof dbpw));
491 494 hexdump(key, sz(key));
492 495
493 496 alert(a_debug, "attempting to decrypt private key");
494 497 for (size_t i = 0; i < sz(key); ++i) {
495 498 priv[i] = priv_enc[i] ^ key[i];
496 499 }
497 500 hexdump(priv, sz(key));
................................................................................
560 563 memcpy(dest, src, sz); return dest + sz;
561 564 }
562 565
563 566 enum bad
564 567 emit_usage(const char* text) {
565 568 say("\x1b[1musage:\x1b[m ");
566 569 write(2, _g_binary_name, strlen(_g_binary_name));
567 - if (text == NULL) {
570 + if (text == nullptr) {
568 571 write(2, kpw_optstr, sz(kpw_optstr));
569 572 write(2, kpw_usage, sz(kpw_usage));
570 573 } else write(2, text, strlen(text));
571 574 return bad_usage;
572 575 }
573 576
574 577 int
................................................................................
588 591
589 592 bool print = false,
590 593 clobber = false,
591 594 no_more_opts = false;
592 595 # ifdef _CLIPBOARD
593 596 bool copy_pw = true;
594 597 # endif
595 - for (const char** arg = argv + 1; *arg != null; ++arg) {
598 + for (const char** arg = argv + 1; *arg != nullptr; ++arg) {
596 599 if (!no_more_opts && (*arg)[0] == '-') {
597 600 if ((*arg)[1] == '-') { /* long opt */
598 601 if((*arg)[2] == 0) {
599 602 no_more_opts = true;
600 603 continue;
601 604 }
602 605 unsigned char a;
................................................................................
615 618 }
616 619 } else {
617 620 if (param > sz(params)) return bad_syntax;
618 621 params[param++] = *arg;
619 622 }
620 623 }
621 624
622 - if (op == getpw && param == 0) return emit_usage(NULL);
625 + if (op == getpw && param == 0) return emit_usage(nullptr);
623 626
624 627 if (sodium_init() < 0)
625 628 return bad_lib_sodium_init;
626 629
627 630 switch(op) {
628 631 # ifdef _SAVEKEY
629 632 case logout:
................................................................................
653 656 key_priv* saved = shmat(shm, 0, 0);
654 657 if (saved == (void*)-1) return bad_shm;
655 658 memcpy(saved, priv, sz(priv));
656 659 shmdt(saved);
657 660 } else {
658 661 int shm = shmget(ipck, sizeof(key_priv), 0);
659 662 if (shm == -1) return bad_no_shm;
660 - shmctl(shm, IPC_RMID, NULL);
663 + shmctl(shm, IPC_RMID, nullptr);
661 664 }
662 665
663 666 return ok;
664 667 }
665 668 # endif
666 669
667 670 case genpw:
................................................................................
668 671 case addpw: {
669 672 if (param == 0) return emit_usage(
670 673 op == addpw ? " -a[p] <account> [<pw>]\n" :
671 674 /* genpw */" -g[lmusp] <account> [<pw len>]\n");
672 675
673 676 if (param > 2 || param < 1) return bad_syntax;
674 677 const char* acct = params[0],
675 - * prm = (param == 2 ? params[1] : NULL);
678 + * prm = (param == 2 ? params[1] : nullptr);
676 679
677 680 alert(a_debug, "opening database");
678 681 int db = dbopen(O_RDWR);
679 682 if (db == -1) return bad_db_load;
680 683 alert(a_debug, "reading in public key");
681 684 byte key [db_pubkey_len];
682 685 ssize_t e = read(db, key, sz(key));
................................................................................
685 688 lseek(db, 0, SEEK_END);
686 689 bool tty_in = isatty(0),
687 690 tty_out = isatty(1);
688 691
689 692 password pw; size_t pwlen;
690 693 const char* acct_pw;
691 694 if (op == addpw) {
692 - if (prm == NULL) {
695 + if (prm == nullptr) {
693 696 pstr prompt_l[] = { _p("- new password for "),
694 697 {0, acct}, _p(": "), };
695 698 char prompt[pstrsum(prompt_l, sz(prompt_l))];
696 699 if (tty_in) pstrcoll(prompt_l, sz(prompt_l), prompt);
697 700
698 701 bad e = pwread(!print, pw, &pwlen,
699 702 prompt, sz(prompt));
700 703 if (e != ok) return e;
701 704 if (tty_in && !print) {
702 705 password pw_conf;
703 - e = pwread(true, pw_conf, NULL, _str("- confirm: "));
706 + e = pwread(true, pw_conf, nullptr, _str("- confirm: "));
704 707 if (e != ok) return e;
705 708 if (strcmp(pw,pw_conf) != 0)
706 709 return bad_pw_match;
707 710 }
708 711 acct_pw = pw;
709 712 } else acct_pw = prm, pwlen = strlen(prm);
710 713 } else if (op == genpw) {
711 714 unsigned long long len;
712 - if (prm != NULL) {
715 + if (prm != nullptr) {
713 716 alert(a_debug, "converting length parameter to integer");
714 717 bad e = katoi(10, prm, &len);
715 718 if (e != ok) return bad_num;
716 719 } else alert(a_debug, "using default password length"),
717 720 len = default_pw_len;
718 721
719 722 alert(a_debug, "generating new password");
................................................................................
762 765 /* op==chpw */ " -c <account> [<new pw>]\n");
763 766
764 767 if (param < 1 || param > (op == delpw ? 1 : 2))
765 768 return bad_syntax;
766 769 const char* target = params[0];
767 770 const char* delta;
768 771 if (param == 2) delta=params[1];
769 - else delta=NULL;
772 + else delta=nullptr;
770 773
771 774 int db = dbopen(O_RDWR);
772 775 if (db == -1) return bad_db_load;
773 776
774 777 const size_t dbsz = lseek(db, 0, SEEK_END);
775 778 lseek(db, 0, SEEK_SET);
776 779
................................................................................
827 830 const char* newpass;
828 831 size_t pwlen;
829 832 if (op == regen) {
830 833 alert(a_debug, "generating new password");
831 834 /* generating a new password. use the default
832 835 * length if the user hasn't supplied one herself,
833 836 * or if she has, convert it to an integer. */
834 - if (delta == NULL) pwlen = default_pw_len; else {
837 + if (delta == nullptr) pwlen = default_pw_len; else {
835 838 unsigned long long value;
836 839 bad k = katoi(10, delta, &value);
837 840 if (k != ok) return bad_num;
838 841 pwlen = value;
839 842 }
840 843 bad m = mkpw(mode, pwbuf, pwlen);
841 844 if (m != ok) return m;
842 845 newpass = pwbuf;
843 846 } else if (op == chpw) {
844 847 /* the user has requested a password change. take
845 848 * it from the command line if available, otherwise
846 849 * generate a prompt and read from stdin */
847 850
848 - if (delta == NULL) {
851 + if (delta == nullptr) {
849 852 pstr prompt_l[] = { _p("- new password for "),
850 853 {0, target}, _p(": "), };
851 854 char prompt[pstrsum(prompt_l, sz(prompt_l))];
852 855 if (_g_term_type[0] > plain_term)
853 856 pstrcoll(prompt_l, sz(prompt_l), prompt);
854 857
855 858 bad p = pwread(!print, pwbuf, &pwlen, prompt, sz(prompt));
856 859 if (p != ok) return p;
857 860 /* prompt again to make sure the user entered
858 861 * her new password correctly */
859 862 if(!print && _g_term_type[0] > plain_term) {
860 863 password passconf;
861 - p = pwread(!print, passconf, NULL, _str("confirm: "));
864 + p = pwread(!print, passconf, nullptr, _str("confirm: "));
862 865 if (p != ok) return p;
863 866 if (strcmp(passconf, pwbuf) != 0)
864 867 return bad_pw_match;
865 868 }
866 869 newpass = pwbuf;
867 870 } else newpass = delta, pwlen = strlen(delta);
868 871 } else return bad_assert;
................................................................................
918 921 return ok;
919 922 }
920 923
921 924 case getpw: /* kpw <acct> */
922 925 case lspw: { /* kpw -t[p] [<prefix>] */
923 926 const char* target;
924 927 if (param == 1) target = params[0];
925 - else if (param == 0) target = NULL;
928 + else if (param == 0) target = nullptr;
926 929 else return bad_syntax;
927 930
928 931 alert(a_debug, "opening database for reading");
929 932 int db = dbopen(O_RDONLY);
930 933 if (db == -1) return bad_db_load;
931 934
932 935 key_pub pub;
................................................................................
1015 1018 alert(a_notice, "database keypair generated, encrypting");
1016 1019 password dbpw;
1017 1020 size_t pwlen;
1018 1021 bad e = pwread(!print, dbpw, &pwlen, _str("- new database key: "));
1019 1022 if (e != ok) return e;
1020 1023 if (!print && isatty(0)) {
1021 1024 password dbpw_conf;
1022 - e = pwread(!print, dbpw_conf, NULL, _str("- confirm: "));
1025 + e = pwread(!print, dbpw_conf, nullptr, _str("- confirm: "));
1023 1026 if (e != ok) return e;
1024 1027
1025 1028 if(strcmp(dbpw,dbpw_conf) != 0)
1026 1029 return bad_pw_match;
1027 1030 }
1028 1031
1029 1032 byte salt [crypto_pwhash_SALTBYTES],
................................................................................
1094 1097
1095 1098 int
1096 1099 main (int argc, const char** argv) {
1097 1100 const char* colorterm = getenv("COLORTERM");
1098 1101 const char* term = getenv("TERM");
1099 1102 bool color, ansi;
1100 1103
1101 - if (colorterm != NULL)
1104 + if (colorterm != nullptr)
1102 1105 color = true;
1103 - else if (term == NULL)
1106 + else if (term == nullptr)
1104 1107 ansi = false, color = false;
1105 - else if (strstr(term, "color") == NULL)
1108 + else if (strstr(term, "color") == nullptr)
1106 1109 ansi = true, color = false;
1107 1110 else color = true;
1108 1111
1109 1112 for (uint8_t i = 0; i < 3; ++i) {
1110 1113 if(isatty(i)) {
1111 1114 _g_term_type[i] = (color ? color_term :
1112 1115 ansi ? ansi_term : plain_term);