diff --git a/apps/dav/appinfo/v1/publicwebdav.php b/apps/dav/appinfo/v1/publicwebdav.php
index 5bdfd94e65858e05331e086f5e0a31cd08f7fb5a..cf0488038d33e3f0a30f078f9fd0c829290fbd11 100644
--- a/apps/dav/appinfo/v1/publicwebdav.php
+++ b/apps/dav/appinfo/v1/publicwebdav.php
@@ -39,7 +39,8 @@ $serverFactory = new OCA\DAV\Connector\Sabre\ServerFactory(
 	\OC::$server->getUserSession(),
 	\OC::$server->getMountManager(),
 	\OC::$server->getTagManager(),
-	\OC::$server->getEventDispatcher()
+	\OC::$server->getEventDispatcher(),
+	\OC::$server->getRequest()
 );
 
 $requestUri = \OC::$server->getRequest()->getRequestUri();
diff --git a/apps/dav/appinfo/v1/webdav.php b/apps/dav/appinfo/v1/webdav.php
index f28736f1f01398bb01c64d9d92617437c2dd04bf..8324f962b8ee34241446b9c4adba32cdd6236d4a 100644
--- a/apps/dav/appinfo/v1/webdav.php
+++ b/apps/dav/appinfo/v1/webdav.php
@@ -40,7 +40,8 @@ $serverFactory = new \OCA\DAV\Connector\Sabre\ServerFactory(
 	\OC::$server->getUserSession(),
 	\OC::$server->getMountManager(),
 	\OC::$server->getTagManager(),
-	\OC::$server->getEventDispatcher()
+	\OC::$server->getEventDispatcher(),
+	\OC::$server->getRequest()
 );
 
 // Backends
diff --git a/apps/dav/lib/connector/sabre/fakelockerplugin.php b/apps/dav/lib/connector/sabre/fakelockerplugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..493d3b0ade4179f283881f912f979a9d87b4b3e0
--- /dev/null
+++ b/apps/dav/lib/connector/sabre/fakelockerplugin.php
@@ -0,0 +1,159 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\DAV\Connector\Sabre;
+
+use Sabre\DAV\Locks\LockInfo;
+use Sabre\DAV\Property\LockDiscovery;
+use Sabre\DAV\Property\SupportedLock;
+use Sabre\DAV\ServerPlugin;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Sabre\DAV\PropFind;
+use Sabre\DAV\INode;
+
+/**
+ * Class FakeLockerPlugin is a plugin only used when connections come in from
+ * OS X via Finder. The fake locking plugin does emulate Class 2 WebDAV support
+ * (locking of files) which allows Finder to access the storage in write mode as
+ * well.
+ *
+ * No real locking is performed, instead the plugin just returns always positive
+ * responses.
+ *
+ * @see https://github.com/owncloud/core/issues/17732
+ * @package OCA\DAV\Connector\Sabre
+ */
+class FakeLockerPlugin extends ServerPlugin {
+	/** @var \Sabre\DAV\Server */
+	private $server;
+
+	/** {@inheritDoc} */
+	public function initialize(\Sabre\DAV\Server $server) {
+		$this->server = $server;
+		$this->server->on('method:LOCK', [$this, 'fakeLockProvider'], 1);
+		$this->server->on('method:UNLOCK', [$this, 'fakeUnlockProvider'], 1);
+		$server->on('propFind', [$this, 'propFind']);
+		$server->on('validateTokens', [$this, 'validateTokens']);
+	}
+
+	/**
+	 * Indicate that we support LOCK and UNLOCK
+	 *
+	 * @param string $path
+	 * @return array
+	 */
+	public function getHTTPMethods($path) {
+		return [
+			'LOCK',
+			'UNLOCK',
+		];
+	}
+
+	/**
+	 * Indicate that we support locking
+	 *
+	 * @return array
+	 */
+	function getFeatures() {
+		return [2];
+	}
+
+	/**
+	 * Return some dummy response for PROPFIND requests with regard to locking
+	 *
+	 * @param PropFind $propFind
+	 * @param INode $node
+	 * @return void
+	 */
+	function propFind(PropFind $propFind, INode $node) {
+		$propFind->handle('{DAV:}supportedlock', function() {
+			return new SupportedLock(true);
+		});
+		$propFind->handle('{DAV:}lockdiscovery', function() use ($propFind) {
+			return new LockDiscovery([]);
+		});
+	}
+
+	/**
+	 * Mark a locking token always as valid
+	 *
+	 * @param RequestInterface $request
+	 * @param array $conditions
+	 */
+	public function validateTokens(RequestInterface $request, &$conditions) {
+		foreach($conditions as &$fileCondition) {
+			if(isset($fileCondition['tokens'])) {
+				foreach($fileCondition['tokens'] as &$token) {
+					if(isset($token['token'])) {
+						if(substr($token['token'], 0, 16) === 'opaquelocktoken:') {
+							$token['validToken'] = true;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Fakes a successful LOCK
+	 *
+	 * @param RequestInterface $request
+	 * @param ResponseInterface $response
+	 * @return bool
+	 */
+	public function fakeLockProvider(RequestInterface $request,
+									 ResponseInterface $response) {
+		$dom = new \DOMDocument('1.0', 'utf-8');
+		$prop = $dom->createElementNS('DAV:', 'd:prop');
+		$dom->appendChild($prop);
+
+		$lockDiscovery = $dom->createElementNS('DAV:', 'd:lockdiscovery');
+		$prop->appendChild($lockDiscovery);
+
+		$lockInfo = new LockInfo();
+		$lockInfo->token = md5($request->getPath());
+		$lockInfo->uri = $request->getPath();
+		$lockInfo->depth = \Sabre\DAV\Server::DEPTH_INFINITY;
+		$lockInfo->timeout = 1800;
+
+		$lockObj = new LockDiscovery([$lockInfo]);
+		$lockObj->serialize($this->server, $lockDiscovery);
+
+		$response->setBody($dom->saveXML());
+
+		return false;
+	}
+
+	/**
+	 * Fakes a successful LOCK
+	 *
+	 * @param RequestInterface $request
+	 * @param ResponseInterface $response
+	 * @return bool
+	 */
+	public function fakeUnlockProvider(RequestInterface $request,
+									 ResponseInterface $response) {
+		$response->setStatus(204);
+		$response->setHeader('Content-Length', '0');
+		return false;
+	}
+}
diff --git a/apps/dav/lib/connector/sabre/serverfactory.php b/apps/dav/lib/connector/sabre/serverfactory.php
index f67e949e8025fc3e5276e9e623ed21dda0dc2e20..a33acc9f00b50bc81efb6dd662a2c7f1f5294dc0 100644
--- a/apps/dav/lib/connector/sabre/serverfactory.php
+++ b/apps/dav/lib/connector/sabre/serverfactory.php
@@ -26,12 +26,41 @@ use OCP\Files\Mount\IMountManager;
 use OCP\IConfig;
 use OCP\IDBConnection;
 use OCP\ILogger;
+use OCP\IRequest;
 use OCP\ITagManager;
 use OCP\IUserSession;
 use Sabre\DAV\Auth\Backend\BackendInterface;
+use Sabre\DAV\Locks\Plugin;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
 class ServerFactory {
+	/** @var IConfig */
+	private $config;
+	/** @var ILogger */
+	private $logger;
+	/** @var IDBConnection */
+	private $databaseConnection;
+	/** @var IUserSession */
+	private $userSession;
+	/** @var IMountManager */
+	private $mountManager;
+	/** @var ITagManager */
+	private $tagManager;
+	/** @var EventDispatcherInterface */
+	private $dispatcher;
+	/** @var IRequest */
+	private $request;
+
+	/**
+	 * @param IConfig $config
+	 * @param ILogger $logger
+	 * @param IDBConnection $databaseConnection
+	 * @param IUserSession $userSession
+	 * @param IMountManager $mountManager
+	 * @param ITagManager $tagManager
+	 * @param EventDispatcherInterface $dispatcher
+	 * @param IRequest $request
+	 */
 	public function __construct(
 		IConfig $config,
 		ILogger $logger,
@@ -39,7 +68,8 @@ class ServerFactory {
 		IUserSession $userSession,
 		IMountManager $mountManager,
 		ITagManager $tagManager,
-		EventDispatcherInterface $dispatcher
+		EventDispatcherInterface $dispatcher,
+		IRequest $request
 	) {
 		$this->config = $config;
 		$this->logger = $logger;
@@ -48,6 +78,7 @@ class ServerFactory {
 		$this->mountManager = $mountManager;
 		$this->tagManager = $tagManager;
 		$this->dispatcher = $dispatcher;
+		$this->request = $request;
 	}
 
 	/**
@@ -57,7 +88,10 @@ class ServerFactory {
 	 * @param callable $viewCallBack callback that should return the view for the dav endpoint
 	 * @return Server
 	 */
-	public function createServer($baseUri, $requestUri, BackendInterface $authBackend, callable $viewCallBack) {
+	public function createServer($baseUri,
+								 $requestUri,
+								 BackendInterface $authBackend,
+								 callable $viewCallBack) {
 		// Fire up server
 		$objectTree = new \OCA\DAV\Connector\Sabre\ObjectTree();
 		$server = new \OCA\DAV\Connector\Sabre\Server($objectTree);
@@ -75,6 +109,11 @@ class ServerFactory {
 		$server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $this->logger));
 		$server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin($objectTree));
 		$server->addPlugin(new \OCA\DAV\Connector\Sabre\ListenerPlugin($this->dispatcher));
+		// Finder on OS X requires Class 2 WebDAV support (locking), since we do
+		// not provide locking we emulate it using a fake locking plugin.
+		if($this->request->isUserAgent(['/WebDAVFS/'])) {
+			$server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin());
+		}
 
 		// wait with registering these until auth is handled and the filesystem is setup
 		$server->on('beforeMethod', function () use ($server, $objectTree, $viewCallBack) {
diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php
index a92c9980f54a8b93163c9c6df45021a92da1ee45..395544761abc5a72c3f86d7e51e50720a0e09aad 100644
--- a/apps/dav/lib/server.php
+++ b/apps/dav/lib/server.php
@@ -37,6 +37,12 @@ class Server {
 
 		$this->server->addPlugin(new \Sabre\CardDAV\Plugin());
 
+		// Finder on OS X requires Class 2 WebDAV support (locking), since we do
+		// not provide locking we emulate it using a fake locking plugin.
+		if($request->isUserAgent(['/WebDAVFS/'])) {
+			$this->server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin());
+		}
+
 		// wait with registering these until auth is handled and the filesystem is setup
 		$this->server->on('beforeMethod', function () {
 			// custom properties plugin must be the last one
diff --git a/apps/dav/tests/unit/connector/sabre/FakeLockerPluginTest.php b/apps/dav/tests/unit/connector/sabre/FakeLockerPluginTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..dfe8cc220a37e99031ae15d7befecbca9a09d11e
--- /dev/null
+++ b/apps/dav/tests/unit/connector/sabre/FakeLockerPluginTest.php
@@ -0,0 +1,173 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OCA\DAV\Tests\Unit\Connector\Sabre;
+
+use OCA\DAV\Connector\Sabre\FakeLockerPlugin;
+use Test\TestCase;
+
+/**
+ * Class FakeLockerPluginTest
+ *
+ * @package OCA\DAV\Tests\Unit\Connector\Sabre
+ */
+class FakeLockerPluginTest extends TestCase {
+	/** @var FakeLockerPlugin */
+	private $fakeLockerPlugin;
+
+	public function setUp() {
+		parent::setUp();
+		$this->fakeLockerPlugin = new FakeLockerPlugin();
+	}
+
+	public function testInitialize() {
+		/** @var \Sabre\DAV\Server $server */
+		$server = $this->getMock('\Sabre\DAV\Server');
+		$server
+			->expects($this->at(0))
+			->method('on')
+			->with('method:LOCK', [$this->fakeLockerPlugin, 'fakeLockProvider'], 1);
+		$server
+			->expects($this->at(1))
+			->method('on')
+			->with('method:UNLOCK', [$this->fakeLockerPlugin, 'fakeUnlockProvider'], 1);
+		$server
+			->expects($this->at(2))
+			->method('on')
+			->with('propFind', [$this->fakeLockerPlugin, 'propFind']);
+		$server
+			->expects($this->at(3))
+			->method('on')
+			->with('validateTokens', [$this->fakeLockerPlugin, 'validateTokens']);
+
+		$this->fakeLockerPlugin->initialize($server);
+	}
+
+	public function testGetHTTPMethods() {
+		$expected = [
+			'LOCK',
+			'UNLOCK',
+		];
+		$this->assertSame($expected, $this->fakeLockerPlugin->getHTTPMethods('Test'));
+	}
+
+	public function testGetFeatures() {
+		$expected = [
+			2,
+		];
+		$this->assertSame($expected, $this->fakeLockerPlugin->getFeatures());
+	}
+
+	public function testPropFind() {
+		$propFind = $this->getMockBuilder('\Sabre\DAV\PropFind')
+			->disableOriginalConstructor()
+			->getMock();
+		$node = $this->getMock('\Sabre\DAV\INode');
+
+		$propFind->expects($this->at(0))
+			->method('handle')
+			->with('{DAV:}supportedlock');
+		$propFind->expects($this->at(1))
+			->method('handle')
+			->with('{DAV:}lockdiscovery');
+
+		$this->fakeLockerPlugin->propFind($propFind, $node);
+	}
+
+	public function tokenDataProvider() {
+		return [
+			[
+				[
+					[
+						'tokens' => [
+							[
+								'token' => 'aToken',
+								'validToken' => false,
+							],
+							[],
+							[
+								'token' => 'opaquelocktoken:asdf',
+								'validToken' => false,
+							]
+						],
+					]
+				],
+				[
+					[
+						'tokens' => [
+							[
+								'token' => 'aToken',
+								'validToken' => false,
+							],
+							[],
+							[
+								'token' => 'opaquelocktoken:asdf',
+								'validToken' => true,
+							]
+						],
+					]
+				],
+			]
+		];
+	}
+
+	/**
+	 * @dataProvider tokenDataProvider
+	 * @param array $input
+	 * @param array $expected
+	 */
+	public function testValidateTokens(array $input, array $expected) {
+		$request = $this->getMock('\Sabre\HTTP\RequestInterface');
+		$this->fakeLockerPlugin->validateTokens($request, $input);
+		$this->assertSame($expected, $input);
+	}
+
+	public function testFakeLockProvider() {
+		$request = $this->getMock('\Sabre\HTTP\RequestInterface');
+		$response = $this->getMock('\Sabre\HTTP\ResponseInterface');
+		$server = $this->getMock('\Sabre\DAV\Server');
+		$this->fakeLockerPlugin->initialize($server);
+
+		$request->expects($this->exactly(2))
+			->method('getPath')
+			->will($this->returnValue('MyPath'));
+		$response->expects($this->once())
+			->method('setBody')
+			->with('<?xml version="1.0" encoding="utf-8"?>
+<d:prop xmlns:d="DAV:"><d:lockdiscovery><d:activelock><d:lockscope><d:exclusive/></d:lockscope><d:locktype><d:write/></d:locktype><d:lockroot><d:href>MyPath</d:href></d:lockroot><d:depth>infinity</d:depth><d:timeout>Second-1800</d:timeout><d:locktoken><d:href>opaquelocktoken:fe4f7f2437b151fbcb4e9f5c8118c6b1</d:href></d:locktoken><d:owner/></d:activelock></d:lockdiscovery></d:prop>
+');
+
+		$this->assertSame(false, $this->fakeLockerPlugin->fakeLockProvider($request, $response));
+	}
+
+	public function testFakeUnlockProvider() {
+		$request = $this->getMock('\Sabre\HTTP\RequestInterface');
+		$response = $this->getMock('\Sabre\HTTP\ResponseInterface');
+
+		$response->expects($this->once())
+				->method('setStatus')
+				->with('204');
+		$response->expects($this->once())
+				->method('setHeader')
+				->with('Content-Length', '0');
+
+		$this->assertSame(false, $this->fakeLockerPlugin->fakeUnlockProvider($request, $response));
+	}
+}
diff --git a/apps/dav/tests/unit/connector/sabre/requesttest/requesttest.php b/apps/dav/tests/unit/connector/sabre/requesttest/requesttest.php
index d90cf6e19bcbfc63a74e4bc93d5fb5e03b05a65f..a83f25c15854ecf329087273767bdb17b1808c56 100644
--- a/apps/dav/tests/unit/connector/sabre/requesttest/requesttest.php
+++ b/apps/dav/tests/unit/connector/sabre/requesttest/requesttest.php
@@ -46,7 +46,8 @@ abstract class RequestTest extends TestCase {
 			\OC::$server->getUserSession(),
 			\OC::$server->getMountManager(),
 			\OC::$server->getTagManager(),
-			\OC::$server->getEventDispatcher()
+			\OC::$server->getEventDispatcher(),
+			$this->getMock('\OCP\IRequest')
 		);
 	}
 
@@ -67,6 +68,7 @@ abstract class RequestTest extends TestCase {
 	 * @param resource|string|null $body
 	 * @param array|null $headers
 	 * @return \Sabre\HTTP\Response
+	 * @throws \Exception
 	 */
 	protected function request($view, $user, $password, $method, $url, $body = null, $headers = null) {
 		if (is_string($body)) {