/**
 * 
 * @param type $username
 * @param type $password
 * @return boolean  returns true if the password for the given user is correct, false otherwise.
 */
function confirm_user_password($username, &$password)
{
    $getUserSecureSQL = " SELECT " . implode(",", array(COL_ID, COL_PWD, COL_SALT)) . " FROM " . TBL_USERS_SECURE . " WHERE BINARY " . COL_UNM . "=?";
    // Use binary keyword to require case sensitive username match
    $userSecure = privQuery($getUserSecureSQL, array($username));
    if (is_array($userSecure)) {
        $phash = oemr_password_hash($password, $userSecure[COL_SALT]);
        if ($phash == $userSecure[COL_PWD]) {
            return true;
        }
    }
    return false;
}
Example #2
0
 public function add_initial_user()
 {
     if ($this->execute_sql("INSERT INTO groups (id, name, user) VALUES (1,'{$this->igroup}','{$this->iuser}')") == FALSE) {
         $this->error_message = "ERROR. Unable to add initial user group\n" . "<p>" . mysqli_error($this->dbh) . " (#" . mysqli_errno($this->dbh) . ")\n";
         return FALSE;
     }
     $password_hash = "NoLongerUsed";
     // This is the value to insert into the password column in the "users" table. password details are now being stored in users_secure instead.
     $salt = oemr_password_salt();
     // Uses the functions defined in library/authentication/password_hashing.php
     $hash = oemr_password_hash($this->iuserpass, $salt);
     if ($this->execute_sql("INSERT INTO users (id, username, password, authorized, lname, fname, facility_id, calendar, cal_ui) VALUES (1,'{$this->iuser}','{$password_hash}',1,'{$this->iuname}','{$this->iufname}',3,1,3)") == FALSE) {
         $this->error_message = "ERROR. Unable to add initial user\n" . "<p>" . mysqli_error($this->dbh) . " (#" . mysqli_errno($this->dbh) . ")\n";
         return FALSE;
     }
     // Create the new style login credentials with blowfish and salt
     if ($this->execute_sql("INSERT INTO users_secure (id, username, password, salt) VALUES (1,'{$this->iuser}','{$hash}','{$salt}')") == FALSE) {
         $this->error_message = "ERROR. Unable to add initial user login credentials\n" . "<p>" . mysqli_error($this->dbh) . " (#" . mysqli_errno($this->dbh) . ")\n";
         return FALSE;
     }
     // Add the official openemr users (services)
     if ($this->load_file($this->additional_users, "Additional Official Users") == FALSE) {
         return FALSE;
     }
     return TRUE;
 }
/**
 * Setup or change a user's password
 * 
 * @param type $activeUser      ID of who is trying to make the change (either the user himself, or an administrator)
 * @param type $targetUser      ID of what account's password is to be updated (for a new user this doesn't exist yet).
 * @param type $currentPwd      the active user's current password 
 * @param type $newPwd          the new password for the target user
 * @param type $errMsg          passed by reference to return any 
 * @param type $create          Are we creating a new user or 
 * @param type $insert_sql      SQL to run to create the row in "users" (and generate a new id) when needed.
 * @param type $new_username    The username for a new user
 * @param type $newid           Return by reference of the ID of a created user
 * @return boolean              Was the password successfully updated/created? If false, then $errMsg will tell you why it failed.
 */
function update_password($activeUser, $targetUser, &$currentPwd, &$newPwd, &$errMsg, $create = false, $insert_sql = "", $new_username = null, &$newid = null)
{
    $userSQL = "SELECT " . implode(",", array(COL_PWD, COL_SALT, COL_PWD_H1, COL_SALT_H1, COL_PWD_H2, COL_SALT_H2)) . " FROM " . TBL_USERS_SECURE . " WHERE " . COL_ID . "=?";
    $userInfo = privQuery($userSQL, array($targetUser));
    // Verify the active user's password
    $changingOwnPassword = $activeUser == $targetUser;
    // True if this is the current user changing their own password
    if ($changingOwnPassword) {
        if ($create) {
            $errMsg = xl("Trying to create user with existing username!");
            return false;
        }
        // If this user is changing his own password, then confirm that they have the current password correct
        $hash_current = oemr_password_hash($currentPwd, $userInfo[COL_SALT]);
        if ($hash_current != $userInfo[COL_PWD]) {
            $errMsg = xl("Incorrect password!");
            return false;
        }
    } else {
        // If this is an administrator changing someone else's password, then check that they have the password right
        $adminSQL = " SELECT " . implode(",", array(COL_PWD, COL_SALT)) . " FROM " . TBL_USERS_SECURE . " WHERE " . COL_ID . "=?";
        $adminInfo = privQuery($adminSQL, array($activeUser));
        $hash_admin = oemr_password_hash($currentPwd, $adminInfo[COL_SALT]);
        if ($hash_admin != $adminInfo[COL_PWD]) {
            $errMsg = xl("Incorrect password!");
            return false;
        }
        if (!acl_check('admin', 'users')) {
            $errMsg = xl("Not authorized to manage users!");
            return false;
        }
    }
    // End active user check
    //Test password validity
    if (strlen($newPwd) == 0) {
        $errMsg = xl("Empty Password Not Allowed");
        return false;
    }
    if (!test_password_strength($newPwd, $errMsg)) {
        return false;
    }
    // End password validty checks
    if ($userInfo === false) {
        // No userInfo means either a new user, or an existing user who has not been migrated to blowfish yet
        // In these cases don't worry about password history
        if ($create) {
            privStatement($insert_sql, array());
            $getUserID = " SELECT " . COL_ID . " FROM " . TBL_USERS . " WHERE " . COL_UNM . "=?";
            $user_id = privQuery($getUserID, array($new_username));
            initializePassword($new_username, $user_id[COL_ID], $newPwd);
            $newid = $user_id[COL_ID];
        } else {
            $getUserNameSQL = "SELECT " . COL_UNM . " FROM " . TBL_USERS . " WHERE " . COL_ID . "=?";
            $unm = privQuery($getUserNameSQL, array($targetUser));
            if ($unm === false) {
                $errMsg = xl("Unknown user id:" . $targetUser);
                return false;
            }
            initializePassword($unm[COL_UNM], $targetUser, $newPwd);
            purgeCompatabilityPassword($unm[COL_UNM], $targetUser);
        }
    } else {
        // We are trying to update the password of an existing user
        if ($create) {
            $errMsg = xl("Trying to create user with existing username!");
            return false;
        }
        $forbid_reuse = $GLOBALS['password_history'] != 0;
        if ($forbid_reuse) {
            // password reuse disallowed
            $hash_current = oemr_password_hash($newPwd, $userInfo[COL_SALT]);
            $hash_history1 = oemr_password_hash($newPwd, $userInfo[COL_SALT_H1]);
            $hash_history2 = oemr_password_hash($newPwd, $userInfo[COL_SALT_H2]);
            if ($hash_current == $userInfo[COL_PWD] || $hash_history1 == $userInfo[COL_PWD_H1] || $hash_history2 == $userInfo[COL_PWD_H2]) {
                $errMsg = xl("Reuse of three previous passwords not allowed!");
                return false;
            }
        }
        // Everything checks out at this point, so update the password record
        $newSalt = oemr_password_salt();
        $newHash = oemr_password_hash($newPwd, $newSalt);
        $updateParams = array();
        $updateSQL = "UPDATE " . TBL_USERS_SECURE;
        $updateSQL .= " SET " . COL_PWD . "=?," . COL_SALT . "=?";
        array_push($updateParams, $newHash);
        array_push($updateParams, $newSalt);
        if ($forbid_reuse) {
            $updateSQL .= "," . COL_PWD_H1 . "=?" . "," . COL_SALT_H1 . "=?";
            array_push($updateParams, $userInfo[COL_PWD]);
            array_push($updateParams, $userInfo[COL_SALT]);
            $updateSQL .= "," . COL_PWD_H2 . "=?" . "," . COL_SALT_H2 . "=?";
            array_push($updateParams, $userInfo[COL_PWD_H1]);
            array_push($updateParams, $userInfo[COL_SALT_H1]);
        }
        $updateSQL .= " WHERE " . COL_ID . "=?";
        array_push($updateParams, $targetUser);
        privStatement($updateSQL, $updateParams);
        // If the user is changing their own password, we need to update the session
        if ($changingOwnPassword) {
            $_SESSION['authPass'] = $newHash;
        }
    }
    if ($GLOBALS['password_expiration_days'] != 0) {
        $exp_days = $GLOBALS['password_expiration_days'];
        $exp_date = date('Y-m-d', strtotime("+{$exp_days} days"));
        privStatement("update users set pwd_expiration_date=? where id=?", array($exp_date, $targetUser));
    }
    return true;
}
/**
 * 
 * @param type $username
 * @param type $password    password is passed by reference so that it can be "cleared out"
 *                          as soon as we are done with it.
 * @param type $provider
 */
function validate_user_password($username, &$password, $provider)
{
    $ip = $_SERVER['REMOTE_ADDR'];
    $valid = false;
    $getUserSecureSQL = " SELECT " . implode(",", array(COL_ID, COL_PWD, COL_SALT)) . " FROM " . TBL_USERS_SECURE . " WHERE BINARY " . COL_UNM . "=?";
    // Use binary keyword to require case sensitive username match
    $userSecure = privQuery($getUserSecureSQL, array($username));
    if (is_array($userSecure)) {
        $phash = oemr_password_hash($password, $userSecure[COL_SALT]);
        if ($phash != $userSecure[COL_PWD]) {
            return false;
        }
        $valid = true;
    } else {
        if (!isset($GLOBALS['password_compatibility']) || $GLOBALS['password_compatibility']) {
            $getUserSQL = "select username,id, password from users where BINARY username = ?";
            $userInfo = privQuery($getUserSQL, array($username));
            if ($userInfo === false) {
                return false;
            }
            $username = $userInfo['username'];
            $dbPasswordLen = strlen($userInfo['password']);
            if ($dbPasswordLen == 32) {
                $phash = md5($password);
                $valid = $phash == $userInfo['password'];
            } else {
                if ($dbPasswordLen == 40) {
                    $phash = sha1($password);
                    $valid = $phash == $userInfo['password'];
                }
            }
            if ($valid) {
                $phash = initializePassword($username, $userInfo['id'], $password);
                purgeCompatabilityPassword($username, $userInfo['id']);
                $_SESSION['relogin'] = 1;
            } else {
                return false;
            }
        }
    }
    $getUserSQL = "select id, authorized, see_auth" . ", cal_ui, active " . " from users where BINARY username = ?";
    $userInfo = privQuery($getUserSQL, array($username));
    if ($userInfo['active'] != 1) {
        newEvent('login', $username, $provider, 0, "failure: {$ip}. user not active or not found in users table");
        $password = '';
        return false;
    }
    // Done with the cleartext password at this point!
    $password = '';
    if ($valid) {
        if ($authGroup = privQuery("select * from groups where user=? and name=?", array($username, $provider))) {
            $_SESSION['authUser'] = $username;
            $_SESSION['authPass'] = $phash;
            $_SESSION['authGroup'] = $authGroup['name'];
            $_SESSION['authUserID'] = $userInfo['id'];
            $_SESSION['authProvider'] = $provider;
            $_SESSION['authId'] = $userInfo['id'];
            $_SESSION['cal_ui'] = $userInfo['cal_ui'];
            $_SESSION['userauthorized'] = $userInfo['authorized'];
            // Some users may be able to authorize without being providers:
            if ($userInfo['see_auth'] > '2') {
                $_SESSION['userauthorized'] = '1';
            }
            newEvent('login', $username, $provider, 1, "success: {$ip}");
            $valid = true;
        } else {
            newEvent('login', $username, $provider, 0, "failure: {$ip}. user not in group: {$provider}");
            $valid = false;
        }
    }
    return $valid;
}
    if ($emailFlag) {
        $message = "<br><br>" . htmlspecialchars(xl("Email was sent to following address"), ENT_NOQUOTES) . ": " . htmlspecialchars($patientData['email'], ENT_NOQUOTES) . "<br><br>" . $message;
    }
    echo "<html><body onload='top.printLogPrint(window);'>" . $message . "</body></html>";
}
if (isset($_REQUEST['form_save']) && $_REQUEST['form_save'] == 'SUBMIT') {
    require_once "{$srcdir}/authentication/common_operations.php";
    $clear_pass = $_REQUEST['pwd'];
    $res = sqlStatement("SELECT * FROM patient_access_" . add_escape_custom($portalsite) . "site WHERE pid=?", array($pid));
    $query_parameters = array($_REQUEST['uname']);
    $salt_clause = "";
    if ($portalsite == 'on') {
        // For onsite portal create a blowfish based hash and salt.
        $new_salt = oemr_password_salt();
        $salt_clause = ",portal_salt=? ";
        array_push($query_parameters, oemr_password_hash($clear_pass, $new_salt), $new_salt);
    } else {
        // For offsite portal still create and SHA1 hashed password
        // When offsite portal is updated to handle blowfish, then both portals can use the same execution path.
        array_push($query_parameters, SHA1($clear_pass));
    }
    array_push($query_parameters, $pid);
    if (sqlNumRows($res)) {
        sqlStatement("UPDATE patient_access_" . add_escape_custom($portalsite) . "site SET portal_username=?,portal_pwd=?,portal_pwd_status=0 " . $salt_clause . " WHERE pid=?", $query_parameters);
    } else {
        sqlStatement("INSERT INTO patient_access_" . add_escape_custom($portalsite) . "site SET portal_username=?,portal_pwd=?,portal_pwd_status=0" . $salt_clause . " ,pid=?", $query_parameters);
    }
    // Create the message
    $message = messageCreate($_REQUEST['uname'], $clear_pass, $portalsite);
    // Email and display/print the message
    if (emailLogin($pid, $message)) {
                    }

        if ($auth['pid'] != $userData['pid']) {
            // Not sure if this is even possible, but should escape if this happens
            session_destroy();
            header('Location: '.$landingpage.'&w');
            exit;
        }

        if ( $password_update)
            {
                $code_new=$_POST['pass_new'];
                $code_new_confirm=$_POST['pass_new_confirm'];
                if(!(empty($_POST['pass_new'])) && !(empty($_POST['pass_new_confirm'])) && ($code_new == $code_new_confirm)) {
                $new_salt=oemr_password_salt();
                $new_hash=oemr_password_hash($code_new,$new_salt);

                // Update the password and continue (patient is authorized)
                privStatement("UPDATE ".TBL_PAT_ACC_ON
                              ."  SET ".COL_POR_PWD."=?,".COL_POR_SALT."=?,".COL_POR_PWD_STAT."=1 WHERE id=?", array($new_hash,$new_salt,$auth['id']) );
                $authorizedPortal = true;
            }
        }
        if ($auth['portal_pwd_status'] == 0) {
            if(!$authorizedPortal) {
                // Need to enter a new password in the index.php script
                $_SESSION['password_update'] = 1;
                                header('Location: '.$landingpage);
                exit;
            }
        }