1 #include "SSL_Context.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"
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>
35 /// Reference count of the number of times the ACE_SSL_Context was
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)
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 */
64 ACE_SSL_LOCKING_CALLBACK_NAME (int mode
,
66 const char * /* file */,
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);
76 // if (CRYPTO_LOCK_SSL_CERT == type)
77 // fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
78 // CRYPTO_thread_id(),
81 if (mode
& CRYPTO_LOCK
)
82 (void) ssl_locks
[type
].acquire ();
84 (void) ssl_locks
[type
].release ();
87 // -------------------------------
89 // Return the current thread ID. OpenSSL uses this on platforms
92 ACE_SSL_THREAD_ID_NAME ()
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 ()
111 default_verify_mode_ (SSL_VERIFY_NONE
),
112 default_verify_callback_ (0),
115 ACE_TRACE ("ACE_SSL_Context::ACE_SSL_Context");
117 ACE_SSL_Context::ssl_library_init ();
120 ACE_SSL_Context::~ACE_SSL_Context ()
122 ACE_TRACE ("ACE_SSL_Context::~ACE_SSL_Context");
126 ::SSL_CTX_free (this->context_
);
130 ACE_SSL_Context::ssl_library_fini ();
134 ACE_SSL_Context::instance ()
136 ACE_TRACE ("ACE_SSL_Context::instance");
138 return ACE_Unmanaged_Singleton
<ACE_SSL_Context
, ACE_SYNCH_MUTEX
>::instance ();
142 ACE_SSL_Context::close ()
144 ACE_TRACE ("ACE_SSL_Context::close");
146 ACE_Unmanaged_Singleton
<ACE_SSL_Context
, ACE_SYNCH_MUTEX
>::close ();
150 ACE_SSL_Context::ssl_library_init ()
152 ACE_TRACE ("ACE_SSL_Context::ssl_library_init");
154 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex
,
156 *ACE_Static_Object_Lock::instance ()));
158 if (ssl_library_init_count
== 0)
160 // Initialize the locking callbacks before initializing anything
162 #if defined(ACE_HAS_THREADS) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
163 int const num_locks
= ::CRYPTO_num_locks ();
165 this->locks_
= new lock_type
[num_locks
];
166 ssl_locks
= this->locks_
;
168 # if !defined (WIN32)
169 // This call isn't necessary on some platforms. See the CRYPTO
170 // library's threads(3) man page for details.
171 ::CRYPTO_set_id_callback (ACE_SSL_THREAD_ID_NAME
);
173 ::CRYPTO_set_locking_callback (ACE_SSL_LOCKING_CALLBACK_NAME
);
174 #endif /* ACE_HAS_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L */
176 ::SSLeay_add_ssl_algorithms ();
177 ::SSL_load_error_strings ();
179 // Seed the random number generator. Note that the random
180 // number generator can be seeded more than once to "stir" its
184 // Seed the random number generator by sampling the screen.
185 # if OPENSSL_VERSION_NUMBER < 0x10100000L
189 # endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
192 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
193 // OpenSSL < 0.9.5 doesn't have EGD support.
195 const char *egd_socket_file
=
196 ACE_OS::getenv (ACE_SSL_EGD_FILE_ENV
);
198 if (egd_socket_file
!= 0)
199 (void) this->egd_file (egd_socket_file
);
200 #endif /* OPENSSL_VERSION_NUMBER */
202 const char *rand_file
= ACE_OS::getenv (ACE_SSL_RAND_FILE_ENV
);
206 (void) this->seed_file (rand_file
);
209 // Initialize the mutexes that will be used by the SSL and
213 ++ssl_library_init_count
;
217 ACE_SSL_Context::ssl_library_fini ()
219 ACE_TRACE ("ACE_SSL_Context::ssl_library_fini");
221 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex
,
223 *ACE_Static_Object_Lock::instance ()));
225 --ssl_library_init_count
;
226 if (ssl_library_init_count
== 0)
228 #if OPENSSL_VERSION_NUMBER < 0x10100000L
229 ::ERR_free_strings ();
232 // Clean up the locking callbacks after everything else has been
234 #ifdef ACE_HAS_THREADS
235 ::CRYPTO_set_locking_callback (0);
238 delete [] this->locks_
;
240 #endif /* ACE_HAS_THREADS && */
241 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
246 ACE_SSL_Context::set_mode (int mode
)
248 ACE_TRACE ("ACE_SSL_Context::set_mode");
250 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
,
252 *ACE_Static_Object_Lock::instance (),
255 if (this->context_
!= 0)
258 #if OPENSSL_VERSION_NUMBER >= 0x10000002
259 const SSL_METHOD
*method
= 0;
261 SSL_METHOD
*method
= 0;
266 case ACE_SSL_Context::SSLv23_client
:
267 method
= ::SSLv23_client_method ();
269 case ACE_SSL_Context::SSLv23_server
:
270 method
= ::SSLv23_server_method ();
272 case ACE_SSL_Context::SSLv23
:
273 method
= ::SSLv23_method ();
276 method
= ::SSLv23_method ();
280 this->context_
= ::SSL_CTX_new (method
);
281 if (this->context_
== 0)
286 // Load the trusted certificate authority (default) certificate
287 // locations. But do not return -1 on error, doing so confuses CTX
288 // allocation (severe error) with the less important loading of CA
289 // certificate location error. If it is important for your
290 // application then call ACE_SSL_Context::have_trusted_ca(),
291 // immediately following this call to set_mode().
292 (void) this->load_trusted_ca ();
298 ACE_SSL_Context::filter_versions (const char* versionlist
)
300 ACE_TRACE ("ACE_SSL_Context::filter_versions");
302 this->check_context ();
304 ACE_CString vlist
= versionlist
;
305 ACE_CString seplist
= " ,;";
306 ACE_CString::size_type pos
= 0;
309 for (; pos
< vlist
.length (); pos
++)
311 vlist
[pos
] = ACE_OS::ace_tolower (vlist
[pos
]);
314 #if defined (SSL_OP_NO_SSLv2)
315 pos
= vlist
.find("sslv2");
316 match
= pos
!= ACE_CString::npos
&&
317 (pos
== vlist
.length () - 5 ||
318 seplist
.find (vlist
[pos
+ 5]) != ACE_CString::npos
);
321 ::SSL_CTX_set_options (this->context_
, SSL_OP_NO_SSLv2
);
323 #endif /* SSL_OP_NO_SSLv2 */
325 #if defined (SSL_OP_NO_SSLv3)
326 pos
= vlist
.find("sslv3");
327 match
= pos
!= ACE_CString::npos
&&
328 (pos
== vlist
.length () - 5 ||
329 seplist
.find (vlist
[pos
+ 5]) != ACE_CString::npos
);
332 ::SSL_CTX_set_options (this->context_
, SSL_OP_NO_SSLv3
);
334 #endif /* SSL_OP_NO_SSLv3 */
336 #if defined (SSL_OP_NO_TLSv1)
337 pos
= vlist
.find("tlsv1");
338 match
= pos
!= ACE_CString::npos
&&
339 (pos
== vlist
.length () - 5 ||
340 seplist
.find (vlist
[pos
+ 5]) != ACE_CString::npos
);
343 ::SSL_CTX_set_options (this->context_
, SSL_OP_NO_TLSv1
);
345 #endif /* SSL_OP_NO_TLSv1 */
347 #if defined (SSL_OP_NO_TLSv1_1)
348 pos
= vlist
.find("tlsv1.1");
349 match
= pos
!= ACE_CString::npos
&&
350 (pos
== vlist
.length () - 7 ||
351 seplist
.find (vlist
[pos
+ 7]) != ACE_CString::npos
);
354 ::SSL_CTX_set_options (this->context_
, SSL_OP_NO_TLSv1_1
);
356 #endif /* SSL_OP_NO_TLSv1_1 */
358 #if defined (SSL_OP_NO_TLSv1_2)
359 pos
= vlist
.find("tlsv1.2");
360 match
= pos
!= ACE_CString::npos
&&
361 (pos
== vlist
.length () - 7 ||
362 seplist
.find (vlist
[pos
+ 7]) != ACE_CString::npos
);
365 ::SSL_CTX_set_options (this->context_
, SSL_OP_NO_TLSv1_2
);
367 #endif /* SSL_OP_NO_TLSv1_2 */
369 #if defined (SSL_OP_NO_TLSv1_3)
370 pos
= vlist
.find("tlsv1.3");
371 match
= pos
!= ACE_CString::npos
&&
372 (pos
== vlist
.length() - 7 ||
373 seplist
.find(vlist
[pos
+ 7]) != ACE_CString::npos
);
376 ::SSL_CTX_set_options(this->context_
, SSL_OP_NO_TLSv1_3
);
378 #endif /* SSL_OP_NO_TLSv1_3 */
383 ACE_SSL_Context::check_host (const ACE_INET_Addr
&host
, SSL
*peerssl
)
385 ACE_TRACE ("ACE_SSL_Context::check_host");
387 #if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10002001L)
389 this->check_context ();
391 char name
[MAXHOSTNAMELEN
+1];
393 if (peerssl
== 0 || host
.get_host_name (name
, MAXHOSTNAMELEN
) == -1)
398 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
399 X509
* cert
= ::SSL_get1_peer_certificate(peerssl
);
401 X509
* cert
= ::SSL_get_peer_certificate(peerssl
);
410 char **peerarg
= ACE::debug () ? &peer
: 0;
411 int const flags
= X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
;
412 size_t const len
= ACE_OS::strlen (name
);
414 int const result
= ::X509_check_host (cert
, name
, len
, flags
, peerarg
);
418 ACELIB_DEBUG ((LM_DEBUG
,
419 ACE_TEXT ("ACE (%P|%t) SSL_Context::check_host ")
420 ACE_TEXT ("name <%C> returns %d, peer <%C>\n"),
421 name
, result
, peer
));
425 ::OPENSSL_free (peer
);
432 ACE_UNUSED_ARG (host
);
433 ACE_UNUSED_ARG (peerssl
);
436 #endif /* OPENSSL_VERSION_NUMBER */
440 ACE_SSL_Context::load_trusted_ca (const char* ca_file
,
442 bool use_env_defaults
)
444 ACE_TRACE ("ACE_SSL_Context::load_trusted_ca");
446 this->check_context ();
448 if (ca_file
== 0 && use_env_defaults
)
450 // Use the default environment settings.
451 ca_file
= ACE_OS::getenv (ACE_SSL_CERT_FILE_ENV
);
452 #ifdef ACE_DEFAULT_SSL_CERT_FILE
454 ca_file
= ACE_DEFAULT_SSL_CERT_FILE
;
458 if (ca_dir
== 0 && use_env_defaults
)
460 // Use the default environment settings.
461 ca_dir
= ACE_OS::getenv (ACE_SSL_CERT_DIR_ENV
);
462 #ifdef ACE_DEFAULT_SSL_CERT_DIR
464 ca_dir
= ACE_DEFAULT_SSL_CERT_DIR
;
468 // NOTE: SSL_CTX_load_verify_locations() returns 0 on error.
469 if (::SSL_CTX_load_verify_locations (this->context_
,
474 ACE_SSL_Context::report_error ();
480 // For TLS/SSL servers scan all certificates in ca_file and ca_dir and
481 // list them as acceptable CAs when requesting a client certificate.
482 if (mode_
== SSLv23
|| mode_
== SSLv23_server
)
484 // Note: The STACK_OF(X509_NAME) pointer is a copy of the pointer in
485 // the CTX; any changes to it by way of these function calls will
486 // change the CTX directly.
487 STACK_OF (X509_NAME
) * cert_names
= 0;
488 cert_names
= ::SSL_CTX_get_client_CA_list (this->context_
);
490 // Add CAs from both the file and dir, if specified. There should
491 // already be a STACK_OF(X509_NAME) in the CTX, but if not, we create
498 if ((cert_names
= ::SSL_load_client_CA_file (ca_file
)) != 0)
499 ::SSL_CTX_set_client_CA_list (this->context_
, cert_names
);
505 // Add new certificate names to the list.
506 error
= (0 == ::SSL_add_file_cert_subjects_to_stack (cert_names
,
513 ACE_SSL_Context::report_error ();
518 // SSL_add_dir_cert_subjects_to_stack is defined at 0.9.8a (but not
519 // on Mac Classic); it may be available earlier. Change
520 // this comparison if so. It's still (1.0.1g) broken on windows too.
521 #if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090801fL)
522 # if !defined (OPENSSL_SYS_MACINTOSH_CLASSIC)
523 # if !defined (OPENSSL_SYS_WIN32)
529 if ((cert_names
= sk_X509_NAME_new_null ()) == 0)
532 ACE_SSL_Context::report_error ();
535 ::SSL_CTX_set_client_CA_list (this->context_
, cert_names
);
537 if (0 == ::SSL_add_dir_cert_subjects_to_stack (cert_names
, ca_dir
))
540 ACE_SSL_Context::report_error ();
544 # endif /* !OPENSSL_SYS_WIN32 */
545 # endif /* !OPENSSL_SYS_MACINTOSH_CLASSIC */
546 #endif /* OPENSSL_VERSION_NUMBER >= 0.9.8a release */
554 ACE_SSL_Context::private_key (const char *file_name
,
557 ACE_TRACE ("ACE_SSL_Context::private_key");
559 if (this->private_key_
.type () != -1)
562 this->check_context ();
564 this->private_key_
= ACE_SSL_Data_File (file_name
, type
);
566 if (::SSL_CTX_use_PrivateKey_file (this->context_
,
567 this->private_key_
.file_name (),
568 this->private_key_
.type ()) <= 0)
570 this->private_key_
= ACE_SSL_Data_File ();
574 return this->verify_private_key ();
578 ACE_SSL_Context::verify_private_key ()
580 ACE_TRACE ("ACE_SSL_Context::verify_private_key");
582 this->check_context ();
584 return (::SSL_CTX_check_private_key (this->context_
) <= 0 ? -1 : 0);
588 ACE_SSL_Context::certificate (const char *file_name
,
591 ACE_TRACE ("ACE_SSL_Context::certificate:file_name:type");
593 if (this->certificate_
.type () != -1)
596 this->certificate_
= ACE_SSL_Data_File (file_name
, type
);
598 this->check_context ();
600 if (::SSL_CTX_use_certificate_file (this->context_
,
601 this->certificate_
.file_name (),
602 this->certificate_
.type ()) <= 0)
604 this->certificate_
= ACE_SSL_Data_File ();
612 ACE_SSL_Context::certificate (X509
* cert
)
614 ACE_TRACE ("ACE_SSL_Context::certificate:cert");
616 // Is it really a good idea to return 0 if we're not setting the
618 if (this->certificate_
.type () != -1)
621 this->check_context();
623 if (::SSL_CTX_use_certificate (this->context_
, cert
) <= 0)
629 // No file is associated with the certificate, set this to a fictional
630 // value so we don't reset it later.
631 this->certificate_
= ACE_SSL_Data_File ("MEMORY CERTIFICATE");
638 ACE_SSL_Context::certificate_chain (const char *file_name
, int type
)
640 ACE_TRACE ("ACE_SSL_Context::certificate_chain:file_name");
642 this->certificate_
= ACE_SSL_Data_File (file_name
, type
);
644 this->check_context ();
646 if (::SSL_CTX_use_certificate_chain_file (this->context_
,
647 this->certificate_
.file_name ()) <= 0)
656 ACE_SSL_Context::set_verify_peer (int strict
, int once
, int depth
)
658 ACE_TRACE ("ACE_SSL_Context::set_verify_peer");
660 this->check_context ();
662 // Setup the peer verification mode.
663 int verify_mode
= SSL_VERIFY_PEER
;
665 verify_mode
|= SSL_VERIFY_CLIENT_ONCE
;
667 verify_mode
|= SSL_VERIFY_FAIL_IF_NO_PEER_CERT
;
669 // set the default verify mode
670 this->default_verify_mode (verify_mode
);
672 // Set the max certificate depth but later let the verify_callback
673 // catch the depth error by adding one to the required depth.
675 ::SSL_CTX_set_verify_depth (this->context_
, depth
+ 1);
679 ACE_SSL_Context::random_seed (const char * seed
)
681 ACE_TRACE ("ACE_SSL_Context::random_seed");
683 int len
= ACE_Utils::truncate_cast
<int> (ACE_OS::strlen (seed
));
684 ::RAND_seed (seed
, len
);
686 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
687 // RAND_status() returns 1 if the PRNG has enough entropy.
688 return (::RAND_status () == 1 ? 0 : -1);
690 return 0; // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status().
691 #endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
695 ACE_SSL_Context::egd_file (const char * socket_file
)
697 ACE_TRACE ("ACE_SSL_Context::egd_file");
699 #if OPENSSL_VERSION_NUMBER < 0x00905100L || defined (OPENSSL_NO_EGD)
700 // OpenSSL < 0.9.5 doesn't have EGD support. OpenSSL 1.1 and newer
701 // disable egd by default
702 ACE_UNUSED_ARG (socket_file
);
703 ACE_NOTSUP_RETURN (-1);
705 // RAND_egd() returns the amount of entropy used to seed the random
706 // number generator. The actual value should be greater than 16,
708 if (::RAND_egd (socket_file
) > 0)
712 #endif /* OPENSSL_VERSION_NUMBER < 0x00905100L */
716 ACE_SSL_Context::seed_file (const char * seed_file
, long bytes
)
718 ACE_TRACE ("ACE_SSL_Context::seed_file");
720 // RAND_load_file() returns the number of bytes used to seed the
721 // random number generator. If the file reads ok, check RAND_status to
722 // see if it got enough entropy.
723 if (::RAND_load_file (seed_file
, bytes
) > 0)
724 #if OPENSSL_VERSION_NUMBER >= 0x00905100L
725 // RAND_status() returns 1 if the PRNG has enough entropy.
726 return (::RAND_status () == 1 ? 0 : -1);
728 return 0; // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status().
729 #endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
735 ACE_SSL_Context::report_error (unsigned long error_code
)
737 ACE_TRACE ("ACE_SSL_Context::report_error:error_code");
741 char error_string
[256];
743 // OpenSSL < 0.9.6a doesn't have ERR_error_string_n() function.
744 #if OPENSSL_VERSION_NUMBER >= 0x0090601fL
745 (void) ::ERR_error_string_n (error_code
, error_string
, sizeof error_string
);
746 #else /* OPENSSL_VERSION_NUMBER >= 0x0090601fL */
747 (void) ::ERR_error_string (error_code
, error_string
);
748 #endif /* OPENSSL_VERSION_NUMBER >= 0x0090601fL */
750 ACELIB_ERROR ((LM_ERROR
,
751 ACE_TEXT ("ACE_SSL (%P|%t) error code: %u - %C\n"),
758 ACE_SSL_Context::report_error ()
760 ACE_TRACE ("ACE_SSL_Context::report_error");
762 unsigned long const err
= ::ERR_get_error ();
763 ACE_SSL_Context::report_error (err
);
764 ACE_OS::last_error (err
);
768 ACE_SSL_Context::dh_params (const char *file_name
,
771 ACE_TRACE ("ACE_SSL_Context::dh_params");
773 if (this->dh_params_
.type () != -1)
776 // For now we only support PEM encodings
777 if (type
!= SSL_FILETYPE_PEM
)
780 this->dh_params_
= ACE_SSL_Data_File (file_name
, type
);
782 this->check_context ();
785 // Swiped from Rescorla's examples and the OpenSSL s_server.c app
789 if ((bio
= ::BIO_new_file (this->dh_params_
.file_name (), "r")) == 0)
791 this->dh_params_
= ACE_SSL_Data_File ();
795 ret
= PEM_read_bio_DHparams (bio
, 0, 0, 0);
800 this->dh_params_
= ACE_SSL_Data_File ();
804 if (::SSL_CTX_set_tmp_dh (this->context_
, ret
) < 0)
806 this->dh_params_
= ACE_SSL_Data_File ();
815 // ****************************************************************
816 ACE_SINGLETON_TEMPLATE_INSTANTIATE(ACE_Unmanaged_Singleton
, ACE_SSL_Context
, ACE_SYNCH_MUTEX
)
818 ACE_END_VERSIONED_NAMESPACE_DECL