Merge remote-tracking branch 'security/QA_4_6-security' into QA_4_6

This commit is contained in:
Isaac Bennetch 2016-08-16 16:34:37 -04:00
commit 0f6b76b578
101 changed files with 1029 additions and 1668 deletions

View File

@ -3,7 +3,7 @@ imports:
- javascript
- php
filter:
excluded_paths: [libraries/php-gettext/*, libraries/tcpdf/*, libraries/bfShapeFiles/*, libraries/phpseclib/*, libraries/plugins/auth/recaptchalib.php, libraries/plugins/auth/swekey/swekey.php, libraries/sql-formatter/*, js/jquery/*, js/jqplot/*, js/openlayers/*, js/codemirror/*, js/canvg/*, js/tracekit/*, js/OpenStreetMap.js, js/sprintf.js, test/libraries/php-gettext/*, test/libraries/sql-formatter/*]
excluded_paths: [libraries/php-gettext/*, libraries/tcpdf/*, libraries/bfShapeFiles/*, libraries/phpseclib/*, libraries/plugins/auth/recaptchalib.php, libraries/sql-formatter/*, js/jquery/*, js/jqplot/*, js/openlayers/*, js/codemirror/*, js/canvg/*, js/tracekit/*, js/OpenStreetMap.js, js/sprintf.js, test/libraries/php-gettext/*, test/libraries/sql-formatter/*]
tools:
php_code_sniffer:
config:

View File

@ -55,7 +55,7 @@
<arg line="${source_comma_sep}
xml
codesize,design,naming,unusedcode
--exclude test,build,tcpdf,php-gettext,bfShapeFiles,phpseclib,recaptchalib.php,swekey.php,vendor,sql-parser
--exclude test,build,tcpdf,php-gettext,bfShapeFiles,phpseclib,recaptchalib.php,vendor,sql-parser
--reportfile '${basedir}/build/logs/pmd.xml'" />
</exec>
</target>
@ -71,7 +71,6 @@
--exclude libraries/bfShapeFiles
--exclude libraries/phpseclib
--exclude libraries/plugins/auth/recaptcha/recaptchalib.php
--exclude libraries/plugins/auth/swekey/swekey.php
--exclude libraries/sql-parser
${source}" />
</exec>
@ -88,7 +87,6 @@
--exclude libraries/bfShapeFiles
--exclude libraries/phpseclib
--exclude libraries/plugins/auth/recaptcha/recaptchalib.php
--exclude libraries/plugins/auth/swekey/swekey.php
--exclude libraries/sql-parser
${source}" />
</exec>
@ -103,7 +101,7 @@
<target name="phpcs" description="Generate checkstyle.xml using PHP_CodeSniffer excluding third party libraries" depends="phpcs-config">
<exec executable="phpcs">
<arg line="
--ignore=*/php-gettext/*,*/vendor/*,*/tcpdf/*,*/canvg/*,*/codemirror/*,*/openlayers/*,*/jquery/*,*/jqplot/*,*/build/*,*/bfShapeFiles/*,*/phpseclib/*,*/recaptcha/*,*/swekey/*,*/sql-parser/*
--ignore=*/php-gettext/*,*/vendor/*,*/tcpdf/*,*/canvg/*,*/codemirror/*,*/openlayers/*,*/jquery/*,*/jqplot/*,*/build/*,*/bfShapeFiles/*,*/phpseclib/*,*/recaptcha/*,*/sql-parser/*
--report=checkstyle
--extensions=php
--report-file='${basedir}/build/logs/checkstyle.xml'

View File

@ -13,6 +13,7 @@ require 'libraries/common.inc.php';
$response = PMA\libraries\Response::getInstance();
$response->disable();
$response->getHeader()->sendHttpHeaders();
$filename = CHANGELOG_FILE;
@ -154,6 +155,7 @@ echo '</pre>';
var links = document.getElementsByTagName("a");
for(var i = 0; i < links.length; i++) {
links[i].target = "_blank";
links[i].rel = "noopener noreferrer";
}
</script>
</body>

View File

@ -12,7 +12,7 @@
/**
* This is needed for cookie based authentication to encrypt password in
* cookie
* cookie. Needs to be 32 chars long.
*/
$cfg['blowfish_secret'] = ''; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */
@ -64,8 +64,6 @@ $cfg['Servers'][$i]['AllowNoPassword'] = false;
// $cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
// $cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
// $cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';
/* Contrib / Swekey authentication */
// $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf';
/**
* End of servers configuration

View File

@ -414,15 +414,6 @@ Server connection settings
"phpMyAdmin " and either :config:option:`$cfg['Servers'][$i]['verbose']` or
:config:option:`$cfg['Servers'][$i]['host']` will be used.
.. _servers_auth_swekey_config:
.. config:option:: $cfg['Servers'][$i]['auth_swekey_config']
:type: string
:default: ``''``
The name of the file containing :ref:`swekey` ids and login names for hardware
authentication. Leave empty to deactivate this feature.
.. _servers_user:
.. config:option:: $cfg['Servers'][$i]['user']
@ -1473,7 +1464,10 @@ Cookie authentication options
The "cookie" auth\_type uses AES algorithm to encrypt the password. If you
are using the "cookie" auth\_type, enter here a random passphrase of your
choice. It will be used internally by the AES algorithm: you wont be
prompted for this passphrase. There is no maximum length for this secret.
prompted for this passphrase.
The secret should be 32 characters long. Using shorter will lead to weaker security
of encrypted cookies, using longer will cause no harm.
.. note::
@ -1833,11 +1827,6 @@ Main panel
You can additionally hide more information by using
:config:option:`$cfg['Servers'][$i]['verbose']`.
.. config:option:: $cfg['ShowPhpInfo']
:type: boolean
:default: false
.. config:option:: $cfg['ShowChgPassword']
:type: boolean
@ -1848,18 +1837,11 @@ Main panel
:type: boolean
:default: true
Defines whether to display the :guilabel:`PHP information` and
Defines whether to display the
:guilabel:`Change password` links and form for creating database or not at
the starting main (right) frame. This setting does not check MySQL commands
entered directly.
Please note that to block the usage of ``phpinfo()`` in scripts, you have to
put this in your :file:`php.ini`:
.. code-block:: ini
disable_functions = phpinfo()
Also note that enabling the :guilabel:`Change password` link has no effect
with config authentication mode: because of the hard coded password value
in the configuration file, end users can't be allowed to change their

View File

@ -248,7 +248,8 @@ simple configuration may look like this:
<?php
$cfg['blowfish_secret'] = 'ba17c1ec07d65003'; // use here a value of your choice
// use here a value of your choice at least 32 chars long
$cfg['blowfish_secret'] = '1{dd0`<Q),5XP_:R9UK%%8\"EEcyH#{o';
$i=0;
$i++;
@ -738,40 +739,6 @@ Config authentication mode
of which are beyond the scope of this manual but easily searchable
with Google).
.. index:: pair: Swekey; Authentication mode
.. _swekey:
Swekey authentication mode
--------------------------
The Swekey is a low cost authentication USB key that can be used in
web applications. When Swekey authentication is activated, phpMyAdmin
requires the users's Swekey to be plugged before entering the login
page (currently supported for cookie authentication mode only). Swekey
Authentication is disabled by default. To enable it, add the following
line to :file:`config.inc.php`:
.. code-block:: php
$cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey.conf';
You then have to create the ``swekey.conf`` file that will associate
each user with their Swekey Id. It is important to place this file
outside of your web server's document root (in the example, it is
located in ``/etc``). Feel free to use it with your own users'
information. If you want to purchase a Swekey please visit
`https://www.phpmyadmin.net/auth\_key/ <https://www.phpmyadmin.net/auth_key/>`_
since this link provides funding for phpMyAdmin.
A self documented sample file is provided in the
file :file:`examples/swekey.sample.conf`:
.. literalinclude:: ../examples/swekey.sample.conf
:language: sh
.. seealso:: :config:option:`$cfg['Servers'][$i]['auth_swekey_config']`
Securing your phpMyAdmin installation
+++++++++++++++++++++++++++++++++++++

View File

@ -74,11 +74,11 @@ function Die_error($e)
/* Need to have cookie visible from parent directory */
session_set_cookie_params(0, '/', '', false);
session_set_cookie_params(0, '/', '', true, true);
/* Create signon session */
$session_name = 'SignonSession';
session_name($session_name);
session_start();
@session_start();
// Determine realm and return_to
$base = 'http';

View File

@ -12,13 +12,13 @@
*/
/* Need to have cookie visible from parent directory */
session_set_cookie_params(0, '/', '', false);
session_set_cookie_params(0, '/', '', true, true);
/* Create signon session */
$session_name = 'SignonSession';
session_name($session_name);
// Uncomment and change the following line to match your $cfg['SessionSavePath']
//session_save_path('/foobar');
session_start();
@session_start();
/* Was data posted? */
if (isset($_POST['user'])) {
@ -31,7 +31,7 @@ if (isset($_POST['user'])) {
$_SESSION['PMA_single_signon_cfgupdate'] = array('verbose' => 'Signon test');
$id = session_id();
/* Close that session */
session_write_close();
@session_write_close();
/* Redirect to phpMyAdmin (should use absolute URL here!) */
header('Location: ../index.php');
} else {

View File

@ -1,44 +0,0 @@
# This is a typical file used to enable Swekey hardware authentication.
#
# To activate the Swekey authentication add the following line to your config.inc.php file.
# $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf';
# Then rename this file "swekey-pma.conf" and copy it to the /etc directory.
# Add all the Swekey ids you want to grant access to in the file.
# After each Swekey id put the corresponding user name.
#
# If you don't know the id of a Swekey just visit http://www.swekey.com?sel=support
# while your Swekey is connected.
#
# If you need to purchase a Swekey please visit https://www.phpmyadmin.net/auth_key/
# since this link provides funding to PhpMyAdmin.
#
0000000000000000000000000000763A:root
000000000000000000000000000089E4:steve
0000000000000000000000000000231E:scott
#
# It is recommended to include the following lines to contact the
# authentication servers in SSL mode.
#
SERVER_CHECK=https://auth-check-ssl.musbe.net
SERVER_RNDTOKEN=https://auth-rnd-gen-ssl.musbe.net
SERVER_STATUS=https://auth-status-ssl.musbe.net
#
# The path of the root certificate file used to ensure a secure
# communication with the authentication servers in SSL mode.
# If not specified, will use musbe-ca.crt found in your
# phpMyAdmin/libraries/auth/swekey.
#
#CA_FILE=/var/http-root/phpmyadmin/libraries/auth/swekey/musbe-ca.crt
#
# If your server receives many login requests, you can enable the random
# token caching to accelerate the authentication process.
# Token caching is enabled by default.
#
#ENABLE_TOKEN_CACHE=0

View File

@ -10,59 +10,7 @@
define('PMA_MINIMUM_COMMON', true);
require_once 'libraries/common.inc.php';
/* For chart exporting */
if (isset($_REQUEST['filename']) && isset($_REQUEST['image'])) {
$allowed = array(
'image/png' => 'png',
'image/svg+xml' => 'svg',
);
/* Check whether MIME type is allowed */
if (! isset($allowed[$_REQUEST['type']])) {
PMA_fatalError(__('Invalid export type'));
}
/*
* Check file name to match mime type and not contain new lines
* to prevent response splitting.
*/
$extension = $allowed[$_REQUEST['type']];
$valid_match = '/^[^\n\r]*\.' . $extension . '$/';
if (! preg_match($valid_match, $_REQUEST['filename'])) {
if (! preg_match('/^[^\n\r]*$/', $_REQUEST['filename'])) {
/* Filename is unsafe, discard it */
$filename = 'download.' . $extension;
} else {
/* Add extension */
$filename = $_REQUEST['filename'] . '.' . $extension;
}
} else {
/* Filename from request should be safe here */
$filename = $_REQUEST['filename'];
}
/* Decode data */
if ($extension != 'svg') {
$data = mb_substr(
$_REQUEST['image'],
mb_strpos($_REQUEST['image'], ',') + 1
);
$data = base64_decode($data);
} else {
$data = $_REQUEST['image'];
}
/* Send download header */
PMA_downloadHeader(
$filename,
$_REQUEST['type'],
strlen($data)
);
/* Send data */
echo $data;
} else if (isset($_REQUEST['monitorconfig'])) {
if (isset($_REQUEST['monitorconfig'])) {
/* For monitor chart config export */
PMA_downloadHeader('monitor.cfg', 'application/json; charset=UTF-8');
header('X-Content-Type-Options: nosniff');

View File

@ -7,6 +7,11 @@
*/
use PMA\libraries\plugins\ImportPlugin;
/* Enable LOAD DATA LOCAL INFILE for LDI plugin */
if (isset($_POST['format']) && $_POST['format'] == 'ldi') {
define('PMA_ENABLE_LDI', 1);
}
/**
* Get the variables sent or posted to this script and a core script
*/
@ -435,6 +440,15 @@ if (! empty($local_import_file) && ! empty($cfg['UploadDir'])) {
$import_file = PMA\libraries\Util::userDir($cfg['UploadDir'])
. $local_import_file;
/*
* Do not allow symlinks to avoid security issues
* (user can create symlink to file he can not access,
* but phpMyAdmin can).
*/
if (@is_link($import_file)) {
$import_file = 'none';
}
} elseif (empty($import_file) || ! is_uploaded_file($import_file)) {
$import_file = 'none';
}

View File

@ -317,7 +317,7 @@ if ($server > 0 && $GLOBALS['cfg']['ShowServerInfo']) {
. ' </div>';
}
if ($GLOBALS['cfg']['ShowServerInfo'] || $GLOBALS['cfg']['ShowPhpInfo']) {
if ($GLOBALS['cfg']['ShowServerInfo']) {
echo '<div class="group">';
echo '<h2>' , __('Web server') , '</h2>';
echo '<ul>';
@ -357,15 +357,6 @@ if ($GLOBALS['cfg']['ShowServerInfo'] || $GLOBALS['cfg']['ShowPhpInfo']) {
}
}
if ($cfg['ShowPhpInfo']) {
PMA_printListItem(
__('Show PHP information'),
'li_phpinfo',
'phpinfo.php' . $common_url_query,
null,
'_blank'
);
}
echo ' </ul>';
echo ' </div>';
}
@ -519,15 +510,23 @@ if ($GLOBALS['cfg']['LoginCookieStore'] != 0
/**
* Check if user does not have defined blowfish secret and it is being used.
*/
if (! empty($_SESSION['encryption_key'])
&& empty($GLOBALS['cfg']['blowfish_secret'])
) {
trigger_error(
__(
'The configuration file now needs a secret passphrase (blowfish_secret).'
),
E_USER_WARNING
);
if (! empty($_SESSION['encryption_key'])) {
if (empty($GLOBALS['cfg']['blowfish_secret'])) {
trigger_error(
__(
'The configuration file now needs a secret passphrase (blowfish_secret).'
),
E_USER_WARNING
);
}
if (strlen($GLOBALS['cfg']['blowfish_secret']) < 32) {
trigger_error(
__(
'The secret passphrase in configuration (blowfish_secret) is too short.'
),
E_USER_WARNING
);
}
}
/**

View File

@ -4105,7 +4105,16 @@ AJAX.registerOnload('functions.js', function () {
* Load version information asynchronously.
*/
if ($('li.jsversioncheck').length > 0) {
$.getJSON('version_check.php', {'server' : PMA_commonParams.get('server')}, PMA_current_version);
$.ajax({
dataType: "json",
url: 'version_check.php',
method: "POST",
data: {
"server": PMA_commonParams.get('server'),
"token": PMA_commonParams.get('token'),
},
success: PMA_current_version
});
}
if ($('#is_git_revision').length > 0) {

View File

@ -23,7 +23,7 @@ function setDropdownValues($dropdown, values, selectedValue) {
// add an empty string to the beginning for empty selection
values.unshift('');
$.each(values, function () {
optionsAsString += "<option value='" + this + "'" + (selectedValue == this ? " selected='selected'" : "") + ">" + this + "</option>";
optionsAsString += "<option value='" + escapeHtml(this) + "'" + (selectedValue == this ? " selected='selected'" : "") + ">" + escapeHtml(this) + "</option>";
});
$dropdown.append($(optionsAsString));
}

View File

@ -353,10 +353,10 @@ class DbSearch
$html_output .= '<td><a name="delete_search" class="ajax" href="'
. $delete_result_path . '" onclick="deleteResult(\''
. $delete_result_path . '\' , \''
. sprintf(
. PMA_escapeJsString(sprintf(
__('Delete the matches for the %s table?'),
htmlspecialchars($each_table)
)
))
. '\');return false;">'
. __('Delete') . '</a></td>';
} else {

View File

@ -117,12 +117,17 @@ class Error extends Message
{
$result = array();
$members = array('file', 'line', 'function', 'class', 'type');
$members = array('line', 'function', 'class', 'type');
foreach ($backtrace as $idx => $step) {
/* Create new backtrace entry */
$result[$idx] = array();
/* Make path relative */
if (isset($step['file'])) {
$result[$idx]['file'] = Error::relPath($step['file']);
}
/* Store members we want */
foreach ($members as $name) {
if (isset($step[$name])) {

View File

@ -420,6 +420,11 @@ class File
$this->setName(
Util::userDir($GLOBALS['cfg']['UploadDir']) . PMA_securePath($name)
);
if (@is_link($this->getName())) {
$this->_error_message = __('File is a symbolic link');
$this->setName(null);
return false;
}
if (! $this->isReadable()) {
$this->_error_message = __('File could not be read!');
$this->setName(null);

View File

@ -96,7 +96,7 @@ class RecentFavoriteTable
// Read from phpMyAdmin database, if recent tables is not in session
$sql_query
= " SELECT `tables` FROM " . $this->_getPmaTable() .
" WHERE `username` = '" . $GLOBALS['cfg']['Server']['user'] . "'";
" WHERE `username` = '" . Util::sqlAddSlashes($GLOBALS['cfg']['Server']['user']) . "'";
$return = array();
$result = PMA_queryAsControlUser($sql_query, false);
@ -119,7 +119,7 @@ class RecentFavoriteTable
$username = $GLOBALS['cfg']['Server']['user'];
$sql_query
= " REPLACE INTO " . $this->_getPmaTable() . " (`username`, `tables`)" .
" VALUES ('" . $username . "', '"
" VALUES ('" . Util::sqlAddSlashes($username) . "', '"
. Util::sqlAddSlashes(
json_encode($this->_tables)
) . "')";

View File

@ -60,6 +60,13 @@ class Response
* @var bool
*/
private $_isAjax;
/**
* Whether response object is disabled
*
* @access private
* @var bool
*/
private $_isDisabled;
/**
* Whether we are servicing an ajax request for a page
* that was fired using the generic page handler in JS.
@ -102,6 +109,7 @@ class Response
$this->_isSuccess = true;
$this->_isAjax = false;
$this->_isAjaxPage = false;
$this->_isDisabled = false;
if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) {
$this->_isAjax = true;
}
@ -174,6 +182,7 @@ class Response
{
$this->_header->disable();
$this->_footer->disable();
$this->_isDisabled = true;
}
/**
@ -277,6 +286,12 @@ class Response
*/
private function _ajaxResponse()
{
/* Avoid wrapping in case we're disabled */
if ($this->_isDisabled) {
echo $this->_getDisplay();
return;
}
if (! isset($this->_JSON['message'])) {
$this->_JSON['message'] = $this->_getDisplay();
} else if ($this->_JSON['message'] instanceof Message) {

View File

@ -1494,7 +1494,7 @@ class Table
// Read from phpMyAdmin database
$sql_query = " SELECT `prefs` FROM " . $pma_table
. " WHERE `username` = '" . $GLOBALS['cfg']['Server']['user'] . "'"
. " WHERE `username` = '" . Util::sqlAddSlashes($GLOBALS['cfg']['Server']['user']) . "'"
. " AND `db_name` = '" . Util::sqlAddSlashes($this->_db_name) . "'"
. " AND `table_name` = '" . Util::sqlAddSlashes($this->_name) . "'";
@ -1522,7 +1522,7 @@ class Table
$username = $GLOBALS['cfg']['Server']['user'];
$sql_query = " REPLACE INTO " . $pma_table
. " (username, db_name, table_name, prefs) VALUES ('"
. $username . "', '" . $secureDbName
. Util::sqlAddSlashes($username) . "', '" . $secureDbName
. "', '" . Util::sqlAddSlashes($this->_name) . "', '"
. Util::sqlAddSlashes(json_encode($this->uiprefs)) . "')";

View File

@ -2691,7 +2691,7 @@ class Util
$dir .= '/';
}
return str_replace('%u', $GLOBALS['cfg']['Server']['user'], $dir);
return str_replace('%u', PMA_securePath($GLOBALS['cfg']['Server']['user']), $dir);
}
/**

View File

@ -51,20 +51,7 @@ class VersionInformation
session_write_close();
}
$file = 'https://www.phpmyadmin.net/home_page/version.json';
if (ini_get('allow_url_fopen')) {
$context = array(
'http' => array(
'request_fulluri' => true,
'timeout' => $connection_timeout,
)
);
$context = Util::handleContext($context);
$response = file_get_contents(
$file,
false,
stream_context_create($context)
);
} else if (function_exists('curl_init')) {
if (function_exists('curl_init')) {
$curl_handle = curl_init($file);
if ($curl_handle === false) {
return null;
@ -86,6 +73,19 @@ class VersionInformation
$connection_timeout
);
$response = curl_exec($curl_handle);
} else if (ini_get('allow_url_fopen')) {
$context = array(
'http' => array(
'request_fulluri' => true,
'timeout' => $connection_timeout,
)
);
$context = Util::handleContext($context);
$response = file_get_contents(
$file,
false,
stream_context_create($context)
);
}
}

View File

@ -309,7 +309,6 @@ $goto_whitelist = array(
'index.php',
'pdf_pages.php',
'pdf_schema.php',
//'phpinfo.php',
'server_binlog.php',
'server_collations.php',
'server_databases.php',

View File

@ -236,14 +236,6 @@ $cfg['Servers'][$i]['auth_type'] = 'cookie';
*/
$cfg['Servers'][$i]['auth_http_realm'] = '';
/**
* File containing Swekey ids and login names (see /contrib);
* leave empty to deactivate Swekey hardware authentication
*
* @global string $cfg['Servers'][$i]['auth_swekey_config']
*/
$cfg['Servers'][$i]['auth_swekey_config'] = '';
/**
* MySQL user
*
@ -1046,13 +1038,6 @@ $cfg['NavigationTreeShowEvents'] = true;
*/
$cfg['ShowStats'] = true;
/**
* show PHP info link
*
* @global boolean $cfg['ShowPhpInfo']
*/
$cfg['ShowPhpInfo'] = false;
/**
* show MySQL server and web server information
*

View File

@ -214,10 +214,22 @@ class ServerConfigChecks
$blowfishSecret, $cookieAuthServer, $blowfishSecretSet
) {
if ($cookieAuthServer && $blowfishSecret === null) {
$blowfishSecret = uniqid('', true);
$blowfishSecret = '';
if (! function_exists('openssl_random_pseudo_bytes')) {
$random_func = 'phpseclib\\Crypt\\Random::string';
} else {
$random_func = 'openssl_random_pseudo_bytes';
}
while (strlen($blowfishSecret) < 32) {
$byte = $random_func(1);
// We want only ASCII chars
if (ord($byte) > 32 && ord($byte) < 127) {
$blowfishSecret .= $byte;
}
}
$blowfishSecretSet = true;
$this->cfg->set('blowfish_secret', $blowfishSecret);
return array($blowfishSecret, $blowfishSecretSet);
}
return array($blowfishSecret, $blowfishSecretSet);
}
@ -329,10 +341,10 @@ class ServerConfigChecks
} else {
$blowfishWarnings = array();
// check length
if (mb_strlen($blowfishSecret) < 8) {
if (strlen($blowfishSecret) < 32) {
// too short key
$blowfishWarnings[] = __(
'Key is too short, it should have at least 8 characters.'
'Key is too short, it should have at least 32 characters.'
);
}
// check used characters

View File

@ -183,6 +183,7 @@ class Validator
) {
// static::testPHPErrorMsg();
$error = null;
$host = PMA_sanitizeMySQLHost($host);
if (DatabaseInterface::checkDbExtension('mysqli')) {
$socket = empty($socket) || $connect_type == 'tcp' ? null : $socket;

View File

@ -632,12 +632,6 @@ $strConfigServers_SessionTimeZone_desc = __(
$strConfigServers_auth_http_realm_desc
= __('HTTP Basic Auth Realm name to display when doing HTTP Auth.');
$strConfigServers_auth_http_realm_name = __('HTTP Realm');
$strConfigServers_auth_swekey_config_desc = __(
'The path for the config file for SweKey hardware '
. 'authentication (not located in your document root; suggested: '
. '/etc/swekey.conf).'
);
$strConfigServers_auth_swekey_config_name = __('SweKey config file');
$strConfigServers_auth_type_desc = __('Authentication method to use.');
$strConfigServers_auth_type_name = __('Authentication type');
$strConfigServers_bookmarktable_desc = __(
@ -871,11 +865,6 @@ $strConfigShowFunctionFields_desc = __(
$strConfigShowFunctionFields_name = __('Show function fields');
$strConfigShowHint_desc = __('Whether to show hint or not.');
$strConfigShowHint_name = __('Show hint');
$strConfigShowPhpInfo_desc = __(
'Shows link to [a@https://php.net/manual/function.phpinfo.php]phpinfo()[/a] ' .
'output.'
);
$strConfigShowPhpInfo_name = __('Show phpinfo() link');
$strConfigShowServerInfo_name = __('Show detailed MySQL server information');
$strConfigShowSQL_desc = __(
'Defines whether SQL queries generated by phpMyAdmin should be displayed.'

View File

@ -41,9 +41,6 @@ $forms['Servers']['Server_auth'] = array('Servers' => array(1 => array(
'user',
'password',
':group:end',
':group:' . __('Cookie authentication'),
'auth_swekey_config' => './swekey.conf',
':group:end',
':group:' . __('HTTP authentication'),
'auth_http_realm',
':group:end',
@ -206,7 +203,6 @@ $forms['Main_panel']['Startup'] = array(
'ShowCreateDb',
'ShowStats',
'ShowServerInfo',
'ShowPhpInfo',
'ShowChgPassword');
$forms['Main_panel']['DbStructure'] = array(
'ShowDbStructureComment',

View File

@ -510,11 +510,6 @@ function PMA_sendHeaderLocation($uri, $use_refresh = false)
session_write_close();
if ($response->headersSent()) {
if (function_exists('debug_print_backtrace')) {
echo '<pre>';
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
echo '</pre>';
}
trigger_error(
'PMA_sendHeaderLocation called when headers are already sent!',
E_USER_ERROR
@ -759,6 +754,10 @@ function PMA_linkURL($url)
function PMA_isAllowedDomain($url)
{
$arr = parse_url($url);
// Avoid URLs without hostname or with credentials
if (empty($arr['host']) || ! empty($arr['user']) || ! empty($arr['pass'])) {
return false;
}
$domain = $arr["host"];
$domainWhiteList = array(
/* Include current domain */
@ -985,3 +984,135 @@ if(! function_exists('hash_equals')) {
return ! $ret;
}
}
/* Compatibility with PHP < 5.1 or PHP without hash extension */
if (! function_exists('hash_hmac')) {
function hash_hmac($algo, $data, $key, $raw_output = false)
{
$algo = strtolower($algo);
$pack = 'H'.strlen($algo('test'));
$size = 64;
$opad = str_repeat(chr(0x5C), $size);
$ipad = str_repeat(chr(0x36), $size);
if (strlen($key) > $size) {
$key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
} else {
$key = str_pad($key, $size, chr(0x00));
}
for ($i = 0; $i < strlen($key) - 1; $i++) {
$opad[$i] = $opad[$i] ^ $key[$i];
$ipad[$i] = $ipad[$i] ^ $key[$i];
}
$output = $algo($opad.pack($pack, $algo($ipad.$data)));
return ($raw_output) ? pack($pack, $output) : $output;
}
}
/**
* Sanitizes MySQL hostname
*
* * strips p: prefix
*
* @param string $name User given hostname
*
* @return string
*/
function PMA_sanitizeMySQLHost($name)
{
if (strtolower(substr($name, 0, 2)) == 'p:') {
return substr($name, 2);
}
return $name;
}
/**
* Safe unserializer wrapper
*
* It does not unserialize data containing objects
*
* @param string $data Data to unserialize
*
* @return mixed
*/
function PMA_safeUnserialize($data)
{
if (! is_string($data)) {
return null;
}
/* validate serialized data */
$length = strlen($data);
$depth = 0;
for ($i = 0; $i < $length; $i++) {
$value = $data[$i];
switch ($value)
{
case '}':
/* end of array */
if ($depth <= 0) {
return null;
}
$depth--;
break;
case 's':
/* string */
// parse sting length
$strlen = intval($data[$i + 2]);
// string start
$i = strpos($data, ':', $i + 2);
if ($i === false) {
return null;
}
// skip string, quotes and ;
$i += 2 + $strlen + 1;
if ($data[$i] != ';') {
return null;
}
break;
case 'b':
case 'i':
case 'd':
/* bool, integer or double */
// skip value to sepearator
$i = strpos($data, ';', $i);
if ($i === false) {
return null;
}
break;
case 'a':
/* array */
// find array start
$i = strpos($data, '{', $i);
if ($i === false) {
return null;
}
// remember nesting
$depth++;
break;
case 'N':
/* null */
// skip to end
$i = strpos($data, ';', $i);
if ($i === false) {
return null;
}
break;
default:
/* any other elements are not wanted */
return null;
}
}
// check unterminated arrays
if ($depth > 0) {
return null;
}
return unserialize($data);
}

View File

@ -445,13 +445,16 @@ function PMA_getTableCreationQuery($db, $table)
function PMA_getNumberOfFieldsFromRequest()
{
if (isset($_REQUEST['submit_num_fields'])) { // adding new fields
$num_fields = $_REQUEST['orig_num_fields'] + $_REQUEST['added_fields'];
$num_fields = min(
4096,
intval($_REQUEST['orig_num_fields']) + intval($_REQUEST['added_fields'])
);
} elseif (isset($_REQUEST['orig_num_fields'])) { // retaining existing fields
$num_fields = $_REQUEST['orig_num_fields'];
$num_fields = min(4096, intval($_REQUEST['orig_num_fields']));
} elseif (isset($_REQUEST['num_fields'])
&& intval($_REQUEST['num_fields']) > 0
) { // new table with specified number of fields
$num_fields = (int) $_REQUEST['num_fields'];
$num_fields = min(4096, intval($_REQUEST['num_fields']));
} else { // new table with unspecified number of fields
$num_fields = 4;
}

View File

@ -90,7 +90,7 @@ function PMA_getPageIdsAndNames($db)
$result = array();
while ($curr_page = $GLOBALS['dbi']->fetchAssoc($page_rs)) {
$result[$curr_page['page_nr']] = $curr_page['page_descr'];
$result[intval($curr_page['page_nr'])] = $curr_page['page_descr'];
}
return $result;
}

View File

@ -124,10 +124,12 @@ class DBIMysql implements DBIExtension
$client_flags = 0;
// always use CLIENT_LOCAL_FILES as defined in mysql_com.h
// for the case where the client library was not compiled
// with --enable-local-infile
$client_flags |= 128;
if (defined('PMA_ENABLE_LDI')) {
// use CLIENT_LOCAL_FILES as defined in mysql_com.h
// for the case where the client library was not compiled
// with --enable-local-infile
$client_flags |= 128;
}
/* Optionally compress connection */
if (defined('MYSQL_CLIENT_COMPRESS') && $cfg['Server']['compress']) {

View File

@ -138,7 +138,11 @@ class DBIMysqli implements DBIExtension
$link = mysqli_init();
mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, true);
if (defined('PMA_ENABLE_LDI')) {
mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, true);
} else {
mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, false);
}
$client_flags = 0;

View File

@ -250,7 +250,7 @@ function PMA_getOptionsForExportTemplates($export_type)
. PMA\libraries\Util::backquote($cfgRelation['export_templates'])
. " WHERE `username` = "
. "'" . PMA\libraries\Util::sqlAddSlashes($GLOBALS['cfg']['Server']['user'])
. "' AND `export_type` = '" . $export_type . "'"
. "' AND `export_type` = '" . PMA\libraries\Util::sqlAddSlashes($export_type) . "'"
. " ORDER BY `template_name`;";
$result = PMA_queryAsControlUser($query);

View File

@ -37,7 +37,7 @@ function PMA_printGitRevision()
'https://github.com/phpmyadmin/phpmyadmin/commit/'
. $GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_COMMITHASH')
)
. '" target="_blank">' . $commit_hash . '</a>';
. '" rel="noopener noreferrer" target="_blank">' . $commit_hash . '</a>';
}
$branch = $GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_BRANCH');
@ -47,7 +47,7 @@ function PMA_printGitRevision()
'https://github.com/phpmyadmin/phpmyadmin/tree/'
. $GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_BRANCH')
)
. '" target="_blank">' . $branch . '</a>';
. '" rel="noopener noreferrer" target="_blank">' . $branch . '</a>';
}
if ($branch !== false) {
$branch = sprintf(__('%1$s from %2$s branch'), $commit_hash, $branch);

View File

@ -182,7 +182,7 @@ class Pbxt extends StorageEngine
. ' can be found on the %sPrimeBase XT Home Page%s.'
),
'<a href="' . PMA_linkURL('https://mariadb.com/kb/en/mariadb/about-pbxt/')
. '" target="_blank">',
. '" rel="noopener noreferrer" target="_blank">',
'</a>'
)
. '</p>' . "\n";

View File

@ -178,7 +178,24 @@ function PMA_sanitizeUrl($url)
function PMA_sendErrorReport($report)
{
$data_string = json_encode($report);
if (ini_get('allow_url_fopen')) {
if (function_exists('curl_init')) {
$curl_handle = curl_init(SUBMISSION_URL);
if ($curl_handle === false) {
return null;
}
$curl_handle = PMA\libraries\Util::configureCurl($curl_handle);
curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt(
$curl_handle, CURLOPT_HTTPHEADER,
array('Expect:', 'Content-Type: application/json')
);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl_handle);
curl_close($curl_handle);
return $response;
} else if (ini_get('allow_url_fopen')) {
$context = array("http" =>
array(
'method' => 'POST',
@ -195,26 +212,7 @@ function PMA_sendErrorReport($report)
return $response;
}
if (!function_exists('curl_init')) {
return null;
}
$curl_handle = curl_init(SUBMISSION_URL);
if ($curl_handle === false) {
return null;
}
$curl_handle = PMA\libraries\Util::configureCurl($curl_handle);
curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt(
$curl_handle, CURLOPT_HTTPHEADER,
array('Expect:', 'Content-Type: application/json')
);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl_handle);
curl_close($curl_handle);
return $response;
return null;
}
/**

View File

@ -26,6 +26,7 @@ function PMA_getDirContent($dir, $expression = '')
}
while ($file = @readdir($handle)) {
if (@is_file($dir . $file)
&& ! @is_link($dir . $file)
&& ($expression == '' || preg_match($expression, $file))
) {
$result[] = $file;

View File

@ -129,11 +129,11 @@ abstract class GISGeometry
. 'bound.extend(new OpenLayers.LonLat('
. $scale_data['minX'] . ', ' . $scale_data['minY']
. ').transform(new OpenLayers.Projection("EPSG:'
. $srid . '"), map.getProjectionObject())); '
. intval($srid) . '"), map.getProjectionObject())); '
. 'bound.extend(new OpenLayers.LonLat('
. $scale_data['maxX'] . ', ' . $scale_data['maxY']
. ').transform(new OpenLayers.Projection("EPSG:'
. $srid . '"), map.getProjectionObject()));';
. intval($srid) . '"), map.getProjectionObject()));';
}
/**
@ -222,7 +222,7 @@ abstract class GISGeometry
// Extract coordinates of the point
$cordinates = explode(" ", $point);
if (isset($cordinates[0]) && trim($cordinates[0]) != ''
if (!empty($cordinates[0]) && trim($cordinates[0]) != ''
&& isset($cordinates[1])
&& trim($cordinates[1]) != ''
) {
@ -231,8 +231,8 @@ abstract class GISGeometry
$y = $scale_data['height']
- ($cordinates[1] - $scale_data['y']) * $scale_data['scale'];
} else {
$x = trim($cordinates[0]);
$y = trim($cordinates[1]);
$x = floatval(trim($cordinates[0]));
$y = floatval(trim($cordinates[1]));
}
} else {
$x = '';
@ -394,6 +394,6 @@ abstract class GISGeometry
{
return '(new OpenLayers.Geometry.Point(' . $point[0] . ',' . $point[1] . '))'
. '.transform(new OpenLayers.Projection("EPSG:'
. $srid . '"), map.getProjectionObject())';
. intval($srid) . '"), map.getProjectionObject())';
}
}

View File

@ -30,14 +30,21 @@ function PMA_getIp()
return $direct_ip;
}
$trusted_header_value
= PMA_getenv($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
$matches = array();
/**
* Parse header in form:
* X-Forwarded-For: client, proxy1, proxy2
*/
// Get header content
$value = PMA_getenv($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
// Grab first element what is client adddress
$value = explode(',', $value)[0];
// Extract IP address
// the $ checks that the header contains only one IP address,
// ?: makes sure the () don't capture
$matches = array();
$is_ip = preg_match(
'|^(?:[0-9]{1,3}\.){3,3}[0-9]{1,3}$|',
$trusted_header_value, $matches
$value, $matches
);
if ($is_ip && (count($matches) == 1)) {
@ -45,8 +52,8 @@ function PMA_getIp()
return $matches[0];
}
/* Return true IP */
return $direct_ip;
// We could not parse header
return false;
} // end of the 'PMA_getIp()' function

View File

@ -174,7 +174,7 @@ class NavigationTree
$query = "SELECT (COUNT(DB_first_level) DIV %d) * %d ";
$query .= "from ( ";
$query .= " SELECT distinct SUBSTRING_INDEX(SCHEMA_NAME, ";
$query .= " '{$GLOBALS['cfg']['NavigationTreeDbSeparator']}', 1) ";
$query .= " '" . Util::sqlAddSlashes($GLOBALS['cfg']['NavigationTreeDbSeparator']) . "', 1) ";
$query .= " DB_first_level ";
$query .= " FROM INFORMATION_SCHEMA.SCHEMATA ";
$query .= " WHERE `SCHEMA_NAME` < '%s' ";

View File

@ -434,7 +434,7 @@ class Node
$query .= "SELECT DB_first_level ";
$query .= "FROM ( ";
$query .= "SELECT DISTINCT SUBSTRING_INDEX(SCHEMA_NAME, ";
$query .= "'$dbSeparator', 1) ";
$query .= "'" . Util::sqlAddSlashes($dbSeparator) . "', 1) ";
$query .= "DB_first_level ";
$query .= "FROM INFORMATION_SCHEMA.SCHEMATA ";
$query .= $this->_getWhereClause('SCHEMA_NAME', $searchClause);
@ -444,9 +444,9 @@ class Node
$query .= ") t2 ";
$query .= $this->_getWhereClause('SCHEMA_NAME', $searchClause);
$query .= "AND 1 = LOCATE(CONCAT(DB_first_level, ";
$query .= "'$dbSeparator'), ";
$query .= "'" . Util::sqlAddSlashes($dbSeparator) . "'), ";
$query .= "CONCAT(SCHEMA_NAME, ";
$query .= "'$dbSeparator')) ";
$query .= "'" . Util::sqlAddSlashes($dbSeparator) . "')) ";
$query .= "ORDER BY SCHEMA_NAME ASC";
$retval = $GLOBALS['dbi']->fetchResult($query);

View File

@ -690,7 +690,7 @@ class NodeDatabase extends Node
. '<a href="navigation.php'
. PMA_URL_getCommon()
. '&showUnhideDialog=true'
. '&dbName=' . urldecode($this->real_name) . '"'
. '&dbName=' . urlencode($this->real_name) . '"'
. ' class="showUnhide ajax">'
. Util::getImage(
'lightbulb.png',

View File

@ -37,7 +37,10 @@ function PMA_getPlugin(
if (is_file($plugins_dir . $file)) {
//include_once $plugins_dir . $file;
$fqnClass = 'PMA\\' . str_replace('/', '\\', $plugins_dir) . $class_name;
return new $fqnClass;
// check if class exists, could be caused by skip_import
if (class_exists($fqnClass)) {
return new $fqnClass;
}
}
return null;

View File

@ -27,11 +27,6 @@ if (! empty($_REQUEST['target'])) {
$GLOBALS['target'] = basename(PMA_getenv('SCRIPT_NAME'));
}
/**
* Swekey authentication functions.
*/
require './libraries/plugins/auth/swekey/swekey.auth.lib.php';
/**
* Handles the cookie authentication method
*
@ -229,10 +224,6 @@ class AuthenticationCookie extends AuthenticationPlugin
echo '</fieldset>
</form>';
// BEGIN Swekey Integration
Swekey_login('input_username', 'input_go');
// END Swekey Integration
if ($GLOBALS['error_handler']->hasDisplayErrors()) {
echo '<div id="pma_errors">';
$GLOBALS['error_handler']->dispErrors();
@ -279,12 +270,6 @@ class AuthenticationCookie extends AuthenticationPlugin
$GLOBALS['PHP_AUTH_USER'] = $GLOBALS['PHP_AUTH_PW'] = '';
$GLOBALS['from_cookie'] = false;
// BEGIN Swekey Integration
if (! Swekey_Auth_check()) {
return false;
}
// END Swekey Integration
if (! empty($_REQUEST['pma_username'])) {
// Verify Captcha if it is required.
@ -341,7 +326,7 @@ class AuthenticationCookie extends AuthenticationPlugin
return false;
}
}
$GLOBALS['pma_auth_server'] = $_REQUEST['pma_servername'];
$GLOBALS['pma_auth_server'] = PMA_sanitizeMySQLHost($_REQUEST['pma_servername']);
}
PMA_secureSession();
return true;
@ -350,18 +335,8 @@ class AuthenticationCookie extends AuthenticationPlugin
// At the end, try to set the $GLOBALS['PHP_AUTH_USER']
// and $GLOBALS['PHP_AUTH_PW'] variables from cookies
// servername
if ($GLOBALS['cfg']['AllowArbitraryServer']
&& ! empty($_COOKIE['pmaServer-' . $GLOBALS['server']])
) {
$GLOBALS['pma_auth_server']
= $_COOKIE['pmaServer-' . $GLOBALS['server']];
}
// check cookies
if (empty($_COOKIE['pmaUser-' . $GLOBALS['server']])
|| empty($_COOKIE['pma_iv-' . $GLOBALS['server']])
) {
if (empty($_COOKIE['pmaUser-' . $GLOBALS['server']])) {
return false;
}
@ -398,17 +373,23 @@ class AuthenticationCookie extends AuthenticationPlugin
}
// check password cookie
if (empty($_COOKIE['pmaPass-' . $GLOBALS['server']])) {
if (empty($_COOKIE['pmaAuth-' . $GLOBALS['server']])) {
return false;
}
$GLOBALS['PHP_AUTH_PW'] = $this->cookieDecrypt(
$_COOKIE['pmaPass-' . $GLOBALS['server']],
$this->_getSessionEncryptionSecret()
$auth_data = json_decode(
$this->cookieDecrypt(
$_COOKIE['pmaAuth-' . $GLOBALS['server']],
$this->_getSessionEncryptionSecret()
),
true
);
if ($GLOBALS['PHP_AUTH_PW'] == "\xff(blank)") {
$GLOBALS['PHP_AUTH_PW'] = '';
if (! is_array($auth_data) || ! isset($auth_data['password'])) {
return false;
}
$GLOBALS['PHP_AUTH_PW'] = $auth_data['password'];
if ($GLOBALS['cfg']['AllowArbitraryServer'] && ! empty($auth_data['server'])) {
$GLOBALS['pma_auth_server'] = $auth_data['server'];
}
$GLOBALS['from_cookie'] = true;
@ -485,8 +466,6 @@ class AuthenticationCookie extends AuthenticationPlugin
{
global $cfg;
$this->createIV();
// Name and password cookies need to be refreshed each time
// Duration = one month for username
$this->storeUsernameCookie($cfg['Server']['user']);
@ -501,21 +480,6 @@ class AuthenticationCookie extends AuthenticationPlugin
// Set server cookies if required (once per session) and, in this case,
// force reload to ensure the client accepts cookies
if (! $GLOBALS['from_cookie']) {
if ($GLOBALS['cfg']['AllowArbitraryServer']) {
if (! empty($GLOBALS['pma_auth_server'])) {
// Duration = one month for servername
$GLOBALS['PMA_Config']->setCookie(
'pmaServer-' . $GLOBALS['server'],
$cfg['Server']['host']
);
} else {
// Delete servername cookie
$GLOBALS['PMA_Config']->removeCookie(
'pmaServer-' . $GLOBALS['server']
);
}
}
// URL where to go:
$redirect_url = './index.php';
@ -585,11 +549,15 @@ class AuthenticationCookie extends AuthenticationPlugin
*/
public function storePasswordCookie($password)
{
$payload = array('password' => $password);
if ($GLOBALS['cfg']['AllowArbitraryServer'] && ! empty($GLOBALS['pma_auth_server'])) {
$payload['server'] = $GLOBALS['pma_auth_server'];
}
// Duration = as configured
$GLOBALS['PMA_Config']->setCookie(
'pmaPass-' . $GLOBALS['server'],
'pmaAuth-' . $GLOBALS['server'],
$this->cookieEncrypt(
! empty($password) ? $password : "\xff(blank)",
json_encode($payload),
$this->_getSessionEncryptionSecret()
),
null,
@ -613,7 +581,7 @@ class AuthenticationCookie extends AuthenticationPlugin
global $conn_error;
// Deletes password cookie and displays the login form
$GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $GLOBALS['server']);
$GLOBALS['PMA_Config']->removeCookie('pmaAuth-' . $GLOBALS['server']);
$conn_error = $this->getErrorMessage();
@ -636,8 +604,7 @@ class AuthenticationCookie extends AuthenticationPlugin
if (empty($GLOBALS['cfg']['blowfish_secret'])) {
return $this->_getSessionEncryptionSecret();
} else {
// apply md5() to work around too long secrets (returns 32 characters)
return md5($GLOBALS['cfg']['blowfish_secret']);
return $GLOBALS['cfg']['blowfish_secret'];
}
}
@ -650,9 +617,9 @@ class AuthenticationCookie extends AuthenticationPlugin
{
if (empty($_SESSION['encryption_key'])) {
if (self::useOpenSSL()) {
$_SESSION['encryption_key'] = openssl_random_pseudo_bytes(256);
$_SESSION['encryption_key'] = openssl_random_pseudo_bytes(32);
} else {
$_SESSION['encryption_key'] = Crypt\Random::string(256);
$_SESSION['encryption_key'] = Crypt\Random::string(32);
}
}
return $_SESSION['encryption_key'];
@ -672,6 +639,64 @@ class AuthenticationCookie extends AuthenticationPlugin
);
}
/**
* Concatenates secret in order to make it 16 bytes log
*
* This doesn't add any security, just ensures the secret
* is long enough by copying it.
*
* @param string $secret Original secret
*
* @return string
*/
public function enlargeSecret($secret)
{
while (strlen($secret) < 16) {
$secret .= $secret;
}
return substr($secret, 0, 16);
}
/**
* Derives MAC secret from encryption secret.
*
* @param string $secret the secret
*
* @return string the MAC secret
*/
public function getMACSecret($secret)
{
// Grab first part, up to 16 chars
// The MAC and AES secrets can overlap if original secret is short
$length = strlen($secret);
if ($length > 16) {
return substr($secret, 0, 16);
}
return $this->enlargeSecret(
$length == 1 ? $secret : substr($secret, 0, -1)
);
}
/**
* Derives AES secret from encryption secret.
*
* @param string $secret the secret
*
* @return string the AES secret
*/
public function getAESSecret($secret)
{
// Grab second part, up to 16 chars
// The MAC and AES secrets can overlap if original secret is short
$length = strlen($secret);
if ($length > 16) {
return substr($secret, -16);
}
return $this->enlargeSecret(
$length == 1 ? $secret : substr($secret, 1)
);
}
/**
* Encryption using openssl's AES or phpseclib's AES
* (phpseclib uses mcrypt when it is available)
@ -683,20 +708,31 @@ class AuthenticationCookie extends AuthenticationPlugin
*/
public function cookieEncrypt($data, $secret)
{
$mac_secret = $this->getMACSecret($secret);
$aes_secret = $this->getAESSecret($secret);
$iv = $this->createIV();
if (self::useOpenSSL()) {
return openssl_encrypt(
$result = openssl_encrypt(
$data,
'AES-128-CBC',
$secret,
0,
$this->_cookie_iv
$iv
);
} else {
$cipher = new Crypt\AES(Crypt\Base::MODE_CBC);
$cipher->setIV($this->_cookie_iv);
$cipher->setKey($secret);
return base64_encode($cipher->encrypt($data));
$cipher->setIV($iv);
$cipher->setKey($aes_secret);
$result = base64_encode($cipher->encrypt($data));
}
$iv = base64_encode($iv);
return json_encode(
array(
'iv' => $iv,
'mac' => hash_hmac('sha1', $iv . $result, $mac_secret),
'payload' => $result,
)
);
}
/**
@ -706,33 +742,39 @@ class AuthenticationCookie extends AuthenticationPlugin
* @param string $encdata encrypted data
* @param string $secret the secret
*
* @return string original data
* @return string|bool original data, false on error
*/
public function cookieDecrypt($encdata, $secret)
{
if (is_null($this->_cookie_iv)) {
$this->_cookie_iv = base64_decode(
$_COOKIE['pma_iv-' . $GLOBALS['server']],
true
);
$data = json_decode($encdata, true);
if (! is_array($data) || ! isset($data['mac']) || ! isset($data['iv']) || ! isset($data['payload'])
|| ! is_string($data['mac']) || ! is_string($data['iv']) || ! is_string($data['payload'])
) {
return false;
}
if (strlen($this->_cookie_iv) < $this->getIVSize()) {
$this->createIV();
$mac_secret = $this->getMACSecret($secret);
$aes_secret = $this->getAESSecret($secret);
$newmac = hash_hmac('sha1', $data['iv'] . $data['payload'], $mac_secret);
if (! hash_equals($data['mac'], $newmac)) {
return false;
}
if (self::useOpenSSL()) {
return openssl_decrypt(
$encdata,
$data['payload'],
'AES-128-CBC',
$secret,
0,
$this->_cookie_iv
base64_decode($data['iv'])
);
} else {
$cipher = new Crypt\AES(Crypt\Base::MODE_CBC);
$cipher->setIV($this->_cookie_iv);
$cipher->setKey($secret);
return $cipher->decrypt(base64_decode($encdata));
$cipher->setIV(base64_decode($data['iv']));
$cipher->setKey($aes_secret);
return $cipher->decrypt(base64_decode($data['payload']));
}
}
@ -760,24 +802,26 @@ class AuthenticationCookie extends AuthenticationPlugin
*/
public function createIV()
{
/* Testsuite shortcut only to allow predictable IV */
if (! is_null($this->_cookie_iv)) {
return $this->_cookie_iv;
}
if (self::useOpenSSL()) {
$this->_cookie_iv = openssl_random_pseudo_bytes(
return openssl_random_pseudo_bytes(
$this->getIVSize()
);
} else {
$this->_cookie_iv = Crypt\Random::string(
return Crypt\Random::string(
$this->getIVSize()
);
}
$GLOBALS['PMA_Config']->setCookie(
'pma_iv-' . $GLOBALS['server'],
base64_encode($this->_cookie_iv)
);
}
/**
* Sets encryption IV to use
*
* This is for testing only!
*
* @param string $vector The IV
*
* @return void
@ -809,17 +853,17 @@ class AuthenticationCookie extends AuthenticationPlugin
// -> delete password cookie(s)
if ($GLOBALS['cfg']['LoginCookieDeleteAll']) {
foreach ($GLOBALS['cfg']['Servers'] as $key => $val) {
$GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $key);
if (isset($_COOKIE['pmaPass-' . $key])) {
unset($_COOKIE['pmaPass-' . $key]);
$GLOBALS['PMA_Config']->removeCookie('pmaAuth-' . $key);
if (isset($_COOKIE['pmaAuth-' . $key])) {
unset($_COOKIE['pmaAuth-' . $key]);
}
}
} else {
$GLOBALS['PMA_Config']->removeCookie(
'pmaPass-' . $GLOBALS['server']
'pmaAuth-' . $GLOBALS['server']
);
if (isset($_COOKIE['pmaPass-' . $GLOBALS['server']])) {
unset($_COOKIE['pmaPass-' . $GLOBALS['server']]);
if (isset($_COOKIE['pmaAuth-' . $GLOBALS['server']])) {
unset($_COOKIE['pmaAuth-' . $GLOBALS['server']]);
}
}
parent::logOut();

View File

@ -1,176 +0,0 @@
<?php
/**
* Authentication functions
*
* @package Swekey
*/
?>
<script>
var g_SwekeyPlugin = null;
// -------------------------------------------------------------------
// Create the swekey plugin if it does not exists
function Swekey_Plugin()
{
try
{
if (g_SwekeyPlugin != null)
return g_SwekeyPlugin;
if (window.ActiveXObject)
{
g_SwekeyPlugin = document.getElementById("swekey_activex");
if (g_SwekeyPlugin == null)
{
// we must create the activex that way instead of
// new ActiveXObject("FbAuthAx.FbAuthCtl");
// otherwise SetClientSite is not called and
// we can not get the url
var div = document.createElement('div');
div.innerHTML='<object id="swekey_activex" style="display:none" CLASSID="CLSID:8E02E3F9-57AA-4EE1-AA68-A42DD7B0FADE"></object>';
// Never append to the body because it may still loading and it breaks IE
document.body.insertBefore(div, document.body.firstChild);
g_SwekeyPlugin = document.getElementById("swekey_activex");
}
return g_SwekeyPlugin;
}
g_SwekeyPlugin = document.getElementById("swekey_plugin");
if (g_SwekeyPlugin != null)
return g_SwekeyPlugin;
for (i = 0; i < navigator.plugins.length; i ++)
{
try
{
if (navigator.plugins[i] == null)
{
navigator.plugins.refresh();
}
else if (navigator.plugins[i][0] != null && navigator.plugins[i][0].type == "application/fbauth-plugin")
{
var x = document.createElement('embed');
x.setAttribute('type', 'application/fbauth-plugin');
x.setAttribute('id', 'swekey_plugin');
x.setAttribute('width', '0');
x.setAttribute('height', '0');
x.style.dislay='none';
//document.body.appendChild(x);
document.body.insertBefore(x, document.body.firstChild);
g_SwekeyPlugin = document.getElementById("swekey_plugin");
return g_SwekeyPlugin;
}
}
catch (e)
{
navigator.plugins.refresh();
//alert ('Failed to create plugin: ' + e);
}
}
}
catch (e)
{
//alert("Swekey_Plugin " + e);
g_SwekeyPlugin = null;
}
return null;
}
// -------------------------------------------------------------------
// Returns true if the swekey plugin is installed
function Swekey_Installed()
{
return (Swekey_Plugin() != null);
}
// -------------------------------------------------------------------
// List the id of the Swekey connected to the PC
// Returns a string containing comma separated Swekey Ids
// A Swekey is a 32 char hexadecimal value.
function Swekey_ListKeyIds()
{
try
{
return Swekey_Plugin().list();
}
catch (e)
{
// alert("Swekey_ListKeyIds " + e);
}
return "";
}
// -------------------------------------------------------------------
// Ask the Connected Swekey to generate an OTP
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
// rt: A random token
// return: The calculated OTP encoded in a 64 chars hexadecimal value.
function Swekey_GetOtp(id, rt)
{
try
{
return Swekey_Plugin().getotp(id, rt);
}
catch (e)
{
// alert("Swekey_GetOtp " + e);
}
return "";
}
// -------------------------------------------------------------------
// Ask the Connected Swekey to generate a OTP linked to the current https host
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
// rt: A random token
// return: The calculated OTP encoded in a 64 chars hexadecimal value.
// or "" if the current url does not start with https
function Swekey_GetLinkedOtp(id, rt)
{
try
{
return Swekey_Plugin().getlinkedotp(id, rt);
}
catch (e)
{
// alert("Swekey_GetSOtp " + e);
}
return "";
}
// -------------------------------------------------------------------
// Calls Swekey_GetOtp or Swekey_GetLinkedOtp depending if we are in
// an https page or not.
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
// rt: A random token
// return: The calculated OTP encoded in a 64 chars hexadecimal value.
function Swekey_GetSmartOtp(id, rt)
{
var res = Swekey_GetLinkedOtp(id, rt);
if (res == "")
res = Swekey_GetOtp(id, rt);
return res;
}
// -------------------------------------------------------------------
// Set a unplug handler (url) to the specified connected feebee
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
// key: The key that index that url, (aplhanumeric values only)
// url: The url that will be launched ("" deletes the url)
function Swekey_SetUnplugUrl(id, key, url)
{
try
{
return Swekey_Plugin().setunplugurl(id, key, url);
}
catch (e)
{
// alert("Swekey_SetUnplugUrl " + e);
}
}
</script>

View File

@ -1,25 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEKjCCAxKgAwIBAgIJAMjw7QcLWCd6MA0GCSqGSIb3DQEBBQUAMGsxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQKEwtNdXNiZSwgSW5j
LjESMBAGA1UEAxMJbXVzYmUuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQG11c2Jl
LmNvbTAeFw0wODA5MDQxNDE2MTNaFw0zNzEyMjExNDE2MTNaMGsxCzAJBgNVBAYT
AlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQKEwtNdXNiZSwgSW5jLjES
MBAGA1UEAxMJbXVzYmUuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQG11c2JlLmNv
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOBhOljxVzQfK4gted2I
d3BemcjW4abAUOzn3KYWXpPO5xIfVeXNDGkDbyH+X+7fo94sX25/ewuKNFDSOcvo
tXHq7uQenTHB35r+a+LY81KceUHgW90a3XsqPAkwAjyYcgo3zmM2DtLvw+5Yod8T
wAHk9m3qavnQ1uk99jBTwL7RZ9jIZHh9pFCL93uJc2obtd8O96Iycbn2q0w/AWbb
+eUVWIHzvLtfPvROeL3lJzr/Uz5LjKapxJ3qyqASflfHpnj9pU8l6g2TQ6Hg5KT5
tLFkRe7uGhOfRtOQ/+NjaWrEuNCFnpyN4Q5Fv+5qA1Ip1IpH0200sWbAf/k2u0Qp
Sx0CAwEAAaOB0DCBzTAdBgNVHQ4EFgQUczJrQ7hCvtsnzcqiDIZ/GSn/CiwwgZ0G
A1UdIwSBlTCBkoAUczJrQ7hCvtsnzcqiDIZ/GSn/Ciyhb6RtMGsxCzAJBgNVBAYT
AlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQKEwtNdXNiZSwgSW5jLjES
MBAGA1UEAxMJbXVzYmUuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQG11c2JlLmNv
bYIJAMjw7QcLWCd6MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGxk
8xzIljeBDQWWVRr0NEALVSv3i09V4jAKkyEOfmZ8lKMKJi0atwbtjrXTzLnNYj+Q
pyUbyY/8ItWvV7pnVxMiF9qcer7e9X4vw358GZuMVE/da1nWxz+CwzTm5oO30RzA
antM9bISFFr9lJq69bDWOnCUi1IG8DSL3TxtlABso7S4vqiZ+sB33l6k1K4a/Njb
QkU9UejKhKkVVZTsOrumfnOJ4MCmPfX8Y/AY2o670y5HnzpxerIYziCVzApPVrW7
sKH0tuVGturMfQOKgstYe4/m9glBTeTLMkjD+6MJC2ONBD7GAiOO95gNl5M1fzJQ
FEe5CJ7DCYl0GdmLXXw=
-----END CERTIFICATE-----

View File

@ -1,315 +0,0 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Swekey
*
* @package Swekey
*/
use PMA\libraries\Message;
/**
* Checks Swekey authentication.
*
* @return boolean whether authentication succeeded or not
*/
function Swekey_Auth_check()
{
global $cfg;
$confFile = $cfg['Server']['auth_swekey_config'];
if (! isset($_SESSION['SWEKEY'])) {
$_SESSION['SWEKEY'] = array();
}
$_SESSION['SWEKEY']['ENABLED'] = (! empty($confFile) && @file_exists($confFile));
// Load the swekey.conf file the first time
if ($_SESSION['SWEKEY']['ENABLED']
&& empty($_SESSION['SWEKEY']['CONF_LOADED'])
) {
$_SESSION['SWEKEY']['CONF_LOADED'] = true;
$_SESSION['SWEKEY']['VALID_SWEKEYS'] = array();
$valid_swekeys = explode("\n", @file_get_contents($confFile));
foreach ($valid_swekeys as $line) {
if (preg_match("/^[0-9A-F]{32}:.+$/", $line) != false) {
$items = explode(":", $line);
if (count($items) == 2) {
$_SESSION['SWEKEY']['VALID_SWEKEYS'][$items[0]]
= trim($items[1]);
}
} elseif (preg_match("/^[A-Z_]+=.*$/", $line) != false) {
$items = explode("=", $line);
$_SESSION['SWEKEY']['CONF_' . trim($items[0])] = trim($items[1]);
}
}
// Set default values for settings
if (! isset($_SESSION['SWEKEY']['CONF_SERVER_CHECK'])) {
$_SESSION['SWEKEY']['CONF_SERVER_CHECK'] = "";
}
if (! isset($_SESSION['SWEKEY']['CONF_SERVER_RNDTOKEN'])) {
$_SESSION['SWEKEY']['CONF_SERVER_RNDTOKEN'] = "";
}
if (! isset($_SESSION['SWEKEY']['CONF_SERVER_STATUS'])) {
$_SESSION['SWEKEY']['CONF_SERVER_STATUS'] = "";
}
if (! isset($_SESSION['SWEKEY']['CONF_CA_FILE'])) {
$_SESSION['SWEKEY']['CONF_CA_FILE'] = "";
}
if (! isset($_SESSION['SWEKEY']['CONF_ENABLE_TOKEN_CACHE'])) {
$_SESSION['SWEKEY']['CONF_ENABLE_TOKEN_CACHE'] = true;
}
if (! isset($_SESSION['SWEKEY']['CONF_DEBUG'])) {
$_SESSION['SWEKEY']['CONF_DEBUG'] = false;
}
}
// check if a web key has been authenticated
if ($_SESSION['SWEKEY']['ENABLED']) {
if (empty($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'])) {
return false;
}
}
return true;
}
/**
* Handle Swekey authentication error.
*
* @return string HTML
*/
function Swekey_Auth_error()
{
if (! isset($_SESSION['SWEKEY'])) {
return null;
}
if (! $_SESSION['SWEKEY']['ENABLED']) {
return null;
}
include_once './libraries/plugins/auth/swekey/authentication.inc.php';
?>
<script>
function Swekey_GetValidKey()
{
var valids = "<?php
foreach ($_SESSION['SWEKEY']['VALID_SWEKEYS'] as $key => $value) {
echo $key , ',';
}
?>";
var connected_keys = Swekey_ListKeyIds().split(",");
for (i in connected_keys) {
if (connected_keys[i] != null && connected_keys[i].length == 32) {
if (valids.indexOf(connected_keys[i]) >= 0) {
return connected_keys[i];
}
}
}
if (connected_keys.length > 0) {
if (connected_keys[0].length == 32) {
return "unknown_key_" + connected_keys[0];
}
}
return "none";
}
var key = Swekey_GetValidKey();
function timedCheck()
{
if (key != Swekey_GetValidKey()) {
window.location.search = "?swekey_reset";
} else {
setTimeout("timedCheck()",1000);
}
}
setTimeout("timedCheck()",1000);
</script>
<?php
if (! empty($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'])) {
return null;
}
if (count($_SESSION['SWEKEY']['VALID_SWEKEYS']) == 0) {
return sprintf(
__('File %s does not contain any key id'),
$GLOBALS['cfg']['Server']['auth_swekey_config']
);
}
include_once "libraries/plugins/auth/swekey/swekey.php";
Swekey_SetCheckServer($_SESSION['SWEKEY']['CONF_SERVER_CHECK']);
Swekey_SetRndTokenServer($_SESSION['SWEKEY']['CONF_SERVER_RNDTOKEN']);
Swekey_SetStatusServer($_SESSION['SWEKEY']['CONF_SERVER_STATUS']);
Swekey_EnableTokenCache($_SESSION['SWEKEY']['CONF_ENABLE_TOKEN_CACHE']);
$caFile = $_SESSION['SWEKEY']['CONF_CA_FILE'];
if (empty($caFile)) {
$caFile = __FILE__;
$pos = strrpos($caFile, '/');
if ($pos === false) {
$pos = strrpos($caFile, '\\'); // windows
}
$caFile = substr($caFile, 0, $pos + 1) . 'musbe-ca.crt';
// echo "\n<!-- $caFile -->\n";
// if (file_exists($caFile))
// echo "<!-- exists -->\n";
}
if (@file_exists($caFile)) {
Swekey_SetCAFile($caFile);
} elseif (! empty($caFile)
&& (substr($_SESSION['SWEKEY']['CONF_SERVER_CHECK'], 0, 8) == "https://")
) {
return "Internal Error: CA File $caFile not found";
}
$result = null;
$swekey_id = $_GET['swekey_id'];
$swekey_otp = $_GET['swekey_otp'];
if (isset($swekey_id)) {
unset($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY']);
if (! isset($_SESSION['SWEKEY']['RND_TOKEN'])) {
unset($swekey_id);
} else {
if (strlen($swekey_id) == 32) {
$res = Swekey_CheckOtp(
$swekey_id, $_SESSION['SWEKEY']['RND_TOKEN'], $swekey_otp
);
unset($_SESSION['SWEKEY']['RND_TOKEN']);
if (! $res) {
$result = __('Hardware authentication failed!') . ' (' . Swekey_GetLastError() . ')';
} else {
$_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'] = $swekey_id;
$_SESSION['SWEKEY']['FORCE_USER']
= $_SESSION['SWEKEY']['VALID_SWEKEYS'][$swekey_id];
return null;
}
} else {
$result = __('No valid authentication key plugged');
if ($_SESSION['SWEKEY']['CONF_DEBUG']) {
$result .= "<br/>" . htmlspecialchars($swekey_id);
}
unset($_SESSION['SWEKEY']['CONF_LOADED']); // reload the conf file
}
}
} else {
unset($_SESSION['SWEKEY']);
}
$_SESSION['SWEKEY']['RND_TOKEN'] = Swekey_GetFastRndToken();
if (strlen($_SESSION['SWEKEY']['RND_TOKEN']) != 64) {
$result = __('Hardware authentication failed!') . ' (' . Swekey_GetLastError() . ')';
unset($_SESSION['SWEKEY']['CONF_LOADED']); // reload the conf file
}
if (! isset($swekey_id)) {
?>
<script>
if (key.length != 32) {
window.location.search="?swekey_id=" + key + "&token=<?php echo $_SESSION[' PMA_token ']; ?>";
} else {
var url = "" + window.location;
if (url.indexOf("?") > 0) {
url = url.substr(0, url.indexOf("?"));
}
Swekey_SetUnplugUrl(key, "pma_login", url + "?session_to_unset=<?php echo session_id();?>&token=<?php echo $_SESSION[' PMA_token ']; ?>");
var otp = Swekey_GetOtp(key, <?php echo '"' , $_SESSION['SWEKEY']['RND_TOKEN'] , '"';?>);
window.location.search="?swekey_id=" + key + "&swekey_otp=" + otp + "&token=<?php echo $_SESSION[' PMA_token ']; ?>";
}
</script>
<?php
return __('Authenticating…');
}
return $result;
}
/**
* Perform login using Swekey.
*
* @param string $input_name Input "Name"
* @param string $input_go Input "Go"
*
* @return void
*/
function Swekey_login($input_name, $input_go)
{
$swekeyErr = Swekey_Auth_error();
if ($swekeyErr != null) {
Message::error($swekeyErr)->display();
if ($GLOBALS['error_handler']->hasDisplayErrors()) {
echo '<div>';
$GLOBALS['error_handler']->dispErrors();
echo '</div>';
}
}
if (isset($_SESSION['SWEKEY']) && $_SESSION['SWEKEY']['ENABLED']) {
echo '<script type="text/javascript">';
if (empty($_SESSION['SWEKEY']['FORCE_USER'])) {
echo 'var user = null;';
} else {
echo 'var user = "' . $_SESSION['SWEKEY']['FORCE_USER'] . '";';
}
?>
function open_swekey_site()
{
window.open("<?php echo PMA_linkURL('https://www.phpmyadmin.net/auth_key/'); ?>");
}
var input_username = document.getElementById("<?php echo $input_name; ?>");
var input_go = document.getElementById("<?php echo $input_go; ?>");
var swekey_status = document.createElement('img');
swekey_status.setAttribute('onclick', 'open_swekey_site()');
swekey_status.setAttribute('style', 'width:8px; height:16px; border:0px; vspace:0px; hspace:0px; frameborder:no');
if (user == null) {
swekey_status.setAttribute('src', 'http://artwork.swekey.com/unplugged-8x16.png');
//swekey_status.setAttribute('title', 'No swekey plugged');
input_go.disabled = true;
} else {
swekey_status.setAttribute('src', 'http://artwork.swekey.com/plugged-8x16.png');
//swekey_status.setAttribute('title', 'swekey plugged');
input_username.value = user;
}
input_username.readOnly = true;
if (input_username.nextSibling == null) {
input_username.parentNode.appendChild(swekey_status);
} else {
input_username.parentNode.insertBefore(swekey_status, input_username.nextSibling);
}
<?php
echo '</script>';
}
}
if (!empty($_GET['session_to_unset'])) {
session_write_close();
session_id($_GET['session_to_unset']);
session_start();
$_SESSION = array();
session_write_close();
session_destroy();
exit;
}
if (isset($_GET['swekey_reset'])) {
unset($_SESSION['SWEKEY']);
}

View File

@ -1,536 +0,0 @@
<?php
/**
* Library that provides common functions that are used to help integrating Swekey Authentication in a PHP web site
* Version 1.0
*
* History:
* 1.2 Use curl (widely installed) to query the server
* Fixed a possible tempfile race attack
* Random token cache can now be disabled
* 1.1 Added Swekey_HttpGet function that support faulty servers
* Support for custom servers
* 1.0 First release
*
* @package Swekey
*/
/**
* Errors codes
*/
define("SWEKEY_ERR_INVALID_DEV_STATUS", 901); // The satus of the device is not SWEKEY_STATUS_OK
define("SWEKEY_ERR_INTERNAL", 902); // Should never occurd
define("SWEKEY_ERR_OUTDATED_RND_TOKEN", 910); // You random token is too old
define("SWEKEY_ERR_INVALID_OTP", 911); // The otp was not correct
/**
* Those errors are considered as an attack and your site will be blacklisted during one minute
* if you receive one of those errors
*/
define("SWEKEY_ERR_BADLY_ENCODED_REQUEST", 920);
define("SWEKEY_ERR_INVALID_RND_TOKEN", 921);
define("SWEKEY_ERR_DEV_NOT_FOUND", 922);
/**
* Default values for configuration.
*/
define('SWEKEY_DEFAULT_CHECK_SERVER', 'https://auth-check.musbe.net');
define('SWEKEY_DEFAULT_RND_SERVER', 'https://auth-rnd-gen.musbe.net');
define('SWEKEY_DEFAULT_STATUS_SERVER', 'https://auth-status.musbe.net');
/**
* The last error of an operation is alway put in this global var
*/
global $gSwekeyLastError;
$gSwekeyLastError = 0;
global $gSwekeyLastResult;
$gSwekeyLastResult = "<not set>";
/**
* Servers addresses
* Use the Swekey_SetXxxServer($server) functions to set them
*/
global $gSwekeyCheckServer;
if (! isset($gSwekeyCheckServer)) {
$gSwekeyCheckServer = SWEKEY_DEFAULT_CHECK_SERVER;
}
global $gSwekeyRndTokenServer;
if (! isset($gSwekeyRndTokenServer)) {
$gSwekeyRndTokenServer = SWEKEY_DEFAULT_RND_SERVER;
}
global $gSwekeyStatusServer;
if (! isset($gSwekeyStatusServer)) {
$gSwekeyStatusServer = SWEKEY_DEFAULT_STATUS_SERVER;
}
global $gSwekeyCA;
global $gSwekeyTokenCacheEnabled;
if (! isset($gSwekeyTokenCacheEnabled)) {
$gSwekeyTokenCacheEnabled = true;
}
/**
* Change the address of the Check server.
* If $server is empty the default value 'http://auth-check.musbe.net' will be used
*
* @param int $server The protocol and hostname to use
*
* @access public
*/
function Swekey_SetCheckServer($server)
{
global $gSwekeyCheckServer;
if (empty($server)) {
$gSwekeyCheckServer = SWEKEY_DEFAULT_CHECK_SERVER;
} else {
$gSwekeyCheckServer = $server;
}
}
/**
* Change the address of the Random Token Generator server.
* If $server is empty the default value 'http://auth-rnd-gen.musbe.net' will be used
*
* @param int $server The protocol and hostname to use
*
* @access public
*/
function Swekey_SetRndTokenServer($server)
{
global $gSwekeyRndTokenServer;
if (empty($server)) {
$gSwekeyRndTokenServer = SWEKEY_DEFAULT_RND_SERVER;
} else {
$gSwekeyRndTokenServer = $server;
}
}
/**
* Change the address of the Satus server.
* If $server is empty the default value 'http://auth-status.musbe.net' will be used
*
* @param int $server The protocol and hostname to use
*
* @access public
*/
function Swekey_SetStatusServer($server)
{
global $gSwekeyStatusServer;
if (empty($server)) {
$gSwekeyStatusServer = SWEKEY_DEFAULT_STATUS_SERVER;
} else {
$gSwekeyStatusServer = $server;
}
}
/**
* Change the certificat file in case of the the severs use https instead of http
*
* @param string $cafile The path of the crt file to use
*
* @access public
*/
function Swekey_SetCAFile($cafile)
{
global $gSwekeyCA;
$gSwekeyCA = $cafile;
}
/**
* Enable or disable the random token caching
* Because everybody has full access to the cache file, it can be a DOS vulnerability
* So disable it if you are running in a non secure enviromnement
*
* @param $enable
*
* @access public
*/
function Swekey_EnableTokenCache($enable)
{
global $gSwekeyTokenCacheEnabled;
$gSwekeyTokenCacheEnabled = ! empty($enable);
}
/**
* Return the last error.
*
* @return string The Last Error
* @access public
*/
function Swekey_GetLastError()
{
global $gSwekeyLastError;
return $gSwekeyLastError;
}
/**
* Return the last result.
*
* @return string The Last Error
* @access public
*/
function Swekey_GetLastResult()
{
global $gSwekeyLastResult;
return $gSwekeyLastResult;
}
/**
* Send a synchronous request to the server.
* This function manages timeout then will not block if one of the server is down
*
* @param string $url The url to get
* @param string $response_code The response code
*
* @return string The body of the response or "" in case of error
* @access private
*/
function Swekey_HttpGet($url, &$response_code)
{
global $gSwekeyLastError;
$gSwekeyLastError = 0;
global $gSwekeyLastResult;
$gSwekeyLastResult = "<not set>";
// use curl if available
if (function_exists('curl_init')) {
$sess = curl_init($url);
if (substr($url, 0, 8) == "https://") {
global $gSwekeyCA;
if (! empty($gSwekeyCA)) {
if (file_exists($gSwekeyCA)) {
if (! curl_setopt($sess, CURLOPT_CAINFO, $gSwekeyCA)) {
error_log(
"SWEKEY_ERROR:Could not set CA file : ".curl_error($sess)
);
} else {
$caFileOk = true;
}
} else {
error_log(
"SWEKEY_ERROR:Could not find CA file $gSwekeyCA getting $url"
);
}
}
curl_setopt($sess, CURLOPT_SSL_VERIFYHOST, '2');
curl_setopt($sess, CURLOPT_SSL_VERIFYPEER, '1');
curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '20');
curl_setopt($sess, CURLOPT_TIMEOUT, '20');
} else {
curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '3');
curl_setopt($sess, CURLOPT_TIMEOUT, '5');
}
curl_setopt($sess, CURLOPT_RETURNTRANSFER, '1');
$res=curl_exec($sess);
$response_code = curl_getinfo($sess, CURLINFO_HTTP_CODE);
$curlerr = curl_error($sess);
curl_close($sess);
if ($response_code == 200) {
$gSwekeyLastResult = $res;
return $res;
}
if (! empty($response_code)) {
$gSwekeyLastError = $response_code;
error_log(
"SWEKEY_ERROR:Error $gSwekeyLastError ($curlerr) getting $url"
);
return "";
}
$response_code = 408; // Request Timeout
$gSwekeyLastError = $response_code;
error_log("SWEKEY_ERROR:Error $curlerr getting $url");
return "";
}
// use pecl_http if available
if (class_exists('HttpRequest')) {
// retry if one of the server is down
for ($num=1; $num <= 3; $num++ ) {
$r = new HttpRequest($url);
$options = array('timeout' => '3');
if (substr($url, 0, 6) == "https:") {
$sslOptions = array();
$sslOptions['verifypeer'] = true;
$sslOptions['verifyhost'] = true;
$capath = __FILE__;
$name = strrchr($capath, '/');
// windows
if (empty($name)) {
$name = strrchr($capath, '\\');
}
$capath = substr($capath, 0, strlen($capath) - strlen($name) + 1)
. 'musbe-ca.crt';
if (! empty($gSwekeyCA)) {
$sslOptions['cainfo'] = $gSwekeyCA;
}
$options['ssl'] = $sslOptions;
}
$r->setOptions($options);
/*
try
{
*/
$reply = $r->send();
$res = $reply->getBody();
$info = $r->getResponseInfo();
$response_code = $info['response_code'];
if ($response_code != 200) {
$gSwekeyLastError = $response_code;
error_log(
"SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url
);
return "";
}
$gSwekeyLastResult = $res;
return $res;
/*
}
catch (HttpException $e)
{
error_log("SWEKEY_WARNING:HttpException ".$e." getting ".$url);
}
*/
}
$response_code = 408; // Request Timeout
$gSwekeyLastError = $response_code;
error_log("SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url);
return "";
}
global $http_response_header;
$res = @file_get_contents($url);
$response_code = substr($http_response_header[0], 9, 3); //HTTP/1.0
if ($response_code == 200) {
$gSwekeyLastResult = $res;
return $res;
}
$gSwekeyLastError = $response_code;
error_log("SWEKEY_ERROR:Error ".$response_code." getting ".$url);
return "";
}
/**
* Get a Random Token from a Token Server
* The RT is a 64 vhars hexadecimal value
* You should better use Swekey_GetFastRndToken() for performance
* @access public
*/
function Swekey_GetRndToken()
{
global $gSwekeyRndTokenServer;
return Swekey_HttpGet($gSwekeyRndTokenServer.'/FULL-RND-TOKEN', $response_code);
}
/**
* Get a Half Random Token from a Token Server
* The RT is a 64 vhars hexadecimal value
* Use this value if you want to make your own Swekey_GetFastRndToken()
* @access public
*/
function Swekey_GetHalfRndToken()
{
global $gSwekeyRndTokenServer;
return Swekey_HttpGet($gSwekeyRndTokenServer.'/HALF-RND-TOKEN', $response_code);
}
/**
* Get a Half Random Token
* The RT is a 64 vhars hexadecimal value
* This function get a new random token and reuse it.
* Token are refetched from the server only once every 30 seconds.
* You should always use this function to get half random token.
* @access public
*/
function Swekey_GetFastHalfRndToken()
{
global $gSwekeyTokenCacheEnabled;
$res = "";
$cachefile = "";
// We check if we have a valid RT is the session
if (isset($_SESSION['rnd-token-date'])) {
if (time() - $_SESSION['rnd-token-date'] < 30) {
$res = $_SESSION['rnd-token'];
}
}
// If not we try to get it from a temp file (PHP >= 5.2.1 only)
if (strlen($res) != 32 && $gSwekeyTokenCacheEnabled) {
if (function_exists('sys_get_temp_dir')) {
$tempdir = sys_get_temp_dir();
$cachefile = $tempdir."/swekey-rnd-token-".get_current_user();
$modif = filemtime($cachefile);
if ($modif != false) {
if (time() - $modif < 30) {
$res = @file_get_contents($cachefile);
if (strlen($res) != 32) {
$res = "";
} else {
$_SESSION['rnd-token'] = $res;
$_SESSION['rnd-token-date'] = $modif;
}
}
}
}
}
// If we don't have a valid RT here we have to get it from the server
if (strlen($res) != 32) {
$res = substr(Swekey_GetHalfRndToken(), 0, 32);
$_SESSION['rnd-token'] = $res;
$_SESSION['rnd-token-date'] = time();
if (! empty($cachefile)) {
// we unlink the file so no possible tempfile race attack
unlink($cachefile);
$file = fopen($cachefile, "x");
if ($file != false) {
@fwrite($file, $res);
@fclose($file);
}
}
}
return $res."00000000000000000000000000000000";
}
/**
* Get a Random Token
* The RT is a 64 vhars hexadecimal value
* This function generates a unique random token for each call but call the
* server only once every 30 seconds.
* You should always use this function to get random token.
* @access public
*/
function Swekey_GetFastRndToken()
{
$res = Swekey_GetFastHalfRndToken();
if (strlen($res) == 64) {
return substr($res, 0, 32).strtoupper(md5("Musbe Authentication Key" . mt_rand() . date(DATE_ATOM)));
}
return "";
}
/**
* Checks that an OTP generated by a Swekey is valid
*
* @param mixed $id The id of the swekey
* @param mixed $rt The random token used to generate the otp
* @param mixed $otp The otp generated by the swekey
*
* @return boolean Success
* @access public
*/
function Swekey_CheckOtp($id, $rt, $otp)
{
global $gSwekeyCheckServer;
$res = Swekey_HttpGet(
$gSwekeyCheckServer.'/CHECK-OTP/'.$id.'/'.$rt.'/'.$otp,
$response_code
);
return $response_code == 200 && $res == "OK";
}
/**
* Values that are associated with a key.
* The following values can be returned by the Swekey_GetStatus() function
*/
define("SWEKEY_STATUS_OK", 0);
define("SWEKEY_STATUS_NOT_FOUND", 1); // The key does not exist in the db
define("SWEKEY_STATUS_INACTIVE", 2); // The key has never been activated
define("SWEKEY_STATUS_LOST", 3); // The user has lost his key
define("SWEKEY_STATUS_STOLEN", 4); // The key was stolen
define("SWEKEY_STATUS_FEE_DUE", 5); // The annual fee was not paid
define("SWEKEY_STATUS_OBSOLETE", 6); // The hardware is no longer supported
define("SWEKEY_STATUS_UNKOWN", 201); // We could not connect to the authentication server
/**
* Values that are associated with a key.
* The Javascript Api can also return the following values
*/
define("SWEKEY_STATUS_REPLACED", 100); // This key has been replaced by a backup key
define("SWEKEY_STATUS_BACKUP_KEY", 101); // This key is a backup key that is not activated yet
define("SWEKEY_STATUS_NOTPLUGGED", 200); // This key is not plugged in the computer
/**
* Return the text corresponding to the integer status of a key
*
* @param int $status The status
*
* @return string The text corresponding to the status
* @access public
*/
function Swekey_GetStatusStr($status)
{
switch($status)
{
case SWEKEY_STATUS_OK :
return 'OK';
case SWEKEY_STATUS_NOT_FOUND :
return 'Key does not exist in the db';
case SWEKEY_STATUS_INACTIVE :
return 'Key not activated';
case SWEKEY_STATUS_LOST :
return 'Key was lost';
case SWEKEY_STATUS_STOLEN :
return 'Key was stolen';
case SWEKEY_STATUS_FEE_DUE :
return 'The annual fee was not paid';
case SWEKEY_STATUS_OBSOLETE :
return 'Key no longer supported';
case SWEKEY_STATUS_REPLACED :
return 'This key has been replaced by a backup key';
case SWEKEY_STATUS_BACKUP_KEY :
return 'This key is a backup key that is not activated yet';
case SWEKEY_STATUS_NOTPLUGGED :
return 'This key is not plugged in the computer';
case SWEKEY_STATUS_UNKOWN :
return 'Unknow Status, could not connect to the authentication server';
}
return 'unknown status '.$status;
}
/**
* If your web site requires a key to login you should check that the key
* is still valid (has not been lost or stolen) before requiring it.
* A key can be authenticated only if its status is SWEKEY_STATUS_OK
*
* @param mixed $id The id of the swekey
*
* @return int The status of the swekey
* @access public
*/
function Swekey_GetStatus($id)
{
global $gSwekeyStatusServer;
$res = Swekey_HttpGet($gSwekeyStatusServer.'/GET-STATUS/'.$id, $response_code);
if ($response_code == 200) {
return intval($res);
}
return SWEKEY_STATUS_UNKOWN;
}

View File

@ -360,7 +360,7 @@ class ExportMediawiki extends ExportPlugin
// see http://www.mediawiki.org/wiki/Help:Formatting
$comment = $this->_exportCRLF();
$comment .= '<!--' . $this->_exportCRLF();
$comment .= $text . $this->_exportCRLF();
$comment .= htmlspecialchars($text) . $this->_exportCRLF();
$comment .= '-->' . str_repeat($this->_exportCRLF(), 2);
return $comment;

View File

@ -65,6 +65,19 @@ class ExportPhparray extends ExportPlugin
$this->properties = $exportPluginProperties;
}
/**
* Removes end of comment from a string
*
* @param string $string String to replace
*
* @return string
*/
public function commentString($string)
{
return strtr($string, '*/', '-');
}
/**
* Outputs export header
*
@ -76,7 +89,7 @@ class ExportPhparray extends ExportPlugin
'<?php' . $GLOBALS['crlf']
. '/**' . $GLOBALS['crlf']
. ' * Export to PHP Array plugin for PHPMyAdmin' . $GLOBALS['crlf']
. ' * @version 0.2b' . $GLOBALS['crlf']
. ' * @version ' . PMA_VERSION . $GLOBALS['crlf']
. ' */' . $GLOBALS['crlf'] . $GLOBALS['crlf']
);
@ -107,9 +120,9 @@ class ExportPhparray extends ExportPlugin
$db_alias = $db;
}
PMA_exportOutputHandler(
'//' . $GLOBALS['crlf']
. '// Database ' . PMA\libraries\Util::backquote($db_alias)
. $GLOBALS['crlf'] . '//' . $GLOBALS['crlf']
'/**' . $GLOBALS['crlf']
. ' * Database ' . $this->commentString(PMA\libraries\Util::backquote($db_alias))
. $GLOBALS['crlf'] . ' */' . $GLOBALS['crlf']
);
return true;
@ -207,9 +220,9 @@ class ExportPhparray extends ExportPlugin
$buffer = '';
$record_cnt = 0;
// Output table name as comment
$buffer .= $crlf . '// '
. PMA\libraries\Util::backquote($db_alias) . '.'
. PMA\libraries\Util::backquote($table_alias) . $crlf;
$buffer .= $crlf . '/* '
. $this->commentString(PMA\libraries\Util::backquote($db_alias)) . '.'
. $this->commentString(PMA\libraries\Util::backquote($table_alias)) . ' */' . $crlf;
$buffer .= '$' . $tablefixed . ' = array(';
while ($record = $GLOBALS['dbi']->fetchRow($result)) {

View File

@ -595,7 +595,16 @@ class ExportSql extends ExportPlugin
&& $GLOBALS['sql_include_comments']
) {
// see https://dev.mysql.com/doc/refman/5.0/en/ansi-diff-comments.html
return '--' . (empty($text) ? '' : ' ') . $text . $GLOBALS['crlf'];
if (empty($text)) {
return '--' . $GLOBALS['crlf'];
} else {
$lines = preg_split("/\\r\\n|\\r|\\n/", $text);
$result = array();
foreach ($lines as $line) {
$result[] = '-- ' . $line . $GLOBALS['crlf'];
}
return implode('', $result);
}
} else {
return '';
}
@ -1112,7 +1121,7 @@ class ExportSql extends ExportPlugin
$dbNameColumn
)
. " = '" . Util::sqlAddSlashes($db) . "'"
. " AND `page_nr` = '" . $page . "'";
. " AND `page_nr` = '" . intval($page) . "'";
if (!$this->exportData(
$cfgRelation['db'],

View File

@ -185,7 +185,7 @@ class ExportXml extends ExportPlugin
if ($names) {
foreach ($names as $name) {
$head .= ' <pma:' . $type . ' name="'
. $name . '">' . $crlf;
. htmlspecialchars($name) . '">' . $crlf;
// Do some formatting
$sql = $GLOBALS['dbi']->getDefinition($db, $dbitype, $name);
@ -232,7 +232,7 @@ class ExportXml extends ExportPlugin
. '- version ' . PMA_VERSION . $crlf
. '- https://www.phpmyadmin.net' . $crlf
. '-' . $crlf
. '- ' . __('Host:') . ' ' . $cfg['Server']['host'];
. '- ' . __('Host:') . ' ' . htmlspecialchars($cfg['Server']['host']);
if (!empty($cfg['Server']['port'])) {
$head .= ':' . $cfg['Server']['port'];
}
@ -263,7 +263,7 @@ class ExportXml extends ExportPlugin
$head .= ' -->' . $crlf;
$head .= ' <pma:structure_schemas>' . $crlf;
$head .= ' <pma:database name="' . htmlspecialchars($db)
. '" collation="' . $db_collation . '" charset="' . $db_charset
. '" collation="' . htmlspecialchars($db_collation) . '" charset="' . htmlspecialchars($db_charset)
. '">' . $crlf;
if (count($tables) == 0) {
@ -296,7 +296,7 @@ class ExportXml extends ExportPlugin
continue;
}
$head .= ' <pma:' . $type . ' name="' . $table . '">'
$head .= ' <pma:' . $type . ' name="' . htmlspecialchars($table) . '">'
. $crlf;
$tbl = " " . htmlspecialchars($tbl);
@ -314,7 +314,7 @@ class ExportXml extends ExportPlugin
foreach ($triggers as $trigger) {
$code = $trigger['create'];
$head .= ' <pma:trigger name="'
. $trigger['name'] . '">' . $crlf;
. htmlspecialchars($trigger['name']) . '">' . $crlf;
// Do some formatting
$code = mb_substr(rtrim($code), 0, -3);
@ -402,7 +402,7 @@ class ExportXml extends ExportPlugin
) {
$head = ' <!--' . $crlf
. ' - ' . __('Database:') . ' ' . '\''
. $db_alias . '\'' . $crlf
. htmlspecialchars($db_alias) . '\'' . $crlf
. ' -->' . $crlf . ' <database name="'
. htmlspecialchars($db_alias) . '">' . $crlf;
@ -491,7 +491,7 @@ class ExportXml extends ExportPlugin
unset($i);
$buffer = ' <!-- ' . __('Table') . ' '
. $table_alias . ' -->' . $crlf;
. htmlspecialchars($table_alias) . ' -->' . $crlf;
if (!PMA_exportOutputHandler($buffer)) {
return false;
}

View File

@ -96,21 +96,24 @@ class ImportShp extends ImportPlugin
// Extract the .dbf file and point to it.
$extracted = PMA_zipExtract(
$import_file,
realpath($GLOBALS['cfg']['TempDir']),
array($dbf_file_name)
$dbf_file_name
);
if ($extracted) {
if ($extracted !== false) {
$dbf_file_path = realpath($GLOBALS['cfg']['TempDir'])
. (PMA_IS_WINDOWS ? '\\' : '/') . $dbf_file_name;
$temp_dbf_file = true;
// Replace the .dbf with .*, as required
// by the bsShapeFiles library.
$file_name = mb_substr(
$dbf_file_path,
0,
mb_strlen($dbf_file_path) - 4
) . '.*';
$shp->FileName = $file_name;
. (PMA_IS_WINDOWS ? '\\' : '/')
. PMA_sanitizeFilename($dbf_file_name, true);
$handle = fopen($dbf_file_path, 'wb');
if ($handle !== false) {
fwrite($handle, $extracted);
fclose($handle);
$temp_dbf_file = true;
// Replace the .dbf with .*, as required
// by the bsShapeFiles library.
$file_name = substr(
$dbf_file_path, 0, strlen($dbf_file_path) - 4
) . '.*';
$shp->FileName = $file_name;
}
}
}
} elseif (!empty($local_import_file)
@ -130,6 +133,14 @@ class ImportShp extends ImportPlugin
}
}
// Delete the .dbf file extracted to 'TempDir'
if ($temp_dbf_file
&& isset($dbf_file_path)
&& file_exists($dbf_file_path)
) {
unlink($dbf_file_path);
}
// Load data
$shp->loadFromFile('');
if ($shp->lastError != "") {
@ -142,14 +153,6 @@ class ImportShp extends ImportPlugin
return;
}
// Delete the .dbf file extracted to 'TempDir'
if ($temp_dbf_file
&& isset($dbf_file_path)
&& file_exists($dbf_file_path)
) {
unlink($dbf_file_path);
}
$esri_types = array(
0 => 'Null Shape',
1 => 'Point',

View File

@ -53,7 +53,7 @@ class ExportRelationSchema
*/
public function setPageNumber($value)
{
$this->pageNumber = $value;
$this->pageNumber = intval($value);
}
/**

View File

@ -42,7 +42,9 @@ abstract class FormattedTransformationsPlugin extends TransformationsPlugin
*/
public function applyTransformation($buffer, $options = array(), $meta = '')
{
return $buffer;
return '<iframe srcdoc="'
. strtr($buffer, '"', '\'')
. '" sandbox=""></iframe>';
}

View File

@ -49,7 +49,7 @@ abstract class ImageLinkTransformationsPlugin extends TransformationsPlugin
{
// must disable the page loader, see
// https://wiki.phpmyadmin.net/pma/Page_loader#Bypassing_the_page_loader
return '<a class="disableAjax" target="_new" href="transformation_wrapper.php'
return '<a class="disableAjax" target="_blank" rel="noopener noreferrer" href="transformation_wrapper.php'
. $options['wrapper_link'] . '" alt="[' . htmlspecialchars($buffer) . ']">[BLOB]</a>';
}

View File

@ -82,8 +82,8 @@ abstract class ImageUploadTransformationsPlugin extends IOTransformationsPlugin
$src = 'transformation_wrapper.php' . $options['wrapper_link'];
}
$html .= '<img src="' . $src . '" width="'
. (isset($options[0]) ? $options[0] : '100') . '" height="'
. (isset($options[1]) ? $options[1] : '100') . '" alt="'
. (isset($options[0]) ? intval($options[0]) : '100') . '" height="'
. (isset($options[1]) ? intval($options[1]) : '100') . '" alt="'
. __('Image preview here') . '"/>';
$html .= '<br/><input type="file" name="fields_upload'
. $column_name_appendix . '" accept="image/*" class="image-upload"/>';

View File

@ -51,10 +51,10 @@ abstract class InlineTransformationsPlugin extends TransformationsPlugin
if (PMA_IS_GD2) {
return '<a href="transformation_wrapper.php'
. $options['wrapper_link']
. '" target="_blank"><img src="transformation_wrapper.php'
. '" rel="noopener noreferrer" target="_blank"><img src="transformation_wrapper.php'
. $options['wrapper_link'] . '&amp;resize=jpeg&amp;newWidth='
. (isset($options[0]) ? $options[0] : '100') . '&amp;newHeight='
. (isset($options[1]) ? $options[1] : 100)
. (isset($options[0]) ? intval($options[0]) : '100') . '&amp;newHeight='
. (isset($options[1]) ? intval($options[1]) : 100)
. '" alt="[' . htmlspecialchars($buffer) . ']" border="0" /></a>';
} else {
return '<img src="transformation_wrapper.php'

View File

@ -50,7 +50,7 @@ abstract class RegexValidationTransformationsPlugin extends IOTransformationsPlu
$this->success = false;
$this->error = sprintf(
__('Validation failed for the input string %s.'),
$buffer
htmlspecialchars($buffer)
);
}

View File

@ -49,13 +49,13 @@ abstract class TextImageLinkTransformationsPlugin extends TransformationsPlugin
$url = (isset($options[0]) ? $options[0] : '') . $buffer;
$parsed = parse_url($url);
/* Do not allow javascript links */
if (isset($parsed['scheme']) && $parsed['scheme'] == 'javascript') {
if (! isset($parsed['scheme']) || ! in_array(strtolower($parsed['scheme']), array('http', 'https', 'ftp', 'mailto'))) {
return htmlspecialchars($url);
}
return '<a href="' . htmlspecialchars($url)
. '" target="_blank"><img src="' . htmlspecialchars($url)
. '" border="0" width="' . (isset($options[1]) ? $options[1] : 100)
. '" height="' . (isset($options[2]) ? $options[2] : 50) . '" />'
. '" rel="noopener noreferrer" target="_blank"><img src="' . htmlspecialchars($url)
. '" border="0" width="' . (isset($options[1]) ? intval($options[1]) : 100)
. '" height="' . (isset($options[2]) ? intval($options[2]) : 50) . '" />'
. htmlspecialchars($buffer) . '</a>';
}

View File

@ -49,14 +49,14 @@ abstract class TextLinkTransformationsPlugin extends TransformationsPlugin
$url = (isset($options[0]) ? $options[0] : '') . ((isset($options[2]) && $options[2]) ? '' : $buffer);
$parsed = parse_url($url);
/* Do not allow javascript links */
if (isset($parsed['scheme']) && $parsed['scheme'] == 'javascript') {
if (! isset($parsed['scheme']) || ! in_array(strtolower($parsed['scheme']), array('http', 'https', 'ftp', 'mailto'))) {
return htmlspecialchars($url);
}
return '<a href="'
. htmlspecialchars($url)
. '" title="'
. htmlspecialchars(isset($options[1]) ? $options[1] : '')
. '" target="_new">'
. '" target="_blank" rel="noopener noreferrer">'
. htmlspecialchars(isset($options[1]) ? $options[1] : $buffer)
. '</a>';
}

View File

@ -261,7 +261,7 @@ function PMA_getTablePositions($pg)
1 AS `H`
FROM " . PMA\libraries\Util::backquote($cfgRelation['db'])
. "." . PMA\libraries\Util::backquote($cfgRelation['table_coords']) . "
WHERE pdf_page_number = " . $pg;
WHERE pdf_page_number = " . intval($pg);
$tab_pos = $GLOBALS['dbi']->fetchResult(
$query,
@ -290,7 +290,7 @@ function PMA_getPageName($pg)
$query = "SELECT `page_descr`"
. " FROM " . PMA\libraries\Util::backquote($cfgRelation['db'])
. "." . PMA\libraries\Util::backquote($cfgRelation['pdf_pages'])
. " WHERE " . PMA\libraries\Util::backquote('page_nr') . " = " . $pg;
. " WHERE " . PMA\libraries\Util::backquote('page_nr') . " = " . intval($pg);
$page_name = $GLOBALS['dbi']->fetchResult(
$query,
null,
@ -317,7 +317,7 @@ function PMA_deletePage($pg)
$query = "DELETE FROM " . PMA\libraries\Util::backquote($cfgRelation['db'])
. "." . PMA\libraries\Util::backquote($cfgRelation['table_coords'])
. " WHERE " . PMA\libraries\Util::backquote('pdf_page_number') . " = " . $pg;
. " WHERE " . PMA\libraries\Util::backquote('pdf_page_number') . " = " . intval($pg);
$success = PMA_queryAsControlUser(
$query, true, PMA\libraries\DatabaseInterface::QUERY_STORE
);
@ -325,7 +325,7 @@ function PMA_deletePage($pg)
if ($success) {
$query = "DELETE FROM " . PMA\libraries\Util::backquote($cfgRelation['db'])
. "." . PMA\libraries\Util::backquote($cfgRelation['pdf_pages'])
. " WHERE " . PMA\libraries\Util::backquote('page_nr') . " = " . $pg;
. " WHERE " . PMA\libraries\Util::backquote('page_nr') . " = " . intval($pg);
$success = PMA_queryAsControlUser(
$query, true, PMA\libraries\DatabaseInterface::QUERY_STORE
);
@ -364,7 +364,7 @@ function PMA_getDefaultPage($db)
);
if (count($default_page_no)) {
return $default_page_no[0];
return intval($default_page_no[0]);
}
return -1;
}
@ -406,7 +406,7 @@ function PMA_getLoadingPage($db)
$page_no = $min_page_no[0];
}
}
return $page_no;
return intval($page_no);
}
/**

View File

@ -1665,7 +1665,7 @@ function PMA_REL_renameTable($source_db, $target_db, $source_table, $target_tabl
* @param array $cfgRelation Relation configuration
* @param string $db database name
*
* @return string $pdf_page_number
* @return int $pdf_page_number
*/
function PMA_REL_createPage($newpage, $cfgRelation, $db)
{

View File

@ -293,13 +293,13 @@ function PMA_Replication_connectToMaster(
$user, $password, $host = null, $port = null, $socket = null
) {
$server = array();
$server["host"] = $host;
$server["host"] = PMA_sanitizeMySQLHost($host);
$server["port"] = $port;
$server["socket"] = $socket;
// 5th parameter set to true means that it's an auxiliary connection
// and we must not go back to login page if it fails
return $GLOBALS['dbi']->connect($user, $password, false, $server, true);
return PMA_DBI_connect($user, $password, false, $server, true);
}
/**
* Fetches position and file of current binary log on master

View File

@ -548,7 +548,7 @@ function PMA_getHtmlForReplicationStatusTable($type, $hidden = false, $title = t
foreach (${"{$type}_variables"} as $variable) {
$html .= ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">';
$html .= ' <td class="name">';
$html .= $variable;
$html .= htmlspecialchars($variable);
$html .= ' </td>';
$html .= ' <td class="value">';
@ -571,13 +571,13 @@ function PMA_getHtmlForReplicationStatusTable($type, $hidden = false, $title = t
'Replicate_Do_Table', 'Replicate_Ignore_Table',
'Replicate_Wild_Do_Table', 'Replicate_Wild_Ignore_Table');
if (in_array($variable, $variables_wrap)) {
$html .= str_replace(
$html .= htmlspecialchars(str_replace(
',',
', ',
${"server_{$type}_replication"}[0][$variable]
);
));
} else {
$html .= ${"server_{$type}_replication"}[0][$variable];
$html .= htmlspecialchars(${"server_{$type}_replication"}[0][$variable]);
}
$html .= '</span>';
@ -806,7 +806,7 @@ function PMA_getHtmlForAddUserLoginForm($username_length)
. (empty($_REQUEST['username']) ? '' : ' value="'
. (isset($GLOBALS['new_username'])
? $GLOBALS['new_username']
: $_REQUEST['username']) . '"')
: htmlspecialchars($_REQUEST['username'])) . '"')
. ' />'
. '</div>';
@ -836,7 +836,7 @@ function PMA_getHtmlForTableInfoForm($hostname_length)
. '</span>'
. '<input type="text" name="hostname" id="pma_hostname" maxlength="'
. $hostname_length . '" value="'
. (isset($_REQUEST['hostname']) ? $_REQUEST['hostname'] : '')
. (isset($_REQUEST['hostname']) ? htmlspecialchars($_REQUEST['hostname']) : '')
. '" title="' . __('Host')
. '" />'
. PMA\libraries\Util::showHint(

View File

@ -54,6 +54,9 @@ function PMA_replaceBBLink($found)
$target = '';
if (! empty($found[3])) {
$target = ' target="' . $found[3] . '"';
if ($found[3] == '_blank') {
$target .= ' rel="noopener noreferrer"';
}
}
/* Construct url */

View File

@ -2400,13 +2400,13 @@ function PMA_getHtmlTableBodyForSpecificDbRoutinePrivs($db, $odd_row, $index_che
. 'id="checkbox_sel_users_' . ($index_checkbox++) . '" '
. 'value="' . $value . '" /></td>';
$html_output .= '<td>' . $row['User']
$html_output .= '<td>' . htmlspecialchars($row['User'])
. '</td>'
. '<td>' . $row['Host']
. '<td>' . htmlspecialchars($row['Host'])
. '</td>'
. '<td>' . 'routine'
. '</td>'
. '<td>' . '<code>' . $row['Routine_name'] . '</code>'
. '<td>' . '<code>' . htmlspecialchars($row['Routine_name']) . '</code>'
. '</td>'
. '<td>' . 'Yes'
. '</td>';

View File

@ -284,7 +284,7 @@ function PMA_getHtmlForRenderVariables($ServerStatusData, $alerts, $strShowStatu
$retval .= '<span class="allfine">';
}
}
$retval .= $value;
$retval .= htmlspecialchars($value);
if (isset($alerts[$name])) {
$retval .= '</span>';
}

View File

@ -351,7 +351,7 @@ function PMA_editUserGroup($userGroup, $new = false)
}
$tabName = $tabGroupName . '_' . $tab;
$allowed = isset($_REQUEST[$tabName]) && $_REQUEST[$tabName] == 'Y';
$sql_query .= "('" . $userGroup . "', '" . $tabName . "', '"
$sql_query .= "('" . PMA_Util::sqlAddSlashes($userGroup) . "', '" . $tabName . "', '"
. ($allowed ? "Y" : "N") . "')";
$first = false;
}

View File

@ -73,7 +73,23 @@ function PMA_sessionFailed($errors)
{
$messages = array();
foreach ($errors as $error) {
$messages[] = $error->getMessage();
/*
* Remove path from open() in error message to avoid path disclossure
*
* This can happen with PHP 5 when nonexisting session ID is provided,
* since PHP 7, session existence is checked first.
*
* This error can also happen in case of session backed error (eg.
* read only filesystem) on any PHP version.
*
* The message string is currently hardcoded in PHP, so hopefully it
* will not change in future.
*/
$messages[] = preg_replace(
'/open(.*, O_RDWR)/',
'open(SESSION_FILE, O_RDWR)',
$error->getMessage()
);
}
/*

View File

@ -388,9 +388,7 @@ function PMA_getHtmlForTableVersionDetails(
function PMA_getTableLastVersionNumber($sql_result)
{
$maxversion = $GLOBALS['dbi']->fetchArray($sql_result);
$last_version = $maxversion['version'];
return $last_version;
return intval($maxversion['version']);
}
/**
@ -862,7 +860,10 @@ function PMA_getHtmlForSchemaSnapshot($url_query)
);
// Unserialize snapshot
$temp = unserialize($data['schema_snapshot']);
$temp = PMA_safeUnserialize($data['schema_snapshot']);
if ($temp === null) {
$temp = array('COLUMNS' => array(), 'INDEXES' => array());
}
$columns = $temp['COLUMNS'];
$indexes = $temp['INDEXES'];
$html .= PMA_getHtmlForColumns($columns);

View File

@ -143,19 +143,18 @@ function PMA_getNoOfFilesInZip($file)
/**
* Extracts a set of files from the given zip archive to a given destinations.
*
* @param string $zip_path path to the zip archive
* @param string $destination destination to extract files
* @param array $entries files in archive that should be extracted
* @param string $zip_path path to the zip archive
* @param string $entry file in the archive that should be extracted
*
* @return bool true on success, false otherwise
* @return string|bool data on sucess, false otherwise
*/
function PMA_zipExtract($zip_path, $destination, $entries)
function PMA_zipExtract($zip_path, $entry)
{
$zip = new ZipArchive;
if ($zip->open($zip_path) === true) {
$zip->extractTo($destination, $entries);
$result = $zip->getFromName($entry);
$zip->close();
return true;
return $result;
}
return false;
}

View File

@ -7,6 +7,8 @@
*/
use PMA\libraries\Linter;
$_GET['ajax_request'] = 'true';
/**
* Loading common files. Used to check for authorization, localization and to
* load the parsing library.

View File

@ -26,7 +26,7 @@ if (isset($_REQUEST['getColumns'])) {
exit;
}
if (isset($_REQUEST['splitColumn'])) {
$num_fields = $_REQUEST['numFields'];
$num_fields = min(4096, intval($_REQUEST['numFields']));
$html = PMA_getHtmlForCreateNewColumn($num_fields, $db, $table);
$html .= PMA_URL_getHiddenInputs($db, $table);
echo $html;

View File

@ -1,20 +0,0 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* phpinfo() wrapper to allow displaying only when configured to do so.
*
* @package PhpMyAdmin
*/
/**
* Gets core libraries and defines some variables
*/
require_once 'libraries/common.inc.php';
PMA\libraries\Response::getInstance()->disable();
/**
* Displays PHP information
*/
if ($GLOBALS['cfg']['ShowPhpInfo']) {
phpinfo();
}

View File

@ -48,7 +48,6 @@
<directory suffix=".php">libraries/bfShapeFiles</directory>
<directory suffix=".php">libraries/php-gettext</directory>
<directory suffix=".php">libraries/phpseclib</directory>
<directory suffix=".php">libraries/plugins/auth/swekey/</directory>
<directory suffix=".php">libraries/sql-parser</directory>
<directory suffix=".php">libraries/tcpdf</directory>
<!-- examples for users -->

View File

@ -42,10 +42,13 @@ if (isset($_REQUEST['submit_num_fields'])) {
if (isset($_REQUEST['orig_field_where'])) {
$_REQUEST['field_where'] = $_REQUEST['orig_field_where'];
}
$num_fields = $_REQUEST['orig_num_fields'] + $_REQUEST['added_fields'];
$num_fields = min(
intval($_REQUEST['orig_num_fields']) + intval($_REQUEST['added_fields']),
4096
);
$regenerate = true;
} elseif (isset($_REQUEST['num_fields']) && intval($_REQUEST['num_fields']) > 0) {
$num_fields = (int) $_REQUEST['num_fields'];
$num_fields = min(4096, intval($_REQUEST['num_fields']));
} else {
$num_fields = 1;
}

View File

@ -21,6 +21,10 @@
? ' target="' . $url['target'] . '"'
: null;
?>
<?= !empty($url['target']) && $url['target'] == '_blank'
? ' rel="noopener noreferrer"'
: null;
?>
<?= !empty($url['id']) ? ' id="' . $url['id'] . '"' : null; ?>
<?= !empty($url['class'])
? ' class="' . $url['class'] . '"'

View File

@ -15,7 +15,7 @@
<input type="hidden" name="dbstats" value="1" />
<?php endif; ?>
<input type="text" name="new_db" value="<?= $GLOBALS['db_to_create']; ?>"
<input type="text" name="new_db" value="<?= htmlspecialchars($GLOBALS['db_to_create']); ?>"
maxlength="64" class="textfield" id="text_create_db" required
placeholder="<?= __('Database name'); ?>" />
<?= PMA_generateCharsetDropdownBox(PMA_CSDROPDOWN_COLLATION, 'db_collation', null, null, true); ?>
@ -33,4 +33,4 @@
</span>
<?php endif; ?>
</li>
</ul>
</ul>

View File

@ -10,8 +10,8 @@
<select name="visualizationSettings[labelColumn]" id="labelColumn" class="autosubmit">
<option value=""><?= __("-- None --"); ?></option>
<?php foreach ($labelCandidates as $value): ?>
<option value="<?= $value; ?>" <?= ($value == $visualizationSettings['labelColumn'] ? 'selected="selected"' : ''); ?>>
<?= $value; ?>
<option value="<?= htmlspecialchars($value); ?>" <?= ($value == $visualizationSettings['labelColumn'] ? 'selected="selected"' : ''); ?>>
<?= htmlspecialchars($value); ?>
</option>
<?php endforeach; ?>
</select>
@ -20,8 +20,8 @@
</label>
<select name="visualizationSettings[spatialColumn]" id="spatialColumn" class="autosubmit">
<?php foreach ($spatialCandidates as $value): ?>
<option value="<?= $value; ?>" <?= ($value == $visualizationSettings['spatialColumn'] ? 'selected="selected"' : ''); ?>>
<?= $value; ?>
<option value="<?= htmlspecialchars($value); ?>" <?= ($value == $visualizationSettings['spatialColumn'] ? 'selected="selected"' : ''); ?>>
<?= htmlspecialchars($value); ?>
</option>
<?php endforeach; ?>
</select>

View File

@ -16,7 +16,7 @@
</a>
</center>
<div id="querydata" style="display:none">
<?= json_encode($data); ?>
<?= htmlspecialchars(json_encode($data)); ?>
</div>
<div id="querychart"></div>
<button class="button-reset">
@ -96,4 +96,4 @@
</table>
</div>
<input type="hidden" id="queryID" name="sql_query" />
</form>
</form>

View File

@ -186,7 +186,7 @@ $rownum = 0; $odd_row = true; ?>
$tmp_partition_description = $firstPartition->getDescription();
$removeSQL = "ALTER TABLE " . Util::backquote($table) . " REMOVE PARTITIONING";
$removeUrl = 'sql.php' . $url_query . '&sql_query=' . urldecode($removeSQL);
$removeUrl = 'sql.php' . $url_query . '&sql_query=' . urlencode($removeSQL);
echo Template::get('table/structure/display_partitions')->render(
array(
@ -222,4 +222,4 @@ $rownum = 0; $odd_row = true; ?>
<?php if ($GLOBALS['cfg']['ShowStats']): ?>
<?= $tablestats; ?>
<?php endif; ?>
<div class="clearfloat"></div>
<div class="clearfloat"></div>

View File

@ -1385,7 +1385,7 @@ class DisplayResultsTest extends PMATestCase
$meta,
$url_params,
null,
'<a href="1001" title="" target="_new">1001</a>'
'1001'
),
array(
false,
@ -1514,7 +1514,7 @@ class DisplayResultsTest extends PMATestCase
0,
'binary',
'<td class="left grid_edit transformed hex">'
. '<a href="1001" title="" target="_new">1001</a></td>'
. '1001</td>'
),
array(
'noblob',

View File

@ -252,7 +252,7 @@ class PbxtTest extends PMATestCase
. ' can be found on the %sPrimeBase XT Home Page%s.'
),
'<a href="' . PMA_linkURL('https://mariadb.com/kb/en/mariadb/about-pbxt/')
. '" target="_blank">',
. '" rel="noopener noreferrer" target="_blank">',
'</a>'
)
. '</p>' . "\n"

View File

@ -404,22 +404,6 @@ class AuthenticationCookieTest extends PMATestCase
$attrInstance->setValue($restoreInstance);
}
/**
* Test for PMA\libraries\plugins\auth\AuthenticationConfig::authCheck
*
* @return void
*/
public function testAuthCheckSwekey()
{
$GLOBALS['cfg']['Server']['auth_swekey_config'] = 'testConfigSwekey';
file_put_contents('testConfigSwekey', '');
$this->assertFalse(
$this->object->authCheck()
);
@unlink('testConfigSwekey');
}
/**
* Test for PMA\libraries\plugins\auth\AuthenticationConfig::authCheck
*
@ -427,7 +411,6 @@ class AuthenticationCookieTest extends PMATestCase
*/
public function testAuthCheckCaptcha()
{
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = 'testprivkey';
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = 'testpubkey';
$_POST["g-recaptcha-response"] = '';
@ -470,18 +453,17 @@ class AuthenticationCookieTest extends PMATestCase
$attrInstance->setAccessible(true);
$attrInstance->setValue($mockResponse);
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = '';
$GLOBALS['cfg']['LoginCookieDeleteAll'] = true;
$GLOBALS['cfg']['Servers'] = array(1);
$_COOKIE['pmaPass-0'] = 'test';
$_COOKIE['pmaAuth-0'] = 'test';
$this->object->logOut();
$this->assertFalse(
isset($_COOKIE['pmaPass-0'])
isset($_COOKIE['pmaAuth-0'])
);
$attrInstance->setValue($restoreInstance);
}
@ -512,19 +494,18 @@ class AuthenticationCookieTest extends PMATestCase
$attrInstance = new ReflectionProperty('PMA\libraries\Response', '_instance');
$attrInstance->setAccessible(true);
$attrInstance->setValue($mockResponse);
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = '';
$GLOBALS['cfg']['LoginCookieDeleteAll'] = false;
$GLOBALS['cfg']['Servers'] = array(1);
$GLOBALS['server'] = 1;
$_COOKIE['pmaPass-1'] = 'test';
$_COOKIE['pmaAuth-1'] = 'test';
$this->object->logOut();
$this->assertFalse(
isset($_COOKIE['pmaPass-1'])
isset($_COOKIE['pmaAuth-1'])
);
$attrInstance->setValue($restoreInstance);
}
@ -536,7 +517,6 @@ class AuthenticationCookieTest extends PMATestCase
*/
public function testAuthCheckArbitrary()
{
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = '';
$_REQUEST['old_usr'] = '';
@ -565,7 +545,7 @@ class AuthenticationCookieTest extends PMATestCase
);
$this->assertFalse(
isset($_COOKIE['pmaPass-1'])
isset($_COOKIE['pmaAuth-1'])
);
}
@ -574,26 +554,19 @@ class AuthenticationCookieTest extends PMATestCase
*
* @return void
*/
public function testAuthCheckIV()
public function testAuthCheckInvalidCookie()
{
$GLOBALS['cfg']['AllowArbitraryServer'] = true;
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
$_REQUEST['pma_servername'] = 'testPMAServer';
$_REQUEST['pma_password'] = 'testPMAPSWD';
$_REQUEST['pma_username'] = '';
$GLOBALS['server'] = 1;
$_COOKIE['pmaServer-1'] = 'pmaServ1';
$_COOKIE['pmaUser-1'] = '';
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
$this->assertFalse(
$this->object->authCheck()
);
$this->assertEquals(
'pmaServ1',
$GLOBALS['pma_auth_server']
);
}
/**
@ -603,12 +576,11 @@ class AuthenticationCookieTest extends PMATestCase
*/
public function testAuthCheckExpires()
{
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
$GLOBALS['server'] = 1;
$_COOKIE['pmaServer-1'] = 'pmaServ1';
$_COOKIE['pmaUser-1'] = 'pmaUser1';
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
$_COOKIE['pmaPass-1'] = '';
$_COOKIE['pmaAuth-1'] = '';
$GLOBALS['cfg']['blowfish_secret'] = 'secret';
$_SESSION['last_access_time'] = time() - 1000;
$GLOBALS['cfg']['LoginCookieValidity'] = 1440;
@ -625,7 +597,6 @@ class AuthenticationCookieTest extends PMATestCase
*/
public function testAuthCheckDecryptUser()
{
$GLOBALS['cfg']['Server']['auth_swekey_config'] = 'testConfigSwekey';
$GLOBALS['server'] = 1;
$_REQUEST['old_usr'] = '';
$_REQUEST['pma_username'] = '';
@ -664,13 +635,12 @@ class AuthenticationCookieTest extends PMATestCase
*/
public function testAuthCheckDecryptPassword()
{
$GLOBALS['cfg']['Server']['auth_swekey_config'] = 'testConfigSwekey';
$GLOBALS['server'] = 1;
$_REQUEST['old_usr'] = '';
$_REQUEST['pma_username'] = '';
$_COOKIE['pmaServer-1'] = 'pmaServ1';
$_COOKIE['pmaUser-1'] = 'pmaUser1';
$_COOKIE['pmaPass-1'] = 'pmaPass1';
$_COOKIE['pmaAuth-1'] = 'pmaAuth1';
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
$GLOBALS['cfg']['blowfish_secret'] = 'secret';
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
@ -686,7 +656,7 @@ class AuthenticationCookieTest extends PMATestCase
$this->object->expects($this->at(1))
->method('cookieDecrypt')
->will($this->returnValue("\xff(blank)"));
->will($this->returnValue('{"password":""}'));
$this->assertTrue(
$this->object->authCheck()
@ -710,7 +680,6 @@ class AuthenticationCookieTest extends PMATestCase
*/
public function testAuthCheckAuthFails()
{
$GLOBALS['cfg']['Server']['auth_swekey_config'] = 'testConfigSwekey';
$GLOBALS['server'] = 1;
$_REQUEST['old_usr'] = '';
$_REQUEST['pma_username'] = '';
@ -785,7 +754,7 @@ class AuthenticationCookieTest extends PMATestCase
);
$this->assertTrue(
isset($_COOKIE['pmaPass-1'])
isset($_COOKIE['pmaAuth-1'])
);
$arr['password'] = 'testPW';
@ -857,10 +826,6 @@ class AuthenticationCookieTest extends PMATestCase
$this->object->authSetUser();
$this->object->storeUserCredentials();
$this->assertTrue(
isset($_COOKIE['pmaServer-2'])
);
$attrInstance->setValue($restoreInstance);
}
@ -908,7 +873,7 @@ class AuthenticationCookieTest extends PMATestCase
->getMock();
$GLOBALS['server'] = 2;
$_COOKIE['pmaPass-2'] = 'pass';
$_COOKIE['pmaAuth-2'] = 'pass';
$GLOBALS['login_without_password_is_forbidden'] = '1';
@ -933,7 +898,7 @@ class AuthenticationCookieTest extends PMATestCase
->getMock();
$GLOBALS['server'] = 2;
$_COOKIE['pmaPass-2'] = 'pass';
$_COOKIE['pmaAuth-2'] = 'pass';
$GLOBALS['login_without_password_is_forbidden'] = '';
$GLOBALS['allowDeny_forbidden'] = '1';
@ -957,7 +922,7 @@ class AuthenticationCookieTest extends PMATestCase
->getMock();
$GLOBALS['server'] = 2;
$_COOKIE['pmaPass-2'] = 'pass';
$_COOKIE['pmaAuth-2'] = 'pass';
$GLOBALS['allowDeny_forbidden'] = '';
@ -983,7 +948,7 @@ class AuthenticationCookieTest extends PMATestCase
->getMock();
$GLOBALS['server'] = 2;
$_COOKIE['pmaPass-2'] = 'pass';
$_COOKIE['pmaAuth-2'] = 'pass';
$dbi = $this->getMockBuilder('PMA\libraries\DatabaseInterface')
@ -1026,7 +991,7 @@ class AuthenticationCookieTest extends PMATestCase
$GLOBALS['dbi'] = $dbi;
$GLOBALS['server'] = 2;
$_COOKIE['pmaPass-2'] = 'pass';
$_COOKIE['pmaAuth-2'] = 'pass';
unset($GLOBALS['errno']);
@ -1065,7 +1030,7 @@ class AuthenticationCookieTest extends PMATestCase
);
$this->assertEquals(
256,
32,
strlen($result)
);
}
@ -1088,7 +1053,7 @@ class AuthenticationCookieTest extends PMATestCase
$result = $method->invoke($this->object, null);
$this->assertEquals(
md5('notEmpty'),
'notEmpty',
$result
);
}
@ -1103,7 +1068,7 @@ class AuthenticationCookieTest extends PMATestCase
$this->object->setIV('testiv09testiv09');
// works with the openssl extension active or inactive
$this->assertEquals(
'+coP/up/ZBTBwbiEpCUVXQ==',
'{"iv":"dGVzdGl2MDl0ZXN0aXYwOQ==","mac":"34367a80e4276906637b5eaecf8c3931547aae68","payload":"+coP\/up\/ZBTBwbiEpCUVXQ=="}',
$this->object->cookieEncrypt('data123', 'sec321')
);
}
@ -1115,16 +1080,101 @@ class AuthenticationCookieTest extends PMATestCase
*/
public function testCookieDecrypt()
{
$this->object->setIV('testiv09testiv09');
// works with the openssl extension active or inactive
$this->assertEquals(
'data123',
$this->object->cookieDecrypt(
'+coP/up/ZBTBwbiEpCUVXQ==',
'{"iv":"dGVzdGl2MDl0ZXN0aXYwOQ==","mac":"34367a80e4276906637b5eaecf8c3931547aae68","payload":"+coP\/up\/ZBTBwbiEpCUVXQ=="}',
'sec321'
)
);
}
/**
* Test for PMA\libraries\plugins\auth\AuthenticationConfig::cookieDecrypt
*
* @return void
*/
public function testCookieDecryptInvalid()
{
// works with the openssl extension active or inactive
$this->assertEquals(
false,
$this->object->cookieDecrypt(
'{"iv":0,"mac":0,"payload":0}',
'sec321'
)
);
}
/**
* Test for secret splitting using getAESSecret
*
* @return void
*
* @dataProvider secretsProvider
*/
public function testMACSecretSplit($secret, $mac, $aes)
{
$this->assertEquals(
$mac,
$this->object->getMACSecret($secret)
);
}
/**
* Test for secret splitting using getMACSecret and getAESSecret
*
* @return void
*
* @dataProvider secretsProvider
*/
public function testAESSecretSplit($secret, $mac, $aes)
{
$this->assertEquals(
$aes,
$this->object->getAESSecret($secret)
);
}
/**
* Data provider for secrets splitting.
*
* @return array
*/
public function secretsProvider()
{
return array(
// Optimal case
array(
'1234567890123456abcdefghijklmnop',
'1234567890123456',
'abcdefghijklmnop',
),
// Overlapping secret
array(
'12345678901234567',
'1234567890123456',
'2345678901234567',
),
// Short secret
array(
'1234567890123456',
'1234567890123451',
'2345678901234562',
),
// Really short secret
array(
'12',
'1111111111111111',
'2222222222222222',
),
// Too short secret
array(
'1',
'1111111111111111',
'1111111111111111',
),
);
}
}

View File

@ -163,7 +163,7 @@ class ExportPhparrayTest extends PMATestCase
*/
public function testExportDBHeader()
{
$GLOBALS['crlf'] = ' ';
$GLOBALS['crlf'] = "\n";
ob_start();
$this->assertTrue(
@ -172,7 +172,7 @@ class ExportPhparrayTest extends PMATestCase
$result = ob_get_clean();
$this->assertContains(
'// Database `db` ',
"/**\n * Database `db`\n */",
$result
);
}
@ -253,7 +253,7 @@ class ExportPhparrayTest extends PMATestCase
$result = ob_get_clean();
$this->assertEquals(
"\n" . '// `db`.`table`' . "\n" .
"\n" . '/* `db`.`table` */' . "\n" .
'$table = array(' . "\n" .
' array(\'c1\' => 1,\'\' => \'a\')' . "\n" .
');' . "\n",

View File

@ -529,6 +529,8 @@ class ExportXmlTest extends PMATestCase
public function testExportData()
{
$GLOBALS['xml_export_contents'] = true;
$GLOBALS['asfile'] = true;
$GLOBALS['output_charset_conversion'] = false;
$dbi = $this->getMockBuilder('PMA\libraries\DatabaseInterface')
->disableOriginalConstructor()
@ -587,33 +589,33 @@ class ExportXmlTest extends PMATestCase
$result = ob_get_clean();
$this->assertContains(
"&lt;!-- Table ta&lt;ble --&gt;",
"<!-- Table ta&lt;ble -->",
$result
);
$this->assertContains(
"&lt;table name=&quot;ta&amp;lt;ble&quot;&gt;",
"<table name=\"ta&lt;ble\">",
$result
);
$this->assertContains(
"&lt;column name=&quot;fName1&quot;&gt;NULL&lt;/column&gt;",
"<column name=\"fName1\">NULL</column>",
$result
);
$this->assertContains(
"&lt;column name=&quot;fNa&amp;quot;me2&quot;&gt;&amp;lt;a&amp;gt;" .
"&lt;/column&gt;",
"<column name=\"fNa&quot;me2\">&lt;a&gt;" .
"</column>",
$result
);
$this->assertContains(
"&lt;column name=&quot;fName3&quot;&gt;NULL&lt;/column&gt;",
"<column name=\"fName3\">NULL</column>",
$result
);
$this->assertContains(
"&lt;/table&gt;",
"</table>",
$result
);
}

View File

@ -778,8 +778,8 @@ class TransformationPluginsTest extends PMATestCase
array("./image/", "200", "wrapper_link"=>"PMA_wrapper_link")
),
'<a href="transformation_wrapper.phpPMA_wrapper_link" '
. 'target="_blank"><img src="transformation_wrapper.php'
. 'PMA_wrapper_link&amp;resize=jpeg&amp;newWidth=./image/&amp;'
. 'rel="noopener noreferrer" target="_blank"><img src="transformation_wrapper.php'
. 'PMA_wrapper_link&amp;resize=jpeg&amp;newWidth=0&amp;'
. 'newHeight=200" alt="[PMA_JPEG_Inline]" border="0" /></a>'
),
array(
@ -788,7 +788,7 @@ class TransformationPluginsTest extends PMATestCase
'PMA_IMAGE_LINK',
array("./image/", "200", "wrapper_link"=>"PMA_wrapper_link")
),
'<a class="disableAjax" target="_new"'
'<a class="disableAjax" target="_blank" rel="noopener noreferrer"'
. ' href="transformation_wrapper.phpPMA_wrapper_link"'
. ' alt="[PMA_IMAGE_LINK]">[BLOB]</a>'
),
@ -799,9 +799,9 @@ class TransformationPluginsTest extends PMATestCase
array("./image/", "200", "wrapper_link"=>"PMA_wrapper_link")
),
'<a href="transformation_wrapper.phpPMA_wrapper_link"'
. ' target="_blank"><img src="transformation_wrapper.php'
. ' rel="noopener noreferrer" target="_blank"><img src="transformation_wrapper.php'
. 'PMA_wrapper_link&amp;'
. 'resize=jpeg&amp;newWidth=./image/&amp;newHeight=200" '
. 'resize=jpeg&amp;newWidth=0&amp;newHeight=200" '
. 'alt="[PMA_PNG_Inline]" border="0" /></a>'
),
array(
@ -866,7 +866,25 @@ class TransformationPluginsTest extends PMATestCase
"<a ref='https://www.example.com/'>PMA_BUFFER</a>",
array("option1", "option2")
),
"<a ref='https://www.example.com/'>PMA_BUFFER</a>"
"<iframe srcdoc=\"<a ref='https://www.example.com/'>PMA_BUFFER</a>\" sandbox=\"\"></iframe>"
),
array(
new Text_Plain_Formatted(),
array(
"<a ref=\"https://www.example.com/\">PMA_BUFFER</a>",
array("option1", "option2")
),
"<iframe srcdoc=\"<a ref='https://www.example.com/'>PMA_BUFFER</a>\" sandbox=\"\"></iframe>"
),
array(
new Text_Plain_Imagelink(),
array(
'PMA_IMAGE',
array("http://image/", "200")
),
'<a href="http://image/PMA_IMAGE" rel="noopener noreferrer" target="_blank">'
. '<img src="http://image/PMA_IMAGE" border="0" width="200" '
. 'height="50" />PMA_IMAGE</a>'
),
array(
new Text_Plain_Imagelink(),
@ -874,9 +892,7 @@ class TransformationPluginsTest extends PMATestCase
'PMA_IMAGE',
array("./image/", "200")
),
'<a href="./image/PMA_IMAGE" target="_blank">'
. '<img src="./image/PMA_IMAGE" border="0" width="200" '
. 'height="50" />PMA_IMAGE</a>'
'./image/PMA_IMAGE'
),
array(
new Text_Plain_Sql(),
@ -894,8 +910,32 @@ class TransformationPluginsTest extends PMATestCase
'PMA_TXT_LINK',
array("./php/", "text_name")
),
'<a href="./php/PMA_TXT_LINK"'
. ' title="text_name" target="_new">text_name</a>'
'./php/PMA_TXT_LINK'
),
array(
new Text_Plain_Link(),
array(
'PMA_TXT_LINK',
array(),
),
'PMA_TXT_LINK'
),
array(
new Text_Plain_Link(),
array(
'https://example.com/PMA_TXT_LINK',
array(),
),
'<a href="https://example.com/PMA_TXT_LINK" title=""'
. ' target="_blank" rel="noopener noreferrer">https://example.com/PMA_TXT_LINK</a>'
),
array(
new Text_Plain_Link(),
array(
'PMA_TXT_LINK',
array("./php/", "text_name")
),
'./php/PMA_TXT_LINK'
),
array(
new Text_Plain_Longtoipv4(),

View File

@ -51,32 +51,58 @@ class PMA_Ip_Allow_Deny_Test extends PHPUnit_Framework_TestCase
* Test for PMA_getIp
*
* @return void
*
* @dataProvider proxyIPs
*/
public function testGetIp()
public function testGetIp($remote, $header, $expected, $proxyip = null)
{
//$_SERVER['REMOTE_ADDR'] is empty
unset($_SERVER['REMOTE_ADDR']);
unset($_SERVER['TEST_FORWARDED_HEADER']);
$GLOBALS['cfg']['TrustedProxies'] = array();
if (!is_null($remote)) {
$_SERVER['REMOTE_ADDR'] = $remote;
}
if (!is_null($header)) {
if (is_null($proxyip)) {
$proxyip = $remote;
}
$GLOBALS['cfg']['TrustedProxies'][$proxyip] = 'TEST_FORWARDED_HEADER';
$_SERVER['TEST_FORWARDED_HEADER'] = $header;
}
$this->assertEquals(
false,
$expected,
PMA_getIp()
);
$_SERVER['REMOTE_ADDR'] = "101.0.0.25";
$this->assertEquals(
"101.0.0.25",
PMA_getIp()
);
unset($_SERVER['REMOTE_ADDR']);
unset($_SERVER['TEST_FORWARDED_HEADER']);
$GLOBALS['cfg']['TrustedProxies'] = array();
}
//proxy
$var_name = "direct_ip";
$direct_ip = $_SERVER['REMOTE_ADDR'];
$GLOBALS['cfg']['TrustedProxies'][$direct_ip] = $var_name;
$_SERVER[$var_name] = "192.168.0.1";
$this->assertEquals(
"192.168.0.1",
PMA_getIp()
/**
* Data provider for PMA_getIp tests
*
* @return array
*/
public function proxyIPs()
{
return array(
// Nothing set
array(null, null, false),
// Remote IP set
array('101.0.0.25', null, '101.0.0.25'),
// Proxy
array('101.0.0.25', '192.168.10.10', '192.168.10.10'),
// Several proxies
array('101.0.0.25', '192.168.10.1, 192.168.100.100', '192.168.10.1'),
// Invalid proxy
array('101.0.0.25', 'invalid', false),
// Direct IP with proxy enabled
array('101.0.0.25', '192.168.10.10', '101.0.0.25', '10.10.10.10'),
);
unset($_SERVER[$var_name]);
unset($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
}
/**

View File

@ -118,10 +118,16 @@ class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
public function testZipExtract()
{
$this->assertEquals(
false,
PMA_zipExtract(
'./test/test_data/test.zip', './test/test_data/', 'wrongName'
),
true
'./test/test_data/test.zip', 'wrongName'
)
);
$this->assertEquals(
"TEST FILE\n",
PMA_zipExtract(
'./test/test_data/test.zip', 'test.file'
)
);
}

View File

@ -0,0 +1,53 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Test for PMA_isAllowedDomain
*
* @package PhpMyAdmin-test
*/
/*
* Include to test.
*/
require_once 'libraries/core.lib.php';
class PMA_isAllowedDomain_test extends PHPUnit_Framework_TestCase
{
/**
* Test for unserializing
*
* @param string $url URL to test
* @param mixed $expected Expected result
*
* @return void
*
* @dataProvider provideURLs
*/
function testIsAllowedDomain($url, $expected)
{
$_SERVER['SERVER_NAME'] = 'server.local';
$this->assertEquals(
$expected,
PMA_isAllowedDomain($url)
);
}
/**
* Test data provider
*
* @return array
*/
function provideURLs()
{
return array(
array('https://www.phpmyadmin.net/', true),
array('http://duckduckgo.com\\@github.com', false),
array('https://github.com/', true),
array('https://server.local/', true),
array('./relative/', false),
);
}
}

View File

@ -0,0 +1,55 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Test for PMA_safeUnserialize
*
* @package PhpMyAdmin-test
*/
/*
* Include to test.
*/
require_once 'libraries/core.lib.php';
class PMA_safeUnserialize_test extends PHPUnit_Framework_TestCase
{
/**
* Test for unserializing
*
* @param string $data Serialized data
* @param mixed $expected Expected result
*
* @return void
*
* @dataProvider provideMySQLHosts
*/
function testSanitizeMySQLHost($data, $expected)
{
$this->assertEquals(
$expected,
PMA_safeUnserialize($data)
);
}
/**
* Test data provider
*
* @return array
*/
function provideMySQLHosts()
{
return array(
array('s:6:"foobar";', 'foobar'),
array('foobar', null),
array('b:0;', false),
array('O:1:"a":1:{s:5:"value";s:3:"100";}', null),
array('O:8:"stdClass":1:{s:5:"field";O:8:"stdClass":0:{}}', null),
array(serialize(array(1, 2, 3)), array(1, 2, 3)),
array(serialize('string""'), 'string""'),
array(serialize(array('foo' => 'bar')), array('foo' => 'bar')),
array(serialize(array('1', new stdClass(), '2')), null),
);
}
}

View File

@ -0,0 +1,48 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Test for PMA_sanitizeMySQLHost
*
* @package PhpMyAdmin-test
*/
/*
* Include to test.
*/
require_once 'libraries/core.lib.php';
class PMA_sanitizeMySQLHost_test extends PHPUnit_Framework_TestCase
{
/**
* Test for MySQL host sanitizing
*
* @param string $host Test host name
* @param string $expected Expected result
*
* @return void
*
* @dataProvider provideMySQLHosts
*/
function testSanitizeMySQLHost($host, $expected)
{
$this->assertEquals(
$expected,
PMA_sanitizeMySQLHost($host)
);
}
/**
* Test data provider
*
* @return array
*/
function provideMySQLHosts()
{
return array(
array('p:foo.bar', 'foo.bar'),
array('bar.baz', 'bar.baz'),
array('P:example.com', 'example.com'),
);
}
}

View File

@ -21,7 +21,7 @@ $hash = '#pma_' . preg_replace('/([0-9]*)\.([0-9]*)\..*/', '\1_\2', PMA_VERSI
$url = PMA_linkURL('https://www.phpmyadmin.net/themes/') . $hash;
$output = '<h1>phpMyAdmin - ' . __('Theme') . '</h1>';
$output .= '<p>';
$output .= '<a href="' . $url . '" class="_blank">';
$output .= '<a href="' . $url . '" rel="noopener noreferrer" class="_blank">';
$output .= __('Get more themes!');
$output .= '</a>';
$output .= '</p>';

View File

@ -34,9 +34,20 @@ $request_params = array(
'transform_key',
'where_clause'
);
$size_params = array(
'newHeight',
'newWidth',
);
foreach ($request_params as $one_request_param) {
if (isset($_REQUEST[$one_request_param])) {
$GLOBALS[$one_request_param] = $_REQUEST[$one_request_param];
if (in_array($one_request_param, $size_params)) {
$GLOBALS[$one_request_param] = intval($_REQUEST[$one_request_param]);
if ($GLOBALS[$one_request_param] > 2000) {
$GLOBALS[$one_request_param] = 2000;
}
} else {
$GLOBALS[$one_request_param] = $_REQUEST[$one_request_param];
}
}
}
@ -91,7 +102,7 @@ $response->getHeader()->sendHttpHeaders();
if (isset($ct) && ! empty($ct)) {
$mime_type = $ct;
} else {
$mime_type = (isset($mime_map[$transform_key]['mimetype'])
$mime_type = (!empty($mime_map[$transform_key]['mimetype'])
? str_replace('_', '/', $mime_map[$transform_key]['mimetype'])
: $default_ct)
. (isset($mime_options['charset']) ? $mime_options['charset'] : '');
@ -100,7 +111,11 @@ if (isset($ct) && ! empty($ct)) {
PMA_downloadHeader($cn, $mime_type);
if (! isset($_REQUEST['resize'])) {
echo $row[$transform_key];
if (stripos($mime_type, 'html') === false) {
echo $row[$transform_key];
} else {
echo htmlspecialchars($row[$transform_key]);
}
} else {
// if image_*__inline.inc.php finds that we can resize,
// it sets the resize parameter to jpeg or png

View File

@ -16,6 +16,11 @@ require_once './libraries/common.inc.php';
*/
require_once './libraries/js_escape.lib.php';
// Only output the http headers
$response = PMA\libraries\Response::getInstance();
$response->getHeader()->sendHttpHeaders();
$response->disable();
if (! PMA_isValid($_REQUEST['url'])
|| ! preg_match('/^https:\/\/[^\n\r]*$/', $_REQUEST['url'])
|| ! PMA_isAllowedDomain($_REQUEST['url'])

View File

@ -120,6 +120,9 @@ function PMA_setChangePasswordMsg()
__('The passwords aren\'t the same!')
);
$error = true;
} elseif (strlen($_REQUEST['pma_pw']) > 256) {
$message = PMA_Message::error(__('Password is too long!'));
$error = true;
}
}
return array('error' => $error, 'msg' => $message);

Some files were not shown because too many files have changed in this diff Show More