aboutsummaryrefslogtreecommitdiff
path: root/src/gns/gnunet-gns-proxy.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-09-17 13:23:07 +0000
committerChristian Grothoff <christian@grothoff.org>2013-09-17 13:23:07 +0000
commit0ac8167bf788134f942c72e0deea6f22af382e87 (patch)
tree5ac4798e97000f9ddee0722f761f00c041d8e868 /src/gns/gnunet-gns-proxy.c
parent7a02c0cc81e84a455d3281e9635d636c78c41351 (diff)
downloadgnunet-0ac8167bf788134f942c72e0deea6f22af382e87.tar.gz
gnunet-0ac8167bf788134f942c72e0deea6f22af382e87.zip
starting to clean up socks5 handling
Diffstat (limited to 'src/gns/gnunet-gns-proxy.c')
-rw-r--r--src/gns/gnunet-gns-proxy.c629
1 files changed, 411 insertions, 218 deletions
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c
index 217404f39..7deee988f 100644
--- a/src/gns/gnunet-gns-proxy.c
+++ b/src/gns/gnunet-gns-proxy.c
@@ -60,6 +60,13 @@
60#define POSTBUFFERSIZE 4096 60#define POSTBUFFERSIZE 4096
61 61
62/** 62/**
63 * Size of the read/write buffers for Socks. Uses
64 * 256 bytes for the hostname (at most), plus a few
65 * bytes overhead for the messages.
66 */
67#define SOCKS_BUFFERSIZE (256 + 32)
68
69/**
63 * Port for plaintext HTTP. 70 * Port for plaintext HTTP.
64 */ 71 */
65#define HTTP_PORT 80 72#define HTTP_PORT 80
@@ -97,22 +104,89 @@
97 104
98 105
99/** 106/**
100 * The socks phases 107 * Commands in Socks5.
108 */
109enum Socks5Commands
110{
111 /**
112 * Establish TCP/IP stream.
113 */
114 SOCKS5_CMD_TCP_STREAM = 1,
115
116 /**
117 * Establish TCP port binding.
118 */
119 SOCKS5_CMD_TCP_PORT = 2,
120
121 /**
122 * Establish UDP port binding.
123 */
124 SOCKS5_CMD_UDP_PORT = 3
125};
126
127
128/**
129 * Address types in Socks5.
130 */
131enum Socks5AddressType
132{
133 /**
134 * IPv4 address.
135 */
136 SOCKS5_AT_IPV4 = 1,
137
138 /**
139 * IPv4 address.
140 */
141 SOCKS5_AT_DOMAINNAME = 3,
142
143 /**
144 * IPv6 address.
145 */
146 SOCKS5_AT_IPV6 = 4
147
148};
149
150
151/**
152 * Status codes in Socks5 response.
153 */
154enum Socks5StatusCode
155{
156 SOCKS5_STATUS_REQUEST_GRANTED = 0,
157 SOCKS5_STATUS_GENERAL_FAILURE = 1,
158 SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE = 2,
159 SOCKS5_STATUS_NETWORK_UNREACHABLE = 3,
160 SOCKS5_STATUS_HOST_UNREACHABLE = 4,
161 SOCKS5_STATUS_CONNECTION_REFUSED_BY_HOST = 5,
162 SOCKS5_STATUS_TTL_EXPIRED = 6,
163 SOCKS5_STATUS_COMMAND_NOT_SUPPORTED = 7,
164 SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED = 8
165};
166
167
168/**
169 * The socks phases.
101 */ 170 */
102enum SocksPhase 171enum SocksPhase
103{ 172{
104 /** 173 /**
105 * We're waiting to get the request. 174 * We're waiting to get the client hello.
106 */ 175 */
107 SOCKS5_INIT, 176 SOCKS5_INIT,
108 177
109 /** 178 /**
110 * FIXME. 179 * We're waiting to get the initial request.
111 */ 180 */
112 SOCKS5_REQUEST, 181 SOCKS5_REQUEST,
113 182
114 /** 183 /**
115 * FIXME. 184 * We are currently resolving the destination.
185 */
186 SOCKS5_RESOLVING,
187
188 /**
189 * We're in transfer mode.
116 */ 190 */
117 SOCKS5_DATA_TRANSFER 191 SOCKS5_DATA_TRANSFER
118}; 192};
@@ -190,11 +264,6 @@ struct Socks5Request
190 struct GNUNET_NETWORK_Handle *remote_sock; 264 struct GNUNET_NETWORK_Handle *remote_sock;
191 265
192 /** 266 /**
193 * The socks state
194 */
195 enum SocksPhase state;
196
197 /**
198 * Client socket read task 267 * Client socket read task
199 */ 268 */
200 GNUNET_SCHEDULER_TaskIdentifier rtask; 269 GNUNET_SCHEDULER_TaskIdentifier rtask;
@@ -217,22 +286,32 @@ struct Socks5Request
217 /** 286 /**
218 * Read buffer 287 * Read buffer
219 */ 288 */
220 char rbuf[2048]; 289 char rbuf[SOCKS_BUFFERSIZE];
221 290
222 /** 291 /**
223 * Write buffer 292 * Write buffer
224 */ 293 */
225 char wbuf[2048]; 294 char wbuf[SOCKS_BUFFERSIZE];
226 295
227 /** 296 /**
228 * Length of data in read buffer 297 * Number of bytes already in read buffer
229 */ 298 */
230 unsigned int rbuf_len; 299 size_t rbuf_len;
231 300
232 /** 301 /**
233 * Length of data in write buffer 302 * Number of bytes already in write buffer
303 */
304 size_t wbuf_len;
305
306 /**
307 * Once known, what's the target address for the connection?
234 */ 308 */
235 unsigned int wbuf_len; 309 struct sockaddr_storage destination_address;
310
311 /**
312 * The socks state
313 */
314 enum SocksPhase state;
236 315
237 /** 316 /**
238 * This handle is scheduled for cleanup? 317 * This handle is scheduled for cleanup?
@@ -538,10 +617,26 @@ struct Socks5ClientHelloMessage
538 */ 617 */
539 uint8_t num_auth_methods; 618 uint8_t num_auth_methods;
540 619
620 /* followed by supported authentication methods, 1 byte per method */
621
622};
623
624
625/**
626 * Server hello in Socks5 protocol.
627 */
628struct Socks5ServerHelloMessage
629{
541 /** 630 /**
542 * FIXME: this is not a message format... 631 * Should be #SOCKS_VERSION_5.
543 */ 632 */
544 char* auth_methods; 633 uint8_t version;
634
635 /**
636 * Chosen authentication method, for us always #SOCKS_AUTH_NONE,
637 * which skips the authentication step.
638 */
639 uint8_t auth_method;
545}; 640};
546 641
547 642
@@ -556,45 +651,29 @@ struct Socks5ClientRequestMessage
556 uint8_t version; 651 uint8_t version;
557 652
558 /** 653 /**
559 * FIXME: what goes here? 654 * Command code, we only uspport #SOCKS5_CMD_TCP_STREAM.
560 */ 655 */
561 uint8_t command; 656 uint8_t command;
562 657
563 /** 658 /**
564 * FIXME: what goes here? 659 * Reserved, always zero.
565 */ 660 */
566 uint8_t resvd; 661 uint8_t resvd;
567 662
568 /** 663 /**
569 * FIXME: what goes here? 664 * Address type, an `enum Socks5AddressType`.
570 */ 665 */
571 uint8_t addr_type; 666 uint8_t addr_type;
572 667
573 /* 668 /*
574 * followed by either an ip4/ipv6 address 669 * Followed by either an ip4/ipv6 address or a domain name with a
575 * or a domain name with a length field in front 670 * length field (uint8_t) in front (depending on @e addr_type).
671 * followed by port number in network byte order (uint16_t).
576 */ 672 */
577}; 673};
578 674
579 675
580/** 676/**
581 * Server hello in Socks5 protocol.
582 */
583struct Socks5ServerHelloMessage
584{
585 /**
586 * Should be #SOCKS_VERSION_5.
587 */
588 uint8_t version;
589
590 /**
591 * FIXME: what goes here?
592 */
593 uint8_t auth_method;
594};
595
596
597/**
598 * Server response to client requests in Socks5 protocol. 677 * Server response to client requests in Socks5 protocol.
599 */ 678 */
600struct Socks5ServerResponseMessage 679struct Socks5ServerResponseMessage
@@ -605,24 +684,26 @@ struct Socks5ServerResponseMessage
605 uint8_t version; 684 uint8_t version;
606 685
607 /** 686 /**
608 * FIXME: what goes here? 687 * Status code, an `enum Socks5StatusCode`
609 */ 688 */
610 uint8_t reply; 689 uint8_t reply;
611 690
612 /** 691 /**
613 * FIXME: what goes here? 692 * Always zero.
614 */ 693 */
615 uint8_t reserved; 694 uint8_t reserved;
616 695
617 /** 696 /**
618 * FIXME: what goes here? 697 * Address type, an `enum Socks5AddressType`.
619 */ 698 */
620 uint8_t addr_type; 699 uint8_t addr_type;
621 700
622 /** 701 /*
623 * FIXME: what goes here? 702 * Followed by either an ip4/ipv6 address or a domain name with a
703 * length field (uint8_t) in front (depending on @e addr_type).
704 * followed by port number in network byte order (uint16_t).
624 */ 705 */
625 uint8_t add_port[18]; 706
626}; 707};
627 708
628 709
@@ -747,6 +828,7 @@ static struct GNUNET_IDENTITY_Operation *id_op;
747 */ 828 */
748static const struct GNUNET_CONFIGURATION_Handle *cfg; 829static const struct GNUNET_CONFIGURATION_Handle *cfg;
749 830
831
750/** 832/**
751 * Clean up s5r handles 833 * Clean up s5r handles
752 * 834 *
@@ -774,6 +856,24 @@ cleanup_s5r (struct Socks5Request *s5r)
774 856
775 857
776/** 858/**
859 * Remove the first @a len bytes from the beginning of the read buffer.
860 *
861 * @param s5r the handle clear the read buffer for
862 * @param len number of bytes in read buffer to advance
863 */
864static void
865clear_from_s5r_rbuf (struct Socks5Request *s5r,
866 size_t len)
867{
868 GNUNET_assert (len <= s5r->rbuf_len);
869 memmove (s5r->rbuf,
870 &s5r->rbuf[len],
871 s5r->rbuf_len - len);
872 s5r->rbuf_len -= len;
873}
874
875
876/**
777 * Checks if name is in tld 877 * Checks if name is in tld
778 * 878 *
779 * @param name the name to check 879 * @param name the name to check
@@ -2665,6 +2765,63 @@ add_handle_to_ssl_mhd (struct GNUNET_NETWORK_Handle *h,
2665 2765
2666 2766
2667/** 2767/**
2768 * Return a server response message indicating a failure to the client.
2769 *
2770 * @param s5r request to return failure code for
2771 * @param sc status code to return
2772 */
2773static void
2774signal_socks_failure (struct Socks5Request *s5r,
2775 enum Socks5StatusCode sc)
2776{
2777 struct Socks5ServerResponseMessage *s_resp;
2778
2779 s_resp = (struct Socks5ServerResponseMessage *) &s5r->wbuf[s5r->wbuf_len];
2780 memset (s_resp, 0, sizeof (struct Socks5ServerResponseMessage));
2781 s_resp->version = SOCKS_VERSION_5;
2782 s_resp->reply = sc;
2783 s5r->cleanup = GNUNET_YES;
2784 s5r->cleanup_sock = GNUNET_YES;
2785 if (GNUNET_SCHEDULER_NO_TASK != s5r->wtask)
2786 s5r->wtask =
2787 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2788 s5r->sock,
2789 &do_write, s5r);
2790}
2791
2792
2793/**
2794 * Return a server response message indicating success.
2795 *
2796 * @param s5r request to return success status message for
2797 */
2798static void
2799signal_socks_success (struct Socks5Request *s5r)
2800{
2801 struct Socks5ServerResponseMessage *s_resp;
2802
2803 s_resp = (struct Socks5ServerResponseMessage *) &s5r->wbuf[s5r->wbuf_len];
2804 s_resp->version = SOCKS_VERSION_5;
2805 s_resp->reply = SOCKS5_STATUS_REQUEST_GRANTED;
2806 s_resp->reserved = 0;
2807 s_resp->addr_type = SOCKS5_AT_IPV4;
2808 /* zero out IPv4 address and port */
2809 memset (&s_resp[1],
2810 0,
2811 sizeof (struct in_addr) + sizeof (uint16_t));
2812 s5r->wbuf_len += sizeof (struct Socks5ServerResponseMessage) +
2813 sizeof (struct in_addr) + sizeof (uint16_t);
2814 s5r->cleanup = GNUNET_YES;
2815 s5r->cleanup_sock = GNUNET_NO;
2816 if (GNUNET_SCHEDULER_NO_TASK == s5r->wtask)
2817 s5r->wtask =
2818 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2819 s5r->sock,
2820 &do_write, s5r);
2821}
2822
2823
2824/**
2668 * Read data from incoming Socks5 connection 2825 * Read data from incoming Socks5 connection
2669 * 2826 *
2670 * @param cls the closure with the `struct Socks5Request` 2827 * @param cls the closure with the `struct Socks5Request`
@@ -2674,213 +2831,249 @@ static void
2674do_s5r_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 2831do_s5r_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2675{ 2832{
2676 struct Socks5Request *s5r = cls; 2833 struct Socks5Request *s5r = cls;
2677 struct Socks5ClientHelloMessage *c_hello; 2834 const struct Socks5ClientHelloMessage *c_hello;
2678 struct Socks5ServerHelloMessage *s_hello; 2835 struct Socks5ServerHelloMessage *s_hello;
2679 struct Socks5ClientRequestMessage *c_req; 2836 const struct Socks5ClientRequestMessage *c_req;
2680 struct Socks5ServerResponseMessage *s_resp;
2681 int ret; 2837 int ret;
2682 char domain[256]; 2838 ssize_t rlen;
2683 uint8_t dom_len; 2839 size_t alen;
2684 uint16_t req_port;
2685 struct hostent *phost;
2686 uint32_t remote_ip;
2687 struct sockaddr_in remote_addr;
2688 struct in_addr *r_sin_addr;
2689 2840
2690 s5r->rtask = GNUNET_SCHEDULER_NO_TASK; 2841 s5r->rtask = GNUNET_SCHEDULER_NO_TASK;
2691 if ( (NULL != tc->read_ready) && 2842 if ( (NULL != tc->read_ready) &&
2692 (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->sock)) ) 2843 (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->sock)) )
2693 s5r->rbuf_len = GNUNET_NETWORK_socket_recv (s5r->sock, s5r->rbuf,
2694 sizeof (s5r->rbuf));
2695 else
2696 s5r->rbuf_len = 0;
2697 if (0 == s5r->rbuf_len)
2698 { 2844 {
2699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2845 rlen = GNUNET_NETWORK_socket_recv (s5r->sock,
2700 "socks5 client disconnected.\n"); 2846 &s5r->rbuf[s5r->rbuf_len],
2701 cleanup_s5r (s5r); 2847 sizeof (s5r->rbuf) - s5r->rbuf_len);
2702 return; 2848 if (rlen <= 0)
2849 {
2850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2851 "socks5 client disconnected.\n");
2852 cleanup_s5r (s5r);
2853 return;
2854 }
2855 s5r->rbuf_len += rlen;
2703 } 2856 }
2857 s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2858 s5r->sock,
2859 &do_s5r_read, s5r);
2704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2705 "Processing socks data in state %d\n", 2861 "Processing %u bytes of socks data in state %d\n",
2862 s5r->rbuf_len,
2706 s5r->state); 2863 s5r->state);
2707 switch (s5r->state) 2864 switch (s5r->state)
2708 { 2865 {
2709 case SOCKS5_INIT: 2866 case SOCKS5_INIT:
2710 /* FIXME: failed to check if we got enough data yet! */ 2867 c_hello = (const struct Socks5ClientHelloMessage*) &s5r->rbuf;
2711 c_hello = (struct Socks5ClientHelloMessage*) &s5r->rbuf; 2868 if ( (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage)) ||
2712 GNUNET_assert (c_hello->version == SOCKS_VERSION_5); 2869 (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods) )
2713 s_hello = (struct Socks5ServerHelloMessage*) &s5r->wbuf; 2870 return; /* need more data */
2714 s5r->wbuf_len = sizeof( struct Socks5ServerHelloMessage ); 2871 if (SOCKS_VERSION_5 != c_hello->version)
2715 s_hello->version = c_hello->version; 2872 {
2873 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2874 _("Unsupported socks version %d\n"),
2875 (int) c_hello->version);
2876 cleanup_s5r (s5r);
2877 return;
2878 }
2879 clear_from_s5r_rbuf (s5r,
2880 sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods);
2881 GNUNET_assert (0 == s5r->wbuf_len);
2882 s_hello = (struct Socks5ServerHelloMessage *) &s5r->wbuf;
2883 s5r->wbuf_len = sizeof (struct Socks5ServerHelloMessage);
2884 s_hello->version = SOCKS_VERSION_5;
2716 s_hello->auth_method = SOCKS_AUTH_NONE; 2885 s_hello->auth_method = SOCKS_AUTH_NONE;
2717 /* Write response to client */ 2886 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s5r->wtask);
2718 s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 2887 s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2719 s5r->sock, 2888 s5r->sock,
2720 &do_write, s5r); 2889 &do_write, s5r);
2721 s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2722 s5r->sock,
2723 &do_s5r_read, s5r);
2724 s5r->state = SOCKS5_REQUEST; 2890 s5r->state = SOCKS5_REQUEST;
2725 return; 2891 return;
2726 case SOCKS5_REQUEST: 2892 case SOCKS5_REQUEST:
2727 /* FIXME: failed to check if we got enough data yet!? */ 2893 c_req = (const struct Socks5ClientRequestMessage *) &s5r->rbuf;
2728 c_req = (struct Socks5ClientRequestMessage *) &s5r->rbuf; 2894 if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage))
2729 s_resp = (struct Socks5ServerResponseMessage *) &s5r->wbuf; 2895 return;
2730 //Only 10 byte for ipv4 response! 2896 switch (c_req->command)
2731 s5r->wbuf_len = 10;//sizeof (struct Socks5ServerResponseMessage);
2732 GNUNET_assert (c_req->addr_type == 3);
2733 dom_len = *((uint8_t*)(&(c_req->addr_type) + 1));
2734 memset(domain, 0, sizeof(domain));
2735 strncpy(domain, (char*)(&(c_req->addr_type) + 2), dom_len);
2736 req_port = *((uint16_t*)(&(c_req->addr_type) + 2 + dom_len));
2737 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2738 "Requested connection is to %s:%d\n",
2739 domain,
2740 ntohs(req_port));
2741 if (is_tld (domain, GNUNET_GNS_TLD) ||
2742 is_tld (domain, GNUNET_GNS_TLD_ZKEY))
2743 { 2897 {
2744 /* GNS TLD */ 2898 case SOCKS5_CMD_TCP_STREAM:
2745 ret = MHD_NO; 2899 /* handled below */
2746 if (ntohs (req_port) == HTTPS_PORT) 2900 break;
2747 { 2901 default:
2748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2902 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2749 "Requested connection is HTTPS\n"); 2903 _("Unsupported socks command %d\n"),
2750 ret = add_handle_to_ssl_mhd ( s5r->sock, domain ); 2904 (int) c_req->command);
2751 } 2905 signal_socks_failure (s5r,
2752 else if (NULL != httpd) 2906 SOCKS5_STATUS_COMMAND_NOT_SUPPORTED);
2753 {
2754 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2755 "Requested connection is HTTP\n");
2756 ret = add_handle_to_mhd (s5r->sock, httpd );
2757 }
2758
2759 if (ret != MHD_YES)
2760 {
2761 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2762 _("Failed to start HTTP server\n"));
2763 s_resp->version = 0x05;
2764 s_resp->reply = 0x01;
2765 s5r->cleanup = GNUNET_YES;
2766 s5r->cleanup_sock = GNUNET_YES;
2767 s5r->wtask =
2768 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2769 s5r->sock,
2770 &do_write, s5r);
2771 return;
2772 }
2773
2774 /* Signal success */
2775 s_resp->version = 0x05;
2776 s_resp->reply = 0x00;
2777 s_resp->reserved = 0x00;
2778 s_resp->addr_type = 0x01;
2779
2780 s5r->cleanup = GNUNET_YES;
2781 s5r->cleanup_sock = GNUNET_NO;
2782 s5r->wtask =
2783 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2784 s5r->sock,
2785 &do_write, s5r);
2786 run_httpds ();
2787 return; 2907 return;
2788 } 2908 }
2789 else 2909 switch (c_req->addr_type)
2790 { 2910 {
2791 /* non-GNS TLD, use DNS to resolve */ 2911 case SOCKS5_AT_IPV4:
2792 /* FIXME: make asynchronous! */
2793 phost = (struct hostent *) gethostbyname (domain);
2794 if (phost == NULL)
2795 { 2912 {
2796 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2913 const struct in_addr *v4 = (const struct in_addr *) &c_req[1];
2797 "Resolve %s error!\n", domain ); 2914 const uint16_t *port = (const uint16_t *) &v4[1];
2798 s_resp->version = 0x05; 2915 struct sockaddr_in *in;
2799 s_resp->reply = 0x01; 2916
2800 s5r->cleanup = GNUNET_YES; 2917 alen = sizeof (struct in_addr);
2801 s5r->cleanup_sock = GNUNET_YES; 2918 if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
2802 s5r->wtask = 2919 alen + sizeof (uint16_t))
2803 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, 2920 return; /* need more data */
2804 s5r->sock, 2921 in = (struct sockaddr_in *) &s5r->destination_address;
2805 &do_write, s5r); 2922 in->sin_family = AF_INET;
2806 return; 2923 in->sin_addr = *v4;
2807 } 2924 in->sin_port = *port;
2808
2809 s5r->remote_sock = GNUNET_NETWORK_socket_create (AF_INET,
2810 SOCK_STREAM,
2811 0);
2812 r_sin_addr = (struct in_addr*)(phost->h_addr);
2813 remote_ip = r_sin_addr->s_addr;
2814 memset(&remote_addr, 0, sizeof(remote_addr));
2815 remote_addr.sin_family = AF_INET;
2816#if HAVE_SOCKADDR_IN_SIN_LEN 2925#if HAVE_SOCKADDR_IN_SIN_LEN
2817 remote_addr.sin_len = sizeof (remote_addr); 2926 in->sin_len = sizeof (*in);
2818#endif 2927#endif
2819 remote_addr.sin_addr.s_addr = remote_ip; 2928 s5r->state = SOCKS5_DATA_TRANSFER;
2820 remote_addr.sin_port = req_port;
2821
2822 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2823 "target server: %s:%u\n", inet_ntoa(remote_addr.sin_addr),
2824 ntohs(req_port));
2825
2826 if ((GNUNET_OK !=
2827 GNUNET_NETWORK_socket_connect ( s5r->remote_sock,
2828 (const struct sockaddr*)&remote_addr,
2829 sizeof (remote_addr)))
2830 && (errno != EINPROGRESS))
2831 {
2832 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect");
2833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2834 "socket request error...\n");
2835 s_resp->version = 0x05;
2836 s_resp->reply = 0x01;
2837 s5r->wtask =
2838 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2839 s5r->sock,
2840 &do_write, s5r);
2841 //TODO see above
2842 return;
2843 } 2929 }
2844 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2930 break;
2845 "new remote connection\n"); 2931 case SOCKS5_AT_DOMAINNAME:
2846 s_resp->version = 0x05;
2847 s_resp->reply = 0x00;
2848 s_resp->reserved = 0x00;
2849 s_resp->addr_type = 0x01;
2850 s5r->state = SOCKS5_DATA_TRANSFER;
2851 s5r->wtask =
2852 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2853 s5r->sock,
2854 &do_write, s5r);
2855 s5r->rtask =
2856 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
2857 s5r->sock,
2858 &do_s5r_read, s5r);
2859 }
2860 return;
2861 case SOCKS5_DATA_TRANSFER:
2862 {
2863 if ((s5r->remote_sock == NULL) || (s5r->rbuf_len == 0))
2864 { 2932 {
2933 const uint8_t *dom_len;
2934 const char *dom_name;
2935 const uint16_t *port;
2936 char domain[256];
2937 struct hostent *phost;
2938 uint32_t remote_ip;
2939 struct sockaddr_in remote_addr;
2940 struct in_addr *r_sin_addr;
2941
2942 dom_len = (const uint8_t *) &c_req[1];
2943 alen = *dom_len + 1;
2944 if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
2945 alen + sizeof (uint16_t))
2946 return; /* need more data */
2947 dom_name = (const char *) &dom_len[1];
2948 port = (const uint16_t*) &dom_name[*dom_len];
2949
2950
2951 strncpy (domain, dom_name, *dom_len);
2952 domain[*dom_len] = '\0';
2953
2865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2866 "Closing connection to client\n"); 2955 "Requested connection is to %s:%d\n",
2867 cleanup_s5r (s5r); 2956 domain,
2868 return; 2957 ntohs (*port));
2958
2959 if (is_tld (domain, GNUNET_GNS_TLD) ||
2960 is_tld (domain, GNUNET_GNS_TLD_ZKEY))
2961 {
2962 /* GNS TLD */
2963 ret = MHD_NO;
2964 if (ntohs (*port) == HTTPS_PORT)
2965 {
2966 ret = add_handle_to_ssl_mhd (s5r->sock, domain);
2967 }
2968 else
2969 {
2970 ret = add_handle_to_mhd (s5r->sock, httpd);
2971 }
2972 if (ret != MHD_YES)
2973 {
2974 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2975 _("Failed to start HTTP server\n"));
2976 signal_socks_failure (s5r,
2977 SOCKS5_STATUS_GENERAL_FAILURE);
2978 return;
2979 }
2980 }
2981 else
2982 {
2983 /* non-GNS TLD, use DNS to resolve */
2984 /* FIXME: make asynchronous! */
2985 phost = (struct hostent *) gethostbyname (domain);
2986 if (phost == NULL)
2987 {
2988 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2989 "Failed to resolve `%s'!\n",
2990 domain);
2991 signal_socks_failure (s5r,
2992 SOCKS5_STATUS_GENERAL_FAILURE);
2993 return;
2994 }
2995
2996 s5r->remote_sock = GNUNET_NETWORK_socket_create (AF_INET,
2997 SOCK_STREAM,
2998 0);
2999 r_sin_addr = (struct in_addr*)(phost->h_addr);
3000 remote_ip = r_sin_addr->s_addr;
3001 memset(&remote_addr, 0, sizeof(remote_addr));
3002 remote_addr.sin_family = AF_INET;
3003#if HAVE_SOCKADDR_IN_SIN_LEN
3004 remote_addr.sin_len = sizeof (remote_addr);
3005#endif
3006 remote_addr.sin_addr.s_addr = remote_ip;
3007 remote_addr.sin_port = *port;
3008
3009 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3010 "target server: %s:%u\n",
3011 inet_ntoa(remote_addr.sin_addr),
3012 ntohs(*port));
3013
3014 if ((GNUNET_OK !=
3015 GNUNET_NETWORK_socket_connect ( s5r->remote_sock,
3016 (const struct sockaddr*)&remote_addr,
3017 sizeof (remote_addr)))
3018 && (errno != EINPROGRESS))
3019 {
3020 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect");
3021 signal_socks_failure (s5r,
3022 SOCKS5_STATUS_NETWORK_UNREACHABLE);
3023 return;
3024 }
3025 s5r->state = SOCKS5_DATA_TRANSFER;
3026 }
3027 break;
2869 } 3028 }
2870 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3029 case SOCKS5_AT_IPV6:
2871 "forwarding %d bytes from client\n", s5r->rbuf_len);
2872 s5r->fwdwtask =
2873 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
2874 s5r->remote_sock,
2875 &do_write_remote, s5r);
2876 if (s5r->fwdrtask == GNUNET_SCHEDULER_NO_TASK)
2877 { 3030 {
2878 s5r->fwdrtask = 3031 const struct in6_addr *v6 = (const struct in6_addr *) &c_req[1];
2879 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 3032 const uint16_t *port = (const uint16_t *) &v6[1];
2880 s5r->remote_sock, 3033 struct sockaddr_in6 *in;
2881 &do_read_remote, s5r); 3034
3035 alen = sizeof (struct in6_addr);
3036 if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
3037 alen + sizeof (uint16_t))
3038 return; /* need more data */
3039 in = (struct sockaddr_in6 *) &s5r->destination_address;
3040 in->sin6_family = AF_INET6;
3041 in->sin6_addr = *v6;
3042 in->sin6_port = *port;
3043#if HAVE_SOCKADDR_IN_SIN_LEN
3044 in->sin6_len = sizeof (*in);
3045#endif
3046 s5r->state = SOCKS5_DATA_TRANSFER;
2882 } 3047 }
3048 break;
3049 default:
3050 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3051 _("Unsupported socks address type %d\n"),
3052 (int) c_req->addr_type);
3053 signal_socks_failure (s5r,
3054 SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED);
3055 return;
3056 }
3057 clear_from_s5r_rbuf (s5r,
3058 sizeof (struct Socks5ClientRequestMessage) +
3059 alen + sizeof (uint16_t));
3060 if (0 != s5r->rbuf_len)
3061 {
3062 /* read more bytes than healthy, why did the client send more? */
3063 GNUNET_break_op (0);
3064 signal_socks_failure (s5r,
3065 SOCKS5_STATUS_GENERAL_FAILURE);
3066 return;
2883 } 3067 }
3068 signal_socks_success (s5r);
3069 run_httpds (); // needed here!?
3070 return;
3071 case SOCKS5_DATA_TRANSFER:
3072 GNUNET_assert (0 < s5r->rbuf_len);
3073 if (GNUNET_SCHEDULER_NO_TASK == s5r->wtask)
3074 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
3075 s5r->remote_sock,
3076 &do_write /* _remote */, s5r);
2884 return; 3077 return;
2885 default: 3078 default:
2886 GNUNET_break (0); 3079 GNUNET_break (0);