Subversion Repositories oidplus

Rev

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