From 2b934aaade0a88ae0d94010f7e57dabbd1ba0f0a Mon Sep 17 00:00:00 2001 From: Raphael Jackstadt Date: Sun, 7 Dec 2014 05:12:00 +0100 Subject: [PATCH 1/2] reCAPTCHA integration --- application/config/aauth.php | 5 + application/helpers/recaptchalib_helper.php | 141 ++++++++++++++++ application/language/english/aauth_lang.php | 1 + application/libraries/Aauth.php | 174 ++++++++++++++------ 4 files changed, 275 insertions(+), 46 deletions(-) create mode 100644 application/helpers/recaptchalib_helper.php diff --git a/application/config/aauth.php b/application/config/aauth.php index 9bbdbff8..12c88edc 100644 --- a/application/config/aauth.php +++ b/application/config/aauth.php @@ -55,6 +55,11 @@ //if it is true, the user will be banned temporary when he exceed the login 'try' 'ddos_protection' => true, + 'recaptcha_active' => false, + 'recaptcha_login_attempts' => 4, + 'recaptcha_siteKey' => '', + 'recaptcha_secret' => '', + // login attempts time interval // default 20 times in one hour 'max_login_attempt' => 10, diff --git a/application/helpers/recaptchalib_helper.php b/application/helpers/recaptchalib_helper.php new file mode 100644 index 00000000..60efba52 --- /dev/null +++ b/application/helpers/recaptchalib_helper.php @@ -0,0 +1,141 @@ +" . self::$_signupUrl . ""); + } + $this->_secret=$secret; + } + + /** + * Encodes the given data into a query string format. + * + * @param array $data array of string elements to be encoded. + * + * @return string - encoded request. + */ + private function _encodeQS($data) + { + $req = ""; + foreach ($data as $key => $value) { + $req .= $key . '=' . urlencode(stripslashes($value)) . '&'; + } + + // Cut the last '&' + $req=substr($req, 0, strlen($req)-1); + return $req; + } + + /** + * Submits an HTTP GET to a reCAPTCHA server. + * + * @param string $path url path to recaptcha server. + * @param array $data array of parameters to be sent. + * + * @return array response + */ + private function _submitHTTPGet($path, $data) + { + $req = $this->_encodeQS($data); + $response = file_get_contents($path . $req); + return $response; + } + + /** + * Calls the reCAPTCHA siteverify API to verify whether the user passes + * CAPTCHA test. + * + * @param string $remoteIp IP address of end user. + * @param string $response response string from recaptcha verification. + * + * @return ReCaptchaResponse + */ + public function verifyResponse($remoteIp, $response) + { + // Discard empty solution submissions + if ($response == null || strlen($response) == 0) { + $recaptchaResponse = new ReCaptchaResponse(); + $recaptchaResponse->success = false; + $recaptchaResponse->errorCodes = 'missing-input'; + return $recaptchaResponse; + } + + $getResponse = $this->_submitHttpGet( + self::$_siteVerifyUrl, + array ( + 'secret' => $this->_secret, + 'remoteip' => $remoteIp, + 'v' => self::$_version, + 'response' => $response + ) + ); + $answers = json_decode($getResponse, true); + $recaptchaResponse = new ReCaptchaResponse(); + + print_r($answers); + if (trim($answers['success']) == true) { + $recaptchaResponse->success = true; + } else { + $recaptchaResponse->success = false; + $recaptchaResponse->errorCodes = $answers['error-codes']; + } + + return $recaptchaResponse; + } +} + +?> diff --git a/application/language/english/aauth_lang.php b/application/language/english/aauth_lang.php index feffbb05..c6c59328 100644 --- a/application/language/english/aauth_lang.php +++ b/application/language/english/aauth_lang.php @@ -22,6 +22,7 @@ // $lang['wrong'] = 'E-mail or Password is wrong.'; $lang['exceeded'] = 'Login try limit exceeded.'; +$lang['recaptcha_not_correct'] = 'reCAPTCHA is incorrect.'; $lang['no_user'] = 'User not Exist'; $lang['not_verified'] = 'Please verify your account.'; $lang['group_exist'] = 'Group already exists'; diff --git a/application/libraries/Aauth.php b/application/libraries/Aauth.php index d337a658..68a3122e 100644 --- a/application/libraries/Aauth.php +++ b/application/libraries/Aauth.php @@ -61,6 +61,9 @@ public function __construct() { $this->CI = & get_instance(); // Dependancies + if(CI_VERSION >= 2.2){ + $this->CI->load->library('driver'); + } $this->CI->load->library('session'); $this->CI->load->library('email'); $this->CI->load->database(); @@ -68,12 +71,13 @@ public function __construct() { $this->CI->load->helper('string'); $this->CI->load->helper('email'); $this->CI->load->helper('language'); + $this->CI->load->helper('recaptchalib'); $this->CI->lang->load('aauth'); // config/aauth.php $this->CI->config->load('aauth'); - $this->config_vars = & $this->CI->config->item('aauth'); + $this->config_vars = $this->CI->config->item('aauth'); } @@ -130,6 +134,15 @@ public function login($email, $pass, $remember = FALSE) { $this->error($this->CI->lang->line('exceeded')); return false; } + if($query->num_rows() > 0 and $this->config_vars['ddos_protection'] and $this->config_vars['recaptcha_active'] and $row->login_attempts >= $this->config_vars['recaptcha_login_attempts']){ + $reCAPTCHA_cookie = array( + 'name' => 'reCAPTCHA', + 'value' => 'true', + 'expire' => time()+7200, + 'path' => '/', + ); + $this->CI->input->set_cookie($reCAPTCHA_cookie); + } // if user is not verified $query = null; @@ -146,14 +159,14 @@ public function login($email, $pass, $remember = FALSE) { // to find user id, create sessions and cookies $query = $this->CI->db->where('email', $email); $query = $this->CI->db->get($this->config_vars['users']); - - if($query->num_rows() == 0){ - $this->error($this->CI->lang->line('wrong')); + + if($query->num_rows() == 0){ + $this->error($this->CI->lang->line('wrong')); return false; - } - - $user_id = $query->row()->id; - + } + + $user_id = $query->row()->id; + $query = null; $query = $this->CI->db->where('email', $email); @@ -164,7 +177,16 @@ public function login($email, $pass, $remember = FALSE) { $query = $this->CI->db->get($this->config_vars['users']); $row = $query->row(); + if($this->CI->input->cookie('reCAPTCHA', TRUE) == 'true'){ + $reCaptcha = new ReCaptcha( $this->config_vars['recaptcha_secret']); + $resp = $reCaptcha->verifyResponse( $this->CI->input->server("REMOTE_ADDR"), $this->CI->input->post("g-recaptcha-response") ); + if(!$resp->success){ + $this->error($this->CI->lang->line('recaptcha_not_correct')); + return false; + } + } + // if email and pass matches and not banned if ( $query->num_rows() > 0 ) { @@ -197,10 +219,19 @@ public function login($email, $pass, $remember = FALSE) { $this->CI->input->set_cookie($cookie); } + $reCAPTCHA_cookie = array( + 'name' => 'reCAPTCHA', + 'value' => 'false', + 'expire' => time()-3600, + 'path' => '/', + ); + $this->CI->input->set_cookie($reCAPTCHA_cookie); + // update last login $this->update_last_login($row->id); $this->update_activity(); - + $this->reset_login_attempts($row->id); + return TRUE; } // if not matches @@ -333,7 +364,7 @@ public function login_fast($user_id){ */ public function reset_login_attempts($user_id) { - $data['last_login_attempts'] = null; + $data['login_attempts'] = null; $this->CI->db->where('id', $user_id); return $this->CI->db->update($this->config_vars['users'], $data); } @@ -446,7 +477,6 @@ public function update_login_attempts($email) { $data = array(); if ( strtotime($row->last_login_attempt) == strtotime(date("Y-m-d H:0:0"))) { - $data['login_attempts'] = $row->login_attempts + 1; $query = $this->CI->db->where('id', $user_id); @@ -501,15 +531,19 @@ public function update_remember($user_id, $expression=null, $expire=null) { * @param string $name User's name * @return int|bool False if create fails or returns user id if successful */ - public function create_user($email, $pass, $name='') { + public function create_user($email, $pass, $name) { $valid = true; // if email is already exist - if ( ! $this->check_email($email)) { + if ($this->user_exsist_by_email($email)) { $this->error($this->CI->lang->line('email_taken')); $valid = false; } + if ($this->user_exsist_by_name($name)) { + $this->error($this->CI->lang->line('name_taken')); + $valid = false; + } if ( ! valid_email($email)){ $this->error($this->CI->lang->line('email_invalid')); @@ -523,6 +557,10 @@ public function create_user($email, $pass, $name='') { $this->error($this->CI->lang->line('name_invalid')); $valid = false; } + if (empty($name)){ + $this->error($this->CI->lang->line('name_invalid')); + $valid = false; + } if (!$valid) { return false; } @@ -803,6 +841,60 @@ public function is_banned($user_id) { return FALSE; } + /** + * user_exsist_by_id + * Check if user exist by user id + * @param $user_id + * + * @return bool + */ + public function user_exsist_by_id( $user_id ) { + $query = $this->CI->db->where('id', $user_id); + + $query = $this->CI->db->get($this->config_vars['users']); + + if ($query->num_rows() > 0) + return TRUE; + else + return FALSE; + } + + /** + * user_exsist_by_name + * Check if user exist by name + * @param $user_id + * + * @return bool + */ + public function user_exsist_by_name( $name ) { + $query = $this->CI->db->where('name', $name); + + $query = $this->CI->db->get($this->config_vars['users']); + + if ($query->num_rows() > 0) + return TRUE; + else + return FALSE; + } + + /** + * user_exsist_by_email + * Check if user exsist by user email + * @param $user_email + * + * @return bool + */ + public function user_exsist_by_email( $user_email ) { + $query = $this->CI->db->where('email', $user_email); + + $query = $this->CI->db->get($this->config_vars['users']); + + if ($query->num_rows() > 0) + return TRUE; + else + return FALSE; + } + /** * Get user id * Get user id from email address, if par. not given, return current user's id @@ -844,26 +936,6 @@ public function get_user_groups($user_id = false){ return $query = $this->CI->db->get()->result(); } - //tested - /** - * Check email - * Checks if an email address is available - * @param string $email Email to check - * @return bool True if available, False if not - */ - public function check_email($email) { - - $this->CI->db->where("email", $email); - $query = $this->CI->db->get($this->config_vars['users']); - - if ($query->num_rows() > 0) { - $this->info($this->CI->lang->line('email_taken')); - return FALSE; - } - else - return TRUE; - } - //tested /** * Update activity @@ -956,11 +1028,11 @@ public function delete_group($group_par) { $group_id = $this->get_group_id($group_par); - $this->CI->db->where('id',$group_id); - $query = $this->CI->db->get($this->config_vars['groups']); - if ($query->num_rows() == 0){ - return false; - } + $this->CI->db->where('id',$group_id); + $query = $this->CI->db->get($this->config_vars['groups']); + if ($query->num_rows() == 0){ + return false; + } // bug fixed // now users are deleted from user_to_group table @@ -1805,7 +1877,7 @@ public function list_user_var_keys($user_id = false){ if ( ! $this->get_user($user_id)){ return false; } - $query = $this->CI->db->select('key'); + $query = $this->CI->db->select('key'); $query = $this->CI->db->where('user_id', $user_id); @@ -1902,13 +1974,23 @@ public function get_system_var( $key ){ */ public function list_system_var_keys(){ - $query = $this->CI->db->select('key'); - $query = $this->CI->db->get( $this->config_vars['system_variables'] ); - // if variable not set - if ($query->num_rows() < 1) { return false;} - else { - return $query->result(); - } + $query = $this->CI->db->select('key'); + $query = $this->CI->db->get( $this->config_vars['system_variables'] ); + // if variable not set + if ($query->num_rows() < 1) { return false;} + else { + return $query->result(); + } + } + + public function generate_recaptcha_field(){ + $content = ''; + if($this->config_vars['ddos_protection'] and $this->config_vars['recaptcha_active'] and $this->CI->input->cookie('reCAPTCHA', TRUE) == 'true'){ + $content .= ""; + $siteKey = $this->config_vars['recaptcha_siteKey']; + $content .= "
"; + } + return $content; } } // end class From 1006f8800f2c3e0b0a4f41e9dd0994ba3446a786 Mon Sep 17 00:00:00 2001 From: Raphael Jackstadt Date: Sun, 7 Dec 2014 05:20:40 +0100 Subject: [PATCH 2/2] lil fix for reCAPTCHA --- application/libraries/Aauth.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/application/libraries/Aauth.php b/application/libraries/Aauth.php index 68a3122e..eade8786 100644 --- a/application/libraries/Aauth.php +++ b/application/libraries/Aauth.php @@ -134,6 +134,12 @@ public function login($email, $pass, $remember = FALSE) { $this->error($this->CI->lang->line('exceeded')); return false; } + + //recaptcha login_attempts check + $query = null; + $query = $this->CI->db->where('email', $email); + $query = $this->CI->db->get($this->config_vars['users']); + $row = $query->row(); if($query->num_rows() > 0 and $this->config_vars['ddos_protection'] and $this->config_vars['recaptcha_active'] and $row->login_attempts >= $this->config_vars['recaptcha_login_attempts']){ $reCAPTCHA_cookie = array( 'name' => 'reCAPTCHA',