From b3887773bcb867e8fb7cad376279f2a9ee39dda2 Mon Sep 17 00:00:00 2001 From: cantor Date: Fri, 1 Feb 2008 02:17:20 +0000 Subject: [PATCH] Refactor extraction of certificate details. Add X509SubjectName/X509IssuerSerial to KeyInfo handling. git-svn-id: https://svn.middleware.georgetown.edu/cpp-xmltooling/trunk@465 de75baf8-a10c-0410-a50a-987c0e22f00f --- xmltooling/encryption/impl/Decrypter.cpp | 15 +--- xmltooling/security/BasicX509Credential.h | 29 ++++++- xmltooling/security/CredentialCriteria.h | 29 ++++--- xmltooling/security/X509Credential.h | 26 ++++++- xmltooling/security/impl/BasicX509Credential.cpp | 90 +++++++++++++++++++--- .../security/impl/FilesystemCredentialResolver.cpp | 3 +- xmltooling/security/impl/InlineKeyResolver.cpp | 68 +++++++++++++++- xmltooling/signature/KeyInfo.h | 7 -- xmltooling/signature/Signature.h | 8 -- xmltooling/signature/impl/KeyInfoImpl.cpp | 35 --------- xmltooling/signature/impl/XMLSecSignatureImpl.cpp | 15 ---- 11 files changed, 212 insertions(+), 113 deletions(-) diff --git a/xmltooling/encryption/impl/Decrypter.cpp b/xmltooling/encryption/impl/Decrypter.cpp index c68d1cd..a87fa89 100644 --- a/xmltooling/encryption/impl/Decrypter.cpp +++ b/xmltooling/encryption/impl/Decrypter.cpp @@ -87,10 +87,7 @@ DOMDocumentFragment* Decrypter::decryptData(const EncryptedData& encryptedData, // Resolve a decryption key directly. vector creds; - int types = - CredentialCriteria::KEYINFO_EXTRACTION_KEY | - CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES | - CredentialCriteria::KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES; + int types = CredentialCriteria::KEYINFO_EXTRACTION_KEY | CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES; if (m_criteria) { m_criteria->setUsage(Credential::ENCRYPTION_CREDENTIAL); m_criteria->setKeyInfo(encryptedData.getKeyInfo(), types); @@ -187,10 +184,7 @@ void Decrypter::decryptData(ostream& out, const EncryptedData& encryptedData, co // Resolve a decryption key directly. vector creds; - int types = - CredentialCriteria::KEYINFO_EXTRACTION_KEY | - CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES | - CredentialCriteria::KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES; + int types = CredentialCriteria::KEYINFO_EXTRACTION_KEY | CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES; if (m_criteria) { m_criteria->setUsage(Credential::ENCRYPTION_CREDENTIAL); m_criteria->setKeyInfo(encryptedData.getKeyInfo(), types); @@ -270,10 +264,7 @@ XSECCryptoKey* Decrypter::decryptKey(const EncryptedKey& encryptedKey, const XML m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedKey.getDOM()->getOwnerDocument()); // Resolve key decryption keys. - int types = - CredentialCriteria::KEYINFO_EXTRACTION_KEY | - CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES | - CredentialCriteria::KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES; + int types = CredentialCriteria::KEYINFO_EXTRACTION_KEY | CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES; vector creds; if (m_criteria) { m_criteria->setUsage(Credential::ENCRYPTION_CREDENTIAL); diff --git a/xmltooling/security/BasicX509Credential.h b/xmltooling/security/BasicX509Credential.h index b398133..37948e5 100644 --- a/xmltooling/security/BasicX509Credential.h +++ b/xmltooling/security/BasicX509Credential.h @@ -41,7 +41,7 @@ namespace xmltooling { * * @param ownCerts true iff any certificates subsequently stored should be freed by destructor */ - BasicX509Credential(bool ownCerts) : m_key(NULL), m_ownCerts(ownCerts), m_crl(NULL), m_keyInfo(NULL), m_compactKeyInfo(NULL) { + BasicX509Credential(bool ownCerts) : m_key(NULL), m_serial(-1), m_ownCerts(ownCerts), m_crl(NULL), m_keyInfo(NULL), m_compactKeyInfo(NULL) { } /** @@ -52,7 +52,7 @@ namespace xmltooling { * @param crl optional CRL */ BasicX509Credential(XSECCryptoKey* key, const std::vector& certs, XSECCryptoX509CRL* crl=NULL) - : m_key(key), m_xseccerts(certs), m_ownCerts(true), m_crl(crl), m_keyInfo(NULL), m_compactKeyInfo(NULL) { + : m_key(key), m_serial(-1), m_xseccerts(certs), m_ownCerts(true), m_crl(crl), m_keyInfo(NULL), m_compactKeyInfo(NULL) { } /** The private/secret key/keypair. */ @@ -61,6 +61,15 @@ namespace xmltooling { /** Key names (derived from credential, KeyInfo, or both). */ std::set m_keyNames; + /** Subject DN. */ + std::string m_subjectName; + + /** Issuer DN. */ + std::string m_issuerName; + + /** Serial number. */ + int m_serial; + /** The X.509 certificate chain. */ std::vector m_xseccerts; @@ -80,7 +89,7 @@ namespace xmltooling { * Initializes (or reinitializes) a ds:KeyInfo to represent the Credential. */ void initKeyInfo(); - + public: virtual ~BasicX509Credential(); @@ -125,6 +134,20 @@ namespace xmltooling { XSECCryptoX509CRL* getCRL() const { return m_crl; } + + const char* getSubjectName() const { + return m_subjectName.c_str(); + } + + const char* getIssuerName() const { + return m_issuerName.c_str(); + } + + int getSerialNumber() const { + return m_serial; + } + + void extract(); }; }; diff --git a/xmltooling/security/CredentialCriteria.h b/xmltooling/security/CredentialCriteria.h index 8e40b9f..57fd628 100644 --- a/xmltooling/security/CredentialCriteria.h +++ b/xmltooling/security/CredentialCriteria.h @@ -196,8 +196,7 @@ namespace xmltooling { */ enum keyinfo_extraction_t { KEYINFO_EXTRACTION_KEY = 1, - KEYINFO_EXTRACTION_KEYNAMES = 2, - KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES = 4 + KEYINFO_EXTRACTION_KEYNAMES = 2 }; /** @@ -223,17 +222,16 @@ namespace xmltooling { return; int types = (extraction & KEYINFO_EXTRACTION_KEY) ? Credential::RESOLVE_KEYS : 0; - types |= (extraction & KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES) ? X509Credential::RESOLVE_CERTS : 0; + types |= (extraction & KEYINFO_EXTRACTION_KEYNAMES) ? X509Credential::RESOLVE_CERTS : 0; m_credential = XMLToolingConfig::getConfig().getKeyInfoResolver()->resolve(keyInfo,types); if (extraction & KEYINFO_EXTRACTION_KEY) setPublicKey(m_credential->getPublicKey()); - if (extraction & KEYINFO_EXTRACTION_KEYNAMES) + if (extraction & KEYINFO_EXTRACTION_KEYNAMES) { + X509Credential* xcred = dynamic_cast(m_credential); + if (xcred) + xcred->extract(); m_keyNames.insert(m_credential->getKeyNames().begin(), m_credential->getKeyNames().end()); - if (extraction & KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES) { - const X509Credential* xcred = dynamic_cast(m_credential); - if (xcred && !xcred->getEntityCertificateChain().empty()) - X509Credential::extractNames(xcred->getEntityCertificateChain().front(), m_keyNames); } } @@ -260,17 +258,16 @@ namespace xmltooling { return; int types = (extraction & KEYINFO_EXTRACTION_KEY) ? Credential::RESOLVE_KEYS : 0; - types |= (extraction & KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES) ? X509Credential::RESOLVE_CERTS : 0; + types |= (extraction & KEYINFO_EXTRACTION_KEYNAMES) ? X509Credential::RESOLVE_CERTS : 0; m_credential = XMLToolingConfig::getConfig().getKeyInfoResolver()->resolve(keyInfo,types); if (extraction & KEYINFO_EXTRACTION_KEY) setPublicKey(m_credential->getPublicKey()); - if (extraction & KEYINFO_EXTRACTION_KEYNAMES) + if (extraction & KEYINFO_EXTRACTION_KEYNAMES) { + X509Credential* xcred = dynamic_cast(m_credential); + if (xcred) + xcred->extract(); m_keyNames.insert(m_credential->getKeyNames().begin(), m_credential->getKeyNames().end()); - if (extraction & KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES) { - const X509Credential* xcred = dynamic_cast(m_credential); - if (xcred && !xcred->getEntityCertificateChain().empty()) - X509Credential::extractNames(xcred->getEntityCertificateChain().front(), m_keyNames); } } @@ -284,10 +281,10 @@ namespace xmltooling { setXMLAlgorithm(sig.getSignatureAlgorithm()); xmlsignature::KeyInfo* k = sig.getKeyInfo(); if (k) - return setKeyInfo(k,extraction); + return setKeyInfo(k, extraction); DSIGSignature* dsig = sig.getXMLSignature(); if (dsig) - setNativeKeyInfo(dsig->getKeyInfoList(),extraction); + setNativeKeyInfo(dsig->getKeyInfoList(), extraction); } private: diff --git a/xmltooling/security/X509Credential.h b/xmltooling/security/X509Credential.h index 6442ca1..387dc72 100644 --- a/xmltooling/security/X509Credential.h +++ b/xmltooling/security/X509Credential.h @@ -65,12 +65,30 @@ namespace xmltooling { virtual XSECCryptoX509CRL* getCRL() const=0; /** - * Extracts Subject CN and DNS/URI subjectAltNames from a certificate. + * Gets the subject name of the first certificate in the chain. * - * @param x509 certificate to extract - * @param names a set to insert names into + * @return the Subject DN */ - static void extractNames(XSECCryptoX509* x509, std::set& names); + virtual const char* getSubjectName() const=0; + + /** + * Gets the issuer name of the first certificate in the chain. + * + * @return the Issuer DN + */ + virtual const char* getIssuerName() const=0; + + /** + * Gets the serial number of the first certificate in the chain. + * + * @return the serial number + */ + virtual int getSerialNumber() const=0; + + /** + * Extracts properties like issuer and subject from the first certificate in the chain. + */ + virtual void extract()=0; }; }; diff --git a/xmltooling/security/impl/BasicX509Credential.cpp b/xmltooling/security/impl/BasicX509Credential.cpp index df3d1aa..ff7fb52 100644 --- a/xmltooling/security/impl/BasicX509Credential.cpp +++ b/xmltooling/security/impl/BasicX509Credential.cpp @@ -54,41 +54,113 @@ void BasicX509Credential::initKeyInfo() m_compactKeyInfo = KeyInfoBuilder::buildKeyInfo(); VectorOf(KeyName) knames = m_compactKeyInfo->getKeyNames(); for (set::const_iterator n = names.begin(); n!=names.end(); ++n) { + if (*n == m_subjectName) + continue; auto_ptr_XMLCh wide(n->c_str()); KeyName* kname = KeyNameBuilder::buildKeyName(); kname->setName(wide.get()); knames.push_back(kname); } } + + if (!m_subjectName.empty() || (!m_issuerName.empty() && m_serial >= 0)) { + if (!m_compactKeyInfo) + m_compactKeyInfo = KeyInfoBuilder::buildKeyInfo(); + X509Data* x509Data=X509DataBuilder::buildX509Data(); + m_compactKeyInfo->getX509Datas().push_back(x509Data); + if (!m_subjectName.empty()) { + X509SubjectName* sn = X509SubjectNameBuilder::buildX509SubjectName(); + auto_ptr_XMLCh wide(m_subjectName.c_str()); + sn->setName(wide.get()); + x509Data->getX509SubjectNames().push_back(sn); + } + + if (!m_issuerName.empty() && m_serial >= 0) { + X509IssuerSerial* is = X509IssuerSerialBuilder::buildX509IssuerSerial(); + X509IssuerName* in = X509IssuerNameBuilder::buildX509IssuerName(); + auto_ptr_XMLCh wide(m_issuerName.c_str()); + in->setName(wide.get()); + is->setX509IssuerName(in); + X509SerialNumber* ser = X509SerialNumberBuilder::buildX509SerialNumber(); + char buf[64]; + sprintf(buf,"%d",m_serial); + auto_ptr_XMLCh wide2(buf); + ser->setSerialNumber(wide2.get()); + is->setX509SerialNumber(ser); + x509Data->getX509IssuerSerials().push_back(is); + } + } if (!m_xseccerts.empty()) { m_keyInfo = m_compactKeyInfo ? m_compactKeyInfo->cloneKeyInfo() : KeyInfoBuilder::buildKeyInfo(); - X509Data* x509Data=X509DataBuilder::buildX509Data(); - m_keyInfo->getX509Datas().push_back(x509Data); + if (m_keyInfo->getX509Datas().empty()) + m_keyInfo->getX509Datas().push_back(X509DataBuilder::buildX509Data()); for (vector::const_iterator x = m_xseccerts.begin(); x!=m_xseccerts.end(); ++x) { safeBuffer& buf=(*x)->getDEREncodingSB(); X509Certificate* x509=X509CertificateBuilder::buildX509Certificate(); x509->setValue(buf.sbStrToXMLCh()); - x509Data->getX509Certificates().push_back(x509); + m_keyInfo->getX509Datas().front()->getX509Certificates().push_back(x509); } } } -void X509Credential::extractNames(XSECCryptoX509* x509, set& names) +void BasicX509Credential::extract() { + XSECCryptoX509* x509 = m_xseccerts.empty() ? NULL : m_xseccerts.front(); if (!x509 || x509->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) return; - X509* cert = static_cast(x509)->getOpenSSLX509(); if (!cert) return; - + + BIO* b; + int len; + char buf[256]; + + X509_NAME* issuer=X509_get_issuer_name(cert); + if (issuer) { + memset(buf,0,sizeof(buf)); + b = BIO_new(BIO_s_mem()); + BIO_set_mem_eof_return(b, 0); + len=X509_NAME_print_ex(b,issuer,0,XN_FLAG_RFC2253); + BIO_flush(b); + m_issuerName.erase(); + while ((len = BIO_read(b, buf, 255)) > 0) { + buf[len] = '\0'; + m_issuerName+=buf; + } + BIO_free(b); + } + + ASN1_INTEGER* serialASN = X509_get_serialNumber(cert); + BIGNUM* serialBN = ASN1_INTEGER_to_BN(serialASN, NULL); + if (serialBN) { + char* serial = BN_bn2dec(serialBN); + if (serial) { + m_serial = atoi(serial); + free(serial); + } + BN_free(serialBN); + } + X509_NAME* subject=X509_get_subject_name(cert); if (subject) { - char buf[256]; + memset(buf,0,sizeof(buf)); + b = BIO_new(BIO_s_mem()); + BIO_set_mem_eof_return(b, 0); + len=X509_NAME_print_ex(b,subject,0,XN_FLAG_RFC2253); + BIO_flush(b); + m_subjectName.erase(); + while ((len = BIO_read(b, buf, 255)) > 0) { + buf[len] = '\0'; + m_subjectName+=buf; + } + m_keyNames.insert(m_subjectName); + BIO_free(b); + memset(buf,0,sizeof(buf)); if (X509_NAME_get_text_by_NID(subject,NID_commonName,buf,255)>0) - names.insert(buf); + m_keyNames.insert(buf); STACK_OF(GENERAL_NAME)* altnames=(STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); if (altnames) { @@ -102,7 +174,7 @@ void X509Credential::extractNames(XSECCryptoX509* x509, set& names) if (altlen>0) { alt.erase(); alt.append(altptr,altlen); - names.insert(alt); + m_keyNames.insert(alt); } } } diff --git a/xmltooling/security/impl/FilesystemCredentialResolver.cpp b/xmltooling/security/impl/FilesystemCredentialResolver.cpp index acd79c9..0c0bbff 100644 --- a/xmltooling/security/impl/FilesystemCredentialResolver.cpp +++ b/xmltooling/security/impl/FilesystemCredentialResolver.cpp @@ -73,8 +73,7 @@ namespace xmltooling { FilesystemCredential( FilesystemCredentialResolver* resolver, XSECCryptoKey* key, const std::vector& xseccerts, XSECCryptoX509CRL* crl=NULL ) : BasicX509Credential(key, xseccerts, crl), m_resolver(resolver), m_usage(UNSPECIFIED_CREDENTIAL) { - if (!m_xseccerts.empty()) - extractNames(m_xseccerts.front(), m_keyNames); + extract(); initKeyInfo(); } virtual ~FilesystemCredential() { diff --git a/xmltooling/security/impl/InlineKeyResolver.cpp b/xmltooling/security/impl/InlineKeyResolver.cpp index deaf595..a9771fb 100644 --- a/xmltooling/security/impl/InlineKeyResolver.cpp +++ b/xmltooling/security/impl/InlineKeyResolver.cpp @@ -182,7 +182,45 @@ void InlineCredential::resolve(const KeyInfo* keyInfo, int types) if (types & X509Credential::RESOLVE_CRLS) resolveCRL(keyInfo); - keyInfo->extractNames(m_keyNames); + const XMLCh* n; + char* kn; + const vector& knames=keyInfo->getKeyNames(); + for (vector::const_iterator kn_i=knames.begin(); kn_i!=knames.end(); ++kn_i) { + n=(*kn_i)->getName(); + if (n && *n) { + kn=toUTF8(n); + m_keyNames.insert(kn); + delete[] kn; + } + } + const vector datas=keyInfo->getX509Datas(); + for (vector::const_iterator x_i=datas.begin(); x_i!=datas.end(); ++x_i) { + const vector snames = const_cast(*x_i)->getX509SubjectNames(); + for (vector::const_iterator sn_i = snames.begin(); sn_i!=snames.end(); ++sn_i) { + n = (*sn_i)->getName(); + if (n && *n) { + kn=toUTF8(n); + m_keyNames.insert(kn); + m_subjectName = kn; + delete[] kn; + } + } + + const vector inames = const_cast(*x_i)->getX509IssuerSerials(); + if (!inames.empty()) { + const X509IssuerName* iname = inames.front()->getX509IssuerName(); + if (iname) { + kn = toUTF8(iname->getName()); + if (kn) + m_issuerName = kn; + delete[] kn; + } + + const X509SerialNumber* ser = inames.front()->getX509SerialNumber(); + if (ser) + m_serial = XMLString::parseInt(ser->getSerialNumber()); + } + } } bool InlineCredential::resolveKey(const KeyInfo* keyInfo) @@ -372,5 +410,31 @@ void InlineCredential::resolve(DSIGKeyInfoList* keyInfo, int types) } } - Signature::extractNames(keyInfo, m_keyNames); + char* kn; + const XMLCh* n; + + for (size_t s=0; sgetSize(); s++) { + DSIGKeyInfo* dki = keyInfo->item(s); + n=dki->getKeyName(); + if (n && *n) { + kn=toUTF8(n); + m_keyNames.insert(kn); + if (dki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) + m_subjectName = kn; + delete[] kn; + } + + if (dki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) { + DSIGKeyInfoX509* kix = static_cast(dki); + n = kix->getX509IssuerName(); + if (n && *n) { + kn=toUTF8(n); + m_issuerName = kn; + delete[] kn; + } + n = kix->getX509IssuerSerialNumber(); + if (n && *n) + m_serial = XMLString::parseInt(n); + } + } } diff --git a/xmltooling/signature/KeyInfo.h b/xmltooling/signature/KeyInfo.h index a0d16f5..d9382a8 100644 --- a/xmltooling/signature/KeyInfo.h +++ b/xmltooling/signature/KeyInfo.h @@ -160,13 +160,6 @@ namespace xmlsignature { DECL_TYPED_CHILDREN(SPKIData); /** KeyInfoType local name */ static const XMLCh TYPE_NAME[]; - - /** - * Populates a set of key names using the information found in this KeyInfo object. - * - * @param names a set of names to populate - */ - virtual void extractNames(std::set& names) const=0; END_XMLOBJECT; DECL_XMLSIGOBJECTBUILDER(PGPData); diff --git a/xmltooling/signature/Signature.h b/xmltooling/signature/Signature.h index 76e80d1..4196295 100644 --- a/xmltooling/signature/Signature.h +++ b/xmltooling/signature/Signature.h @@ -193,14 +193,6 @@ namespace xmlsignature { unsigned int in_len ); - /** - * Populates a set of key names using the information found in a native KeyInfo object. - * - * @param keyInfo a native KeyInfo object - * @param names a set of names to populate - */ - static void extractNames(DSIGKeyInfoList* keyInfo, std::set& names); - protected: Signature() {} }; diff --git a/xmltooling/signature/impl/KeyInfoImpl.cpp b/xmltooling/signature/impl/KeyInfoImpl.cpp index 9a2152e..1f59137 100644 --- a/xmltooling/signature/impl/KeyInfoImpl.cpp +++ b/xmltooling/signature/impl/KeyInfoImpl.cpp @@ -705,41 +705,6 @@ namespace xmlsignature { IMPL_TYPED_CHILDREN(PGPData,m_children.end()); IMPL_XMLOBJECT_CHILDREN(UnknownXMLObject,m_children.end()); - void extractNames(set& names) const { - const XMLCh* n; - char* kn; - const vector& knames=getKeyNames(); - for (vector::const_iterator kn_i=knames.begin(); kn_i!=knames.end(); ++kn_i) { - n=(*kn_i)->getName(); - if (n && *n) { - kn=toUTF8(n); - names.insert(kn); - delete[] kn; - } - } - const vector datas=getX509Datas(); - for (vector::const_iterator x_i=datas.begin(); x_i!=datas.end(); ++x_i) { - const vector snames = const_cast(*x_i)->getX509SubjectNames(); - for (vector::const_iterator sn_i = snames.begin(); sn_i!=snames.end(); ++sn_i) { - n = (*sn_i)->getName(); - if (n && *n) { - kn=toUTF8(n); - names.insert(kn); - delete[] kn; - } - } - const vector skis = const_cast(*x_i)->getX509SKIs(); - for (vector::const_iterator sk_i = skis.begin(); sk_i!=skis.end(); ++sk_i) { - n = (*sk_i)->getValue(); - if (n && *n) { - kn=toUTF8(n); - names.insert(kn); - delete[] kn; - } - } - } - } - protected: void marshallAttributes(DOMElement* domElement) const { MARSHALL_ID_ATTRIB(Id,ID,NULL); diff --git a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp index 938a684..da8eb1a 100644 --- a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp +++ b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp @@ -529,18 +529,3 @@ bool Signature::verifyRawSignature( throw SignatureException(string("Caught an XMLSecurity exception while verifying raw signature: ") + e.getMsg()); } } - -void Signature::extractNames(DSIGKeyInfoList* keyInfo, set& names) -{ - char* kn; - const XMLCh* n; - - for (size_t s=0; sgetSize(); s++) { - n=keyInfo->item(s)->getKeyName(); - if (n && *n) { - kn=toUTF8(n); - names.insert(kn); - delete[] kn; - } - } -} -- 2.1.4