File indexing completed on 2024-12-22 05:33:32

0001 <?php
0002 
0003 /**
0004  *  ocs-webserver
0005  *
0006  *  Copyright 2016 by pling GmbH.
0007  *
0008  *    This file is part of ocs-webserver.
0009  *
0010  *    This program is free software: you can redistribute it and/or modify
0011  *    it under the terms of the GNU Affero General Public License as
0012  *    published by the Free Software Foundation, either version 3 of the
0013  *    License, or (at your option) any later version.
0014  *
0015  *    This program is distributed in the hope that it will be useful,
0016  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018  *    GNU Affero General Public License for more details.
0019  *
0020  *    You should have received a copy of the GNU Affero General Public License
0021  *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0022  *
0023  * Created: 02.05.2018
0024  */
0025 class PasswordController extends Local_Controller_Action_DomainSwitch
0026 {
0027 
0028     const C = 10800;
0029     private $from_alias = "opendesktop.org";
0030     private $from_mail = "contact@opendesktop.org";
0031     private $options = array(
0032         // Encryption type - Openssl or Mcrypt
0033         'adapter'   => 'mcrypt',
0034         // Initialization vector
0035         'vector'    => '236587hgtyujkirtfgty5678',
0036         // Encryption algorithm
0037         'algorithm' => 'rijndael-192',
0038         // Encryption key
0039         'key'       => 'KFJGKDK$$##^FFS345678FG2'
0040     );
0041 
0042     public function requestAction()
0043     {
0044         if ($this->_request->isGet()) {
0045             return;
0046         }
0047 
0048         $email = $this->getParam('mail');
0049         if (empty($email)) {
0050             Zend_Registry::get('logger')->debug(__METHOD__ . ' - param mail is empty');
0051 
0052             return;
0053         }
0054         $validate = new Zend_Validate_EmailAddress();
0055 
0056         if (false == $validate->isValid($email)) {
0057             $this->_helper->flashMessenger->addMessage('<p class="text-error">Please type in a valid email address.</p>');
0058             Zend_Registry::get('logger')->debug(__METHOD__ . ' - param mail not valid');
0059 
0060             return;
0061         }
0062 
0063         $modelMember = new Default_Model_Member();
0064         $member = $modelMember->findActiveMemberByMail($email);
0065 
0066         if (empty($member->member_id)) {
0067 
0068             $member = $modelMember->findActiveMemberByMail($email.'_double');
0069 
0070             if (empty($member->member_id)) {
0071                 Zend_Registry::get('logger')->debug(__METHOD__ . ' - no active member found. ' . $email);
0072 
0073                 return;
0074             }
0075         }
0076 
0077         $url = $this->generateUrl($member);
0078 
0079         $this->sendMail($email, $url, 'Reset your password');
0080         $this->redirect("/login");
0081     }
0082 
0083     private function generateUrl($member)
0084     {
0085         $encrypt = $this->getEncryptFilter();
0086 
0087         $duration = self::C; // in seconds
0088 
0089         $payload = array(
0090             'member_id' => $member->member_id,
0091             'expire'    => time() + $duration
0092         );
0093 
0094         /** @var Zend_Controller_Request_Http $request */
0095         $request = Zend_Controller_Front::getInstance()->getRequest();
0096 
0097         $secret =  $this->base64url_encode($encrypt->filter(json_encode($payload)));
0098 
0099         $url = $request->getScheme() . '://' . $request->getHttpHost() . '/password/change?' . $secret;
0100 
0101         Zend_Registry::get('logger')->debug(__METHOD__ . ' - generated url: ' . $url);
0102 
0103         Zend_Registry::get('cache')->save($secret, sha1($secret), array(), self::C);
0104 
0105         return $url;
0106     }
0107 
0108     /**
0109      * @return Zend_Filter_Encrypt
0110      */
0111     private function getEncryptFilter()
0112     {
0113         /* Initialize the library and pass the options */
0114         $filter = new Zend_Filter_Encrypt($this->options);
0115 
0116         return $filter;
0117     }
0118 
0119     /**
0120      * @param $mail
0121      * @param $url
0122      * @param $subject
0123      *
0124      * @throws Zend_Exception
0125      * @throws Zend_View_Exception
0126      */
0127     private function sendMail($email, $url, $subject)
0128     {
0129         $renderer = new Zend_View();
0130         $renderer->setScriptPath(APPLICATION_PATH . '/modules/default/views/emails/');
0131 
0132         $renderer->assign('mail', $email);
0133         $renderer->assign('url', $url);
0134 
0135         $body_text = $renderer->render('url_forgot_password.phtml');
0136 
0137         try {
0138             $mail = new Zend_Mail('utf-8');
0139             $mail->setBodyHtml($body_text);
0140             $mail->setFrom($this->from_mail, $this->from_alias);
0141 
0142             $mail->addTo($email);
0143             $mail->setSubject($subject);
0144             $mail->send();
0145         } catch (Exception $e) {
0146             Zend_Registry::get('logger')->err(__METHOD__ . " - " . print_r($e, true) . PHP_EOL);
0147         }
0148     }
0149 
0150     public function changeAction()
0151     {
0152         $debugMsg = '' . __METHOD__ . PHP_EOL;
0153         $uri_part = explode("?", $this->_request->getRequestUri());
0154         $debugMsg .= ' - $uri_part = ' . print_r($uri_part, true) . PHP_EOL;
0155         $secret = preg_replace('/[^-a-zA-Z0-9_=\/]/', '', array_pop($uri_part));
0156         $debugMsg .= ' - $secret = ' . print_r($secret, true) . PHP_EOL;
0157 
0158         $decrypt = $this->getDecryptFilter();
0159         $step1 = $this->base64url_decode($secret);
0160         $debugMsg .= ' - $step1 = ' . print_r($step1, true) . PHP_EOL;
0161         $step2 = $decrypt->filter($step1);
0162         $debugMsg .= ' - $step2 = ' . print_r($step2, true) . PHP_EOL;
0163         $payload = json_decode(trim($step2), true);
0164         $debugMsg .= ' - $payload = ' . print_r($payload, true) . PHP_EOL;
0165 
0166         if (false == Zend_Registry::get('cache')->load(sha1($secret))) {
0167             $debugMsg .= '- unknown request url' . PHP_EOL;
0168             Zend_Registry::get('logger')->debug($debugMsg);
0169             throw new Zend_Controller_Action_Exception('Unknown request url for password change');
0170         }
0171 
0172         if (empty($payload) OR (false == is_array($payload))) {
0173             $debugMsg .= '- wrong request url' . PHP_EOL;
0174             Zend_Registry::get('logger')->debug($debugMsg);
0175             throw new Zend_Controller_Action_Exception('Wrong request url for password change');
0176         }
0177 
0178         if (time() > $payload['expire']) {
0179             $debugMsg .= '- password change request expired' . PHP_EOL;
0180             Zend_Registry::get('logger')->debug($debugMsg);
0181             $this->_helper->flashMessenger->addMessage('<p class="text-error">Your password change request is expired.</p>');
0182             $this->forward('login', 'authorization');
0183         }
0184 
0185         $this->view->assign('action', '/password/change?' . $secret);
0186 
0187         if ($this->_request->isGet()) {
0188             $debugMsg .= '- show password change form' . PHP_EOL;
0189             Zend_Registry::get('logger')->debug($debugMsg);
0190             return;
0191         }
0192 
0193         $filterInput = new Zend_Filter_Input(array('*' => 'StringTrim'), array(
0194             'password1' => array(
0195                 new Zend_Validate_StringLength(array('min' => 6, 'max' => 200)),
0196                 'presence' => 'required'
0197             ),
0198             'password2' => array(
0199                 new Zend_Validate_StringLength(array('min' => 6, 'max' => 200)),
0200                 'presence' => 'required'
0201             ),
0202         ), $this->getAllParams());
0203 
0204         if (false === $filterInput->isValid()) {
0205             foreach ($filterInput->getMessages() as $message) {
0206                 $this->_helper->flashMessenger->addMessage('<p class="text-error">' . $message . '</p>');
0207             }
0208 
0209             return;
0210         }
0211 
0212         $password1 = $filterInput->getUnescaped('password1');
0213         $password2 = $filterInput->getUnescaped('password2');
0214 
0215         if ($password1 != $password2) {
0216             $this->_helper->flashMessenger->addMessage('<p class="text-error">Your passwords are not identical.</p>');
0217             return;
0218         }
0219 
0220         $model_member = new Default_Model_DbTable_Member();
0221         $member_data = $model_member->fetchRow(array('member_id = ?' => $payload['member_id']));
0222         
0223         if($member_data->password_type == Default_Model_Member::PASSWORD_TYPE_HIVE) {
0224             //Save old data
0225             $member_data->password_old = $member_data->password;
0226             $member_data->password_type_old = Default_Model_Member::PASSWORD_TYPE_HIVE;
0227             
0228             //Change type and password
0229             $member_data->password_type = Default_Model_Member::PASSWORD_TYPE_OCS;
0230         }
0231         
0232         $member_data->password = Local_Auth_Adapter_Ocs::getEncryptedPassword($password1, Default_Model_Member::PASSWORD_TYPE_OCS);
0233         $member_data->save();
0234 
0235         Zend_Registry::get('cache')->remove(sha1($secret));
0236 
0237         //Update Auth-Services
0238         try {
0239             $id_server = new Default_Model_Ocs_OAuth();
0240             $id_server->updatePasswordForUser($member_data->member_id);
0241             $messages = $id_server->getMessages();
0242             if (false == empty($messages)) {
0243                 Zend_Registry::get('logger')->info(json_encode($messages));
0244             }
0245         } catch (Exception $e) {
0246             Zend_Registry::get('logger')->err($e->getMessage() . PHP_EOL . $e->getTraceAsString());
0247         }
0248         try {
0249             $ldap_server = new Default_Model_Ocs_Ldap();
0250             $ldap_server->updatePassword($member_data->member_id, $password1);
0251             $messages = $ldap_server->getMessages();
0252             if (false == empty($messages)) {
0253                 Zend_Registry::get('logger')->info(json_encode($messages));
0254             }
0255         } catch (Exception $e) {
0256             Zend_Registry::get('logger')->err($e->getMessage() . PHP_EOL . $e->getTraceAsString());
0257         }
0258 
0259         $debugMsg .= '- password changed' . PHP_EOL;
0260         Zend_Registry::get('logger')->debug($debugMsg);
0261 
0262         $this->_helper->flashMessenger->addMessage('<p class="text-error">Your password is changed.</p>');
0263         $this->redirect($this->_helper->url('login', 'authorization'));
0264     }
0265     
0266     
0267     public function setpasswordAction() 
0268     {
0269         $debugMsg = "";
0270         $this->view->assign('action', '/password/setpassword');
0271 
0272         if ($this->_request->isGet()) {
0273             $debugMsg .= '- show password change form' . PHP_EOL;
0274             Zend_Registry::get('logger')->debug($debugMsg);
0275             return;
0276         }
0277 
0278         $filterInput = new Zend_Filter_Input(array('*' => 'StringTrim'), array(
0279             'password1' => array(
0280                 new Zend_Validate_StringLength(array('min' => 6, 'max' => 200)),
0281                 'presence' => 'required'
0282             ),
0283             'password2' => array(
0284                 new Zend_Validate_StringLength(array('min' => 6, 'max' => 200)),
0285                 'presence' => 'required'
0286             ),
0287         ), $this->getAllParams());
0288 
0289         if (false === $filterInput->isValid()) {
0290             foreach ($filterInput->getMessages() as $message) {
0291                 $this->_helper->flashMessenger->addMessage('<p class="text-error">' . $message . '</p>');
0292             }
0293 
0294             return;
0295         }
0296 
0297         $password1 = $filterInput->getUnescaped('password1');
0298         $password2 = $filterInput->getUnescaped('password2');
0299 
0300         if ($password1 != $password2) {
0301             $this->_helper->flashMessenger->addMessage('<p class="text-error">Your passwords are not identical.</p>');
0302             return;
0303         }
0304 
0305         $model_member = new Default_Model_DbTable_Member();
0306         $auth = Zend_Auth::getInstance();
0307         $memberId = $auth->getStorage()->read()->member_id;
0308         $member_data = $model_member->fetchRow(array('member_id = ?' => $memberId));
0309         
0310         $member_data->password = Local_Auth_Adapter_Ocs::getEncryptedPassword($password1, Default_Model_Member::PASSWORD_TYPE_OCS);
0311         $member_data->save();
0312 
0313         //Update Auth-Services
0314         try {
0315             $id_server = new Default_Model_Ocs_OAuth();
0316             $id_server->updatePasswordForUser($member_data->member_id);
0317             $messages = $id_server->getMessages();
0318             if (false == empty($messages)) {
0319                 Zend_Registry::get('logger')->info(json_encode($messages));
0320             }
0321         } catch (Exception $e) {
0322             Zend_Registry::get('logger')->err($e->getMessage() . PHP_EOL . $e->getTraceAsString());
0323         }
0324         try {
0325             $ldap_server = new Default_Model_Ocs_Ldap();
0326             $ldap_server->updatePassword($member_data->member_id, $password1);
0327             $messages = $ldap_server->getMessages();
0328             if (false == empty($messages)) {
0329                 Zend_Registry::get('logger')->info(json_encode($messages));
0330             }
0331         } catch (Exception $e) {
0332             Zend_Registry::get('logger')->err($e->getMessage() . PHP_EOL . $e->getTraceAsString());
0333         }
0334 
0335         $debugMsg .= '- password for Github User changed' . PHP_EOL;
0336         Zend_Registry::get('logger')->debug($debugMsg);
0337 
0338         $this->_helper->flashMessenger->addMessage('<p class="text-error">Your password was set.</p>');
0339         $this->redirect($this->_helper->url('login', 'authorization'));
0340     }
0341     
0342     
0343 
0344     /**
0345      * @return Zend_Filter_Encrypt
0346      */
0347     private function getDecryptFilter()
0348     {
0349         /* Initialize the library and pass the options */
0350         $filter = new Zend_Filter_Decrypt($this->options);
0351 
0352         return $filter;
0353     }
0354 
0355     protected function base64url_encode($data) {
0356         return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
0357     }
0358 
0359     protected function base64url_decode($data) {
0360         return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
0361     }
0362 
0363 }