From 7b5c86947ee397b0dcd62ce71c992c5cd5e87971 Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Fri, 1 Jun 2012 12:37:50 +0000 Subject: [PATCH] -more --- src/gns/gns_proxy_proto.h | 2 + src/gns/gnunet-gns-proxy.c | 207 ++++++++++++++++++++++++++++++++++++- 2 files changed, 205 insertions(+), 4 deletions(-) diff --git a/src/gns/gns_proxy_proto.h b/src/gns/gns_proxy_proto.h index 85a203d7d..39f7e881c 100644 --- a/src/gns/gns_proxy_proto.h +++ b/src/gns/gns_proxy_proto.h @@ -1,4 +1,6 @@ +#define SOCKS_VERSION_5 0x05 +#define SOCKS_AUTH_NONE 0 /* The socks phases */ enum diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index a2e4ee6a5..1cc889d38 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c @@ -21,9 +21,38 @@ #include "platform.h" #include #include "gns_proxy_proto.h" +#include "gns.h" #define GNUNET_GNS_PROXY_PORT 7777 +//TODO maybe make this an api call +/** + * Checks if name is in tld + * + * @param name the name to check + * @param tld the TLD to check for + * @return GNUNET_YES or GNUNET_NO + */ +int +is_tld(const char* name, const char* tld) +{ + int offset = 0; + + if (strlen(name) <= strlen(tld)) + { + return GNUNET_NO; + } + + offset = strlen(name)-strlen(tld); + if (strcmp (name+offset, tld) != 0) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "%s is not in .%s TLD\n", name, tld); + return GNUNET_NO; + } + + return GNUNET_YES; +} struct Socks5Request { @@ -31,10 +60,17 @@ struct Socks5Request struct Socks5Request *next; struct GNUNET_NETWORK_Handle *sock; + struct GNUNET_NETWORK_Handle *remote_sock; int state; GNUNET_SCHEDULER_TaskIdentifier rtask; + GNUNET_SCHEDULER_TaskIdentifier wtask; + + char rbuf[512]; + char wbuf[512]; + unsigned int rbuf_len; + unsigned int wbuf_len; }; struct Socks5Connections @@ -49,6 +85,37 @@ static struct GNUNET_NETWORK_Handle *lsock; GNUNET_SCHEDULER_TaskIdentifier ltask; static struct Socks5Connections s5conns; +/** + * Write data to socket + * + * @param cls the closure + * @param tc scheduler context + */ +static void +do_write (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct Socks5Request *s5r = cls; + unsigned int len = s5r->wbuf_len; + + s5r->wtask = GNUNET_SCHEDULER_NO_TASK; + + if ((NULL != tc->read_ready) && + (GNUNET_NETWORK_fdset_isset (tc->write_ready, s5r->sock)) && + (len = GNUNET_NETWORK_socket_send (s5r->sock, &s5r->wbuf, + len))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Successfully sent %d bytes to socket\n", + len); + } + else + { + GNUNET_NETWORK_socket_close (s5r->sock); + GNUNET_free(s5r); + return; + } +} + /** * Read data from incoming connection * @@ -59,14 +126,26 @@ static void do_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Socks5Request *s5r = cls; - char rbuf[512]; unsigned int len; + struct socks5_client_hello *c_hello; + struct socks5_server_hello *s_hello; + struct socks5_client_request *c_req; + struct socks5_server_response *s_resp; + + char domain[256]; + uint8_t dom_len; + uint16_t req_port; + struct hostent *phost; + uint32_t remote_ip; + struct sockaddr_in remote_addr; + struct in_addr *r_sin_addr; s5r->rtask = GNUNET_SCHEDULER_NO_TASK; if ((NULL != tc->write_ready) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->sock)) && - (len = GNUNET_NETWORK_socket_recv (s5r->sock, &rbuf, sizeof (rbuf)))) + (len = GNUNET_NETWORK_socket_recv (s5r->sock, &s5r->rbuf, + sizeof (s5r->rbuf)))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully read %d bytes from socket\n", @@ -82,10 +161,130 @@ do_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (s5r->state == SOCKS5_INIT) { - //DO sth etc + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "SOCKS5 init\n"); + c_hello = (struct socks5_client_hello*)&s5r->rbuf; + + GNUNET_assert (c_hello->version == SOCKS_VERSION_5); + + s_hello = (struct socks5_server_hello*)&s5r->wbuf; + s5r->wbuf_len = sizeof( struct socks5_server_hello ); + + s_hello->version = c_hello->version; + s_hello->auth_method = SOCKS_AUTH_NONE; + + /* Write response to client */ + s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + s5r->sock, + &do_write, s5r); + + s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + s5r->sock, + &do_read, s5r); + + s5r->state = SOCKS5_REQUEST; + return; + } + + if (s5r->state == SOCKS5_REQUEST) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Processing SOCKS5 request\n"); + c_req = (struct socks5_client_request*)&s5r->rbuf; + s_resp = (struct socks5_server_response*)&s5r->wbuf; + s5r->wbuf_len = sizeof (struct socks5_server_response); + + GNUNET_assert (c_req->addr_type == 3); + + dom_len = *((uint8_t*)(&(c_req->addr_type) + 1)); + memset(domain, 0, sizeof(domain)); + strncpy(domain, (char*)(&(c_req->addr_type) + 2), dom_len); + req_port = *((uint16_t*)(&(c_req->addr_type) + 2 + dom_len)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Requested connection is %s:%d\n", + domain, + ntohs(req_port)); + + if (is_tld (domain, GNUNET_GNS_TLD) || + is_tld (domain, GNUNET_GNS_TLD_ZKEY)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Requested connection is gnunet tld\n", + domain); + } + else + { + phost = (struct hostent*)gethostbyname (domain); + if (phost == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Resolve %s error!\n", domain ); + s_resp->version = 0x05; + s_resp->reply = 0x01; + s5r->wtask = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + s5r->sock, + &do_write, s5r); + //ERROR! + //TODO! close socket after the write! schedule task + //GNUNET_NETWORK_socket_close (s5r->sock); + //GNUNET_free(s5r); + return; + } + + s5r->remote_sock = GNUNET_NETWORK_socket_create (AF_INET, + SOCK_STREAM, + 0); + r_sin_addr = (struct in_addr*)(phost->h_addr); + remote_ip = r_sin_addr->s_addr; + memset(&remote_addr, 0, sizeof(remote_addr)); + remote_addr.sin_family = AF_INET; + remote_addr.sin_addr.s_addr = remote_ip; + remote_addr.sin_port = req_port; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "target server: %s:%u\n", inet_ntoa(remote_addr.sin_addr), + ntohs(req_port)); + + GNUNET_assert ( s5r->remote_sock != NULL ); + + if (GNUNET_OK != + GNUNET_NETWORK_socket_connect ( s5r->remote_sock, + (struct sockaddr*)&remote_addr, + sizeof (struct sockaddr))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "socket request error...\n"); + s_resp->version = 0x05; + s_resp->reply = 0x01; + s5r->wtask = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + s5r->sock, + &do_write, s5r); + //TODO see above + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "new remote connection\n"); + + s_resp->version = 0x05; + s_resp->reply = 0x00; + s_resp->reserved = 0x00; + s_resp->addr_type = 0x01; + + s5r->state = SOCKS5_DATA_TRANSFER; + + s5r->wtask = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + s5r->sock, + &do_write, s5r); + + } } - GNUNET_CONTAINER_DLL_remove (s5conns.head, s5conns.tail, s5r); + //GNUNET_CONTAINER_DLL_remove (s5conns.head, s5conns.tail, s5r); } -- 2.25.1