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