From 783170e3725921bf1429703ce81ec99ebd48964d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Capil=C3=A9?= Date: Sun, 12 Apr 2015 16:32:57 -0300 Subject: [PATCH 01/17] Added client SSL certificate authentication as a CakePHP plugin --- app/Config/bootstrap.default.php | 6 + app/Config/config.default.php | 33 +++ app/Controller/AppController.php | 7 + .../Auth/CertificateAuthenticate.php | 262 ++++++++++++++++++ app/Plugin/CertAuth/README.md | 4 + 5 files changed, 312 insertions(+) create mode 100644 app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php create mode 100644 app/Plugin/CertAuth/README.md diff --git a/app/Config/bootstrap.default.php b/app/Config/bootstrap.default.php index 1c795864c..45280f5b1 100755 --- a/app/Config/bootstrap.default.php +++ b/app/Config/bootstrap.default.php @@ -108,6 +108,12 @@ CakePlugin::load('Assets'); // having Logable CakePlugin::load('SysLogLogable'); CakePlugin::load('UrlCache'); +/** + * Uncomment the following line to enable client SSL certificate authentication. + * It's also necessary to configure the plugin — for more information, please read app/Plugin/CertAuth/reame.md + */ +// CakePlugin::load('CertAuth'); + /** * You can attach event listeners to the request lifecyle as Dispatcher Filter . By Default CakePHP bundles two filters: * diff --git a/app/Config/config.default.php b/app/Config/config.default.php index c9f6a61f9..000a80806 100644 --- a/app/Config/config.default.php +++ b/app/Config/config.default.php @@ -6,6 +6,7 @@ $config = array ( 'level' => 'medium', 'salt' => 'Rooraenietu8Eeyo '', + //'auth'=>array('CertAuth.Certificate'), // additional authentication methods ), 'MISP' => array ( @@ -39,4 +40,36 @@ $config = array ( 'amount' => 5, 'expire' => 300, ), + // Uncomment the following to enable client SSL certificate authentication + /* + 'CertAuth' => + array( + 'register'=>true, + 'ca'=>'FIRST.Org', + 'caId'=>'org', + 'mapCa'=>array( + 'O'=>'org', + 'emailAddress'=>'email', + ), + 'map'=>array( + 'O'=>'org', + 'emailAddress'=>'email', + ), + 'userModel'=>'User', + 'userModelKey'=>'nids_sid', + 'enableSession' => true, + 'syncUser'=>true, + 'restApi'=>array( + 'url'=>'https://www.first.org/data/members?scope=full&limit=1', + 'headers'=>array(), + 'param'=>array('email'=>'email'), + 'map'=>array( + 'uid'=>'nids_sid', + 'team'=>'org', + 'email'=>'email', + 'pgp_public'=>'gpgkey', + ), + ), + ), + */ ); diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index b04b77d52..c0d126a5b 100755 --- a/app/Controller/AppController.php +++ b/app/Controller/AppController.php @@ -102,6 +102,13 @@ class AppController extends Controller { throw new ForbiddenException('The authentication key provided cannot be used for syncing.'); } } + } else if(!$this->Session->read('Auth.User')) { + // load authentication plugins from Configure::read('Security.auth') + $auth = Configure::read('Security.auth'); + if($auth) { + $this->Auth->authenticate = array_merge($auth, $this->Auth->authenticate); + $this->Auth->startup($this); + } } // user must accept terms // diff --git a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php new file mode 100644 index 000000000..13f740d99 --- /dev/null +++ b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php @@ -0,0 +1,262 @@ +self::$user[$k]); + } else { + $q = self::$user; + } + $User = ClassRegistry::init($cn); + $U = $User->find('first', array( + 'conditions' => $q, + 'recursive' => false + )); + if($U) { + if($sync) { + $write = array(); + foreach(self::$user as $k=>$v) { + if(array_key_exists($k, $U[$cn]) && trim($U[$cn][$k])!=trim($v)) { + $write[] = $k; + $U[$cn][$k] = trim($v); + } + unset($k, $v); + } + if($write && !$User->save($U[$cn], true, $write)) { + CakeLog::write('alert', 'Could not update model at database with RestAPI data.'); + } + unset($write); + } + self::$user = $U[$cn]; + } else if($sync) { + $User->create(); + if($User->save(self::$user, true, array_keys(self::$user))) { + $U = $User->read(); + self::$user = $U[$cn]; + } else { + CakeLog::write('alert', 'Could not insert model at database from RestAPI data.'); + } + } + unset($U, $User, $q, $k); + } + unset($cn); + } + } + + if(Configure::read('CertAuth.enableSession')) { + if(!CakeSession::read(AuthComponent::$sessionKey)) { + CakeSession::write(AuthComponent::$sessionKey, self::$user); + } + } else { + AuthComponent::$sessionKey = false; + } + return self::$user; + } + + // to enable stateless authentication + public function authenticate(CakeRequest $request, CakeResponse $response) + { + return self::getUser($request); + } + + /** + * Fetches user information from external REST API + * + * Valid options (should be configured under CertAuth.restApi): + * + * @param (optional) array $options API configuration + * url (string) Where to fetch information from + * headers (array) list of additional headers to be used, reserved for authentication tokens + * params (array) mapping of additional params to be included at the url, uses $user values + * map (array) mapping of the return values to be added to the self::$user + * @return array updated user object + */ + public function getRestUser($options=null, $user=null) + { + if(is_null($options)) { + $options = Configure::read('CertAuth.restApi'); + } + if(!is_null($user)) { + self::$user = $user; + } + + if(!isset($options['url'])) { + return null; + } + + // Create a stream + $req = array( + 'http'=>array( + 'method'=>'GET', + 'header'=>"Accept: application/json\r\n" + ), + ); + if(isset($options['headers'])) { + foreach($options['headers'] as $k=>$v) { + if(is_int($k)) { + $req['header'] .= "{$v}\r\n"; + } else { + $req['header'] .= "{$k}: {$v}\r\n"; + } + unset($k, $v); + } + } + + $url = $options['url']; + if(isset($options['param'])) { + foreach($options['param'] as $k=>$v) { + if(isset(self::$user[$v])) { + $url .= ((strpos($url, '?'))?('&'):('?')) + . $k . '=' . urlencode(self::$user[$v]); + } + unset($k, $v); + } + } + $ctx = stream_context_create($req); + $a = file_get_contents($url, false, $ctx); + if(!$a) return null; + + $A = json_decode($a, true); + if(!isset($A['data'][0])) return false; + if(isset($options['map'])) { + foreach($options['map'] as $k=>$v) { + if(isset($A['data'][0][$k])) { + self::$user[$v] = $A['data'][0][$k]; + } + unset($k, $v); + } + } + + return self::$user; + } + + +} \ No newline at end of file diff --git a/app/Plugin/CertAuth/README.md b/app/Plugin/CertAuth/README.md new file mode 100644 index 000000000..417c3ba92 --- /dev/null +++ b/app/Plugin/CertAuth/README.md @@ -0,0 +1,4 @@ +#Client SSL Certificate Authentication for CakePHP + +This plugin enables CakePHP applications to use client SSL certificates to stateless authenticate its users. It reads information from the client certificate and can synchronize data with a foreign REST API and the client User model. + From 10ecc9f9339faa49bcd120ba0d73f106b8321933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Capil=C3=A9?= Date: Sun, 12 Apr 2015 16:56:14 -0300 Subject: [PATCH 02/17] Added client SSL certificate authentication as a CakePHP plugin --- app/Config/config.default.php | 40 ++++++++++++++------------------- app/Plugin/CertAuth/README.md | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/app/Config/config.default.php b/app/Config/config.default.php index 000a80806..0816344d9 100644 --- a/app/Config/config.default.php +++ b/app/Config/config.default.php @@ -41,33 +41,27 @@ $config = array ( 'expire' => 300, ), // Uncomment the following to enable client SSL certificate authentication - /* 'CertAuth' => array( - 'register'=>true, - 'ca'=>'FIRST.Org', - 'caId'=>'org', - 'mapCa'=>array( - 'O'=>'org', + 'ca' => array( 'FIRST.Org' ), // allowed CAs + 'caId' => 'O', // which attribute will be used to verify the CA + 'userModel' => 'User', // name of the User class to check if user exists + 'userModelKey' => 'nids_sid', // User field that will be used for querying + 'map' => array( // maps client certificate attributes to User properties + 'O' => 'org', 'emailAddress'=>'email', ), - 'map'=>array( - 'O'=>'org', - 'emailAddress'=>'email', - ), - 'userModel'=>'User', - 'userModelKey'=>'nids_sid', - 'enableSession' => true, - 'syncUser'=>true, - 'restApi'=>array( - 'url'=>'https://www.first.org/data/members?scope=full&limit=1', - 'headers'=>array(), - 'param'=>array('email'=>'email'), - 'map'=>array( - 'uid'=>'nids_sid', - 'team'=>'org', - 'email'=>'email', - 'pgp_public'=>'gpgkey', + 'enableSession' => true, // if FALSE then disables session cookies + 'syncUser' => true, // should the User be synchronized with an external REST API + 'restApi' => array( // API parameters + 'url' => 'https://example.com/data/users', // URL to query + 'headers' => array(), // additional headers, used for authentication + 'param' => array( 'email' => 'email'), // query parameters to add to the URL, mapped to USer properties + 'map' => array( // maps REST result to the User properties + 'uid' => 'nids_sid', + 'team' => 'org', + 'email' => 'email', + 'pgp_public'=> 'gpgkey', ), ), ), diff --git a/app/Plugin/CertAuth/README.md b/app/Plugin/CertAuth/README.md index 417c3ba92..030486db9 100644 --- a/app/Plugin/CertAuth/README.md +++ b/app/Plugin/CertAuth/README.md @@ -2,3 +2,45 @@ This plugin enables CakePHP applications to use client SSL certificates to stateless authenticate its users. It reads information from the client certificate and can synchronize data with a foreign REST API and the client User model. +Basically it loads the `SSL_CLIENT_*` variables, parses and maps the certificate information to the user. So you first need a server that checks client certificates and forwards that information to the PHP `$_SERVER` environment. + +## Usage + +Enable the plugin at bootstrap.php: + +```php +CakePlugin::load('CertAuth'); +``` + +And configure it: + +```php +Configure::write('CertAuth', + array( + 'ca' => array( 'FIRST.Org' ), // allowed CAs + 'caId' => 'O', // which attribute will be used to verify the CA + 'userModel' => 'User', // name of the User class to check if user exists + 'userModelKey' => 'nids_sid', // User field that will be used for querying + 'map' => array( // maps client certificate attributes to User properties + 'O' => 'org', + 'emailAddress'=>'email', + ), + 'enableSession' => true, // if FALSE then disables session cookies + 'syncUser' => true, // should the User be synchronized with an external REST API + 'restApi' => array( // API parameters + 'url' => 'https://example.com/data/users', // URL to query + 'headers' => array(), // additional headers, used for authentication + 'param' => array( 'email' => 'email'), // query parameters to add to the URL, mapped to USer properties + 'map' => array( // maps REST result to the User properties + 'uid' => 'id', + 'name' => 'name', + 'company' => 'org', + 'email' => 'email', + ), + ), + ), +)); +``` + + + From 3224feb25a47be3e13358fa09ddf83362660db2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Capil=C3=A9?= Date: Wed, 15 Apr 2015 14:02:16 -0300 Subject: [PATCH 03/17] added user defaults to plugin --- app/Config/config.default.php | 4 ++++ .../Controller/Component/Auth/CertificateAuthenticate.php | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/app/Config/config.default.php b/app/Config/config.default.php index 0816344d9..3c7128be2 100644 --- a/app/Config/config.default.php +++ b/app/Config/config.default.php @@ -41,6 +41,7 @@ $config = array ( 'expire' => 300, ), // Uncomment the following to enable client SSL certificate authentication + /* 'CertAuth' => array( 'ca' => array( 'FIRST.Org' ), // allowed CAs @@ -53,6 +54,9 @@ $config = array ( ), 'enableSession' => true, // if FALSE then disables session cookies 'syncUser' => true, // should the User be synchronized with an external REST API + 'userDefaults'=> array( // default user attributes, only used when creating new users + 'role_id' => 4, + ), 'restApi' => array( // API parameters 'url' => 'https://example.com/data/users', // URL to query 'headers' => array(), // additional headers, used for authentication diff --git a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php index 13f740d99..ab834abef 100644 --- a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php +++ b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php @@ -158,6 +158,11 @@ class CertificateAuthenticate extends BaseAuthenticate self::$user = $U[$cn]; } else if($sync) { $User->create(); + $d = Configure::read('CertAuth.userDefaults'); + if($d && is_array($d)) { + self::$user += $d; + } + unset($d); if($User->save(self::$user, true, array_keys(self::$user))) { $U = $User->read(); self::$user = $U[$cn]; From d0c3b44e34d3a47d33b71212592640a94256d08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Capil=C3=A9?= Date: Sun, 12 Apr 2015 16:32:57 -0300 Subject: [PATCH 04/17] Added client SSL certificate authentication as a CakePHP plugin --- app/Config/bootstrap.default.php | 6 + app/Config/config.default.php | 33 +++ app/Controller/AppController.php | 7 + .../Auth/CertificateAuthenticate.php | 262 ++++++++++++++++++ app/Plugin/CertAuth/README.md | 4 + 5 files changed, 312 insertions(+) create mode 100644 app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php create mode 100644 app/Plugin/CertAuth/README.md diff --git a/app/Config/bootstrap.default.php b/app/Config/bootstrap.default.php index 1c795864c..45280f5b1 100755 --- a/app/Config/bootstrap.default.php +++ b/app/Config/bootstrap.default.php @@ -108,6 +108,12 @@ CakePlugin::load('Assets'); // having Logable CakePlugin::load('SysLogLogable'); CakePlugin::load('UrlCache'); +/** + * Uncomment the following line to enable client SSL certificate authentication. + * It's also necessary to configure the plugin — for more information, please read app/Plugin/CertAuth/reame.md + */ +// CakePlugin::load('CertAuth'); + /** * You can attach event listeners to the request lifecyle as Dispatcher Filter . By Default CakePHP bundles two filters: * diff --git a/app/Config/config.default.php b/app/Config/config.default.php index 457973c24..cc9c636d9 100644 --- a/app/Config/config.default.php +++ b/app/Config/config.default.php @@ -6,6 +6,7 @@ $config = array ( 'level' => 'medium', 'salt' => 'Rooraenietu8Eeyo '', + //'auth'=>array('CertAuth.Certificate'), // additional authentication methods ), 'MISP' => array ( @@ -48,4 +49,36 @@ $config = array ( 'amount' => 5, 'expire' => 300, ), + // Uncomment the following to enable client SSL certificate authentication + /* + 'CertAuth' => + array( + 'register'=>true, + 'ca'=>'FIRST.Org', + 'caId'=>'org', + 'mapCa'=>array( + 'O'=>'org', + 'emailAddress'=>'email', + ), + 'map'=>array( + 'O'=>'org', + 'emailAddress'=>'email', + ), + 'userModel'=>'User', + 'userModelKey'=>'nids_sid', + 'enableSession' => true, + 'syncUser'=>true, + 'restApi'=>array( + 'url'=>'https://www.first.org/data/members?scope=full&limit=1', + 'headers'=>array(), + 'param'=>array('email'=>'email'), + 'map'=>array( + 'uid'=>'nids_sid', + 'team'=>'org', + 'email'=>'email', + 'pgp_public'=>'gpgkey', + ), + ), + ), + */ ); diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index b04b77d52..c0d126a5b 100755 --- a/app/Controller/AppController.php +++ b/app/Controller/AppController.php @@ -102,6 +102,13 @@ class AppController extends Controller { throw new ForbiddenException('The authentication key provided cannot be used for syncing.'); } } + } else if(!$this->Session->read('Auth.User')) { + // load authentication plugins from Configure::read('Security.auth') + $auth = Configure::read('Security.auth'); + if($auth) { + $this->Auth->authenticate = array_merge($auth, $this->Auth->authenticate); + $this->Auth->startup($this); + } } // user must accept terms // diff --git a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php new file mode 100644 index 000000000..13f740d99 --- /dev/null +++ b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php @@ -0,0 +1,262 @@ +self::$user[$k]); + } else { + $q = self::$user; + } + $User = ClassRegistry::init($cn); + $U = $User->find('first', array( + 'conditions' => $q, + 'recursive' => false + )); + if($U) { + if($sync) { + $write = array(); + foreach(self::$user as $k=>$v) { + if(array_key_exists($k, $U[$cn]) && trim($U[$cn][$k])!=trim($v)) { + $write[] = $k; + $U[$cn][$k] = trim($v); + } + unset($k, $v); + } + if($write && !$User->save($U[$cn], true, $write)) { + CakeLog::write('alert', 'Could not update model at database with RestAPI data.'); + } + unset($write); + } + self::$user = $U[$cn]; + } else if($sync) { + $User->create(); + if($User->save(self::$user, true, array_keys(self::$user))) { + $U = $User->read(); + self::$user = $U[$cn]; + } else { + CakeLog::write('alert', 'Could not insert model at database from RestAPI data.'); + } + } + unset($U, $User, $q, $k); + } + unset($cn); + } + } + + if(Configure::read('CertAuth.enableSession')) { + if(!CakeSession::read(AuthComponent::$sessionKey)) { + CakeSession::write(AuthComponent::$sessionKey, self::$user); + } + } else { + AuthComponent::$sessionKey = false; + } + return self::$user; + } + + // to enable stateless authentication + public function authenticate(CakeRequest $request, CakeResponse $response) + { + return self::getUser($request); + } + + /** + * Fetches user information from external REST API + * + * Valid options (should be configured under CertAuth.restApi): + * + * @param (optional) array $options API configuration + * url (string) Where to fetch information from + * headers (array) list of additional headers to be used, reserved for authentication tokens + * params (array) mapping of additional params to be included at the url, uses $user values + * map (array) mapping of the return values to be added to the self::$user + * @return array updated user object + */ + public function getRestUser($options=null, $user=null) + { + if(is_null($options)) { + $options = Configure::read('CertAuth.restApi'); + } + if(!is_null($user)) { + self::$user = $user; + } + + if(!isset($options['url'])) { + return null; + } + + // Create a stream + $req = array( + 'http'=>array( + 'method'=>'GET', + 'header'=>"Accept: application/json\r\n" + ), + ); + if(isset($options['headers'])) { + foreach($options['headers'] as $k=>$v) { + if(is_int($k)) { + $req['header'] .= "{$v}\r\n"; + } else { + $req['header'] .= "{$k}: {$v}\r\n"; + } + unset($k, $v); + } + } + + $url = $options['url']; + if(isset($options['param'])) { + foreach($options['param'] as $k=>$v) { + if(isset(self::$user[$v])) { + $url .= ((strpos($url, '?'))?('&'):('?')) + . $k . '=' . urlencode(self::$user[$v]); + } + unset($k, $v); + } + } + $ctx = stream_context_create($req); + $a = file_get_contents($url, false, $ctx); + if(!$a) return null; + + $A = json_decode($a, true); + if(!isset($A['data'][0])) return false; + if(isset($options['map'])) { + foreach($options['map'] as $k=>$v) { + if(isset($A['data'][0][$k])) { + self::$user[$v] = $A['data'][0][$k]; + } + unset($k, $v); + } + } + + return self::$user; + } + + +} \ No newline at end of file diff --git a/app/Plugin/CertAuth/README.md b/app/Plugin/CertAuth/README.md new file mode 100644 index 000000000..417c3ba92 --- /dev/null +++ b/app/Plugin/CertAuth/README.md @@ -0,0 +1,4 @@ +#Client SSL Certificate Authentication for CakePHP + +This plugin enables CakePHP applications to use client SSL certificates to stateless authenticate its users. It reads information from the client certificate and can synchronize data with a foreign REST API and the client User model. + From 9179a2263f06386f19c294e150973663b3ce38c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Capil=C3=A9?= Date: Sun, 12 Apr 2015 16:56:14 -0300 Subject: [PATCH 05/17] Added client SSL certificate authentication as a CakePHP plugin --- app/Config/config.default.php | 40 ++++++++++++++------------------- app/Plugin/CertAuth/README.md | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/app/Config/config.default.php b/app/Config/config.default.php index cc9c636d9..c0f24dd32 100644 --- a/app/Config/config.default.php +++ b/app/Config/config.default.php @@ -50,33 +50,27 @@ $config = array ( 'expire' => 300, ), // Uncomment the following to enable client SSL certificate authentication - /* 'CertAuth' => array( - 'register'=>true, - 'ca'=>'FIRST.Org', - 'caId'=>'org', - 'mapCa'=>array( - 'O'=>'org', + 'ca' => array( 'FIRST.Org' ), // allowed CAs + 'caId' => 'O', // which attribute will be used to verify the CA + 'userModel' => 'User', // name of the User class to check if user exists + 'userModelKey' => 'nids_sid', // User field that will be used for querying + 'map' => array( // maps client certificate attributes to User properties + 'O' => 'org', 'emailAddress'=>'email', ), - 'map'=>array( - 'O'=>'org', - 'emailAddress'=>'email', - ), - 'userModel'=>'User', - 'userModelKey'=>'nids_sid', - 'enableSession' => true, - 'syncUser'=>true, - 'restApi'=>array( - 'url'=>'https://www.first.org/data/members?scope=full&limit=1', - 'headers'=>array(), - 'param'=>array('email'=>'email'), - 'map'=>array( - 'uid'=>'nids_sid', - 'team'=>'org', - 'email'=>'email', - 'pgp_public'=>'gpgkey', + 'enableSession' => true, // if FALSE then disables session cookies + 'syncUser' => true, // should the User be synchronized with an external REST API + 'restApi' => array( // API parameters + 'url' => 'https://example.com/data/users', // URL to query + 'headers' => array(), // additional headers, used for authentication + 'param' => array( 'email' => 'email'), // query parameters to add to the URL, mapped to USer properties + 'map' => array( // maps REST result to the User properties + 'uid' => 'nids_sid', + 'team' => 'org', + 'email' => 'email', + 'pgp_public'=> 'gpgkey', ), ), ), diff --git a/app/Plugin/CertAuth/README.md b/app/Plugin/CertAuth/README.md index 417c3ba92..030486db9 100644 --- a/app/Plugin/CertAuth/README.md +++ b/app/Plugin/CertAuth/README.md @@ -2,3 +2,45 @@ This plugin enables CakePHP applications to use client SSL certificates to stateless authenticate its users. It reads information from the client certificate and can synchronize data with a foreign REST API and the client User model. +Basically it loads the `SSL_CLIENT_*` variables, parses and maps the certificate information to the user. So you first need a server that checks client certificates and forwards that information to the PHP `$_SERVER` environment. + +## Usage + +Enable the plugin at bootstrap.php: + +```php +CakePlugin::load('CertAuth'); +``` + +And configure it: + +```php +Configure::write('CertAuth', + array( + 'ca' => array( 'FIRST.Org' ), // allowed CAs + 'caId' => 'O', // which attribute will be used to verify the CA + 'userModel' => 'User', // name of the User class to check if user exists + 'userModelKey' => 'nids_sid', // User field that will be used for querying + 'map' => array( // maps client certificate attributes to User properties + 'O' => 'org', + 'emailAddress'=>'email', + ), + 'enableSession' => true, // if FALSE then disables session cookies + 'syncUser' => true, // should the User be synchronized with an external REST API + 'restApi' => array( // API parameters + 'url' => 'https://example.com/data/users', // URL to query + 'headers' => array(), // additional headers, used for authentication + 'param' => array( 'email' => 'email'), // query parameters to add to the URL, mapped to USer properties + 'map' => array( // maps REST result to the User properties + 'uid' => 'id', + 'name' => 'name', + 'company' => 'org', + 'email' => 'email', + ), + ), + ), +)); +``` + + + From 6de2541c9a71533858bf1f4fff05bc17ce317809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Capil=C3=A9?= Date: Wed, 15 Apr 2015 14:02:16 -0300 Subject: [PATCH 06/17] added user defaults to plugin --- app/Config/config.default.php | 4 ++++ .../Controller/Component/Auth/CertificateAuthenticate.php | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/app/Config/config.default.php b/app/Config/config.default.php index c0f24dd32..159020c04 100644 --- a/app/Config/config.default.php +++ b/app/Config/config.default.php @@ -50,6 +50,7 @@ $config = array ( 'expire' => 300, ), // Uncomment the following to enable client SSL certificate authentication + /* 'CertAuth' => array( 'ca' => array( 'FIRST.Org' ), // allowed CAs @@ -62,6 +63,9 @@ $config = array ( ), 'enableSession' => true, // if FALSE then disables session cookies 'syncUser' => true, // should the User be synchronized with an external REST API + 'userDefaults'=> array( // default user attributes, only used when creating new users + 'role_id' => 4, + ), 'restApi' => array( // API parameters 'url' => 'https://example.com/data/users', // URL to query 'headers' => array(), // additional headers, used for authentication diff --git a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php index 13f740d99..ab834abef 100644 --- a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php +++ b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php @@ -158,6 +158,11 @@ class CertificateAuthenticate extends BaseAuthenticate self::$user = $U[$cn]; } else if($sync) { $User->create(); + $d = Configure::read('CertAuth.userDefaults'); + if($d && is_array($d)) { + self::$user += $d; + } + unset($d); if($User->save(self::$user, true, array_keys(self::$user))) { $U = $User->read(); self::$user = $U[$cn]; From d2eaccec31bd13c9062407cee87b4f8662a8cd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Capil=C3=A9?= Date: Tue, 28 Apr 2015 11:25:13 -0300 Subject: [PATCH 07/17] removed session handling from plugin and moved to AppController --- app/Config/config.default.php | 1 - app/Controller/AppController.php | 21 +++++++++++++++---- .../Auth/CertificateAuthenticate.php | 20 +++++++++++------- app/Plugin/CertAuth/README.md | 1 - 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/app/Config/config.default.php b/app/Config/config.default.php index 159020c04..84275a6e4 100644 --- a/app/Config/config.default.php +++ b/app/Config/config.default.php @@ -61,7 +61,6 @@ $config = array ( 'O' => 'org', 'emailAddress'=>'email', ), - 'enableSession' => true, // if FALSE then disables session cookies 'syncUser' => true, // should the User be synchronized with an external REST API 'userDefaults'=> array( // default user attributes, only used when creating new users 'role_id' => 4, diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index c0d126a5b..13d36789f 100755 --- a/app/Controller/AppController.php +++ b/app/Controller/AppController.php @@ -92,6 +92,7 @@ class AppController extends Controller { if (!empty($_SERVER['HTTP_AUTHORIZATION'])) { $user = $this->checkAuthUser($_SERVER['HTTP_AUTHORIZATION']); if ($user) { + unset($user['gpgkey']); // User found in the db, add the user info to the session $this->Session->renew(); $this->Session->write(AuthComponent::$sessionKey, $user['User']); @@ -101,21 +102,33 @@ class AppController extends Controller { $this->Session->destroy(); throw new ForbiddenException('The authentication key provided cannot be used for syncing.'); } + unset($user); } - } else if(!$this->Session->read('Auth.User')) { + } else if(!$this->Session->read(AuthComponent::$sessionKey)) { // load authentication plugins from Configure::read('Security.auth') $auth = Configure::read('Security.auth'); if($auth) { $this->Auth->authenticate = array_merge($auth, $this->Auth->authenticate); - $this->Auth->startup($this); + if($this->Auth->startup($this)) { + $user = $this->Auth->user(); + if ($user) { + unset($user['gpgkey']); + // User found in the db, add the user info to the session + $this->Session->renew(); + $this->Session->write(AuthComponent::$sessionKey, $user); + } + unset($user); + } } + unset($auth); } + // user must accept terms // - if ($this->Session->check('Auth.User') && !$this->Auth->user('termsaccepted') && (!in_array($this->request->here, array('/users/terms', '/users/logout', '/users/login')))) { + if ($this->Session->check(AuthComponent::$sessionKey) && !$this->Auth->user('termsaccepted') && (!in_array($this->request->here, array('/users/terms', '/users/logout', '/users/login')))) { $this->redirect(array('controller' => 'users', 'action' => 'terms', 'admin' => false)); } - if ($this->Session->check('Auth.User') && $this->Auth->user('change_pw') && (!in_array($this->request->here, array('/users/terms', '/users/change_pw', '/users/logout', '/users/login')))) { + if ($this->Session->check(AuthComponent::$sessionKey) && $this->Auth->user('change_pw') && (!in_array($this->request->here, array('/users/terms', '/users/change_pw', '/users/logout', '/users/login')))) { $this->redirect(array('controller' => 'users', 'action' => 'change_pw', 'admin' => false)); } diff --git a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php index ab834abef..e638e5756 100644 --- a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php +++ b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php @@ -176,13 +176,6 @@ class CertificateAuthenticate extends BaseAuthenticate } } - if(Configure::read('CertAuth.enableSession')) { - if(!CakeSession::read(AuthComponent::$sessionKey)) { - CakeSession::write(AuthComponent::$sessionKey, self::$user); - } - } else { - AuthComponent::$sessionKey = false; - } return self::$user; } @@ -263,5 +256,18 @@ class CertificateAuthenticate extends BaseAuthenticate return self::$user; } + protected static $instance; + + public static function ca() + { + if(is_null(self::$ca)) new CertificateAuthenticate(); + return self::$ca; + } + + public static function client() + { + if(is_null(self::$client)) new CertificateAuthenticate(); + return self::$client; + } } \ No newline at end of file diff --git a/app/Plugin/CertAuth/README.md b/app/Plugin/CertAuth/README.md index 030486db9..065668144 100644 --- a/app/Plugin/CertAuth/README.md +++ b/app/Plugin/CertAuth/README.md @@ -25,7 +25,6 @@ Configure::write('CertAuth', 'O' => 'org', 'emailAddress'=>'email', ), - 'enableSession' => true, // if FALSE then disables session cookies 'syncUser' => true, // should the User be synchronized with an external REST API 'restApi' => array( // API parameters 'url' => 'https://example.com/data/users', // URL to query From 3055d153f86083b76132566354f6a6f464f9b69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilherme=20Capil=C3=A9?= Date: Tue, 28 Apr 2015 11:32:20 -0300 Subject: [PATCH 08/17] minor typo in the unset -- should be ['User']['gpgkey'] --- app/Controller/AppController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index 13d36789f..f917c02bb 100755 --- a/app/Controller/AppController.php +++ b/app/Controller/AppController.php @@ -92,7 +92,7 @@ class AppController extends Controller { if (!empty($_SERVER['HTTP_AUTHORIZATION'])) { $user = $this->checkAuthUser($_SERVER['HTTP_AUTHORIZATION']); if ($user) { - unset($user['gpgkey']); + unset($user['User']['gpgkey']); // User found in the db, add the user info to the session $this->Session->renew(); $this->Session->write(AuthComponent::$sessionKey, $user['User']); From 76811250a170322eb51cb64ca3e70d6ff7993de0 Mon Sep 17 00:00:00 2001 From: remg427 Date: Tue, 28 Apr 2015 22:10:08 +0200 Subject: [PATCH 09/17] Update UPDATE.txt app missing in path for cakephp --- INSTALL/UPDATE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL/UPDATE.txt b/INSTALL/UPDATE.txt index 5965b23f9..cdc1933db 100644 --- a/INSTALL/UPDATE.txt +++ b/INSTALL/UPDATE.txt @@ -7,7 +7,7 @@ git pull # 2. Update CakePHP to the latest 2.6 code -cd /var/www/MISP/Lib/cakephp +cd /var/www/MISP/app/Lib/cakephp git fetch origin git checkout 2.6 From 97c1dc95f610fa6f86cd05554e287f16c1c210ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Moln=C3=A1r?= Date: Mon, 11 May 2015 11:09:04 +0200 Subject: [PATCH 10/17] Note salt key length requirement to INSTALL.md --- INSTALL/INSTALL.ubuntu1404.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/INSTALL/INSTALL.ubuntu1404.txt b/INSTALL/INSTALL.ubuntu1404.txt index 4e2e0d61b..62ffd2b76 100644 --- a/INSTALL/INSTALL.ubuntu1404.txt +++ b/INSTALL/INSTALL.ubuntu1404.txt @@ -151,6 +151,7 @@ cp -a config.default.php config.php # require_once dirname(__DIR__) . '/Vendor/autoload.php'; # Important! Change the salt key in /var/www/MISP/app/Config/config.php +# The salt key must be a 32 byte long string. # The admin user account will be generated on the first login, make sure that the salt is changed before you create that user # If you forget to do this step, and you are still dealing with a fresh installation, just alter the salt, # delete the user from mysql and log in again using the default admin credentials (admin@admin.test / admin) From 62f1e516ce8cd9a74daebc2f4dde3e097e90b566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Moln=C3=A1r?= Date: Mon, 11 May 2015 12:56:51 +0200 Subject: [PATCH 11/17] Calrify salt length in INSTALL.md --- INSTALL/INSTALL.ubuntu1404.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL/INSTALL.ubuntu1404.txt b/INSTALL/INSTALL.ubuntu1404.txt index 62ffd2b76..7b88eccae 100644 --- a/INSTALL/INSTALL.ubuntu1404.txt +++ b/INSTALL/INSTALL.ubuntu1404.txt @@ -151,7 +151,7 @@ cp -a config.default.php config.php # require_once dirname(__DIR__) . '/Vendor/autoload.php'; # Important! Change the salt key in /var/www/MISP/app/Config/config.php -# The salt key must be a 32 byte long string. +# The salt key must be an at least 32 byte long string. # The admin user account will be generated on the first login, make sure that the salt is changed before you create that user # If you forget to do this step, and you are still dealing with a fresh installation, just alter the salt, # delete the user from mysql and log in again using the default admin credentials (admin@admin.test / admin) From 91245f770505775026ec9f6f605bbd1c5f455b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Andr=C3=A9?= Date: Tue, 12 May 2015 15:09:33 +0200 Subject: [PATCH 12/17] Removed the RSA key recommendation from INSTALL.centos6.txt --- INSTALL/INSTALL.centos6.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/INSTALL/INSTALL.centos6.txt b/INSTALL/INSTALL.centos6.txt index 8257f3abe..5deaa08d9 100644 --- a/INSTALL/INSTALL.centos6.txt +++ b/INSTALL/INSTALL.centos6.txt @@ -191,7 +191,6 @@ chmod 700 /var/www/MISP/.gnupg # can't connect to `/var/www/MISP/.gnupg/S.gpg-agent': No such file or directory gpg --homedir /var/www/MISP/.gnupg --gen-key chown -R apache:apache /var/www/MISP/.gnupg -# Recommended key type: RSA # The email address should match the one set in the config.php configuration file # Make sure that you use the same settings in the MISP Server Settings tool (Described on line 212) From 40a3fe5f8bd3026b9b685dc852dae35fb934f79e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Andr=C3=A9?= Date: Tue, 12 May 2015 15:10:59 +0200 Subject: [PATCH 13/17] Removed the RSA key recommendation from INSTALL.centos7.txt --- INSTALL/INSTALL.centos7.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL/INSTALL.centos7.txt b/INSTALL/INSTALL.centos7.txt index faae937ba..37bd3910f 100644 --- a/INSTALL/INSTALL.centos7.txt +++ b/INSTALL/INSTALL.centos7.txt @@ -205,7 +205,7 @@ chmod 700 /var/www/MISP/.gnupg # can't connect to `/var/www/MISP/.gnupg/S.gpg-agent': No such file or directory gpg --homedir /var/www/MISP/.gnupg --gen-key chown -R apache:apache /var/www/MISP/.gnupg -# Recommended key type: RSA + # The email address should match the one set in the config.php configuration file # Make sure that you use the same settings in the MISP Server Settings tool (Described on line 226) From 7d3f53e5ace7a93873663caa7c38a9eccb657dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Andr=C3=A9?= Date: Tue, 12 May 2015 15:11:43 +0200 Subject: [PATCH 14/17] Removed the RSA key recommendation from INSTALL.ubuntu1404.txt --- INSTALL/INSTALL.ubuntu1404.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL/INSTALL.ubuntu1404.txt b/INSTALL/INSTALL.ubuntu1404.txt index 4e2e0d61b..3193b77b2 100644 --- a/INSTALL/INSTALL.ubuntu1404.txt +++ b/INSTALL/INSTALL.ubuntu1404.txt @@ -164,7 +164,7 @@ mkdir /var/www/MISP/.gnupg chown www-data:www-data /var/www/MISP/.gnupg chmod 700 /var/www/MISP/.gnupg sudo -u www-data gpg --homedir /var/www/MISP/.gnupg --gen-key -# Recommended key type: RSA + # The email address should match the one set in the config.php configuration file # Make sure that you use the same settings in the MISP Server Settings tool (Described on line 184) From 35134a7f2e8ce8b59f0ffdf9243e26bdf86b569b Mon Sep 17 00:00:00 2001 From: iglocska Date: Wed, 13 May 2015 16:12:06 +0200 Subject: [PATCH 15/17] Implemented correct from / to api parameter checks - based on stevengoossensB's pull request --- VERSION.json | 2 +- app/Controller/AttributesController.php | 16 +++++++++------- app/Controller/EventsController.php | 16 ++++++++++++++++ app/Model/Event.php | 8 ++++++++ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/VERSION.json b/VERSION.json index b3ea3fe9c..0e2afcbbe 100644 --- a/VERSION.json +++ b/VERSION.json @@ -1 +1 @@ -{"major":2, "minor":3, "hotfix":63} +{"major":2, "minor":3, "hotfix":64} diff --git a/app/Controller/AttributesController.php b/app/Controller/AttributesController.php index 4b45abdaa..44983df30 100755 --- a/app/Controller/AttributesController.php +++ b/app/Controller/AttributesController.php @@ -1495,11 +1495,6 @@ class AttributesController extends AppController { // ! - you can negate a search term. For example: google.com&&!mail would search for all attributes with value google.com but not ones that include mail. www.google.com would get returned, mail.google.com wouldn't. public function restSearch($key='download', $value=false, $type=false, $category=false, $org=false, $tags=false, $from=false, $to=false) { if ($tags) $tags = str_replace(';', ':', $tags); - if ($tags === 'null') $tags = null; - if ($value === 'null') $value = null; - if ($type === 'null') $type = null; - if ($category === 'null') $category = null; - if ($org === 'null') $org = null; if ($key!=null && $key!='download') { $user = $this->checkAuthUser($key); } else { @@ -1530,6 +1525,13 @@ class AttributesController extends AppController { else ${$p} = null; } } + $simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to'); + foreach ($simpleFalse as $sF) { + if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false; + } + + if ($from) $from = $this->Attribute->Event->dateFieldCheck($from); + if ($to) $from = $this->Attribute->Event->dateFieldCheck($to); if (!isset($this->request->params['ext']) || $this->request->params['ext'] !== 'json') { $this->response->type('xml'); // set the content type $this->layout = 'xml/default'; @@ -1768,8 +1770,8 @@ class AttributesController extends AppController { if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false; } if ($type === 'null' || $type === '0' || $type === 'false') $type = 'all'; - if ($from && !preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $from)) $from = false; - if ($to && !preg_match('/^[0-9]{4}-[l0-9]{2}-[0-9]{2}$/', $from)) $from = false; + if ($from) $from = $this->Attribute->Event->dateFieldCheck($from); + if ($to) $from = $this->Attribute->Event->dateFieldCheck($to); if ($key != 'download') { // check if the key is valid -> search for users based on key $user = $this->checkAuthUser($key); diff --git a/app/Controller/EventsController.php b/app/Controller/EventsController.php index 2e205065c..cdc4df007 100755 --- a/app/Controller/EventsController.php +++ b/app/Controller/EventsController.php @@ -1725,6 +1725,8 @@ class EventsController extends AppController { foreach ($simpleFalse as $sF) { if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false; } + if ($from) $from = $this->Event->dateFieldCheck($from); + if ($to) $from = $this->Event->dateFieldCheck($to); if ($tags) $tags = str_replace(';', ':', $tags); $eventIdArray = array(); @@ -1802,6 +1804,9 @@ class EventsController extends AppController { foreach ($simpleFalse as $sF) { if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false; } + + if ($from) $from = $this->Event->dateFieldCheck($from); + if ($to) $from = $this->Event->dateFieldCheck($to); if ($tags) $tags = str_replace(';', ':', $tags); // backwards compatibility, swap key and format if ($format != 'snort' && $format != 'suricata') { @@ -1837,6 +1842,9 @@ class EventsController extends AppController { foreach ($simpleFalse as $sF) { if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false; } + + if ($from) $from = $this->Event->dateFieldCheck($from); + if ($to) $from = $this->Event->dateFieldCheck($to); if ($tags) $tags = str_replace(';', ':', $tags); $this->response->type('txt'); // set the content type $this->header('Content-Disposition: download; filename="misp.' . $type . '.rules"'); @@ -1869,6 +1877,9 @@ class EventsController extends AppController { foreach ($simpleFalse as $sF) { if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false; } + + if ($from) $from = $this->Event->dateFieldCheck($from); + if ($to) $from = $this->Event->dateFieldCheck($to); if ($tags) $tags = str_replace(';', ':', $tags); $list = array(); if ($key != 'download') { @@ -2399,6 +2410,9 @@ class EventsController extends AppController { foreach ($simpleFalse as $sF) { if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false; } + + if ($from) $from = $this->Event->dateFieldCheck($from); + if ($to) $from = $this->Event->dateFieldCheck($to); if ($tags) $tags = str_replace(';', ':', $tags); if ($searchall === 'true') $searchall = "1"; @@ -2974,6 +2988,8 @@ class EventsController extends AppController { foreach ($simpleFalse as $sF) { if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false; } + if ($from) $from = $this->Event->dateFieldCheck($from); + if ($to) $from = $this->Event->dateFieldCheck($to); // set null if a null string is passed $numeric = false; diff --git a/app/Model/Event.php b/app/Model/Event.php index ba2c4b197..32b0c78d7 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -1916,4 +1916,12 @@ class Event extends AppModel { } return $fn; } + + // expects a date string in the DD-MM-YYYY format + // returns the passed string or false if the format is invalid + // based on the fix provided by stevengoosensB + public function dateFieldCheck($date) { + // regex check for from / to field by stevengoossensB + return (preg_match('/^[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])$/', $date)) ? $date : false; + } } From 0851f44764881e9a1501c3b7513750c3f0f29833 Mon Sep 17 00:00:00 2001 From: iglocska Date: Wed, 13 May 2015 17:01:56 +0200 Subject: [PATCH 16/17] PGP key lookup for lazy MISP instance admins, fixes #492 - Added a button for the add user / edit user views that fetches the entered e-mail addresses pgp key from pgp.mit.edu --- app/View/Users/admin_add.ctp | 3 +++ app/View/Users/admin_edit.ctp | 3 +++ app/webroot/js/ajaxification.js | 15 +++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/app/View/Users/admin_add.ctp b/app/View/Users/admin_add.ctp index 5d421c4b5..5c9531449 100644 --- a/app/View/Users/admin_add.ctp +++ b/app/View/Users/admin_add.ctp @@ -13,6 +13,9 @@ echo $this->Form->input('authkey', array('value' => $authkey, 'readonly' => 'readonly')); echo $this->Form->input('nids_sid'); echo $this->Form->input('gpgkey', array('label' => 'GPG key', 'div' => 'clear', 'class' => 'input-xxlarge')); + ?> +
Fetch GPG key
+ Form->input('autoalert', array('label' => 'Receive alerts when events are published')); echo $this->Form->input('contactalert', array('label' => 'Receive alerts from "contact reporter" requests')); diff --git a/app/View/Users/admin_edit.ctp b/app/View/Users/admin_edit.ctp index 85703d9d7..42101f08d 100755 --- a/app/View/Users/admin_edit.ctp +++ b/app/View/Users/admin_edit.ctp @@ -18,6 +18,9 @@ 'class' => 'datepicker', )); echo $this->Form->input('gpgkey', array('label' => 'GPG key', 'div' => 'clear', 'class' => 'input-xxlarge')); + ?> +
Fetch GPG key
+ Form->input('termsaccepted', array('label' => 'Terms accepted')); echo $this->Form->input('change_pw', array('type' => 'checkbox', 'label' => 'Change Password')); echo $this->Form->input('autoalert', array('label' => 'Receive alerts when events are published')); diff --git a/app/webroot/js/ajaxification.js b/app/webroot/js/ajaxification.js index 57dac8682..6aaed501d 100644 --- a/app/webroot/js/ajaxification.js +++ b/app/webroot/js/ajaxification.js @@ -1350,3 +1350,18 @@ function freetextImportResultsSubmit(id, count) { }, }); } + +function lookupPGPKey(emailFieldName) { + $.ajax({ + type: "get", + url: "https://pgp.mit.edu/pks/lookup?op=get&search=" + $('#' + emailFieldName).val(), + success: function (data) { + var result = $("
").html(data)[0].getElementsByTagName("pre")[0]['innerText']; + $("#UserGpgkey").val(result); + showMessage('success', "Key found!"); + }, + error: function (data, textStatus, errorThrown) { + showMessage('fail', textStatus + ": " + errorThrown); + } + }); +} From 962a21e3c60d0beb30830f1b49982b6f87cc8d91 Mon Sep 17 00:00:00 2001 From: iglocska Date: Wed, 13 May 2015 17:04:09 +0200 Subject: [PATCH 17/17] Left off a file --- app/View/Users/edit.ctp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/View/Users/edit.ctp b/app/View/Users/edit.ctp index b03204a49..fec270cd6 100755 --- a/app/View/Users/edit.ctp +++ b/app/View/Users/edit.ctp @@ -12,6 +12,9 @@ else echo $this->Form->input('role_id', array('disabled' => 'disabled')); // TODO ACL, check, My Profile not edit role_id. echo $this->Form->input('nids_sid'); echo $this->Form->input('gpgkey', array('label' => 'GPG key', 'div' => 'clear', 'class' => 'input-xxlarge')); + ?> +
Fetch GPG key
+ Form->input('autoalert', array('label' => 'Receive alerts when events are published')); echo $this->Form->input('contactalert', array('label' => 'Receive alerts from "contact reporter" requests')); ?>