2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2007 - 2008, Digium, Inc.
6 * Luigi Rizzo (TCP and TLS server code)
7 * Brett Bryant <brettbryant@gmail.com> (updated for client support)
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
22 * \brief Code to support TCP and TLS server/client
25 * \author Brett Bryant <brettbryant@gmail.com>
30 #include "asterisk/tcptls.h" /* for ast_tls_config, ast_tcptls_se... */
31 #include "asterisk/iostream.h" /* for DO_SSL, ast_iostream_close, a... */
34 #include <fcntl.h> /* for O_NONBLOCK */
35 #endif /* HAVE_FCNTL_H */
36 #include <netinet/in.h> /* for IPPROTO_TCP */
38 #include <openssl/asn1.h> /* for ASN1_STRING_to_UTF8 */
39 #include <openssl/crypto.h> /* for OPENSSL_free */
40 #include <openssl/opensslconf.h> /* for OPENSSL_NO_SSL3_METHOD, OPENS... */
41 #include <openssl/opensslv.h> /* for OPENSSL_VERSION_NUMBER */
42 #include <openssl/safestack.h> /* for STACK_OF */
43 #include <openssl/ssl.h> /* for SSL_CTX_free, SSL_get_error, ... */
44 #include <openssl/x509.h> /* for X509_free, X509_NAME_ENTRY_ge... */
45 #include <openssl/x509v3.h> /* for GENERAL_NAME, sk_GENERAL_NAME... */
47 #include <openssl/bio.h> /* for BIO_free, BIO_new_file */
48 #include <openssl/dh.h> /* for DH_free */
49 #include <openssl/pem.h> /* for PEM_read_bio_DHparams */
50 #endif /* OPENSSL_NO_DH */
52 #include <openssl/ec.h> /* for EC_KEY_free, EC_KEY_new_by_cu... */
53 #endif /* OPENSSL_NO_EC */
55 #include <pthread.h> /* for pthread_cancel, pthread_join */
56 #include <signal.h> /* for pthread_kill, SIGURG */
57 #include <sys/socket.h> /* for setsockopt, shutdown, socket */
58 #include <sys/stat.h> /* for stat */
60 #include "asterisk/app.h" /* for ast_read_textfile */
61 #include "asterisk/astobj2.h" /* for ao2_ref, ao2_t_ref, ao2_alloc */
62 #include "asterisk/compat.h" /* for strcasecmp */
63 #include "asterisk/config.h" /* for ast_parse_arg, ast_parse_flag... */
64 #include "asterisk/io.h" /* for ast_sd_get_fd */
65 #include "asterisk/lock.h" /* for AST_PTHREADT_NULL */
66 #include "asterisk/logger.h" /* for ast_log, LOG_ERROR, ast_debug */
67 #include "asterisk/netsock2.h" /* for ast_sockaddr_copy, ast_sockad... */
68 #include "asterisk/pbx.h" /* for ast_thread_inhibit_escalations */
69 #include "asterisk/utils.h" /* for ast_true, ast_free, ast_wait_... */
71 static void session_instance_destructor(void *obj)
73 struct ast_tcptls_session_instance *i = obj;
76 ast_iostream_close(i->stream);
79 ast_free(i->overflow_buf);
80 ao2_cleanup(i->private_data);
84 static int check_tcptls_cert_name(ASN1_STRING *cert_str, const char *hostname, const char *desc)
89 ret = ASN1_STRING_to_UTF8(&str, cert_str);
90 if (ret < 0 || !str) {
94 if (strlen((char *) str) != ret) {
95 ast_log(LOG_WARNING, "Invalid certificate %s length (contains NULL bytes?)\n", desc);
98 } else if (!strcasecmp(hostname, (char *) str)) {
104 ast_debug(3, "SSL %s compare s1='%s' s2='%s'\n", desc, hostname, str);
112 * creates a FILE * from the fd passed by the accept thread.
113 * This operation is potentially expensive (certificate verification),
114 * so we do it in the child thread context.
116 * \note must decrement ref count before returning NULL on error
118 static void *handle_tcptls_connection(void *data)
120 struct ast_tcptls_session_instance *tcptls_session = data;
125 /* TCP/TLS connections are associated with external protocols, and
126 * should not be allowed to execute 'dangerous' functions. This may
127 * need to be pushed down into the individual protocol handlers, but
128 * this seems like a good general policy.
130 if (ast_thread_inhibit_escalations()) {
131 ast_log(LOG_ERROR, "Failed to inhibit privilege escalations; killing connection\n");
132 ast_tcptls_close_session_file(tcptls_session);
133 ao2_ref(tcptls_session, -1);
137 if (tcptls_session->parent->tls_cfg) {
139 if (ast_iostream_start_tls(&tcptls_session->stream, tcptls_session->parent->tls_cfg->ssl_ctx, tcptls_session->client) < 0) {
140 ast_tcptls_close_session_file(tcptls_session);
141 ao2_ref(tcptls_session, -1);
145 ssl = ast_iostream_get_ssl(tcptls_session->stream);
146 if ((tcptls_session->client && !ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_DONT_VERIFY_SERVER))
147 || (!tcptls_session->client && ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_VERIFY_CLIENT))) {
150 peer = SSL_get_peer_certificate(ssl);
152 ast_log(LOG_ERROR, "No peer SSL certificate to verify\n");
153 ast_tcptls_close_session_file(tcptls_session);
154 ao2_ref(tcptls_session, -1);
158 res = SSL_get_verify_result(ssl);
159 if (res != X509_V_OK) {
160 ast_log(LOG_ERROR, "Certificate did not verify: %s\n", X509_verify_cert_error_string(res));
162 ast_tcptls_close_session_file(tcptls_session);
163 ao2_ref(tcptls_session, -1);
166 if (!ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_IGNORE_COMMON_NAME)) {
168 X509_NAME *name = X509_get_subject_name(peer);
169 STACK_OF(GENERAL_NAME) *alt_names;
174 /* Walk the certificate to check all available "Common Name" */
175 /* XXX Probably should do a gethostbyname on the hostname and compare that as well */
176 pos = X509_NAME_get_index_by_NID(name, NID_commonName, pos);
180 str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, pos));
181 if (!check_tcptls_cert_name(str, tcptls_session->parent->hostname, "common name")) {
188 alt_names = X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL);
189 if (alt_names != NULL) {
190 int alt_names_count = sk_GENERAL_NAME_num(alt_names);
192 for (pos = 0; pos < alt_names_count; pos++) {
193 const GENERAL_NAME *alt_name = sk_GENERAL_NAME_value(alt_names, pos);
195 if (alt_name->type != GEN_DNS) {
199 if (!check_tcptls_cert_name(alt_name->d.dNSName, tcptls_session->parent->hostname, "alt name")) {
205 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
210 ast_log(LOG_ERROR, "Certificate common name did not match (%s)\n", tcptls_session->parent->hostname);
212 ast_tcptls_close_session_file(tcptls_session);
213 ao2_ref(tcptls_session, -1);
220 ast_log(LOG_ERROR, "Attempted a TLS connection without OpenSSL support. This will not work!\n");
221 ast_tcptls_close_session_file(tcptls_session);
222 ao2_ref(tcptls_session, -1);
227 if (tcptls_session->parent->worker_fn) {
228 return tcptls_session->parent->worker_fn(tcptls_session);
230 return tcptls_session;
234 void *ast_tcptls_server_root(void *data)
236 struct ast_tcptls_session_args *desc = data;
238 struct ast_sockaddr addr;
239 struct ast_tcptls_session_instance *tcptls_session;
245 if (desc->periodic_fn) {
246 desc->periodic_fn(desc);
248 i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout);
250 /* Prevent tight loop from hogging CPU */
254 fd = ast_accept(desc->accept_fd, &addr);
257 && errno != EWOULDBLOCK
259 && errno != ECONNABORTED) {
260 ast_log(LOG_ERROR, "TCP/TLS accept failed: %s\n", strerror(errno));
261 if (errno != EMFILE) {
265 /* Prevent tight loop from hogging CPU */
269 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor);
270 if (!tcptls_session) {
275 tcptls_session->overflow_buf = ast_str_create(128);
276 if (!tcptls_session->overflow_buf) {
277 ao2_ref(tcptls_session, -1);
281 ast_fd_clear_flags(fd, O_NONBLOCK);
283 tcptls_session->stream = ast_iostream_from_fd(&fd);
284 if (!tcptls_session->stream) {
285 ao2_ref(tcptls_session, -1);
290 tcptls_session->parent = desc;
291 ast_sockaddr_copy(&tcptls_session->remote_address, &addr);
293 tcptls_session->client = 0;
295 /* This thread is now the only place that controls the single ref to tcptls_session */
296 if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, tcptls_session)) {
297 ast_log(LOG_ERROR, "TCP/TLS unable to launch helper thread: %s\n",
299 ao2_ref(tcptls_session, -1);
303 ast_log(LOG_ERROR, "TCP/TLS listener thread ended abnormally\n");
305 /* Close the listener socket so Asterisk doesn't appear dead. */
306 fd = desc->accept_fd;
307 desc->accept_fd = -1;
315 static void __ssl_setup_certs(struct ast_tls_config *cfg, const size_t cert_file_len, const char *key_type_extension, const char *key_type)
317 char *cert_file = ast_strdupa(cfg->certfile);
319 memcpy(cert_file + cert_file_len - 8, key_type_extension, 5);
320 if (access(cert_file, F_OK) == 0) {
321 if (SSL_CTX_use_certificate_chain_file(cfg->ssl_ctx, cert_file) == 0) {
322 ast_log(LOG_WARNING, "TLS/SSL error loading public %s key (certificate) from <%s>.\n", key_type, cert_file);
323 } else if (SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, cert_file, SSL_FILETYPE_PEM) == 0) {
324 ast_log(LOG_WARNING, "TLS/SSL error loading private %s key from <%s>.\n", key_type, cert_file);
325 } else if (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0) {
326 ast_log(LOG_WARNING, "TLS/SSL error matching private %s key and certificate in <%s>.\n", key_type, cert_file);
332 static int __ssl_setup(struct ast_tls_config *cfg, int client)
336 ast_log(LOG_NOTICE, "Configured without OpenSSL Development Headers");
348 /* Get rid of an old SSL_CTX since we're about to
352 SSL_CTX_free(cfg->ssl_ctx);
357 #if !defined(OPENSSL_NO_SSL2) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
358 if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) {
359 ast_log(LOG_WARNING, "Usage of SSLv2 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n");
360 cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method());
363 #if !defined(OPENSSL_NO_SSL3_METHOD) && !(defined(OPENSSL_API_COMPAT) && (OPENSSL_API_COMPAT >= 0x10100000L))
364 if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) {
365 ast_log(LOG_WARNING, "Usage of SSLv3 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n");
366 cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
369 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
370 cfg->ssl_ctx = SSL_CTX_new(TLS_client_method());
372 if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) {
373 cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
376 cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
381 cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
385 ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n");
390 /* Due to the POODLE vulnerability, completely disable
391 * SSLv2 and SSLv3 if we are not explicitly told to use
392 * them. SSLv23_*_method supports TLSv1+.
395 ssl_opts |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
398 if (ast_test_flag(&cfg->flags, AST_SSL_SERVER_CIPHER_ORDER)) {
399 ssl_opts |= SSL_OP_CIPHER_SERVER_PREFERENCE;
402 if (ast_test_flag(&cfg->flags, AST_SSL_DISABLE_TLSV1)) {
403 ssl_opts |= SSL_OP_NO_TLSv1;
405 #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2)
406 if (ast_test_flag(&cfg->flags, AST_SSL_DISABLE_TLSV11)) {
407 ssl_opts |= SSL_OP_NO_TLSv1_1;
409 if (ast_test_flag(&cfg->flags, AST_SSL_DISABLE_TLSV12)) {
410 ssl_opts |= SSL_OP_NO_TLSv1_2;
413 ast_log(LOG_WARNING, "Your version of OpenSSL leaves you potentially vulnerable "
414 "to the SSL BEAST attack. Please upgrade to OpenSSL 1.0.1 or later\n");
417 SSL_CTX_set_options(cfg->ssl_ctx, ssl_opts);
419 SSL_CTX_set_verify(cfg->ssl_ctx,
420 ast_test_flag(&cfg->flags, AST_SSL_VERIFY_CLIENT) ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE,
423 if (!ast_strlen_zero(cfg->certfile)) {
424 char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile;
425 if (SSL_CTX_use_certificate_chain_file(cfg->ssl_ctx, cfg->certfile) == 0) {
427 /* Clients don't need a certificate, but if its setup we can use it */
428 ast_log(LOG_ERROR, "TLS/SSL error loading cert file. <%s>\n", cfg->certfile);
430 SSL_CTX_free(cfg->ssl_ctx);
435 if ((SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, tmpprivate, SSL_FILETYPE_PEM) == 0) || (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 )) {
437 /* Clients don't need a private key, but if its setup we can use it */
438 ast_log(LOG_ERROR, "TLS/SSL error loading private key file. <%s>\n", tmpprivate);
440 SSL_CTX_free(cfg->ssl_ctx);
446 size_t certfile_len = strlen(cfg->certfile);
448 /* expects a file name which contains _rsa. like asterisk_rsa.pem
449 * ignores any 3-character file-extension like .pem, .cer, .crt
451 if (certfile_len >= 8 && !strncmp(cfg->certfile + certfile_len - 8, "_rsa.", 5)) {
452 __ssl_setup_certs(cfg, certfile_len, "_ecc.", "ECC");
453 __ssl_setup_certs(cfg, certfile_len, "_dsa.", "DSA");
457 if (!ast_strlen_zero(cfg->cipher)) {
458 if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) {
460 ast_log(LOG_ERROR, "TLS/SSL cipher error <%s>\n", cfg->cipher);
462 SSL_CTX_free(cfg->ssl_ctx);
468 if (!ast_strlen_zero(cfg->cafile) || !ast_strlen_zero(cfg->capath)) {
469 if (SSL_CTX_load_verify_locations(cfg->ssl_ctx, S_OR(cfg->cafile, NULL), S_OR(cfg->capath,NULL)) == 0) {
470 ast_log(LOG_ERROR, "TLS/SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath);
474 #ifdef HAVE_OPENSSL_EC
476 if (!ast_strlen_zero(cfg->pvtfile)) {
477 BIO *bio = BIO_new_file(cfg->pvtfile, "r");
479 DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
481 if (SSL_CTX_set_tmp_dh(cfg->ssl_ctx, dh)) {
482 long options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE;
483 options = SSL_CTX_set_options(cfg->ssl_ctx, options);
484 ast_verb(2, "TLS/SSL DH initialized, PFS cipher-suites enabled\n");
491 #ifndef SSL_CTRL_SET_ECDH_AUTO
492 #define SSL_CTRL_SET_ECDH_AUTO 94
494 /* SSL_CTX_set_ecdh_auto(cfg->ssl_ctx, on); requires OpenSSL 1.0.2 which wraps: */
495 if (SSL_CTX_ctrl(cfg->ssl_ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL)) {
496 ast_verb(2, "TLS/SSL ECDH initialized (automatic), faster PFS ciphers enabled\n");
498 /* enables AES-128 ciphers, to get AES-256 use NID_secp384r1 */
499 EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
501 if (SSL_CTX_set_tmp_ecdh(cfg->ssl_ctx, ecdh)) {
502 ast_verb(2, "TLS/SSL ECDH initialized (secp256r1), faster PFS cipher-suites enabled\n");
508 #endif /* #ifdef HAVE_OPENSSL_EC */
510 ast_verb(2, "TLS/SSL certificate ok\n"); /* We should log which one that is ok. This message doesn't really make sense in production use */
515 int ast_ssl_setup(struct ast_tls_config *cfg)
517 return __ssl_setup(cfg, 0);
520 void ast_ssl_teardown(struct ast_tls_config *cfg)
523 if (cfg && cfg->ssl_ctx) {
524 SSL_CTX_free(cfg->ssl_ctx);
530 struct ast_tcptls_session_instance *ast_tcptls_client_start(struct ast_tcptls_session_instance *tcptls_session)
532 struct ast_tcptls_session_args *desc;
534 if (!(desc = tcptls_session->parent)) {
535 goto client_start_error;
538 if (ast_connect(desc->accept_fd, &desc->remote_address)) {
539 ast_log(LOG_ERROR, "Unable to connect %s to %s: %s\n",
541 ast_sockaddr_stringify(&desc->remote_address),
543 goto client_start_error;
546 ast_fd_clear_flags(desc->accept_fd, O_NONBLOCK);
549 desc->tls_cfg->enabled = 1;
550 __ssl_setup(desc->tls_cfg, 1);
553 return handle_tcptls_connection(tcptls_session);
557 close(desc->accept_fd);
558 desc->accept_fd = -1;
560 ao2_ref(tcptls_session, -1);
565 struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_session_args *desc)
568 struct ast_tcptls_session_instance *tcptls_session = NULL;
570 /* Do nothing if nothing has changed */
571 if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) {
572 ast_debug(1, "Nothing changed in %s\n", desc->name);
576 /* If we return early, there is no connection */
577 ast_sockaddr_setnull(&desc->old_address);
579 if (desc->accept_fd != -1) {
580 close(desc->accept_fd);
583 fd = desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ?
584 AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
585 if (desc->accept_fd < 0) {
586 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n",
587 desc->name, strerror(errno));
591 /* if a local address was specified, bind to it so the connection will
592 originate from the desired address */
593 if (!ast_sockaddr_isnull(&desc->local_address) &&
594 !ast_sockaddr_is_any(&desc->local_address)) {
595 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
596 if (ast_bind(desc->accept_fd, &desc->local_address)) {
597 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
599 ast_sockaddr_stringify(&desc->local_address),
605 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor);
606 if (!tcptls_session) {
610 tcptls_session->overflow_buf = ast_str_create(128);
611 if (!tcptls_session->overflow_buf) {
614 tcptls_session->client = 1;
615 tcptls_session->stream = ast_iostream_from_fd(&fd);
616 if (!tcptls_session->stream) {
620 tcptls_session->parent = desc;
621 tcptls_session->parent->worker_fn = NULL;
622 ast_sockaddr_copy(&tcptls_session->remote_address,
623 &desc->remote_address);
625 /* Set current info */
626 ast_sockaddr_copy(&desc->old_address, &desc->remote_address);
627 return tcptls_session;
630 close(desc->accept_fd);
631 desc->accept_fd = -1;
632 ao2_cleanup(tcptls_session);
636 void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
647 /* Store the hashes of the TLS certificate etc. */
648 if (stat(desc->tls_cfg->certfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->certfile))) {
651 ast_sha1_hash(hash, str);
655 memcpy(desc->tls_cfg->certhash, hash, 41);
656 if (stat(desc->tls_cfg->pvtfile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->pvtfile))) {
659 ast_sha1_hash(hash, str);
663 memcpy(desc->tls_cfg->pvthash, hash, 41);
664 if (stat(desc->tls_cfg->cafile, &st) || NULL == (str = ast_read_textfile(desc->tls_cfg->cafile))) {
667 ast_sha1_hash(hash, str);
671 memcpy(desc->tls_cfg->cahash, hash, 41);
673 /* Check whether TLS configuration has changed */
674 if (!desc->old_tls_cfg) { /* No previous configuration */
676 desc->old_tls_cfg = ast_calloc(1, sizeof(*desc->old_tls_cfg));
677 } else if (memcmp(desc->tls_cfg->certhash, desc->old_tls_cfg->certhash, 41)) {
679 } else if (memcmp(desc->tls_cfg->pvthash, desc->old_tls_cfg->pvthash, 41)) {
681 } else if (strcmp(desc->tls_cfg->cipher, desc->old_tls_cfg->cipher)) {
683 } else if (memcmp(desc->tls_cfg->cahash, desc->old_tls_cfg->cahash, 41)) {
685 } else if (strcmp(desc->tls_cfg->capath, desc->old_tls_cfg->capath)) {
687 } else if (memcmp(&desc->tls_cfg->flags, &desc->old_tls_cfg->flags, sizeof(desc->tls_cfg->flags))) {
692 ast_debug(1, "Changed parameters for %s found\n", desc->name);
696 /* Do nothing if nothing has changed */
697 if (!tls_changed && !ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
698 ast_debug(1, "Nothing changed in %s\n", desc->name);
702 /* If we return early, there is no one listening */
703 ast_sockaddr_setnull(&desc->old_address);
705 /* Shutdown a running server if there is one */
706 if (desc->master != AST_PTHREADT_NULL) {
707 pthread_cancel(desc->master);
708 pthread_kill(desc->master, SIGURG);
709 pthread_join(desc->master, NULL);
712 sd_socket = ast_sd_get_fd(SOCK_STREAM, &desc->local_address);
714 if (sd_socket != -1) {
715 if (desc->accept_fd != sd_socket) {
716 if (desc->accept_fd != -1) {
717 close(desc->accept_fd);
719 desc->accept_fd = sd_socket;
722 goto systemd_socket_activation;
725 if (desc->accept_fd != -1) {
726 close(desc->accept_fd);
729 /* If there's no new server, stop here */
730 if (ast_sockaddr_isnull(&desc->local_address)) {
731 ast_debug(2, "Server disabled: %s\n", desc->name);
735 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ?
736 AF_INET6 : AF_INET, SOCK_STREAM, 0);
737 if (desc->accept_fd < 0) {
738 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
742 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
743 if (ast_bind(desc->accept_fd, &desc->local_address)) {
744 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
746 ast_sockaddr_stringify(&desc->local_address),
750 if (listen(desc->accept_fd, 10)) {
751 ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name);
755 systemd_socket_activation:
756 ast_fd_set_flags(desc->accept_fd, O_NONBLOCK);
757 if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
758 ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
760 ast_sockaddr_stringify(&desc->local_address),
765 /* Set current info */
766 ast_sockaddr_copy(&desc->old_address, &desc->local_address);
767 if (desc->old_tls_cfg) {
768 ast_free(desc->old_tls_cfg->certfile);
769 ast_free(desc->old_tls_cfg->pvtfile);
770 ast_free(desc->old_tls_cfg->cipher);
771 ast_free(desc->old_tls_cfg->cafile);
772 ast_free(desc->old_tls_cfg->capath);
773 desc->old_tls_cfg->certfile = ast_strdup(desc->tls_cfg->certfile);
774 desc->old_tls_cfg->pvtfile = ast_strdup(desc->tls_cfg->pvtfile);
775 desc->old_tls_cfg->cipher = ast_strdup(desc->tls_cfg->cipher);
776 desc->old_tls_cfg->cafile = ast_strdup(desc->tls_cfg->cafile);
777 desc->old_tls_cfg->capath = ast_strdup(desc->tls_cfg->capath);
778 memcpy(desc->old_tls_cfg->certhash, desc->tls_cfg->certhash, 41);
779 memcpy(desc->old_tls_cfg->pvthash, desc->tls_cfg->pvthash, 41);
780 memcpy(desc->old_tls_cfg->cahash, desc->tls_cfg->cahash, 41);
781 memcpy(&desc->old_tls_cfg->flags, &desc->tls_cfg->flags, sizeof(desc->old_tls_cfg->flags));
787 close(desc->accept_fd);
788 desc->accept_fd = -1;
791 void ast_tcptls_close_session_file(struct ast_tcptls_session_instance *tcptls_session)
793 if (tcptls_session->stream) {
794 ast_iostream_close(tcptls_session->stream);
795 tcptls_session->stream = NULL;
797 ast_debug(1, "ast_tcptls_close_session_file invoked on session instance without file or file descriptor\n");
801 void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc)
803 if (desc->master != AST_PTHREADT_NULL) {
804 pthread_cancel(desc->master);
805 pthread_kill(desc->master, SIGURG);
806 pthread_join(desc->master, NULL);
807 desc->master = AST_PTHREADT_NULL;
809 if (desc->accept_fd != -1) {
810 close(desc->accept_fd);
812 desc->accept_fd = -1;
814 if (desc->old_tls_cfg) {
815 ast_free(desc->old_tls_cfg->certfile);
816 ast_free(desc->old_tls_cfg->pvtfile);
817 ast_free(desc->old_tls_cfg->cipher);
818 ast_free(desc->old_tls_cfg->cafile);
819 ast_free(desc->old_tls_cfg->capath);
820 ast_free(desc->old_tls_cfg);
821 desc->old_tls_cfg = NULL;
824 ast_debug(2, "Stopped server :: %s\n", desc->name);
827 int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_args *tls_desc, const char *varname, const char *value)
829 if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) {
830 tls_cfg->enabled = ast_true(value) ? 1 : 0;
831 } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) {
832 ast_free(tls_cfg->certfile);
833 tls_cfg->certfile = ast_strdup(value);
834 } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) {
835 ast_free(tls_cfg->pvtfile);
836 tls_cfg->pvtfile = ast_strdup(value);
837 } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) {
838 ast_free(tls_cfg->cipher);
839 tls_cfg->cipher = ast_strdup(value);
840 } else if (!strcasecmp(varname, "tlscafile")) {
841 ast_free(tls_cfg->cafile);
842 tls_cfg->cafile = ast_strdup(value);
843 } else if (!strcasecmp(varname, "tlscapath") || !strcasecmp(varname, "tlscadir")) {
844 ast_free(tls_cfg->capath);
845 tls_cfg->capath = ast_strdup(value);
846 } else if (!strcasecmp(varname, "tlsverifyclient")) {
847 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_VERIFY_CLIENT);
848 } else if (!strcasecmp(varname, "tlsdontverifyserver")) {
849 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DONT_VERIFY_SERVER);
850 } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) {
851 if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address))
852 ast_log(LOG_ERROR, "Invalid %s '%s'\n", varname, value);
853 } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) {
854 if (!strcasecmp(value, "tlsv1")) {
855 ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
856 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
857 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
858 } else if (!strcasecmp(value, "sslv3")) {
859 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
860 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
861 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
862 } else if (!strcasecmp(value, "sslv2")) {
863 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
864 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
865 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
867 } else if (!strcasecmp(varname, "tlsservercipherorder")) {
868 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_SERVER_CIPHER_ORDER);
869 } else if (!strcasecmp(varname, "tlsdisablev1")) {
870 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DISABLE_TLSV1);
871 } else if (!strcasecmp(varname, "tlsdisablev11")) {
872 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DISABLE_TLSV11);
873 } else if (!strcasecmp(varname, "tlsdisablev12")) {
874 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DISABLE_TLSV12);