index.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <?php
  2. use function Hestiacp\quoteshellarg\quoteshellarg;
  3. // Init
  4. define("NO_AUTH_REQUIRED", true);
  5. define("NO_AUTH_REQUIRED2", true);
  6. header("Content-Type: text/plain; charset=utf-8");
  7. include $_SERVER["DOCUMENT_ROOT"] . "/inc/main.php";
  8. // Checking IP of incoming connection, checking is it NAT address
  9. $ok = 0;
  10. $ip = $_SERVER["REMOTE_ADDR"];
  11. exec(HESTIA_CMD . "v-list-sys-ips json", $output, $return_var);
  12. $output = implode("", $output);
  13. $arr = json_decode($output, true);
  14. foreach ($arr as $arr_key => $arr_val) {
  15. // search for NAT IPs and allow them
  16. if ($ip == $arr_key || $ip == $arr_val["NAT"]) {
  17. $ok = 1;
  18. break;
  19. }
  20. }
  21. if ($ip == $_SERVER["SERVER_ADDR"]) {
  22. $ok = 1;
  23. }
  24. if ($ip == "127.0.0.1") {
  25. $ok = 1;
  26. }
  27. if ($ok == 0) {
  28. exit();
  29. }
  30. if (isset($_SERVER["HTTP_X_REAL_IP"]) || isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
  31. exit();
  32. }
  33. // Check arguments
  34. if (empty($_POST["email"])) {
  35. echo "error email address not provided";
  36. exit();
  37. }
  38. if (empty($_POST["password"])) {
  39. echo "error old password provided";
  40. exit();
  41. }
  42. if (empty($_POST["new"])) {
  43. echo "error new password not provided";
  44. exit();
  45. }
  46. [$v_account, $v_domain] = explode("@", $_POST["email"]);
  47. $v_domain = quoteshellarg($v_domain);
  48. $v_account = quoteshellarg($v_account);
  49. $v_password = $_POST["password"];
  50. // Get domain owner
  51. exec(HESTIA_CMD . "v-search-domain-owner " . $v_domain . " 'mail'", $output, $return_var);
  52. if ($return_var != 0 || empty($output[0])) {
  53. echo "error domain owner not found";
  54. exit();
  55. }
  56. $v_user = $output[0];
  57. unset($output);
  58. // Get current password hash (called "md5" for legacy reasons, it's not guaranteed to be md5)
  59. exec(
  60. HESTIA_CMD .
  61. "v-get-mail-account-value " .
  62. quoteshellarg($v_user) .
  63. " " .
  64. $v_domain .
  65. " " .
  66. $v_account .
  67. " 'md5'",
  68. $output,
  69. $return_var,
  70. );
  71. if ($return_var != 0 || empty($output[0])) {
  72. echo "error unable to get current account password hash";
  73. exit();
  74. }
  75. $v_hash = $output[0];
  76. unset($output);
  77. // v_hash use doveadm password hash format, which is basically {HASH_NAME}normal_crypt_format,
  78. // so we just need to remove the {HASH_NAME} before we can ask password_verify if its correct or not.
  79. $hash_for_password_verify = explode("}", $v_hash, 2);
  80. $hash_for_password_verify = end($hash_for_password_verify);
  81. if (!password_verify($v_password, $hash_for_password_verify)) {
  82. die("error old password does not match");
  83. }
  84. // Change password
  85. $fp = tmpfile();
  86. $new_password_file = stream_get_meta_data($fp)["uri"];
  87. fwrite($fp, $_POST["new"] . "\n");
  88. exec(
  89. HESTIA_CMD .
  90. "v-change-mail-account-password " .
  91. quoteshellarg($v_user) .
  92. " " .
  93. $v_domain .
  94. " " .
  95. $v_account .
  96. " " .
  97. quoteshellarg($new_password_file),
  98. $output,
  99. $return_var,
  100. );
  101. fclose($fp);
  102. if ($return_var == 0) {
  103. echo "==ok==";
  104. exit();
  105. }
  106. echo "error v-change-mail-account-password returned non-zero: " . $return_var;
  107. exit();