From 32eaf83f24ec4b355add6fa8ffbcc0ef5884f7d1 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@warmcat.com>
Date: Fri, 1 Sep 2017 19:09:47 +0800
Subject: [PATCH] socks5: style and exit handling
---
lib/client-handshake.c | 49 ++++-----
lib/client.c | 224 ++++++++++++-----------------------------
2 files changed, 89 insertions(+), 184 deletions(-)
diff --git a/lib/client-handshake.c b/lib/client-handshake.c
index ae4bcdc8..cfb1f39c 100644
--- a/lib/client-handshake.c
+++ b/lib/client-handshake.c
@@ -87,8 +87,7 @@ lws_client_connect_2(struct lws *wsi)
} else if (wsi->vhost->socks_proxy_port) {
socks_generate_msg(wsi, SOCKS_MSG_GREETING, &plen);
- lwsl_client("%s\n", "Sending SOCKS Greeting.");
-
+ lwsl_client("Sending SOCKS Greeting\n");
ads = wsi->vhost->socks_proxy_address;
port = wsi->vhost->socks_proxy_port;
#endif
@@ -366,8 +365,7 @@ lws_client_connect_2(struct lws *wsi)
n = send(wsi->desc.sockfd, (char *)pt->serv_buf, plen,
MSG_NOSIGNAL);
if (n < 0) {
- lwsl_debug("ERROR writing greeting to socks proxy"
- "socket.\n");
+ lwsl_debug("ERROR writing socks greeting\n");
cce = "socks write failed";
goto failed;
}
@@ -980,9 +978,12 @@ void socks_generate_msg(struct lws *wsi, enum socks_msg_type type,
{
struct lws_context *context = wsi->context;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- ssize_t len = 0;
+ ssize_t len = 0, n, passwd_len;
+ short net_num;
+ char *p;
- if (type == SOCKS_MSG_GREETING) {
+ switch (type) {
+ case SOCKS_MSG_GREETING:
/* socks version, version 5 only */
pt->serv_buf[len++] = SOCKS_VERSION_5;
/* number of methods */
@@ -991,33 +992,30 @@ void socks_generate_msg(struct lws *wsi, enum socks_msg_type type,
pt->serv_buf[len++] = SOCKS_AUTH_USERNAME_PASSWORD;
/* no authentication method */
pt->serv_buf[len++] = SOCKS_AUTH_NO_AUTH;
- }
- else if (type == SOCKS_MSG_USERNAME_PASSWORD) {
- ssize_t user_len = 0;
- ssize_t passwd_len = 0;
+ break;
- user_len = strlen(wsi->vhost->socks_user);
+ case SOCKS_MSG_USERNAME_PASSWORD:
+ n = strlen(wsi->vhost->socks_user);
passwd_len = strlen(wsi->vhost->socks_password);
/* the subnegotiation version */
pt->serv_buf[len++] = SOCKS_SUBNEGOTIATION_VERSION_1;
/* length of the user name */
- pt->serv_buf[len++] = user_len;
+ pt->serv_buf[len++] = n;
/* user name */
strncpy((char *)&pt->serv_buf[len], wsi->vhost->socks_user,
context->pt_serv_buf_size - len);
- len += user_len;
+ len += n;
/* length of the password */
pt->serv_buf[len++] = passwd_len;
/* password */
strncpy((char *)&pt->serv_buf[len], wsi->vhost->socks_password,
context->pt_serv_buf_size - len);
len += passwd_len;
- }
- else if (type == SOCKS_MSG_CONNECT) {
- ssize_t len_index = 0;
- short net_num = 0;
- char *net_buf = (char*)&net_num;
+ break;
+
+ case SOCKS_MSG_CONNECT:
+ p = (char*)&net_num;
/* socks version */
pt->serv_buf[len++] = SOCKS_VERSION_5;
@@ -1027,20 +1025,25 @@ void socks_generate_msg(struct lws *wsi, enum socks_msg_type type,
pt->serv_buf[len++] = 0;
/* address type */
pt->serv_buf[len++] = SOCKS_ATYP_DOMAINNAME;
- len_index = len++;
+ /* skip length, we fill it in at the end */
+ n = len++;
/* the address we tell SOCKS proxy to connect to */
strncpy((char *)&(pt->serv_buf[len]), wsi->u.hdr.stash->address,
context->pt_serv_buf_size - len);
len += strlen(wsi->u.hdr.stash->address);
- net_num = htons((short)wsi->c_port);
+ net_num = htons(wsi->c_port);
/* the port we tell SOCKS proxy to connect to */
- pt->serv_buf[len++] = net_buf[0];
- pt->serv_buf[len++] = net_buf[1];
+ pt->serv_buf[len++] = p[0];
+ pt->serv_buf[len++] = p[1];
/* the length of the address, excluding port */
- pt->serv_buf[len_index] = strlen(wsi->u.hdr.stash->address);
+ pt->serv_buf[n] = strlen(wsi->u.hdr.stash->address);
+ break;
+
+ default:
+ return;
}
*msg_len = len;
diff --git a/lib/client.c b/lib/client.c
index 40ba4b32..f712271d 100755
--- a/lib/client.c
+++ b/lib/client.c
@@ -113,192 +113,98 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
#if defined(LWS_WITH_SOCKS5)
/* SOCKS Greeting Reply */
case LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY:
+ case LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY:
+ case LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY:
/* handle proxy hung up on us */
if (pollfd->revents & LWS_POLLHUP) {
-
lwsl_warn("SOCKS connection %p (fd=%d) dead\n",
(void *)wsi, pollfd->fd);
-
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
- return 0;
+ goto bail3;
}
n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
if (n < 0) {
if (LWS_ERRNO == LWS_EAGAIN) {
- lwsl_debug("SOCKS read returned EAGAIN..."
- "retrying\n");
+ lwsl_debug("SOCKS read EAGAIN, retrying\n");
return 0;
}
-
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
lwsl_err("ERROR reading from SOCKS socket\n");
- return 0;
- }
-
- /* processing greeting reply */
- if (pt->serv_buf[0] == SOCKS_VERSION_5
- && pt->serv_buf[1] == SOCKS_AUTH_NO_AUTH)
- {
- lwsl_client("%s\n", "SOCKS greeting reply received "
- "- No Authentication Method");
- socks_generate_msg(wsi, SOCKS_MSG_CONNECT, &len);
-
- conn_mode = LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY;
- pending_timeout = PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
- lwsl_client("%s\n", "Sending SOCKS connect command");
- }
- else if (pt->serv_buf[0] == SOCKS_VERSION_5
- && pt->serv_buf[1] == SOCKS_AUTH_USERNAME_PASSWORD)
- {
- lwsl_client("%s\n", "SOCKS greeting reply received "
- "- User Name Password Method");
- socks_generate_msg(wsi, SOCKS_MSG_USERNAME_PASSWORD,
- &len);
-
- conn_mode = LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY;
- pending_timeout = PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY;
- lwsl_client("%s\n", "Sending SOCKS user/password");
- }
- else
- {
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
- lwsl_err("ERROR SOCKS greeting reply failed, method "
- "code: %d\n", pt->serv_buf[1]);
- return 0;
- }
-
- n = send(wsi->desc.sockfd, (char *)pt->serv_buf, len,
- MSG_NOSIGNAL);
- if (n < 0) {
- lwsl_debug("ERROR writing socks command to socks proxy "
- "socket\n");
- return 0;
+ goto bail3;
}
- lws_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT);
- wsi->mode = conn_mode;
+ switch (wsi->mode) {
- break;
- /* SOCKS auth Reply */
- case LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY:
-
- /* handle proxy hung up on us */
+ case LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY:
+ if (pt->serv_buf[0] != SOCKS_VERSION_5)
+ goto socks_reply_fail;
- if (pollfd->revents & LWS_POLLHUP) {
-
- lwsl_warn("SOCKS connection %p (fd=%d) dead\n",
- (void *)wsi, pollfd->fd);
-
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
- return 0;
- }
+ if (pt->serv_buf[1] == SOCKS_AUTH_NO_AUTH) {
+ lwsl_client("SOCKS greeting reply: No Auth Method\n");
+ socks_generate_msg(wsi, SOCKS_MSG_CONNECT, &len);
+ conn_mode = LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY;
+ pending_timeout = PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
+ goto socks_send;
+ }
- n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
- if (n < 0) {
- if (LWS_ERRNO == LWS_EAGAIN) {
- lwsl_debug("SOCKS read returned EAGAIN... "
- "retrying\n");
- return 0;
+ if (pt->serv_buf[1] == SOCKS_AUTH_USERNAME_PASSWORD) {
+ lwsl_client("SOCKS greeting reply: User/Pw Method\n");
+ socks_generate_msg(wsi, SOCKS_MSG_USERNAME_PASSWORD, &len);
+ conn_mode = LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY;
+ pending_timeout = PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY;
+ goto socks_send;
}
+ goto socks_reply_fail;
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
- lwsl_err("ERROR reading from socks socket\n");
- return 0;
- }
+ case LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY:
+ if (pt->serv_buf[0] != SOCKS_SUBNEGOTIATION_VERSION_1 ||
+ pt->serv_buf[1] != SOCKS_SUBNEGOTIATION_STATUS_SUCCESS)
+ goto socks_reply_fail;
- /* processing auth reply */
- if (pt->serv_buf[0] == SOCKS_SUBNEGOTIATION_VERSION_1
- && pt->serv_buf[1] == SOCKS_SUBNEGOTIATION_STATUS_SUCCESS)
- {
- lwsl_client("%s\n", "SOCKS password reply recieved - "
- "successful");
+ lwsl_client("SOCKS password OK, sending connect\n");
socks_generate_msg(wsi, SOCKS_MSG_CONNECT, &len);
-
conn_mode = LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY;
- pending_timeout =
- PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
- lwsl_client("%s\n", "Sending SOCKS connect command");
- }
- else
- {
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
- lwsl_err("ERROR : SOCKS user/password reply failed, "
- "error code: %d\n", pt->serv_buf[1]);
- return 0;
- }
-
- n = send(wsi->desc.sockfd, (char *)pt->serv_buf, len,
- MSG_NOSIGNAL);
- if (n < 0) {
- lwsl_debug("ERROR writing connect command to SOCKS "
- "socket\n");
- return 0;
- }
-
- lws_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT);
- wsi->mode = conn_mode;
-
- break;
-
- /* SOCKS connect command Reply */
- case LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY:
-
- /* handle proxy hung up on us */
-
- if (pollfd->revents & LWS_POLLHUP) {
-
- lwsl_warn("SOCKS connection %p (fd=%d) dead\n",
- (void *)wsi, pollfd->fd);
-
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
- return 0;
- }
-
- n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
- if (n < 0) {
- if (LWS_ERRNO == LWS_EAGAIN) {
- lwsl_debug("SOCKS read returned EAGAIN... "
- "retrying\n");
- return 0;
+ pending_timeout = PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
+socks_send:
+ n = send(wsi->desc.sockfd, (char *)pt->serv_buf, len,
+ MSG_NOSIGNAL);
+ if (n < 0) {
+ lwsl_debug("ERROR writing to socks proxy\n");
+ goto bail3;
}
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
- lwsl_err("ERROR reading from socks socket\n");
- return 0;
- }
+ lws_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT);
+ wsi->mode = conn_mode;
+ break;
- /* processing connect reply */
- if (pt->serv_buf[0] == SOCKS_VERSION_5
- && pt->serv_buf[1] == SOCKS_REQUEST_REPLY_SUCCESS)
- {
- lwsl_client("%s\n", "SOCKS connect reply recieved - "
- "successful");
- }
- else
- {
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
- lwsl_err("ERROR SOCKS connect reply failed, error "
- "code: %d\n", pt->serv_buf[1]);
- return 0;
- }
+socks_reply_fail:
+ lwsl_notice("socks reply: v%d, err %d\n",
+ pt->serv_buf[0], pt->serv_buf[1]);
+ goto bail3;
- /* free stash since we are done with it */
- lws_free_set_NULL(wsi->u.hdr.stash);
+ case LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY:
+ if (pt->serv_buf[0] != SOCKS_VERSION_5 ||
+ pt->serv_buf[1] != SOCKS_REQUEST_REPLY_SUCCESS)
+ goto socks_reply_fail;
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
- wsi->vhost->socks_proxy_address))
- goto bail3;
- wsi->c_port = wsi->vhost->socks_proxy_port;
+ lwsl_client("socks connect OK\n");
- /* clear his proxy connection timeout */
+ /* free stash since we are done with it */
+ lws_free_set_NULL(wsi->u.hdr.stash);
+ if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
+ wsi->vhost->socks_proxy_address))
+ goto bail3;
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+ wsi->c_port = wsi->vhost->socks_proxy_port;
- goto start_ws_hanshake;
+ /* clear his proxy connection timeout */
+ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+ goto start_ws_handshake;
+ }
+ break;
#endif
+
case LWSCM_WSCL_WAITING_PROXY_REPLY:
/* handle proxy hung up on us */
@@ -308,8 +214,7 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
lwsl_warn("Proxy connection %p (fd=%d) dead\n",
(void *)wsi, pollfd->fd);
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
- return 0;
+ goto bail3;
}
n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
@@ -318,18 +223,15 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
lwsl_debug("Proxy read returned EAGAIN... retrying\n");
return 0;
}
-
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
lwsl_err("ERROR reading from proxy socket\n");
- return 0;
+ goto bail3;
}
pt->serv_buf[13] = '\0';
if (strcmp(sb, "HTTP/1.0 200 ") &&
strcmp(sb, "HTTP/1.1 200 ")) {
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
lwsl_err("ERROR proxy: %s\n", sb);
- return 0;
+ goto bail3;
}
/* clear his proxy connection timeout */
@@ -348,7 +250,7 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
* happening at a time when there's no real connection yet
*/
#if defined(LWS_WITH_SOCKS5)
-start_ws_hanshake:
+start_ws_handshake:
#endif
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
return -1;
--
GitLab