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;
}
Exemple #2
0
DSIGReferenceList *DSIGReference::loadReferenceListFromXML(const XSECEnv * env, DOMNode *firstReference) {

	// Have the first reference element in the document,
	// so want to find and load them all

	DOMNode *tmpRef = firstReference;
	DSIGReferenceList * refList;
	DSIGReference * r;

	XSECnew(refList, DSIGReferenceList());
	Janitor<DSIGReferenceList> j_refList(refList);

	while (tmpRef != 0) {

		// Must be an element node

		if (tmpRef->getNodeType() != DOMNode::ELEMENT_NODE ||
			!strEquals(getDSIGLocalName(tmpRef), "Reference")) {

			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
				"Expected <Reference> as child of <SignedInfo>");

		}

		XSECnew(r, DSIGReference(env, tmpRef));

		refList->addReference(r);

		// Load the reference before moving on
		r->load();

		// Find next element Node
		tmpRef = tmpRef->getNextSibling();

		while (tmpRef != 0 && tmpRef->getNodeType() != DOMNode::ELEMENT_NODE) {
			if (tmpRef->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
				throw XSECException(XSECException::ExpectedDSIGChildNotFound,
					"EntityReference nodes in <Reference> are unsupported.");
			}
			tmpRef = tmpRef->getNextSibling();
		}

	}

	j_refList.release();
	return refList;

}
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();

	}

}