Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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 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 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 */
69  AST_SSL_DONT_VERIFY_SERVER = (1 << 1),
70  /*! Don't compare "Common Name" against IP or hostname */
71  AST_SSL_IGNORE_COMMON_NAME = (1 << 2),
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 */
79  AST_SSL_SERVER_CIPHER_ORDER = (1 << 6),
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 570 of file tcptls.c.

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

References __ssl_setup().

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

◆ 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.

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:96

References NULL, and ast_tls_config::ssl_ctx.

Referenced by sip_tcptls_client_args_destructor(), and 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 678 of file tcptls.c.

679 {
680  int fd, x = 1;
681  struct ast_tcptls_session_instance *tcptls_session = NULL;
682 
683  /* Do nothing if nothing has changed */
684  if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) {
685  ast_debug(1, "Nothing changed in %s\n", desc->name);
686  return NULL;
687  }
688 
689  /* If we return early, there is no connection */
690  ast_sockaddr_setnull(&desc->old_address);
691 
692  fd = desc->accept_fd = ast_socket_nonblock(ast_sockaddr_is_ipv6(&desc->remote_address) ?
693  AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
694  if (desc->accept_fd < 0) {
695  ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n",
696  desc->name, strerror(errno));
697  return NULL;
698  }
699 
700  /* if a local address was specified, bind to it so the connection will
701  originate from the desired address */
702  if (!ast_sockaddr_isnull(&desc->local_address) &&
703  !ast_sockaddr_is_any(&desc->local_address)) {
704  setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
705  if (ast_bind(desc->accept_fd, &desc->local_address)) {
706  ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
707  desc->name,
708  ast_sockaddr_stringify(&desc->local_address),
709  strerror(errno));
710  goto error;
711  }
712  }
713 
714  tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor);
715  if (!tcptls_session) {
716  goto error;
717  }
718 
719  tcptls_session->overflow_buf = ast_str_create(128);
720  if (!tcptls_session->overflow_buf) {
721  goto error;
722  }
723  tcptls_session->client = 1;
724  tcptls_session->stream = ast_iostream_from_fd(&fd);
725  if (!tcptls_session->stream) {
726  goto error;
727  }
728 
729  /* From here on out, the iostream owns the accept_fd and it will take
730  * care of closing it when the iostream is closed */
731 
732  tcptls_session->parent = desc;
733  tcptls_session->parent->worker_fn = NULL;
734  ast_sockaddr_copy(&tcptls_session->remote_address,
735  &desc->remote_address);
736 
737  /* Set current info */
738  ast_sockaddr_copy(&desc->old_address, &desc->remote_address);
739 
740  return tcptls_session;
741 
742 error:
743  close(desc->accept_fd);
744  desc->accept_fd = -1;
745  ao2_cleanup(tcptls_session);
746  return NULL;
747 }
#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
struct ast_iostream * ast_iostream_from_fd(int *fd)
Create an iostream from a file descriptor.
Definition: iostream.c:604
int errno
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
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
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
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
void *(* worker_fn)(void *)
Definition: tcptls.h:142
describes a server instance
Definition: tcptls.h:150
struct ast_iostream * stream
Definition: tcptls.h:161
struct ast_sockaddr remote_address
Definition: tcptls.h:152
struct ast_tcptls_session_args * parent
Definition: tcptls.h:153
struct ast_str * overflow_buf
Definition: tcptls.h:159
static void session_instance_destructor(void *obj)
Definition: tcptls.c:72
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1068

References 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_socket_nonblock, ast_str_create, ast_tcptls_session_instance::client, desc, errno, error(), LOG_ERROR, 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 sip_prepare_socket().

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

674 {
675  return ast_tcptls_client_start_timeout(tcptls_session, -1);
676 }
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:645

References ast_tcptls_client_start_timeout().

Referenced by _sip_tcp_helper_thread(), and 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 645 of file tcptls.c.

647 {
649 
650  if (!(desc = tcptls_session->parent)) {
651  ao2_ref(tcptls_session, -1);
652  return NULL;
653  }
654 
655  if (socket_connect(desc->accept_fd, &desc->remote_address, timeout)) {
656  ast_log(LOG_WARNING, "Unable to connect %s to %s: %s\n", desc->name,
657  ast_sockaddr_stringify(&desc->remote_address), strerror(errno));
658 
659  ao2_ref(tcptls_session, -1);
660  return NULL;
661  }
662 
663  ast_fd_clear_flags(desc->accept_fd, O_NONBLOCK);
664 
665  if (desc->tls_cfg) {
666  desc->tls_cfg->enabled = 1;
667  __ssl_setup(desc->tls_cfg, 1);
668  }
669 
670  return handle_tcptls_connection(tcptls_session);
671 }
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define LOG_WARNING
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:601
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:1050

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().

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

904 {
905  if (tcptls_session->stream) {
906  ast_iostream_close(tcptls_session->stream);
907  tcptls_session->stream = NULL;
908  } else {
909  ast_debug(1, "ast_tcptls_close_session_file invoked on session instance without file or file descriptor\n");
910  }
911 }
int ast_iostream_close(struct ast_iostream *stream)
Close an iostream.
Definition: iostream.c:528

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().

◆ 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 */
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 }
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: main/utils.c:1665
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:592

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

750 {
751  int x = 1;
752  int tls_changed = 0;
753  int sd_socket;
754 
755  if (desc->tls_cfg) {
756  char hash[41];
757  char *str = NULL;
758  struct stat st;
759 
760  /* Store the hashes of the TLS certificate etc. */
761  if (stat(desc->tls_cfg->certfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->certfile))) {
762  memset(hash, 0, 41);
763  } else {
764  ast_sha1_hash(hash, str);
765  }
766  ast_free(str);
767  str = NULL;
768  memcpy(desc->tls_cfg->certhash, hash, 41);
769  if (stat(desc->tls_cfg->pvtfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->pvtfile))) {
770  memset(hash, 0, 41);
771  } else {
772  ast_sha1_hash(hash, str);
773  }
774  ast_free(str);
775  str = NULL;
776  memcpy(desc->tls_cfg->pvthash, hash, 41);
777  if (stat(desc->tls_cfg->cafile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->cafile))) {
778  memset(hash, 0, 41);
779  } else {
780  ast_sha1_hash(hash, str);
781  }
782  ast_free(str);
783  str = NULL;
784  memcpy(desc->tls_cfg->cahash, hash, 41);
785 
786  /* Check whether TLS configuration has changed */
787  if (!desc->old_tls_cfg) { /* No previous configuration */
788  tls_changed = 1;
789  desc->old_tls_cfg = ast_calloc(1, sizeof(*desc->old_tls_cfg));
790  } else if (memcmp(desc->tls_cfg->certhash, desc->old_tls_cfg->certhash, 41)) {
791  tls_changed = 1;
792  } else if (memcmp(desc->tls_cfg->pvthash, desc->old_tls_cfg->pvthash, 41)) {
793  tls_changed = 1;
794  } else if (strcmp(desc->tls_cfg->cipher, desc->old_tls_cfg->cipher)) {
795  tls_changed = 1;
796  } else if (memcmp(desc->tls_cfg->cahash, desc->old_tls_cfg->cahash, 41)) {
797  tls_changed = 1;
798  } else if (strcmp(desc->tls_cfg->capath, desc->old_tls_cfg->capath)) {
799  tls_changed = 1;
800  } else if (memcmp(&desc->tls_cfg->flags, &desc->old_tls_cfg->flags, sizeof(desc->tls_cfg->flags))) {
801  tls_changed = 1;
802  }
803 
804  if (tls_changed) {
805  ast_debug(1, "Changed parameters for %s found\n", desc->name);
806  }
807  }
808 
809  /* Do nothing if nothing has changed */
810  if (!tls_changed && !ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
811  ast_debug(1, "Nothing changed in %s\n", desc->name);
812  return;
813  }
814 
815  /* If we return early, there is no one listening */
816  ast_sockaddr_setnull(&desc->old_address);
817 
818  /* Shutdown a running server if there is one */
819  if (desc->master != AST_PTHREADT_NULL) {
820  pthread_cancel(desc->master);
821  pthread_kill(desc->master, SIGURG);
822  pthread_join(desc->master, NULL);
823  }
824 
825  sd_socket = ast_sd_get_fd(SOCK_STREAM, &desc->local_address);
826 
827  if (sd_socket != -1) {
828  if (desc->accept_fd != sd_socket) {
829  if (desc->accept_fd != -1) {
830  close(desc->accept_fd);
831  }
832  desc->accept_fd = sd_socket;
833  }
834 
835  goto systemd_socket_activation;
836  }
837 
838  if (desc->accept_fd != -1) {
839  close(desc->accept_fd);
840  }
841 
842  /* If there's no new server, stop here */
843  if (ast_sockaddr_isnull(&desc->local_address)) {
844  ast_debug(2, "Server disabled: %s\n", desc->name);
845  return;
846  }
847 
848  desc->accept_fd = ast_socket_nonblock(ast_sockaddr_is_ipv6(&desc->local_address) ?
849  AF_INET6 : AF_INET, SOCK_STREAM, 0);
850  if (desc->accept_fd < 0) {
851  ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
852  return;
853  }
854 
855  setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
856  if (ast_bind(desc->accept_fd, &desc->local_address)) {
857  ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
858  desc->name,
859  ast_sockaddr_stringify(&desc->local_address),
860  strerror(errno));
861  goto error;
862  }
863  if (listen(desc->accept_fd, 10)) {
864  ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name);
865  goto error;
866  }
867 
868 systemd_socket_activation:
869  if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
870  ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
871  desc->name,
872  ast_sockaddr_stringify(&desc->local_address),
873  strerror(errno));
874  goto error;
875  }
876 
877  /* Set current info */
878  ast_sockaddr_copy(&desc->old_address, &desc->local_address);
879  if (desc->old_tls_cfg) {
880  ast_free(desc->old_tls_cfg->certfile);
881  ast_free(desc->old_tls_cfg->pvtfile);
882  ast_free(desc->old_tls_cfg->cipher);
883  ast_free(desc->old_tls_cfg->cafile);
884  ast_free(desc->old_tls_cfg->capath);
885  desc->old_tls_cfg->certfile = ast_strdup(desc->tls_cfg->certfile);
886  desc->old_tls_cfg->pvtfile = ast_strdup(desc->tls_cfg->pvtfile);
887  desc->old_tls_cfg->cipher = ast_strdup(desc->tls_cfg->cipher);
888  desc->old_tls_cfg->cafile = ast_strdup(desc->tls_cfg->cafile);
889  desc->old_tls_cfg->capath = ast_strdup(desc->tls_cfg->capath);
890  memcpy(desc->old_tls_cfg->certhash, desc->tls_cfg->certhash, 41);
891  memcpy(desc->old_tls_cfg->pvthash, desc->tls_cfg->pvthash, 41);
892  memcpy(desc->old_tls_cfg->cahash, desc->tls_cfg->cahash, 41);
893  memcpy(&desc->old_tls_cfg->flags, &desc->tls_cfg->flags, sizeof(desc->old_tls_cfg->flags));
894  }
895 
896  return;
897 
898 error:
899  close(desc->accept_fd);
900  desc->accept_fd = -1;
901 }
const char * str
Definition: app_jack.c:147
#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:3009
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:66
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:587
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
Definition: main/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(), http_server_start(), and reload_config().

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

914 {
915  if (desc->master != AST_PTHREADT_NULL) {
916  pthread_cancel(desc->master);
917  pthread_kill(desc->master, SIGURG);
918  pthread_join(desc->master, NULL);
919  desc->master = AST_PTHREADT_NULL;
920  }
921  if (desc->accept_fd != -1) {
922  close(desc->accept_fd);
923  }
924  desc->accept_fd = -1;
925 
926  if (desc->old_tls_cfg) {
927  ast_free(desc->old_tls_cfg->certfile);
928  ast_free(desc->old_tls_cfg->pvtfile);
929  ast_free(desc->old_tls_cfg->cipher);
930  ast_free(desc->old_tls_cfg->cafile);
931  ast_free(desc->old_tls_cfg->capath);
932  ast_free(desc->old_tls_cfg);
933  desc->old_tls_cfg = NULL;
934  }
935 
936  ast_debug(2, "Stopped server :: %s\n", desc->name);
937 }

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

940 {
941  if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) {
942  tls_cfg->enabled = ast_true(value) ? 1 : 0;
943  } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) {
944  ast_free(tls_cfg->certfile);
945  tls_cfg->certfile = ast_strdup(value);
946  } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) {
947  ast_free(tls_cfg->pvtfile);
948  tls_cfg->pvtfile = ast_strdup(value);
949  } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) {
950  ast_free(tls_cfg->cipher);
951  tls_cfg->cipher = ast_strdup(value);
952  } else if (!strcasecmp(varname, "tlscafile")) {
953  ast_free(tls_cfg->cafile);
954  tls_cfg->cafile = ast_strdup(value);
955  } else if (!strcasecmp(varname, "tlscapath") || !strcasecmp(varname, "tlscadir")) {
956  ast_free(tls_cfg->capath);
957  tls_cfg->capath = ast_strdup(value);
958  } else if (!strcasecmp(varname, "tlsverifyclient")) {
960  } else if (!strcasecmp(varname, "tlsdontverifyserver")) {
962  } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) {
963  if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address))
964  ast_log(LOG_ERROR, "Invalid %s '%s'\n", varname, value);
965  } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) {
966  if (!strcasecmp(value, "tlsv1")) {
970  } else if (!strcasecmp(value, "sslv3")) {
974  } else if (!strcasecmp(value, "sslv2")) {
978  }
979  } else if (!strcasecmp(varname, "tlsservercipherorder")) {
981  } else if (!strcasecmp(varname, "tlsdisablev1")) {
983  } else if (!strcasecmp(varname, "tlsdisablev11")) {
985  } else if (!strcasecmp(varname, "tlsdisablev12")) {
987  } else {
988  return -1;
989  }
990 
991  return 0;
992 }
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
Definition: main/config.c:3726
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: main/utils.c:2097
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(), __init_manager(), and reload_config().