root = dirname($root); } /** * Stampa il classico tasto di login di SPID (Area Pubblica) * * @return void */ public static function printLoginButton() { @session_start(); $_SESSION["SV83MHQJAII4K-PRE-SPID-UPGRADE-URL"] = null; include __DIR__ . "/view/button.php"; } /** * Stampa il tasto piccolo di login con Spid che apre la selezione dell'iDP in una modal. Il tasto è visibile se e solo se l'utente è già loggato * * @return void */ public static function printSmallLoginButton() { if(! empty($_SESSION["utente"]) && $_SESSION["utente"]->authenticationLevel == 1) { @session_start(); $_SESSION["SV83MHQJAII4K-PRE-SPID-UPGRADE-URL"] = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; include __DIR__ . DIRECTORY_SEPARATOR . "view" . DIRECTORY_SEPARATOR . "small-button.php"; } } /** * Verifica se l'utente sta effettuando l'upgrade della sua autenticazione * * @return bool */ public static function isUserUpgradingWithSPID() : bool { @session_start(); return ! empty($_SESSION["SV83MHQJAII4K-PRE-SPID-UPGRADE-URL"]); } public static function printMemo() { include __DIR__ . "/view/memo.php"; } public static function sendToSPID($entityCode, $entityName, $assertionUrl, $logoutUrl, $piattaforma, $codice = 0, $privato = false) { global $config; $endpoint = $config["spidEnpoint"]; $user = $config["spidUser"]; $password = $config["spidPassword"]; $put = []; $put["codice"] = $codice; $put["entityCode"] = $entityCode; $put["entityName"] = $entityName; $put["isPrivate"] = ($privato) ? "1" : "0"; $put["assertionUrl"] = $assertionUrl; $put["logoutUrl"] = $logoutUrl; $put["piattaforma"] = $piattaforma; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $endpoint . "/put", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_SSL_VERIFYPEER => FALSE, CURLOPT_POSTFIELDS => json_encode($put, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), CURLOPT_HTTPHEADER => array( 'Authorization: Basic ' . base64_encode($user . ":" . $password), 'Content-Type: application/json' ), )); $response = curl_exec($curl); curl_close($curl); $response = json_decode($response, true); if (!empty($response)) { if (!empty($response["id"])) { return $response["id"]; } } return false; } public static function getIndexs($platform) { global $config; $endpoint = $config["spidEnpoint"]; $user = $config["spidUser"]; $password = $config["spidPassword"]; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $endpoint . "/getIndexFromPlatform?piattaforma=" . $platform, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_SSL_VERIFYPEER => FALSE, CURLOPT_HTTPHEADER => array( 'Authorization: Basic ' . base64_encode($user . ":" . $password), 'Content-Type: application/json' ), )); $response = curl_exec($curl); curl_close($curl); $response = json_decode($response, true); if (!empty($response)) { if (!empty($response[0])) { return $response; } } return false; } public static function getFromSPID($codice_spid, $metadata = "false") { global $config; $endpoint = $config["spidEnpoint"]; $user = $config["spidUser"]; $password = $config["spidPassword"]; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $endpoint . "/get?codice=" . $codice_spid . "&metadata={$metadata}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_SSL_VERIFYPEER => FALSE, CURLOPT_HTTPHEADER => array( 'Authorization: Basic ' . base64_encode($user . ":" . $password), 'Content-Type: application/json' ), )); $response = curl_exec($curl); curl_close($curl); $response = json_decode($response, true); if (!empty($response)) { if (!empty($response["codice"])) { return $response; } } return false; } public static function deleteFromSPID($codice_spid) { global $config; $endpoint = $config["spidEnpoint"]; $user = $config["spidUser"]; $password = $config["spidPassword"]; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $endpoint . "/delete?codice=" . $codice_spid, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'DELETE', CURLOPT_HTTPHEADER => array( 'Authorization: Basic ' . base64_encode($user . ":" . $password), 'Content-Type: application/json' ), )); $response = curl_exec($curl); curl_close($curl); $response = json_decode($response, true); if (!empty($response)) { if (empty($response["error"])) { return true; } } return false; } private static function xmlToArray(SimpleXMLElement $xml, $options = array()) { $defaults = array( 'namespaceSeparator' => ':', //you may want this to be something other than a colon 'attributePrefix' => '@', //to distinguish between attributes and nodes with the same name 'alwaysArray' => array(), //array of xml tag names which should always become arrays 'autoArray' => true, //only create arrays for tags which appear more than once 'textContent' => '$', //key used for the text content of elements 'autoText' => true, //skip textContent key if node has no attributes or child nodes 'keySearch' => false, //optional search and replace on tag and attribute names 'keyReplace' => false //replace values for above search values (as passed to str_replace()) ); $options = array_merge($defaults, $options); $namespaces = $xml->getDocNamespaces(); $namespaces[''] = null; //add base (empty) namespace //get attributes from all namespaces $attributesArray = array(); foreach ($namespaces as $prefix => $namespace) { foreach ($xml->attributes($namespace) as $attributeName => $attribute) { //replace characters in attribute name if ($options['keySearch']) $attributeName = str_replace($options['keySearch'], $options['keyReplace'], $attributeName); $attributeKey = $options['attributePrefix'] . ($prefix ? $prefix . $options['namespaceSeparator'] : '') . $attributeName; $attributesArray[$attributeKey] = (string) $attribute; } } //get child nodes from all namespaces $tagsArray = array(); foreach ($namespaces as $prefix => $namespace) { foreach ($xml->children($namespace) as $childXml) { //recurse into child nodes $childArray = self::xmlToArray($childXml, $options); foreach($childArray as $key => $value) { $childTagName = $key; $childProperties = $value; } //replace characters in tag name if ($options['keySearch']) $childTagName = str_replace($options['keySearch'], $options['keyReplace'], $childTagName); //add namespace prefix, if any if ($prefix) $childTagName = $prefix . $options['namespaceSeparator'] . $childTagName; if (!isset($tagsArray[$childTagName])) { //only entry with this key //test if tags of this type should always be arrays, no matter the element count $tagsArray[$childTagName] = in_array($childTagName, $options['alwaysArray']) || !$options['autoArray'] ? array($childProperties) : $childProperties; } elseif ( is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName]) === range(0, count($tagsArray[$childTagName]) - 1) ) { //key already exists and is integer indexed array $tagsArray[$childTagName][] = $childProperties; } else { //key exists so convert to integer indexed array with previous value in position 0 $tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties); } } } //get text content of node $textContentArray = array(); $plainText = trim((string) $xml); if ($plainText !== '') $textContentArray[$options['textContent']] = $plainText; //stick it all together $propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '') ? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText; //return node as array return array( $xml->getName() => $propertiesArray ); } private static function simple_encrypt($text, $salt) { if (!function_exists("simple_encrypt")) { return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); } return simple_encrypt($text, $salt); } public static function requestLog($url) { $components = parse_url($url); parse_str($components["query"], $variables); if (isset($variables["SAMLRequest"])) { $SAMLRequest = gzinflate(base64_decode($variables["SAMLRequest"])); $DecodedSAMLRequest = simplexml_load_string($SAMLRequest); $DecodedSAMLRequest = self::xmlToArray($DecodedSAMLRequest); return [ 'action' => 'login', 'request' => preg_replace('~[[:cntrl:]]~', '', $SAMLRequest), 'req_id' => $DecodedSAMLRequest["AuthnRequest"]["@ID"], 'req_instant' => $DecodedSAMLRequest["AuthnRequest"]["@IssueInstant"], ]; } return []; } public static function responseLog($response) { try { $SAMLResponse = base64_decode($response); $DecodedSAMLResponse = simplexml_load_string($SAMLResponse); $DecodedSAMLResponse = self::xmlToArray($DecodedSAMLResponse); return [ "res_id" => $DecodedSAMLResponse["Response"]["@ID"], "res_instant" => $DecodedSAMLResponse["Response"]["@IssueInstant"], "res_issuer" => $DecodedSAMLResponse["Response"]["saml:Issuer"]["$"] ?? null, "assertion_id" => $DecodedSAMLResponse["Response"]["saml:Assertion"]["@ID"] ?? null, "assertion_subject" => $DecodedSAMLResponse["Response"]["saml:Assertion"]["saml:Subject"]["saml:NameID"]["$"] ?? null, "assertion_qualifier" => $DecodedSAMLResponse["Response"]["saml:Assertion"]["saml:Subject"]["saml:NameID"]["@NameQualifier"] ?? null, "response" => $SAMLResponse ]; } catch (Exception $th) { return []; } } }