| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- <?php
- namespace MGModule\DNSManager2\mgLibs\custom\dns\submodules;
- use \MGModule\DNSManager2\mgLibs\custom\dns;
- 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\mgLibs\custom\dns\submodules\cPanel as cPanelUapi;
- use MGModule\DNSManager2\mgLibs\custom\helpers\IdnaHelper;
- class CPanel extends dns\SubmoduleAbstract implements
- interfaces\SubmoduleIPInterface,
- interfaces\SubmoduleRDNSInterface,
- interfaces\SubmoduleTTLInterface,
- interfaces\SubmoduleDNSSecInterface,
- interfaces\SubmoduleImportInterface
- {
- public $configFields = array(
- 'username' =>array (
- 'friendlyName' => 'Username',
- 'validators' => array(
- 'required' => 'required',
- )
- ),
- 'password' =>array (
- 'friendlyName' => 'User Password',
- 'type'=> 'password',
- ),
- 'resellerAccount' =>array (
- 'friendlyName' => 'Reseller Account',
- 'type'=> 'yesno',
- ),
- 'hash' =>array (
- 'friendlyName' => 'Access Key',
- 'type'=> 'textarea',
- ),
- 'hostname' =>array (
- 'friendlyName' => 'Hostname/IP',
- 'validators' => array(
- 'required' => 'required',
- )
- ),
- 'ssl' =>array (
- 'friendlyName' => 'Enable SSL',
- 'type'=> 'yesno',
- ),
- 'timeout' =>array (
- 'friendlyName' => 'Timeout',
- 'help' => 'Set timeout in second for the API connection. If value is empty, the default value is 30',
- ),
- 'default_ip' =>array (
- 'friendlyName' => 'Default IP',
- 'validators' => array(
- 'required' => 'required',
- 'pattern' => Patterns::IP4_OR_IP6,
- )
- ),
- 'allow_create' =>array (
- 'friendlyName' => 'In cPanel Zones',
- 'type' => 'yesno',
- 'help' => 'Allow to create zones when already in CPanel as account',
- ),
- 'template' =>array (
- 'friendlyName' => 'Template',
- 'help' => 'Default zone template from your cPanel'
- ),
- );
-
- public $availableTypes = array('A', 'AAAA','CAA', 'NS', 'MX', 'CNAME', 'DNAME', 'LOC', 'TXT', 'SRV', 'PTR', 'AFSDB', 'NAPTR', 'RP', 'SOA');
- protected $uapi;
- public function testConnection()
- {
- try
- {
- $this->get('get_nameserver_config');
- return true;
- }
- catch( exceptions\DNSSubmoduleException $e )
- {
- $this->get('listzones', ['api.chunk.enable' => 1, 'api.chunk.size' => 1]);
- return true;
- }
- }
- public function getRecords($recordType = false) {
- $out = $this->get('dumpzone', array(
- 'domain' => $this->domain
- ));
- $return = array();
- if(!isset($out->zone[0]->record)){
- throw new exceptions\DNSSubmoduleException('Unable to fetch records from server', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- foreach($out->zone[0]->record as $r) {
- $recordAdapter = '\MGModule\DNSManager2\mgLibs\custom\dns\submodules\cPanel\\'.$r->type.'Adapter';
- if (class_exists($recordAdapter))
- {
- $return[] = $recordAdapter::toDnsManagerRecord((array)$r);
- }
- elseif ( in_array((string)$r->type, $recordType !== false ? [strtoupper($recordType)] : $this->getAvailableRecordTypes()) )
- {
- $return[] = dns\record\Record::tryToCreateFromArray((array)$r);
- }
- }
- return $return;
- }
- public function addRecord(dns\record\Record $record)
- {
- $adapterClassName = '\MGModule\DNSManager2\mgLibs\custom\dns\submodules\cPanel\\'.$record->type.'Adapter';
- if(class_exists($adapterClassName))
- {
- /** @var dns\record\Record $record */
- $record = new $adapterClassName($record);
- }
- $input = $record->toMergedArray(false);
- $input['domain'] = $this->domain;
- $input['name'] = IdnaHelper::idnaEncode($record->nameToAbsolute($this->domain));
- $this->logAction('addRecord', $input, $record);
- $this->get('addzonerecord', $input);
- return true;
- }
-
- public function editRecord(dns\record\Record $record) {
- $records = $this->getRecords();
- if(empty($records))
- return false;
-
- $lines = array();
- foreach($records as $r) {
- $lines[$r['line']] = $r;
- }
- if(!isset($lines[$record['line']]) || !$record->isEqualTo($lines[$record['line']])) {
- $adapterClassName = '\MGModule\DNSManager2\mgLibs\custom\dns\submodules\cPanel\\'.$record->type.'Adapter';
- if(class_exists($adapterClassName))
- {
- /** @var dns\record\Record $record */
- $record = new $adapterClassName($record);
- }
- $input = $record->toMergedArray(false);
- $input['domain'] = $this->domain;
- $input['name'] = IdnaHelper::idnaEncode($record->nameToAbsolute($this->domain));
- $this->get('editzonerecord', $input);
- }
-
-
- }
-
- public function deleteRecord(dns\record\Record $record) {
- $this->get('removezonerecord', array(
- 'zone' => $this->domain,
- 'line' => $record['line']
- ));
- }
- public function zoneExists()
- {
- try
- {
- $this->get('dumpzone', ['domain' => $this->domain]);
- }
- catch( exceptions\DNSSubmoduleException $e )
- {
- if( $e->getCode() == dns\SubmoduleExceptionCodes::COMMAND_ERROR )
- {
- return false;
- }
- throw $e;
- }
- return true;
- }
-
- public function activateZone() {
- if($this->ip != '') {
- if(!filter_var($this->ip, FILTER_VALIDATE_IP)) {
- throw new exceptions\DNSSubmoduleException('IP is not valid!', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- } else {
- $this->ip = $this->config['default_ip'];
- }
- $params = array(
- 'domain' => $this->domain,
- 'ip' => $this->ip
- );
- if($this->config['resellerAccount'] == "on"){
- $params['trueowner'] = $this->config['username'];
- }
- if($this->config['template'] != "")
- $params['template'] = $this->config['template'];
-
- try {
- $this->get('adddns', $params);
- } catch (exceptions\DNSSubmoduleException $e) {
- if(preg_match('/is owned by another user/', $e->getMessage()) && $this->config['allow_create'] == 'on') {
- $res = $this->get('listaccts', array('want' => 'user', 'searchtype' => 'domain', 'search' => $this->domain, 'searchmethod' => 'exact'));
- $user = $res->acct[0]->user;
- $params['trueowner'] = $user;
- $this->get('adddns', $params);
- return ;
- }
- throw $e;
- }
- }
-
- public function terminateZone() {
- $this->get('killdns', array(
- 'domain' => $this->domain
- ));
- }
-
- public function getZones()
- {
- $out = array();
-
- $res = $this->get('listzones', array());
- foreach($res->zone as $zone)
- {
- $out[(string)$zone->domain] = '';
- }
- //TODO: tu skonczyłem - dokończyc whm1
-
- try
- {
- $res = $this->get('listaccts', array('want' => 'domain,ip'));
-
- foreach ($res->acct as $zone)
- {
- if(isset($out[(string)$zone->domain]))
- {
- $out[(string)$zone->domain] = (string)$zone->ip;
- }
- }
- }
- catch(exceptions\DNSSubmoduleException $exc)
- {
-
- }
- return $out;
- }
-
- private function get($function, $params=array()) {
- $params['api.version'] = 1;
- $url = ($this->config['ssl']? 'https://'.$this->config['hostname'].':2087' : 'http://'.$this->config['hostname'].':2086').'/json-api/'.$function;
- $ch = curl_init();
- if(is_array($params)) {
- $url .= '?';
- foreach($params as $key=>$value) {
- $value = urlencode($value);
- $url .= "{$key}={$value}&";
- }
- }
- $url = trim($url, '&');
- $this->log('REQUEST: ' . $url);
- $chOptions = array (
- CURLOPT_URL => $url,
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_SSL_VERIFYPEER => false,
- CURLOPT_SSL_VERIFYHOST => false,
- CURLOPT_TIMEOUT => is_numeric($this->config['timeout']) ? intval($this->config['timeout']) : 30
- );
-
- if($this->config['hash'] != '') {
- $header[0] = 'Authorization: WHM '.$this->config['username'].':'.str_replace(array("\r", "\n"),"", $this->config['hash']);
- $chOptions[CURLOPT_HTTPHEADER] = $header;
- } elseif($this->config['password'] != '') {
- $chOptions[CURLOPT_USERPWD] = $this->config['username'].':'.$this->config['password'];
- } else {
- throw new exceptions\DNSSubmoduleException('Password or Access key is required', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
- }
-
- curl_setopt_array($ch, $chOptions);
- $out = curl_exec($ch);
- $this->log('RESPONSE: ' . $out);
- if (curl_errno($ch)) {
- throw new exceptions\DNSSubmoduleException("cURL Error: " . curl_errno($ch) . " - " . curl_error($ch), dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
- }
-
- $out_info = curl_getinfo($ch);
- if($out_info['http_code'] != 200) {
- if($out_info['http_code'] == 301 || $out_info['http_code'] == 302){
- throw new exceptions\DNSSubmoduleException('Module require SSL', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
- }
- }
-
- curl_close($ch);
-
- if(strpos($out, 'SSL encryption is required for access to this server') !== FALSE) {
- throw new exceptions\DNSSubmoduleException('SSL encryption is required for access to this server', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
- }
- $a = json_decode($out);
- if($a===FALSE) {
- throw new exceptions\DNSSubmoduleException('Unable to parse response', dns\SubmoduleExceptionCodes::INVALID_RESPONSE);
- }
- if ($a->cpanelresult->error && $a->cpanelresult->data->result == 0)
- {
- throw new exceptions\DNSSubmoduleException($a->cpanelresult->error, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- if(isset($a->status) && $a->status == 0){
- throw new exceptions\DNSSubmoduleException($a->statusmsg?:'Unknown Error', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
-
- if(isset($a->data->result) && $a->data->result == 0) {
- throw new exceptions\DNSSubmoduleException($a->data->reason?:'Unknown Error', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
-
- if(!empty($a->error)) {
- throw new exceptions\DNSSubmoduleException($a->error, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
-
- if(isset($a->metadata->result) && $a->metadata->result == 0) {
- throw new exceptions\DNSSubmoduleException($a->metadata->reason, dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
-
- // if(!isset($a->data)) {
- // throw new exceptions\DNSSubmoduleException("There is no data in output", dns\SubmoduleExceptionCodes::INVALID_RESPONSE);
- // }
- return isset($a->data)?$a->data:$a;
- }
-
- private function logAction($action, $request, $response)
- {
- $addonConfig = \MGModule\DNSManager2\addon::config();
- logmodulecall(
- $addonConfig['name'],
- 'cPanel '.($action),
- array($request),
- array($response),
- null,
- array($this->config['hostname'], $this->config['hostname'], $this->config['hash'])
- );
- }
- public function getSignKeys(){
- $fetchDSRecords = $this->get('fetch_ds_records_for_domains', array('domain' => $this->domain));
- $dnssec = new \MGModule\DNSManager2\mgLibs\custom\dns\dnssec\DnsSec();
- foreach($fetchDSRecords->domains[0]->ds_records->keys as $dsKey => $dsRecord){
- foreach($dsRecord->digests as $diggestKey => $diggestRecord){
- $ds = new dns\record\type\DS();
- $ds->setKeytag($dsRecord->key_tag);
- $ds->setAlgorithm($dsRecord->algo_num);
- $ds->setDigestType($diggestRecord->algo_num);
- $ds->setDigest($diggestRecord->digest);
- $dnssec->addDs($ds);
- }
- switch (strtolower($dsRecord->key_type)){
- case 'csk':
- $dnskey = new dns\record\type\DNSKEY();
- $dnskey->setFlags($dsRecord->flags);
- $dnskey->setProtocol(3);
- $dnskey->setAlgorithm($dsRecord->algo_num);
- $zoneKey = new dns\dnssec\CSK();
- $zoneKey->setId($dsKey);
- $zoneKey->setBits($dsRecord->bits);
- $zoneKey->setDnsKey($dnskey);
- $dnssec->addKey($zoneKey);
- break;
- case 'ksk':
- $dnskey = new dns\record\type\DNSKEY();
- $dnskey->setFlags($dsRecord->flags);
- $dnskey->setProtocol(3);
- $dnskey->setAlgorithm($dsRecord->algo_num);
- $ksk = new dns\dnssec\KSK();
- $ksk->setId($dsKey);
- $ksk->setBits($dsRecord->bits);
- $ksk->setDnsKey($dnskey);
- $dnssec->addKey($ksk);
- break;
- case 'zsk':
- $dnskey = new dns\record\type\DNSKEY();
- $dnskey->setFlags($dsRecord->flags);
- $dnskey->setProtocol(3);
- $dnskey->setAlgorithm($dsRecord->algo_num);
- $zsk = new dns\dnssec\ZSK();
- $zsk->setId($dsKey);
- $zsk->setBits($dsRecord->bits);
- $zsk->setDnsKey($dnskey);
- $dnssec->addKey($zsk);
- break;
- }
- }
- return $dnssec;
- }
- public function sign(){
- $this->get('enable_dnssec_for_domains', array('domain' => $this->domain));
- }
- public function unsign(){
- $this->get('disable_dnssec_for_domains', array('domain' => $this->domain));
- }
- public function rectify(){
- return true;
- }
- public function isSigned(){
- $fetchDSRecords = $this->get('fetch_ds_records_for_domains', array('domain' => $this->domain));
- $checkDsRecords = $fetchDSRecords->domains[0]->ds_records;
- if(empty(get_object_vars($checkDsRecords)))
- return false;
- return true;
- }
- /* No need to use it anymore. It is not deleted to have it in future implementations - just in case */
- /* private function uAPI()
- {
- $res = $this->get('listaccts', array('want' => 'user', 'searchtype' => 'domain', 'search' => $this->domain, 'searchmethod' => 'exact'));
- $user = $res->acct[0]->user;
- if (!is_null($this->uapi))
- {
- return $this->uapi;
- }
- $this->uapi = new cPanelUapi\Uapi();
- $this->uapi->setLogin($this->config, $user)
- ->createSession();
- return $this->uapi;
- }
- */
- }
|