#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 363 of file tcptls.c.
References __ssl_setup().
00364 { 00365 return __ssl_setup(cfg, 0); 00366 }
struct ast_tcptls_session_instance* ast_tcptls_client_create | ( | struct ast_tcptls_session_args * | desc | ) |
Definition at line 405 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().
00406 { 00407 int x = 1; 00408 struct ast_tcptls_session_instance *tcptls_session = NULL; 00409 00410 /* Do nothing if nothing has changed */ 00411 if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) { 00412 ast_debug(1, "Nothing changed in %s\n", desc->name); 00413 return NULL; 00414 } 00415 00416 ast_sockaddr_copy(&desc->old_address, &desc->remote_address); 00417 00418 if (desc->accept_fd != -1) 00419 close(desc->accept_fd); 00420 00421 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ? 00422 AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP); 00423 if (desc->accept_fd < 0) { 00424 ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n", 00425 desc->name, strerror(errno)); 00426 return NULL; 00427 } 00428 00429 /* if a local address was specified, bind to it so the connection will 00430 originate from the desired address */ 00431 if (!ast_sockaddr_isnull(&desc->local_address)) { 00432 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00433 if (ast_bind(desc->accept_fd, &desc->local_address)) { 00434 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", 00435 desc->name, 00436 ast_sockaddr_stringify(&desc->local_address), 00437 strerror(errno)); 00438 goto error; 00439 } 00440 } 00441 00442 if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) 00443 goto error; 00444 00445 ast_mutex_init(&tcptls_session->lock); 00446 tcptls_session->client = 1; 00447 tcptls_session->fd = desc->accept_fd; 00448 tcptls_session->parent = desc; 00449 tcptls_session->parent->worker_fn = NULL; 00450 ast_sockaddr_copy(&tcptls_session->remote_address, 00451 &desc->remote_address); 00452 00453 return tcptls_session; 00454 00455 error: 00456 close(desc->accept_fd); 00457 desc->accept_fd = -1; 00458 if (tcptls_session) 00459 ao2_ref(tcptls_session, -1); 00460 return NULL; 00461 }
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 368 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().
00369 { 00370 struct ast_tcptls_session_args *desc; 00371 int flags; 00372 00373 if (!(desc = tcptls_session->parent)) { 00374 goto client_start_error; 00375 } 00376 00377 if (ast_connect(desc->accept_fd, &desc->remote_address)) { 00378 ast_log(LOG_ERROR, "Unable to connect %s to %s: %s\n", 00379 desc->name, 00380 ast_sockaddr_stringify(&desc->remote_address), 00381 strerror(errno)); 00382 goto client_start_error; 00383 } 00384 00385 flags = fcntl(desc->accept_fd, F_GETFL); 00386 fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK); 00387 00388 if (desc->tls_cfg) { 00389 desc->tls_cfg->enabled = 1; 00390 __ssl_setup(desc->tls_cfg, 1); 00391 } 00392 00393 return handle_tcptls_connection(tcptls_session); 00394 00395 client_start_error: 00396 close(desc->accept_fd); 00397 desc->accept_fd = -1; 00398 if (tcptls_session) { 00399 ao2_ref(tcptls_session, -1); 00400 } 00401 return NULL; 00402 00403 }
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 234 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().
00235 { 00236 struct ast_tcptls_session_args *desc = data; 00237 int fd; 00238 struct ast_sockaddr addr; 00239 struct ast_tcptls_session_instance *tcptls_session; 00240 pthread_t launched; 00241 00242 for (;;) { 00243 int i, flags; 00244 00245 if (desc->periodic_fn) 00246 desc->periodic_fn(desc); 00247 i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout); 00248 if (i <= 0) 00249 continue; 00250 fd = ast_accept(desc->accept_fd, &addr); 00251 if (fd < 0) { 00252 if ((errno != EAGAIN) && (errno != EINTR)) 00253 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00254 continue; 00255 } 00256 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor); 00257 if (!tcptls_session) { 00258 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00259 close(fd); 00260 continue; 00261 } 00262 00263 ast_mutex_init(&tcptls_session->lock); 00264 00265 flags = fcntl(fd, F_GETFL); 00266 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00267 tcptls_session->fd = fd; 00268 tcptls_session->parent = desc; 00269 ast_sockaddr_copy(&tcptls_session->remote_address, &addr); 00270 00271 tcptls_session->client = 0; 00272 00273 /* This thread is now the only place that controls the single ref to tcptls_session */ 00274 if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, tcptls_session)) { 00275 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00276 close(tcptls_session->fd); 00277 ao2_ref(tcptls_session, -1); 00278 } 00279 } 00280 return NULL; 00281 }
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 463 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.
00464 { 00465 int flags; 00466 int x = 1; 00467 00468 /* Do nothing if nothing has changed */ 00469 if (!ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) { 00470 ast_debug(1, "Nothing changed in %s\n", desc->name); 00471 return; 00472 } 00473 00474 ast_sockaddr_copy(&desc->old_address, &desc->local_address); 00475 00476 /* Shutdown a running server if there is one */ 00477 if (desc->master != AST_PTHREADT_NULL) { 00478 pthread_cancel(desc->master); 00479 pthread_kill(desc->master, SIGURG); 00480 pthread_join(desc->master, NULL); 00481 } 00482 00483 if (desc->accept_fd != -1) 00484 close(desc->accept_fd); 00485 00486 /* If there's no new server, stop here */ 00487 if (ast_sockaddr_isnull(&desc->local_address)) { 00488 ast_debug(2, "Server disabled: %s\n", desc->name); 00489 return; 00490 } 00491 00492 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ? 00493 AF_INET6 : AF_INET, SOCK_STREAM, 0); 00494 if (desc->accept_fd < 0) { 00495 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno)); 00496 return; 00497 } 00498 00499 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00500 if (ast_bind(desc->accept_fd, &desc->local_address)) { 00501 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", 00502 desc->name, 00503 ast_sockaddr_stringify(&desc->local_address), 00504 strerror(errno)); 00505 goto error; 00506 } 00507 if (listen(desc->accept_fd, 10)) { 00508 ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name); 00509 goto error; 00510 } 00511 flags = fcntl(desc->accept_fd, F_GETFL); 00512 fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK); 00513 if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) { 00514 ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n", 00515 desc->name, 00516 ast_sockaddr_stringify(&desc->local_address), 00517 strerror(errno)); 00518 goto error; 00519 } 00520 return; 00521 00522 error: 00523 close(desc->accept_fd); 00524 desc->accept_fd = -1; 00525 }
void ast_tcptls_server_stop | ( | struct ast_tcptls_session_args * | desc | ) |
Shutdown a running server if there is one.
Definition at line 527 of file tcptls.c.
References ast_debug, AST_PTHREADT_NULL, and desc.
Referenced by unload_module().
00528 { 00529 if (desc->master != AST_PTHREADT_NULL) { 00530 pthread_cancel(desc->master); 00531 pthread_kill(desc->master, SIGURG); 00532 pthread_join(desc->master, NULL); 00533 } 00534 if (desc->accept_fd != -1) 00535 close(desc->accept_fd); 00536 desc->accept_fd = -1; 00537 ast_debug(2, "Stopped server :: %s\n", desc->name); 00538 }
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().
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 540 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().
00541 { 00542 if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) { 00543 tls_cfg->enabled = ast_true(value) ? 1 : 0; 00544 } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) { 00545 ast_free(tls_cfg->certfile); 00546 tls_cfg->certfile = ast_strdup(value); 00547 } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) { 00548 ast_free(tls_cfg->pvtfile); 00549 tls_cfg->pvtfile = ast_strdup(value); 00550 } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) { 00551 ast_free(tls_cfg->cipher); 00552 tls_cfg->cipher = ast_strdup(value); 00553 } else if (!strcasecmp(varname, "tlscafile")) { 00554 ast_free(tls_cfg->cafile); 00555 tls_cfg->cafile = ast_strdup(value); 00556 } else if (!strcasecmp(varname, "tlscapath") || !strcasecmp(varname, "tlscadir")) { 00557 ast_free(tls_cfg->capath); 00558 tls_cfg->capath = ast_strdup(value); 00559 } else if (!strcasecmp(varname, "tlsverifyclient")) { 00560 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_VERIFY_CLIENT); 00561 } else if (!strcasecmp(varname, "tlsdontverifyserver")) { 00562 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DONT_VERIFY_SERVER); 00563 } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) { 00564 if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address)) 00565 ast_log(LOG_WARNING, "Invalid %s '%s'\n", varname, value); 00566 } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) { 00567 if (!strcasecmp(value, "tlsv1")) { 00568 ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00569 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00570 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00571 } else if (!strcasecmp(value, "sslv3")) { 00572 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00573 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00574 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00575 } else if (!strcasecmp(value, "sslv2")) { 00576 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00577 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00578 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00579 } 00580 } else { 00581 return -1; 00582 } 00583 00584 return 0; 00585 }