From 465807490d7648e5675f1cdbc5b1d232cda4feee Mon Sep 17 00:00:00 2001
From: Christoph Wurst <christoph@owncloud.com>
Date: Mon, 13 Jun 2016 16:00:49 +0200
Subject: [PATCH] create session token only for clients that support cookies

---
 .../tests/unit/Connector/Sabre/AuthTest.php   | 17 ++-----
 lib/private/User/Session.php                  | 13 ++++-
 tests/lib/User/SessionTest.php                | 48 +++++++++++++++++--
 3 files changed, 61 insertions(+), 17 deletions(-)

diff --git a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
index b3ab49a027e..147a0c2b8c5 100644
--- a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
@@ -159,7 +159,7 @@ class AuthTest extends TestCase {
 		$user = $this->getMockBuilder('\OCP\IUser')
 			->disableOriginalConstructor()
 			->getMock();
-		$user->expects($this->exactly(4))
+		$user->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('MyTestUser'));
 		$this->userSession
@@ -167,7 +167,7 @@ class AuthTest extends TestCase {
 			->method('isLoggedIn')
 			->will($this->returnValue(true));
 		$this->userSession
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUser')
 			->will($this->returnValue($user));
 		$this->session
@@ -178,12 +178,8 @@ class AuthTest extends TestCase {
 		$this->userSession
 			->expects($this->once())
 			->method('logClientIn')
-			->with('MyTestUser', 'MyTestPassword')
+			->with('MyTestUser', 'MyTestPassword', $this->request)
 			->will($this->returnValue(true));
-		$this->userSession
-			->expects($this->once())
-			->method('createSessionToken')
-			->with($this->request, 'MyTestUser', 'MyTestUser', 'MyTestPassword');
 		$this->session
 			->expects($this->once())
 			->method('set')
@@ -626,17 +622,14 @@ class AuthTest extends TestCase {
 			->method('logClientIn')
 			->with('username', 'password')
 			->will($this->returnValue(true));
-		$this->userSession
-			->expects($this->once())
-			->method('createSessionToken');
 		$user = $this->getMockBuilder('\OCP\IUser')
 			->disableOriginalConstructor()
 			->getMock();
-		$user->expects($this->exactly(4))
+		$user->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('MyTestUser'));
 		$this->userSession
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUser')
 			->will($this->returnValue($user));
 		$response = $this->auth->check($server->httpRequest, $server->httpResponse);
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index 0376e81b6dc..0cebb3e0613 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -370,11 +370,21 @@ class Session implements IUserSession, Emitter {
 			return false;
 		}
 
-		$this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
+		if ($this->supportsCookies($request)) {
+			$this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
+		}
 
 		return true;
 	}
 
+	protected function supportsCookies(IRequest $request) {
+		if (!is_null($request->getCookie('cookie_test'))) {
+			return true;
+		}
+		setcookie('cookie_test', 'test', $this->timeFacory->getTime() + 3600);
+		return false;
+	}
+
 	private function isTokenAuthEnforced() {
 		return $this->config->getSystemValue('token_auth_enforced', false);
 	}
@@ -432,7 +442,6 @@ class Session implements IUserSession, Emitter {
 	 */
 	public function tryBasicAuthLogin(IRequest $request) {
 		if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) {
-			$request = \OC::$server->getRequest();
 			$result = $this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW'], $request);
 			if ($result === true) {
 				/**
diff --git a/tests/lib/User/SessionTest.php b/tests/lib/User/SessionTest.php
index eac38ebba16..28f6b6a5377 100644
--- a/tests/lib/User/SessionTest.php
+++ b/tests/lib/User/SessionTest.php
@@ -311,11 +311,13 @@ class SessionTest extends \Test\TestCase {
 			->disableOriginalConstructor()
 			->getMock();
 		$session = $this->getMock('\OCP\ISession');
+		$request = $this->getMock('\OCP\IRequest');
+		$user = $this->getMock('\OCP\IUser');
 
 		/** @var \OC\User\Session $userSession */
 		$userSession = $this->getMockBuilder('\OC\User\Session')
 			->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
-			->setMethods(['login'])
+			->setMethods(['login', 'supportsCookies', 'createSessionToken', 'getUser'])
 			->getMock();
 
 		$this->tokenProvider->expects($this->once())
@@ -327,7 +329,46 @@ class SessionTest extends \Test\TestCase {
 			->with('token_auth_enforced', false)
 			->will($this->returnValue(true));
 
-		$this->assertFalse($userSession->logClientIn('john', 'doe'));
+		$this->assertFalse($userSession->logClientIn('john', 'doe', $request));
+	}
+
+	public function testLogClientInWithTokenPassword() {
+		$manager = $this->getMockBuilder('\OC\User\Manager')
+			->disableOriginalConstructor()
+			->getMock();
+		$session = $this->getMock('\OCP\ISession');
+		$request = $this->getMock('\OCP\IRequest');
+		$user = $this->getMock('\OCP\IUser');
+
+		/** @var \OC\User\Session $userSession */
+		$userSession = $this->getMockBuilder('\OC\User\Session')
+			->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
+			->setMethods(['isTokenPassword', 'login', 'supportsCookies', 'createSessionToken', 'getUser'])
+			->getMock();
+
+		$userSession->expects($this->once())
+			->method('isTokenPassword')
+			->will($this->returnValue(true));
+		$userSession->expects($this->once())
+			->method('login')
+			->with('john', 'doe')
+			->will($this->returnValue(true));
+
+		$userSession->expects($this->once())
+			->method('supportsCookies')
+			->with($request)
+			->will($this->returnValue(true));
+		$userSession->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($user));
+		$user->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('user123'));
+		$userSession->expects($this->once())
+			->method('createSessionToken')
+			->with($request, 'user123', 'john', 'doe');
+		
+		$this->assertTrue($userSession->logClientIn('john', 'doe', $request));
 	}
 
 	public function testLogClientInNoTokenPasswordNo2fa() {
@@ -336,6 +377,7 @@ class SessionTest extends \Test\TestCase {
 			->getMock();
 		$session = $this->getMock('\OCP\ISession');
 		$user = $this->getMock('\OCP\IUser');
+		$request = $this->getMock('\OCP\IRequest');
 
 		/** @var \OC\User\Session $userSession */
 		$userSession = $this->getMockBuilder('\OC\User\Session')
@@ -357,7 +399,7 @@ class SessionTest extends \Test\TestCase {
 			->with('john')
 			->will($this->returnValue(true));
 
-		$this->assertFalse($userSession->logClientIn('john', 'doe'));
+		$this->assertFalse($userSession->logClientIn('john', 'doe', $request));
 	}
 
 	public function testRememberLoginValidToken() {
-- 
GitLab