Marius Cramer
2015-08-06 37b29231e47a0c4458dc1c15d98588f16f07e1e2
commit | author | age
7dbea0 1 <?php
T 2
3 /*
4 Copyright (c) 2009, 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 class bind_plugin {
7fe908 32
7dbea0 33     var $plugin_name = 'bind_plugin';
T 34     var $class_name  = 'bind_plugin';
35     var $action = 'update';
7fe908 36
7dbea0 37     //* This function is called during ispconfig installation to determine
T 38     //  if a symlink shall be created for this plugin.
39     function onInstall() {
40         global $conf;
7fe908 41
4bd960 42         if(isset($conf['bind']['installed']) && $conf['bind']['installed'] == true && @is_link('/usr/local/ispconfig/server/mods-enabled/dns_module.inc.php')) {
7dbea0 43             return true;
T 44         } else {
45             return false;
46         }
7fe908 47
7dbea0 48     }
7fe908 49
MC 50
7dbea0 51     /*
T 52          This function is called when the plugin is loaded
53     */
7fe908 54
7dbea0 55     function onLoad() {
T 56         global $app;
7fe908 57
7dbea0 58         /*
T 59         Register for the events
60         */
a59731 61
7fe908 62         //* SOA
MC 63         $app->plugins->registerEvent('dns_soa_insert', $this->plugin_name, 'soa_insert');
64         $app->plugins->registerEvent('dns_soa_update', $this->plugin_name, 'soa_update');
65         $app->plugins->registerEvent('dns_soa_delete', $this->plugin_name, 'soa_delete');
66
67         //* SLAVE
68         $app->plugins->registerEvent('dns_slave_insert', $this->plugin_name, 'slave_insert');
69         $app->plugins->registerEvent('dns_slave_update', $this->plugin_name, 'slave_update');
70         $app->plugins->registerEvent('dns_slave_delete', $this->plugin_name, 'slave_delete');
71
7dbea0 72         //* RR
7fe908 73         $app->plugins->registerEvent('dns_rr_insert', $this->plugin_name, 'rr_insert');
MC 74         $app->plugins->registerEvent('dns_rr_update', $this->plugin_name, 'rr_update');
75         $app->plugins->registerEvent('dns_rr_delete', $this->plugin_name, 'rr_delete');
76
7dbea0 77     }
7fe908 78
MC 79
80     function soa_insert($event_name, $data) {
7dbea0 81         global $app, $conf;
7fe908 82
7dbea0 83         $this->action = 'insert';
7fe908 84         $this->soa_update($event_name, $data);
MC 85
7dbea0 86     }
7fe908 87
MC 88     function soa_update($event_name, $data) {
7dbea0 89         global $app, $conf;
7fe908 90
fc70a2 91         //* Load libraries
T 92         $app->uses("getconf,tpl");
7fe908 93
7dbea0 94         //* load the server configuration options
T 95         $dns_config = $app->getconf->get_server_config($conf["server_id"], 'dns');
7fe908 96
7dbea0 97         //* Write the domain file
fdb514 98         if(!empty($data['new']['id'])) {
8ee180 99             $tpl = new tpl();
T 100             $tpl->newTemplate("bind_pri.domain.master");
7fe908 101
8ee180 102             $zone = $data['new'];
T 103             $tpl->setVar($zone);
7fe908 104
cc7a82 105             $records = $app->db->queryAllRecords("SELECT * FROM dns_rr WHERE zone = ? AND active = 'Y'", $zone['id']);
615a0a 106             if(is_array($records) && !empty($records)){
T 107                 for($i=0;$i<sizeof($records);$i++){
108                     if($records[$i]['ttl'] == 0) $records[$i]['ttl'] = '';
42f822 109                     if($records[$i]['name'] == '') $records[$i]['name'] = '@';
793c77 110                     //* Split TXT records, if nescessary
TB 111                     if($records[$i]['type'] == 'TXT' && strlen($records[$i]['data']) > 255) {
112                         $records[$i]['data'] = implode('" "',str_split( $records[$i]['data'], 255));
113                     }
615a0a 114                 }
T 115             }
7fe908 116             $tpl->setLoop('zones', $records);
MC 117
4b88c2 118             //TODO : change this when distribution information has been integrated into server record
7fe908 119             if (file_exists('/etc/gentoo-release')) {
d907c0 120                 $filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/pri/'.str_replace("/", "_", substr($zone['origin'], 0, -1)));
7fe908 121             }
MC 122             else {
123                 $filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($zone['origin'], 0, -1)));
124             }
125
126             file_put_contents($filename, $tpl->grab());
8e725d 127             chown($filename, escapeshellcmd($dns_config['bind_user']));
J 128             chgrp($filename, escapeshellcmd($dns_config['bind_group']));
7fe908 129
f038c0 130             //* Check the zonefile
T 131             if(is_file($filename.'.err')) unlink($filename.'.err');
7fe908 132             exec('named-checkzone '.escapeshellarg($zone['origin']).' '.escapeshellarg($filename), $out, $return_status);
f038c0 133             if($return_status === 0) {
7fe908 134                 $app->log("Writing BIND domain file: ".$filename, LOGLEVEL_DEBUG);
f038c0 135             } else {
3fa443 136                 if($dns_config['disable_bind_log'] === 'y') {
FS 137                     $app->log("Writing BIND domain file failed: ".$filename." ".implode(' ', $out), LOGLEVEL_DEBUG);
138                 } else {
139                     $app->log("Writing BIND domain file failed: ".$filename." ".implode(' ', $out), LOGLEVEL_WARN);
140                 }
7fe908 141                 rename($filename, $filename.'.err');
f038c0 142             }
8ee180 143             unset($tpl);
T 144             unset($records);
a59ad3 145             unset($records_out);
8ee180 146             unset($zone);
T 147         }
7fe908 148
7dbea0 149         //* rebuild the named.conf file if the origin has changed or when the origin is inserted.
fc70a2 150         //if($this->action == 'insert' || $data['old']['origin'] != $data['new']['origin']) {
7fe908 151         $this->write_named_conf($data, $dns_config);
fc70a2 152         //}
7fe908 153
7dbea0 154         //* Delete old domain file, if domain name has been changed
T 155         if($data['old']['origin'] != $data['new']['origin']) {
4b88c2 156             //TODO : change this when distribution information has been integrated into server record
7fe908 157             if (file_exists('/etc/gentoo-release')) {
d907c0 158                 $filename = $dns_config['bind_zonefiles_dir'].'/pri/'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
7fe908 159             }
MC 160             else {
161                 $filename = $dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
162             }
163
f038c0 164             if(is_file($filename)) unlink($filename);
T 165             if(is_file($filename.'.err')) unlink($filename.'.err');
7dbea0 166         }
7fe908 167
eb64c3 168         //* Restart bind nameserver if update_acl is not empty, otherwise reload it
TB 169         if($data['new']['update_acl'] != '') {
170             $app->services->restartServiceDelayed('bind', 'restart');
171         } else {
172             $app->services->restartServiceDelayed('bind', 'reload');
173         }
7fe908 174
7dbea0 175     }
a59731 176
7fe908 177     function soa_delete($event_name, $data) {
a59731 178         global $app, $conf;
7fe908 179
MC 180         //* load the server configuration options
181         $app->uses("getconf,tpl");
182         $dns_config = $app->getconf->get_server_config($conf["server_id"], 'dns');
183
184         //* rebuild the named.conf file
185         $this->write_named_conf($data, $dns_config);
186
187         //* Delete the domain file
188         //TODO : change this when distribution information has been integrated into server record
189         if (file_exists('/etc/gentoo-release')) {
190             $zone_file_name = $dns_config['bind_zonefiles_dir'].'/pri/'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
191         }
192         else {
193             $zone_file_name = $dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
194         }
195
196         if(is_file($zone_file_name)) unlink($zone_file_name);
197         if(is_file($zone_file_name.'.err')) unlink($zone_file_name.'.err');
198         $app->log("Deleting BIND domain file: ".$zone_file_name, LOGLEVEL_DEBUG);
199
200         //* Reload bind nameserver
201         $app->services->restartServiceDelayed('bind', 'reload');
202
a59731 203     }
7fe908 204
MC 205     function slave_insert($event_name, $data) {
a59731 206         global $app, $conf;
7fe908 207
MC 208         $this->action = 'insert';
209         $this->slave_update($event_name, $data);
210
211     }
212
213     function slave_update($event_name, $data) {
214         global $app, $conf;
215
a59731 216         //* Load libraries
D 217         $app->uses("getconf,tpl");
7fe908 218
a59731 219         //* load the server configuration options
D 220         $dns_config = $app->getconf->get_server_config($conf["server_id"], 'dns');
7fe908 221
a59731 222         //* rebuild the named.conf file if the origin has changed or when the origin is inserted.
D 223         //if($this->action == 'insert' || $data['old']['origin'] != $data['new']['origin']) {
7fe908 224         $this->write_named_conf($data, $dns_config);
a59731 225         //}
7fe908 226
a59731 227         //* Delete old domain file, if domain name has been changed
D 228         if($data['old']['origin'] != $data['new']['origin']) {
4b88c2 229             //TODO : change this when distribution information has been integrated into server record
7fe908 230             if (file_exists('/etc/gentoo-release')) {
MC 231                 $filename = $dns_config['bind_zonefiles_dir'].'/sec/'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
232             }
233             else {
234                 $filename = $dns_config['bind_zonefiles_dir'].'/slave/sec.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
235             }
236
a59731 237             if(is_file($filename)) unset($filename);
D 238         }
7fe908 239
355efb 240         //* Ensure that the named slave directory is writable by the named user
T 241         if (file_exists('/etc/gentoo-release')) {
242             $slave_record_dir = $dns_config['bind_zonefiles_dir'].'/sec';
243         } else {
244             $slave_record_dir = $dns_config['bind_zonefiles_dir'].'/slave';
245         }
7fe908 246         if(!@is_dir($slave_record_dir)) mkdir($slave_record_dir, 0770);
MC 247         chown($slave_record_dir, $dns_config['bind_user']);
248         chgrp($slave_record_dir, $dns_config['bind_group']);
249
a59731 250         //* Reload bind nameserver
7fe908 251         $app->services->restartServiceDelayed('bind', 'reload');
MC 252
a59731 253     }
7fe908 254
MC 255     function slave_delete($event_name, $data) {
a59731 256         global $app, $conf;
7fe908 257
MC 258
a59731 259         //* load the server configuration options
D 260         $app->uses("getconf,tpl");
261         $dns_config = $app->getconf->get_server_config($conf["server_id"], 'dns');
7fe908 262
a59731 263         //* rebuild the named.conf file
7fe908 264         $this->write_named_conf($data, $dns_config);
MC 265
a59731 266         //* Delete the domain file
4b88c2 267         //TODO : change this when distribution information has been integrated into server record
7fe908 268         if (file_exists('/etc/gentoo-release')) {
MC 269             $zone_file_name = $dns_config['bind_zonefiles_dir'].'/sec/'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
270         }
271         else {
272             $zone_file_name = $dns_config['bind_zonefiles_dir'].'/slave/sec.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
273         }
274
a59731 275         if(is_file($zone_file_name)) unlink($zone_file_name);
7fe908 276         $app->log("Deleting BIND domain file for secondary zone: ".$zone_file_name, LOGLEVEL_DEBUG);
MC 277
a59731 278         //* Reload bind nameserver
7fe908 279         $app->services->restartServiceDelayed('bind', 'reload');
MC 280
7dbea0 281
T 282     }
7fe908 283
MC 284     function rr_insert($event_name, $data) {
7dbea0 285         global $app, $conf;
7fe908 286
7dbea0 287         //* Get the data of the soa and call soa_update
cc7a82 288         $tmp = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ?", $data['new']['zone']);
7dbea0 289         $data["new"] = $tmp;
T 290         $data["old"] = $tmp;
291         $this->action = 'update';
7fe908 292         $this->soa_update($event_name, $data);
MC 293
7dbea0 294     }
7fe908 295
MC 296     function rr_update($event_name, $data) {
7dbea0 297         global $app, $conf;
7fe908 298
MC 299         //* Get the data of the soa and call soa_update
cc7a82 300         $tmp = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ?", $data['new']['zone']);
7fe908 301         $data["new"] = $tmp;
MC 302         $data["old"] = $tmp;
303         $this->action = 'update';
304         $this->soa_update($event_name, $data);
305
306     }
307
308     function rr_delete($event_name, $data) {
309         global $app, $conf;
310
7dbea0 311         //* Get the data of the soa and call soa_update
cc7a82 312         $tmp = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ?", $data['old']['zone']);
7dbea0 313         $data["new"] = $tmp;
T 314         $data["old"] = $tmp;
315         $this->action = 'update';
7fe908 316         $this->soa_update($event_name, $data);
MC 317
7dbea0 318     }
7fe908 319
MC 320     //##################################################################
321
7dbea0 322     function write_named_conf($data, $dns_config) {
T 323         global $app, $conf;
7fe908 324
MC 325         //* Only write the master file for the current server
cc7a82 326         $tmps = $app->db->queryAllRecords("SELECT origin, xfer, also_notify, update_acl FROM dns_soa WHERE active = 'Y' AND server_id=?", $conf["server_id"]);
fc70a2 327         $zones = array();
7fe908 328
957aaf 329         //* Check if the current zone that triggered this function has at least one NS record
7fe908 330
4b88c2 331         //TODO : change this when distribution information has been integrated into server record
7fe908 332         if (file_exists('/etc/gentoo-release')) {
MC 333             $pri_zonefiles_path = $dns_config['bind_zonefiles_dir'].'/pri/';
334             $sec_zonefiles_path = $dns_config['bind_zonefiles_dir'].'/sec/';
335
336         }
337         else {
338             $pri_zonefiles_path = $dns_config['bind_zonefiles_dir'].'/pri.';
339             $sec_zonefiles_path = $dns_config['bind_zonefiles_dir'].'/slave/sec.';
340         }
a59ad3 341
957aaf 342         //* Loop trough zones
fc70a2 343         foreach($tmps as $tmp) {
7fe908 344
MC 345             $zone_file = $pri_zonefiles_path.str_replace("/", "_", substr($tmp['origin'], 0, -1));
346
a59ad3 347             $options = '';
a59731 348             if(trim($tmp['xfer']) != '') {
7fe908 349                 $options .= "        allow-transfer {".str_replace(',', ';', $tmp['xfer']).";};\n";
a59731 350             } else {
D 351                 $options .= "        allow-transfer {none;};\n";
352             }
7fe908 353             if(trim($tmp['also_notify']) != '') $options .= '        also-notify {'.str_replace(',', ';', $tmp['also_notify']).";};\n";
MC 354             if(trim($tmp['update_acl']) != '') $options .= "        allow-update {".str_replace(',', ';', $tmp['update_acl']).";};\n";
355
f038c0 356             if(file_exists($zone_file)) {
7fe908 357                 $zones[] = array( 'zone' => substr($tmp['origin'], 0, -1),
MC 358                     'zonefile_path' => $zone_file,
359                     'options' => $options
360                 );
957aaf 361             }
fc70a2 362         }
a59731 363
7dbea0 364         $tpl = new tpl();
T 365         $tpl->newTemplate("bind_named.conf.local.master");
7fe908 366         $tpl->setLoop('zones', $zones);
MC 367
a59731 368         //* And loop through the secondary zones, but only for the current server
cc7a82 369         $tmps_sec = $app->db->queryAllRecords("SELECT origin, xfer, ns FROM dns_slave WHERE active = 'Y' AND server_id=?", $conf["server_id"]);
a59731 370         $zones_sec = array();
D 371
372         foreach($tmps_sec as $tmp) {
7fe908 373
a59731 374             $options = "        masters {".$tmp['ns'].";};\n";
7fe908 375             if(trim($tmp['xfer']) != '') {
MC 376                 $options .= "        allow-transfer {".str_replace(',', ';', $tmp['xfer']).";};\n";
377             } else {
378                 $options .= "        allow-transfer {none;};\n";
379             }
a59731 380
D 381
7fe908 382             $zones_sec[] = array( 'zone' => substr($tmp['origin'], 0, -1),
MC 383                 'zonefile_path' => $sec_zonefiles_path.str_replace("/", "_", substr($tmp['origin'], 0, -1)),
384                 'options' => $options
385             );
a59731 386
7fe908 387             //   $filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/slave/sec.'.substr($tmp['origin'],0,-1));
MC 388             //   $app->log("Writing BIND domain file: ".$filename,LOGLEVEL_DEBUG);
389
390
a59731 391         }
7fe908 392
a59731 393         $tpl_sec = new tpl();
D 394         $tpl_sec->newTemplate("bind_named.conf.local.slave");
7fe908 395         $tpl_sec->setLoop('zones', $zones_sec);
a59731 396
7fe908 397         file_put_contents($dns_config['named_conf_local_path'], $tpl->grab()."\n".$tpl_sec->grab());
MC 398         $app->log("Writing BIND named.conf.local file: ".$dns_config['named_conf_local_path'], LOGLEVEL_DEBUG);
399
400         unset($tpl_sec);
401         unset($zones_sec);
402         unset($tmps_sec);
7dbea0 403         unset($tpl);
fc70a2 404         unset($zones);
T 405         unset($tmps);
7fe908 406
7dbea0 407     }
7fe908 408
MC 409
410
7dbea0 411
T 412 } // end class
413
a59731 414 ?>