Explorar o código

[UI] Initial: Import private keys for DKIM/ARC

andryyy %!s(int64=8) %!d(string=hai) anos
pai
achega
744784cb62
Modificáronse 3 ficheiros con 144 adicións e 1 borrados
  1. 21 0
      data/web/admin.php
  2. 90 1
      data/web/inc/functions.dkim.inc.php
  3. 33 0
      data/web/json_api.php

+ 21 - 0
data/web/admin.php

@@ -230,6 +230,27 @@ $tfa_data = get_tfa();
           </div>
           <button class="btn btn-default" id="add_item" data-id="dkim" data-api-url='add/dkim' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
         </form>
+
+        <legend data-target="#import_dkim" style="margin-top:40px;cursor:pointer" data-toggle="collapse">↳ Import private key</legend>
+        <div id="import_dkim" class="collapse">
+        <form class="form" data-id="dkim_import" role="form" method="post">
+          <div class="form-group">
+            <label for="domain">Domain</label>
+            <input class="form-control" id="domain" name="domain" placeholder="example.org" required>
+          </div>
+          <div class="form-group">
+            <label for="domain">Selector</label>
+            <input class="form-control" id="dkim_selector" name="dkim_selector" value="dkim" required>
+          </div>
+          <div class="form-group">
+            <label for="private_key_file">Private key:</label>
+            <textarea class="form-control" rows="5" name="private_key_file" id="private_key_file" required placeholder="-----BEGIN RSA PRIVATE KEY-----
+XYZ
+-----END RSA PRIVATE KEY-----"></textarea>
+          </div>
+          <button class="btn btn-default" id="add_item" data-id="dkim_import" data-api-url='add/dkim_import' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> Import</button>
+        </form>
+        </div>
       </div>
     </div>
     

+ 90 - 1
data/web/inc/functions.dkim.inc.php

@@ -88,6 +88,84 @@ function dkim($_action, $_data = null) {
         return false;
       }
     break;
+    case 'import':
+      if ($_SESSION['mailcow_cc_role'] != "admin") {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['access_denied'])
+        );
+        return false;
+      }
+      $private_key_input = trim($_data['private_key_file']);
+      $private_key_normalized = preg_replace('~\r\n?~', "\n", $private_key_input);
+      $private_key = openssl_pkey_get_private($private_key_normalized);
+      if ($ssl_error = openssl_error_string()) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => 'Private key error: ' . $ssl_error
+        );
+        return false;
+      }
+      // Explode by nl
+      $pem_public_key_array = explode(PHP_EOL, trim(openssl_pkey_get_details($private_key)['key']));
+      // Remove first and last line/item
+      array_shift($pem_public_key_array);
+      array_pop($pem_public_key_array);
+      // Implode as single string
+      $pem_public_key = implode('', $pem_public_key_array);
+      $dkim_selector = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : 'dkim';
+      $domain	= $_data['domain'];
+      if (!is_valid_domain_name($domain)) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
+        );
+        return false;
+      }
+      if ($redis->hGet('DKIM_PUB_KEYS', $domain)) {
+          $_SESSION['return'] = array(
+            'type' => 'danger',
+            'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
+          );
+          return false;
+      }
+      if (!ctype_alnum($dkim_selector)) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => sprintf($lang['danger']['dkim_domain_or_sel_invalid'])
+        );
+        return false;
+      }
+      try {
+        $redis->hSet('DKIM_PUB_KEYS', $domain, $pem_public_key);
+        $redis->hSet('DKIM_SELECTORS', $domain, $dkim_selector);
+        $redis->hSet('DKIM_PRIV_KEYS', $dkim_selector . '.' . $domain, $private_key_normalized);
+      }
+      catch (RedisException $e) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => 'Redis: '.$e
+        );
+        return false;
+      }
+      unset($private_key_normalized);
+      unset($private_key);
+      unset($private_key_input);
+      try {
+      }
+      catch (RedisException $e) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => 'Redis: '.$e
+        );
+        return false;
+      }
+      $_SESSION['return'] = array(
+        'type' => 'success',
+        'msg' => sprintf($lang['success']['dkim_added'])
+      );
+      return true;
+    break;
     case 'details':
       if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
         return false;
@@ -95,7 +173,18 @@ function dkim($_action, $_data = null) {
       $dkimdata = array();
       if ($redis_dkim_key_data = $redis->hGet('DKIM_PUB_KEYS', $_data)) {
         $dkimdata['pubkey'] = $redis_dkim_key_data;
-        $dkimdata['length'] = (strlen($dkimdata['pubkey']) < 391) ? 1024 : 2048;
+        if (strlen($dkimdata['pubkey']) < 391) {
+          $dkimdata['length'] = "1024";
+        }
+        elseif (strlen($dkimdata['pubkey']) < 736) {
+          $dkimdata['length'] = "2048";
+        }
+        elseif (strlen($dkimdata['pubkey']) < 1416) {
+          $dkimdata['length'] = "4096";
+        }
+        else {
+          $dkimdata['length'] = ">= 8192";
+        }
         $dkimdata['dkim_txt'] = 'v=DKIM1;k=rsa;t=s;s=email;p=' . $redis_dkim_key_data;
         $dkimdata['dkim_selector'] = $redis->hGet('DKIM_SELECTORS', $_data);
       }

+ 33 - 0
data/web/json_api.php

@@ -390,6 +390,39 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
               ));
             }
           break;
+          case "dkim_import":
+            if (isset($_POST['attr'])) {
+              $attr = (array)json_decode($_POST['attr'], true);
+              if (dkim('import', $attr) === false) {
+                if (isset($_SESSION['return'])) {
+                  echo json_encode($_SESSION['return']);
+                }
+                else {
+                  echo json_encode(array(
+                    'type' => 'error',
+                    'msg' => 'Cannot add item'
+                  ));
+                }
+              }
+              else {
+                if (isset($_SESSION['return'])) {
+                  echo json_encode($_SESSION['return']);
+                }
+                else {
+                  echo json_encode(array(
+                    'type' => 'success',
+                    'msg' => 'Task completed'
+                  ));
+                }
+              }
+            }
+            else {
+              echo json_encode(array(
+                'type' => 'error',
+                'msg' => 'Cannot find attributes in post data'
+              ));
+            }
+          break;
           case "domain-admin":
             if (isset($_POST['attr'])) {
               $attr = (array)json_decode($_POST['attr'], true);