Marius Cramer
2014-02-17 ebbe6374fc9c308daf729d2ad1b2f8007ed771ce
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
8ee180 105             $records = $app->db->queryAllRecords("SELECT * FROM dns_rr WHERE zone = ".$zone['id']." AND active = 'Y'");
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'] = '';
109                 }
110             }
7fe908 111             $tpl->setLoop('zones', $records);
MC 112
4b88c2 113             //TODO : change this when distribution information has been integrated into server record
7fe908 114             if (file_exists('/etc/gentoo-release')) {
MC 115                 $filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($zone['origin'], 0, -1)));
116             }
117             else {
118                 $filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($zone['origin'], 0, -1)));
119             }
120
121             file_put_contents($filename, $tpl->grab());
8e725d 122             chown($filename, escapeshellcmd($dns_config['bind_user']));
J 123             chgrp($filename, escapeshellcmd($dns_config['bind_group']));
7fe908 124
f038c0 125             //* Check the zonefile
T 126             if(is_file($filename.'.err')) unlink($filename.'.err');
7fe908 127             exec('named-checkzone '.escapeshellarg($zone['origin']).' '.escapeshellarg($filename), $out, $return_status);
f038c0 128             if($return_status === 0) {
7fe908 129                 $app->log("Writing BIND domain file: ".$filename, LOGLEVEL_DEBUG);
f038c0 130             } else {
7fe908 131                 $app->log("Writing BIND domain file failed: ".$filename." ".implode(' ', $out), LOGLEVEL_WARN);
MC 132                 rename($filename, $filename.'.err');
f038c0 133             }
8ee180 134             unset($tpl);
T 135             unset($records);
a59ad3 136             unset($records_out);
8ee180 137             unset($zone);
T 138         }
7fe908 139
7dbea0 140         //* rebuild the named.conf file if the origin has changed or when the origin is inserted.
fc70a2 141         //if($this->action == 'insert' || $data['old']['origin'] != $data['new']['origin']) {
7fe908 142         $this->write_named_conf($data, $dns_config);
fc70a2 143         //}
7fe908 144
7dbea0 145         //* Delete old domain file, if domain name has been changed
T 146         if($data['old']['origin'] != $data['new']['origin']) {
4b88c2 147             //TODO : change this when distribution information has been integrated into server record
7fe908 148             if (file_exists('/etc/gentoo-release')) {
MC 149                 $filename = $dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
150             }
151             else {
152                 $filename = $dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
153             }
154
f038c0 155             if(is_file($filename)) unlink($filename);
T 156             if(is_file($filename.'.err')) unlink($filename.'.err');
7dbea0 157         }
7fe908 158
eb64c3 159         //* Restart bind nameserver if update_acl is not empty, otherwise reload it
TB 160         if($data['new']['update_acl'] != '') {
161             $app->services->restartServiceDelayed('bind', 'restart');
162         } else {
163             $app->services->restartServiceDelayed('bind', 'reload');
164         }
7fe908 165
7dbea0 166     }
a59731 167
7fe908 168     function soa_delete($event_name, $data) {
a59731 169         global $app, $conf;
7fe908 170
MC 171         //* load the server configuration options
172         $app->uses("getconf,tpl");
173         $dns_config = $app->getconf->get_server_config($conf["server_id"], 'dns');
174
175         //* rebuild the named.conf file
176         $this->write_named_conf($data, $dns_config);
177
178         //* Delete the domain file
179         //TODO : change this when distribution information has been integrated into server record
180         if (file_exists('/etc/gentoo-release')) {
181             $zone_file_name = $dns_config['bind_zonefiles_dir'].'/pri/'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
182         }
183         else {
184             $zone_file_name = $dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
185         }
186
187         if(is_file($zone_file_name)) unlink($zone_file_name);
188         if(is_file($zone_file_name.'.err')) unlink($zone_file_name.'.err');
189         $app->log("Deleting BIND domain file: ".$zone_file_name, LOGLEVEL_DEBUG);
190
191         //* Reload bind nameserver
192         $app->services->restartServiceDelayed('bind', 'reload');
193
a59731 194     }
7fe908 195
MC 196     function slave_insert($event_name, $data) {
a59731 197         global $app, $conf;
7fe908 198
MC 199         $this->action = 'insert';
200         $this->slave_update($event_name, $data);
201
202     }
203
204     function slave_update($event_name, $data) {
205         global $app, $conf;
206
a59731 207         //* Load libraries
D 208         $app->uses("getconf,tpl");
7fe908 209
a59731 210         //* load the server configuration options
D 211         $dns_config = $app->getconf->get_server_config($conf["server_id"], 'dns');
7fe908 212
a59731 213         //* rebuild the named.conf file if the origin has changed or when the origin is inserted.
D 214         //if($this->action == 'insert' || $data['old']['origin'] != $data['new']['origin']) {
7fe908 215         $this->write_named_conf($data, $dns_config);
a59731 216         //}
7fe908 217
a59731 218         //* Delete old domain file, if domain name has been changed
D 219         if($data['old']['origin'] != $data['new']['origin']) {
4b88c2 220             //TODO : change this when distribution information has been integrated into server record
7fe908 221             if (file_exists('/etc/gentoo-release')) {
MC 222                 $filename = $dns_config['bind_zonefiles_dir'].'/sec/'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
223             }
224             else {
225                 $filename = $dns_config['bind_zonefiles_dir'].'/slave/sec.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
226             }
227
a59731 228             if(is_file($filename)) unset($filename);
D 229         }
7fe908 230
355efb 231         //* Ensure that the named slave directory is writable by the named user
T 232         if (file_exists('/etc/gentoo-release')) {
233             $slave_record_dir = $dns_config['bind_zonefiles_dir'].'/sec';
234         } else {
235             $slave_record_dir = $dns_config['bind_zonefiles_dir'].'/slave';
236         }
7fe908 237         if(!@is_dir($slave_record_dir)) mkdir($slave_record_dir, 0770);
MC 238         chown($slave_record_dir, $dns_config['bind_user']);
239         chgrp($slave_record_dir, $dns_config['bind_group']);
240
a59731 241         //* Reload bind nameserver
7fe908 242         $app->services->restartServiceDelayed('bind', 'reload');
MC 243
a59731 244     }
7fe908 245
MC 246     function slave_delete($event_name, $data) {
a59731 247         global $app, $conf;
7fe908 248
MC 249
a59731 250         //* load the server configuration options
D 251         $app->uses("getconf,tpl");
252         $dns_config = $app->getconf->get_server_config($conf["server_id"], 'dns');
7fe908 253
a59731 254         //* rebuild the named.conf file
7fe908 255         $this->write_named_conf($data, $dns_config);
MC 256
a59731 257         //* Delete the domain file
4b88c2 258         //TODO : change this when distribution information has been integrated into server record
7fe908 259         if (file_exists('/etc/gentoo-release')) {
MC 260             $zone_file_name = $dns_config['bind_zonefiles_dir'].'/sec/'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
261         }
262         else {
263             $zone_file_name = $dns_config['bind_zonefiles_dir'].'/slave/sec.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1));
264         }
265
a59731 266         if(is_file($zone_file_name)) unlink($zone_file_name);
7fe908 267         $app->log("Deleting BIND domain file for secondary zone: ".$zone_file_name, LOGLEVEL_DEBUG);
MC 268
a59731 269         //* Reload bind nameserver
7fe908 270         $app->services->restartServiceDelayed('bind', 'reload');
MC 271
7dbea0 272
T 273     }
7fe908 274
MC 275     function rr_insert($event_name, $data) {
7dbea0 276         global $app, $conf;
7fe908 277
7dbea0 278         //* Get the data of the soa and call soa_update
T 279         $tmp = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$data['new']['zone']);
280         $data["new"] = $tmp;
281         $data["old"] = $tmp;
282         $this->action = 'update';
7fe908 283         $this->soa_update($event_name, $data);
MC 284
7dbea0 285     }
7fe908 286
MC 287     function rr_update($event_name, $data) {
7dbea0 288         global $app, $conf;
7fe908 289
MC 290         //* Get the data of the soa and call soa_update
291         $tmp = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$data['new']['zone']);
292         $data["new"] = $tmp;
293         $data["old"] = $tmp;
294         $this->action = 'update';
295         $this->soa_update($event_name, $data);
296
297     }
298
299     function rr_delete($event_name, $data) {
300         global $app, $conf;
301
7dbea0 302         //* Get the data of the soa and call soa_update
531afa 303         $tmp = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".intval($data['old']['zone']));
7dbea0 304         $data["new"] = $tmp;
T 305         $data["old"] = $tmp;
306         $this->action = 'update';
7fe908 307         $this->soa_update($event_name, $data);
MC 308
7dbea0 309     }
7fe908 310
MC 311     //##################################################################
312
7dbea0 313     function write_named_conf($data, $dns_config) {
T 314         global $app, $conf;
7fe908 315
MC 316         //* Only write the master file for the current server
c36fe4 317         $tmps = $app->db->queryAllRecords("SELECT origin, xfer, also_notify, update_acl FROM dns_soa WHERE active = 'Y' AND server_id=".$conf["server_id"]);
fc70a2 318         $zones = array();
7fe908 319
957aaf 320         //* Check if the current zone that triggered this function has at least one NS record
f038c0 321         /* Has been replaced by a better zone check
531afa 322         $rec_num = $app->db->queryOneRecord("SELECT count(id) as ns FROM dns_rr WHERE type = 'NS' AND zone = ".intval($data['new']['id'])." AND active = 'Y'");
957aaf 323         if($rec_num['ns'] == 0) {
T 324             $exclude_zone = $data['new']['origin'];
325         } else {
326             $exclude_zone = '';
327         }
f038c0 328         */
7fe908 329
4b88c2 330         //TODO : change this when distribution information has been integrated into server record
7fe908 331         if (file_exists('/etc/gentoo-release')) {
MC 332             $pri_zonefiles_path = $dns_config['bind_zonefiles_dir'].'/pri/';
333             $sec_zonefiles_path = $dns_config['bind_zonefiles_dir'].'/sec/';
334
335         }
336         else {
337             $pri_zonefiles_path = $dns_config['bind_zonefiles_dir'].'/pri.';
338             $sec_zonefiles_path = $dns_config['bind_zonefiles_dir'].'/slave/sec.';
339         }
a59ad3 340
957aaf 341         //* Loop trough zones
fc70a2 342         foreach($tmps as $tmp) {
7fe908 343
MC 344             $zone_file = $pri_zonefiles_path.str_replace("/", "_", substr($tmp['origin'], 0, -1));
345
a59ad3 346             $options = '';
a59731 347             if(trim($tmp['xfer']) != '') {
7fe908 348                 $options .= "        allow-transfer {".str_replace(',', ';', $tmp['xfer']).";};\n";
a59731 349             } else {
D 350                 $options .= "        allow-transfer {none;};\n";
351             }
7fe908 352             if(trim($tmp['also_notify']) != '') $options .= '        also-notify {'.str_replace(',', ';', $tmp['also_notify']).";};\n";
MC 353             if(trim($tmp['update_acl']) != '') $options .= "        allow-update {".str_replace(',', ';', $tmp['update_acl']).";};\n";
354
f038c0 355             if(file_exists($zone_file)) {
7fe908 356                 $zones[] = array( 'zone' => substr($tmp['origin'], 0, -1),
MC 357                     'zonefile_path' => $zone_file,
358                     'options' => $options
359                 );
957aaf 360             }
fc70a2 361         }
a59731 362
7dbea0 363         $tpl = new tpl();
T 364         $tpl->newTemplate("bind_named.conf.local.master");
7fe908 365         $tpl->setLoop('zones', $zones);
MC 366
a59731 367         //* And loop through the secondary zones, but only for the current server
D 368         $tmps_sec = $app->db->queryAllRecords("SELECT origin, xfer, ns FROM dns_slave WHERE active = 'Y' AND server_id=".$conf["server_id"]);
369         $zones_sec = array();
370
371         foreach($tmps_sec as $tmp) {
7fe908 372
a59731 373             $options = "        masters {".$tmp['ns'].";};\n";
7fe908 374             if(trim($tmp['xfer']) != '') {
MC 375                 $options .= "        allow-transfer {".str_replace(',', ';', $tmp['xfer']).";};\n";
376             } else {
377                 $options .= "        allow-transfer {none;};\n";
378             }
a59731 379
D 380
7fe908 381             $zones_sec[] = array( 'zone' => substr($tmp['origin'], 0, -1),
MC 382                 'zonefile_path' => $sec_zonefiles_path.str_replace("/", "_", substr($tmp['origin'], 0, -1)),
383                 'options' => $options
384             );
a59731 385
7fe908 386             //   $filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/slave/sec.'.substr($tmp['origin'],0,-1));
MC 387             //   $app->log("Writing BIND domain file: ".$filename,LOGLEVEL_DEBUG);
388
389
a59731 390         }
7fe908 391
a59731 392         $tpl_sec = new tpl();
D 393         $tpl_sec->newTemplate("bind_named.conf.local.slave");
7fe908 394         $tpl_sec->setLoop('zones', $zones_sec);
a59731 395
7fe908 396         file_put_contents($dns_config['named_conf_local_path'], $tpl->grab()."\n".$tpl_sec->grab());
MC 397         $app->log("Writing BIND named.conf.local file: ".$dns_config['named_conf_local_path'], LOGLEVEL_DEBUG);
398
399         unset($tpl_sec);
400         unset($zones_sec);
401         unset($tmps_sec);
7dbea0 402         unset($tpl);
fc70a2 403         unset($zones);
T 404         unset($tmps);
7fe908 405
7dbea0 406     }
7fe908 407
MC 408
409
7dbea0 410
T 411 } // end class
412
a59731 413 ?>