#include "asterisk.h"
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
#include "asterisk/compat.h"
#include "asterisk/tcptls.h"
#include "asterisk/http.h"
#include "asterisk/utils.h"
#include "asterisk/strings.h"
#include "asterisk/options.h"
#include "asterisk/manager.h"
#include "asterisk/astobj2.h"
Go to the source code of this file.
Functions | |
static int | __ssl_setup (struct ast_tls_config *cfg, int client) |
int | ast_ssl_setup (struct ast_tls_config *cfg) |
ast_tcptls_session_instance * | ast_tcptls_client_create (struct ast_tcptls_session_args *desc) |
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. | |
HOOK_T | ast_tcptls_server_read (struct ast_tcptls_session_instance *tcptls_session, void *buf, size_t count) |
void * | ast_tcptls_server_root (void *data) |
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 *tcptls_session, void *buf, size_t count) |
static void * | handle_tcptls_connection (void *data) |
creates a FILE * from the fd passed by the accept thread. This operation is potentially expensive (certificate verification), so we do it in the child thread context. | |
static void | session_instance_destructor (void *obj) |
static int | ssl_close (void *cookie) |
static HOOK_T | ssl_read (void *cookie, char *buf, LEN_T len) |
replacement read/write functions for SSL support. We use wrappers rather than SSL_read/SSL_write directly so we can put in some debugging. | |
static HOOK_T | ssl_write (void *cookie, const char *buf, LEN_T len) |
Brett Bryant <brettbryant@gmail.com>
Definition in file tcptls.c.
static int __ssl_setup | ( | struct ast_tls_config * | cfg, | |
int | client | |||
) | [static] |
Definition at line 285 of file tcptls.c.
References ast_debug, ast_strlen_zero(), ast_verb, ast_tls_config::cafile, ast_tls_config::capath, ast_tls_config::certfile, ast_tls_config::cipher, ast_tls_config::enabled, S_OR, and ast_tls_config::ssl_ctx.
Referenced by ast_ssl_setup(), and ast_tcptls_client_start().
00286 { 00287 #ifndef DO_SSL 00288 cfg->enabled = 0; 00289 return 0; 00290 #else 00291 if (!cfg->enabled) 00292 return 0; 00293 00294 SSL_load_error_strings(); 00295 SSLeay_add_ssl_algorithms(); 00296 00297 if (!(cfg->ssl_ctx = SSL_CTX_new( client ? SSLv23_client_method() : SSLv23_server_method() ))) { 00298 ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n"); 00299 cfg->enabled = 0; 00300 return 0; 00301 } 00302 if (!ast_strlen_zero(cfg->certfile)) { 00303 if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 || 00304 SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 || 00305 SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 ) { 00306 if (!client) { 00307 /* Clients don't need a certificate, but if its setup we can use it */ 00308 ast_verb(0, "SSL cert error <%s>", cfg->certfile); 00309 sleep(2); 00310 cfg->enabled = 0; 00311 return 0; 00312 } 00313 } 00314 } 00315 if (!ast_strlen_zero(cfg->cipher)) { 00316 if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) { 00317 if (!client) { 00318 ast_verb(0, "SSL cipher error <%s>", cfg->cipher); 00319 sleep(2); 00320 cfg->enabled = 0; 00321 return 0; 00322 } 00323 } 00324 } 00325 if (!ast_strlen_zero(cfg->cafile) || !ast_strlen_zero(cfg->capath)) { 00326 if (SSL_CTX_load_verify_locations(cfg->ssl_ctx, S_OR(cfg->cafile, NULL), S_OR(cfg->capath,NULL)) == 0) 00327 ast_verb(0, "SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath); 00328 } 00329 00330 ast_verb(0, "SSL certificate ok\n"); 00331 return 1; 00332 #endif 00333 }
int ast_ssl_setup | ( | struct ast_tls_config * | cfg | ) |
Definition at line 335 of file tcptls.c.
References __ssl_setup().
00336 { 00337 return __ssl_setup(cfg, 0); 00338 }
struct ast_tcptls_session_instance* ast_tcptls_client_create | ( | struct ast_tcptls_session_args * | desc | ) |
Definition at line 377 of file tcptls.c.
References ao2_alloc, ao2_ref, ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_init(), desc, errno, LOG_ERROR, LOG_WARNING, and session_instance_destructor().
Referenced by sip_prepare_socket().
00378 { 00379 int x = 1; 00380 struct ast_tcptls_session_instance *tcptls_session = NULL; 00381 00382 /* Do nothing if nothing has changed */ 00383 if (!memcmp(&desc->old_address, &desc->remote_address, sizeof(desc->old_address))) { 00384 ast_debug(1, "Nothing changed in %s\n", desc->name); 00385 return NULL; 00386 } 00387 00388 desc->old_address = desc->remote_address; 00389 00390 if (desc->accept_fd != -1) 00391 close(desc->accept_fd); 00392 00393 desc->accept_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 00394 if (desc->accept_fd < 0) { 00395 ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n", 00396 desc->name, strerror(errno)); 00397 return NULL; 00398 } 00399 00400 /* if a local address was specified, bind to it so the connection will 00401 originate from the desired address */ 00402 if (desc->local_address.sin_family != 0) { 00403 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00404 if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) { 00405 ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n", 00406 desc->name, 00407 ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port), 00408 strerror(errno)); 00409 goto error; 00410 } 00411 } 00412 00413 if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) 00414 goto error; 00415 00416 ast_mutex_init(&tcptls_session->lock); 00417 tcptls_session->client = 1; 00418 tcptls_session->fd = desc->accept_fd; 00419 tcptls_session->parent = desc; 00420 tcptls_session->parent->worker_fn = NULL; 00421 memcpy(&tcptls_session->remote_address, &desc->remote_address, sizeof(tcptls_session->remote_address)); 00422 00423 return tcptls_session; 00424 00425 error: 00426 close(desc->accept_fd); 00427 desc->accept_fd = -1; 00428 if (tcptls_session) 00429 ao2_ref(tcptls_session, -1); 00430 return NULL; 00431 }
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.
Definition at line 340 of file tcptls.c.
References __ssl_setup(), ao2_ref, ast_inet_ntoa(), ast_log(), desc, errno, handle_tcptls_connection(), LOG_ERROR, and ast_tcptls_session_instance::parent.
Referenced by _sip_tcp_helper_thread().
00341 { 00342 struct ast_tcptls_session_args *desc; 00343 int flags; 00344 00345 if (!(desc = tcptls_session->parent)) { 00346 goto client_start_error; 00347 } 00348 00349 if (connect(desc->accept_fd, (const struct sockaddr *) &desc->remote_address, sizeof(desc->remote_address))) { 00350 ast_log(LOG_ERROR, "Unable to connect %s to %s:%d: %s\n", 00351 desc->name, 00352 ast_inet_ntoa(desc->remote_address.sin_addr), ntohs(desc->remote_address.sin_port), 00353 strerror(errno)); 00354 goto client_start_error; 00355 } 00356 00357 flags = fcntl(desc->accept_fd, F_GETFL); 00358 fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK); 00359 00360 if (desc->tls_cfg) { 00361 desc->tls_cfg->enabled = 1; 00362 __ssl_setup(desc->tls_cfg, 1); 00363 } 00364 00365 return handle_tcptls_connection(tcptls_session); 00366 00367 client_start_error: 00368 close(desc->accept_fd); 00369 desc->accept_fd = -1; 00370 if (tcptls_session) { 00371 ao2_ref(tcptls_session, -1); 00372 } 00373 return NULL; 00374 00375 }
HOOK_T ast_tcptls_server_read | ( | struct ast_tcptls_session_instance * | tcptls_session, | |
void * | buf, | |||
size_t | count | |||
) |
Definition at line 86 of file tcptls.c.
References ast_log(), errno, ast_tcptls_session_instance::fd, LOG_ERROR, ast_tcptls_session_instance::ssl, and ssl_read().
00087 { 00088 if (tcptls_session->fd == -1) { 00089 ast_log(LOG_ERROR, "server_read called with an fd of -1\n"); 00090 errno = EIO; 00091 return -1; 00092 } 00093 00094 #ifdef DO_SSL 00095 if (tcptls_session->ssl) 00096 return ssl_read(tcptls_session->ssl, buf, count); 00097 #endif 00098 return read(tcptls_session->fd, buf, count); 00099 }
void* ast_tcptls_server_root | ( | void * | data | ) |
Definition at line 234 of file tcptls.c.
References ao2_alloc, ao2_ref, ast_log(), ast_mutex_init(), ast_pthread_create_detached_background, ast_wait_for_input(), desc, errno, handle_tcptls_connection(), LOG_WARNING, and session_instance_destructor().
00235 { 00236 struct ast_tcptls_session_args *desc = data; 00237 int fd; 00238 struct sockaddr_in sin; 00239 socklen_t sinlen; 00240 struct ast_tcptls_session_instance *tcptls_session; 00241 pthread_t launched; 00242 00243 for (;;) { 00244 int i, flags; 00245 00246 if (desc->periodic_fn) 00247 desc->periodic_fn(desc); 00248 i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout); 00249 if (i <= 0) 00250 continue; 00251 sinlen = sizeof(sin); 00252 fd = accept(desc->accept_fd, (struct sockaddr *) &sin, &sinlen); 00253 if (fd < 0) { 00254 if ((errno != EAGAIN) && (errno != EINTR)) 00255 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00256 continue; 00257 } 00258 tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor); 00259 if (!tcptls_session) { 00260 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00261 close(fd); 00262 continue; 00263 } 00264 00265 ast_mutex_init(&tcptls_session->lock); 00266 00267 flags = fcntl(fd, F_GETFL); 00268 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00269 tcptls_session->fd = fd; 00270 tcptls_session->parent = desc; 00271 memcpy(&tcptls_session->remote_address, &sin, sizeof(tcptls_session->remote_address)); 00272 00273 tcptls_session->client = 0; 00274 00275 /* This thread is now the only place that controls the single ref to tcptls_session */ 00276 if (ast_pthread_create_detached_background(&launched, NULL, handle_tcptls_connection, tcptls_session)) { 00277 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00278 close(tcptls_session->fd); 00279 ao2_ref(tcptls_session, -1); 00280 } 00281 } 00282 return NULL; 00283 }
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 433 of file tcptls.c.
References ast_debug, ast_inet_ntoa(), ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, desc, errno, and LOG_ERROR.
00434 { 00435 int flags; 00436 int x = 1; 00437 00438 /* Do nothing if nothing has changed */ 00439 if (!memcmp(&desc->old_address, &desc->local_address, sizeof(desc->old_address))) { 00440 ast_debug(1, "Nothing changed in %s\n", desc->name); 00441 return; 00442 } 00443 00444 desc->old_address = desc->local_address; 00445 00446 /* Shutdown a running server if there is one */ 00447 if (desc->master != AST_PTHREADT_NULL) { 00448 pthread_cancel(desc->master); 00449 pthread_kill(desc->master, SIGURG); 00450 pthread_join(desc->master, NULL); 00451 } 00452 00453 if (desc->accept_fd != -1) 00454 close(desc->accept_fd); 00455 00456 /* If there's no new server, stop here */ 00457 if (desc->local_address.sin_family == 0) { 00458 return; 00459 } 00460 00461 desc->accept_fd = socket(AF_INET, SOCK_STREAM, 0); 00462 if (desc->accept_fd < 0) { 00463 ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", 00464 desc->name, strerror(errno)); 00465 return; 00466 } 00467 00468 setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00469 if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) { 00470 ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n", 00471 desc->name, 00472 ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port), 00473 strerror(errno)); 00474 goto error; 00475 } 00476 if (listen(desc->accept_fd, 10)) { 00477 ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name); 00478 goto error; 00479 } 00480 flags = fcntl(desc->accept_fd, F_GETFL); 00481 fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK); 00482 if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) { 00483 ast_log(LOG_ERROR, "Unable to launch thread for %s on %s:%d: %s\n", 00484 desc->name, 00485 ast_inet_ntoa(desc->local_address.sin_addr), ntohs(desc->local_address.sin_port), 00486 strerror(errno)); 00487 goto error; 00488 } 00489 return; 00490 00491 error: 00492 close(desc->accept_fd); 00493 desc->accept_fd = -1; 00494 }
void ast_tcptls_server_stop | ( | struct ast_tcptls_session_args * | desc | ) |
Shutdown a running server if there is one.
Definition at line 496 of file tcptls.c.
References AST_PTHREADT_NULL, and desc.
Referenced by unload_module().
00497 { 00498 if (desc->master != AST_PTHREADT_NULL) { 00499 pthread_cancel(desc->master); 00500 pthread_kill(desc->master, SIGURG); 00501 pthread_join(desc->master, NULL); 00502 } 00503 if (desc->accept_fd != -1) 00504 close(desc->accept_fd); 00505 desc->accept_fd = -1; 00506 }
HOOK_T ast_tcptls_server_write | ( | struct ast_tcptls_session_instance * | tcptls_session, | |
void * | buf, | |||
size_t | count | |||
) |
Definition at line 101 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().
00102 { 00103 if (tcptls_session->fd == -1) { 00104 ast_log(LOG_ERROR, "server_write called with an fd of -1\n"); 00105 errno = EIO; 00106 return -1; 00107 } 00108 00109 #ifdef DO_SSL 00110 if (tcptls_session->ssl) 00111 return ssl_write(tcptls_session->ssl, buf, count); 00112 #endif 00113 return write(tcptls_session->fd, buf, count); 00114 }
static void* handle_tcptls_connection | ( | void * | data | ) | [static] |
creates a FILE * from the fd passed by the accept thread. This operation is potentially expensive (certificate verification), so we do it in the child thread context.
Definition at line 129 of file tcptls.c.
References ao2_ref, ast_debug, ast_log(), AST_SSL_DONT_VERIFY_SERVER, AST_SSL_IGNORE_COMMON_NAME, AST_SSL_VERIFY_CLIENT, ast_test_flag, ast_verb, ast_tcptls_session_instance::client, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, ast_tls_config::flags, ast_tcptls_session_args::hostname, LOG_ERROR, LOG_WARNING, name, ast_tcptls_session_instance::parent, ast_tcptls_session_instance::ssl, ssl_close(), ast_tls_config::ssl_ctx, ssl_read(), ssl_write(), str, ast_tcptls_session_args::tls_cfg, and ast_tcptls_session_args::worker_fn.
Referenced by ast_tcptls_client_start(), and ast_tcptls_server_root().
00130 { 00131 struct ast_tcptls_session_instance *tcptls_session = data; 00132 #ifdef DO_SSL 00133 int (*ssl_setup)(SSL *) = (tcptls_session->client) ? SSL_connect : SSL_accept; 00134 int ret; 00135 char err[256]; 00136 #endif 00137 00138 /* 00139 * open a FILE * as appropriate. 00140 */ 00141 if (!tcptls_session->parent->tls_cfg) { 00142 tcptls_session->f = fdopen(tcptls_session->fd, "w+"); 00143 setvbuf(tcptls_session->f, NULL, _IONBF, 0); 00144 } 00145 #ifdef DO_SSL 00146 else if ( (tcptls_session->ssl = SSL_new(tcptls_session->parent->tls_cfg->ssl_ctx)) ) { 00147 SSL_set_fd(tcptls_session->ssl, tcptls_session->fd); 00148 if ((ret = ssl_setup(tcptls_session->ssl)) <= 0) { 00149 ast_verb(2, "Problem setting up ssl connection: %s\n", ERR_error_string(ERR_get_error(), err)); 00150 } else { 00151 #if defined(HAVE_FUNOPEN) /* the BSD interface */ 00152 tcptls_session->f = funopen(tcptls_session->ssl, ssl_read, ssl_write, NULL, ssl_close); 00153 00154 #elif defined(HAVE_FOPENCOOKIE) /* the glibc/linux interface */ 00155 static const cookie_io_functions_t cookie_funcs = { 00156 ssl_read, ssl_write, NULL, ssl_close 00157 }; 00158 tcptls_session->f = fopencookie(tcptls_session->ssl, "w+", cookie_funcs); 00159 #else 00160 /* could add other methods here */ 00161 ast_debug(2, "no tcptls_session->f methods attempted!"); 00162 #endif 00163 if ((tcptls_session->client && !ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_DONT_VERIFY_SERVER)) 00164 || (!tcptls_session->client && ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_VERIFY_CLIENT))) { 00165 X509 *peer; 00166 long res; 00167 peer = SSL_get_peer_certificate(tcptls_session->ssl); 00168 if (!peer) 00169 ast_log(LOG_WARNING, "No peer SSL certificate\n"); 00170 res = SSL_get_verify_result(tcptls_session->ssl); 00171 if (res != X509_V_OK) 00172 ast_log(LOG_ERROR, "Certificate did not verify: %s\n", X509_verify_cert_error_string(res)); 00173 if (!ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_IGNORE_COMMON_NAME)) { 00174 ASN1_STRING *str; 00175 unsigned char *str2; 00176 X509_NAME *name = X509_get_subject_name(peer); 00177 int pos = -1; 00178 int found = 0; 00179 00180 for (;;) { 00181 /* Walk the certificate to check all available "Common Name" */ 00182 /* XXX Probably should do a gethostbyname on the hostname and compare that as well */ 00183 pos = X509_NAME_get_index_by_NID(name, NID_commonName, pos); 00184 if (pos < 0) 00185 break; 00186 str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, pos)); 00187 ASN1_STRING_to_UTF8(&str2, str); 00188 if (str2) { 00189 if (!strcasecmp(tcptls_session->parent->hostname, (char *) str2)) 00190 found = 1; 00191 ast_debug(3, "SSL Common Name compare s1='%s' s2='%s'\n", tcptls_session->parent->hostname, str2); 00192 OPENSSL_free(str2); 00193 } 00194 if (found) 00195 break; 00196 } 00197 if (!found) { 00198 ast_log(LOG_ERROR, "Certificate common name did not match (%s)\n", tcptls_session->parent->hostname); 00199 if (peer) 00200 X509_free(peer); 00201 close(tcptls_session->fd); 00202 fclose(tcptls_session->f); 00203 ao2_ref(tcptls_session, -1); 00204 return NULL; 00205 } 00206 } 00207 if (peer) 00208 X509_free(peer); 00209 } 00210 } 00211 if (!tcptls_session->f) /* no success opening descriptor stacking */ 00212 SSL_free(tcptls_session->ssl); 00213 } 00214 #endif /* DO_SSL */ 00215 00216 if (!tcptls_session->f) { 00217 close(tcptls_session->fd); 00218 ast_log(LOG_WARNING, "FILE * open failed!\n"); 00219 #ifndef DO_SSL 00220 if (tcptls_session->parent->tls_cfg) { 00221 ast_log(LOG_WARNING, "Attempted a TLS connection without OpenSSL support. This will not work!\n"); 00222 } 00223 #endif 00224 ao2_ref(tcptls_session, -1); 00225 return NULL; 00226 } 00227 00228 if (tcptls_session && tcptls_session->parent->worker_fn) 00229 return tcptls_session->parent->worker_fn(tcptls_session); 00230 else 00231 return tcptls_session; 00232 }
static void session_instance_destructor | ( | void * | obj | ) | [static] |
Definition at line 116 of file tcptls.c.
References ast_mutex_destroy(), and ast_tcptls_session_instance::lock.
Referenced by ast_tcptls_client_create(), and ast_tcptls_server_root().
00117 { 00118 struct ast_tcptls_session_instance *i = obj; 00119 ast_mutex_destroy(&i->lock); 00120 }
static int ssl_close | ( | void * | cookie | ) | [static] |
Definition at line 77 of file tcptls.c.
Referenced by handle_tcptls_connection().
00078 { 00079 close(SSL_get_fd(cookie)); 00080 SSL_shutdown(cookie); 00081 SSL_free(cookie); 00082 return 0; 00083 }
static HOOK_T ssl_read | ( | void * | cookie, | |
char * | buf, | |||
LEN_T | len | |||
) | [static] |
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 55 of file tcptls.c.
References ast_verb.
Referenced by ast_tcptls_server_read(), and handle_tcptls_connection().
00056 { 00057 int i = SSL_read(cookie, buf, len-1); 00058 #if 0 00059 if (i >= 0) 00060 buf[i] = '\0'; 00061 ast_verb(0, "ssl read size %d returns %d <%s>\n", (int)len, i, buf); 00062 #endif 00063 return i; 00064 }
static HOOK_T ssl_write | ( | void * | cookie, | |
const char * | buf, | |||
LEN_T | len | |||
) | [static] |
Definition at line 66 of file tcptls.c.
Referenced by ast_tcptls_server_write(), and handle_tcptls_connection().
00067 { 00068 #if 0 00069 char *s = alloca(len+1); 00070 strncpy(s, buf, len); 00071 s[len] = '\0'; 00072 ast_verb(0, "ssl write size %d <%s>\n", (int)len, s); 00073 #endif 00074 return SSL_write(cookie, buf, len); 00075 }