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 }