summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLukas Reschke <lukas@owncloud.com>2014-08-31 15:50:30 +0200
committerLukas Reschke <lukas@owncloud.com>2014-08-31 15:50:30 +0200
commit8009df0b60c71bac41e4ead9ec8e4e92812e0d75 (patch)
treea937e0948af28bffff46eb08f24c93712032d26a /lib
parent73685892ed6f255a916512863cd5549914d071e1 (diff)
parent3a85767182e04ac013f59d82cc3a8c4d08bab151 (diff)
downloadnextcloud-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.php2
-rw-r--r--lib/private/security/certificate.php126
-rw-r--r--lib/private/security/certificatemanager.php134
-rw-r--r--lib/private/server.php18
-rw-r--r--lib/public/icertificate.php56
-rw-r--r--lib/public/icertificatemanager.php40
-rw-r--r--lib/public/iservercontainer.php7
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);
}