SSL fixes, seems to work with stunnel4 as a client but not linuxdcpp using SSL directly.
This commit is contained in:
		
							parent
							
								
									4aa65733d0
								
							
						
					
					
						commit
						84bd2591d6
					
				@ -27,7 +27,7 @@ extern struct hub_info* g_hub;
 | 
				
			|||||||
#ifdef DEBUG_SENDQ
 | 
					#ifdef DEBUG_SENDQ
 | 
				
			||||||
void debug_sendq_send(struct hub_user* user, int sent, int total)
 | 
					void debug_sendq_send(struct hub_user* user, int sent, int total)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	LOG_DUMP("SEND: sd=%d, %d/%d bytes\n", user->net.connection.sd, sent, total);
 | 
						LOG_DUMP("SEND: sd=%d, %d/%d bytes\n", user->connection->sd, sent, total);
 | 
				
			||||||
	if (sent == -1)
 | 
						if (sent == -1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int err = net_error();
 | 
							int err = net_error();
 | 
				
			||||||
@ -162,7 +162,7 @@ void net_event(struct net_connection* con, int event, void *arg)
 | 
				
			|||||||
	int flag_close = 0;
 | 
						int flag_close = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DEBUG_SENDQ
 | 
					#ifdef DEBUG_SENDQ
 | 
				
			||||||
	LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", fd, (int) event, arg);
 | 
						LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (event == NET_EVENT_TIMEOUT)
 | 
						if (event == NET_EVENT_TIMEOUT)
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define NET_CLEANUP               0x8000
 | 
					#define NET_CLEANUP               0x8000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#define NET_CON_STRUCT_BASIC \
 | 
					#define NET_CON_STRUCT_BASIC \
 | 
				
			||||||
	int                  sd;        /** socket descriptor */ \
 | 
						int                  sd;        /** socket descriptor */ \
 | 
				
			||||||
	uint32_t             flags;     /** Connection flags */ \
 | 
						uint32_t             flags;     /** Connection flags */ \
 | 
				
			||||||
@ -38,6 +37,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define NET_CON_STRUCT_SSL \
 | 
					#define NET_CON_STRUCT_SSL \
 | 
				
			||||||
	SSL*                 ssl;       /** SSL handle */ \
 | 
						SSL*                 ssl;       /** SSL handle */ \
 | 
				
			||||||
 | 
						uint32_t             ssl_state; /** SSL state */ \
 | 
				
			||||||
	size_t               write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \
 | 
						size_t               write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef SSL_SUPPORT
 | 
					#ifdef SSL_SUPPORT
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,17 @@
 | 
				
			|||||||
#include "network/common.h"
 | 
					#include "network/common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef SSL_SUPPORT
 | 
					#ifdef SSL_SUPPORT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum uhub_tls_state
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						tls_st_none,
 | 
				
			||||||
 | 
						tls_st_error,
 | 
				
			||||||
 | 
						tls_st_accepting,
 | 
				
			||||||
 | 
						tls_st_connecting,
 | 
				
			||||||
 | 
						tls_st_connected,
 | 
				
			||||||
 | 
						tls_st_disconnecting,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int handle_openssl_error(struct net_connection* con, int ret)
 | 
					static int handle_openssl_error(struct net_connection* con, int ret)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uhub_assert(con);
 | 
						uhub_assert(con);
 | 
				
			||||||
@ -30,30 +41,19 @@ static int handle_openssl_error(struct net_connection* con, int ret)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		case SSL_ERROR_ZERO_RETURN:
 | 
							case SSL_ERROR_ZERO_RETURN:
 | 
				
			||||||
			LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
 | 
								LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
 | 
				
			||||||
 | 
								con->ssl_state = tls_st_error;
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case SSL_ERROR_WANT_READ:
 | 
							case SSL_ERROR_WANT_READ:
 | 
				
			||||||
			LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
 | 
								LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
 | 
				
			||||||
			net_con_update(con, NET_EVENT_READ | NET_WANT_SSL_READ);
 | 
								con->flags |= NET_WANT_SSL_READ;
 | 
				
			||||||
 | 
								net_con_update(con, NET_EVENT_READ);
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case SSL_ERROR_WANT_WRITE:
 | 
							case SSL_ERROR_WANT_WRITE:
 | 
				
			||||||
			LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
 | 
								LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
 | 
				
			||||||
			net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE | NET_WANT_SSL_WRITE);
 | 
								con->flags |= NET_WANT_SSL_WRITE;
 | 
				
			||||||
			return 0;
 | 
								net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		case SSL_ERROR_WANT_CONNECT:
 | 
					 | 
				
			||||||
			LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_CONNECT", ret, error);
 | 
					 | 
				
			||||||
			net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE | NET_WANT_SSL_CONNECT);
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case SSL_ERROR_WANT_ACCEPT:
 | 
					 | 
				
			||||||
			LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_ACCEPT", ret, error);
 | 
					 | 
				
			||||||
			net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE | NET_WANT_SSL_ACCEPT);
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case SSL_ERROR_WANT_X509_LOOKUP:
 | 
					 | 
				
			||||||
			LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_X509_LOOKUP", ret, error);
 | 
					 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case SSL_ERROR_SYSCALL:
 | 
							case SSL_ERROR_SYSCALL:
 | 
				
			||||||
@ -67,6 +67,7 @@ static int handle_openssl_error(struct net_connection* con, int ret)
 | 
				
			|||||||
		case SSL_ERROR_SSL:
 | 
							case SSL_ERROR_SSL:
 | 
				
			||||||
			LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
 | 
								LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
 | 
				
			||||||
			/* internal openssl error */
 | 
								/* internal openssl error */
 | 
				
			||||||
 | 
								con->ssl_state = tls_st_error;
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -76,7 +77,7 @@ static int handle_openssl_error(struct net_connection* con, int ret)
 | 
				
			|||||||
ssize_t net_con_ssl_accept(struct net_connection* con)
 | 
					ssize_t net_con_ssl_accept(struct net_connection* con)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uhub_assert(con);
 | 
						uhub_assert(con);
 | 
				
			||||||
 | 
						con->ssl_state = tls_st_accepting;
 | 
				
			||||||
	ssize_t ret = SSL_accept(con->ssl);
 | 
						ssize_t ret = SSL_accept(con->ssl);
 | 
				
			||||||
#ifdef NETWORK_DUMP_DEBUG
 | 
					#ifdef NETWORK_DUMP_DEBUG
 | 
				
			||||||
	LOG_PROTO("SSL_accept() ret=%d", ret);
 | 
						LOG_PROTO("SSL_accept() ret=%d", ret);
 | 
				
			||||||
@ -84,6 +85,7 @@ ssize_t net_con_ssl_accept(struct net_connection* con)
 | 
				
			|||||||
	if (ret > 0)
 | 
						if (ret > 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		net_con_update(con, NET_EVENT_READ);
 | 
							net_con_update(con, NET_EVENT_READ);
 | 
				
			||||||
 | 
							con->ssl_state = tls_st_connected;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -96,12 +98,14 @@ ssize_t net_con_ssl_connect(struct net_connection* con)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	uhub_assert(con);
 | 
						uhub_assert(con);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						con->ssl_state = tls_st_connecting;
 | 
				
			||||||
	ssize_t ret = SSL_connect(con->ssl);
 | 
						ssize_t ret = SSL_connect(con->ssl);
 | 
				
			||||||
#ifdef NETWORK_DUMP_DEBUG
 | 
					#ifdef NETWORK_DUMP_DEBUG
 | 
				
			||||||
	LOG_PROTO("SSL_connect() ret=%d", ret);
 | 
						LOG_PROTO("SSL_connect() ret=%d", ret);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	if (ret > 0)
 | 
						if (ret > 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							con->ssl_state = tls_st_connected;
 | 
				
			||||||
		net_con_update(con, NET_EVENT_READ);
 | 
							net_con_update(con, NET_EVENT_READ);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
@ -136,28 +140,42 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
 | 
					ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
 | 
						int ret;
 | 
				
			||||||
	if (ret == -1)
 | 
					#ifdef SSL_SUPPORT
 | 
				
			||||||
 | 
						if (!con->ssl)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (net_error() == EWOULDBLOCK || net_error() == EINTR)
 | 
					#endif
 | 
				
			||||||
			return 0;
 | 
							ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
 | 
				
			||||||
		return -1;
 | 
							if (ret == -1)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (net_error() == EWOULDBLOCK || net_error() == EINTR)
 | 
				
			||||||
 | 
									return 0;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					#ifdef SSL_SUPPORT
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							con->write_len = len;
 | 
				
			||||||
 | 
							ret = SSL_write(con->ssl, buf, len);
 | 
				
			||||||
 | 
							LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
 | 
				
			||||||
 | 
							if (ret <= 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return -handle_openssl_error(con, ret);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
 | 
					ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uhub_assert(con);
 | 
						int ret;
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef SSL_SUPPORT
 | 
					#ifdef SSL_SUPPORT
 | 
				
			||||||
	if (!net_con_is_ssl(con))
 | 
						if (!net_con_is_ssl(con))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		int ret = net_recv(con->sd, buf, len, 0);
 | 
							ret = net_recv(con->sd, buf, len, 0);
 | 
				
			||||||
#ifdef NETWORK_DUMP_DEBUG
 | 
					 | 
				
			||||||
		LOG_PROTO("net_recv: ret=%d", ret);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		if (ret == -1)
 | 
							if (ret == -1)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (net_error() == EWOULDBLOCK || net_error() == EINTR)
 | 
								if (net_error() == EWOULDBLOCK || net_error() == EINTR)
 | 
				
			||||||
@ -168,16 +186,15 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
#ifdef SSL_SUPPORT
 | 
					#ifdef SSL_SUPPORT
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int ret = SSL_read(con->ssl, buf, len);
 | 
							if (con->ssl_state == tls_st_error)
 | 
				
			||||||
#ifdef NETWORK_DUMP_DEBUG
 | 
								return -1;
 | 
				
			||||||
		LOG_PROTO("net_recv: ret=%d", ret);
 | 
					
 | 
				
			||||||
#endif
 | 
							ret = SSL_read(con->ssl, buf, len);
 | 
				
			||||||
 | 
							LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
 | 
				
			||||||
		if (ret > 0)
 | 
							if (ret > 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			net_con_update(con, NET_EVENT_READ);
 | 
								net_con_update(con, NET_EVENT_READ);
 | 
				
			||||||
@ -186,9 +203,9 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			return -handle_openssl_error(con, ret);
 | 
								return -handle_openssl_error(con, ret);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
 | 
					ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
 | 
				
			||||||
@ -234,7 +251,7 @@ void* net_con_get_ptr(struct net_connection* con)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void net_con_callback(struct net_connection* con, int events)
 | 
					void net_con_callback(struct net_connection* con, int events)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if ((con->flags & NET_CLEANUP))
 | 
						if (con->flags & NET_CLEANUP)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (events == NET_EVENT_TIMEOUT)
 | 
						if (events == NET_EVENT_TIMEOUT)
 | 
				
			||||||
@ -254,27 +271,47 @@ void net_con_callback(struct net_connection* con, int events)
 | 
				
			|||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
#ifdef NETWORK_DUMP_DEBUG
 | 
					#ifdef NETWORK_DUMP_DEBUG
 | 
				
			||||||
		LOG_PROTO("net_con_event: events=%d, con=%p", ev, con);
 | 
							LOG_PROTO("net_con_event: events=%d, con=%p, state=%d", events, con, con->ssl_state);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		if (events == NET_EVENT_READ && con->flags & NET_WANT_SSL_READ)
 | 
							switch (con->ssl_state)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			con->callback(con, NET_EVENT_WRITE, con->ptr);
 | 
								case tls_st_none:
 | 
				
			||||||
		}
 | 
									con->callback(con, events, con->ptr);
 | 
				
			||||||
		else if (events == NET_EVENT_WRITE && con->flags & NET_WANT_SSL_WRITE)
 | 
									break;
 | 
				
			||||||
		{
 | 
					
 | 
				
			||||||
			con->callback(con, events & NET_EVENT_READ, con->ptr);
 | 
								case tls_st_accepting:
 | 
				
			||||||
		}
 | 
									if (net_con_ssl_accept(con) < 0)
 | 
				
			||||||
		if (con->flags & NET_WANT_SSL_ACCEPT)
 | 
									{
 | 
				
			||||||
		{
 | 
										con->callback(con, NET_EVENT_READ, con->ptr);
 | 
				
			||||||
			net_con_ssl_accept(con);
 | 
									}
 | 
				
			||||||
		}
 | 
									break;
 | 
				
			||||||
		else if (con->flags & NET_WANT_SSL_CONNECT)
 | 
					
 | 
				
			||||||
		{
 | 
								case tls_st_connecting:
 | 
				
			||||||
			net_con_ssl_connect(con);
 | 
									if (net_con_ssl_connect(con) < 0)
 | 
				
			||||||
		}
 | 
									{
 | 
				
			||||||
		else
 | 
										con->callback(con, NET_EVENT_READ, con->ptr);
 | 
				
			||||||
		{
 | 
									}
 | 
				
			||||||
			con->callback(con, events, con->ptr);
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case tls_st_connected:
 | 
				
			||||||
 | 
									LOG_PROTO("tls_st_connected, events=%s%s, ssl_flags=%s%s", (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), con->flags & NET_WANT_SSL_READ ? "R" : "", con->flags & NET_WANT_SSL_WRITE ? "W" : "");
 | 
				
			||||||
 | 
									if (events & NET_EVENT_WRITE && con->flags & NET_WANT_SSL_READ)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										con->callback(con, events & NET_EVENT_READ, con->ptr);
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (events & NET_EVENT_READ && con->flags & NET_WANT_SSL_WRITE)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										con->callback(con, events & NET_EVENT_READ, con->ptr);
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									con->callback(con, events, con->ptr);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case tls_st_disconnecting:
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user