diff options
author | Lukas Reschke <lukas@owncloud.com> | 2014-08-31 15:50:30 +0200 |
---|---|---|
committer | Lukas Reschke <lukas@owncloud.com> | 2014-08-31 15:50:30 +0200 |
commit | 8009df0b60c71bac41e4ead9ec8e4e92812e0d75 (patch) | |
tree | a937e0948af28bffff46eb08f24c93712032d26a /lib | |
parent | 73685892ed6f255a916512863cd5549914d071e1 (diff) | |
parent | 3a85767182e04ac013f59d82cc3a8c4d08bab151 (diff) | |
download | nextcloud-server-8009df0b60c71bac41e4ead9ec8e4e92812e0d75.tar.gz nextcloud-server-8009df0b60c71bac41e4ead9ec8e4e92812e0d75.zip |
Merge pull request #10420 from owncloud/external-share-self-signed
Make external shares work with imported self signed certificates
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/l10n.php | 2 | ||||
-rw-r--r-- | lib/private/security/certificate.php | 126 | ||||
-rw-r--r-- | lib/private/security/certificatemanager.php | 134 | ||||
-rw-r--r-- | lib/private/server.php | 18 | ||||
-rw-r--r-- | lib/public/icertificate.php | 56 | ||||
-rw-r--r-- | lib/public/icertificatemanager.php | 40 | ||||
-rw-r--r-- | lib/public/iservercontainer.php | 7 |
7 files changed, 382 insertions, 1 deletions
diff --git a/lib/private/l10n.php b/lib/private/l10n.php index 28b35e92a2f..57886a796cd 100644 --- a/lib/private/l10n.php +++ b/lib/private/l10n.php @@ -354,7 +354,7 @@ class OC_L10N implements \OCP\IL10N { case 'datetime': case 'time': if($data instanceof DateTime) { - return $data->format($this->localizations[$type]); + $data = $data->getTimestamp(); } elseif(is_string($data) && !is_numeric($data)) { $data = strtotime($data); } diff --git a/lib/private/security/certificate.php b/lib/private/security/certificate.php new file mode 100644 index 00000000000..778524507e0 --- /dev/null +++ b/lib/private/security/certificate.php @@ -0,0 +1,126 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Security; + +use OCP\ICertificate; + +class Certificate implements ICertificate { + protected $name; + + protected $commonName; + + protected $organization; + + protected $serial; + + protected $issueDate; + + protected $expireDate; + + protected $issuerName; + + protected $issuerOrganization; + + /** + * @param string $data base64 encoded certificate + * @param string $name + * @throws \Exception If the certificate could not get parsed + */ + public function __construct($data, $name) { + $this->name = $name; + try { + $gmt = new \DateTimeZone('GMT'); + $info = openssl_x509_parse($data); + $this->commonName = isset($info['subject']['CN']) ? $info['subject']['CN'] : null; + $this->organization = isset($info['subject']['O']) ? $info['subject']['O'] : null; + $this->serial = $this->formatSerial($info['serialNumber']); + $this->issueDate = new \DateTime('@' . $info['validFrom_time_t'], $gmt); + $this->expireDate = new \DateTime('@' . $info['validTo_time_t'], $gmt); + $this->issuerName = isset($info['issuer']['CN']) ? $info['issuer']['CN'] : null; + $this->issuerOrganization = isset($info['issuer']['O']) ? $info['issuer']['O'] : null; + } catch (\Exception $e) { + throw new \Exception('Certificate could not get parsed.'); + } + } + + /** + * Format the numeric serial into AA:BB:CC hex format + * + * @param int $serial + * @return string + */ + protected function formatSerial($serial) { + $hex = strtoupper(dechex($serial)); + return trim(chunk_split($hex, 2, ':'), ':'); + } + + /** + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * @return string|null + */ + public function getCommonName() { + return $this->commonName; + } + + /** + * @return string + */ + public function getOrganization() { + return $this->organization; + } + + /** + * @return string + */ + public function getSerial() { + return $this->serial; + } + + /** + * @return \DateTime + */ + public function getIssueDate() { + return $this->issueDate; + } + + /** + * @return \DateTime + */ + public function getExpireDate() { + return $this->expireDate; + } + + /** + * @return bool + */ + public function isExpired() { + $now = new \DateTime(); + return $this->issueDate > $now or $now > $this->expireDate; + } + + /** + * @return string|null + */ + public function getIssuerName() { + return $this->issuerName; + } + + /** + * @return string|null + */ + public function getIssuerOrganization() { + return $this->issuerOrganization; + } +} diff --git a/lib/private/security/certificatemanager.php b/lib/private/security/certificatemanager.php new file mode 100644 index 00000000000..cae9730eb26 --- /dev/null +++ b/lib/private/security/certificatemanager.php @@ -0,0 +1,134 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Security; + +use OC\Files\Filesystem; +use OCP\ICertificateManager; + +/** + * Manage trusted certificates for users + */ +class CertificateManager implements ICertificateManager { + /** + * @var \OCP\IUser + */ + protected $user; + + /** + * @param \OCP\IUser $user + */ + public function __construct($user) { + $this->user = $user; + } + + /** + * Returns all certificates trusted by the user + * + * @return \OCP\ICertificate[] + */ + public function listCertificates() { + $path = $this->user->getHome() . '/files_external/uploads/'; + if (!is_dir($path)) { + return array(); + } + $result = array(); + $handle = opendir($path); + if (!is_resource($handle)) { + return array(); + } + while (false !== ($file = readdir($handle))) { + if ($file != '.' && $file != '..') { + try { + $result[] = new Certificate(file_get_contents($path . $file), $file); + } catch(\Exception $e) {} + } + } + return $result; + } + + /** + * create the certificate bundle of all trusted certificated + */ + protected function createCertificateBundle() { + $path = $this->user->getHome() . '/files_external/'; + $certs = $this->listCertificates(); + + $fh_certs = fopen($path . '/rootcerts.crt', 'w'); + foreach ($certs as $cert) { + $file = $path . '/uploads/' . $cert->getName(); + $data = file_get_contents($file); + if (strpos($data, 'BEGIN CERTIFICATE')) { + fwrite($fh_certs, $data); + fwrite($fh_certs, "\r\n"); + } + } + + fclose($fh_certs); + } + + /** + * Save the certificate and re-generate the certificate bundle + * + * @param string $certificate the certificate data + * @param string $name the filename for the certificate + * @return \OCP\ICertificate|void|bool + * @throws \Exception If the certificate could not get added + */ + public function addCertificate($certificate, $name) { + if (!Filesystem::isValidPath($name) or Filesystem::isFileBlacklisted($name)) { + return false; + } + + $dir = $this->user->getHome() . '/files_external/uploads/'; + if (!file_exists($dir)) { + //path might not exist (e.g. non-standard OC_User::getHome() value) + //in this case create full path using 3rd (recursive=true) parameter. + //note that we use "normal" php filesystem functions here since the certs need to be local + mkdir($dir, 0700, true); + } + + try { + $file = $dir . $name; + $certificateObject = new Certificate($certificate, $name); + file_put_contents($file, $certificate); + $this->createCertificateBundle(); + return $certificateObject; + } catch (\Exception $e) { + throw $e; + } + + } + + /** + * Remove the certificate and re-generate the certificate bundle + * + * @param string $name + * @return bool + */ + public function removeCertificate($name) { + if (!Filesystem::isValidPath($name)) { + return false; + } + $path = $this->user->getHome() . '/files_external/uploads/'; + if (file_exists($path . $name)) { + unlink($path . $name); + $this->createCertificateBundle(); + } + return true; + } + + /** + * Get the path to the certificate bundle for this user + * + * @return string + */ + public function getCertificateBundle() { + return $this->user->getHome() . '/files_external/rootcerts.crt'; + } +} diff --git a/lib/private/server.php b/lib/private/server.php index 28c4fe60856..5d40f1327f6 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -6,6 +6,7 @@ use OC\AppFramework\Http\Request; use OC\AppFramework\Db\Db; use OC\AppFramework\Utility\SimpleContainer; use OC\Cache\UserCache; +use OC\Security\CertificateManager; use OC\DB\ConnectionWrapper; use OC\Files\Node\Root; use OC\Files\View; @@ -474,4 +475,21 @@ class Server extends SimpleContainer implements IServerContainer { function getDb() { return $this->query('Db'); } + + /** + * Get the certificate manager for the user + * + * @param \OCP\IUser $user (optional) if not specified the current loggedin user is used + * @return \OCP\ICertificateManager + */ + function getCertificateManager($user = null) { + if (is_null($user)) { + $userSession = $this->getUserSession(); + $user = $userSession->getUser(); + if (is_null($user)) { + return null; + } + } + return new CertificateManager($user); + } } diff --git a/lib/public/icertificate.php b/lib/public/icertificate.php new file mode 100644 index 00000000000..013496cb373 --- /dev/null +++ b/lib/public/icertificate.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP; + +interface ICertificate { + /** + * @return string + */ + public function getName(); + + /** + * @return string + */ + public function getCommonName(); + + /** + * @return string + */ + public function getOrganization(); + + /** + * @return string + */ + public function getSerial(); + + /** + * @return \DateTime + */ + public function getIssueDate(); + + /** + * @return \DateTime + */ + public function getExpireDate(); + + /** + * @return bool + */ + public function isExpired(); + + /** + * @return string + */ + public function getIssuerName(); + + /** + * @return string + */ + public function getIssuerOrganization(); +} diff --git a/lib/public/icertificatemanager.php b/lib/public/icertificatemanager.php new file mode 100644 index 00000000000..24b8d123634 --- /dev/null +++ b/lib/public/icertificatemanager.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP; + +/** + * Manage trusted certificates for users + */ +interface ICertificateManager { + /** + * Returns all certificates trusted by the user + * + * @return \OCP\ICertificate[] + */ + public function listCertificates(); + + /** + * @param string $certificate the certificate data + * @param string $name the filename for the certificate + * @return bool | \OCP\ICertificate + */ + public function addCertificate($certificate, $name); + + /** + * @param string $name + */ + public function removeCertificate($name); + + /** + * Get the path to the certificate bundle for this user + * + * @return string + */ + public function getCertificateBundle(); +} diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index 64f5f350b1e..60b0b497c54 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -228,4 +228,11 @@ interface IServerContainer { */ function getSearch(); + /** + * Get the certificate manager for the user + * + * @param \OCP\IUser $user (optional) if not specified the current loggedin user is used + * @return \OCP\ICertificateManager + */ + function getCertificateManager($user = null); } |