rename password functions for PHP 5.5 compatibility
[openemr.git] / library / authentication / password_change.php
blob6677c23939765ef574f207092caf1f91723e2153
1 <?php
2 /**
3 * Function used when changing a user's password
4 * (either the user's own password or an administrator updating a different user)
5 *
6 * Copyright (C) 2013 Kevin Yeh <kevin.y@integralemr.com> and OEMR <www.oemr.org>
8 * LICENSE: This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 3
11 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>;.
19 * @package OpenEMR
20 * @author Kevin Yeh <kevin.y@integralemr.com>
21 * @link http://www.open-emr.org
23 require_once("$srcdir/authentication/common_operations.php");
25 /**
26 * Does the new password meet the security requirements?
28 * @param type $pwd the password to test
29 * @param type $errMsg why there was a failure
30 * @return boolean is the password good enough?
32 function test_password_strength($pwd,&$errMsg)
34 $require_strong=$GLOBALS['secure_password'] !=0;
35 if($require_strong)
37 if(strlen($pwd)<8)
39 $errMsg=xl("Password too short. Minimum 8 characters required.");
40 return false;
42 $features=0;
43 $reg_security=array("/[a-z]+/","/[A-Z]+/","/\d+/","/[\W_]+/");
44 foreach($reg_security as $expr)
46 if(preg_match($expr,$pwd))
48 $features++;
51 if($features<3)
53 $errMsg=xl("Password does not meet minimum requirements and should contain at least three of the four following items: A number, a lowercase letter, an uppercase letter, a special character (Not a leter or number).");
54 return false;
57 return true;
59 /**
60 * Setup or change a user's password
62 * @param type $activeUser ID of who is trying to make the change (either the user himself, or an administrator)
63 * @param type $targetUser ID of what account's password is to be updated (for a new user this doesn't exist yet).
64 * @param type $currentPwd the active user's current password
65 * @param type $newPwd the new password for the target user
66 * @param type $errMsg passed by reference to return any
67 * @param type $create Are we creating a new user or
68 * @param type $insert_sql SQL to run to create the row in "users" (and generate a new id) when needed.
69 * @param type $new_username The username for a new user
70 * @param type $newid Return by reference of the ID of a created user
71 * @return boolean Was the password successfully updated/created? If false, then $errMsg will tell you why it failed.
73 function update_password($activeUser,$targetUser,&$currentPwd,&$newPwd,&$errMsg,$create=false,$insert_sql="",$new_username=null,&$newid=null)
75 $userSQL="SELECT ".implode(",",array(COL_PWD,COL_SALT,COL_PWD_H1,COL_SALT_H1,COL_PWD_H2,COL_SALT_H2))
76 ." FROM ".TBL_USERS_SECURE
77 ." WHERE ".COL_ID."=?";
78 $userInfo=privQuery($userSQL,array($targetUser));
80 // Verify the active user's password
81 if($activeUser==$targetUser)
83 if($create)
85 $errMsg=xl("Trying to create user with existing username!");
86 return false;
88 // If this user is changing his own password, then confirm that they have the current password correct
89 $hash_current = oemr_password_hash($currentPwd,$userInfo[COL_SALT]);
90 if(($hash_current!=$userInfo[COL_PWD]))
92 $errMsg=xl("Incorrect password!");
93 return false;
96 else {
97 // If this is an administrator changing someone else's password, then check that they have the password right
99 $adminSQL=" SELECT ".implode(",",array(COL_PWD,COL_SALT))
100 ." FROM ".TBL_USERS_SECURE
101 ." WHERE ".COL_ID."=?";
102 $adminInfo=privQuery($adminSQL,array($activeUser));
103 $hash_admin = oemr_password_hash($currentPwd,$adminInfo[COL_SALT]);
104 if($hash_admin!=$adminInfo[COL_PWD])
106 $errMsg=xl("Incorrect password!");
107 return false;
109 if(!acl_check('admin', 'users'))
112 $errMsg=xl("Not authorized to manage users!");
113 return false;
116 // End active user check
119 //Test password validity
120 if(strlen($newPwd)==0)
122 $errMsg=xl("Empty Password Not Allowed");
123 return false;
125 if(!test_password_strength($newPwd,$errMsg))
127 return false;
129 // End password validty checks
131 if($userInfo===false)
133 // No userInfo means either a new user, or an existing user who has not been migrated to blowfish yet
134 // In these cases don't worry about password history
135 if($create)
137 privStatement($insert_sql,array());
138 $getUserID= " SELECT ".COL_ID
139 ." FROM ".TBL_USERS
140 ." WHERE ".COL_UNM."=?";
141 $user_id=privQuery($getUserID,array($new_username));
142 initializePassword($new_username,$user_id[COL_ID],$newPwd);
143 $newid=$user_id[COL_ID];
145 else
147 $getUserNameSQL="SELECT ".COL_UNM
148 ." FROM ".TBL_USERS
149 ." WHERE ".COL_ID."=?";
150 $unm=privQuery($getUserNameSQL,array($targetUser));
151 if($unm===false)
153 $errMsg=xl("Unknown user id:".$targetUser);
154 return false;
156 initializePassword($unm[COL_UNM],$targetUser,$newPwd);
157 purgeCompatabilityPassword($unm[COL_UNM],$targetUser);
161 else
163 if($create)
165 $errMsg=xl("Trying to create user with existing username!");
166 return false;
169 $forbid_reuse=$GLOBALS['password_history'] != 0;
170 if($forbid_reuse)
172 // password reuse disallowed
173 $hash_current = oemr_password_hash($newPwd,$userInfo[COL_SALT]);
174 $hash_history1 = oemr_password_hash($newPwd,$userInfo[COL_SALT_H1]);
175 $hash_history2 = oemr_password_hash($newPwd,$userInfo[COL_SALT_H2]);
176 if(($hash_current==$userInfo[COL_PWD])
177 ||($hash_history1==$userInfo[COL_PWD_H1])
178 || ($hash_history2==$userInfo[COL_PWD_H2]))
180 $errMsg=xl("Reuse of three previous passwords not allowed!");
181 return false;
185 // Everything checks out at this point, so update the password record
186 $newSalt = oemr_password_salt();
187 $newHash = oemr_password_hash($newPwd,$newSalt);
188 $updateParams=array();
189 $updateSQL= "UPDATE ".TBL_USERS_SECURE;
190 $updateSQL.=" SET ".COL_PWD."=?,".COL_SALT."=?"; array_push($updateParams,$newHash); array_push($updateParams,$newSalt);
191 if($forbid_reuse){
192 $updateSQL.=",".COL_PWD_H1."=?".",".COL_SALT_H1."=?"; array_push($updateParams,$userInfo[COL_PWD]); array_push($updateParams,$userInfo[COL_SALT]);
193 $updateSQL.=",".COL_PWD_H2."=?".",".COL_SALT_H2."=?"; array_push($updateParams,$userInfo[COL_PWD_H1]); array_push($updateParams,$userInfo[COL_SALT_H1]);
196 $updateSQL.=" WHERE ".COL_ID."=?"; array_push($updateParams,$targetUser);
197 privStatement($updateSQL,$updateParams);
200 if($GLOBALS['password_expiration_days'] != 0){
201 $exp_days=$GLOBALS['password_expiration_days'];
202 $exp_date = date('Y-m-d', strtotime("+$exp_days days"));
203 privStatement("update users set pwd_expiration_date=? where id=?",array($exp_date,$targetUser));
205 return true;