Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

cgdconfig -e and a couple of small improvements



Java-based console on one of my servers is so bad I can't enter
a passphrase correctly unless it echoed. The new -e option does
exactly this:

# cgdconfig -eC
/dev/wd0f's passphrase (echo):123456

While I was there I also changed a couple of small things:

- If a local buffer isn't long enough for _SC_PASS_MAX
  long passphrase, I allocate enough space dynamically.
- I changed getpass to getpass_r.
- The buffer is zeroes after use.

I'm going to commit the changes after I test them a bit.

Alex
Index: src/sbin/cgdconfig/cgdconfig.c
===================================================================
RCS file: /cvsroot/src/sbin/cgdconfig/cgdconfig.c,v
retrieving revision 1.41
diff -p -u -u -r1.41 cgdconfig.c
--- src/sbin/cgdconfig/cgdconfig.c	10 Jan 2017 20:45:19 -0000	1.41
+++ src/sbin/cgdconfig/cgdconfig.c	6 May 2018 18:51:23 -0000
@@ -89,9 +89,11 @@ int	nflag = 0;
 
 /* if pflag is set to PFLAG_STDIN read from stdin rather than getpass(3) */
 
-#define	PFLAG_GETPASS	0x01
-#define	PFLAG_STDIN	0x02
-int	pflag = PFLAG_GETPASS;
+#define	PFLAG_GETPASS		0x01
+#define	PFLAG_GETPASS_ECHO	0x02
+#define	PFLAG_GETPASS_MASK	0x03
+#define	PFLAG_STDIN		0x04
+static int	pflag = PFLAG_GETPASS;
 
 static int	configure(int, char **, struct params *, int);
 static int	configure_stdin(struct params *, int argc, char **);
@@ -199,7 +201,7 @@ main(int argc, char **argv)
 	p = params_new();
 	kg = NULL;
 
-	while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:lno:spuv")) != -1)
+	while ((ch = getopt(argc, argv, "CGUV:b:ef:gi:k:lno:spuv")) != -1)
 		switch (ch) {
 		case 'C':
 			set_action(&action, ACTION_CONFIGALL);
@@ -228,6 +230,9 @@ main(int argc, char **argv)
 				p = params_combine(p, tp);
 			}
 			break;
+		case 'e':
+			pflag = PFLAG_GETPASS_ECHO;
+			break;
 		case 'f':
 			if (cfile)
 				usage();
@@ -374,17 +379,29 @@ getkey_randomkey(const char *target, str
 static char *
 maybe_getpass(char *prompt)
 {
-	char	 buf[1024];
-	char	*p = buf;
-	char	*tmp;
+	char	 local_buf[1024];
+	char	*buf = local_buf, *p = NULL;
+	char	*tmp, *pass;
+	long	 buf_len = sizeof(local_buf), pass_max;
+
+	pass_max = sysconf(_SC_PASS_MAX);
+	if (pass_max >= buf_len) {
+		buf_len = pass_max + 1;
+		buf = emalloc(buf_len);
+	}
 
 	switch (pflag) {
 	case PFLAG_GETPASS:
-		p = getpass(prompt);
+		p = getpass_r(prompt, buf, buf_len);
+		break;
+
+	case PFLAG_GETPASS_ECHO:
+		p = getpassfd(prompt, buf, buf_len, NULL,
+		    GETPASS_ECHO|GETPASS_NEED_TTY, 0);
 		break;
 
 	case PFLAG_STDIN:
-		p = fgets(buf, sizeof(buf), stdin);
+		p = fgets(buf, buf_len, stdin);
 		if (p) {
 			tmp = strchr(p, '\n');
 			if (tmp)
@@ -399,7 +416,13 @@ maybe_getpass(char *prompt)
 	if (!p)
 		err(EXIT_FAILURE, "failed to read passphrase");
 
-	return estrdup(p);
+	pass = estrdup(p);
+	memset(buf, 0, buf_len);
+
+	if (buf != local_buf)
+		free(buf);
+
+	return pass;
 }
 
 /*ARGSUSED*/
@@ -420,7 +443,8 @@ getkey_pkcs5_pbkdf2(const char *target, 
 	char		 buf[1024];
 	u_int8_t	*tmp;
 
-	snprintf(buf, sizeof(buf), "%s's passphrase:", target);
+	snprintf(buf, sizeof(buf), "%s's passphrase%s:",
+	    target, pflag & PFLAG_GETPASS_ECHO ? " (echo)" : "");
 	passp = maybe_getpass(buf);
 	if (pkcs5_pbkdf2(&tmp, BITS2BYTES(keylen), (uint8_t *)passp,
 	    strlen(passp),
@@ -570,7 +594,9 @@ configure(int argc, char **argv, struct 
 	 * a password.
 	 */
 
-	for (kg = p->keygen; pflag == PFLAG_GETPASS && kg; kg = kg->next)
+	for (kg = p->keygen;
+	    (pflag & PFLAG_GETPASS_MASK) && kg;
+	    kg = kg->next)
 		if ((kg->kg_method == KEYGEN_PKCS5_PBKDF2_SHA1) ||
 		    (kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD )) {
 			loop = 1;


Home | Main Index | Thread Index | Old Index