summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Ice/PropertyNames.cpp4
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/src/IceSSL/SChannelEngine.cpp308
-rw-r--r--cpp/src/IceSSL/SecureTransportEngine.cpp13
-rw-r--r--cpp/src/IceSSL/Util.cpp433
-rw-r--r--cpp/src/IceSSL/Util.h5
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
//