/src/lib-imap-urlauth/imap-urlauth-backend.c

https://github.com/dovecot/core · C · 175 lines · 149 code · 23 blank · 3 comment · 21 complexity · e413ee6d9a2bb9584151c662496b37aa MD5 · raw file

  1. /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
  2. #include "lib.h"
  3. #include "buffer.h"
  4. #include "hex-binary.h"
  5. #include "randgen.h"
  6. #include "mail-user.h"
  7. #include "mail-storage.h"
  8. #include "mailbox-list-iter.h"
  9. #include "imap-urlauth-private.h"
  10. #include "imap-urlauth-backend.h"
  11. #define IMAP_URLAUTH_KEY MAILBOX_ATTRIBUTE_PREFIX_DOVECOT"imap-urlauth"
  12. static int
  13. imap_urlauth_backend_trans_set_mailbox_key(struct mailbox *box,
  14. unsigned char mailbox_key_r[IMAP_URLAUTH_KEY_LEN],
  15. const char **client_error_r,
  16. enum mail_error *error_code_r)
  17. {
  18. struct mail_attribute_value urlauth_key;
  19. const char *mailbox_key_hex = NULL;
  20. int ret;
  21. if (mailbox_open(box) < 0) {
  22. *client_error_r = mailbox_get_last_error(box, error_code_r);
  23. return -1;
  24. }
  25. struct mailbox_transaction_context *t =
  26. mailbox_transaction_begin(box,
  27. MAILBOX_TRANSACTION_FLAG_EXTERNAL,
  28. __func__);
  29. /* create new key */
  30. random_fill(mailbox_key_r, IMAP_URLAUTH_KEY_LEN);
  31. mailbox_key_hex = binary_to_hex(mailbox_key_r,
  32. IMAP_URLAUTH_KEY_LEN);
  33. i_zero(&urlauth_key);
  34. urlauth_key.value = mailbox_key_hex;
  35. ret = mailbox_attribute_set(t, MAIL_ATTRIBUTE_TYPE_PRIVATE,
  36. IMAP_URLAUTH_KEY, &urlauth_key);
  37. if (mailbox_transaction_commit(&t) < 0) {
  38. *client_error_r = mailbox_get_last_error(box, error_code_r);
  39. ret = -1;
  40. }
  41. return ret;
  42. }
  43. static int
  44. imap_urlauth_backend_trans_get_mailbox_key(struct mailbox *box,
  45. bool create,
  46. unsigned char mailbox_key_r[IMAP_URLAUTH_KEY_LEN],
  47. const char **client_error_r,
  48. enum mail_error *error_code_r)
  49. {
  50. struct mail_user *user = mail_storage_get_user(mailbox_get_storage(box));
  51. struct mail_attribute_value urlauth_key;
  52. const char *mailbox_key_hex = NULL;
  53. buffer_t key_buf;
  54. int ret;
  55. *client_error_r = "Internal server error";
  56. *error_code_r = MAIL_ERROR_TEMP;
  57. ret = mailbox_attribute_get(box, MAIL_ATTRIBUTE_TYPE_PRIVATE,
  58. IMAP_URLAUTH_KEY, &urlauth_key);
  59. if (ret < 0)
  60. return -1;
  61. e_debug(user->event, "imap-urlauth: %skey found for mailbox %s",
  62. (ret > 0 ? "" : "no "), mailbox_get_vname(box));
  63. if (ret == 0) {
  64. if (!create)
  65. return 0;
  66. ret = imap_urlauth_backend_trans_set_mailbox_key(box,
  67. mailbox_key_r,
  68. client_error_r,
  69. error_code_r);
  70. if (ret < 0)
  71. return -1;
  72. e_debug(user->event, "imap-urlauth: created key for mailbox %s",
  73. mailbox_get_vname(box));
  74. } else {
  75. /* read existing key */
  76. buffer_create_from_data(&key_buf, mailbox_key_r,
  77. IMAP_URLAUTH_KEY_LEN);
  78. mailbox_key_hex = urlauth_key.value;
  79. if (strlen(mailbox_key_hex) != 2*IMAP_URLAUTH_KEY_LEN ||
  80. hex_to_binary(mailbox_key_hex, &key_buf) < 0 ||
  81. key_buf.used != IMAP_URLAUTH_KEY_LEN) {
  82. i_error("imap-urlauth: key found for mailbox %s is invalid",
  83. mailbox_get_vname(box));
  84. return -1;
  85. }
  86. }
  87. return 1;
  88. }
  89. int imap_urlauth_backend_get_mailbox_key(struct mailbox *box, bool create,
  90. unsigned char mailbox_key_r[IMAP_URLAUTH_KEY_LEN],
  91. const char **client_error_r,
  92. enum mail_error *error_code_r)
  93. {
  94. int ret;
  95. ret = imap_urlauth_backend_trans_get_mailbox_key(box, create,
  96. mailbox_key_r,
  97. client_error_r,
  98. error_code_r);
  99. return ret;
  100. }
  101. int imap_urlauth_backend_reset_mailbox_key(struct mailbox *box)
  102. {
  103. struct mailbox_transaction_context *t;
  104. int ret;
  105. t = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_EXTERNAL,
  106. __func__);
  107. ret = mailbox_attribute_unset(t, MAIL_ATTRIBUTE_TYPE_PRIVATE,
  108. IMAP_URLAUTH_KEY);
  109. if (mailbox_transaction_commit(&t) < 0)
  110. ret = -1;
  111. return ret;
  112. }
  113. static int imap_urlauth_backend_mailbox_reset_key(struct mailbox *box)
  114. {
  115. const char *errstr;
  116. enum mail_error error;
  117. if (mailbox_open(box) < 0) {
  118. errstr = mailbox_get_last_internal_error(box, &error);
  119. if (error == MAIL_ERROR_NOTFOUND || error == MAIL_ERROR_PERM)
  120. return 0;
  121. i_error("urlauth key reset: Couldn't open mailbox %s: %s",
  122. mailbox_get_vname(box), errstr);
  123. return -1;
  124. }
  125. return imap_urlauth_backend_reset_mailbox_key(box);
  126. }
  127. int imap_urlauth_backend_reset_all_keys(struct mail_user *user)
  128. {
  129. const char *const patterns[] = { "*", NULL };
  130. struct mailbox_list_iterate_context *iter;
  131. const struct mailbox_info *info;
  132. struct mailbox *box;
  133. int ret = 0;
  134. iter = mailbox_list_iter_init_namespaces(user->namespaces, patterns,
  135. MAIL_NAMESPACE_TYPE_MASK_ALL,
  136. MAILBOX_LIST_ITER_NO_AUTO_BOXES |
  137. MAILBOX_LIST_ITER_SKIP_ALIASES |
  138. MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
  139. while ((info = mailbox_list_iter_next(iter)) != NULL) {
  140. box = mailbox_alloc(info->ns->list, info->vname, 0);
  141. mailbox_set_reason(box, "URLAUTH reset all keys");
  142. if (imap_urlauth_backend_mailbox_reset_key(box) < 0)
  143. ret = -1;
  144. mailbox_free(&box);
  145. }
  146. if (mailbox_list_iter_deinit(&iter) < 0) {
  147. i_error("urlauth key reset: Couldn't iterate mailboxes: %s",
  148. mailbox_list_get_last_internal_error(user->namespaces->list, NULL));
  149. ret = -1;
  150. }
  151. return ret;
  152. }