Also use Objects as part of an operation but as a result don't generate Any operation...
[ACE_TAO.git] / ACE / ace / SSL / SSL_Context.cpp
blobbadc7239546b5b61906ba8af8a2a5385dea97743
1 #include "SSL_Context.h"
3 #include "sslconf.h"
5 #if !defined(__ACE_INLINE__)
6 #include "SSL_Context.inl"
7 #endif /* __ACE_INLINE__ */
9 #include "ace/Guard_T.h"
10 #include "ace/Object_Manager.h"
11 #include "ace/Log_Category.h"
12 #include "ace/Singleton.h"
13 #include "ace/Synch_Traits.h"
14 #include "ace/Truncate.h"
15 #include "ace/ACE.h"
16 #include "ace/INET_Addr.h"
17 #include "ace/OS_NS_errno.h"
18 #include "ace/OS_NS_string.h"
19 #include "ace/OS_NS_ctype.h"
20 #include "ace/OS_NS_netdb.h"
22 #ifdef ACE_HAS_THREADS
23 # include "ace/Thread_Mutex.h"
24 # include "ace/OS_NS_Thread.h"
25 #endif /* ACE_HAS_THREADS */
27 #include <openssl/x509.h>
28 #include <openssl/x509v3.h>
29 #include <openssl/err.h>
30 #include <openssl/rand.h>
31 #include <openssl/safestack.h>
33 namespace
35 /// Reference count of the number of times the ACE_SSL_Context was
36 /// initialized.
37 int ssl_library_init_count = 0;
39 // @@ This should also be done with a singleton, otherwise it is not
40 // thread safe and/or portable to some weird platforms...
42 #if defined(ACE_HAS_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
43 /// Array of mutexes used internally by OpenSSL when the SSL
44 /// application is multithreaded.
45 ACE_SSL_Context::lock_type * ssl_locks = 0;
47 // @@ This should also be managed by a singleton.
48 #endif /* ACE_HAS_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L */
51 #if defined (ACE_HAS_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
53 # if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
54 # define ACE_SSL_LOCKING_CALLBACK_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_locking_callback)
55 # define ACE_SSL_THREAD_ID_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_thread_id)
56 # else
57 # define ACE_SSL_LOCKING_CALLBACK_NAME ACE_SSL_locking_callback
58 # define ACE_SSL_THREAD_ID_NAME ACE_SSL_thread_id
59 # endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
61 extern "C"
63 void
64 ACE_SSL_LOCKING_CALLBACK_NAME (int mode,
65 int type,
66 const char * /* file */,
67 int /* line */)
69 // #ifdef undef
70 // fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
71 // CRYPTO_thread_id(),
72 // (mode&CRYPTO_LOCK)?"l":"u",
73 // (type&CRYPTO_READ)?"r":"w",file,line);
74 // #endif
75 // /*
76 // if (CRYPTO_LOCK_SSL_CERT == type)
77 // fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
78 // CRYPTO_thread_id(),
79 // mode,file,line);
80 // */
81 if (mode & CRYPTO_LOCK)
82 (void) ssl_locks[type].acquire ();
83 else
84 (void) ssl_locks[type].release ();
87 // -------------------------------
89 // Return the current thread ID. OpenSSL uses this on platforms
90 // that need it.
91 unsigned long
92 ACE_SSL_THREAD_ID_NAME (void)
94 return (unsigned long) ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::thr_self ();
97 #endif /* ACE_HAS_THREADS && (OPENSSL_VERSION_NUMBER < 0x10100000L) */
100 // ****************************************************************
102 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
104 #if defined (ACE_HAS_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
105 ACE_SSL_Context::lock_type * ACE_SSL_Context::locks_ = 0;
106 #endif /* ACE_HAS_THREADS && (OPENSSL_VERSION_NUMBER < 0x10100000L) */
108 ACE_SSL_Context::ACE_SSL_Context (void)
109 : context_ (0),
110 mode_ (-1),
111 default_verify_mode_ (SSL_VERIFY_NONE),
112 default_verify_callback_ (0),
113 have_ca_ (0)
115 ACE_SSL_Context::ssl_library_init ();
118 ACE_SSL_Context::~ACE_SSL_Context (void)
120 if (this->context_)
122 ::SSL_CTX_free (this->context_);
123 this->context_ = 0;
126 ACE_SSL_Context::ssl_library_fini ();
129 ACE_SSL_Context *
130 ACE_SSL_Context::instance (void)
132 return ACE_Unmanaged_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::instance ();
135 void
136 ACE_SSL_Context::close (void)
138 ACE_Unmanaged_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::close ();
141 void
142 ACE_SSL_Context::ssl_library_init (void)
144 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
145 ace_ssl_mon,
146 *ACE_Static_Object_Lock::instance ()));
148 if (ssl_library_init_count == 0)
150 // Initialize the locking callbacks before initializing anything
151 // else.
152 #if defined(ACE_HAS_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
153 int const num_locks = ::CRYPTO_num_locks ();
155 this->locks_ = new lock_type[num_locks];
156 ssl_locks = this->locks_;
158 # if !defined (WIN32)
159 // This call isn't necessary on some platforms. See the CRYPTO
160 // library's threads(3) man page for details.
161 ::CRYPTO_set_id_callback (ACE_SSL_THREAD_ID_NAME);
162 # endif /* !WIN32 */
163 ::CRYPTO_set_locking_callback (ACE_SSL_LOCKING_CALLBACK_NAME);
164 #endif /* ACE_HAS_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L */
166 ::SSLeay_add_ssl_algorithms ();
167 ::SSL_load_error_strings ();
169 // Seed the random number generator. Note that the random
170 // number generator can be seeded more than once to "stir" its
171 // state.
173 #ifdef WIN32
174 // Seed the random number generator by sampling the screen.
175 # if OPENSSL_VERSION_NUMBER < 0x10100000L
176 ::RAND_screen ();
177 # else
178 ::RAND_poll ();
179 # endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
180 #endif /* WIN32 */
182 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
183 // OpenSSL < 0.9.5 doesn't have EGD support.
185 const char *egd_socket_file =
186 ACE_OS::getenv (ACE_SSL_EGD_FILE_ENV);
188 if (egd_socket_file != 0)
189 (void) this->egd_file (egd_socket_file);
190 #endif /* OPENSSL_VERSION_NUMBER */
192 const char *rand_file = ACE_OS::getenv (ACE_SSL_RAND_FILE_ENV);
194 if (rand_file != 0)
196 (void) this->seed_file (rand_file);
199 // Initialize the mutexes that will be used by the SSL and
200 // crypto library.
203 ++ssl_library_init_count;
206 void
207 ACE_SSL_Context::ssl_library_fini (void)
209 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
210 ace_ssl_mon,
211 *ACE_Static_Object_Lock::instance ()));
213 --ssl_library_init_count;
214 if (ssl_library_init_count == 0)
216 #if OPENSSL_VERSION_NUMBER < 0x10100000L
217 ::ERR_free_strings ();
218 ::EVP_cleanup ();
220 // Clean up the locking callbacks after everything else has been
221 // cleaned up.
222 #ifdef ACE_HAS_THREADS
223 ::CRYPTO_set_locking_callback (0);
224 ssl_locks = 0;
226 delete [] this->locks_;
227 this->locks_ = 0;
228 #endif /* ACE_HAS_THREADS && */
229 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
234 ACE_SSL_Context::set_mode (int mode)
236 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
237 ace_ssl_mon,
238 *ACE_Static_Object_Lock::instance (),
239 -1));
241 if (this->context_ != 0)
242 return -1;
244 #if OPENSSL_VERSION_NUMBER >= 0x10000002
245 const SSL_METHOD *method = 0;
246 #else
247 SSL_METHOD *method = 0;
248 #endif
250 switch (mode)
252 case ACE_SSL_Context::SSLv23_client:
253 method = ::SSLv23_client_method ();
254 break;
255 case ACE_SSL_Context::SSLv23_server:
256 method = ::SSLv23_server_method ();
257 break;
258 case ACE_SSL_Context::SSLv23:
259 method = ::SSLv23_method ();
260 break;
261 default:
262 method = ::SSLv23_method ();
263 break;
266 this->context_ = ::SSL_CTX_new (method);
267 if (this->context_ == 0)
268 return -1;
270 this->mode_ = mode;
272 // Load the trusted certificate authority (default) certificate
273 // locations. But do not return -1 on error, doing so confuses CTX
274 // allocation (severe error) with the less important loading of CA
275 // certificate location error. If it is important for your
276 // application then call ACE_SSL_Context::have_trusted_ca(),
277 // immediately following this call to set_mode().
278 (void) this->load_trusted_ca ();
280 return 0;
284 ACE_SSL_Context::filter_versions (const char* versionlist)
286 this->check_context ();
288 ACE_CString vlist = versionlist;
289 ACE_CString seplist = " ,;";
290 ACE_CString::size_type pos = 0;
291 bool match = false;
293 for (; pos < vlist.length (); pos++)
295 vlist[pos] = ACE_OS::ace_tolower (vlist[pos]);
298 #if defined (SSL_OP_NO_SSLv2)
299 pos = vlist.find("sslv2");
300 match = pos != ACE_CString::npos &&
301 (pos == vlist.length () - 5 ||
302 seplist.find (vlist[pos + 5]) != ACE_CString::npos);
303 if (!match)
305 ::SSL_CTX_set_options (this->context_, SSL_OP_NO_SSLv2);
307 #endif /* SSL_OP_NO_SSLv2 */
309 #if defined (SSL_OP_NO_SSLv3)
310 pos = vlist.find("sslv3");
311 match = pos != ACE_CString::npos &&
312 (pos == vlist.length () - 5 ||
313 seplist.find (vlist[pos + 5]) != ACE_CString::npos);
314 if (!match)
316 ::SSL_CTX_set_options (this->context_, SSL_OP_NO_SSLv3);
318 #endif /* SSL_OP_NO_SSLv3 */
320 #if defined (SSL_OP_NO_TLSv1)
321 pos = vlist.find("tlsv1");
322 match = pos != ACE_CString::npos &&
323 (pos == vlist.length () - 5 ||
324 seplist.find (vlist[pos + 5]) != ACE_CString::npos);
325 if (!match)
327 ::SSL_CTX_set_options (this->context_, SSL_OP_NO_TLSv1);
329 #endif /* SSL_OP_NO_TLSv1 */
331 #if defined (SSL_OP_NO_TLSv1_1)
332 pos = vlist.find("tlsv1.1");
333 match = pos != ACE_CString::npos &&
334 (pos == vlist.length () - 7 ||
335 seplist.find (vlist[pos + 7]) != ACE_CString::npos);
336 if (!match)
338 ::SSL_CTX_set_options (this->context_, SSL_OP_NO_TLSv1_1);
340 #endif /* SSL_OP_NO_TLSv1_1 */
342 #if defined (SSL_OP_NO_TLSv1_2)
343 pos = vlist.find("tlsv1.2");
344 match = pos != ACE_CString::npos &&
345 (pos == vlist.length () - 7 ||
346 seplist.find (vlist[pos + 7]) != ACE_CString::npos);
347 if (!match)
349 ::SSL_CTX_set_options (this->context_, SSL_OP_NO_TLSv1_2);
351 #endif /* SSL_OP_NO_TLSv1_2 */
352 return 0;
355 bool
356 ACE_SSL_Context::check_host (const ACE_INET_Addr &host, SSL *peerssl)
358 #if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10002001L)
360 this->check_context ();
362 char name[MAXHOSTNAMELEN+1];
364 if (peerssl == 0 || host.get_host_name (name, MAXHOSTNAMELEN) == -1)
366 return false;
369 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
370 X509* cert = ::SSL_get1_peer_certificate(peerssl);
371 #else
372 X509* cert = ::SSL_get_peer_certificate(peerssl);
373 #endif
375 if (cert == 0)
377 return false;
380 char *peer = 0;
381 char **peerarg = ACE::debug () ? &peer : 0;
382 int flags = X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT;
383 size_t len = ACE_OS::strlen (name);
385 int const result = ::X509_check_host (cert, name, len, flags, peerarg);
387 if (ACE::debug ())
389 ACELIB_DEBUG ((LM_DEBUG,
390 ACE_TEXT ("ACE (%P|%t) SSL_Context::check_host ")
391 ACE_TEXT ("name <%C> returns %d, peer <%s>\n"),
392 name, result, peer));
394 if (peer != 0)
396 ::OPENSSL_free (peer);
399 ::X509_free (cert);
401 return result == 1;
402 #else
403 ACE_UNUSED_ARG (host);
404 ACE_UNUSED_ARG (peerssl);
406 return false;
407 #endif /* OPENSSL_VERSION_NUMBER */
411 ACE_SSL_Context::load_trusted_ca (const char* ca_file,
412 const char* ca_dir,
413 bool use_env_defaults)
415 this->check_context ();
417 if (ca_file == 0 && use_env_defaults)
419 // Use the default environment settings.
420 ca_file = ACE_OS::getenv (ACE_SSL_CERT_FILE_ENV);
421 #ifdef ACE_DEFAULT_SSL_CERT_FILE
422 if (ca_file == 0)
423 ca_file = ACE_DEFAULT_SSL_CERT_FILE;
424 #endif
427 if (ca_dir == 0 && use_env_defaults)
429 // Use the default environment settings.
430 ca_dir = ACE_OS::getenv (ACE_SSL_CERT_DIR_ENV);
431 #ifdef ACE_DEFAULT_SSL_CERT_DIR
432 if (ca_dir == 0)
433 ca_dir = ACE_DEFAULT_SSL_CERT_DIR;
434 #endif
437 // NOTE: SSL_CTX_load_verify_locations() returns 0 on error.
438 if (::SSL_CTX_load_verify_locations (this->context_,
439 ca_file,
440 ca_dir) <= 0)
442 if (ACE::debug ())
443 ACE_SSL_Context::report_error ();
444 return -1;
447 ++this->have_ca_;
449 // For TLS/SSL servers scan all certificates in ca_file and ca_dir and
450 // list them as acceptable CAs when requesting a client certificate.
451 if (mode_ == SSLv23 || mode_ == SSLv23_server)
453 // Note: The STACK_OF(X509_NAME) pointer is a copy of the pointer in
454 // the CTX; any changes to it by way of these function calls will
455 // change the CTX directly.
456 STACK_OF (X509_NAME) * cert_names = 0;
457 cert_names = ::SSL_CTX_get_client_CA_list (this->context_);
459 // Add CAs from both the file and dir, if specified. There should
460 // already be a STACK_OF(X509_NAME) in the CTX, but if not, we create
461 // one.
462 if (ca_file)
464 bool error = false;
465 if (cert_names == 0)
467 if ((cert_names = ::SSL_load_client_CA_file (ca_file)) != 0)
468 ::SSL_CTX_set_client_CA_list (this->context_, cert_names);
469 else
470 error = true;
472 else
474 // Add new certificate names to the list.
475 error = (0 == ::SSL_add_file_cert_subjects_to_stack (cert_names,
476 ca_file));
479 if (error)
481 if (ACE::debug ())
482 ACE_SSL_Context::report_error ();
483 return -1;
487 // SSL_add_dir_cert_subjects_to_stack is defined at 0.9.8a (but not
488 // on OpenVMS or Mac Classic); it may be available earlier. Change
489 // this comparison if so. It's still (1.0.1g) broken on windows too.
490 #if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090801fL)
491 # if !defined (OPENSSL_SYS_VMS) && !defined (OPENSSL_SYS_MACINTOSH_CLASSIC)
492 # if !defined (OPENSSL_SYS_WIN32)
494 if (ca_dir != 0)
496 if (cert_names == 0)
498 if ((cert_names = sk_X509_NAME_new_null ()) == 0)
500 if (ACE::debug ())
501 ACE_SSL_Context::report_error ();
502 return -1;
504 ::SSL_CTX_set_client_CA_list (this->context_, cert_names);
506 if (0 == ::SSL_add_dir_cert_subjects_to_stack (cert_names, ca_dir))
508 if (ACE::debug ())
509 ACE_SSL_Context::report_error ();
510 return -1;
513 # endif /* !OPENSSL_SYS_WIN32 */
514 # endif /* !OPENSSL_SYS_VMS && !OPENSSL_SYS_MACINTOSH_CLASSIC */
515 #endif /* OPENSSL_VERSION_NUMBER >= 0.9.8a release */
519 return 0;
523 ACE_SSL_Context::private_key (const char *file_name,
524 int type)
526 if (this->private_key_.type () != -1)
527 return 0;
529 this->check_context ();
531 this->private_key_ = ACE_SSL_Data_File (file_name, type);
533 if (::SSL_CTX_use_PrivateKey_file (this->context_,
534 this->private_key_.file_name (),
535 this->private_key_.type ()) <= 0)
537 this->private_key_ = ACE_SSL_Data_File ();
538 return -1;
540 else
541 return this->verify_private_key ();
545 ACE_SSL_Context::verify_private_key (void)
547 this->check_context ();
549 return (::SSL_CTX_check_private_key (this->context_) <= 0 ? -1 : 0);
553 ACE_SSL_Context::certificate (const char *file_name,
554 int type)
556 if (this->certificate_.type () != -1)
557 return 0;
559 this->certificate_ = ACE_SSL_Data_File (file_name, type);
561 this->check_context ();
563 if (::SSL_CTX_use_certificate_file (this->context_,
564 this->certificate_.file_name (),
565 this->certificate_.type ()) <= 0)
567 this->certificate_ = ACE_SSL_Data_File ();
568 return -1;
570 else
571 return 0;
575 ACE_SSL_Context::certificate (X509* cert)
577 // Is it really a good idea to return 0 if we're not setting the
578 // certificate?
579 if (this->certificate_.type () != -1)
580 return 0;
582 this->check_context();
584 if (::SSL_CTX_use_certificate (this->context_, cert) <= 0)
586 return -1;
588 else
590 // No file is associated with the certificate, set this to a fictional
591 // value so we don't reset it later.
592 this->certificate_ = ACE_SSL_Data_File ("MEMORY CERTIFICATE");
594 return 0;
598 void
599 ACE_SSL_Context::set_verify_peer (int strict, int once, int depth)
601 this->check_context ();
603 // Setup the peer verification mode.
604 int verify_mode = SSL_VERIFY_PEER;
605 if (once)
606 verify_mode |= SSL_VERIFY_CLIENT_ONCE;
607 if (strict)
608 verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
610 // set the default verify mode
611 this->default_verify_mode (verify_mode);
613 // Set the max certificate depth but later let the verify_callback
614 // catch the depth error by adding one to the required depth.
615 if (depth > 0)
616 ::SSL_CTX_set_verify_depth (this->context_, depth + 1);
620 ACE_SSL_Context::random_seed (const char * seed)
622 int len = ACE_Utils::truncate_cast<int> (ACE_OS::strlen (seed));
623 ::RAND_seed (seed, len);
625 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
626 // RAND_status() returns 1 if the PRNG has enough entropy.
627 return (::RAND_status () == 1 ? 0 : -1);
628 #else
629 return 0; // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status().
630 #endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
634 ACE_SSL_Context::egd_file (const char * socket_file)
636 #if OPENSSL_VERSION_NUMBER < 0x00905100L || defined (OPENSSL_NO_EGD)
637 // OpenSSL < 0.9.5 doesn't have EGD support. OpenSSL 1.1 and newer
638 // disable egd by default
639 ACE_UNUSED_ARG (socket_file);
640 ACE_NOTSUP_RETURN (-1);
641 #else
642 // RAND_egd() returns the amount of entropy used to seed the random
643 // number generator. The actual value should be greater than 16,
644 // i.e. 128 bits.
645 if (::RAND_egd (socket_file) > 0)
646 return 0;
647 else
648 return -1;
649 #endif /* OPENSSL_VERSION_NUMBER < 0x00905100L */
653 ACE_SSL_Context::seed_file (const char * seed_file, long bytes)
655 // RAND_load_file() returns the number of bytes used to seed the
656 // random number generator. If the file reads ok, check RAND_status to
657 // see if it got enough entropy.
658 if (::RAND_load_file (seed_file, bytes) > 0)
659 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
660 // RAND_status() returns 1 if the PRNG has enough entropy.
661 return (::RAND_status () == 1 ? 0 : -1);
662 #else
663 return 0; // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status().
664 #endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
665 else
666 return -1;
669 void
670 ACE_SSL_Context::report_error (unsigned long error_code)
672 if (error_code != 0)
674 char error_string[256];
676 // OpenSSL < 0.9.6a doesn't have ERR_error_string_n() function.
677 #if OPENSSL_VERSION_NUMBER >= 0x0090601fL
678 (void) ::ERR_error_string_n (error_code, error_string, sizeof error_string);
679 #else /* OPENSSL_VERSION_NUMBER >= 0x0090601fL */
680 (void) ::ERR_error_string (error_code, error_string);
681 #endif /* OPENSSL_VERSION_NUMBER >= 0x0090601fL */
683 ACELIB_ERROR ((LM_ERROR,
684 ACE_TEXT ("ACE_SSL (%P|%t) error code: %u - %C\n"),
685 error_code,
686 error_string));
690 void
691 ACE_SSL_Context::report_error (void)
693 unsigned long err = ::ERR_get_error ();
694 ACE_SSL_Context::report_error (err);
695 ACE_OS::last_error (err);
699 ACE_SSL_Context::dh_params (const char *file_name,
700 int type)
702 if (this->dh_params_.type () != -1)
703 return 0;
705 // For now we only support PEM encodings
706 if (type != SSL_FILETYPE_PEM)
707 return -1;
709 this->dh_params_ = ACE_SSL_Data_File (file_name, type);
711 this->check_context ();
714 // Swiped from Rescorla's examples and the OpenSSL s_server.c app
715 DH * ret=0;
716 BIO * bio = 0;
718 if ((bio = ::BIO_new_file (this->dh_params_.file_name (), "r")) == 0)
720 this->dh_params_ = ACE_SSL_Data_File ();
721 return -1;
724 ret = PEM_read_bio_DHparams (bio, 0, 0, 0);
725 BIO_free (bio);
727 if (ret == 0)
729 this->dh_params_ = ACE_SSL_Data_File ();
730 return -1;
733 if (::SSL_CTX_set_tmp_dh (this->context_, ret) < 0)
735 this->dh_params_ = ACE_SSL_Data_File ();
736 return -1;
738 DH_free (ret);
741 return 0;
744 // ****************************************************************
745 ACE_SINGLETON_TEMPLATE_INSTANTIATE(ACE_Unmanaged_Singleton, ACE_SSL_Context, ACE_SYNCH_MUTEX)
747 ACE_END_VERSIONED_NAMESPACE_DECL