[lvm-devel] [PATCH 04/15] Add simple password helpers.

Milan Broz mbroz at redhat.com
Wed Jan 21 11:19:45 UTC 2009


These enable to read password from
	- terminal
	- standard input
	- file

(Key store handlers will use this.)

(Alternative is use some exported funtion provided
by some crypto library but I think we should
not rely here on external library.)

Signed-off-by: Milan Broz <mbroz at redhat.com>
---
 lib/Makefile.in        |    1 +
 lib/crypt/lvm-crypto.h |    6 ++
 lib/crypt/masterkey.c  |    3 +
 lib/crypt/password.c   |  127 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 137 insertions(+), 0 deletions(-)
 create mode 100644 lib/crypt/password.c

diff --git a/lib/Makefile.in b/lib/Makefile.in
index 9705580..d7b2bf2 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -38,6 +38,7 @@ SOURCES =\
 	commands/toolcontext.c \
 	config/config.c \
 	crypt/masterkey.c \
+	crypt/password.c \
 	datastruct/btree.c \
 	datastruct/str_list.c \
 	device/dev-cache.c \
diff --git a/lib/crypt/lvm-crypto.h b/lib/crypt/lvm-crypto.h
index 9690779..1a7825d 100644
--- a/lib/crypt/lvm-crypto.h
+++ b/lib/crypt/lvm-crypto.h
@@ -84,4 +84,10 @@ masterkey_t lvm_masterkeys_query(const struct id *id);
 int lvm_masterkeys_verify(struct crypto_store *cs, const char *key);
 int lvm_masterkeys_retrieve(const char *for_text, struct crypto_store *cs);
 
+/*
+ * Crypto Helper functions
+ */
+int lvm_set_password_dev(const char *password_file);
+int lvm_read_password(char *message, char *pass, size_t len);
+
 #endif
diff --git a/lib/crypt/masterkey.c b/lib/crypt/masterkey.c
index 6efefcd..c3870ca 100644
--- a/lib/crypt/masterkey.c
+++ b/lib/crypt/masterkey.c
@@ -126,6 +126,7 @@ out:
 
 int lvm_masterkeys_init()
 {
+	(void)lvm_set_password_dev(NULL);
 	//FIXME: clear keys?
 	if (_key_hash)
 		return 1;
@@ -140,6 +141,8 @@ int lvm_masterkeys_init()
 
 void lvm_masterkeys_destroy()
 {
+	(void)lvm_set_password_dev(NULL);
+
 	if (_key_hash) {
 		log_debug("Destroying master key cache (%u).", dm_hash_get_num_entries(_key_hash));
 		dm_hash_iter(_key_hash, (dm_hash_iterate_fn) _masterkeys_destroy_entry);
diff --git a/lib/crypt/password.c b/lib/crypt/password.c
new file mode 100644
index 0000000..a7f5a46
--- /dev/null
+++ b/lib/crypt/password.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Various password read helpers
+ */
+#include <fcntl.h>
+#include <termios.h>
+#include "lib.h"
+#include "lvm-crypto.h"
+
+/*
+ * File name where to read password form
+ */
+static char _password_dev_name[PATH_MAX+1];
+
+static int lvm_read_password_from_stdin(char *pass, size_t maxlen)
+{
+	int ret, fd = 0;
+
+	ret = read(fd, pass, maxlen);
+
+	if (ret > 0 && ret < maxlen)
+		pass[ret-1] = 0;
+
+	return ret;
+}
+
+static int lvm_read_password_from_tty(char *message, char *pass,
+				      size_t maxlen)
+{
+	struct termios term_orig, term_noecho;
+	int fd, ret = 0;
+
+	// FIXME: add timeout option
+	// FIXME: fail if not on compatible termial
+	// FIXME: support alternative imput (file)
+
+	if ((fd = open("/dev/tty", O_RDWR)) == -1)
+		return 0;
+
+	/*
+	 * Switch echo off
+	 */
+	if (tcgetattr(fd, &term_orig))
+		goto out_err;
+	memcpy(&term_noecho, &term_orig, sizeof(term_noecho));
+	term_noecho.c_lflag &= ~ECHO;
+	if (tcsetattr(fd, TCSAFLUSH, &term_noecho))
+		goto out_err;
+
+	if (message)
+		(void)write(fd, message, strlen(message));
+
+	ret = read(fd, pass, maxlen);
+
+	if (ret > 0 && ret < maxlen)
+		pass[ret-1] = 0;
+
+	(void)write(fd, "\n", 1);
+
+	(void)tcsetattr(fd, TCSAFLUSH, &term_orig);
+
+out_err:
+	(void)close(fd);
+
+	if (!ret)
+		log_error("Unable to get password from terminal.");
+
+	return ret;
+}
+
+static int lvm_read_password_from_file(const char *password_file,
+				      char *pass, size_t len)
+{
+	struct device *dev;
+	int r = 1;
+
+	if (!(dev = dev_create_file(password_file, NULL, NULL, 1)))
+		return 0;
+
+	if (!dev_open(dev)) {
+		log_error("Cannot open key file: %s", password_file);
+		return 0;
+	}
+
+	if (!dev_read(dev, 0, len, pass))
+		r = 0;
+
+	if (!dev_close(dev))
+		stack;
+
+	return r;
+}
+
+int lvm_set_password_dev(const char *password_file)
+{
+	if (!password_file)
+		memset(_password_dev_name, 0, sizeof(_password_dev_name));
+	else
+		strncpy(_password_dev_name, password_file, PATH_MAX);
+
+	//FIXME: verify file path?
+
+	return 1;
+}
+
+int lvm_read_password(char *message, char *pass, size_t len)
+{
+	if(!_password_dev_name[0])
+		return lvm_read_password_from_tty(message, pass, len);
+	else if(!strcmp(_password_dev_name, "-"))
+		return lvm_read_password_from_stdin(pass, len);
+
+	return lvm_read_password_from_file(_password_dev_name, pass, len);
+}
-- 
1.5.6.5




More information about the lvm-devel mailing list