Generic support for tcp/tls servers in Asterisk. More...
#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) |
| Set up an SSL server. | |
| void | ast_ssl_teardown (struct ast_tls_config *cfg) |
| free resources used by an SSL server | |
| struct ast_tcptls_session_instance * | ast_tcptls_client_create (struct ast_tcptls_session_args *desc) |
| 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. | |
| 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. | |
| 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. | |
Generic support for tcp/tls servers in Asterisk.
TLS/SSL support is basically implemented by reading from a config file (currently http.conf and sip.conf) the names of the certificate and cipher to use, and then run ssl_setup() to create an appropriate SSL_CTX (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.
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(), __init_manager(), and reload_config().
| enum ast_ssl_flags |
| 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 |
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 | ) |
Set up an SSL server.
| cfg | Configuration for the SSL server |
| 1 | Success | |
| 0 | Failure |
Definition at line 427 of file tcptls.c.
References __ssl_setup().
Referenced by __ast_http_load(), __init_manager(), and reload_config().
00428 { 00429 return __ssl_setup(cfg, 0); 00430 }
| void ast_ssl_teardown | ( | struct ast_tls_config * | cfg | ) |
free resources used by an SSL server
| cfg | Configuration for the SSL server |
Definition at line 432 of file tcptls.c.
References ast_tls_config::ssl_ctx.
Referenced by sip_tcptls_client_args_destructor(), and unload_module().
| struct ast_tcptls_session_instance* ast_tcptls_client_create | ( | struct ast_tcptls_session_args * | desc | ) | [read] |
Definition at line 479 of file tcptls.c.
References ast_tcptls_session_args::accept_fd, 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_setnull(), ast_sockaddr_stringify(), ast_str_create(), ast_tcptls_session_instance::client, errno, ast_tcptls_session_instance::fd, ast_tcptls_session_args::local_address, ast_tcptls_session_instance::lock, LOG_ERROR, LOG_WARNING, ast_tcptls_session_args::name, ast_tcptls_session_args::old_address, ast_tcptls_session_instance::overflow_buf, ast_tcptls_session_instance::parent, ast_tcptls_session_instance::remote_address, ast_tcptls_session_args::remote_address, session_instance_destructor(), and ast_tcptls_session_args::worker_fn.
Referenced by app_exec(), and sip_prepare_socket().
00480 { 00481 int x = 1; 00482 struct ast_tcptls_session_instance *tcptls_session = NULL; 00483 00484 /* Do nothing if nothing has changed */ 00485 if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) { 00486 ast_debug(1, "Nothing changed in %s\n", desc->name); 00487 return NULL; 00488 } 00489 00490 /* If we return early, there is no connection */ 00491 ast_sockaddr_setnull(&desc->old_address); 00492 00493 if (desc->accept_fd != -1) 00494 close(desc->accept_fd); 00495 00496 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ? 00497 AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP); 00498 if (desc->accept_fd < 0) { 00499 ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n", 00500 desc->name, strerror(errno)); 00501 return NULL; 00502 } 00503 00504 /* if a local address was specified, bind to it so the connection will 00505 originate from the desired address */ 00506 if (!ast_sockaddr_isnull(&desc->local_address)) { 00507 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00508 if (ast_bind(desc->accept_fd, &desc->local_address)) { 00509 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", 00510 desc->name, 00511 ast_sockaddr_stringify(&desc->local_address), 00512 strerror(errno)); 00513 goto error; 00514 } 00515 } 00516 00517 if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) 00518 goto error; 00519 00520 ast_mutex_init(&tcptls_session->lock); 00521 tcptls_session->overflow_buf = ast_str_create(128); 00522 tcptls_session->client = 1; 00523 tcptls_session->fd = desc->accept_fd; 00524 tcptls_session->parent = desc; 00525 tcptls_session->parent->worker_fn = NULL; 00526 ast_sockaddr_copy(&tcptls_session->remote_address, 00527 &desc->remote_address); 00528 00529 /* Set current info */ 00530 ast_sockaddr_copy(&desc->old_address, &desc->remote_address); 00531 return tcptls_session; 00532 00533 error: 00534 close(desc->accept_fd); 00535 desc->accept_fd = -1; 00536 if (tcptls_session) 00537 ao2_ref(tcptls_session, -1); 00538 return NULL; 00539 }
| struct ast_tcptls_session_instance* ast_tcptls_client_start | ( | struct ast_tcptls_session_instance * | tcptls_session | ) | [read] |
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 442 of file tcptls.c.
References __ssl_setup(), ast_tcptls_session_args::accept_fd, ao2_ref, ast_connect(), ast_log(), ast_sockaddr_stringify(), desc, ast_tls_config::enabled, errno, handle_tcptls_connection(), LOG_ERROR, ast_tcptls_session_args::name, ast_tcptls_session_instance::parent, ast_tcptls_session_args::remote_address, and ast_tcptls_session_args::tls_cfg.
Referenced by _sip_tcp_helper_thread(), and app_exec().
00443 { 00444 struct ast_tcptls_session_args *desc; 00445 int flags; 00446 00447 if (!(desc = tcptls_session->parent)) { 00448 goto client_start_error; 00449 } 00450 00451 if (ast_connect(desc->accept_fd, &desc->remote_address)) { 00452 ast_log(LOG_ERROR, "Unable to connect %s to %s: %s\n", 00453 desc->name, 00454 ast_sockaddr_stringify(&desc->remote_address), 00455 strerror(errno)); 00456 goto client_start_error; 00457 } 00458 00459 flags = fcntl(desc->accept_fd, F_GETFL); 00460 fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK); 00461 00462 if (desc->tls_cfg) { 00463 desc->tls_cfg->enabled = 1; 00464 __ssl_setup(desc->tls_cfg, 1); 00465 } 00466 00467 return handle_tcptls_connection(tcptls_session); 00468 00469 client_start_error: 00470 if (desc) { 00471 close(desc->accept_fd); 00472 desc->accept_fd = -1; 00473 } 00474 ao2_ref(tcptls_session, -1); 00475 return NULL; 00476 00477 }
| 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 610 of file tcptls.c.
References ast_log(), errno, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, and LOG_ERROR.
Referenced by _sip_tcp_helper_thread(), ast_tcptls_server_root(), handle_tcptls_connection(), and sip_prepare_socket().
00611 { 00612 if (tcptls_session->f) { 00613 if (fclose(tcptls_session->f)) { 00614 ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno)); 00615 } 00616 tcptls_session->f = NULL; 00617 tcptls_session->fd = -1; 00618 } else if (tcptls_session->fd != -1) { 00619 if (close(tcptls_session->fd)) { 00620 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno)); 00621 } 00622 tcptls_session->fd = -1; 00623 } else { 00624 ast_log(LOG_ERROR, "ast_tcptls_close_session_file invoked on session instance without file or file descriptor\n"); 00625 } 00626 }
| HOOK_T ast_tcptls_server_read | ( | struct ast_tcptls_session_instance * | ser, | |
| void * | buf, | |||
| size_t | count | |||
| ) |
Definition at line 112 of file tcptls.c.
References ast_log(), errno, ast_tcptls_session_instance::fd, LOG_ERROR, ast_tcptls_session_instance::ssl, and ssl_read().
00113 { 00114 if (tcptls_session->fd == -1) { 00115 ast_log(LOG_ERROR, "server_read called with an fd of -1\n"); 00116 errno = EIO; 00117 return -1; 00118 } 00119 00120 #ifdef DO_SSL 00121 if (tcptls_session->ssl) 00122 return ssl_read(tcptls_session->ssl, buf, count); 00123 #endif 00124 return read(tcptls_session->fd, buf, count); 00125 }
| void* ast_tcptls_server_root | ( | void * | ) |
Definition at line 282 of file tcptls.c.
References ast_tcptls_session_args::accept_fd, ao2_alloc, ao2_ref, ast_accept(), ast_log(), ast_mutex_init, ast_pthread_create_detached_background, ast_sockaddr_copy(), ast_str_create(), ast_tcptls_close_session_file(), ast_wait_for_input(), ast_tcptls_session_instance::client, desc, errno, ast_tcptls_session_instance::fd, handle_tcptls_connection(), ast_tcptls_session_instance::lock, LOG_ERROR, LOG_WARNING, ast_tcptls_session_instance::overflow_buf, ast_tcptls_session_instance::parent, ast_tcptls_session_args::periodic_fn, ast_tcptls_session_args::poll_timeout, ast_tcptls_session_instance::remote_address, and session_instance_destructor().
00283 { 00284 struct ast_tcptls_session_args *desc = data; 00285 int fd; 00286 struct ast_sockaddr addr; 00287 struct ast_tcptls_session_instance *tcptls_session; 00288 pthread_t launched; 00289 00290 for (;;) { 00291 int i, flags; 00292 00293 if (desc->periodic_fn) 00294 desc->periodic_fn(desc); 00295 i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout); 00296 if (i <= 0) 00297 continue; 00298 fd = ast_accept(desc->accept_fd, &addr); 00299 if (fd < 0) { 00300 if ((errno != EAGAIN) && (errno != EINTR)) 00301 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00302 continue; 00303 } 00304 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor); 00305 if (!tcptls_session) { 00306 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00307 if (close(fd)) { 00308 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno)); 00309 } 00310 continue; 00311 } 00312 00313 ast_mutex_init(&tcptls_session->lock); 00314 tcptls_session->overflow_buf = ast_str_create(128); 00315 00316 flags = fcntl(fd, F_GETFL); 00317 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00318 tcptls_session->fd = fd; 00319 tcptls_session->parent = desc; 00320 ast_sockaddr_copy(&tcptls_session->remote_address, &addr); 00321 00322 tcptls_session->client = 0; 00323 00324 /* This thread is now the only place that controls the single ref to tcptls_session */ 00325 if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, tcptls_session)) { 00326 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00327 ast_tcptls_close_session_file(tcptls_session); 00328 ao2_ref(tcptls_session, -1); 00329 } 00330 } 00331 return NULL; 00332 }
| 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 541 of file tcptls.c.
References ast_tcptls_session_args::accept_fd, ast_tcptls_session_args::accept_fn, 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_setnull(), ast_sockaddr_stringify(), errno, ast_tcptls_session_args::local_address, LOG_ERROR, ast_tcptls_session_args::master, ast_tcptls_session_args::name, and ast_tcptls_session_args::old_address.
Referenced by __ast_http_load(), __init_manager(), and reload_config().
00542 { 00543 int flags; 00544 int x = 1; 00545 00546 /* Do nothing if nothing has changed */ 00547 if (!ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) { 00548 ast_debug(1, "Nothing changed in %s\n", desc->name); 00549 return; 00550 } 00551 00552 /* If we return early, there is no one listening */ 00553 ast_sockaddr_setnull(&desc->old_address); 00554 00555 /* Shutdown a running server if there is one */ 00556 if (desc->master != AST_PTHREADT_NULL) { 00557 pthread_cancel(desc->master); 00558 pthread_kill(desc->master, SIGURG); 00559 pthread_join(desc->master, NULL); 00560 } 00561 00562 if (desc->accept_fd != -1) 00563 close(desc->accept_fd); 00564 00565 /* If there's no new server, stop here */ 00566 if (ast_sockaddr_isnull(&desc->local_address)) { 00567 ast_debug(2, "Server disabled: %s\n", desc->name); 00568 return; 00569 } 00570 00571 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ? 00572 AF_INET6 : AF_INET, SOCK_STREAM, 0); 00573 if (desc->accept_fd < 0) { 00574 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno)); 00575 return; 00576 } 00577 00578 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00579 if (ast_bind(desc->accept_fd, &desc->local_address)) { 00580 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", 00581 desc->name, 00582 ast_sockaddr_stringify(&desc->local_address), 00583 strerror(errno)); 00584 goto error; 00585 } 00586 if (listen(desc->accept_fd, 10)) { 00587 ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name); 00588 goto error; 00589 } 00590 flags = fcntl(desc->accept_fd, F_GETFL); 00591 fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK); 00592 if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) { 00593 ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n", 00594 desc->name, 00595 ast_sockaddr_stringify(&desc->local_address), 00596 strerror(errno)); 00597 goto error; 00598 } 00599 00600 /* Set current info */ 00601 ast_sockaddr_copy(&desc->old_address, &desc->local_address); 00602 00603 return; 00604 00605 error: 00606 close(desc->accept_fd); 00607 desc->accept_fd = -1; 00608 }
| void ast_tcptls_server_stop | ( | struct ast_tcptls_session_args * | desc | ) |
Shutdown a running server if there is one.
Definition at line 628 of file tcptls.c.
References ast_tcptls_session_args::accept_fd, ast_debug, AST_PTHREADT_NULL, ast_tcptls_session_args::master, and ast_tcptls_session_args::name.
Referenced by __ast_http_load(), __init_manager(), http_shutdown(), manager_shutdown(), and unload_module().
00629 { 00630 if (desc->master != AST_PTHREADT_NULL) { 00631 pthread_cancel(desc->master); 00632 pthread_kill(desc->master, SIGURG); 00633 pthread_join(desc->master, NULL); 00634 desc->master = AST_PTHREADT_NULL; 00635 } 00636 if (desc->accept_fd != -1) 00637 close(desc->accept_fd); 00638 desc->accept_fd = -1; 00639 ast_debug(2, "Stopped server :: %s\n", desc->name); 00640 }
| HOOK_T ast_tcptls_server_write | ( | struct ast_tcptls_session_instance * | ser, | |
| const void * | buf, | |||
| size_t | count | |||
| ) |
Definition at line 127 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().
00128 { 00129 if (tcptls_session->fd == -1) { 00130 ast_log(LOG_ERROR, "server_write called with an fd of -1\n"); 00131 errno = EIO; 00132 return -1; 00133 } 00134 00135 #ifdef DO_SSL 00136 if (tcptls_session->ssl) 00137 return ssl_write(tcptls_session->ssl, buf, count); 00138 #endif 00139 return write(tcptls_session->fd, buf, count); 00140 }
| 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 642 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(), __init_manager(), and reload_config().
00643 { 00644 if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) { 00645 tls_cfg->enabled = ast_true(value) ? 1 : 0; 00646 } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) { 00647 ast_free(tls_cfg->certfile); 00648 tls_cfg->certfile = ast_strdup(value); 00649 } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) { 00650 ast_free(tls_cfg->pvtfile); 00651 tls_cfg->pvtfile = ast_strdup(value); 00652 } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) { 00653 ast_free(tls_cfg->cipher); 00654 tls_cfg->cipher = ast_strdup(value); 00655 } else if (!strcasecmp(varname, "tlscafile")) { 00656 ast_free(tls_cfg->cafile); 00657 tls_cfg->cafile = ast_strdup(value); 00658 } else if (!strcasecmp(varname, "tlscapath") || !strcasecmp(varname, "tlscadir")) { 00659 ast_free(tls_cfg->capath); 00660 tls_cfg->capath = ast_strdup(value); 00661 } else if (!strcasecmp(varname, "tlsverifyclient")) { 00662 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_VERIFY_CLIENT); 00663 } else if (!strcasecmp(varname, "tlsdontverifyserver")) { 00664 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DONT_VERIFY_SERVER); 00665 } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) { 00666 if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address)) 00667 ast_log(LOG_WARNING, "Invalid %s '%s'\n", varname, value); 00668 } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) { 00669 if (!strcasecmp(value, "tlsv1")) { 00670 ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00671 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00672 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00673 } else if (!strcasecmp(value, "sslv3")) { 00674 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00675 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00676 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00677 } else if (!strcasecmp(value, "sslv2")) { 00678 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00679 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00680 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00681 } 00682 } else { 00683 return -1; 00684 } 00685 00686 return 0; 00687 }
1.6.1