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: - - /* 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; - } - - 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; - } - - lws_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT); - wsi->mode = conn_mode; - - break; - /* SOCKS auth Reply */ case LWSCM_WSCL_WAITING_SOCKS_AUTH_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; - } - - lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); - lwsl_err("ERROR reading from socks socket\n"); - return 0; - } - - /* 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"); - 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; + 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 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; - } - - /* 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)) + lwsl_err("ERROR reading from SOCKS socket\n"); goto bail3; - wsi->c_port = wsi->vhost->socks_proxy_port; + } - /* clear his proxy connection timeout */ + switch (wsi->mode) { - lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); + case LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY: + if (pt->serv_buf[0] != SOCKS_VERSION_5) + goto socks_reply_fail; - goto start_ws_hanshake; + 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; + } + + 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; + + 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; + + 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; +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_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT); + wsi->mode = conn_mode; + break; + +socks_reply_fail: + lwsl_notice("socks reply: v%d, err %d\n", + pt->serv_buf[0], pt->serv_buf[1]); + goto bail3; + + 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; + + lwsl_client("socks connect OK\n"); + + /* 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; + + wsi->c_port = wsi->vhost->socks_proxy_port; + + /* 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;