| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918 |
- <?php
- namespace MGModule\DNSManager2\mgLibs\custom\dns\submodules;
- use Exception;
- use \MGModule\DNSManager2\mgLibs\custom\dns;
- use MGModule\DNSManager2\mgLibs\custom\dns\dnssec\DnsSec;
- use \MGModule\DNSManager2\mgLibs\custom\dns\exceptions;
- use \MGModule\DNSManager2\mgLibs\custom\dns\interfaces;
- use \MGModule\DNSManager2\mgLibs\custom\dns\utils\Patterns;
- use MGModule\DNSManager2 as main;
- class PowerDNS extends dns\SubmoduleAbstract implements
- interfaces\SubmoduleIPInterface, interfaces\SubmoduleRDNSInterface, interfaces\SubmoduleTTLInterface, interfaces\SubmoduleImportInterface, interfaces\SubmoduleDNSSecInterface
- {
- public $configFields = [
- 'username' => [
- 'friendlyName' => 'Username',
- 'validators' => [
- 'required' => 'required',
- ]
- ],
- 'password' => [
- 'friendlyName' => 'User Password',
- 'type' => 'password',
- 'validators' => [
- 'required' => 'required',
- ]
- ],
- 'hostname' => [
- 'friendlyName' => 'Hostname/IP',
- 'validators' => [
- 'required' => 'required',
- ]
- ],
- 'database' => [
- 'friendlyName' => 'Database',
- 'validators' => [
- 'required' => 'required',
- ]
- ],
- 'ssh_host' => [
- 'friendlyName' => 'SSH Host',
- 'type' => 'text',
- ],
- 'ssh_username' => [
- 'friendlyName' => 'SSH User',
- 'type' => 'text',
- ],
- 'ssh_password' => [
- 'friendlyName' => 'SSH Password',
- 'type' => 'password',
- ],
- 'ssh_port' => [
- 'friendlyName' => 'SSH Port',
- 'type' => 'text'
- ],
- 'ssh_public_key' => [
- 'friendlyName' => 'SSH Public Key',
- 'type' => 'text',
- ],
- 'ssh_private_key' => [
- 'friendlyName' => 'SSH Private Key',
- 'type' => 'text',
- ],
- 'pdnsutil_path' => [
- 'friendlyName' => 'Path To PDNSUTIL',
- 'type' => 'text',
- ],
- 'default_ip' => [
- 'friendlyName' => 'Default IP',
- 'validators' => [
- 'required' => 'required',
- 'pattern' => Patterns::IP4_OR_IP6,
- ]
- ],
- 'soa_name' => [
- 'friendlyName' => 'Name',
- 'help' => '{$domain} will be repleaced with name of the domain',
- ],
- 'domain_type' => [
- 'friendlyName' => 'Domain Type',
- 'type' => 'select',
- 'options' => ['MASTER' => 'MASTER', 'SLAVE' => 'SLAVE', 'NATIVE' => 'NATIVE'],
- ],
- 'soa_primary' => [
- 'friendlyName' => 'Primary',
- ],
- 'soa_hostmaster' => [
- 'friendlyName' => 'Hostmaster',
- ],
- 'soa_refresh' => [
- 'friendlyName' => 'Refresh',
- ],
- 'soa_retry' => [
- 'friendlyName' => 'Retry',
- ],
- 'soa_expire' => [
- 'friendlyName' => 'Expire',
- ],
- 'soa_default_ttl' => [
- 'friendlyName' => 'Default TTL',
- 'type' => 'number',
- ],
- 'soa_ttl' => [
- 'friendlyName' => 'TTL',
- 'type' => 'number',
- 'value' => '555',
- ],
- 'soa_edit' => [
- 'friendlyName' => 'Allow To Edit SOA Records',
- 'type' => 'yesno'
- ],
- 'disable_validation' => [
- 'friendlyName' => 'Disable Records Validation',
- 'type' => 'yesno'
- ],
- 'disable_doubled' => [
- 'friendlyName' => 'Double Records',
- 'type' => 'yesno',
- 'help' => 'Select to enable creating double records'
- ],
- 'zone_account' => [
- 'friendlyName' => 'Zone Account',
- ],
- 'update_notified_serial' => [
- 'friendlyName' => 'Update Notified Serial',
- 'type' => 'yesno'
- ],
- ];
- private $error;
- private $ssh = null;
- private $remote_db = null;
- /** available records types * */
- public $availableTypes = ['A', 'AAAA', 'NS', 'MX', 'CNAME', 'DNAME', 'TXT', 'SPF', 'SRV', 'PTR', 'SOA', 'CAA', 'AFSDB', 'ALIAS', 'DNSKEY', 'DS', 'HINFO', 'LOC', 'MINFO', 'MR', 'NAPTR', 'RP', 'RRSIG', 'WKS', 'URI', 'URL']; //LOC
- public $typesCantBeDoubled = ['A', 'AAAA', 'SPF', 'SRV', 'PTR', 'SOA'];
- public function __destruct()
- {
- $this->disconnect();
- }
- protected function validateIP()
- {
- if(empty($this->ip)) return false;
- return (ip2long($this->ip) !== false);
- }
- private function mysql_safequery($query, $params = [] )
- {
- try
- {
- $this->connect();
- $qsql = main\mgLibs\MySQL\query::debugQuery($query, $params);
- $sql_query = main\mgLibs\MySQL\query::query($query, $params, 'pdns');
- $this->disconnect();
- $this->log('SQL: ' . $qsql);
- }
- catch( Exception $ex)
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException($ex, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- return ($sql_query);
- }
- private function connect()
- {
- try
- {
- main\mgLibs\MySQL\query::createInstance([
- 'host' => $this->config['hostname'],
- 'user' => $this->config['username'],
- 'pass' => $this->config['password'],
- 'name' => $this->config['database']
- ]);
- }
- catch( Exception $ex)
- {
- throw new exceptions\DNSSubmoduleException('Unable to connect to the Power DNS database', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
- }
- return true;
- }
- private function disconnect()
- {
- main\mgLibs\MySQL\query::dropInstance('pdns');
- }
- public function testConnection()
- {
- $this->log('TEST CONNECTION');
- $this->connect();
- $this->mysql_safequery('SELECT * FROM domains ');
- $this->disconnect();
- }
- private function updateSoaSerial()
- {
- if (in_array($this->config['domain_type'], ['MASTER','NATIVE']) || preg_match('/in-addr.arpa$/', $this->domain))
- {
- $q = $this->mysql_safequery("SELECT r.id as record_id, r.content FROM records r JOIN domains d ON(r.domain_id = d.id) WHERE r.type = 'SOA' AND d.name = ?", [$this->domain]);
- $row = $q->fetch();
- $record_id = $row['record_id'];
- $content = explode(' ', $row['content']);
- if ($content[2])
- {
- $inc = (int) substr($content[2], 8, 2);
- $current_date = date('Ymd');
- $serial_current_date = substr($content[2], 0, 8);
- $date = $serial_current_date === $current_date ? substr($content[2], 0, 8) : $current_date;
- if ($serial_current_date !== $current_date)
- {
- $serial = $current_date . '00';
- }
- elseif ($inc === 99)
- {
- $serial = date('Ymd', strtotime($date) + (60 * 60 * 24)) . '00';
- }
- else
- {
- $inc++;
- $serial = $date . ($inc <= 9 ? '0' . $inc : $inc);
- }
- }
- if (!empty($serial))
- {
- $content[2] = $serial;
- $this->mysql_safequery('UPDATE records SET content = ? WHERE id = ?', [implode(' ', $content), $record_id]);
- }
- }
- }
- private function updateNotifiedSerial()
- {
- if ($this->config['update_notified_serial'] === 'on')
- {
- $q = $this->mysql_safequery('SELECT notified_serial FROM domains WHERE name = ?', [$this->domain]);
- $row = $q->fetch();
- if ($row !== false)
- {
- $notified_serial = $row['notified_serial'];
- if (empty($notified_serial))
- {
- $current_date = date('Ymd');
- $serial = $current_date . '01';
- }
- else
- {
- $inc = (int) substr($notified_serial, 8, 2);
- $current_date = date('Ymd');
- $serial_current_date = substr($notified_serial, 0, 8);
- $date = $serial_current_date == $current_date ? substr($notified_serial, 0, 8) : $current_date;
- if ($serial_current_date !== $current_date)
- {
- $serial = $current_date . '01';
- }
- elseif ($inc === 99)
- {
- $serial = date('Ymd', strtotime($date) + (60 * 60 * 24)) . '01';
- }
- else
- {
- $inc += 2;
- $serial = $date . ($inc <= 9 ? '0' . $inc : $inc);
- }
- }
- $this->mysql_safequery('UPDATE domains SET notified_serial = ? WHERE name = ?', [$serial, $this->domain]);
- }
- }
- }
- public function zoneExists()
- {
- $this->log('CHECK ZONE EXIST');
- $this->domain = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($this->domain);
- if($this->connect())
- {
- $q = $this->mysql_safequery('SELECT name, account FROM domains WHERE name = ?', [$this->domain]);
- $row = $q->fetch();
- $this->disconnect();
- return strtolower($row['name']) === strtolower($this->domain);
- }
- return false;
- }
- public function activateZone()
- {
- $this->log('ACTIVATE ZONE');
- $this->domain = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($this->domain);
- if ($this->zoneExists())
- {
- throw new exceptions\DNSSubmoduleException('Domain name already exists!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- if (empty($this->domain))
- {
- throw new exceptions\DNSSubmoduleException('Domain name is not valid!', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- if (preg_match('/in-addr.arpa$/', $this->domain))
- {
- $this->config['domain_type'] = 'MASTER';
- }
- if ($this->config['domain_type'] === 'SLAVE')
- {
- $ip = $this->ip == '' ? $this->config['default_ip'] : $this->ip;
- if (!filter_var($ip, FILTER_VALIDATE_IP))
- {
- throw new exceptions\DNSSubmoduleException('This is not a valid IPv4 or IPv6 address.', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- }
- if ($this->config['update_notified_serial'] === 'on' )
- {
- $current_date = date('Ymd');
- $serial = $current_date . '00';
- }
- else
- {
- $serial = 0;
- }
- if ($this->connect())
- {
- if (in_array($this->config['domain_type'], ['MASTER','NATIVE']) || preg_match('/in-addr.arpa$/', $this->domain) || preg_match('/ip6.arpa$/', $this->domain))
- {
- if (!empty($this->config['zone_account']))
- {
- $args = [$this->domain, $serial, $this->config['zone_account']];
- $query = "INSERT INTO domains (name, type, notified_serial, account) VALUES( ?, '" . $this->config['domain_type'] . "', ?, ? )";
- }
- else
- {
- $args = [$this->domain, $serial];
- $query = "INSERT INTO domains (name, type, notified_serial) VALUES( ?, '" . $this->config['domain_type'] . "', ? )";
- }
- }
- elseif(!empty($this->config['zone_account']))
- {
- $args = [$this->domain, $ip, $serial, $this->config['zone_account']];
- $query = "INSERT INTO domains (name, type, master, notified_serial, account) VALUES( ?, 'SLAVE', ?, ?, ? )";
- }
- else
- {
- $args = [$this->domain, $ip, $serial];
- $query = "INSERT INTO domains (name, type, master, notified_serial) VALUES( ?, 'SLAVE', ?, ?)";
- }
- if ($this->mysql_safequery($query, $args))
- {
- if ($this->config['domain_type'] === 'MASTER' || $this->config['domain_type'] === 'NATIVE' || preg_match('/in-addr.arpa$/', $this->domain) || preg_match('/ip6.arpa$/', $this->domain))
- {
- $to_search = ['{$domain}'];
- $to_replace = [$this->domain];
- $name = preg_match('/in-addr.arpa$/', $this->domain) || preg_match('/ip6.arpa$/', $this->domain) ? $this->domain : str_replace($to_search, $to_replace, $this->config['soa_name']);
- if (preg_match('/in-addr.arpa$/', $this->domain) || preg_match('/ip6.arpa$/', $this->domain))
- {
- $content = $this->domain . ' ' . 'hostmaster.' . $this->domain . ' ' . date('Ymd') . '00' . ' ' . $this->config['soa_refresh'] . ' ' . $this->config['soa_retry'] . ' ' . $this->config['soa_expire'] . ' ' . $this->config['soa_default_ttl'];
- }
- else
- {
- $content = str_replace($to_search, $to_replace, $this->config['soa_primary']) . ' ' . str_replace($to_search, $to_replace, $this->config['soa_hostmaster']) . ' ' . date('Ymd') . '00' . ' ' . $this->config['soa_refresh'] . ' ' . $this->config['soa_retry'] . ' ' . $this->config['soa_expire'] . ' ' . $this->config['soa_default_ttl'];
- }
- $input = [
- $this->domain,
- $name,
- 'SOA',
- $this->config['soa_ttl'],
- time(),
- $content
- ];
- $this->mysql_safequery('INSERT INTO records (domain_id, name, type, ttl, prio, change_date, content) VALUES((SELECT id FROM domains WHERE name = ?), ?, ?, ?, 0, ?, ?)', $input);
- }
- $this->disconnect();
- return true;
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException($this->remote_db->error, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
- return false;
- }
- public function terminateZone()
- {
- $this->domain = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($this->domain);
- if (!$this->zoneExists())
- {
- throw new exceptions\DNSSubmoduleException('Domain name not exists!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- $this->log('TERMINATE ZONE');
- if (empty($this->domain))
- {
- throw new exceptions\DNSSubmoduleException('Domain name is not valid!', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- if ($this->connect())
- {
- $q = $this->mysql_safequery('SELECT id FROM domains WHERE name = ?', [$this->domain]);
- $row = $q->fetch();
- if($this->mysql_safequery('DELETE FROM domains WHERE name = ?', [$this->domain]))
- {
- $this->mysql_safequery('DELETE FROM records WHERE domain_id = ?', [$row['id']]);
- $this->disconnect();
- return true;
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException($this->remote_db->error, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
- return false;
- }
- public function getRecords($recordType = false)
- {
- $this->log('GET RECORDS');
- $out = [];
- $this->domain = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($this->domain);
- if ($this->connect())
- {
- $q = $this->mysql_safequery('SELECT r.id as record_id, r.name, r.type, r.ttl, r.prio, r.content FROM records r JOIN domains d ON(r.domain_id = d.id) WHERE d.name = ?', [$this->domain]);
- while ($row = $q->fetch())
- {
- if ( !$recordType && $this->config['soa_edit'] !== 'on' && $row['type'] === 'SOA')
- {
- continue;
- }
- if ( in_array($row['type'], $recordType ? [strtoupper($recordType)] : $this->getAvailableRecordTypes(), true) )
- {
- $record = new dns\record\Record();
- $record->line = $row['record_id'];
- $record->name = rtrim($row['name'],'.') .'.';
- $record->type = $row['type'];
- $record->ttl = $row['ttl'];
- $record->createRDATAObject();
- if($record['type'] !=='TXT')
- {
- $row['content'] = main\mgLibs\custom\helpers\IdnaHelper::idnaDecode($row['content']);
- }
- switch ($row['type'])
- {
- case 'SRV':
- $content = preg_split('/\s+/', $row['content']);
- $record->rdata->priority = $row['prio'];
- $record->rdata->weight = $content[0];
- $record->rdata->port = $content[1];
- $record->rdata->target = $content[2];
- break;
- case 'MX':
- case 'URI':
- $record->rdata->fromString($row['prio'] . ' ' . $row['content']);
- break;
- case 'DNSKEY':
- $exploded = preg_split('/\s+/', $row['content']);
- $newRecord['protocol'] = $exploded[0];
- $newRecord['flags'] = $exploded[1];
- $newRecord['algorithm'] = $exploded[2];
- unset($exploded[0], $exploded[1], $exploded[2]);
- $newRecord['publickey'] = implode(' ', $exploded);
- $record->rdata->setDataFromArray($newRecord);
- break;
- default:
- $record->rdata->fromString($row['content']);
- break;
- }
-
- $out[] = $record;
- }
- }
- $this->disconnect();
- }
- return $out;
- }
- public function addRecord(dns\record\Record $record)
- {
- $this->domain = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($this->domain);
- if ( $record->type !== 'PTR' && (preg_match('/in-addr.arpa$/', $this->domain) || preg_match('/ip6.arpa$/', $this->domain)) )
- {
- throw new exceptions\DNSSubmoduleException('This record type (' . $record->type . ') is not allowe for rDNS zone', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- switch ($record->type)
- {
- case 'MX':
- $prio = $record->rdata->preference;
- $value = $record->rdata->exchange;
- break;
- case 'SRV':
- $prio = $record->rdata->priority;
- $value = $record->rdata->toString(['weight', 'port', 'target']);
- break;
- case 'URI':
- $prio = $record->rdata->priority;
- $value = $record->rdata->toString(['weight', 'target']);
- break;
- case 'CNAME':
- $prio = 0;
- $value = rtrim($record->rdata->toString(), '.');
- break;
- default:
- $prio = 0;
- $value = $record->rdata->toString();
- break;
- }
- $value = str_replace("\t", ' ', $value);
- $value = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($value);
- $input = [
- strtolower($this->domain),
- main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($record->nameToAbsolute($this->domain, false)),
- $record->type,
- $record->ttl,
- $prio,
- time(),
- $value
- ];
- $record->name = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($record->name);
- $valid = $this->validate_input(false, $record->type, $value, $record->name, $prio, $record->ttl);
- if ($valid === true)
- {
- $this->log('ADD RECORDS');
- if ($this->connect())
- {
- if(empty($this->config['disable_doubled']) && in_array($record->type, $this->typesCantBeDoubled))
- {
- if($this->checkIfRecordSameExist($record))
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException('Such record alredy exists', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
-
- if ($this->mysql_safequery('INSERT INTO records (domain_id, name, type, ttl, prio, change_date, content) VALUES((SELECT id FROM domains WHERE LOWER(name) = ?), ?, ?, ?, ?, ?, ?)', $input))
- {
- $this->updateSoaSerial();
- $this->updateNotifiedSerial();
- $this->disconnect();
-
- try
- {
- if($this->isSigned())
- {
- $this->rectify();
- }
- }
- catch( Exception $ex)
- {}
-
- return true;
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException($this->remote_db->error, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException('Connection problem', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
- }
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException('Validation error: ' . $this->error, dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- }
- public function editRecord(dns\record\Record $record) //Prawie ctr + c -> ctrl + v
- {
- $this->domain = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($this->domain);
- $record->name = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($record->name);
- switch ($record->type)
- {
- case 'MX':
- $prio = $record->rdata->preference;
- $value = $record->rdata->exchange;
- break;
- case 'SRV':
- $prio = $record->rdata->priority;
- $value = $record->rdata->toString(['weight', 'port' , 'target']);
- break;
- case 'URI':
- $prio = $record->rdata->priority;
- $value = $record->rdata->toString(['weight', 'target']);
- break;
- case 'CNAME':
- $prio = 0;
- $value = rtrim($record->rdata->toString(), '.');
- break;
- default:
- $prio = 0;
- $value = $record->rdata->toString();
- break;
- }
- $value = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($value);
- $input = [
- main\mgLibs\custom\helpers\IdnaHelper::idnaEncode( $record->nameToAbsolute($this->domain, false)),
- $record->type,
- $record->ttl,
- $prio,
- time(),
- $value,
- $record->line
- ];
- $valid = $this->validate_input($record->line, $record->type, $value, $input[0], $prio, $record->ttl);
- if ($valid === true)
- {
- $this->log('MODIFY RECORDS');
- if ($this->connect())
- {
- if(empty($this->config['disable_doubled']) && in_array($record->type, $this->typesCantBeDoubled))
- {
- if($this->checkIfRecordSameExist($record))
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException('You cannot add two the same ' .$record->type. ' records', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
-
- if ($this->mysql_safequery('UPDATE records SET name = ?, type = ?, ttl = ?, prio = ?, change_date = ?, content = ? WHERE id = ?', $input))
- {
- $this->updateSoaSerial();
- $this->updateNotifiedSerial();
- $this->disconnect();
-
- try
- {
- if($this->isSigned())
- {
- $this->rectify();
- }
- }
- catch( Exception $ex)
- {}
-
- return true;
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException($this->remote_db->error, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException('Connection problem', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
- }
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException('Validation error: ' . $this->error, dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- }
- public function deleteRecord(dns\record\Record $record)
- {
- $this->domain = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($this->domain);
- if ($this->connect())
- {
- if (strtoupper($record->type) == 'SOA')
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException('You can not remove the SOA record', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- else
- {
- $q = $this->mysql_safequery('DELETE FROM records WHERE id = ?', [$record->line]);
- $this->log('DELETE RECORD');
- if ($q)
- {
- $this->updateSoaSerial();
- $this->updateNotifiedSerial();
- $this->disconnect();
-
- try
- {
- if($this->isSigned())
- {
- $this->rectify();
- }
- }
- catch( Exception $ex)
- {}
-
- return true;
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException('Error occured: ' . $this->remote_db->error, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
- }
- else
- {
- $this->disconnect();
- throw new exceptions\DNSSubmoduleException('Connection problem', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
- }
- }
- public function getZones()
- {
- $this->connect();
- $q = $this->mysql_safequery('SELECT name, master FROM domains');
- $this->log('GET ZONES');
- $out = [];
- while ($row = $q->fetch())
- {
- $out[$row['name']] = $row['master'];
- }
- $this->disconnect();
- return $out;
- }
- /* * ****************************************
- *
- * VALIDATION
- *
- * **************************************** */
- private function validate_input( $rid = false, $type, $content, $name, $prio, $ttl)
- {
- if ($this->config['disable_validation'] === 'on' || $type === 'PTR')
- return true;
- switch ($type)
- {
- case 'A':
- if (!$this->is_valid_ipv4($content))
- return false;
- if (!$this->is_valid_rr_cname_exists($name, $rid))
- return false;
- if (!$this->is_valid_hostname_fqdn($name, 1))
- return false;
- break;
- case 'AAAA':
- if (!$this->is_valid_ipv6($content))
- return false;
- if (!$this->is_valid_rr_cname_exists($name, $rid))
- return false;
- if (!$this->is_valid_hostname_fqdn($name, 1))
- return false;
- break;
- case 'CNAME':
- if (!$this->is_valid_rr_cname_name($name))
- return false;
- if (!$this->is_valid_rr_cname_unique($name, $rid))
- return false;
- if (!$this->is_valid_hostname_fqdn($name, 1))
- return false;
- if (!$this->is_valid_hostname_fqdn($content, 0))
- return false;
- if (!$this->is_not_empty_cname_rr($name, $this->domain))
- return false;
- break;
- case 'NS':
- case 'MX':
- if (!$this->is_valid_hostname_fqdn($content, 0))
- return false;
- if (!$this->is_valid_hostname_fqdn($name, 1))
- return false;
- if (!$this->is_valid_non_alias_target($content))
- return false;
- break;
- case 'SOA':
- if (!$this->is_valid_rr_soa_name($name, $this->domain))
- return false;
- if (!$this->is_valid_hostname_fqdn($name, 1))
- return false;
- if (!$this->is_valid_rr_soa_content($content))
- return false;
- break;
- case 'SRV':
- if (!$this->is_valid_rr_srv_name($name))
- return false;
- if (!$this->is_valid_rr_srv_content($content))
- return false;
- break;
- case 'SPF':
- case 'TXT':
- if (!$this->is_valid_printable($name))
- return false;
- if (!$this->is_valid_printable(main\mgLibs\custom\helpers\IdnaHelper::idnaEncode(trim($content,'"'))))
- return false;
- break;
- case 'LOC':
- if (!$this->is_valid_loc($content))
- return false;
- if (!$this->is_valid_hostname_fqdn($name, 1))
- return false;
- break;
- case 'CAA':
- if(!$this->is_valid_caa($content))
- return false;
- break;
- //2.9.0
- case 'ALIAS':
- if (!$this->is_valid_hostname_fqdn($name, 0))
- return false;
- if (!$this->is_valid_caa_target($content))
- return false;
- break;
- case 'AFSDB':
- if (!$this->is_valid_hostname_fqdn($name, 0))
- return false;
- if (!$this->is_valid_afsdb_record($content))
- return false;
- break;
- case 'WKS':
- if (!$this->is_valid_hostname_fqdn($name, 0))
- return false;
- if (!$this->is_valid_wks_record($content))
- return false;
- break;
- case 'RP':
- case 'NAPTR':
- case 'MR':
- case 'MINFO':
- case 'HINFO':
- case 'DS':
- case 'DNSKEY':
- case 'DNAME':
- case 'RRSIG':
- if (!$this->is_valid_hostname_fqdn($name, 0))
- return false;
- break;
- case 'URL':
- break;
- default:
- $this->error = ERR_DNS_RR_TYPE;
- return false;
- }
- if (!$this->is_valid_rr_prio($prio, $type))
- return false;
- if (!$this->is_valid_rr_ttl($ttl))
- return false;
- return true;
- }
- private function is_valid_hostname_fqdn($hostname, $wildcard)
- {
- $hostname = main\mgLibs\custom\helpers\IdnaHelper::idnaEncode($hostname);
- $dns_strict_tld_check = false;
- $valid_tlds = false;
- $hostname = preg_replace("/\.$/", '', $hostname);
- # The full domain name may not exceed a total length of 253 characters.
- if (strlen($hostname) > 253)
- {
- $this->error = ERR_DNS_HN_TOO_LONG;
- return false;
- }
- $hostname_labels = explode('.', $hostname);
- $label_count = count($hostname_labels);
- if ($label_count == 1)
- {
- $this->error = ERR_DNS_HN_LENGTH;
- return false;
- }
- foreach ($hostname_labels as
- $hostname_label)
- {
- if ($wildcard == 1 && !isset($first))
- {
- if (!preg_match('/^(\*|[\w\-\/]+)$/', $hostname_label))
- {
- $this->error = ERR_DNS_HN_INV_CHARS;
- return false;
- }
- $first = 1;
- }
- else
- {
- if (!preg_match('/^[\w\-\/]+$/', $hostname_label))
- {
- $this->error = ERR_DNS_HN_INV_CHARS;
- return false;
- }
- }
- if ( strpos($hostname_label, '-') === 0 )
- {
- $this->error = ERR_DNS_HN_DASH;
- return false;
- }
- if (substr($hostname_label, -1, 1) === '-' )
- {
- $this->error = ERR_DNS_HN_DASH;
- return false;
- }
- if ( $hostname_label === '' || strlen($hostname_label) > 63)
- {
- $this->error = ERR_DNS_HN_LENGTH;
- return false;
- }
- }
- if ($hostname_labels[$label_count - 1] === 'arpa' && (substr_count($hostname_labels[0], '/') === 1 XOR substr_count($hostname_labels[1], '/') === 1))
- {
- if (substr_count($hostname_labels[0], '/') === 1)
- {
- $array = explode('/', $hostname_labels[0]);
- }
- else
- {
- $array = explode('/', $hostname_labels[1]);
- }
- if (count($array) !== 2)
- {
- $this->error = ERR_DNS_HOSTNAME;
- return false;
- }
- if (!is_numeric($array[0]) || $array[0] < 0 || $array[0] > 255)
- {
- $this->error = ERR_DNS_HOSTNAME;
- return false;
- }
- if (!is_numeric($array[1]) || $array[1] < 25 || $array[1] > 31)
- {
- $this->error = ERR_DNS_HOSTNAME;
- return false;
- }
- }
- else
- {
- if (substr_count($hostname, '/') > 0)
- {
- $this->error = ERR_DNS_HN_SLASH;
- return false;
- }
- }
- if ($dns_strict_tld_check && !in_array(strtolower($hostname_labels[$label_count - 1]), $valid_tlds))
- {
- $this->error = ERR_DNS_INV_TLD;
- return false;
- }
- return true;
- }
- private function is_valid_ipv4($ipv4, $answer = true)
- {
- if (!preg_match('/^[0-9.]{7,15}$/', $ipv4))
- {
- if ($answer)
- {
- $this->error = ERR_DNS_IPV4;
- }
- return false;
- }
- $quads = explode('.', $ipv4);
- $numquads = count($quads);
- if ($numquads !== 4)
- {
- if ($answer)
- {
- $this->error = ERR_DNS_IPV4;
- }
- return false;
- }
- for ($i = 0;
- $i < 4;
- $i++)
- {
- if ($quads[$i] > 255)
- {
- if ($answer)
- {
- $this->error = ERR_DNS_IPV4;
- }
- return false;
- }
- }
- return true;
- }
- private function is_valid_ipv6($ipv6, $answer = true)
- {
- if (!preg_match('/^[0-9a-f]{0,4}:([0-9a-f]{0,4}:){0,6}[0-9a-f]{0,4}$/i', $ipv6))
- {
- if ($answer)
- {
- $this->error = ERR_DNS_IPV6;
- }
- return false;
- }
- $quads = explode(':', $ipv6);
- $numquads = count($quads);
- if ($numquads > 8 || $numquads < 3)
- {
- if ($answer)
- {
- $this->error = ERR_DNS_IPV6;
- }
- return false;
- }
- $emptyquads = 0;
- for ($i = 1;
- $i < $numquads - 1;
- $i++)
- {
- if ($quads[$i] == '' )
- $emptyquads++;
- }
- if ($emptyquads > 1)
- {
- if ($answer)
- {
- $this->error = ERR_DNS_IPV6;
- }
- return false;
- }
- if ($emptyquads === 0 && $numquads !== 8)
- {
- if ($answer)
- {
- $this->error = ERR_DNS_IPV6;
- }
- return false;
- }
- return true;
- }
- private function is_valid_printable($string)
- {
- if (!preg_match('/^[[:print:]]+$/', trim($string)))
- {
- $this->error = ERR_DNS_PRINTABLE;
- return false;
- }
- return true;
- }
-
- private function is_valid_afsdb_record($string)
- {
- $record = explode(' ', $string);
- if (!$this->is_valid_hostname_fqdn($record[1], 1)){
- return false;
- }
- if(!$this->is_valid_subtype($record[0])){
- return false;
- }
- return true;
- }
-
- private function is_valid_subtype($type){
- if($type == 1 || $type == 2){
- return true;
- }
-
- $this->error = ERR_DNS_SUBTYPE;
- return false;
- }
-
- private function is_valid_wks_record($string)
- {
- $record = explode(' ', $string);
- if (!$this->is_valid_ipv4($record[0])){
- return false;
- }
- return true;
- }
-
- private function is_valid_rr_cname_name($name)
- {
- if ($this->connect())
- {
- $q = $this->mysql_safequery("SELECT type, content FROM records WHERE content = ? AND (type = 'MX' OR type = 'NS')", [
- $name
- ]);
- if ($q !== false)
- {
- if($q->numRows() > 0)
- {
- $this->error = ERR_DNS_CNAME;
- return false;
- }
- }
- else
- {
- $this->error = 'Power DNS database error: ' . $this->remote_db->error;
- return false;
- }
- $this->disconnect();
- }
- else
- {
- $this->error = 'Unable connect to Power DNS database';
- return false;
- }
- return true;
- }
- private function is_valid_rr_cname_exists($name, $rid)
- {
- if ($this->connect())
- {
- $args[] = $name;
- if ($rid > 0)
- {
- $where = ' AND id != ? ';
- $args[] = $rid;
- }
- else
- {
- $where = '';
- }
- $q = $this->mysql_safequery('SELECT type, name FROM records WHERE name = ?' . $where . " AND TYPE = 'CNAME'", $args);
- if($q !== false)
- {
- if($q->numRows() > 0)
- {
- $this->error = ERR_DNS_CNAME_EXISTS;
- return false;
- }
- }
- else
- {
- $this->error = 'Power DNS database error: ' . $this->remote_db->error;
- return false;
- }
- $this->disconnect();
- }
- else
- {
- $this->error = 'Unable connect to Power DNS database';
- return false;
- }
- return true;
- }
- private function is_valid_rr_cname_unique($name, $rid)
- {
- if ($this->connect())
- {
- $args[] = $name;
- if ($rid > 0)
- {
- $where = ' AND id != ? ';
- $args[] = $rid;
- }
- else
- {
- $where = '';
- }
- $q = $this->mysql_safequery('SELECT * FROM records WHERE name = ? ' . $where . " AND TYPE IN ('A', 'AAAA', 'CNAME')", $args);
- if ($q !== false)
- {
- if($q->numRows() > 0)
- {
- $this->error = ERR_DNS_CNAME_UNIQUE;
- return false;
- }
- }
- else
- {
- $this->error = 'Power DNS database error: ' . $this->remote_db->error;
- return false;
- }
- $this->disconnect();
- }
- else
- {
- $this->error = 'Unable connect to Power DNS database';
- return false;
- }
- return true;
- }
- private function is_not_empty_cname_rr($name, $zone)
- {
- if ($name == $zone)
- {
- $this->error = ERR_DNS_CNAME_EMPTY;
- return false;
- }
- return true;
- }
- private function is_valid_non_alias_target($target)
- {
- if ($this->connect())
- {
- $q = $this->mysql_safequery("SELECT type, name FROM records WHERE name = ? AND TYPE = 'CNAME'", [
- $target
- ]);
- if ($q !== false)
- {
- if($q->numRows() > 0)
- {
- $this->error = ERR_DNS_NON_ALIAS_TARGET;
- return false;
- }
- }
- else
- {
- $this->error = 'Power DNS database error: ' . $this->remote_db->error;
- return false;
- }
- $this->disconnect();
- }
- else
- {
- $this->error = 'Unable connect to Power DNS database';
- return false;
- }
- return true;
- }
- private function is_valid_rr_soa_content($content)
- {
- $fields = preg_split("/\s+/", trim($content));
- $field_count = count($fields);
- if ($field_count == 0 || $field_count > 7)
- {
- return false;
- }
- else
- {
- if (!$this->is_valid_hostname_fqdn($fields[0], 0) || preg_match('/\.arpa\.?$/', $fields[0]))
- {
- return false;
- }
- $final_soa = $fields[0];
- if (isset($fields[1]))
- {
- $addr_input = $fields[1];
- }
- else
- {
- global $dns_hostmaster;
- $addr_input = $dns_hostmaster;
- }
- if (!preg_match('/@/', $addr_input))
- {
- $addr_input = preg_split('/(?<!\\\)\./', $addr_input, 2);
- $addr_to_check = str_replace("\\", '', $addr_input[0]) . '@' . $addr_input[1];
- }
- else
- {
- $addr_to_check = $addr_input;
- }
- if (!$this->is_valid_email($addr_to_check))
- {
- return false;
- }
- else
- {
- $addr_final = explode('@', $addr_to_check, 2);
- $final_soa .= ' ' . str_replace('.', "\\.", $addr_final[0]) . '.' . $addr_final[1];
- }
- if (isset($fields[2]))
- {
- if (!is_numeric($fields[2]))
- {
- return false;
- }
- $final_soa .= ' ' . $fields[2];
- }
- else
- {
- $final_soa .= ' 0';
- }
- if ($field_count == 7)
- {
- for ($i = 3;
- ($i < 7);
- $i++)
- {
- if (!is_numeric($fields[$i]))
- {
- return false;
- }
- else
- {
- $final_soa .= ' ' . $fields[$i];
- }
- }
- }
- }
- $content = $final_soa;
- return true;
- }
- private function is_valid_email($addr)
- {
- if (filter_var($addr, FILTER_VALIDATE_EMAIL) === false)
- {
- $this->error = ERR_INV_EMAIL;
- return false;
- }
- else
- {
- return true;
- }
- }
- private function is_valid_rr_soa_name($name, $zone)
- {
- $zone = rtrim($zone,'.').'.';
- $name = rtrim($name,'.').'.';
- if ($name != $zone)
- {
- $this->error = ERR_DNS_SOA_NAME;
- return false;
- }
- return true;
- }
- private function is_valid_rr_prio(&$prio, $type)
- {
- if ($type == 'MX' || $type == 'SRV' )
- {
- if (!is_numeric($prio) || $prio < 0 || $prio > 65535)
- {
- $this->error = ERR_DNS_INV_PRIO;
- return false;
- }
- }
- else
- {
- $prio = 0;
- }
- return true;
- }
- private function is_valid_rr_srv_name(&$name)
- {
- if (strlen($name) > 255)
- {
- $this->error = ERR_DNS_HN_TOO_LONG;
- return false;
- }
- $fields = explode('.', $name, 3);
- if (!preg_match('/^_[\w-]+$/', $fields[0]))
- {
- $this->error = ERR_DNS_SRV_NAME;
- return false;
- }
- if (!preg_match('/^_[\w]+$/', $fields[1]))
- {
- $this->error = ERR_DNS_SRV_NAME;
- return false;
- }
- if (!$this->is_valid_hostname_fqdn($fields[2], 0))
- {
- $this->error = ERR_DNS_SRV_NAME;
- return false;
- }
- $name = implode('.', $fields);
- return true;
- }
- private function is_valid_rr_srv_content(&$content)
- {
- $fields = preg_split("/\s+/", trim($content), 3);
- if (!is_numeric($fields[0]) || $fields[0] < 0 || $fields[0] > 65535)
- {
- $this->error = ERR_DNS_SRV_WGHT;
- return false;
- }
- if (!is_numeric($fields[1]) || $fields[1] < 0 || $fields[1] > 65535)
- {
- $this->error = ERR_DNS_SRV_PORT;
- return false;
- }
- if ($fields[2] === '' || ($fields[2] !== '.' && !$this->is_valid_hostname_fqdn($fields[2], 0)))
- {
- $this->error = ERR_DNS_SRV_TRGT;
- return false;
- }
- $content = implode(' ', $fields);
- return true;
- }
- private function is_valid_rr_ttl(&$ttl)
- {
- if (!isset($ttl) || $ttl == '' )
- {
- global $dns_ttl;
- $ttl = $dns_ttl;
- }
- if (!is_numeric($ttl) || $ttl < 0 || $ttl > 2147483647)
- {
- $this->error = ERR_DNS_INV_TTL;
- return false;
- }
- return true;
- }
- private function is_valid_loc($content)
- {
- $regex = "^(90|[1-8]\d|0?\d)( ([1-5]\d|0?\d)( ([1-5]\d|0?\d)(\.\d{1,3})?)?)? [NS] (180|1[0-7]\d|[1-9]\d|0?\d)( ([1-5]\d|0?\d)( ([1-5]\d|0?\d)(\.\d{1,3})?)?)? [EW] (-(100000(\.00)?|\d{1,5}(\.\d\d)?)|([1-3]?\d{1,7}(\.\d\d)?|4([01][0-9]{6}|2([0-7][0-9]{5}|8([0-3][0-9]{4}|4([0-8][0-9]{3}|9([0-5][0-9]{2}|6([0-6][0-9]|7[01]))))))(\.\d\d)?|42849672(\.([0-8]\d|9[0-5]))?))[m]?( (\d{1,7}|[1-8]\d{7})(\.\d\d)?[m]?){0,3}$^";
- if (!preg_match($regex, $content))
- {
- return false;
- }
- else
- {
- return true;
- }
- }
-
- private function is_valid_caa($content)
- {
- $vars = explode(' ',$content);
- if($this->is_valid_caa_flag($vars[0]) && $this->is_valid_caa_tag($vars[1]) && $this->is_valid_caa_target($vars[2]))
- {
- return true;
- }
-
- return false;
- }
-
- private function is_valid_caa_flag($flag)
- {
- if(is_numeric($flag) && $flag >= 0 && $flag <= 255)
- {
- return true;
- }
-
- $this->error = ERR_DNS_CAA_FLAG;
- return false;
- }
-
- private function is_valid_caa_tag($tag)
- {
- return is_string($tag);
- }
-
- private function is_valid_caa_target($target)
- {
- if($target[0] === '"' && $target[strlen($target) - 1] === '"')
- {
- return true;
- }
-
- $this->error = ERR_DNS_CAA_TARGET;
- return false;
- }
- /**********************************************
- * DNS SEC
- *********************************************/
- public function generateSignKeys()
- {
-
- }
- /**
- *
- * @return DnsSec
- */
- public function getSignKeys()
- {
- $dnssec = new DnsSec();
- $command = $this->pdnsutil("show-zone $this->domain");
- $keys = array_filter(explode("\n", substr($command['stdio'], strpos($command['stdio'], 'keys:')+5)));
-
-
- foreach($keys as $index => $key)
- {
- if(strpos($key, 'DS') === 0)
- {
- $ex = preg_split('/\s+/', $key);
- $ds = new dns\record\type\DS();
- $ds->setKeytag($ex[5]);
- $ds->setAlgorithm($ex[6]);
- $ds->setDigestType($ex[7]);
- $ds->setDigest($ex[8]);
-
- $dnssec->addDs($ds);
- }
- elseif(strpos($key, 'CSK DNSKEY') === 0)
- {
- $ex = preg_split('/\s+/', $key);
-
- $dnskey = new dns\record\type\DNSKEY();
- $dnskey->setFlags($ex[6]);
- $dnskey->setProtocol($ex[7]);
- $dnskey->setAlgorithm($ex[8]);
- $dnskey->setPublicKey($ex[9]);
-
- $ex = array_map(function($field){return explode('=', $field);}, explode(',', $keys[$index-1]));
- $ex = array_map(function($field){return [trim($field[0]) => trim($field[1])];}, $ex);
-
- $zoneKey = new dns\dnssec\CSK();
- $zoneKey->setId((int)$ex[2]['tag']);
- $zoneKey->setBits((int)$ex[4]['bits']);
- $zoneKey->setDnsKey($dnskey);
-
- $dnssec->addKey($zoneKey);
- }
- elseif(strpos($key, 'KSK DNSKEY') === 0)
- {
- $ex = preg_split('/\s+/', $key);
-
- $dnskey = new dns\record\type\DNSKEY();
- $dnskey->setFlags($ex[6]);
- $dnskey->setProtocol($ex[7]);
- $dnskey->setAlgorithm($ex[8]);
- $dnskey->setPublicKey($ex[9]);
-
- $dnskey2 = new dns\record\type\DNSKEY();
- $dnskey2->setFlags($ex[6]);
- $dnskey2->setProtocol($ex[7]);
- $dnskey2->setAlgorithm($ex[8]);
-
- $ex = array_map(function($field){return explode('=', $field);}, explode(',', $keys[$index-1]));
- $ex = array_map(function($field){return [trim($field[0]) => trim($field[1])];}, $ex);
-
- $ksk = new dns\dnssec\KSK();
- $ksk->setId((int)$ex[2]['tag']);
- $ksk->setBits((int)$ex[4]['bits']);
- $ksk->setDnsKey($dnskey);
-
- $ex = array_map(function($field){return explode('=', $field);}, explode(',', $keys[$index-2]));
- $ex = array_map(function($field){return [trim($field[0]) => trim($field[1])];}, $ex);
-
- $zsk = new dns\dnssec\ZSK();
- $zsk->setId((int)$ex[2]['tag']);
- $zsk->setBits((int)$ex[4]['bits']);
- $zsk->setDnsKey($dnskey2);
-
- $dnssec->addKey($ksk);
- $dnssec->addKey($zsk);
- }
- }
-
- return $dnssec;
- }
- public function isSigned()
- {
- $command = $this->pdnsutil("show-zone $this->domain");
-
- if(stripos($command['stderr'], 'No keys for zone') !== false)
- {
- return false;
- }
- return true;
- }
- public function sign()
- {
- $command = $this->pdnsutil("secure-zone $this->domain", false);
- $match = preg_match("/Zone {$this->domain}\.? secured/", $command['stdio']);
-
- if(!$match && $command['stderr'])
- {
- throw new exceptions\DNSSubmoduleException($command['stderr'], dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
- public function unsign()
- {
- $command = $this->pdnsutil("disable-dnssec $this->domain");
- if(!empty($command['stderr']))
- {
- throw new exceptions\DNSSubmoduleException($command['stderr'], dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
-
- public function rectify()
- {
- $command = $this->pdnsutil("rectify-zone $this->domain");
- if(!empty($command['stderr']) && stripos($command['stderr'], 'Adding NSEC') === false)
- {
- throw new exceptions\DNSSubmoduleException($command['stderr'], dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- }
-
- protected function connectSSH()
- {
- if(!function_exists('ssh2_connect'))
- {
- throw new exceptions\DNSSubmoduleException('Cannot find SSH2 for PHP. Please <a href="http://php.net/manual/en/ssh2.installation.php">install</a> SSH2 extension', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
-
- if(empty($this->config['ssh_host']))
- {
- throw new exceptions\DNSSubmoduleException('SSH Host field is empty. Cannot connect to server', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
-
- if(empty($this->config['ssh_username']))
- {
- throw new exceptions\DNSSubmoduleException('SSH Username field is empty. Cannot connect to server', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
-
- if(empty($this->config['ssh_password']) && (empty($this->config['ssh_public_key']) && empty($this->config['ssh_private_key'])))
- {
- throw new exceptions\DNSSubmoduleException('SSH Password or SSH Key field is empty. Cannot connect to server', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
-
- if(empty($this->config['ssh_port']))
- {
- throw new exceptions\DNSSubmoduleException('SSH Port field is empty. Cannot connect to server', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
-
- $this->ssh = ssh2_connect($this->config['ssh_host'], $this->config['ssh_port']);
- if(!$this->ssh)
- {
- throw new exceptions\DNSSubmoduleException('Cannot connect to SSH', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
-
- if(!empty($this->config['ssh_public_key']) && !empty($this->config['ssh_private_key']))
- {
- $sshPublicKey =
- $this->config['ssh_public_key'][0] === '/'
- ? $this->config['ssh_public_key']
- : ROOTDIR.DIRECTORY_SEPARATOR.'ssh_keys'.DIRECTORY_SEPARATOR.$this->config['ssh_public_key'];
- $shhPrivateKey =
- $this->config['ssh_private_key'][0] === '/'
- ? $this->config['ssh_private_key']
- : ROOTDIR.DIRECTORY_SEPARATOR.'ssh_keys'.DIRECTORY_SEPARATOR.$this->config['ssh_private_key'];
-
- if(!file_get_contents($sshPublicKey)) {
- throw new exceptions\DNSSubmoduleException('SSH public key file does not exist at path: ' . $sshPublicKey, dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- if(!file_get_contents($shhPrivateKey)) {
- throw new exceptions\DNSSubmoduleException('SSH private key file does not exist at path: ' . $shhPrivateKey, dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
-
- $auth = ssh2_auth_pubkey_file($this->ssh, $this->config['ssh_username'], $sshPublicKey, $shhPrivateKey);
-
- if(!$auth)
- {
- $this->ssh = null;
- throw new exceptions\DNSSubmoduleException('Cannot login to server (SSH). Check your credentials', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- }
- else
- {
- $auth = ssh2_auth_password($this->ssh, $this->config['ssh_username'], $this->config['ssh_password']);
- if(!$auth)
- {
- $this->ssh = null;
- throw new exceptions\DNSSubmoduleException('Cannot login to server. Check your credentials', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- }
- }
-
- protected function pdnsutil($command = '', $throwErrorWhenStdErr = true)
- {
- if(!$this->ssh)
- {
- $this->connectSSH();
- }
- if(!$this->config['pdnsutil_path'])
- {
- throw new exceptions\DNSSubmoduleException('PDNSUTIL path empty. Cannot run command', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
-
- $pdnsutil = $this->config['pdnsutil_path'];
- $stream = ssh2_exec($this->ssh, $pdnsutil.' '.$command);
- $errorStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
-
- stream_set_blocking($errorStream, true);
- stream_set_blocking($stream, true);
-
- $streamContent = stream_get_contents($stream);
- $errorStreamContent = stream_get_contents($errorStream);
- // Close the streams
- fclose($errorStream);
- fclose($stream);
-
- return
- [
- 'stdio' => $streamContent,
- 'stderr' => $errorStreamContent
- ];
- }
-
- public function checkIfRecordSameExist($record)
- {
- if(empty($record->line))
- {
- $res = $this->mysql_safequery('SELECT id, name, content FROM records WHERE domain_id = (SELECT id FROM domains WHERE LOWER(name) = ?) AND type = ? AND name = ?',
- [strtolower($this->domain), $record->type, $record->name]);
- }
- else
- {
- $res = $this->mysql_safequery('SELECT id, name, content FROM records WHERE domain_id = (SELECT id FROM domains WHERE name = ?) AND type = ? AND name = ? AND id != ?',
- [$this->domain, $record->type, $record->name, $record->line]);
- }
- return $res->numRows() > 0;
- }
- public function validateRecord($record)
- {
- if($this->server->getModuleConfiguration()['disable_validation'] !== 'on') {
- parent::validateRecord($record);
- }
- }
- }
- $messages_file = substr(__DIR__, 0, strpos(__DIR__, '' . DIRECTORY_SEPARATOR . 'includes')) . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'addons' . DIRECTORY_SEPARATOR . 'dns_manager' . DIRECTORY_SEPARATOR . 'powerdns_messages.php';
- if (file_exists($messages_file))
- {
- require_once($messages_file);
- }
- else
- {
- define('ERR_PERM_SEARCH', 'You do not have the permission to perform searches.');
- define('ERR_PERM_ADD_RECORD', 'You do not have the permission to add a record to this zone.');
- define('ERR_PERM_EDIT_RECORD', 'You do not have the permission to edit this record.');
- define('ERR_PERM_VIEW_RECORD', 'You do not have the permission to view this record.');
- define('ERR_PERM_DEL_RECORD', 'You do not have the permission to delete this record.');
- define('ERR_PERM_ADD_ZONE_MASTER', 'You do not have the permission to add a master zone.');
- define('ERR_PERM_ADD_ZONE_SLAVE', 'You do not have the permission to add a slave zone.');
- define('ERR_PERM_DEL_ZONE', 'You do not have the permission to delete a zone.');
- define('ERR_PERM_VIEW_COMMENT', 'You do not have the permission to view this comment.');
- define('ERR_PERM_EDIT_COMMENT', 'You do not have the permission to edit this comment.');
- define('ERR_PERM_DEL_SM', 'You do not have the permission to delete a supermaster.');
- define('ERR_PERM_VIEW_ZONE', 'You do not have the permission to view this zone.');
- define('ERR_PERM_EDIT_USER', 'You do not have the permission to edit this user.');
- define('ERR_PERM_EDIT_PERM_TEMPL', 'You do not have the permission to edit permission templates.');
- define('ERR_PERM_DEL_PERM_TEMPL', 'You do not have the permission to delete permission templates.');
- define('ERR_PERM_ADD_USER', 'You do not have the permission to add a new user.');
- define('ERR_PERM_DEL_USER', 'You do not have the permission to delete this user.');
- define('ERR_PERM_EDIT_ZONE_TEMPL', 'You do not have the permission to edit zone templates.');
- define('ERR_PERM_DEL_ZONE_TEMPL', 'You do not have the permission to delete zone templates.');
- define('ERR_PERM_ADD_ZONE_TEMPL', 'You do not have the permission to add a zone template.');
- /* DOMAIN STUFF */
- define('ERR_DOMAIN_INVALID', 'This is an invalid zone name.');
- define('ERR_SM_EXISTS', 'There is already a supermaster with this IP address and hostname.');
- define('ERR_DOMAIN_EXISTS', 'There is already a zone with this name.');
- /* USER STUFF */
- define('ERR_USER_EXIST', 'Username exist already, please choose another one.');
- define('ERR_USER_NOT_EXIST', 'User does not exist.');
- define('ERR_USER_WRONG_CURRENT_PASS', 'You did not enter the correct current password.');
- define('ERR_USER_MATCH_NEW_PASS', 'The two new password fields do not match.');
- define('ERR_PERM_TEMPL_ASSIGNED', 'This template is assigned to at least one user.');
- /* OTHER */
- define('ERR_INV_INPUT', 'Invalid or unexpected input given.');
- define('ERR_INV_ARG', 'Invalid argument(s) given to function %s');
- define('ERR_INV_ARGC', 'Invalid argument(s) given to function %s %s');
- define('ERR_UNKNOWN', 'Unknown error.');
- define('ERR_INV_EMAIL', 'Enter a valid email address.');
- define('ERR_ZONE_NOT_EXIST', 'There is no zone with this ID.');
- define('ERR_REVERS_ZONE_NOT_EXIST', 'There is no matching reverse-zone for: %s.');
- define('ERR_ZONE_TEMPL_NOT_EXIST', 'There is no zone template with this ID.');
- define('ERR_INSTALL_DIR_EXISTS', 'The <a href="install/">install/</a> directory exists, you must remove it first before proceeding.');
- define('ERR_ZONE_TEMPL_EXIST', 'Zone template with this name already exists, please choose another one.');
- define('ERR_ZONE_TEMPL_IS_EMPTY', 'Template name can\'t be an empty string.');
- define('ERR_DEFAULT_CRYPTOKEY_USED', 'Default session encryption key is used, please set it in your configuration file.');
- define('ERR_LOCALE_FAILURE', 'Failed to set locale.');
- define('ERR_ZONE_UPD', 'Zone has not been updated successfully.');
- define('ERR_EXEC_NOT_ALLOWED', 'Failed to call function exec. Make sure that exec is not listed in disable_functions at php.ini');
- /* DATABASE */
- define('ERR_DB_NO_DB_NAME', 'No database name has been set in config.inc.php.');
- define('ERR_DB_NO_DB_HOST', 'No database host has been set in config.inc.php.');
- define('ERR_DB_NO_DB_USER', 'No database username has been set in config.inc.php.');
- define('ERR_DB_NO_DB_PASS', 'No database password has been set in config.inc.php.');
- define('ERR_DB_NO_DB_TYPE', 'No or unknown database type has been set in config.inc.php.');
- define('ERR_DB_NO_DB_FILE', 'No database file has been set in config.inc.php.');
- define('ERR_DB_NO_DB_UPDATE', 'It seems that you forgot to update the database after Poweradmin upgrade to new version.');
- define('ERR_DB_UNK_TYPE', 'Unknown database type.');
- /* DNS */
- define('ERR_DNS_CONTENT', 'Your content field doesnt have a legit value.');
- define('ERR_DNS_HOSTNAME', 'Invalid hostname.');
- define('ERR_DNS_HN_INV_CHARS', 'You have invalid characters in your hostname.');
- define('ERR_DNS_HN_INV_CONTENT', 'Invalid content.');
- define('ERR_DNS_HN_DASH', 'A hostname can not start or end with a dash.');
- define('ERR_DNS_HN_LENGTH', 'Given hostname or one of the labels is too short or too long.');
- define('ERR_DNS_HN_SLASH', 'Given hostname has too many slashes.');
- define('ERR_DNS_RR_TYPE', 'Unknown record type.');
- define('ERR_DNS_IP', 'This is not a valid IPv4 or IPv6 address.');
- define('ERR_DNS_IPV6', 'This is not a valid IPv6 address.');
- define('ERR_DNS_IPV4', 'This is not a valid IPv4 address.');
- define('ERR_DNS_CNAME', 'This is not a valid CNAME. Did you assign an MX or NS record to the record?');
- define('ERR_DNS_CNAME_EXISTS', 'This is not a valid record. There is already exists a CNAME with this name.');
- define('ERR_DNS_CNAME_UNIQUE', 'This is not a valid CNAME. There is already exists an A, AAAA or CNAME with this name.');
- define('ERR_DNS_CNAME_EMPTY', 'Empty CNAME records are not allowed.');
- define('ERR_DNS_NON_ALIAS_TARGET', 'You can not point a NS or MX record to a CNAME record. Remove or rame the CNAME record first, or take another name.');
- define('ERR_DNS_NS_HNAME', 'NS records must be a hostnames.');
- define('ERR_DNS_MX_PRIO', 'A prio field should be numeric.');
- define('ERR_DNS_SOA_NAME', 'Invalid value for name field of SOA record. It should be the name of the zone.');
- define('ERR_DNS_SOA_MNAME', 'You have an error in the MNAME field of the SOA record.');
- define('ERR_DNS_HINFO_INV_CONTENT', 'Invalid value for content field of HINFO record.');
- define('ERR_DNS_HN_TOO_LONG', 'The hostname is too long.');
- define('ERR_DNS_INV_TLD', 'You are using an invalid top level domain.');
- define('ERR_DNS_INV_TTL', 'Invalid value for TTL field. It should be numeric.');
- define('ERR_DNS_INV_PRIO', 'Invalid value for prio field. It should be numeric.');
- define('ERR_DNS_SRV_NAME', 'Invalid value for name field of SRV record.');
- define('ERR_DNS_SRV_WGHT', 'Invalid value for the priority field of the SRV record.');
- define('ERR_DNS_SRV_PORT', 'Invalid value for the weight field of the SRV record.');
- define('ERR_DNS_SRV_TRGT', 'Invalid SRV target.');
- define('ERR_DNS_PRINTABLE', 'Invalid characters have been used in this record.');
- define('ERR_DNS_CAA_FLAG', 'Invalid flag value.');
- define('ERR_DNS_CAA_TARGET', 'Target has to be in " "');
- /* PDNSSEC */
- define('ERR_EXEC_PDNSSEC', 'Failed to call pdnssec utility.');
- define('ERR_EXEC_PDNSSEC_SECURE_ZONE', 'Failed to secure zone.');
- define('ERR_EXEC_PDNSSEC_RECTIFY_ZONE', 'Failed to rectify zone.');
- /* GOOD! */
- define('SUC_ZONE_ADD', 'Zone has been added successfully.');
- define('SUC_ZONE_DEL', 'Zone has been deleted successfully.');
- define('SUC_ZONE_UPD', 'Zone has been updated successfully.');
- define('SUC_ZONES_UPD', 'Zones have been updated successfully.');
- define('SUC_USER_UPD', 'The user has been updated successfully.');
- define('SUC_USER_ADD', 'The user has been created successfully.');
- define('SUC_USER_DEL', 'The user has been deleted successfully.');
- define('SUC_RECORD_UPD', 'The record has been updated successfully.');
- define('SUC_RECORD_DEL', 'The record has been deleted successfully.');
- define('SUC_COMMENT_UPD', 'The comment has been updated successfully.');
- define('SUC_SM_DEL', 'The supermaster has been deleted successfully.');
- define('SUC_SM_ADD', 'The supermaster has been added successfully.');
- define('SUC_PERM_TEMPL_ADD', 'The permission template has been added successfully.');
- define('SUC_PERM_TEMPL_UPD', 'The permission template has been updated successfully.');
- define('SUC_PERM_TEMPL_DEL', 'The permission template has been deleted successfully.');
- define('SUC_ZONE_TEMPL_ADD', 'Zone template has been added successfully.');
- define('SUC_ZONE_TEMPL_UPD', 'Zone template has been updated successfully.');
- define('SUC_ZONE_TEMPL_DEL', 'Zone template has been deleted successfully.');
- define('SUC_EXEC_PDNSSEC_RECTIFY_ZONE', 'Zone has been rectified successfully.');
-
-
- //2.9.0
- define('ERR_DNS_SUBTYPE', 'This is not a valid subtype. Valid type is 1 or 2 depending on whether the endpoint is an AFS Volume Location Server or DCE Authentication Server.');
- }
|