2a2e7df25ab17411edc8fb7b042878c0edeeec46
1 <?php
3 class termDNS extends plugin
4 {
5 /* CLI vars */
6 var $cli_summary= "Manage server basic objects";
7 var $cli_description= "Some longer text\nfor help";
8 var $cli_parameters= array("eins" => "Eins ist toll", "zwei" => "Zwei ist noch besser");
10 /* attribute list for save action */
11 var $ignore_account= TRUE;
12 var $DNSattributes = array("dNSClass","zoneName","dNSTTL");
13 var $attributes= array("ipHostNumber","macAddress");
14 var $objectclasses= array("whatever");
16 var $ipHostNumber =""; // IP address
17 var $macAddress =""; // Mac address
18 var $cn =""; // CN of currently edited device
20 var $Zones = array(); // All Available Zones like array("3.2.1"=>"MyServer.de")
21 var $RecordTypes= array(); // Possible record types
23 var $dNSClass = "IN"; // dNSClass name
24 var $zoneName = ""; // Used ZoneName
25 var $dNSTTL = 7200; // TTL settings for the created entries
27 /* Used records */
28 var $types = array();
29 var $DNSinitially_was_account = false;
31 function termDNS ($config, $dn,$objectClasses)
32 {
33 /* We need to know which objectClasses are used, to store the ip/mac*/
34 $this->objectclasses= $objectClasses;
35 plugin::plugin ($config, $dn);
37 /* All types with required attrs */
38 $this->RecordTypes['aRecord'] = "aRecord"; // ok
39 $this->RecordTypes['mDRecord'] = "mDRecord"; // ok
40 $this->RecordTypes['mXRecord'] = "mXRecord"; // ok
41 $this->RecordTypes['nSRecord'] = "nSRecord"; // ok
42 $this->RecordTypes['pTRRecord'] = "relativeDomainName";// ok
43 $this->RecordTypes['hInfoRecord'] = "hInfoRecord"; // ok
44 $this->RecordTypes['mInfoRecord'] = "mInfoRecord"; // ok
45 $this->RecordTypes['cNAMERecord'] = "relativeDomainName";// ok
46 $this->RecordTypes['tXTRecord'] = "tXTRecord"; // ok
47 $this->RecordTypes['aFSDBRecord'] = "aFSDBRecord"; // ok
48 $this->RecordTypes['SigRecord'] = "SigRecord"; // ok
49 $this->RecordTypes['KeyRecord'] = "KeyRecord"; // ok
50 $this->RecordTypes['aAAARecord'] = "aAAARecord"; // ok
51 $this->RecordTypes['LocRecord'] = "LocRecord"; // ok
52 $this->RecordTypes['nXTRecord'] = "nXTRecord"; // ok
53 $this->RecordTypes['sRVRecord'] = "sRVRecord"; // ok
54 $this->RecordTypes['nAPTRRecord'] = "nAPTRRecord"; // ok
55 $this->RecordTypes['kXRecord'] = "kXRecord"; // ok
56 $this->RecordTypes['certRecord'] = "certRecord"; // ok
57 $this->RecordTypes['a6Record'] = "a6Record"; // ok
58 $this->RecordTypes['dSRecord'] = "dSRecord"; // ok
59 $this->RecordTypes['sSHFPRecord'] = "sSHFPRecord"; // ok
60 $this->RecordTypes['rRSIGRecord'] = "rRSIGRecord"; // ok
61 $this->RecordTypes['nSECRecord'] = "nSECRecord"; // ok
63 /* Get all available zones */
64 $this->cn = $this->attrs['cn'][0];
65 $this->Zones = $this->get_Zones();
66 $types = array();
68 /* Get all records */
69 $ldap = $this->config->get_ldap_link();
70 $ldap->cd($this->dn);
71 $ldap->search("(&(objectClass=dNSZone)(zoneName=*)(!(relativeDomainName=@)))",array("*"));
73 while($attrs = $ldap->fetch()){
74 /* If relative domainname == cn
75 * Try to read dnsclass / TTl / zone
76 */
77 if($attrs['relativeDomainName'][0] == $this->cn){
78 /* Get class */
79 if(isset($attrs['dNSClass'][0])){
80 $this->dNSClass = $attrs['dNSClass'][0];
81 }
82 /* Get Zone*/
83 if(isset($attrs['zoneName'][0])){
84 $this->zoneName = $attrs['zoneName'][0];
85 }
86 /* Get ttl */
87 if(isset($attrs['dNSTTL'][0])){
88 $this->dNSTTL = $attrs['dNSTTL'][0];
89 }
90 }
92 /* Create list with all used records */
93 foreach($this->RecordTypes as $name => $value){
95 /* If there is a record attribute */
96 if(isset($attrs[$name])){
99 /* get all entries */
100 for($i = 0 ; $i < $attrs[$value]['count']; $i ++){
101 if(($value == "aRecord")&&($this->ipHostNumber==$attrs[$value][$i])){
102 continue;
103 }
104 $types[] =array("type"=>$name,"inittype"=>$name,"value"=>$attrs[$value][$i],"status"=>"edited","dn"=>$attrs['dn']);
105 }
106 }
107 }
108 }
110 /* If there is at least one entry in this -> types, we have DNS enabled */
111 $this->types = $types;
112 if(count($this->types) == 0){
113 $this->DNS_is_account = false;
114 }else{
115 $this->DNS_is_account = true;
116 }
118 /* Store initally account settings */
119 $this->DNSinitially_was_account = $this->DNS_is_account;
120 }
122 function execute()
123 {
124 /* Call parent execute */
125 $smarty= get_smarty();
126 $display= "";
128 /* Add new empty array with status new, to our record list */
129 if(isset($_POST['AddNewRecord'])){
130 $this->types[] =array("type"=>"aRecord","value"=>"","status"=>"new");
131 }
133 /* Handle all posts */
134 $only_once =true;
135 foreach($_POST as $name => $value){
137 /* Check if we have to delete a record entry */
138 if((preg_match("/RemoveRecord_/",$name))&&($only_once)) {
140 /* Avoid performing this once again */
141 $only_once = false;
143 /* Extract id for specified entry */
144 $id = preg_replace("/RemoveRecord_/","",$name);
145 $id = preg_replace("/_.*$/","",$id);
147 /* Delete this record, mark edited entries to be able to delete them */
148 if(isset($this->types[$id])){
149 if($this->types[$id]['status'] == "edited"){
150 $this->types[$id]['status'] = "deleted";
151 }else{
152 unset($this->types[$id]);
153 }
154 }
155 }
156 }
158 /* Assign smarty all non DNs attributes */
159 foreach($this->attributes as $attr){
160 $smarty->assign($attr,$this->$attr);
161 }
163 /* Assign smarty all DNS attributes */
164 foreach($this->DNSattributes as $attr){
165 $smarty->assign($attr,$this->$attr);
166 }
168 /* Assign all needed vars */
169 $smarty->assign("DNSAccount",$this->DNS_is_account);
170 $smarty->assign("Zones",$this->Zones);
171 $smarty->assign("ZoneKeys",($this->Zones));
172 $changeStateForRecords ="";
173 $smarty->assign("records",$this->generateRecordsList(&$changeStateForRecords));
174 $smarty->assign("changeStateForRecords",$changeStateForRecords);
175 $smarty->assign("dNSClasses",array("IN"=>"IN"));
176 $smarty->assign("staticAddress","<font class=\"must\">*</font>");
177 $display.= $smarty->fetch(get_template_path('network.tpl', TRUE));
178 return($display);
179 }
181 function remove_from_parent()
182 {
183 /* This cannot be removed... */
184 }
186 /* Save data to object */
187 function save_object()
188 {
189 /* Save all posted vars */
190 plugin::save_object();
192 /* Ge all non dns attributes (IP/MAC)*/
193 foreach($this->attributes as $attr){
194 if(isset($_POST[$attr])){
195 $this->$attr = $_POST[$attr];
196 }
197 }
199 /* Get dns attributes */
200 if(isset($_POST['network_tpl_posted'])){
202 /* Check for posted record changes */
203 foreach($this->types as $key => $value){
205 /* Check if type has changed */
206 if(isset($_POST['RecordTypeSelectedFor_'.$key])){
207 $this->types[$key]['type'] = $_POST['RecordTypeSelectedFor_'.$key];
208 }
209 /* Check if value has changed */
210 if(isset($_POST['RecordValue_'.$key])){
211 $this->types[$key]['value'] = $_POST['RecordValue_'.$key];
212 }
213 }
215 /* Get all basic DNS attributes (TTL, Clas ..)*/
216 foreach($this->DNSattributes as $attr){
217 if(isset($_POST[$attr])){
218 $this->$attr = $_POST[$attr];
219 }
220 }
222 /* Enable diable DNS */
223 if(isset($_POST['enableDNS'])){
224 $this->DNS_is_account = true;
225 }else{
226 $this->DNS_is_account = false;
227 }
228 }
229 }
232 /* Check supplied data */
233 function check()
234 {
235 $message= array();
237 /* Check if mac is empty */
238 if ($this->macAddress == "" && chkacl ($this->acl, "macAddress") == ""){
239 $message[]= _("The required field 'MAC-address' is not set.");
240 }
242 /* Check if ip is empty */
243 if ($this->ipHostNumber == "" && chkacl ($this->acl, "ipHostNumber") == ""){
244 $message[]= _("The required field 'IP-address' is not set.");
245 }
247 /* check if given ip is valid ip*/
248 $num="(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";
249 if (!preg_match("/^$num\\.$num\\.$num\\.$num$/", $this->ipHostNumber)){
250 $message[]= _("Wrong IP format in field IP-address.");
251 }
253 /* Check if given mac is valid mac */
254 $tr = count(split(":",$this->macAddress));
255 if($tr!=6){
256 $message[]=(_("The given macaddress is invalid. There must be 6 1byte segments seperated by ':'."));
257 }
259 /* only perfrom this checks if this is a valid DNS account */
260 if($this->DNS_is_account){
261 foreach($this->types as $name => $values){
263 /* Check if there is an aRecord defined which uses the same IP as used in IPhostAddress */
264 if(($values['type'] == "aRecord")&&($values['value'] == $this->ipHostNumber)&&($values['status']!="deleted")){
265 $message[]=sprintf(_("The device IP '%s' is added as 'A Record', this will be done automatically, please remove the record."),
266 $this->ipHostNumber);
267 }
269 /* only lower-case is allowed in record entries ... */
270 if($values['value'] != strtolower($values['value'])){
271 $message[] = sprintf(_("Only lowercase is allowed, please check your '%ss'."),$values['type']);
272 }
273 }
274 }
276 return ($message);
277 }
280 /* Save to LDAP */
281 function save($dn)
282 {
283 $ldap= $this->config->get_ldap_link();
285 /*******************/
286 /* IP-MAC HANDLING */
287 /*******************/
289 /* $dn was posted as parameter */
290 $this->dn = $dn;
292 /* Save DNS setting & ip/Mac*/
293 plugin::save();
295 /* Write back to ldap */
296 $ldap->cd($this->dn);
297 $ldap->modify($this->attrs);
299 /****************/
300 /* DNS HANDLING */
301 /****************/
303 /* If isn't DNS account but initially was DNS account
304 remove all DNS entries
305 */
306 if(!$this->DNS_is_account){
307 if($this->DNSinitially_was_account){
308 $tmp = array();
309 foreach($this->types as $type){
310 $dn = $type['dn'];
311 if(!isset($tmp[$dn])) {
312 $ldap->cd($dn);
313 $ldap->rmDir($dn);
314 }
315 $tmp[$dn]=$dn;
316 }
317 }
318 }else{
320 /* DNS is enabled, check what we have to do */
321 $delete = array();
323 /* Generate a list of new ldap entries,
324 & $delete contains all dns which should be deleted
325 */
326 $entries = $this->generate_LDAP_entries(&$delete);
328 /* Delete dns */
329 foreach($delete as $dn => $del){
330 $ldap->cd($dn);
331 $ldap->rmDir($dn);
332 }
334 /* Add || Update new DNS entries */
335 foreach($entries as $dn => $attrs){
336 $ldap->cd($dn);
337 $ldap->cat($dn);
339 if(count($ldap->fetch())){
340 $ldap->cd($dn);
341 $ldap->modify($attrs);
342 }else{
343 $ldap->cd($dn);
344 $ldap->add($attrs);
345 }
346 }
347 }
348 if($ldap->get_error() != "Success"){
349 show_ldap_error($ldap->get_error());
350 }
352 }
354 /* Create html table with all used record types
355 */
356 function generateRecordsList($changeStateForRecords)
357 {
358 $changeStateForRecords = "";
360 if(!$this->DNS_is_account) {
361 $str = "<input type='submit' value='"._("Add")."' name='AddNewRecord' id='AddNewRecord' disabled>";
362 return $str;
363 }
365 $str = "<table summary=''>";
366 foreach($this->types as $key => $entry){
367 if($entry['status'] == "deleted") continue;
369 $changeStateForRecords.= "changeState('RecordTypeSelectedFor_".$key."');\n";
370 $changeStateForRecords.= "changeState('RecordValue_".$key."');\n";
371 $changeStateForRecords.= "changeState('RemoveRecord_".$key."');\n";
373 $str.=" <tr>".
374 " <td>".$this->generateRecordListBox($entry['type'],"RecordTypeSelectedFor_".$key)."</td>".
375 " <td><input type='text' value='".$entry['value']."' name='RecordValue_".$key."' id='RecordValue_".$key."'></td>".
376 " <td><input type='submit' name='RemoveRecord_".$key."' value='"._("Delete")."' id='RemoveRecord_".$key."'></td>".
377 "</tr>";
378 }
380 $str.= " <tr>".
381 " <td colspan=2></td><td>".
382 " <input type='submit' value='"._("Add")."' name='AddNewRecord'>".
383 " </td>".
384 " </tr>".
385 "</table>";
386 return($str);
387 }
389 /* Create a html select box which allows us to select different types of records */
390 function generateRecordListBox($selected,$name)
391 {
392 $str = "<select name='".$name."' id='".$name."'>";
393 foreach($this->RecordTypes as $type => $value){
394 $use = "";
395 if($type == $selected){
396 $use = " selected ";
397 }
398 $str.="\n <option value='".$type."' ".$use.">".$type."</option>";
399 }
400 $str.="</select>";
401 return($str);
402 }
404 /* return all Zone names */
405 function get_Zones()
406 {
407 $ret = array();
408 $ldap = $this->config->get_ldap_link();
409 $ldap-> cd ($this->config->current['BASE']);
410 $ldap->search("(&(objectClass=dNSZone)(sOARecord=*))",array("*"));
412 while($at = $ldap->fetch()){
413 if(preg_match("/\.in\-addr\.arpa/",$at['zoneName'][0])){
414 $ret[$at['relativeDomainName'][0]]['addr']= $at['zoneName'][0];
415 }else{
416 $ret[$at['relativeDomainName'][0]]['name']= $at['zoneName'][0];
417 }
418 }
420 $tmp =array();
421 foreach($ret as $name => $entry){
422 if((isset($entry['addr']))&&(isset($entry['name']))){
423 $tmp[$entry['addr']]=$entry['name'];
424 }
425 }
426 $ret = $tmp;
427 return($ret);
428 }
430 /* this is used to generate ldap friendly output of our
431 dns configuration
432 */
433 function generate_LDAP_entries($delete)
434 {
435 $entries = array();
436 $delete = array();
438 /* Generate Main Entry */
439 $dn = "relativeDomainName=".$this->cn.",".$this->dn;
440 $entries[$dn]['dNSClass'] = $this->dNSClass;
441 $entries[$dn]['zoneName'] = $this->zoneName;
442 $entries[$dn]['dNSTTL'] = $this->dNSTTL;
443 $entries[$dn]['relativeDomainName'] = $this->cn;
445 /* Generate cNAMERecord */
446 $aRecords = array();
447 foreach($this->types as $type){
448 if($type['type'] == "cNAMERecord"){
450 $Cdn = "relativeDomainName=".$type['value'].",".$this->dn;
451 if($type['status']=="deleted"){
452 $delete [$type['dn']] = $Cdn;
453 }else{
454 $entries[$Cdn] = $entries[$dn];
455 $entries[$Cdn]['relativeDomainName'] = $type['value'];
456 $entries[$Cdn]['cNAMERecord'] = $this->cn.".".$this->zoneName;
457 }
458 }
459 }
461 /* Generate tXTRecord */
462 $aRecords = array();
463 foreach($this->types as $type){
464 if(($type['type'] == "tXTRecord")&&($type['status']!="deleted")){
465 $entries[$dn]['tXTRecord'][] = $type['value'];
466 }
467 }
469 /* Generate mDRecord */
470 $aRecords = array();
471 foreach($this->types as $type){
472 if(($type['type'] == "mDRecord")&&($type['status']!="deleted")){
473 $entries[$dn]['mDRecord'][] = $type['value'];
474 }
475 }
477 /* Generate mXRecord */
478 $aRecords = array();
479 foreach($this->types as $type){
480 if(($type['type'] == "mXRecord")&&($type['status']!="deleted")){
481 $entries[$dn]['mXRecord'][] = $type['value'];
482 }
483 }
485 /* Generate hInfoRecord */
486 $aRecords = array();
487 foreach($this->types as $type){
488 if(($type['type'] == "hInfoRecord")&&($type['status']!="deleted")){
489 $entries[$dn]['hInfoRecord'][] = $type['value'];
490 }
491 }
493 /* Generate mInfoRecord */
494 $aRecords = array();
495 foreach($this->types as $type){
496 if(($type['type'] == "mInfoRecord")&&($type['status']!="deleted")){
497 $entries[$dn]['mInfoRecord'][] = $type['value'];
498 }
499 }
501 /* Generate aFSDBRecord */
502 $aRecords = array();
503 foreach($this->types as $type){
504 if(($type['type'] == "aFSDBRecord")&&($type['status']!="deleted")){
505 $entries[$dn]['aFSDBRecord'][] = $type['value'];
506 }
507 }
509 /* Generate some attrs */
510 $arr = array("SigRecord","KeyRecord","aAAARecord","nSRecord",
511 "LocRecord","nXTRecord","sRVRecord","nAPTRRecord","kXRecord","certRecord","a6Record","dSRecord","sSHFPRecord","rRSIGRecord","nSECRecord");
512 $aRecords = array();
513 foreach($arr as $ar){
514 foreach($this->types as $type){
515 if(($type['type'] == $ar)&&($type['status']!="deleted")){
516 $entries[$dn][$ar][] = $type['value'];
517 }
518 }
519 }
522 /* Generate A Records (IP Address relation) */
523 $aRecords = array();
524 foreach($this->types as $type){
525 if(($type['type'] == "aRecord")&&($type['status']!="deleted")){
526 $aRecords[] = $type['value'];
527 }
528 }
529 if(count($aRecords)){
531 /* Add ipHostNumber as default aRecord */
532 $aRecords[] = $this->ipHostNumber;
534 $dn = "relativeDomainName=".$this->cn.",".$this->dn;
535 foreach($aRecords as $rec){
536 $entries[$dn]['aRecord'][] = $rec;
537 }
538 }
540 /* Generate pTRRecord Records */
541 foreach($this->types as $type){
542 if($type['type'] == "pTRRecord"){
543 $PTRdn= "relativeDomainName=".$type['value'].",".$this->dn;
544 if($type['status']=="deleted"){
545 $delete [$type['dn']] = $PTRdn;
546 }else{
547 $zones = array_flip($this->Zones);
548 $zone = $zones[$this->zoneName];
549 $entries[$PTRdn]['relativeDomainName'] = $type['value'];
550 $entries[$PTRdn]['pTRRecord'] = $this->cn.".".$this->zoneName;
551 $entries[$PTRdn]['zoneName'] = $zone;
552 }
553 }
554 }
556 /* add ObjectClasses */
557 foreach($entries as $key => $entry ){
558 $entries[$key]['objectClass']=array("top","dNSZone");
559 $entries[$key] = array_reverse($entries[$key]);
560 }
562 /* Check if record type has changed, and if we need to delete this record attribute from ldap entry */
563 foreach($this->types as $type){
564 if(isset($type['inittype'])){
565 if(!isset($entries[$dn][$type['inittype']])){
566 $entries[$dn][$type['inittype']] = array();
567 }
568 }
569 }
571 return($entries);
572 }
573 }
575 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
576 ?>