From 0ca5b7a79fb0216d9ead8c288c8962dbd9d58d12 Mon Sep 17 00:00:00 2001 From: Jonathan Labreuille Date: Wed, 19 Oct 2016 14:37:18 +0200 Subject: [PATCH] API Security - added APIAccess class to define access levels of API Endpoints (permissions) - use "mailpoet_token" for all nonce (just as before) - merged setupPublic/setupAdmin methods in API in order to avoid duplication - check permission if access level is not all - fixed ABSPATH check in some classes --- lib/API/API.php | 48 +++++++++++++++++++++---------- lib/API/Access.php | 12 ++++++++ lib/API/Endpoint.php | 2 ++ lib/API/Endpoints/Subscribers.php | 6 ++++ lib/Cron/Daemon.php | 2 ++ lib/Cron/Workers/Scheduler.php | 2 ++ lib/Form/Widget.php | 2 +- lib/Mailer/Mailer.php | 2 ++ 8 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 lib/API/Access.php diff --git a/lib/API/API.php b/lib/API/API.php index 80b043b60d..8142efefb8 100644 --- a/lib/API/API.php +++ b/lib/API/API.php @@ -13,26 +13,25 @@ class API { private $_data = array(); function init() { - // Admin API (Ajax only) + // Admin Security token + add_action( + 'admin_head', + array($this, 'setToken') + ); + + // ajax (logged in users) add_action( 'wp_ajax_mailpoet', - array($this, 'setupAdmin') + array($this, 'setupAjax') ); - - // Public API (Ajax) + // ajax (logged out users) add_action( 'wp_ajax_nopriv_mailpoet', - array($this, 'setupPublic') + array($this, 'setupAjax') ); } - function setupAdmin() { - $this->getRequestData(); - $this->checkPermissions(); - $this->processRoute(); - } - - function setupPublic() { + function setupAjax() { $this->getRequestData(); $this->checkToken(); $this->processRoute(); @@ -88,6 +87,18 @@ class API { function processRoute() { try { $endpoint = new $this->_endpoint_class(); + + // check the accessibility of the requested endpoint's action + // by default, an endpoint's action is considered "private" + $permissions = $endpoint->permissions; + if( + array_key_exists($this->_method, $permissions) === false + || + $permissions[$this->_method] !== Access::ALL + ) { + $this->checkPermissions(); + } + $response = $endpoint->{$this->_method}($this->_data); $response->send(); } catch(\Exception $e) { @@ -117,9 +128,7 @@ class API { } function checkToken() { - $action = $this->_endpoint.'_'.$this->_method; - - $is_valid_token = wp_verify_nonce($this->_token, $action); + $is_valid_token = wp_verify_nonce($this->_token, 'mailpoet_token'); if($is_valid_token === false) { $error_response = new ErrorResponse( @@ -132,4 +141,13 @@ class API { $error_response->send(); } } + + function setToken() { + $global = ''; + echo $global; + } } \ No newline at end of file diff --git a/lib/API/Access.php b/lib/API/Access.php new file mode 100644 index 0000000000..3817bb1c16 --- /dev/null +++ b/lib/API/Access.php @@ -0,0 +1,12 @@ + APIAccess::ALL + ); + function get($data = array()) { $id = (isset($data['id']) ? (int)$data['id'] : false); $subscriber = Subscriber::findOne($id); diff --git a/lib/Cron/Daemon.php b/lib/Cron/Daemon.php index fa1b11e1a0..0ebbbe1765 100644 --- a/lib/Cron/Daemon.php +++ b/lib/Cron/Daemon.php @@ -6,6 +6,8 @@ use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker; if(!defined('ABSPATH')) exit; require_once(ABSPATH . 'wp-includes/pluggable.php'); +require_once(ABSPATH . 'wp-includes/pluggable.php'); + class Daemon { public $daemon; public $request_data; diff --git a/lib/Cron/Workers/Scheduler.php b/lib/Cron/Workers/Scheduler.php index bb84a124b8..a895f36497 100644 --- a/lib/Cron/Workers/Scheduler.php +++ b/lib/Cron/Workers/Scheduler.php @@ -13,6 +13,8 @@ use MailPoet\Newsletter\Scheduler\Scheduler as NewsletterScheduler; if(!defined('ABSPATH')) exit; require_once(ABSPATH . 'wp-includes/pluggable.php'); +require_once(ABSPATH . 'wp-includes/pluggable.php'); + class Scheduler { public $timer; const UNCONFIRMED_SUBSCRIBER_RESCHEDULE_TIMEOUT = 5; diff --git a/lib/Form/Widget.php b/lib/Form/Widget.php index c4d61755b7..ab06584387 100644 --- a/lib/Form/Widget.php +++ b/lib/Form/Widget.php @@ -161,7 +161,7 @@ class Widget extends \WP_Widget { ); // generate security token - $data['token'] = Security::generateToken('subscribers_subscribe'); + $data['token'] = Security::generateToken(); // render form $renderer = new Renderer(); diff --git a/lib/Mailer/Mailer.php b/lib/Mailer/Mailer.php index e3fa43b44d..1bd9175ad2 100644 --- a/lib/Mailer/Mailer.php +++ b/lib/Mailer/Mailer.php @@ -5,6 +5,8 @@ use MailPoet\Models\Setting; if(!defined('ABSPATH')) exit; require_once(ABSPATH . 'wp-includes/pluggable.php'); +require_once(ABSPATH . 'wp-includes/pluggable.php'); + class Mailer { public $mailer_config; public $sender;