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.
		
		
		
		
		
			
		
			
				
					214 lines
				
				6.0 KiB
			
		
		
			
		
	
	
					214 lines
				
				6.0 KiB
			| 
								 
											2 years ago
										 
									 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Hestia way to enable support for SSO to PHPmyAdmin */
							 | 
						||
| 
								 | 
							
								/* To install please run v-add-sys-pma-sso */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Following keys will get replaced when calling v-add-sys-pma-sso */
							 | 
						||
| 
								 | 
							
								define("PHPMYADMIN_KEY", "%PHPMYADMIN_KEY%");
							 | 
						||
| 
								 | 
							
								define("API_HOST_NAME", "%API_HOST_NAME%");
							 | 
						||
| 
								 | 
							
								define("API_HESTIA_PORT", "%API_HESTIA_PORT%");
							 | 
						||
| 
								 | 
							
								define("API_KEY", "%API_KEY%");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Hestia_API {
							 | 
						||
| 
								 | 
							
									/** @var string */
							 | 
						||
| 
								 | 
							
									public $hostname;
							 | 
						||
| 
								 | 
							
									/** @var string */
							 | 
						||
| 
								 | 
							
									public $key;
							 | 
						||
| 
								 | 
							
									/** @var string */
							 | 
						||
| 
								 | 
							
									public $pma_key;
							 | 
						||
| 
								 | 
							
									/** @var string */
							 | 
						||
| 
								 | 
							
									private $api_url;
							 | 
						||
| 
								 | 
							
									public function __construct() {
							 | 
						||
| 
								 | 
							
										$this->hostname = "https://" . API_HOST_NAME . ":" . API_HESTIA_PORT . "/api/";
							 | 
						||
| 
								 | 
							
										$this->key = API_KEY;
							 | 
						||
| 
								 | 
							
										$this->pma_key = PHPMYADMIN_KEY;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Creates curl request */
							 | 
						||
| 
								 | 
							
									public function request($postvars) {
							 | 
						||
| 
								 | 
							
										$postdata = http_build_query($postvars);
							 | 
						||
| 
								 | 
							
										$curl = curl_init();
							 | 
						||
| 
								 | 
							
										curl_setopt($curl, CURLOPT_URL, $this->hostname);
							 | 
						||
| 
								 | 
							
										curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
							 | 
						||
| 
								 | 
							
										curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
							 | 
						||
| 
								 | 
							
										curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
							 | 
						||
| 
								 | 
							
										curl_setopt($curl, CURLOPT_POST, true);
							 | 
						||
| 
								 | 
							
										curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
							 | 
						||
| 
								 | 
							
										$answer = curl_exec($curl);
							 | 
						||
| 
								 | 
							
										return $answer;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Creates an new temp user in mysql */
							 | 
						||
| 
								 | 
							
									public function create_temp_user($database, $user, $host) {
							 | 
						||
| 
								 | 
							
										$post_request = [
							 | 
						||
| 
								 | 
							
											"hash" => $this->key,
							 | 
						||
| 
								 | 
							
											"returncode" => "no",
							 | 
						||
| 
								 | 
							
											"cmd" => "v-add-database-temp-user",
							 | 
						||
| 
								 | 
							
											"arg1" => $user,
							 | 
						||
| 
								 | 
							
											"arg2" => $database,
							 | 
						||
| 
								 | 
							
											"arg3" => "mysql",
							 | 
						||
| 
								 | 
							
											"arg4" => $host,
							 | 
						||
| 
								 | 
							
										];
							 | 
						||
| 
								 | 
							
										$request = $this->request($post_request);
							 | 
						||
| 
								 | 
							
										$json = json_decode($request);
							 | 
						||
| 
								 | 
							
										if (json_last_error() == JSON_ERROR_NONE) {
							 | 
						||
| 
								 | 
							
											return $json;
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											trigger_error("Unable to connect over API please check api connection", E_USER_WARNING);
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Delete an new temp user in mysql */
							 | 
						||
| 
								 | 
							
									public function delete_temp_user($database, $user, $dbuser, $host) {
							 | 
						||
| 
								 | 
							
										$post_request = [
							 | 
						||
| 
								 | 
							
											"hash" => $this->key,
							 | 
						||
| 
								 | 
							
											"returncode" => "yes",
							 | 
						||
| 
								 | 
							
											"cmd" => "v-delete-database-temp-user",
							 | 
						||
| 
								 | 
							
											"arg1" => $user,
							 | 
						||
| 
								 | 
							
											"arg2" => $database,
							 | 
						||
| 
								 | 
							
											"arg3" => $dbuser,
							 | 
						||
| 
								 | 
							
											"arg4" => "mysql",
							 | 
						||
| 
								 | 
							
											"arg5" => $host,
							 | 
						||
| 
								 | 
							
										];
							 | 
						||
| 
								 | 
							
										$request = $this->request($post_request);
							 | 
						||
| 
								 | 
							
										if (is_numeric($request) && $request == 0) {
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function get_user_ip() {
							 | 
						||
| 
								 | 
							
										// Saving user IPs to the session for preventing session hijacking
							 | 
						||
| 
								 | 
							
										$user_combined_ip = [];
							 | 
						||
| 
								 | 
							
										if ($_SERVER["REMOTE_ADDR"] != $_SERVER["SERVER_ADDR"]) {
							 | 
						||
| 
								 | 
							
											$user_combined_ip[] = $_SERVER["REMOTE_ADDR"];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (isset($_SERVER["HTTP_CLIENT_IP"])) {
							 | 
						||
| 
								 | 
							
											$user_combined_ip .= "|" . $_SERVER["HTTP_CLIENT_IP"];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
							 | 
						||
| 
								 | 
							
											if ($_SERVER["REMOTE_ADDR"] != $_SERVER["HTTP_X_FORWARDED_FOR"]) {
							 | 
						||
| 
								 | 
							
												$user_combined_ip[] = $_SERVER["HTTP_X_FORWARDED_FOR"];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (isset($_SERVER["HTTP_FORWARDED_FOR"])) {
							 | 
						||
| 
								 | 
							
											if ($_SERVER["REMOTE_ADDR"] != $_SERVER["HTTP_FORWARDED_FOR"]) {
							 | 
						||
| 
								 | 
							
												$user_combined_ip[] = $_SERVER["HTTP_FORWARDED_FOR"];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (isset($_SERVER["HTTP_X_FORWARDED"])) {
							 | 
						||
| 
								 | 
							
											if ($_SERVER["REMOTE_ADDR"] != $_SERVER["HTTP_X_FORWARDED"]) {
							 | 
						||
| 
								 | 
							
												$user_combined_ip[] = $_SERVER["HTTP_X_FORWARDED"];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (isset($_SERVER["HTTP_FORWARDED"])) {
							 | 
						||
| 
								 | 
							
											if ($_SERVER["REMOTE_ADDR"] != $_SERVER["HTTP_FORWARDED"]) {
							 | 
						||
| 
								 | 
							
												$user_combined_ip[] = "|" . $_SERVER["HTTP_FORWARDED"];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
							 | 
						||
| 
								 | 
							
											if (!empty($_SERVER["HTTP_CF_CONNECTING_IP"])) {
							 | 
						||
| 
								 | 
							
												$user_combined_ip[] = $_SERVER["HTTP_CF_CONNECTING_IP"];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return implode("|", $user_combined_ip);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function verify_token($database, $user, $ip, $time, $token) {
							 | 
						||
| 
								 | 
							
									if (!password_verify($database . $user . $ip . $time . PHPMYADMIN_KEY, $token)) {
							 | 
						||
| 
								 | 
							
										if (
							 | 
						||
| 
								 | 
							
											!password_verify(
							 | 
						||
| 
								 | 
							
												$database . $user . $_SERVER["SERVER_ADDR"] . "|" . $ip . $time . PHPMYADMIN_KEY,
							 | 
						||
| 
								 | 
							
												$token,
							 | 
						||
| 
								 | 
							
											)
							 | 
						||
| 
								 | 
							
										) {
							 | 
						||
| 
								 | 
							
											trigger_error(
							 | 
						||
| 
								 | 
							
												"Access denied: There is a security token mismatch " . $time,
							 | 
						||
| 
								 | 
							
												E_USER_WARNING,
							 | 
						||
| 
								 | 
							
											);
							 | 
						||
| 
								 | 
							
											session_invalid();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/* Need to have cookie visible from parent directory */
							 | 
						||
| 
								 | 
							
								session_set_cookie_params(0, "/", "", true, true);
							 | 
						||
| 
								 | 
							
								/* Create signon session */
							 | 
						||
| 
								 | 
							
								$session_name = "SignonSession";
							 | 
						||
| 
								 | 
							
								session_name($session_name);
							 | 
						||
| 
								 | 
							
								@session_start();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function session_invalid() {
							 | 
						||
| 
								 | 
							
									global $session_name;
							 | 
						||
| 
								 | 
							
									//delete all current sessions
							 | 
						||
| 
								 | 
							
									session_destroy();
							 | 
						||
| 
								 | 
							
									setcookie($session_name, null, -1, "/");
							 | 
						||
| 
								 | 
							
									header("Location: " . dirname($_SERVER["PHP_SELF"]) . "/index.php");
							 | 
						||
| 
								 | 
							
									die();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								$api = new Hestia_API();
							 | 
						||
| 
								 | 
							
								if (!empty($_GET)) {
							 | 
						||
| 
								 | 
							
									if (isset($_GET["logout"])) {
							 | 
						||
| 
								 | 
							
										$api->delete_temp_user(
							 | 
						||
| 
								 | 
							
											$_SESSION["HESTIA_sso_database"],
							 | 
						||
| 
								 | 
							
											$_SESSION["HESTIA_sso_user"],
							 | 
						||
| 
								 | 
							
											$_SESSION["PMA_single_signon_user"],
							 | 
						||
| 
								 | 
							
											$_SESSION["HESTIA_sso_host"],
							 | 
						||
| 
								 | 
							
										);
							 | 
						||
| 
								 | 
							
										//remove session
							 | 
						||
| 
								 | 
							
										session_invalid();
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										if (isset($_GET["user"]) && isset($_GET["hestia_token"])) {
							 | 
						||
| 
								 | 
							
											$database = $_GET["database"];
							 | 
						||
| 
								 | 
							
											$user = $_GET["user"];
							 | 
						||
| 
								 | 
							
											$host = "localhost";
							 | 
						||
| 
								 | 
							
											$token = $_GET["hestia_token"];
							 | 
						||
| 
								 | 
							
											if (is_numeric($_GET["exp"])) {
							 | 
						||
| 
								 | 
							
												$time = $_GET["exp"];
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												$time = 0;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ($time + 60 > time()) {
							 | 
						||
| 
								 | 
							
												//note: Possible issues with cloudflare due to ip obfuscation
							 | 
						||
| 
								 | 
							
												$ip = $api->get_user_ip();
							 | 
						||
| 
								 | 
							
												verify_token($database, $user, $ip, $time, $token);
							 | 
						||
| 
								 | 
							
												$id = session_id();
							 | 
						||
| 
								 | 
							
												//create a new temp user
							 | 
						||
| 
								 | 
							
												$data = $api->create_temp_user($database, $user, $host);
							 | 
						||
| 
								 | 
							
												if ($data) {
							 | 
						||
| 
								 | 
							
													$_SESSION["PMA_single_signon_user"] = $data->login->user;
							 | 
						||
| 
								 | 
							
													$_SESSION["PMA_single_signon_password"] = $data->login->password;
							 | 
						||
| 
								 | 
							
													$_SESSION["PMA_single_signon_host"] = $host;
							 | 
						||
| 
								 | 
							
													//save database / username to be used for sending logout notification.
							 | 
						||
| 
								 | 
							
													$_SESSION["HESTIA_sso_user"] = $user;
							 | 
						||
| 
								 | 
							
													$_SESSION["HESTIA_sso_database"] = $database;
							 | 
						||
| 
								 | 
							
													$_SESSION["HESTIA_sso_host"] = $host;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													@session_write_close();
							 | 
						||
| 
								 | 
							
													setcookie($session_name, $id, 0, "/");
							 | 
						||
| 
								 | 
							
													header("Location: " . dirname($_SERVER["PHP_SELF"]) . "/index.php");
							 | 
						||
| 
								 | 
							
													die();
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													session_invalid();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												trigger_error(
							 | 
						||
| 
								 | 
							
													"Link has been expired: System time: " .
							 | 
						||
| 
								 | 
							
														time() .
							 | 
						||
| 
								 | 
							
														" / Time provided in link: " .
							 | 
						||
| 
								 | 
							
														$time,
							 | 
						||
| 
								 | 
							
													E_USER_WARNING,
							 | 
						||
| 
								 | 
							
												);
							 | 
						||
| 
								 | 
							
												session_invalid();
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								} else {
							 | 
						||
| 
								 | 
							
									session_invalid();
							 | 
						||
| 
								 | 
							
								}
							 |