diff --git a/apps/dav/appinfo/database.xml b/apps/dav/appinfo/database.xml
index 5e2dad097e48458d2072cc7cc0b01d507ed23c4c..48641c2be6ffc5d32608550b0c0528d319f69b3c 100644
--- a/apps/dav/appinfo/database.xml
+++ b/apps/dav/appinfo/database.xml
@@ -570,4 +570,55 @@ CREATE TABLE calendarobjects (
 
 		</declaration>
 	</table>
+
+	<table>
+		<name>*dbprefix*dav_shares</name>
+		<declaration>
+			<field>
+				<name>id</name>
+				<type>integer</type>
+				<default>0</default>
+				<notnull>true</notnull>
+				<autoincrement>1</autoincrement>
+				<unsigned>true</unsigned>
+				<length>11</length>
+			</field>
+			<field>
+				<name>uri</name>
+				<type>text</type>
+			</field>
+			<field>
+				<name>principaluri</name>
+				<type>text</type>
+			</field>
+			<field>
+				<name>type</name>
+				<type>text</type>
+			</field>
+			<field>
+				<name>access</name>
+				<type>integer</type>
+				<length>1</length>
+			</field>
+			<field>
+				<name>resourceid</name>
+				<type>integer</type>
+				<notnull>true</notnull>
+				<unsigned>true</unsigned>
+			</field>
+			<index>
+				<name>dav_shares_index</name>
+				<unique>true</unique>
+				<field>
+					<name>principaluri</name>
+				</field>
+				<field>
+					<name>uri</name>
+				</field>
+				<field>
+					<name>type</name>
+				</field>
+			</index>
+		</declaration>
+	</table>
 </database>
diff --git a/apps/dav/lib/carddav/addressbook.php b/apps/dav/lib/carddav/addressbook.php
new file mode 100644
index 0000000000000000000000000000000000000000..e50f6f4adf6f828391b7ba07d32cf566857f1950
--- /dev/null
+++ b/apps/dav/lib/carddav/addressbook.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace OCA\DAV\CardDAV;
+
+use OCA\DAV\CardDAV\Sharing\IShareableAddressBook;
+use OCP\IUserManager;
+
+class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareableAddressBook {
+
+	/** @var IUserManager */
+	private $userManager;
+
+	public function __construct(CardDavBackend $carddavBackend, array $addressBookInfo) {
+		parent::__construct($carddavBackend, $addressBookInfo);
+	}
+
+	/**
+	 * Updates the list of shares.
+	 *
+	 * The first array is a list of people that are to be added to the
+	 * addressbook.
+	 *
+	 * Every element in the add array has the following properties:
+	 *   * href - A url. Usually a mailto: address
+	 *   * commonName - Usually a first and last name, or false
+	 *   * summary - A description of the share, can also be false
+	 *   * readOnly - A boolean value
+	 *
+	 * Every element in the remove array is just the address string.
+	 *
+	 * @param array $add
+	 * @param array $remove
+	 * @return void
+	 */
+	function updateShares(array $add, array $remove) {
+		/** @var CardDavBackend $carddavBackend */
+		$carddavBackend = $this->carddavBackend;
+		$carddavBackend->updateShares($this->getName(), $add, $remove);
+	}
+
+	/**
+	 * Returns the list of people whom this addressbook is shared with.
+	 *
+	 * Every element in this array should have the following properties:
+	 *   * href - Often a mailto: address
+	 *   * commonName - Optional, for example a first + last name
+	 *   * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
+	 *   * readOnly - boolean
+	 *   * summary - Optional, a description for the share
+	 *
+	 * @return array
+	 */
+	function getShares() {
+		/** @var CardDavBackend $carddavBackend */
+		$carddavBackend = $this->carddavBackend;
+		$carddavBackend->getShares($this->getName());
+	}
+}
\ No newline at end of file
diff --git a/apps/dav/lib/carddav/addressbookroot.php b/apps/dav/lib/carddav/addressbookroot.php
new file mode 100644
index 0000000000000000000000000000000000000000..ee99ac8d7989dd19b53d70d07ca04ec44a706464
--- /dev/null
+++ b/apps/dav/lib/carddav/addressbookroot.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace OCA\DAV\CardDAV;
+
+class AddressBookRoot extends \Sabre\CardDAV\AddressBookRoot {
+
+	/**
+	 * This method returns a node for a principal.
+	 *
+	 * The passed array contains principal information, and is guaranteed to
+	 * at least contain a uri item. Other properties may or may not be
+	 * supplied by the authentication backend.
+	 *
+	 * @param array $principal
+	 * @return \Sabre\DAV\INode
+	 */
+	function getChildForPrincipal(array $principal) {
+
+		return new UserAddressBooks($this->carddavBackend, $principal['uri']);
+
+	}
+
+}
\ No newline at end of file
diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php
index b2597baedc6336252e274491613aba4c12449b7a..348c166a5311e258910f11f0b9ad66fabe25987c 100644
--- a/apps/dav/lib/carddav/carddavbackend.php
+++ b/apps/dav/lib/carddav/carddavbackend.php
@@ -22,6 +22,7 @@
 
 namespace OCA\DAV\CardDAV;
 
+use OCA\DAV\Connector\Sabre\Principal;
 use Sabre\CardDAV\Backend\BackendInterface;
 use Sabre\CardDAV\Backend\SyncSupport;
 use Sabre\CardDAV\Plugin;
@@ -29,8 +30,12 @@ use Sabre\DAV\Exception\BadRequest;
 
 class CardDavBackend implements BackendInterface, SyncSupport {
 
-	public function __construct(\OCP\IDBConnection $db) {
+	/** @var Principal */
+	private $principalBackend;
+
+	public function __construct(\OCP\IDBConnection $db, Principal $principalBackend) {
 		$this->db = $db;
+		$this->principalBackend = $principalBackend;
 	}
 
 	/**
@@ -73,9 +78,61 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 		}
 		$result->closeCursor();
 
+		// query for shared calendars
+		$query = $this->db->getQueryBuilder();
+		$query2 = $this->db->getQueryBuilder();
+		$query2->select(['resourceid'])
+			->from('dav_shares')
+			->where($query2->expr()->eq('principaluri', $query2->createParameter('principaluri')))
+			->andWhere($query2->expr()->eq('type', $query2->createParameter('type')));
+		$result = $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken'])
+			->from('addressbooks')
+			->where($query->expr()->in('id', $query->createFunction($query2->getSQL())))
+			->setParameter('type', 'addressbook')
+			->setParameter('principaluri', $principalUri)
+			->execute();
+
+		while($row = $result->fetch()) {
+			$addressBooks[] = [
+				'id'  => $row['id'],
+				'uri' => $row['uri'],
+				'principaluri' => $row['principaluri'],
+				'{DAV:}displayname' => $row['displayname'],
+				'{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'],
+				'{http://calendarserver.org/ns/}getctag' => $row['synctoken'],
+				'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
+			];
+		}
+		$result->closeCursor();
+
 		return $addressBooks;
 	}
 
+	private function getAddressBooksByUri($addressBookUri) {
+		$query = $this->db->getQueryBuilder();
+		$result = $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken'])
+			->from('addressbooks')
+			->where($query->expr()->eq('uri', $query->createNamedParameter($addressBookUri)))
+			->setMaxResults(1)
+			->execute();
+
+		$row = $result->fetch();
+		if (is_null($row)) {
+			return null;
+		}
+		$result->closeCursor();
+
+		return [
+				'id'  => $row['id'],
+				'uri' => $row['uri'],
+				'principaluri' => $row['principaluri'],
+				'{DAV:}displayname' => $row['displayname'],
+				'{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'],
+				'{http://calendarserver.org/ns/}getctag' => $row['synctoken'],
+				'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
+			];
+	}
+
 	/**
 	 * Updates properties for an address book.
 	 *
@@ -86,7 +143,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 	 * Calling the handle method is like telling the PropPatch object "I
 	 * promise I can handle updating this property".
 	 *
-	 * Read the PropPatch documenation for more info and examples.
+	 * Read the PropPatch documentation for more info and examples.
 	 *
 	 * @param string $addressBookId
 	 * @param \Sabre\DAV\PropPatch $propPatch
@@ -201,6 +258,11 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 			->where($query->expr()->eq('id', $query->createParameter('id')))
 			->setParameter('id', $addressBookId)
 			->execute();
+
+		$query->delete('dav_shares')
+			->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressBookId)))
+			->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook')))
+			->execute();
 	}
 
 	/**
@@ -561,4 +623,115 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 		return $cardData;
 	}
 
+	/**
+	 * @param string $path
+	 * @param string[] $add
+	 * @param string[] $remove
+	 */
+	public function updateShares($path, $add, $remove) {
+		foreach($add as $element) {
+			$this->shareWith($path, $element);
+		}
+		foreach($remove as $element) {
+			$this->unshare($path, $element);
+		}
+	}
+
+	/**
+	 * @param string $addressBookUri
+	 * @param string $element
+	 */
+	private function shareWith($addressBookUri, $element) {
+		$user = $element['href'];
+		$parts = explode(':', $user, 2);
+		if ($parts[0] !== 'principal') {
+			return;
+		}
+		$p = $this->principalBackend->getPrincipalByPath($parts[1]);
+		if (is_null($p)) {
+			return;
+		}
+
+		$addressBook = $this->getAddressBooksByUri($addressBookUri);
+		if (is_null($addressBook)) {
+			return;
+		}
+
+		// remove the share if it already exists
+		$this->unshare($addressBookUri, $element);
+
+		$query = $this->db->getQueryBuilder();
+		$query->insert('dav_shares')
+			->values([
+				'principaluri' => $query->createNamedParameter($parts[1]),
+				'uri' => $query->createNamedParameter($addressBookUri),
+				'type' => $query->createNamedParameter('addressbook'),
+				'access' => $query->createNamedParameter(0),
+				'resourceid' => $query->createNamedParameter($addressBook['id'])
+			]);
+		$query->execute();
+	}
+
+	/**
+	 * @param string $addressBookUri
+	 * @param string $element
+	 */
+	private function unshare($addressBookUri, $element) {
+		$user = $element['href'];
+		$parts = explode(':', $user, 2);
+		if ($parts[0] !== 'principal') {
+			return;
+		}
+		$p = $this->principalBackend->getPrincipalByPath($parts[1]);
+		if (is_null($p)) {
+			return;
+		}
+
+		$addressBook = $this->getAddressBooksByUri($addressBookUri);
+		if (is_null($addressBook)) {
+			return;
+		}
+
+		$query = $this->db->getQueryBuilder();
+		$query->delete('dav_shares')
+			->where($query->expr()->eq('resourceid', $query->createNamedParameter($addressBook['id'])))
+			->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook')))
+			->andWhere($query->expr()->eq('principaluri', $query->createNamedParameter($parts[1])))
+		;
+		$query->execute();
+	}
+
+	/**
+	 * Returns the list of people whom this address book is shared with.
+	 *
+	 * Every element in this array should have the following properties:
+	 *   * href - Often a mailto: address
+	 *   * commonName - Optional, for example a first + last name
+	 *   * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
+	 *   * readOnly - boolean
+	 *   * summary - Optional, a description for the share
+	 *
+	 * @return array
+	 */
+	public function getShares($addressBookUri) {
+		$query = $this->db->getQueryBuilder();
+		$result = $query->select(['principaluri', 'access'])
+			->from('dav_shares')
+			->where($query->expr()->eq('uri', $query->createNamedParameter($addressBookUri)))
+			->andWhere($query->expr()->eq('type', $query->createNamedParameter('addressbook')))
+			->execute();
+
+		$shares = [];
+		while($row = $result->fetch()) {
+			$p = $this->principalBackend->getPrincipalByPath($row['principaluri']);
+			$shares[]= [
+				'href' => "principal:${p['uri']}",
+				'commonName' => isset($p['{DAV:}displayname']) ? $p['{DAV:}displayname'] : '',
+				'status' => 1,
+				'readOnly' => ($row['access'] === 1)
+			];
+		}
+
+		return $shares;
+	}
 }
diff --git a/apps/dav/lib/carddav/sharing/ishareableaddressbook.php b/apps/dav/lib/carddav/sharing/ishareableaddressbook.php
new file mode 100644
index 0000000000000000000000000000000000000000..856a9ed18e61585fe4be7dbba449585729de0f4c
--- /dev/null
+++ b/apps/dav/lib/carddav/sharing/ishareableaddressbook.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace OCA\DAV\CardDAV\Sharing;
+use Sabre\CardDAV\IAddressBook;
+
+/**
+ * This interface represents a Calendar that can be shared with other users.
+ *
+ */
+interface IShareableAddressBook extends IAddressBook {
+
+	/**
+	 * Updates the list of shares.
+	 *
+	 * The first array is a list of people that are to be added to the
+	 * addressbook.
+	 *
+	 * Every element in the add array has the following properties:
+	 *   * href - A url. Usually a mailto: address
+	 *   * commonName - Usually a first and last name, or false
+	 *   * summary - A description of the share, can also be false
+	 *   * readOnly - A boolean value
+	 *
+	 * Every element in the remove array is just the address string.
+	 *
+	 * @param array $add
+	 * @param array $remove
+	 * @return void
+	 */
+	function updateShares(array $add, array $remove);
+
+	/**
+	 * Returns the list of people whom this addressbook is shared with.
+	 *
+	 * Every element in this array should have the following properties:
+	 *   * href - Often a mailto: address
+	 *   * commonName - Optional, for example a first + last name
+	 *   * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
+	 *   * readOnly - boolean
+	 *   * summary - Optional, a description for the share
+	 *
+	 * @return array
+	 */
+	function getShares();
+
+}
\ No newline at end of file
diff --git a/apps/dav/lib/carddav/sharing/plugin.php b/apps/dav/lib/carddav/sharing/plugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..eeb5abc6d23957da5b9f1c987f9d031b06cbce5c
--- /dev/null
+++ b/apps/dav/lib/carddav/sharing/plugin.php
@@ -0,0 +1,218 @@
+<?php
+
+namespace OCA\DAV\CardDAV\Sharing;
+
+use OCA\DAV\Connector\Sabre\Auth;
+use OCP\IRequest;
+use Sabre\DAV\Exception\BadRequest;
+use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+use Sabre\DAV\XMLUtil;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+
+class Plugin extends ServerPlugin {
+
+	public function __construct(Auth $authBackEnd, IRequest $request) {
+		$this->auth = $authBackEnd;
+		$this->request = $request;
+	}
+
+	/**
+	 * Reference to SabreDAV server object.
+	 *
+	 * @var \Sabre\DAV\Server
+	 */
+	protected $server;
+
+	/**
+	 * This method should return a list of server-features.
+	 *
+	 * This is for example 'versioning' and is added to the DAV: header
+	 * in an OPTIONS response.
+	 *
+	 * @return array
+	 */
+	function getFeatures() {
+
+		return ['oc-addressbook-sharing'];
+
+	}
+
+	/**
+	 * Returns a plugin name.
+	 *
+	 * Using this name other plugins will be able to access other plugins
+	 * using Sabre\DAV\Server::getPlugin
+	 *
+	 * @return string
+	 */
+	function getPluginName() {
+
+		return 'carddav-sharing';
+
+	}
+
+	/**
+	 * This initializes the plugin.
+	 *
+	 * This function is called by Sabre\DAV\Server, after
+	 * addPlugin is called.
+	 *
+	 * This method should set up the required event subscriptions.
+	 *
+	 * @param Server $server
+	 * @return void
+	 */
+	function initialize(Server $server) {
+		$this->server = $server;
+		$server->resourceTypeMapping['OCA\\DAV\CardDAV\\ISharedAddressbook'] = '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}shared';
+
+		$this->server->on('method:POST', [$this, 'httpPost']);
+	}
+
+	/**
+	 * We intercept this to handle POST requests on calendars.
+	 *
+	 * @param RequestInterface $request
+	 * @param ResponseInterface $response
+	 * @return null|bool
+	 */
+	function httpPost(RequestInterface $request, ResponseInterface $response) {
+
+		$path = $request->getPath();
+
+		// Only handling xml
+		$contentType = $request->getHeader('Content-Type');
+		if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false)
+			return;
+
+		// Making sure the node exists
+		try {
+			$node = $this->server->tree->getNodeForPath($path);
+		} catch (NotFound $e) {
+			return;
+		}
+
+		// CSRF protection
+		$this->protectAgainstCSRF();
+
+		$requestBody = $request->getBodyAsString();
+
+		// If this request handler could not deal with this POST request, it
+		// will return 'null' and other plugins get a chance to handle the
+		// request.
+		//
+		// However, we already requested the full body. This is a problem,
+		// because a body can only be read once. This is why we preemptively
+		// re-populated the request body with the existing data.
+		$request->setBody($requestBody);
+
+		$dom = XMLUtil::loadDOMDocument($requestBody);
+
+		$documentType = XMLUtil::toClarkNotation($dom->firstChild);
+
+		switch ($documentType) {
+
+			// Dealing with the 'share' document, which modified invitees on a
+			// calendar.
+			case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}share' :
+
+				// We can only deal with IShareableCalendar objects
+				if (!$node instanceof IShareableAddressBook) {
+					return;
+				}
+
+				$this->server->transactionType = 'post-calendar-share';
+
+				// Getting ACL info
+				$acl = $this->server->getPlugin('acl');
+
+				// If there's no ACL support, we allow everything
+				if ($acl) {
+					$acl->checkPrivileges($path, '{DAV:}write');
+				}
+
+				$mutations = $this->parseShareRequest($dom);
+
+				$node->updateShares($mutations[0], $mutations[1]);
+
+				$response->setStatus(200);
+				// Adding this because sending a response body may cause issues,
+				// and I wanted some type of indicator the response was handled.
+				$response->setHeader('X-Sabre-Status', 'everything-went-well');
+
+				// Breaking the event chain
+				return false;
+		}
+	}
+
+	/**
+	 * Parses the 'share' POST request.
+	 *
+	 * This method returns an array, containing two arrays.
+	 * The first array is a list of new sharees. Every element is a struct
+	 * containing a:
+	 *   * href element. (usually a mailto: address)
+	 *   * commonName element (often a first and lastname, but can also be
+	 *     false)
+	 *   * readOnly (true or false)
+	 *   * summary (A description of the share, can also be false)
+	 *
+	 * The second array is a list of sharees that are to be removed. This is
+	 * just a simple array with 'hrefs'.
+	 *
+	 * @param \DOMDocument $dom
+	 * @return array
+	 */
+	function parseShareRequest(\DOMDocument $dom) {
+
+		$xpath = new \DOMXPath($dom);
+		$xpath->registerNamespace('cs', \Sabre\CardDAV\Plugin::NS_CARDDAV);
+		$xpath->registerNamespace('d', 'urn:DAV');
+
+		$set = [];
+		$elems = $xpath->query('cs:set');
+
+		for ($i = 0; $i < $elems->length; $i++) {
+
+			$xset = $elems->item($i);
+			$set[] = [
+				'href' => $xpath->evaluate('string(d:href)', $xset),
+				'commonName' => $xpath->evaluate('string(cs:common-name)', $xset),
+				'summary' => $xpath->evaluate('string(cs:summary)', $xset),
+				'readOnly' => $xpath->evaluate('boolean(cs:read)', $xset) !== false
+			];
+
+		}
+
+		$remove = [];
+		$elems = $xpath->query('cs:remove');
+
+		for ($i = 0; $i < $elems->length; $i++) {
+
+			$xremove = $elems->item($i);
+			$remove[] = $xpath->evaluate('string(d:href)', $xremove);
+
+		}
+
+		return [$set, $remove];
+
+	}
+
+	private function protectAgainstCSRF() {
+		$user = $this->auth->getCurrentUser();
+		if ($this->auth->isDavAuthenticated($user)) {
+			return true;
+		}
+
+		if ($this->request->passesCSRFCheck()) {
+			return true;
+		}
+
+		throw new BadRequest();
+	}
+
+
+}
diff --git a/apps/dav/lib/carddav/useraddressbooks.php b/apps/dav/lib/carddav/useraddressbooks.php
new file mode 100644
index 0000000000000000000000000000000000000000..adbb0292fa7a946d543c09c2895e4dd89445d292
--- /dev/null
+++ b/apps/dav/lib/carddav/useraddressbooks.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace OCA\DAV\CardDAV;
+
+class UserAddressBooks extends \Sabre\CardDAV\UserAddressBooks {
+
+	/**
+	 * Returns a list of addressbooks
+	 *
+	 * @return array
+	 */
+	function getChildren() {
+
+		$addressbooks = $this->carddavBackend->getAddressBooksForUser($this->principalUri);
+		$objs = [];
+		foreach($addressbooks as $addressbook) {
+			$objs[] = new AddressBook($this->carddavBackend, $addressbook);
+		}
+		return $objs;
+
+	}
+
+}
diff --git a/apps/dav/lib/connector/sabre/auth.php b/apps/dav/lib/connector/sabre/auth.php
index 39a7df31b7f93d01c624874f5c0d9a387a68a229..0394bfd67728fd14bab02d0808970988603cf917 100644
--- a/apps/dav/lib/connector/sabre/auth.php
+++ b/apps/dav/lib/connector/sabre/auth.php
@@ -65,7 +65,7 @@ class Auth extends AbstractBasic {
 	 * @param string $username
 	 * @return bool
 	 */
-	protected function isDavAuthenticated($username) {
+	public function isDavAuthenticated($username) {
 		return !is_null($this->session->get(self::DAV_AUTHENTICATED)) &&
 		$this->session->get(self::DAV_AUTHENTICATED) === $username;
 	}
diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php
index 10baff072cce7253d333e10327c07d8a77cdd6e3..672e0a98684aaf460a2f77f74ad24ae193c123e8 100644
--- a/apps/dav/lib/rootcollection.php
+++ b/apps/dav/lib/rootcollection.php
@@ -3,11 +3,11 @@
 namespace OCA\DAV;
 
 use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CardDAV\AddressBookRoot;
 use OCA\DAV\CardDAV\CardDavBackend;
 use OCA\DAV\Connector\Sabre\Principal;
 use Sabre\CalDAV\CalendarRoot;
 use Sabre\CalDAV\Principal\Collection;
-use Sabre\CardDAV\AddressBookRoot;
 use Sabre\DAV\SimpleCollection;
 
 class RootCollection extends SimpleCollection {
@@ -30,7 +30,9 @@ class RootCollection extends SimpleCollection {
 		$caldavBackend = new CalDavBackend($db);
 		$calendarRoot = new CalendarRoot($principalBackend, $caldavBackend);
 		$calendarRoot->disableListing = $disableListing;
-		$cardDavBackend = new CardDavBackend($db);
+
+		$cardDavBackend = new CardDavBackend(\OC::$server->getDatabaseConnection(), $principalBackend);
+
 		$addressBookRoot = new AddressBookRoot($principalBackend, $cardDavBackend);
 		$addressBookRoot->disableListing = $disableListing;
 
diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php
index 229f33858d9454b51a842b5002a807fd17be81d0..44afcf23df684b86c6dc2223bd6a22efedc307ec 100644
--- a/apps/dav/lib/server.php
+++ b/apps/dav/lib/server.php
@@ -50,6 +50,7 @@ class Server {
 		$this->server->addPlugin(new \Sabre\CalDAV\SharingPlugin());
 		$this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
 		$this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());
+		$this->server->addPlugin(new CardDAV\Sharing\Plugin($authBackend, \OC::$server->getRequest()));
 
 		// addressbook plugins
 		$this->server->addPlugin(new \Sabre\CardDAV\Plugin());
diff --git a/apps/dav/tests/misc/sharing.xml b/apps/dav/tests/misc/sharing.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8771256ce79a28824480cc6b6f7b76336ccb7a63
--- /dev/null
+++ b/apps/dav/tests/misc/sharing.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" ?>
+		<CS:share xmlns:D="DAV:" xmlns:CS="urn:ietf:params:xml:ns:carddav">
+			     <CS:set>
+	       <D:href>principal:principals/admin</D:href>
+	       <CS:read-write />
+	     </CS:set>
+		   </CS:share>
diff --git a/apps/dav/tests/unit/carddav/carddavbackendtest.php b/apps/dav/tests/unit/carddav/carddavbackendtest.php
index 79ef36d8097fa310c9c41582c9e7d419c471a890..dd5e205242a15b498c6e65c9dc11656815f75c0e 100644
--- a/apps/dav/tests/unit/carddav/carddavbackendtest.php
+++ b/apps/dav/tests/unit/carddav/carddavbackendtest.php
@@ -24,6 +24,13 @@ use OCA\DAV\CardDAV\CardDavBackend;
 use Sabre\DAV\PropPatch;
 use Test\TestCase;
 
+/**
+ * Class CardDavBackendTest
+ *
+ * @group DB
+ *
+ * @package OCA\DAV\Tests\Unit\CardDAV
+ */
 class CardDavBackendTest extends TestCase {
 
 	/** @var CardDavBackend */
@@ -31,12 +38,20 @@ class CardDavBackendTest extends TestCase {
 
 	const UNIT_TEST_USER = 'carddav-unit-test';
 
-
 	public function setUp() {
 		parent::setUp();
 
+		$principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal')
+			->disableOriginalConstructor()
+			->setMethods(['getPrincipalByPath'])
+			->getMock();
+		$principal->method('getPrincipalByPath')
+			->willReturn([
+				'uri' => 'principals/best-friend'
+			]);
+
 		$db = \OC::$server->getDatabaseConnection();
-		$this->backend = new CardDavBackend($db);
+		$this->backend = new CardDavBackend($db, $principal);
 
 		$this->tearDown();
 	}
@@ -178,4 +193,32 @@ class CardDavBackendTest extends TestCase {
 		$changes = $this->backend->getChangesForAddressBook($bookId, $syncToken, 1);
 		$this->assertEquals($uri0, $changes['added'][0]);
 	}
+
+	public function testSharing() {
+		$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
+		$books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER);
+		$this->assertEquals(1, count($books));
+
+		$this->backend->updateShares('Example', [['href' => 'principal:principals/best-friend']], []);
+
+		$shares = $this->backend->getShares('Example');
+		$this->assertEquals(1, count($shares));
+
+		// adding the same sharee again has no effect
+		$this->backend->updateShares('Example', [['href' => 'principal:principals/best-friend']], []);
+
+		$shares = $this->backend->getShares('Example');
+		$this->assertEquals(1, count($shares));
+
+		$books = $this->backend->getAddressBooksForUser('principals/best-friend');
+		$this->assertEquals(1, count($books));
+
+		$this->backend->updateShares('Example', [], [['href' => 'principal:principals/best-friend']]);
+
+		$shares = $this->backend->getShares('Example');
+		$this->assertEquals(0, count($shares));
+
+		$books = $this->backend->getAddressBooksForUser('principals/best-friend');
+		$this->assertEquals(0, count($books));
+	}
 }