Subversion Repositories oidplus

Rev

Rev 256 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 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('IN_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 static function getPluginInformation() {
  30.                 $out = array();
  31.                 $out['name'] = 'System registration';
  32.                 $out['author'] = 'ViaThinkSoft';
  33.                 $out['version'] = null;
  34.                 $out['descriptionHTML'] = null;
  35.                 return $out;
  36.         }
  37.  
  38.         public function priority() {
  39.                 return 120;
  40.         }
  41.  
  42.         public function action(&$handled) {
  43.                 // Nothing
  44.         }
  45.  
  46.         public function cfgSetValue($name, $value) {
  47.                 if ($name == 'reg_privacy') {
  48.                         if (($value != '0') && ($value != '1') && ($value != '2')) {
  49.                                 throw new OIDplusException("Please enter either 0, 1 or 2.");
  50.                         }
  51.                         // Now do a recheck and notify the ViaThinkSoft server
  52.                         OIDplus::config()->setValue('reg_last_ping', 0);
  53.                         $this->sendRegistrationQuery($value);
  54.                 }
  55.         }
  56.  
  57.         public function gui($id, &$out, &$handled) {
  58.                 if ($id === 'oidplus:srv_registration') {
  59.                         $handled = true;
  60.                         $out['title'] = 'System registration settings';
  61.                         $out['icon'] = file_exists(__DIR__.'/icon_big.png') ? OIDplus::webpath(__DIR__).'icon_big.png' : '';
  62.  
  63.                         if (!OIDplus::authUtils()::isAdminLoggedIn()) {
  64.                                 $out['icon'] = 'img/error_big.png';
  65.                                 $out['text'] = '<p>You need to <a '.OIDplus::gui()->link('oidplus:login').'>log in</a> as administrator.</p>';
  66.                         } else {
  67.                                 $out['text'] = file_get_contents(__DIR__ . '/info.tpl');
  68.                                
  69.                                 if (!OIDplus::getPkiStatus()) {
  70.                                         $out['text'] .= '<p><font color="red">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>';
  71.                                 } else {
  72.                                         $out['text'] .= '<p><input type="button" onclick="openOidInPanel(\'oidplus:srvreg_status\');" value="Check status of the registration and collected data"></p>';
  73.  
  74.                                         if (defined('REGISTRATION_HIDE_SYSTEM') && REGISTRATION_HIDE_SYSTEM) {
  75.                                                 $out['text'] .= '<p><font color="red"><b>Attention!</b> <code>REGISTRATION_HIDE_SYSTEM</code> is set in the local configuration file! Therefore, this system will not register itself, despire the settings below.</font></p>';
  76.                                         }
  77.  
  78.                                         $out['text'] .= '<p>You can adjust your privacy level here:</p><p><select name="reg_privacy" id="reg_privacy">';
  79.  
  80.                                         # ---
  81.  
  82.                                         $out['text'] .= '<option value="0"';
  83.                                         if (OIDplus::config()->getValue('reg_privacy') == 0) {
  84.                                                 $out['text'] .= ' selected';
  85.                                         } else {
  86.                                                 $out['text'] .= '';
  87.                                         }
  88.                                         $out['text'] .= '>0 = Register to directory service and automatically publish RA/OID data at oid-info.com</option>';
  89.  
  90.                                         # ---
  91.  
  92.                                         $out['text'] .= '<option value="1"';
  93.                                         if (OIDplus::config()->getValue('reg_privacy') == 1) {
  94.                                                 $out['text'] .= ' selected';
  95.                                         } else {
  96.                                                 $out['text'] .= '';
  97.                                         }
  98.                                         $out['text'] .= '>1 = Only register to directory service</option>';
  99.  
  100.                                         # ---
  101.  
  102.                                         $out['text'] .= '<option value="2"';
  103.                                         if (OIDplus::config()->getValue('reg_privacy') == 2) {
  104.                                                 $out['text'] .= ' selected';
  105.                                         } else {
  106.                                                 $out['text'] .= '';
  107.                                         }
  108.                                         $out['text'] .= '>2 = Hide system</option>';
  109.  
  110.                                         # ---
  111.  
  112.                                         $out['text'] .= '</select> <input type="button" value="Change" onclick="crudActionRegPrivacyUpdate()"></p>';
  113.  
  114.                                         $out['text'] .= '<p>After clicking "change", your OIDplus installation will contact the ViaThinkSoft server to adjust (add or remove information) your privacy setting. This may take a few minutes.</p>';
  115.  
  116.                                         $out['text'] .= '<p><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>.';
  117.                                 }
  118.                         }
  119.                 }
  120.                 if ($id === 'oidplus:srvreg_status') {
  121.                         $handled = true;
  122.  
  123.                         $query = self::QUERY_LIVESTATUS_V1;
  124.  
  125.                         $payload = array(
  126.                                 "query" => $query, // we must repeat the query because we want to sign it
  127.                                 "system_id" => OIDplus::getSystemId(false)
  128.                         );
  129.  
  130.                         $signature = '';
  131.                         if (!@openssl_sign(json_encode($payload), $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  132.                                 throw new OIDplusException("Signature failed");
  133.                         }
  134.  
  135.                         $data = array(
  136.                                 "payload" => $payload,
  137.                                 "signature" => base64_encode($signature)
  138.                         );
  139.  
  140.                         $ch = curl_init();
  141.                         curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
  142.                         curl_setopt($ch, CURLOPT_POST, 1);
  143.                         curl_setopt($ch, CURLOPT_POSTFIELDS, "query=$query&data=".base64_encode(json_encode($data)));
  144.                         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  145.                         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  146.                         curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  147.                         if (!($res = @curl_exec($ch))) {
  148.                                 throw new OIDplusException("Communication with ViaThinkSoft server failed");
  149.                         }
  150.                         curl_close($ch);
  151.                         // die("RES: $res\n");
  152.                         // if ($res == 'OK') ...
  153.  
  154.                         $out['title'] = 'Registration live status';
  155.                         $out['text']  = '<p><a '.OIDplus::gui()->link('oidplus:srv_registration').'><img src="img/arrow_back.png" width="16"> Go back to registration settings</a></p>' .
  156.                                         $res;
  157.                 }
  158.         }
  159.  
  160.         public function sendRegistrationQuery($privacy_level=null) {
  161.                 if (is_null($privacy_level)) {
  162.                         $privacy_level = OIDplus::config()->getValue('reg_privacy');
  163.                 }
  164.  
  165.                 $system_url = OIDplus::getSystemUrl();
  166.  
  167.                 // It is very important that we set the ping time NOW, because ViaThinkSoft might contact us during the ping,
  168.                 // and this would cause an endless loop!
  169.                 OIDplus::config()->setValue('reg_last_ping', time());
  170.                
  171.                 if (!OIDplus::getPkiStatus()) return false;
  172.  
  173.                 if ($privacy_level == 2) {
  174.                         // The user wants to unregister
  175.                         // but we only unregister if we are registered. Check this "anonymously" (i.e. without revealing our system ID)
  176.                         if (in_array(OIDplus::getSystemId(false), explode(';',file_get_contents('https://oidplus.viathinksoft.com/reg2/query.php?query='.self::QUERY_LISTALLSYSTEMIDS_V1)))) {
  177.                                 $query = self::QUERY_UNREGISTER_V1;
  178.  
  179.                                 $payload = array(
  180.                                         "query" => $query, // we must repeat the query because we want to sign it
  181.                                         "system_id" => OIDplus::getSystemId(false)
  182.                                 );
  183.  
  184.                                 $signature = '';
  185.                                 if (!@openssl_sign(json_encode($payload), $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  186.                                         return false; // throw new OIDplusException("Signature failed");
  187.                                 }
  188.  
  189.                                 $data = array(
  190.                                         "payload" => $payload,
  191.                                         "signature" => base64_encode($signature)
  192.                                 );
  193.  
  194.                                 $ch = curl_init();
  195.                                 curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
  196.                                 curl_setopt($ch, CURLOPT_POST, 1);
  197.                                 curl_setopt($ch, CURLOPT_POSTFIELDS, "query=$query&data=".base64_encode(json_encode($data)));
  198.                                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  199.                                 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  200.                                 curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  201.                                 if (!($res = @curl_exec($ch))) {
  202.                                         return false; // throw new OIDplusException("Communication with ViaThinkSoft server failed");
  203.                                 }
  204.                                 curl_close($ch);
  205.                                 // die("RES: $res\n");
  206.                                 // if ($res == 'OK') ...
  207.                         }
  208.                 } else {
  209.                         if ($privacy_level == 0) {
  210.                                 if (class_exists('OIDplusPageAdminOIDInfoExport')) {
  211.                                         ob_start();
  212.                                         OIDplusPageAdminOIDInfoExport::outputXML(false); // no online check, because the query should be short (since the query is done while a visitor waits for the response)
  213.                                         $oidinfo_xml = ob_get_contents();
  214.                                         ob_end_clean();
  215.                                 } else {
  216.                                         $oidinfo_xml = false;
  217.                                 }
  218.                         } else {
  219.                                 $oidinfo_xml = false;
  220.                         }
  221.  
  222.                         $query = self::QUERY_REGISTER_V1;
  223.  
  224.                         $root_oids = array();
  225.                         foreach (OIDplus::getEnabledObjectTypes() as $ot) {
  226.                                 if ($ot::ns() == 'oid') {
  227.                                         $res = OIDplus::db()->query("select id from ".OIDPLUS_TABLENAME_PREFIX."objects where " .
  228.                                                                     "parent = 'oid:' " .
  229.                                                                     "order by ".OIDplus::db()->natOrder('id'));
  230.                                         while ($row = $res->fetch_array()) {
  231.                                                 $root_oids[] = substr($row['id'],strlen('oid:'));
  232.                                         }
  233.                                 }
  234.                         }
  235.                         $payload = array(
  236.                                 "query" => $query, // we must repeat the query because we want to sign it
  237.                                 "privacy_level" => $privacy_level,
  238.                                 "system_id" => OIDplus::getSystemId(false),
  239.                                 "public_key" => OIDplus::config()->getValue('oidplus_public_key'),
  240.                                 "system_url" => $system_url,
  241.                                 "hide_system_url" => 0,
  242.                                 "hide_public_key" => 0,
  243.                                 "admin_email" => OIDplus::config()->getValue('admin_email'),
  244.                                 "system_title" => OIDplus::config()->getValue('system_title'),
  245.                                 "oidinfo_xml" => @base64_encode($oidinfo_xml),
  246.                                 "root_oids" => $root_oids,
  247.                                 "system_version" => OIDplus::getVersion(),
  248.                                 "system_install_type" => OIDplus::getInstallType()
  249.                         );
  250.  
  251.                         $signature = '';
  252.                         if (!@openssl_sign(json_encode($payload), $signature, OIDplus::config()->getValue('oidplus_private_key'))) {
  253.                                         return false; // throw new OIDplusException("Signature failed");
  254.                         }
  255.  
  256.                         $data = array(
  257.                                 "payload" => $payload,
  258.                                 "signature" => base64_encode($signature)
  259.                         );
  260.  
  261.                         $ch = curl_init();
  262.                         curl_setopt($ch, CURLOPT_URL, 'https://oidplus.viathinksoft.com/reg2/query.php');
  263.                         curl_setopt($ch, CURLOPT_POST, 1);
  264.                         curl_setopt($ch, CURLOPT_POSTFIELDS, "query=$query&data=".base64_encode(json_encode($data)));
  265.                         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  266.                         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  267.                         curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  268.                         if (!($res = @curl_exec($ch))) {
  269.                                 return false; // throw new OIDplusException("Communication with ViaThinkSoft server failed");
  270.                         }
  271.                         curl_close($ch);
  272.  
  273.                         if ($res === 'HASH_CONFLICT') {
  274.                                 OIDplus::logger()->log("A!", "Removing SystemID and key pair because there is a hash conflict with another OIDplus system!");
  275.  
  276.                                 // Delete the system ID since we have a conflict with the 31-bit hash!
  277.                                 OIDplus::config()->setValue('oidplus_private_key', '');
  278.                                 OIDplus::config()->setValue('oidplus_public_key', '');
  279.  
  280.                                 // Try to generate a new system ID
  281.                                 OIDplus::getPkiStatus(true);
  282.  
  283.                                 // Enforce a new registration attempt at the next run
  284.                                 // We will not try again here, because that might lead to an endless loop if the VTS server would always return 'HASH_CONFLCIT'
  285.                                 OIDplus::config()->setValue('reg_last_ping', 0);
  286.                         }
  287.  
  288.                         // die("RES: $res\n");
  289.                         // if ($res == 'OK') ...
  290.                 }
  291.         }
  292.  
  293.         public function init($html=true) {
  294.                 OIDplus::config()->prepareConfigKey('reg_wizard_done', 'Registration wizard done once?', '0', 1, 0);
  295.                 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', '0', 0, 1);
  296.                 OIDplus::config()->prepareConfigKey('reg_ping_interval', 'Registration ping interval (in seconds)', '3600', 0, 0);
  297.                 OIDplus::config()->prepareConfigKey('reg_last_ping', 'Last ping to ViaThinkSoft directory services', '0', 1, 0);
  298.                
  299.                 $oobe_done = OIDplus::config()->getValue('reg_wizard_done') == '1';
  300.                
  301.                 if (!$oobe_done) {
  302.                         // Show registration/configuration wizard once
  303.                         if ($html) {
  304.                                 if (basename($_SERVER['SCRIPT_NAME']) != 'registration.php') {
  305.                                         header('Location:'.OIDplus::webpath(__DIR__).'registration.php');
  306.                                         die('Redirecting to registration wizard...');
  307.                                 }
  308.                         }
  309.                 } else {
  310.                         // Is it time to register / renew the directory entry?
  311.                         // Note: REGISTRATION_HIDE_SYSTEM is an undocumented constant that can be put in the config.inc.php files of a test system accessing the same database as the productive system that is registered.
  312.                         // 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)
  313.  
  314.                         if (!defined('REGISTRATION_HIDE_SYSTEM') || !REGISTRATION_HIDE_SYSTEM) {
  315.                                 $privacy_level = OIDplus::config()->getValue('reg_privacy');
  316.  
  317.                                 if (php_sapi_name() !== 'cli') { // don't register when called from CLI, otherweise the oidinfo XML can't convert relative links into absolute links
  318.                                         if ((time()-OIDplus::config()->getValue('reg_last_ping') >= OIDplus::config()->getValue('reg_ping_interval'))) {
  319.                                                 $this->sendRegistrationQuery();
  320.                                         }
  321.                                 }
  322.                         }
  323.                 }
  324.         }
  325.  
  326.         public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {
  327.                 if (file_exists(__DIR__.'/treeicon.png')) {
  328.                         $tree_icon = OIDplus::webpath(__DIR__).'treeicon.png';
  329.                 } else {
  330.                         $tree_icon = null; // default icon (folder)
  331.                 }
  332.  
  333.                 $json[] = array(
  334.                         'id' => 'oidplus:srv_registration',
  335.                         'icon' => $tree_icon,
  336.                         'text' => 'System registration'
  337.                 );
  338.  
  339.                 return true;
  340.         }
  341.  
  342.         public function tree_search($request) {
  343.                 return false;
  344.         }
  345. }
  346.