public static function getInstance() { if (self::$instance !== null) { return self::$instance; } $publicKeyPath = Config::getCertPath('oauth2_module.crt'); $publicKey = new CryptKey($publicKeyPath); self::$instance = new ResourceServer(new AccessTokenRepository(), $publicKey); return self::$instance; }
public static function getInstance() { if (self::$instance !== null) { return self::$instance; } $oauth2config = \SimpleSAML_Configuration::getConfig('module_oauth2.php'); $accessTokenDuration = $oauth2config->getString('accessTokenDuration'); $authCodeDuration = $oauth2config->getString('authCodeDuration'); $passPhrase = $oauth2config->getString('pass_phrase', null); $refreshTokenDuration = $oauth2config->getString('refreshTokenDuration'); $privateKeyPath = Config::getCertPath('oauth2_module.pem'); $publicKeyPath = Config::getCertPath('oauth2_module.crt'); $privateKey = new CryptKey($privateKeyPath, $passPhrase); $publicKey = new CryptKey($publicKeyPath); self::$instance = new AuthorizationServer(new ClientRepository(), new AccessTokenRepository(), new ScopeRepository(), $privateKey, $publicKey); $authCodeGrant = new AuthCodeGrant(new AuthCodeRepository(), new RefreshTokenRepository(), new \DateInterval($authCodeDuration)); $authCodeGrant->setRefreshTokenTTL(new \DateInterval($refreshTokenDuration)); // refresh tokens will expire after 1 month self::$instance->enableGrantType($authCodeGrant, new \DateInterval($accessTokenDuration)); $implicitGrant = new ImplicitGrant(new \DateInterval($accessTokenDuration)); self::$instance->enableGrantType($implicitGrant, new \DateInterval($accessTokenDuration)); return self::$instance; }
public function validate() { assert('$this->dom instanceof DOMDocument'); if ($this->messageValidated) { /* This message was validated externally. */ return TRUE; } /* Validate the signature. */ $this->validator = new SimpleSAML_XML_Validator($this->dom, array('ResponseID', 'AssertionID')); // Get the issuer of the response. $issuer = $this->getIssuer(); /* Get the metadata of the issuer. */ $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $md = $metadata->getMetaDataConfig($issuer, 'shib13-idp-remote'); $publicKeys = $md->getPublicKeys('signing'); if ($publicKeys !== NULL) { $certFingerprints = array(); foreach ($publicKeys as $key) { if ($key['type'] !== 'X509Certificate') { continue; } $certFingerprints[] = sha1(base64_decode($key['X509Certificate'])); } $this->validator->validateFingerprint($certFingerprints); } elseif ($md->hasValue('certFingerprint')) { $certFingerprints = $md->getArrayizeString('certFingerprint'); /* Validate the fingerprint. */ $this->validator->validateFingerprint($certFingerprints); } elseif ($md->hasValue('caFile')) { /* Validate against CA. */ $this->validator->validateCA(\SimpleSAML\Utils\Config::getCertPath($md->getString('caFile'))); } else { throw new SimpleSAML_Error_Exception('Missing certificate in Shibboleth 1.3 IdP Remote metadata for identity provider [' . $issuer . '].'); } return true; }
/** * This function receives a SAML 1.1 artifact. * * @param SimpleSAML_Configuration $spMetadata The metadata of the SP. * @param SimpleSAML_Configuration $idpMetadata The metadata of the IdP. * @return string The <saml1p:Response> element, as an XML string. */ public static function receive(SimpleSAML_Configuration $spMetadata, SimpleSAML_Configuration $idpMetadata) { $artifacts = self::getArtifacts(); $request = self::buildRequest($artifacts); \SimpleSAML\Utils\XML::debugSAMLMessage($request, 'out'); $url = $idpMetadata->getDefaultEndpoint('ArtifactResolutionService', array('urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding')); $url = $url['Location']; $peerPublicKeys = $idpMetadata->getPublicKeys('signing', TRUE); $certData = ''; foreach ($peerPublicKeys as $key) { if ($key['type'] !== 'X509Certificate') { continue; } $certData .= "-----BEGIN CERTIFICATE-----\n" . chunk_split($key['X509Certificate'], 64) . "-----END CERTIFICATE-----\n"; } $file = SimpleSAML\Utils\System::getTempDir() . DIRECTORY_SEPARATOR . sha1($certData) . '.crt'; if (!file_exists($file)) { SimpleSAML\Utils\System::writeFile($file, $certData); } $spKeyCertFile = \SimpleSAML\Utils\Config::getCertPath($spMetadata->getString('privatekey')); $opts = array('ssl' => array('verify_peer' => TRUE, 'cafile' => $file, 'local_cert' => $spKeyCertFile, 'capture_peer_cert' => TRUE, 'capture_peer_chain' => TRUE), 'http' => array('method' => 'POST', 'content' => $request, 'header' => 'SOAPAction: http://www.oasis-open.org/committees/security' . "\r\n" . 'Content-Type: text/xml')); // Fetch the artifact $response = \SimpleSAML\Utils\HTTP::fetch($url, $opts); if ($response === FALSE) { throw new SimpleSAML_Error_Exception('Failed to retrieve assertion from IdP.'); } \SimpleSAML\Utils\XML::debugSAMLMessage($response, 'in'); // Find the response in the SOAP message $response = self::extractResponse($response); return $response; }
/** * Get public key from metadata. * * @param string|null $use The purpose this key can be used for. (encryption or signing). * @param bool $required Whether the public key is required. If this is true, a * missing key will cause an exception. Default is false. * @param string $prefix The prefix which should be used when reading from the metadata * array. Defaults to ''. * * @return array|null Public key data, or null if no public key or was found. * * @throws Exception If the certificate or public key cannot be loaded from a file. * @throws SimpleSAML_Error_Exception If the file does not contain a valid PEM-encoded certificate, or there is no * certificate in the metadata. */ public function getPublicKeys($use = null, $required = false, $prefix = '') { assert('is_bool($required)'); assert('is_string($prefix)'); if ($this->hasValue($prefix . 'keys')) { $ret = array(); foreach ($this->getArray($prefix . 'keys') as $key) { if ($use !== null && isset($key[$use]) && !$key[$use]) { continue; } if (isset($key['X509Certificate'])) { // Strip whitespace from key $key['X509Certificate'] = preg_replace('/\\s+/', '', $key['X509Certificate']); } $ret[] = $key; } if (!empty($ret)) { return $ret; } } elseif ($this->hasValue($prefix . 'certData')) { $certData = $this->getString($prefix . 'certData'); $certData = preg_replace('/\\s+/', '', $certData); return array(array('encryption' => true, 'signing' => true, 'type' => 'X509Certificate', 'X509Certificate' => $certData)); } elseif ($this->hasValue($prefix . 'certificate')) { $file = $this->getString($prefix . 'certificate'); $file = \SimpleSAML\Utils\Config::getCertPath($file); $data = @file_get_contents($file); if ($data === false) { throw new Exception($this->location . ': Unable to load certificate/public key from file "' . $file . '".'); } // extract certificate data (if this is a certificate) $pattern = '/^-----BEGIN CERTIFICATE-----([^-]*)^-----END CERTIFICATE-----/m'; if (!preg_match($pattern, $data, $matches)) { throw new SimpleSAML_Error_Exception($this->location . ': Could not find PEM encoded certificate in "' . $file . '".'); } $certData = preg_replace('/\\s+/', '', $matches[1]); return array(array('encryption' => true, 'signing' => true, 'type' => 'X509Certificate', 'X509Certificate' => $certData)); } if ($required) { throw new SimpleSAML_Error_Exception($this->location . ': Missing certificate in metadata.'); } else { return null; } }
/** * If this EntityDescriptor was signed this function use the public key to check the signature. * * @param array $certificates One ore more certificates with the public key. This makes it possible * to do a key rollover. * * @return boolean True if it is possible to check the signature with the certificate, false otherwise. * @throws Exception If the certificate file cannot be found. */ public function validateSignature($certificates) { foreach ($certificates as $cert) { assert('is_string($cert)'); $certFile = \SimpleSAML\Utils\Config::getCertPath($cert); if (!file_exists($certFile)) { throw new Exception('Could not find certificate file [' . $certFile . '], which is needed to validate signature'); } $certData = file_get_contents($certFile); foreach ($this->validators as $validator) { $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public')); $key->loadKey($certData); try { if ($validator->validate($key)) { return true; } } catch (Exception $e) { // this certificate did not sign this element, skip } } } SimpleSAML_Logger::debug('Could not validate signature'); return false; }
/** * @deprecated This method will be removed in SSP 2.0. Please use SimpleSAML\Utils\Config::getCertPath() instead. */ public static function resolveCert($path) { return \SimpleSAML\Utils\Config::getCertPath($path); }
/** * Signs the given metadata if metadata signing is enabled. * * @param string $metadataString A string with the metadata. * @param array $entityMetadata The metadata of the entity. * @param string $type A string which describes the type entity this is, e.g. 'SAML 2 IdP' or 'Shib 1.3 SP'. * * @return string The $metadataString with the signature embedded. * @throws Exception If the certificate or private key cannot be loaded, or the metadata doesn't parse properly. */ public static function sign($metadataString, $entityMetadata, $type) { $config = SimpleSAML_Configuration::getInstance(); // check if metadata signing is enabled if (!self::isMetadataSigningEnabled($config, $entityMetadata, $type)) { return $metadataString; } // find the key & certificate which should be used to sign the metadata $keyCertFiles = self::findKeyCert($config, $entityMetadata, $type); $keyFile = \SimpleSAML\Utils\Config::getCertPath($keyCertFiles['privatekey']); if (!file_exists($keyFile)) { throw new Exception('Could not find private key file [' . $keyFile . '], which is needed to sign the metadata'); } $keyData = file_get_contents($keyFile); $certFile = \SimpleSAML\Utils\Config::getCertPath($keyCertFiles['certificate']); if (!file_exists($certFile)) { throw new Exception('Could not find certificate file [' . $certFile . '], which is needed to sign the metadata'); } $certData = file_get_contents($certFile); // convert the metadata to a DOM tree try { $xml = SAML2_DOMDocumentFactory::fromString($metadataString); } catch (Exception $e) { throw new Exception('Error parsing self-generated metadata.'); } // load the private key $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private')); if (array_key_exists('privatekey_pass', $keyCertFiles)) { $objKey->passphrase = $keyCertFiles['privatekey_pass']; } $objKey->loadKey($keyData, false); // get the EntityDescriptor node we should sign $rootNode = $xml->firstChild; // sign the metadata with our private key if ($type == 'ADFS IdP') { $objXMLSecDSig = new sspmod_adfs_XMLSecurityDSig($metadataString); } else { $objXMLSecDSig = new XMLSecurityDSig(); } $objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); $objXMLSecDSig->addReferenceList(array($rootNode), XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N), array('id_name' => 'ID')); $objXMLSecDSig->sign($objKey); // add the certificate to the signature $objXMLSecDSig->add509Cert($certData, true); // add the signature to the metadata $objXMLSecDSig->insertSignature($rootNode, $rootNode->firstChild); // return the DOM tree as a string return $xml->saveXML(); }
public static function sendResponse(array $state) { $spMetadata = $state["SPMetadata"]; $spEntityId = $spMetadata['entityid']; $spMetadata = SimpleSAML_Configuration::loadFromArray($spMetadata, '$metadata[' . var_export($spEntityId, TRUE) . ']'); $attributes = $state['Attributes']; $nameidattribute = $spMetadata->getValue('simplesaml.nameidattribute'); if (!empty($nameidattribute)) { if (!array_key_exists($nameidattribute, $attributes)) { throw new Exception('simplesaml.nameidattribute does not exist in resulting attribute set'); } $nameid = $attributes[$nameidattribute][0]; } else { $nameid = SimpleSAML\Utils\Random::generateID(); } $idp = SimpleSAML_IdP::getByState($state); $idpMetadata = $idp->getConfig(); $idpEntityId = $idpMetadata->getString('entityid'); $idp->addAssociation(array('id' => 'adfs:' . $spEntityId, 'Handler' => 'sspmod_adfs_IdP_ADFS', 'adfs:entityID' => $spEntityId)); $response = sspmod_adfs_IdP_ADFS::ADFS_GenerateResponse($idpEntityId, $spEntityId, $nameid, $attributes); $privateKeyFile = \SimpleSAML\Utils\Config::getCertPath($idpMetadata->getString('privatekey')); $certificateFile = \SimpleSAML\Utils\Config::getCertPath($idpMetadata->getString('certificate')); $wresult = sspmod_adfs_IdP_ADFS::ADFS_SignResponse($response, $privateKeyFile, $certificateFile); $wctx = $state['adfs:wctx']; sspmod_adfs_IdP_ADFS::ADFS_PostResponse($spMetadata->getValue('prp'), $wresult, $wctx); }
/** * Add an extra certificate to the certificate chain in the signature. * * Extra certificates will be added to the certificate chain in the order they * are added. * * @param $file The file which contains the certificate, relative to the cert-directory. */ public function addCertificate($file) { assert('is_string($file)'); $certFile = \SimpleSAML\Utils\Config::getCertPath($file); if (!file_exists($certFile)) { throw new Exception('Could not find extra certificate file "' . $certFile . '".'); } $certificate = file_get_contents($certFile); if ($certificate === FALSE) { throw new Exception('Unable to read extra certificate file "' . $certFile . '".'); } $this->extraCertificates[] = $certificate; }