util  Diff

Differences From Artifact [9379e84c9e]:

To Artifact [f38f0771ed]:


    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);