1 // **********************************************************************
3 // Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
8 // **********************************************************************
10 #include <IceUtil/Config.h>
12 # include <winsock2.h>
15 #include <IceSSL/Instance.h>
16 #include <IceSSL/EndpointI.h>
17 #include <IceSSL/Util.h>
18 #include <IceSSL/TrustManager.h>
20 #include <Ice/Communicator.h>
21 #include <Ice/LocalException.h>
22 #include <Ice/Logger.h>
23 #include <Ice/LoggerUtil.h>
24 #include <Ice/Properties.h>
25 #include <Ice/ProtocolPluginFacade.h>
26 #include <Ice/StringConverter.h>
28 #include <IceUtil/Mutex.h>
29 #include <IceUtil/MutexPtrLock.h>
30 #include <IceUtil/StringUtil.h>
32 #include <openssl/rand.h>
33 #include <openssl/err.h>
35 #include <IceUtil/DisableWarnings.h>
39 using namespace IceSSL
;
41 IceUtil::Shared
* IceInternal::upCast(IceSSL::Instance
* p
) { return p
; }
46 IceUtil::Mutex
* staticMutex
= 0;
47 int instanceCount
= 0;
48 IceUtil::Mutex
* locks
= 0;
56 staticMutex
= new IceUtil::Mutex
;
80 // OpenSSL mutex callback.
83 IceSSL_opensslLockCallback(int mode
, int n
, const char* file
, int line
)
86 if(mode
& CRYPTO_LOCK
)
97 // OpenSSL thread id callback.
100 IceSSL_opensslThreadIdCallback()
103 return static_cast<unsigned long>(GetCurrentThreadId());
104 #elif defined(__FreeBSD__) || defined(__APPLE__) || defined(__osf1__)
106 // On some platforms, pthread_t is a pointer to a per-thread structure.
108 return reinterpret_cast<unsigned long>(pthread_self());
109 #elif (defined(__linux) || defined(__sun) || defined(__hpux)) || defined(_AIX)
111 // On Linux, Solaris, HP-UX and AIX, pthread_t is an integer.
113 return static_cast<unsigned long>(pthread_self());
115 # error "Unknown platform"
120 IceSSL_opensslPasswordCallback(char* buf
, int size
, int flag
, void* userData
)
122 IceSSL::Instance
* p
= reinterpret_cast<IceSSL::Instance
*>(userData
);
123 string passwd
= p
->password(flag
== 1);
124 int sz
= static_cast<int>(passwd
.size());
129 strncpy(buf
, passwd
.c_str(), sz
);
132 for(string::iterator i
= passwd
.begin(); i
!= passwd
.end(); ++i
)
140 #ifndef OPENSSL_NO_DH
142 IceSSL_opensslDHCallback(SSL
* ssl
, int /*isExport*/, int keyLength
)
144 IceSSL::Instance
* p
= reinterpret_cast<IceSSL::Instance
*>(SSL_CTX_get_ex_data(ssl
->ctx
, 0));
145 return p
->dhParams(keyLength
);
150 IceSSL_opensslVerifyCallback(int ok
, X509_STORE_CTX
* ctx
)
152 SSL
* ssl
= reinterpret_cast<SSL
*>(X509_STORE_CTX_get_ex_data(ctx
, SSL_get_ex_data_X509_STORE_CTX_idx()));
153 IceSSL::Instance
* p
= reinterpret_cast<IceSSL::Instance
*>(SSL_CTX_get_ex_data(ssl
->ctx
, 0));
154 return p
->verifyCallback(ok
, ssl
, ctx
);
162 int reason
= ERR_GET_REASON(ERR_peek_error());
163 return (reason
== PEM_R_BAD_BASE64_DECODE
||
164 reason
== PEM_R_BAD_DECRYPT
||
165 reason
== PEM_R_BAD_PASSWORD_READ
||
166 reason
== PEM_R_PROBLEMS_GETTING_PASSWORD
);
169 IceSSL::Instance::Instance(const CommunicatorPtr
& communicator
) :
170 _logger(communicator
->getLogger()),
177 // Initialize OpenSSL if necessary.
179 IceUtilInternal::MutexPtrLock
<IceUtil::Mutex
> sync(staticMutex
);
182 if(instanceCount
== 1)
184 PropertiesPtr properties
= communicator
->getProperties();
187 // Create the mutexes and set the callbacks.
191 locks
= new IceUtil::Mutex
[CRYPTO_num_locks()];
192 CRYPTO_set_locking_callback(IceSSL_opensslLockCallback
);
193 CRYPTO_set_id_callback(IceSSL_opensslThreadIdCallback
);
197 // Load human-readable error messages.
199 SSL_load_error_strings();
202 // Initialize the SSL library.
207 // This is necessary to allow programs that use OpenSSL 0.9.x to
208 // load private key files generated by OpenSSL 1.x.
210 OpenSSL_add_all_algorithms();
213 // Initialize the PRNG.
216 RAND_screen(); // Uses data from the screen if possible.
219 if(RAND_file_name(randFile
, sizeof(randFile
))) // Gets the name of a default seed file.
221 RAND_load_file(randFile
, 1024);
223 string randFiles
= Ice::nativeToUTF8(communicator
, properties
->getProperty("IceSSL.Random"));
225 if(!randFiles
.empty())
227 vector
<string
> files
;
229 const string sep
= ";";
231 const string sep
= ":";
233 string defaultDir
= Ice::nativeToUTF8(communicator
, properties
->getProperty("IceSSL.DefaultDir"));
235 if(!IceUtilInternal::splitString(randFiles
, sep
, files
))
237 PluginInitializationException
ex(__FILE__
, __LINE__
);
238 ex
.reason
= "IceSSL: invalid value for IceSSL.Random:\n" + randFiles
;
241 for(vector
<string
>::iterator p
= files
.begin(); p
!= files
.end(); ++p
)
244 if(!checkPath(file
, defaultDir
, false))
246 PluginInitializationException
ex(__FILE__
, __LINE__
);
247 ex
.reason
= "IceSSL: entropy data file not found:\n" + file
;
250 if(!RAND_load_file(file
.c_str(), 1024))
252 PluginInitializationException
ex(__FILE__
, __LINE__
);
253 ex
.reason
= "IceSSL: unable to load entropy data from " + file
;
260 // The Entropy Gathering Daemon (EGD) is not available on Windows.
261 // The file should be a Unix domain socket for the daemon.
263 string entropyDaemon
= properties
->getProperty("IceSSL.EntropyDaemon");
264 if(!entropyDaemon
.empty())
266 if(RAND_egd(entropyDaemon
.c_str()) <= 0)
268 PluginInitializationException
ex(__FILE__
, __LINE__
);
269 ex
.reason
= "IceSSL: EGD failure using file " + entropyDaemon
;
276 communicator
->getLogger()->warning("IceSSL: insufficient data to initialize PRNG");
280 _facade
= IceInternal::getProtocolPluginFacade(communicator
);
281 _securityTraceLevel
= communicator
->getProperties()->getPropertyAsInt("IceSSL.Trace.Security");
282 _securityTraceCategory
= "Security";
283 _trustManager
= new TrustManager(communicator
);
286 // Register the endpoint factory. We have to do this now, rather than
287 // in initialize, because the communicator may need to interpret
288 // proxies before the plug-in is fully initialized.
290 _facade
->addEndpointFactory(new EndpointFactoryI(this));
292 __setNoDelete(false);
295 IceSSL::Instance::~Instance()
298 // Clean up OpenSSL resources.
300 IceUtilInternal::MutexPtrLock
<IceUtil::Mutex
> sync(staticMutex
);
302 if(--instanceCount
== 0)
305 // NOTE: We can't destroy the locks here: threads which might have called openssl methods
306 // might access openssl locks upon termination (from DllMain/THREAD_DETACHED). Instead,
307 // we release the locks in the ~Init() static destructor. See bug #4156.
309 //CRYPTO_set_locking_callback(0);
310 //CRYPTO_set_id_callback(0);
314 CRYPTO_cleanup_all_ex_data();
322 IceSSL::Instance::initialize()
331 const string propPrefix
= "IceSSL.";
332 PropertiesPtr properties
= communicator()->getProperties();
335 // CheckCertName determines whether we compare the name in a peer's
336 // certificate against its hostname.
338 _checkCertName
= properties
->getPropertyAsIntWithDefault(propPrefix
+ "CheckCertName", 0) > 0;
341 // VerifyDepthMax establishes the maximum length of a peer's certificate
342 // chain, including the peer's certificate. A value of 0 means there is
345 _verifyDepthMax
= properties
->getPropertyAsIntWithDefault(propPrefix
+ "VerifyDepthMax", 2);
348 // VerifyPeer determines whether certificate validation failures abort a connection.
350 _verifyPeer
= properties
->getPropertyAsIntWithDefault(propPrefix
+ "VerifyPeer", 2);
353 // Create an SSL context if the application hasn't supplied one.
357 _ctx
= SSL_CTX_new(SSLv23_method());
360 PluginInitializationException
ex(__FILE__
, __LINE__
);
361 ex
.reason
= "IceSSL: unable to create SSL context:\n" + sslErrors();
366 // Check for a default directory. We look in this directory for
367 // files mentioned in the configuration.
369 string defaultDir
= properties
->getProperty(propPrefix
+ "DefaultDir");
372 // If the configuration defines a password, or the application has supplied
373 // a password prompt object, then register a password callback. Otherwise,
374 // let OpenSSL use its default behavior.
377 // TODO: Support quoted value?
378 string password
= properties
->getProperty(propPrefix
+ "Password");
379 if(!password
.empty() || _prompt
)
381 SSL_CTX_set_default_passwd_cb(_ctx
, IceSSL_opensslPasswordCallback
);
382 SSL_CTX_set_default_passwd_cb_userdata(_ctx
, this);
383 _password
= password
;
387 int passwordRetryMax
= properties
->getPropertyAsIntWithDefault(propPrefix
+ "PasswordRetryMax", 3);
390 // Establish the location of CA certificates.
393 string caFile
= properties
->getProperty(propPrefix
+ "CertAuthFile");
394 string caDir
= properties
->getPropertyWithDefault(propPrefix
+ "CertAuthDir", defaultDir
);
395 const char* file
= 0;
399 if(!checkPath(caFile
, defaultDir
, false))
401 PluginInitializationException
ex(__FILE__
, __LINE__
);
402 ex
.reason
= "IceSSL: CA certificate file not found:\n" + caFile
;
405 file
= caFile
.c_str();
409 if(!checkPath(caDir
, defaultDir
, true))
411 PluginInitializationException
ex(__FILE__
, __LINE__
);
412 ex
.reason
= "IceSSL: CA certificate directory not found:\n" + caDir
;
420 // The certificate may be stored in an encrypted file, so handle
425 while(count
< passwordRetryMax
)
428 err
= SSL_CTX_load_verify_locations(_ctx
, file
, dir
);
437 string msg
= "IceSSL: unable to establish CA certificates";
440 msg
+= ":\ninvalid password";
444 string err
= sslErrors();
450 PluginInitializationException
ex(__FILE__
, __LINE__
);
458 // Establish the certificate chains and private keys. One RSA certificate and
459 // one DSA certificate are allowed.
463 const string sep
= ";";
465 const string sep
= ":";
467 string certFile
= properties
->getProperty(propPrefix
+ "CertFile");
468 string keyFile
= properties
->getProperty(propPrefix
+ "KeyFile");
469 vector
<string
>::size_type numCerts
= 0;
470 if(!certFile
.empty())
472 vector
<string
> files
;
473 if(!IceUtilInternal::splitString(certFile
, sep
, files
) || files
.size() > 2)
475 PluginInitializationException
ex(__FILE__
, __LINE__
);
476 ex
.reason
= "IceSSL: invalid value for " + propPrefix
+ "CertFile:\n" + certFile
;
479 numCerts
= files
.size();
480 for(vector
<string
>::iterator p
= files
.begin(); p
!= files
.end(); ++p
)
483 if(!checkPath(file
, defaultDir
, false))
485 PluginInitializationException
ex(__FILE__
, __LINE__
);
486 ex
.reason
= "IceSSL: certificate file not found:\n" + file
;
490 // The certificate may be stored in an encrypted file, so handle
495 while(count
< passwordRetryMax
)
498 err
= SSL_CTX_use_certificate_chain_file(_ctx
, file
.c_str());
507 string msg
= "IceSSL: unable to load certificate chain from file " + file
;
510 msg
+= ":\ninvalid password";
514 string err
= sslErrors();
520 PluginInitializationException
ex(__FILE__
, __LINE__
);
528 keyFile
= certFile
; // Assume the certificate file also contains the private key.
532 vector
<string
> files
;
533 if(!IceUtilInternal::splitString(keyFile
, sep
, files
) || files
.size() > 2)
535 PluginInitializationException
ex(__FILE__
, __LINE__
);
536 ex
.reason
= "IceSSL: invalid value for " + propPrefix
+ "KeyFile:\n" + keyFile
;
539 if(files
.size() != numCerts
)
541 PluginInitializationException
ex(__FILE__
, __LINE__
);
542 ex
.reason
= "IceSSL: " + propPrefix
+ "KeyFile does not agree with " + propPrefix
+ "CertFile";
545 for(vector
<string
>::iterator p
= files
.begin(); p
!= files
.end(); ++p
)
548 if(!checkPath(file
, defaultDir
, false))
550 PluginInitializationException
ex(__FILE__
, __LINE__
);
551 ex
.reason
= "IceSSL: key file not found:\n" + file
;
555 // The private key may be stored in an encrypted file, so handle
560 while(count
< passwordRetryMax
)
563 err
= SSL_CTX_use_PrivateKey_file(_ctx
, file
.c_str(), SSL_FILETYPE_PEM
);
572 string msg
= "IceSSL: unable to load private key from file " + file
;
575 msg
+= ":\ninvalid password";
579 string err
= sslErrors();
585 PluginInitializationException
ex(__FILE__
, __LINE__
);
590 if(!SSL_CTX_check_private_key(_ctx
))
592 PluginInitializationException
ex(__FILE__
, __LINE__
);
593 ex
.reason
= "IceSSL: unable to validate private key(s):\n" + sslErrors();
600 // Diffie Hellman configuration.
603 #ifndef OPENSSL_NO_DH
604 _dhParams
= new DHParams
;
605 SSL_CTX_set_options(_ctx
, SSL_OP_SINGLE_DH_USE
);
606 SSL_CTX_set_tmp_dh_callback(_ctx
, IceSSL_opensslDHCallback
);
609 // Properties have the following form:
611 // ...DH.<keyLength>=file
613 const string dhPrefix
= propPrefix
+ "DH.";
614 PropertyDict d
= properties
->getPropertiesForPrefix(dhPrefix
);
618 _logger
->warning("IceSSL: OpenSSL is not configured for Diffie Hellman");
620 for(PropertyDict::iterator p
= d
.begin(); p
!= d
.end(); ++p
)
622 string s
= p
->first
.substr(dhPrefix
.size());
623 int keyLength
= atoi(s
.c_str());
626 string file
= p
->second
;
627 if(!checkPath(file
, defaultDir
, false))
629 PluginInitializationException
ex(__FILE__
, __LINE__
);
630 ex
.reason
= "IceSSL: DH parameter file not found:\n" + file
;
633 if(!_dhParams
->add(keyLength
, file
))
635 PluginInitializationException
ex(__FILE__
, __LINE__
);
636 ex
.reason
= "IceSSL: unable to read DH parameter file " + file
;
647 // Store a pointer to ourself for use in OpenSSL callbacks.
649 SSL_CTX_set_ex_data(_ctx
, 0, this);
652 // This is necessary for successful interop with Java. Without it, a Java
653 // client would fail to reestablish a connection: the server gets the
654 // error "session id context uninitialized" and the client receives
655 // "SSLHandshakeException: Remote host closed connection during handshake".
657 SSL_CTX_set_session_cache_mode(_ctx
, SSL_SESS_CACHE_OFF
);
662 StringSeq protocols
= properties
->getPropertyAsList(propPrefix
+ "Protocols");
663 if(!protocols
.empty())
665 parseProtocols(protocols
);
669 // Establish the cipher list.
671 string ciphers
= properties
->getProperty(propPrefix
+ "Ciphers");
674 if(!SSL_CTX_set_cipher_list(_ctx
, ciphers
.c_str()))
676 PluginInitializationException
ex(__FILE__
, __LINE__
);
677 ex
.reason
= "IceSSL: unable to set ciphers using `" + ciphers
+ "':\n" + sslErrors();
683 // Determine whether a certificate is required from the peer.
690 sslVerifyMode
= SSL_VERIFY_NONE
;
693 sslVerifyMode
= SSL_VERIFY_PEER
;
696 sslVerifyMode
= SSL_VERIFY_PEER
|SSL_VERIFY_FAIL_IF_NO_PEER_CERT
;
700 PluginInitializationException
ex(__FILE__
, __LINE__
);
701 ex
.reason
= "IceSSL: invalid value for " + propPrefix
+ "VerifyPeer";
705 SSL_CTX_set_verify(_ctx
, sslVerifyMode
, IceSSL_opensslVerifyCallback
);
711 // We free the SSL context regardless of whether the plugin created it
712 // or the application supplied it.
723 IceSSL::Instance::context(SSL_CTX
* context
)
727 PluginInitializationException
ex(__FILE__
, __LINE__
);
728 ex
.reason
= "IceSSL: plug-in is already initialized";
737 IceSSL::Instance::context() const
743 IceSSL::Instance::setCertificateVerifier(const CertificateVerifierPtr
& verifier
)
745 _verifier
= verifier
;
749 IceSSL::Instance::setPasswordPrompt(const PasswordPromptPtr
& prompt
)
755 IceSSL::Instance::communicator() const
757 return _facade
->getCommunicator();
760 IceInternal::EndpointHostResolverPtr
761 IceSSL::Instance::endpointHostResolver() const
763 return _facade
->getEndpointHostResolver();
766 IceInternal::ProtocolSupport
767 IceSSL::Instance::protocolSupport() const
769 return _facade
->getProtocolSupport();
773 IceSSL::Instance::defaultHost() const
775 return _facade
->getDefaultHost();
779 IceSSL::Instance::networkTraceLevel() const
781 return _facade
->getNetworkTraceLevel();
785 IceSSL::Instance::networkTraceCategory() const
787 return _facade
->getNetworkTraceCategory();
791 IceSSL::Instance::securityTraceLevel() const
793 return _securityTraceLevel
;
797 IceSSL::Instance::securityTraceCategory() const
799 return _securityTraceCategory
;
803 IceSSL::Instance::verifyPeer(SSL
* ssl
, SOCKET fd
, const string
& address
, const NativeConnectionInfoPtr
& info
)
805 long result
= SSL_get_verify_result(ssl
);
806 if(result
!= X509_V_OK
)
810 if(_securityTraceLevel
>= 1)
813 ostr
<< "IceSSL: ignoring certificate verification failure:\n" << X509_verify_cert_error_string(result
);
814 _logger
->trace(_securityTraceCategory
, ostr
.str());
820 ostr
<< "IceSSL: certificate verification failed:\n" << X509_verify_cert_error_string(result
);
821 string msg
= ostr
.str();
822 if(_securityTraceLevel
>= 1)
824 _logger
->trace(_securityTraceCategory
, msg
);
826 SecurityException
ex(__FILE__
, __LINE__
);
832 X509
* rawCert
= SSL_get_peer_certificate(ssl
);
836 cert
= new Certificate(rawCert
);
840 // For an outgoing connection, we compare the proxy address (if any) against
841 // fields in the server's certificate (if any).
843 if(cert
&& !address
.empty())
846 // Extract the IP addresses and the DNS names from the subject
847 // alternative names.
849 vector
<pair
<int, string
> > subjectAltNames
= cert
->getSubjectAlternativeNames();
850 vector
<string
> ipAddresses
;
851 vector
<string
> dnsNames
;
852 for(vector
<pair
<int, string
> >::const_iterator p
= subjectAltNames
.begin(); p
!= subjectAltNames
.end(); ++p
)
856 ipAddresses
.push_back(IceUtilInternal::toLower(p
->second
));
858 else if(p
->first
== 2)
860 dnsNames
.push_back(IceUtilInternal::toLower(p
->second
));
865 // Compare the peer's address against the common name.
867 bool certNameOK
= false;
869 string addrLower
= IceUtilInternal::toLower(address
);
871 DistinguishedName d
= cert
->getSubjectDN();
872 dn
= IceUtilInternal::toLower(string(d
));
873 string cn
= "cn=" + addrLower
;
874 string::size_type pos
= dn
.find(cn
);
875 if(pos
!= string::npos
)
878 // Ensure we match the entire common name.
880 certNameOK
= (pos
+ cn
.size() == dn
.size()) || (dn
[pos
+ cn
.size()] == ',');
885 // Compare the peer's address against the the dnsName and ipAddress
886 // values in the subject alternative name.
890 certNameOK
= find(ipAddresses
.begin(), ipAddresses
.end(), addrLower
) != ipAddresses
.end();
894 certNameOK
= find(dnsNames
.begin(), dnsNames
.end(), addrLower
) != dnsNames
.end();
898 // Log a message if the name comparison fails. If CheckCertName is defined,
899 // we also raise an exception to abort the connection. Don't log a message if
900 // CheckCertName is not defined and a verifier is present.
902 if(!certNameOK
&& (_checkCertName
|| (_securityTraceLevel
>= 1 && !_verifier
)))
910 ostr
<< "certificate validation failure:\npeer certificate does not have `" << address
911 << "' as its commonName or in its subjectAltName extension";
914 ostr
<< "\nSubject DN: " << dn
;
916 if(!dnsNames
.empty())
918 ostr
<< "\nDNS names found in certificate: ";
919 for(vector
<string
>::const_iterator p
= dnsNames
.begin(); p
!= dnsNames
.end(); ++p
)
921 if(p
!= dnsNames
.begin())
928 if(!ipAddresses
.empty())
930 ostr
<< "\nIP addresses found in certificate: ";
931 for(vector
<string
>::const_iterator p
= ipAddresses
.begin(); p
!= ipAddresses
.end(); ++p
)
933 if(p
!= ipAddresses
.begin())
940 string msg
= ostr
.str();
941 if(_securityTraceLevel
>= 1)
943 Trace
out(_logger
, _securityTraceCategory
);
948 SecurityException
ex(__FILE__
, __LINE__
);
955 if(_verifyDepthMax
> 0 && static_cast<int>(info
->certs
.size()) > _verifyDepthMax
)
958 ostr
<< (info
->incoming
? "incoming" : "outgoing") << " connection rejected:\n"
959 << "length of peer's certificate chain (" << info
->certs
.size() << ") exceeds maximum of "
961 string msg
= ostr
.str();
962 if(_securityTraceLevel
>= 1)
964 _logger
->trace(_securityTraceCategory
, msg
+ "\n" + IceInternal::fdToString(fd
));
966 SecurityException
ex(__FILE__
, __LINE__
);
971 if(!_trustManager
->verify(info
))
973 string msg
= string(info
->incoming
? "incoming" : "outgoing") + " connection rejected by trust manager";
974 if(_securityTraceLevel
>= 1)
976 _logger
->trace(_securityTraceCategory
, msg
+ "\n" + IceInternal::fdToString(fd
));
978 SecurityException
ex(__FILE__
, __LINE__
);
983 if(_verifier
&& !_verifier
->verify(info
))
985 string msg
= string(info
->incoming
? "incoming" : "outgoing") + " connection rejected by certificate verifier";
986 if(_securityTraceLevel
>= 1)
988 _logger
->trace(_securityTraceCategory
, msg
+ "\n" + IceInternal::fdToString(fd
));
990 SecurityException
ex(__FILE__
, __LINE__
);
997 IceSSL::Instance::sslErrors() const
999 return getSslErrors(_securityTraceLevel
>= 1);
1003 IceSSL::Instance::destroy()
1014 IceSSL::Instance::password(bool /*encrypting*/)
1020 return _prompt
->getPassword();
1025 // Don't allow exceptions to cross an OpenSSL boundary.
1037 IceSSL::Instance::verifyCallback(int ok
, SSL
* ssl
, X509_STORE_CTX
* c
)
1039 if(!ok
&& _securityTraceLevel
>= 1)
1041 X509
* cert
= X509_STORE_CTX_get_current_cert(c
);
1042 int err
= X509_STORE_CTX_get_error(c
);
1045 Trace
out(_logger
, _securityTraceCategory
);
1046 out
<< "certificate verification failure\n";
1048 X509_NAME_oneline(X509_get_issuer_name(cert
), buf
, static_cast<int>(sizeof(buf
)));
1049 out
<< "issuer = " << buf
<< '\n';
1050 X509_NAME_oneline(X509_get_subject_name(cert
), buf
, static_cast<int>(sizeof(buf
)));
1051 out
<< "subject = " << buf
<< '\n';
1052 out
<< "depth = " << X509_STORE_CTX_get_error_depth(c
) << '\n';
1053 out
<< "error = " << X509_verify_cert_error_string(err
) << '\n';
1054 out
<< IceInternal::fdToString(SSL_get_fd(ssl
));
1059 #ifndef OPENSSL_NO_DH
1061 IceSSL::Instance::dhParams(int keyLength
)
1063 return _dhParams
->get(keyLength
);
1068 IceSSL::Instance::traceConnection(SSL
* ssl
, bool incoming
)
1070 Trace
out(_logger
, _securityTraceCategory
);
1071 out
<< "SSL summary for " << (incoming
? "incoming" : "outgoing") << " connection\n";
1074 // The const_cast is necesary because Solaris still uses OpenSSL 0.9.7.
1076 //const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
1077 SSL_CIPHER
*cipher
= const_cast<SSL_CIPHER
*>(SSL_get_current_cipher(ssl
));
1080 out
<< "unknown cipher\n";
1084 out
<< "cipher = " << SSL_CIPHER_get_name(cipher
) << "\n";
1085 out
<< "bits = " << SSL_CIPHER_get_bits(cipher
, 0) << "\n";
1086 out
<< "protocol = " << SSL_get_version(ssl
) << "\n";
1088 out
<< IceInternal::fdToString(SSL_get_fd(ssl
));
1092 IceSSL::Instance::parseProtocols(const StringSeq
& protocols
)
1094 bool sslv3
= false, tlsv1
= false;
1095 for(Ice::StringSeq::const_iterator p
= protocols
.begin(); p
!= protocols
.end(); ++p
)
1099 if(prot
== "ssl3" || prot
== "sslv3")
1103 else if(prot
== "tls" || prot
== "tls1" || prot
== "tlsv1")
1109 PluginInitializationException
ex(__FILE__
, __LINE__
);
1110 ex
.reason
= "IceSSL: unrecognized protocol `" + prot
+ "'";
1115 long opts
= SSL_OP_NO_SSLv2
; // SSLv2 is not supported.
1118 opts
|= SSL_OP_NO_SSLv3
;
1122 opts
|= SSL_OP_NO_TLSv1
;
1124 SSL_CTX_set_options(_ctx
, opts
);