Merge pull request #10420 from owncloud/external-share-self-signed
Make external shares work with imported self signed certificates
This commit is contained in:
commit
8009df0b60
|
@ -1,45 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
OCP\JSON::checkAppEnabled('files_external');
|
|
||||||
OCP\JSON::callCheck();
|
|
||||||
|
|
||||||
if ( ! ($filename = $_FILES['rootcert_import']['name']) ) {
|
|
||||||
header('Location:' . OCP\Util::linkToRoute( "settings_personal" ));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$fh = fopen($_FILES['rootcert_import']['tmp_name'], 'r');
|
|
||||||
$data = fread($fh, filesize($_FILES['rootcert_import']['tmp_name']));
|
|
||||||
fclose($fh);
|
|
||||||
$filename = $_FILES['rootcert_import']['name'];
|
|
||||||
|
|
||||||
$view = new \OC\Files\View('/'.\OCP\User::getUser().'/files_external/uploads');
|
|
||||||
if (!$view->file_exists('')) {
|
|
||||||
$view->mkdir('');
|
|
||||||
}
|
|
||||||
|
|
||||||
$isValid = openssl_pkey_get_public($data);
|
|
||||||
|
|
||||||
//maybe it was just the wrong file format, try to convert it...
|
|
||||||
if ($isValid == false) {
|
|
||||||
$data = chunk_split(base64_encode($data), 64, "\n");
|
|
||||||
$data = "-----BEGIN CERTIFICATE-----\n".$data."-----END CERTIFICATE-----\n";
|
|
||||||
$isValid = openssl_pkey_get_public($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the certificate if it could be verified
|
|
||||||
if ( $isValid ) {
|
|
||||||
// disable proxy to prevent multiple fopen calls
|
|
||||||
$proxyStatus = \OC_FileProxy::$enabled;
|
|
||||||
\OC_FileProxy::$enabled = false;
|
|
||||||
$view->file_put_contents($filename, $data);
|
|
||||||
OC_Mount_Config::createCertificateBundle();
|
|
||||||
\OC_FileProxy::$enabled = $proxyStatus;
|
|
||||||
} else {
|
|
||||||
OCP\Util::writeLog('files_external',
|
|
||||||
'Couldn\'t import SSL root certificate ('.$filename.'), allowed formats: PEM and DER',
|
|
||||||
OCP\Util::WARN);
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Location:' . OCP\Util::linkToRoute( "settings_personal" ));
|
|
||||||
exit;
|
|
|
@ -1,13 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
OCP\JSON::checkAppEnabled('files_external');
|
|
||||||
OCP\JSON::checkLoggedIn();
|
|
||||||
OCP\JSON::callCheck();
|
|
||||||
|
|
||||||
$view = \OCP\Files::getStorage("files_external");
|
|
||||||
$file = 'uploads/'.ltrim($_POST['cert'], "/\\.");
|
|
||||||
|
|
||||||
if ( $view->file_exists($file) ) {
|
|
||||||
$view->unlink($file);
|
|
||||||
OC_Mount_Config::createCertificateBundle();
|
|
||||||
}
|
|
|
@ -619,53 +619,6 @@ class OC_Mount_Config {
|
||||||
@chmod($file, 0640);
|
@chmod($file, 0640);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all user uploaded ssl root certificates
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public static function getCertificates() {
|
|
||||||
$path=OC_User::getHome(OC_User::getUser()) . '/files_external/uploads/';
|
|
||||||
\OCP\Util::writeLog('files_external', 'checking path '.$path, \OCP\Util::INFO);
|
|
||||||
if ( ! is_dir($path)) {
|
|
||||||
//path might not exist (e.g. non-standard OC_User::getHome() value)
|
|
||||||
//in this case create full path using 3rd (recursive=true) parameter.
|
|
||||||
mkdir($path, 0777, true);
|
|
||||||
}
|
|
||||||
$result = array();
|
|
||||||
$handle = opendir($path);
|
|
||||||
if(!is_resource($handle)) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
while (false !== ($file = readdir($handle))) {
|
|
||||||
if ($file != '.' && $file != '..') $result[] = $file;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* creates certificate bundle
|
|
||||||
*/
|
|
||||||
public static function createCertificateBundle() {
|
|
||||||
$path=OC_User::getHome(OC_User::getUser()) . '/files_external';
|
|
||||||
|
|
||||||
$certs = OC_Mount_Config::getCertificates();
|
|
||||||
$fh_certs = fopen($path."/rootcerts.crt", 'w');
|
|
||||||
foreach ($certs as $cert) {
|
|
||||||
$file=$path.'/uploads/'.$cert;
|
|
||||||
$fh = fopen($file, "r");
|
|
||||||
$data = fread($fh, filesize($file));
|
|
||||||
fclose($fh);
|
|
||||||
if (strpos($data, 'BEGIN CERTIFICATE')) {
|
|
||||||
fwrite($fh_certs, $data);
|
|
||||||
fwrite($fh_certs, "\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose($fh_certs);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check dependencies
|
* check dependencies
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,7 +27,6 @@ $backends = OC_Mount_Config::getPersonalBackends();
|
||||||
$tmpl = new OCP\Template('files_external', 'settings');
|
$tmpl = new OCP\Template('files_external', 'settings');
|
||||||
$tmpl->assign('isAdminPage', false);
|
$tmpl->assign('isAdminPage', false);
|
||||||
$tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints());
|
$tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints());
|
||||||
$tmpl->assign('certs', OC_Mount_Config::getCertificates());
|
|
||||||
$tmpl->assign('dependencies', OC_Mount_Config::checkDependencies());
|
$tmpl->assign('dependencies', OC_Mount_Config::checkDependencies());
|
||||||
$tmpl->assign('backends', $backends);
|
$tmpl->assign('backends', $backends);
|
||||||
return $tmpl->fetchPage();
|
return $tmpl->fetchPage();
|
||||||
|
|
|
@ -119,30 +119,3 @@
|
||||||
</p>
|
</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<?php if ( ! $_['isAdminPage']): ?>
|
|
||||||
<form id="files_external" class="section"
|
|
||||||
method="post"
|
|
||||||
enctype="multipart/form-data"
|
|
||||||
action="<?php p(OCP\Util::linkTo('files_external', 'ajax/addRootCertificate.php')); ?>">
|
|
||||||
<h2><?php p($l->t('SSL root certificates'));?></h2>
|
|
||||||
<table id="sslCertificate" data-admin='<?php print_unescaped(json_encode($_['isAdminPage'])); ?>'>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($_['certs'] as $rootCert): ?>
|
|
||||||
<tr id="<?php p($rootCert) ?>">
|
|
||||||
<td class="rootCert"><?php p($rootCert) ?></td>
|
|
||||||
<td <?php if ($rootCert != ''): ?>class="remove"
|
|
||||||
<?php else: ?>style="visibility:hidden;"
|
|
||||||
<?php endif; ?>><img alt="<?php p($l->t('Delete')); ?>"
|
|
||||||
title="<?php p($l->t('Delete')); ?>"
|
|
||||||
class="svg action"
|
|
||||||
src="<?php print_unescaped(image_path('core', 'actions/delete.svg')); ?>" /></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']); ?>">
|
|
||||||
<input type="file" id="rootcert_import" name="rootcert_import">
|
|
||||||
<input type="submit" name="cert_import" value="<?php p($l->t('Import Root Certificate')); ?>" />
|
|
||||||
</form>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
|
@ -113,9 +113,11 @@ class Manager {
|
||||||
* @return Mount
|
* @return Mount
|
||||||
*/
|
*/
|
||||||
protected function mountShare($data) {
|
protected function mountShare($data) {
|
||||||
|
$user = $this->userSession->getUser();
|
||||||
$data['manager'] = $this;
|
$data['manager'] = $this;
|
||||||
$mountPoint = '/' . $this->userSession->getUser()->getUID() . '/files' . $data['mountpoint'];
|
$mountPoint = '/' . $user->getUID() . '/files' . $data['mountpoint'];
|
||||||
$data['mountpoint'] = $mountPoint;
|
$data['mountpoint'] = $mountPoint;
|
||||||
|
$data['certificateManager'] = \OC::$server->getCertificateManager($user);
|
||||||
$mount = new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader);
|
$mount = new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader);
|
||||||
$this->mountManager->addMount($mount);
|
$this->mountManager->addMount($mount);
|
||||||
return $mount;
|
return $mount;
|
||||||
|
|
|
@ -37,6 +37,11 @@ class Storage extends DAV implements ISharedStorage {
|
||||||
*/
|
*/
|
||||||
private $token;
|
private $token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \OCP\ICertificateManager
|
||||||
|
*/
|
||||||
|
private $certificateManager;
|
||||||
|
|
||||||
private $updateChecked = false;
|
private $updateChecked = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,6 +51,7 @@ class Storage extends DAV implements ISharedStorage {
|
||||||
|
|
||||||
public function __construct($options) {
|
public function __construct($options) {
|
||||||
$this->manager = $options['manager'];
|
$this->manager = $options['manager'];
|
||||||
|
$this->certificateManager = $options['certificateManager'];
|
||||||
$this->remote = $options['remote'];
|
$this->remote = $options['remote'];
|
||||||
$this->remoteUser = $options['owner'];
|
$this->remoteUser = $options['owner'];
|
||||||
list($protocol, $remote) = explode('://', $this->remote);
|
list($protocol, $remote) = explode('://', $this->remote);
|
||||||
|
@ -190,6 +196,10 @@ class Storage extends DAV implements ISharedStorage {
|
||||||
http_build_query(array('password' => $password)));
|
http_build_query(array('password' => $password)));
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||||
|
curl_setopt($ch, CURLOPT_CAINFO, $this->certificateManager->getCertificateBundle());
|
||||||
|
|
||||||
$result = curl_exec($ch);
|
$result = curl_exec($ch);
|
||||||
|
|
||||||
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
|
|
@ -65,6 +65,7 @@ class Test_Files_Sharing_External_Storage extends \PHPUnit_Framework_TestCase {
|
||||||
* @dataProvider optionsProvider
|
* @dataProvider optionsProvider
|
||||||
*/
|
*/
|
||||||
public function testStorageMountOptions($inputUri, $baseUri) {
|
public function testStorageMountOptions($inputUri, $baseUri) {
|
||||||
|
$certificateManager = \OC::$server->getCertificateManager();
|
||||||
$storage = new TestSharingExternalStorage(
|
$storage = new TestSharingExternalStorage(
|
||||||
array(
|
array(
|
||||||
'remote' => $inputUri,
|
'remote' => $inputUri,
|
||||||
|
@ -72,7 +73,8 @@ class Test_Files_Sharing_External_Storage extends \PHPUnit_Framework_TestCase {
|
||||||
'mountpoint' => 'remoteshare',
|
'mountpoint' => 'remoteshare',
|
||||||
'token' => 'abcdef',
|
'token' => 'abcdef',
|
||||||
'password' => '',
|
'password' => '',
|
||||||
'manager' => null
|
'manager' => null,
|
||||||
|
'certificateManager' => $certificateManager
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->assertEquals($baseUri, $storage->getBaseUri());
|
$this->assertEquals($baseUri, $storage->getBaseUri());
|
||||||
|
|
|
@ -354,7 +354,7 @@ class OC_L10N implements \OCP\IL10N {
|
||||||
case 'datetime':
|
case 'datetime':
|
||||||
case 'time':
|
case 'time':
|
||||||
if($data instanceof DateTime) {
|
if($data instanceof DateTime) {
|
||||||
return $data->format($this->localizations[$type]);
|
$data = $data->getTimestamp();
|
||||||
} elseif(is_string($data) && !is_numeric($data)) {
|
} elseif(is_string($data) && !is_numeric($data)) {
|
||||||
$data = strtotime($data);
|
$data = strtotime($data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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';
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ use OC\AppFramework\Http\Request;
|
||||||
use OC\AppFramework\Db\Db;
|
use OC\AppFramework\Db\Db;
|
||||||
use OC\AppFramework\Utility\SimpleContainer;
|
use OC\AppFramework\Utility\SimpleContainer;
|
||||||
use OC\Cache\UserCache;
|
use OC\Cache\UserCache;
|
||||||
|
use OC\Security\CertificateManager;
|
||||||
use OC\DB\ConnectionWrapper;
|
use OC\DB\ConnectionWrapper;
|
||||||
use OC\Files\Node\Root;
|
use OC\Files\Node\Root;
|
||||||
use OC\Files\View;
|
use OC\Files\View;
|
||||||
|
@ -474,4 +475,21 @@ class Server extends SimpleContainer implements IServerContainer {
|
||||||
function getDb() {
|
function getDb() {
|
||||||
return $this->query('Db');
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -228,4 +228,11 @@ interface IServerContainer {
|
||||||
*/
|
*/
|
||||||
function getSearch();
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
OCP\JSON::checkLoggedIn();
|
||||||
|
OCP\JSON::callCheck();
|
||||||
|
|
||||||
|
$l = new OC_L10N('core');
|
||||||
|
|
||||||
|
if (!isset($_FILES['rootcert_import'])) {
|
||||||
|
OCP\JSON::error(array('error' => 'No certificate uploaded'));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = file_get_contents($_FILES['rootcert_import']['tmp_name']);
|
||||||
|
$filename = basename($_FILES['rootcert_import']['name']);
|
||||||
|
|
||||||
|
$certificateManager = \OC::$server->getCertificateManager();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$cert = $certificateManager->addCertificate($data, $filename);
|
||||||
|
OCP\JSON::success(array(
|
||||||
|
'name' => $cert->getName(),
|
||||||
|
'commonName' => $cert->getCommonName(),
|
||||||
|
'organization' => $cert->getOrganization(),
|
||||||
|
'validFrom' => $cert->getIssueDate()->getTimestamp(),
|
||||||
|
'validTill' => $cert->getExpireDate()->getTimestamp(),
|
||||||
|
'validFromString' => $l->l('date', $cert->getIssueDate()),
|
||||||
|
'validTillString' => $l->l('date', $cert->getExpireDate()),
|
||||||
|
'issuer' => $cert->getIssuerName(),
|
||||||
|
'issuerOrganization' => $cert->getIssuerOrganization()
|
||||||
|
));
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
OCP\JSON::error(array('error' => 'Couldn\'t import SSL root certificate, allowed formats: PEM and DER'));
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
OCP\JSON::checkLoggedIn();
|
||||||
|
OCP\JSON::callCheck();
|
||||||
|
|
||||||
|
$name = $_POST['cert'];
|
||||||
|
$certificateManager = \OC::$server->getCertificateManager();
|
||||||
|
$certificateManager->removeCertificate($name);
|
|
@ -6,9 +6,11 @@ select#languageinput, select#timezone { width:15em; }
|
||||||
input#openid, input#webdav { width:20em; }
|
input#openid, input#webdav { width:20em; }
|
||||||
|
|
||||||
/* PERSONAL */
|
/* PERSONAL */
|
||||||
#rootcert_import {
|
#sslCertificate tr.expired {
|
||||||
margin: 0 0 10px 0;
|
background-color: rgba(255, 0, 0, 0.5);
|
||||||
display: block;
|
}
|
||||||
|
#sslCertificate td {
|
||||||
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sync clients */
|
/* Sync clients */
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
*
|
*
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
jQuery.fn.keyUpDelayedOrEnter = function(callback){
|
jQuery.fn.keyUpDelayedOrEnter = function (callback) {
|
||||||
var cb = callback;
|
var cb = callback;
|
||||||
var that = this;
|
var that = this;
|
||||||
this.keyup(_.debounce(function (event) {
|
this.keyup(_.debounce(function (event) {
|
||||||
// enter is already handled in keypress
|
// enter is already handled in keypress
|
||||||
if(event.keyCode === 13) {
|
if (event.keyCode === 13) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (that.val() !== '') {
|
if (that.val() !== '') {
|
||||||
|
@ -27,7 +27,7 @@ jQuery.fn.keyUpDelayedOrEnter = function(callback){
|
||||||
}, 1000));
|
}, 1000));
|
||||||
|
|
||||||
this.keypress(function (event) {
|
this.keypress(function (event) {
|
||||||
if (event.keyCode === 13 && that.val() !== '' ){
|
if (event.keyCode === 13 && that.val() !== '') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
|
@ -38,48 +38,48 @@ jQuery.fn.keyUpDelayedOrEnter = function(callback){
|
||||||
/**
|
/**
|
||||||
* Post the email address change to the server.
|
* Post the email address change to the server.
|
||||||
*/
|
*/
|
||||||
function changeEmailAddress(){
|
function changeEmailAddress () {
|
||||||
var emailInfo = $('#email');
|
var emailInfo = $('#email');
|
||||||
if (emailInfo.val() === emailInfo.defaultValue){
|
if (emailInfo.val() === emailInfo.defaultValue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emailInfo.defaultValue = emailInfo.val();
|
emailInfo.defaultValue = emailInfo.val();
|
||||||
OC.msg.startSaving('#lostpassword .msg');
|
OC.msg.startSaving('#lostpassword .msg');
|
||||||
var post = $( "#lostpassword" ).serialize();
|
var post = $("#lostpassword").serialize();
|
||||||
$.post( 'ajax/lostpassword.php', post, function(data){
|
$.post('ajax/lostpassword.php', post, function (data) {
|
||||||
OC.msg.finishedSaving('#lostpassword .msg', data);
|
OC.msg.finishedSaving('#lostpassword .msg', data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post the display name change to the server.
|
* Post the display name change to the server.
|
||||||
*/
|
*/
|
||||||
function changeDisplayName(){
|
function changeDisplayName () {
|
||||||
if ($('#displayName').val() !== '' ) {
|
if ($('#displayName').val() !== '') {
|
||||||
OC.msg.startSaving('#displaynameform .msg');
|
OC.msg.startSaving('#displaynameform .msg');
|
||||||
// Serialize the data
|
// Serialize the data
|
||||||
var post = $( "#displaynameform" ).serialize();
|
var post = $("#displaynameform").serialize();
|
||||||
// Ajax foo
|
// Ajax foo
|
||||||
$.post( 'ajax/changedisplayname.php', post, function(data){
|
$.post('ajax/changedisplayname.php', post, function (data) {
|
||||||
if( data.status === "success" ){
|
if (data.status === "success") {
|
||||||
$('#oldDisplayName').val($('#displayName').val());
|
$('#oldDisplayName').val($('#displayName').val());
|
||||||
// update displayName on the top right expand button
|
// update displayName on the top right expand button
|
||||||
$('#expandDisplayName').text($('#displayName').val());
|
$('#expandDisplayName').text($('#displayName').val());
|
||||||
updateAvatar();
|
updateAvatar();
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
$('#newdisplayname').val(data.data.displayName);
|
$('#newdisplayname').val(data.data.displayName);
|
||||||
}
|
}
|
||||||
OC.msg.finishedSaving('#displaynameform .msg', data);
|
OC.msg.finishedSaving('#displaynameform .msg', data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateAvatar (hidedefault) {
|
function updateAvatar (hidedefault) {
|
||||||
var $headerdiv = $('#header .avatardiv');
|
var $headerdiv = $('#header .avatardiv');
|
||||||
var $displaydiv = $('#displayavatar .avatardiv');
|
var $displaydiv = $('#displayavatar .avatardiv');
|
||||||
|
|
||||||
if(hidedefault) {
|
if (hidedefault) {
|
||||||
$headerdiv.hide();
|
$headerdiv.hide();
|
||||||
$('#header .avatardiv').removeClass('avatardiv-shown');
|
$('#header .avatardiv').removeClass('avatardiv-shown');
|
||||||
} else {
|
} else {
|
||||||
|
@ -93,16 +93,16 @@ function updateAvatar (hidedefault) {
|
||||||
$('#removeavatar').show();
|
$('#removeavatar').show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAvatarCropper() {
|
function showAvatarCropper () {
|
||||||
var $cropper = $('#cropper');
|
var $cropper = $('#cropper');
|
||||||
$cropper.prepend("<img>");
|
$cropper.prepend("<img>");
|
||||||
var $cropperImage = $('#cropper img');
|
var $cropperImage = $('#cropper img');
|
||||||
|
|
||||||
$cropperImage.attr('src',
|
$cropperImage.attr('src',
|
||||||
OC.generateUrl('/avatar/tmp')+'?requesttoken='+oc_requesttoken+'#'+Math.floor(Math.random()*1000));
|
OC.generateUrl('/avatar/tmp') + '?requesttoken=' + oc_requesttoken + '#' + Math.floor(Math.random() * 1000));
|
||||||
|
|
||||||
// Looks weird, but on('load', ...) doesn't work in IE8
|
// Looks weird, but on('load', ...) doesn't work in IE8
|
||||||
$cropperImage.ready(function(){
|
$cropperImage.ready(function () {
|
||||||
$('#displayavatar').hide();
|
$('#displayavatar').hide();
|
||||||
$cropper.show();
|
$cropper.show();
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ function showAvatarCropper() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendCropData() {
|
function sendCropData () {
|
||||||
cleanCropper();
|
cleanCropper();
|
||||||
|
|
||||||
var cropperData = $('#cropper').data();
|
var cropperData = $('#cropper').data();
|
||||||
|
@ -130,11 +130,11 @@ function sendCropData() {
|
||||||
$.post(OC.generateUrl('/avatar/cropped'), {crop: data}, avatarResponseHandler);
|
$.post(OC.generateUrl('/avatar/cropped'), {crop: data}, avatarResponseHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveCoords(c) {
|
function saveCoords (c) {
|
||||||
$('#cropper').data(c);
|
$('#cropper').data(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanCropper() {
|
function cleanCropper () {
|
||||||
var $cropper = $('#cropper');
|
var $cropper = $('#cropper');
|
||||||
$('#displayavatar').show();
|
$('#displayavatar').show();
|
||||||
$cropper.hide();
|
$cropper.hide();
|
||||||
|
@ -143,7 +143,7 @@ function cleanCropper() {
|
||||||
$('#cropper img').remove();
|
$('#cropper img').remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
function avatarResponseHandler(data) {
|
function avatarResponseHandler (data) {
|
||||||
var $warning = $('#avatar .warning');
|
var $warning = $('#avatar .warning');
|
||||||
$warning.hide();
|
$warning.hide();
|
||||||
if (data.status === "success") {
|
if (data.status === "success") {
|
||||||
|
@ -156,20 +156,20 @@ function avatarResponseHandler(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function () {
|
||||||
$("#passwordbutton").click( function(){
|
$("#passwordbutton").click(function () {
|
||||||
if ($('#pass1').val() !== '' && $('#pass2').val() !== '') {
|
if ($('#pass1').val() !== '' && $('#pass2').val() !== '') {
|
||||||
// Serialize the data
|
// Serialize the data
|
||||||
var post = $( "#passwordform" ).serialize();
|
var post = $("#passwordform").serialize();
|
||||||
$('#passwordchanged').hide();
|
$('#passwordchanged').hide();
|
||||||
$('#passworderror').hide();
|
$('#passworderror').hide();
|
||||||
// Ajax foo
|
// Ajax foo
|
||||||
$.post(OC.generateUrl('/settings/personal/changepassword'), post, function(data){
|
$.post(OC.generateUrl('/settings/personal/changepassword'), post, function (data) {
|
||||||
if( data.status === "success" ){
|
if (data.status === "success") {
|
||||||
$('#pass1').val('');
|
$('#pass1').val('');
|
||||||
$('#pass2').val('');
|
$('#pass2').val('');
|
||||||
$('#passwordchanged').show();
|
$('#passwordchanged').show();
|
||||||
} else{
|
} else {
|
||||||
if (typeof(data.data) !== "undefined") {
|
if (typeof(data.data) !== "undefined") {
|
||||||
$('#passworderror').html(data.data.message);
|
$('#passworderror').html(data.data.message);
|
||||||
} else {
|
} else {
|
||||||
|
@ -190,22 +190,22 @@ $(document).ready(function(){
|
||||||
$('#displayName').keyUpDelayedOrEnter(changeDisplayName);
|
$('#displayName').keyUpDelayedOrEnter(changeDisplayName);
|
||||||
$('#email').keyUpDelayedOrEnter(changeEmailAddress);
|
$('#email').keyUpDelayedOrEnter(changeEmailAddress);
|
||||||
|
|
||||||
$("#languageinput").change( function(){
|
$("#languageinput").change(function () {
|
||||||
// Serialize the data
|
// Serialize the data
|
||||||
var post = $( "#languageinput" ).serialize();
|
var post = $("#languageinput").serialize();
|
||||||
// Ajax foo
|
// Ajax foo
|
||||||
$.post( 'ajax/setlanguage.php', post, function(data){
|
$.post('ajax/setlanguage.php', post, function (data) {
|
||||||
if( data.status === "success" ){
|
if (data.status === "success") {
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
$('#passworderror').html( data.data.message );
|
$('#passworderror').html(data.data.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
$('button:button[name="submitDecryptAll"]').click(function() {
|
$('button:button[name="submitDecryptAll"]').click(function () {
|
||||||
var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val();
|
var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val();
|
||||||
$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true);
|
$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true);
|
||||||
$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true);
|
$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true);
|
||||||
|
@ -213,23 +213,23 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$('button:button[name="submitRestoreKeys"]').click(function() {
|
$('button:button[name="submitRestoreKeys"]').click(function () {
|
||||||
$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true);
|
$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true);
|
||||||
$('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true);
|
$('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true);
|
||||||
OC.Encryption.restoreKeys();
|
OC.Encryption.restoreKeys();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('button:button[name="submitDeleteKeys"]').click(function() {
|
$('button:button[name="submitDeleteKeys"]').click(function () {
|
||||||
$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true);
|
$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true);
|
||||||
$('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true);
|
$('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true);
|
||||||
OC.Encryption.deleteKeys();
|
OC.Encryption.deleteKeys();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#decryptAll input:password[name="privateKeyPassword"]').keyup(function(event) {
|
$('#decryptAll input:password[name="privateKeyPassword"]').keyup(function (event) {
|
||||||
var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val();
|
var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val();
|
||||||
if (privateKeyPassword !== '' ) {
|
if (privateKeyPassword !== '') {
|
||||||
$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", false);
|
$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", false);
|
||||||
if(event.which === 13) {
|
if (event.which === 13) {
|
||||||
$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true);
|
$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true);
|
||||||
$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true);
|
$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true);
|
||||||
OC.Encryption.decryptAll(privateKeyPassword);
|
OC.Encryption.decryptAll(privateKeyPassword);
|
||||||
|
@ -240,21 +240,21 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
var uploadparms = {
|
var uploadparms = {
|
||||||
done: function(e, data) {
|
done: function (e, data) {
|
||||||
avatarResponseHandler(data.result);
|
avatarResponseHandler(data.result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$('#uploadavatarbutton').click(function(){
|
$('#uploadavatarbutton').click(function () {
|
||||||
$('#uploadavatar').click();
|
$('#uploadavatar').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#uploadavatar').fileupload(uploadparms);
|
$('#uploadavatar').fileupload(uploadparms);
|
||||||
|
|
||||||
$('#selectavatar').click(function(){
|
$('#selectavatar').click(function () {
|
||||||
OC.dialogs.filepicker(
|
OC.dialogs.filepicker(
|
||||||
t('settings', "Select a profile picture"),
|
t('settings', "Select a profile picture"),
|
||||||
function(path){
|
function (path) {
|
||||||
$.post(OC.generateUrl('/avatar/'), {path: path}, avatarResponseHandler);
|
$.post(OC.generateUrl('/avatar/'), {path: path}, avatarResponseHandler);
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
@ -262,27 +262,27 @@ $(document).ready(function(){
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#removeavatar').click(function(){
|
$('#removeavatar').click(function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'DELETE',
|
type: 'DELETE',
|
||||||
url: OC.generateUrl('/avatar/'),
|
url: OC.generateUrl('/avatar/'),
|
||||||
success: function() {
|
success: function () {
|
||||||
updateAvatar(true);
|
updateAvatar(true);
|
||||||
$('#removeavatar').hide();
|
$('#removeavatar').hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#abortcropperbutton').click(function(){
|
$('#abortcropperbutton').click(function () {
|
||||||
cleanCropper();
|
cleanCropper();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#sendcropperbutton').click(function(){
|
$('#sendcropperbutton').click(function () {
|
||||||
sendCropData();
|
sendCropData();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#pass2').strengthify({
|
$('#pass2').strengthify({
|
||||||
zxcvbn: OC.linkTo('3rdparty','zxcvbn/js/zxcvbn.js'),
|
zxcvbn: OC.linkTo('3rdparty', 'zxcvbn/js/zxcvbn.js'),
|
||||||
titles: [
|
titles: [
|
||||||
t('core', 'Very weak password'),
|
t('core', 'Very weak password'),
|
||||||
t('core', 'Weak password'),
|
t('core', 'Weak password'),
|
||||||
|
@ -298,18 +298,58 @@ $(document).ready(function(){
|
||||||
'/avatar/{user}/{size}',
|
'/avatar/{user}/{size}',
|
||||||
{user: OC.currentUser, size: 1}
|
{user: OC.currentUser, size: 1}
|
||||||
) + '?requesttoken=' + oc_requesttoken;
|
) + '?requesttoken=' + oc_requesttoken;
|
||||||
$.get(url, function(result) {
|
$.get(url, function (result) {
|
||||||
if (typeof(result) === 'object') {
|
if (typeof(result) === 'object') {
|
||||||
$('#removeavatar').hide();
|
$('#removeavatar').hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} );
|
|
||||||
|
$('#sslCertificate').on('click', 'td.remove > img', function () {
|
||||||
|
var row = $(this).parent().parent();
|
||||||
|
$.post(OC.generateUrl('settings/ajax/removeRootCertificate'), {
|
||||||
|
cert: row.data('name')
|
||||||
|
});
|
||||||
|
row.remove();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#sslCertificate tr > td').tipsy({fade: true, gravity: 'n', live: true});
|
||||||
|
|
||||||
|
$('#rootcert_import').fileupload({
|
||||||
|
done: function (e, data) {
|
||||||
|
var issueDate = new Date(data.result.validFrom * 1000);
|
||||||
|
var expireDate = new Date(data.result.validTill * 1000);
|
||||||
|
var now = new Date();
|
||||||
|
var isExpired = !(issueDate <= now && now <= expireDate);
|
||||||
|
|
||||||
|
var row = $('<tr/>');
|
||||||
|
row.addClass(isExpired? 'expired': 'valid');
|
||||||
|
row.append($('<td/>').attr('title', data.result.organization).text(data.result.commonName));
|
||||||
|
row.append($('<td/>').attr('title', t('core,', 'Valid until {date}', {date: data.result.validFromString}))
|
||||||
|
.text(data.result.validTillString));
|
||||||
|
row.append($('<td/>').attr('title', data.result.issuerOrganization).text(data.result.issuer));
|
||||||
|
row.append($('<td/>').addClass('remove').append(
|
||||||
|
$('<img/>').attr({
|
||||||
|
alt: t('core', 'Delete'),
|
||||||
|
title: t('core', 'Delete'),
|
||||||
|
src: OC.imagePath('core', 'actions/delete.svg')
|
||||||
|
}).addClass('action')
|
||||||
|
));
|
||||||
|
|
||||||
|
$('#sslCertificate tbody').append(row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#rootcert_import_button').click(function () {
|
||||||
|
$('#rootcert_import').click();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
OC.Encryption = {
|
OC.Encryption = {
|
||||||
decryptAll: function(password) {
|
decryptAll: function (password) {
|
||||||
var message = t('settings', 'Decrypting files... Please wait, this can take some time.');
|
var message = t('settings', 'Decrypting files... Please wait, this can take some time.');
|
||||||
OC.Encryption.msg.start('#decryptAll .msg', message);
|
OC.Encryption.msg.start('#decryptAll .msg', message);
|
||||||
$.post('ajax/decryptall.php', {password:password}, function(data) {
|
$.post('ajax/decryptall.php', {password: password}, function (data) {
|
||||||
if (data.status === "error") {
|
if (data.status === "error") {
|
||||||
OC.Encryption.msg.finished('#decryptAll .msg', data);
|
OC.Encryption.msg.finished('#decryptAll .msg', data);
|
||||||
$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", false);
|
$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", false);
|
||||||
|
@ -320,10 +360,10 @@ OC.Encryption = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteKeys: function() {
|
deleteKeys: function () {
|
||||||
var message = t('settings', 'Delete encryption keys permanently.');
|
var message = t('settings', 'Delete encryption keys permanently.');
|
||||||
OC.Encryption.msg.start('#restoreBackupKeys .msg', message);
|
OC.Encryption.msg.start('#restoreBackupKeys .msg', message);
|
||||||
$.post('ajax/deletekeys.php', null, function(data) {
|
$.post('ajax/deletekeys.php', null, function (data) {
|
||||||
if (data.status === "error") {
|
if (data.status === "error") {
|
||||||
OC.Encryption.msg.finished('#restoreBackupKeys .msg', data);
|
OC.Encryption.msg.finished('#restoreBackupKeys .msg', data);
|
||||||
$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false);
|
$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false);
|
||||||
|
@ -334,10 +374,10 @@ OC.Encryption = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
restoreKeys: function() {
|
restoreKeys: function () {
|
||||||
var message = t('settings', 'Restore encryption keys.');
|
var message = t('settings', 'Restore encryption keys.');
|
||||||
OC.Encryption.msg.start('#restoreBackupKeys .msg', message);
|
OC.Encryption.msg.start('#restoreBackupKeys .msg', message);
|
||||||
$.post('ajax/restorekeys.php', {}, function(data) {
|
$.post('ajax/restorekeys.php', {}, function (data) {
|
||||||
if (data.status === "error") {
|
if (data.status === "error") {
|
||||||
OC.Encryption.msg.finished('#restoreBackupKeys .msg', data);
|
OC.Encryption.msg.finished('#restoreBackupKeys .msg', data);
|
||||||
$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false);
|
$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false);
|
||||||
|
@ -349,24 +389,24 @@ OC.Encryption = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
OC.Encryption.msg={
|
OC.Encryption.msg = {
|
||||||
start:function(selector, msg){
|
start: function (selector, msg) {
|
||||||
var spinner = '<img src="'+ OC.imagePath('core', 'loading-small.gif') +'">';
|
var spinner = '<img src="' + OC.imagePath('core', 'loading-small.gif') + '">';
|
||||||
$(selector)
|
$(selector)
|
||||||
.html( msg + ' ' + spinner )
|
.html(msg + ' ' + spinner)
|
||||||
.removeClass('success')
|
.removeClass('success')
|
||||||
.removeClass('error')
|
.removeClass('error')
|
||||||
.stop(true, true)
|
.stop(true, true)
|
||||||
.show();
|
.show();
|
||||||
},
|
},
|
||||||
finished:function(selector, data){
|
finished: function (selector, data) {
|
||||||
if( data.status === "success" ){
|
if (data.status === "success") {
|
||||||
$(selector).html( data.data.message )
|
$(selector).html(data.data.message)
|
||||||
.addClass('success')
|
.addClass('success')
|
||||||
.stop(true, true)
|
.stop(true, true)
|
||||||
.delay(3000);
|
.delay(3000);
|
||||||
}else{
|
} else {
|
||||||
$(selector).html( data.data.message ).addClass('error');
|
$(selector).html(data.data.message).addClass('error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
OC_Util::checkLoggedIn();
|
OC_Util::checkLoggedIn();
|
||||||
|
|
||||||
$defaults = new OC_Defaults(); // initialize themable default strings and urls
|
$defaults = new OC_Defaults(); // initialize themable default strings and urls
|
||||||
|
$certificateManager = \OC::$server->getCertificateManager();
|
||||||
|
|
||||||
// Highlight navigation entry
|
// Highlight navigation entry
|
||||||
OC_Util::addScript( 'settings', 'personal' );
|
OC_Util::addScript( 'settings', 'personal' );
|
||||||
|
@ -98,6 +99,7 @@ $tmpl->assign('backupKeysExists' , $backupKeysExists);
|
||||||
$tmpl->assign('filesStillEncrypted' , $filesStillEncrypted);
|
$tmpl->assign('filesStillEncrypted' , $filesStillEncrypted);
|
||||||
$tmpl->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true));
|
$tmpl->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true));
|
||||||
$tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser()));
|
$tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser()));
|
||||||
|
$tmpl->assign('certs', $certificateManager->listCertificates());
|
||||||
|
|
||||||
$forms=OC_App::getForms('personal');
|
$forms=OC_App::getForms('personal');
|
||||||
$tmpl->assign('forms', array());
|
$tmpl->assign('forms', array());
|
||||||
|
|
|
@ -62,6 +62,10 @@ $this->create('settings_ajax_restorekeys', '/settings/ajax/restorekeys.php')
|
||||||
->actionInclude('settings/ajax/restorekeys.php');
|
->actionInclude('settings/ajax/restorekeys.php');
|
||||||
$this->create('settings_ajax_deletekeys', '/settings/ajax/deletekeys.php')
|
$this->create('settings_ajax_deletekeys', '/settings/ajax/deletekeys.php')
|
||||||
->actionInclude('settings/ajax/deletekeys.php');
|
->actionInclude('settings/ajax/deletekeys.php');
|
||||||
|
$this->create('settings_cert_post', '/settings/ajax/addRootCertificate')
|
||||||
|
->actionInclude('settings/ajax/addRootCertificate.php');
|
||||||
|
$this->create('settings_cert_remove', '/settings/ajax/removeRootCertificate')
|
||||||
|
->actionInclude('settings/ajax/removeRootCertificate.php');
|
||||||
// apps
|
// apps
|
||||||
$this->create('settings_ajax_apps_ocs', '/settings/ajax/apps/ocs.php')
|
$this->create('settings_ajax_apps_ocs', '/settings/ajax/apps/ocs.php')
|
||||||
->actionInclude('settings/ajax/apps/ocs.php');
|
->actionInclude('settings/ajax/apps/ocs.php');
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
|
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
|
||||||
* This file is licensed under the Affero General Public License version 3 or later.
|
* This file is licensed under the Affero General Public License version 3 or later.
|
||||||
* See the COPYING-README file.
|
* See the COPYING-README file.
|
||||||
*/?>
|
*/
|
||||||
|
|
||||||
|
/** @var $_ array */
|
||||||
|
?>
|
||||||
|
|
||||||
<div class="clientsbox center">
|
<div class="clientsbox center">
|
||||||
<h2><?php p($l->t('Get the apps to sync your files'));?></h2>
|
<h2><?php p($l->t('Get the apps to sync your files'));?></h2>
|
||||||
|
@ -150,6 +153,44 @@ if($_['passwordChangeSupported']) {
|
||||||
print_unescaped($form);
|
print_unescaped($form);
|
||||||
};?>
|
};?>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2><?php p($l->t('SSL root certificates')); ?></h2>
|
||||||
|
<table id="sslCertificate" class="grid">
|
||||||
|
<thead>
|
||||||
|
<th><?php p($l->t('Common Name')); ?></th>
|
||||||
|
<th><?php p($l->t('Valid until')); ?></th>
|
||||||
|
<th><?php p($l->t('Issued By')); ?></th>
|
||||||
|
<th/>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($_['certs'] as $rootCert): /**@var \OCP\ICertificate $rootCert*/ ?>
|
||||||
|
<tr class="<?php echo ($rootCert->isExpired()) ? 'expired' : 'valid' ?>" data-name="<?php p($rootCert->getName()) ?>">
|
||||||
|
<td class="rootCert" title="<?php p($rootCert->getOrganization())?>">
|
||||||
|
<?php p($rootCert->getCommonName()) ?>
|
||||||
|
</td>
|
||||||
|
<td title="<?php p($l->t('Valid until %s', $l->l('date', $rootCert->getExpireDate()))) ?>">
|
||||||
|
<?php echo $l->l('date', $rootCert->getExpireDate()) ?>
|
||||||
|
</td>
|
||||||
|
<td title="<?php p($rootCert->getIssuerOrganization()) ?>">
|
||||||
|
<?php p($rootCert->getIssuerName()) ?>
|
||||||
|
</td>
|
||||||
|
<td <?php if ($rootCert != ''): ?>class="remove"
|
||||||
|
<?php else: ?>style="visibility:hidden;"
|
||||||
|
<?php endif; ?>><img alt="<?php p($l->t('Delete')); ?>"
|
||||||
|
title="<?php p($l->t('Delete')); ?>"
|
||||||
|
class="svg action"
|
||||||
|
src="<?php print_unescaped(image_path('core', 'actions/delete.svg')); ?>"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<form class="uploadButton" method="post" action="<?php p(\OC_Helper::linkToRoute('settings_cert_post')); ?>" target="certUploadFrame">
|
||||||
|
<input type="file" id="rootcert_import" name="rootcert_import" class="hidden">
|
||||||
|
<input type="button" id="rootcert_import_button" value="<?php p($l->t('Import Root Certificate')); ?>"/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<?php if($_['enableDecryptAll']): ?>
|
<?php if($_['enableDecryptAll']): ?>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
|
|
||||||
|
@ -177,11 +218,8 @@ if($_['passwordChangeSupported']) {
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="restoreBackupKeys" <?php $_['backupKeysExists'] ? '' : print_unescaped("class='hidden'") ?>>
|
<div id="restoreBackupKeys" <?php $_['backupKeysExists'] ? '' : print_unescaped("class='hidden'") ?>>
|
||||||
|
|
||||||
<?php p($l->t( "Your encryption keys are moved to a backup location. If something went wrong you can restore the keys. Only delete them permanently if you are sure that all files are decrypted correctly." )); ?>
|
<?php p($l->t( "Your encryption keys are moved to a backup location. If something went wrong you can restore the keys. Only delete them permanently if you are sure that all files are decrypted correctly." )); ?>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICATCCAWoCCQDNdmb4pJrUeDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
|
||||||
|
VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
|
||||||
|
cyBQdHkgTHRkMB4XDTE0MDgyNzA4NDg1MVoXDTE1MDgyNzA4NDg1MVowRTELMAkG
|
||||||
|
A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0
|
||||||
|
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvrMe
|
||||||
|
x5D45HVMV2U4kqTU0mzHAihHT6r+OtO6g7S9yIlJZGGVcEet6An78Ow7aYM141eI
|
||||||
|
Jfbvqql7OIblHXSw7mvkw4bOQ1ee5lmJYOYCgaMNJ6mBLJfpK9xwidb0ZvhWOA8P
|
||||||
|
DLIiBKA3T5ChXCzilD5GF2+H/BXBE9lL9tuDjM0CAwEAATANBgkqhkiG9w0BAQUF
|
||||||
|
AAOBgQCJwfJe7j+aNkopw+P8uxobfOnMWU9XC4Pu+39TVLeakeSqu2Y8vJSHmkjF
|
||||||
|
WK3VXAJr33Eul5VP/3SWGwuRPd9X4i4iLh1gJfYvi9MJf1lQNYncGCM+xtdrNu2O
|
||||||
|
u0yexkOBRrapDYjcv58BiOaFgvFLquKvtVj9HlcYRfwfM77uKQ==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,13 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICATCCAWoCCQCjCIB6tCZ2sDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
|
||||||
|
VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
|
||||||
|
cyBQdHkgTHRkMB4XDTE0MDgyNzA5MTI0M1oXDTE0MDgyODA5MTI0M1owRTELMAkG
|
||||||
|
A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0
|
||||||
|
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvrMe
|
||||||
|
x5D45HVMV2U4kqTU0mzHAihHT6r+OtO6g7S9yIlJZGGVcEet6An78Ow7aYM141eI
|
||||||
|
Jfbvqql7OIblHXSw7mvkw4bOQ1ee5lmJYOYCgaMNJ6mBLJfpK9xwidb0ZvhWOA8P
|
||||||
|
DLIiBKA3T5ChXCzilD5GF2+H/BXBE9lL9tuDjM0CAwEAATANBgkqhkiG9w0BAQUF
|
||||||
|
AAOBgQBuNClmOj3wudlX86nygcZgQT2+ZS8f1iJgM9lbrrkenT6tgcT1/YjcrN9C
|
||||||
|
BZR29Wz7htflpqverLUGZXh72K+gYercyR16Zu7zjt/NWuZldZmzJ3bUGq2HSoCX
|
||||||
|
2sDykAEuaDxUlzdJrztlOH4vPlRaGbxUogpC2hB1BQfxA90CIA==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,15 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICazCCAdQCCQCySF7HjQD78DANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJD
|
||||||
|
SDEPMA0GA1UECBMGWnVyaWNoMQ8wDQYDVQQHEwZadXJpY2gxFjAUBgNVBAoTDW93
|
||||||
|
bkNsb3VkIEluYy4xETAPBgNVBAsTCFNlY3VyaXR5MR4wHAYDVQQDExVzZWN1cml0
|
||||||
|
eS5vd25jbG91ZC5jb20wHhcNMTQwODI3MDg0NTUyWhcNMTUwODI3MDg0NTUyWjB6
|
||||||
|
MQswCQYDVQQGEwJDSDEPMA0GA1UECBMGWnVyaWNoMQ8wDQYDVQQHEwZadXJpY2gx
|
||||||
|
FjAUBgNVBAoTDW93bkNsb3VkIEluYy4xETAPBgNVBAsTCFNlY3VyaXR5MR4wHAYD
|
||||||
|
VQQDExVzZWN1cml0eS5vd25jbG91ZC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A
|
||||||
|
MIGJAoGBAL55lB4RvU0pTyh7YsLCxPBq43xxkRZBxfZENoflCIUsBo7/mXNz2zVO
|
||||||
|
476oQ4L47heUOX3j8kemOgPmWEqA34JB8rusijCy5WqFBLnm4HsRLa66i+Jgd+Yl
|
||||||
|
QhcKvhGas1K/CVTG4oSLoAmA2coZUL94uxnRtd8aluflHMNGApIlAgMBAAEwDQYJ
|
||||||
|
KoZIhvcNAQEFBQADgYEADo08zWdOtIvCKFDnLbzRwIjSYTlAtQtQaULv7KQe3qIn
|
||||||
|
iaFAi6fAynHfdC8/2tvmSeniw0OZBkrfVGIVtUbwCSrljNSUY/lWrUR0pE61lb4r
|
||||||
|
DpX0JZjlk48XEaErRVDfu3wq6n/2nYg6HnaLOPwt8OSYYrxzvXlFPrKBH3q6R+M=
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,93 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use \OC\Security\Certificate;
|
||||||
|
|
||||||
|
class CertificateTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
/** @var Certificate That contains a valid certificate */
|
||||||
|
protected $goodCertificate;
|
||||||
|
/** @var Certificate That contains an invalid certificate */
|
||||||
|
protected $invalidCertificate;
|
||||||
|
/** @var Certificate That contains an expired certificate */
|
||||||
|
protected $expiredCertificate;
|
||||||
|
|
||||||
|
function setUp() {
|
||||||
|
$goodCertificate = file_get_contents(__DIR__ . '/../../data/certificates/goodCertificate.crt');
|
||||||
|
$this->goodCertificate = new Certificate($goodCertificate, 'GoodCertificate');
|
||||||
|
$badCertificate = file_get_contents(__DIR__ . '/../../data/certificates/badCertificate.crt');
|
||||||
|
$this->invalidCertificate = new Certificate($badCertificate, 'BadCertificate');
|
||||||
|
$expiredCertificate = file_get_contents(__DIR__ . '/../../data/certificates/expiredCertificate.crt');
|
||||||
|
$this->expiredCertificate = new Certificate($expiredCertificate, 'ExpiredCertificate');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Exception
|
||||||
|
* @expectedExceptionMessage Certificate could not get parsed.
|
||||||
|
*/
|
||||||
|
function testBogusData() {
|
||||||
|
new Certificate('foo', 'bar');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetName() {
|
||||||
|
$this->assertSame('GoodCertificate', $this->goodCertificate->getName());
|
||||||
|
$this->assertSame('BadCertificate', $this->invalidCertificate->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetCommonName() {
|
||||||
|
$this->assertSame('security.owncloud.com', $this->goodCertificate->getCommonName());
|
||||||
|
$this->assertSame(null, $this->invalidCertificate->getCommonName());
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetOrganization() {
|
||||||
|
$this->assertSame('ownCloud Inc.', $this->goodCertificate->getOrganization());
|
||||||
|
$this->assertSame('Internet Widgits Pty Ltd', $this->invalidCertificate->getOrganization());
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetSerial() {
|
||||||
|
$this->assertSame('7F:FF:FF:FF:FF:FF:FF:FF', $this->goodCertificate->getSerial());
|
||||||
|
$this->assertSame('7F:FF:FF:FF:FF:FF:FF:FF', $this->invalidCertificate->getSerial());
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetIssueDate() {
|
||||||
|
$expected = new DateTime('2014-08-27 08:45:52 GMT');
|
||||||
|
$this->assertEquals($expected->getTimestamp(), $this->goodCertificate->getIssueDate()->getTimestamp());
|
||||||
|
$expected = new DateTime('2014-08-27 08:48:51 GMT');
|
||||||
|
$this->assertEquals($expected->getTimestamp(), $this->invalidCertificate->getIssueDate()->getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetExpireDate() {
|
||||||
|
$expected = new DateTime('2015-08-27 08:45:52 GMT');
|
||||||
|
$this->assertEquals($expected->getTimestamp(), $this->goodCertificate->getExpireDate()->getTimestamp());
|
||||||
|
$expected = new DateTime('2015-08-27 08:48:51 GMT');
|
||||||
|
$this->assertEquals($expected->getTimestamp(), $this->invalidCertificate->getExpireDate()->getTimestamp());
|
||||||
|
$expected = new DateTime('2014-08-28 09:12:43 GMT');
|
||||||
|
$this->assertEquals($expected->getTimestamp(), $this->expiredCertificate->getExpireDate()->getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obviously the following test case might fail after 2015-08-27, just create a new certificate with longer validity then
|
||||||
|
*/
|
||||||
|
function testIsExpired() {
|
||||||
|
$this->assertSame(false, $this->goodCertificate->isExpired());
|
||||||
|
$this->assertSame(false, $this->invalidCertificate->isExpired());
|
||||||
|
$this->assertSame(true, $this->expiredCertificate->isExpired());
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetIssuerName() {
|
||||||
|
$this->assertSame('security.owncloud.com', $this->goodCertificate->getIssuerName());
|
||||||
|
$this->assertSame(null, $this->invalidCertificate->getIssuerName());
|
||||||
|
$this->assertSame(null, $this->expiredCertificate->getIssuerName());
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetIssuerOrganization() {
|
||||||
|
$this->assertSame('ownCloud Inc.', $this->goodCertificate->getIssuerOrganization());
|
||||||
|
$this->assertSame('Internet Widgits Pty Ltd', $this->invalidCertificate->getIssuerOrganization());
|
||||||
|
$this->assertSame('Internet Widgits Pty Ltd', $this->expiredCertificate->getIssuerOrganization());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use \OC\Security\CertificateManager;
|
||||||
|
|
||||||
|
class CertificateManagerTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
/** @var CertificateManager */
|
||||||
|
private $certificateManager;
|
||||||
|
/** @var String */
|
||||||
|
private $username;
|
||||||
|
/** @var \OC\User\User */
|
||||||
|
private $user;
|
||||||
|
|
||||||
|
function setUp() {
|
||||||
|
$this->username = OC_Util::generateRandomBytes(20);
|
||||||
|
OC_User::createUser($this->username, OC_Util::generateRandomBytes(20));
|
||||||
|
|
||||||
|
\OC_Util::tearDownFS();
|
||||||
|
\OC_User::setUserId('');
|
||||||
|
\OC\Files\Filesystem::tearDown();
|
||||||
|
\OC_Util::setupFS($this->username);
|
||||||
|
|
||||||
|
$this->user = \OC::$server->getUserManager()->get($this->username);
|
||||||
|
|
||||||
|
$this->certificateManager = new CertificateManager($this->user);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tearDown() {
|
||||||
|
\OC_User::deleteUser($this->username);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function assertEqualsArrays($expected, $actual) {
|
||||||
|
sort($expected);
|
||||||
|
sort($actual);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testListCertificates() {
|
||||||
|
// Test empty certificate bundle
|
||||||
|
$this->assertSame(array(), $this->certificateManager->listCertificates());
|
||||||
|
|
||||||
|
// Add some certificates
|
||||||
|
$this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
|
||||||
|
$certificateStore = array();
|
||||||
|
$certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__.'/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
|
||||||
|
$this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates());
|
||||||
|
|
||||||
|
// Add another certificates
|
||||||
|
$this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate');
|
||||||
|
$certificateStore[] = new \OC\Security\Certificate(file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'), 'ExpiredCertificate');
|
||||||
|
$this->assertEqualsArrays($certificateStore, $this->certificateManager->listCertificates());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Exception
|
||||||
|
* @expectedExceptionMessage Certificate could not get parsed.
|
||||||
|
*/
|
||||||
|
function testAddInvalidCertificate() {
|
||||||
|
$this->certificateManager->addCertificate('InvalidCertificate', 'invalidCertificate');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testAddDangerousFile() {
|
||||||
|
$this->assertFalse($this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'), '.htaccess'));
|
||||||
|
$this->assertFalse($this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/expiredCertificate.crt'), '../../foo.txt'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testRemoveDangerousFile() {
|
||||||
|
$this->assertFalse($this->certificateManager->removeCertificate('../../foo.txt'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testRemoveExistingFile() {
|
||||||
|
$this->certificateManager->addCertificate(file_get_contents(__DIR__.'/../../data/certificates/goodCertificate.crt'), 'GoodCertificate');
|
||||||
|
$this->assertTrue($this->certificateManager->removeCertificate('GoodCertificate'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetCertificateBundle() {
|
||||||
|
$this->assertSame($this->user->getHome().'/files_external/rootcerts.crt', $this->certificateManager->getCertificateBundle());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue