Move certificate management code to core

This commit is contained in:
Robin Appelman 2014-08-14 14:24:10 +02:00
parent 23137f4798
commit ecdbf00628
8 changed files with 193 additions and 81 deletions

View File

@ -3,8 +3,8 @@
OCP\JSON::checkAppEnabled('files_external');
OCP\JSON::callCheck();
if ( ! ($filename = $_FILES['rootcert_import']['name']) ) {
header('Location:' . OCP\Util::linkToRoute( "settings_personal" ));
if (!($filename = $_FILES['rootcert_import']['name'])) {
header('Location:' . OCP\Util::linkToRoute("settings_personal"));
exit;
}
@ -13,33 +13,13 @@ $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('');
}
$certificateManager = \OC::$server->getCertificateManager();
$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 {
if (!$certificateManager->addCertificate($data, $filename)) {
OCP\Util::writeLog('files_external',
'Couldn\'t import SSL root certificate ('.$filename.'), allowed formats: PEM and DER',
OCP\Util::WARN);
'Couldn\'t import SSL root certificate (' . $filename . '), allowed formats: PEM and DER',
OCP\Util::WARN);
}
header('Location:' . OCP\Util::linkToRoute( "settings_personal" ));
header('Location:' . OCP\Util::linkToRoute("settings_personal"));
exit;

View File

@ -4,10 +4,8 @@ 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();
$name = $_POST['cert'];
$certificateManager = \OC::$server->getCertificateManager();
if (\OC\Files\Filesystem::isValidPath($name)) {
$certificateManager->removeCertificate($name);
}

View File

@ -619,53 +619,6 @@ class OC_Mount_Config {
@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
*/

View File

@ -23,11 +23,12 @@
OCP\Util::addScript('files_external', 'settings');
OCP\Util::addStyle('files_external', 'settings');
$backends = OC_Mount_Config::getPersonalBackends();
$certificateManager = \OC::$server->getCertificateManager();
$tmpl = new OCP\Template('files_external', 'settings');
$tmpl->assign('isAdminPage', false);
$tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints());
$tmpl->assign('certs', OC_Mount_Config::getCertificates());
$tmpl->assign('certs', $certificateManager->listCertificates());
$tmpl->assign('dependencies', OC_Mount_Config::checkDependencies());
$tmpl->assign('backends', $backends);
return $tmpl->fetchPage();

View File

@ -0,0 +1,116 @@
<?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;
/**
* Manage trusted certificates for users
*/
class CertificateManager {
/**
* @var \OCP\IUser
*/
protected $user;
/**
* @param \OCP\IUser $user
*/
public function __construct($user) {
$this->user = $user;
}
/**
* Returns all certificates trusted by the user
*
* @return string[]
*/
public function listCertificates() {
$path = $this->user->getHome() . '/files_external/uploads/';
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.
//note that we use "normal" php filesystem functions here since the certs need to be local
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;
}
/**
* 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;
$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);
}
/**
* @param string $certificate the certificate data
* @param string $name the filename for the certificate
* @return bool
*/
public function addCertificate($certificate, $name) {
$isValid = openssl_pkey_get_public($certificate);
if (!$isValid) {
$data = chunk_split(base64_encode($certificate), 64, "\n");
$data = "-----BEGIN CERTIFICATE-----\n" . $data . "-----END CERTIFICATE-----\n";
$isValid = openssl_pkey_get_public($data);
}
if ($isValid) {
$file = $this->user->getHome() . '/files_external/uploads/' . $name;
file_put_contents($file, $certificate);
$this->createCertificateBundle();
return true;
} else {
return false;
}
}
/**
* @param string $name
*/
public function removeCertificate($name) {
$path = $this->user->getHome() . '/files_external/uploads/';
if (file_exists($path . $name)) {
unlink($path . $name);
$this->createCertificateBundle();
}
}
/**
* Get the path to the certificate bundle for this user
*
* @return string
*/
public function getCertificateBundle() {
return $this->user->getHome() . '/files_external/rootcerts.crt';
}
}

View File

@ -469,4 +469,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);
}
}

View File

@ -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 string[]
*/
public function listCertificates();
/**
* @param string $certificate the certificate data
* @param string $name the filename for the certificate
* @return bool
*/
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();
}

View File

@ -226,4 +226,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);
}