mail-crypt-key.c revision 156e2ce64bdacb1c5242f023a4b5e229d19510f9
/* Copyright (c) 2015-2016 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "dict.h"
#include "array.h"
#include "var-expand.h"
#include "mail-storage.h"
#include "mailbox-attribute.h"
#include "mail-crypt-common.h"
#include "mail-crypt-key.h"
#include "mail-crypt-plugin.h"
#include "mail-user.h"
#include "hex-binary.h"
#include "safe-memset.h"
#include "base64.h"
#include "sha2.h"
struct mail_crypt_key_cache_entry {
struct mail_crypt_key_cache_entry *next;
char *pubid;
/* this is lazily initialized */
struct dcrypt_keypair pair;
};
static
const char *pubid,
struct dcrypt_private_key **privkey_r,
struct dcrypt_public_key **pubkey_r)
{
{
return 1;
return 1;
i_unreached();
}
}
}
return 0;
}
static
const char *pubid,
struct dcrypt_private_key *privkey,
struct dcrypt_public_key *pubkey)
{
{
}
}
} else
i_unreached();
return;
}
}
/* not found */
struct mail_crypt_key_cache_entry *ent =
} else {
}
}
{
}
}
{
error_r))
return -1;
return -1;
}
return 0;
}
return 1;
}
{
error_r))
return -1;
return -1;
}
return 0;
}
return 1;
}
static
struct dcrypt_private_key **key_r,
const char **error_r)
{
struct mail_crypt_global_keys global_keys;
int ret = 0;
return -1;
}
/* see if we got a key */
struct dcrypt_private_key *key =
ret = 1;
}
return ret;
}
static
{
public ? PUBKEYS_PREFIX :
pubid);
return ret;
}
static
const char *data,
struct dcrypt_private_key **key_r,
const char **error_r)
{
enum dcrypt_key_kind key_kind;
int ret = 0;
/* see what the key needs for decrypting */
return -1;
}
if (key_kind != DCRYPT_KEY_KIND_PRIVATE) {
"Expected private key, got public key",
pubid);
return -1;
}
"Incorrect key hash %s stored",
key_hash);
return -1;
}
/* see if it needs decrypting */
if (enc_type == DCRYPT_KEY_ENCRYPTION_TYPE_NONE) {
/* no key or password */
} else if (enc_type == DCRYPT_KEY_ENCRYPTION_TYPE_PASSWORD) {
"Password not available",
pubid);
return -1;
}
} else if (enc_type == DCRYPT_KEY_ENCRYPTION_TYPE_KEY) {
/* last resort, look at environment */
"Private key %s not available:",
return -1;
} else if (ret < 0) {
return ret;
}
}
}
if (!res)
return -1;
return -1;
}
return 1;
}
struct dcrypt_private_key **key_r,
const char **error_r)
{
/* check cache */
return 1;
}
struct mail_attribute_value value;
struct dcrypt_private_key *key;
int ret;
if (ret < 0) {
shared ? "/shared/" :
"/priv/",
}
return ret;
}
return ret;
return 1;
}
struct dcrypt_private_key **key_r,
const char **error_r)
{
struct mail_attribute_value value;
int ret;
/* try retrieve currently active user key */
if (mailbox_open(box) < 0) {
"INBOX",
return -1;
}
&value)) <= 0) {
if (ret < 0) {
}
} else {
ret = 1;
}
} else
ret = 1;
/* try to open key */
if (ret > 0)
mailbox_free(&box);
return ret;
}
struct dcrypt_private_key **key_r,
const char **error_r)
{
struct mail_attribute_value value;
int ret;
/* get active key */
if (ret < 0) {
}
return ret;
}
}
static
int mail_crypt_set_private_key(struct mailbox_transaction_context *t,
struct dcrypt_public_key *enc_key,
struct dcrypt_private_key *key,
const char **error_r)
{
/* folder keys must be encrypted with some other key,
unless they are shared keys */
struct mail_attribute_value value;
int ret;
} else if (user_key &&
!= NULL) {
}
/* export key */
return -1;
}
/* store it */
value.last_change = 0;
if ((ret = mailbox_attribute_set(t,
&value)) < 0) {
}
return ret;
}
struct dcrypt_private_key *key,
const char **error_r)
{
struct mailbox_transaction_context *t;
int ret;
error_r)) < 0) {
return -1;
} else if (ret > 0) {
}
{
"generate user keypair without password or key";
return -1;
}
if (mailbox_open(box) < 0) {
"INBOX",
return -1;
}
t = mailbox_transaction_begin(box, 0);
error_r)) < 0) {
} else if ((ret = mailbox_transaction_commit(&t)) < 0) {
}
mailbox_free(&box);
return ret;
}
struct dcrypt_private_key *key,
struct dcrypt_public_key *user_key,
const char **error_r)
{
int ret;
struct mailbox_transaction_context *t;
t = mailbox_transaction_begin(box, 0);
} else if ((ret = mailbox_transaction_commit(&t)) < 0) {
}
return ret;
}
static
const char **error_r)
{
/* check cache */
return 1;
}
enum dcrypt_key_kind key_kind;
struct dcrypt_public_key *key;
struct mail_attribute_value value;
int ret;
if (ret < 0) {
}
return ret;
}
return -1;
}
if (key_kind != DCRYPT_KEY_KIND_PUBLIC) {
"Expected public key, got private key",
pubid);
return -1;
}
"Incorrect key hash %s stored",
return -1;
}
/* load the key */
return -1;
}
return -1;
}
return 1;
}
struct dcrypt_public_key **key_r,
const char **error_r)
{
struct mail_attribute_value value;
int ret;
/* try retrieve currently active user key */
if (mailbox_open(box) < 0) {
"INBOX",
return -1;
}
&value)) <= 0) {
if (ret < 0) {
}
} else {
}
mailbox_free(&box);
return ret;
}
struct dcrypt_public_key **key_r,
const char **error_r)
{
struct mail_attribute_value value;
int ret;
&value)) <= 0) {
if (ret < 0) {
}
return ret;
}
}
static
int mail_crypt_set_public_key(struct mailbox_transaction_context *t,
struct dcrypt_public_key *key,
const char **error_r)
{
struct mail_attribute_value value;
/* export key */
error_r)) {
return -1;
}
/* store it */
value.last_change = 0;
if (mailbox_attribute_set(t,
&value) < 0) {
"/shared",
return -1;
}
return 0;
}
struct dcrypt_public_key *key,
const char **error_r)
{
struct mailbox_transaction_context *t;
struct mail_attribute_value value;
int ret;
/* try retrieve currently active user key */
if (mailbox_open(box) < 0) {
"INBOX",
return -1;
}
t = mailbox_transaction_begin(box, 0);
error_r)) == 0) {
value.last_change = 0;
&value)) < 0) {
}
}
if (ret < 0) {
} else if (mailbox_transaction_commit(&t) < 0) {
ret = -1;
}
mailbox_free(&box);
return ret;
}
struct dcrypt_public_key *key,
const char **error_r)
{
int ret;
struct mailbox_transaction_context *t;
struct mail_attribute_value value;
t = mailbox_transaction_begin(box, 0);
error_r)) == 0) {
value.last_change = 0;
&value)) < 0) {
}
}
if (ret < 0) {
} else if (mailbox_transaction_commit(&t) < 0) {
ret = -1;
}
return ret;
}
static
const char *pubid,
struct dcrypt_private_key *privkey,
struct dcrypt_public_key *pubkey,
const char **error_r)
{
return -1;
return -1;
return 0;
}
static
const char *pubid,
struct dcrypt_private_key *privkey,
struct dcrypt_public_key *user_key,
struct dcrypt_public_key *pubkey,
const char **error_r)
{
error_r) < 0)
return -1;
return -1;
return 0;
}
const char *pubid,
struct dcrypt_private_key **key_r,
const char **error_r)
{
struct mail_attribute_value value;
int ret;
/* check cache */
return 1;
}
const char *hexname =
PRIVKEYS_PREFIX"%s/%s",
pubid);
if (ret < 0) {
return ret;
}
error_r);
} else {
return ret;
}
return 1;
}
int mail_crypt_box_set_shared_key(struct mailbox_transaction_context *t,
const char *pubid,
struct dcrypt_private_key *privkey,
const char *target_uid,
struct dcrypt_public_key *user_key,
const char **error_r)
{
struct mail_attribute_value value;
int ret;
const char *attr_name;
if (target_uid != NULL) {
/* hash target UID */
const char *hexname =
binary_to_hex((const unsigned char*)target_uid,
strlen(target_uid));
PRIVKEYS_PREFIX"%s/%s",
pubid);
} else {
PRIVKEYS_PREFIX"%s",
pubid);
}
return -1;
}
value.last_change = 0;
NULL));
}
return ret;
}
int mail_crypt_box_unset_shared_key(struct mailbox_transaction_context *t,
const char *pubid,
const char *target_uid,
const char **error_r)
{
int ret;
const char *hexname =
binary_to_hex((const unsigned char*)target_uid,
strlen(target_uid));
PRIVKEYS_PREFIX"%s/%s",
pubid);
attr_name)) <= 0) {
if (ret < 0) {
" /shared/%s): failed: %s",
NULL));
}
}
return ret;
}
static
int mail_crypt_generate_keypair(const char *curve,
struct dcrypt_keypair *pair_r,
const char **pubid_r,
const char **error_r)
{
return -1;
}
return -1;
}
error_r)) {
return -1;
}
return 0;
};
struct dcrypt_keypair *pair,
const char **pubid_r,
const char **error_r)
{
return -1;
}
return -1;
}
return 0;
}
struct dcrypt_keypair *pair,
struct dcrypt_public_key *user_key,
const char **pubid_r,
const char **error_r)
{
int ret;
&user_key,
error_r)) <= 0) {
if (ret < 0)
return ret;
/* generate keypair */
struct dcrypt_keypair user_pair;
const char *user_pubid;
error_r) < 0) {
return -1;
}
}
} else {
}
ret = 0;
/* failed */
error_r)) < 0) {
} else {
}
return ret;
}
enum mail_attribute_type type,
const char **error_r)
{
struct mailbox_attribute_iter *iter;
const char *key;
int ret;
}
if (ret < 0)
return ret;
}
const char **error_r)
{
struct mailbox_attribute_iter *iter;
const char *id;
int ret;
(void)mailbox_attribute_iter_deinit(&iter);
return -1;
} else if (ret > 0)
}
if (ret < 0)
return ret;
}
int mail_crypt_box_share_private_keys(struct mailbox_transaction_context *t,
struct dcrypt_public_key *dest_pub_key,
const char *dest_user,
const char **error_r)
{
int ret = 0;
ret = -1;
dest_pub_key, error_r)) < 0)
break;
}
return ret;
}
int
struct dcrypt_public_key **pub_r,
const char **error_r)
{
int ret;
struct dcrypt_keypair pair;
return -1;
}
} else
return ret;
return 0;
}
int
struct dcrypt_public_key **pub_r,
const char **error_r)
{
int ret;
struct dcrypt_public_key *user_key;
error_r) < 0) {
return -1;
}
struct dcrypt_keypair pair;
return -1;
}
} else
return ret;
return 0;
}
{
const char *env =
/* disabled by default */
/* enable unless specifically
requested not to */
switch (env[0]) {
case 'n':
case 'N':
case '0':
case 'f':
case 'F':
}
}
return ret;
}
static const struct mailbox_attribute_internal mailbox_internal_attributes[] = {
.key = BOX_CRYPT_PREFIX,
},
.key = BOX_CRYPT_PREFIX,
},
.key = USER_CRYPT_PREFIX,
},
.key = USER_CRYPT_PREFIX,
}
};
{
}