Updates to SSL and other general items
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
* @copyright (c) 2009-2014 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Controller_Admin_SSL extends Controller_SSL {
|
||||
class Controller_Admin_Ssl extends Controller_Ssl {
|
||||
protected $auth_required = TRUE;
|
||||
|
||||
protected $secure_actions = array(
|
||||
|
@@ -1,14 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides SSL management
|
||||
*
|
||||
* @package SSL
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2014 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Controller_SSL extends Controller_TemplateDefault {
|
||||
}
|
||||
?>
|
27
modules/ssl/classes/Controller/Ssl.php
Normal file
27
modules/ssl/classes/Controller/Ssl.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides SSL management
|
||||
*
|
||||
* @package SSL
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2014 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Controller_Ssl extends Controller_TemplateDefault {
|
||||
protected $auth_required = FALSE;
|
||||
|
||||
public function action_download() {
|
||||
$so = ORM::factory('SSL_CA')->where('id','=',$this->request->param('id'))->or_where('name','=',$this->request->param('id'))->find();
|
||||
|
||||
if (! $so->loaded() OR ! $so->cert)
|
||||
throw HTTP_Exception::factory(404,'SSL either doesnt exist');
|
||||
|
||||
$this->auto_render = FALSE;
|
||||
$this->response->headers('Content-Type','plain/text');
|
||||
$this->response->headers('Content-Disposition','attachment; filename="'.$so->name.'.crt"');
|
||||
$this->response->body($so->cert);
|
||||
}
|
||||
}
|
||||
?>
|
@@ -9,7 +9,7 @@
|
||||
* @copyright (c) 2009-2013 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Controller_User_SSL extends Controller_SSL {
|
||||
class Controller_User_Ssl extends Controller_Ssl {
|
||||
protected $auth_required = TRUE;
|
||||
|
||||
protected $secure_actions = array(
|
||||
@@ -19,31 +19,58 @@ class Controller_User_SSL extends Controller_SSL {
|
||||
);
|
||||
|
||||
public function action_add() {
|
||||
if ($this->request->post()) {
|
||||
$so = ORM::factory('SSL');
|
||||
if ($this->request->post() OR $_FILES) {
|
||||
if ($_FILES AND $this->request->post('csr'))
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Validation failed'),
|
||||
'type'=>'info',
|
||||
'body'=>_('Only supply a CSR file OR the CSR text, not both!'),
|
||||
));
|
||||
|
||||
$so->account_id = (string)Auth::instance()->get_user();
|
||||
else {
|
||||
|
||||
// Set our values, so that our filters have data
|
||||
$so->values($this->request->post());
|
||||
|
||||
$this->save($so);
|
||||
$so = ORM::factory('SSL');
|
||||
$so->account_id = (string)Auth::instance()->get_user();
|
||||
|
||||
if ($so->saved())
|
||||
HTTP::redirect(URL::link('user','ssl/view/'.$so->id));
|
||||
// Set our values, so that our filters have data
|
||||
$so->values($this->request->post());
|
||||
|
||||
if ($_FILES) {
|
||||
// Process upload
|
||||
$files = Validation::factory($_FILES)
|
||||
->rule('csr_file','Upload::valid')
|
||||
->rule('csr_file','Upload::not_empty')
|
||||
->rule('csr_file','Upload::type',array(':value',array('csr')))
|
||||
->rule('csr_file','Upload::size',array(':value','512K'));
|
||||
|
||||
if ($files->check())
|
||||
foreach ($files->data() as $file) {
|
||||
$so->csr = file_get_contents($file['tmp_name']);
|
||||
break;
|
||||
}
|
||||
|
||||
if (! $so->csr)
|
||||
throw HTTP_Exception::factory(501,'No CSR data :csr_file?',$files->errors('user/ssl/add'));
|
||||
}
|
||||
|
||||
$this->save($so);
|
||||
|
||||
if ($so->saved())
|
||||
HTTP::redirect(URL::link('user','ssl/view/'.$so->id));
|
||||
}
|
||||
}
|
||||
|
||||
Block::factory()
|
||||
->type('form-horizontal')
|
||||
->title('Add/Edit Record')
|
||||
->title_icon('fa-wrench')
|
||||
->title('SSL Certificate')
|
||||
->title_icon('fa-certificate')
|
||||
->body(View::factory('ssl/user/add')->set('o',$this->ao));
|
||||
}
|
||||
|
||||
public function action_download() {
|
||||
$passwd_len = Kohana::$config->load('ssl')->minpass_length;
|
||||
|
||||
$so = ORM::factory('SSL',$this->request->post('sid'));
|
||||
$so = ORM::factory('SSL',$this->request->param('id'));
|
||||
|
||||
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account))
|
||||
throw HTTP_Exception::factory(403,'SSL either doesnt exist, or you are not authorised to see it');
|
||||
|
@@ -1,339 +1,4 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class supports SSL Certificates
|
||||
*
|
||||
* @package SSL
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class Model_SSL extends ORM {
|
||||
protected $_cert_details = NULL;
|
||||
|
||||
// Relationships
|
||||
protected $_belongs_to = array(
|
||||
'account'=>array(),
|
||||
);
|
||||
|
||||
protected $_has_one = array(
|
||||
'ca'=>array('model'=>'SSL_CA','far_key'=>'ssl_ca_id','foreign_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'csr'=>array(
|
||||
array('Model_SSL::subject_csr',array(':value')),
|
||||
),
|
||||
'cert'=>array(
|
||||
array('Model_SSL::subject_cert',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
protected $_save_message = TRUE;
|
||||
|
||||
/**
|
||||
* Parse our AuthorityKeyIndentifier Extension to extract information
|
||||
* @param $key Return just that index
|
||||
*/
|
||||
private function _aki($key=NULL) {
|
||||
$result = array();
|
||||
|
||||
$aki = $this->_extensions('authorityKeyIdentifier');
|
||||
if (! $aki)
|
||||
return '';
|
||||
|
||||
foreach (explode("\n",preg_replace("/\n$/",'',$aki)) as $x) {
|
||||
if (! $x)
|
||||
continue;
|
||||
|
||||
if (strstr($x,':')) {
|
||||
list($a,$b) = explode(':',$x,2);
|
||||
$result[strtolower($a)] = $b;
|
||||
}
|
||||
}
|
||||
|
||||
return is_null($key) ? $result : Arr::get($result,$key);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will convert a large decimal number into hex
|
||||
* @param $number Large decimal number
|
||||
*/
|
||||
private static function _dec_to_hex($number) {
|
||||
$hex = array();
|
||||
|
||||
if ($number == 0)
|
||||
return '00';
|
||||
|
||||
while ($number > 0) {
|
||||
if ($number == 0) {
|
||||
array_push($hex, '0');
|
||||
|
||||
} else {
|
||||
$x = (int) ($number/16);
|
||||
array_push($hex,strtoupper(dechex((int)($number-($x*16)))));
|
||||
$number = $x;
|
||||
}
|
||||
}
|
||||
|
||||
return preg_replace('/^:/','',preg_replace('/(..)/',":$1",implode(array_reverse($hex))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse our Sign Certifcate to extract information
|
||||
* @param $key Return just that index
|
||||
*/
|
||||
private function _details($key=NULL) {
|
||||
if (! $this->cert)
|
||||
return array();
|
||||
|
||||
return is_null($key) ? $this->_cert_details : Arr::get($this->_cert_details,$key,array());
|
||||
}
|
||||
|
||||
private static function _dn(array $array) {
|
||||
$result = '';
|
||||
$i = 0;
|
||||
|
||||
foreach ($array as $k=>$v) {
|
||||
if ($i++)
|
||||
$result .= ',';
|
||||
|
||||
$result .= sprintf('%s=%s',$k,$v);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse our Sign Certifcate Extensions to extract information
|
||||
* @param $key Return just that index
|
||||
*/
|
||||
protected function _extensions($key=NULL) {
|
||||
$result = Arr::get($this->_cert_details,'extensions');
|
||||
|
||||
return is_null($key) ? $result : Arr::get($result,$key);
|
||||
}
|
||||
|
||||
// We want to inject the SSL object into this Model
|
||||
protected function _load_values(array $values) {
|
||||
parent::_load_values($values);
|
||||
|
||||
$this->_cert_details = openssl_x509_parse($this->cert);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function aki_dirname() {
|
||||
return $this->_aki('dirname');
|
||||
}
|
||||
|
||||
public function aki_keyid() {
|
||||
return $this->_aki('keyid');
|
||||
}
|
||||
|
||||
public function aki_serial() {
|
||||
return $this->_aki('serial');
|
||||
}
|
||||
|
||||
public function algorithm() {
|
||||
if (! $this->cert)
|
||||
return NULL;
|
||||
|
||||
$e = '';
|
||||
openssl_x509_export(openssl_x509_read($this->cert),$e,FALSE);
|
||||
|
||||
// @todo There must be a nice way to get this?
|
||||
return (preg_match('/^\s+Signature Algorithm:\s*(.*)\s*$/m',$e,$match)) ? $match[1] : _('Unknown');
|
||||
}
|
||||
|
||||
public function download_button() {
|
||||
if ($this->valid_to() < time())
|
||||
return '';
|
||||
|
||||
$passwd_len = Kohana::$config->load('ssl')->minpass_length;
|
||||
|
||||
$output = Form::open(URL::link('user','ssl/download'),array('class'=>'form-inline','data-toggle'=>'validator','role'=>'form'));
|
||||
$output .= Form::hidden('sid',$this->id);
|
||||
|
||||
if ($passwd_len) {
|
||||
$output .= '<div class="form-group">';
|
||||
$output .= '<div class="input-group">';
|
||||
$output .= Form::password('passwd','',array('class'=>'form-control','placeholder'=>_('Choose a password'),'nocg'=>TRUE,'pattern'=>'.{'.$passwd_len.',}','data-error'=>"Minimum ${passwd_len} characters",'required'));
|
||||
$output .= '<span class="input-group-btn">';
|
||||
}
|
||||
|
||||
$output .= Form::button('download','Download',array('class'=>'btn btn-default','nocg'=>TRUE));
|
||||
|
||||
if ($passwd_len) {
|
||||
$output .= '</span>';
|
||||
$output .= '</div>';
|
||||
$output .= '<div class="help-block with-errors"></div>';
|
||||
$output .= '</div>';
|
||||
}
|
||||
|
||||
$output .= Form::close();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function dn() {
|
||||
return $this->display($this->signed() ? 'cert' : 'csr');
|
||||
}
|
||||
|
||||
public function hash() {
|
||||
return Arr::get($this->_cert_details,'hash');
|
||||
}
|
||||
|
||||
public function issuer() {
|
||||
return self::_dn(Arr::get($this->_cert_details,'issuer',array()));
|
||||
}
|
||||
|
||||
public function serial() {
|
||||
return $this->_dec_to_hex(Arr::get($this->_cert_details,'serialNumber'));
|
||||
}
|
||||
|
||||
/**
|
||||
* (Re)Sign an SSL Certificate
|
||||
*/
|
||||
public function sign($force=FALSE) {
|
||||
$ssl_config = Kohana::$config->load('ssl');
|
||||
$ssl_conf = Kohana::find_file('config',$ssl_config->config,'');
|
||||
$ssl_conf = array_pop($ssl_conf);
|
||||
|
||||
// If our certificate is not old enough skip
|
||||
if ($this->valid_to() > time()+$ssl_config->min_renew_days*86400 AND ! $force)
|
||||
return FALSE;
|
||||
|
||||
$today = mktime(0,0,0,date('n'),date('j'),date('Y'));
|
||||
$days = (int)$this->account->renew;
|
||||
|
||||
if (! $this->ca->pk)
|
||||
throw HTTP_Exception::factory(400,'Unable to sign, missing Private Key for CA :ca',array(':ca'=>$this->ca->subject_cn()));
|
||||
|
||||
$res = openssl_csr_sign($this->csr,$this->ca->cert,$this->ca->pk,$days,array(
|
||||
'config'=>$ssl_conf,
|
||||
'x509_extensions'=>'client',
|
||||
'digest_alg'=>'sha1',
|
||||
),time());
|
||||
|
||||
if ($res AND openssl_x509_export($res,$cert)) {
|
||||
$this->cert = $cert;
|
||||
$this->save();
|
||||
|
||||
return TRUE;
|
||||
|
||||
} else {
|
||||
/*
|
||||
echo Debug::vars(array(
|
||||
'csr'=>$this->csr,
|
||||
'ca'=>$this->ca->cert,
|
||||
'caid'=>$this->ca->id,
|
||||
'days'=>$days,
|
||||
'ssl'=>$ssl_conf,
|
||||
'x509e'=>'client',
|
||||
// 'command'=>sprintf('openssl ca -days %s -cert /tmp/ssl_ca.crt -keyfile /tmp/ssl_ca.key -out /tmp/ssl.crt -in /tmp/ssl.csr -extensions %s -config %s',$days,'client',$ssl_conf),
|
||||
));
|
||||
|
||||
file_put_contents('/tmp/ssl.csr',$this->csr);
|
||||
file_put_contents('/tmp/ssl_ca.key',$this->ca->pk);
|
||||
file_put_contents('/tmp/ssl_ca.crt',$this->ca->cert);
|
||||
*/
|
||||
throw HTTP_Exception::factory(501,'Error Creating SSL Certificate :error',array(':error'=>openssl_error_string()));
|
||||
}
|
||||
}
|
||||
|
||||
private function signed() {
|
||||
return $this->_cert_details ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
public function ski() {
|
||||
return $this->_extensions('subjectKeyIdentifier');
|
||||
}
|
||||
|
||||
public function issuer_cn() {
|
||||
return Arr::get($this->cert ? Arr::get($this->_cert_details,'issuer') : array(),'CN');
|
||||
}
|
||||
|
||||
public function subject_cn() {
|
||||
return $this->cert ? Arr::get(Arr::get($this->_cert_details,'subject'),'CN') : self::subject_csr($this->csr);
|
||||
}
|
||||
|
||||
public static function subject_cert($cert) {
|
||||
try {
|
||||
return self::_dn(Arr::get(openssl_x509_parse($cert),'subject'));
|
||||
} catch (exception $e) {
|
||||
return 'Invalid Cert';
|
||||
}
|
||||
}
|
||||
|
||||
public static function subject_csr($csr) {
|
||||
try {
|
||||
return self::_dn(openssl_csr_get_subject($csr));
|
||||
} catch (exception $e) {
|
||||
return 'Invalid CSR';
|
||||
}
|
||||
}
|
||||
|
||||
public function validCA($format=FALSE) {
|
||||
return StaticList_YesNo::get(($this->_cert_details AND $this->ssl_ca_id AND $this->aki_keyid()==$this->ca->ski()) ? $this->ca->validParent() : FALSE,$format);
|
||||
}
|
||||
|
||||
public function valid_from($format=FALSE) {
|
||||
$k = Arr::get($this->_cert_details,'validFrom_time_t');
|
||||
|
||||
if (! $k)
|
||||
return NULL;
|
||||
|
||||
return $format ? Site::Date($k) : $k;
|
||||
}
|
||||
|
||||
public function valid_to($format=FALSE) {
|
||||
$k = Arr::get($this->_cert_details,'validTo_time_t');
|
||||
|
||||
if (! $k)
|
||||
return NULL;
|
||||
|
||||
return $format ? Site::Date($k) : $k;
|
||||
}
|
||||
|
||||
// If we change the SSL certificate, we need to reload our SSL object
|
||||
public function values(array $values, array $expected = NULL) {
|
||||
parent::values($values,$expected);
|
||||
|
||||
if (array_key_exists('cert',$this->_changed))
|
||||
$this->_cert_details = openssl_x509_parse($this->cert);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function version() {
|
||||
return Arr::get($this->_cert_details,'version');
|
||||
}
|
||||
|
||||
public function list_ca() {
|
||||
$result = array();
|
||||
|
||||
if (! $this->validCA())
|
||||
return $result;
|
||||
|
||||
$x = $this;
|
||||
while (! is_null($x->ssl_ca_id) AND $x->id != $x->ssl_ca_id AND $x=$x->ca)
|
||||
array_push($result,$x);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all our CA Certs for this certificate
|
||||
*/
|
||||
public function list_ca_crts() {
|
||||
$result = array();
|
||||
|
||||
foreach ($this->list_ca() as $so)
|
||||
array_push($result,$so->cert);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
class Model_SSL extends lnApp_Model_SSL {}
|
||||
?>
|
||||
|
350
modules/ssl/classes/lnApp/Model/SSL.php
Normal file
350
modules/ssl/classes/lnApp/Model/SSL.php
Normal file
@@ -0,0 +1,350 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class supports SSL Certificates
|
||||
*
|
||||
* @package SSL
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
abstract class lnApp_Model_SSL extends ORM {
|
||||
protected $_cert_details = NULL;
|
||||
|
||||
// Relationships
|
||||
protected $_belongs_to = array(
|
||||
'account'=>array(),
|
||||
);
|
||||
|
||||
protected $_has_one = array(
|
||||
'ca'=>array('model'=>'SSL_CA','far_key'=>'ssl_ca_id','foreign_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'csr'=>array(
|
||||
array('Model_SSL::subject_csr',array(':value')),
|
||||
),
|
||||
'cert'=>array(
|
||||
array('Model_SSL::subject_cert',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
protected $_save_message = TRUE;
|
||||
|
||||
public function rules() {
|
||||
return Arr::merge(parent::rules(),array(
|
||||
'csr'=>array(
|
||||
array(array($this,'isCSR')),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse our AuthorityKeyIndentifier Extension to extract information
|
||||
* @param $key Return just that index
|
||||
*/
|
||||
protected function _aki($key=NULL) {
|
||||
$result = array();
|
||||
|
||||
$aki = $this->_extensions('authorityKeyIdentifier');
|
||||
if (! $aki)
|
||||
return '';
|
||||
|
||||
foreach (explode("\n",preg_replace("/\n$/",'',$aki)) as $x) {
|
||||
if (! $x)
|
||||
continue;
|
||||
|
||||
if (strstr($x,':')) {
|
||||
list($a,$b) = explode(':',$x,2);
|
||||
$result[strtolower($a)] = $b;
|
||||
}
|
||||
}
|
||||
|
||||
return is_null($key) ? $result : Arr::get($result,$key);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will convert a large decimal number into hex
|
||||
* @param $number Large decimal number
|
||||
*/
|
||||
protected static function _dec_to_hex($number) {
|
||||
$hex = array();
|
||||
|
||||
if ($number == 0)
|
||||
return '00';
|
||||
|
||||
while ($number > 0) {
|
||||
if ($number == 0) {
|
||||
array_push($hex, '0');
|
||||
|
||||
} else {
|
||||
$x = (int) ($number/16);
|
||||
array_push($hex,strtoupper(dechex((int)($number-($x*16)))));
|
||||
$number = $x;
|
||||
}
|
||||
}
|
||||
|
||||
return preg_replace('/^:/','',preg_replace('/(..)/',":$1",implode(array_reverse($hex))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse our Sign Certifcate to extract information
|
||||
* @param $key Return just that index
|
||||
*/
|
||||
protected function _details($key=NULL) {
|
||||
if (! $this->cert)
|
||||
return array();
|
||||
|
||||
return is_null($key) ? $this->_cert_details : Arr::get($this->_cert_details,$key,array());
|
||||
}
|
||||
|
||||
protected static function _dn(array $array) {
|
||||
$result = '';
|
||||
$i = 0;
|
||||
|
||||
foreach ($array as $k=>$v) {
|
||||
if ($i++)
|
||||
$result .= ',';
|
||||
|
||||
$result .= sprintf('%s=%s',$k,$v);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse our Sign Certifcate Extensions to extract information
|
||||
* @param $key Return just that index
|
||||
*/
|
||||
protected function _extensions($key=NULL) {
|
||||
$result = Arr::get($this->_cert_details,'extensions');
|
||||
|
||||
return is_null($key) ? $result : Arr::get($result,$key);
|
||||
}
|
||||
|
||||
// We want to inject the SSL object into this Model
|
||||
protected function _load_values(array $values) {
|
||||
parent::_load_values($values);
|
||||
|
||||
$this->_cert_details = openssl_x509_parse($this->cert);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function aki_dirname() {
|
||||
return $this->_aki('dirname');
|
||||
}
|
||||
|
||||
public function aki_keyid() {
|
||||
return $this->_aki('keyid');
|
||||
}
|
||||
|
||||
public function aki_serial() {
|
||||
return $this->_aki('serial');
|
||||
}
|
||||
|
||||
public function algorithm() {
|
||||
if (! $this->cert)
|
||||
return NULL;
|
||||
|
||||
$e = '';
|
||||
openssl_x509_export(openssl_x509_read($this->cert),$e,FALSE);
|
||||
|
||||
// @todo There must be a nice way to get this?
|
||||
return (preg_match('/^\s+Signature Algorithm:\s*(.*)\s*$/m',$e,$match)) ? $match[1] : _('Unknown');
|
||||
}
|
||||
|
||||
public function download_button() {
|
||||
if ($this->valid_to() < time())
|
||||
return '';
|
||||
|
||||
$passwd_len = Kohana::$config->load('ssl')->minpass_length;
|
||||
|
||||
$output = Form::open(URL::link('user','ssl/download/'.$this->id),array('class'=>'form-inline','data-toggle'=>'validator','role'=>'form'));
|
||||
|
||||
if ($passwd_len) {
|
||||
$output .= '<div class="form-group">';
|
||||
$output .= '<div class="input-group">';
|
||||
$output .= Form::password('passwd','',array('class'=>'form-control','placeholder'=>_('Choose a password'),'nocg'=>TRUE,'pattern'=>'.{'.$passwd_len.',}','data-error'=>"Minimum ${passwd_len} characters",'required'));
|
||||
$output .= '<span class="input-group-btn">';
|
||||
}
|
||||
|
||||
$output .= Form::button('download','Download',array('class'=>'btn btn-default','nocg'=>TRUE));
|
||||
|
||||
if ($passwd_len) {
|
||||
$output .= '</span>';
|
||||
$output .= '</div>';
|
||||
$output .= '<div class="help-block with-errors"></div>';
|
||||
$output .= '</div>';
|
||||
}
|
||||
|
||||
$output .= Form::close();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function dn() {
|
||||
return $this->display($this->signed() ? 'cert' : 'csr');
|
||||
}
|
||||
|
||||
public function hash() {
|
||||
return Arr::get($this->_cert_details,'hash');
|
||||
}
|
||||
|
||||
public function isCSR() {
|
||||
return openssl_csr_get_subject($this->csr);
|
||||
}
|
||||
|
||||
public function issuer() {
|
||||
return self::_dn(Arr::get($this->_cert_details,'issuer',array()));
|
||||
}
|
||||
|
||||
public function serial() {
|
||||
return $this->_dec_to_hex(Arr::get($this->_cert_details,'serialNumber'));
|
||||
}
|
||||
|
||||
/**
|
||||
* (Re)Sign an SSL Certificate
|
||||
*/
|
||||
public function sign($force=FALSE) {
|
||||
$ssl_config = Kohana::$config->load('ssl');
|
||||
$ssl_conf = Kohana::find_file('config',$ssl_config->config,'');
|
||||
$ssl_conf = array_pop($ssl_conf);
|
||||
|
||||
// If our certificate is not old enough skip
|
||||
if ($this->valid_to() > time()+$ssl_config->min_renew_days*86400 AND ! $force)
|
||||
return FALSE;
|
||||
|
||||
$today = mktime(0,0,0,date('n'),date('j'),date('Y'));
|
||||
$days = (int)$this->account->renew;
|
||||
|
||||
if (! $this->ca->pk)
|
||||
throw HTTP_Exception::factory(400,'Unable to sign, missing Private Key for CA :ca',array(':ca'=>$this->ca->subject_cn()));
|
||||
|
||||
$res = openssl_csr_sign($this->csr,$this->ca->cert,$this->ca->pk,$days,array(
|
||||
'config'=>$ssl_conf,
|
||||
'x509_extensions'=>'client',
|
||||
'digest_alg'=>'sha1',
|
||||
),time());
|
||||
|
||||
if ($res AND openssl_x509_export($res,$cert)) {
|
||||
$this->cert = $cert;
|
||||
$this->save();
|
||||
|
||||
return TRUE;
|
||||
|
||||
} else {
|
||||
/*
|
||||
echo Debug::vars(array(
|
||||
'csr'=>$this->csr,
|
||||
'ca'=>$this->ca->cert,
|
||||
'caid'=>$this->ca->id,
|
||||
'days'=>$days,
|
||||
'ssl'=>$ssl_conf,
|
||||
'x509e'=>'client',
|
||||
// 'command'=>sprintf('openssl ca -days %s -cert /tmp/ssl_ca.crt -keyfile /tmp/ssl_ca.key -out /tmp/ssl.crt -in /tmp/ssl.csr -extensions %s -config %s',$days,'client',$ssl_conf),
|
||||
));
|
||||
|
||||
file_put_contents('/tmp/ssl.csr',$this->csr);
|
||||
file_put_contents('/tmp/ssl_ca.key',$this->ca->pk);
|
||||
file_put_contents('/tmp/ssl_ca.crt',$this->ca->cert);
|
||||
*/
|
||||
throw HTTP_Exception::factory(501,'Error Creating SSL Certificate :error',array(':error'=>openssl_error_string()));
|
||||
}
|
||||
}
|
||||
|
||||
protected function signed() {
|
||||
return $this->_cert_details ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
public function ski() {
|
||||
return $this->_extensions('subjectKeyIdentifier');
|
||||
}
|
||||
|
||||
public function issuer_cn() {
|
||||
return Arr::get($this->cert ? Arr::get($this->_cert_details,'issuer') : array(),'CN');
|
||||
}
|
||||
|
||||
public function subject_cn() {
|
||||
return Arr::get($this->cert ? Arr::get($this->_cert_details,'subject') : openssl_csr_get_subject($this->csr),'CN');
|
||||
}
|
||||
|
||||
public static function subject_cert($cert) {
|
||||
try {
|
||||
return self::_dn(Arr::get(openssl_x509_parse($cert),'subject'));
|
||||
} catch (exception $e) {
|
||||
return 'Invalid Cert';
|
||||
}
|
||||
}
|
||||
|
||||
public static function subject_csr($csr) {
|
||||
try {
|
||||
return self::_dn(openssl_csr_get_subject($csr));
|
||||
} catch (exception $e) {
|
||||
return 'Invalid CSR';
|
||||
}
|
||||
}
|
||||
|
||||
public function validCA($format=FALSE) {
|
||||
return StaticList_YesNo::get(($this->_cert_details AND $this->ssl_ca_id AND $this->aki_keyid()==$this->ca->ski()) ? $this->ca->validParent() : FALSE,$format);
|
||||
}
|
||||
|
||||
public function valid_from($format=FALSE) {
|
||||
$k = Arr::get($this->_cert_details,'validFrom_time_t');
|
||||
|
||||
if (! $k)
|
||||
return NULL;
|
||||
|
||||
return $format ? Site::Date($k) : $k;
|
||||
}
|
||||
|
||||
public function valid_to($format=FALSE) {
|
||||
$k = Arr::get($this->_cert_details,'validTo_time_t');
|
||||
|
||||
if (! $k)
|
||||
return NULL;
|
||||
|
||||
return $format ? Site::Date($k) : $k;
|
||||
}
|
||||
|
||||
// If we change the SSL certificate, we need to reload our SSL object
|
||||
public function values(array $values, array $expected = NULL) {
|
||||
parent::values($values,$expected);
|
||||
|
||||
if (array_key_exists('cert',$this->_changed))
|
||||
$this->_cert_details = openssl_x509_parse($this->cert);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function version() {
|
||||
return Arr::get($this->_cert_details,'version');
|
||||
}
|
||||
|
||||
public function list_ca() {
|
||||
$result = array();
|
||||
|
||||
if (! $this->validCA())
|
||||
return $result;
|
||||
|
||||
$x = $this;
|
||||
while (! is_null($x->ssl_ca_id) AND $x->id != $x->ssl_ca_id AND $x=$x->ca)
|
||||
array_push($result,$x);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all our CA Certs for this certificate
|
||||
*/
|
||||
public function list_ca_crts() {
|
||||
$result = array();
|
||||
|
||||
foreach ($this->list_ca() as $so)
|
||||
array_push($result,$so->cert);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
18
modules/ssl/messages/models/ssl.php
Normal file
18
modules/ssl/messages/models/ssl.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* SSL Certificate validation messages.
|
||||
*
|
||||
* @package SSL
|
||||
* @category Validation
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
|
||||
return array(
|
||||
'csr'=>array(
|
||||
'isCSR'=>'This is not a valid Certificate Sign Request',
|
||||
),
|
||||
);
|
||||
?>
|
18
modules/ssl/messages/user/ssl/add.php
Normal file
18
modules/ssl/messages/user/ssl/add.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* CSR validation messages.
|
||||
*
|
||||
* @package SSL
|
||||
* @category Validation
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
|
||||
return array(
|
||||
'csr_file'=>array(
|
||||
'Upload::type'=>'Incorrect upload type, it must be CSR',
|
||||
),
|
||||
);
|
||||
?>
|
@@ -69,6 +69,8 @@
|
||||
|
||||
<legend>Private Key Data</legend>
|
||||
<?php echo Form::textarea('pk',$o->pk,array('divclass'=>'col-md-12','placeholder'=>'Private Key','style'=>'font-family: monospace; font-size: 95%;','rows'=>Form::textarea_rows($o->pk))); ?>
|
||||
|
||||
<?php echo Form::input('name',$o->name,array('divclass'=>'col-md-6','label'=>'Name','placeholder'=>'Label')); ?>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="col-md-6">
|
||||
|
@@ -4,7 +4,8 @@
|
||||
<p>To use SSL with this application, you need to receive a certificate from this service.<p>
|
||||
<p>Please do the following:<p>
|
||||
<ol>
|
||||
<li>Paste the contents of your CSR file here:<br/>
|
||||
<li>Upload your CSR file here <?php echo Form::file('csr_file',array('class'=>'col-md-3','label'=>'CSR File')); ?>
|
||||
OR, paste the contents of your CSR file here:<br/>
|
||||
<?php echo Form::textarea('csr','',array('class'=>'col-md-6','label'=>'CSR','placeholder'=>'Certificate Sign Request','style'=>'font-family: monospace;','cols'=>61,'rows'=>15)); ?>
|
||||
</li>
|
||||
|
||||
@@ -16,5 +17,5 @@
|
||||
<div class="col-md-offset-1">
|
||||
<button type="submit" class="btn btn-primary">Save changes</button>
|
||||
<button type="button" class="btn btn-default">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -61,7 +61,7 @@
|
||||
'issuer_cn()'=>'Issuer',
|
||||
))
|
||||
->prepend(array(
|
||||
'id'=>array('url'=>URL::link('admin','ssl/edit/')),
|
||||
'id'=>array('url'=>URL::link('','ssl/download/')),
|
||||
)); ?>
|
||||
<?php endif ?>
|
||||
</fieldset>
|
||||
@@ -79,9 +79,4 @@
|
||||
echo Form::button('submit','Renew',array('class'=>'btn btn-primary'));
|
||||
endif
|
||||
?>
|
||||
|
||||
<!--
|
||||
<?php #echo Form::textarea('cert','',array('class'=>'col-md-6','label'=>'CSR','placeholder'=>'Certificate Sign Request','style'=>'font-family: monospace;','cols'=>61,'rows'=>15)); ?>
|
||||
<button type="submit" class="btn btn-primary">Save changes</button>
|
||||
-->
|
||||
</fieldset>
|
||||
|
Reference in New Issue
Block a user