2
0

functions.dkim.inc.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <?php
  2. function dkim($_action, $_data = null) {
  3. global $redis;
  4. global $lang;
  5. switch ($_action) {
  6. case 'add':
  7. if ($_SESSION['mailcow_cc_role'] != "admin") {
  8. $_SESSION['return'] = array(
  9. 'type' => 'danger',
  10. 'msg' => sprintf($lang['danger']['access_denied'])
  11. );
  12. return false;
  13. }
  14. $key_length = intval($_data['key_size']);
  15. $dkim_selector = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : 'dkim';
  16. $domain = $_data['domain'];
  17. if (!is_valid_domain_name($domain) || !is_numeric($key_length)) {
  18. $_SESSION['return'] = array(
  19. 'type' => 'danger',
  20. 'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
  21. );
  22. return false;
  23. }
  24. if ($redis->hGet('DKIM_PUB_KEYS', $domain)) {
  25. $_SESSION['return'] = array(
  26. 'type' => 'danger',
  27. 'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
  28. );
  29. return false;
  30. }
  31. if (!ctype_alnum($dkim_selector)) {
  32. $_SESSION['return'] = array(
  33. 'type' => 'danger',
  34. 'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
  35. );
  36. return false;
  37. }
  38. $config = array(
  39. "digest_alg" => "sha256",
  40. "private_key_bits" => $key_length,
  41. "private_key_type" => OPENSSL_KEYTYPE_RSA,
  42. );
  43. if ($keypair_ressource = openssl_pkey_new($config)) {
  44. $key_details = openssl_pkey_get_details($keypair_ressource);
  45. $pubKey = implode(array_slice(
  46. array_filter(
  47. explode(PHP_EOL, $key_details['key'])
  48. ), 1, -1)
  49. );
  50. // Save public key and selector to redis
  51. try {
  52. $redis->hSet('DKIM_PUB_KEYS', $domain, $pubKey);
  53. $redis->hSet('DKIM_SELECTORS', $domain, $dkim_selector);
  54. }
  55. catch (RedisException $e) {
  56. $_SESSION['return'] = array(
  57. 'type' => 'danger',
  58. 'msg' => 'Redis: '.$e
  59. );
  60. return false;
  61. }
  62. // Export private key and save private key to redis
  63. openssl_pkey_export($keypair_ressource, $privKey);
  64. if (isset($privKey) && !empty($privKey)) {
  65. try {
  66. $redis->hSet('DKIM_PRIV_KEYS', $dkim_selector . '.' . $domain, trim($privKey));
  67. }
  68. catch (RedisException $e) {
  69. $_SESSION['return'] = array(
  70. 'type' => 'danger',
  71. 'msg' => 'Redis: '.$e
  72. );
  73. return false;
  74. }
  75. }
  76. $_SESSION['return'] = array(
  77. 'type' => 'success',
  78. 'msg' => sprintf($lang['success']['dkim_added'])
  79. );
  80. return true;
  81. }
  82. else {
  83. $_SESSION['return'] = array(
  84. 'type' => 'danger',
  85. 'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
  86. );
  87. return false;
  88. }
  89. break;
  90. case 'details':
  91. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
  92. return false;
  93. }
  94. $dkimdata = array();
  95. if ($redis_dkim_key_data = $redis->hGet('DKIM_PUB_KEYS', $_data)) {
  96. $dkimdata['pubkey'] = $redis_dkim_key_data;
  97. $dkimdata['length'] = (strlen($dkimdata['pubkey']) < 391) ? 1024 : 2048;
  98. $dkimdata['dkim_txt'] = 'v=DKIM1;k=rsa;t=s;s=email;p=' . $redis_dkim_key_data;
  99. $dkimdata['dkim_selector'] = $redis->hGet('DKIM_SELECTORS', $_data);
  100. }
  101. return $dkimdata;
  102. break;
  103. case 'blind':
  104. if ($_SESSION['mailcow_cc_role'] != "admin") {
  105. return false;
  106. }
  107. $blinddkim = array();
  108. foreach ($redis->hKeys('DKIM_PUB_KEYS') as $redis_dkim_domain) {
  109. $blinddkim[] = $redis_dkim_domain;
  110. }
  111. return array_diff($blinddkim, array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')));
  112. break;
  113. case 'delete':
  114. $domains = (array)$_data['domains'];
  115. if ($_SESSION['mailcow_cc_role'] != "admin") {
  116. $_SESSION['return'] = array(
  117. 'type' => 'danger',
  118. 'msg' => sprintf($lang['danger']['access_denied'])
  119. );
  120. return false;
  121. }
  122. foreach ($domains as $domain) {
  123. if (!is_valid_domain_name($domain)) {
  124. $_SESSION['return'] = array(
  125. 'type' => 'danger',
  126. 'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
  127. );
  128. return false;
  129. }
  130. try {
  131. $selector = $redis->hGet('DKIM_SELECTORS', $domain);
  132. $redis->hDel('DKIM_PUB_KEYS', $domain);
  133. $redis->hDel('DKIM_PRIV_KEYS', $selector . '.' . $domain);
  134. $redis->hDel('DKIM_SELECTORS', $domain);
  135. }
  136. catch (RedisException $e) {
  137. $_SESSION['return'] = array(
  138. 'type' => 'danger',
  139. 'msg' => 'Redis: '.$e
  140. );
  141. return false;
  142. }
  143. }
  144. $_SESSION['return'] = array(
  145. 'type' => 'success',
  146. 'msg' => sprintf($lang['success']['dkim_removed'], htmlspecialchars(implode(', ', $domains)))
  147. );
  148. break;
  149. }
  150. }