From 9d4aae315eb98abb94bcfc79932869c8887fd1f9 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 25 Mar 2019 15:26:30 +0100 Subject: [PATCH] WIP socks5 - refactor socks5 --- src/donar_client.c | 170 +++++++++++++++------------------------------ src/donar_client.h | 1 + src/socks5.c | 51 +++++++++----- src/socks5.h | 21 +++++- 4 files changed, 110 insertions(+), 133 deletions(-) diff --git a/src/donar_client.c b/src/donar_client.c index bc93276..9c3c900 100644 --- a/src/donar_client.c +++ b/src/donar_client.c @@ -5,121 +5,69 @@ void load_onion_services(struct donar_client_ctx* ctx, char* onion_file, int por tor_os_read (&(ctx->tos)); } -void init_tcp_client(struct donar_client_ctx* ctx, int i) { - struct evt_core_cat cat = {0}; - struct evt_core_fdinfo fdinfo = {0}; - char url_buf[255]; - int err; - - ctx->ports[i] = 7500 + i; - cat.name = "configure-socks5"; - fdinfo.cat = &cat; - fdinfo.url = url_buf; - - while (1) { - fdinfo.fd = create_tcp_client("127.0.0.1", "9050"); - if (fdinfo.fd < 0) goto failed_socks5; - ctx->client_sock[i].fd = fdinfo.fd; - ctx->client_sock[i].state = SOCKS5_STATE_NEW; - sprintf(url_buf, "socks5:dist:%d", i); - evt_core_add_fd (&(ctx->evts), &fdinfo); - //@FIXME: We suppose that we will be able to do the whole write at once which is wrong - err = socks5_handshake_syn(fdinfo.fd); - if (err) goto failed_socks5; - - break; -failed_socks5: - fprintf(stderr, "Failed connection for socket %d/%d. Sleeping 2 seconds...\n",i+1, CLIENT_PORT_SIZE); - close(fdinfo.fd); - sleep(2); - } -} - -int configure_tcp_clients(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { - int err, pos; - struct donar_client_ctx* app_ctx = (struct donar_client_ctx*) fdinfo->cat->app_ctx; - - pos = -1; - for (int i = 0; i < CLIENT_PORT_SIZE; i++) { - if (app_ctx->client_sock[i].fd == fdinfo->fd) { - pos = i; - } - } - - char target_host[255]; +void init_socks5_client(struct donar_client_ctx* app_ctx, int pos) { + char target_host[255]; if (strlen(app_ctx->tos.keys[pos].pub) > 254) { fprintf(stderr, "Domain name is too long\n"); exit(EXIT_FAILURE); } sprintf(target_host, "%s.onion", app_ctx->tos.keys[pos].pub); - switch (app_ctx->client_sock[pos].state) { - case SOCKS5_STATE_NEW: - //@FIXME: We suppose that we will be able to do the whole read at once which is wrong - err = socks5_handshake_ack (fdinfo->fd); - if (err < 0) goto on_socks5_err; - //@FIXME: We suppose that we will be able to do the whole write at once which is wrong too - err = socks5_connect_dns(fdinfo->fd, target_host, app_ctx->ports[pos]); - if (err < 0) goto on_socks5_err; - app_ctx->client_sock[pos].state = SOCKS5_STATE_ACK; - printf("Socket %d/%d %s:%d is connecting...\n", pos+1, CLIENT_PORT_SIZE, target_host, app_ctx->ports[pos]); - break; - case SOCKS5_STATE_ACK: - //@FIXME: We suppose that we will be able to do the whole read at once which is wrong too - err = socks5_reply (fdinfo->fd); - if (err == -SOCKS5_REP_GENERAL_FAILURE || err == -SOCKS5_REP_TTLEXP || err == -SOCKS5_REP_HOSTUNREACH) { - fprintf(stderr, "%s is not ready, received %s\n", fdinfo->url, socks5_rep(-err)); - goto on_socks5_err; - } else if (err < 0) { - fprintf(stderr, "An other error occured on %s\n", fdinfo->url); - exit(EXIT_FAILURE); - } - app_ctx->client_sock[pos].state = SOCKS5_STATE_RDY; - int sock1, sock2; - sock1 = dup(fdinfo->fd); - sock2 = dup(fdinfo->fd); - if (sock1 < 0 || sock2 < 0) { - exit(EXIT_FAILURE); - } - void* fdcat = evt_core_rm_fd (ctx, fdinfo->fd); - if (fdcat == NULL) { - exit(EXIT_FAILURE); - } - struct evt_core_fdinfo fdinfo = {0}; - struct evt_core_cat cat = {0}; - char url[1024]; - fdinfo.cat = &cat; - fdinfo.url = url; + app_ctx->ports[pos] = 7500 + pos; + socks5_create_dns_client (&app_ctx->evts, "127.0.0.1", "9050", target_host, app_ctx->ports[pos]); +} - fdinfo.cat->name = "tcp-write"; - fdinfo.fd = sock1; - sprintf(fdinfo.url, "tcp:write:127.0.0.1:%d", app_ctx->ports[pos]); - evt_core_add_fd (ctx, &fdinfo); +int on_socks5_success(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { + struct evt_core_fdinfo fdinfo_n = {0}; + struct evt_core_cat cat_n = {0}; + struct socks5_ctx* s5ctx = fdinfo->other; + fdinfo_n.cat = &cat_n; + int ret = 0; - fdinfo.cat->name = "tcp-read"; - fdinfo.fd = sock2; - sprintf(fdinfo.url, "tcp:read:127.0.0.1:%d", app_ctx->ports[pos]); - evt_core_add_fd (ctx, &fdinfo); + fdinfo_n.fd = dup(fdinfo->fd); + fdinfo_n.cat->name = "tcp-write"; + ret = asprintf(&fdinfo_n.url, "tcp:write:127.0.0.1:%d", s5ctx->port); + if (ret < 0) goto failed; + evt_core_add_fd (ctx, &fdinfo_n); - printf("Socket %d/%d %s:%d has been added to the pool!\n", pos+1, CLIENT_PORT_SIZE, target_host, app_ctx->ports[pos]); - break; - case SOCKS5_STATE_RDY: - goto on_socks5_err; - break; - case SOCKS5_STATE_ERR: - goto on_socks5_err; - break; - } + fdinfo_n.fd = dup(fdinfo->fd); + fdinfo_n.cat->name = "tcp-read"; + ret = asprintf(&fdinfo_n.url, "tcp:read:127.0.0.1:%d", s5ctx->port); + if (ret < 0) goto failed; + evt_core_add_fd (ctx, &fdinfo_n); - return 1; -on_socks5_err: - //perror("An error occured while connecting to an Onion Service"); - app_ctx->client_sock[pos].state = SOCKS5_STATE_ERR; - evt_core_rm_fd (ctx, fdinfo->fd); - sleep(2); - init_tcp_client (app_ctx, pos); - return 1; + evt_core_rm_fd (ctx, fdinfo->fd); + return 1; + +failed: + fprintf(stderr, "Memory allocation failed\n"); + exit(EXIT_FAILURE); +} + +int on_socks5_failed(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { + struct donar_client_ctx* app_ctx = fdinfo->cat->app_ctx; + struct socks5_ctx* s5ctx = fdinfo->other; + int pos = 7500 - s5ctx->port; + + evt_core_rm_fd (ctx, fdinfo->fd); + init_socks5_client (app_ctx, pos); + return 1; +} + +void init_socks5_sinks(struct donar_client_ctx* app_ctx) { + struct evt_core_cat template = { 0 }; + + template.cb = on_socks5_success; + template.name = "socks5-success"; + template.flags = EPOLLET; + evt_core_add_cat(&app_ctx->evts, &template); + + template.cb = on_socks5_failed; + template.app_ctx = app_ctx; + template.name = "socks5-failed"; + template.flags = EPOLLET; + evt_core_add_cat(&app_ctx->evts, &template); } void donar_client(struct donar_client_ctx* ctx, char* algoname, @@ -128,16 +76,8 @@ void donar_client(struct donar_client_ctx* ctx, char* algoname, evt_core_init (&(ctx->evts)); init_algo(&ctx->evts, &algo, algoname); - struct evt_core_cat init_socks5 = { - .app_ctx = ctx, - .free_app_ctx = NULL, - .cb = configure_tcp_clients, - .err_cb = NULL, - .name = "configure-socks5", - .flags = EPOLLIN | EPOLLET, - .socklist = NULL - }; - evt_core_add_cat (&(ctx->evts), &init_socks5); + socks5_init (&ctx->evts); + init_socks5_sinks(ctx); evt_core_add_cat (&(ctx->evts), &(algo.on_tcp_co)); evt_core_add_cat (&(ctx->evts), &(algo.on_udp_read)); evt_core_add_cat (&(ctx->evts), &(algo.on_tcp_read)); @@ -149,7 +89,7 @@ void donar_client(struct donar_client_ctx* ctx, char* algoname, printf("--- Onion services loaded\n"); for (int i = 0; i < CLIENT_PORT_SIZE; i++) { - init_tcp_client(ctx, i); + init_socks5_client(ctx, i); } printf("--- TCP Clients Connected\n"); diff --git a/src/donar_client.h b/src/donar_client.h index 497259d..b9d5909 100644 --- a/src/donar_client.h +++ b/src/donar_client.h @@ -1,4 +1,5 @@ #pragma once +#define _GNU_SOURCE #include #include #include diff --git a/src/socks5.c b/src/socks5.c index 3e20d43..cc801fe 100644 --- a/src/socks5.c +++ b/src/socks5.c @@ -1,26 +1,11 @@ #include "socks5.h" -struct socks5_ctx { - struct client_handshake ch; - struct server_handshake sh; - struct client_request cr; - struct server_reply sr; - uint64_t ch_cursor; - uint64_t sh_cursor; - uint64_t cr_cursor; - uint64_t sr_cursor; - char cr_buffer[262]; - size_t ch_size; - size_t cr_size; - uint8_t sr_host_read; -}; - void socks5_free_ctx(void* elem) { struct socks5_ctx* ctx = elem; free(ctx); } -void create_socks5_dns_client(struct evt_core_ctx* ctx, char* proxy_host, char* proxy_port, char* addr, uint16_t port) { +void socks5_create_dns_client(struct evt_core_ctx* ctx, char* proxy_host, char* proxy_port, char* addr, uint16_t port) { struct evt_core_fdinfo fdinfo; struct evt_core_cat cat; struct socks5_ctx* s5ctx; @@ -57,6 +42,7 @@ void create_socks5_dns_client(struct evt_core_ctx* ctx, char* proxy_host, char* // 3. Fill socks5_ctx structures s5ctx = fdinfo.other; + s5ctx->port = port; // 3.1 Client handshake to send s5ctx->ch.ver = VER_SOCKS5; @@ -292,6 +278,39 @@ move_to_failed: return 1; } +int on_socks5_err(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) { + evt_core_mv_fd2 (ctx, fdinfo, "socks5-failed"); + return 1; +} + +void socks5_init(struct evt_core_ctx* ctx) { + struct evt_core_cat template = {0}; + + template.cb = on_socks5_send_handshake; + template.err_cb = on_socks5_err; + template.name = "socks5-send-handshake"; + template.flags = EPOLLOUT | EPOLLET; + evt_core_add_cat (ctx, &template); + + template.cb = on_socks5_recv_handshake; + template.err_cb = on_socks5_err; + template.name = "socks5-recv-handshake"; + template.flags = EPOLLIN | EPOLLET; + evt_core_add_cat (ctx, &template); + + template.cb = on_socks5_send_client_req; + template.err_cb = on_socks5_err; + template.name = "socks5-send-client-req"; + template.flags = EPOLLOUT | EPOLLET; + evt_core_add_cat(ctx, &template); + + template.cb = on_socks5_recv_server_reply; + template.err_cb = on_socks5_err; + template.name = "socks5-recv-server-reply"; + template.flags = EPOLLIN | EPOLLET; + evt_core_add_cat(ctx, &template); +} + char* socks5_rep (enum socks5_rep rep) { return rep_msg[rep]; } diff --git a/src/socks5.h b/src/socks5.h index f47dd0d..917e23e 100644 --- a/src/socks5.h +++ b/src/socks5.h @@ -107,6 +107,23 @@ struct server_reply { uint16_t port; }; -void init_socks5(struct evt_core_ctx* ctx); -void create_socks5_dns_client(struct evt_core_ctx* ctx, char* proxy_host, char* proxy_port, char* addr, uint16_t port); +struct socks5_ctx { + uint16_t port; + + struct client_handshake ch; + struct server_handshake sh; + struct client_request cr; + struct server_reply sr; + uint64_t ch_cursor; + uint64_t sh_cursor; + uint64_t cr_cursor; + uint64_t sr_cursor; + char cr_buffer[262]; + size_t ch_size; + size_t cr_size; + uint8_t sr_host_read; +}; + +void socks5_init(struct evt_core_ctx* ctx); +void socks5_create_dns_client(struct evt_core_ctx* ctx, char* proxy_host, char* proxy_port, char* addr, uint16_t port); char* socks5_rep (enum socks5_rep rep);