dect
/
asterisk
Archived
13
0
Fork 0

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: http://svn.digium.com/svn/asterisk/trunk@191177 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
dvossel 2009-04-29 21:13:43 +00:00
parent 46a59c6246
commit 0f6a1e66b9
4 changed files with 57 additions and 12 deletions

View File

@ -23,6 +23,8 @@ SIP Changes
* Added tlsprivatekey option to sip.conf. This allows a separate .pem file
to be used for holding a private key. If tlsprivatekey is not specified,
tlscertfile is searched for both public and private key.
* Added tlsclientmethod option to sip.conf. This allows the protocol for
outbound client connections to be specified.
Applications
------------

View File

@ -142,8 +142,12 @@ tcpbindaddr=0.0.0.0 ; IP address for TCP server to bind to (0.0.0.0
;tlscipher=<SSL cipher string>
; A string specifying which SSL ciphers to use or not use
; A list of valid SSL cipher strings can be found at:
; A list of valid SSL cipher strings can be found at:
; http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS
;
;tlsclientmethod=tlsv1 ; values include tlsv1, sslv3, sslv2.
; Specify protocol for outbound client connections.
; If left unspecified, the default is sslv2.
srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; Note: Asterisk only uses the first host

View File

@ -72,7 +72,13 @@ enum ast_ssl_flags {
/*! Don't verify certificate when connecting to a server */
AST_SSL_DONT_VERIFY_SERVER = (1 << 1),
/*! Don't compare "Common Name" against IP or hostname */
AST_SSL_IGNORE_COMMON_NAME = (1 << 2)
AST_SSL_IGNORE_COMMON_NAME = (1 << 2),
/*! Use SSLv2 for outgoing client connections */
AST_SSL_SSLV2_CLIENT = (1 << 3),
/*! Use SSLv3 for outgoing client connections */
AST_SSL_SSLV3_CLIENT = (1 << 4),
/*! Use TLSv1 for outgoing client connections */
AST_SSL_TLSV1_CLIENT = (1 << 5)
};
struct ast_tls_config {

View File

@ -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;
}