static bool SAMLCheckReference(const DOMDocument *doc, DSIGSignature *sig) { DOMElement *rootElem = doc->getDocumentElement(); const XMLCh *id = rootElem->getAttribute(MAKE_UNICODE_STRING("ID")); if (NULL == id) { Debug("%s: NULL ID attribute.\n", __FUNCTION__); return false; } XMLSize_t idLen = XMLString::stringLen(id); if (0 == idLen) { Debug("%s: Root element has no or an empty ID attribute.\n", __FUNCTION__); return false; } /* * At least one reference should contain a URI that refers to the root * element. To do so, that URI should be "#" followed by the value of * the ID element of the root node; for example if the ID is "SAML" the * URI must be "#SAML". * * TODO: The vmacore implementation of SAML parsing, used by clients * validating tokens, allows for multiple references and considers if * at least one matches. However, the SAML spec (section 5.4.2) requires * that there be only one reference element in the signature. Currently * we follow the vmacore behavior. */ XMLT uriPrefix("#"); XMLSize_t prefixLen = XMLString::stringLen(uriPrefix.getUnicodeStr()); DSIGReferenceList *references = sig->getReferenceList(); DSIGReferenceList::size_type numReferences = references->getSize(); for (DSIGReferenceList::size_type i = 0; i < numReferences; i++) { DSIGReference *ref = references->item(i); const XMLCh *uri = ref->getURI(); if (uri != NULL && XMLString::startsWith(uri, uriPrefix.getUnicodeStr()) && XMLString::equals(id, uri + prefixLen)) { return true; } } Debug("%s: No matching reference found in the signature for ID '%s'.\n", __FUNCTION__, SAMLStringWrapper(id).c_str()); return false; }
void XKMSAuthenticationImpl::load(const XMLCh * id) { if (mp_authenticationElement == NULL) { throw XSECException(XSECException::ExpectedXKMSChildNotFound, "XKMSAuthenticationImpl::load - called on empty DOM"); } // Store for later use mp_keyBindingId = id; DOMElement * tmpElt = findFirstElementChild(mp_authenticationElement); if (tmpElt != NULL && strEquals(getXKMSLocalName(tmpElt), XKMSConstants::s_tagKeyBindingAuthentication)) { // Find the signature mp_keyBindingAuthenticationSignatureElement = (DOMElement *) findFirstElementChild(tmpElt); while (mp_keyBindingAuthenticationSignatureElement != NULL && !strEquals(getDSIGLocalName(mp_keyBindingAuthenticationSignatureElement), XKMSConstants::s_tagSignature)) { mp_keyBindingAuthenticationSignatureElement= findNextElementChild(mp_keyBindingAuthenticationSignatureElement); } // The provider will take care of cleaning this up later. if (mp_keyBindingAuthenticationSignatureElement != NULL) { mp_keyBindingAuthenticationSignature = m_prov.newSignatureFromDOM( mp_keyBindingAuthenticationSignatureElement->getOwnerDocument(), mp_keyBindingAuthenticationSignatureElement); mp_keyBindingAuthenticationSignature->load(); // Check the signature is across the correct input DSIGReferenceList * rl = mp_keyBindingAuthenticationSignature->getReferenceList(); if (rl->getSize() != 1) { throw XSECException(XSECException::XKMSError, "XKMSAuthenticationImpl::load - KeyBindingAuthentication Signature with incorrect number of references found (should be 1)"); } safeBuffer sb; sb.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty); sb.sbXMLChAppendCh(chPound); sb.sbXMLChCat(mp_keyBindingId); if (!strEquals(rl->item(0)->getURI(), sb.rawXMLChBuffer())) { throw XSECException(XSECException::XKMSError, "XKMSAuthenticationImpl::load - KeyBindingAuthentication Signature refers to incorrect Id (should be for KeyBinding)"); } // We don't actually check the signature as we have no key material to do so! } tmpElt = findNextElementChild(tmpElt); } if (tmpElt != NULL && strEquals(getXKMSLocalName(tmpElt), XKMSConstants::s_tagNotBoundAuthentication)) { XSECnew(mp_notBoundAuthentication, XKMSNotBoundAuthenticationImpl(mp_env, tmpElt)); mp_notBoundAuthentication->load(); } }