diff --git a/protected/controllers/RegistrationController.php b/protected/controllers/RegistrationController.php index 6e91bccc..a1ca021a 100644 --- a/protected/controllers/RegistrationController.php +++ b/protected/controllers/RegistrationController.php @@ -1,397 +1,403 @@ array('index', 'enterDetails', 'confirm'), 'users' => array('@'), ), array('allow', // Allow users not yet logged in to register accounts 'actions' => array('index', 'enterDetails', 'confirm'), 'users' => array('*'), ), array('allow', // Allow sysadmins to see pending registrations, and view or delete them 'actions' => array('list', 'view', 'update', 'delete'), 'roles' => array('sysadmins'), ), array('deny', // Any other action is denied 'users' => array('*'), ), ); } public function actionIndex() { // If they have confirmed they accept our terms, mark them as accepted if( isset($_POST['confirmAcceptance']) && isset($_POST['continue']) ) { Yii::app()->user->setState('registerTermsAccepted', 'confirmed'); } // If they have already accepted our terms, do not reprompt them if( Yii::app()->user->getState('registerTermsAccepted') == 'confirmed' ) { $this->redirect( array('enterDetails') ); } // Make sure they are not an attempted spammer if( $this->performSpamCheck() ) { throw new CHttpException(403, "Client rejected by automatic spammer detection system"); } if( $this->performIpBlacklistCheck() ) { throw new CHttpException(403, "Access Denied: Internet Service Provider blacklisted due to abuse. Please email sysadmin@kde.org to register an account."); } /** * Check referer during the registration process to be able to show the user * the page he is coming from and be able to redirect him at the end of the * registration process. */ $refererHelper = new SiteReferer(); $refererHelper->checkReferer(); $this->render('index'); } public function actionEnterDetails() { // Make sure they have accepted our terms.... if( Yii::app()->user->getState('registerTermsAccepted') != 'confirmed' ) { $this->redirect( array('index') ); } // Have they tried to register before? if( Yii::app()->user->getState('sentRegistration') == 'yes' ) { throw new CHttpException(403, "Access Denied: Attempt to perform multiple registrations detected.
" . "If you have received this notice and have not previously attempted to register, please email sysadmin@kde.org for further assistance." ); } $model = new Token('register'); // Maybe they have provided the needed information, in which case we need to act on it... if( isset($_POST['Token']) ) { $model->type = Token::TypeRegisterAccount; $model->attributes = $_POST['Token']; if( $this->performSpamCheck($model->mail) ) { throw new CHttpException(403, "Client rejected by automatic spammer detection system"); } if( $this->performCaptchaCheck() ) { throw new CHttpException(403, "CAPTCHA Incorrect. Please go back and try again. If the CAPTCHA is not visible please disable all privacy and adblocker browser addons."); } if( $this->performIpBlacklistCheck() ) { throw new CHttpException(403, "Access Denied: Internet Service Provider blacklisted due to abuse. Please email sysadmin@kde.org to register an account."); } if( $model->save() ) { $this->sendEmail($model->mail, '/mail/confirmRegistration', array('model' => $model)); $this->render('confirmationSent', array('model' => $model)); Yii::app()->user->setState('sentRegistration', 'yes'); Yii::app()->end(); } } $this->render('enterDetails', array( 'model' => $model, )); } public function actionConfirm($id, $token) { // Ensure the provided registration confirmation is valid $tokenModel = Token::model()->findByAttributes( array('id' => $id, 'type' => Token::TypeRegisterAccount, 'token' => $token) ); if( !$tokenModel instanceof CActiveRecord ) { throw new CHttpException(404, 'The given validation could not be confirmed, please contact the site administrator.'); } // Prepare the user which we will be finalising $model = new User('register'); $knownData = $tokenModel->getAttributes( array('uid', 'givenName', 'sn', 'mail') ); $model->setAttributes( $knownData, false ); // Copy unsafe values as well as this is internally stored // Maybe we have a submission to handle? if( isset($_POST['User']) ) { // Assign the inbound data $model->attributes = $_POST['User']; // Set the DN the new user will be created in $model->setDnByParent( Yii::app()->params['registrationUnit'] ); // Try to create the user now. If the username/password is bad then it will fail if( $model->save() ) { // Creation succeeded, so cleanup.... $tokenModel->delete(); // Inform the site administrator of the account creation //$this->sendEmail(Yii::app()->params['registerNotify'], '/mail/notifyRegistration', array('model' => $model)); // Give the user an email with their account details $this->sendEmail($model->mail, '/mail/notifyUserOfAccount', array('model' => $model)); // Give the user a page informing them of their account details $this->render('complete', array('model' => $model)); Yii::app()->end(); } } $this->render('confirm', array( 'model' => $model, )); } public function actionList() { $model = new Token('search'); if( isset($_GET['Token']) ) { $model->attributes = $_GET['Token']; } + // Setup our list, including search support + $criteria = new CDbCriteria; + $criteria->compare('type', Token::TypeRegisterAccount); + $criteria->compare('givenName', $model->givenName, true); + $criteria->compare('sn', $model->sn, true); + $criteria->compare('mail', $model->mail, true); $dataProvider = new CActiveDataProvider($model, array( - 'criteria' => array('condition' => 'type = ' . Token::TypeRegisterAccount), + 'criteria' => $criteria, 'pagination' => array('pageSize' => 20), )); $this->render('list', array( 'model' => $model, 'dataProvider' => $dataProvider, )); } public function actionView($id) { $model = $this->loadModel($id); if( isset($_POST['resendConfirmation']) ) { $this->sendEmail($model->mail, '/mail/confirmRegistration', array('model' => $model)); Yii::app()->user->setFlash('success', 'Registration confirmation has been resent.'); } $this->render('view', array( 'model' => $model, )); } public function actionUpdate($id) { $model = $this->loadModel($id); $model->setScenario('register'); if( isset($_POST['Token']) ) { $model->attributes = $_POST['Token']; if( $model->save() ) { $this->redirect(array('view', 'id' => $model->id)); } } $this->render('update', array( 'model' => $model, )); } public function actionDelete($id) { $model = $this->loadModel($id); if( isset($_POST['confirmDeletion']) && isset($_POST['deleteAccount']) ) { if( $model->delete() ) { $this->redirect( array('list') ); } } $this->render('delete', array( 'model' => $model, )); } protected function performSpamCheck($email = "") { // Address of the API we are using $query = "http://www.stopforumspam.com/api"; // We want php serialized data $query .= "?f=serial"; // Add email address and ip address parameters if we have them... if( $email != "" ) { $query .= "&email=" . trim($email); } // Add the ip address $query .= "&ip=" . Yii::app()->request->userHostAddress; // Perform the query... $result = @file_get_contents($query); // if we have network issues, let him through. if( $result === false ) { return false; } // Decode the data we recieved $result = unserialize($result); // if the query failed, permit the request if( $result["success"] != 1 ) { return false; } // If there is a greater than 80% the ip address is used by spammers, reject the request if( isset($result["ip"]["confidence"] ) && $result["ip"]["confidence"] > 80 ) { return true; } // If the email address has been used to spam anywhere, reject the request if( $email != "" && isset($result["email"]["confidence"]) && $result["email"]["confidence"] > 0 ) { return true; } // let everyone through. return false; } protected function performCaptchaCheck() { $secret = Yii::app()->params['recaptcha-secret']; $recaptcha = new ReCaptcha($secret); $resp = $recaptcha->verify( Yii::app()->request->getPost('g-recaptcha-response'), Yii::app()->request->userHostAddress ); if( !$resp->isSuccess() ) { return true; } return false; } protected function performIpBlacklistCheck() { $userIp = Yii::app()->request->userHostAddress; $blacklistedRanges = array( // Shenzhen Tinmok Information Network Co (Chinese Network Provider) '103.56.218.0/23', // Moomu (Unknown) '103.27.220.0/25', // Bharti Airtel Ltd (Indian ISP) '122.177.0.0/16', '182.64.0.0/12', '122.180.0.0/16', // Nextra Televentures (Indian ISP) '103.30.252.0/24', '103.225.43.0/24', // Odeon Infrastructure (Indian ISP) '45.120.58.0/24', // Tata Teleservices (Indian ISP) '14.96.0.0/14', '61.12.64.0/19', '14.98.96.0/20', '14.98.128.0/20', '121.245.126.0/24', // Precious Netcom Pvt Ltd (Indian ISP) '43.230.198.0/24', // Anjani Broadband Solutions (Indian ISP) '43.225.193.0/24', // Den Digital Entertainment Networks (Indian ISP) '112.196.128.0/18', // Hathway Cable (Indian ISP) '116.72.0.0/14', // Speednet (Indian ISP) '110.172.140.0/24', // Spectranet (Indian ISP) '180.151.0.0/16', // Citycom Networks (Indian ISP) '125.63.64.0/18', // BSNL (Indian ISP) '117.220.0.0/15', // Dabas IT (Indian VPS) '103.199.120.0/22', // City Reservations Private Limited (Indian Corporate) '45.115.141.0/24', '45.115.142.0/24', // Neo SunCity Private Limited (Indian Corporate) '45.121.191.0/24', // Quadranet (American VPS) '104.223.0.0/17', // DigitalOcean (American VPS) '46.101.0.0/17', '162.243.0.0/16', '104.131.0.0/16', '104.236.0.0/16', '107.170.0.0/16', // Choopa LLC (American VPS) '108.61.0.0/16', // EGI Hosting (American VPS) '72.13.80.0/20', // Lunanode Hosting (American VPS) '170.75.160.0/20', // Secured Servers LLC (American VPS) '66.85.128.0/18', // Atlantic.net Inc (American ??) '69.28.64.0/19', // Xponent LLC (American / Australian Corporate) '103.251.64.0/24', '103.251.65.0/24', // Unus, Inc (American Corporate) '128.90.0.0/16', // UK2 Infrastructure (Unknown) '185.80.220.0/23', '159.253.145.128/26', '37.130.224.0/21', // Falco Networks B.V (French ?) '85.203.17.0/24', '85.203.18.0/24', // NForce Entertainment B.V // Offending sub-block delegated to Alanna Investment Limited in the British Virgin Islands // Due to it's reputation - we're blaming the parent owner of the IP block and banning the entire thing '46.166.136.0/21', // GleSYS Internet Services AB (Swedish VPS) '46.21.96.0/20', // Comvive Servidores S.L. (Spanish VPS) '93.93.64.0/21', // Linode (Japan) '106.187.48.0/21', ); foreach( $blacklistedRanges as $ipRange ) { // Compute the necessary details for this IP range list ($net, $mask) = split("/", $ipRange); $ip_net = ip2long($net); $ip_mask = ~((1 << (32 - $mask)) - 1); // Breakdown the information about our user's IP address $ip_ip = ip2long($userIp); $ip_ip_net = $ip_ip & $ip_mask; if( $ip_ip_net == $ip_net ) { return true; } } return false; } protected function loadModel($id) { $model = Token::model()->findByAttributes( array('id' => $id, 'type' => Token::TypeRegisterAccount) ); if( $model === null ) { throw new CHttpException(404, 'The requested page does not exist.'); } return $model; } }