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