#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 |
struct | SSL |
struct | SSL_CTX |
Defines | |
#define | AST_CERTFILE "asterisk.pem" |
#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) } |
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, void *buf, size_t count) |
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 67 of file tcptls.h.
Referenced by __ast_http_load(), and __init_manager().
enum ast_ssl_flags |
Definition at line 69 of file tcptls.h.
00069 { 00070 /*! Verify certificate when acting as server */ 00071 AST_SSL_VERIFY_CLIENT = (1 << 0), 00072 /*! Don't verify certificate when connecting to a server */ 00073 AST_SSL_DONT_VERIFY_SERVER = (1 << 1), 00074 /*! Don't compare "Common Name" against IP or hostname */ 00075 AST_SSL_IGNORE_COMMON_NAME = (1 << 2) 00076 };
int ast_ssl_setup | ( | struct ast_tls_config * | cfg | ) |
Definition at line 335 of file tcptls.c.
References __ssl_setup().
00336 { 00337 return __ssl_setup(cfg, 0); 00338 }
struct ast_tcptls_session_instance* ast_tcptls_client_create | ( | struct ast_tcptls_session_args * | desc | ) |
Definition at line 377 of file tcptls.c.
References ao2_alloc, ao2_ref, ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_init(), desc, errno, LOG_ERROR, LOG_WARNING, and session_instance_destructor().
Referenced by sip_prepare_socket().
00378 { 00379 int x = 1; 00380 struct ast_tcptls_session_instance *tcptls_session = NULL; 00381 00382 /* Do nothing if nothing has changed */ 00383 if (!memcmp(&desc->old_address, &desc->remote_address, sizeof(desc->old_address))) { 00384 ast_debug(1, "Nothing changed in %s\n", desc->name); 00385 return NULL; 00386 } 00387 00388 desc->old_address = desc->remote_address; 00389 00390 if (desc->accept_fd != -1) 00391 close(desc->accept_fd); 00392 00393 desc->accept_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 00394 if (desc->accept_fd < 0) { 00395 ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n", 00396 desc->name, strerror(errno)); 00397 return NULL; 00398 } 00399 00400 /* if a local address was specified, bind to it so the connection will 00401 originate from the desired address */ 00402 if (desc->local_address.sin_family != 0) { 00403 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00404 if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) { 00405 ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n", 00406 desc->name, 00407 ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port), 00408 strerror(errno)); 00409 goto error; 00410 } 00411 } 00412 00413 if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) 00414 goto error; 00415 00416 ast_mutex_init(&tcptls_session->lock); 00417 tcptls_session->client = 1; 00418 tcptls_session->fd = desc->accept_fd; 00419 tcptls_session->parent = desc; 00420 tcptls_session->parent->worker_fn = NULL; 00421 memcpy(&tcptls_session->remote_address, &desc->remote_address, sizeof(tcptls_session->remote_address)); 00422 00423 return tcptls_session; 00424 00425 error: 00426 close(desc->accept_fd); 00427 desc->accept_fd = -1; 00428 if (tcptls_session) 00429 ao2_ref(tcptls_session, -1); 00430 return NULL; 00431 }
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 340 of file tcptls.c.
References __ssl_setup(), ao2_ref, ast_inet_ntoa(), ast_log(), desc, errno, handle_tcptls_connection(), LOG_ERROR, and ast_tcptls_session_instance::parent.
Referenced by _sip_tcp_helper_thread().
00341 { 00342 struct ast_tcptls_session_args *desc; 00343 int flags; 00344 00345 if (!(desc = tcptls_session->parent)) { 00346 goto client_start_error; 00347 } 00348 00349 if (connect(desc->accept_fd, (const struct sockaddr *) &desc->remote_address, sizeof(desc->remote_address))) { 00350 ast_log(LOG_ERROR, "Unable to connect %s to %s:%d: %s\n", 00351 desc->name, 00352 ast_inet_ntoa(desc->remote_address.sin_addr), ntohs(desc->remote_address.sin_port), 00353 strerror(errno)); 00354 goto client_start_error; 00355 } 00356 00357 flags = fcntl(desc->accept_fd, F_GETFL); 00358 fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK); 00359 00360 if (desc->tls_cfg) { 00361 desc->tls_cfg->enabled = 1; 00362 __ssl_setup(desc->tls_cfg, 1); 00363 } 00364 00365 return handle_tcptls_connection(tcptls_session); 00366 00367 client_start_error: 00368 close(desc->accept_fd); 00369 desc->accept_fd = -1; 00370 if (tcptls_session) { 00371 ao2_ref(tcptls_session, -1); 00372 } 00373 return NULL; 00374 00375 }
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_log(), ast_mutex_init(), ast_pthread_create_detached_background, 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 sockaddr_in sin; 00239 socklen_t sinlen; 00240 struct ast_tcptls_session_instance *tcptls_session; 00241 pthread_t launched; 00242 00243 for (;;) { 00244 int i, flags; 00245 00246 if (desc->periodic_fn) 00247 desc->periodic_fn(desc); 00248 i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout); 00249 if (i <= 0) 00250 continue; 00251 sinlen = sizeof(sin); 00252 fd = accept(desc->accept_fd, (struct sockaddr *) &sin, &sinlen); 00253 if (fd < 0) { 00254 if ((errno != EAGAIN) && (errno != EINTR)) 00255 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00256 continue; 00257 } 00258 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor); 00259 if (!tcptls_session) { 00260 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00261 close(fd); 00262 continue; 00263 } 00264 00265 ast_mutex_init(&tcptls_session->lock); 00266 00267 flags = fcntl(fd, F_GETFL); 00268 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00269 tcptls_session->fd = fd; 00270 tcptls_session->parent = desc; 00271 memcpy(&tcptls_session->remote_address, &sin, sizeof(tcptls_session->remote_address)); 00272 00273 tcptls_session->client = 0; 00274 00275 /* This thread is now the only place that controls the single ref to tcptls_session */ 00276 if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, tcptls_session)) { 00277 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00278 close(tcptls_session->fd); 00279 ao2_ref(tcptls_session, -1); 00280 } 00281 } 00282 return NULL; 00283 }
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 433 of file tcptls.c.
References ast_debug, ast_inet_ntoa(), ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, desc, errno, and LOG_ERROR.
00434 { 00435 int flags; 00436 int x = 1; 00437 00438 /* Do nothing if nothing has changed */ 00439 if (!memcmp(&desc->old_address, &desc->local_address, sizeof(desc->old_address))) { 00440 ast_debug(1, "Nothing changed in %s\n", desc->name); 00441 return; 00442 } 00443 00444 desc->old_address = desc->local_address; 00445 00446 /* Shutdown a running server if there is one */ 00447 if (desc->master != AST_PTHREADT_NULL) { 00448 pthread_cancel(desc->master); 00449 pthread_kill(desc->master, SIGURG); 00450 pthread_join(desc->master, NULL); 00451 } 00452 00453 if (desc->accept_fd != -1) 00454 close(desc->accept_fd); 00455 00456 /* If there's no new server, stop here */ 00457 if (desc->local_address.sin_family == 0) { 00458 return; 00459 } 00460 00461 desc->accept_fd = socket(AF_INET, SOCK_STREAM, 0); 00462 if (desc->accept_fd < 0) { 00463 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", 00464 desc->name, strerror(errno)); 00465 return; 00466 } 00467 00468 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00469 if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) { 00470 ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n", 00471 desc->name, 00472 ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port), 00473 strerror(errno)); 00474 goto error; 00475 } 00476 if (listen(desc->accept_fd, 10)) { 00477 ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name); 00478 goto error; 00479 } 00480 flags = fcntl(desc->accept_fd, F_GETFL); 00481 fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK); 00482 if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) { 00483 ast_log(LOG_ERROR, "Unable to launch thread for %s on %s:%d: %s\n", 00484 desc->name, 00485 ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port), 00486 strerror(errno)); 00487 goto error; 00488 } 00489 return; 00490 00491 error: 00492 close(desc->accept_fd); 00493 desc->accept_fd = -1; 00494 }
void ast_tcptls_server_stop | ( | struct ast_tcptls_session_args * | desc | ) |
Shutdown a running server if there is one.
Definition at line 496 of file tcptls.c.
References AST_PTHREADT_NULL, and desc.
Referenced by unload_module().
00497 { 00498 if (desc->master != AST_PTHREADT_NULL) { 00499 pthread_cancel(desc->master); 00500 pthread_kill(desc->master, SIGURG); 00501 pthread_join(desc->master, NULL); 00502 } 00503 if (desc->accept_fd != -1) 00504 close(desc->accept_fd); 00505 desc->accept_fd = -1; 00506 }
HOOK_T ast_tcptls_server_write | ( | struct ast_tcptls_session_instance * | ser, | |
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 }