function drupal_valid_test_ua in Drupal 10
Same name and namespace in other branches
- 8 core/includes/bootstrap.inc \drupal_valid_test_ua()
- 7 includes/bootstrap.inc \drupal_valid_test_ua()
- 9 core/includes/bootstrap.inc \drupal_valid_test_ua()
Returns the test prefix if this is an internal request from a test.
Parameters
string $new_prefix: Internal use only. A new prefix to be stored.
Return value
string|false Either the simpletest prefix (the string "simpletest" followed by any number of digits) or FALSE if the user agent does not contain a valid HMAC and timestamp.
15 calls to drupal_valid_test_ua()
- CoreServiceProvider::registerTest in core/
lib/ Drupal/ Core/ CoreServiceProvider.php - Registers services and event subscribers for a site under test.
- DrupalKernel::bootEnvironment in core/
lib/ Drupal/ Core/ DrupalKernel.php - Setup a consistent PHP environment.
- DrupalKernel::findSitePath in core/
lib/ Drupal/ Core/ DrupalKernel.php - Returns the appropriate site directory for a request.
- drupal_generate_test_ua in core/
includes/ bootstrap.inc - Generates a user agent string with a HMAC and timestamp for tests.
- ExtensionDiscovery::scan in core/
lib/ Drupal/ Core/ Extension/ ExtensionDiscovery.php - Discovers available extensions of a given type.
File
- core/
includes/ bootstrap.inc, line 214 - Functions that need to be loaded on every Drupal request.
Code
function drupal_valid_test_ua($new_prefix = NULL) {
static $test_prefix;
if (isset($new_prefix)) {
$test_prefix = $new_prefix;
}
if (isset($test_prefix)) {
return $test_prefix;
}
// Unless the below User-Agent and HMAC validation succeeds, we are not in
// a test environment.
$test_prefix = FALSE;
// A valid test request will contain a hashed and salted authentication code.
// Check if this code is present in a cookie or custom user agent string.
$http_user_agent = $_SERVER['HTTP_USER_AGENT'] ?? NULL;
$user_agent = $_COOKIE['SIMPLETEST_USER_AGENT'] ?? $http_user_agent;
if (isset($user_agent) && preg_match("/^simple(\\w+\\d+):(.+):(.+):(.+)\$/", $user_agent, $matches)) {
[
,
$prefix,
$time,
$salt,
$hmac,
] = $matches;
$check_string = $prefix . ':' . $time . ':' . $salt;
// Read the hash salt prepared by drupal_generate_test_ua().
// This function is called before settings.php is read and Drupal's error
// handlers are set up. While Drupal's error handling may be properly
// configured on production sites, the server's PHP error_reporting may not.
// Ensure that no information leaks on production sites.
$test_db = new TestDatabase($prefix);
$key_file = DRUPAL_ROOT . '/' . $test_db
->getTestSitePath() . '/.htkey';
if (!is_readable($key_file) || is_dir($key_file)) {
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
exit;
}
$private_key = file_get_contents($key_file);
// The string from drupal_generate_test_ua() is 74 bytes long. If we don't
// have it, tests cannot be allowed.
if (empty($private_key) || strlen($private_key) < 74) {
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
exit;
}
// The file properties add more entropy not easily accessible to others.
$key = $private_key . filectime(__FILE__) . fileinode(__FILE__);
$time_diff = time() - $time;
$test_hmac = Crypt::hmacBase64($check_string, $key);
// Since we are making a local request a 600 second time window is allowed,
// and the HMAC must match.
if ($time_diff >= 0 && $time_diff <= 600 && hash_equals($test_hmac, $hmac)) {
$test_prefix = $prefix;
}
else {
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden (SIMPLETEST_USER_AGENT invalid)');
exit;
}
}
return $test_prefix;
}