From 00e37ceb88990f36eb6bf89ccf899e15416be4a4 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 21 Feb 2020 17:55:06 +0100 Subject: [PATCH] Finalize socks5 --- src/socks5.c | 144 ++++++++++++++++++++++++++++++++++++++------------- src/socks5.h | 9 ++++ 2 files changed, 118 insertions(+), 35 deletions(-) diff --git a/src/socks5.c b/src/socks5.c index e6a53fe..5bdb869 100644 --- a/src/socks5.c +++ b/src/socks5.c @@ -376,31 +376,32 @@ error: int on_socks5_server_recv_handshake(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { struct socks5_ctx* s5ctx = fdinfo->other; - // 1. We have read the whole buffer, change category - if (s5ctx->ch_cursor > 2 && s5ctx->ch_cursor >= s5ctx->ch.nmethods + 2) { - printf("[%s][socks5] read client handshake version: %d, nmethods: %d\n", current_human_datetime (), s5ctx->ch.ver, s5ctx->ch.nmethods); - for (int i = 0; i < s5ctx->ch.nmethods; i++) { - if (s5ctx->ch.methods[i] == METHOD_NOAUTH) { - evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-send-handshake"); - return EVT_CORE_FD_EXHAUSTED; // Success, we are compatible with client, moving to next state - } - } - // We failed to find a NOAUTH - fprintf(stderr, "Unable to find a NOAUTH method in the list of available method\n"); - evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-failed"); - return EVT_CORE_FD_EXHAUSTED; + // 1. We need to read more + if (s5ctx->ch_cursor < 2 || s5ctx->ch_cursor < s5ctx->ch.nmethods + 2) { + size_t to_read = 0; + if (s5ctx->ch_cursor < 2) to_read = 2 - s5ctx->ch_cursor; + else to_read = s5ctx->ch.nmethods - (s5ctx->ch_cursor - 2); + ssize_t nread = recv(fdinfo->fd, ((void*)&s5ctx->ch) + s5ctx->ch_cursor, to_read, 0); + if (nread == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; + if (nread == -1) goto serv_handshake_err; + s5ctx->ch_cursor += nread; + return EVT_CORE_FD_UNFINISHED; } - // 2. We need to read more - size_t to_read = 0; - if (s5ctx->ch_cursor < 2) to_read = 2 - s5ctx->ch_cursor; - else to_read = s5ctx->ch.nmethods - (s5ctx->ch_cursor - 2); - ssize_t nread = recv(fdinfo->fd, ((void*)&s5ctx->ch) + s5ctx->ch_cursor, to_read, 0); - if (nread == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; - if (nread == -1) goto serv_handshake_err; - s5ctx->ch_cursor += nread; + printf("[%s][socks5] read client handshake version: %d, nmethods: %d\n", current_human_datetime (), s5ctx->ch.ver, s5ctx->ch.nmethods); + for (int i = 0; i < s5ctx->ch.nmethods; i++) { + if (s5ctx->ch.methods[i] == METHOD_NOAUTH) goto success; + } + + fprintf(stderr, "Unable to find a NOAUTH method in the list of available method\n"); + evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-failed"); + return EVT_CORE_FD_EXHAUSTED; + +success: + printf("[%s][socks5] received client handshake handshake\n", current_human_datetime ()); + evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-send-handshake"); + return EVT_CORE_FD_EXHAUSTED; // Success, we are compatible with client, moving to next state - return EVT_CORE_FD_UNFINISHED; serv_handshake_err: perror("[socks5] unable to read handshake from socket."); evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-failed"); @@ -410,19 +411,18 @@ serv_handshake_err: int on_socks5_server_send_handshake(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { struct socks5_ctx* s5ctx = fdinfo->other; - // 1. We have sent the whole buffer - if (s5ctx->sh_cursor >= sizeof(s5ctx->sh)) { - printf("[%s][socks5] sent server handshake\n", current_human_datetime ()); - evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-recv-client-req"); - return EVT_CORE_FD_EXHAUSTED; + if (s5ctx->sh_cursor < sizeof(s5ctx->sh)) { + ssize_t nsent = send(fdinfo->fd, &s5ctx->sh, sizeof(s5ctx->sh) - s5ctx->sh_cursor, 0); + if (nsent == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; + if (nsent == -1) goto send_hs_error; + s5ctx->sh_cursor += nsent; + return EVT_CORE_FD_UNFINISHED; } - ssize_t nsent = send(fdinfo->fd, &s5ctx->sh, sizeof(s5ctx->sh) - s5ctx->sh_cursor, 0); - if (nsent == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; - if (nsent == -1) goto send_hs_error; - s5ctx->sh_cursor += nsent; + printf("[%s][socks5] sent server handshake\n", current_human_datetime ()); + evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-recv-client-req"); + return EVT_CORE_FD_EXHAUSTED; - return EVT_CORE_FD_UNFINISHED; send_hs_error: perror("[socks5] unable to send handshake to socket."); evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-failed"); @@ -431,15 +431,89 @@ send_hs_error: int on_socks5_server_recv_client_req(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { struct socks5_ctx* s5ctx = fdinfo->other; + ssize_t nread = 0; + size_t to_read = 0; - if (s5ctx->cr_cursor ) + size_t fixed_size = ((void*)&s5ctx->cr.dest_addr) - ((void*)&s5ctx->cr); + if (s5ctx->cr_cursor < fixed_size) { + to_read = fixed_size - s5ctx->cr_cursor; + nread = recv(fdinfo->fd, ((void*)&s5ctx->cr) + s5ctx->cr_cursor, to_read, 0); + if (nread == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; + if (nread == -1) goto recv_client_req_error; + s5ctx->cr_cursor += nread; + if (nread == to_read) s5ctx->cr_cursor = 0; + else return EVT_CORE_FD_UNFINISHED; + } - return EVT_CORE_FD_UNFINISHED; + if (!s5ctx->cr_host_read && s5ctx->cr.atyp == ATYP_DOMAINNAME) { + to_read = sizeof(s5ctx->cr.dest_addr.dns.len) + s5ctx->cr.dest_addr.dns.len - s5ctx->cr_cursor; + nread = recv(fdinfo->fd, ((void*)&s5ctx->cr.dest_addr.dns) + s5ctx->cr_cursor, to_read, 0); + if (nread == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; + if (nread == -1) goto recv_client_req_error; + s5ctx->cr_cursor += nread; + if (to_read == nread) { + s5ctx->cr_host_read = TRUE; + s5ctx->cr_cursor = 0; + } else return EVT_CORE_FD_UNFINISHED; + } else if (!s5ctx->cr_host_read && s5ctx->cr.atyp == ATYP_IPV4) { + to_read = sizeof(s5ctx->cr.dest_addr.ipv4) - s5ctx->cr_cursor; + nread = recv(fdinfo->fd, ((void*)&s5ctx->cr.dest_addr.ipv4) + s5ctx->cr_cursor, to_read, 0); + if (nread == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; + if (nread == -1) goto recv_client_req_error; + s5ctx->cr_cursor += nread; + if (to_read == nread) { + s5ctx->cr_host_read = TRUE; + s5ctx->cr_cursor = 0; + } else return EVT_CORE_FD_UNFINISHED; + } else if (!s5ctx->cr_host_read && s5ctx->cr.atyp == ATYP_IPV6) { + to_read = sizeof(s5ctx->cr.dest_addr.ipv6) - s5ctx->cr_cursor; + nread = recv(fdinfo->fd, ((void*)&s5ctx->cr.dest_addr.ipv6) + s5ctx->cr_cursor, to_read, 0); + if (nread == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; + if (nread == -1) goto recv_client_req_error; + s5ctx->cr_cursor += nread; + if (to_read == nread) { + s5ctx->cr_host_read = TRUE; + s5ctx->cr_cursor = 0; + } else return EVT_CORE_FD_UNFINISHED; + } else if (!s5ctx->cr_host_read) goto recv_client_req_error; + + to_read = ((void*)&s5ctx->cr+1) - ((void*)&s5ctx->cr.port) - s5ctx->cr_cursor; + nread = recv(fdinfo->fd, ((void*)&s5ctx->cr.port) + s5ctx->cr_cursor, to_read, 0); + if (nread == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; + if (nread == -1) goto recv_client_req_error; + s5ctx->cr_cursor += nread; + if (to_read != nread) return EVT_CORE_FD_UNFINISHED; + + printf("[%s][socks5] received client request atyp=%s: ", current_human_datetime (), atyp_str[s5ctx->cr.atyp]); + evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-send-server-reply"); + return EVT_CORE_FD_EXHAUSTED; + +recv_client_req_error: + perror("[socks5] unable to receive client request from socket."); + evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-failed"); + return EVT_CORE_FD_EXHAUSTED; } int on_socks5_server_send_server_reply(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { + struct socks5_ctx* s5ctx = fdinfo->other; + ssize_t nsent = 0; + size_t to_send = s5ctx->sr_size - s5ctx->sr_cursor; - return EVT_CORE_FD_UNFINISHED; + nsent = send(fdinfo->fd, s5ctx->sr_buffer + s5ctx->sr_cursor, to_send, 0); + if (nsent == -1 && errno == EAGAIN) return EVT_CORE_FD_EXHAUSTED; + if (nsent == -1) goto send_server_rep_error; + s5ctx->sr_cursor += nsent; + + if (nsent != to_send) return EVT_CORE_FD_UNFINISHED; + + printf("[%s][socks5] sent server reply\n", current_human_datetime ()); + evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-sucess"); + return EVT_CORE_FD_EXHAUSTED; + +send_server_rep_error: + perror("[socks5] unable to send server reply to socket."); + evt_core_mv_fd2 (ctx, fdinfo, "socks5-server-failed"); + return EVT_CORE_FD_EXHAUSTED; } void socks5_server_init(struct evt_core_ctx* ctx) { diff --git a/src/socks5.h b/src/socks5.h index 8d52696..f7cb8c0 100644 --- a/src/socks5.h +++ b/src/socks5.h @@ -29,6 +29,14 @@ enum atyp { ATYP_IPV6 = 0x04 }; +static char *atyp_str[] = { + "INVALID", + "IPV4", + "INVALID" + "DOMAIN NAME", + "IPV6" +}; + enum ver { VER_SOCKS5 = 0x05 }; @@ -129,6 +137,7 @@ struct socks5_ctx { size_t cr_size; size_t sr_size; uint8_t sr_host_read; + uint8_t cr_host_read; }; void socks5_init(struct evt_core_ctx* ctx);