Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Macros | Enumerations | Functions
tcptls.h File Reference

Generic support for tcp/tls servers in Asterisk. More...

#include <pthread.h>
#include <sys/param.h>
#include "asterisk/iostream.h"
#include "asterisk/netsock2.h"
#include "asterisk/utils.h"
Include dependency graph for tcptls.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_tcptls_session_args
 arguments for the accepting thread More...
 
struct  ast_tcptls_session_instance
 describes a server instance More...
 
struct  ast_tls_config
 

Macros

#define AST_CERTFILE   "asterisk.pem"
 

Enumerations

enum  ast_ssl_flags {
  AST_SSL_VERIFY_CLIENT = (1 << 0) , AST_SSL_DONT_VERIFY_SERVER = (1 << 1) , AST_SSL_IGNORE_COMMON_NAME = (1 << 2) , AST_SSL_SSLV2_CLIENT = (1 << 3) ,
  AST_SSL_SSLV3_CLIENT = (1 << 4) , AST_SSL_TLSV1_CLIENT = (1 << 5) , AST_SSL_SERVER_CIPHER_ORDER = (1 << 6) , AST_SSL_DISABLE_TLSV1 = (1 << 7) ,
  AST_SSL_DISABLE_TLSV11 = (1 << 8) , AST_SSL_DISABLE_TLSV12 = (1 << 9)
}
 

Functions

int ast_ssl_setup (struct ast_tls_config *cfg)
 Set up an SSL server. More...
 
void ast_ssl_teardown (struct ast_tls_config *cfg)
 free resources used by an SSL server More...
 
struct ast_tcptls_session_instanceast_tcptls_client_create (struct ast_tcptls_session_args *desc)
 Creates a client connection's ast_tcptls_session_instance. More...
 
struct ast_tcptls_session_instanceast_tcptls_client_start (struct ast_tcptls_session_instance *tcptls_session)
 Attempt to connect and start a tcptls session. More...
 
struct ast_tcptls_session_instanceast_tcptls_client_start_timeout (struct ast_tcptls_session_instance *tcptls_session, int timeout)
 Attempt to connect and start a tcptls session within the given timeout. More...
 
void ast_tcptls_close_session_file (struct ast_tcptls_session_instance *tcptls_session)
 Closes a tcptls session instance's file and/or file descriptor. The tcptls_session will be set to NULL and it's file descriptor will be set to -1 by this function. More...
 
void * ast_tcptls_server_root (void *)
 
void ast_tcptls_server_start (struct ast_tcptls_session_args *desc)
 This is a generic (re)start routine for a TCP server, which does the socket/bind/listen and starts a thread for handling accept(). More...
 
void ast_tcptls_server_stop (struct ast_tcptls_session_args *desc)
 Shutdown a running server if there is one. More...
 
int ast_tls_read_conf (struct ast_tls_config *tls_cfg, struct ast_tcptls_session_args *tls_desc, const char *varname, const char *value)
 Used to parse conf files containing tls/ssl options. More...
 

Detailed Description

Generic support for tcp/tls servers in Asterisk.

Note
In order to have TLS/SSL support, we need the openssl libraries. Still we can decide whether or not to use them by commenting in or out the DO_SSL macro.

TLS/SSL support is basically implemented by reading from a config file (currently manager.conf, http.conf and pjsip.conf) the names of the certificate files and cipher to use, and then run ssl_setup() to create an appropriate data structure named ssl_ctx.

If we support multiple domains, presumably we need to read multiple certificates.

When we are requested to open a TLS socket, we run make_file_from_fd() on the socket, to do the necessary setup. At the moment the context's name is hardwired in the function, but we can certainly make it into an extra parameter to the function.

We declare most of ssl support variables unconditionally, because their number is small and this simplifies the code.

Note
The ssl-support variables (ssl_ctx, do_ssl, certfile, cipher) and their setup should be moved to a more central place, e.g. asterisk.conf and the source files that processes it. Similarly, ssl_setup() should be run earlier in the startup process so modules have it available.

TLS Implementation Overview

Definition in file tcptls.h.

Macro Definition Documentation

◆ AST_CERTFILE

#define AST_CERTFILE   "asterisk.pem"

SSL support

Definition at line 63 of file tcptls.h.

Enumeration Type Documentation

◆ ast_ssl_flags

Enumerator
AST_SSL_VERIFY_CLIENT 

Verify certificate when acting as server

AST_SSL_DONT_VERIFY_SERVER 

Don't verify certificate when connecting to a server

AST_SSL_IGNORE_COMMON_NAME 

Don't compare "Common Name" against IP or hostname

AST_SSL_SSLV2_CLIENT 

Use SSLv2 for outgoing client connections

AST_SSL_SSLV3_CLIENT 

Use SSLv3 for outgoing client connections

AST_SSL_TLSV1_CLIENT 

Use TLSv1 for outgoing client connections

AST_SSL_SERVER_CIPHER_ORDER 

Use server cipher order instead of the client order

AST_SSL_DISABLE_TLSV1 

Disable TLSv1 support

AST_SSL_DISABLE_TLSV11 

Disable TLSv1.1 support

AST_SSL_DISABLE_TLSV12 

Disable TLSv1.2 support

Definition at line 65 of file tcptls.h.

65 {
66 /*! Verify certificate when acting as server */
67 AST_SSL_VERIFY_CLIENT = (1 << 0),
68 /*! Don't verify certificate when connecting to a server */
70 /*! Don't compare "Common Name" against IP or hostname */
72 /*! Use SSLv2 for outgoing client connections */
73 AST_SSL_SSLV2_CLIENT = (1 << 3),
74 /*! Use SSLv3 for outgoing client connections */
75 AST_SSL_SSLV3_CLIENT = (1 << 4),
76 /*! Use TLSv1 for outgoing client connections */
77 AST_SSL_TLSV1_CLIENT = (1 << 5),
78 /*! Use server cipher order instead of the client order */
80 /*! Disable TLSv1 support */
81 AST_SSL_DISABLE_TLSV1 = (1 << 7),
82 /*! Disable TLSv1.1 support */
83 AST_SSL_DISABLE_TLSV11 = (1 << 8),
84 /*! Disable TLSv1.2 support */
85 AST_SSL_DISABLE_TLSV12 = (1 << 9),
86};
@ AST_SSL_VERIFY_CLIENT
Definition: tcptls.h:67
@ AST_SSL_DONT_VERIFY_SERVER
Definition: tcptls.h:69
@ AST_SSL_SSLV3_CLIENT
Definition: tcptls.h:75
@ AST_SSL_DISABLE_TLSV11
Definition: tcptls.h:83
@ AST_SSL_IGNORE_COMMON_NAME
Definition: tcptls.h:71
@ AST_SSL_TLSV1_CLIENT
Definition: tcptls.h:77
@ AST_SSL_DISABLE_TLSV12
Definition: tcptls.h:85
@ AST_SSL_SERVER_CIPHER_ORDER
Definition: tcptls.h:79
@ AST_SSL_DISABLE_TLSV1
Definition: tcptls.h:81
@ AST_SSL_SSLV2_CLIENT
Definition: tcptls.h:73

Function Documentation

◆ ast_ssl_setup()

int ast_ssl_setup ( struct ast_tls_config cfg)

Set up an SSL server.

Parameters
cfgConfiguration for the SSL server
Return values
1Success
0Failure

Definition at line 577 of file tcptls.c.

578{
579 return __ssl_setup(cfg, 0, 0);
580}
static int __ssl_setup(struct ast_tls_config *cfg, int client, int suppress_progress_msgs)
Definition: tcptls.c:382

References __ssl_setup().

Referenced by __ast_http_load(), and __init_manager().

◆ ast_ssl_teardown()

void ast_ssl_teardown ( struct ast_tls_config cfg)

free resources used by an SSL server

Note
This only needs to be called if ast_ssl_setup() was directly called first.
Parameters
cfgConfiguration for the SSL server

Definition at line 582 of file tcptls.c.

583{
584#ifdef DO_SSL
585 if (cfg && cfg->ssl_ctx) {
586 SSL_CTX_free(cfg->ssl_ctx);
587 cfg->ssl_ctx = NULL;
588 }
589#endif
590}
#define NULL
Definition: resample.c:96
SSL_CTX * ssl_ctx
Definition: tcptls.h:96

References NULL, and ast_tls_config::ssl_ctx.

Referenced by websocket_client_args_destroy().

◆ ast_tcptls_client_create()

struct ast_tcptls_session_instance * ast_tcptls_client_create ( struct ast_tcptls_session_args desc)

Creates a client connection's ast_tcptls_session_instance.

Definition at line 686 of file tcptls.c.

687{
688 int fd, x = 1;
689 struct ast_tcptls_session_instance *tcptls_session = NULL;
690
691 ast_assert(!desc->tls_cfg
692 || ast_test_flag(&desc->tls_cfg->flags, AST_SSL_DONT_VERIFY_SERVER)
693 || !ast_strlen_zero(desc->hostname));
694
695 /* Do nothing if nothing has changed */
696 if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) {
697 ast_debug(1, "Nothing changed in %s\n", desc->name);
698 return NULL;
699 }
700
701 /* If we return early, there is no connection */
702 ast_sockaddr_setnull(&desc->old_address);
703
704 fd = desc->accept_fd = ast_socket_nonblock(ast_sockaddr_is_ipv6(&desc->remote_address) ?
705 AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
706 if (desc->accept_fd < 0) {
707 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n",
708 desc->name, strerror(errno));
709 return NULL;
710 }
711
712 /* if a local address was specified, bind to it so the connection will
713 originate from the desired address */
714 if (!ast_sockaddr_isnull(&desc->local_address) &&
715 !ast_sockaddr_is_any(&desc->local_address)) {
716 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
717 if (ast_bind(desc->accept_fd, &desc->local_address)) {
718 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
719 desc->name,
720 ast_sockaddr_stringify(&desc->local_address),
721 strerror(errno));
722 goto error;
723 }
724 }
725
726 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor);
727 if (!tcptls_session) {
728 goto error;
729 }
730
731 tcptls_session->overflow_buf = ast_str_create(128);
732 if (!tcptls_session->overflow_buf) {
733 goto error;
734 }
735 tcptls_session->client = 1;
736 tcptls_session->stream = ast_iostream_from_fd(&fd);
737 if (!tcptls_session->stream) {
738 goto error;
739 }
740
741 /* From here on out, the iostream owns the accept_fd and it will take
742 * care of closing it when the iostream is closed */
743
744 tcptls_session->parent = desc;
745 tcptls_session->parent->worker_fn = NULL;
746 ast_sockaddr_copy(&tcptls_session->remote_address,
747 &desc->remote_address);
748
749 /* Set current info */
750 ast_sockaddr_copy(&desc->old_address, &desc->remote_address);
751
752 if (!ast_strlen_zero(desc->hostname)) {
753 if (ast_iostream_set_sni_hostname(tcptls_session->stream, desc->hostname) != 0) {
754 ast_log(LOG_WARNING, "Unable to set SNI hostname '%s' on connection '%s'\n",
755 desc->hostname, desc->name);
756 }
757 }
758
759 return tcptls_session;
760
761error:
762 close(desc->accept_fd);
763 desc->accept_fd = -1;
764 ao2_cleanup(tcptls_session);
765 return NULL;
766}
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
static const char desc[]
Definition: cdr_radius.c:84
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_WARNING
struct ast_iostream * ast_iostream_from_fd(int *fd)
Create an iostream from a file descriptor.
Definition: iostream.c:611
int ast_iostream_set_sni_hostname(struct ast_iostream *stream, const char *sni_hostname)
Set the iostream's SNI hostname for TLS client connections.
Definition: iostream.c:156
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
Definition: netsock2.h:167
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
Definition: netsock2.c:534
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:138
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
void *(* worker_fn)(void *)
Definition: tcptls.h:142
describes a server instance
Definition: tcptls.h:151
struct ast_iostream * stream
Definition: tcptls.h:162
struct ast_sockaddr remote_address
Definition: tcptls.h:153
struct ast_tcptls_session_args * parent
Definition: tcptls.h:154
struct ast_str * overflow_buf
Definition: tcptls.h:160
static void session_instance_destructor(void *obj)
Definition: tcptls.c:72
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_assert(a)
Definition: utils.h:739
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1073

References ao2_alloc, ao2_cleanup, ast_assert, ast_bind(), ast_debug, ast_iostream_from_fd(), ast_iostream_set_sni_hostname(), ast_log, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_is_any(), ast_sockaddr_is_ipv6(), ast_sockaddr_isnull(), ast_sockaddr_setnull(), ast_sockaddr_stringify(), ast_socket_nonblock, AST_SSL_DONT_VERIFY_SERVER, ast_str_create, ast_strlen_zero(), ast_test_flag, ast_tcptls_session_instance::client, desc, errno, error(), LOG_ERROR, LOG_WARNING, NULL, ast_tcptls_session_instance::overflow_buf, ast_tcptls_session_instance::parent, ast_tcptls_session_instance::remote_address, session_instance_destructor(), ast_tcptls_session_instance::stream, and ast_tcptls_session_args::worker_fn.

Referenced by app_exec(), and websocket_client_connect().

◆ ast_tcptls_client_start()

struct ast_tcptls_session_instance * ast_tcptls_client_start ( struct ast_tcptls_session_instance tcptls_session)

Attempt to connect and start a tcptls session.

Blocks until a connection is established, or an error occurs.

Note
On error the tcptls_session's ref count is decremented, fd and file are closed, and NULL is returned.
Parameters
tcptls_sessionThe session instance to connect and start
Returns
The tcptls_session, or NULL on error

Definition at line 681 of file tcptls.c.

682{
683 return ast_tcptls_client_start_timeout(tcptls_session, -1);
684}
struct ast_tcptls_session_instance * ast_tcptls_client_start_timeout(struct ast_tcptls_session_instance *tcptls_session, int timeout)
Attempt to connect and start a tcptls session within the given timeout.
Definition: tcptls.c:652

References ast_tcptls_client_start_timeout().

Referenced by app_exec().

◆ ast_tcptls_client_start_timeout()

struct ast_tcptls_session_instance * ast_tcptls_client_start_timeout ( struct ast_tcptls_session_instance tcptls_session,
int  timeout 
)

Attempt to connect and start a tcptls session within the given timeout.

Note
On error the tcptls_session's ref count is decremented, fd and file are closed, and NULL is returned.
Parameters
tcptls_sessionThe session instance to connect and start
timeoutHow long (in milliseconds) to attempt to connect (-1 equals infinite)
Returns
The tcptls_session, or NULL on error

Definition at line 652 of file tcptls.c.

654{
656
657 if (!(desc = tcptls_session->parent)) {
658 ao2_ref(tcptls_session, -1);
659 return NULL;
660 }
661
662 if (socket_connect(desc->accept_fd, &desc->remote_address, timeout)) {
663 if (!desc->suppress_connection_msgs) {
664 ast_log(LOG_WARNING, "Unable to connect %s to %s: %s\n", desc->name,
665 ast_sockaddr_stringify(&desc->remote_address), strerror(errno));
666 }
667
668 ao2_ref(tcptls_session, -1);
669 return NULL;
670 }
671
672 ast_fd_clear_flags(desc->accept_fd, O_NONBLOCK);
673
674 if (desc->tls_cfg) {
675 __ssl_setup(desc->tls_cfg, 1, desc->suppress_connection_msgs);
676 }
677
678 return handle_tcptls_connection(tcptls_session);
679}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
arguments for the accepting thread
Definition: tcptls.h:130
static int socket_connect(int sockfd, const struct ast_sockaddr *addr, int timeout)
Definition: tcptls.c:608
static void * handle_tcptls_connection(void *data)
creates a FILE * from the fd passed by the accept thread. This operation is potentially expensive (ce...
Definition: tcptls.c:140
#define ast_fd_clear_flags(fd, flags)
Clear flags on the given file descriptor.
Definition: utils.h:1055

References __ssl_setup(), ao2_ref, ast_fd_clear_flags, ast_log, ast_sockaddr_stringify(), desc, errno, handle_tcptls_connection(), LOG_WARNING, NULL, ast_tcptls_session_instance::parent, and socket_connect().

Referenced by ast_tcptls_client_start(), and websocket_client_connect().

◆ ast_tcptls_close_session_file()

void ast_tcptls_close_session_file ( struct ast_tcptls_session_instance tcptls_session)

Closes a tcptls session instance's file and/or file descriptor. The tcptls_session will be set to NULL and it's file descriptor will be set to -1 by this function.

Definition at line 923 of file tcptls.c.

924{
925 if (tcptls_session->stream) {
926 ast_iostream_close(tcptls_session->stream);
927 tcptls_session->stream = NULL;
928 } else {
929 ast_debug(1, "ast_tcptls_close_session_file invoked on session instance without file or file descriptor\n");
930 }
931}
int ast_iostream_close(struct ast_iostream *stream)
Close an iostream.
Definition: iostream.c:539

References ast_debug, ast_iostream_close(), NULL, and ast_tcptls_session_instance::stream.

Referenced by ast_http_create_response(), ast_http_send(), handle_tcptls_connection(), and httpd_helper_thread().

◆ ast_tcptls_server_root()

void * ast_tcptls_server_root ( void *  data)

Definition at line 280 of file tcptls.c.

281{
282 struct ast_tcptls_session_args *desc = data;
283 int fd;
284 struct ast_sockaddr addr;
285 struct ast_tcptls_session_instance *tcptls_session;
286 pthread_t launched;
287
288 for (;;) {
289 int i;
290
291 if (desc->periodic_fn) {
292 desc->periodic_fn(desc);
293 }
294 i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout);
295 if (i <= 0) {
296 /* Prevent tight loop from hogging CPU */
297 usleep(1);
298 continue;
299 }
300 fd = ast_accept(desc->accept_fd, &addr);
301 if (fd < 0) {
302 if (errno != EAGAIN
303 && errno != EWOULDBLOCK
304 && errno != EINTR
305 && errno != ECONNABORTED) {
306 ast_log(LOG_ERROR, "TCP/TLS accept failed: %s\n", strerror(errno));
307 if (errno != EMFILE) {
308 break;
309 }
310 }
311 /* Prevent tight loop from hogging CPU */
312 usleep(1);
313 continue;
314 }
315 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor);
316 if (!tcptls_session) {
317 close(fd);
318 continue;
319 }
320
321 tcptls_session->overflow_buf = ast_str_create(128);
322 if (!tcptls_session->overflow_buf) {
323 ao2_ref(tcptls_session, -1);
324 close(fd);
325 continue;
326 }
327 ast_fd_clear_flags(fd, O_NONBLOCK);
328
329 tcptls_session->stream = ast_iostream_from_fd(&fd);
330 if (!tcptls_session->stream) {
331 ao2_ref(tcptls_session, -1);
332 close(fd);
333 continue;
334 }
335
336 tcptls_session->parent = desc;
337 ast_sockaddr_copy(&tcptls_session->remote_address, &addr);
338
339 tcptls_session->client = 0;
340
341 /* This thread is now the only place that controls the single ref to tcptls_session */
343 ast_log(LOG_ERROR, "TCP/TLS unable to launch helper thread for peer '%s': %s\n",
344 ast_sockaddr_stringify(&tcptls_session->remote_address),
345 strerror(errno));
346 ao2_ref(tcptls_session, -1);
347 }
348 }
349
350 ast_log(LOG_ERROR, "TCP/TLS listener thread ended abnormally\n");
351
352 /* Close the listener socket so Asterisk doesn't appear dead. */
353 fd = desc->accept_fd;
354 desc->accept_fd = -1;
355 if (0 <= fd) {
356 close(fd);
357 }
358 return NULL;
359}
int ast_accept(int sockfd, struct ast_sockaddr *addr)
Wrapper around accept(2) that uses struct ast_sockaddr.
Definition: netsock2.c:584
Socket address structure.
Definition: netsock2.h:97
int ast_wait_for_input(int fd, int ms)
Definition: utils.c:1698
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:597

References ao2_alloc, ao2_ref, ast_accept(), ast_fd_clear_flags, ast_iostream_from_fd(), ast_log, ast_pthread_create_detached_background, ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_str_create, ast_wait_for_input(), ast_tcptls_session_instance::client, desc, errno, handle_tcptls_connection(), LOG_ERROR, NULL, ast_tcptls_session_instance::overflow_buf, ast_tcptls_session_instance::parent, ast_tcptls_session_instance::remote_address, session_instance_destructor(), and ast_tcptls_session_instance::stream.

Referenced by http_server_create().

◆ ast_tcptls_server_start()

void ast_tcptls_server_start ( struct ast_tcptls_session_args desc)

This is a generic (re)start routine for a TCP server, which does the socket/bind/listen and starts a thread for handling accept().

Version
1.6.1 changed desc parameter to be of ast_tcptls_session_args type

Definition at line 768 of file tcptls.c.

769{
770 int x = 1;
771 int tls_changed = 0;
772 int sd_socket;
773
774 if (desc->tls_cfg) {
775 char hash[41];
776 char *str = NULL;
777 struct stat st;
778
779 /* Store the hashes of the TLS certificate etc. */
780 if (stat(desc->tls_cfg->certfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->certfile))) {
781 memset(hash, 0, 41);
782 } else {
783 ast_sha1_hash(hash, str);
784 }
785 ast_free(str);
786 str = NULL;
787 memcpy(desc->tls_cfg->certhash, hash, 41);
788 if (stat(desc->tls_cfg->pvtfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->pvtfile))) {
789 memset(hash, 0, 41);
790 } else {
791 ast_sha1_hash(hash, str);
792 }
793 ast_free(str);
794 str = NULL;
795 memcpy(desc->tls_cfg->pvthash, hash, 41);
796 if (stat(desc->tls_cfg->cafile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->cafile))) {
797 memset(hash, 0, 41);
798 } else {
799 ast_sha1_hash(hash, str);
800 }
801 ast_free(str);
802 str = NULL;
803 memcpy(desc->tls_cfg->cahash, hash, 41);
804
805 /* Check whether TLS configuration has changed */
806 if (!desc->old_tls_cfg) { /* No previous configuration */
807 tls_changed = 1;
808 desc->old_tls_cfg = ast_calloc(1, sizeof(*desc->old_tls_cfg));
809 } else if (memcmp(desc->tls_cfg->certhash, desc->old_tls_cfg->certhash, 41)) {
810 tls_changed = 1;
811 } else if (memcmp(desc->tls_cfg->pvthash, desc->old_tls_cfg->pvthash, 41)) {
812 tls_changed = 1;
813 } else if (strcmp(desc->tls_cfg->cipher, desc->old_tls_cfg->cipher)) {
814 tls_changed = 1;
815 } else if (memcmp(desc->tls_cfg->cahash, desc->old_tls_cfg->cahash, 41)) {
816 tls_changed = 1;
817 } else if (strcmp(desc->tls_cfg->capath, desc->old_tls_cfg->capath)) {
818 tls_changed = 1;
819 } else if (memcmp(&desc->tls_cfg->flags, &desc->old_tls_cfg->flags, sizeof(desc->tls_cfg->flags))) {
820 tls_changed = 1;
821 }
822
823 if (tls_changed) {
824 ast_debug(1, "Changed parameters for %s found\n", desc->name);
825 }
826 }
827
828 /* Do nothing if nothing has changed */
829 if (!tls_changed && !ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
830 ast_debug(1, "Nothing changed in %s\n", desc->name);
831 return;
832 }
833
834 /* If we return early, there is no one listening */
835 ast_sockaddr_setnull(&desc->old_address);
836
837 /* Shutdown a running server if there is one */
838 if (desc->master != AST_PTHREADT_NULL) {
839 pthread_cancel(desc->master);
840 pthread_kill(desc->master, SIGURG);
841 pthread_join(desc->master, NULL);
842 }
843
844 sd_socket = ast_sd_get_fd(SOCK_STREAM, &desc->local_address);
845
846 if (sd_socket != -1) {
847 if (desc->accept_fd != sd_socket) {
848 if (desc->accept_fd != -1) {
849 close(desc->accept_fd);
850 }
851 desc->accept_fd = sd_socket;
852 }
853
854 goto systemd_socket_activation;
855 }
856
857 if (desc->accept_fd != -1) {
858 close(desc->accept_fd);
859 desc->accept_fd = -1;
860 }
861
862 /* If there's no new server, stop here */
863 if (ast_sockaddr_isnull(&desc->local_address)) {
864 ast_debug(2, "Server disabled: %s\n", desc->name);
865 return;
866 }
867
868 desc->accept_fd = ast_socket_nonblock(ast_sockaddr_is_ipv6(&desc->local_address) ?
869 AF_INET6 : AF_INET, SOCK_STREAM, 0);
870 if (desc->accept_fd < 0) {
871 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
872 return;
873 }
874
875 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
876 if (ast_bind(desc->accept_fd, &desc->local_address)) {
877 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
878 desc->name,
879 ast_sockaddr_stringify(&desc->local_address),
880 strerror(errno));
881 goto error;
882 }
883 if (listen(desc->accept_fd, 10)) {
884 ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name);
885 goto error;
886 }
887
888systemd_socket_activation:
889 if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
890 ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
891 desc->name,
892 ast_sockaddr_stringify(&desc->local_address),
893 strerror(errno));
894 goto error;
895 }
896
897 /* Set current info */
898 ast_sockaddr_copy(&desc->old_address, &desc->local_address);
899 if (desc->old_tls_cfg) {
900 ast_free(desc->old_tls_cfg->certfile);
901 ast_free(desc->old_tls_cfg->pvtfile);
902 ast_free(desc->old_tls_cfg->cipher);
903 ast_free(desc->old_tls_cfg->cafile);
904 ast_free(desc->old_tls_cfg->capath);
905 desc->old_tls_cfg->certfile = ast_strdup(desc->tls_cfg->certfile);
906 desc->old_tls_cfg->pvtfile = ast_strdup(desc->tls_cfg->pvtfile);
907 desc->old_tls_cfg->cipher = ast_strdup(desc->tls_cfg->cipher);
908 desc->old_tls_cfg->cafile = ast_strdup(desc->tls_cfg->cafile);
909 desc->old_tls_cfg->capath = ast_strdup(desc->tls_cfg->capath);
910 memcpy(desc->old_tls_cfg->certhash, desc->tls_cfg->certhash, 41);
911 memcpy(desc->old_tls_cfg->pvthash, desc->tls_cfg->pvthash, 41);
912 memcpy(desc->old_tls_cfg->cahash, desc->tls_cfg->cahash, 41);
913 memcpy(&desc->old_tls_cfg->flags, &desc->tls_cfg->flags, sizeof(desc->old_tls_cfg->flags));
914 }
915
916 return;
917
918error:
919 close(desc->accept_fd);
920 desc->accept_fd = -1;
921}
const char * str
Definition: app_jack.c:150
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
char * ast_read_textfile(const char *file)
Read a file into asterisk.
Definition: main/app.c:2949
int ast_sd_get_fd(int type, const struct ast_sockaddr *addr)
Find a listening file descriptor provided by socket activation.
Definition: io.c:438
#define AST_PTHREADT_NULL
Definition: lock.h:70
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
Definition: utils.c:266

References ast_bind(), ast_calloc, ast_debug, ast_free, ast_log, ast_pthread_create_background, AST_PTHREADT_NULL, ast_read_textfile(), ast_sd_get_fd(), ast_sha1_hash(), ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_is_ipv6(), ast_sockaddr_isnull(), ast_sockaddr_setnull(), ast_sockaddr_stringify(), ast_socket_nonblock, ast_strdup, desc, errno, error(), LOG_ERROR, NULL, and str.

Referenced by __ast_http_load(), __init_manager(), and http_server_start().

◆ ast_tcptls_server_stop()

void ast_tcptls_server_stop ( struct ast_tcptls_session_args desc)

Shutdown a running server if there is one.

Version
1.6.1 changed desc parameter to be of ast_tcptls_session_args type

Definition at line 933 of file tcptls.c.

934{
935 if (desc->master != AST_PTHREADT_NULL) {
936 pthread_cancel(desc->master);
937 pthread_kill(desc->master, SIGURG);
938 pthread_join(desc->master, NULL);
939 desc->master = AST_PTHREADT_NULL;
940 }
941 if (desc->accept_fd != -1) {
942 close(desc->accept_fd);
943 }
944 desc->accept_fd = -1;
945
946 if (desc->old_tls_cfg) {
947 ast_free(desc->old_tls_cfg->certfile);
948 ast_free(desc->old_tls_cfg->pvtfile);
949 ast_free(desc->old_tls_cfg->cipher);
950 ast_free(desc->old_tls_cfg->cafile);
951 ast_free(desc->old_tls_cfg->capath);
952 ast_free(desc->old_tls_cfg);
953 desc->old_tls_cfg = NULL;
954 }
955
956 ast_debug(2, "Stopped server :: %s\n", desc->name);
957}

References ast_debug, ast_free, AST_PTHREADT_NULL, desc, and NULL.

Referenced by __ast_http_load(), __init_manager(), http_server_destroy(), manager_shutdown(), and unload_module().

◆ ast_tls_read_conf()

int ast_tls_read_conf ( struct ast_tls_config tls_cfg,
struct ast_tcptls_session_args tls_desc,
const char *  varname,
const char *  value 
)

Used to parse conf files containing tls/ssl options.

Definition at line 959 of file tcptls.c.

960{
961 if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) {
962 tls_cfg->enabled = ast_true(value) ? 1 : 0;
963 } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) {
964 ast_free(tls_cfg->certfile);
965 tls_cfg->certfile = ast_strdup(value);
966 } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) {
967 ast_free(tls_cfg->pvtfile);
968 tls_cfg->pvtfile = ast_strdup(value);
969 } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) {
970 ast_free(tls_cfg->cipher);
971 tls_cfg->cipher = ast_strdup(value);
972 } else if (!strcasecmp(varname, "tlscafile")) {
973 ast_free(tls_cfg->cafile);
974 tls_cfg->cafile = ast_strdup(value);
975 } else if (!strcasecmp(varname, "tlscapath") || !strcasecmp(varname, "tlscadir")) {
976 ast_free(tls_cfg->capath);
977 tls_cfg->capath = ast_strdup(value);
978 } else if (!strcasecmp(varname, "tlsverifyclient")) {
980 } else if (!strcasecmp(varname, "tlsdontverifyserver")) {
982 } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) {
984 ast_log(LOG_ERROR, "Invalid %s '%s'\n", varname, value);
985 } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) {
986 if (!strcasecmp(value, "tlsv1")) {
990 } else if (!strcasecmp(value, "sslv3")) {
994 } else if (!strcasecmp(value, "sslv2")) {
998 }
999 } else if (!strcasecmp(varname, "tlsservercipherorder")) {
1001 } else if (!strcasecmp(varname, "tlsdisablev1")) {
1003 } else if (!strcasecmp(varname, "tlsdisablev11")) {
1005 } else if (!strcasecmp(varname, "tlsdisablev12")) {
1007 } else {
1008 return -1;
1009 }
1010
1011 return 0;
1012}
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
Definition: main/config.c:4047
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
struct ast_sockaddr local_address
Definition: tcptls.h:131
int enabled
Definition: tcptls.h:89
char * certfile
Definition: tcptls.h:90
char * cipher
Definition: tcptls.h:92
char * pvtfile
Definition: tcptls.h:91
char * capath
Definition: tcptls.h:94
char * cafile
Definition: tcptls.h:93
struct ast_flags flags
Definition: tcptls.h:95
int value
Definition: syslog.c:37
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ast_clear_flag, ast_free, ast_log, ast_parse_arg(), ast_set2_flag, ast_set_flag, AST_SSL_DISABLE_TLSV1, AST_SSL_DISABLE_TLSV11, AST_SSL_DISABLE_TLSV12, AST_SSL_DONT_VERIFY_SERVER, AST_SSL_SERVER_CIPHER_ORDER, AST_SSL_SSLV2_CLIENT, AST_SSL_SSLV3_CLIENT, AST_SSL_TLSV1_CLIENT, AST_SSL_VERIFY_CLIENT, ast_strdup, ast_true(), ast_tls_config::cafile, ast_tls_config::capath, ast_tls_config::certfile, ast_tls_config::cipher, ast_tls_config::enabled, ast_tls_config::flags, ast_tcptls_session_args::local_address, LOG_ERROR, PARSE_ADDR, ast_tls_config::pvtfile, and value.

Referenced by __ast_http_load(), and __init_manager().