diff options
Diffstat (limited to 'tinyNET/src/tls/tnet_tls.c')
-rwxr-xr-x | tinyNET/src/tls/tnet_tls.c | 475 |
1 files changed, 235 insertions, 240 deletions
diff --git a/tinyNET/src/tls/tnet_tls.c b/tinyNET/src/tls/tnet_tls.c index 0ae520c..1904fa3 100755 --- a/tinyNET/src/tls/tnet_tls.c +++ b/tinyNET/src/tls/tnet_tls.c @@ -1,19 +1,19 @@ /* * Copyright (C) 2010-2012 Mamadou Diop. * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -34,270 +34,266 @@ #define TNET_TLS_TIMEOUT 2000 #define TNET_TLS_RETRY_COUNT 10 -typedef struct tnet_tls_socket_s -{ - TSK_DECLARE_OBJECT; - - tnet_fd_t fd; /* not owner: do not try to close */ +typedef struct tnet_tls_socket_s { + TSK_DECLARE_OBJECT; + + tnet_fd_t fd; /* not owner: do not try to close */ #if HAVE_OPENSSL - SSL *ssl; + SSL *ssl; #endif - TSK_DECLARE_SAFEOBJ; + TSK_DECLARE_SAFEOBJ; } tnet_tls_socket_t; tsk_bool_t tnet_tls_is_supported() { #if HAVE_OPENSSL - return tsk_true; + return tsk_true; #else - return tsk_false; + return tsk_false; #endif } tnet_tls_socket_handle_t* tnet_tls_socket_create(tnet_fd_t fd, struct ssl_ctx_st* ssl_ctx) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("OpenSSL not enabled"); - return tsk_null; + TSK_DEBUG_ERROR("OpenSSL not enabled"); + return tsk_null; #else - tnet_tls_socket_t* socket; - if(fd <= 0 || !ssl_ctx){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - if((socket = tsk_object_new(tnet_tls_socket_def_t))){ - socket->fd = fd; - if(!(socket->ssl = SSL_new(ssl_ctx))){ - TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - TSK_OBJECT_SAFE_FREE(socket); - return tsk_null; - } - if(SSL_set_fd(socket->ssl, socket->fd) != 1){ - TSK_DEBUG_ERROR("SSL_set_fd(%d) failed [%s]", socket->fd, ERR_error_string(ERR_get_error(), tsk_null)); - TSK_OBJECT_SAFE_FREE(socket); - return tsk_null; - } - } - return socket; + tnet_tls_socket_t* socket; + if(fd <= 0 || !ssl_ctx) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + if((socket = tsk_object_new(tnet_tls_socket_def_t))) { + socket->fd = fd; + if(!(socket->ssl = SSL_new(ssl_ctx))) { + TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + TSK_OBJECT_SAFE_FREE(socket); + return tsk_null; + } + if(SSL_set_fd(socket->ssl, socket->fd) != 1) { + TSK_DEBUG_ERROR("SSL_set_fd(%d) failed [%s]", socket->fd, ERR_error_string(ERR_get_error(), tsk_null)); + TSK_OBJECT_SAFE_FREE(socket); + return tsk_null; + } + } + return socket; #endif } int tnet_tls_socket_connect(tnet_tls_socket_handle_t* self) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("You MUST enable OpenSSL"); - return -200; + TSK_DEBUG_ERROR("You MUST enable OpenSSL"); + return -200; #else - int ret; - tnet_tls_socket_t* socket = self; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if((ret = SSL_connect(socket->ssl)) != 1){ - ret = SSL_get_error(socket->ssl, ret); - if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_SYSCALL){ - ret = 0; /* up to the caller to check that the socket is writable and valid */ - } - else{ - TSK_DEBUG_ERROR("SSL_connect failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - } - } - else{ - ret = 0; - } - - return ret; + int ret; + tnet_tls_socket_t* socket = self; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if((ret = SSL_connect(socket->ssl)) != 1) { + ret = SSL_get_error(socket->ssl, ret); + if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_SYSCALL) { + ret = 0; /* up to the caller to check that the socket is writable and valid */ + } + else { + TSK_DEBUG_ERROR("SSL_connect failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + } + } + else { + ret = 0; + } + + return ret; #endif } int tnet_tls_socket_accept(tnet_tls_socket_handle_t* self) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("You MUST enable OpenSSL"); - return -200; + TSK_DEBUG_ERROR("You MUST enable OpenSSL"); + return -200; #else - int ret = -1; - tnet_tls_socket_t* socket = self; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if((ret = SSL_accept(socket->ssl)) != 1){ - ret = SSL_get_error(socket->ssl, ret); - if(ret == SSL_ERROR_WANT_READ){ - int retval; - fd_set rfds; - while (1) - { - FD_ZERO(&rfds); - FD_SET(socket->fd, &rfds); - retval = select(socket->fd + 1, &rfds, NULL, NULL, NULL); - if (retval == -1){ - TNET_PRINT_LAST_ERROR("select() failed"); - } - else if (retval) - { - if (FD_ISSET(socket->fd, &rfds)){ - ret = SSL_accept(socket->ssl); - ret = SSL_get_error(socket->ssl, ret); - if (ret == SSL_ERROR_WANT_READ){ - continue; - } - else{ - if(ret == SSL_ERROR_NONE){ - return 0; - } - break; - } - } - } - else - { - break; - } - } - } - TSK_DEBUG_ERROR("SSL_accept() failed with error code [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - return -3; - } - - return 0; + int ret = -1; + tnet_tls_socket_t* socket = self; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if((ret = SSL_accept(socket->ssl)) != 1) { + ret = SSL_get_error(socket->ssl, ret); + if(ret == SSL_ERROR_WANT_READ) { + int retval; + fd_set rfds; + while (1) { + FD_ZERO(&rfds); + FD_SET(socket->fd, &rfds); + retval = select(socket->fd + 1, &rfds, NULL, NULL, NULL); + if (retval == -1) { + TNET_PRINT_LAST_ERROR("select() failed"); + } + else if (retval) { + if (FD_ISSET(socket->fd, &rfds)) { + ret = SSL_accept(socket->ssl); + ret = SSL_get_error(socket->ssl, ret); + if (ret == SSL_ERROR_WANT_READ) { + continue; + } + else { + if(ret == SSL_ERROR_NONE) { + return 0; + } + break; + } + } + } + else { + break; + } + } + } + TSK_DEBUG_ERROR("SSL_accept() failed with error code [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + return -3; + } + + return 0; #endif } int tnet_tls_socket_write(tnet_tls_socket_handle_t* self, const void* data, tsk_size_t size) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("You MUST enable OpenSSL"); - return -200; + TSK_DEBUG_ERROR("You MUST enable OpenSSL"); + return -200; #else - int ret = -1; - tnet_tls_socket_t* socket = self; - tsk_bool_t try_again = tsk_true, want_read, want_write; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - /* Write */ - tsk_safeobj_lock(socket); - while(((ret = SSL_write(socket->ssl, data, (int)size)) <= 0) && try_again){ - ret = SSL_get_error(socket->ssl, ret); - want_read = (ret == SSL_ERROR_WANT_READ); - want_write = (ret == SSL_ERROR_WANT_WRITE); - - if(want_write || want_read){ - if(!(ret = tnet_sockfd_waitUntil(socket->fd, TNET_TLS_TIMEOUT, want_write))){ - continue; - } - } - else{ - TSK_DEBUG_ERROR("SSL_write failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - ret = -3; - try_again = tsk_false; - } - } - tsk_safeobj_unlock(socket); - - ret = (ret > 0) ? 0 : -3; - return ret; + int ret = -1; + tnet_tls_socket_t* socket = self; + tsk_bool_t try_again = tsk_true, want_read, want_write; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + /* Write */ + tsk_safeobj_lock(socket); + while(((ret = SSL_write(socket->ssl, data, (int)size)) <= 0) && try_again) { + ret = SSL_get_error(socket->ssl, ret); + want_read = (ret == SSL_ERROR_WANT_READ); + want_write = (ret == SSL_ERROR_WANT_WRITE); + + if(want_write || want_read) { + if(!(ret = tnet_sockfd_waitUntil(socket->fd, TNET_TLS_TIMEOUT, want_write))) { + continue; + } + } + else { + TSK_DEBUG_ERROR("SSL_write failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + ret = -3; + try_again = tsk_false; + } + } + tsk_safeobj_unlock(socket); + + ret = (ret > 0) ? 0 : -3; + return ret; #endif } int tnet_tls_socket_recv(tnet_tls_socket_handle_t* self, void** data, tsk_size_t *size, tsk_bool_t *isEncrypted) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("You MUST enable OpenSSL"); - return -200; + TSK_DEBUG_ERROR("You MUST enable OpenSSL"); + return -200; #else - int ret = -1; - tsk_size_t read = 0; - tsk_size_t to_read = *size; - int rcount = TNET_TLS_RETRY_COUNT; - tnet_tls_socket_t* socket = self; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(socket); - - *isEncrypted = SSL_is_init_finished(socket->ssl) ? tsk_false : tsk_true; - - /* SSL handshake has completed? */ - if(*isEncrypted){ - char* buffer[1024]; - if((ret = SSL_read(socket->ssl, buffer, sizeof(buffer))) <= 0){ - ret = SSL_get_error(socket->ssl, ret); - if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ){ - ret = 0; - } - else{ - TSK_DEBUG_ERROR("SSL_read failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - } - *size = 0; - } - else{ - *size = ret; - ret = 0; - } - - goto bail; - } - - /* Read Application data */ -ssl_read: - if(rcount && ((ret = SSL_read(socket->ssl, (((uint8_t*)*data)+read), (int)to_read)) <= 0)){ - ret = SSL_get_error(socket->ssl, ret); - if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ){ - if(!(ret = tnet_sockfd_waitUntil(socket->fd, TNET_TLS_TIMEOUT, (ret == SSL_ERROR_WANT_WRITE)))){ - rcount--; - goto ssl_read; - } - } - else if(SSL_ERROR_ZERO_RETURN){ /* connection closed: do nothing, the transport layer will be alerted. */ - *size = 0; - ret = 0; - TSK_DEBUG_INFO("TLS connection closed."); - } - else{ - TSK_DEBUG_ERROR("SSL_read failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - } - } - else if(ret >=0){ - read += (tsk_size_t)ret; - - if((ret = SSL_pending(socket->ssl)) > 0){ - void *ptr; - to_read = ret; - - if((ptr = tsk_realloc(*data, (read + to_read)))){ - *data = ptr; - goto ssl_read; - } - } - } + int ret = -1; + tsk_size_t read = 0; + tsk_size_t to_read = *size; + int rcount = TNET_TLS_RETRY_COUNT; + tnet_tls_socket_t* socket = self; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + tsk_safeobj_lock(socket); + + *isEncrypted = SSL_is_init_finished(socket->ssl) ? tsk_false : tsk_true; + + /* SSL handshake has completed? */ + if(*isEncrypted) { + char* buffer[1024]; + if((ret = SSL_read(socket->ssl, buffer, sizeof(buffer))) <= 0) { + ret = SSL_get_error(socket->ssl, ret); + if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) { + ret = 0; + } + else { + TSK_DEBUG_ERROR("SSL_read failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + } + *size = 0; + } + else { + *size = ret; + ret = 0; + } + + goto bail; + } + + /* Read Application data */ +ssl_read: + if(rcount && ((ret = SSL_read(socket->ssl, (((uint8_t*)*data)+read), (int)to_read)) <= 0)) { + ret = SSL_get_error(socket->ssl, ret); + if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) { + if(!(ret = tnet_sockfd_waitUntil(socket->fd, TNET_TLS_TIMEOUT, (ret == SSL_ERROR_WANT_WRITE)))) { + rcount--; + goto ssl_read; + } + } + else if(SSL_ERROR_ZERO_RETURN) { /* connection closed: do nothing, the transport layer will be alerted. */ + *size = 0; + ret = 0; + TSK_DEBUG_INFO("TLS connection closed."); + } + else { + TSK_DEBUG_ERROR("SSL_read failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + } + } + else if(ret >=0) { + read += (tsk_size_t)ret; + + if((ret = SSL_pending(socket->ssl)) > 0) { + void *ptr; + to_read = ret; + + if((ptr = tsk_realloc(*data, (read + to_read)))) { + *data = ptr; + goto ssl_read; + } + } + } bail: - tsk_safeobj_unlock(socket); - - if(read){ - *size = read; - return 0; - } - else{ - return ret; - } + tsk_safeobj_unlock(socket); + + if(read) { + *size = read; + return 0; + } + else { + return ret; + } #endif } @@ -309,34 +305,33 @@ bail: // static tsk_object_t* tnet_tls_socket_ctor(tsk_object_t * self, va_list * app) { - tnet_tls_socket_t *socket = self; - if(socket){ - tsk_safeobj_init(socket); - } - return self; + tnet_tls_socket_t *socket = self; + if(socket) { + tsk_safeobj_init(socket); + } + return self; } static tsk_object_t* tnet_tls_socket_dtor(tsk_object_t * self) -{ - tnet_tls_socket_t *socket = self; - if(socket){ +{ + tnet_tls_socket_t *socket = self; + if(socket) { #if HAVE_OPENSSL - if(socket->ssl){ - SSL_shutdown(socket->ssl); - SSL_free(socket->ssl); - } + if(socket->ssl) { + SSL_shutdown(socket->ssl); + SSL_free(socket->ssl); + } #endif - tsk_safeobj_deinit(socket); - } - return self; + tsk_safeobj_deinit(socket); + } + return self; } -static const tsk_object_def_t tnet_tls_socket_def_s = -{ - sizeof(tnet_tls_socket_t), - tnet_tls_socket_ctor, - tnet_tls_socket_dtor, - tsk_null, +static const tsk_object_def_t tnet_tls_socket_def_s = { + sizeof(tnet_tls_socket_t), + tnet_tls_socket_ctor, + tnet_tls_socket_dtor, + tsk_null, }; const tsk_object_def_t *tnet_tls_socket_def_t = &tnet_tls_socket_def_s; |