Overview
Comment: | updates |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
c2ffe127f32fd6e37b3c9df9523acdd8 |
User & Date: | lexi on 2019-08-15 08:34:03 |
Other Links: | manifest | tags |
Context
2019-08-15
| ||
11:24 | FUCK THIS SHIT check-in: 218f1d20c2 user: lexi tags: trunk | |
08:34 | updates check-in: c2ffe127f3 user: lexi tags: trunk | |
05:45 | add kpw source check-in: a3ccd193d5 user: lexi tags: trunk | |
Changes
Modified kpw.d/errtab from [203a9ab500] to [59271087af].
1 1 ok completed successfully debug 0 2 2 fail unknown error 3 3 mem out of memory 4 +num not a number 4 5 user kpw started as wrong user 5 6 option unrecognized option passed 6 7 syntax invalid invocation syntax 7 8 entropy could not acquire entropy 8 9 copy could not copy password 10 +pipe could not create pipe 9 11 insane your environment is not sane 10 12 db_create database could not be created 13 +db_load database could not be read 14 +db_corrupt database corrupt 11 15 cancel user canceled operation notice 12 16 pw invalid password 13 17 pw_match passwords do not match 14 18 usage usage displayed to user debug 64 15 19 lib unspecified library error fatal 128 16 -lib_sodium_init could not initialize libsodium fatal 20 +lib_sodium_init could not initialize libsodium
Modified kpw.d/kpw.c from [f865f78c63] to [f4297483ea].
13 13 * systems, but should run fine on Linux as well 14 14 * as BSDs with getrandom() support. 15 15 * ! for getrandom() to work with the version of 16 16 * libc on my android phone, the getrandom() call 17 17 * had to be converted to use the syscall() 18 18 * interface. this is unlikely to cause problems, 19 19 * but should be kept in mind. 20 + * 21 + * TODO prevent pw reads from going off the edge of 22 + * the screen and fucking up all the shit 20 23 */ 21 24 22 25 #include <unistd.h> 23 26 #include <sys/random.h> 24 27 #include <sys/syscall.h> 25 28 #include <stddef.h> 26 29 #include <stdint.h> ................................................................................ 29 32 #include <fcntl.h> 30 33 #include <sodium.h> 31 34 #include <termios.h> 32 35 33 36 34 37 #define sz(a) ( sizeof (a) / sizeof (a) [0] ) 35 38 #define say(x) (write(2, (x), sizeof (x))) 39 +#define _str(s) (s),sizeof(s) 36 40 37 41 #ifdef _CLIPBOARD 38 42 # include <sys/types.h> 39 43 # include <pwd.h> 40 44 # include <stdlib.h> 41 45 #else 42 46 # define copy(str,len) ................................................................................ 48 52 49 53 #include "err.inc" 50 54 51 55 enum /* db format constants */ { 52 56 db_pubkey_len = crypto_box_PUBLICKEYBYTES, 53 57 db_privkey_len = crypto_box_SECRETKEYBYTES, 54 58 kpw_db_pw_max = 64, 59 + default_pw_len = 32, 55 60 }; 56 61 57 62 typedef _Bool bool; 58 63 typedef unsigned long long iaia_word_type; 59 64 typedef bad iaia_error_type; 60 65 enum /* iaia errors */ { 61 66 iaia_e_ok = ok, ................................................................................ 82 87 83 88 #define str_ucase "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 84 89 #define str_lcase "abcdefghijklmnopqrstuvwxyz" 85 90 #define str_num "0123456789" 86 91 const char* reftbl = str_num str_ucase str_lcase; 87 92 const char* reftbl_lcase = str_num str_lcase; 88 93 94 +const char* _g_binary_name; 89 95 #ifdef _CLIPBOARD 90 96 char* const* 91 97 cbd_cmds[] = { 92 98 /* NOTE: these commands must be specified in order of 93 99 * most- to least-specific. more than one utility may 94 100 * be present on a given system, so we need to make sure 95 101 * the right one is called. */ 96 102 (char* const[]){"termux-clipboard-set", null}, 97 103 (char* const[]){"xsel", "-bi", null}, 98 104 /* TODO: allow command to be specified by env var */ 99 105 null 100 106 }; 101 107 102 -bad 108 +enum { plain_term, ansi_term, color_term } _g_term_type[3]; 109 +enum alert {a_notice, a_warn, a_debug, a_fatal = 1 << 8}; 110 +pstr alert_msg[] = { 111 + _p("(kpw notice)"), _p("(kpw warn)"), 112 + _p("(kpw debug)"), _p("(kpw fatal)") 113 +}; 114 + 115 +bool _g_alert_quiet = false, 116 + _g_debug_msgs = false; 117 +void alert(uint16_t kind, const char* msg) { 118 + if (!((kind >= a_fatal) || 119 + (_g_debug_msgs && kind == a_debug) || 120 + (!_g_alert_quiet && kind != a_debug))) return; 121 + 122 + uint8_t idx; 123 + if (kind & a_fatal) idx = a_debug + 1; 124 + else idx = kind; 125 + 126 + 127 + if (_g_term_type[2] == color_term) { 128 + char msgcode[] = "\x1b[90m"; 129 + char* color = msgcode+3; 130 + *color = '0' + (4 - idx); 131 + write(2,msgcode, sz(msgcode)); 132 + } else if (_g_term_type[2] == ansi_term) { 133 + write(2,"\x1b[1m",4); 134 + } 135 + 136 + write(2,alert_msg[idx].ptr, 137 + alert_msg[idx].len); 138 + 139 + if (_g_term_type[2] != plain_term) write(2,"\x1b[m ",4); 140 + else write(2," ",1); 141 + write(2,msg,strlen(msg)); 142 + write(2,"\n",1); 143 + 144 + if (kind & a_fatal) exit(kind & (~a_fatal)); 145 +} 146 + 147 +enum bad 103 148 copy(const char* str, size_t len) { 149 + alert(a_debug, "copying password to clipboard"); 150 + if (geteuid() == 0) { 151 + /* on a sane system, what we'd do is hike up the process 152 + * tree til we found a non-root user. alas, this is UNIX. */ 153 + const char* realuser = getenv("SUDO_USER"); 154 + if (realuser == null) realuser = "nobody"; 155 + 156 + alert(a_warn, "running as root! dropping privileges to prevent malicious use of copy functionality"); 157 + setenv("USER", realuser, true); 158 + 159 + struct passwd* nobody = getpwnam(realuser); 160 + if (nobody == null) { 161 + alert(a_fatal | bad_user, "could not get UID to drop privileges; bailing"); 162 + return bad_user; 163 + } else { 164 + setenv("HOME", nobody -> pw_dir, true); 165 + setenv("SHELL", "/dev/null", true); 166 + setuid(nobody -> pw_uid); 167 + if (geteuid() == 0) 168 + alert(a_fatal | bad_user, "i don't fucking think so, you sneaky bastard"); 169 + } 170 + 171 + } 104 172 char* const clipboard_env = getenv("mkpw_clipboard_setter"); 105 173 char* const clipboard_env_arg = getenv("mkpw_clipboard_setter_arg"); 106 174 // FIXME: allow multiple args 107 175 int fds[2]; 108 - if (pipe(fds) != 0) return 63; 176 + if (pipe(fds) != 0) return bad_pipe; 109 177 if (!fork()) { 110 178 close(fds[1]); 111 179 dup2(fds[0], 0); 112 180 if (clipboard_env != null) { 113 181 execvp(clipboard_env, (char* const[]){ 114 182 clipboard_env, clipboard_env_arg, null}); 115 183 return bad_copy; ................................................................................ 125 193 return ok; 126 194 } 127 195 } 128 196 #endif 129 197 130 198 enum genmode { upper, mix, lower, stupid }; 131 199 132 -bad 200 +enum bad 133 201 mkpw(enum genmode mode, char* buf, size_t const len) { 134 202 const unsigned char chars = (sizeof str_num - 1) + 135 203 ((mode == upper) ? (sizeof str_ucase - 1) : 136 204 ((mode == lower) ? (sizeof str_lcase - 1) : 137 205 ((sizeof str_ucase - 1) + (sizeof str_lcase - 1)))); 138 206 const char* tbl = (mode == upper) ? reftbl : 139 207 ((mode == lower) ? reftbl_lcase : reftbl); ................................................................................ 164 232 pstr account; 165 233 pstr pw; 166 234 }; 167 235 168 236 enum term_clear {term_clear_line, 169 237 term_clear_screen}; 170 238 171 -enum alert {a_notice, a_warn, a_debug, a_fatal = 1 << 8}; 172 -pstr alert_msg[] = { 173 - _p("(notice)"), _p("(warn)"), 174 - _p("(debug)"), _p("(fatal)") 175 -}; 176 - 177 -bool _g_alert_quiet = false, 178 - _g_debug_msgs = false; 179 -void alert(uint16_t kind, const char* msg) { 180 - if (!((kind >= a_fatal) || 181 - (_g_debug_msgs && kind == a_debug) || 182 - (!_g_alert_quiet && kind != a_debug))) return; 183 - 184 - uint8_t idx; 185 - if (kind & a_fatal) idx = a_debug + 1; 186 - else idx = kind; 187 - 188 - 189 - if (isatty(2)) { 190 - char msgcode[] = "\x1b[1;30m"; 191 - char* color = msgcode+5; 192 - *color = '0' + (4 - idx); 193 - write(2,msgcode, sz(msgcode)); 194 - } 195 - 196 - write(2,alert_msg[idx].ptr,alert_msg[idx].len); 197 - if (isatty(2)) write(2,"\x1b[m ",4); 198 - else write(2," ",1); 199 - write(2,msg,strlen(msg)); 200 - write(2,"\n",1); 201 - 202 - if (kind & a_fatal) exit(kind & (~a_fatal)); 203 -} 204 - 205 239 void term_clear(enum term_clear behavior) { 206 240 switch(behavior) { 207 241 case term_clear_line: write(1,"\r\x1b[2K",5); break; 208 242 case term_clear_screen: write(1,"\r\x1b[3J",5); break; 209 243 } 210 244 } 211 245 void term_bell() { 212 246 write(1,"\a",1); 213 247 } 214 248 215 249 typedef char password[kpw_db_pw_max + 1]; 216 -bad pwread(char* dest, size_t* out_len, const char* prompt, const size_t plen) { 250 +bad pwread(bool obscure, char* dest, size_t* out_len, const char* prompt, const size_t plen) { 217 251 if (isatty(0)) { 218 252 struct termios initial; { 219 253 /* in order to take PW input, we need to shut 220 254 * off echo and canonical mode. now we're in 221 255 * charge of reading each keypress. */ 222 256 tcgetattr(1, &initial); 223 257 struct termios nt = initial; ................................................................................ 226 260 } 227 261 228 262 *dest = 0; 229 263 char* p = dest; 230 264 231 265 do { 232 266 term_clear(term_clear_line); 233 - write(1, "\x1b[1m", 4); 267 + if (_g_term_type[1] >= ansi_term) write(1, "\x1b[1m", 4); 234 268 write(1, prompt, plen); 235 - write(1, "\x1b[21m", 5); 269 + if (_g_term_type[1] >= ansi_term) write(1, "\x1b[21m", 5); 236 270 237 - for(size_t i = 0; i < p - dest; ++i) 271 + if (obscure) for(size_t i = 0; i < p - dest; ++i) 238 272 write(1, "*", 1); 273 + else write(1, dest, p-dest); 239 274 240 275 char c; 241 276 if (read(0, &c, 1) == 1) { 242 277 switch (c) { 243 278 case '\n': case '\r': 244 279 /* accept pw */ 245 280 if (p > dest) goto end_read_loop; ................................................................................ 307 342 } 308 343 309 344 return db; 310 345 } 311 346 312 347 int 313 348 kpw(int argc, const char** argv) { 314 - if (argc == 0) return -1; 315 - if (argc == 1) { 316 - size_t namelen = strlen(argv[0]); 317 - say("\x1b[1musage:\x1b[m "); 318 - write(2, argv[0], namelen); 319 - write(2, kpw_optstr, sz(kpw_optstr)); 320 - write(2, kpw_usage, sz(kpw_usage)); 321 - return bad_usage; 322 - } 349 + if (argc == 0) return bad_insane; 350 + _g_binary_name = argv[0]; 323 351 324 352 enum genmode 325 353 mode = lower; 326 - enum {usage,getpw,addpw,delpw,genpw, 354 + enum {usage,getpw,addpw,delpw,lspw,genpw, 327 355 chpw,keyin,logout,createdb,rekeydb} 328 356 op = getpw; 329 357 330 358 const char* params[3]; 331 359 uint8_t param = 0; 332 360 333 361 bool print = false, 334 - clobber = false; 362 + clobber = false, 363 + no_more_opts = false; 335 364 # ifdef _CLIPBOARD 336 365 bool copy_pw = true; 337 366 # endif 338 367 for (const char** arg = argv + 1; *arg != null; ++arg) { 339 - if ((*arg)[0] == '-') { 368 + if (!no_more_opts && (*arg)[0] == '-') { 340 369 if ((*arg)[1] == '-') { /* long opt */ 370 + if((*arg)[2] == 0) { 371 + no_more_opts = true; 372 + continue; 373 + } 341 374 unsigned char a; 342 375 if (tblget(sz(argtbl), argtbl, *arg + 2, &a) == ok) switch (a) { 343 376 kpw_emit_long_option_switch 344 377 } else { 345 378 return bad_option; 346 379 } 347 380 } else { /* short opt */ ................................................................................ 353 386 } 354 387 } 355 388 } else { 356 389 if (param > sz(params)) return bad_syntax; 357 390 params[param++] = *arg; 358 391 } 359 392 } 393 + 394 + if (op == getpw && param == 0) { 395 + size_t namelen = strlen(argv[0]); 396 + say("\x1b[1musage:\x1b[m "); 397 + write(2, argv[0], namelen); 398 + write(2, kpw_optstr, sz(kpw_optstr)); 399 + write(2, kpw_usage, sz(kpw_usage)); 400 + return bad_usage; 401 + } 360 402 361 403 if (sodium_init() < 0) 362 404 return bad_lib_sodium_init; 363 405 364 406 switch(op) { 365 407 case getpw:{ /* kpw <acct> */ 366 408 break; 367 409 } 368 410 369 - case addpw:{ /* kpw -a <acct> [<pw>] */ 411 + case genpw: /* kpw -g[lmu] <acct> [<len>] */ 412 + case addpw: { /* kpw -a <acct> [<pw>] */ 413 + if (param > 2 || param < 1) return bad_syntax; 414 + const char* acct = params[0], 415 + * prm = (param == 2 ? params[1] : NULL); 416 + 417 + alert(a_debug, "opening database"); 418 + int db = dbopen(O_RDWR); 419 + if (db == -1) return bad_db_load; 420 + alert(a_debug, "reading in public key"); 421 + uint8_t key [db_pubkey_len]; 422 + ssize_t e = read(db, key, sz(key)); 423 + if(e < sz(key)) return bad_db_corrupt; 424 + 425 + lseek(db, 0, SEEK_END); 426 + bool tty_in = isatty(0), 427 + tty_out = isatty(1); 428 + 429 + password pw; size_t pwlen; 430 + const char* acct_pw; 431 + if (op == addpw) { 432 + if (prm == NULL) { 433 + pstr prompt_l[] = { _p("- new password for "), 434 + {0, acct}, _p(": "), }; 435 + char prompt[pstrsum(prompt_l, sz(prompt_l)) + 1]; 436 + if (tty_in) pstrcoll(prompt_l, sz(prompt_l), prompt); 437 + 438 + bad e = pwread(!print, pw, &pwlen, 439 + prompt, sz(prompt) - 1); 440 + if (e != ok) return e; 441 + if (tty_in && !print) { 442 + password pw_conf; 443 + e = pwread(true, pw_conf, NULL, _str("- confirm: ")); 444 + if (e != ok) return e; 445 + if (strcmp(pw,pw_conf) != 0) 446 + return bad_pw_match; 447 + } 448 + acct_pw = pw; 449 + } else acct_pw = prm; 450 + 451 + } else if (op == genpw) { 452 + unsigned long long len; 453 + if (prm != NULL) { 454 + alert(a_debug, "converting length parameter to integer"); 455 + bad e = katoi(10, prm, &len); 456 + if (e != ok) return bad_num; 457 + } else alert(a_debug, "using default password length"), 458 + len = default_pw_len; 459 + 460 + alert(a_debug, "generating new password"); 461 + mkpw(mode, pw, len); 462 + if (print || !tty_out) { 463 + write(1, pw, len); 464 + if(tty_out) write(1, "\n", 1); 465 + } 466 + pwlen = len; 467 + } 468 + if (copy_pw) copy(pw, pwlen); 469 + alert(a_debug, "enciphering password"); 470 + 370 471 break; 371 472 } 372 473 373 474 case delpw:{ /* kpw -d <acct> */ 374 475 break; 375 476 } 376 477 377 - case genpw:{ /* kpw -g[lmu] <acct> [<len>] */ 478 + case lspw: { /* kpw -t[p] [<prefix>] */ 378 479 break; 379 480 } 380 481 381 482 case createdb: { /* kpw -C [<db>] */ 382 483 alert(a_debug, "creating new database"); 383 484 if (clobber) 384 485 alert(a_warn, "will clobber any existing database"); 385 486 /* before we open our new file, we need to generate 386 487 * our keypairs. the private key will be encrypted 387 488 * with a blake2 hash of a user-supplied passphrase 388 489 * and stored in the database after the unencrypted 389 490 * public key. 390 491 */ 391 - uint8_t pub [crypto_box_PUBLICKEYBYTES], 392 - priv[crypto_box_SECRETKEYBYTES]; 492 + uint8_t pub [db_pubkey_len], 493 + priv[db_privkey_len]; 393 494 uint8_t priv_enc[sz(priv)]; 394 495 395 496 alert(a_debug, "generating keypair"); 396 497 crypto_box_keypair(pub, priv); 397 498 398 499 /* kpw works very differently compared to 399 500 * most password managers. it uses public-key ................................................................................ 400 501 * encryption so that new passwords can be saved 401 502 * to the db without bothering the user for the 402 503 * password. now we have our keypair, we can 403 504 * prompt the user for a secret passphrase with 404 505 * which to encrypt the private key with. 405 506 */ 406 507 407 - 408 508 alert(a_notice, "database keypair generated, encrypting"); 409 509 password dbpw; 410 510 size_t pwlen; 411 -# define _str(s) (s),sizeof(s) 412 - bad e = pwread(dbpw, &pwlen, _str("database passphrase: ")); 511 + bad e = pwread(!print, dbpw, &pwlen, _str("- database passphrase: ")); 413 512 if (e != ok) return e; 414 - if (isatty(0)) { 513 + if (!print && isatty(0)) { 415 514 password dbpw_conf; 416 - e = pwread(dbpw_conf, NULL, _str("confirm: ")); 417 -# undef _str 515 + e = pwread(!print, dbpw_conf, NULL, _str("- confirm: ")); 418 516 if (e != ok) return e; 419 517 420 518 if(strcmp(dbpw,dbpw_conf) != 0) 421 519 return bad_pw_match; 422 520 } 423 521 424 522 uint8_t salt[crypto_pwhash_SALTBYTES], ................................................................................ 442 540 crypto_box_seal(salt_enc, salt, sz(salt), priv); 443 541 444 542 /* we have everything we need. now we create the 445 543 * file, failing if it already exists so as not 446 544 * to clobber anyone's passwords. 447 545 */ 448 546 int db; 449 - const int flags = O_CREAT | (clobber ? O_TRUNC : O_EXCL); 547 + const int flags = O_CREAT | O_WRONLY | 548 + (clobber ? O_TRUNC : O_EXCL); 450 549 if(param == 0) 451 550 db = dbopen(flags); 452 551 else if (param == 1) 453 552 db = open(params[0], flags, 0600); 454 553 else return bad_syntax; 455 554 456 555 if (db == -1) return bad_db_create; 457 556 557 + /* the file is safely created; all that's left to 558 + * do is write out the header and then we can call 559 + * it a day. 560 + */ 458 561 write(db, pub, sz(pub)); 459 562 write(db, salt, sz(salt)); 460 563 write(db, priv_enc, sz(priv_enc)); 461 564 write(db, salt_enc, sz(salt_enc)); 462 565 close(db); 463 566 464 - for (int i = 0; i < sz(key); ++i) { 465 - printf("%2x ", key[i]); 466 - if (!((i+1)%8)) printf("\n"); 467 - } 567 + alert(a_debug, "database created"); 468 568 break; 469 569 } 470 570 } 471 571 472 -# ifdef _CLIPBOARD 473 - if (geteuid() == 0 && copy_pw) { 474 - /* on a sane system, what we'd do is hike up the process 475 - * tree til we found a non-root user. alas, this is UNIX. */ 476 - const char* realuser = getenv("SUDO_USER"); 477 - if (realuser == null) realuser = "nobody"; 478 - 479 - say("\x1b[1;33mwarning:\x1b[m you are running \x1b[4m"); 480 - size_t namelen = strlen(argv[0]); 481 - write(2,argv[0],namelen); 482 - say("\x1b[24m as \x1b[1mroot\x1b[m! dropping to \x1b[1m"); 483 - write(2,realuser,strlen(realuser)); 484 - setenv("USER", realuser, true); 485 - say("\x1b[m to prevent malicious behavior\n"); 486 - 487 - struct passwd* nobody = getpwnam(realuser); 488 - if (nobody == null) { 489 - say("\x1b[1;31mfatal:\x1b[m could not get UID to drop privileges; bailing"); 490 - return bad_user; 491 - } else { 492 - setenv("HOME", nobody -> pw_dir, true); 493 - setenv("SHELL", "/dev/null", true); 494 - setuid(nobody -> pw_uid); 495 - } 496 - 497 - } 498 -# endif 499 572 500 573 501 574 /* char buf[len+1]; */ 502 575 /* *buf = 0; */ 503 576 /* mkpw(mode,buf,len); */ 504 577 /* write(1, buf, len + 1); */ 505 578 506 579 # ifdef _CLIPBOARD 507 580 if (copy_pw) { 508 - copy(buf,len); 581 + /* copy(buf,len); */ 509 582 } 510 583 # endif 511 584 512 585 return ok; 513 586 } 514 587 515 588 int 516 589 main (int argc, const char** argv) { 590 + const char* colorterm = getenv("COLORTERM"); 591 + const char* term = getenv("TERM"); 592 + bool color, ansi; 593 + 594 + if (colorterm != NULL) 595 + color = true; 596 + else if (term == NULL) 597 + ansi = false, color = false; 598 + else if (strstr(term, "color") == NULL) 599 + ansi = true, color = false; 600 + else color = true; 601 + 602 + for (uint8_t i = 0; i < 3; ++i) { 603 + if(isatty(i)) { 604 + _g_term_type[i] = (color ? color_term : 605 + ansi ? ansi_term : plain_term); 606 + } else _g_term_type[i] = plain_term; 607 + } 608 + 609 + 517 610 int e = 0; 518 611 const char* msg; 519 612 uint16_t level; 520 613 uint8_t rv; 521 614 switch (e = kpw(argc, argv)) { 522 615 kpw_emit_error_switch 523 616 } 524 617 525 618 alert(level, msg); 526 619 return rv; 527 620 }
Modified kpw.d/optab from [4bfd28626b] to [652ae10981].
1 1 C create op = createdb create a new password database 2 -R rekey op = rekeydb change database passphrase and key 2 +R rekey op = rekeydb change database passphrase 3 3 a add op = addpw add password to the database 4 4 g gen op = genpw add account with a random password 5 5 d del op = delpw delete password from the database 6 +t list op = lspw list all accounts (with passwords if -p is set) 6 7 c chpw op = chpw change password in the database 7 8 l lower mode = lower generate lowercase password 8 9 m mix mode = mix generate mix-case password 9 10 u upper mode = upper generate uppercase password 10 11 s stupid mode = stupid circumvent dumb pw restrictions 11 12 k key op = keyin save database key in session memory 12 13 o logout op = logout delete db key from session memory 13 -n nocopy copy_pw = false don't copy generated pw to clipboard _CLIPBOARD 14 -p print print = true display generated password 14 +n no-copy copy_pw = false print password instead of copying to clipboard _CLIPBOARD 15 +p print print = true display passwords onscreen 15 16 q quiet _g_alert_quiet = true hide non-fatal reports 16 17 v verbose _g_debug_msgs = true display debug reports 17 18 ! clobber clobber = true disable safety checks
Modified kpw.d/optab.awk from [b43a4e1b77] to [7d6b5c7a46].
11 11 print "#define kpw_emit_short_option_switch \\" 12 12 end = "\\" 13 13 } else if (emit == "usage") { 14 14 print "const char kpw_usage[] =" 15 15 } 16 16 globalc = 0 17 17 } 18 - 18 +function cify(str) { 19 + gsub(/[- ]/, "_", str); 20 + return str; 21 +} 19 22 function say(line) { 20 23 if (NF == 5) { 21 24 print "\tkpw_only_" $5 "(" line ") " end 22 25 globals[globalc] = $5 23 26 ++ globalc 24 27 } else { 25 28 print "\t" line " " end 26 29 } 27 30 } 28 31 29 32 { optstr = optstr $1 } 30 -emit == "enum" { say("arg_" $2 ",") } 31 -emit == "argtbl" { say("{ arg_" $2", \"" $2 "\" },") } 32 -emit == "olong" { say("case arg_" $2 ": " $3 "; break;") } 33 +emit == "enum" { say("arg_" cify($2) ",") } 34 +emit == "argtbl" { say("{ arg_" cify($2)", \"" $2 "\" },") } 35 +emit == "olong" { say("case arg_" cify($2) ": " $3 "; break;") } 33 36 emit == "oshort" { say("case '" $1 "': " $3 "; break;") } 34 37 emit == "usage" { say("\"\\t-"$1", --"$2": "$4"\\n\"") } 35 38 36 39 emit == "cond" { 37 40 if (NF == 5 && !($5 in condlist)) { 38 41 condlist[$5] = 1 39 42 print "#ifdef " $5
Modified mkpw.c from [f1f30ece5b] to [9bb8a09cb3].
184 184 if (nobody == null) { 185 185 say("\x1b[1;31mfatal:\x1b[m could not get UID to drop privileges; bailing"); 186 186 return bad_user; 187 187 } else { 188 188 setenv("HOME", nobody -> pw_dir, true); 189 189 setenv("SHELL", "/dev/null", true); 190 190 setuid(nobody -> pw_uid); 191 + if (geteuid() == 0) 192 + say("\x1b[1;31mnice try:\x1b[m i don't fucking think so, you sneaky bastard"); 191 193 } 192 194 193 195 } 194 196 # endif 195 197 196 198 const unsigned char chars = (sizeof str_num - 1) + 197 199 ((mode == upper) ? (sizeof str_ucase - 1) :
Modified readme.md from [2e8787ac9f] to [dd56c0b568].
1 1 # util 2 2 various odds and ends. all code in this repository is licensed under the AGPL unless otherwise noted. 3 3 4 4 * **safekill.c**: utility to help keep from accidentally killing important windows; compile with `cc -Ofast safekill.c -lX11 -lc -osafekill` 5 5 * **bgrd.c**: it’s… a long story. just read the header. 6 +* **kpw**: an extremely simple, lightweight, secure password manager for POSIX OSes written in C. depends on libsodium for crypto primitives. compile with `make kpw`.