hestia-sso.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /* Hestia way to enable support for SSO to PHPmyAdmin */
  3. /* To install please run v-add-sys-pma-sso */
  4. /* Following keys will get replaced when calling v-add-sys-pma-sso */
  5. define('PHPMYADMIN_KEY', '%PHPMYADMIN_KEY%');
  6. define('API_HOST_NAME', '%API_HOST_NAME%');
  7. define('API_HESTIA_PORT', '%API_HESTIA_PORT%');
  8. define('API_KEY', '%API_KEY%');
  9. class Hestia_API
  10. {
  11. private $api_url;
  12. public function __construct()
  13. {
  14. $this -> hostname = 'https://' . API_HOST_NAME . ':' . API_HESTIA_PORT .'/api/';
  15. $this -> key = API_KEY;
  16. $this -> pma_key = PHPMYADMIN_KEY;
  17. }
  18. /* Creates curl request */
  19. public function request($postvars)
  20. {
  21. $postdata = http_build_query($postvars);
  22. $curl = curl_init();
  23. curl_setopt($curl, CURLOPT_URL, $this -> hostname);
  24. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  25. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  26. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  27. curl_setopt($curl, CURLOPT_POST, true);
  28. curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
  29. $answer = curl_exec($curl);
  30. return $answer;
  31. }
  32. /* Creates an new temp user in mysql */
  33. public function create_temp_user($database, $user, $host)
  34. {
  35. $post_request = array(
  36. 'hash' => $this -> key,
  37. 'returncode' => 'no',
  38. 'cmd' => 'v-add-database-temp-user',
  39. 'arg1' => $user,
  40. 'arg2' => $database,
  41. 'arg3' => 'mysql',
  42. 'arg4' => $host
  43. );
  44. $request = $this -> request($post_request);
  45. $json = json_decode($request);
  46. if (json_last_error() == JSON_ERROR_NONE) {
  47. return $json;
  48. } else {
  49. trigger_error('Unable to connect over API please check api connection', E_USER_WARNING);
  50. return false;
  51. }
  52. }
  53. /* Delete an new temp user in mysql */
  54. public function delete_temp_user($database, $user, $dbuser, $host)
  55. {
  56. $post_request = array(
  57. 'hash' => $this -> key,
  58. 'returncode' => 'yes',
  59. 'cmd' => 'v-delete-database-temp-user',
  60. 'arg1' => $user,
  61. 'arg2' => $database,
  62. 'arg3' => $dbuser,
  63. 'arg4' => 'mysql',
  64. 'arg5' => $host
  65. );
  66. $request = $this -> request($post_request);
  67. if (is_numeric($request) && $request == 0) {
  68. return true;
  69. } else {
  70. return false;
  71. }
  72. }
  73. public function get_user_ip()
  74. {
  75. // Saving user IPs to the session for preventing session hijacking
  76. $user_combined_ip = array();
  77. if ($_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) {
  78. $user_combined_ip[] = $_SERVER['REMOTE_ADDR'];
  79. }
  80. if (isset($_SERVER['HTTP_CLIENT_IP'])) {
  81. $user_combined_ip .= '|'. $_SERVER['HTTP_CLIENT_IP'];
  82. }
  83. if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  84. if ($_SERVER['REMOTE_ADDR'] != $_SERVER['HTTP_X_FORWARDED_FOR']) {
  85. $user_combined_ip[] = $_SERVER['HTTP_X_FORWARDED_FOR'];
  86. }
  87. }
  88. if (isset($_SERVER['HTTP_FORWARDED_FOR'])) {
  89. if ($_SERVER['REMOTE_ADDR'] != $_SERVER['HTTP_FORWARDED_FOR']) {
  90. $user_combined_ip[] = $_SERVER['HTTP_FORWARDED_FOR'];
  91. }
  92. }
  93. if (isset($_SERVER['HTTP_X_FORWARDED'])) {
  94. if ($_SERVER['REMOTE_ADDR'] != $_SERVER['HTTP_X_FORWARDED']) {
  95. $user_combined_ip[] = $_SERVER['HTTP_X_FORWARDED'];
  96. }
  97. }
  98. if (isset($_SERVER['HTTP_FORWARDED'])) {
  99. if ($_SERVER['REMOTE_ADDR'] != $_SERVER['HTTP_FORWARDED']) {
  100. $user_combined_ip[] = '|'. $_SERVER['HTTP_FORWARDED'];
  101. }
  102. }
  103. if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
  104. if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
  105. $user_combined_ip[] = $_SERVER['HTTP_CF_CONNECTING_IP'];
  106. }
  107. }
  108. return implode('|',$user_combined_ip);
  109. }
  110. }
  111. /* Need to have cookie visible from parent directory */
  112. session_set_cookie_params(0, '/', '', true, true);
  113. /* Create signon session */
  114. $session_name = 'SignonSession';
  115. session_name($session_name);
  116. @session_start();
  117. function session_invalid()
  118. {
  119. global $session_name;
  120. //delete all current sessions
  121. session_destroy();
  122. setcookie($session_name, null, -1, '/');
  123. header("Location: " . dirname($_SERVER['PHP_SELF']) . "/index.php");
  124. die();
  125. }
  126. $api = new Hestia_API();
  127. if (!empty($_GET)) {
  128. if (isset($_GET['logout'])) {
  129. $api -> delete_temp_user($_SESSION['HESTIA_sso_database'], $_SESSION['HESTIA_sso_user'], $_SESSION['PMA_single_signon_user'], $_SESSION['HESTIA_sso_host']);
  130. //remove sessin
  131. session_invalid();
  132. header("Location: " . dirname($_SERVER['PHP_SELF']) . "/index.php");
  133. die();
  134. } else {
  135. if (isset($_GET['user']) && isset($_GET['hestia_token'])) {
  136. $database = $_GET['database'];
  137. $user = $_GET['user'];
  138. $host = 'localhost';
  139. $token = $_GET['hestia_token'];
  140. $time = $_GET['exp'];
  141. if ($time + 60 > time()) {
  142. //note: Possible issues with cloudflare due to ip obfuscation
  143. $ip = $api -> get_user_ip();
  144. if (!password_verify($database.$user.$ip.$time.PHPMYADMIN_KEY, $token)) {
  145. trigger_error('Access denied: There is a security token mismatch '. $time, E_USER_WARNING);
  146. session_invalid();
  147. die();
  148. session_invalid();
  149. } else {
  150. $id = session_id();
  151. //create a new temp user
  152. $data = $api -> create_temp_user($database, $user, $host);
  153. if ($data) {
  154. $_SESSION['PMA_single_signon_user'] = $data -> login -> user;
  155. $_SESSION['PMA_single_signon_password'] = $data -> login -> password ;
  156. $_SESSION['PMA_single_signon_host'] = $host;
  157. //save database / username to be used for sending logout notification.
  158. $_SESSION['HESTIA_sso_user'] = $user;
  159. $_SESSION['HESTIA_sso_database'] = $database;
  160. $_SESSION['HESTIA_sso_host'] = $host;
  161. @session_write_close();
  162. setcookie($session_name, $id, 0, "/");
  163. header("Location: " . dirname($_SERVER['PHP_SELF']) . "/index.php");
  164. } else {
  165. session_invalid();
  166. }
  167. die();
  168. }
  169. } else {
  170. trigger_error('Link has been expired: System time: '. time() .' / Time provided in link: '. $time, E_USER_WARNING);
  171. session_invalid();
  172. die();
  173. }
  174. }
  175. }
  176. } else {
  177. session_invalid();
  178. die();
  179. }