Пример #1
0
 /**
  * Test invalid dir specified by env var results in a thrown exception
  */
 public function testInvalidEnvVariableConfigDirThrowsException()
 {
     // I used a random hash to ensure this test directory is always invalid
     $invalidDir = __DIR__ . '/e9826ad19cbc4f5bf20c0913ffcd2ce6';
     putenv('SIMPLESAMLPHP_CONFIG_DIR=' . $invalidDir);
     $this->setExpectedException('InvalidArgumentException', 'Config directory specified by environment variable SIMPLESAMLPHP_CONFIG_DIR is not a directory.  ' . 'Given: "' . $invalidDir . '"');
     Config::getConfigDir();
 }
 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;
 }
Пример #4
0
 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;
 }
Пример #5
0
 /**
  * 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;
 }
Пример #6
0
 /**
  * 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;
     }
 }
Пример #7
0
 /**
  * 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;
 }
Пример #8
0
 /**
  * @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);
 }
Пример #9
0
 /**
  * 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();
 }
Пример #10
0
 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);
 }
Пример #11
0
 /**
  * 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;
 }