summaryrefslogtreecommitdiff
path: root/main/tcptls.c
diff options
context:
space:
mode:
authorDavid Vossel <dvossel@digium.com>2009-04-29 21:13:43 +0000
committerDavid Vossel <dvossel@digium.com>2009-04-29 21:13:43 +0000
commita6adc84e6952883381805a75d1ebcae3c192dfd6 (patch)
treed6c952359c1ff180fb4c871647ce784eaf1684e4 /main/tcptls.c
parentd35fd35ae3dfa0e6c5567711a30ec617dbc012fc (diff)
SIP option to specify outbound TLS/SSL client protocol.
chan_sip allows for outbound TLS connections, but does not allow the user to specify what protocol to use (default was SSLv2, and still is if this new option is not specified). This patch lets the user pick the SSL/TLS client method for outbound connections in sip. (closes issue #14770) Reported by: TheOldSaint (closes issue #14768) Reported by: TheOldSaint Review: http://reviewboard.digium.com/r/240/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@191177 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/tcptls.c')
-rw-r--r--main/tcptls.c53
1 files changed, 43 insertions, 10 deletions
diff --git a/main/tcptls.c b/main/tcptls.c
index 4609438f5..e51d7a208 100644
--- a/main/tcptls.c
+++ b/main/tcptls.c
@@ -173,7 +173,7 @@ static void *handle_tls_connection(void *data)
X509_NAME *name = X509_get_subject_name(peer);
int pos = -1;
int found = 0;
-
+
for (;;) {
/* Walk the certificate to check all available "Common Name" */
/* XXX Probably should do a gethostbyname on the hostname and compare that as well */
@@ -229,7 +229,7 @@ void *ast_tcptls_server_root(void *data)
socklen_t sinlen;
struct ast_tcptls_session_instance *tcptls_session;
pthread_t launched;
-
+
for (;;) {
int i, flags;
@@ -261,7 +261,7 @@ void *ast_tcptls_server_root(void *data)
memcpy(&tcptls_session->remote_address, &sin, sizeof(tcptls_session->remote_address));
tcptls_session->client = 0;
-
+
if (ast_pthread_create_detached_background(&launched, NULL, handle_tls_connection, tcptls_session)) {
ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
close(tcptls_session->fd);
@@ -283,7 +283,26 @@ static int __ssl_setup(struct ast_tls_config *cfg, int client)
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
- if (!(cfg->ssl_ctx = SSL_CTX_new( client ? SSLv23_client_method() : SSLv23_server_method() ))) {
+ if (client) {
+ if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) {
+ cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method());
+ } else if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) {
+ cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
+ } else if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) {
+ cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
+ } else {
+ /* SSLv23_client_method() sends SSLv2, this was the original
+ * default for ssl clients before the option was given to
+ * pick what protocol a client should use. In order not
+ * to break expected behavior it remains the default. */
+ cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
+ }
+ } else {
+ /* SSLv23_server_method() supports TLSv1, SSLv2, and SSLv3 inbound connections. */
+ cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
+ }
+
+ if (!cfg->ssl_ctx) {
ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n");
cfg->enabled = 0;
return 0;
@@ -417,22 +436,22 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
{
int flags;
int x = 1;
-
+
/* Do nothing if nothing has changed */
if (!memcmp(&desc->old_address, &desc->local_address, sizeof(desc->old_address))) {
ast_debug(1, "Nothing changed in %s\n", desc->name);
return;
}
-
+
desc->old_address = desc->local_address;
-
+
/* Shutdown a running server if there is one */
if (desc->master != AST_PTHREADT_NULL) {
pthread_cancel(desc->master);
pthread_kill(desc->master, SIGURG);
pthread_join(desc->master, NULL);
}
-
+
if (desc->accept_fd != -1)
close(desc->accept_fd);
@@ -447,7 +466,7 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
return;
}
-
+
setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) {
ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n",
@@ -494,7 +513,7 @@ int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_
if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) {
tls_cfg->enabled = ast_true(value) ? 1 : 0;
tls_desc->local_address.sin_family = AF_INET;
- } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert")) {
+ } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) {
ast_free(tls_cfg->certfile);
tls_cfg->certfile = ast_strdup(value);
} else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) {
@@ -518,6 +537,20 @@ int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_
ast_log(LOG_WARNING, "Invalid %s '%s'\n", varname, value);
} else if (!strcasecmp(varname, "tlsbindport") || !strcasecmp(varname, "sslbindport")) {
tls_desc->local_address.sin_port = htons(atoi(value));
+ } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) {
+ if (!strcasecmp(value, "tlsv1")) {
+ ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
+ ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
+ ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
+ } else if (!strcasecmp(value, "sslv3")) {
+ ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
+ ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
+ ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
+ } else if (!strcasecmp(value, "sslv2")) {
+ ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
+ ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
+ ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
+ }
} else {
return -1;
}