Skip to content

Commit 892eb7d

Browse files
committed
fix(AppFramework): Log malformed protocol values and unify fallback behavior
Signed-off-by: Josh <josh.t.richards@gmail.com>
1 parent dd0f7f0 commit 892eb7d

File tree

2 files changed

+57
-22
lines changed

2 files changed

+57
-22
lines changed

lib/private/AppFramework/Http/Request.php

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use OCP\IConfig;
1515
use OCP\IRequest;
1616
use OCP\IRequestId;
17+
use Psr\Log\LoggerInterface;
1718
use Symfony\Component\HttpFoundation\IpUtils;
1819

1920
/**
@@ -613,36 +614,50 @@ private function isOverwriteCondition(): bool {
613614

614615
/**
615616
* Returns the server protocol. It respects one or more reverse proxies servers
616-
* and load balancers
617+
<<<<<<< HEAD
618+
* and load balancers. Precedence:
619+
=======
620+
* and load balancers. Precedence:
621+
>>>>>>> ec37b3558fc (fix(AppFramework): Log malformed protocol values)
622+
* 1. `overwriteprotocol` config value
623+
* 2. `X-Forwarded-Proto` header value
624+
* 3. $_SERVER['HTTPS'] value
625+
* If an invalid protocol is provided, defaults to http and logs an error.
626+
*
617627
* @return string Server protocol (http or https)
618628
*/
619629
public function getServerProtocol(): string {
630+
$proto = 'http';
631+
620632
if ($this->config->getSystemValueString('overwriteprotocol') !== ''
621-
&& $this->isOverwriteCondition()) {
622-
return $this->config->getSystemValueString('overwriteprotocol');
623-
}
624-
625-
if ($this->fromTrustedProxy() && isset($this->server['HTTP_X_FORWARDED_PROTO'])) {
633+
&& $this->isOverwriteCondition()
634+
) {
635+
$proto = strtolower($this->config->getSystemValueString('overwriteprotocol'));
636+
} elseif ($this->fromTrustedProxy()
637+
&& isset($this->server['HTTP_X_FORWARDED_PROTO'])
638+
) {
626639
if (str_contains($this->server['HTTP_X_FORWARDED_PROTO'], ',')) {
627640
$parts = explode(',', $this->server['HTTP_X_FORWARDED_PROTO']);
628641
$proto = strtolower(trim($parts[0]));
629642
} else {
630643
$proto = strtolower($this->server['HTTP_X_FORWARDED_PROTO']);
631644
}
632-
633-
// Verify that the protocol is always HTTP or HTTPS
634-
// default to http if an invalid value is provided
635-
return $proto === 'https' ? 'https' : 'http';
636-
}
637-
638-
if (isset($this->server['HTTPS'])
639-
&& $this->server['HTTPS'] !== null
645+
} elseif (!empty($this->server['HTTPS'])
640646
&& $this->server['HTTPS'] !== 'off'
641-
&& $this->server['HTTPS'] !== '') {
642-
return 'https';
647+
) {
648+
$proto = 'https';
643649
}
644650

645-
return 'http';
651+
if ($proto !== 'https' && $proto !== 'http') {
652+
// log unrecognized value so admin has a chance to fix it
653+
\OC::$server->get(LoggerInterface::class)->critical(
654+
'Server protocol is malformed [falling back to http] (check overwriteprotocol and/or X-Forwarded-Proto to remedy): ' . $proto,
655+
['app' => 'core']
656+
);
657+
}
658+
659+
// default to http if provided an invalid value
660+
return $proto === 'https' ? 'https' : 'http';
646661
}
647662

648663
/**
@@ -729,11 +744,11 @@ public function getRawPathInfo(): string {
729744
}
730745

731746
/**
732-
* Get PathInfo from request
747+
* Get PathInfo from request (rawurldecoded)
733748
* @throws \Exception
734749
* @return string|false Path info or false when not found
735750
*/
736-
public function getPathInfo() {
751+
public function getPathInfo(): string|false {
737752
$pathInfo = $this->getRawPathInfo();
738753
return \Sabre\HTTP\decodePath($pathInfo);
739754
}

tests/lib/AppFramework/Http/RequestTest.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -787,12 +787,12 @@ public function testGetHttpProtocol($input, $expected): void {
787787
$this->assertSame($expected, $request->getHttpProtocol());
788788
}
789789

790-
public function testGetServerProtocolWithOverride(): void {
790+
public function testGetServerProtocolWithOverrideValid(): void {
791791
$this->config
792792
->expects($this->exactly(3))
793793
->method('getSystemValueString')
794794
->willReturnMap([
795-
['overwriteprotocol', '', 'customProtocol'],
795+
['overwriteprotocol', '', 'HTTPS'], // should be automatically lowercased
796796
['overwritecondaddr', '', ''],
797797
]);
798798

@@ -804,9 +804,29 @@ public function testGetServerProtocolWithOverride(): void {
804804
$this->stream
805805
);
806806

807-
$this->assertSame('customProtocol', $request->getServerProtocol());
807+
$this->assertSame('https', $request->getServerProtocol());
808808
}
809809

810+
public function testGetServerProtocolWithOverrideInValid(): void {
811+
$this->config
812+
->expects($this->exactly(3))
813+
->method('getSystemValueString')
814+
->willReturnMap([
815+
['overwriteprotocol', '', 'bogusProtocol'], // should trigger fallback to http
816+
['overwritecondaddr', '', ''],
817+
]);
818+
819+
$request = new Request(
820+
[],
821+
$this->requestId,
822+
$this->config,
823+
$this->csrfTokenManager,
824+
$this->stream
825+
);
826+
827+
$this->assertSame('http', $request->getServerProtocol());
828+
}
829+
810830
public function testGetServerProtocolWithProtoValid(): void {
811831
$this->config
812832
->method('getSystemValue')

0 commit comments

Comments
 (0)