From 9b18966510771d9299e58c8922ece9df7dc90a81 Mon Sep 17 00:00:00 2001 From: Marius Cramer Date: Fri, 18 Oct 2013 08:34:20 +0200 Subject: [PATCH] Readded missing dkim files lost on migration --- interface/lib/classes/validate_dkim.inc.php | 79 +++++++++ interface/web/dns/dns_dkim_edit.php | 142 ++++++++++++++++ interface/web/dns/dns_dkim_get.php | 91 +++++++++++ interface/web/dns/form/dns_dkim.tform.php | 154 ++++++++++++++++++ interface/web/dns/lib/lang/en_dns_dkim.lng | 8 + interface/web/dns/templates/dns_dkim_edit.htm | 38 +++++ interface/web/js/dns_dkim.js | 73 +++++++++ interface/web/js/mail_domain_dkim.js | 72 ++++++++ .../web/mail/mail_domain_dkim_create.php | 99 +++++++++++ 9 files changed, 756 insertions(+) create mode 100644 interface/lib/classes/validate_dkim.inc.php create mode 100644 interface/web/dns/dns_dkim_edit.php create mode 100644 interface/web/dns/dns_dkim_get.php create mode 100644 interface/web/dns/form/dns_dkim.tform.php create mode 100644 interface/web/dns/lib/lang/en_dns_dkim.lng create mode 100644 interface/web/dns/templates/dns_dkim_edit.htm create mode 100644 interface/web/js/dns_dkim.js create mode 100644 interface/web/js/mail_domain_dkim.js create mode 100644 interface/web/mail/mail_domain_dkim_create.php diff --git a/interface/lib/classes/validate_dkim.inc.php b/interface/lib/classes/validate_dkim.inc.php new file mode 100644 index 0000000000..12c0945875 --- /dev/null +++ b/interface/lib/classes/validate_dkim.inc.php @@ -0,0 +1,79 @@ +tform->wordbook[$errmsg])) { + return $app->tform->wordbook[$errmsg]."
\r\n"; + } else { + return $errmsg."
\r\n"; + } + } + + /* Validator function for private DKIM-Key */ + function check_private_key($field_name, $field_value, $validator) { + $dkim_enabled=$_POST['dkim']; + if ($dkim_enabled == 'y') { + if (empty($field_value)) return $this->get_error($validator['errmsg']); + exec('echo '.escapeshellarg($field_value).'|openssl rsa -check',$output,$result); + if($result != 0) return $this->get_error($validator['errmsg']); + } + } + + /* Validator function for DKIM Path */ + function check_dkim_path($field_name, $field_value, $validator) { + if(empty($field_value)) return $this->get_error($validator['errmsg']); + if (substr(sprintf('%o', fileperms($field_value)),-3) <= 600) + return $this->get_error($validator['errmsg']); + } + + /* Check function for DNS-Template */ + function check_template($field_name, $field_value, $validator) { + $dkim=false; + foreach($field_value as $field ) { if($field == 'DKIM') $dkim=true; } + if ($dkim && $field_value[0]!='DOMAIN') return $this->get_error($validator['errmsg']); + } + + /* Validator function for $_POST */ + function validate_post($key,$value) { + switch ($key) { + case 'public': + if (preg_match("/(^-----BEGIN PUBLIC KEY-----)[a-zA-Z0-9\r\n\/\+=]{1,221}(-----END PUBLIC KEY-----(\n|\r)$)/",$value) === 1) { return true; } else { return false; } + break; + case 'private': + if (preg_match("/(^-----BEGIN RSA PRIVATE KEY-----)[a-zA-Z0-9\r\n\/\+=]{1,850}(-----END RSA PRIVATE KEY-----(\n|\r)$)/",$value) === 1) { return true; } else { return false; } + break; + } + } +} + diff --git a/interface/web/dns/dns_dkim_edit.php b/interface/web/dns/dns_dkim_edit.php new file mode 100644 index 0000000000..61b0bd7fb6 --- /dev/null +++ b/interface/web/dns/dns_dkim_edit.php @@ -0,0 +1,142 @@ +auth->check_module_permissions('dns'); + +// Loading classes +$app->uses('tpl,tform,tform_actions,validate_dns'); +$app->load('tform_actions'); + +class page_action extends tform_actions { + + function onShowNew() { + global $app, $conf; + // we will check only users, not admins + if($_SESSION["s"]["user"]["typ"] == 'user') { + + // Get the limits of the client + $client_group_id = $_SESSION["s"]["user"]["default_group"]; + $client = $app->db->queryOneRecord("SELECT limit_dns_record FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); + + // Check if the user may add another record. + if($client["limit_dns_record"] >= 0) { + $tmp = $app->db->queryOneRecord("SELECT count(id) as number FROM dns_rr WHERE sys_groupid = $client_group_id"); + if($tmp["number"] >= $client["limit_dns_record"]) { + $app->error($app->tform->wordbook["limit_dns_record_txt"]); + } + } + } + + parent::onShowNew(); + } + + function onSubmit() { + global $app, $conf; + // Get the parent soa record of the domain + $soa = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = '".$app->functions->intval($_POST["zone"])."' AND ".$app->tform->getAuthSQL('r')); + // Check if Domain belongs to user + if($soa["id"] != $_POST["zone"]) $app->tform->errorMessage .= $app->tform->wordbook["no_zone_perm"]; + + // Check the client limits, if user is not the admin + if($_SESSION["s"]["user"]["typ"] != 'admin') { // if user is not admin + // Get the limits of the client + $client_group_id = $_SESSION["s"]["user"]["default_group"]; + $client = $app->db->queryOneRecord("SELECT limit_dns_record FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id"); + // Check if the user may add another record. + if($this->id == 0 && $client["limit_dns_record"] >= 0) { + $tmp = $app->db->queryOneRecord("SELECT count(id) as number FROM dns_rr WHERE sys_groupid = $client_group_id"); + if($tmp["number"] >= $client["limit_dns_record"]) { + $app->error($app->tform->wordbook["limit_dns_record_txt"]); + } + } + } // end if user is not admin + + // Set the server ID of the rr record to the same server ID as the parent record. + $this->dataRecord["server_id"] = $soa["server_id"]; + + // add dkim-settings to the public-key in the txt-record + $this->dataRecord['data']='v=DKIM1; t=s; p='.$this->dataRecord['data']; + $this->dataRecord['name']='default._domainkey.'.$this->dataRecord['name']; + + // Update the serial number and timestamp of the RR record + $soa = $app->db->queryOneRecord("SELECT serial FROM dns_rr WHERE id = ".$this->id); + $this->dataRecord["serial"] = $app->validate_dns->increase_serial($soa["serial"]); + $this->dataRecord["stamp"] = date('Y-m-d H:i:s'); + + // check for duplicate entry + $check=$app->db->queryOneRecord("SELECT * FROM dns_rr WHERE zone = ".$this->dataRecord["zone"]." AND type = '".$this->dataRecord["type"]."' AND data ='".$this->dataRecord["data"]."' AND name = '".$this->dataRecord['name']."'"); + if ($check!='') $app->tform->errorMessage .= $app->tform->wordbook["record_exists_txt"]; + + parent::onSubmit(); + } + + function onAfterInsert() { + global $app, $conf; + + //* Set the sys_groupid of the rr record to be the same then the sys_groupid of the soa record + $soa = $app->db->queryOneRecord("SELECT sys_groupid,serial FROM dns_soa WHERE id = '".$app->functions->intval($this->dataRecord["zone"])."' AND ".$app->tform->getAuthSQL('r')); + $app->db->datalogUpdate('dns_rr', "sys_groupid = ".$soa['sys_groupid'], 'id', $this->id); + + //* Update the serial number of the SOA record + $soa_id = $app->functions->intval($_POST["zone"]); + $serial = $app->validate_dns->increase_serial($soa["serial"]); + $app->db->datalogUpdate('dns_soa', "serial = $serial", 'id', $soa_id); + } + + function onAfterUpdate() { + global $app, $conf; + + //* Update the serial number of the SOA record + $soa = $app->db->queryOneRecord("SELECT serial FROM dns_soa WHERE id = '".$app->functions->intval($this->dataRecord["zone"])."' AND ".$app->tform->getAuthSQL('r')); + $soa_id = $app->functions->intval($_POST["zone"]); + $serial = $app->validate_dns->increase_serial($soa["serial"]); + $app->db->datalogUpdate('dns_soa', "serial = $serial", 'id', $soa_id); + } +} + +$page = new page_action; +$page->onLoad(); + +?> diff --git a/interface/web/dns/dns_dkim_get.php b/interface/web/dns/dns_dkim_get.php new file mode 100644 index 0000000000..6b8b90b4c2 --- /dev/null +++ b/interface/web/dns/dns_dkim_get.php @@ -0,0 +1,91 @@ +auth->check_module_permissions('dns'); + +global $app, $conf; + +// Loading classes +$app->uses('tform,tform_actions'); + +header('Content-Type: text/xml; charset=utf-8'); +header('Cache-Control: must-revalidate, pre-check=0, no-store, no-cache, max-age=0, post-check=0'); + +/* + This function fix PHP's messing up POST input containing characters space, dot, + open square bracket and others to be compatible with with the deprecated register_globals +*/ +function getRealPOST() { + $pairs = explode("&", file_get_contents("php://input")); + $vars = array(); + foreach ($pairs as $pair) { + $nv = explode("=", $pair, 2); + $name = urldecode($nv[0]); + $value = $nv[1]; + $vars[$name] = $value; + } + return $vars; +} +function pub_key($pubkey) { + $public_key=''; + foreach($pubkey as $values) $public_key=$public_key.$values; + return $public_key; +} + +$_POST=getRealPost(); + +if (ctype_digit($_POST['zone'])) { + // Get the parent soa record of the domain + $soa = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = '".$app->db->quote($_POST['zone'])."' AND ".$app->tform->getAuthSQL('r')); + + $public_key=$app->db->queryOneRecord("SELECT dkim_public FROM mail_domain WHERE domain = '".substr_replace($soa['origin'],'',-1)."' AND ".$app->tform->getAuthSQL('r')); + + $public_key=pub_key($public_key); + + $public_key=str_replace(array('-----BEGIN PUBLIC KEY-----','-----END PUBLIC KEY-----',"\r","\n"),'',$public_key); + + echo "\n"; + echo "\n"; + echo "".$public_key."\n"; + echo "".$soa['origin']."\n"; + echo "\n"; +} +?> diff --git a/interface/web/dns/form/dns_dkim.tform.php b/interface/web/dns/form/dns_dkim.tform.php new file mode 100644 index 0000000000..ffeee58bf6 --- /dev/null +++ b/interface/web/dns/form/dns_dkim.tform.php @@ -0,0 +1,154 @@ + 0 id must match with id of current user +$form["auth_preset"]["groupid"] = 0; // 0 = default groupid of the user, > 0 id must match with groupid of current user +$form["auth_preset"]["perm_user"] = 'riud'; //r = read, i = insert, u = update, d = delete +$form["auth_preset"]["perm_group"] = 'riud'; //r = read, i = insert, u = update, d = delete +$form["auth_preset"]["perm_other"] = ''; //r = read, i = insert, u = update, d = delete + +$form["tabs"]['dns'] = array ( + 'title' => "DNS DKIM", + 'width' => 100, + 'template' => "templates/dns_dkim_edit.htm", + 'fields' => array ( + ################################## + # Begin Datatable fields + ################################## + 'server_id' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'SELECT', + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'zone' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'default' => @$app->functions->intval($_REQUEST["zone"]), + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'name' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'filters' => array( 0 => array( 'event' => 'SAVE', + 'type' => 'IDNTOASCII'), + 1 => array( 'event' => 'SHOW', + 'type' => 'IDNTOUTF8'), + 2 => array( 'event' => 'SAVE', + 'type' => 'TOLOWER') + ), + 'validators' => array ( 0 => array ( 'type' => 'REGEX', + 'regex' => '/^[\w\.\-]{0,255}$/', + 'errmsg'=> 'name_error_regex'), + ), + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'type' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => 'TXT', + 'value' => '', + 'width' => '5', + 'maxlength' => '5' + ), + 'data' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', + 'errmsg'=> 'data_error_empty'), + ), + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'ttl' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'default' => '86400', + 'value' => '', + 'width' => '10', + 'maxlength' => '10' + ), + 'active' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'CHECKBOX', + 'default' => 'Y', + 'value' => array(0 => 'N',1 => 'Y') + ), + 'stamp' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'serial' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'default' => '', + 'value' => '', + 'width' => '10', + 'maxlength' => '10' + ), + ################################## + # ENDE Datatable fields + ################################## + ) +); + + + +?> diff --git a/interface/web/dns/lib/lang/en_dns_dkim.lng b/interface/web/dns/lib/lang/en_dns_dkim.lng new file mode 100644 index 0000000000..526257e909 --- /dev/null +++ b/interface/web/dns/lib/lang/en_dns_dkim.lng @@ -0,0 +1,8 @@ + diff --git a/interface/web/dns/templates/dns_dkim_edit.htm b/interface/web/dns/templates/dns_dkim_edit.htm new file mode 100644 index 0000000000..cbf8db941a --- /dev/null +++ b/interface/web/dns/templates/dns_dkim_edit.htm @@ -0,0 +1,38 @@ +

+

+ +
+
+
+
+ + +
+
+ + +
+ +
+

{tmpl_var name='active_txt'}

+
+ {tmpl_var name='active'} +
+
+
+ + + + + +
+ +
+ + +
+
+ + + + diff --git a/interface/web/js/dns_dkim.js b/interface/web/js/dns_dkim.js new file mode 100644 index 0000000000..1294fd0249 --- /dev/null +++ b/interface/web/js/dns_dkim.js @@ -0,0 +1,73 @@ +/* +Copyright (c) 2007 - 2013, Till Brehm, projektfarm Gmbh +Copyright (c) 2013, Florian Schaal, info@schaal-24.de +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of ISPConfig nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +This Javascript is invoked by + * dns/templates/dns_dkim_edit.htm to get the public key +*/ + var request = false; + + function setRequest(zone) { + if (window.XMLHttpRequest) {request = new XMLHttpRequest();} + else if (window.ActiveXObject) { + try {request = new ActiveXObject('Msxml2.XMLHTTP');} + catch (e) { + try {request = new ActiveXObject('Microsoft.XMLHTTP');} + catch (e) {} + } + } + if (!request) { + alert("Error creating XMLHTTP-instance"); + return false; + } else { + request.open('POST', 'dns/dns_dkim_get.php', true); + request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + request.send('&zone='+zone); + request.onreadystatechange = interpretRequest; + } + } + + function interpretRequest() { + switch (request.readyState) { + case 4: + if (request.status != 200) {alert("Request done but NOK\nError:"+request.status);} + else { + document.getElementsByName('data')[0].value = request.responseXML.getElementsByTagName('data')[0].firstChild.nodeValue; + document.getElementsByName('name')[0].value = request.responseXML.getElementsByTagName('name')[0].firstChild.nodeValue; + } + break; + default: + break; + } + } + +var serverType = jQuery('#zone').val(); +setRequest(serverType); + + diff --git a/interface/web/js/mail_domain_dkim.js b/interface/web/js/mail_domain_dkim.js new file mode 100644 index 0000000000..b07abc4f3e --- /dev/null +++ b/interface/web/js/mail_domain_dkim.js @@ -0,0 +1,72 @@ +/* +Copyright (c) 2007 - 2013, Till Brehm, projektfarm Gmbh +Copyright (c) 2013, Florian Schaal, info@schaal-24.de +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of ISPConfig nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +This Javascript is invoked by + * mail/templates/mail_domain_edit.htm to show and/or create the key-pair +*/ + var request = false; + + function setRequest(action,value,privatekey) { + if (window.XMLHttpRequest) {request = new XMLHttpRequest();} + else if (window.ActiveXObject) { + try {request = new ActiveXObject('Msxml2.XMLHTTP');} + catch (e) { + try {request = new ActiveXObject('Microsoft.XMLHTTP');} + catch (e) {} + } + } + if (!request) { + alert("Error creating XMLHTTP-instance"); + return false; + } else { + request.open('POST', 'mail/mail_domain_dkim_create.php', true); + request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + request.send('domain='+value+'&action='+action+'&pkey='+privatekey); + request.onreadystatechange = interpretRequest; + } + } + + function interpretRequest() { + switch (request.readyState) { + case 4: + if (request.status != 200) {alert("Request done but NOK\nError:"+request.status);} + else { + document.getElementsByName('dkim_private')[0].value = request.responseXML.getElementsByTagName('privatekey')[0].firstChild.nodeValue; + document.getElementsByName('dkim_public')[0].value = request.responseXML.getElementsByTagName('publickey')[0].firstChild.nodeValue; + } + break; + default: + break; + } + } + +var serverType = jQuery('#dkim_private').val(); +setRequest('show','{tmpl_var name="domain"}',serverType); + diff --git a/interface/web/mail/mail_domain_dkim_create.php b/interface/web/mail/mail_domain_dkim_create.php new file mode 100644 index 0000000000..aab83a6d33 --- /dev/null +++ b/interface/web/mail/mail_domain_dkim_create.php @@ -0,0 +1,99 @@ +auth->check_module_permissions('mail'); + +header('Content-Type: text/xml; charset=utf-8'); +header('Cache-Control: must-revalidate, pre-check=0, no-store, no-cache, max-age=0, post-check=0'); + +/* + This function fix PHP's messing up POST input containing characters space, dot, + open square bracket and others to be compatible with with the deprecated register_globals +*/ +function getRealPOST() { + $pairs = explode("&", file_get_contents("php://input")); + $vars = array(); + foreach ($pairs as $pair) { + $nv = explode("=", $pair, 2); + $name = urldecode($nv[0]); + $value = $nv[1]; + $vars[$name] = $value; + } + return $vars; +} + +function pub_key($pubkey) { + $public_key=''; + foreach($pubkey as $values) $public_key=$public_key.$values."\n"; + return $public_key; +} +$_POST=getRealPOST(); + +switch ($_POST['action']) { + case 'create': /* create DKIM Private-key */ + exec('openssl rand -out /usr/local/ispconfig/server/temp/random-data.bin 4096',$output,$result); + exec('openssl genrsa -rand /usr/local/ispconfig/server/temp/random-data.bin 1024',$privkey,$result); + unlink("/usr/local/ispconfig/server/temp/random-data.bin"); + $private_key=''; + foreach($privkey as $values) $private_key=$private_key.$values."\n"; + if($validate_dkim->validate_post('private',$private_key)) { /* validate the $_POST-value */ + exec('echo '.escapeshellarg($private_key).'|openssl rsa -pubout -outform PEM',$pubkey,$result); + $public_key=pub_key($pubkey); + } else { $public_key='invalid key'; } + break; + case 'show': /* show the DNS-Record onLoad */ + $private_key=$_POST['pkey']; + if($validate_dkim->validate_post('private',$private_key)) { /* validate the $_POST-value */ + /* get the public-key */ + exec('echo '.escapeshellarg($private_key).'|openssl rsa -pubout -outform PEM',$pubkey,$result); + $public_key=pub_key($pubkey); + } else { $public_key='invalid key'; } + break; +} +echo "\n"; +echo "\n"; +echo "".$private_key."\n"; +echo "".$public_key."\n"; +echo "\n"; +?> -- GitLab