Skip to content

Commit 575eb49

Browse files
committed
fix: use empty() to check if header exists
1 parent 5b795e7 commit 575eb49

File tree

3 files changed

+46
-20
lines changed

3 files changed

+46
-20
lines changed

changelog/unreleased/40856

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Bugfix: Request header can hold an empty string if not set
2+
3+
Due to Apache rewrite rules originally not existing headers can hold an empty
4+
string.
5+
6+
https://github.com/owncloud/core/pull/40856

lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ public function beforeController($controller, $methodName) {
142142
// CSRF check - also registers the CSRF token since the session may be closed later
143143
Util::callRegister();
144144
if (!$this->reflector->hasAnnotation('NoCSRFRequired')) {
145-
if (!$this->request->passesCSRFCheck() && $this->request->getHeader("Authorization") === null) {
145+
$hasNoAuthHeader = empty($this->request->getHeader("Authorization"));
146+
if (!$this->request->passesCSRFCheck() && $hasNoAuthHeader) {
146147
throw new CrossSiteRequestForgeryException();
147148
}
148149
}

tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php

+38-19
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
use OCP\ISession;
4141
use OCP\AppFramework\Controller;
4242
use OCP\IUserSession;
43+
use ReflectionException;
4344
use Test\TestCase;
4445
use OCP\AppFramework\Http\Response;
4546
use OCP\IConfig;
@@ -135,7 +136,7 @@ private function getMiddleware($isLoggedIn, $isAdminUser) {
135136
* @PublicPage
136137
* @NoCSRFRequired
137138
* @throws SecurityException
138-
* @throws \ReflectionException
139+
* @throws ReflectionException
139140
*/
140141
public function testSetNavigationEntry() {
141142
$this->navigationManager->expects($this->once())
@@ -150,7 +151,7 @@ public function testSetNavigationEntry() {
150151
* @param string $method
151152
* @param string $test
152153
* @param $status
153-
* @throws \ReflectionException
154+
* @throws ReflectionException
154155
*/
155156
private function ajaxExceptionStatus($method, $test, $status) {
156157
$isLoggedIn = false;
@@ -178,7 +179,7 @@ private function ajaxExceptionStatus($method, $test, $status) {
178179
}
179180

180181
/**
181-
* @throws \ReflectionException
182+
* @throws ReflectionException
182183
*/
183184
public function testAjaxStatusLoggedInCheck() {
184185
$this->ajaxExceptionStatus(
@@ -190,7 +191,7 @@ public function testAjaxStatusLoggedInCheck() {
190191

191192
/**
192193
* @NoCSRFRequired
193-
* @throws \ReflectionException
194+
* @throws ReflectionException
194195
*/
195196
public function testAjaxNotAdminCheck() {
196197
$this->ajaxExceptionStatus(
@@ -202,7 +203,7 @@ public function testAjaxNotAdminCheck() {
202203

203204
/**
204205
* @PublicPage
205-
* @throws \ReflectionException
206+
* @throws ReflectionException
206207
*/
207208
public function testAjaxStatusCSRFCheck() {
208209
$this->ajaxExceptionStatus(
@@ -215,10 +216,10 @@ public function testAjaxStatusCSRFCheck() {
215216
/**
216217
* @PublicPage
217218
* @NoCSRFRequired
218-
* @throws \ReflectionException
219-
* @throws \ReflectionException
220-
* @throws \ReflectionException
221-
* @throws \ReflectionException
219+
* @throws ReflectionException
220+
* @throws ReflectionException
221+
* @throws ReflectionException
222+
* @throws ReflectionException
222223
*/
223224
public function testAjaxStatusAllGood() {
224225
$this->ajaxExceptionStatus(
@@ -247,7 +248,7 @@ public function testAjaxStatusAllGood() {
247248
* @PublicPage
248249
* @NoCSRFRequired
249250
* @throws SecurityException
250-
* @throws \ReflectionException
251+
* @throws ReflectionException
251252
*/
252253
public function testNoChecks() {
253254
$this->request->expects($this->never())
@@ -265,7 +266,7 @@ public function testNoChecks() {
265266
* @param string $expects
266267
* @param bool $shouldFail
267268
* @throws SecurityException
268-
* @throws \ReflectionException
269+
* @throws ReflectionException
269270
*/
270271
private function securityCheck($method, $expects, $shouldFail=false) {
271272
// admin check requires login
@@ -292,10 +293,10 @@ private function securityCheck($method, $expects, $shouldFail=false) {
292293
/**
293294
* @PublicPage
294295
* @throws SecurityException
295-
* @throws \ReflectionException
296+
* @throws ReflectionException
296297
*/
297298
public function testCsrfCheck() {
298-
$this->expectException(\OC\AppFramework\Middleware\Security\Exceptions\CrossSiteRequestForgeryException::class);
299+
$this->expectException(CrossSiteRequestForgeryException::class);
299300

300301
$this->request->expects($this->once())
301302
->method('passesCSRFCheck')
@@ -309,7 +310,7 @@ public function testCsrfCheck() {
309310
* @PublicPage
310311
* @NoCSRFRequired
311312
* @throws SecurityException
312-
* @throws \ReflectionException
313+
* @throws ReflectionException
313314
*/
314315
public function testNoCsrfCheck() {
315316
$this->request->expects($this->never())
@@ -323,7 +324,7 @@ public function testNoCsrfCheck() {
323324
/**
324325
* @PublicPage
325326
* @throws SecurityException
326-
* @throws \ReflectionException
327+
* @throws ReflectionException
327328
*/
328329
public function testFailCsrfCheck() {
329330
$this->request->expects($this->once())
@@ -334,11 +335,29 @@ public function testFailCsrfCheck() {
334335
$this->middleware->beforeController(__CLASS__, __FUNCTION__);
335336
}
336337

338+
/**
339+
* @PublicPage
340+
* @throws SecurityException
341+
* @throws ReflectionException
342+
*/
343+
public function testFailCsrfCheckWithoutAuthHeader(): void {
344+
$this->expectException(CrossSiteRequestForgeryException::class);
345+
$this->request->expects($this->once())
346+
->method('passesCSRFCheck')
347+
->willReturn(false);
348+
$this->request->expects($this->once())
349+
->method('getHeader')
350+
->willReturn('');
351+
352+
$this->reader->reflect(__CLASS__, __FUNCTION__);
353+
$this->middleware->beforeController(__CLASS__, __FUNCTION__);
354+
}
355+
337356
/**
338357
* @NoCSRFRequired
339358
* @NoAdminRequired
340359
* @throws SecurityException
341-
* @throws \ReflectionException
360+
* @throws ReflectionException
342361
*/
343362
public function testLoggedInCheck() {
344363
$this->securityCheck(__FUNCTION__, 'isLoggedIn');
@@ -348,7 +367,7 @@ public function testLoggedInCheck() {
348367
* @NoCSRFRequired
349368
* @NoAdminRequired
350369
* @throws SecurityException
351-
* @throws \ReflectionException
370+
* @throws ReflectionException
352371
*/
353372
public function testFailLoggedInCheck() {
354373
$this->securityCheck(__FUNCTION__, 'isLoggedIn', true);
@@ -357,7 +376,7 @@ public function testFailLoggedInCheck() {
357376
/**
358377
* @NoCSRFRequired
359378
* @throws SecurityException
360-
* @throws \ReflectionException
379+
* @throws ReflectionException
361380
*/
362381
public function testIsAdminCheck() {
363382
$this->securityCheck(__FUNCTION__, 'isAdminUser');
@@ -366,7 +385,7 @@ public function testIsAdminCheck() {
366385
/**
367386
* @NoCSRFRequired
368387
* @throws SecurityException
369-
* @throws \ReflectionException
388+
* @throws ReflectionException
370389
*/
371390
public function testFailIsAdminCheck() {
372391
$this->securityCheck(__FUNCTION__, 'isAdminUser', true);

0 commit comments

Comments
 (0)