diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Ice/PropertyNames.cpp | 4 | ||||
-rw-r--r-- | cpp/src/Ice/PropertyNames.h | 2 | ||||
-rw-r--r-- | cpp/src/IceSSL/SChannelEngine.cpp | 308 | ||||
-rw-r--r-- | cpp/src/IceSSL/SecureTransportEngine.cpp | 13 | ||||
-rw-r--r-- | cpp/src/IceSSL/Util.cpp | 433 | ||||
-rw-r--r-- | cpp/src/IceSSL/Util.h | 5 |
6 files changed, 456 insertions, 309 deletions
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp index 0b1422b3e7b..4f42559437a 100644 --- a/cpp/src/Ice/PropertyNames.cpp +++ b/cpp/src/Ice/PropertyNames.cpp @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ../config/PropertyNames.xml, Fri Aug 15 11:14:41 2014 +// Generated by makeprops.py from file ../config/PropertyNames.xml, Mon Aug 18 23:51:46 2014 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -1038,6 +1038,8 @@ const IceInternal::Property IceSSLPropsData[] = IceInternal::Property("IceSSL.ProtocolVersionMax", false, 0), IceInternal::Property("IceSSL.ProtocolVersionMin", false, 0), IceInternal::Property("IceSSL.Random", false, 0), + IceInternal::Property("IceSSL.SecureTransport.FindCert", false, 0), + IceInternal::Property("IceSSL.SChannel.FindCert.*", false, 0), IceInternal::Property("IceSSL.Trace.Security", false, 0), IceInternal::Property("IceSSL.TrustOnly", false, 0), IceInternal::Property("IceSSL.TrustOnly.Client", false, 0), diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h index 8db1b8abf12..57fec2eff3c 100644 --- a/cpp/src/Ice/PropertyNames.h +++ b/cpp/src/Ice/PropertyNames.h @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ../config/PropertyNames.xml, Fri Aug 15 11:14:41 2014 +// Generated by makeprops.py from file ../config/PropertyNames.xml, Mon Aug 18 23:51:46 2014 // IMPORTANT: Do not edit this file -- any edits made here will be lost! diff --git a/cpp/src/IceSSL/SChannelEngine.cpp b/cpp/src/IceSSL/SChannelEngine.cpp index 4f8a8d061b4..e0aa2bc216e 100644 --- a/cpp/src/IceSSL/SChannelEngine.cpp +++ b/cpp/src/IceSSL/SChannelEngine.cpp @@ -76,7 +76,7 @@ addCertificateToStore(const string& file, HCERTSTORE store, PCCERT_CONTEXT* cert } if(!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &outBuffer[0], - outLength, CERT_STORE_ADD_NEW, cert)) + outLength, CERT_STORE_ADD_NEW, cert)) { if(GetLastError() != static_cast<DWORD>(CRYPT_E_EXISTS)) { @@ -157,310 +157,6 @@ algorithmId(const string& name) return 0; } -// -// Parse a string of the form "location.name" into two parts. -// -void -parseStore(const string& prop, const string& store, DWORD& loc, string& sname) -{ - size_t pos = store.find('.'); - if(pos == string::npos) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: property `" + prop + "' has invalid format"); - } - - const string sloc = toUpper(store.substr(0, pos)); - if(sloc == "CURRENTUSER") - { - loc = CERT_SYSTEM_STORE_CURRENT_USER; - } - else if(sloc == "LOCALMACHINE") - { - loc = CERT_SYSTEM_STORE_LOCAL_MACHINE; - } - else - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unknown store location `" + sloc + "' in " + prop); - } - - sname = store.substr(pos + 1); - if(sname.empty()) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: invalid store name in " + prop); - } -} - - -bool -parseBytes(const string& arg, vector<BYTE>& buffer) -{ - string v = toUpper(arg); - - // - // Check for any invalid characters. - // - size_t pos = v.find_first_not_of(" :0123456789ABCDEF"); - if(pos != string::npos) - { - return false; - } - - // - // Remove any separator characters. - // - ostringstream s; - for(string::const_iterator i = v.begin(); i != v.end(); ++i) - { - if(*i == ' ' || *i == ':') - { - continue; - } - s << *i; - } - v = s.str(); - - // - // Convert the bytes. - // - for(size_t i = 0, length = v.size(); i + 2 <= length;) - { - buffer.push_back(static_cast<BYTE>(strtol(v.substr(i, 2).c_str(), 0, 16))); - i += 2; - } - return true; -} - -void -addMatchingCertificates(HCERTSTORE source, HCERTSTORE target, DWORD findType, const void* findParam) -{ - PCCERT_CONTEXT next = 0; - do - { - if((next = CertFindCertificateInStore(source, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, - findType, findParam, next))) - { - if(!CertAddCertificateContextToStore(target, next, CERT_STORE_ADD_ALWAYS, 0)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error adding certificate to store:\n" + lastErrorToString()); - } - } - } - while(next); -} - -vector<PCCERT_CONTEXT> -findCertificates(const string& prop, const string& storeSpec, const string& value, vector<HCERTSTORE>& stores) -{ - DWORD storeLoc = 0; - string storeName; - parseStore(prop, storeSpec, storeLoc, storeName); - - HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, storeLoc, stringToWstring(storeName).c_str()); - if(!store) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: failure while opening store specified by " + prop + ":\n" + lastErrorToString()); - } - - // - // Start with all of the certificates in the collection and filter as necessary. - // - // - If the value is "*", return all certificates. - // - Otherwise, search using key:value pairs. The following keys are supported: - // - // Issuer - // IssuerDN - // Serial - // Subject - // SubjectDN - // SubjectKeyId - // Thumbprint - // - // A value must be enclosed in single or double quotes if it contains whitespace. - // - - HCERTSTORE tmpStore = 0; - try - { - if(value != "*") - { - size_t start = 0; - size_t pos; - while((pos = value.find(':', start)) != string::npos) - { - string field = toUpper(trim(value.substr(start, pos - start))); - if(field != "SUBJECT" && field != "SUBJECTDN" && field != "ISSUER" && field != "ISSUERDN" && - field != "THUMBPRINT" && field != "SUBJECTKEYID" && field != "SERIAL") - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unknown key in `" + value + "'"); - } - - start = pos + 1; - while(start < value.size() && (value[start] == ' ' || value[start] == '\t')) - { - ++start; - } - - if(start == value.size()) - { - throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: missing argument in `" + value + "'"); - } - - string arg; - if(value[start] == '"' || value[start] == '\'') - { - size_t end = start; - ++end; - while(end < value.size()) - { - if(value[end] == value[start] && value[end - 1] != '\\') - { - break; - } - ++end; - } - if(end == value.size() || value[end] != value[start]) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: unmatched quote in `" + value + "'"); - } - ++start; - arg = value.substr(start, end - start); - start = end + 1; - } - else - { - size_t end = value.find_first_of(" \t", start); - if(end == string::npos) - { - arg = value.substr(start); - start = value.size(); - } - else - { - arg = value.substr(start, end - start); - start = end + 1; - } - } - - tmpStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, 0); - if(!tmpStore) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error adding certificate to store:\n" + lastErrorToString()); - } - - if(field == "SUBJECT" || field == "ISSUER") - { - const wstring argW = stringToWstring(arg); - DWORD findType = field == "SUBJECT" ? CERT_FIND_SUBJECT_STR : CERT_FIND_ISSUER_STR; - addMatchingCertificates(store, tmpStore, findType, argW.c_str()); - } - else if(field == "SUBJECTDN" || field == "ISSUERDN") - { - const wstring argW = stringToWstring(arg); - DWORD length = 0; - if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, - 0, 0, &length, 0)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: invalid value `" + value + "' for property `" + prop + "'\n" + - lastErrorToString()); - } - - vector<BYTE> buffer(length); - if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, - 0, &buffer[0], &length, 0)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: invalid value `" + value + "' for property `" + prop + "'\n" + - lastErrorToString()); - } - - CERT_NAME_BLOB name = { length, &buffer[0] }; - DWORD findType = field == "SUBJECTDN" ? CERT_FIND_SUBJECT_NAME : CERT_FIND_ISSUER_NAME; - addMatchingCertificates(store, tmpStore, findType, &name); - } - else if(field == "THUMBPRINT" || field == "SUBJECTKEYID") - { - vector<BYTE> buffer; - if(!parseBytes(arg, buffer)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: invalid value `" + value + "' for property `" + prop + "'"); - } - - CRYPT_HASH_BLOB hash = { static_cast<DWORD>(buffer.size()), &buffer[0] }; - DWORD findType = field == "THUMBPRINT" ? CERT_FIND_HASH : CERT_FIND_KEY_IDENTIFIER; - addMatchingCertificates(store, tmpStore, findType, &hash); - } - else if(field == "SERIAL") - { - vector<BYTE> buffer; - if(!parseBytes(arg, buffer)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: invalid value `" + value + "' for property `" + prop + "'"); - } - - CRYPT_INTEGER_BLOB serial = { static_cast<DWORD>(buffer.size()), &buffer[0] }; - PCCERT_CONTEXT next = 0; - do - { - if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, - CERT_FIND_ANY, 0, next))) - { - if(CertCompareIntegerBlob(&serial, &next->pCertInfo->SerialNumber)) - { - if(!CertAddCertificateContextToStore(tmpStore, next, CERT_STORE_ADD_ALWAYS, 0)) - { - throw PluginInitializationException(__FILE__, __LINE__, - "IceSSL: error adding certificate to store:\n" + lastErrorToString()); - } - } - } - } - while(next); - } - CertCloseStore(store, 0); - store = tmpStore; - } - } - } - catch(...) - { - if(store && store != tmpStore) - { - CertCloseStore(store, 0); - } - - if(tmpStore) - { - CertCloseStore(tmpStore, 0); - tmpStore = 0; - } - throw; - } - - vector<PCCERT_CONTEXT> certs; - if(store) - { - PCCERT_CONTEXT next = 0; - do - { - if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, 0, - next))) - { - certs.push_back(next); - } - } - while(next); - stores.push_back(store); - } - return certs; -} - } SChannelEngine::SChannelEngine(const CommunicatorPtr& communicator) : @@ -834,7 +530,7 @@ SChannelEngine::initialize() _allCerts.insert(_allCerts.end(), _certs.begin(), _certs.end()); } - const string findPrefix = prefix + "FindCert."; + const string findPrefix = prefix + "SChannel.FindCert."; map<string, string> certProps = properties->getPropertiesForPrefix(findPrefix); if(!certProps.empty()) { diff --git a/cpp/src/IceSSL/SecureTransportEngine.cpp b/cpp/src/IceSSL/SecureTransportEngine.cpp index 37ae0a2dceb..00d4611a017 100644 --- a/cpp/src/IceSSL/SecureTransportEngine.cpp +++ b/cpp/src/IceSSL/SecureTransportEngine.cpp @@ -1032,6 +1032,19 @@ IceSSL::SecureTransportEngine::initialize() } } } + + if(!cert) + { + const string prop = propPrefix + "SecureTransport.FindCert"; + string val = properties->getProperty(prop); + if(!val.empty()) + { + if(!(cert = findCertificates(keychain, prop, val))) + { + throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: no certificates found"); + } + } + } if(cert) { diff --git a/cpp/src/IceSSL/Util.cpp b/cpp/src/IceSSL/Util.cpp index 37a4888e11f..f1c4da46c80 100644 --- a/cpp/src/IceSSL/Util.cpp +++ b/cpp/src/IceSSL/Util.cpp @@ -50,6 +50,48 @@ IceSSL::readFile(const string& file, vector<char>& buffer) } } +namespace +{ +bool +parseBytes(const string& arg, vector<unsigned char>& buffer) +{ + string v = IceUtilInternal::toUpper(arg); + + // + // Check for any invalid characters. + // + size_t pos = v.find_first_not_of(" :0123456789ABCDEF"); + if(pos != string::npos) + { + return false; + } + + // + // Remove any separator characters. + // + ostringstream s; + for(string::const_iterator i = v.begin(); i != v.end(); ++i) + { + if(*i == ' ' || *i == ':') + { + continue; + } + s << *i; + } + v = s.str(); + + // + // Convert the bytes. + // + for(size_t i = 0, length = v.size(); i + 2 <= length;) + { + buffer.push_back(static_cast<unsigned char>(strtol(v.substr(i, 2).c_str(), 0, 16))); + i += 2; + } + return true; +} +} + #ifdef ICE_USE_OPENSSL namespace { @@ -951,6 +993,397 @@ IceSSL::loadCACertificates(const string& file, const string& passphrase, const P } return certificateAuthorities; } + +SecCertificateRef +IceSSL::findCertificates(SecKeychainRef keychain, const string& prop, const string& value) +{ + // + // Search the keychain using key:value pairs. The following keys are supported: + // + // Label + // Serial + // Subject + // SubjectKeyId + // + // A value must be enclosed in single or double quotes if it contains whitespace. + // + CFMutableDictionaryRef query = + CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + const void* values[] = { keychain }; + CFArrayRef searchList = CFArrayCreate(kCFAllocatorDefault, values, 1, &kCFTypeArrayCallBacks); + + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFDictionarySetValue(query, kSecClass, kSecClassCertificate); + CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); + CFDictionarySetValue(query, kSecMatchCaseInsensitive, kCFBooleanTrue); + + size_t start = 0; + size_t pos; + while((pos = value.find(':', start)) != string::npos) + { + string field = IceUtilInternal::toUpper(IceUtilInternal::trim(value.substr(start, pos - start))); + string arg; + try + { + if(field != "LABEL" && field != "SERIAL" && field != "SUBJECT" && field != "SUBJECTKEYID") + { + throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unknown key in `" + value + "'"); + } + + start = pos + 1; + while(start < value.size() && (value[start] == ' ' || value[start] == '\t')) + { + ++start; + } + + if(start == value.size()) + { + throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: missing argument in `" + value + "'"); + } + + if(value[start] == '"' || value[start] == '\'') + { + size_t end = start; + ++end; + while(end < value.size()) + { + if(value[end] == value[start] && value[end - 1] != '\\') + { + break; + } + ++end; + } + if(end == value.size() || value[end] != value[start]) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: unmatched quote in `" + value + "'"); + } + ++start; + arg = value.substr(start, end - start); + start = end + 1; + } + else + { + size_t end = value.find_first_of(" \t", start); + if(end == string::npos) + { + arg = value.substr(start); + start = value.size(); + } + else + { + arg = value.substr(start, end - start); + start = end + 1; + } + } + } + catch(...) + { + CFRelease(searchList); + CFRelease(query); + throw; + } + + if(field == "SUBJECT" || field == "LABEL") + { + CFDictionarySetValue(query, field == "LABEL" ? kSecAttrLabel : kSecMatchSubjectContains, toCFString(arg)); + } + else if(field == "SUBJECTKEYID" || field == "SERIAL") + { + vector<unsigned char> buffer; + if(!parseBytes(arg, buffer)) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: invalid value `" + value + "' for property `" + prop + "'"); + } + CFDataRef data = CFDataCreate(kCFAllocatorDefault, &buffer[0], buffer.size()); + CFDictionarySetValue(query, field == "SUBJECTKEYID" ? kSecAttrSubjectKeyID : kSecAttrSerialNumber, data); + } + } + + SecKeychainItemRef item = 0; + OSStatus err = SecItemCopyMatching(query, (CFTypeRef*)&item); + CFRelease(searchList); + CFRelease(query); + if(err != noErr && err != errSecItemNotFound) + { + throw PluginInitializationException(__FILE__, __LINE__, + "Error searching for keychain items\n" + errorToString(err)); + } + return (SecCertificateRef)item; +} +#elif defined(ICE_USE_SCHANNEL) + +namespace +{ +// +// Parse a string of the form "location.name" into two parts. +// +void +parseStore(const string& prop, const string& store, DWORD& loc, string& sname) +{ + size_t pos = store.find('.'); + if(pos == string::npos) + { + throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: property `" + prop + "' has invalid format"); + } + + const string sloc = IceUtilInternal::toUpper(store.substr(0, pos)); + if(sloc == "CURRENTUSER") + { + loc = CERT_SYSTEM_STORE_CURRENT_USER; + } + else if(sloc == "LOCALMACHINE") + { + loc = CERT_SYSTEM_STORE_LOCAL_MACHINE; + } + else + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: unknown store location `" + sloc + "' in " + prop); + } + + sname = store.substr(pos + 1); + if(sname.empty()) + { + throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: invalid store name in " + prop); + } +} + +void +addMatchingCertificates(HCERTSTORE source, HCERTSTORE target, DWORD findType, const void* findParam) +{ + PCCERT_CONTEXT next = 0; + do + { + if((next = CertFindCertificateInStore(source, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, + findType, findParam, next))) + { + if(!CertAddCertificateContextToStore(target, next, CERT_STORE_ADD_ALWAYS, 0)) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: error adding certificate to store:\n" + IceUtilInternal::lastErrorToString()); + } + } + } + while(next); +} + +} + +vector<PCCERT_CONTEXT> +IceSSL::findCertificates(const string& prop, const string& storeSpec, const string& value, vector<HCERTSTORE>& stores) +{ + DWORD storeLoc = 0; + string storeName; + parseStore(prop, storeSpec, storeLoc, storeName); + + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, storeLoc, stringToWstring(storeName).c_str()); + if(!store) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: failure while opening store specified by " + prop + ":\n" + IceUtilInternal::lastErrorToString()); + } + + // + // Start with all of the certificates in the collection and filter as necessary. + // + // - If the value is "*", return all certificates. + // - Otherwise, search using key:value pairs. The following keys are supported: + // + // Issuer + // IssuerDN + // Serial + // Subject + // SubjectDN + // SubjectKeyId + // Thumbprint + // + // A value must be enclosed in single or double quotes if it contains whitespace. + // + HCERTSTORE tmpStore = 0; + try + { + if(value != "*") + { + size_t start = 0; + size_t pos; + while((pos = value.find(':', start)) != string::npos) + { + string field = IceUtilInternal::toUpper(IceUtilInternal::trim(value.substr(start, pos - start))); + if(field != "SUBJECT" && field != "SUBJECTDN" && field != "ISSUER" && field != "ISSUERDN" && + field != "THUMBPRINT" && field != "SUBJECTKEYID" && field != "SERIAL") + { + throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: unknown key in `" + value + "'"); + } + + start = pos + 1; + while(start < value.size() && (value[start] == ' ' || value[start] == '\t')) + { + ++start; + } + + if(start == value.size()) + { + throw PluginInitializationException(__FILE__, __LINE__, "IceSSL: missing argument in `" + value + "'"); + } + + string arg; + if(value[start] == '"' || value[start] == '\'') + { + size_t end = start; + ++end; + while(end < value.size()) + { + if(value[end] == value[start] && value[end - 1] != '\\') + { + break; + } + ++end; + } + if(end == value.size() || value[end] != value[start]) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: unmatched quote in `" + value + "'"); + } + ++start; + arg = value.substr(start, end - start); + start = end + 1; + } + else + { + size_t end = value.find_first_of(" \t", start); + if(end == string::npos) + { + arg = value.substr(start); + start = value.size(); + } + else + { + arg = value.substr(start, end - start); + start = end + 1; + } + } + + tmpStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, 0); + if(!tmpStore) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: error adding certificate to store:\n" + IceUtilInternal::lastErrorToString()); + } + + if(field == "SUBJECT" || field == "ISSUER") + { + const wstring argW = stringToWstring(arg); + DWORD findType = field == "SUBJECT" ? CERT_FIND_SUBJECT_STR : CERT_FIND_ISSUER_STR; + addMatchingCertificates(store, tmpStore, findType, argW.c_str()); + } + else if(field == "SUBJECTDN" || field == "ISSUERDN") + { + const wstring argW = stringToWstring(arg); + DWORD length = 0; + if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, + 0, 0, &length, 0)) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: invalid value `" + value + "' for property `" + prop + "'\n" + + IceUtilInternal::lastErrorToString()); + } + + vector<BYTE> buffer(length); + if(!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, + 0, &buffer[0], &length, 0)) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: invalid value `" + value + "' for property `" + prop + "'\n" + + IceUtilInternal::lastErrorToString()); + } + + CERT_NAME_BLOB name = { length, &buffer[0] }; + DWORD findType = field == "SUBJECTDN" ? CERT_FIND_SUBJECT_NAME : CERT_FIND_ISSUER_NAME; + addMatchingCertificates(store, tmpStore, findType, &name); + } + else if(field == "THUMBPRINT" || field == "SUBJECTKEYID") + { + vector<BYTE> buffer; + if(!parseBytes(arg, buffer)) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: invalid value `" + value + "' for property `" + prop + "'"); + } + + CRYPT_HASH_BLOB hash = { static_cast<DWORD>(buffer.size()), &buffer[0] }; + DWORD findType = field == "THUMBPRINT" ? CERT_FIND_HASH : CERT_FIND_KEY_IDENTIFIER; + addMatchingCertificates(store, tmpStore, findType, &hash); + } + else if(field == "SERIAL") + { + vector<BYTE> buffer; + if(!parseBytes(arg, buffer)) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: invalid value `" + value + "' for property `" + prop + "'"); + } + + CRYPT_INTEGER_BLOB serial = { static_cast<DWORD>(buffer.size()), &buffer[0] }; + PCCERT_CONTEXT next = 0; + do + { + if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, + CERT_FIND_ANY, 0, next))) + { + if(CertCompareIntegerBlob(&serial, &next->pCertInfo->SerialNumber)) + { + if(!CertAddCertificateContextToStore(tmpStore, next, CERT_STORE_ADD_ALWAYS, 0)) + { + throw PluginInitializationException(__FILE__, __LINE__, + "IceSSL: error adding certificate to store:\n" + + IceUtilInternal::lastErrorToString()); + } + } + } + } + while(next); + } + CertCloseStore(store, 0); + store = tmpStore; + } + } + } + catch(...) + { + if(store && store != tmpStore) + { + CertCloseStore(store, 0); + } + + if(tmpStore) + { + CertCloseStore(tmpStore, 0); + tmpStore = 0; + } + throw; + } + + vector<PCCERT_CONTEXT> certs; + if(store) + { + PCCERT_CONTEXT next = 0; + do + { + if((next = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, 0, + next))) + { + certs.push_back(next); + } + } + while(next); + stores.push_back(store); + } + return certs; +} #endif bool diff --git a/cpp/src/IceSSL/Util.h b/cpp/src/IceSSL/Util.h index 6204dedbb4d..73641441047 100644 --- a/cpp/src/IceSSL/Util.h +++ b/cpp/src/IceSSL/Util.h @@ -114,7 +114,10 @@ void loadCertificate(SecCertificateRef*, CFDataRef*, SecKeyRef*, SecKeychainRef, const std::string& = "", const PasswordPromptPtr& = 0, int = 0); CFArrayRef loadCACertificates(const std::string&, const std::string& = "", const PasswordPromptPtr& = 0, int = 0); - +SecCertificateRef findCertificates(SecKeychainRef, const std::string&, const std::string&); +#elif defined(ICE_USE_SCHANNEL) +std::vector<PCCERT_CONTEXT> +findCertificates(const std::string&, const std::string&, const std::string&, std::vector<HCERTSTORE>&); #endif // |