Bootswatch, Summernote, and Captcheck mods for Mods for HESK (mods-for-hesk.com). In use at support.netsyms.com.
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.

password.php 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. /**
  3. *
  4. * This file is part of HESK - PHP Help Desk Software.
  5. *
  6. * (c) Copyright Klemen Stirn. All rights reserved.
  7. * https://www.hesk.com
  8. *
  9. * For the full copyright and license agreement information visit
  10. * https://www.hesk.com/eula.php
  11. *
  12. */
  13. define('IN_SCRIPT', 1);
  14. define('HESK_PATH', '../');
  15. define('PAGE_TITLE', 'LOGIN');
  16. /* Get all the required files and functions */
  17. require(HESK_PATH . 'hesk_settings.inc.php');
  18. require(HESK_PATH . 'inc/common.inc.php');
  19. // Connect to database and check for brute force attempts
  20. hesk_load_database_functions();
  21. hesk_dbConnect();
  22. $modsForHesk_settings = mfh_getSettings();
  23. // Is the password reset function enabled?
  24. if (!$hesk_settings['reset_pass']) {
  25. die($hesklang['attempt']);
  26. }
  27. // Allow additional 5 attempts in case the user is already blocked
  28. $hesk_settings['attempt_limit'] += 5;
  29. // Start session
  30. hesk_session_start();
  31. if (!isset($_SESSION['a_iserror'])) {
  32. $_SESSION['a_iserror'] = array();
  33. }
  34. $hesk_error_buffer = array();
  35. // If this is a POST method, check input
  36. if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  37. // Verify security image
  38. if ($hesk_settings['secimg_use']) {
  39. // Using ReCaptcha?
  40. if ($hesk_settings['recaptcha_use'] == 1) {
  41. require_once(HESK_PATH . 'inc/recaptcha/recaptchalib.php');
  42. $resp = recaptcha_check_answer($hesk_settings['recaptcha_private_key'],
  43. hesk_getClientIP(),
  44. hesk_POST('recaptcha_challenge_field', ''),
  45. hesk_POST('recaptcha_response_field', '')
  46. );
  47. if ($resp->is_valid) {
  48. //$_SESSION['img_a_verified']=true;
  49. } else {
  50. $hesk_error_buffer['mysecnum'] = $hesklang['recaptcha_error'];
  51. }
  52. } // Using ReCaptcha API v2?
  53. elseif ($hesk_settings['recaptcha_use'] == 2) {
  54. require(HESK_PATH . 'inc/recaptcha/recaptchalib_v2.php');
  55. $resp = null;
  56. $reCaptcha = new ReCaptcha($hesk_settings['recaptcha_private_key']);
  57. // Was there a reCAPTCHA response?
  58. if (isset($_POST["g-recaptcha-response"])) {
  59. $resp = $reCaptcha->verifyResponse(hesk_getClientIP(), hesk_POST("g-recaptcha-response"));
  60. }
  61. if ($resp != null && $resp->success) {
  62. //$_SESSION['img_a_verified']=true;
  63. } else {
  64. $hesk_error_buffer['mysecnum'] = $hesklang['recaptcha_error'];
  65. }
  66. } // Using PHP generated image
  67. else {
  68. $mysecnum = intval(hesk_POST('mysecnum', 0));
  69. if (empty($mysecnum)) {
  70. $hesk_error_buffer['mysecnum'] = $hesklang['sec_miss'];
  71. } else {
  72. require(HESK_PATH . 'inc/secimg.inc.php');
  73. $sc = new PJ_SecurityImage($hesk_settings['secimg_sum']);
  74. if (isset($_SESSION['checksum']) && $sc->checkCode($mysecnum, $_SESSION['checksum'])) {
  75. //$_SESSION['img_a_verified'] = true;
  76. } else {
  77. $hesk_error_buffer['mysecnum'] = $hesklang['sec_wrng'];
  78. }
  79. }
  80. }
  81. }
  82. hesk_limitBfAttempts();
  83. // Get email
  84. $email = hesk_validateEmail(hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer['email'] = $hesklang['enter_valid_email'];
  85. // Any errors?
  86. if (count($hesk_error_buffer) != 0) {
  87. $_SESSION['a_iserror'] = array_keys($hesk_error_buffer);
  88. $tmp = '';
  89. foreach ($hesk_error_buffer as $error) {
  90. $tmp .= "<li>$error</li>\n";
  91. }
  92. $hesk_error_buffer = $tmp;
  93. $hesk_error_buffer = $hesklang['pcer'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
  94. hesk_process_messages($hesk_error_buffer, 'NOREDIRECT');
  95. } elseif (defined('HESK_DEMO')) {
  96. hesk_process_messages($hesklang['ddemo'], 'NOREDIRECT');
  97. } else {
  98. // Get user data from the database
  99. $res = hesk_dbQuery("SELECT `id`, `name`, `pass` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `email` LIKE '" . hesk_dbEscape($email) . "' LIMIT 1");
  100. if (hesk_dbNumRows($res) != 1) {
  101. hesk_process_messages($hesklang['noace'], 'NOREDIRECT');
  102. } else {
  103. $row = hesk_dbFetchAssoc($res);
  104. $hash = sha1(microtime() . hesk_getClientIP() . mt_rand() . $row['id'] . $row['name'] . $row['pass']);
  105. // Insert the verification hash into the database
  106. hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reset_password` (`user`, `hash`, `ip`) VALUES (" . intval($row['id']) . ", '{$hash}', '" . hesk_dbEscape($_SERVER['REMOTE_ADDR']) . "') ");
  107. // Prepare and send email
  108. require(HESK_PATH . 'inc/email_functions.inc.php');
  109. // Get the email message
  110. $msg = hesk_getEmailMessage('reset_password', array(), $modsForHesk_settings, 1, 0, 1);
  111. $htmlMsg = hesk_getHtmlMessage('reset_password', array(), $modsForHesk_settings, 1, 0, 1);
  112. // Replace message special tags
  113. $msg = str_replace('%%NAME%%', hesk_msgToPlain($row['name'], 1, 1), $msg);
  114. $msg = str_replace('%%SITE_URL%%', $hesk_settings['site_url'], $msg);
  115. $msg = str_replace('%%SITE_TITLE%%', $hesk_settings['site_title'], $msg);
  116. $msg = str_replace('%%PASSWORD_RESET%%', $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/password.php?h=' . $hash, $msg);
  117. $htmlMsg = str_replace('%%NAME%%', hesk_msgToPlain($row['name'], 1, 1), $htmlMsg);
  118. $htmlMsg = str_replace('%%SITE_URL%%', $hesk_settings['site_url'], $htmlMsg);
  119. $htmlMsg = str_replace('%%SITE_TITLE%%', $hesk_settings['site_title'], $htmlMsg);
  120. $htmlMsg = str_replace('%%PASSWORD_RESET%%', $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/password.php?h=' . $hash, $htmlMsg);
  121. // Send email
  122. hesk_mail($email, $hesklang['reset_password'], $msg, $htmlMsg, $modsForHesk_settings);
  123. // Show success
  124. hesk_process_messages($hesklang['pemls'], 'NOREDIRECT', 'SUCCESS');
  125. }
  126. }
  127. } // If the "h" parameter is set verify it and reset the password
  128. elseif (isset($_GET['h'])) {
  129. // Get the hash
  130. $hash = preg_replace('/[^a-zA-Z0-9]/', '', $_GET['h']);
  131. // Connect to database
  132. hesk_dbConnect();
  133. // Expire verification hashes older than 2 hours
  134. hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reset_password` WHERE `dt` < (NOW() - INTERVAL 2 HOUR)");
  135. // Verify the hash exists
  136. $res = hesk_dbQuery("SELECT `user`, `ip` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reset_password` WHERE `hash` = '{$hash}' LIMIT 1");
  137. if (hesk_dbNumRows($res) != 1) {
  138. // Not a valid hash
  139. hesk_limitBfAttempts();
  140. hesk_process_messages($hesklang['ehash'], 'NOREDIRECT');
  141. } else {
  142. // Get info from database
  143. $row = hesk_dbFetchAssoc($res);
  144. // Only allow resetting password from the same IP address that submitted password reset request
  145. if ($row['ip'] != $_SERVER['REMOTE_ADDR']) {
  146. hesk_limitBfAttempts();
  147. hesk_process_messages($hesklang['ehaip'], 'NOREDIRECT');
  148. } else {
  149. // Expire all verification hashes for this user
  150. hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reset_password` WHERE `user`=" . intval($row['user']));
  151. // Load additional required functions
  152. require(HESK_PATH . 'inc/admin_functions.inc.php');
  153. // Get user details
  154. $res = hesk_dbQuery('SELECT * FROM `' . $hesk_settings['db_pfix'] . "users` WHERE `id`=" . intval($row['user']) . " LIMIT 1");
  155. $row = hesk_dbFetchAssoc($res);
  156. foreach ($row as $k => $v) {
  157. $_SESSION[$k] = $v;
  158. }
  159. // Set a tag that will be used to expire sessions after username or password change
  160. $_SESSION['session_verify'] = hesk_activeSessionCreateTag($_SESSION['user'], $_SESSION['pass']);
  161. // We don't need the password hash anymore
  162. unset($_SESSION['pass']);
  163. // Clean brute force attempts
  164. hesk_cleanBfAttempts();
  165. // Regenerate session ID (security)
  166. hesk_session_regenerate_id();
  167. // Get allowed categories
  168. if (empty($_SESSION['isadmin'])) {
  169. $_SESSION['categories'] = explode(',', $_SESSION['categories']);
  170. }
  171. // Redirect to the profile page
  172. hesk_process_messages($hesklang['resim'], 'profile.php', 'NOTICE');
  173. exit();
  174. } // End IP matches
  175. }
  176. }
  177. // Tell header to load reCaptcha API if needed
  178. if ($hesk_settings['recaptcha_use'] == 2) {
  179. define('RECAPTCHA', 1);
  180. }
  181. $hesk_settings['tmp_title'] = $hesk_settings['hesk_title'] . ' - ' . $hesklang['passr'];
  182. require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
  183. ?>
  184. <div class="login-box">
  185. <div class="login-logo">
  186. <?php echo $hesk_settings['hesk_title']; ?>
  187. </div>
  188. <div class="login-box-body">
  189. <h4 class="login-box-msg">
  190. <?php echo $hesklang['passr']; ?>
  191. </h4>
  192. <form action="password.php" method="post" name="form1" class="form-horizontal" role="form">
  193. <?php
  194. /* This will handle error, success and notice messages */
  195. hesk_handle_messages();
  196. $has_error = '';
  197. if (in_array('email', $_SESSION['a_iserror'])) {
  198. $has_error = 'has-error';
  199. }
  200. $form_email = '';
  201. if (isset($email)) {
  202. $form_email = stripslashes(hesk_input($email));
  203. }
  204. ?>
  205. <div class="form-group <?php echo $has_error; ?>">
  206. <label for="email" class="col-sm-3 control-label">
  207. <?php echo $hesklang['email']; ?>
  208. </label>
  209. <div class="col-sm-9">
  210. <input type="text" name="email" size="35" value="<?php echo $form_email; ?>"
  211. class="form-control" placeholder="<?php echo htmlspecialchars($hesklang['email']); ?>">
  212. </div>
  213. </div>
  214. <?php
  215. if ($hesk_settings['secimg_use']) {
  216. ?>
  217. <div class="form-group">
  218. <div class="col-sm-11 col-sm-offset-1">
  219. <?php
  220. // Should we use Recaptcha?
  221. if ($hesk_settings['recaptcha_use'] == 1) {
  222. ?>
  223. <script type="text/javascript">
  224. var RecaptchaOptions = {
  225. theme: '<?php echo ( isset($_SESSION['a_iserror']) && in_array('mysecnum',$_SESSION['a_iserror']) ) ? 'red' : 'white'; ?>',
  226. custom_translations: {
  227. visual_challenge: "<?php echo hesk_slashJS($hesklang['visual_challenge']); ?>",
  228. audio_challenge: "<?php echo hesk_slashJS($hesklang['audio_challenge']); ?>",
  229. refresh_btn: "<?php echo hesk_slashJS($hesklang['refresh_btn']); ?>",
  230. instructions_visual: "<?php echo hesk_slashJS($hesklang['instructions_visual']); ?>",
  231. instructions_context: "<?php echo hesk_slashJS($hesklang['instructions_context']); ?>",
  232. instructions_audio: "<?php echo hesk_slashJS($hesklang['instructions_audio']); ?>",
  233. help_btn: "<?php echo hesk_slashJS($hesklang['help_btn']); ?>",
  234. play_again: "<?php echo hesk_slashJS($hesklang['play_again']); ?>",
  235. cant_hear_this: "<?php echo hesk_slashJS($hesklang['cant_hear_this']); ?>",
  236. incorrect_try_again: "<?php echo hesk_slashJS($hesklang['incorrect_try_again']); ?>",
  237. image_alt_text: "<?php echo hesk_slashJS($hesklang['image_alt_text']); ?>"
  238. }
  239. };
  240. </script>
  241. <?php
  242. require_once(HESK_PATH . 'inc/recaptcha/recaptchalib.php');
  243. echo recaptcha_get_html($hesk_settings['recaptcha_public_key'], null, true);
  244. }
  245. // Use reCaptcha API v2?
  246. elseif ($hesk_settings['recaptcha_use'] == 2)
  247. {
  248. ?>
  249. <div class="g-recaptcha"
  250. data-sitekey="<?php echo $hesk_settings['recaptcha_public_key']; ?>"></div>
  251. <?php
  252. }
  253. // At least use some basic PHP generated image (better than nothing)
  254. else {
  255. $cls = in_array('mysecnum', $_SESSION['a_iserror']) ? ' class="isError" ' : '';
  256. echo $hesklang['sec_enter'] . '<br />&nbsp;<br /><img src="' . HESK_PATH . 'print_sec_img.php?' . rand(10000, 99999) . '" width="150" height="40" alt="' . $hesklang['sec_img'] . '" title="' . $hesklang['sec_img'] . '" border="1" name="secimg" style="vertical-align:text-bottom" /> ' .
  257. '<a href="javascript:void(0)" onclick="javascript:document.form1.secimg.src=\'' . HESK_PATH . 'print_sec_img.php?\'+ ( Math.floor((90000)*Math.random()) + 10000);"><img src="' . HESK_PATH . 'img/reload.png" height="24" width="24" alt="' . $hesklang['reload'] . '" title="' . $hesklang['reload'] . '" border="0" style="vertical-align:text-bottom" /></a>' .
  258. '<br />&nbsp;<br /><input type="text" name="mysecnum" size="20" maxlength="5" ' . $cls . ' />';
  259. }
  260. ?>
  261. </div>
  262. </div>
  263. <?php
  264. }
  265. ?>
  266. <div class="form-group">
  267. <div class="col-sm-9 col-sm-offset-3">
  268. <input type="submit" value="<?php echo $hesklang['passs']; ?>" class="btn btn-default">
  269. </div>
  270. </div>
  271. </form>
  272. </div>
  273. </div>
  274. <?php
  275. // Clean session errors
  276. hesk_cleanSessionVars('a_iserror');
  277. hesk_cleanSessionVars('img_a_verified');
  278. ?>