bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "lib.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "buffer.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "hex-binary.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "randgen.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "mail-user.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "mail-storage.h"
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen#include "mailbox-list-iter.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "imap-urlauth-private.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "imap-urlauth-backend.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
7b9197b917d6f546bfea70ba8a443e61de90242aTimo Sirainen#define IMAP_URLAUTH_KEY MAILBOX_ATTRIBUTE_PREFIX_DOVECOT"imap-urlauth"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenstatic int
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomiimap_urlauth_backend_trans_set_mailbox_key(struct mailbox *box,
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi unsigned char mailbox_key_r[IMAP_URLAUTH_KEY_LEN],
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi const char **error_r,
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi enum mail_error *error_code_r)
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi{
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi struct mail_attribute_value urlauth_key;
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi const char *mailbox_key_hex = NULL;
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi int ret;
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi if (mailbox_open(box) < 0) {
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi *error_r = mailbox_get_last_error(box, error_code_r);
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi return -1;
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi }
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi struct mailbox_transaction_context *t =
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi mailbox_transaction_begin(box,
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi MAILBOX_TRANSACTION_FLAG_EXTERNAL,
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi __func__);
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi /* create new key */
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi random_fill(mailbox_key_r, IMAP_URLAUTH_KEY_LEN);
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi mailbox_key_hex = binary_to_hex(mailbox_key_r,
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi IMAP_URLAUTH_KEY_LEN);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&urlauth_key);
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi urlauth_key.value = mailbox_key_hex;
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi ret = mailbox_attribute_set(t, MAIL_ATTRIBUTE_TYPE_PRIVATE,
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi IMAP_URLAUTH_KEY, &urlauth_key);
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi if (mailbox_transaction_commit(&t) < 0) {
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi *error_r = mailbox_get_last_error(box, error_code_r);
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi ret = -1;
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi }
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi return ret;
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi}
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomistatic int
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomiimap_urlauth_backend_trans_get_mailbox_key(struct mailbox *box,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen bool create,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen unsigned char mailbox_key_r[IMAP_URLAUTH_KEY_LEN],
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen const char **error_r,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen enum mail_error *error_code_r)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen struct mail_user *user = mail_storage_get_user(mailbox_get_storage(box));
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen struct mail_attribute_value urlauth_key;
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen const char *mailbox_key_hex = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch buffer_t key_buf;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
d49214c55881d251a54edddb117ca7735360addcTimo Sirainen *error_r = "Internal server error";
d49214c55881d251a54edddb117ca7735360addcTimo Sirainen *error_code_r = MAIL_ERROR_TEMP;
d49214c55881d251a54edddb117ca7735360addcTimo Sirainen
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi ret = mailbox_attribute_get(box, MAIL_ATTRIBUTE_TYPE_PRIVATE,
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen IMAP_URLAUTH_KEY, &urlauth_key);
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen if (ret < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen if (user->mail_debug) {
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen i_debug("imap-urlauth: %skey found for mailbox %s",
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen (ret > 0 ? "" : "no "), mailbox_get_vname(box));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (!create)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi ret = imap_urlauth_backend_trans_set_mailbox_key(box,
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi mailbox_key_r,
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi error_r,
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi error_code_r);
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen if (ret < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen if (user->mail_debug) {
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen i_debug("imap-urlauth: created key for mailbox %s",
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen mailbox_get_vname(box));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read existing key */
d49214c55881d251a54edddb117ca7735360addcTimo Sirainen buffer_create_from_data(&key_buf, mailbox_key_r,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_KEY_LEN);
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen mailbox_key_hex = urlauth_key.value;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strlen(mailbox_key_hex) != 2*IMAP_URLAUTH_KEY_LEN ||
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch hex_to_binary(mailbox_key_hex, &key_buf) < 0 ||
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch key_buf.used != IMAP_URLAUTH_KEY_LEN) {
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen i_error("imap-urlauth: key found for mailbox %s is invalid",
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen mailbox_get_vname(box));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenint imap_urlauth_backend_get_mailbox_key(struct mailbox *box, bool create,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen unsigned char mailbox_key_r[IMAP_URLAUTH_KEY_LEN],
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen const char **error_r,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen enum mail_error *error_code_r)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen{
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen int ret;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi ret = imap_urlauth_backend_trans_get_mailbox_key(box, create, mailbox_key_r, error_r, error_code_r);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return ret;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen}
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainenint imap_urlauth_backend_reset_mailbox_key(struct mailbox *box)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen struct mailbox_transaction_context *t;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen int ret;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi t = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_EXTERNAL,
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi __func__);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen ret = mailbox_attribute_unset(t, MAIL_ATTRIBUTE_TYPE_PRIVATE,
fd81c8f5a38df19d1ecdfd5d6605b114ab56841eTimo Sirainen IMAP_URLAUTH_KEY);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (mailbox_transaction_commit(&t) < 0)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen ret = -1;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return ret;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen}
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenstatic int imap_urlauth_backend_mailbox_reset_key(struct mailbox *box)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen{
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen const char *errstr;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen enum mail_error error;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (mailbox_open(box) < 0) {
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi errstr = mailbox_get_last_internal_error(box, &error);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (error == MAIL_ERROR_NOTFOUND || error == MAIL_ERROR_PERM)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return 0;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen i_error("urlauth key reset: Couldn't open mailbox %s: %s",
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen mailbox_get_vname(box), errstr);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return -1;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen }
fd81c8f5a38df19d1ecdfd5d6605b114ab56841eTimo Sirainen return imap_urlauth_backend_reset_mailbox_key(box);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainenint imap_urlauth_backend_reset_all_keys(struct mail_user *user)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen const char *const patterns[] = { "*", NULL };
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen struct mailbox_list_iterate_context *iter;
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen const struct mailbox_info *info;
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen struct mailbox *box;
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen int ret = 0;
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen iter = mailbox_list_iter_init_namespaces(user->namespaces, patterns,
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen MAIL_NAMESPACE_TYPE_MASK_ALL,
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen MAILBOX_LIST_ITER_NO_AUTO_BOXES |
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen MAILBOX_LIST_ITER_SKIP_ALIASES |
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen box = mailbox_alloc(info->ns->list, info->vname, 0);
61cf001f1944d92eb25f113ba4c08985d6e30d53Timo Sirainen mailbox_set_reason(box, "URLAUTH reset all keys");
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (imap_urlauth_backend_mailbox_reset_key(box) < 0)
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen ret = -1;
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen mailbox_free(&box);
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen }
168204692e01267b08ce69106331701669dea202Timo Sirainen if (mailbox_list_iter_deinit(&iter) < 0) {
168204692e01267b08ce69106331701669dea202Timo Sirainen i_error("urlauth key reset: Couldn't iterate mailboxes: %s",
d4847b921058734e0668bc7690465c91523d9ec0Martti Rannanjärvi mailbox_list_get_last_internal_error(user->namespaces->list, NULL));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = -1;
168204692e01267b08ce69106331701669dea202Timo Sirainen }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}