You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
11 KiB

<?php
/**
* portal/get_patient_info.php
*
* @package OpenEMR
* @link https://www.open-emr.org
* @author Cassian LUP <cassi.lup@gmail.com>
* @author Jerry Padgett <sjpadgett@gmail.com>
* @author Brady Miller <brady.g.miller@gmail.com>
* @copyright Copyright (c) 2011 Cassian LUP <cassi.lup@gmail.com>
* @copyright Copyright (c) 2016-2017 Jerry Padgett <sjpadgett@gmail.com>
* @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com>
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
*/
// starting the PHP session
// Will start the (patient) portal OpenEMR session/cookie.
require_once(dirname(__FILE__) . "/../src/Common/Session/SessionUtil.php");
OpenEMR\Common\Session\SessionUtil::portalSessionStart();
// regenerating the session id to avoid session fixation attacks
session_regenerate_id(true);
//
// landing page definition -- where to go if something goes wrong
$landingpage = "index.php?site=" . urlencode($_SESSION['site_id'] ?? ($_GET['site'] ?? 'default'));
//
// checking whether the request comes from index.php
if (!isset($_SESSION['itsme'])) {
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w');
exit();
}
// some validation
if (!isset($_POST['uname']) || empty($_POST['uname'])) {
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w&c');
exit();
}
if (!isset($_POST['pass']) || empty($_POST['pass'])) {
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w&c');
exit();
}
// set the language
if (!empty($_POST['languageChoice'])) {
$_SESSION['language_choice'] = (int)$_POST['languageChoice'];
} elseif (empty($_SESSION['language_choice'])) {
// just in case both are empty, then use english
$_SESSION['language_choice'] = 1;
} else {
// keep the current session language token
}
// Settings that will override globals.php
$ignoreAuth_onsite_portal = true;
//
// Authentication
require_once('../interface/globals.php');
require_once(dirname(__FILE__) . "/lib/appsql.class.php");
require_once("$srcdir/user.inc");
use OpenEMR\Common\Auth\AuthHash;
use OpenEMR\Common\Csrf\CsrfUtils;
$logit = new ApplicationTable();
$password_update = isset($_SESSION['password_update']) ? $_SESSION['password_update'] : 0;
unset($_SESSION['password_update']);
$authorizedPortal = false; // flag
DEFINE("TBL_PAT_ACC_ON", "patient_access_onsite");
DEFINE("COL_ID", "id");
DEFINE("COL_PID", "pid");
DEFINE("COL_POR_PWD", "portal_pwd");
DEFINE("COL_POR_USER", "portal_username");
DEFINE("COL_POR_LOGINUSER", "portal_login_username");
DEFINE("COL_POR_PWD_STAT", "portal_pwd_status");
DEFINE("COL_POR_ONETIME", "portal_onetime");
// 2 is flag for one time credential reset else 1 = normal reset.
// one time reset requires a PIN where normal uses a new temp pass sent to user.
if ($password_update === 2 && !empty($_SESSION['pin'])) {
$sql = "SELECT " . implode(",", array(
COL_ID, COL_PID, COL_POR_PWD, COL_POR_USER, COL_POR_LOGINUSER, COL_POR_PWD_STAT, COL_POR_ONETIME)) . " FROM " . TBL_PAT_ACC_ON .
" WHERE BINARY " . COL_POR_ONETIME . "= ?";
$auth = privQuery($sql, array($_SESSION['forward']));
if ($auth !== false) {
// remove the token from database
privStatement("UPDATE " . TBL_PAT_ACC_ON . " SET " . COL_POR_ONETIME . "=NULL WHERE BINARY " . COL_POR_ONETIME . " = ?", [$auth['portal_onetime']]);
// validation
$validate = substr($auth[COL_POR_ONETIME], 32, 6);
if (!empty($validate) && !empty($_POST['token_pin'])) {
if ($_SESSION['pin'] !== $_POST['token_pin']) {
$auth = false;
} elseif ($validate !== $_POST['token_pin']) {
$auth = false;
}
} else {
$auth = false;
}
unset($_SESSION['forward']);
unset($_SESSION['pin']);
unset($_POST['token_pin']);
}
} else {
// normal login
$sql = "SELECT " . implode(",", array(
COL_ID, COL_PID, COL_POR_PWD, COL_POR_USER, COL_POR_LOGINUSER, COL_POR_PWD_STAT)) . " FROM " . TBL_PAT_ACC_ON .
" WHERE " . COL_POR_LOGINUSER . "= ?";
if ($password_update === 1) {
$sql = "SELECT " . implode(",", array(
COL_ID, COL_PID, COL_POR_PWD, COL_POR_USER, COL_POR_LOGINUSER, COL_POR_PWD_STAT)) . " FROM " . TBL_PAT_ACC_ON .
" WHERE " . COL_POR_USER . "= ?";
}
$auth = privQuery($sql, array($_POST['uname']));
}
if ($auth === false) {
$logit->portalLog('login attempt', '', ($_POST['uname'] . ':invalid username'), '', '0');
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w&u');
exit();
}
if ($password_update === 2) {
if ($_POST['pass'] != $auth[COL_POR_PWD]) {
$logit->portalLog('login attempt', '', ($_POST['uname'] . ':invalid password'), '', '0');
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w&p');
exit();
}
} else {
if (AuthHash::passwordVerify($_POST['pass'], $auth[COL_POR_PWD])) {
$authHashPortal = new AuthHash('auth');
if ($authHashPortal->passwordNeedsRehash($auth[COL_POR_PWD])) {
// If so, create a new hash, and replace the old one (this will ensure always using most modern hashing)
$reHash = $authHashPortal->passwordHash($_POST['pass']);
if (empty($reHash)) {
// Something is seriously wrong
error_log('OpenEMR Error : OpenEMR is not working because unable to create a hash.');
die("OpenEMR Error : OpenEMR is not working because unable to create a hash.");
}
privStatement(
"UPDATE " . TBL_PAT_ACC_ON . " SET " . COL_POR_PWD . " = ? WHERE " . COL_ID . " = ?",
[
$reHash,
$auth[COL_ID]
]
);
}
} else {
$logit->portalLog('login attempt', '', ($_POST['uname'] . ':invalid password'), '', '0');
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w&p');
exit();
}
}
$_SESSION['portal_username'] = $auth[COL_POR_USER];
$_SESSION['portal_login_username'] = $auth[COL_POR_LOGINUSER];
$sql = "SELECT * FROM `patient_data` WHERE `pid` = ?";
if ($userData = sqlQuery($sql, array($auth['pid']))) { // if query gets executed
if (empty($userData)) {
$logit->portalLog('login attempt', '', ($_POST['uname'] . ':not active patient'), '', '0');
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w');
exit();
}
if ($userData['email'] != ($_POST['passaddon'] ?? '') && $GLOBALS['enforce_signin_email']) {
$logit->portalLog('login attempt', '', ($_POST['uname'] . ':invalid email'), '', '0');
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w');
exit();
}
if ($userData['allow_patient_portal'] != "YES") {
// Patient has not authorized portal, so escape
$logit->portalLog('login attempt', '', ($_POST['uname'] . ':allow portal turned off'), '', '0');
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w');
exit();
}
if ($auth['pid'] != $userData['pid']) {
// Not sure if this is even possible, but should escape if this happens
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
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_hash = (new AuthHash('auth'))->passwordHash($code_new);
if (empty($new_hash)) {
// Something is seriously wrong
error_log('OpenEMR Error : OpenEMR is not working because unable to create a hash.');
die("OpenEMR Error : OpenEMR is not working because unable to create a hash.");
}
// Update the password and continue (patient is authorized)
privStatement(
"UPDATE " . TBL_PAT_ACC_ON . " SET " . COL_POR_LOGINUSER . "=?," . COL_POR_PWD . "=?," . COL_POR_PWD_STAT . "=1 WHERE id=?",
array(
$_POST['login_uname'],
$new_hash,
$auth['id']
)
);
$authorizedPortal = true;
$logit->portalLog('password update', $auth['pid'], ($_POST['login_uname'] . ': ' . $_SESSION['ptName'] . ':success'));
}
}
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();
}
}
if ($auth['portal_pwd_status'] == 1) {
// continue (patient is authorized)
$authorizedPortal = true;
}
if ($authorizedPortal) {
// patient is authorized (prepare the session variables)
unset($_SESSION['password_update']); // just being safe
unset($_SESSION['itsme']); // just being safe
$_SESSION['pid'] = $auth['pid'];
$_SESSION['patient_portal_onsite_two'] = 1;
$tmp = getUserIDInfo($userData['providerID']);
$_SESSION['providerName'] = $tmp['fname'] . ' ' . $tmp['lname'];
$_SESSION['providerUName'] = $tmp['username'];
$_SESSION['sessionUser'] = '-patient-'; // $_POST['uname'];
$_SESSION['providerId'] = $userData['providerID'] ? $userData['providerID'] : 'undefined';
$_SESSION['ptName'] = $userData['fname'] . ' ' . $userData['lname'];
// never set authUserID though authUser is used for ACL!
$_SESSION['authUser'] = 'portal-user';
// Set up the csrf private_key (for the paient portal)
// Note this key always remains private and never leaves server session. It is used to create
// the csrf tokens.
CsrfUtils::setupCsrfKey();
$logit->portalLog('login', $_SESSION['pid'], ($_SESSION['portal_username'] . ': ' . $_SESSION['ptName'] . ':success'));
} else {
$logit->portalLog('login', '', ($_POST['uname'] . ':not authorized'), '', '0');
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w');
exit();
}
} else { // problem with query
OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
header('Location: ' . $landingpage . '&w');
exit();
}
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache");
header("Pragma: no-cache");
header('Location: ./home.php');
exit();