diff --git a/src/donar_client.c b/src/donar_client.c index dbda5f7..80337b7 100644 --- a/src/donar_client.c +++ b/src/donar_client.c @@ -6,7 +6,39 @@ void load_onion_services(struct donar_client_ctx* ctx, char* onion_file, int por } void init_tcp_clients(struct donar_client_ctx* ctx) { + for (uint16_t i = 0; i < CLIENT_PORT_SIZE ; i++) { + ctx->ports[i] = 7500 + i; + } + int sock1, sock2, err; + char target_host[255]; + for (int i = 0; i < CLIENT_PORT_SIZE; ) { + sock1 = create_tcp_client("127.0.0.1", "9050"); + err = socks5_handshake(sock1); + if (err < 0) goto failed_socks5; + if (strlen(ctx->tos.keys[i].pub) > 254) { + fprintf(stderr, "Domain name is too long\n"); + exit(EXIT_FAILURE); + } + sprintf(target_host, "%s.onion", ctx->tos.keys[i].pub); + err = socks5_connect_dns(sock1, target_host, ctx->ports[i]); + if (err < 0) goto failed_socks5; + err = socks5_reply(sock1); + if (err < 0) goto failed_socks5; + + sock2 = dup(sock1); + if (sock2 < 0) goto failed_socks5; + evt_core_add_fd (&(ctx->evts), "tcp-read", sock1); + evt_core_add_fd (&(ctx->evts), "tcp-write", sock2); + printf("Socket %d/%d %s:%d has been added to the pool\n", i+1, CLIENT_PORT_SIZE, target_host, ctx->ports[i]); + + i++; + continue; +failed_socks5: + fprintf(stderr, "Failed connection for socket %d/%d. Sleeping 2 seconds...\n",i+1, CLIENT_PORT_SIZE); + close(sock1); + sleep(2); + } } void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo, char* onion_file, char* port) { @@ -20,15 +52,7 @@ void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo, char* on load_onion_services (ctx, onion_file, CLIENT_PORT_SIZE); printf("--- Onion services loaded\n"); - - for (int i = 0; i < ctx->tos.filled; i++) { - printf("onion service: %s\n",ctx->tos.keys[i].pub); - } - - for (uint16_t i = 0; i < CLIENT_PORT_SIZE ; i++) { - ctx->ports[i] = 7500 + i; - } - init_tcp_clients(ctx); - + printf("--- TCP Clients Connected\n"); + // TODO: Debug that, listen UDP and launch loop } diff --git a/src/donar_client.h b/src/donar_client.h index 43e8d6f..7b80881 100644 --- a/src/donar_client.h +++ b/src/donar_client.h @@ -3,6 +3,7 @@ #include #include "algo_skel.h" #include "tor_os.h" +#include "socks5.h" #define CLIENT_PORT_SIZE 10 diff --git a/src/socks5.c b/src/socks5.c index 03167ba..c825dd1 100644 --- a/src/socks5.c +++ b/src/socks5.c @@ -1,25 +1,34 @@ #include "socks5.h" -void socks5_handshake(int sock) { - struct client_handshake ch = {0x05, 0x01, {0x00}}; +int socks5_handshake(int sock) { + struct client_handshake ch = { + .ver = 0x05, + .nmethods = 0x01, + .methods = {0x00} + }; int size = sizeof(uint8_t) * (2 + ch.nmethods); if (size != write(sock, &ch, size)) { fprintf(stderr, "partial/failed write\n"); - exit(EXIT_FAILURE); + return -1; } struct server_handshake sh = {0}; int err = read_entity(sock, &sh, sizeof(struct server_handshake)); if (err == -1) { - perror("read"); - exit(EXIT_FAILURE); + perror("sock5 handshake failed read"); + return -1; + } + if (ch.ver != sh.ver || sh.method != ch.methods[0]) { + fprintf(stderr, "Protocol error: client asks for ver=%d, method=%d and server answers with ver=%d, method=%d\n", + ch.ver, ch.methods[0], sh.ver, sh.method); + return -1; } - printf("[server_handshake] ver=%d, method=%d\n", sh.ver, sh.method); + return 0; } -void socks5_reply(int sock) { +int socks5_reply(int sock) { struct server_reply sr = {0}; read_entity(sock, &sr, sizeof(uint8_t) * 4); switch(sr.atyp) { @@ -38,21 +47,25 @@ void socks5_reply(int sock) { goto read_error; break; default: - fprintf(stderr, "unsupported ATYP in server reply\n"); - exit(EXIT_FAILURE); + fprintf(stderr, "Unsupported ATYP in server reply\n"); + return -128; } read_entity(sock, &sr.port, sizeof(uint16_t)); - printf("[server_reply] ver=%d, rep=%d, atyp=%d, port=%d\n", sr.ver, sr.rep, sr.atyp, sr.port); + if (sr.rep < 0 || sr.rep > 0x08) { + fprintf(stderr, "Invalid reply field\n"); + return -128; + } - return; + printf("[server_reply] ver=%d, rep=%s, atyp=%d, port=%d\n", sr.ver, rep_msg[sr.rep], sr.atyp, sr.port); + return -sr.rep; read_error: - fprintf(stderr, "unsupported ATYP in server reply\n"); - exit(EXIT_FAILURE); + fprintf(stderr, "Unable to read ATYP\n"); + return -128; } -void socks5_connect_dns(int sock, char* addr, uint16_t port) { +int socks5_connect_dns(int sock, char* addr, uint16_t port) { char buffer[262]; size_t domainLength = strlen(addr); if (domainLength > 255) { @@ -67,6 +80,6 @@ void socks5_connect_dns(int sock, char* addr, uint16_t port) { if (written != write(sock, buffer, written)) { fprintf(stderr, "partial/failed write\n"); - exit(EXIT_FAILURE); + return -1; } } diff --git a/src/socks5.h b/src/socks5.h index 46e3cc2..b67dc71 100644 --- a/src/socks5.h +++ b/src/socks5.h @@ -29,6 +29,18 @@ union socks5_addr { uint8_t ipv6[16]; }; +static char* rep_msg[9] = { + "Succeeded", + "General SOCKS server failure", + "Connection not allowed by ruleset", + "Network unreachable", + "Host unreachable", + "Connection refused", + "TTL expired", + "Command not supported", + "Address type not supported" +}; + /* * RFC 1928 Messages * https://tools.ietf.org/html/rfc1928 @@ -64,6 +76,6 @@ struct server_reply { uint16_t port; }; -void socks5_handshake(int sock); -void socks5_connect_dns(int sock, char* addr, uint16_t port); -void socks5_reply(int sock); +int socks5_handshake(int sock); +int socks5_connect_dns(int sock, char* addr, uint16_t port); +int socks5_reply(int sock);