Marius Cramer
2014-08-13 42539643c396f9d8865dcf9a51b13dc869709d16
commit | author | age
40e657 1 <?php
W 2
3 /*
4 Copyright (c) 2009, Falko Timme, Till Brehm, projektfarm Gmbh
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9
10     * Redistributions of source code must retain the above copyright notice,
11       this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright notice,
13       this list of conditions and the following disclaimer in the documentation
14       and/or other materials provided with the distribution.
15     * Neither the name of ISPConfig nor the names of its contributors
16       may be used to endorse or promote products derived from this software without
17       specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /*
32 TABLE STRUCTURE of the "named" database:
33
34 CREATE TABLE IF NOT EXISTS `records` (
35   `id` int(10) unsigned NOT NULL auto_increment,
36   `zone` varchar(255) NOT NULL,
37   `ttl` int(11) NOT NULL default '86400',
38   `type` varchar(255) NOT NULL,
39   `host` varchar(255) NOT NULL default '@',
40   `mx_priority` int(11) default NULL,
41   `data` text,
42   `primary_ns` varchar(255) default NULL,
43   `resp_contact` varchar(255) default NULL,
44   `serial` bigint(20) default NULL,
45   `refresh` int(11) default NULL,
46   `retry` int(11) default NULL,
47   `expire` int(11) default NULL,
48   `minimum` int(11) default NULL,
49   `ispconfig_id` int(11) NOT NULL,
50   PRIMARY KEY  (`id`),
51   KEY `type` (`type`),
52   KEY `host` (`host`),
53   KEY `zone` (`zone`)
54 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
55
56 CREATE TABLE IF NOT EXISTS `xfr` (
57   `id` int(11) NOT NULL auto_increment,
58   `zone` varchar(255) NOT NULL,
59   `client` varchar(255) NOT NULL,
60   `ispconfig_id` int(11) NOT NULL,
61   PRIMARY KEY  (`id`),
62   KEY `zone` (`zone`),
63   KEY `client` (`client`)
64 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
65
66 */
67
68 class bind_dlz_plugin {
7fe908 69
40e657 70     var $plugin_name = 'bind_dlz_plugin';
W 71     var $class_name  = 'bind_dlz_plugin';
7fe908 72
40e657 73     //* This function is called during ispconfig installation to determine
W 74     //  if a symlink shall be created for this plugin.
75     function onInstall()
76     {
77         global $conf;
7fe908 78
40e657 79         if(isset($conf['bind']['installed']) && $conf['bind']['installed'] == true) {
7fe908 80             // Temporarily disabled until the installer supports the automatic creation of the necessary
MC 81             // database or at least to select between filebased nd db based bind, as not all bind versions
c5e095 82             // support dlz out of the box. To enable this plugin manually, create a symlink from the plugins-enabled
T 83             // directory to this file in the plugins-available directory.
84             return false;
85             //return true;
40e657 86         } else {
W 87             return false;
88         }
7fe908 89
40e657 90     }
7fe908 91
40e657 92     /*
W 93          This function is called when the plugin is loaded
94     */
7fe908 95
MC 96     function onLoad()
40e657 97     {
W 98         global $app;
7fe908 99
40e657 100         /*
W 101         Register for the events
102         */
7fe908 103
40e657 104         //* SOA
7fe908 105         $app->plugins->registerEvent('dns_soa_insert', $this->plugin_name, 'soa_insert');
MC 106         $app->plugins->registerEvent('dns_soa_update', $this->plugin_name, 'soa_update');
107         $app->plugins->registerEvent('dns_soa_delete', $this->plugin_name, 'soa_delete');
108
40e657 109         //* RR
7fe908 110         $app->plugins->registerEvent('dns_rr_insert', $this->plugin_name, 'rr_insert');
MC 111         $app->plugins->registerEvent('dns_rr_update', $this->plugin_name, 'rr_update');
112         $app->plugins->registerEvent('dns_rr_delete', $this->plugin_name, 'rr_delete');
40e657 113     }
7fe908 114
MC 115
116     function soa_insert($event_name, $data)
40e657 117     {
W 118         global $app, $conf;
7fe908 119
40e657 120         if($data["new"]["active"] != 'Y') return;
7fe908 121
40e657 122         $origin = substr($data["new"]["origin"], 0, -1);
W 123         $ispconfig_id = $data["new"]["id"];
124         $serial = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$ispconfig_id);
125
126         $ttl = $data["new"]["ttl"];
7fe908 127
cc6568 128         //$_db = clone $app->db;
H 129         //$_db->dbName = 'named';
7fe908 130
cc6568 131         $app->db->query("INSERT INTO named.records (zone, ttl, type, primary_ns, resp_contact, serial, refresh, retry, expire, minimum, ispconfig_id) VALUES ".
7fe908 132             "('$origin', $ttl, 'SOA', '{$data["new"]["ns"]}', '{$data["new"]["mbox"]}', '{$serial["serial"]}', '{$serial["refresh"]}'," .
MC 133             "'{$serial["retry"]}', '{$serial["expire"]}', '{$serial["minimum"]}', $ispconfig_id)");
134         //unset($_db);
40e657 135     }
7fe908 136
MC 137     function soa_update($event_name, $data)
40e657 138     {
W 139         global $app, $conf;
7fe908 140
40e657 141         if($data["new"]["active"] != 'Y')
W 142         {
143             if($data["old"]["active"] != 'Y') return;
7fe908 144             $this->soa_delete($event_name, $data);
MC 145         }
146         else
40e657 147         {
W 148             if($data["old"]["active"] == 'Y')
149             {
150                 $origin = substr($data["new"]["origin"], 0, -1);
151                 $ispconfig_id = $data["new"]["id"];
152                 $serial = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$ispconfig_id);
153
154                 $ttl = $data["new"]["ttl"];
7fe908 155
cc6568 156                 //$_db = clone $app->db;
H 157                 //$_db->dbName = 'named';
7fe908 158
cc6568 159                 $app->db->query("UPDATE named.records SET zone = '$origin', ttl = $ttl, primary_ns = '{$data["new"]["ns"]}', resp_contact = '{$data["new"]["mbox"]}', ".
7fe908 160                     "serial = '{$serial["serial"]}', refresh = '{$serial["refresh"]}', retry = '{$serial["retry"]}', expire = '{$serial["expire"]}', ".
MC 161                     "minimum = '{$serial["minimum"]}' WHERE ispconfig_id = ".$data["new"]["id"]." AND type = 'SOA'");
cc6568 162                 //unset($_db);
7fe908 163             }
MC 164             else
40e657 165             {
7fe908 166                 $this->soa_insert($event_name, $data);
40e657 167                 $ispconfig_id = $data["new"]["id"];
7fe908 168
40e657 169                 if ($records = $app->db->queryAllRecords("SELECT * FROM dns_rr WHERE zone = $ispconfig_id AND active = 'Y'"))
W 170                 {
7fe908 171                     foreach($records as $record)
40e657 172                     {
W 173                         foreach ($record as $key => $val) {
174                             $data["new"][$key] = $val;
175                         }
176                         $this->rr_insert("dns_rr_insert", $data);
177                     }
178                 }
179             }
180         }
7fe908 181
40e657 182     }
7fe908 183
MC 184     function soa_delete($event_name, $data)
40e657 185     {
W 186         global $app, $conf;
7fe908 187
cc6568 188         //$_db = clone $app->db;
H 189         //$_db->dbName = 'named';
7fe908 190
4c842d 191         $app->db->query( "DELETE FROM named.dns_records WHERE zone = '".substr($data['old']['origin'], 0, -1)."'");
7fe908 192         //unset($_db);
40e657 193     }
7fe908 194
MC 195     function rr_insert($event_name, $data)
40e657 196     {
W 197         global $app, $conf;
198         if($data["new"]["active"] != 'Y') return;
7fe908 199
40e657 200         $zone = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$data["new"]["zone"]);
W 201         $origin = substr($zone["origin"], 0, -1);
202         $ispconfig_id = $data["new"]["id"];
7fe908 203
40e657 204         $type = $data["new"]["type"];
7fe908 205
40e657 206         if (substr($data["new"]["name"], -1) == '.') {
W 207             $name = substr($data["new"]["name"], 0, -1);
208         } else {
209             $name = ($data["new"]["name"] == "") ? $name = '@' : $data["new"]["name"];
210         }
7fe908 211
40e657 212         if ($name == $origin || $name == '') {
W 213             $name = '@';
214         }
7fe908 215
MC 216         switch ($type)
40e657 217         {
7fe908 218         case "CNAME":
MC 219         case "MX":
220         case "NS":
221         case "ALIAS":
222         case "PTR":
223         case "SRV":
224             if(substr($data["new"]["data"], -1) != '.'){
225                 $content = $data["new"]["data"] . '.';
226             } else {
40e657 227                 $content = $data["new"]["data"];
7fe908 228             }
MC 229             break;
230         case "HINFO":
231             $content = $data["new"]["data"];
232             $quote1 = strpos($content, '"');
233
234             if($quote1 !== FALSE) {
235                 $quote2 = strpos(substr($content, ($quote1 + 1)), '"');
236             }
237
238             if ($quote1 !== FALSE && $quote2 !== FALSE) {
239                 $text_between_quotes = str_replace(' ', '_', substr($content, ($quote1 + 1), (($quote2 - $quote1))));
240                 $content = $text_between_quotes.substr($content, ($quote2 + 2));
241             }
242             break;
243         default:
244             $content = $data["new"]["data"];
40e657 245         }
7fe908 246
40e657 247         $ttl = $data["new"]["ttl"];
7fe908 248
cc6568 249         //$_db = clone $app->db;
H 250         //$_db->dbName = 'named';
7fe908 251
40e657 252         if ($type == 'MX') {
cc6568 253             $app->db->query("INSERT INTO named.records (zone, ttl, type, host, mx_priority, data, ispconfig_id)".
7fe908 254                 " VALUES ('$origin', $ttl, '$type', '$name', {$data["new"]["aux"]}, '$content', $ispconfig_id)");
75cc84 255         } elseif ($type == 'SRV') {
TB 256             $app->db->query("INSERT INTO named.records (zone, ttl, type, data, ispconfig_id)".
257                 " VALUES ('$origin', $ttl, '$type', '{$data["new"]["aux"]} $content', $ispconfig_id)");
40e657 258         } else {
cc6568 259             $app->db->query("INSERT INTO named.records (zone, ttl, type, host, data, ispconfig_id)".
7fe908 260                 " VALUES ('$origin', $ttl, '$type', '$name', '$content', $ispconfig_id)");
40e657 261         }
W 262
cc6568 263         //unset($_db);
40e657 264     }
7fe908 265
MC 266     function rr_update($event_name, $data)
40e657 267     {
W 268         global $app, $conf;
7fe908 269
40e657 270         if ($data["new"]["active"] != 'Y')
W 271         {
272             if($data["old"]["active"] != 'Y') return;
7fe908 273             $this->rr_delete($event_name, $data);
40e657 274         }
W 275         else
276         {
277             if ($data["old"]["active"] == 'Y')
278             {
279                 $zone = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$data["new"]["zone"]);
280                 $origin = substr($zone["origin"], 0, -1);
281                 $ispconfig_id = $data["new"]["id"];
7fe908 282
MC 283                 $type = $data["new"]["type"];
284
40e657 285                 if (substr($data["new"]["name"], -1) == '.') {
W 286                     $name = substr($data["new"]["name"], 0, -1);
287                 } else {
288                     $name = ($data["new"]["name"] == "") ? $name = '@' : $data["new"]["name"];
289                 }
7fe908 290
40e657 291                 if ($name == $origin || $name == '') {
W 292                     $name = '@';
293                 }
294
7fe908 295                 switch ($type)
40e657 296                 {
7fe908 297                 case "CNAME":
MC 298                 case "MX":
299                 case "NS":
300                 case "ALIAS":
301                 case "PTR":
302                 case "SRV":
303                     if(substr($data["new"]["data"], -1) != '.'){
304                         $content = $data["new"]["data"] . '.';
305                     } else {
40e657 306                         $content = $data["new"]["data"];
7fe908 307                     }
MC 308                     break;
309                 case "HINFO":
310                     $content = $data["new"]["data"];
311                     $quote1 = strpos($content, '"');
312                     if($quote1 !== FALSE){
313                         $quote2 = strpos(substr($content, ($quote1 + 1)), '"');
314                     }
315                     if($quote1 !== FALSE && $quote2 !== FALSE){
316                         $text_between_quotes = str_replace(' ', '_', substr($content, ($quote1 + 1), (($quote2 - $quote1))));
317                         $content = $text_between_quotes.substr($content, ($quote2 + 2));
318                     }
319                     break;
320                 default:
321                     $content = $data["new"]["data"];
40e657 322                 }
7fe908 323
40e657 324                 $ttl = $data["new"]["ttl"];
W 325                 $prio = (int)$data["new"]["aux"];
7fe908 326
cc6568 327                 //$_db = clone $app->db;
H 328                 //$_db->dbName = 'named';
7fe908 329
40e657 330                 if ($type == 'MX') {
cc6568 331                     $app->db->query("UPDATE named.records SET zone = '$origin', ttl = $ttl, type = '$type', host = '$name', mx_priority = $prio, ".
7fe908 332                         "data = '$content' WHERE ispconfig_id = $ispconfig_id AND type != 'SOA'");
75cc84 333                 } elseif ($type == 'SRV') {
TB 334                     $app->db->query("UPDATE named.records SET zone = '$origin', ttl = $ttl, type = '$type', ".
335                         "data = '$prio $content' WHERE ispconfig_id = $ispconfig_id AND type != 'SOA'");
40e657 336                 } else {
cc6568 337                     $app->db->query("UPDATE named.records SET zone = '$origin', ttl = $ttl, type = '$type', host = '$name', ".
7fe908 338                         "data = '$content' WHERE ispconfig_id = $ispconfig_id AND type != 'SOA'");
40e657 339                 }
7fe908 340
cc6568 341                 //unset($_db);
40e657 342             } else {
7fe908 343                 $this->rr_insert($event_name, $data);
40e657 344             }
W 345         }
346     }
7fe908 347
MC 348     function rr_delete($event_name, $data) {
40e657 349         global $app, $conf;
7fe908 350
cc6568 351         //$_db = clone $app->db;
H 352         //$_db->dbName = 'named';
7fe908 353
4c842d 354         $app->db->query( "DELETE FROM named.dns_records WHERE type != 'SOA' AND zone = '".substr($data['old']['origin'], 0, -1)."'");
cc6568 355         //unset($_db);
40e657 356     }
7fe908 357
40e657 358 } // end class
c128b1 359 ?>