Browse Source

tls: tls state is now separate from tcp state

- tls connection state is now kept separately from the tcp state.
- update tls_h_fix_read_conn() to what tcp expects now.

Closes: FlySpray#14.
Andrei Pelinescu-Onciul 16 years ago
parent
commit
68e94429ae
4 changed files with 222 additions and 120 deletions
  1. 103 60
      modules/tls/tls_server.c
  2. 8 0
      modules/tls/tls_server.h
  3. 103 60
      modules_s/tls/tls_server.c
  4. 8 0
      modules_s/tls/tls_server.h

+ 103 - 60
modules/tls/tls_server.c

@@ -33,6 +33,8 @@
  * --------
  *  2007-01-26  openssl kerberos malloc bug detection/workaround (andrei)
  *  2007-02-23  openssl low memory bugs workaround (andrei)
+ *  2009-09-21  tls connection state is now kept in c->extra_data (no
+ *               longer shared with tcp state) (andrei)
  */
 
 #include <sys/poll.h>
@@ -68,6 +70,7 @@ static int tls_complete_init(struct tcp_connection* c)
 	tls_domain_t* dom;
 	struct tls_extra_data* data = 0;
 	tls_cfg_t* cfg;
+	enum tls_conn_states state;
 
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
@@ -90,12 +93,17 @@ static int tls_complete_init(struct tcp_connection* c)
 	      */
 	cfg->ref_count++;
 
-	if (c->state == S_CONN_ACCEPT) {
-		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV, &c->rcv.dst_ip, c->rcv.dst_port);
-	} else if (c->state == S_CONN_CONNECT) {
-		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI, &c->rcv.dst_ip, c->rcv.dst_port);
+	if (c->flags & F_CONN_PASSIVE) {
+		state=S_TLS_ACCEPTING;
+		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV,
+								&c->rcv.dst_ip, c->rcv.dst_port);
 	} else {
-		BUG("Invalid connection state (bug in TCP code)\n");
+		state=S_TLS_CONNECTING;
+		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI,
+								&c->rcv.dst_ip, c->rcv.dst_port);
+	}
+	if (unlikely(c->state<0)) {
+		BUG("Invalid connection (state %d)\n", c->state);
 		goto error;
 	}
 	DBG("Using TLS domain %s\n", tls_domain_str(dom));
@@ -108,6 +116,7 @@ static int tls_complete_init(struct tcp_connection* c)
 	memset(data, '\0', sizeof(struct tls_extra_data));
 	data->ssl = SSL_new(dom->ctx[process_no]);
 	data->cfg = cfg;
+	data->state = state;
 
 	if (data->ssl == 0) {
 		TLS_ERR("Failed to create SSL structure:");
@@ -127,7 +136,6 @@ static int tls_complete_init(struct tcp_connection* c)
 	cfg->ref_count--;
 	if (data) shm_free(data);
  error2:
-	c->state = S_CONN_BAD;
 	return -1;
 }
 
@@ -300,24 +308,27 @@ static int tls_accept(struct tcp_connection *c, int* error)
 	int ret, err, ssl_err;
 	SSL *ssl;
 	X509* cert;
+	struct tls_extra_data* tls_c;
 
-	if (c->state != S_CONN_ACCEPT) {
-		BUG("Invalid connection state (bug in TLS code)\n");
-		     /* Not critical */
-		return 0;
-	}
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
 				" operation: %lu\n", shm_available());
 		goto err;
 	}
-
-	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
+	
+	tls_c=(struct tls_extra_data*)c->extra_data;
+	ssl=tls_c->ssl;
+	
+	if (tls_c->state != S_TLS_ACCEPTING) {
+		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
+		/* Not critical */
+		return 0;
+	}
 	ret = SSL_accept(ssl);
 	if (ret == 1) {
 		DBG("TLS accept successful\n");
-		c->state = S_CONN_OK;
-		LOG(tls_log, "tls_accept: new connection from %s:%d using %s %s %d\n", 
+		tls_c->state = S_TLS_ESTABLISHED;
+		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)
@@ -383,8 +394,7 @@ static int tls_accept(struct tcp_connection *c, int* error)
 		}
 	}
 	return 0;
- err:
-	c->state = S_CONN_BAD;
+err:
 	return -1;
 }
 
@@ -397,23 +407,26 @@ static int tls_connect(struct tcp_connection *c, int* error)
 	SSL *ssl;
 	int ret, err, ssl_err;
 	X509* cert;
+	struct tls_extra_data* tls_c;
 
-	if (c->state != S_CONN_CONNECT) {
-		BUG("Invalid connection state\n");
-		     /* Not critical */
-		return 0;
-	}
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
 				" operation: %lu\n", shm_available());
 		goto err;
 	}
 
-	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
+	tls_c=(struct tls_extra_data*)c->extra_data;
+	ssl=tls_c->ssl;
+	
+	if (tls_c->state != S_TLS_CONNECTING) {
+		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
+		/* Not critical */
+		return 0;
+	}
 	ret = SSL_connect(ssl);
 	if (ret == 1) {
 		DBG("TLS connect successuful\n");
-		c->state = S_CONN_OK;
+		tls_c->state = S_TLS_ESTABLISHED;
 		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),
@@ -481,8 +494,7 @@ static int tls_connect(struct tcp_connection *c, int* error)
 		}
 	}
 	return 0;
- err:
-	c->state = S_CONN_BAD;
+err:
 	return -1;
 }
 
@@ -707,17 +719,19 @@ int tls_h_blocking_write(struct tcp_connection *c, int fd, const char *buf,
 	int err, n, ticks, tout;
 	fd_set sel_set;
 	struct timeval timeout;
+	struct tls_extra_data* tls_c;
 	
 	n = 0;
 	if (tls_update_fd(c, fd) < 0) goto error;
+	tls_c=(struct tls_extra_data*)c->extra_data;
 again:
 	err = 0;
 	     /* first try  a "fast" write -- avoid the extra select call,
 	      * we might get lucky and not need it */
-	if (c->state == S_CONN_CONNECT) {
+	if (tls_c->state == S_TLS_CONNECTING) {
 		if (tls_connect(c, &err) < 0) goto error;
 		tout = tls_handshake_timeout;
-	} else if (c->state == S_CONN_ACCEPT) {
+	} else if (tls_c->state == S_TLS_ACCEPTING) {
 		if (tls_accept(c, &err) < 0) goto error;
 		tout = tls_handshake_timeout;
 	} else {
@@ -806,17 +820,19 @@ int tls_h_nonblocking_write(struct tcp_connection *c, int fd, const char *buf,
 			  unsigned int len)
 {
 	int err, n;
+	struct tls_extra_data* tls_c;
 	
 	n = 0;
 	if (tls_update_fd(c, fd) < 0) goto error;
+	tls_c=(struct tls_extra_data*)c->extra_data;
 again:
 	err = 0;
-	if (c->state == S_CONN_CONNECT) {
+	if (tls_c->state == S_TLS_CONNECTING) {
 		if (tls_connect(c, &err) < 0) goto error;
-	} else if (c->state == S_CONN_ACCEPT) {
+	} else if (tls_c->state == S_TLS_ACCEPTING) {
 		if (tls_accept(c, &err) < 0) goto error;
 	}
-	if (c->state!=S_CONN_CONNECT && c->state!=S_CONN_ACCEPT){
+	if (tls_c->state!=S_TLS_CONNECTING && tls_c->state!=S_TLS_ACCEPTING){
 		n = tls_write(c, buf, len, &err);
 		if (n < 0) {
 			DBG("tls_write error %d (ssl %d)\n", n, err);
@@ -857,8 +873,8 @@ end:
 
 
 /*
- * called only when a connection is in S_CONN_OK, we do not have to care
- * about accepting or connecting here, each modification of ssl data
+ * called only when a connection is in S_TLS_ESTABLISHED, we do not have to
+ * care about accepting or connecting here. 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 
@@ -945,40 +961,67 @@ int tls_h_read(struct tcp_connection * c)
 
 /*
  * called before tls_read, the this function should attempt tls_accept or
- * tls_connect depending on the state of the connection, if this function
- * does not transit a connection into S_CONN_OK then tcp layer would not
+ * tls_connect depending on the state of the connection.
+ * If this function does not return 1, then the tcp layer would not
  * call tcp_read 
+ * @return  1 success, 0 try again (don't attempt tls_read()), -1 error
  */
 int tls_h_fix_read_conn(struct tcp_connection *c)
 {
 	int ret;
-	ret = 0;
-
-	switch (c->state) {
-	case S_CONN_ACCEPT:
+	struct tls_extra_data* tls_c;
+	
+	ret = -1;
+	tls_c = 0;
+	if (unlikely(c->extra_data==0)){
 		lock_get(&c->write_lock);
-		     /* It might have changed meanwhile */
-		if (c->state == S_CONN_ACCEPT) {
-			ret = tls_update_fd(c, c->fd);
-			if (ret == 0) ret = tls_accept(c, 0);
-			else ret = -1;
-		}
+			if (unlikely(tls_update_fd(c, c->fd) < 0)){
+				ret = -1;
+			} else {
+				tls_c=(struct tls_extra_data*)c->extra_data;
+				switch(tls_c->state){
+					case S_TLS_ACCEPTING:
+						ret=tls_accept(c, 0);
+						break;
+					case S_TLS_CONNECTING:
+						ret=tls_connect(c, 0);
+						break;
+					default:
+						/* fall through */
+						ret=1;
+						break;
+				}
+			}
 		lock_release(&c->write_lock);
-		break;
-		
-	case S_CONN_CONNECT:
-		lock_get(&c->write_lock);
-		     /* It might have changed meanwhile */
-		if (c->state == S_CONN_CONNECT) {
-			ret = tls_update_fd(c, c->fd);
-			if (ret == 0) ret = tls_connect(c, 0);
-			else ret = -1;
+	} else {
+		tls_c=(struct tls_extra_data*)c->extra_data;
+		switch (tls_c->state) {
+			case S_TLS_ACCEPTING:
+				lock_get(&c->write_lock);
+					tls_c=(struct tls_extra_data*)c->extra_data;
+					/* It might have changed meanwhile */
+					if (likely(tls_c->state == S_TLS_ACCEPTING)) {
+						ret = tls_update_fd(c, c->fd);
+						if (ret == 0) ret = tls_accept(c, 0);
+						else ret = -1;
+					}
+				lock_release(&c->write_lock);
+			break;
+			case S_TLS_CONNECTING:
+				lock_get(&c->write_lock);
+					tls_c=(struct tls_extra_data*)c->extra_data;
+					/* It might have changed meanwhile */
+					if (likely(tls_c->state == S_TLS_CONNECTING)) {
+						ret = tls_update_fd(c, c->fd);
+						if (ret == 0) ret = tls_connect(c, 0);
+						else ret = -1;
+					}
+				lock_release(&c->write_lock);
+			break;
+		default: /* fall through */
+			ret=1;
+			break;
 		}
-		lock_release(&c->write_lock);
-		break;
-		
-	default: /* fall through */
-		break;
 	}
-	return ret;
+	return (ret>=0)?(tls_c->state==S_TLS_ESTABLISHED):ret;
 }

+ 8 - 0
modules/tls/tls_server.h

@@ -36,9 +36,17 @@
 #include "../../tcp_conn.h"
 #include "tls_domain.h"
 
+enum tls_conn_states {
+						S_TLS_NONE = 0,
+						S_TLS_ACCEPTING,
+						S_TLS_CONNECTING,
+						S_TLS_ESTABLISHED
+					};
+
 struct tls_extra_data {
 	tls_cfg_t* cfg; /* Configuration used for this connection */
 	SSL* ssl;       /* SSL context used for the connection */
+	enum  tls_conn_states state;
 };
 
 /*

+ 103 - 60
modules_s/tls/tls_server.c

@@ -33,6 +33,8 @@
  * --------
  *  2007-01-26  openssl kerberos malloc bug detection/workaround (andrei)
  *  2007-02-23  openssl low memory bugs workaround (andrei)
+ *  2009-09-21  tls connection state is now kept in c->extra_data (no
+ *               longer shared with tcp state) (andrei)
  */
 
 #include <sys/poll.h>
@@ -68,6 +70,7 @@ static int tls_complete_init(struct tcp_connection* c)
 	tls_domain_t* dom;
 	struct tls_extra_data* data = 0;
 	tls_cfg_t* cfg;
+	enum tls_conn_states state;
 
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
@@ -90,12 +93,17 @@ static int tls_complete_init(struct tcp_connection* c)
 	      */
 	cfg->ref_count++;
 
-	if (c->state == S_CONN_ACCEPT) {
-		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV, &c->rcv.dst_ip, c->rcv.dst_port);
-	} else if (c->state == S_CONN_CONNECT) {
-		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI, &c->rcv.dst_ip, c->rcv.dst_port);
+	if (c->flags & F_CONN_PASSIVE) {
+		state=S_TLS_ACCEPTING;
+		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV,
+								&c->rcv.dst_ip, c->rcv.dst_port);
 	} else {
-		BUG("Invalid connection state (bug in TCP code)\n");
+		state=S_TLS_CONNECTING;
+		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI,
+								&c->rcv.dst_ip, c->rcv.dst_port);
+	}
+	if (unlikely(c->state<0)) {
+		BUG("Invalid connection (state %d)\n", c->state);
 		goto error;
 	}
 	DBG("Using TLS domain %s\n", tls_domain_str(dom));
@@ -108,6 +116,7 @@ static int tls_complete_init(struct tcp_connection* c)
 	memset(data, '\0', sizeof(struct tls_extra_data));
 	data->ssl = SSL_new(dom->ctx[process_no]);
 	data->cfg = cfg;
+	data->state = state;
 
 	if (data->ssl == 0) {
 		TLS_ERR("Failed to create SSL structure:");
@@ -127,7 +136,6 @@ static int tls_complete_init(struct tcp_connection* c)
 	cfg->ref_count--;
 	if (data) shm_free(data);
  error2:
-	c->state = S_CONN_BAD;
 	return -1;
 }
 
@@ -300,24 +308,27 @@ static int tls_accept(struct tcp_connection *c, int* error)
 	int ret, err, ssl_err;
 	SSL *ssl;
 	X509* cert;
+	struct tls_extra_data* tls_c;
 
-	if (c->state != S_CONN_ACCEPT) {
-		BUG("Invalid connection state (bug in TLS code)\n");
-		     /* Not critical */
-		return 0;
-	}
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
 				" operation: %lu\n", shm_available());
 		goto err;
 	}
-
-	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
+	
+	tls_c=(struct tls_extra_data*)c->extra_data;
+	ssl=tls_c->ssl;
+	
+	if (tls_c->state != S_TLS_ACCEPTING) {
+		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
+		/* Not critical */
+		return 0;
+	}
 	ret = SSL_accept(ssl);
 	if (ret == 1) {
 		DBG("TLS accept successful\n");
-		c->state = S_CONN_OK;
-		LOG(tls_log, "tls_accept: new connection from %s:%d using %s %s %d\n", 
+		tls_c->state = S_TLS_ESTABLISHED;
+		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)
@@ -383,8 +394,7 @@ static int tls_accept(struct tcp_connection *c, int* error)
 		}
 	}
 	return 0;
- err:
-	c->state = S_CONN_BAD;
+err:
 	return -1;
 }
 
@@ -397,23 +407,26 @@ static int tls_connect(struct tcp_connection *c, int* error)
 	SSL *ssl;
 	int ret, err, ssl_err;
 	X509* cert;
+	struct tls_extra_data* tls_c;
 
-	if (c->state != S_CONN_CONNECT) {
-		BUG("Invalid connection state\n");
-		     /* Not critical */
-		return 0;
-	}
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
 				" operation: %lu\n", shm_available());
 		goto err;
 	}
 
-	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
+	tls_c=(struct tls_extra_data*)c->extra_data;
+	ssl=tls_c->ssl;
+	
+	if (tls_c->state != S_TLS_CONNECTING) {
+		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
+		/* Not critical */
+		return 0;
+	}
 	ret = SSL_connect(ssl);
 	if (ret == 1) {
 		DBG("TLS connect successuful\n");
-		c->state = S_CONN_OK;
+		tls_c->state = S_TLS_ESTABLISHED;
 		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),
@@ -481,8 +494,7 @@ static int tls_connect(struct tcp_connection *c, int* error)
 		}
 	}
 	return 0;
- err:
-	c->state = S_CONN_BAD;
+err:
 	return -1;
 }
 
@@ -707,17 +719,19 @@ int tls_h_blocking_write(struct tcp_connection *c, int fd, const char *buf,
 	int err, n, ticks, tout;
 	fd_set sel_set;
 	struct timeval timeout;
+	struct tls_extra_data* tls_c;
 	
 	n = 0;
 	if (tls_update_fd(c, fd) < 0) goto error;
+	tls_c=(struct tls_extra_data*)c->extra_data;
 again:
 	err = 0;
 	     /* first try  a "fast" write -- avoid the extra select call,
 	      * we might get lucky and not need it */
-	if (c->state == S_CONN_CONNECT) {
+	if (tls_c->state == S_TLS_CONNECTING) {
 		if (tls_connect(c, &err) < 0) goto error;
 		tout = tls_handshake_timeout;
-	} else if (c->state == S_CONN_ACCEPT) {
+	} else if (tls_c->state == S_TLS_ACCEPTING) {
 		if (tls_accept(c, &err) < 0) goto error;
 		tout = tls_handshake_timeout;
 	} else {
@@ -805,17 +819,19 @@ int tls_h_nonblocking_write(struct tcp_connection *c, int fd, const char *buf,
 			  unsigned int len)
 {
 	int err, n;
+	struct tls_extra_data* tls_c;
 	
 	n = 0;
 	if (tls_update_fd(c, fd) < 0) goto error;
+	tls_c=(struct tls_extra_data*)c->extra_data;
 again:
 	err = 0;
-	if (c->state == S_CONN_CONNECT) {
+	if (tls_c->state == S_TLS_CONNECTING) {
 		if (tls_connect(c, &err) < 0) goto error;
-	} else if (c->state == S_CONN_ACCEPT) {
+	} else if (tls_c->state == S_TLS_ACCEPTING) {
 		if (tls_accept(c, &err) < 0) goto error;
 	}
-	if (c->state!=S_CONN_CONNECT && c->state!=S_CONN_ACCEPT){
+	if (tls_c->state!=S_TLS_CONNECTING && tls_c->state!=S_TLS_ACCEPTING){
 		n = tls_write(c, buf, len, &err);
 		if (n < 0) {
 			DBG("tls_write error %d (ssl %d)\n", n, err);
@@ -856,8 +872,8 @@ end:
 
 
 /*
- * called only when a connection is in S_CONN_OK, we do not have to care
- * about accepting or connecting here, each modification of ssl data
+ * called only when a connection is in S_TLS_ESTABLISHED, we do not have to
+ * care about accepting or connecting here. 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 
@@ -944,40 +960,67 @@ int tls_h_read(struct tcp_connection * c)
 
 /*
  * called before tls_read, the this function should attempt tls_accept or
- * tls_connect depending on the state of the connection, if this function
- * does not transit a connection into S_CONN_OK then tcp layer would not
+ * tls_connect depending on the state of the connection.
+ * If this function does not return 1, then the tcp layer would not
  * call tcp_read 
+ * @return  1 success, 0 try again (don't attempt tls_read()), -1 error
  */
 int tls_h_fix_read_conn(struct tcp_connection *c)
 {
 	int ret;
-	ret = 0;
-
-	switch (c->state) {
-	case S_CONN_ACCEPT:
+	struct tls_extra_data* tls_c;
+	
+	ret = -1;
+	tls_c = 0;
+	if (unlikely(c->extra_data==0)){
 		lock_get(&c->write_lock);
-		     /* It might have changed meanwhile */
-		if (c->state == S_CONN_ACCEPT) {
-			ret = tls_update_fd(c, c->fd);
-			if (ret == 0) ret = tls_accept(c, 0);
-			else ret = -1;
-		}
+			if (unlikely(tls_update_fd(c, c->fd) < 0)){
+				ret = -1;
+			} else {
+				tls_c=(struct tls_extra_data*)c->extra_data;
+				switch(tls_c->state){
+					case S_TLS_ACCEPTING:
+						ret=tls_accept(c, 0);
+						break;
+					case S_TLS_CONNECTING:
+						ret=tls_connect(c, 0);
+						break;
+					default:
+						/* fall through */
+						ret=1;
+						break;
+				}
+			}
 		lock_release(&c->write_lock);
-		break;
-		
-	case S_CONN_CONNECT:
-		lock_get(&c->write_lock);
-		     /* It might have changed meanwhile */
-		if (c->state == S_CONN_CONNECT) {
-			ret = tls_update_fd(c, c->fd);
-			if (ret == 0) ret = tls_connect(c, 0);
-			else ret = -1;
+	} else {
+		tls_c=(struct tls_extra_data*)c->extra_data;
+		switch (tls_c->state) {
+			case S_TLS_ACCEPTING:
+				lock_get(&c->write_lock);
+					tls_c=(struct tls_extra_data*)c->extra_data;
+					/* It might have changed meanwhile */
+					if (likely(tls_c->state == S_TLS_ACCEPTING)) {
+						ret = tls_update_fd(c, c->fd);
+						if (ret == 0) ret = tls_accept(c, 0);
+						else ret = -1;
+					}
+				lock_release(&c->write_lock);
+			break;
+			case S_TLS_CONNECTING:
+				lock_get(&c->write_lock);
+					tls_c=(struct tls_extra_data*)c->extra_data;
+					/* It might have changed meanwhile */
+					if (likely(tls_c->state == S_TLS_CONNECTING)) {
+						ret = tls_update_fd(c, c->fd);
+						if (ret == 0) ret = tls_connect(c, 0);
+						else ret = -1;
+					}
+				lock_release(&c->write_lock);
+			break;
+		default: /* fall through */
+			ret=1;
+			break;
 		}
-		lock_release(&c->write_lock);
-		break;
-		
-	default: /* fall through */
-		break;
 	}
-	return ret;
+	return (ret>=0)?(tls_c->state==S_TLS_ESTABLISHED):ret;
 }

+ 8 - 0
modules_s/tls/tls_server.h

@@ -36,9 +36,17 @@
 #include "../../tcp_conn.h"
 #include "tls_domain.h"
 
+enum tls_conn_states {
+						S_TLS_NONE = 0,
+						S_TLS_ACCEPTING,
+						S_TLS_CONNECTING,
+						S_TLS_ESTABLISHED
+					};
+
 struct tls_extra_data {
 	tls_cfg_t* cfg; /* Configuration used for this connection */
 	SSL* ssl;       /* SSL context used for the connection */
+	enum  tls_conn_states state;
 };
 
 /*