Subversion Repositories oidplus

Rev

Rev 635 | Rev 715 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. if (!defined('INSIDE_OIDPLUS')) die();
  21.  
  22. class OIDplusPageAdminRegistration extends OIDplusPagePluginAdmin {
  23.  
  24.         /*private*/ const QUERY_REGISTER_V1 =         '1.3.6.1.4.1.37476.2.5.2.1.1.1';
  25.         /*private*/ const QUERY_UNREGISTER_V1 =       '1.3.6.1.4.1.37476.2.5.2.1.2.1';
  26.         /*private*/ const QUERY_LISTALLSYSTEMIDS_V1 = '1.3.6.1.4.1.37476.2.5.2.1.3.1';
  27.         /*private*/ const QUERY_LIVESTATUS_V1 =       '1.3.6.1.4.1.37476.2.5.2.1.4.1';
  28.  
  29.         public function csrfUnlock($actionID) {
  30.                 if ($actionID == 'verify_pubkey') return true;
  31.                 return parent::csrfUnlock($actionID);
  32.         }
  33.  
  34.         public function action($actionID, $params) {
  35.                 if ($actionID == 'verify_pubkey') {
  36.                         _CheckParamExists($params, 'challenge');
  37.  
  38.                         $payload = 'oidplus-verify-pubkey:'.sha3_512($params['challenge']);
  39.  
  40.                         $signature = '';
  41.                         if (!OIDplus::getPkiStatus() || !@openssl_sign($payload, $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  42.                                 throw new OIDplusException(_L('Signature failed'));
  43.                         }
  44.  
  45.                         return array(
  46.                                 "status" => 0,
  47.                                 "response" => base64_encode($signature)
  48.                         );
  49.                 } else {
  50.                         throw new OIDplusException(_L('Unknown action ID'));
  51.                 }
  52.         }
  53.  
  54.         public function gui($id, &$out, &$handled) {
  55.                 if ($id === 'oidplus:srv_registration') {
  56.                         $handled = true;
  57.                         $out['title'] = _L('System registration settings');
  58.                         $out['icon'] = file_exists(__DIR__.'/icon_big.png') ? OIDplus::webpath(__DIR__).'icon_big.png' : '';
  59.  
  60.                         if (!OIDplus::authUtils()->isAdminLoggedIn()) {
  61.                                 $out['icon'] = 'img/error_big.png';
  62.                                 $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')).'</p>';
  63.                                 return;
  64.                         }
  65.  
  66.                         if (file_exists(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html')) {
  67.                                 $info = file_get_contents(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html');
  68.                         } else {
  69.                                 $info = file_get_contents(__DIR__ . '/info.html');
  70.                         }
  71.  
  72.                         list($html, $js, $css) = extractHtmlContents($info);
  73.                         $info = '';
  74.                         if (!empty($js))  $info .= "<script>\n$js\n</script>";
  75.                         if (!empty($css)) $info .= "<style>\n$css\n</style>";
  76.                         $info .= $html;
  77.  
  78.                         $out['text'] = $info;
  79.  
  80.                         if (!OIDplus::getPkiStatus()) {
  81.                                 $out['text'] .= '<p><font color="red">'._L('Error: Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system). Therefore, you cannot register/unregister your OIDplus instance.').'</font></p>';
  82.                         } else {
  83.                                 $out['text'] .= '<p><input type="button" onclick="openOidInPanel(\'oidplus:srvreg_status\');" value="'._L('Check status of the registration and collected data').'"></p>';
  84.  
  85.                                 if (OIDplus::baseConfig()->getValue('REGISTRATION_HIDE_SYSTEM', false)) {
  86.                                         $out['text'] .= '<p><font color="red"><b>'._L('Attention!').'</b> '._L('<code>REGISTRATION_HIDE_SYSTEM</code> is set in the local configuration file! Therefore, this system will not register itself, despite of the settings below.').'</font></p>';
  87.                                 }
  88.  
  89.                                 $out['text'] .= '<p>'._L('You can adjust your privacy level here').':</p><p><select name="reg_privacy" id="reg_privacy">';
  90.  
  91.                                 # ---
  92.  
  93.                                 $out['text'] .= '<option value="0"';
  94.                                 if (OIDplus::config()->getValue('reg_privacy') == 0) {
  95.                                         $out['text'] .= ' selected';
  96.                                 } else {
  97.                                         $out['text'] .= '';
  98.                                 }
  99.                                 $out['text'] .= '>'._L('0 = Register to directory service and automatically publish RA/OID data at oid-info.com').'</option>';
  100.  
  101.                                 # ---
  102.  
  103.                                 $out['text'] .= '<option value="1"';
  104.                                 if (OIDplus::config()->getValue('reg_privacy') == 1) {
  105.                                         $out['text'] .= ' selected';
  106.                                 } else {
  107.                                         $out['text'] .= '';
  108.                                 }
  109.                                 $out['text'] .= '>'._L('1 = Only register to directory service').'</option>';
  110.  
  111.                                 # ---
  112.  
  113.                                 $out['text'] .= '<option value="2"';
  114.                                 if (OIDplus::config()->getValue('reg_privacy') == 2) {
  115.                                         $out['text'] .= ' selected';
  116.                                 } else {
  117.                                         $out['text'] .= '';
  118.                                 }
  119.                                 $out['text'] .= '>'._L('2 = Hide system').'</option>';
  120.  
  121.                                 # ---
  122.  
  123.                                 $out['text'] .= '</select> <input type="button" value="'._L('Change').'" onclick="OIDplusPageAdminRegistration.crudActionRegPrivacyUpdate()"></p>';
  124.  
  125.                                 $out['text'] .= '<p>'._L('After clicking "change", your OIDplus system will contact the ViaThinkSoft server to adjust (add or remove information) your privacy setting. This may take a few minutes.').'</p>';
  126.  
  127.                                 $out['text'] .= '<p>'._L('<i>Privacy information:</i> Please note that removing your system from the directory does not automatically delete information about OIDs which are already published at oid-info.com. To remove already submitted OIDs at oid-info.com, please contact the <a href="mailto:admin@oid-info.com">OID Repository Webmaster</a>.').'</p>';
  128.                         }
  129.                 }
  130.                 if ($id === 'oidplus:srvreg_status') {
  131.                         $handled = true;
  132.                         $out['title'] = _L('Registration live status');
  133.                         $out['icon'] = file_exists(__DIR__.'/icon_big.png') ? OIDplus::webpath(__DIR__).'icon_big.png' : '';
  134.  
  135.                         if (!OIDplus::authUtils()->isAdminLoggedIn()) {
  136.                                 $out['icon'] = 'img/error_big.png';
  137.                                 $out['text'] = '<p>'._L('You need to <a %1>log in</a> as administrator.',OIDplus::gui()->link('oidplus:login$admin')).'</p>';
  138.                                 return;
  139.                         }
  140.  
  141.                         $query = self::QUERY_LIVESTATUS_V1;
  142.  
  143.                         $payload = array(
  144.                                 "query" => $query, // we must repeat the query because we want to sign it
  145.                                 "lang" => OIDplus::getCurrentLang(),
  146.                                 "system_id" => OIDplus::getSystemId(false)
  147.                         );
  148.  
  149.                         $signature = '';
  150.                         if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  151.                                 throw new OIDplusException(_L('Signature failed'));
  152.                         }
  153.  
  154.                         $data = array(
  155.                                 "payload" => $payload,
  156.                                 "signature" => base64_encode($signature)
  157.                         );
  158.  
  159.                         if (!function_exists('curl_init')) {
  160.                                 throw new OIDplusException(_L('The "%1" PHP extension is not installed at your system. Please enable the PHP extension <code>%2</code>.','CURL','php_curl'));
  161.                         }
  162.  
  163.                         $ch = curl_init();
  164.                         if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
  165.                         curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
  166.                         curl_setopt($ch, CURLOPT_POST, 1);
  167.                         if (function_exists('gzdeflate')) {
  168.                                 $compressed = "1";
  169.                                 $data2 = gzdeflate(json_encode($data));
  170.                         } else {
  171.                                 $compressed = "0";
  172.                                 $data2 = json_encode($data);
  173.                         }
  174.                         curl_setopt($ch, CURLOPT_POSTFIELDS, "query=".urlencode($query)."&compressed=$compressed&data=".urlencode(base64_encode($data2)));
  175.                         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  176.                         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  177.                         curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  178.                         if (!($res = @curl_exec($ch))) {
  179.                                 throw new OIDplusException(_L('Communication with ViaThinkSoft server failed: %1',curl_error($ch)));
  180.                         }
  181.                         curl_close($ch);
  182.  
  183.                         $json = @json_decode($res, true);
  184.  
  185.                         if (!$json) {
  186.                                 $out['icon'] = 'img/error_big.png';
  187.                                 $out['text'] = _L('JSON reply from ViaThinkSoft decoding error: %1',$res);
  188.                                 return;
  189.                         }
  190.  
  191.                         if (isset($json['error']) || ($json['status'] < 0)) {
  192.                                 $out['icon'] = 'img/error_big.png';
  193.                                 if (isset($json['error'])) {
  194.                                         $out['text'] = _L('Received error status code: %1',$json['error']);
  195.                                 } else {
  196.                                         $out['text'] = _L('Received error status code: %1',$json['status']);
  197.                                 }
  198.                                 return;
  199.                         }
  200.  
  201.                         $out['text']  = '<p><a '.OIDplus::gui()->link('oidplus:srv_registration').'><img src="img/arrow_back.png" width="16" alt="'._L('Go back').'"> '._L('Go back to registration settings').'</a></p>' .
  202.                                         $json['content'];
  203.                 }
  204.         }
  205.  
  206.         protected function areWeRegistered() {
  207.                 // To check if we are registered. Check it "anonymously" (i.e. without revealing our system ID)
  208.                 $res = file_get_contents('https://oidplus.viathinksoft.com/reg2/query.php?query='.self::QUERY_LISTALLSYSTEMIDS_V1);
  209.  
  210.                 $json = @json_decode($res, true);
  211.  
  212.                 if (!$json) {
  213.                         return false; // throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res));
  214.                 }
  215.  
  216.                 if (isset($json['error']) || ($json['status'] < 0)) {
  217.                         if (isset($json['error'])) {
  218.                                 return false; // throw new OIDplusException(_L('Received error status code: %1',$json['error']));
  219.                         } else {
  220.                                 return false; // throw new OIDplusException(_L('Received error status code: %1',$json['status']));
  221.                         }
  222.                 }
  223.  
  224.                 $list = $json['list'];
  225.  
  226.                 return in_array(OIDplus::getSystemId(false), $list);
  227.         }
  228.  
  229.         public function sendRegistrationQuery($privacy_level=null) {
  230.                 if (is_null($privacy_level)) {
  231.                         $privacy_level = OIDplus::config()->getValue('reg_privacy');
  232.                 }
  233.  
  234.                 $system_url = OIDplus::webpath();
  235.  
  236.                 // It is very important that we set the ping time NOW, because ViaThinkSoft might contact us during the ping,
  237.                 // and this would cause an endless loop!
  238.                 OIDplus::config()->setValue('reg_last_ping', time());
  239.  
  240.                 if (!OIDplus::getPkiStatus()) return false;
  241.  
  242.                 if ($privacy_level == 2) {
  243.                         // The user wants to unregister,  but we only unregister if we are registered
  244.                         if ($this->areWeRegistered()) {
  245.                                 $query = self::QUERY_UNREGISTER_V1;
  246.  
  247.                                 $payload = array(
  248.                                         "query" => $query, // we must repeat the query because we want to sign it
  249.                                         "system_id" => OIDplus::getSystemId(false)
  250.                                 );
  251.  
  252.                                 $signature = '';
  253.                                 if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  254.                                         return false; // throw new OIDplusException(_L('Signature failed'));
  255.                                 }
  256.  
  257.                                 $data = array(
  258.                                         "payload" => $payload,
  259.                                         "signature" => base64_encode($signature)
  260.                                 );
  261.  
  262.                                 if (!function_exists('curl_init')) {
  263.                                         return false; // throw new OIDplusException(_L('The "%1" PHP extension is not installed at your system. Please enable the PHP extension <code>%2</code>.','CURL','php_curl'));
  264.                                 }
  265.  
  266.                                 $ch = curl_init();
  267.                                 if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
  268.                                 curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
  269.                                 curl_setopt($ch, CURLOPT_POST, 1);
  270.                                 if (function_exists('gzdeflate')) {
  271.                                         $compressed = "1";
  272.                                         $data2 = gzdeflate(json_encode($data));
  273.                                 } else {
  274.                                         $compressed = "0";
  275.                                         $data2 = json_encode($data);
  276.                                 }
  277.                                 curl_setopt($ch, CURLOPT_POSTFIELDS, "query=".urlencode($query)."&compressed=$compressed&data=".urlencode(base64_encode($data2)));
  278.                                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  279.                                 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  280.                                 curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  281.                                 if (!($res = @curl_exec($ch))) {
  282.                                         return false; // throw new OIDplusException(_L('Communication with ViaThinkSoft server failed: %1',curl_error($ch)));
  283.                                 }
  284.                                 curl_close($ch);
  285.  
  286.                                 $json = @json_decode($res, true);
  287.  
  288.                                 if (!$json) {
  289.                                         return false; // throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res));
  290.                                 }
  291.  
  292.                                 if (isset($json['error']) || ($json['status'] < 0)) {
  293.                                         if (isset($json['error'])) {
  294.                                                 return false; // throw new OIDplusException(_L('Received error status code: %1',$json['error']));
  295.                                         } else {
  296.                                                 return false; // throw new OIDplusException(_L('Received error status code: %1',$json['status']));
  297.                                         }
  298.                                 }
  299.                         }
  300.                 } else {
  301.                         if ($privacy_level == 0) {
  302.                                 $adminExportPlugin = OIDplus::getPluginByOid('1.3.6.1.4.1.37476.2.5.2.4.3.400'); // OIDplusPageAdminOIDInfoExport
  303.                                 if (!is_null($adminExportPlugin)) {
  304.                                         ob_start();
  305.                                         OIDplusPageAdminOIDInfoExport::outputXML(false); // no online check, because the query should be short (since the query is done while a visitor waits for the response)
  306.                                         $oidinfo_xml = ob_get_contents();
  307.                                         ob_end_clean();
  308.                                 } else {
  309.                                         $oidinfo_xml = false;
  310.                                 }
  311.                         } else {
  312.                                 $oidinfo_xml = false;
  313.                         }
  314.  
  315.                         $query = self::QUERY_REGISTER_V1;
  316.  
  317.                         $root_oids = array();
  318.                         foreach (OIDplus::getEnabledObjectTypes() as $ot) {
  319.                                 if ($ot::ns() == 'oid') {
  320.                                         $res = OIDplus::db()->query("select id from ###objects where " .
  321.                                                                     "(parent = 'oid:' or " .
  322.                                                                     // The following two cases are special cases e.g. if there are multiple PEN or UUID-OIDs, and the system owner decides to use the IANA PEN as root OID, but actually, it is not "his" root then! The OIDs inside the IANA PEN root are his root then!
  323.                                                                     "parent in (select oid from ###asn1id where well_known = ?) or " .
  324.                                                                     "parent in (select oid from ###iri where well_known = ?)) and " .
  325.                                                                     // We assume hereby that RAs of well-known OIDs (e.g. IANA) will not use OIDplus for allocating OIDs:
  326.                                                                     "id not in (select oid from ###asn1id where well_known = ?) and " .
  327.                                                                     "id not in (select oid from ###iri where well_known = ?) " .
  328.                                                                     "order by ".OIDplus::db()->natOrder('id'), array(true, true, true, true));
  329.                                         while ($row = $res->fetch_array()) {
  330.                                                 $root_oids[] = substr($row['id'],strlen('oid:'));
  331.                                         }
  332.                                 }
  333.                         }
  334.                         $payload = array(
  335.                                 "query" => $query, // we must repeat the query because we want to sign it
  336.                                 "privacy_level" => $privacy_level,
  337.                                 "system_id" => OIDplus::getSystemId(false),
  338.                                 "public_key" => OIDplus::config()->getValue('oidplus_public_key'),
  339.                                 "system_url" => $system_url,
  340.                                 "hide_system_url" => 0,
  341.                                 "hide_public_key" => 0,
  342.                                 "admin_email" => OIDplus::config()->getValue('admin_email'),
  343.                                 "system_title" => OIDplus::config()->getValue('system_title'),
  344.                                 "oidinfo_xml" => @base64_encode($oidinfo_xml),
  345.                                 "root_oids" => $root_oids,
  346.                                 "system_version" => OIDplus::getVersion(),
  347.                                 "system_install_type" => OIDplus::getInstallType()
  348.                         );
  349.  
  350.                         $signature = '';
  351.                         if (!OIDplus::getPkiStatus() || !@openssl_sign(json_encode($payload), $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  352.                                 return false; // throw new OIDplusException(_L('Signature failed'));
  353.                         }
  354.  
  355.                         $data = array(
  356.                                 "payload" => $payload,
  357.                                 "signature" => base64_encode($signature)
  358.                         );
  359.  
  360.  
  361.                         if (!function_exists('curl_init')) {
  362.                                 return false; // throw new OIDplusException(_L('The "%1" PHP extension is not installed at your system. Please enable the PHP extension <code>%2</code>.','CURL','php_curl'));
  363.                         }
  364.  
  365.                         $ch = curl_init();
  366.                         if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
  367.                         curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
  368.                         curl_setopt($ch, CURLOPT_POST, 1);
  369.                         if (function_exists('gzdeflate')) {
  370.                                 $compressed = "1";
  371.                                 $data2 = gzdeflate(json_encode($data));
  372.                         } else {
  373.                                 $compressed = "0";
  374.                                 $data2 = json_encode($data);
  375.                         }
  376.                         curl_setopt($ch, CURLOPT_POSTFIELDS, "query=".urlencode($query)."&compressed=$compressed&data=".urlencode(base64_encode($data2)));
  377.                         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  378.                         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  379.                         curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  380.                         if (!($res = @curl_exec($ch))) {
  381.                                 return false; // throw new OIDplusException(_L('Communication with ViaThinkSoft server failed: %1',curl_error($ch)));
  382.                         }
  383.                         curl_close($ch);
  384.  
  385.                         $json = @json_decode($res, true);
  386.  
  387.                         if (!$json) {
  388.                                 return false; // throw new OIDplusException(_L('JSON reply from ViaThinkSoft decoding error: %1',$res));
  389.                         }
  390.  
  391.                         if (isset($json['error']) || ($json['status'] < 0)) {
  392.                                 if (isset($json['error'])) {
  393.                                         return false; // throw new OIDplusException(_L('Received error status code: %1',$json['error']));
  394.                                 } else {
  395.                                         return false; // throw new OIDplusException(_L('Received error status code: %1',$json['status']));
  396.                                 }
  397.                         } else if ($json['status'] == 99/*Hash conflict*/) {
  398.                                 OIDplus::logger()->log("[WARN]A!", "Removing SystemID and key pair because there is a hash conflict with another OIDplus system!");
  399.  
  400.                                 // Delete the system ID since we have a conflict with the 31-bit hash!
  401.                                 OIDplus::config()->setValue('oidplus_private_key', '');
  402.                                 OIDplus::config()->setValue('oidplus_public_key', '');
  403.  
  404.                                 // Try to generate a new system ID
  405.                                 OIDplus::getPkiStatus(true);
  406.  
  407.                                 // Enforce a new registration attempt at the next page visit
  408.                                 // We will not try again here, because that might lead to an endless loop if the VTS server would always return 'HASH_CONFLCIT'
  409.                                 OIDplus::config()->setValue('reg_last_ping', 0);
  410.                         }
  411.                 }
  412.         }
  413.  
  414.         public function init($html=true) {
  415.                 if (OIDplus::getEditionInfo()['vendor'] != 'ViaThinkSoft') {
  416.                         throw new OIDplusException(_L('This plugin is only available in the ViaThinkSoft edition of OIDplus'));
  417.                 }
  418.  
  419.                 // Note: It is important that the default value is '2', otherwise, systems which don't have CURL will fail
  420.                 OIDplus::config()->prepareConfigKey('reg_privacy', '2=Hide your system, 1=Register your system to the ViaThinkSoft directory and oid-info.com, 0=Publish your system to ViaThinkSoft directory and all public contents (RA/OID) to oid-info.com', '2', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
  421.                         if (($value != '0') && ($value != '1') && ($value != '2')) {
  422.                                 throw new OIDplusException(_L('Please enter either 0, 1 or 2.'));
  423.                         }
  424.                         // Now do a recheck and notify the ViaThinkSoft server
  425.                         if (($value == 2) || !OIDplus::baseConfig()->getValue('REGISTRATION_HIDE_SYSTEM', false)) {
  426.                                 OIDplus::config()->setValue('reg_last_ping', 0);
  427.                                 $this->sendRegistrationQuery($value);
  428.                         }
  429.                 });
  430.                 OIDplus::config()->prepareConfigKey('reg_ping_interval', 'Registration ping interval (in seconds)', '3600', OIDplusConfig::PROTECTION_HIDDEN, function($value) {
  431.  
  432.                 });
  433.                 OIDplus::config()->prepareConfigKey('reg_last_ping', 'Last ping to ViaThinkSoft directory services', '0', OIDplusConfig::PROTECTION_HIDDEN, function($value) {
  434.  
  435.                 });
  436.                 OIDplus::config()->prepareConfigKey('oobe_registration_done', '"Out Of Box Experience" wizard for OIDplusPageAdminRegistration done once?', '0', OIDplusConfig::PROTECTION_HIDDEN, function($value) {});
  437.  
  438.                 // Is it time to register / renew the directory entry?
  439.                 // Note: REGISTRATION_HIDE_SYSTEM is an undocumented constant that can be put in the userdata/baseconfig/config.inc.php files of a test system accessing the same database as the productive system that is registered.
  440.                 // This avoids that the URL of a productive system is overridden with the URL of a cloned test system (since they use the same database, they also have the same system ID)
  441.  
  442.                 if (OIDplus::config()->getValue('oobe_registration_done') == '1') {
  443.                         if (!OIDplus::baseConfig()->getValue('REGISTRATION_HIDE_SYSTEM', false)) {
  444.                                 $privacy_level = OIDplus::config()->getValue('reg_privacy');
  445.  
  446.                                 if (PHP_SAPI !== 'cli') { // don't register when called from CLI, otherwise the oidinfo XML can't convert relative links into absolute links
  447.                                         if ((time()-OIDplus::config()->getValue('reg_last_ping') >= OIDplus::config()->getValue('reg_ping_interval'))) {
  448.                                                 $this->sendRegistrationQuery();
  449.                                         }
  450.                                 }
  451.                         }
  452.                 }
  453.         }
  454.  
  455.         public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {
  456.                 if (!OIDplus::authUtils()->isAdminLoggedIn()) return false;
  457.  
  458.                 if (file_exists(__DIR__.'/treeicon.png')) {
  459.                         $tree_icon = OIDplus::webpath(__DIR__).'treeicon.png';
  460.                 } else {
  461.                         $tree_icon = null; // default icon (folder)
  462.                 }
  463.  
  464.                 $json[] = array(
  465.                         'id' => 'oidplus:srv_registration',
  466.                         'icon' => $tree_icon,
  467.                         'text' => _L('System registration')
  468.                 );
  469.  
  470.                 return true;
  471.         }
  472.  
  473.         public function tree_search($request) {
  474.                 return false;
  475.         }
  476.  
  477.         public function implementsFeature($id) {
  478.                 if (strtolower($id) == '1.3.6.1.4.1.37476.2.5.2.3.1') return true; // oobeEntry, oobeRequested
  479.                 return false;
  480.         }
  481.  
  482.         public function oobeRequested(): bool {
  483.                 // Interface 1.3.6.1.4.1.37476.2.5.2.3.1
  484.  
  485.                 return OIDplus::config()->getValue('oobe_registration_done') == '0';
  486.         }
  487.  
  488.         public function oobeEntry($step, $do_edits, &$errors_happened)/*: void*/ {
  489.                 // Interface 1.3.6.1.4.1.37476.2.5.2.3.1
  490.  
  491.                 echo '<p><u>'._L('Step %1: System registration and automatic publishing (optional)',$step).'</u></p>';
  492.  
  493.                 if (file_exists(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html')) {
  494.                         $info = file_get_contents(__DIR__ . '/info$'.OIDplus::getCurrentLang().'.html');
  495.                 } else {
  496.                         $info = file_get_contents(__DIR__ . '/info.html');
  497.                 }
  498.  
  499.                 // make sure the program works even if the user provided HTML is not UTF-8
  500.                 $info = iconv(mb_detect_encoding($info, mb_detect_order(), true), 'UTF-8//IGNORE', $info);
  501.                 $bom = pack('H*','EFBBBF');
  502.                 $info = preg_replace("/^$bom/", '', $info);
  503.  
  504.                 echo $info;
  505.  
  506.                 if (!function_exists('curl_init')) {
  507.                         echo '<p><font color="red">';
  508.                         echo _L('The "%1" PHP extension is not installed at your system. Please enable the PHP extension <code>%2</code>.','CURL','php_curl').' ';
  509.                         echo _L('Therefore, you <b>cannot</b> register your OIDplus instance now.');
  510.                         echo '</font></p>';
  511.                         if ($do_edits) {
  512.                                 OIDplus::config()->setValue('oobe_registration_done', '1');
  513.                         }
  514.                         return;
  515.                 }
  516.  
  517.                 $testurl = 'https://www.google.com/';
  518.                 $ch = curl_init();
  519.                 if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . 'vendor/cacert.pem');
  520.                 curl_setopt($ch, CURLOPT_URL, $testurl);
  521.                 curl_setopt($ch, CURLOPT_HEADER, TRUE);
  522.                 curl_setopt($ch, CURLOPT_NOBODY, TRUE);
  523.                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  524.                 curl_exec($ch);
  525.                 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  526.                 curl_close($ch);
  527.                 if (!$httpCode) {
  528.                         echo '<p><font color="red">';
  529.                         echo _L('The "CURL" PHP extension cannot access HTTPS webpages. Therefore, you cannot use this feature. Please download <a href="https://curl.haxx.se/ca/cacert.pem">cacert.pem</a>, place it somewhere and then adjust the setting <code>curl.cainfo</code> in PHP.ini.').' ';
  530.                         echo _L('Therefore, you <b>cannot</b> register your OIDplus instance now.');
  531.                         echo '</font></p>';
  532.                         if ($do_edits) {
  533.                                 OIDplus::config()->setValue('oobe_registration_done', '1');
  534.                         }
  535.                         return;
  536.                 }
  537.  
  538.                 $pki_status = OIDplus::getPkiStatus();
  539.  
  540.                 if (!$pki_status) {
  541.                         echo '<p><font color="red">';
  542.                         echo _L('Your system could not generate a private/public key pair. (OpenSSL is probably missing on your system).').' ';
  543.                         echo _L('Therefore, you <b>cannot</b> register your OIDplus instance now.');
  544.                         echo '</font></p>';
  545.                         if ($do_edits) {
  546.                                 OIDplus::config()->setValue('oobe_registration_done', '1');
  547.                         }
  548.                         return;
  549.                 }
  550.  
  551.                 echo '<p>'._L('Privacy level').':</p><select name="reg_privacy" id="reg_privacy">';
  552.  
  553.                 # ---
  554.  
  555.                 echo '<option value="0"';
  556.                 if (isset($_REQUEST['sent'])) {
  557.                         if (isset($_REQUEST['reg_privacy']) && ($_REQUEST['reg_privacy'] == 0)) echo ' selected';
  558.                 } else {
  559.                         if ((OIDplus::config()->getValue('reg_privacy') == 0) || !OIDplus::config()->getValue('oobe_registration_done')) {
  560.                                 echo ' selected';
  561.                         } else {
  562.                                 echo '';
  563.                         }
  564.                 }
  565.                 echo '>'._L('0 = Register to directory service and automatically publish RA/OID data at oid-info.com').'</option>';
  566.  
  567.                 # ---
  568.  
  569.                 echo '<option value="1"';
  570.                 if (isset($_REQUEST['sent'])) {
  571.                         if (isset($_REQUEST['reg_privacy']) && ($_REQUEST['reg_privacy'] == 1)) echo ' selected';
  572.                 } else {
  573.                         if ((OIDplus::config()->getValue('reg_privacy') == 1)) {
  574.                                 echo ' selected';
  575.                         } else {
  576.                                 echo '';
  577.                         }
  578.                 }
  579.                 echo '>'._L('1 = Only register to directory service').'</option>';
  580.  
  581.                 # ---
  582.  
  583.                 echo '<option value="2"';
  584.                 if (isset($_REQUEST['sent'])) {
  585.                         if (isset($_REQUEST['reg_privacy']) && ($_REQUEST['reg_privacy'] == 2)) echo ' selected';
  586.                 } else {
  587.                         if ((OIDplus::config()->getValue('reg_privacy') == 2)) {
  588.                                 echo ' selected';
  589.                         } else {
  590.                                 echo '';
  591.                         }
  592.                 }
  593.                 echo '>'._L('2 = Hide system').'</option>';
  594.  
  595.                 # ---
  596.  
  597.                 echo '</select>';
  598.  
  599.                 $msg = '';
  600.                 if ($do_edits) {
  601.                         try {
  602.                                 OIDplus::config()->setValue('reg_privacy', isset($_REQUEST['reg_privacy']) ? $_REQUEST['reg_privacy'] : 1);
  603.                                 OIDplus::config()->setValue('oobe_registration_done', '1');
  604.                         } catch (Exception $e) {
  605.                                 $msg = $e->getMessage();
  606.                                 $errors_happened = true;
  607.                         }
  608.                 }
  609.                 echo ' <font color="red"><b>'.$msg.'</b></font>';
  610.  
  611.                 echo '<p>'._L('<i>Privacy information:</i> This setting can always be changed in the administrator login / control panel.').'<br>';
  612.                 echo _L('<a %1>Click here</a> for more information about privacy related topics.','href="../../../../res/OIDplus/privacy_documentation.html" target="_blank"');
  613.                 echo '</p>';
  614.         }
  615.  
  616. }
  617.