common.inc.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Misc stuff and REQUIRED by ALL the scripts.
  5. * MUST be included by every script
  6. *
  7. * Among other things, it contains the advanced authentication work.
  8. *
  9. * Order of sections for common.inc.php:
  10. *
  11. * the authentication libraries must be before the connection to db
  12. *
  13. * ... so the required order is:
  14. *
  15. * LABEL_variables_init
  16. * - initialize some variables always needed
  17. * LABEL_parsing_config_file
  18. * - parsing of the configuration file
  19. * LABEL_loading_language_file
  20. * - loading language file
  21. * LABEL_setup_servers
  22. * - check and setup configured servers
  23. * LABEL_theme_setup
  24. * - setting up themes
  25. *
  26. * - load of MySQL extension (if necessary)
  27. * - loading of an authentication library
  28. * - db connection
  29. * - authentication work
  30. *
  31. * @package PhpMyAdmin
  32. */
  33. use PhpMyAdmin\Config;
  34. use PhpMyAdmin\Core;
  35. use PhpMyAdmin\DatabaseInterface;
  36. use PhpMyAdmin\ErrorHandler;
  37. use PhpMyAdmin\LanguageManager;
  38. use PhpMyAdmin\Logging;
  39. use PhpMyAdmin\Message;
  40. use PhpMyAdmin\Plugins\AuthenticationPlugin;
  41. use PhpMyAdmin\Response;
  42. use PhpMyAdmin\Session;
  43. use PhpMyAdmin\ThemeManager;
  44. use PhpMyAdmin\Tracker;
  45. use PhpMyAdmin\Util;
  46. /**
  47. * block attempts to directly run this script
  48. */
  49. if (getcwd() == dirname(__FILE__)) {
  50. die('Attack stopped');
  51. }
  52. /**
  53. * Minimum PHP version; can't call Core::fatalError() which uses a
  54. * PHP 5 function, so cannot easily localize this message.
  55. */
  56. if (version_compare(PHP_VERSION, '5.5.0', 'lt')) {
  57. die(
  58. 'PHP 5.5+ is required. <br /> Currently installed version is: '
  59. . phpversion()
  60. );
  61. }
  62. /**
  63. * for verification in all procedural scripts under libraries
  64. */
  65. define('PHPMYADMIN', true);
  66. /**
  67. * Load vendor configuration.
  68. */
  69. require_once './libraries/vendor_config.php';
  70. /**
  71. * Load hash polyfill.
  72. */
  73. require_once './libraries/hash.lib.php';
  74. /**
  75. * Activate autoloader
  76. */
  77. if (! @is_readable(AUTOLOAD_FILE)) {
  78. die(
  79. 'File <tt>' . AUTOLOAD_FILE . '</tt> missing or not readable. <br />'
  80. . 'Most likely you did not run Composer to '
  81. . '<a href="https://docs.phpmyadmin.net/en/latest/setup.html#installing-from-git">install library files</a>.'
  82. );
  83. }
  84. require_once AUTOLOAD_FILE;
  85. /**
  86. * Load gettext functions.
  87. */
  88. PhpMyAdmin\MoTranslator\Loader::loadFunctions();
  89. /**
  90. * initialize the error handler
  91. */
  92. $GLOBALS['error_handler'] = new ErrorHandler();
  93. /**
  94. * Warning about missing PHP extensions.
  95. */
  96. Core::checkExtensions();
  97. /**
  98. * Configure required PHP settings.
  99. */
  100. Core::configure();
  101. /******************************************************************************/
  102. /* start procedural code label_start_procedural */
  103. Core::cleanupPathInfo();
  104. /******************************************************************************/
  105. /* parsing configuration file LABEL_parsing_config_file */
  106. /**
  107. * @global Config $GLOBALS['PMA_Config']
  108. * force reading of config file, because we removed sensitive values
  109. * in the previous iteration
  110. */
  111. $GLOBALS['PMA_Config'] = new Config(CONFIG_FILE);
  112. /**
  113. * include session handling after the globals, to prevent overwriting
  114. */
  115. Session::setUp($GLOBALS['PMA_Config'], $GLOBALS['error_handler']);
  116. /**
  117. * init some variables LABEL_variables_init
  118. */
  119. /**
  120. * holds parameters to be passed to next page
  121. * @global array $GLOBALS['url_params']
  122. */
  123. $GLOBALS['url_params'] = array();
  124. /**
  125. * holds page that should be displayed
  126. * @global string $GLOBALS['goto']
  127. */
  128. $GLOBALS['goto'] = '';
  129. // Security fix: disallow accessing serious server files via "?goto="
  130. if (Core::checkPageValidity($_REQUEST['goto'])) {
  131. $GLOBALS['goto'] = $_REQUEST['goto'];
  132. $GLOBALS['url_params']['goto'] = $_REQUEST['goto'];
  133. } else {
  134. unset($_REQUEST['goto'], $_GET['goto'], $_POST['goto'], $_COOKIE['goto']);
  135. }
  136. /**
  137. * returning page
  138. * @global string $GLOBALS['back']
  139. */
  140. if (Core::checkPageValidity($_REQUEST['back'])) {
  141. $GLOBALS['back'] = $_REQUEST['back'];
  142. } else {
  143. unset($_REQUEST['back'], $_GET['back'], $_POST['back'], $_COOKIE['back']);
  144. }
  145. /**
  146. * Check whether user supplied token is valid, if not remove any possibly
  147. * dangerous stuff from request.
  148. *
  149. * remember that some objects in the session with session_start and __wakeup()
  150. * could access this variables before we reach this point
  151. * f.e. PhpMyAdmin\Config: fontsize
  152. *
  153. * Check for token mismatch only if the Request method is POST
  154. * GET Requests would never have token and therefore checking
  155. * mis-match does not make sense
  156. *
  157. * @todo variables should be handled by their respective owners (objects)
  158. * f.e. lang, server in PhpMyAdmin\Config
  159. */
  160. $token_mismatch = true;
  161. $token_provided = false;
  162. if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  163. if (Core::isValid($_POST['token'])) {
  164. $token_provided = true;
  165. $token_mismatch = ! @hash_equals($_SESSION[' PMA_token '], $_POST['token']);
  166. }
  167. if ($token_mismatch) {
  168. /* Warn in case the mismatch is result of failed setting of session cookie */
  169. if (isset($_POST['set_session']) && $_POST['set_session'] != session_id()) {
  170. trigger_error(
  171. __(
  172. 'Failed to set session cookie. Maybe you are using '
  173. . 'HTTP instead of HTTPS to access phpMyAdmin.'
  174. ),
  175. E_USER_ERROR
  176. );
  177. }
  178. /**
  179. * We don't allow any POST operation parameters if the token is mismatched
  180. * or is not provided
  181. */
  182. $whitelist = array('ajax_request');
  183. PhpMyAdmin\Sanitize::removeRequestVars($whitelist);
  184. }
  185. }
  186. /**
  187. * current selected database
  188. * @global string $GLOBALS['db']
  189. */
  190. Core::setGlobalDbOrTable('db');
  191. /**
  192. * current selected table
  193. * @global string $GLOBALS['table']
  194. */
  195. Core::setGlobalDbOrTable('table');
  196. /**
  197. * Store currently selected recent table.
  198. * Affect $GLOBALS['db'] and $GLOBALS['table']
  199. */
  200. if (Core::isValid($_REQUEST['selected_recent_table'])) {
  201. $recent_table = json_decode($_REQUEST['selected_recent_table'], true);
  202. $GLOBALS['db']
  203. = (array_key_exists('db', $recent_table) && is_string($recent_table['db'])) ?
  204. $recent_table['db'] : '';
  205. $GLOBALS['url_params']['db'] = $GLOBALS['db'];
  206. $GLOBALS['table']
  207. = (array_key_exists('table', $recent_table) && is_string($recent_table['table'])) ?
  208. $recent_table['table'] : '';
  209. $GLOBALS['url_params']['table'] = $GLOBALS['table'];
  210. }
  211. /**
  212. * SQL query to be executed
  213. * @global string $GLOBALS['sql_query']
  214. */
  215. $GLOBALS['sql_query'] = '';
  216. if (Core::isValid($_POST['sql_query'])) {
  217. $GLOBALS['sql_query'] = $_POST['sql_query'];
  218. }
  219. //$_REQUEST['set_theme'] // checked later in this file LABEL_theme_setup
  220. //$_REQUEST['server']; // checked later in this file
  221. //$_REQUEST['lang']; // checked by LABEL_loading_language_file
  222. /******************************************************************************/
  223. /* loading language file LABEL_loading_language_file */
  224. /**
  225. * lang detection is done here
  226. */
  227. $language = LanguageManager::getInstance()->selectLanguage();
  228. $language->activate();
  229. /**
  230. * check for errors occurred while loading configuration
  231. * this check is done here after loading language files to present errors in locale
  232. */
  233. $GLOBALS['PMA_Config']->checkPermissions();
  234. $GLOBALS['PMA_Config']->checkErrors();
  235. /* Check server configuration */
  236. Core::checkConfiguration();
  237. /* Check request for possible attacks */
  238. Core::checkRequest();
  239. /******************************************************************************/
  240. /* setup servers LABEL_setup_servers */
  241. $GLOBALS['PMA_Config']->checkServers();
  242. /**
  243. * current server
  244. * @global integer $GLOBALS['server']
  245. */
  246. $GLOBALS['server'] = $GLOBALS['PMA_Config']->selectServer();
  247. $GLOBALS['url_params']['server'] = $GLOBALS['server'];
  248. /**
  249. * BC - enable backward compatibility
  250. * exports all configuration settings into $GLOBALS ($GLOBALS['cfg'])
  251. */
  252. $GLOBALS['PMA_Config']->enableBc();
  253. /******************************************************************************/
  254. /* setup themes LABEL_theme_setup */
  255. ThemeManager::initializeTheme();
  256. if (! defined('PMA_MINIMUM_COMMON')) {
  257. /**
  258. * save some settings in cookies
  259. * @todo should be done in PhpMyAdmin\Config
  260. */
  261. $GLOBALS['PMA_Config']->setCookie('pma_lang', $GLOBALS['lang']);
  262. ThemeManager::getInstance()->setThemeCookie();
  263. if (! empty($cfg['Server'])) {
  264. /**
  265. * Loads the proper database interface for this server
  266. */
  267. DatabaseInterface::load();
  268. // get LoginCookieValidity from preferences cache
  269. // no generic solution for loading preferences from cache as some settings
  270. // need to be kept for processing in
  271. // PhpMyAdmin\Config::loadUserPreferences()
  272. $cache_key = 'server_' . $GLOBALS['server'];
  273. if (isset($_SESSION['cache'][$cache_key]['userprefs']['LoginCookieValidity'])
  274. ) {
  275. $value
  276. = $_SESSION['cache'][$cache_key]['userprefs']['LoginCookieValidity'];
  277. $GLOBALS['PMA_Config']->set('LoginCookieValidity', $value);
  278. $GLOBALS['cfg']['LoginCookieValidity'] = $value;
  279. unset($value);
  280. }
  281. unset($cache_key);
  282. // Gets the authentication library that fits the $cfg['Server'] settings
  283. // and run authentication
  284. /**
  285. * the required auth type plugin
  286. */
  287. $auth_class = 'PhpMyAdmin\\Plugins\\Auth\\Authentication' . ucfirst(strtolower($cfg['Server']['auth_type']));
  288. if (! @class_exists($auth_class)) {
  289. Core::fatalError(
  290. __('Invalid authentication method set in configuration:')
  291. . ' ' . $cfg['Server']['auth_type']
  292. );
  293. }
  294. if (isset($_REQUEST['pma_password']) && strlen($_REQUEST['pma_password']) > 256) {
  295. $_REQUEST['pma_password'] = substr($_REQUEST['pma_password'], 0, 256);
  296. }
  297. $auth_plugin = new $auth_class();
  298. $auth_plugin->authenticate();
  299. // Try to connect MySQL with the control user profile (will be used to
  300. // get the privileges list for the current user but the true user link
  301. // must be open after this one so it would be default one for all the
  302. // scripts)
  303. $controllink = false;
  304. if ($cfg['Server']['controluser'] != '') {
  305. $controllink = $GLOBALS['dbi']->connect(
  306. DatabaseInterface::CONNECT_CONTROL
  307. );
  308. }
  309. // Connects to the server (validates user's login)
  310. /** @var DatabaseInterface $userlink */
  311. $userlink = $GLOBALS['dbi']->connect(DatabaseInterface::CONNECT_USER);
  312. if ($userlink === false) {
  313. $auth_plugin->showFailure('mysql-denied');
  314. }
  315. if (! $controllink) {
  316. /*
  317. * Open separate connection for control queries, this is needed
  318. * to avoid problems with table locking used in main connection
  319. * and phpMyAdmin issuing queries to configuration storage, which
  320. * is not locked by that time.
  321. */
  322. $controllink = $GLOBALS['dbi']->connect(
  323. DatabaseInterface::CONNECT_USER,
  324. null,
  325. DatabaseInterface::CONNECT_CONTROL
  326. );
  327. }
  328. $auth_plugin->rememberCredentials();
  329. $auth_plugin->checkTwoFactor();
  330. /* Log success */
  331. Logging::logUser($cfg['Server']['user']);
  332. if ($GLOBALS['dbi']->getVersion() < $cfg['MysqlMinVersion']['internal']) {
  333. Core::fatalError(
  334. __('You should upgrade to %s %s or later.'),
  335. array('MySQL', $cfg['MysqlMinVersion']['human'])
  336. );
  337. }
  338. // Sets the default delimiter (if specified).
  339. if (!empty($_REQUEST['sql_delimiter'])) {
  340. PhpMyAdmin\SqlParser\Lexer::$DEFAULT_DELIMITER = $_REQUEST['sql_delimiter'];
  341. }
  342. // TODO: Set SQL modes too.
  343. } else { // end server connecting
  344. $response = Response::getInstance();
  345. $response->getHeader()->disableMenuAndConsole();
  346. $response->getFooter()->setMinimal();
  347. }
  348. /**
  349. * check if profiling was requested and remember it
  350. * (note: when $cfg['ServerDefault'] = 0, constant is not defined)
  351. */
  352. if (isset($_REQUEST['profiling'])
  353. && Util::profilingSupported()
  354. ) {
  355. $_SESSION['profiling'] = true;
  356. } elseif (isset($_REQUEST['profiling_form'])) {
  357. // the checkbox was unchecked
  358. unset($_SESSION['profiling']);
  359. }
  360. /**
  361. * Inclusion of profiling scripts is needed on various
  362. * pages like sql, tbl_sql, db_sql, tbl_select
  363. */
  364. $response = Response::getInstance();
  365. if (isset($_SESSION['profiling'])) {
  366. $scripts = $response->getHeader()->getScripts();
  367. $scripts->addFile('chart.js');
  368. $scripts->addFile('vendor/jqplot/jquery.jqplot.js');
  369. $scripts->addFile('vendor/jqplot/plugins/jqplot.pieRenderer.js');
  370. $scripts->addFile('vendor/jqplot/plugins/jqplot.highlighter.js');
  371. $scripts->addFile('vendor/jquery/jquery.tablesorter.js');
  372. }
  373. /*
  374. * There is no point in even attempting to process
  375. * an ajax request if there is a token mismatch
  376. */
  377. if ($response->isAjax() && $_SERVER['REQUEST_METHOD'] == 'POST' && $token_mismatch) {
  378. $response->setRequestStatus(false);
  379. $response->addJSON(
  380. 'message',
  381. Message::error(__('Error: Token mismatch'))
  382. );
  383. exit;
  384. }
  385. }
  386. // load user preferences
  387. $GLOBALS['PMA_Config']->loadUserPreferences();
  388. /* Tell tracker that it can actually work */
  389. Tracker::enable();