17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "lib.h"
884cc4cc720145bb3aa506543a96f7acad221370Timo Sirainen#include "dcrypt.h"
884cc4cc720145bb3aa506543a96f7acad221370Timo Sirainen#include "istream.h"
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen#include "istream-decrypt.h"
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen#include "dcrypt-iostream.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "doveadm-dump.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include <stdio.h>
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenstatic int get_digest(const char *digest,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen struct dcrypt_private_key **priv_key_r ATTR_UNUSED,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen const char **error_r ATTR_UNUSED,
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch void *context)
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch{
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch const char **digest_r = (const char**)context;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen *digest_r = t_strdup(digest);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen return 0;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen}
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainenstatic void dcrypt_istream_dump_metadata(const struct istream *stream)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen{
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen enum io_stream_encrypt_flags flags = i_stream_encrypt_get_flags(stream);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if ((flags & IO_STREAM_ENC_INTEGRITY_HMAC) != 0)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen printf("flags: IO_STREAM_ENC_INTEGRITY_HMAC\n");
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if ((flags & IO_STREAM_ENC_INTEGRITY_AEAD) != 0)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen printf("flags: IO_STREAM_ENC_INTEGRITY_AEAD\n");
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen if ((flags & IO_STREAM_ENC_INTEGRITY_NONE) != 0)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen printf("flags: IO_STREAM_ENC_INTEGRITY_NONE\n");
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if ((flags & IO_STREAM_ENC_VERSION_1) != 0)
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen printf("flags: IO_STREAM_ENC_VERSION_1\n");
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen enum decrypt_istream_format format = i_stream_encrypt_get_format(stream);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen switch (format) {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen case DECRYPT_FORMAT_V1:
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen printf("format: DECRYPT_FORMAT_V1\n");
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen break;
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen case DECRYPT_FORMAT_V2:
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen printf("format: DECRYPT_FORMAT_V2\n");
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen break;
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen }
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen}
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainenstatic bool dcrypt_file_dump_metadata(const char *filename, bool print)
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen{
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen bool ret = FALSE;
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen struct istream *is = i_stream_create_file(filename, IO_BLOCK_SIZE);
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen const char *key_digest = NULL;
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen struct istream *ds = i_stream_create_decrypt_callback(is,
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen get_digest, &key_digest);
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen ssize_t size = i_stream_read(ds);
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen i_assert(size < 0);
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen if (key_digest != NULL) {
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen ret = TRUE;
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen if (print) {
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen dcrypt_istream_dump_metadata(ds);
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen printf("decrypt key digest: %s\n", key_digest);
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen }
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen } else if (print && ds->stream_errno != 0) {
96e3a90451b495d8bedbe5dd731539269cb8c08dStephan Bosch i_error("read(%s) failed: %s",
96e3a90451b495d8bedbe5dd731539269cb8c08dStephan Bosch i_stream_get_name(ds),
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen i_stream_get_error(ds));
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen i_stream_unref(&ds);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen i_stream_unref(&is);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return ret;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen}
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenstatic bool test_dump_dcrypt_file(const char *path)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen{
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (!dcrypt_initialize("openssl", NULL, NULL))
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return FALSE;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen bool ret = dcrypt_file_dump_metadata(path, FALSE);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen dcrypt_deinitialize();
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return ret;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen}
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenstatic void cmd_dump_dcrypt_file(int argc ATTR_UNUSED, char *argv[])
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen{
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen const char *error = NULL;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (!dcrypt_initialize("openssl", NULL, &error))
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen i_fatal("dcrypt_initialize failed: %s", error);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen (void)dcrypt_file_dump_metadata(argv[1], TRUE);
994a2b017b5b7da97914baa1ef711b124c8d15a7Timo Sirainen dcrypt_deinitialize();
994a2b017b5b7da97914baa1ef711b124c8d15a7Timo Sirainen}
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
struct doveadm_cmd_dump doveadm_cmd_dump_dcrypt_file = {
"dcrypt-file",
test_dump_dcrypt_file,
cmd_dump_dcrypt_file
};