Asterisk - The Open Source Telephony Project  18.5.0
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)
 
struct ast_tcptls_session_instanceast_tcptls_client_start (struct ast_tcptls_session_instance *tcptls_session)
 attempts to connect and start tcptls session, on error the tcptls_session's ref count is decremented, fd and file are closed, and NULL is returned. 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 sip.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 62 of file tcptls.h.

Referenced by __ast_http_load(), manager_set_defaults(), and reload_config().

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 64 of file tcptls.h.

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

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 570 of file tcptls.c.

References __ssl_setup().

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

571 {
572  return __ssl_setup(cfg, 0);
573 }
static int __ssl_setup(struct ast_tls_config *cfg, int client)
Definition: tcptls.c:382

◆ 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 575 of file tcptls.c.

References NULL, and ast_tls_config::ssl_ctx.

Referenced by sip_tcptls_client_args_destructor(), unload_module(), and websocket_client_args_destroy().

576 {
577 #ifdef DO_SSL
578  if (cfg && cfg->ssl_ctx) {
579  SSL_CTX_free(cfg->ssl_ctx);
580  cfg->ssl_ctx = NULL;
581  }
582 #endif
583 }
#define NULL
Definition: resample.c:96
SSL_CTX * ssl_ctx
Definition: tcptls.h:95

◆ ast_tcptls_client_create()

struct ast_tcptls_session_instance* ast_tcptls_client_create ( struct ast_tcptls_session_args desc)

Definition at line 615 of file tcptls.c.

References ast_tcptls_session_args::accept_fd, ao2_alloc, ao2_cleanup, ast_bind(), ast_debug, ast_iostream_from_fd(), 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_str_create, ast_tcptls_session_instance::client, desc, errno, error(), ast_tcptls_session_args::local_address, LOG_ERROR, ast_tcptls_session_args::name, NULL, ast_tcptls_session_args::old_address, ast_tcptls_session_instance::overflow_buf, ast_tcptls_session_instance::parent, ast_tcptls_session_args::remote_address, 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(), sip_prepare_socket(), and websocket_client_connect().

616 {
617  int fd, x = 1;
618  struct ast_tcptls_session_instance *tcptls_session = NULL;
619 
620  /* Do nothing if nothing has changed */
621  if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) {
622  ast_debug(1, "Nothing changed in %s\n", desc->name);
623  return NULL;
624  }
625 
626  /* If we return early, there is no connection */
628 
629  fd = desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ?
630  AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
631  if (desc->accept_fd < 0) {
632  ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n",
633  desc->name, strerror(errno));
634  return NULL;
635  }
636 
637  /* if a local address was specified, bind to it so the connection will
638  originate from the desired address */
639  if (!ast_sockaddr_isnull(&desc->local_address) &&
641  setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
642  if (ast_bind(desc->accept_fd, &desc->local_address)) {
643  ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
644  desc->name,
646  strerror(errno));
647  goto error;
648  }
649  }
650 
651  tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor);
652  if (!tcptls_session) {
653  goto error;
654  }
655 
656  tcptls_session->overflow_buf = ast_str_create(128);
657  if (!tcptls_session->overflow_buf) {
658  goto error;
659  }
660  tcptls_session->client = 1;
661  tcptls_session->stream = ast_iostream_from_fd(&fd);
662  if (!tcptls_session->stream) {
663  goto error;
664  }
665 
666  /* From here on out, the iostream owns the accept_fd and it will take
667  * care of closing it when the iostream is closed */
668 
669  tcptls_session->parent = desc;
670  tcptls_session->parent->worker_fn = NULL;
671  ast_sockaddr_copy(&tcptls_session->remote_address,
672  &desc->remote_address);
673 
674  /* Set current info */
676  return tcptls_session;
677 
678 error:
679  close(desc->accept_fd);
680  desc->accept_fd = -1;
681  ao2_cleanup(tcptls_session);
682  return NULL;
683 }
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:171
struct ast_str * overflow_buf
Definition: tcptls.h:158
struct ast_tcptls_session_args * parent
Definition: tcptls.h:152
static const char desc[]
Definition: cdr_mysql.c:73
struct ast_iostream * ast_iostream_from_fd(int *fd)
Create an iostream from a file descriptor.
Definition: iostream.c:604
#define NULL
Definition: resample.c:96
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
Definition: netsock2.c:534
struct ast_sockaddr remote_address
Definition: tcptls.h:132
describes a server instance
Definition: tcptls.h:149
#define LOG_ERROR
Definition: logger.h:285
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void session_instance_destructor(void *obj)
Definition: tcptls.c:72
void *(* worker_fn)(void *)
Definition: tcptls.h:141
struct ast_sockaddr old_address
Definition: tcptls.h:131
const char * name
Definition: tcptls.h:142
struct ast_iostream * stream
Definition: tcptls.h:160
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int error(const char *format,...)
Definition: utils/frame.c:999
struct ast_sockaddr local_address
Definition: tcptls.h:130
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
struct ast_sockaddr remote_address
Definition: tcptls.h:151

◆ ast_tcptls_client_start()

struct ast_tcptls_session_instance* ast_tcptls_client_start ( struct ast_tcptls_session_instance tcptls_session)

attempts to connect and start tcptls session, on error the tcptls_session's ref count is decremented, fd and file are closed, and NULL is returned.

Definition at line 585 of file tcptls.c.

References __ssl_setup(), ast_tcptls_session_args::accept_fd, ao2_ref, ast_connect(), ast_fd_clear_flags, ast_log, ast_sockaddr_stringify(), desc, ast_tls_config::enabled, errno, handle_tcptls_connection(), LOG_ERROR, ast_tcptls_session_args::name, NULL, ast_tcptls_session_instance::parent, ast_tcptls_session_args::remote_address, and ast_tcptls_session_args::tls_cfg.

Referenced by _sip_tcp_helper_thread(), app_exec(), and websocket_client_connect().

586 {
588 
589  if (!(desc = tcptls_session->parent)) {
590  goto client_start_error;
591  }
592 
593  if (ast_connect(desc->accept_fd, &desc->remote_address)) {
594  ast_log(LOG_ERROR, "Unable to connect %s to %s: %s\n",
595  desc->name,
597  strerror(errno));
598  goto client_start_error;
599  }
600 
601  ast_fd_clear_flags(desc->accept_fd, O_NONBLOCK);
602 
603  if (desc->tls_cfg) {
604  desc->tls_cfg->enabled = 1;
605  __ssl_setup(desc->tls_cfg, 1);
606  }
607 
608  return handle_tcptls_connection(tcptls_session);
609 
610 client_start_error:
611  ao2_ref(tcptls_session, -1);
612  return NULL;
613 }
struct ast_tcptls_session_args * parent
Definition: tcptls.h:152
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
static const char desc[]
Definition: cdr_mysql.c:73
arguments for the accepting thread
Definition: tcptls.h:129
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
struct ast_sockaddr remote_address
Definition: tcptls.h:132
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int __ssl_setup(struct ast_tls_config *cfg, int client)
Definition: tcptls.c:382
#define LOG_ERROR
Definition: logger.h:285
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ast_fd_clear_flags(fd, flags)
Clear flags on the given file descriptor.
Definition: utils.h:1025
const char * name
Definition: tcptls.h:142
struct ast_tls_config * tls_cfg
Definition: tcptls.h:134
int ast_connect(int sockfd, const struct ast_sockaddr *addr)
Wrapper around connect(2) that uses struct ast_sockaddr.
Definition: netsock2.c:595
int enabled
Definition: tcptls.h:88

◆ 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 839 of file tcptls.c.

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

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

840 {
841  if (tcptls_session->stream) {
842  ast_iostream_close(tcptls_session->stream);
843  tcptls_session->stream = NULL;
844  } else {
845  ast_debug(1, "ast_tcptls_close_session_file invoked on session instance without file or file descriptor\n");
846  }
847 }
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int ast_iostream_close(struct ast_iostream *stream)
Close an iostream.
Definition: iostream.c:528
struct ast_iostream * stream
Definition: tcptls.h:160

◆ ast_tcptls_server_root()

void* ast_tcptls_server_root ( void *  )

Definition at line 280 of file tcptls.c.

References ast_tcptls_session_args::accept_fd, 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_args::periodic_fn, ast_tcptls_session_args::poll_timeout, ast_tcptls_session_instance::remote_address, session_instance_destructor(), and ast_tcptls_session_instance::stream.

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 */
342  if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, 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 }
void(* periodic_fn)(void *)
Definition: tcptls.h:140
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:171
struct ast_str * overflow_buf
Definition: tcptls.h:158
struct ast_tcptls_session_args * parent
Definition: tcptls.h:152
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
static const char desc[]
Definition: cdr_mysql.c:73
struct ast_iostream * ast_iostream_from_fd(int *fd)
Create an iostream from a file descriptor.
Definition: iostream.c:604
arguments for the accepting thread
Definition: tcptls.h:129
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:572
#define ast_log
Definition: astobj2.c:42
int ast_accept(int sockfd, struct ast_sockaddr *addr)
Wrapper around accept(2) that uses struct ast_sockaddr.
Definition: netsock2.c:584
#define ao2_ref(o, delta)
Definition: astobj2.h:464
describes a server instance
Definition: tcptls.h:149
#define LOG_ERROR
Definition: logger.h:285
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void session_instance_destructor(void *obj)
Definition: tcptls.c:72
#define ast_fd_clear_flags(fd, flags)
Clear flags on the given file descriptor.
Definition: utils.h:1025
struct ast_iostream * stream
Definition: tcptls.h:160
int ast_wait_for_input(int fd, int ms)
Definition: main/utils.c:1519
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
struct ast_sockaddr remote_address
Definition: tcptls.h:151

◆ 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 685 of file tcptls.c.

References ast_tcptls_session_args::accept_fd, ast_tcptls_session_args::accept_fn, 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, ast_tls_config::cafile, ast_tls_config::cahash, ast_tls_config::capath, ast_tls_config::certfile, ast_tls_config::certhash, ast_tls_config::cipher, errno, error(), ast_tls_config::flags, ast_tcptls_session_args::local_address, LOG_ERROR, ast_tcptls_session_args::master, ast_tcptls_session_args::name, NULL, ast_tcptls_session_args::old_address, ast_tcptls_session_args::old_tls_cfg, ast_tls_config::pvtfile, ast_tls_config::pvthash, str, and ast_tcptls_session_args::tls_cfg.

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

686 {
687  int x = 1;
688  int tls_changed = 0;
689  int sd_socket;
690 
691  if (desc->tls_cfg) {
692  char hash[41];
693  char *str = NULL;
694  struct stat st;
695 
696  /* Store the hashes of the TLS certificate etc. */
697  if (stat(desc->tls_cfg->certfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->certfile))) {
698  memset(hash, 0, 41);
699  } else {
700  ast_sha1_hash(hash, str);
701  }
702  ast_free(str);
703  str = NULL;
704  memcpy(desc->tls_cfg->certhash, hash, 41);
705  if (stat(desc->tls_cfg->pvtfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->pvtfile))) {
706  memset(hash, 0, 41);
707  } else {
708  ast_sha1_hash(hash, str);
709  }
710  ast_free(str);
711  str = NULL;
712  memcpy(desc->tls_cfg->pvthash, hash, 41);
713  if (stat(desc->tls_cfg->cafile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->cafile))) {
714  memset(hash, 0, 41);
715  } else {
716  ast_sha1_hash(hash, str);
717  }
718  ast_free(str);
719  str = NULL;
720  memcpy(desc->tls_cfg->cahash, hash, 41);
721 
722  /* Check whether TLS configuration has changed */
723  if (!desc->old_tls_cfg) { /* No previous configuration */
724  tls_changed = 1;
725  desc->old_tls_cfg = ast_calloc(1, sizeof(*desc->old_tls_cfg));
726  } else if (memcmp(desc->tls_cfg->certhash, desc->old_tls_cfg->certhash, 41)) {
727  tls_changed = 1;
728  } else if (memcmp(desc->tls_cfg->pvthash, desc->old_tls_cfg->pvthash, 41)) {
729  tls_changed = 1;
730  } else if (strcmp(desc->tls_cfg->cipher, desc->old_tls_cfg->cipher)) {
731  tls_changed = 1;
732  } else if (memcmp(desc->tls_cfg->cahash, desc->old_tls_cfg->cahash, 41)) {
733  tls_changed = 1;
734  } else if (strcmp(desc->tls_cfg->capath, desc->old_tls_cfg->capath)) {
735  tls_changed = 1;
736  } else if (memcmp(&desc->tls_cfg->flags, &desc->old_tls_cfg->flags, sizeof(desc->tls_cfg->flags))) {
737  tls_changed = 1;
738  }
739 
740  if (tls_changed) {
741  ast_debug(1, "Changed parameters for %s found\n", desc->name);
742  }
743  }
744 
745  /* Do nothing if nothing has changed */
746  if (!tls_changed && !ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
747  ast_debug(1, "Nothing changed in %s\n", desc->name);
748  return;
749  }
750 
751  /* If we return early, there is no one listening */
753 
754  /* Shutdown a running server if there is one */
755  if (desc->master != AST_PTHREADT_NULL) {
756  pthread_cancel(desc->master);
757  pthread_kill(desc->master, SIGURG);
758  pthread_join(desc->master, NULL);
759  }
760 
761  sd_socket = ast_sd_get_fd(SOCK_STREAM, &desc->local_address);
762 
763  if (sd_socket != -1) {
764  if (desc->accept_fd != sd_socket) {
765  if (desc->accept_fd != -1) {
766  close(desc->accept_fd);
767  }
768  desc->accept_fd = sd_socket;
769  }
770 
771  goto systemd_socket_activation;
772  }
773 
774  if (desc->accept_fd != -1) {
775  close(desc->accept_fd);
776  }
777 
778  /* If there's no new server, stop here */
779  if (ast_sockaddr_isnull(&desc->local_address)) {
780  ast_debug(2, "Server disabled: %s\n", desc->name);
781  return;
782  }
783 
785  AF_INET6 : AF_INET, SOCK_STREAM, 0);
786  if (desc->accept_fd < 0) {
787  ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
788  return;
789  }
790 
791  setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
792  if (ast_bind(desc->accept_fd, &desc->local_address)) {
793  ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
794  desc->name,
796  strerror(errno));
797  goto error;
798  }
799  if (listen(desc->accept_fd, 10)) {
800  ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name);
801  goto error;
802  }
803 
804 systemd_socket_activation:
805  if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
806  ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
807  desc->name,
809  strerror(errno));
810  goto error;
811  }
812 
813  /* Set current info */
815  if (desc->old_tls_cfg) {
816  ast_free(desc->old_tls_cfg->certfile);
817  ast_free(desc->old_tls_cfg->pvtfile);
818  ast_free(desc->old_tls_cfg->cipher);
819  ast_free(desc->old_tls_cfg->cafile);
820  ast_free(desc->old_tls_cfg->capath);
822  desc->old_tls_cfg->pvtfile = ast_strdup(desc->tls_cfg->pvtfile);
823  desc->old_tls_cfg->cipher = ast_strdup(desc->tls_cfg->cipher);
824  desc->old_tls_cfg->cafile = ast_strdup(desc->tls_cfg->cafile);
825  desc->old_tls_cfg->capath = ast_strdup(desc->tls_cfg->capath);
826  memcpy(desc->old_tls_cfg->certhash, desc->tls_cfg->certhash, 41);
827  memcpy(desc->old_tls_cfg->pvthash, desc->tls_cfg->pvthash, 41);
828  memcpy(desc->old_tls_cfg->cahash, desc->tls_cfg->cahash, 41);
829  memcpy(&desc->old_tls_cfg->flags, &desc->tls_cfg->flags, sizeof(desc->old_tls_cfg->flags));
830  }
831 
832  return;
833 
834 error:
835  close(desc->accept_fd);
836  desc->accept_fd = -1;
837 }
char * pvtfile
Definition: tcptls.h:90
char pvthash[41]
Definition: tcptls.h:97
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:171
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1043
char certhash[41]
Definition: tcptls.h:96
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
char * ast_read_textfile(const char *file)
Read a file into asterisk.
Definition: main/app.c:2792
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
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_PTHREADT_NULL
Definition: lock.h:66
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
Definition: main/utils.c:264
#define LOG_ERROR
Definition: logger.h:285
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
char * cafile
Definition: tcptls.h:92
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_sockaddr old_address
Definition: tcptls.h:131
struct ast_tls_config * old_tls_cfg
Definition: tcptls.h:143
char * certfile
Definition: tcptls.h:89
const char * name
Definition: tcptls.h:142
char cahash[41]
Definition: tcptls.h:98
struct ast_flags flags
Definition: tcptls.h:94
int error(const char *format,...)
Definition: utils/frame.c:999
char * capath
Definition: tcptls.h:93
struct ast_tls_config * tls_cfg
Definition: tcptls.h:134
struct ast_sockaddr local_address
Definition: tcptls.h:130
char * cipher
Definition: tcptls.h:91
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
void *(* accept_fn)(void *)
Definition: tcptls.h:139

◆ 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 849 of file tcptls.c.

References ast_tcptls_session_args::accept_fd, ast_debug, ast_free, AST_PTHREADT_NULL, ast_tls_config::cafile, ast_tls_config::capath, ast_tls_config::certfile, ast_tls_config::cipher, ast_tcptls_session_args::master, ast_tcptls_session_args::name, NULL, ast_tcptls_session_args::old_tls_cfg, and ast_tls_config::pvtfile.

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

850 {
851  if (desc->master != AST_PTHREADT_NULL) {
852  pthread_cancel(desc->master);
853  pthread_kill(desc->master, SIGURG);
854  pthread_join(desc->master, NULL);
855  desc->master = AST_PTHREADT_NULL;
856  }
857  if (desc->accept_fd != -1) {
858  close(desc->accept_fd);
859  }
860  desc->accept_fd = -1;
861 
862  if (desc->old_tls_cfg) {
863  ast_free(desc->old_tls_cfg->certfile);
864  ast_free(desc->old_tls_cfg->pvtfile);
865  ast_free(desc->old_tls_cfg->cipher);
866  ast_free(desc->old_tls_cfg->cafile);
867  ast_free(desc->old_tls_cfg->capath);
868  ast_free(desc->old_tls_cfg);
869  desc->old_tls_cfg = NULL;
870  }
871 
872  ast_debug(2, "Stopped server :: %s\n", desc->name);
873 }
char * pvtfile
Definition: tcptls.h:90
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_PTHREADT_NULL
Definition: lock.h:66
char * cafile
Definition: tcptls.h:92
#define ast_free(a)
Definition: astmm.h:182
struct ast_tls_config * old_tls_cfg
Definition: tcptls.h:143
char * certfile
Definition: tcptls.h:89
const char * name
Definition: tcptls.h:142
char * capath
Definition: tcptls.h:93
char * cipher
Definition: tcptls.h:91

◆ 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 875 of file tcptls.c.

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, and ast_tls_config::pvtfile.

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

876 {
877  if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) {
878  tls_cfg->enabled = ast_true(value) ? 1 : 0;
879  } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) {
880  ast_free(tls_cfg->certfile);
881  tls_cfg->certfile = ast_strdup(value);
882  } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) {
883  ast_free(tls_cfg->pvtfile);
884  tls_cfg->pvtfile = ast_strdup(value);
885  } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) {
886  ast_free(tls_cfg->cipher);
887  tls_cfg->cipher = ast_strdup(value);
888  } else if (!strcasecmp(varname, "tlscafile")) {
889  ast_free(tls_cfg->cafile);
890  tls_cfg->cafile = ast_strdup(value);
891  } else if (!strcasecmp(varname, "tlscapath") || !strcasecmp(varname, "tlscadir")) {
892  ast_free(tls_cfg->capath);
893  tls_cfg->capath = ast_strdup(value);
894  } else if (!strcasecmp(varname, "tlsverifyclient")) {
896  } else if (!strcasecmp(varname, "tlsdontverifyserver")) {
898  } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) {
899  if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address))
900  ast_log(LOG_ERROR, "Invalid %s '%s'\n", varname, value);
901  } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) {
902  if (!strcasecmp(value, "tlsv1")) {
906  } else if (!strcasecmp(value, "sslv3")) {
910  } else if (!strcasecmp(value, "sslv2")) {
914  }
915  } else if (!strcasecmp(varname, "tlsservercipherorder")) {
917  } else if (!strcasecmp(varname, "tlsdisablev1")) {
919  } else if (!strcasecmp(varname, "tlsdisablev11")) {
921  } else if (!strcasecmp(varname, "tlsdisablev12")) {
923  } else {
924  return -1;
925  }
926 
927  return 0;
928 }
char * pvtfile
Definition: tcptls.h:90
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
char * cafile
Definition: tcptls.h:92
#define ast_free(a)
Definition: astmm.h:182
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *result,...)
The argument parsing routine.
Definition: main/config.c:3657
char * certfile
Definition: tcptls.h:89
#define ast_clear_flag(p, flag)
Definition: utils.h:77
struct ast_flags flags
Definition: tcptls.h:94
char * capath
Definition: tcptls.h:93
struct ast_sockaddr local_address
Definition: tcptls.h:130
char * cipher
Definition: tcptls.h:91
int enabled
Definition: tcptls.h:88