Merge pull request #1131 in FS/freeswitch from pr/1130 to master

* commit 'c1abfaf4f8f2ec954d9a5ba745c874790e2d279c':
  FS-9903 #resolve #comment fix server side TLS and add client TLS support
This commit is contained in:
Anthony Minessale II 2017-01-02 18:06:54 -06:00
commit 848730a320
3 changed files with 76 additions and 27 deletions

View File

@ -1,6 +1,6 @@
/* /*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2011-2016, Seven Du <dujinfang@gmail.com> * Copyright (C) 2011-2017, Seven Du <dujinfang@gmail.com>
* *
* Version: MPL 1.1 * Version: MPL 1.1
* *
@ -33,6 +33,8 @@
#define _MSRP_H #define _MSRP_H
#include <switch.h> #include <switch.h>
#include <switch_ssl.h>
#define MSRP_LISTEN_PORT 2855 #define MSRP_LISTEN_PORT 2855
#define MSRP_SSL_LISTEN_PORT 2856 #define MSRP_SSL_LISTEN_PORT 2856
@ -93,6 +95,7 @@ typedef struct msrp_socket_s {
struct msrp_client_socket_s { struct msrp_client_socket_s {
switch_socket_t *sock; switch_socket_t *sock;
SSL *ssl;
int secure; int secure;
int client_mode; int client_mode;
struct switch_msrp_session_s *msrp_session; struct switch_msrp_session_s *msrp_session;

View File

@ -31,6 +31,10 @@
#ifndef __SWITCH_SSL_H #ifndef __SWITCH_SSL_H
#define __SWITCH_SSL_H #define __SWITCH_SSL_H
#ifndef HAVE_OPENSSL
#define HAVE_OPENSSL
#endif
#if defined(HAVE_OPENSSL) #if defined(HAVE_OPENSSL)
#if defined (MACOSX) || defined(DARWIN) #if defined (MACOSX) || defined(DARWIN)
/* Disable depricated-declarations on OS X */ /* Disable depricated-declarations on OS X */

View File

@ -1,6 +1,6 @@
/* /*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2011-2016, Seven Du <dujinfang@gmail.com> * Copyright (C) 2011-2017, Seven Du <dujinfang@gmail.com>
* *
* Version: MPL 1.1 * Version: MPL 1.1
* *
@ -30,7 +30,6 @@
*/ */
#include <switch.h> #include <switch.h>
#include <switch_ssl.h>
#include <switch_msrp.h> #include <switch_msrp.h>
#include <switch_stun.h> #include <switch_stun.h>
@ -49,8 +48,9 @@ static struct {
char *key; char *key;
const SSL_METHOD *ssl_method; const SSL_METHOD *ssl_method;
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
SSL *ssl;
int ssl_ready; int ssl_ready;
const SSL_METHOD *ssl_client_method;
SSL_CTX *ssl_client_ctx;
msrp_socket_t msock; msrp_socket_t msock;
msrp_socket_t msock_ssl; msrp_socket_t msock_ssl;
@ -75,7 +75,10 @@ static int msrp_init_ssl()
{ {
const char *err = ""; const char *err = "";
SSL_library_init(); globals.ssl_client_method = SSLv23_client_method();
globals.ssl_client_ctx = SSL_CTX_new(globals.ssl_client_method);
assert(globals.ssl_client_ctx);
SSL_CTX_set_options(globals.ssl_client_ctx, SSL_OP_NO_SSLv2);
globals.ssl_method = SSLv23_server_method(); /* create server instance */ globals.ssl_method = SSLv23_server_method(); /* create server instance */
globals.ssl_ctx = SSL_CTX_new(globals.ssl_method); /* create context */ globals.ssl_ctx = SSL_CTX_new(globals.ssl_method); /* create context */
@ -430,9 +433,12 @@ static switch_status_t msrp_socket_recv(msrp_client_socket_t *csock, char *buf,
if (csock->secure) { if (csock->secure) {
switch_ssize_t r; switch_ssize_t r;
r = SSL_read(globals.ssl, buf, *len); r = SSL_read(csock->ssl, buf, *len);
if (r < 0) { if (r < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "TLS read error: %" SWITCH_SSIZE_T_FMT "\n", r); int error = SSL_get_error(csock->ssl, r);
if (!(SSL_ERROR_SYSCALL == error && errno == 9)) {// socket closed
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TLS read error: ret=%" SWITCH_SSIZE_T_FMT " error=%d errno=%d\n", r, error, errno);
}
*len = 0; *len = 0;
} else { } else {
*len = r; *len = r;
@ -448,7 +454,7 @@ static switch_status_t msrp_socket_recv(msrp_client_socket_t *csock, char *buf,
static switch_status_t msrp_socket_send(msrp_client_socket_t *csock, char *buf, switch_size_t *len) static switch_status_t msrp_socket_send(msrp_client_socket_t *csock, char *buf, switch_size_t *len)
{ {
if (csock->secure) { if (csock->secure) {
*len = SSL_write(globals.ssl, buf, *len); *len = SSL_write(csock->ssl, buf, *len);
return *len ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; return *len ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
} else { } else {
return switch_socket_send(csock->sock, buf, len); return switch_socket_send(csock->sock, buf, len);
@ -961,7 +967,41 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
switch_socket_timeout_set(csock->sock, -1); switch_socket_timeout_set(csock->sock, -1);
if (msrp_session->secure) { if (msrp_session->secure) {
// todo setup tls ... X509 *cert = NULL;
switch_os_socket_t sockdes = SWITCH_SOCK_INVALID;
int ret;
switch_os_sock_get(&sockdes, csock->sock);
switch_assert(sockdes != SWITCH_SOCK_INVALID);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MSRP setup TLS %s\n", msrp_session->call_id);
ssl = SSL_new(globals.ssl_client_ctx);
assert(ssl);
csock->ssl = ssl;
SSL_set_fd(ssl, sockdes);
if ((ret = SSL_connect(ssl)) != 1 ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: Could not build a SSL session to: %s error=%d\n", msrp_session->remote_path, SSL_get_error(ssl, ret));
goto end;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Successfully enabled SSL/TLS session to: %s\n", msrp_session->remote_path);
cert = SSL_get_peer_certificate(ssl);
if (cert == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: Could not get a certificate from: %s\n", msrp_session->remote_path);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got SSL Cert from %s\n", msrp_session->remote_path);
#if 0
certname = X509_NAME_new();
certname = X509_get_subject_name(cert);
X509_NAME_print_ex(outbio, certname, 0, 0);
BIO_printf(outbio, "\n");
#endif
}
} }
helper->msrp_session->csock = csock; helper->msrp_session->csock = csock;
@ -982,6 +1022,7 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
int secure_established = 0; int secure_established = 0;
int sanity = 10; int sanity = 10;
switch_os_socket_t sockdes = SWITCH_SOCK_INVALID; switch_os_socket_t sockdes = SWITCH_SOCK_INVALID;
int code = 0;
switch_os_sock_get(&sockdes, csock->sock); switch_os_sock_get(&sockdes, csock->sock);
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "socket: %d\n", sockdes); // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "socket: %d\n", sockdes);
@ -989,23 +1030,19 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
ssl = SSL_new(globals.ssl_ctx); ssl = SSL_new(globals.ssl_ctx);
assert(ssl); assert(ssl);
globals.ssl = ssl; csock->ssl = ssl;
SSL_set_fd(ssl, sockdes); SSL_set_fd(ssl, sockdes);
do { do {
int code = SSL_accept(ssl); code = SSL_accept(ssl);
if (code == 1) { if (code == 1) {
secure_established = 1; secure_established = 1;
goto done; goto done;
} } else if (code == 0) {
if (code == 0) {
goto err; goto err;
} } else if (code < 0) {
if (code < 0) {
if (code == -1 && SSL_get_error(ssl, code) != SSL_ERROR_WANT_READ) { if (code == -1 && SSL_get_error(ssl, code) != SSL_ERROR_WANT_READ) {
goto err; goto err;
} }
@ -1013,7 +1050,7 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
} while(sanity--); } while(sanity--);
err: err:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SSL ERR\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SSL ERR code=%d error=%d\n", code, SSL_get_error(ssl, code));
goto end; goto end;
done: done:
@ -1084,7 +1121,7 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
switch_safe_free(msrp_msg); switch_safe_free(msrp_msg);
msrp_msg = NULL; msrp_msg = NULL;
while (msrp_socket_recv(csock, p, &len) == SWITCH_STATUS_SUCCESS) { while (msrp_socket_recv(csock, p, &len) == SWITCH_STATUS_SUCCESS && len > 0) {
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "read bytes:%" SWITCH_SIZE_T_FMT "\n", len); // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "read bytes:%" SWITCH_SIZE_T_FMT "\n", len);
if (helper->debug) dump_buffer(buf, (p - buf) + len, __LINE__); if (helper->debug) dump_buffer(buf, (p - buf) + len, __LINE__);
@ -1123,9 +1160,8 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
last_p = msrp_msg->last_p; last_p = msrp_msg->last_p;
} }
while (msrp_session && msrp_session->msrp_msg_count > msrp_session->msrp_msg_buffer_size) { while (msrp_session && msrp_session->running && msrp_session->msrp_msg_count > msrp_session->msrp_msg_buffer_size) {
if (!msrp_session->running) break; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s reading too fast, relax...\n", msrp_session->call_id);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s reading too fast, relax...\n", uuid);
switch_yield(100000); switch_yield(100000);
} }
@ -1200,14 +1236,20 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
} }
end: end:
if (msrp_session) {
switch_mutex_lock(msrp_session->mutex); switch_mutex_lock(msrp_session->mutex);
close_socket(&csock->sock); close_socket(&csock->sock);
switch_mutex_unlock(msrp_session->mutex); switch_mutex_unlock(msrp_session->mutex);
}
if (!client_mode) switch_core_destroy_memory_pool(&pool); if (!client_mode) switch_core_destroy_memory_pool(&pool);
msrp_session->running = 0; if (client_mode && ssl) SSL_free(ssl);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP worker down %s\n", msrp_session->call_id);
if (msrp_session) msrp_session->running = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP worker down %s\n", msrp_session ? msrp_session->call_id : "!");
return NULL; return NULL;
} }