00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 373061 $")
00035
00036 #ifdef HAVE_FCNTL_H
00037 #include <fcntl.h>
00038 #endif
00039
00040 #include <signal.h>
00041 #include <sys/signal.h>
00042
00043 #include "asterisk/compat.h"
00044 #include "asterisk/tcptls.h"
00045 #include "asterisk/http.h"
00046 #include "asterisk/utils.h"
00047 #include "asterisk/strings.h"
00048 #include "asterisk/options.h"
00049 #include "asterisk/manager.h"
00050 #include "asterisk/astobj2.h"
00051
00052
00053
00054
00055
00056
00057
00058 #ifdef DO_SSL
00059 static HOOK_T ssl_read(void *cookie, char *buf, LEN_T len)
00060 {
00061 int i = SSL_read(cookie, buf, len-1);
00062 #if 0
00063 if (i >= 0)
00064 buf[i] = '\0';
00065 ast_verb(0, "ssl read size %d returns %d <%s>\n", (int)len, i, buf);
00066 #endif
00067 return i;
00068 }
00069
00070 static HOOK_T ssl_write(void *cookie, const char *buf, LEN_T len)
00071 {
00072 #if 0
00073 char *s = ast_alloca(len+1);
00074 strncpy(s, buf, len);
00075 s[len] = '\0';
00076 ast_verb(0, "ssl write size %d <%s>\n", (int)len, s);
00077 #endif
00078 return SSL_write(cookie, buf, len);
00079 }
00080
00081 static int ssl_close(void *cookie)
00082 {
00083 int cookie_fd = SSL_get_fd(cookie);
00084 int ret;
00085
00086 if (cookie_fd > -1) {
00087
00088
00089
00090
00091
00092 if ((ret = SSL_shutdown(cookie)) < 0) {
00093 ast_log(LOG_ERROR, "SSL_shutdown() failed: %d\n", SSL_get_error(cookie, ret));
00094 }
00095
00096 if (!((SSL*)cookie)->server) {
00097
00098 ERR_remove_state(0);
00099 }
00100
00101 SSL_free(cookie);
00102
00103 if (close(cookie_fd)) {
00104 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
00105 }
00106 }
00107 return 0;
00108 }
00109 #endif
00110
00111 HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *tcptls_session, void *buf, size_t count)
00112 {
00113 if (tcptls_session->fd == -1) {
00114 ast_log(LOG_ERROR, "server_read called with an fd of -1\n");
00115 errno = EIO;
00116 return -1;
00117 }
00118
00119 #ifdef DO_SSL
00120 if (tcptls_session->ssl)
00121 return ssl_read(tcptls_session->ssl, buf, count);
00122 #endif
00123 return read(tcptls_session->fd, buf, count);
00124 }
00125
00126 HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_session, const void *buf, size_t count)
00127 {
00128 if (tcptls_session->fd == -1) {
00129 ast_log(LOG_ERROR, "server_write called with an fd of -1\n");
00130 errno = EIO;
00131 return -1;
00132 }
00133
00134 #ifdef DO_SSL
00135 if (tcptls_session->ssl)
00136 return ssl_write(tcptls_session->ssl, buf, count);
00137 #endif
00138 return write(tcptls_session->fd, buf, count);
00139 }
00140
00141 static void session_instance_destructor(void *obj)
00142 {
00143 struct ast_tcptls_session_instance *i = obj;
00144 ast_mutex_destroy(&i->lock);
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154 static void *handle_tcptls_connection(void *data)
00155 {
00156 struct ast_tcptls_session_instance *tcptls_session = data;
00157 #ifdef DO_SSL
00158 int (*ssl_setup)(SSL *) = (tcptls_session->client) ? SSL_connect : SSL_accept;
00159 int ret;
00160 char err[256];
00161 #endif
00162
00163
00164
00165
00166 if (!tcptls_session->parent->tls_cfg) {
00167 if ((tcptls_session->f = fdopen(tcptls_session->fd, "w+"))) {
00168 if(setvbuf(tcptls_session->f, NULL, _IONBF, 0)) {
00169 ast_tcptls_close_session_file(tcptls_session);
00170 }
00171 }
00172 }
00173 #ifdef DO_SSL
00174 else if ( (tcptls_session->ssl = SSL_new(tcptls_session->parent->tls_cfg->ssl_ctx)) ) {
00175 SSL_set_fd(tcptls_session->ssl, tcptls_session->fd);
00176 if ((ret = ssl_setup(tcptls_session->ssl)) <= 0) {
00177 ast_verb(2, "Problem setting up ssl connection: %s\n", ERR_error_string(ERR_get_error(), err));
00178 } else {
00179 #if defined(HAVE_FUNOPEN)
00180 tcptls_session->f = funopen(tcptls_session->ssl, ssl_read, ssl_write, NULL, ssl_close);
00181
00182 #elif defined(HAVE_FOPENCOOKIE)
00183 static const cookie_io_functions_t cookie_funcs = {
00184 ssl_read, ssl_write, NULL, ssl_close
00185 };
00186 tcptls_session->f = fopencookie(tcptls_session->ssl, "w+", cookie_funcs);
00187 #else
00188
00189 ast_debug(2, "no tcptls_session->f methods attempted!\n");
00190 #endif
00191 if ((tcptls_session->client && !ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_DONT_VERIFY_SERVER))
00192 || (!tcptls_session->client && ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_VERIFY_CLIENT))) {
00193 X509 *peer;
00194 long res;
00195 peer = SSL_get_peer_certificate(tcptls_session->ssl);
00196 if (!peer)
00197 ast_log(LOG_WARNING, "No peer SSL certificate\n");
00198 res = SSL_get_verify_result(tcptls_session->ssl);
00199 if (res != X509_V_OK)
00200 ast_log(LOG_ERROR, "Certificate did not verify: %s\n", X509_verify_cert_error_string(res));
00201 if (!ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_IGNORE_COMMON_NAME)) {
00202 ASN1_STRING *str;
00203 unsigned char *str2;
00204 X509_NAME *name = X509_get_subject_name(peer);
00205 int pos = -1;
00206 int found = 0;
00207
00208 for (;;) {
00209
00210
00211 pos = X509_NAME_get_index_by_NID(name, NID_commonName, pos);
00212 if (pos < 0)
00213 break;
00214 str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, pos));
00215 ASN1_STRING_to_UTF8(&str2, str);
00216 if (str2) {
00217 if (!strcasecmp(tcptls_session->parent->hostname, (char *) str2))
00218 found = 1;
00219 ast_debug(3, "SSL Common Name compare s1='%s' s2='%s'\n", tcptls_session->parent->hostname, str2);
00220 OPENSSL_free(str2);
00221 }
00222 if (found)
00223 break;
00224 }
00225 if (!found) {
00226 ast_log(LOG_ERROR, "Certificate common name did not match (%s)\n", tcptls_session->parent->hostname);
00227 if (peer) {
00228 X509_free(peer);
00229 }
00230 ast_tcptls_close_session_file(tcptls_session);
00231 ao2_ref(tcptls_session, -1);
00232 return NULL;
00233 }
00234 }
00235 if (peer)
00236 X509_free(peer);
00237 }
00238 }
00239 if (!tcptls_session->f)
00240 SSL_free(tcptls_session->ssl);
00241 }
00242 #endif
00243
00244 if (!tcptls_session->f) {
00245 ast_tcptls_close_session_file(tcptls_session);
00246 ast_log(LOG_WARNING, "FILE * open failed!\n");
00247 #ifndef DO_SSL
00248 if (tcptls_session->parent->tls_cfg) {
00249 ast_log(LOG_WARNING, "Attempted a TLS connection without OpenSSL support. This will not work!\n");
00250 }
00251 #endif
00252 ao2_ref(tcptls_session, -1);
00253 return NULL;
00254 }
00255
00256 if (tcptls_session->parent->worker_fn) {
00257 return tcptls_session->parent->worker_fn(tcptls_session);
00258 } else {
00259 return tcptls_session;
00260 }
00261 }
00262
00263 void *ast_tcptls_server_root(void *data)
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 i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout);
00277 if (i <= 0)
00278 continue;
00279 fd = ast_accept(desc->accept_fd, &addr);
00280 if (fd < 0) {
00281 if ((errno != EAGAIN) && (errno != EINTR))
00282 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
00283 continue;
00284 }
00285 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor);
00286 if (!tcptls_session) {
00287 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
00288 if (close(fd)) {
00289 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
00290 }
00291 continue;
00292 }
00293
00294 ast_mutex_init(&tcptls_session->lock);
00295
00296 flags = fcntl(fd, F_GETFL);
00297 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
00298 tcptls_session->fd = fd;
00299 tcptls_session->parent = desc;
00300 ast_sockaddr_copy(&tcptls_session->remote_address, &addr);
00301
00302 tcptls_session->client = 0;
00303
00304
00305 if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, tcptls_session)) {
00306 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
00307 ast_tcptls_close_session_file(tcptls_session);
00308 ao2_ref(tcptls_session, -1);
00309 }
00310 }
00311 return NULL;
00312 }
00313
00314 static int __ssl_setup(struct ast_tls_config *cfg, int client)
00315 {
00316 #ifndef DO_SSL
00317 cfg->enabled = 0;
00318 return 0;
00319 #else
00320 if (!cfg->enabled)
00321 return 0;
00322
00323
00324
00325
00326 if (cfg->ssl_ctx) {
00327 SSL_CTX_free(cfg->ssl_ctx);
00328 cfg->ssl_ctx = NULL;
00329 }
00330
00331 if (client) {
00332 #ifndef OPENSSL_NO_SSL2
00333 if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) {
00334 cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method());
00335 } else
00336 #endif
00337 if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) {
00338 cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
00339 } else if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) {
00340 cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
00341 } else {
00342
00343
00344
00345
00346 cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
00347 }
00348 } else {
00349
00350 cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
00351 }
00352
00353 if (!cfg->ssl_ctx) {
00354 ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n");
00355 cfg->enabled = 0;
00356 return 0;
00357 }
00358 if (!ast_strlen_zero(cfg->certfile)) {
00359 char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile;
00360 if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0) {
00361 if (!client) {
00362
00363 ast_verb(0, "SSL error loading cert file. <%s>", cfg->certfile);
00364 cfg->enabled = 0;
00365 SSL_CTX_free(cfg->ssl_ctx);
00366 cfg->ssl_ctx = NULL;
00367 return 0;
00368 }
00369 }
00370 if ((SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, tmpprivate, SSL_FILETYPE_PEM) == 0) || (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 )) {
00371 if (!client) {
00372
00373 ast_verb(0, "SSL error loading private key file. <%s>", tmpprivate);
00374 cfg->enabled = 0;
00375 SSL_CTX_free(cfg->ssl_ctx);
00376 cfg->ssl_ctx = NULL;
00377 return 0;
00378 }
00379 }
00380 }
00381 if (!ast_strlen_zero(cfg->cipher)) {
00382 if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) {
00383 if (!client) {
00384 ast_verb(0, "SSL cipher error <%s>", cfg->cipher);
00385 cfg->enabled = 0;
00386 SSL_CTX_free(cfg->ssl_ctx);
00387 cfg->ssl_ctx = NULL;
00388 return 0;
00389 }
00390 }
00391 }
00392 if (!ast_strlen_zero(cfg->cafile) || !ast_strlen_zero(cfg->capath)) {
00393 if (SSL_CTX_load_verify_locations(cfg->ssl_ctx, S_OR(cfg->cafile, NULL), S_OR(cfg->capath,NULL)) == 0)
00394 ast_verb(0, "SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath);
00395 }
00396
00397 ast_verb(0, "SSL certificate ok\n");
00398 return 1;
00399 #endif
00400 }
00401
00402 int ast_ssl_setup(struct ast_tls_config *cfg)
00403 {
00404 return __ssl_setup(cfg, 0);
00405 }
00406
00407 void ast_ssl_teardown(struct ast_tls_config *cfg)
00408 {
00409 #ifdef DO_SSL
00410 if (cfg->ssl_ctx) {
00411 SSL_CTX_free(cfg->ssl_ctx);
00412 cfg->ssl_ctx = NULL;
00413 }
00414 #endif
00415 }
00416
00417 struct ast_tcptls_session_instance *ast_tcptls_client_start(struct ast_tcptls_session_instance *tcptls_session)
00418 {
00419 struct ast_tcptls_session_args *desc;
00420 int flags;
00421
00422 if (!(desc = tcptls_session->parent)) {
00423 goto client_start_error;
00424 }
00425
00426 if (ast_connect(desc->accept_fd, &desc->remote_address)) {
00427 ast_log(LOG_ERROR, "Unable to connect %s to %s: %s\n",
00428 desc->name,
00429 ast_sockaddr_stringify(&desc->remote_address),
00430 strerror(errno));
00431 goto client_start_error;
00432 }
00433
00434 flags = fcntl(desc->accept_fd, F_GETFL);
00435 fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK);
00436
00437 if (desc->tls_cfg) {
00438 desc->tls_cfg->enabled = 1;
00439 __ssl_setup(desc->tls_cfg, 1);
00440 }
00441
00442 return handle_tcptls_connection(tcptls_session);
00443
00444 client_start_error:
00445 if (desc) {
00446 close(desc->accept_fd);
00447 desc->accept_fd = -1;
00448 }
00449 ao2_ref(tcptls_session, -1);
00450 return NULL;
00451
00452 }
00453
00454 struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_session_args *desc)
00455 {
00456 int x = 1;
00457 struct ast_tcptls_session_instance *tcptls_session = NULL;
00458
00459
00460 if (!ast_sockaddr_cmp(&desc->old_address, &desc->remote_address)) {
00461 ast_debug(1, "Nothing changed in %s\n", desc->name);
00462 return NULL;
00463 }
00464
00465
00466 ast_sockaddr_setnull(&desc->old_address);
00467
00468 if (desc->accept_fd != -1)
00469 close(desc->accept_fd);
00470
00471 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->remote_address) ?
00472 AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
00473 if (desc->accept_fd < 0) {
00474 ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n",
00475 desc->name, strerror(errno));
00476 return NULL;
00477 }
00478
00479
00480
00481 if (!ast_sockaddr_isnull(&desc->local_address)) {
00482 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
00483 if (ast_bind(desc->accept_fd, &desc->local_address)) {
00484 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
00485 desc->name,
00486 ast_sockaddr_stringify(&desc->local_address),
00487 strerror(errno));
00488 goto error;
00489 }
00490 }
00491
00492 if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor)))
00493 goto error;
00494
00495 ast_mutex_init(&tcptls_session->lock);
00496 tcptls_session->client = 1;
00497 tcptls_session->fd = desc->accept_fd;
00498 tcptls_session->parent = desc;
00499 tcptls_session->parent->worker_fn = NULL;
00500 ast_sockaddr_copy(&tcptls_session->remote_address,
00501 &desc->remote_address);
00502
00503
00504 ast_sockaddr_copy(&desc->old_address, &desc->remote_address);
00505 return tcptls_session;
00506
00507 error:
00508 close(desc->accept_fd);
00509 desc->accept_fd = -1;
00510 if (tcptls_session)
00511 ao2_ref(tcptls_session, -1);
00512 return NULL;
00513 }
00514
00515 void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
00516 {
00517 int flags;
00518 int x = 1;
00519
00520
00521 if (!ast_sockaddr_cmp(&desc->old_address, &desc->local_address)) {
00522 ast_debug(1, "Nothing changed in %s\n", desc->name);
00523 return;
00524 }
00525
00526
00527 ast_sockaddr_setnull(&desc->old_address);
00528
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
00536 if (desc->accept_fd != -1)
00537 close(desc->accept_fd);
00538
00539
00540 if (ast_sockaddr_isnull(&desc->local_address)) {
00541 ast_debug(2, "Server disabled: %s\n", desc->name);
00542 return;
00543 }
00544
00545 desc->accept_fd = socket(ast_sockaddr_is_ipv6(&desc->local_address) ?
00546 AF_INET6 : AF_INET, SOCK_STREAM, 0);
00547 if (desc->accept_fd < 0) {
00548 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
00549 return;
00550 }
00551
00552 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
00553 if (ast_bind(desc->accept_fd, &desc->local_address)) {
00554 ast_log(LOG_ERROR, "Unable to bind %s to %s: %s\n",
00555 desc->name,
00556 ast_sockaddr_stringify(&desc->local_address),
00557 strerror(errno));
00558 goto error;
00559 }
00560 if (listen(desc->accept_fd, 10)) {
00561 ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name);
00562 goto error;
00563 }
00564 flags = fcntl(desc->accept_fd, F_GETFL);
00565 fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK);
00566 if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
00567 ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
00568 desc->name,
00569 ast_sockaddr_stringify(&desc->local_address),
00570 strerror(errno));
00571 goto error;
00572 }
00573
00574
00575 ast_sockaddr_copy(&desc->old_address, &desc->local_address);
00576
00577 return;
00578
00579 error:
00580 close(desc->accept_fd);
00581 desc->accept_fd = -1;
00582 }
00583
00584 void ast_tcptls_close_session_file(struct ast_tcptls_session_instance *tcptls_session)
00585 {
00586 if (tcptls_session->f) {
00587 if (fclose(tcptls_session->f)) {
00588 ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno));
00589 }
00590 tcptls_session->f = NULL;
00591 tcptls_session->fd = -1;
00592 } else if (tcptls_session->fd != -1) {
00593 if (close(tcptls_session->fd)) {
00594 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
00595 }
00596 tcptls_session->fd = -1;
00597 } else {
00598 ast_log(LOG_ERROR, "ast_tcptls_close_session_file invoked on session instance without file or file descriptor\n");
00599 }
00600 }
00601
00602 void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc)
00603 {
00604 if (desc->master != AST_PTHREADT_NULL) {
00605 pthread_cancel(desc->master);
00606 pthread_kill(desc->master, SIGURG);
00607 pthread_join(desc->master, NULL);
00608 desc->master = AST_PTHREADT_NULL;
00609 }
00610 if (desc->accept_fd != -1)
00611 close(desc->accept_fd);
00612 desc->accept_fd = -1;
00613 ast_debug(2, "Stopped server :: %s\n", desc->name);
00614 }
00615
00616 int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_args *tls_desc, const char *varname, const char *value)
00617 {
00618 if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) {
00619 tls_cfg->enabled = ast_true(value) ? 1 : 0;
00620 } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) {
00621 ast_free(tls_cfg->certfile);
00622 tls_cfg->certfile = ast_strdup(value);
00623 } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) {
00624 ast_free(tls_cfg->pvtfile);
00625 tls_cfg->pvtfile = ast_strdup(value);
00626 } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) {
00627 ast_free(tls_cfg->cipher);
00628 tls_cfg->cipher = ast_strdup(value);
00629 } else if (!strcasecmp(varname, "tlscafile")) {
00630 ast_free(tls_cfg->cafile);
00631 tls_cfg->cafile = ast_strdup(value);
00632 } else if (!strcasecmp(varname, "tlscapath") || !strcasecmp(varname, "tlscadir")) {
00633 ast_free(tls_cfg->capath);
00634 tls_cfg->capath = ast_strdup(value);
00635 } else if (!strcasecmp(varname, "tlsverifyclient")) {
00636 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_VERIFY_CLIENT);
00637 } else if (!strcasecmp(varname, "tlsdontverifyserver")) {
00638 ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DONT_VERIFY_SERVER);
00639 } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) {
00640 if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address))
00641 ast_log(LOG_WARNING, "Invalid %s '%s'\n", varname, value);
00642 } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) {
00643 if (!strcasecmp(value, "tlsv1")) {
00644 ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
00645 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
00646 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
00647 } else if (!strcasecmp(value, "sslv3")) {
00648 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
00649 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
00650 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
00651 } else if (!strcasecmp(value, "sslv2")) {
00652 ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
00653 ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
00654 ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
00655 }
00656 } else {
00657 return -1;
00658 }
00659
00660 return 0;
00661 }