AuthenticationCookie.class.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Cookie Authentication plugin for phpMyAdmin
  5. *
  6. * @package PhpMyAdmin-Authentication
  7. * @subpackage Cookie
  8. */
  9. if (! defined('PHPMYADMIN')) {
  10. exit;
  11. }
  12. /* Get the authentication interface */
  13. require_once 'libraries/plugins/AuthenticationPlugin.class.php';
  14. /**
  15. * Remember where to redirect the user
  16. * in case of an expired session.
  17. */
  18. if (! empty($_REQUEST['target'])) {
  19. $GLOBALS['target'] = $_REQUEST['target'];
  20. } else if (PMA_getenv('SCRIPT_NAME')) {
  21. $GLOBALS['target'] = basename(PMA_getenv('SCRIPT_NAME'));
  22. }
  23. /**
  24. * Swekey authentication functions.
  25. */
  26. require './libraries/plugins/auth/swekey/swekey.auth.lib.php';
  27. /**
  28. * Handles the cookie authentication method
  29. *
  30. * @package PhpMyAdmin-Authentication
  31. */
  32. class AuthenticationCookie extends AuthenticationPlugin
  33. {
  34. /**
  35. * IV for Blowfish.
  36. */
  37. private $_blowfish_iv = null;
  38. /**
  39. * Displays authentication form
  40. *
  41. * this function MUST exit/quit the application
  42. *
  43. * @global string $conn_error the last connection error
  44. *
  45. * @return boolean|void
  46. */
  47. public function auth()
  48. {
  49. global $conn_error;
  50. $response = PMA_Response::getInstance();
  51. if ($response->isAjax()) {
  52. $response->isSuccess(false);
  53. $response->addJSON(
  54. 'redirect_flag',
  55. '1'
  56. );
  57. if (defined('TESTSUITE')) {
  58. return true;
  59. } else {
  60. exit;
  61. }
  62. }
  63. /* Perform logout to custom URL */
  64. if (! empty($_REQUEST['old_usr'])
  65. && ! empty($GLOBALS['cfg']['Server']['LogoutURL'])
  66. ) {
  67. PMA_sendHeaderLocation($GLOBALS['cfg']['Server']['LogoutURL']);
  68. if (defined('TESTSUITE')) {
  69. return true;
  70. } else {
  71. exit;
  72. }
  73. }
  74. // No recall if blowfish secret is not configured as it would produce
  75. // garbage
  76. if ($GLOBALS['cfg']['LoginCookieRecall']
  77. && ! empty($GLOBALS['cfg']['blowfish_secret'])
  78. ) {
  79. $default_user = $GLOBALS['PHP_AUTH_USER'];
  80. $default_server = $GLOBALS['pma_auth_server'];
  81. $autocomplete = '';
  82. } else {
  83. $default_user = '';
  84. $default_server = '';
  85. // skip the IE autocomplete feature.
  86. $autocomplete = ' autocomplete="off"';
  87. }
  88. $response->getFooter()->setMinimal();
  89. $header = $response->getHeader();
  90. $header->setBodyId('loginform');
  91. $header->setTitle('phpMyAdmin');
  92. $header->disableMenu();
  93. $header->disableWarnings();
  94. if (file_exists(CUSTOM_HEADER_FILE)) {
  95. include CUSTOM_HEADER_FILE;
  96. }
  97. echo '
  98. <div class="container">
  99. <a href="';
  100. echo PMA_linkURL('http://www.phpmyadmin.net/');
  101. echo '" target="_blank" class="logo">';
  102. $logo_image = $GLOBALS['pmaThemeImage'] . 'logo_right.png';
  103. if (@file_exists($logo_image)) {
  104. echo '<img src="' . $logo_image
  105. . '" id="imLogo" name="imLogo" alt="phpMyAdmin" border="0" />';
  106. } else {
  107. echo '<img name="imLogo" id="imLogo" src="'
  108. . $GLOBALS['pmaThemeImage'] . 'pma_logo.png' . '" '
  109. . 'border="0" width="88" height="31" alt="phpMyAdmin" />';
  110. }
  111. echo '</a>
  112. <h1>';
  113. echo sprintf(
  114. __('Welcome to %s'),
  115. '<bdo dir="ltr" lang="en">phpMyAdmin</bdo>'
  116. );
  117. echo "</h1>";
  118. // Show error message
  119. if (! empty($conn_error)) {
  120. PMA_Message::rawError($conn_error)->display();
  121. } elseif (isset($_GET['session_expired'])
  122. && intval($_GET['session_expired']) == 1
  123. ) {
  124. PMA_Message::rawError(
  125. __('Your session has expired. Please log in again.')
  126. )->display();
  127. }
  128. echo "<noscript>\n";
  129. PMA_message::error(
  130. __("Javascript must be enabled past this point!")
  131. )->display();
  132. echo "</noscript>\n";
  133. echo "<div class='hide js-show'>";
  134. // Displays the languages form
  135. if (empty($GLOBALS['cfg']['Lang'])) {
  136. include_once './libraries/display_select_lang.lib.php';
  137. // use fieldset, don't show doc link
  138. echo PMA_getLanguageSelectorHtml(true, false);
  139. }
  140. echo '</div>
  141. <br />
  142. <!-- Login form -->
  143. <form method="post" action="index.php" name="login_form"' . $autocomplete .
  144. ' class="disableAjax login hide js-show">
  145. <fieldset>
  146. <legend>';
  147. echo __('Log in');
  148. echo PMA_Util::showDocu('index');
  149. echo '</legend>';
  150. if ($GLOBALS['cfg']['AllowArbitraryServer']) {
  151. echo '
  152. <div class="item">
  153. <label for="input_servername" title="';
  154. echo __(
  155. 'You can enter hostname/IP address and port separated by space.'
  156. );
  157. echo '">';
  158. echo __('Server:');
  159. echo '</label>
  160. <input type="text" name="pma_servername" id="input_servername"';
  161. echo ' value="';
  162. echo htmlspecialchars($default_server);
  163. echo '" size="24" class="textfield" title="';
  164. echo __(
  165. 'You can enter hostname/IP address and port separated by space.'
  166. ); echo '" />
  167. </div>';
  168. }
  169. echo '<div class="item">
  170. <label for="input_username">' . __('Username:') . '</label>
  171. <input type="text" name="pma_username" id="input_username" '
  172. . 'value="' . htmlspecialchars($default_user) . '" size="24"'
  173. . ' class="textfield"/>
  174. </div>
  175. <div class="item">
  176. <label for="input_password">' . __('Password:') . '</label>
  177. <input type="password" name="pma_password" id="input_password"'
  178. . ' value="" size="24" class="textfield" />
  179. </div>';
  180. if (count($GLOBALS['cfg']['Servers']) > 1) {
  181. echo '<div class="item">
  182. <label for="select_server">' . __('Server Choice:') . '</label>
  183. <select name="server" id="select_server"';
  184. if ($GLOBALS['cfg']['AllowArbitraryServer']) {
  185. echo ' onchange="document.forms[\'login_form\'].'
  186. . 'elements[\'pma_servername\'].value = \'\'" ';
  187. }
  188. echo '>';
  189. include_once './libraries/select_server.lib.php';
  190. echo PMA_selectServer(false, false);
  191. echo '</select></div>';
  192. } else {
  193. echo ' <input type="hidden" name="server" value="'
  194. . $GLOBALS['server'] . '" />';
  195. } // end if (server choice)
  196. // We already have one correct captcha.
  197. $skip = false;
  198. if ( isset($_SESSION['last_valid_captcha'])
  199. && $_SESSION['last_valid_captcha']
  200. ) {
  201. $skip = true;
  202. }
  203. // Add captcha input field if reCaptcha is enabled
  204. if ( !empty($GLOBALS['cfg']['CaptchaLoginPrivateKey'])
  205. && !empty($GLOBALS['cfg']['CaptchaLoginPublicKey'])
  206. && !$skip
  207. ) {
  208. // If enabled show captcha to the user on the login screen.
  209. echo '<script type="text/javascript">
  210. var RecaptchaOptions = {
  211. theme : "white"
  212. };
  213. </script>
  214. <script type="text/javascript"
  215. src="https://www.google.com/recaptcha/api/challenge?'
  216. . 'k=' . $GLOBALS['cfg']['CaptchaLoginPublicKey'] . '&amp;'
  217. . 'hl=' . $GLOBALS['lang'] . '">
  218. </script>
  219. <noscript>
  220. <iframe src="https://www.google.com/recaptcha/api/noscript?k='
  221. . $GLOBALS['cfg']['CaptchaLoginPublicKey'] . '"
  222. height="300" width="500" frameborder="0"></iframe><br>
  223. <textarea name="recaptcha_challenge_field" rows="3" cols="40">
  224. </textarea>
  225. <input type="hidden" name="recaptcha_response_field"
  226. value="manual_challenge">
  227. </noscript>
  228. <script type="text/javascript">
  229. $("#recaptcha_reload_btn").addClass("disableAjax");
  230. $("#recaptcha_switch_audio_btn").addClass("disableAjax");
  231. $("#recaptcha_switch_img_btn").addClass("disableAjax");
  232. $("#recaptcha_whatsthis_btn").addClass("disableAjax");
  233. $("#recaptcha_audio_play_again").live("mouseover", function() {
  234. $(this).addClass("disableAjax");
  235. });
  236. </script>';
  237. }
  238. echo '</fieldset>
  239. <fieldset class="tblFooters">
  240. <input value="' . __('Go') . '" type="submit" id="input_go" />';
  241. $_form_params = array();
  242. if (! empty($GLOBALS['target'])) {
  243. $_form_params['target'] = $GLOBALS['target'];
  244. }
  245. if (! empty($GLOBALS['db'])) {
  246. $_form_params['db'] = $GLOBALS['db'];
  247. }
  248. if (! empty($GLOBALS['table'])) {
  249. $_form_params['table'] = $GLOBALS['table'];
  250. }
  251. // do not generate a "server" hidden field as we want the "server"
  252. // drop-down to have priority
  253. echo PMA_URL_getHiddenInputs($_form_params, '', 0, 'server');
  254. echo '</fieldset>
  255. </form>';
  256. // BEGIN Swekey Integration
  257. Swekey_login('input_username', 'input_go');
  258. // END Swekey Integration
  259. if ($GLOBALS['error_handler']->hasDisplayErrors()) {
  260. echo '<div>';
  261. $GLOBALS['error_handler']->dispErrors();
  262. echo '</div>';
  263. }
  264. echo '</div>';
  265. if (file_exists(CUSTOM_FOOTER_FILE)) {
  266. include CUSTOM_FOOTER_FILE;
  267. }
  268. if (! defined('TESTSUITE')) {
  269. exit;
  270. } else {
  271. return true;
  272. }
  273. }
  274. /**
  275. * Gets advanced authentication settings
  276. *
  277. * this function DOES NOT check authentication - it just checks/provides
  278. * authentication credentials required to connect to the MySQL server
  279. * usually with $GLOBALS['dbi']->connect()
  280. *
  281. * it returns false if something is missing - which usually leads to
  282. * auth() which displays login form
  283. *
  284. * it returns true if all seems ok which usually leads to auth_set_user()
  285. *
  286. * it directly switches to authFails() if user inactivity timout is reached
  287. *
  288. * @todo AllowArbitraryServer on does not imply that the user wants an
  289. * arbitrary server, or? so we should also check if this is filled
  290. * and not only if allowed
  291. *
  292. * @return boolean whether we get authentication settings or not
  293. */
  294. public function authCheck()
  295. {
  296. global $conn_error;
  297. // Initialization
  298. /**
  299. * @global $GLOBALS['pma_auth_server'] the user provided server to
  300. * connect to
  301. */
  302. $GLOBALS['pma_auth_server'] = '';
  303. $GLOBALS['PHP_AUTH_USER'] = $GLOBALS['PHP_AUTH_PW'] = '';
  304. $GLOBALS['from_cookie'] = false;
  305. // BEGIN Swekey Integration
  306. if (! Swekey_Auth_check()) {
  307. return false;
  308. }
  309. // END Swekey Integration
  310. if (defined('PMA_CLEAR_COOKIES')) {
  311. foreach ($GLOBALS['cfg']['Servers'] as $key => $val) {
  312. $GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $key);
  313. $GLOBALS['PMA_Config']->removeCookie('pmaServer-' . $key);
  314. $GLOBALS['PMA_Config']->removeCookie('pmaUser-' . $key);
  315. }
  316. return false;
  317. }
  318. // We already have one correct captcha.
  319. $skip = false;
  320. if ( isset($_SESSION['last_valid_captcha'])
  321. && $_SESSION['last_valid_captcha']
  322. ) {
  323. $skip = true;
  324. }
  325. // Verify Captcha if it is required.
  326. if ( !empty($GLOBALS['cfg']['CaptchaLoginPrivateKey'])
  327. && !empty($GLOBALS['cfg']['CaptchaLoginPublicKey'])
  328. && !$skip
  329. ) {
  330. if ( !empty($_POST["recaptcha_challenge_field"])
  331. && !empty($_POST["recaptcha_response_field"])
  332. ) {
  333. include_once 'libraries/plugins/auth/recaptchalib.php';
  334. // Use private key to verify captcha status.
  335. $resp = recaptcha_check_answer(
  336. $GLOBALS['cfg']['CaptchaLoginPrivateKey'],
  337. $_SERVER["REMOTE_ADDR"],
  338. $_POST["recaptcha_challenge_field"],
  339. $_POST["recaptcha_response_field"]
  340. );
  341. // Check if the captcha entered is valid, if not stop the login.
  342. if ( !$resp->is_valid ) {
  343. $conn_error = __('Entered captcha is wrong, try again!');
  344. $_SESSION['last_valid_captcha'] = false;
  345. return false;
  346. } else {
  347. $_SESSION['last_valid_captcha'] = true;
  348. }
  349. } elseif (! empty($_POST["recaptcha_challenge_field"])
  350. && empty($_POST["recaptcha_response_field"])
  351. ) {
  352. $conn_error = __('Please enter correct captcha!');
  353. return false;
  354. } else {
  355. if (! isset($_SESSION['last_valid_captcha'])
  356. || ! $_SESSION['last_valid_captcha']
  357. ) {
  358. return false;
  359. }
  360. }
  361. }
  362. if (! empty($_REQUEST['old_usr'])) {
  363. // The user wants to be logged out
  364. // -> delete his choices that were stored in session
  365. // according to the PHP manual we should do this before the destroy:
  366. //$_SESSION = array();
  367. if (! defined('TESTSUITE')) {
  368. session_destroy();
  369. // $_SESSION array is not immediately emptied
  370. $_SESSION['last_valid_captcha'] = false;
  371. }
  372. // -> delete password cookie(s)
  373. if ($GLOBALS['cfg']['LoginCookieDeleteAll']) {
  374. foreach ($GLOBALS['cfg']['Servers'] as $key => $val) {
  375. $GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $key);
  376. if (isset($_COOKIE['pmaPass-' . $key])) {
  377. unset($_COOKIE['pmaPass-' . $key]);
  378. }
  379. }
  380. } else {
  381. $GLOBALS['PMA_Config']->removeCookie(
  382. 'pmaPass-' . $GLOBALS['server']
  383. );
  384. if (isset($_COOKIE['pmaPass-' . $GLOBALS['server']])) {
  385. unset($_COOKIE['pmaPass-' . $GLOBALS['server']]);
  386. }
  387. }
  388. }
  389. if (! empty($_REQUEST['pma_username'])) {
  390. // The user just logged in
  391. $GLOBALS['PHP_AUTH_USER'] = $_REQUEST['pma_username'];
  392. $GLOBALS['PHP_AUTH_PW'] = empty($_REQUEST['pma_password'])
  393. ? ''
  394. : $_REQUEST['pma_password'];
  395. if ($GLOBALS['cfg']['AllowArbitraryServer']
  396. && isset($_REQUEST['pma_servername'])
  397. ) {
  398. $GLOBALS['pma_auth_server'] = $_REQUEST['pma_servername'];
  399. }
  400. return true;
  401. }
  402. // At the end, try to set the $GLOBALS['PHP_AUTH_USER']
  403. // and $GLOBALS['PHP_AUTH_PW'] variables from cookies
  404. // servername
  405. if ($GLOBALS['cfg']['AllowArbitraryServer']
  406. && ! empty($_COOKIE['pmaServer-' . $GLOBALS['server']])
  407. ) {
  408. $GLOBALS['pma_auth_server']
  409. = $_COOKIE['pmaServer-' . $GLOBALS['server']];
  410. }
  411. // check cookies
  412. if (empty($_COOKIE['pmaUser-' . $GLOBALS['server']])
  413. || empty($_COOKIE['pma_mcrypt_iv'])
  414. ) {
  415. return false;
  416. }
  417. $GLOBALS['PHP_AUTH_USER'] = $this->blowfishDecrypt(
  418. $_COOKIE['pmaUser-' . $GLOBALS['server']],
  419. $this->_getBlowfishSecret()
  420. );
  421. // user was never logged in since session start
  422. if (empty($_SESSION['last_access_time'])) {
  423. return false;
  424. }
  425. // User inactive too long
  426. $last_access_time = time() - $GLOBALS['cfg']['LoginCookieValidity'];
  427. if ($_SESSION['last_access_time'] < $last_access_time
  428. ) {
  429. PMA_Util::cacheUnset('is_create_db_priv', null);
  430. PMA_Util::cacheUnset('is_process_priv', null);
  431. PMA_Util::cacheUnset('is_reload_priv', null);
  432. PMA_Util::cacheUnset('db_to_create', null);
  433. PMA_Util::cacheUnset('dbs_where_create_table_allowed', null);
  434. $GLOBALS['no_activity'] = true;
  435. $this->authFails();
  436. if (! defined('TESTSUITE')) {
  437. exit;
  438. } else {
  439. return false;
  440. }
  441. }
  442. // check password cookie
  443. if (empty($_COOKIE['pmaPass-' . $GLOBALS['server']])) {
  444. return false;
  445. }
  446. $GLOBALS['PHP_AUTH_PW'] = $this->blowfishDecrypt(
  447. $_COOKIE['pmaPass-' . $GLOBALS['server']],
  448. $this->_getBlowfishSecret()
  449. );
  450. if ($GLOBALS['PHP_AUTH_PW'] == "\xff(blank)") {
  451. $GLOBALS['PHP_AUTH_PW'] = '';
  452. }
  453. $GLOBALS['from_cookie'] = true;
  454. return true;
  455. }
  456. /**
  457. * Set the user and password after last checkings if required
  458. *
  459. * @return boolean always true
  460. */
  461. public function authSetUser()
  462. {
  463. global $cfg;
  464. // Ensures valid authentication mode, 'only_db', bookmark database and
  465. // table names and relation table name are used
  466. if ($cfg['Server']['user'] != $GLOBALS['PHP_AUTH_USER']) {
  467. foreach ($cfg['Servers'] as $idx => $current) {
  468. if ($current['host'] == $cfg['Server']['host']
  469. && $current['port'] == $cfg['Server']['port']
  470. && $current['socket'] == $cfg['Server']['socket']
  471. && $current['ssl'] == $cfg['Server']['ssl']
  472. && $current['connect_type'] == $cfg['Server']['connect_type']
  473. && $current['user'] == $GLOBALS['PHP_AUTH_USER']
  474. ) {
  475. $GLOBALS['server'] = $idx;
  476. $cfg['Server'] = $current;
  477. break;
  478. }
  479. } // end foreach
  480. } // end if
  481. if ($GLOBALS['cfg']['AllowArbitraryServer']
  482. && ! empty($GLOBALS['pma_auth_server'])
  483. ) {
  484. /* Allow to specify 'host port' */
  485. $parts = explode(' ', $GLOBALS['pma_auth_server']);
  486. if (count($parts) == 2) {
  487. $tmp_host = $parts[0];
  488. $tmp_port = $parts[1];
  489. } else {
  490. $tmp_host = $GLOBALS['pma_auth_server'];
  491. $tmp_port = '';
  492. }
  493. if ($cfg['Server']['host'] != $GLOBALS['pma_auth_server']) {
  494. $cfg['Server']['host'] = $tmp_host;
  495. if (! empty($tmp_port)) {
  496. $cfg['Server']['port'] = $tmp_port;
  497. }
  498. }
  499. unset($tmp_host, $tmp_port, $parts);
  500. }
  501. $cfg['Server']['user'] = $GLOBALS['PHP_AUTH_USER'];
  502. $cfg['Server']['password'] = $GLOBALS['PHP_AUTH_PW'];
  503. // Avoid showing the password in phpinfo()'s output
  504. unset($GLOBALS['PHP_AUTH_PW']);
  505. unset($_SERVER['PHP_AUTH_PW']);
  506. $_SESSION['last_access_time'] = time();
  507. $this->createBlowfishIV();
  508. // Name and password cookies need to be refreshed each time
  509. // Duration = one month for username
  510. $GLOBALS['PMA_Config']->setCookie(
  511. 'pmaUser-' . $GLOBALS['server'],
  512. $this->blowfishEncrypt(
  513. $cfg['Server']['user'],
  514. $this->_getBlowfishSecret()
  515. )
  516. );
  517. // Duration = as configured
  518. $GLOBALS['PMA_Config']->setCookie(
  519. 'pmaPass-' . $GLOBALS['server'],
  520. $this->blowfishEncrypt(
  521. ! empty($cfg['Server']['password'])
  522. ? $cfg['Server']['password'] : "\xff(blank)",
  523. $this->_getBlowfishSecret()
  524. ),
  525. null,
  526. $GLOBALS['cfg']['LoginCookieStore']
  527. );
  528. // Set server cookies if required (once per session) and, in this case,
  529. // force reload to ensure the client accepts cookies
  530. if (! $GLOBALS['from_cookie']) {
  531. if ($GLOBALS['cfg']['AllowArbitraryServer']) {
  532. if (! empty($GLOBALS['pma_auth_server'])) {
  533. // Duration = one month for servername
  534. $GLOBALS['PMA_Config']->setCookie(
  535. 'pmaServer-' . $GLOBALS['server'],
  536. $cfg['Server']['host']
  537. );
  538. } else {
  539. // Delete servername cookie
  540. $GLOBALS['PMA_Config']->removeCookie(
  541. 'pmaServer-' . $GLOBALS['server']
  542. );
  543. }
  544. }
  545. // URL where to go:
  546. $redirect_url = $cfg['PmaAbsoluteUri'] . 'index.php';
  547. // any parameters to pass?
  548. $url_params = array();
  549. if (strlen($GLOBALS['db'])) {
  550. $url_params['db'] = $GLOBALS['db'];
  551. }
  552. if (strlen($GLOBALS['table'])) {
  553. $url_params['table'] = $GLOBALS['table'];
  554. }
  555. // any target to pass?
  556. if (! empty($GLOBALS['target'])
  557. && $GLOBALS['target'] != 'index.php'
  558. ) {
  559. $url_params['target'] = $GLOBALS['target'];
  560. }
  561. /**
  562. * Clear user cache.
  563. */
  564. PMA_Util::clearUserCache();
  565. PMA_Response::getInstance()->disable();
  566. PMA_sendHeaderLocation(
  567. $redirect_url . PMA_URL_getCommon($url_params, '&'),
  568. true
  569. );
  570. if (! defined('TESTSUITE')) {
  571. exit;
  572. } else {
  573. return false;
  574. }
  575. } // end if
  576. return true;
  577. }
  578. /**
  579. * User is not allowed to login to MySQL -> authentication failed
  580. *
  581. * prepares error message and switches to auth() which display the error
  582. * and the login form
  583. *
  584. * this function MUST exit/quit the application,
  585. * currently doen by call to auth()
  586. *
  587. * @return void
  588. */
  589. public function authFails()
  590. {
  591. global $conn_error;
  592. // Deletes password cookie and displays the login form
  593. $GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $GLOBALS['server']);
  594. if (! empty($GLOBALS['login_without_password_is_forbidden'])) {
  595. $conn_error = __(
  596. 'Login without a password is forbidden by configuration'
  597. . ' (see AllowNoPassword)'
  598. );
  599. } elseif (! empty($GLOBALS['allowDeny_forbidden'])) {
  600. $conn_error = __('Access denied!');
  601. } elseif (! empty($GLOBALS['no_activity'])) {
  602. $conn_error = sprintf(
  603. __('No activity within %s seconds; please log in again.'),
  604. $GLOBALS['cfg']['LoginCookieValidity']
  605. );
  606. } elseif ($GLOBALS['dbi']->getError()) {
  607. $conn_error = '#' . $GLOBALS['errno'] . ' '
  608. . __('Cannot log in to the MySQL server');
  609. } else {
  610. $conn_error = __('Cannot log in to the MySQL server');
  611. }
  612. // needed for PHP-CGI (not need for FastCGI or mod-php)
  613. header('Cache-Control: no-store, no-cache, must-revalidate');
  614. header('Pragma: no-cache');
  615. $this->auth();
  616. }
  617. /**
  618. * Returns blowfish secret or generates one if needed.
  619. *
  620. * @return string
  621. */
  622. private function _getBlowfishSecret()
  623. {
  624. if (empty($GLOBALS['cfg']['blowfish_secret'])) {
  625. if (empty($_SESSION['auto_blowfish_secret'])) {
  626. // this returns 23 characters
  627. $_SESSION['auto_blowfish_secret'] = uniqid('', true);
  628. }
  629. return $_SESSION['auto_blowfish_secret'];
  630. } else {
  631. // apply md5() to work around too long secrets (returns 32 characters)
  632. return md5($GLOBALS['cfg']['blowfish_secret']);
  633. }
  634. }
  635. /**
  636. * Encryption using blowfish algorithm (mcrypt)
  637. * or phpseclib's AES if mcrypt not available
  638. *
  639. * @param string $data original data
  640. * @param string $secret the secret
  641. *
  642. * @return string the encrypted result
  643. */
  644. public function blowfishEncrypt($data, $secret)
  645. {
  646. if (! function_exists('mcrypt_encrypt')) {
  647. /**
  648. * This library uses mcrypt when available, so
  649. * we could always call it instead of having an
  650. * if/then/else logic, however the include_once
  651. * call is costly
  652. */
  653. include_once PHPSECLIB_INC_DIR . '/Crypt/AES.php';
  654. $cipher = new Crypt_AES(CRYPT_AES_MODE_ECB);
  655. $cipher->setKey($secret);
  656. return base64_encode($cipher->encrypt($data));
  657. } else {
  658. return base64_encode(
  659. mcrypt_encrypt(
  660. MCRYPT_BLOWFISH,
  661. $secret,
  662. $data,
  663. MCRYPT_MODE_CBC,
  664. $this->_blowfish_iv
  665. )
  666. );
  667. }
  668. }
  669. /**
  670. * Decryption using blowfish algorithm (mcrypt)
  671. * or phpseclib's AES if mcrypt not available
  672. *
  673. * @param string $encdata encrypted data
  674. * @param string $secret the secret
  675. *
  676. * @return string original data
  677. */
  678. public function blowfishDecrypt($encdata, $secret)
  679. {
  680. if (is_null($this->_blowfish_iv)) {
  681. $this->_blowfish_iv = base64_decode($_COOKIE['pma_mcrypt_iv'], true);
  682. }
  683. if (! function_exists('mcrypt_encrypt')) {
  684. include_once PHPSECLIB_INC_DIR . '/Crypt/AES.php';
  685. $cipher = new Crypt_AES(CRYPT_AES_MODE_ECB);
  686. $cipher->setKey($secret);
  687. return $cipher->decrypt(base64_decode($encdata));
  688. } else {
  689. $data = base64_decode($encdata);
  690. $decrypted = mcrypt_decrypt(
  691. MCRYPT_BLOWFISH,
  692. $secret,
  693. $data,
  694. MCRYPT_MODE_CBC,
  695. $this->_blowfish_iv
  696. );
  697. return trim($decrypted);
  698. }
  699. }
  700. /**
  701. * Initialization
  702. * Store the initialization vector because it will be needed for
  703. * further decryption. I don't think necessary to have one iv
  704. * per server so I don't put the server number in the cookie name.
  705. *
  706. * @return void
  707. */
  708. public function createBlowfishIV()
  709. {
  710. if (function_exists('mcrypt_encrypt')) {
  711. $td = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_CBC, '');
  712. if ($td === false) {
  713. PMA_fatalError(__('Failed to use Blowfish from mcrypt!'));
  714. }
  715. $this->_blowfish_iv = mcrypt_create_iv(
  716. mcrypt_enc_get_iv_size($td),
  717. MCRYPT_DEV_URANDOM
  718. );
  719. } else {
  720. /*
  721. * We don't use this value without mcrypt, but let's set it
  722. * so that we don't have to check conditionally for it.
  723. */
  724. $this->_blowfish_iv = 'dummy';
  725. }
  726. $GLOBALS['PMA_Config']->setCookie(
  727. 'pma_mcrypt_iv',
  728. base64_encode($this->_blowfish_iv)
  729. );
  730. }
  731. /**
  732. * Sets Blowfis IV to use
  733. *
  734. * @param string $vector The IV
  735. *
  736. * @return void
  737. */
  738. public function setBlowfishIv($vector)
  739. {
  740. $this->_blowfish_iv = $vector;
  741. }
  742. /**
  743. * This method is called when any PluginManager to which the observer
  744. * is attached calls PluginManager::notify()
  745. *
  746. * @param SplSubject $subject The PluginManager notifying the observer
  747. * of an update.
  748. *
  749. * @return void
  750. */
  751. public function update (SplSubject $subject)
  752. {
  753. }
  754. }