#include "asterisk/netsock2.h"
#include "asterisk/utils.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
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 |
struct | ast_tls_config |
Defines | |
#define | AST_CERTFILE "asterisk.pem" |
#define | DO_SSL |
#define | HOOK_T ssize_t |
#define | LEN_T size_t |
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) } |
Functions | |
int | ast_ssl_setup (struct ast_tls_config *cfg) |
ast_tcptls_session_instance * | ast_tcptls_client_create (struct ast_tcptls_session_args *desc) |
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. | |
HOOK_T | ast_tcptls_server_read (struct ast_tcptls_session_instance *ser, void *buf, size_t count) |
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(). | |
void | ast_tcptls_server_stop (struct ast_tcptls_session_args *desc) |
Shutdown a running server if there is one. | |
HOOK_T | ast_tcptls_server_write (struct ast_tcptls_session_instance *ser, const void *buf, size_t count) |
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. |
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.
Definition in file tcptls.h.
#define AST_CERTFILE "asterisk.pem" |
SSL support
Definition at line 68 of file tcptls.h.
Referenced by __ast_http_load(), and __init_manager().
enum ast_ssl_flags |
Definition at line 70 of file tcptls.h.
00070 { 00071 /*! Verify certificate when acting as server */ 00072 AST_SSL_VERIFY_CLIENT = (1 << 0), 00073 /*! Don't verify certificate when connecting to a server */ 00074 AST_SSL_DONT_VERIFY_SERVER = (1 << 1), 00075 /*! Don't compare "Common Name" against IP or hostname */ 00076 AST_SSL_IGNORE_COMMON_NAME = (1 << 2), 00077 /*! Use SSLv2 for outgoing client connections */ 00078 AST_SSL_SSLV2_CLIENT = (1 << 3), 00079 /*! Use SSLv3 for outgoing client connections */ 00080 AST_SSL_SSLV3_CLIENT = (1 << 4), 00081 /*! Use TLSv1 for outgoing client connections */ 00082 AST_SSL_TLSV1_CLIENT = (1 << 5) 00083 };
int ast_ssl_setup | ( | struct ast_tls_config * | cfg | ) |
Definition at line 364 of file tcptls.c.
References __ssl_setup().
00365 { 00366 return __ssl_setup(cfg, 0); 00367 }
struct ast_tcptls_session_instance* ast_tcptls_client_create | ( | struct ast_tcptls_session_args * | desc | ) |
Definition at line 406 of file tcptls.c.
References ao2_alloc, ao2_ref, ast_bind(), ast_debug, ast_log(), ast_mutex_init, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_is_ipv6(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), desc, errno, LOG_ERROR, LOG_WARNING, and session_instance_destructor().
Referenced by sip_prepare_socket().
00407 { 00408 int x = 1; 00409 struct ast_tcptls_session_instance *tcptls_session = NULL; 00410 00411 /* Do nothing if nothing has changed */ 00412 if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) { 00413 ast_debug(1, "Nothing changed in %s\n", desc->name); 00414 return NULL; 00415 } 00416 00417 ast_sockaddr_copy(&desc->old_address, &desc->remote_address); 00418 00419 if (desc->accept_fd != -1) 00420 close(desc->accept_fd); 00421 00422 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ? 00423 AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP); 00424 if (desc->accept_fd < 0) { 00425 ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n", 00426 desc->name, strerror(errno)); 00427 return NULL; 00428 } 00429 00430 /* if a local address was specified, bind to it so the connection will 00431 originate from the desired address */ 00432 if (!ast_sockaddr_isnull(&desc->local_address)) { 00433 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00434 if (ast_bind(desc->accept_fd, &desc->local_address)) { 00435 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", 00436 desc->name, 00437 ast_sockaddr_stringify(&desc->local_address), 00438 strerror(errno)); 00439 goto error; 00440 } 00441 } 00442 00443 if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) 00444 goto error; 00445 00446 ast_mutex_init(&tcptls_session->lock); 00447 tcptls_session->client = 1; 00448 tcptls_session->fd = desc->accept_fd; 00449 tcptls_session->parent = desc; 00450 tcptls_session->parent->worker_fn = NULL; 00451 ast_sockaddr_copy(&tcptls_session->remote_address, 00452 &desc->remote_address); 00453 00454 return tcptls_session; 00455 00456 error: 00457 close(desc->accept_fd); 00458 desc->accept_fd = -1; 00459 if (tcptls_session) 00460 ao2_ref(tcptls_session, -1); 00461 return NULL; 00462 }
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 369 of file tcptls.c.
References __ssl_setup(), ao2_ref, ast_connect(), ast_log(), ast_sockaddr_stringify(), desc, errno, handle_tcptls_connection(), LOG_ERROR, and ast_tcptls_session_instance::parent.
Referenced by _sip_tcp_helper_thread().
00370 { 00371 struct ast_tcptls_session_args *desc; 00372 int flags; 00373 00374 if (!(desc = tcptls_session->parent)) { 00375 goto client_start_error; 00376 } 00377 00378 if (ast_connect(desc->accept_fd, &desc->remote_address)) { 00379 ast_log(LOG_ERROR, "Unable to connect %s to %s: %s\n", 00380 desc->name, 00381 ast_sockaddr_stringify(&desc->remote_address), 00382 strerror(errno)); 00383 goto client_start_error; 00384 } 00385 00386 flags = fcntl(desc->accept_fd, F_GETFL); 00387 fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK); 00388 00389 if (desc->tls_cfg) { 00390 desc->tls_cfg->enabled = 1; 00391 __ssl_setup(desc->tls_cfg, 1); 00392 } 00393 00394 return handle_tcptls_connection(tcptls_session); 00395 00396 client_start_error: 00397 close(desc->accept_fd); 00398 desc->accept_fd = -1; 00399 if (tcptls_session) { 00400 ao2_ref(tcptls_session, -1); 00401 } 00402 return NULL; 00403 00404 }
HOOK_T ast_tcptls_server_read | ( | struct ast_tcptls_session_instance * | ser, | |
void * | buf, | |||
size_t | count | |||
) |
Definition at line 86 of file tcptls.c.
References ast_log(), errno, ast_tcptls_session_instance::fd, LOG_ERROR, ast_tcptls_session_instance::ssl, and ssl_read().
00087 { 00088 if (tcptls_session->fd == -1) { 00089 ast_log(LOG_ERROR, "server_read called with an fd of -1\n"); 00090 errno = EIO; 00091 return -1; 00092 } 00093 00094 #ifdef DO_SSL 00095 if (tcptls_session->ssl) 00096 return ssl_read(tcptls_session->ssl, buf, count); 00097 #endif 00098 return read(tcptls_session->fd, buf, count); 00099 }
void* ast_tcptls_server_root | ( | void * | ) |
Definition at line 238 of file tcptls.c.
References ao2_alloc, ao2_ref, ast_accept(), ast_log(), ast_mutex_init, ast_pthread_create_detached_background, ast_sockaddr_copy(), ast_wait_for_input(), desc, errno, handle_tcptls_connection(), LOG_WARNING, and session_instance_destructor().
00239 { 00240 struct ast_tcptls_session_args *desc = data; 00241 int fd; 00242 struct ast_sockaddr addr; 00243 struct ast_tcptls_session_instance *tcptls_session; 00244 pthread_t launched; 00245 00246 for (;;) { 00247 int i, flags; 00248 00249 if (desc->periodic_fn) 00250 desc->periodic_fn(desc); 00251 i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout); 00252 if (i <= 0) 00253 continue; 00254 fd = ast_accept(desc->accept_fd, &addr); 00255 if (fd < 0) { 00256 if ((errno != EAGAIN) && (errno != EINTR)) 00257 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00258 continue; 00259 } 00260 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor); 00261 if (!tcptls_session) { 00262 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00263 close(fd); 00264 continue; 00265 } 00266 00267 ast_mutex_init(&tcptls_session->lock); 00268 00269 flags = fcntl(fd, F_GETFL); 00270 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00271 tcptls_session->fd = fd; 00272 tcptls_session->parent = desc; 00273 ast_sockaddr_copy(&tcptls_session->remote_address, &addr); 00274 00275 tcptls_session->client = 0; 00276 00277 /* This thread is now the only place that controls the single ref to tcptls_session */ 00278 if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, tcptls_session)) { 00279 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00280 close(tcptls_session->fd); 00281 ao2_ref(tcptls_session, -1); 00282 } 00283 } 00284 return NULL; 00285 }
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().
Definition at line 464 of file tcptls.c.
References ast_bind(), ast_debug, ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_is_ipv6(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), desc, errno, and LOG_ERROR.
00465 { 00466 int flags; 00467 int x = 1; 00468 00469 /* Do nothing if nothing has changed */ 00470 if (!ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) { 00471 ast_debug(1, "Nothing changed in %s\n", desc->name); 00472 return; 00473 } 00474 00475 ast_sockaddr_copy(&desc->old_address, &desc->local_address); 00476 00477 /* Shutdown a running server if there is one */ 00478 if (desc->master != AST_PTHREADT_NULL) { 00479 pthread_cancel(desc->master); 00480 pthread_kill(desc->master, SIGURG); 00481 pthread_join(desc->master, NULL); 00482 } 00483 00484 if (desc->accept_fd != -1) 00485 close(desc->accept_fd); 00486 00487 /* If there's no new server, stop here */ 00488 if (ast_sockaddr_isnull(&desc->local_address)) { 00489 ast_debug(2, "Server disabled: %s\n", desc->name); 00490 return; 00491 } 00492 00493 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ? 00494 AF_INET6 : AF_INET, SOCK_STREAM, 0); 00495 if (desc->accept_fd < 0) { 00496 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno)); 00497 return; 00498 } 00499 00500 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00501 if (ast_bind(desc->accept_fd, &desc->local_address)) { 00502 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", 00503 desc->name, 00504 ast_sockaddr_stringify(&desc->local_address), 00505 strerror(errno)); 00506 goto error; 00507 } 00508 if (listen(desc->accept_fd, 10)) { 00509 ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name); 00510 goto error; 00511 } 00512 flags = fcntl(desc->accept_fd, F_GETFL); 00513 fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK); 00514 if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) { 00515 ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n", 00516 desc->name, 00517 ast_sockaddr_stringify(&desc->local_address), 00518 strerror(errno)); 00519 goto error; 00520 } 00521 return; 00522 00523 error: 00524 close(desc->accept_fd); 00525 desc->accept_fd = -1; 00526 }
void ast_tcptls_server_stop | ( | struct ast_tcptls_session_args * | desc | ) |
Shutdown a running server if there is one.
Definition at line 528 of file tcptls.c.
References ast_debug, AST_PTHREADT_NULL, and desc.
Referenced by unload_module().
00529 { 00530 if (desc->master != AST_PTHREADT_NULL) { 00531 pthread_cancel(desc->master); 00532 pthread_kill(desc->master, SIGURG); 00533 pthread_join(desc->master, NULL); 00534 } 00535 if (desc->accept_fd != -1) 00536 close(desc->accept_fd); 00537 desc->accept_fd = -1; 00538 ast_debug(2, "Stopped server :: %s\n", desc->name); 00539 }
HOOK_T ast_tcptls_server_write | ( | struct ast_tcptls_session_instance * | ser, | |
const void * | buf, | |||
size_t | count | |||
) |
Definition at line 101 of file tcptls.c.
References ast_log(), errno, ast_tcptls_session_instance::fd, LOG_ERROR, ast_tcptls_session_instance::ssl, and ssl_write().
Referenced by _sip_tcp_helper_thread().
00102 { 00103 if (tcptls_session->fd == -1) { 00104 ast_log(LOG_ERROR, "server_write called with an fd of -1\n"); 00105 errno = EIO; 00106 return -1; 00107 } 00108 00109 #ifdef DO_SSL 00110 if (tcptls_session->ssl) 00111 return ssl_write(tcptls_session->ssl, buf, count); 00112 #endif 00113 return write(tcptls_session->fd, buf, count); 00114 }
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 541 of file tcptls.c.
References ast_clear_flag, ast_free, ast_log(), ast_parse_arg(), ast_set2_flag, ast_set_flag, AST_SSL_DONT_VERIFY_SERVER, 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_WARNING, PARSE_ADDR, and ast_tls_config::pvtfile.
Referenced by __ast_http_load(), and __init_manager().
00542 { 00543 if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) { 00544 tls_cfg->enabled = ast_true(value) ? 1 : 0; 00545 } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) { 00546 ast_free(tls_cfg->certfile); 00547 tls_cfg->certfile = ast_strdup(value); 00548 } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) { 00549 ast_free(tls_cfg->pvtfile); 00550 tls_cfg->pvtfile = ast_strdup(value); 00551 } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) { 00552 ast_free(tls_cfg->cipher); 00553 tls_cfg->cipher = ast_strdup(value); 00554 } else if (!strcasecmp(varname, "tlscafile")) { 00555 ast_free(tls_cfg->cafile); 00556 tls_cfg->cafile = ast_strdup(value); 00557 } else if (!strcasecmp(varname, "tlscapath")) { 00558 ast_free(tls_cfg->capath); 00559 tls_cfg->capath = ast_strdup(value); 00560 } else if (!strcasecmp(varname, "tlsverifyclient")) { 00561 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_VERIFY_CLIENT); 00562 } else if (!strcasecmp(varname, "tlsdontverifyserver")) { 00563 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DONT_VERIFY_SERVER); 00564 } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) { 00565 if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address)) 00566 ast_log(LOG_WARNING, "Invalid %s '%s'\n", varname, value); 00567 } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) { 00568 if (!strcasecmp(value, "tlsv1")) { 00569 ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00570 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00571 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00572 } else if (!strcasecmp(value, "sslv3")) { 00573 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00574 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00575 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00576 } else if (!strcasecmp(value, "sslv2")) { 00577 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00578 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00579 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00580 } 00581 } else { 00582 return -1; 00583 } 00584 00585 return 0; 00586 }