Subversion Repositories oidplus

Rev

Rev 76 | Rev 80 | 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 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. class OIDplus {
  21.         private static /*OIDplusDataBase*/ $database;
  22.         private static /*OIDplusConfig*/ $config;
  23.         private static /*OIDplusPagePlugin[][]*/ $pagePlugins = array();
  24.         private static /*OIDplusObject*/ $objectTypes = array();
  25.         private static /*OIDplusObject*/ $disabledObjectTypes = array();
  26.  
  27.         private function __construct() {
  28.         }
  29.  
  30.         public static function db() {
  31.                 if (is_null(self::$database)) {
  32.                         self::$database = new OIDplusDataBaseMySQL();
  33.                 }
  34.                 return self::$database;
  35.         }
  36.  
  37.         public static function config() {
  38.                 if (is_null(self::$config)) {
  39.                         self::$config = new OIDplusConfig();
  40.                 }
  41.                 return self::$config;
  42.         }
  43.  
  44.         public static function gui() {
  45.                 return new OIDplusGui();
  46.         }
  47.  
  48.         public static function authUtils() {
  49.                 return new OIDplusAuthUtils();
  50.         }
  51.  
  52.         public static function system_url() {
  53.                 if (!isset($_SERVER["REQUEST_URI"])) return false;
  54.  
  55.                 $test_dir = dirname($_SERVER['SCRIPT_FILENAME']);
  56.                 $c = 0;
  57.                 while (!file_exists($test_dir.'/oidplus.js')) {
  58.                         $test_dir = dirname($test_dir);
  59.                         $c++;
  60.                         if ($c == 1000) return false;
  61.                 }
  62.  
  63.                 $res = dirname($_SERVER['SCRIPT_URI'].'xxx');
  64.  
  65.                 for ($i=1; $i<=$c; $i++) {
  66.                         $res = dirname($res);
  67.                 }
  68.  
  69.                 $res .= '/';
  70.  
  71.                 return $res;
  72.         }
  73.  
  74.         public static function sesHandler() {
  75.                 return new OIDplusSessionHandler(OIDPLUS_SESSION_SECRET);
  76.         }
  77.  
  78.         public static function registerPagePlugin(OIDplusPagePlugin $plugin) {
  79.                 $type = $plugin->type();
  80.                 if ($type === false) return false;
  81.  
  82.                 $prio = $plugin->priority();
  83.                 if ($prio === false) return false;
  84.  
  85.                 if (!isset(self::$pagePlugins[$type])) self::$pagePlugins[$type] = array();
  86.                 self::$pagePlugins[$type][$prio] = $plugin;
  87.  
  88.                 return true;
  89.         }
  90.  
  91.         public static function getPagePlugins($type) {
  92.                 if ($type == '*') {
  93.                         $res = array();
  94.                         foreach (self::$pagePlugins as $data) {
  95.                                 $res = array_merge($res, $data);
  96.                         }
  97.                 } else {
  98.                         $res = self::$pagePlugins[$type];
  99.                 }
  100.                 ksort($res);
  101.                 return $res;
  102.         }
  103.  
  104.         public static function registerObjectType($ot) {
  105.                 $ns = $ot::ns();
  106.  
  107.                 if (empty($ns)) die("Attention: Empty NS at $ot\n");
  108.  
  109.                 $ns_found = false;
  110.                 foreach (OIDplus::getRegisteredObjectTypes() as $test_ot) {
  111.                         if ($test_ot::ns() == $ns) {
  112.                                 $ns_found = true;
  113.                                 break;
  114.                         }
  115.                 }
  116.                 if ($ns_found) {
  117.                         throw new Exception("Attention: Two objectType plugins use the same namespace \"$ns\"!");
  118.                 }
  119.  
  120.                 $init = OIDplus::config()->getValue("objecttypes_initialized");
  121.                 $init_ary = empty($init) ? array() : explode(';', $init);
  122.                 $init_ary = array_map('trim', $init_ary);
  123.  
  124.                 $enabled = OIDplus::config()->getValue("objecttypes_enabled");
  125.                 $enabled_ary = empty($enabled) ? array() : explode(';', $enabled);
  126.                 $enabled_ary = array_map('trim', $enabled_ary);
  127.  
  128.                 $do_enable = false;
  129.                 if (in_array($ns, $enabled_ary)) {
  130.                         $do_enable = true;
  131.                 } else {
  132.                         if (!OIDplus::config()->getValue('registration_done')) {
  133.                                 $do_enable = $ns == 'oid';
  134.                         } else {
  135.                                 $do_enable = !in_array($ns, $init_ary);
  136.                         }
  137.                 }
  138.  
  139.                 if ($do_enable) {
  140.                         self::$objectTypes[] = $ot;
  141.                         usort(self::$objectTypes, function($a, $b) {
  142.                                 $enabled = OIDplus::config()->getValue("objecttypes_enabled");
  143.                                 $enabled_ary = explode(';', $enabled);
  144.  
  145.                                 $idx_a = array_search($a::ns(), $enabled_ary);
  146.                                 $idx_b = array_search($b::ns(), $enabled_ary);
  147.  
  148.                                 if ($idx_a == $idx_b) {
  149.                                     return 0;
  150.                                 }
  151.                                 return ($idx_a > $idx_b) ? +1 : -1;
  152.                         });
  153.                 } else {
  154.                         self::$disabledObjectTypes[] = $ot;
  155.                 }
  156.  
  157.                 if (!in_array($ns, $init_ary)) {
  158.                         // Was never initialized before, so we add it to the list of enabled object types once
  159.  
  160.                         if ($do_enable) {
  161.                                 $enabled_ary[] = $ns;
  162.                                 OIDplus::config()->setValue("objecttypes_enabled", implode(';', $enabled_ary));
  163.                         }
  164.  
  165.                         $init_ary[] = $ns;
  166.                         OIDplus::config()->setValue("objecttypes_initialized", implode(';', $init_ary));
  167.                 }
  168.         }
  169.  
  170.         public static function getRegisteredObjectTypes() {
  171.                 return self::$objectTypes;
  172.         }
  173.  
  174.         public static function getDisabledObjectTypes() {
  175.                 return self::$disabledObjectTypes;
  176.         }
  177.  
  178.         public static function system_id($oid=false) {
  179.                 if (!self::pkiStatus(true)) return false;
  180.                 $pubKey = OIDplus::config()->getValue('oidplus_public_key');
  181.                 if (preg_match('@BEGIN PUBLIC KEY\-+(.+)\-+END PUBLIC KEY@ismU', $pubKey, $m)) {
  182.                         return ($oid ? '1.3.6.1.4.1.37476.30.9.' : '').smallhash(base64_decode($m[1]));
  183.                 }
  184.                 return false;
  185.         }
  186.  
  187.         public static function pkiStatus($try_generate=true) {
  188.                 if (!function_exists('openssl_pkey_new')) return false;
  189.  
  190.                 $privKey = OIDplus::config()->getValue('oidplus_private_key');
  191.                 $pubKey = OIDplus::config()->getValue('oidplus_public_key');
  192.  
  193.                 if ($try_generate && !verify_private_public_key($privKey, $pubKey)) {
  194.                         $config = array(
  195.                             "digest_alg" => "sha512",
  196.                             "private_key_bits" => 2048,
  197.                             "private_key_type" => OPENSSL_KEYTYPE_RSA,
  198.                         );
  199.  
  200.                         // Create the private and public key
  201.                         $res = openssl_pkey_new($config);
  202.  
  203.                         // Extract the private key from $res to $privKey
  204.                         openssl_pkey_export($res, $privKey);
  205.  
  206.                         OIDplus::config()->setValue('oidplus_private_key', $privKey);
  207.  
  208.                         // Extract the public key from $res to $pubKey
  209.                         $pubKey = openssl_pkey_get_details($res);
  210.                         $pubKey = $pubKey["key"];
  211.  
  212.                         OIDplus::config()->setValue('oidplus_public_key', $pubKey);
  213.                 }
  214.  
  215.                 return verify_private_public_key($privKey, $pubKey);
  216.         }
  217.  
  218.         public static function init($html=true) {
  219.                 define('OIDPLUS_HTML_OUTPUT', $html);
  220.  
  221.                 // Include config file
  222.  
  223.                 if (file_exists(__DIR__ . '/../config.inc.php')) {
  224.                         include_once __DIR__ . '/../config.inc.php';
  225.                 } else {
  226.                         if ($html) {
  227.                                 if (!is_dir('setup')) {
  228.                                         echo 'Error: Setup directory missing.';
  229.                                 } else {
  230.                                         header('Location:setup/');
  231.                                 }
  232.                         } else {
  233.                                 echo 'Error: Setup directory missing!';
  234.                         }
  235.                         die();
  236.                 }
  237.  
  238.                 // Auto-fill non-existing config values
  239.  
  240.                 if (!defined('OIDPLUS_CONFIG_VERSION'))   define('OIDPLUS_CONFIG_VERSION',   0.0);
  241.                 if (!defined('OIDPLUS_ADMIN_PASSWORD'))   define('OIDPLUS_ADMIN_PASSWORD',   '');
  242.                 if (!defined('OIDPLUS_MYSQL_HOST'))       define('OIDPLUS_MYSQL_HOST',       'localhost');
  243.                 if (!defined('OIDPLUS_MYSQL_USERNAME'))   define('OIDPLUS_MYSQL_USERNAME',   'root');
  244.                 if (!defined('OIDPLUS_MYSQL_PASSWORD'))   define('OIDPLUS_MYSQL_PASSWORD',   '');
  245.                 if (!defined('OIDPLUS_MYSQL_DATABASE'))   define('OIDPLUS_MYSQL_DATABASE',   'oidplus');
  246.                 if (!defined('OIDPLUS_TABLENAME_PREFIX')) define('OIDPLUS_TABLENAME_PREFIX', '');
  247.                 if (!defined('OIDPLUS_SESSION_SECRET'))   define('OIDPLUS_SESSION_SECRET',   '');
  248.                 if (!defined('RECAPTCHA_ENABLED'))        define('RECAPTCHA_ENABLED',        false);
  249.                 if (!defined('RECAPTCHA_PUBLIC'))         define('RECAPTCHA_PUBLIC',         '');
  250.                 if (!defined('RECAPTCHA_PRIVATE'))        define('RECAPTCHA_PRIVATE',        '');
  251.  
  252.                 // Check version of the config file
  253.  
  254.                 if (OIDPLUS_CONFIG_VERSION != 2.0) {
  255.                         if ($html) {
  256.                                 echo '<h1>Error</h1><p>The information located in <b>includes/config.inc.php</b> is outdated.</p><p>Please run <a href="setup/">setup</a> again.</p>';
  257.                         } else {
  258.                                 echo 'The information located in includes/config.inc.php is outdated. Please run setup again.';
  259.                         }
  260.                         die();
  261.                 }
  262.  
  263.                 // Do redirect stuff etc.
  264.  
  265.                 define('OIDPLUS_SSL_AVAILABLE', self::isSslAvailable());
  266.  
  267.                 // System config settings
  268.  
  269.                 OIDplus::config()->prepareConfigKey('objecttypes_initialized', 'List of object type plugins that were initialized once', '', 1, 1);
  270.                 OIDplus::config()->prepareConfigKey('objecttypes_enabled', 'Enabled object types and their order, separated with a semicolon (please reload the page so that the change is applied)', '', 0, 1);
  271.  
  272.                 OIDplus::config()->prepareConfigKey('oidplus_private_key', 'Private key for this system', '', 1, 0);
  273.                 OIDplus::config()->prepareConfigKey('oidplus_public_key', 'Public key for this system', '', 1, 1);
  274.  
  275.                 // Initialize public / private keys
  276.  
  277.                 OIDplus::pkiStatus(true);
  278.  
  279.                 // Register plugins
  280.  
  281.                 $ary = glob(__DIR__ . '/../../plugins/system/'.'*'.'/plugin.inc.php');
  282.                 foreach ($ary as $a) include $a;
  283.                 $ary = glob(__DIR__ . '/../../plugins/publicPages/'.'*'.'/plugin.inc.php');
  284.                 foreach ($ary as $a) include $a;
  285.                 $ary = glob(__DIR__ . '/../../plugins/raPages/'.'*'.'/plugin.inc.php');
  286.                 foreach ($ary as $a) include $a;
  287.                 $ary = glob(__DIR__ . '/../../plugins/adminPages/'.'*'.'/plugin.inc.php');
  288.                 foreach ($ary as $a) include $a;
  289.                 $ary = glob(__DIR__ . '/../../plugins/objectTypes/'.'*'.'/*.class.php');
  290.                 foreach ($ary as $a) include $a;
  291.  
  292.                 // Initialize plugins
  293.  
  294.                 foreach (OIDplus::getPagePlugins('*') as $plugin) {
  295.                         $plugin->init($html);
  296.                 }
  297.         }
  298.  
  299.         private static function isSslAvailable() {
  300.                 $timeout = 2;
  301.  
  302.                 if (php_sapi_name() == 'cli') return false;
  303.  
  304.                 if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == "on")) {
  305.                         // we are already on HTTPS
  306.                         setcookie('SSL_CHECK', '1', 0, '', '', false, true);
  307.                         return true;
  308.                 } else {
  309.                         if (isset($_COOKIE['SSL_CHECK'])) {
  310.                                 // We already had the HTTPS detection done before.
  311.                                 if ($_COOKIE['SSL_CHECK']) {
  312.                                         // HTTPS was detected before, but we are HTTP. Redirect now
  313.                                         $location = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  314.                                         header('Location:'.$location);
  315.                                         die('Redirect to HTTPS');
  316.                                         return true;
  317.                                 } else {
  318.                                         // No HTTPS available. Do nothing.
  319.                                         return false;
  320.                                 }
  321.                         } else {
  322.                                 // This is our first check (or the browser didn't accept the SSL_CHECK cookie)
  323.                                 if (@fsockopen($_SERVER['HTTP_HOST'], 443, $errno, $errstr, $timeout)) {
  324.                                         // HTTPS detected. Redirect now, and remember that we had detected HTTPS
  325.                                         setcookie('SSL_CHECK', '1', 0, '', '', false, true);
  326.                                         $location = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  327.                                         header('Location:'.$location);
  328.                                         die('Redirect to HTTPS');
  329.                                         return true;
  330.                                 } else {
  331.                                         // No HTTPS detected. Do nothing, and next time, don't try to detect HTTPS again.
  332.                                         setcookie('SSL_CHECK', '0', 0, '', '', false, true);
  333.                                         return false;
  334.                                 }
  335.                         }
  336.                 }
  337.         }
  338. }
  339.