xsec/dsig/DSIGKeyInfoX509.cpp (352 lines of code) (raw):

/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * XSEC * * DSIGKeyX509 := A "Super" key that defines a certificate with a sub-key that defines * the signing key * * $Id$ * */ #include <xsec/dsig/DSIGKeyInfoX509.hpp> #include <xsec/dsig/DSIGSignature.hpp> #include <xsec/framework/XSECEnv.hpp> #include <xsec/framework/XSECError.hpp> #include <xsec/utils/XSECPlatformUtils.hpp> #include "../utils/XSECAutoPtr.hpp" #include "../utils/XSECDOMUtils.hpp" XERCES_CPP_NAMESPACE_USE // -------------------------------------------------------------------------------- // Constructors and Destructors // -------------------------------------------------------------------------------- DSIGKeyInfoX509::DSIGKeyInfoX509(const XSECEnv * env, DOMNode *X509Data) : DSIGKeyInfo(env), mp_X509IssuerName(NULL), mp_X509SerialNumber(NULL), mp_X509SubjectName(NULL), mp_X509SKI(NULL), mp_rawRetrievalURI(NULL), mp_X509SubjectNameTextNode(0), mp_X509IssuerNameTextNode(0), mp_X509SerialNumberTextNode(0), mp_X509SKITextNode(0), mp_X509DigestTextNode(0) { mp_keyInfoDOMNode = X509Data; m_X509List.clear(); m_X509CRLList.clear(); } DSIGKeyInfoX509::DSIGKeyInfoX509(const XSECEnv * env) : DSIGKeyInfo(env), mp_X509IssuerName(NULL), mp_X509SerialNumber(NULL), mp_X509SubjectName(NULL), mp_X509SKI(NULL), mp_rawRetrievalURI(NULL), mp_X509SubjectNameTextNode(0), mp_X509IssuerNameTextNode(0), mp_X509SerialNumberTextNode(0), mp_X509SKITextNode(0), mp_X509DigestTextNode(0){ mp_keyInfoDOMNode = 0; m_X509List.clear(); m_X509CRLList.clear(); } DSIGKeyInfoX509::~DSIGKeyInfoX509() { // SubjectName and IssuerName are local (decoded) copies of the // encoded DName held in the DOM if (mp_X509IssuerName != NULL) XSEC_RELEASE_XMLCH(mp_X509IssuerName); if (mp_X509SubjectName != NULL) XSEC_RELEASE_XMLCH(mp_X509SubjectName); X509ListType::iterator i; for (i = m_X509List.begin(); i != m_X509List.end(); ++i) { if ((*i)->mp_cryptoX509 != NULL) delete ((*i)->mp_cryptoX509); delete (*i); } m_X509List.clear(); m_X509CRLList.clear(); if (mp_rawRetrievalURI != NULL) XSEC_RELEASE_XMLCH(mp_rawRetrievalURI); }; // -------------------------------------------------------------------------------- // Load and Get // -------------------------------------------------------------------------------- // Methods unique to DSIGKeyInfoX509 void DSIGKeyInfoX509::load(void) { // Assuming we have a valid DOM_Node to start with, load the signing key so that it can // be used later on if (mp_keyInfoDOMNode == NULL) { // Attempt to load an empty signature element throw XSECException(XSECException::LoadEmptyX509); } if (!strEquals(getDSIGLocalName(mp_keyInfoDOMNode), "X509Data")) { throw XSECException(XSECException::LoadNonX509); } // Now check for an X509 Data Element we understand DOMNode *tmpElt = mp_keyInfoDOMNode->getFirstChild(); DOMNode *child; // Worker while (tmpElt != 0) { if (tmpElt->getNodeType() == DOMNode::ELEMENT_NODE) { // See if it's a known element type if (strEquals(getDSIGLocalName(tmpElt), "X509Certificate")) { // Loop over Text nodes until we successfully load a certificate. // If we run out, throw out the last exception raised. X509Holder * h; XSECCryptoX509* cryptoX509 = XSECPlatformUtils::g_cryptoProvider->X509(); DOMNode *certElt = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE); while (certElt) { XSECAutoPtrChar charX509(certElt->getNodeValue()); try { cryptoX509->loadX509Base64Bin(charX509.get(), (int) strlen(charX509.get())); // Add to the list XSECnew(h, X509Holder); m_X509List.push_back(h); h->mp_encodedX509 = certElt->getNodeValue(); h->mp_cryptoX509 = cryptoX509; break; } catch (const XSECCryptoException&) { certElt = findNextChildOfType(certElt, DOMNode::TEXT_NODE); if (!certElt) { delete cryptoX509; throw; } } } } else if (strEquals(getDSIGLocalName(tmpElt), "X509SubjectName")) { child = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE); if (child == NULL) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected TEXT_NODE child of <X509SubjectName>"); } mp_X509SubjectName = decodeDName(child->getNodeValue()); } else if (strEquals(getDSIGLocalName(tmpElt), "X509IssuerSerial")) { child = tmpElt->getFirstChild(); while (child != 0 && child->getNodeType() != DOMNode::ELEMENT_NODE && !strEquals(getDSIGLocalName(child), "X509IssuerName")) child = child->getNextSibling(); if (child == NULL) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected <X509IssuerName> child of <X509IssuerSerial>"); } child = child->getFirstChild(); while (child != 0 && child->getNodeType() != DOMNode::TEXT_NODE) child = child->getNextSibling(); if (child == NULL) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected TEXT_NODE child of <X509IssuerSerial>"); } mp_X509IssuerName = decodeDName(child->getNodeValue()); // Now find the serial number child = tmpElt->getFirstChild(); while (child != 0 && (child->getNodeType() != DOMNode::ELEMENT_NODE || !strEquals(getDSIGLocalName(child), "X509SerialNumber"))) child = child->getNextSibling(); if (child == NULL) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected <X509SerialNumber> child of <X509IssuerSerial>"); } child = child->getFirstChild(); while (child != 0 && child->getNodeType() != DOMNode::TEXT_NODE) child = child->getNextSibling(); if (child == NULL) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected TEXT_NODE child of <X509IssuerSerial>"); } mp_X509SerialNumber = child->getNodeValue(); } else if (strEquals(getDSIGLocalName(tmpElt), "X509CRL")) { DOMNode *crlElt = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE); if (crlElt != 0) { // Add to the list m_X509CRLList.push_back(crlElt->getNodeValue()); } } else if (strEquals(getDSIGLocalName(tmpElt), "X509SKI")) { child = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE); if (child == NULL) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected TEXT_NODE child of <X509SKI>"); } mp_X509SKITextNode = child; mp_X509SKI = child->getNodeValue(); } else if (strEquals(getDSIG11LocalName(tmpElt), "X509Digest")) { child = findFirstChildOfType(tmpElt, DOMNode::TEXT_NODE); if (child == NULL) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected TEXT_NODE child of <X509Digest>"); } mp_X509DigestTextNode = child; } } // Go to next data element to load if we understand tmpElt = tmpElt->getNextSibling(); } } const XMLCh * DSIGKeyInfoX509::getKeyName(void) const { return mp_X509SubjectName; // Should return DN } const XMLCh * DSIGKeyInfoX509::getX509SubjectName(void) const { return mp_X509SubjectName; } const XMLCh * DSIGKeyInfoX509::getX509DigestAlgorithm(void) const { return mp_X509DigestTextNode ? static_cast<DOMElement*>(mp_X509DigestTextNode->getParentNode())->getAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm) : NULL; } const XMLCh * DSIGKeyInfoX509::getX509DigestValue(void) const { return mp_X509DigestTextNode ? mp_X509DigestTextNode->getNodeValue() : NULL; } const XMLCh * DSIGKeyInfoX509::getX509IssuerName(void) const { return mp_X509IssuerName; } const XMLCh * DSIGKeyInfoX509::getX509IssuerSerialNumber(void) const { return mp_X509SerialNumber; } const XMLCh * DSIGKeyInfoX509::getX509CRL(void) const { return m_X509CRLList.empty() ? NULL : m_X509CRLList.front(); } int DSIGKeyInfoX509::getX509CRLListSize(void) const { return (int) m_X509CRLList.size(); } const XMLCh * DSIGKeyInfoX509::getX509CRLItem(int item) const { if (item >=0 && (unsigned int) item < m_X509CRLList.size()) return m_X509CRLList[item]; return 0; } const XMLCh * DSIGKeyInfoX509::getX509SKI(void) const { return mp_X509SKI; } int DSIGKeyInfoX509::getCertificateListSize(void) const { return (int) m_X509List.size(); } const XMLCh * DSIGKeyInfoX509::getCertificateItem(int item) const { if (item >=0 && (unsigned int) item < m_X509List.size()) return m_X509List[item]->mp_encodedX509; return 0; } XSECCryptoX509 * DSIGKeyInfoX509::getCertificateCryptoItem(int item) { if (item >=0 && (unsigned int) item < m_X509List.size()) return m_X509List[item]->mp_cryptoX509; return 0; } const XSECCryptoX509 * DSIGKeyInfoX509::getCertificateCryptoItem(int item) const { if (item >=0 && (unsigned int) item < m_X509List.size()) return m_X509List[item]->mp_cryptoX509; return 0; } const XMLCh * DSIGKeyInfoX509::getRawRetrievalURI(void) const { return mp_rawRetrievalURI; } // -------------------------------------------------------------------------------- // Create and Set // -------------------------------------------------------------------------------- DOMElement * DSIGKeyInfoX509::createBlankX509Data(void) { // Create the DOM Structure safeBuffer str; DOMDocument *doc = mp_env->getParentDocument(); const XMLCh * prefix = mp_env->getDSIGNSPrefix(); makeQName(str, prefix, "X509Data"); DOMElement *ret = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); mp_keyInfoDOMNode = ret; mp_env->doPrettyPrint(ret); return ret; } void DSIGKeyInfoX509::setX509CRL(const XMLCh * crl) { appendX509CRL(crl); } void DSIGKeyInfoX509::appendX509CRL(const XMLCh * crl) { safeBuffer str; DOMDocument *doc = mp_env->getParentDocument(); const XMLCh * prefix = mp_env->getDSIGNSPrefix(); makeQName(str, prefix, "X509CRL"); DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); DOMNode * b64Txt = doc->createTextNode(crl); s->appendChild(b64Txt); mp_keyInfoDOMNode->appendChild(s); mp_env->doPrettyPrint(mp_keyInfoDOMNode); // Add to the list m_X509CRLList.push_back(b64Txt->getNodeValue()); } void DSIGKeyInfoX509::setX509SKI(const XMLCh * ski) { if (mp_X509SKITextNode == 0) { safeBuffer str; DOMDocument *doc = mp_env->getParentDocument(); const XMLCh * prefix = mp_env->getDSIGNSPrefix(); makeQName(str, prefix, "X509SKI"); DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); mp_X509SKITextNode = doc->createTextNode(ski); s->appendChild(mp_X509SKITextNode); // Add to the over-arching node mp_keyInfoDOMNode->appendChild(s); mp_env->doPrettyPrint(mp_keyInfoDOMNode); } else { mp_X509SKITextNode->setNodeValue(ski); } mp_X509SKI = mp_X509SKITextNode->getNodeValue(); } void DSIGKeyInfoX509::setX509SubjectName(const XMLCh * name) { if (mp_X509SubjectName != NULL) XSEC_RELEASE_XMLCH(mp_X509SubjectName); mp_X509SubjectName = XMLString::replicate(name); XMLCh * encodedName = encodeDName(name); if (mp_X509SubjectNameTextNode == 0) { // Does not yet exist in the DOM safeBuffer str; DOMDocument *doc = mp_env->getParentDocument(); const XMLCh * prefix = mp_env->getDSIGNSPrefix(); makeQName(str, prefix, "X509SubjectName"); DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); mp_X509SubjectNameTextNode = doc->createTextNode(encodedName); s->appendChild(mp_X509SubjectNameTextNode); // Add to the over-arching node mp_keyInfoDOMNode->appendChild(s); mp_env->doPrettyPrint(mp_keyInfoDOMNode); } else { mp_X509SubjectNameTextNode->setNodeValue(encodedName); } XSEC_RELEASE_XMLCH(encodedName); } void DSIGKeyInfoX509::setX509IssuerSerial(const XMLCh * name, const XMLCh * serial) { if (mp_X509IssuerName != NULL) XSEC_RELEASE_XMLCH(mp_X509IssuerName); mp_X509IssuerName = XMLString::replicate(name); XMLCh * encodedName = encodeDName(name); if (mp_X509IssuerNameTextNode == 0) { // Does not yet exist in the DOM safeBuffer str; DOMDocument *doc = mp_env->getParentDocument(); const XMLCh * prefix = mp_env->getDSIGNSPrefix(); makeQName(str, prefix, "X509IssuerSerial"); DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); mp_env->doPrettyPrint(s); // Create the text nodes with the contents mp_X509IssuerNameTextNode = doc->createTextNode(encodedName); mp_X509SerialNumberTextNode = doc->createTextNode(serial); // Create the sub elements makeQName(str, prefix, "X509IssuerName"); DOMElement * t = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); t->appendChild(mp_X509IssuerNameTextNode); s->appendChild(t); mp_env->doPrettyPrint(s); makeQName(str, prefix, "X509SerialNumber"); t = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); t->appendChild(mp_X509SerialNumberTextNode); s->appendChild(t); mp_env->doPrettyPrint(s); // Add to the over-arching X509Data mp_keyInfoDOMNode->appendChild(s); mp_env->doPrettyPrint(mp_keyInfoDOMNode); } else { mp_X509IssuerNameTextNode->setNodeValue(encodedName); mp_X509SerialNumberTextNode->setNodeValue(serial); } XSEC_RELEASE_XMLCH(encodedName); } void DSIGKeyInfoX509::setX509Digest(const XMLCh * algorithm, const XMLCh * value) { if (mp_X509DigestTextNode == 0) { // Does not yet exist in the DOM safeBuffer str; DOMDocument *doc = mp_env->getParentDocument(); const XMLCh * prefix = mp_env->getDSIG11NSPrefix(); makeQName(str, prefix, "X509Digest"); DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG11, str.rawXMLChBuffer()); s->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm, algorithm); // Create the text node with the contents mp_X509DigestTextNode = doc->createTextNode(value); s->appendChild(mp_X509DigestTextNode); mp_env->doPrettyPrint(s); // Add to the over-arching X509Data mp_keyInfoDOMNode->appendChild(s); mp_env->doPrettyPrint(mp_keyInfoDOMNode); } else { mp_X509DigestTextNode->setNodeValue(value); static_cast<DOMElement*>(mp_X509DigestTextNode->getParentNode())->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm, algorithm); } } void DSIGKeyInfoX509::setRawRetrievalURI(const XMLCh * uri) { if (mp_rawRetrievalURI != NULL) XSEC_RELEASE_XMLCH(mp_rawRetrievalURI); mp_rawRetrievalURI = XMLString::replicate(uri); } void DSIGKeyInfoX509::appendX509Certificate(const XMLCh * base64Certificate) { safeBuffer str; DOMDocument *doc = mp_env->getParentDocument(); const XMLCh * prefix = mp_env->getDSIGNSPrefix(); makeQName(str, prefix, "X509Certificate"); DOMElement * s = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); DOMNode * b64Txt = doc->createTextNode(base64Certificate); s->appendChild(b64Txt); mp_keyInfoDOMNode->appendChild(s); mp_env->doPrettyPrint(mp_keyInfoDOMNode); // Add to the list X509Holder * h; XSECnew(h, X509Holder); m_X509List.push_back(h); h->mp_encodedX509 = b64Txt->getNodeValue(); h->mp_cryptoX509 = XSECPlatformUtils::g_cryptoProvider->X509(); XSECAutoPtrChar charX509(h->mp_encodedX509); h->mp_cryptoX509->loadX509Base64Bin(charX509.get(), (unsigned int) strlen(charX509.get())); }