Commits

Michał Górny committed a5d2d32

Simplify password storage logic.

Store the password in a duplicated memory (using g_strdup()). Always
require the caller to finally free it using mirage_forget_password().
Use GIOChannel to read the password from stdin.

  • Participants
  • Parent commits 3f7cdaa

Comments (0)

Files changed (3)

File mirage-password.c

 #	include <assuan.h>
 #endif
 
-static const gint password_bufsize = 256;
-
-static gchar *buf = NULL;
-
 /* We use this ternary state like that:
  * - error means that something terrible has happened (I/O failure etc),
  * - success means requested operation succedeed,
 	failure
 } mirage_tristate_t;
 
+static gchar *mirage_current_password = NULL;
+
 void mirage_forget_password(void) {
-	if (buf) {
+	if (mirage_current_password) {
 		/* wipe out the buf */
-		memset(buf, 0, strlen(buf));
-		g_free(buf);
-		buf = NULL;
+		memset(mirage_current_password, 0, strlen(mirage_current_password));
+		g_free(mirage_current_password);
+		mirage_current_password = NULL;
 	}
 }
 
-static gboolean mirage_allocbuf(const gint size) {
-	buf = g_malloc(size ? size : password_bufsize);
-	return TRUE;
+void mirage_set_password(gchar* const pass) {
+	mirage_forget_password();
+	mirage_current_password = pass;
 }
 
 #ifdef HAVE_LIBASSUAN
 		return failure;
 	}
 
-	if (!mirage_allocbuf(rcvlen - 1)) {
-		assuan_release(ctx);
-		return error;
-	}
-	strncpy(buf, &rcvbuf[2], rcvlen - 2);
-	buf[rcvlen - 2] = 0;
+	mirage_set_password(g_strndup(&rcvbuf[2], rcvlen - 2));
 
 	/* and we should get one more 'OK' too; if we don't, we assume that connection was broken */
 	if (((err = assuan_read_line(ctx, &rcvbuf, &rcvlen))) != ASSUAN_No_Error) {
 
 #endif
 
-static gboolean mirage_echo(const gboolean newstate) {
+static gboolean mirage_echo(const int fd, const gboolean newstate) {
 #ifdef HAVE_TERMIOS
-	const gint fd = fileno(stdin);
 	struct termios term;
 
 	/* noecho state should have eaten a newline */
 }
 
 static mirage_tristate_t mirage_input_password_stdio(void) {
-	if (!mirage_allocbuf(0))
-		return error;
-
+	const int stdin_fileno = fileno(stdin);
 	/* disable the echo before the prompt as we may output error */
-	const gboolean echooff = mirage_echo(FALSE);
+	const gboolean echooff = mirage_echo(stdin_fileno, FALSE);
 
-	g_printerr("Please input password to the encrypted image: ");
+	GIOChannel *stdin_ch = g_io_channel_unix_new(stdin_fileno);
+	GError *err = NULL;
 
-	if (!fgets(buf, password_bufsize, stdin)) {
-		g_printerr("Password input failed\n");
-		mirage_forget_password();
+	g_printerr("Please input password for the encrypted image: ");
+
+	gchar *buf = NULL;
+	if (g_io_channel_read_line(stdin_ch, &buf, NULL, NULL, &err) == G_IO_STATUS_ERROR) {
 		if (echooff)
-			mirage_echo(TRUE);
+			mirage_echo(stdin_fileno, TRUE);
+		g_printerr("Password input failed: %s\n", err->message);
+		g_error_free(err);
+		g_io_channel_unref(stdin_ch);
 		return error;
 	}
+	g_io_channel_unref(stdin_ch);
 	if (echooff)
-		mirage_echo(TRUE);
+		mirage_echo(stdin_fileno, TRUE);
 
 	/* remove trailing newline */
-	const gint len = strlen(buf);
+	const gint len = buf ? strlen(buf) : 0;
 	gchar *last = &buf[len - 1];
 	gchar *plast = &buf[len - 2];
 
 	}
 
 	/* buf got wiped? */
-	if (!*buf) {
+	if (!buf || !*buf) {
 		g_printerr("No password supplied\n");
-		mirage_forget_password();
+		g_free(buf);
 		return failure;
 	}
 
+	mirage_set_password(buf);
 	return success;
 }
 
 const gchar* mirage_input_password(void) {
-	if (buf) /* password already there */
-		return buf;
+	if (mirage_current_password) /* password already there */
+		return mirage_current_password;
 
 #ifdef HAVE_LIBASSUAN
 	switch (mirage_input_password_pinentry()) {
 		case error: break;
-		case success: return buf;
+		case success: return mirage_current_password;
 		case failure: return NULL;
 	}
 #endif
 
 	switch (mirage_input_password_stdio()) {
 		case error: break;
-		case success: return buf;
+		case success: return mirage_current_password;
 		case failure: return NULL;
 	}
 
 	g_printerr("All supported methods of password input have failed\n");
 	return NULL;
 }
-
-gboolean mirage_set_password(const gchar* const pass) {
-	mirage_forget_password();
-
-	if (!mirage_allocbuf(strlen(pass) + 1))
-		return FALSE;
-
-	strcpy(buf, pass);
-
-	return TRUE;
-}

File mirage-password.h

 
 const gchar* mirage_input_password(void);
 void mirage_forget_password(void);
-gboolean mirage_set_password(const gchar* const pass);
+void mirage_set_password(const gchar* const pass);
 
 #endif

File mirage2iso.c

 			g_printerr("--force has no effect when --stdout in use\n");
 	}
 
-	if (passbuf) {
+	if (passbuf)
 		mirage_set_password(passbuf);
-		g_free(passbuf);
-	}
 
 	const gchar* in;
 	if (!newargv || !(in = newargv[0])) {
 		g_free(helpmsg);
 		g_option_context_free(opt);
 		g_strfreev(newargv);
+		mirage_forget_password();
 		return EX_USAGE;
 	}
 	g_option_context_free(opt);
 					g_printerr("Input file has .iso suffix and no output file specified\n"
 							"Either specify one or use --force to use '.iso.iso' output suffix\n");
 					g_strfreev(newargv);
+					mirage_forget_password();
 					return EX_USAGE;
 				}
 				ext = NULL;
 					g_printerr("No output file specified and guessed filename matches existing file:\n\t%s\n", outbuf);
 					g_free(outbuf);
 					g_strfreev(newargv);
+					mirage_forget_password();
 					return EX_USAGE;
 				}
 			}
 	} else if (use_stdout) {
 		g_printerr("Output file can't be specified with --stdout\n");
 		g_strfreev(newargv);
+		mirage_forget_password();
 		return EX_USAGE;
 	}
 
 	if (!miragewrap_init()) {
 		g_strfreev(newargv);
+		mirage_forget_password();
 		return EX_SOFTWARE;
 	}
 
 	if (!miragewrap_open(in, session_num)) {
 		miragewrap_free();
 		g_strfreev(newargv);
+		mirage_forget_password();
 		return EX_NOINPUT;
 	}
 	if (verbose)
 		if (ret != EX_OK && ret != EX_DATAERR) {
 			miragewrap_free();
 			g_strfreev(newargv);
+			mirage_forget_password();
 			return ret;
 		}
 	}
 
 	miragewrap_free();
 	g_strfreev(newargv);
+	mirage_forget_password();
 	return EX_OK;
 }