Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use empty() to check if header exists #40856

Merged
merged 3 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/files_sharing/lib/Controller/Share20OcsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ protected function formatShare(IShare $share, $received = false) {
* Get a specific share by id
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param string $id
* @return Result
Expand Down Expand Up @@ -684,6 +685,7 @@ private function getSharedWithMe($node, $includeTags, $requestedShareTypes, $sta
* the function will return an empty list.
*
* @NoAdminRequired
* @NoCSRFRequired
*
* - Get shares by the current user
* - Get shares by the current user and reshares (?reshares=true)
Expand Down
6 changes: 6 additions & 0 deletions changelog/unreleased/40856
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Bugfix: Request header can hold an empty string if not set

Due to Apache rewrite rules originally not existing headers can hold an empty
string.

https://github.com/owncloud/core/pull/40856
1 change: 1 addition & 0 deletions core/Controller/OcsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public function checkPerson($login, $password) {
* test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/getattribute
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @return Result
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ public function beforeController($controller, $methodName) {
// CSRF check - also registers the CSRF token since the session may be closed later
Util::callRegister();
if (!$this->reflector->hasAnnotation('NoCSRFRequired')) {
if (!$this->request->passesCSRFCheck() && $this->request->getHeader("Authorization") === null) {
$hasNoAuthHeader = ($this->request->getHeader("Authorization") === null || trim($this->request->getHeader("Authorization")) === '');
if (!$this->request->passesCSRFCheck() && $hasNoAuthHeader) {
throw new CrossSiteRequestForgeryException();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
use OCP\ISession;
use OCP\AppFramework\Controller;
use OCP\IUserSession;
use ReflectionException;
use Test\TestCase;
use OCP\AppFramework\Http\Response;
use OCP\IConfig;
Expand Down Expand Up @@ -135,7 +136,7 @@ private function getMiddleware($isLoggedIn, $isAdminUser) {
* @PublicPage
* @NoCSRFRequired
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testSetNavigationEntry() {
$this->navigationManager->expects($this->once())
Expand All @@ -150,7 +151,7 @@ public function testSetNavigationEntry() {
* @param string $method
* @param string $test
* @param $status
* @throws \ReflectionException
* @throws ReflectionException
*/
private function ajaxExceptionStatus($method, $test, $status) {
$isLoggedIn = false;
Expand Down Expand Up @@ -178,7 +179,7 @@ private function ajaxExceptionStatus($method, $test, $status) {
}

/**
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testAjaxStatusLoggedInCheck() {
$this->ajaxExceptionStatus(
Expand All @@ -190,7 +191,7 @@ public function testAjaxStatusLoggedInCheck() {

/**
* @NoCSRFRequired
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testAjaxNotAdminCheck() {
$this->ajaxExceptionStatus(
Expand All @@ -202,7 +203,7 @@ public function testAjaxNotAdminCheck() {

/**
* @PublicPage
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testAjaxStatusCSRFCheck() {
$this->ajaxExceptionStatus(
Expand All @@ -215,10 +216,7 @@ public function testAjaxStatusCSRFCheck() {
/**
* @PublicPage
* @NoCSRFRequired
* @throws \ReflectionException
* @throws \ReflectionException
* @throws \ReflectionException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testAjaxStatusAllGood() {
$this->ajaxExceptionStatus(
Expand Down Expand Up @@ -247,7 +245,7 @@ public function testAjaxStatusAllGood() {
* @PublicPage
* @NoCSRFRequired
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testNoChecks() {
$this->request->expects($this->never())
Expand All @@ -265,7 +263,7 @@ public function testNoChecks() {
* @param string $expects
* @param bool $shouldFail
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
private function securityCheck($method, $expects, $shouldFail=false) {
// admin check requires login
Expand All @@ -292,10 +290,10 @@ private function securityCheck($method, $expects, $shouldFail=false) {
/**
* @PublicPage
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testCsrfCheck() {
$this->expectException(\OC\AppFramework\Middleware\Security\Exceptions\CrossSiteRequestForgeryException::class);
$this->expectException(CrossSiteRequestForgeryException::class);

$this->request->expects($this->once())
->method('passesCSRFCheck')
Expand All @@ -309,7 +307,7 @@ public function testCsrfCheck() {
* @PublicPage
* @NoCSRFRequired
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testNoCsrfCheck() {
$this->request->expects($this->never())
Expand All @@ -323,7 +321,7 @@ public function testNoCsrfCheck() {
/**
* @PublicPage
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testFailCsrfCheck() {
$this->request->expects($this->once())
Expand All @@ -334,11 +332,29 @@ public function testFailCsrfCheck() {
$this->middleware->beforeController(__CLASS__, __FUNCTION__);
}

/**
* @PublicPage
* @throws SecurityException
* @throws ReflectionException
*/
public function testFailCsrfCheckWithoutAuthHeader(): void {
$this->expectException(CrossSiteRequestForgeryException::class);
$this->request->expects($this->once())
->method('passesCSRFCheck')
->willReturn(false);
$this->request
->method('getHeader')
->willReturn('');

$this->reader->reflect(__CLASS__, __FUNCTION__);
$this->middleware->beforeController(__CLASS__, __FUNCTION__);
}

/**
* @NoCSRFRequired
* @NoAdminRequired
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testLoggedInCheck() {
$this->securityCheck(__FUNCTION__, 'isLoggedIn');
Expand All @@ -348,7 +364,7 @@ public function testLoggedInCheck() {
* @NoCSRFRequired
* @NoAdminRequired
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testFailLoggedInCheck() {
$this->securityCheck(__FUNCTION__, 'isLoggedIn', true);
Expand All @@ -357,7 +373,7 @@ public function testFailLoggedInCheck() {
/**
* @NoCSRFRequired
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testIsAdminCheck() {
$this->securityCheck(__FUNCTION__, 'isAdminUser');
Expand All @@ -366,7 +382,7 @@ public function testIsAdminCheck() {
/**
* @NoCSRFRequired
* @throws SecurityException
* @throws \ReflectionException
* @throws ReflectionException
*/
public function testFailIsAdminCheck() {
$this->securityCheck(__FUNCTION__, 'isAdminUser', true);
Expand Down