2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <openssl/ssl.h>
30 #include <glib-object.h>
33 #include <thrift/c_glib/thrift.h>
34 #include <thrift/c_glib/transport/thrift_transport.h>
35 #include <thrift/c_glib/transport/thrift_socket.h>
36 #include <thrift/c_glib/transport/thrift_ssl_socket.h>
40 #define MUTEX_TYPE HANDLE
41 #define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
42 #define MUTEX_CLEANUP(x) CloseHandle(x)
43 #define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
44 #define MUTEX_UNLOCK(x) ReleaseMutex(x)
46 #define MUTEX_TYPE pthread_mutex_t
47 #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
48 #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
49 #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
50 #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
53 #define OPENSSL_VERSION_NO_THREAD_ID 0x10000000L
56 /* object properties */
57 enum _ThriftSSLSocketProperties
59 PROP_THRIFT_SSL_SOCKET_CONTEXT
= 3,
60 PROP_THRIFT_SSL_SELF_SIGNED
63 /* To hold a global state management of openssl for all instances */
64 static gboolean thrift_ssl_socket_openssl_initialized
=FALSE
;
65 /* This array will store all of the mutexes available to OpenSSL. */
66 static MUTEX_TYPE
*thrift_ssl_socket_global_mutex_buf
=NULL
;
70 * OpenSSL uniq id function.
74 static unsigned long thrift_ssl_socket_static_id_function(void)
77 return GetCurrentThreadId();
79 return ((unsigned long) pthread_self());
83 static void thrift_ssl_socket_static_locking_callback(int mode
, int n
, const char* unk
, int id
) {
84 if (mode
& CRYPTO_LOCK
)
85 MUTEX_LOCK(thrift_ssl_socket_global_mutex_buf
[n
]);
87 MUTEX_UNLOCK(thrift_ssl_socket_global_mutex_buf
[n
]);
90 static int thrift_ssl_socket_static_thread_setup(void)
94 thrift_ssl_socket_global_mutex_buf
= malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE
));
95 if (!thrift_ssl_socket_global_mutex_buf
)
97 for (i
= 0; i
< CRYPTO_num_locks( ); i
++)
98 MUTEX_SETUP(thrift_ssl_socket_global_mutex_buf
[i
]);
99 CRYPTO_set_id_callback(thrift_ssl_socket_static_id_function
);
100 CRYPTO_set_locking_callback(thrift_ssl_socket_static_locking_callback
);
104 static int thrift_ssl_socket_static_thread_cleanup(void)
107 if (!thrift_ssl_socket_global_mutex_buf
)
109 CRYPTO_set_id_callback(NULL
);
110 CRYPTO_set_locking_callback(NULL
);
111 for (i
= 0; i
< CRYPTO_num_locks( ); i
++)
112 MUTEX_CLEANUP(thrift_ssl_socket_global_mutex_buf
[i
]);
113 free(thrift_ssl_socket_global_mutex_buf
);
114 thrift_ssl_socket_global_mutex_buf
= NULL
;
119 static void* thrift_ssl_socket_dyn_lock_create_callback(const char* unk, int id) {
120 g_print("We should create a lock\n");
124 static void thrift_ssl_socket_dyn_lock_callback(int mode, void* lock, const char* unk, int id) {
126 if (mode & CRYPTO_LOCK) {
127 g_printf("We should lock thread %d\n");
129 g_printf("We should unlock thread %d\n");
134 static void thrift_ssl_socket_dyn_lock_destroy_callback(void* lock, const char* unk, int id) {
135 g_printf("We must destroy the lock\n");
140 G_DEFINE_TYPE(ThriftSSLSocket
, thrift_ssl_socket
, THRIFT_TYPE_SOCKET
)
145 * When there's a thread context attached, we pass the SSL socket context so it
146 * can check if the error is outside SSL, on I/O for example
149 * @param thrift_error_no
154 void thrift_ssl_socket_get_ssl_error(ThriftSSLSocket
*socket
, const guchar
*error_msg
, guint thrift_error_no
, int ssl_error
, GError
**error
)
156 unsigned long error_code
;
158 int buffer_size
=1024;
159 gboolean first_error
= TRUE
;
160 int ssl_error_type
= SSL_get_error(socket
->ssl
, ssl_error
);
161 if(ssl_error_type
>0){
162 switch(ssl_error_type
){
164 buffer_size
-=snprintf(buffer
, buffer_size
, "SSL %s: ", error_msg
);
165 while ((error_code
= ERR_get_error()) != 0 && buffer_size
>1) {
166 const char* reason
= ERR_reason_error_string(error_code
);
169 buffer_size
-=snprintf(buffer
+(1024-buffer_size
), buffer_size
, "\n\t");
172 buffer_size
-=snprintf(buffer
+(1024-buffer_size
), buffer_size
, "%lX(%s) -> %s", error_code
, reason
, SSL_state_string(socket
->ssl
));
176 case SSL_ERROR_SYSCALL
:
177 buffer_size
-=snprintf(buffer
, buffer_size
, "%s: ", error_msg
);
178 buffer_size
-=snprintf(buffer
+(1024-buffer_size
), buffer_size
, "%lX -> %s", errno
, strerror(errno
));
180 case SSL_ERROR_WANT_READ
:
181 buffer_size
-=snprintf(buffer
, buffer_size
, "%s: ", error_msg
);
182 buffer_size
-=snprintf(buffer
+(1024-buffer_size
), buffer_size
, "%lX -> %s", ssl_error_type
, "Error while reading from underlaying layer");
184 case SSL_ERROR_WANT_WRITE
:
185 buffer_size
-=snprintf(buffer
, buffer_size
, "%s: ", error_msg
);
186 buffer_size
-=snprintf(buffer
+(1024-buffer_size
), buffer_size
, "%lX -> %s", ssl_error_type
, "Error while writting to underlaying layer");
190 g_set_error (error
, THRIFT_TRANSPORT_ERROR
,
191 thrift_error_no
, "%s", buffer
);
196 * For global SSL errors
198 * @param thrift_error_no
202 void thrift_ssl_socket_get_error(const guchar
*error_msg
, guint thrift_error_no
, GError
**error
)
204 unsigned long error_code
;
205 while ((error_code
= ERR_get_error()) != 0) {
206 const char* reason
= ERR_reason_error_string(error_code
);
207 if (reason
== NULL
) {
208 g_set_error (error
, THRIFT_TRANSPORT_ERROR
,
210 "SSL error %lX: %s", error_code
, error_msg
);
212 g_set_error (error
, THRIFT_TRANSPORT_ERROR
,
214 "SSL error %lX %s: %s", error_code
,reason
, error_msg
);
221 /* implements thrift_transport_is_open */
223 thrift_ssl_socket_is_open (ThriftTransport
*transport
)
225 return thrift_socket_is_open(transport
);
228 /* overrides thrift_transport_peek */
230 thrift_ssl_socket_peek (ThriftTransport
*transport
, GError
**error
)
232 gboolean retval
= FALSE
;
233 ThriftSSLSocket
*ssl_socket
= THRIFT_SSL_SOCKET (transport
);
234 if (thrift_ssl_socket_is_open (transport
))
238 rc
= SSL_peek(ssl_socket
->ssl
, &byte
, 1);
240 thrift_ssl_socket_get_ssl_error(ssl_socket
, "Check socket data",
241 THRIFT_SSL_SOCKET_ERROR_SSL
, rc
, error
);
251 /* implements thrift_transport_open */
253 thrift_ssl_socket_open (ThriftTransport
*transport
, GError
**error
)
257 if (!thrift_socket_open(transport
, error
)) {
261 if (!THRIFT_SSL_SOCKET_GET_CLASS(transport
)->handle_handshake(transport
, error
)) {
262 thrift_ssl_socket_close(transport
, NULL
);
269 /* implements thrift_transport_close */
271 thrift_ssl_socket_close (ThriftTransport
*transport
, GError
**error
)
273 gboolean retval
= FALSE
;
274 ThriftSSLSocket
*ssl_socket
= THRIFT_SSL_SOCKET(transport
);
275 if(ssl_socket
!=NULL
&& ssl_socket
->ssl
) {
276 int rc
= SSL_shutdown(ssl_socket
->ssl
);
278 int errno_copy = THRIFT_SSL_SOCKET_ERROR_SSL;
280 SSL_free(ssl_socket
->ssl
);
281 ssl_socket
->ssl
= NULL
;
284 return thrift_socket_close(transport
, error
);
287 /* implements thrift_transport_read */
289 thrift_ssl_socket_read (ThriftTransport
*transport
, gpointer buf
,
290 guint32 len
, GError
**error
)
292 guint maxRecvRetries_
= 10;
293 ThriftSSLSocket
*ssl_socket
= THRIFT_SSL_SOCKET (transport
);
296 ThriftSocket
*socket
= THRIFT_SOCKET (transport
);
297 g_return_val_if_fail (socket
->sd
!= THRIFT_INVALID_SOCKET
&& ssl_socket
->ssl
!=NULL
, FALSE
);
299 for (retries
=0; retries
< maxRecvRetries_
; retries
++) {
300 bytes
= SSL_read(ssl_socket
->ssl
, buf
, len
);
303 int errno_copy
= THRIFT_GET_SOCKET_ERROR
;
304 if (SSL_get_error(ssl_socket
->ssl
, bytes
) == SSL_ERROR_SYSCALL
) {
305 if (ERR_get_error() == 0 && errno_copy
== THRIFT_EINTR
) {
309 thrift_ssl_socket_get_ssl_error(ssl_socket
, "Receive error",
310 THRIFT_SSL_SOCKET_ERROR_SSL
, bytes
, error
);
318 /* implements thrift_transport_read_end
319 * called when write is complete. nothing to do on our end. */
321 thrift_ssl_socket_read_end (ThriftTransport
*transport
, GError
**error
)
324 THRIFT_UNUSED_VAR (transport
);
325 THRIFT_UNUSED_VAR (error
);
329 /* implements thrift_transport_write */
331 thrift_ssl_socket_write (ThriftTransport
*transport
, const gpointer buf
,
332 const guint32 len
, GError
**error
)
334 ThriftSSLSocket
*ssl_socket
= THRIFT_SSL_SOCKET (transport
);
337 ThriftSocket
*socket
= THRIFT_SOCKET (transport
);
338 g_return_val_if_fail (socket
->sd
!= THRIFT_INVALID_SOCKET
&& ssl_socket
->ssl
!=NULL
, FALSE
);
342 ret
= SSL_write (ssl_socket
->ssl
, (guint8
*)buf
+ sent
, len
- sent
);
345 thrift_ssl_socket_get_ssl_error(ssl_socket
, "Send error",
346 THRIFT_SSL_SOCKET_ERROR_SSL
, ret
, error
);
355 /* implements thrift_transport_write_end
356 * called when write is complete. nothing to do on our end. */
358 thrift_ssl_socket_write_end (ThriftTransport
*transport
, GError
**error
)
361 THRIFT_UNUSED_VAR (transport
);
362 THRIFT_UNUSED_VAR (error
);
366 /* implements thrift_transport_flush
367 * flush pending data. since we are not buffered, this is a no-op */
369 thrift_ssl_socket_flush (ThriftTransport
*transport
, GError
**error
)
371 ThriftSSLSocket
*ssl_socket
= THRIFT_SSL_SOCKET (transport
);
373 ThriftSocket
*socket
= THRIFT_SOCKET (transport
);
374 g_return_val_if_fail (socket
->sd
!= THRIFT_INVALID_SOCKET
&& ssl_socket
->ssl
!=NULL
, FALSE
);
376 BIO
* bio
= SSL_get_wbio(ssl_socket
->ssl
);
378 g_set_error (error
, THRIFT_TRANSPORT_ERROR
,
379 THRIFT_TRANSPORT_ERROR_SEND
,
380 "failed to flush, wbio returned null");
383 if (BIO_flush(bio
) != 1) {
384 g_set_error (error
, THRIFT_TRANSPORT_ERROR
,
385 THRIFT_TRANSPORT_ERROR_SEND
,
386 "failed to flush it returned error");
394 thrift_ssl_socket_handle_handshake(ThriftTransport
* transport
, GError
**error
)
396 ThriftSSLSocket
*ssl_socket
= THRIFT_SSL_SOCKET (transport
);
397 ThriftSocket
*socket
= THRIFT_SOCKET (transport
);
398 g_return_val_if_fail (thrift_transport_is_open (transport
), FALSE
);
400 if(THRIFT_SSL_SOCKET_GET_CLASS(ssl_socket
)->create_ssl_context(transport
, error
)){
402 SSL_set_fd(ssl_socket
->ssl
, socket
->sd
);
404 if(ssl_socket
->server
){
405 rc
= SSL_accept(ssl_socket
->ssl
);
407 rc
= SSL_connect(ssl_socket
->ssl
);
410 thrift_ssl_socket_get_ssl_error(ssl_socket
, "Error while connect/bind", THRIFT_SSL_SOCKET_ERROR_CONNECT_BIND
, rc
, error
);
416 return thrift_ssl_socket_authorize(transport
, error
);
420 thrift_ssl_socket_create_ssl_context(ThriftTransport
* transport
, GError
**error
)
422 ThriftSSLSocket
*socket
= THRIFT_SSL_SOCKET (transport
);
424 if(socket
->ctx
!=NULL
){
425 if(socket
->ssl
!=NULL
) {
429 socket
->ssl
= SSL_new(socket
->ctx
);
430 if (socket
->ssl
== NULL
) {
431 g_set_error (error
, THRIFT_TRANSPORT_ERROR
,
432 THRIFT_SSL_SOCKET_ERROR_TRANSPORT
,
433 "Unable to create default SSL context");
442 gboolean
thrift_ssl_load_cert_from_file(ThriftSSLSocket
*ssl_socket
, const char *file_name
)
444 char error_buffer
[255];
445 if (!thrift_ssl_socket_openssl_initialized
) {
446 g_error("OpenSSL is not initialized yet");
449 int rc
= SSL_CTX_load_verify_locations(ssl_socket
->ctx
, file_name
, NULL
);
450 if (rc
!= 1) { /*verify authentication result*/
451 ERR_error_string_n(ERR_get_error(), error_buffer
, 254);
452 g_warning("Load of certificates failed: %s!", error_buffer
);
459 gboolean
thrift_ssl_load_cert_from_buffer(ThriftSSLSocket
*ssl_socket
, const char chain_certs
[])
461 gboolean retval
= FALSE
;
462 /* Load chain of certs*/
464 BIO
*mem
= BIO_new_mem_buf(chain_certs
,strlen(chain_certs
));
465 X509_STORE
*cert_store
= SSL_CTX_get_cert_store(ssl_socket
->ctx
);
467 if(cert_store
!=NULL
){
469 while ((cacert
= PEM_read_bio_X509(mem
, NULL
, 0, NULL
))!=NULL
) {
471 X509_STORE_add_cert(cert_store
, cacert
);
474 } /* Free immediately */
484 thrift_ssl_socket_authorize(ThriftTransport
* transport
, GError
**error
)
486 ThriftSocket
*socket
= THRIFT_SOCKET (transport
);
487 ThriftSSLSocket
*ssl_socket
= THRIFT_SSL_SOCKET (transport
);
488 ThriftSSLSocketClass
*cls
= THRIFT_SSL_SOCKET_GET_CLASS(ssl_socket
);
489 gboolean authorization_result
= FALSE
;
491 if(cls
!=NULL
&& ssl_socket
->ssl
!=NULL
){
492 int rc
= SSL_get_verify_result(ssl_socket
->ssl
);
493 if (rc
!= X509_V_OK
) { /* verify authentication result */
494 if (rc
== X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
&& ssl_socket
->allow_selfsigned
) {
495 g_debug("The certificate is a self-signed certificate and configuration allows it");
498 THRIFT_TRANSPORT_ERROR
,
499 THRIFT_SSL_SOCKET_ERROR_SSL_CERT_VALIDATION_FAILED
,
500 "The certificate verification failed: %s (%d)", X509_verify_cert_error_string(rc
), rc
);
505 X509
* cert
= SSL_get_peer_certificate(ssl_socket
->ssl
);
507 if (SSL_get_verify_mode(ssl_socket
->ssl
) & SSL_VERIFY_FAIL_IF_NO_PEER_CERT
) {
509 THRIFT_TRANSPORT_ERROR
,
510 THRIFT_SSL_SOCKET_ERROR_SSL_CERT_VALIDATION_FAILED
,
511 "No certificate present. Are you connecting SSL server?");
514 g_debug("No certificate required");
518 /* certificate is present, since we don't support access manager we are done */
519 if (cls
->authorize_peer
== NULL
) {
521 g_debug("Certificate presented but we're not checking it");
524 /* both certificate and access manager are present */
525 struct sockaddr_storage sa
;
526 socklen_t saLength
= sizeof(struct sockaddr_storage
);
527 if (getpeername(socket
->sd
, (struct sockaddr
*)&sa
, &saLength
) != 0) {
528 sa
.ss_family
= AF_UNSPEC
;
530 authorization_result
= cls
->authorize_peer(transport
, cert
, &sa
, error
);
537 return authorization_result
;
541 /* initializes the instance */
543 thrift_ssl_socket_init (ThriftSSLSocket
*socket
)
545 GError
*error
= NULL
;
547 socket
->ctx
= thrift_ssl_socket_context_initialize(SSLTLS
, &error
);
548 if(socket
->ctx
== NULL
) {
549 g_info("The SSL context was not automatically initialized with protocol %d", SSLTLS
);
551 g_info("Reported reason %s", error
->message
);
552 g_error_free (error
);
555 socket
->server
= FALSE
;
556 socket
->allow_selfsigned
= FALSE
;
562 thrift_ssl_socket_finalize (GObject
*object
)
564 ThriftSSLSocket
*socket
= THRIFT_SSL_SOCKET (object
);
567 g_debug("Instance %p destroyed", (void *)socket
);
568 if(socket
->ssl
!= NULL
)
570 thrift_ssl_socket_close(THRIFT_TRANSPORT(object
), &error
);
574 if(socket
->ctx
!=NULL
){
575 g_debug("Freeing the context for the instance");
576 SSL_CTX_free(socket
->ctx
);
581 if (G_OBJECT_CLASS (thrift_ssl_socket_parent_class
)->finalize
)
582 (*G_OBJECT_CLASS (thrift_ssl_socket_parent_class
)->finalize
) (object
);
585 /* property accessor */
587 thrift_ssl_socket_get_property (GObject
*object
, guint property_id
,
588 GValue
*value
, GParamSpec
*pspec
)
590 ThriftSSLSocket
*socket
= THRIFT_SSL_SOCKET (object
);
591 THRIFT_UNUSED_VAR (pspec
);
595 case PROP_THRIFT_SSL_SOCKET_CONTEXT
:
596 g_value_set_pointer (value
, socket
->ctx
);
601 /* property mutator */
603 thrift_ssl_socket_set_property (GObject
*object
, guint property_id
,
604 const GValue
*value
, GParamSpec
*pspec
)
606 ThriftSSLSocket
*socket
= THRIFT_SSL_SOCKET (object
);
608 THRIFT_UNUSED_VAR (pspec
);
611 case PROP_THRIFT_SSL_SOCKET_CONTEXT
:
612 if(socket
->ctx
!=NULL
){
613 g_debug("Freeing the context since we are setting a new one");
614 SSL_CTX_free(socket
->ctx
);
616 socket
->ctx
= g_value_get_pointer(value
); /* We copy the context */
619 case PROP_THRIFT_SSL_SELF_SIGNED
:
620 socket
->allow_selfsigned
= g_value_get_boolean(value
);
623 g_warning("Trying to set property %i that doesn't exists!", property_id
);
624 /* thrift_socket_set_property(object, property_id, value, pspec); */
630 thrift_ssl_socket_initialize_openssl(void)
632 if(thrift_ssl_socket_openssl_initialized
){
635 thrift_ssl_socket_openssl_initialized
=TRUE
;
637 ERR_load_crypto_strings();
638 SSL_load_error_strings();
639 ERR_load_BIO_strings();
642 g_debug("We setup %d threads locks", thrift_ssl_socket_static_thread_setup());
645 CRYPTO_set_dynlock_create_callback(thrift_ssl_socket_dyn_lock_create_callback);
646 CRYPTO_set_dynlock_lock_callback(thrift_ssl_socket_dyn_lock_callback);
647 CRYPTO_set_dynlock_destroy_callback(thrift_ssl_socket_dyn_lock_destroy_callback);
652 void thrift_ssl_socket_finalize_openssl(void)
654 if (!thrift_ssl_socket_openssl_initialized
) {
657 thrift_ssl_socket_openssl_initialized
= FALSE
;
659 g_debug("We cleared %d threads locks", thrift_ssl_socket_static_thread_cleanup());
661 CRYPTO_set_locking_callback(NULL);
662 CRYPTO_set_dynlock_create_callback(NULL);
663 CRYPTO_set_dynlock_lock_callback(NULL);
664 CRYPTO_set_dynlock_destroy_callback(NULL);
668 CRYPTO_cleanup_all_ex_data();
673 /* initializes the class */
675 thrift_ssl_socket_class_init (ThriftSSLSocketClass
*cls
)
677 ThriftTransportClass
*ttc
= THRIFT_TRANSPORT_CLASS (cls
);
678 GObjectClass
*gobject_class
= G_OBJECT_CLASS (cls
);
679 GParamSpec
*param_spec
= NULL
;
681 g_debug("Initialization of ThriftSSLSocketClass");
682 /* setup accessors and mutators */
683 gobject_class
->get_property
= thrift_ssl_socket_get_property
;
684 gobject_class
->set_property
= thrift_ssl_socket_set_property
;
685 param_spec
= g_param_spec_pointer ("ssl_context",
687 "Set the SSL context for handshake with the remote host",
689 g_object_class_install_property (gobject_class
, PROP_THRIFT_SSL_SOCKET_CONTEXT
,
691 param_spec
= g_param_spec_boolean ("ssl_accept_selfsigned",
692 "Accept Self Signed",
693 "Whether or not accept self signed certificate",
696 g_object_class_install_property (gobject_class
, PROP_THRIFT_SSL_SELF_SIGNED
,
699 cls
->handle_handshake
= thrift_ssl_socket_handle_handshake
;
700 cls
->create_ssl_context
= thrift_ssl_socket_create_ssl_context
;
703 gobject_class
->finalize
= thrift_ssl_socket_finalize
;
704 ttc
->is_open
= thrift_ssl_socket_is_open
;
705 ttc
->peek
= thrift_ssl_socket_peek
;
706 ttc
->open
= thrift_ssl_socket_open
;
707 ttc
->close
= thrift_ssl_socket_close
;
708 ttc
->read
= thrift_ssl_socket_read
;
709 ttc
->read_end
= thrift_ssl_socket_read_end
;
710 ttc
->write
= thrift_ssl_socket_write
;
711 ttc
->write_end
= thrift_ssl_socket_write_end
;
712 ttc
->flush
= thrift_ssl_socket_flush
;
720 thrift_ssl_socket_new(ThriftSSLSocketProtocol ssl_protocol
, GError
**error
)
722 ThriftSSLSocket
*thriftSSLSocket
= NULL
;
723 SSL_CTX
*ssl_context
= NULL
;
724 /* Create the context */
725 if((ssl_context
=thrift_ssl_socket_context_initialize(ssl_protocol
, error
))==NULL
){
726 g_warning("We cannot initialize context for protocol %d", ssl_protocol
);
727 return thriftSSLSocket
;
730 /* FIXME if the protocol is different? */
731 thriftSSLSocket
= g_object_new (THRIFT_TYPE_SSL_SOCKET
, "ssl_context", ssl_context
, NULL
);
732 return thriftSSLSocket
;
736 thrift_ssl_socket_new_with_host(ThriftSSLSocketProtocol ssl_protocol
, gchar
*hostname
, guint port
, GError
**error
)
738 ThriftSSLSocket
*thriftSSLSocket
= NULL
;
739 SSL_CTX
*ssl_context
= NULL
;
740 /* Create the context */
741 if((ssl_context
=thrift_ssl_socket_context_initialize(ssl_protocol
, error
))==NULL
){
742 /* FIXME Do error control */
743 return thriftSSLSocket
;
745 /* FIXME if the protocol is different? */
746 thriftSSLSocket
= g_object_new (THRIFT_TYPE_SSL_SOCKET
, "ssl_context", ssl_context
, "hostname", hostname
, "port", port
, NULL
);
747 return thriftSSLSocket
;
750 void thrift_ssl_socket_set_manager(ThriftSSLSocket
*ssl_socket
, AUTHORIZATION_MANAGER_CALLBACK callback
)
752 ThriftSSLSocketClass
*sslSocketClass
= THRIFT_SSL_SOCKET_GET_CLASS (ssl_socket
);
754 sslSocketClass
->authorize_peer
= callback
;
760 thrift_ssl_socket_context_initialize(ThriftSSLSocketProtocol ssl_protocol
, GError
**error
)
762 SSL_CTX
* context
= NULL
;
763 switch(ssl_protocol
){
765 context
= SSL_CTX_new(SSLv23_method());
767 #ifndef OPENSSL_NO_SSL3
769 context
= SSL_CTX_new(SSLv3_method());
773 context
= SSL_CTX_new(TLSv1_method());
776 context
= SSL_CTX_new(TLSv1_1_method());
779 context
= SSL_CTX_new(TLSv1_2_method());
782 g_set_error (error
, THRIFT_TRANSPORT_ERROR
,
783 THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE
,
784 "The SSL protocol is unknown for %d", ssl_protocol
);
789 if (context
== NULL
) {
790 thrift_ssl_socket_get_error("No cipher overlay", THRIFT_SSL_SOCKET_ERROR_CIPHER_NOT_AVAILABLE
, error
);
793 SSL_CTX_set_mode(context
, SSL_MODE_AUTO_RETRY
);
795 /* Disable horribly insecure SSLv2 and SSLv3 protocols but allow a handshake
796 with older clients so they get a graceful denial. */
797 if (ssl_protocol
== SSLTLS
) {
798 SSL_CTX_set_options(context
, SSL_OP_NO_SSLv2
);
799 SSL_CTX_set_options(context
, SSL_OP_NO_SSLv3
); /* THRIFT-3164 */