Преглед на файлове

tls: completed the code for event_route[tls:connection-out]

- event route executed after the connect to destination is done
- using drop() in the event route marks connection for no-send data, so
  nothing is sent over it, being also closed
- added also support for kemi interface
- new mod param: event_callback - specify the name of kemi callback
  function
Daniel-Constantin Mierla преди 8 години
родител
ревизия
5a889756a5
променени са 3 файла, в които са добавени 145 реда и са изтрити 115 реда
  1. 3 3
      src/modules/tls/tls_dump_vf.c
  2. 6 2
      src/modules/tls/tls_mod.c
  3. 136 110
      src/modules/tls/tls_server.c

+ 3 - 3
src/modules/tls/tls_dump_vf.c

@@ -15,8 +15,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * Exception: permission to copy, modify, propagate, and distribute a work
@@ -43,7 +43,7 @@
 void tls_dump_verification_failure(long verification_result)
 {
 	int tls_log;
-	
+
 	tls_log = cfg_get(tls, tls_cfg, log);
 	switch(verification_result) {
 	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:

+ 6 - 2
src/modules/tls/tls_mod.c

@@ -83,6 +83,7 @@ static int w_is_peer_verified(struct sip_msg* msg, char* p1, char* p2);
 MODULE_VERSION
 
 
+extern str sr_tls_event_callback;
 str sr_tls_xavp_cfg = {0, 0};
 /*
  * Default settings when modparams are used
@@ -209,6 +210,7 @@ static param_export_t params[] = {
 	{"low_mem_threshold2",  PARAM_INT,    &default_tls_cfg.low_mem_threshold2},
 	{"renegotiation",       PARAM_INT,    &sr_tls_renegotiation},
 	{"xavp_cfg",            PARAM_STR,    &sr_tls_xavp_cfg},
+	{"event_callback",      PARAM_STR,    &sr_tls_event_callback},
 	{0, 0, 0}
 };
 
@@ -349,7 +351,9 @@ static int mod_init(void)
 #ifndef OPENSSL_NO_DH
 	LM_INFO("With Diffie Hellman\n");
 #endif
-	tls_lookup_event_routes();
+	if(sr_tls_event_callback.s==NULL || sr_tls_event_callback.len<=0) {
+		tls_lookup_event_routes();
+	}
 	return 0;
 error:
 	destroy_tls_h();
@@ -491,4 +495,4 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
 	sr_kemi_modules_add(sr_kemi_tls_exports);
 
 	return 0;
-}
+}

+ 136 - 110
src/modules/tls/tls_server.c

@@ -43,6 +43,8 @@
 #include "../../core/forward.h"
 #include "../../core/onsend.h"
 #include "../../core/xavp.h"
+#include "../../core/fmsg.h"
+#include "../../core/kemi.h"
 
 #include "tls_init.h"
 #include "tls_domain.h"
@@ -59,10 +61,10 @@ int tls_run_event_routes(struct tcp_connection *c);
 /* low memory treshold for openssl bug #1491 workaround */
 #define LOW_MEM_NEW_CONNECTION_TEST() \
 	(cfg_get(tls, tls_cfg, low_mem_threshold1) && \
-	  (shm_available_safe() < cfg_get(tls, tls_cfg, low_mem_threshold1)))
+		(shm_available_safe() < cfg_get(tls, tls_cfg, low_mem_threshold1)))
 #define LOW_MEM_CONNECTED_TEST() \
 	(cfg_get(tls, tls_cfg, low_mem_threshold2) && \
-	  (shm_available_safe() <  cfg_get(tls, tls_cfg, low_mem_threshold2)))
+		(shm_available_safe() <  cfg_get(tls, tls_cfg, low_mem_threshold2)))
 
 #define TLS_RD_MBUF_SZ	65536
 #define TLS_WR_MBUF_SZ	65536
@@ -190,19 +192,19 @@ static int tls_complete_init(struct tcp_connection* c)
 				cfg_get(tls, tls_cfg, low_mem_threshold1));
 		goto error2;
 	}
-	     /* Get current TLS configuration and increase reference
-	      * count immediately.
-	      */
+	/* Get current TLS configuration and increase reference
+	 * count immediately.
+	 */
 
 	LM_DBG("completing tls connection initialization\n");
 
 	lock_get(tls_domains_cfg_lock);
 	cfg = *tls_domains_cfg;
 
-	     /* Increment the reference count in the configuration structure, this
-	      * is to ensure that, while on the garbage queue, the configuration does
-	      * not get deleted if there are still connection referencing its SSL_CTX
-	      */
+	/* Increment the reference count in the configuration structure, this
+	 * is to ensure that, while on the garbage queue, the configuration does
+	 * not get deleted if there are still connection referencing its SSL_CTX
+	 */
 	atomic_inc(&cfg->ref_count);
 	lock_release(tls_domains_cfg_lock);
 
@@ -260,7 +262,7 @@ static int tls_complete_init(struct tcp_connection* c)
 
 #if OPENSSL_VERSION_NUMBER < 0x010100000L
 #ifdef TLS_KSSL_WORKARROUND
-	 /* if needed apply workaround for openssl bug #1467 */
+	/* if needed apply workaround for openssl bug #1467 */
 	if (data->ssl->kssl_ctx && openssl_kssl_malloc_bug){
 		kssl_ctx_free(data->ssl->kssl_ctx);
 		data->ssl->kssl_ctx=0;
@@ -274,10 +276,10 @@ static int tls_complete_init(struct tcp_connection* c)
 	SSL_set_app_data(data->ssl, data);
 	return 0;
 
- error:
+error:
 	atomic_dec(&cfg->ref_count);
 	if (data) shm_free(data);
- error2:
+error2:
 	return -1;
 }
 
@@ -316,7 +318,7 @@ static int tls_fix_connection_unsafe(struct tcp_connection* c)
 static int tls_fix_connection(struct tcp_connection* c)
 {
 	int ret;
-	
+
 	if (unlikely(c->extra_data == 0)) {
 		lock_get(&c->write_lock);
 			if (unlikely(c->extra_data == 0)) {
@@ -346,7 +348,7 @@ static int tls_set_mbufs(struct tcp_connection *c,
 							struct tls_mbuf* wr)
 {
 	BIO *rwbio;
-	
+
 	rwbio = ((struct tls_extra_data*)c->extra_data)->rwbio;
 	if (unlikely(tls_BIO_mbuf_set(rwbio, rd, wr)<=0)) {
 		/* it should be always 1 */
@@ -361,11 +363,11 @@ static void tls_dump_cert_info(char* s, X509* cert)
 {
 	char* subj;
 	char* issuer;
-	
+
 	subj=issuer=0;
 	subj = X509_NAME_oneline(X509_get_subject_name(cert), 0 , 0);
 	issuer = X509_NAME_oneline(X509_get_issuer_name(cert), 0 , 0);
-	
+
 	if (subj){
 		LOG(cfg_get(tls, tls_cfg, log), "%s subject:%s\n", s ? s : "", subj);
 		OPENSSL_free(subj);
@@ -403,7 +405,7 @@ int tls_accept(struct tcp_connection *c, int* error)
 	*error = SSL_ERROR_NONE;
 	tls_c=(struct tls_extra_data*)c->extra_data;
 	ssl=tls_c->ssl;
-	
+
 	if (unlikely(tls_c->state != S_TLS_ACCEPTING)) {
 		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
 		goto err;
@@ -414,19 +416,19 @@ int tls_accept(struct tcp_connection *c, int* error)
 		tls_c->state = S_TLS_ESTABLISHED;
 		tls_log = cfg_get(tls, tls_cfg, log);
 		LOG(tls_log, "tls_accept: new connection from %s:%d using %s %s %d\n",
-		    ip_addr2a(&c->rcv.src_ip), c->rcv.src_port,
-		    SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl), 
-		    SSL_get_cipher_bits(ssl, 0)
-		    );
-		LOG(tls_log, "tls_accept: local socket: %s:%d\n", 
-		    ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port
-		    );
+				ip_addr2a(&c->rcv.src_ip), c->rcv.src_port,
+				SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl),
+				SSL_get_cipher_bits(ssl, 0)
+			);
+		LOG(tls_log, "tls_accept: local socket: %s:%d\n",
+				ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port
+			);
 		cert = SSL_get_peer_certificate(ssl);
-		if (cert != 0) { 
+		if (cert != 0) {
 			tls_dump_cert_info("tls_accept: client certificate", cert);
 			if (SSL_get_verify_result(ssl) != X509_V_OK) {
 				LOG(tls_log, "WARNING: tls_accept: client certificate "
-				    "verification failed!!!\n");
+						"verification failed!!!\n");
 				tls_dump_verification_failure(SSL_get_verify_result(ssl));
 			}
 			X509_free(cert);
@@ -468,7 +470,7 @@ int tls_connect(struct tcp_connection *c, int* error)
 	*error = SSL_ERROR_NONE;
 	tls_c=(struct tls_extra_data*)c->extra_data;
 	ssl=tls_c->ssl;
-	
+
 	if (unlikely(tls_c->state != S_TLS_CONNECTING)) {
 		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
 		goto err;
@@ -478,20 +480,20 @@ int tls_connect(struct tcp_connection *c, int* error)
 		DBG("TLS connect successful\n");
 		tls_c->state = S_TLS_ESTABLISHED;
 		tls_log = cfg_get(tls, tls_cfg, log);
-		LOG(tls_log, "tls_connect: new connection to %s:%d using %s %s %d\n", 
-		    ip_addr2a(&c->rcv.src_ip), c->rcv.src_port,
-		    SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl),
-		    SSL_get_cipher_bits(ssl, 0)
-		    );
-		LOG(tls_log, "tls_connect: sending socket: %s:%d \n", 
-		    ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port
-		    );
+		LOG(tls_log, "tls_connect: new connection to %s:%d using %s %s %d\n",
+				ip_addr2a(&c->rcv.src_ip), c->rcv.src_port,
+				SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl),
+				SSL_get_cipher_bits(ssl, 0)
+			);
+		LOG(tls_log, "tls_connect: sending socket: %s:%d \n",
+				ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port
+			);
 		cert = SSL_get_peer_certificate(ssl);
-		if (cert != 0) { 
+		if (cert != 0) {
 			tls_dump_cert_info("tls_connect: server certificate", cert);
 			if (SSL_get_verify_result(ssl) != X509_V_OK) {
 				LOG(tls_log, "WARNING: tls_connect: server certificate "
-				    "verification failed!!!\n");
+						"verification failed!!!\n");
 				tls_dump_verification_failure(SSL_get_verify_result(ssl));
 			}
 			X509_free(cert);
@@ -527,7 +529,7 @@ static int tls_shutdown(struct tcp_connection *c)
 	}
 	ssl = tls_c->ssl;
 	/* it doesn't make sense to try a TLS level shutdown
-	   if the connection is not fully initialized */
+	 * if the connection is not fully initialized */
 	if (unlikely(tls_c->state != S_TLS_ESTABLISHED))
 		return 0;
 	if (unlikely(LOW_MEM_CONNECTED_TEST())){
@@ -536,7 +538,7 @@ static int tls_shutdown(struct tcp_connection *c)
 				cfg_get(tls, tls_cfg, low_mem_threshold2));
 		goto err;
 	}
-	
+
 	ret = SSL_shutdown(ssl);
 	if (ret == 1) {
 		DBG("TLS shutdown successful\n");
@@ -550,20 +552,20 @@ static int tls_shutdown(struct tcp_connection *c)
 		case SSL_ERROR_ZERO_RETURN:
 			DBG("TLS shutdown failed cleanly\n");
 			goto err;
-			
+
 		case SSL_ERROR_WANT_READ:
 			DBG("Need to get more data to finish TLS shutdown\n");
 			break;
-			
+
 		case SSL_ERROR_WANT_WRITE:
 			DBG("Need to send more data to finish TLS shutdown\n");
 			break;
-			
+
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L /*0.9.7*/
 		case SSL_ERROR_WANT_CONNECT:
 			DBG("Need to retry connect\n");
 			break;
-			
+
 		case SSL_ERROR_WANT_ACCEPT:
 			DBG("Need to retry accept\n");
 			break;
@@ -571,7 +573,7 @@ static int tls_shutdown(struct tcp_connection *c)
 		case SSL_ERROR_WANT_X509_LOOKUP:
 			DBG("Application callback asked to be called again\n");
 			break;
-			
+
 		case SSL_ERROR_SYSCALL:
 			TLS_ERR_RET(ssl_err, "TLS shutdown");
 			if (!ssl_err) {
@@ -582,16 +584,16 @@ static int tls_shutdown(struct tcp_connection *c)
 				}
 			}
 			goto err;
-			
+
 		case SSL_ERROR_SSL:
 		default:
 			TLS_ERR("SSL error:");
 			goto err;
 		}
 	}
-	
+
 	return 0;
- err:
+err:
 	return -1;
 }
 
@@ -654,7 +656,7 @@ void tls_h_close(struct tcp_connection *c, int fd)
 {
 	unsigned char wr_buf[TLS_WR_MBUF_SZ];
 	struct tls_mbuf rd, wr;
-	
+
 	/*
 	 * runs either within global tcp lock or after the connection has
 	 * been "detached" and is unreachable from any other process.
@@ -737,7 +739,7 @@ int tls_encode_f(struct tcp_connection *c,
 	const char* buf;
 	unsigned int len;
 	int x;
-	
+
 	buf = *pbuf;
 	len = *plen;
 	*rest_buf = 0;
@@ -770,8 +772,8 @@ int tls_encode_f(struct tcp_connection *c,
 				goto error_wq_full;
 		}
 		/* buffer queued for a future send attempt, after first reading
-		   some data (key exchange) => don't allow immediate closing of
-		   the connection */
+		 * some data (key exchange) => don't allow immediate closing of
+		 * the connection */
 		send_flags->f &= ~SND_F_CON_CLOSE;
 		goto end;
 	}
@@ -836,15 +838,15 @@ redo_wr:
 				}
 				tls_c->flags |= F_TLS_CON_WR_WANTS_RD;
 				/* buffer queued for a future send attempt, after first
-				   reading some data (key exchange) => don't allow immediate
-				   closing of the connection */
+				 * reading some data (key exchange) => don't allow immediate
+				 * closing of the connection */
 				send_flags->f &= ~SND_F_CON_CLOSE;
 				break; /* or goto end */
 			case SSL_ERROR_WANT_WRITE:
 				if (unlikely(offs == 0)) {
 					/*  error, no record fits in the buffer or
-					  no partial write enabled and buffer to small to fit
-					  all the records */
+					 * no partial write enabled and buffer to small to fit
+					 * all the records */
 					BUG("write buffer too small (%d/%d bytes)\n",
 							wr.used, wr.size);
 					goto bug;
@@ -853,7 +855,7 @@ redo_wr:
 					*rest_buf = buf + offs;
 					*rest_len = len - offs;
 					/* this function should be called again => disallow
-					   immediate closing of the connection */
+					 * immediate closing of the connection */
 					send_flags->f &= ~SND_F_CON_CLOSE;
 					TLS_WR_TRACE("(%p) SSL_ERROR_WANT_WRITE partial write"
 								" (written %p , %d, rest_buf=%p"
@@ -868,22 +870,22 @@ redo_wr:
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L /*0.9.7*/
 			case SSL_ERROR_WANT_CONNECT:
 				/* only if the underlying BIO is not yet connected
-				   and the call would block in connect().
-				   (not possible in our case) */
+				 * and the call would block in connect().
+				 * (not possible in our case) */
 				BUG("unexpected SSL_ERROR_WANT_CONNECT\n");
 				break;
 			case SSL_ERROR_WANT_ACCEPT:
 				/* only if the underlying BIO is not yet connected
-				   and call would block in accept()
-				   (not possible in our case) */
+				 * and call would block in accept()
+				 * (not possible in our case) */
 				BUG("unexpected SSL_ERROR_WANT_ACCEPT\n");
 				break;
 #endif
 			case SSL_ERROR_WANT_X509_LOOKUP:
 				/* can only appear on client application and it indicates that
-				   an installed client cert. callback should be called again
-				   (it returned < 0 indicated that it wants to be called
-				   later). Not possible in our case */
+				 * an installed client cert. callback should be called again
+				 * (it returned < 0 indicated that it wants to be called
+				 * later). Not possible in our case */
 				BUG("unsupported SSL_ERROR_WANT_X509_LOOKUP");
 				goto bug;
 			case SSL_ERROR_SYSCALL:
@@ -903,7 +905,7 @@ redo_wr:
 		}
 	} else if (unlikely(n < (len - offs))) {
 		/* partial ssl write (possible if SSL_MODE_ENABLE_PARTIAL_WRITE) =>
-		   retry with the rest */
+		 * retry with the rest */
 		TLS_WR_TRACE("(%p) partial write (%d < %d, offset %d), retry\n",
 						c, n, len - offs, offs);
 		offs += n;
@@ -938,7 +940,8 @@ ssl_eof:
 
 
 /** tls read.
- * Each modification of ssl data structures has to be protected, another process * might ask for the same connection and attempt write to it which would
+ * Each modification of ssl data structures has to be protected, another process
+ * might ask for the same connection and attempt write to it which would
  * result in updating the ssl structures.
  * WARNING: must be called whic c->write_lock _unlocked_.
  * @param c - tcp connection pointer. The following flags might be set:
@@ -977,7 +980,7 @@ int tls_read_f(struct tcp_connection* c, int* flags)
 	char* err_src;
 	int x;
 	int tls_dbg;
-	
+
 	TLS_RD_TRACE("(%p, %p (%d)) start (%s -> %s:%d*)\n",
 					c, flags, *flags,
 					su2a(&c->rcv.src_su, sizeof(c->rcv.src_su)),
@@ -992,8 +995,8 @@ int tls_read_f(struct tcp_connection* c, int* flags)
 		return -1;
 	}
 	/* here it's safe to use c->extra_data in read-only mode.
-	   If it's != 0 is changed only on destroy. It's not possible to have
-	   parallel reads.*/
+	 * If it's != 0 is changed only on destroy. It's not possible to have
+	 * parallel reads.*/
 	tls_c = c->extra_data;
 	bytes_free = c->req.b_size - (int)(r->pos - r->buf);
 	if (unlikely(bytes_free == 0)) {
@@ -1008,7 +1011,7 @@ redo_read:
 	if (unlikely(tls_c->enc_rd_buf)) {
 		/* use queued data */
 		/* safe to use without locks, because only read changes it and
-		   there can't be parallel reads on the same connection */
+		 * there can't be parallel reads on the same connection */
 		enc_rd_buf = tls_c->enc_rd_buf;
 		tls_c->enc_rd_buf = 0;
 		TLS_RD_TRACE("(%p, %p) using queued data (%p: %p %d bytes)\n", c,
@@ -1029,7 +1032,7 @@ redo_read:
 		/* real read() */
 		tls_mbuf_init(&rd, rd_buf, sizeof(rd_buf));
 		/* read() only if no previously detected EOF, or previous
-		   short read (which means the socket buffer was emptied) */
+		 * short read (which means the socket buffer was emptied) */
 		if (likely(!(*flags & (RD_CONN_EOF|RD_CONN_SHORT_READ)))) {
 			/* don't read more then the free bytes in the tcp req buffer */
 			read_size = MIN_unsigned(rd.size, bytes_free);
@@ -1038,19 +1041,19 @@ redo_read:
 			TLS_RD_TRACE("(%p, %p) tcp_read_data(..., %d, *%d) => %d bytes\n",
 						c, flags, read_size, *flags, bytes_read);
 			/* try SSL_read even on 0 bytes read, it might have
-			   internally buffered data */
+			 * internally buffered data */
 			if (unlikely(bytes_read < 0)) {
 					goto error;
 			}
 			rd.used = bytes_read;
 		}
 	}
-	
+
 continue_ssl_read:
 	tls_mbuf_init(&wr, wr_buf, sizeof(wr_buf));
 	ssl_error = SSL_ERROR_NONE;
 	err_src = "TLS read:";
-	/* we have to avoid to run in the same time 
+	/* we have to avoid to run in the same time
 	 * with a tls_write because of the
 	 * update bio stuff  (we don't want a write
 	 * stealing the wbio or rbio under us or vice versa)
@@ -1110,7 +1113,7 @@ continue_ssl_read:
 				}
 			} else {
 				/* if bytes in then decrypt read buffer into tcpconn req.
-				   buffer */
+				 * buffer */
 				n = SSL_read(ssl, r->pos, bytes_free);
 			}
 			/** handle SSL_read() return.
@@ -1130,7 +1133,7 @@ continue_ssl_read:
 			 * 1. output buffer filled (n == bytes_free):
 			 *    1i.  - still unconsumed input, nothing buffered by openssl
 			 *    1ip. - unconsumed input + buffered data by openssl (pending
-			             on the next SSL_read).
+			 *			 on the next SSL_read).
 			 *    1p.  - completely consumed input, buffered data internally
 			 *            by openssl (pending).
 			 *           Likely to happen, about the only case when
@@ -1229,8 +1232,8 @@ ssl_read_skipped:
 			if (unlikely((*flags & (RD_CONN_EOF | RD_CONN_SHORT_READ)) == 0) &&
 							bytes_free){
 				/* there might still be data to read and there is space
-				   to decrypt it in tcp_req (no byte has been written into
-				    tcp_req in this case) */
+				 * to decrypt it in tcp_req (no byte has been written into
+				 * tcp_req in this case) */
 				TLS_RD_TRACE("(%p, %p) redo read *flags=%d bytes_free=%d\n",
 								c, flags, *flags, bytes_free);
 				goto redo_read;
@@ -1239,8 +1242,8 @@ ssl_read_skipped:
 		case SSL_ERROR_WANT_WRITE:
 			if (wr.used) {
 				/* something was written => buffer not big enough to hold
-				   everything => reset buffer & retry (the tcp_write already
-				   happened if we are here) */
+				 * everything => reset buffer & retry (the tcp_write already
+				 * happened if we are here) */
 				TLS_RD_TRACE("(%p) SSL_ERROR_WANT_WRITE partial write"
 							" (written  %d), retrying\n", c, wr.used);
 				goto continue_ssl_read;
@@ -1256,22 +1259,22 @@ ssl_read_skipped:
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L /*0.9.7*/
 		case SSL_ERROR_WANT_CONNECT:
 			/* only if the underlying BIO is not yet connected
-			   and the call would block in connect().
-			   (not possible in our case) */
+			 * and the call would block in connect().
+			 * (not possible in our case) */
 			BUG("unexpected SSL_ERROR_WANT_CONNECT\n");
 			goto bug;
 		case SSL_ERROR_WANT_ACCEPT:
 			/* only if the underlying BIO is not yet connected
-			   and call would block in accept()
-			   (not possible in our case) */
+			 * and call would block in accept()
+			 * (not possible in our case) */
 			BUG("unexpected SSL_ERROR_WANT_ACCEPT\n");
 			goto bug;
 #endif
 		case SSL_ERROR_WANT_X509_LOOKUP:
 			/* can only appear on client application and it indicates that
-			   an installed client cert. callback should be called again
-			   (it returned < 0 indicated that it wants to be called
-			   later). Not possible in our case */
+			 * an installed client cert. callback should be called again
+			 * (it returned < 0 indicated that it wants to be called
+			 * later). Not possible in our case */
 			BUG("unsupported SSL_ERROR_WANT_X509_LOOKUP");
 			goto bug;
 		case SSL_ERROR_SYSCALL:
@@ -1296,17 +1299,17 @@ ssl_read_skipped:
 	}
 	if (unlikely(rd.pos != rd.used)) {
 		/* encrypted data still in the read buffer (SSL_read() did not
-		   consume all of it) */
+		 * consume all of it) */
 		if (unlikely(n < 0))
 			/* here n should always be >= 0 */
 			BUG("unexpected value (n = %d)\n", n);
 		else {
 			if (unlikely(bytes_free != 0)) {
 				/* 2i or 2ip: unconsumed input and output buffer not filled =>
-				  retry ssl read (SSL_read() will read will stop at
-				  record boundaries, unless readahead==1).
-				  No tcp_read() is attempted, since that would reset the
-				  current no-yet-consumed input data.
+				 * retry ssl read (SSL_read() will read will stop at
+				 * record boundaries, unless readahead==1).
+				 * No tcp_read() is attempted, since that would reset the
+				 * current no-yet-consumed input data.
 				 */
 				TLS_RD_TRACE("(%p, %p) input not fully consumed =>"
 								" retry SSL_read"
@@ -1315,9 +1318,9 @@ ssl_read_skipped:
 				goto continue_ssl_read;
 			}
 			/* 1i or 1ip: bytes_free == 0
-			   (unconsumed input, but filled output  buffer) =>
-			    queue read data, and exit asking for repeating the call
-			    once there is some space in the output buffer.
+			 * (unconsumed input, but filled output  buffer) =>
+			 * queue read data, and exit asking for repeating the call
+			 * once there is some space in the output buffer.
 			 */
 			if (likely(!enc_rd_buf)) {
 				TLS_RD_TRACE("(%p, %p) creating enc_rd_buf (for %d bytes)\n",
@@ -1348,27 +1351,27 @@ ssl_read_skipped:
 			if (unlikely(tls_c->enc_rd_buf))
 				BUG("tls_c->enc_rd_buf!=0 (%p)\n", tls_c->enc_rd_buf);
 			/* there can't be 2 reads in parallel, so no locking is needed
-			   here */
+			 * here */
 			tls_c->enc_rd_buf = enc_rd_buf;
 			enc_rd_buf = 0;
 			*flags |= RD_CONN_REPEAT_READ;
 		}
 	} else if (bytes_free != 0) {
 		/*  2f or 2p: input fully consumed (rd.pos == rd.used),
-		    output buffer not filled, still possible to have pending
-		    data buffered by openssl */
+		 *  output buffer not filled, still possible to have pending
+		 *  data buffered by openssl */
 		if (unlikely((*flags & (RD_CONN_EOF|RD_CONN_SHORT_READ)) == 0)) {
 			/* still space in the tcp unenc. req. buffer, no SSL_read error,
-			   not a short read and not an EOF (possible more data in
-			   the socket buffer) => try a new tcp read too */
+			 * not a short read and not an EOF (possible more data in
+			 * the socket buffer) => try a new tcp read too */
 			TLS_RD_TRACE("(%p, %p) retry read (still space and no short"
 							" tcp read: %d)\n", c, flags, *flags);
 			goto redo_read;
 		} else {
 			/* don't tcp_read() anymore, but there might still be data
-			   buffered internally by openssl (e.g. if readahead==1) =>
-			   retry SSL_read() with the current full input buffer
-			   (if no more internally SSL buffered data => WANT_READ => exit).
+			 * buffered internally by openssl (e.g. if readahead==1) =>
+			 * retry SSL_read() with the current full input buffer
+			 * (if no more internally SSL buffered data => WANT_READ => exit).
 			 */
 			TLS_RD_TRACE("(%p, %p) retry SSL_read only (*flags =%d)\n",
 							c, flags, *flags);
@@ -1376,16 +1379,16 @@ ssl_read_skipped:
 		}
 	} else {
 		/*   1p or 1f: rd.pos == rd.used && bytes_free == 0
-			 (input fully consumed && output buffer filled) */
+		 *   (input fully consumed && output buffer filled) */
 		/* ask for a repeat when there is more buffer space
-		   (there is no definitive way to know if ssl doesn't still have
-		    some internal buffered data until we get WANT_READ, see
-			SSL_read() comment above) */
+		 * (there is no definitive way to know if ssl doesn't still have
+		 * some internal buffered data until we get WANT_READ, see
+		 * SSL_read() comment above) */
 		*flags |= RD_CONN_REPEAT_READ;
 		TLS_RD_TRACE("(%p, %p) output filled, exit asking to be called again"
 						" (*flags =%d)\n", c, flags, *flags);
 	}
-	
+
 end:
 	if (enc_rd_buf)
 		shm_free(enc_rd_buf);
@@ -1414,6 +1417,7 @@ bug:
 
 
 static int _tls_evrt_connection_out = -1; /* default disabled */
+str sr_tls_event_callback = STR_NULL;
 
 /*!
  * lookup tls event routes
@@ -1434,18 +1438,40 @@ int tls_run_event_routes(struct tcp_connection *c)
 {
 	int backup_rt;
 	struct run_act_ctx ctx;
-	sip_msg_t tmsg;
+	sip_msg_t *fmsg = NULL;
+	str evname = str_init("tls:connection-out");
+	sr_kemi_eng_t *keng = NULL;
 
-	if(_tls_evrt_connection_out<0)
+	if(_tls_evrt_connection_out<0 && sr_tls_event_callback.len<=0)
 		return 0;
+
 	if(p_onsend==0 || p_onsend->msg==0)
 		return 0;
 
+	if(faked_msg_init()<0)
+		return -1;
+	fmsg = faked_msg_next();
+
 	backup_rt = get_route_type();
 	set_route_type(LOCAL_ROUTE);
 	init_run_actions_ctx(&ctx);
 	tls_set_pv_con(c);
-	run_top_route(event_rt.rlist[_tls_evrt_connection_out], &tmsg, 0);
+	if(_tls_evrt_connection_out>=0) {
+		run_top_route(event_rt.rlist[_tls_evrt_connection_out], fmsg, 0);
+	} else {
+		keng = sr_kemi_eng_get();
+		if(keng!=NULL) {
+			if(keng->froute(fmsg, EVENT_ROUTE,
+						&sr_tls_event_callback, &evname)<0) {
+				LM_ERR("error running event route kemi callback\n");
+				return -1;
+			}
+		}
+	}
+	/* drop() executed in the event route - set nosend flag */
+	if (unlikely(ctx.run_flags&DROP_R_F)) {
+		c->flags|=F_CONN_NOSEND;
+	}
 	tls_set_pv_con(0);
 	set_route_type(backup_rt);
 	return 0;