From 059d535d66848914562b1b236ff4330df8809b8b Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Thu, 12 Jun 2008 08:48:10 +0000 Subject: [PATCH] Add support for signing the Response-element of the authentication response. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@639 44740490-163a-0410-bde0-09ae8108e29a --- config-templates/config.php | 10 +++ docs/source/simplesamlphp-idp.xml | 16 +++++ lib/SimpleSAML/Bindings/SAML20/HTTPPost.php | 72 +++++++++++---------- www/admin/metadata.php | 2 +- 4 files changed, 64 insertions(+), 36 deletions(-) diff --git a/config-templates/config.php b/config-templates/config.php index 8c4d762e7..50f2f650b 100644 --- a/config-templates/config.php +++ b/config-templates/config.php @@ -196,6 +196,16 @@ $config = array ( */ 'idpdisco.layout' => 'links', + /* + * Whether simpleSAMLphp should sign the response or the assertion in SAML 2.0 authentication + * responses. + * + * The default is to sign the assertion element, but that can be overridden by setting this + * option to TRUE. It can also be overridden on a pr. SP basis by adding an option with the + * same name to the metadata of the SP. + */ + 'saml20.signresponse' => FALSE, + /* * Configuration of Consent storage used for attribute consent. * connect, user and passwd is used with PDO (in example Mysql) diff --git a/docs/source/simplesamlphp-idp.xml b/docs/source/simplesamlphp-idp.xml index 768fec9d6..84cfa7b8e 100644 --- a/docs/source/simplesamlphp-idp.xml +++ b/docs/source/simplesamlphp-idp.xml @@ -838,6 +838,22 @@ openssl x509 -req -days 60 -in server2.csr -signkey server2.key -out server2.crt <literal>eduPersonPrincipalName</literal>.</para> </glossdef> </glossentry> + + <glossentry> + <glossterm>signresponse</glossterm> + + <glossdef> + <para>The default behaviour of simpleSAMLphp is to sign the + Assertion element in the SAML 2.0 response sent to SPs. This + option allows you to override this behaviour on a per SP + basis. Set this to <literal>TRUE</literal> to sign the + Response element. <literal>FALSE</literal> will make the SP + sign the Assertion. If this option is unset, the value from + <literal>saml2.signresponse</literal> in + <literal>config.php</literal> will be used. That value is + <literal>FALSE</literal> by default.</para> + </glossdef> + </glossentry> </glosslist> </section> </section> diff --git a/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php b/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php index 155e3783d..fb5d8fd4b 100644 --- a/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php +++ b/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php @@ -64,14 +64,6 @@ class SimpleSAML_Bindings_SAML20_HTTPPost { $destination = $spmd['AssertionConsumerService']; - /* - $privatekey = "/home/as/erlang/feide2/cert/edugain/server1Key.pem"; - $publiccert = "/home/as/erlang/feide2/cert/edugain/server2chain.pem"; - - $privatekey = "/home/as/erlang/feide2/cert/server.pem"; - $publiccert = "/home/as/erlang/feide2/cert/server.crt"; - */ - $privatekey = $this->configuration->getPathValue('certdir') . $idpmd['privatekey']; $publiccert = $this->configuration->getPathValue('certdir') . $idpmd['certificate']; @@ -86,9 +78,6 @@ class SimpleSAML_Bindings_SAML20_HTTPPost { * XMLDSig. Sign the complete request with the key stored in cert/server.pem */ $objXMLSecDSig = new XMLSecurityDSig(); - //$objXMLSecDSig->idKeys[] = 'ResponseID'; - #$objXMLSecDSig->idKeys = array('ResponseID'); - $objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); @@ -98,22 +87,40 @@ class SimpleSAML_Bindings_SAML20_HTTPPost { } catch (Exception $e) { throw new Exception("foo"); } + $responseroot = $responsedom->getElementsByTagName('Response')->item(0); - - //$assertionroot = $responsedom->getElementsByTagName('Assertion')->item(1); $firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0); + + + /* Determine what we should sign - either the Response element or the Assertion. The default + * is to sign the Assertion, but that can be overridden by the 'signresponse' option in the + * SP metadata or 'saml20.signresponse' in the global configuration. + */ + $signResponse = FALSE; + if(array_key_exists('signresponse', $spmd) && $spmd['signresponse'] !== NULL) { + $signResponse = $spmd['signresponse']; + if(!is_bool($signResponse)) { + throw new Exception('Expected the \'signresponse\' option in the metadata of the' . + ' SP \'' . $spmd['entityid'] . '\' to be a boolean value.'); + } + } else { + $signResponse = $this->configuration->getBoolean('saml20.signresponse', FALSE); + } + + if($signResponse) { + /* Sign the response. */ + + $objXMLSecDSig->addReferenceList(array($responseroot), XMLSecurityDSig::SHA1, + array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N), + array('id_name' => 'ID')); + } else { + /* Sign the assertion. */ + + $objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1, + array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N), + array('id_name' => 'ID')); + } - //$objXMLSecDSig->addReferenceList(array($responseroot), XMLSecurityDSig::SHA1, //array('http://www.w3.org/2000/09/xmldsig#enveloped-signature')); - -// $objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1, -// array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', -// 'http://www.w3.org/2001/10/xml-exc-c14n#')); - - $objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1, - array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N), - array('id_name' => 'ID')); - - #$objXMLSecDSig->addRefInternal($responseroot, $responseroot, XMLSecurityDSig::SHA1); /* create new XMLSecKey using RSA-SHA-1 and type is private key */ $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private')); @@ -132,17 +139,12 @@ class SimpleSAML_Bindings_SAML20_HTTPPost { $public_cert = file_get_contents($publiccert); $objXMLSecDSig->add509Cert($public_cert, true); - /* - $public_cert = file_get_contents("cert/edugain/public2.pem"); - $objXMLSecDSig->add509Cert($public_cert, true); - - $public_cert = file_get_contents("cert/edugain/public3.pem"); - $objXMLSecDSig->add509Cert($public_cert, true); - */ - - - $objXMLSecDSig->appendSignature($firstassertionroot, true, true); - //$objXMLSecDSig->appendSignature($responseroot, true, false); + + if($signResponse) { + $objXMLSecDSig->appendSignature($responseroot, true, false); + } else { + $objXMLSecDSig->appendSignature($firstassertionroot, true, true); + } if (isset($spmd['assertion.encryption']) && $spmd['assertion.encryption']) { $encryptedassertion = $responsedom->createElement("saml:EncryptedAssertion"); diff --git a/www/admin/metadata.php b/www/admin/metadata.php index d45d53096..2a7093ff4 100644 --- a/www/admin/metadata.php +++ b/www/admin/metadata.php @@ -62,7 +62,7 @@ try { foreach ($metalist AS $entityid => $mentry) { $results[$entityid] = SimpleSAML_Utilities::checkAssocArrayRules($mentry, array('entityid', 'AssertionConsumerService'), - array('SingleLogoutService', 'NameIDFormat', 'SPNameQualifier', 'base64attributes', 'simplesaml.nameidattribute', 'attributemap', 'attributealter', 'simplesaml.attributes', 'attributes', 'name', 'description','request.signing','certificate', 'ForceAuthn', 'sharedkey', 'assertion.encryption', 'userid.attribute') + array('SingleLogoutService', 'NameIDFormat', 'SPNameQualifier', 'base64attributes', 'simplesaml.nameidattribute', 'attributemap', 'attributealter', 'simplesaml.attributes', 'attributes', 'name', 'description','request.signing','certificate', 'ForceAuthn', 'sharedkey', 'assertion.encryption', 'userid.attribute', 'signresponse') ); } $et->data['metadata.saml20-sp-remote'] = $results; -- GitLab