changeset 20629:e23e2b702622

doveadm: add doveadm-dump-dcrypt-key
author Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi>
date Sat, 23 Jul 2016 23:40:15 +0300
parents c5438de8fc7f
children b1831491a9d7
files doc/man/doveadm-dump.1.in src/doveadm/Makefile.am src/doveadm/doveadm-dump-dcrypt-key.c src/doveadm/doveadm-dump.c src/doveadm/doveadm-dump.h
diffstat 5 files changed, 221 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/doc/man/doveadm-dump.1.in	Wed Aug 10 19:15:56 2016 +0300
+++ b/doc/man/doveadm-dump.1.in	Sat Jul 23 23:40:15 2016 +0300
@@ -58,6 +58,9 @@
 .B dcrypt-file
 Dump metadata of a dcrypt encrypted file.
 .TP
+.B dcrypt-key
+Dump metadata of a dcrypt key.
+.TP
 .B index
 \(rA dovecot.index, dovecot.map.index
 .TP
--- a/src/doveadm/Makefile.am	Wed Aug 10 19:15:56 2016 +0300
+++ b/src/doveadm/Makefile.am	Sat Jul 23 23:40:15 2016 +0300
@@ -114,6 +114,7 @@
 	doveadm-dump-mailboxlog.c \
 	doveadm-dump-thread.c \
 	doveadm-dump-dcrypt-file.c \
+	doveadm-dump-dcrypt-key.c \
 	doveadm-zlib.c
 
 common = \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-dump-dcrypt-key.c	Sat Jul 23 23:40:15 2016 +0300
@@ -0,0 +1,214 @@
+/* Copyright (c) 2016 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "dcrypt.h"
+#include "ostream-encrypt.h"
+#include "istream-private.h"
+#include "istream-decrypt.h"
+#include "doveadm-dump.h"
+#include "hex-binary.h"
+#include "buffer.h"
+#include "str.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define KEY_BUF_SIZE 4096
+
+static void dcrypt_dump_public_key_metadata(const char *buf)
+{
+	const char *error = NULL;
+	struct dcrypt_public_key *pub_key;
+
+	bool ret = dcrypt_key_load_public(&pub_key, buf, &error);
+	if (ret == FALSE) {
+		i_error("dcrypt_key_load_public: %s", error);
+		return;
+	}
+	enum dcrypt_key_type key_type = dcrypt_key_type_public(pub_key);
+	if (key_type == DCRYPT_KEY_RSA)
+		printf("key type: DCRYPT_KEY_RSA\n");
+	else if (key_type == DCRYPT_KEY_EC)
+		printf("key type: DCRYPT_KEY_EC\n");
+
+	string_t *hash = t_str_new(128);
+	if (!dcrypt_key_id_public(pub_key, "sha256", hash, &error)) {
+		i_error("dcrypt_key_id_public: %s", error);
+		goto out;
+	}
+	const char *v2_hash = binary_to_hex(hash->data, hash->used);
+	printf("v2 hash: %s\n", v2_hash);
+
+	if (key_type == DCRYPT_KEY_EC) {
+		buffer_set_used_size(hash, 0);
+		if (!dcrypt_key_id_public_old(pub_key, hash, &error))
+		{
+			i_error("dcrypt_key_id_public_old: %s", error);
+			goto out;
+		}
+		const char *v1_hash = binary_to_hex(hash->data, hash->used);
+		printf("v1 hash: %s\n", v1_hash);
+	}
+out:
+	dcrypt_key_unref_public(&pub_key);
+}
+
+static void dcrypt_dump_private_key_metadata(const char *buf)
+{
+	const char *error = NULL;
+	struct dcrypt_private_key *priv_key;
+
+	bool ret = dcrypt_key_load_private(&priv_key, buf, NULL, NULL,
+			&error);
+	if (ret == FALSE) {
+		i_error("dcrypt_key_load_private: %s", error);
+		return;
+	}
+	enum dcrypt_key_type key_type = dcrypt_key_type_private(priv_key);
+	if (key_type == DCRYPT_KEY_RSA)
+		printf("key type: DCRYPT_KEY_RSA\n");
+	else if (key_type == DCRYPT_KEY_EC)
+		printf("key type: DCRYPT_KEY_EC\n");
+
+	string_t *hash = t_str_new(128);
+	if (!dcrypt_key_id_private(priv_key, "sha256", hash, &error)) {
+		i_error("dcrypt_key_id_private: %s", error);
+		goto out;
+	}
+	const char *v2_hash = binary_to_hex(hash->data, hash->used);
+	printf("v2 hash: %s\n", v2_hash);
+
+	if (key_type == DCRYPT_KEY_EC) {
+		buffer_set_used_size(hash, 0);
+		if (!dcrypt_key_id_private_old(priv_key, hash, &error))
+		{
+			i_error("dcrypt_key_id_private_old: %s", error);
+			goto out;
+		}
+		const char *v1_hash = binary_to_hex(hash->data, hash->used);
+		printf("v1 hash: %s\n", v1_hash);
+	}
+out:
+	dcrypt_key_unref_private(&priv_key);
+}
+
+static bool dcrypt_key_dump_metadata(const char *filename, bool print)
+{
+	bool ret = TRUE;
+	int fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		if (print) i_error("open(%s) failed: %m", filename);
+		return FALSE;
+	}
+
+	char buf[KEY_BUF_SIZE+1];
+	ssize_t res = read(fd, buf, KEY_BUF_SIZE);
+	if (res < 0) {
+		if (print) i_error("read(%d) failed: %m", fd);
+		i_close_fd(&fd);
+		return FALSE;
+	}
+	i_close_fd(&fd);
+
+	buf[res] = '\0';
+	enum dcrypt_key_format format;
+	enum dcrypt_key_version version;
+	enum dcrypt_key_kind kind;
+	enum dcrypt_key_encryption_type encryption_type;
+	const char *encryption_key_hash;
+	const char *key_hash;
+	const char *error;
+
+	ret = dcrypt_key_string_get_info(buf, &format, &version,
+			&kind, &encryption_type, &encryption_key_hash,
+			&key_hash, &error);
+	if (ret == FALSE) {
+		if (print) i_error("dcrypt_key_string_get_info: %s", error);
+		return FALSE;
+	}
+	if (!print) return TRUE;
+
+	switch (format) {
+	case DCRYPT_FORMAT_PEM:
+		printf("format: DCRYPT_FORMAT_PEM\n");
+		break;
+	case DCRYPT_FORMAT_DOVECOT:
+		printf("format: DCRYPT_FORMAT_DOVECOT\n");
+		break;
+	}
+
+	switch (version) {
+	case DCRYPT_KEY_VERSION_1:
+		printf("version: DCRYPT_KEY_VERSION_1\n");
+		break;
+	case DCRYPT_KEY_VERSION_2:
+		printf("version: DCRYPT_KEY_VERSION_2\n");
+		break;
+	case DCRYPT_KEY_VERSION_NA:
+		printf("version: DCRYPT_KEY_VERSION_NA\n");
+		break;
+	}
+
+	switch (kind) {
+	case DCRYPT_KEY_KIND_PUBLIC:
+		printf("kind: DCRYPT_KEY_KIND_PUBLIC\n");
+		break;
+	case DCRYPT_KEY_KIND_PRIVATE:
+		printf("kind: DCRYPT_KEY_KIND_PRIVATE\n");
+		break;
+	}
+
+	switch (encryption_type) {
+	case DCRYPT_KEY_ENCRYPTION_TYPE_NONE:
+		printf("encryption_type: DCRYPT_KEY_ENCRYPTION_TYPE_NONE\n");
+		break;
+	case DCRYPT_KEY_ENCRYPTION_TYPE_KEY:
+		printf("encryption_type: DCRYPT_KEY_ENCRYPTION_TYPE_KEY\n");
+		break;
+	case DCRYPT_KEY_ENCRYPTION_TYPE_PASSWORD:
+		printf("encryption_type: DCRYPT_KEY_ENCRYPTION_TYPE_PASSWORD\n");
+		break;
+	}
+
+	if (encryption_key_hash != NULL)
+		printf("encryption_key_hash: %s\n", encryption_key_hash);
+	if (key_hash != NULL)
+		printf("key_hash: %s\n", key_hash);
+
+	switch (kind) {
+	case DCRYPT_KEY_KIND_PUBLIC:
+		dcrypt_dump_public_key_metadata(buf);
+		break;
+	case DCRYPT_KEY_KIND_PRIVATE:
+		if (encryption_type == DCRYPT_KEY_ENCRYPTION_TYPE_NONE)
+			dcrypt_dump_private_key_metadata(buf);
+		break;
+	}
+	return TRUE;
+}
+
+static bool test_dump_dcrypt_key(const char *path)
+{
+	if (!dcrypt_initialize("openssl", NULL, NULL))
+		return FALSE;
+	bool ret = dcrypt_key_dump_metadata(path, FALSE);
+	dcrypt_deinitialize();
+	return ret;
+}
+
+static void cmd_dump_dcrypt_key(int argc ATTR_UNUSED, char *argv[])
+{
+	const char *error = NULL;
+	if (!dcrypt_initialize("openssl", NULL, &error))
+		i_fatal("dcrypt_initialize: %s", error);
+	(void)dcrypt_key_dump_metadata(argv[1], TRUE);
+	dcrypt_deinitialize();
+}
+
+struct doveadm_cmd_dump doveadm_cmd_dump_dcrypt_key = {
+	"dcrypt-key",
+	test_dump_dcrypt_key,
+	cmd_dump_dcrypt_key
+};
--- a/src/doveadm/doveadm-dump.c	Wed Aug 10 19:15:56 2016 +0300
+++ b/src/doveadm/doveadm-dump.c	Sat Jul 23 23:40:15 2016 +0300
@@ -88,7 +88,8 @@
 	&doveadm_cmd_dump_mailboxlog,
 	&doveadm_cmd_dump_thread,
 	&doveadm_cmd_dump_zlib,
-	&doveadm_cmd_dump_dcrypt_file
+	&doveadm_cmd_dump_dcrypt_file,
+	&doveadm_cmd_dump_dcrypt_key
 };
 
 void print_dump_types(void)
--- a/src/doveadm/doveadm-dump.h	Wed Aug 10 19:15:56 2016 +0300
+++ b/src/doveadm/doveadm-dump.h	Sat Jul 23 23:40:15 2016 +0300
@@ -16,6 +16,7 @@
 extern struct doveadm_cmd_dump doveadm_cmd_dump_thread;
 extern struct doveadm_cmd_dump doveadm_cmd_dump_zlib;
 extern struct doveadm_cmd_dump doveadm_cmd_dump_dcrypt_file;
+extern struct doveadm_cmd_dump doveadm_cmd_dump_dcrypt_key;
 
 void doveadm_dump_register(const struct doveadm_cmd_dump *dump);