[Pkg-owncloud-commits] [owncloud] 01/36: backport #16532 to stable7

David Prévot taffit at moszumanska.debian.org
Tue Jun 23 23:12:20 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository owncloud.

commit 6b4f1706b906e22d48efca4c3b65aa0d767141ae
Author: Bernhard Posselt <dev at bernhard-posselt.com>
Date:   Wed May 27 14:32:37 2015 +0200

    backport #16532 to stable7
---
 .../dependencyinjection/dicontainer.php            |  7 ++-
 .../middleware/security/corsmiddleware.php         | 46 ++++++++++++--
 .../middleware/security/CORSMiddlewareTest.php     | 73 ++++++++++++++++++++--
 3 files changed, 113 insertions(+), 13 deletions(-)

diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php
index 61a2333..74b0a98 100644
--- a/lib/private/appframework/dependencyinjection/dicontainer.php
+++ b/lib/private/appframework/dependencyinjection/dicontainer.php
@@ -108,18 +108,19 @@ class DIContainer extends SimpleContainer implements IAppContainer{
 			);
 		});
 
-		$this['CORSMiddleware'] = $this->share(function($c) {
+		$this['CORSMiddleware'] = $this->share(function($c) use ($app){
 			return new CORSMiddleware(
 				$c['Request'],
-				$c['ControllerMethodReflector']
+				$c['ControllerMethodReflector'],
+				$app->getServer()->getUserSession()
 			);
 		});
 
 		$middleWares = &$this->middleWares;
 		$this['MiddlewareDispatcher'] = $this->share(function($c) use (&$middleWares) {
 			$dispatcher = new MiddlewareDispatcher();
-			$dispatcher->registerMiddleware($c['SecurityMiddleware']);
 			$dispatcher->registerMiddleware($c['CORSMiddleware']);
+			$dispatcher->registerMiddleware($c['SecurityMiddleware']);
 
 			foreach($middleWares as $middleWare) {
 				$dispatcher->registerMiddleware($c[$middleWare]);
diff --git a/lib/private/appframework/middleware/security/corsmiddleware.php b/lib/private/appframework/middleware/security/corsmiddleware.php
index dca3996..2d768e1 100644
--- a/lib/private/appframework/middleware/security/corsmiddleware.php
+++ b/lib/private/appframework/middleware/security/corsmiddleware.php
@@ -13,30 +13,66 @@ namespace OC\AppFramework\Middleware\Security;
 
 use OC\AppFramework\Utility\ControllerMethodReflector;
 use OCP\IRequest;
+use OCP\IUserSession;
 use OCP\AppFramework\Http\Response;
 use OCP\AppFramework\Middleware;
 
 /**
- * This middleware sets the correct CORS headers on a response if the 
+ * This middleware sets the correct CORS headers on a response if the
  * controller has the @CORS annotation. This is needed for webapps that want
- * to access an API and dont run on the same domain, see 
+ * to access an API and dont run on the same domain, see
  * https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
  */
 class CORSMiddleware extends Middleware {
 
+	/**
+	 * @var IRequest
+	 */
 	private $request;
+	/**
+	 * @var ControllerMethodReflector
+	 */
 	private $reflector;
+	/**
+	 * @var IUserSession
+	 */
+	private $session;
 
 	/**
 	 * @param IRequest $request
 	 * @param ControllerMethodReflector $reflector
+	 * @param IUserSession $session
 	 */
-	public function __construct(IRequest $request, 
-	                            ControllerMethodReflector $reflector) {
+	public function __construct(IRequest $request,
+	                            ControllerMethodReflector $reflector,
+	                            IUserSession $session) {
 		$this->request = $request;
 		$this->reflector = $reflector;
+		$this->session = $session;
 	}
 
+	/**
+	 * This is being run in normal order before the controller is being
+	 * called which allows several modifications and checks
+	 *
+	 * @param Controller $controller the controller that is being called
+	 * @param string $methodName the name of the method that will be called on
+	 *                           the controller
+	 * @since 7.0.0
+	 */
+	public function beforeController($controller, $methodName){
+		// ensure that @CORS annotated API routes are not used in conjunction
+		// with session authentication since this enables CSRF attack vectors
+		if ($this->reflector->hasAnnotation('CORS') &&
+			!$this->reflector->hasAnnotation('PublicPage'))  {
+			$user = $this->request->server['PHP_AUTH_USER'];
+			$pass = $this->request->server['PHP_AUTH_PW'];
+			$this->session->logout();
+			if(!$this->session->login($user, $pass)) {
+				throw new SecurityException('CORS requires basic auth');
+			}
+		}
+	}
 
 	/**
 	 * This is being run after a successful controllermethod call and allows
@@ -54,7 +90,7 @@ class CORSMiddleware extends Middleware {
 		if(isset($this->request->server['HTTP_ORIGIN']) &&
 			$this->reflector->hasAnnotation('CORS')) {
 
-			// allow credentials headers must not be true or CSRF is possible 
+			// allow credentials headers must not be true or CSRF is possible
 			// otherwise
 			foreach($response->getHeaders() as $header => $value ) {
 				if(strtolower($header) === 'access-control-allow-credentials' &&
diff --git a/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php b/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php
index 79cd3b2..9e314d6 100644
--- a/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php
+++ b/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php
@@ -21,9 +21,11 @@ use OCP\AppFramework\Http\Response;
 class CORSMiddlewareTest extends \PHPUnit_Framework_TestCase {
 
 	private $reflector;
+	private $session;
 
 	protected function setUp() {
 		$this->reflector = new ControllerMethodReflector();
+		$this->session = $this->getMock('\OCP\IUserSession');
 	}
 
 	/**
@@ -34,7 +36,7 @@ class CORSMiddlewareTest extends \PHPUnit_Framework_TestCase {
 			array('server' => array('HTTP_ORIGIN' => 'test'))
 		);
 		$this->reflector->reflect($this, __FUNCTION__);
-		$middleware = new CORSMiddleware($request, $this->reflector);
+		$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
 
 		$response = $middleware->afterController($this, __FUNCTION__, new Response());
 		$headers = $response->getHeaders();
@@ -46,7 +48,7 @@ class CORSMiddlewareTest extends \PHPUnit_Framework_TestCase {
 		$request = new Request(
 			array('server' => array('HTTP_ORIGIN' => 'test'))
 		);
-		$middleware = new CORSMiddleware($request, $this->reflector);
+		$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
 
 		$response = $middleware->afterController($this, __FUNCTION__, new Response());
 		$headers = $response->getHeaders();
@@ -60,14 +62,13 @@ class CORSMiddlewareTest extends \PHPUnit_Framework_TestCase {
 	public function testNoOriginHeaderNoCORSHEADER() {
 		$request = new Request();
 		$this->reflector->reflect($this, __FUNCTION__);
-		$middleware = new CORSMiddleware($request, $this->reflector);
+		$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
 
 		$response = $middleware->afterController($this, __FUNCTION__, new Response());
 		$headers = $response->getHeaders();
 		$this->assertFalse(array_key_exists('Access-Control-Allow-Origin', $headers));
 	}
 
-
 	/**
 	 * @CORS
 	 * @expectedException \OC\AppFramework\Middleware\Security\SecurityException
@@ -77,11 +78,73 @@ class CORSMiddlewareTest extends \PHPUnit_Framework_TestCase {
 			array('server' => array('HTTP_ORIGIN' => 'test'))
 		);
 		$this->reflector->reflect($this, __FUNCTION__);
-		$middleware = new CORSMiddleware($request, $this->reflector);
+		$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
 
 		$response = new Response();
 		$response->addHeader('AcCess-control-Allow-Credentials ', 'TRUE');
 		$response = $middleware->afterController($this, __FUNCTION__, $response);
 	}
 
+	/**
+	 * @CORS
+	 * @PublicPage
+	 */
+	public function testNoCORSShouldAllowCookieAuth() {
+		$request = new Request(
+			array(),
+			$this->getMock('\OCP\Security\ISecureRandom'),
+			$this->getMock('\OCP\IConfig')
+		);
+		$this->reflector->reflect($this, __FUNCTION__);
+		$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
+		$middleware->beforeController($this, __FUNCTION__, new Response());
+	}
+
+	/**
+	 * @CORS
+	 */
+	public function testCORSShouldRelogin() {
+		$request = new Request(
+			array('server' => array(
+				'PHP_AUTH_USER' => 'user',
+				'PHP_AUTH_PW' => 'pass'
+			)),
+			$this->getMock('\OCP\Security\ISecureRandom'),
+			$this->getMock('\OCP\IConfig')
+		);
+		$this->session->expects($this->once())
+			->method('logout');
+		$this->session->expects($this->once())
+			->method('login')
+			->with($this->equalTo('user'), $this->equalTo('pass'))
+			->will($this->returnValue(true));
+		$this->reflector->reflect($this, __FUNCTION__);
+		$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
+		$middleware->beforeController($this, __FUNCTION__, new Response());
+	}
+
+	/**
+	 * @CORS
+	 * @expectedException \OC\AppFramework\Middleware\Security\SecurityException
+	 */
+	public function testCORSShouldNotAllowCookieAuth() {
+		$request = new Request(
+			array('server' => array(
+				'PHP_AUTH_USER' => 'user',
+				'PHP_AUTH_PW' => 'pass'
+			)),
+			$this->getMock('\OCP\Security\ISecureRandom'),
+			$this->getMock('\OCP\IConfig')
+		);
+		$this->session->expects($this->once())
+			->method('logout');
+		$this->session->expects($this->once())
+			->method('login')
+			->with($this->equalTo('user'), $this->equalTo('pass'))
+			->will($this->returnValue(false));
+		$this->reflector->reflect($this, __FUNCTION__);
+		$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
+		$middleware->beforeController($this, __FUNCTION__, new Response());
+	}
+
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git



More information about the Pkg-owncloud-commits mailing list