#include "asterisk/netsock2.h"
#include "asterisk/utils.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 |
| describes a server instance More... | |
| 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), 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) |
| 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) |
| replacement read/write functions for SSL support. We use wrappers rather than SSL_read/SSL_write directly so we can put in some debugging. | |
| 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. | |
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 75 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 77 of file tcptls.h.
00077 { 00078 /*! Verify certificate when acting as server */ 00079 AST_SSL_VERIFY_CLIENT = (1 << 0), 00080 /*! Don't verify certificate when connecting to a server */ 00081 AST_SSL_DONT_VERIFY_SERVER = (1 << 1), 00082 /*! Don't compare "Common Name" against IP or hostname */ 00083 AST_SSL_IGNORE_COMMON_NAME = (1 << 2), 00084 /*! Use SSLv2 for outgoing client connections */ 00085 AST_SSL_SSLV2_CLIENT = (1 << 3), 00086 /*! Use SSLv3 for outgoing client connections */ 00087 AST_SSL_SSLV3_CLIENT = (1 << 4), 00088 /*! Use TLSv1 for outgoing client connections */ 00089 AST_SSL_TLSV1_CLIENT = (1 << 5) 00090 };
| int ast_ssl_setup | ( | struct ast_tls_config * | cfg | ) |
Definition at line 399 of file tcptls.c.
References __ssl_setup().
Referenced by __ast_http_load(), __init_manager(), and reload_config().
00400 { 00401 return __ssl_setup(cfg, 0); 00402 }
| struct ast_tcptls_session_instance* ast_tcptls_client_create | ( | struct ast_tcptls_session_args * | desc | ) | [read] |
Definition at line 441 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_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::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().
00442 { 00443 int x = 1; 00444 struct ast_tcptls_session_instance *tcptls_session = NULL; 00445 00446 /* Do nothing if nothing has changed */ 00447 if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) { 00448 ast_debug(1, "Nothing changed in %s\n", desc->name); 00449 return NULL; 00450 } 00451 00452 /* If we return early, there is no connection */ 00453 ast_sockaddr_setnull(&desc->old_address); 00454 00455 if (desc->accept_fd != -1) { 00456 close(desc->accept_fd); 00457 } 00458 00459 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ? 00460 AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP); 00461 if (desc->accept_fd < 0) { 00462 ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n", 00463 desc->name, strerror(errno)); 00464 return NULL; 00465 } 00466 00467 /* if a local address was specified, bind to it so the connection will 00468 originate from the desired address */ 00469 if (!ast_sockaddr_isnull(&desc->local_address)) { 00470 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00471 if (ast_bind(desc->accept_fd, &desc->local_address)) { 00472 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", 00473 desc->name, 00474 ast_sockaddr_stringify(&desc->local_address), 00475 strerror(errno)); 00476 goto error; 00477 } 00478 } 00479 00480 if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) { 00481 goto error; 00482 } 00483 00484 ast_mutex_init(&tcptls_session->lock); 00485 tcptls_session->client = 1; 00486 tcptls_session->fd = desc->accept_fd; 00487 tcptls_session->parent = desc; 00488 tcptls_session->parent->worker_fn = NULL; 00489 ast_sockaddr_copy(&tcptls_session->remote_address, 00490 &desc->remote_address); 00491 00492 /* Set current info */ 00493 ast_sockaddr_copy(&desc->old_address, &desc->remote_address); 00494 return tcptls_session; 00495 00496 error: 00497 close(desc->accept_fd); 00498 desc->accept_fd = -1; 00499 if (tcptls_session) { 00500 ao2_ref(tcptls_session, -1); 00501 } 00502 return NULL; 00503 }
| 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 404 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().
00405 { 00406 struct ast_tcptls_session_args *desc; 00407 int flags; 00408 00409 if (!(desc = tcptls_session->parent)) { 00410 goto client_start_error; 00411 } 00412 00413 if (ast_connect(desc->accept_fd, &desc->remote_address)) { 00414 ast_log(LOG_ERROR, "Unable to connect %s to %s: %s\n", 00415 desc->name, 00416 ast_sockaddr_stringify(&desc->remote_address), 00417 strerror(errno)); 00418 goto client_start_error; 00419 } 00420 00421 flags = fcntl(desc->accept_fd, F_GETFL); 00422 fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK); 00423 00424 if (desc->tls_cfg) { 00425 desc->tls_cfg->enabled = 1; 00426 __ssl_setup(desc->tls_cfg, 1); 00427 } 00428 00429 return handle_tcptls_connection(tcptls_session); 00430 00431 client_start_error: 00432 close(desc->accept_fd); 00433 desc->accept_fd = -1; 00434 if (tcptls_session) { 00435 ao2_ref(tcptls_session, -1); 00436 } 00437 return NULL; 00438 00439 }
| 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 575 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().
00576 { 00577 if (tcptls_session->f) { 00578 if (fclose(tcptls_session->f)) { 00579 ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno)); 00580 } 00581 tcptls_session->f = NULL; 00582 tcptls_session->fd = -1; 00583 } else if (tcptls_session->fd != -1) { 00584 if (close(tcptls_session->fd)) { 00585 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno)); 00586 } 00587 tcptls_session->fd = -1; 00588 } else { 00589 ast_log(LOG_ERROR, "ast_tcptls_close_session_file invoked on session instance without file or file descriptor\n"); 00590 } 00591 }
| HOOK_T ast_tcptls_server_read | ( | struct ast_tcptls_session_instance * | ser, | |
| void * | buf, | |||
| size_t | count | |||
| ) |
replacement read/write functions for SSL support. We use wrappers rather than SSL_read/SSL_write directly so we can put in some debugging.
Definition at line 102 of file tcptls.c.
References ast_log(), errno, ast_tcptls_session_instance::fd, LOG_ERROR, and ast_tcptls_session_instance::ssl.
00103 { 00104 if (tcptls_session->fd == -1) { 00105 ast_log(LOG_ERROR, "server_read called with an fd of -1\n"); 00106 errno = EIO; 00107 return -1; 00108 } 00109 00110 #ifdef DO_SSL 00111 if (tcptls_session->ssl) { 00112 return ssl_read(tcptls_session->ssl, buf, count); 00113 } 00114 #endif 00115 return read(tcptls_session->fd, buf, count); 00116 }
| void* ast_tcptls_server_root | ( | void * | ) |
Definition at line 263 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_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::parent, ast_tcptls_session_args::periodic_fn, ast_tcptls_session_args::poll_timeout, ast_tcptls_session_instance::remote_address, and session_instance_destructor().
00264 { 00265 struct ast_tcptls_session_args *desc = data; 00266 int fd; 00267 struct ast_sockaddr addr; 00268 struct ast_tcptls_session_instance *tcptls_session; 00269 pthread_t launched; 00270 00271 for (;;) { 00272 int i, flags; 00273 00274 if (desc->periodic_fn) { 00275 desc->periodic_fn(desc); 00276 } 00277 i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout); 00278 if (i <= 0) { 00279 continue; 00280 } 00281 fd = ast_accept(desc->accept_fd, &addr); 00282 if (fd < 0) { 00283 if ((errno != EAGAIN) && (errno != EINTR)) { 00284 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00285 } 00286 continue; 00287 } 00288 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor); 00289 if (!tcptls_session) { 00290 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00291 if (close(fd)) { 00292 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno)); 00293 } 00294 continue; 00295 } 00296 00297 ast_mutex_init(&tcptls_session->lock); 00298 00299 flags = fcntl(fd, F_GETFL); 00300 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00301 tcptls_session->fd = fd; 00302 tcptls_session->parent = desc; 00303 ast_sockaddr_copy(&tcptls_session->remote_address, &addr); 00304 00305 tcptls_session->client = 0; 00306 00307 /* This thread is now the only place that controls the single ref to tcptls_session */ 00308 if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, tcptls_session)) { 00309 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00310 ast_tcptls_close_session_file(tcptls_session); 00311 ao2_ref(tcptls_session, -1); 00312 } 00313 } 00314 return NULL; 00315 }
| 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 505 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().
00506 { 00507 int flags; 00508 int x = 1; 00509 00510 /* Do nothing if nothing has changed */ 00511 if (!ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) { 00512 ast_debug(1, "Nothing changed in %s\n", desc->name); 00513 return; 00514 } 00515 00516 /* If we return early, there is no one listening */ 00517 ast_sockaddr_setnull(&desc->old_address); 00518 00519 /* Shutdown a running server if there is one */ 00520 if (desc->master != AST_PTHREADT_NULL) { 00521 pthread_cancel(desc->master); 00522 pthread_kill(desc->master, SIGURG); 00523 pthread_join(desc->master, NULL); 00524 } 00525 00526 if (desc->accept_fd != -1) { 00527 close(desc->accept_fd); 00528 } 00529 00530 /* If there's no new server, stop here */ 00531 if (ast_sockaddr_isnull(&desc->local_address)) { 00532 ast_debug(2, "Server disabled: %s\n", desc->name); 00533 return; 00534 } 00535 00536 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ? 00537 AF_INET6 : AF_INET, SOCK_STREAM, 0); 00538 if (desc->accept_fd < 0) { 00539 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno)); 00540 return; 00541 } 00542 00543 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00544 if (ast_bind(desc->accept_fd, &desc->local_address)) { 00545 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n", 00546 desc->name, 00547 ast_sockaddr_stringify(&desc->local_address), 00548 strerror(errno)); 00549 goto error; 00550 } 00551 if (listen(desc->accept_fd, 10)) { 00552 ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name); 00553 goto error; 00554 } 00555 flags = fcntl(desc->accept_fd, F_GETFL); 00556 fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK); 00557 if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) { 00558 ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n", 00559 desc->name, 00560 ast_sockaddr_stringify(&desc->local_address), 00561 strerror(errno)); 00562 goto error; 00563 } 00564 00565 /* Set current info */ 00566 ast_sockaddr_copy(&desc->old_address, &desc->local_address); 00567 00568 return; 00569 00570 error: 00571 close(desc->accept_fd); 00572 desc->accept_fd = -1; 00573 }
| void ast_tcptls_server_stop | ( | struct ast_tcptls_session_args * | desc | ) |
Shutdown a running server if there is one.
Definition at line 593 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(), and unload_module().
00594 { 00595 if (desc->master != AST_PTHREADT_NULL) { 00596 pthread_cancel(desc->master); 00597 pthread_kill(desc->master, SIGURG); 00598 pthread_join(desc->master, NULL); 00599 desc->master = AST_PTHREADT_NULL; 00600 } 00601 if (desc->accept_fd != -1) { 00602 close(desc->accept_fd); 00603 } 00604 desc->accept_fd = -1; 00605 ast_debug(2, "Stopped server :: %s\n", desc->name); 00606 }
| HOOK_T ast_tcptls_server_write | ( | struct ast_tcptls_session_instance * | ser, | |
| const void * | buf, | |||
| size_t | count | |||
| ) |
Definition at line 118 of file tcptls.c.
References ast_log(), errno, ast_tcptls_session_instance::fd, LOG_ERROR, and ast_tcptls_session_instance::ssl.
Referenced by _sip_tcp_helper_thread().
00119 { 00120 if (tcptls_session->fd == -1) { 00121 ast_log(LOG_ERROR, "server_write called with an fd of -1\n"); 00122 errno = EIO; 00123 return -1; 00124 } 00125 00126 #ifdef DO_SSL 00127 if (tcptls_session->ssl) { 00128 return ssl_write(tcptls_session->ssl, buf, count); 00129 } 00130 #endif 00131 return write(tcptls_session->fd, buf, count); 00132 }
| 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 608 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().
00609 { 00610 if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) { 00611 tls_cfg->enabled = ast_true(value) ? 1 : 0; 00612 } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) { 00613 ast_free(tls_cfg->certfile); 00614 tls_cfg->certfile = ast_strdup(value); 00615 } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) { 00616 ast_free(tls_cfg->pvtfile); 00617 tls_cfg->pvtfile = ast_strdup(value); 00618 } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) { 00619 ast_free(tls_cfg->cipher); 00620 tls_cfg->cipher = ast_strdup(value); 00621 } else if (!strcasecmp(varname, "tlscafile")) { 00622 ast_free(tls_cfg->cafile); 00623 tls_cfg->cafile = ast_strdup(value); 00624 } else if (!strcasecmp(varname, "tlscapath") || !strcasecmp(varname, "tlscadir")) { 00625 ast_free(tls_cfg->capath); 00626 tls_cfg->capath = ast_strdup(value); 00627 } else if (!strcasecmp(varname, "tlsverifyclient")) { 00628 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_VERIFY_CLIENT); 00629 } else if (!strcasecmp(varname, "tlsdontverifyserver")) { 00630 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DONT_VERIFY_SERVER); 00631 } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) { 00632 if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address)) 00633 ast_log(LOG_WARNING, "Invalid %s '%s'\n", varname, value); 00634 } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) { 00635 if (!strcasecmp(value, "tlsv1")) { 00636 ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00637 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00638 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00639 } else if (!strcasecmp(value, "sslv3")) { 00640 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00641 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00642 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00643 } else if (!strcasecmp(value, "sslv2")) { 00644 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT); 00645 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT); 00646 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT); 00647 } 00648 } else { 00649 return -1; 00650 } 00651 00652 return 0; 00653 }
1.5.6