| 1: | <?php |
| 2: | |
| 3: | |
| 4: | |
| 5: | |
| 6: | |
| 7: | |
| 8: | |
| 9: | |
| 10: | |
| 11: | |
| 12: | |
| 13: | |
| 14: | |
| 15: | |
| 16: | |
| 17: | |
| 18: | |
| 19: | |
| 20: | |
| 21: | |
| 22: | include_once 'version.inc.php'; |
| 23: | $class_loader = include_once('vendor/autoload.php'); |
| 24: | |
| 25: | |
| 26: | const SIMPLEID_INSTANT_TOKEN_EXPIRES_IN = 60; |
| 27: | const SIMPLEID_SHORT_TOKEN_EXPIRES_IN = 3600; |
| 28: | const SIMPLEID_HUMAN_TOKEN_EXPIRES_IN = 43200; |
| 29: | const SIMPLEID_LONG_TOKEN_EXPIRES_IN = 1209600; |
| 30: | const SIMPLEID_LONG_TOKEN_EXPIRES_BUFFER = 300; |
| 31: | |
| 32: | |
| 33: | const SIMPLEID_ETERNAL_TOKEN_EXPIRES_IN = 34560000; |
| 34: | |
| 35: | |
| 36: | |
| 37: | $f3 = \Base::instance(); |
| 38: | |
| 39: | $default_config = [ |
| 40: | 'allow_plaintext' => false, |
| 41: | 'openid_verify_return_url' => true, |
| 42: | 'openid_strict_realm_check' => true, |
| 43: | 'webfinger_access_control_allow_origin' => '*', |
| 44: | 'locale' => 'en', |
| 45: | 'debug' => 0, |
| 46: | 'logger' => 'SimpleID\Util\DefaultLogger', |
| 47: | 'log_file' => '', |
| 48: | 'log_level' => 'info', |
| 49: | 'log_location' => false, |
| 50: | 'date_time_format' => 'Y-m-d H:i:s T', |
| 51: | 'acr' => 1, |
| 52: | 'required_modules' => [ |
| 53: | 'SimpleID\Base\IndexModule', |
| 54: | 'SimpleID\Store\DefaultStoreModule', |
| 55: | 'SimpleID\Auth\AuthModule', |
| 56: | 'SimpleID\Base\UserModule', |
| 57: | ], |
| 58: | 'modules' => [ |
| 59: | 'SimpleID\Base\MyModule', |
| 60: | 'SimpleID\Auth\PasswordAuthSchemeModule', |
| 61: | 'SimpleID\Auth\RememberMeAuthSchemeModule', |
| 62: | 'SimpleID\Auth\OTPAuthSchemeModule', |
| 63: | 'SimpleID\Protocols\OpenID\OpenIDModule', |
| 64: | 'SimpleID\Protocols\OpenID\Extensions\SRegOpenIDExtensionModule', |
| 65: | 'SimpleID\Protocols\WebFinger\WebFingerModule', |
| 66: | ], |
| 67: | ]; |
| 68: | |
| 69: | |
| 70: | if (file_exists('conf/config.php')) { |
| 71: | $config_file = 'conf/config.php'; |
| 72: | } elseif (file_exists('config.php')) { |
| 73: | $config_file = 'config.php'; |
| 74: | } else { |
| 75: | die('No configuration file found. See <http://simpleid.org/docs/2/installing/> for instructions on how to set up a configuration file.'); |
| 76: | } |
| 77: | |
| 78: | $config = include_once($config_file); |
| 79: | $config = array_replace_recursive($default_config, $config); |
| 80: | if (!isset($config['canonical_base_path'])) { |
| 81: | $port = $f3->get('PORT'); |
| 82: | $config['canonical_base_path'] = $f3->get('SCHEME') .'://'. $_SERVER['SERVER_NAME'] |
| 83: | . ($port && $port != 80 && $port != 443 ? (':' . $port) : '') . $f3->get('BASE'); |
| 84: | } |
| 85: | |
| 86: | if (isset($config['secure_secret']) && ($config['secure_secret'] != '') && !isset($_ENV['SIMPLEID_SECURE_SECRET'])) { |
| 87: | $_ENV['SIMPLEID_SECURE_SECRET'] = $config['secure_secret']; |
| 88: | $f3->sync('ENV'); |
| 89: | } elseif (isset($config['secure_secret_file']) && ($config['secure_secret_file'] != '') && !isset($_ENV['SIMPLEID_SECURE_SECRET_FILE'])) { |
| 90: | $_ENV['SIMPLEID_SECURE_SECRET_FILE'] = $config['secure_secret_file']; |
| 91: | $f3->sync('ENV'); |
| 92: | } |
| 93: | |
| 94: | date_default_timezone_set(@date_default_timezone_get()); |
| 95: | |
| 96: | $f3->mset([ |
| 97: | 'CASELESS' => false, |
| 98: | 'CORS.origin' => '*', |
| 99: | 'JAR.domain' => '', |
| 100: | 'JAR.secure' => false, |
| 101: | 'JAR.samesite' => 'Strict', |
| 102: | 'PACKAGE' => 'SimpleID/' . SIMPLEID_VERSION, |
| 103: | 'TEMP' => $config['temp_dir'] . '/', |
| 104: | 'UI' => 'html/', |
| 105: | 'PREFIX' => 'intl.' |
| 106: | ]); |
| 107: | |
| 108: | $f3->mset([ |
| 109: | 'FALLBACK' => 'en', |
| 110: | 'LOCALES' => 'locale/' |
| 111: | ]); |
| 112: | $f3->set('version', SIMPLEID_VERSION); |
| 113: | $f3->set('base_path', $f3->get('BASE') . '/'); |
| 114: | $f3->set('config', $config); |
| 115: | $f3->set('class_loader', $class_loader); |
| 116: | |
| 117: | |
| 118: | if (!is_dir($f3->get('TEMP')) || !is_writable($f3->get('TEMP'))) { |
| 119: | die('Temp directory not found or not writeable. Make sure temp_dir is set up properly in config.php.'); |
| 120: | } |
| 121: | |
| 122: | |
| 123: | if (preg_match('/^folder\h*=\h*(.+)/', $config['cache']) && substr($config['cache'], -1) != '/') { |
| 124: | $config['cache'] .= '/'; |
| 125: | } |
| 126: | $f3->set('CACHE', $config['cache']); |
| 127: | $cache = \Cache::instance(); |
| 128: | |
| 129: | |
| 130: | |
| 131: | if (!isset($config['logger']) || ($config['logger'] == '') || ($config['log_file'] == '')) { |
| 132: | $config['logger'] = 'Psr\Log\NullLogger'; |
| 133: | } |
| 134: | if (is_subclass_of($config['logger'], '\Log', true)) $f3->set('LOGS', dirname($config['log_file']) . '/'); |
| 135: | $logger = new $config['logger']($config); |
| 136: | $f3->set('logger', $logger); |
| 137: | |
| 138: | if ($config['debug']) { |
| 139: | Tracy\Debugger::enable('127.0.0.1'); |
| 140: | if (is_int($config['debug'])) $f3->set('DEBUG', $config['debug']); |
| 141: | } |
| 142: | |
| 143: | |
| 144: | fix_http_request($f3); |
| 145: | |
| 146: | |
| 147: | if (isset($_GET['q'])) { |
| 148: | $f3->set('PATH', '/' . $_GET['q']); |
| 149: | unset($_GET['q']); |
| 150: | } |
| 151: | |
| 152: | |
| 153: | if ((@ini_get('register_globals') === 1) || (@ini_get('register_globals') === '1') || (strtolower(@ini_get('register_globals')) == 'on')) { |
| 154: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'register_globals is enabled in PHP configuration.'); |
| 155: | $f3->error(500, $f3->get('intl.bootstrap.register_globals', 'http://simpleid.org/docs/2/system-requirements/')); |
| 156: | } |
| 157: | |
| 158: | if (!isset($_ENV['SIMPLEID_SECURE_SECRET']) && !isset($_ENV['SIMPLEID_SECURE_SECRET_FILE'])) { |
| 159: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'secure_secret or secure_secret_file not set.'); |
| 160: | $f3->error(500, $f3->get('intl.bootstrap.secure_secret')); |
| 161: | } |
| 162: | |
| 163: | if (!\SimpleID\Crypt\BigNum::loaded()) { |
| 164: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'gmp/bcmath PHP extension not loaded.'); |
| 165: | $f3->error(500, $f3->get('intl.bootstrap.extension', [ 'gmp/bcmath', 'http://simpleid.org/docs/2/system-requirements/' ])); |
| 166: | } |
| 167: | if (!function_exists('preg_match')) { |
| 168: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'pcre PHP extension not loaded.'); |
| 169: | $f3->error(500, $f3->get('intl.bootstrap.extension', [ 'pcre', 'http://simpleid.org/docs/2/system-requirements/' ])); |
| 170: | } |
| 171: | if (!function_exists('session_start')) { |
| 172: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'session PHP extension not loaded.'); |
| 173: | $f3->error(500, $f3->get('intl.bootstrap.extension', [ 'session', 'http://simpleid.org/docs/2/system-requirements/' ])); |
| 174: | } |
| 175: | if (!function_exists('xml_parser_create_ns')) { |
| 176: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'xml PHP extension not loaded.'); |
| 177: | $f3->error(500, $f3->get('intl.bootstrap.extension', [ 'xml', 'http://simpleid.org/docs/2/system-requirements/' ])); |
| 178: | } |
| 179: | if (!function_exists('hash')) { |
| 180: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'hash PHP extension not loaded.'); |
| 181: | $f3->error(500, $f3->get('intl.bootstrap.extension', [ 'hash', 'http://simpleid.org/docs/2/system-requirements/' ])); |
| 182: | } |
| 183: | if (!function_exists('openssl_sign')) { |
| 184: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'openssl PHP extension not loaded.'); |
| 185: | $f3->error(500, $f3->get('intl.bootstrap.extension', [ 'openssl', 'http://simpleid.org/docs/2/system-requirements/' ])); |
| 186: | } |
| 187: | if (!function_exists('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt')) { |
| 188: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'sodium PHP extension not loaded.'); |
| 189: | $f3->error(500, $f3->get('intl.bootstrap.extension', [ 'sodium', 'http://simpleid.org/docs/2/system-requirements/' ])); |
| 190: | } |
| 191: | if (is_numeric(@ini_get('suhosin.get.max_value_length')) && (@ini_get('suhosin.get.max_value_length') < 1024)) { |
| 192: | $f3->get('logger')->log(\Psr\Log\LogLevel::CRITICAL, 'suhosin.get.max_value_length < 1024'); |
| 193: | $f3->error(500, $f3->get('intl.bootstrap.suhosin', 'http://simpleid.org/docs/2/system-requirements/')); |
| 194: | } |
| 195: | |
| 196: | |
| 197: | |
| 198: | |
| 199: | |
| 200: | |
| 201: | |
| 202: | |
| 203: | |
| 204: | |
| 205: | function fix_http_request($f3) { |
| 206: | |
| 207: | if (isset($_SERVER['QUERY_STRING'])) { |
| 208: | $get = parse_http_query($_SERVER['QUERY_STRING']); |
| 209: | |
| 210: | foreach ($get as $key => $value) { |
| 211: | |
| 212: | if ((strpos($key, '[') !== FALSE) && (strpos($key, ']') !== FALSE)) $key = substr($key, 0, strpos($key, '[')); |
| 213: | |
| 214: | |
| 215: | $php_key = preg_replace('/[ .[\x80-\x9F]/', '_', $key); |
| 216: | |
| 217: | |
| 218: | if (($key != $php_key) && isset($_GET[$php_key])) { |
| 219: | $_GET[$key] = $_GET[$php_key]; |
| 220: | $_REQUEST[$key] = $_REQUEST[$php_key]; |
| 221: | unset($_GET[$php_key]); |
| 222: | unset($_REQUEST[$php_key]); |
| 223: | } |
| 224: | } |
| 225: | } |
| 226: | |
| 227: | |
| 228: | if ($f3->get('VERB') != 'POST') return; |
| 229: | if ($f3->get('SERVER.CONTENT_TYPE') != 'application/x-www-form-urlencoded') return; |
| 230: | |
| 231: | $input = file_get_contents('php://input'); |
| 232: | if ($input !== FALSE) { |
| 233: | $post = parse_http_query($input); |
| 234: | |
| 235: | foreach ($post as $key => $value) { |
| 236: | |
| 237: | if ((strpos($key, '[') !== FALSE) && (strpos($key, ']') !== FALSE)) $key = substr($key, 0, strpos($key, '[')); |
| 238: | |
| 239: | |
| 240: | $php_key = preg_replace('/[ .[\x80-\x9F]/', '_', $key); |
| 241: | |
| 242: | |
| 243: | if (($key != $php_key) && isset($_POST[$php_key])) { |
| 244: | $_POST[$key] = $_POST[$php_key]; |
| 245: | $_REQUEST[$key] = $_REQUEST[$php_key]; |
| 246: | unset($_POST[$php_key]); |
| 247: | unset($_REQUEST[$php_key]); |
| 248: | } |
| 249: | } |
| 250: | } |
| 251: | } |
| 252: | |
| 253: | |
| 254: | |
| 255: | |
| 256: | |
| 257: | |
| 258: | |
| 259: | |
| 260: | |
| 261: | function parse_http_query($query) { |
| 262: | $data = []; |
| 263: | |
| 264: | if ($query === NULL) return []; |
| 265: | if ($query === '') return []; |
| 266: | |
| 267: | $pairs = explode('&', $query); |
| 268: | |
| 269: | foreach ($pairs as $pair) { |
| 270: | list ($key, $value) = explode('=', $pair, 2); |
| 271: | $data[$key] = urldecode($value); |
| 272: | } |
| 273: | |
| 274: | return $data; |
| 275: | } |
| 276: | |
| 277: | ?> |
| 278: | |