private function selectHostByAuthority(InternalRequest $ireq)
{
$explicitHostId = "{$ireq->uriHost}:{$ireq->uriPort}";
$wildcardHost = "0.0.0.0:{$ireq->uriPort}";
$ipv6WildcardHost = "[::]:{$ireq->uriPort}";
if (isset($this->vhosts[$explicitHostId])) {
$vhost = $this->vhosts[$explicitHostId];
} elseif (isset($this->vhosts[$wildcardHost])) {
$vhost = $this->vhosts[$wildcardHost];
} elseif (isset($this->vhosts[$ipv6WildcardHost])) {
$vhost = $this->vhosts[$ipv6WildcardHost];
} elseif ($this->cachedVhostCount !== 1) {
return null;
} else {
$ipComparison = $ireq->uriHost;
if (!@inet_pton($ipComparison)) {
$ipComparison = substr($ipComparison, 1, -1);
// IPv6 braces
if (!@inet_pton($ipComparison)) {
return null;
}
}
if (!(($vhost = $this->getDefaultHost()) && in_array($ireq->uriPort, $vhost->getPorts($ipComparison)))) {
return null;
}
}
// IMPORTANT: Wildcard IP hosts without names that are running both encrypted and plaintext
// apps on the same interface (via separate ports) must be checked for encryption to avoid
// displaying unencrypted data as a result of carefully crafted Host headers. This is an
// extreme edge case but it's potentially exploitable without this check.
// DO NOT REMOVE THIS UNLESS YOU'RE SURE YOU KNOW WHAT YOU'RE DOING.
if ($vhost->isEncrypted() != $ireq->client->isEncrypted) {
return null;
}
return $vhost;
}