diff options
Diffstat (limited to 'src/gns/gnunet-gns-proxy.c')
-rw-r--r-- | src/gns/gnunet-gns-proxy.c | 558 |
1 files changed, 426 insertions, 132 deletions
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index 08663a57e..d66f5c658 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c | |||
@@ -1,21 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2012-2014 GNUnet e.V. | 3 | Copyright (C) 2012-2018 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software: you can redistribute it and/or modify it |
6 | it under the terms of the GNU General Public License as published | 6 | under the terms of the GNU Affero General Public License as published |
7 | by the Free Software Foundation; either version 3, or (at your | 7 | by the Free Software Foundation, either version 3 of the License, |
8 | option) any later version. | 8 | or (at your option) any later version. |
9 | 9 | ||
10 | GNUnet is distributed in the hope that it will be useful, but | 10 | GNUnet is distributed in the hope that it will be useful, but |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with GNUnet; see the file COPYING. If not, write to the | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | 17 | */ |
20 | /** | 18 | /** |
21 | * @author Martin Schanzenbach | 19 | * @author Martin Schanzenbach |
@@ -48,6 +46,7 @@ | |||
48 | #include "gns.h" | 46 | #include "gns.h" |
49 | 47 | ||
50 | 48 | ||
49 | |||
51 | /** | 50 | /** |
52 | * Default Socks5 listen port. | 51 | * Default Socks5 listen port. |
53 | */ | 52 | */ |
@@ -106,7 +105,13 @@ | |||
106 | * @param fun name of curl_easy-function that gave the error | 105 | * @param fun name of curl_easy-function that gave the error |
107 | * @param rc return code from curl | 106 | * @param rc return code from curl |
108 | */ | 107 | */ |
109 | #define LOG_CURL_EASY(level,fun,rc) GNUNET_log(level, _("%s failed at %s:%d: `%s'\n"), fun, __FILE__, __LINE__, curl_easy_strerror (rc)) | 108 | #define LOG_CURL_EASY(level,fun,rc) \ |
109 | GNUNET_log (level, \ | ||
110 | _("%s failed at %s:%d: `%s'\n"), \ | ||
111 | fun, \ | ||
112 | __FILE__, \ | ||
113 | __LINE__, \ | ||
114 | curl_easy_strerror (rc)) | ||
110 | 115 | ||
111 | 116 | ||
112 | /* *************** Socks protocol definitions (move to TUN?) ****************** */ | 117 | /* *************** Socks protocol definitions (move to TUN?) ****************** */ |
@@ -626,6 +631,11 @@ struct Socks5Request | |||
626 | * Did we suspend MHD processing? | 631 | * Did we suspend MHD processing? |
627 | */ | 632 | */ |
628 | int suspended; | 633 | int suspended; |
634 | |||
635 | /** | ||
636 | * Did we pause CURL processing? | ||
637 | */ | ||
638 | int curl_paused; | ||
629 | }; | 639 | }; |
630 | 640 | ||
631 | 641 | ||
@@ -636,7 +646,7 @@ struct Socks5Request | |||
636 | /** | 646 | /** |
637 | * The port the proxy is running on (default 7777) | 647 | * The port the proxy is running on (default 7777) |
638 | */ | 648 | */ |
639 | static unsigned long long port = GNUNET_GNS_PROXY_PORT; | 649 | static uint16_t port = GNUNET_GNS_PROXY_PORT; |
640 | 650 | ||
641 | /** | 651 | /** |
642 | * The CA file (pem) to use for the proxy CA | 652 | * The CA file (pem) to use for the proxy CA |
@@ -679,6 +689,11 @@ static CURLM *curl_multi; | |||
679 | static struct GNUNET_GNS_Handle *gns_handle; | 689 | static struct GNUNET_GNS_Handle *gns_handle; |
680 | 690 | ||
681 | /** | 691 | /** |
692 | * Disable IPv6. | ||
693 | */ | ||
694 | static int disable_v6; | ||
695 | |||
696 | /** | ||
682 | * DLL for http/https daemons | 697 | * DLL for http/https daemons |
683 | */ | 698 | */ |
684 | static struct MhdHttpList *mhd_httpd_head; | 699 | static struct MhdHttpList *mhd_httpd_head; |
@@ -763,21 +778,37 @@ cleanup_s5r (struct Socks5Request *s5r) | |||
763 | } | 778 | } |
764 | if ( (NULL != s5r->response) && | 779 | if ( (NULL != s5r->response) && |
765 | (curl_failure_response != s5r->response) ) | 780 | (curl_failure_response != s5r->response) ) |
781 | { | ||
766 | MHD_destroy_response (s5r->response); | 782 | MHD_destroy_response (s5r->response); |
783 | s5r->response = NULL; | ||
784 | } | ||
767 | if (NULL != s5r->rtask) | 785 | if (NULL != s5r->rtask) |
786 | { | ||
768 | GNUNET_SCHEDULER_cancel (s5r->rtask); | 787 | GNUNET_SCHEDULER_cancel (s5r->rtask); |
788 | s5r->rtask = NULL; | ||
789 | } | ||
769 | if (NULL != s5r->timeout_task) | 790 | if (NULL != s5r->timeout_task) |
791 | { | ||
770 | GNUNET_SCHEDULER_cancel (s5r->timeout_task); | 792 | GNUNET_SCHEDULER_cancel (s5r->timeout_task); |
793 | s5r->timeout_task = NULL; | ||
794 | } | ||
771 | if (NULL != s5r->wtask) | 795 | if (NULL != s5r->wtask) |
796 | { | ||
772 | GNUNET_SCHEDULER_cancel (s5r->wtask); | 797 | GNUNET_SCHEDULER_cancel (s5r->wtask); |
798 | s5r->wtask = NULL; | ||
799 | } | ||
773 | if (NULL != s5r->gns_lookup) | 800 | if (NULL != s5r->gns_lookup) |
801 | { | ||
774 | GNUNET_GNS_lookup_with_tld_cancel (s5r->gns_lookup); | 802 | GNUNET_GNS_lookup_with_tld_cancel (s5r->gns_lookup); |
803 | s5r->gns_lookup = NULL; | ||
804 | } | ||
775 | if (NULL != s5r->sock) | 805 | if (NULL != s5r->sock) |
776 | { | 806 | { |
777 | if (SOCKS5_SOCKET_WITH_MHD <= s5r->state) | 807 | if (SOCKS5_SOCKET_WITH_MHD <= s5r->state) |
778 | GNUNET_NETWORK_socket_free_memory_only_ (s5r->sock); | 808 | GNUNET_NETWORK_socket_free_memory_only_ (s5r->sock); |
779 | else | 809 | else |
780 | GNUNET_NETWORK_socket_close (s5r->sock); | 810 | GNUNET_NETWORK_socket_close (s5r->sock); |
811 | s5r->sock = NULL; | ||
781 | } | 812 | } |
782 | GNUNET_CONTAINER_DLL_remove (s5r_head, | 813 | GNUNET_CONTAINER_DLL_remove (s5r_head, |
783 | s5r_tail, | 814 | s5r_tail, |
@@ -823,7 +854,9 @@ mhd_content_cb (void *cls, | |||
823 | start the download, the IO buffer is still full | 854 | start the download, the IO buffer is still full |
824 | with upload data. */ | 855 | with upload data. */ |
825 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 856 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
826 | "Pausing MHD download, not yet ready for download\n"); | 857 | "Pausing MHD download %s%s, not yet ready for download\n", |
858 | s5r->domain, | ||
859 | s5r->url); | ||
827 | return 0; /* not yet ready for data download */ | 860 | return 0; /* not yet ready for data download */ |
828 | } | 861 | } |
829 | bytes_to_copy = GNUNET_MIN (max, | 862 | bytes_to_copy = GNUNET_MIN (max, |
@@ -832,12 +865,21 @@ mhd_content_cb (void *cls, | |||
832 | (SOCKS5_SOCKET_DOWNLOAD_DONE != s5r->state) ) | 865 | (SOCKS5_SOCKET_DOWNLOAD_DONE != s5r->state) ) |
833 | { | 866 | { |
834 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 867 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
835 | "Pausing MHD download, no data available\n"); | 868 | "Pausing MHD download %s%s, no data available\n", |
869 | s5r->domain, | ||
870 | s5r->url); | ||
836 | if (NULL != s5r->curl) | 871 | if (NULL != s5r->curl) |
837 | { | 872 | { |
838 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 873 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
839 | "Continuing CURL interaction\n"); | 874 | "Continuing CURL interaction for %s%s\n", |
840 | curl_easy_pause (s5r->curl, CURLPAUSE_CONT); | 875 | s5r->domain, |
876 | s5r->url); | ||
877 | if (GNUNET_YES == s5r->curl_paused) | ||
878 | { | ||
879 | s5r->curl_paused = GNUNET_NO; | ||
880 | curl_easy_pause (s5r->curl, | ||
881 | CURLPAUSE_CONT); | ||
882 | } | ||
841 | curl_download_prepare (); | 883 | curl_download_prepare (); |
842 | } | 884 | } |
843 | if (GNUNET_NO == s5r->suspended) | 885 | if (GNUNET_NO == s5r->suspended) |
@@ -851,13 +893,17 @@ mhd_content_cb (void *cls, | |||
851 | (SOCKS5_SOCKET_DOWNLOAD_DONE == s5r->state) ) | 893 | (SOCKS5_SOCKET_DOWNLOAD_DONE == s5r->state) ) |
852 | { | 894 | { |
853 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 895 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
854 | "Completed MHD download\n"); | 896 | "Completed MHD download %s%s\n", |
897 | s5r->domain, | ||
898 | s5r->url); | ||
855 | return MHD_CONTENT_READER_END_OF_STREAM; | 899 | return MHD_CONTENT_READER_END_OF_STREAM; |
856 | } | 900 | } |
857 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 901 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
858 | "Writing %llu/%llu bytes\n", | 902 | "Writing %llu/%llu bytes to %s%s\n", |
859 | (unsigned long long) bytes_to_copy, | 903 | (unsigned long long) bytes_to_copy, |
860 | (unsigned long long) s5r->io_len); | 904 | (unsigned long long) s5r->io_len, |
905 | s5r->domain, | ||
906 | s5r->url); | ||
861 | GNUNET_memcpy (buf, | 907 | GNUNET_memcpy (buf, |
862 | s5r->io_buf, | 908 | s5r->io_buf, |
863 | bytes_to_copy); | 909 | bytes_to_copy); |
@@ -865,10 +911,14 @@ mhd_content_cb (void *cls, | |||
865 | &s5r->io_buf[bytes_to_copy], | 911 | &s5r->io_buf[bytes_to_copy], |
866 | s5r->io_len - bytes_to_copy); | 912 | s5r->io_len - bytes_to_copy); |
867 | s5r->io_len -= bytes_to_copy; | 913 | s5r->io_len -= bytes_to_copy; |
868 | if (NULL != s5r->curl) | 914 | if ( (NULL != s5r->curl) && |
915 | (GNUNET_YES == s5r->curl_paused) ) | ||
869 | { | 916 | { |
870 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 917 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
871 | "Continuing CURL interaction\n"); | 918 | "Continuing CURL interaction for %s%s\n", |
919 | s5r->domain, | ||
920 | s5r->url); | ||
921 | s5r->curl_paused = GNUNET_NO; | ||
872 | curl_easy_pause (s5r->curl, | 922 | curl_easy_pause (s5r->curl, |
873 | CURLPAUSE_CONT); | 923 | CURLPAUSE_CONT); |
874 | } | 924 | } |
@@ -911,8 +961,10 @@ check_ssl_certificate (struct Socks5Request *s5r) | |||
911 | tlsinfo->backend); | 961 | tlsinfo->backend); |
912 | return GNUNET_SYSERR; | 962 | return GNUNET_SYSERR; |
913 | } | 963 | } |
914 | chainp = gnutls_certificate_get_peers (tlsinfo->internals, &cert_list_size); | 964 | chainp = gnutls_certificate_get_peers (tlsinfo->internals, |
915 | if ( (! chainp) || (0 == cert_list_size) ) | 965 | &cert_list_size); |
966 | if ( (! chainp) || | ||
967 | (0 == cert_list_size) ) | ||
916 | return GNUNET_SYSERR; | 968 | return GNUNET_SYSERR; |
917 | 969 | ||
918 | size = sizeof (certdn); | 970 | size = sizeof (certdn); |
@@ -1015,9 +1067,10 @@ check_ssl_certificate (struct Socks5Request *s5r) | |||
1015 | name))) | 1067 | name))) |
1016 | { | 1068 | { |
1017 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1069 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
1018 | _("TLS certificate subject name (%s) does not match `%s'\n"), | 1070 | _("TLS certificate subject name (%s) does not match `%s': %d\n"), |
1019 | certdn, | 1071 | certdn, |
1020 | name); | 1072 | name, |
1073 | rc); | ||
1021 | gnutls_x509_crt_deinit (x509_cert); | 1074 | gnutls_x509_crt_deinit (x509_cert); |
1022 | return GNUNET_SYSERR; | 1075 | return GNUNET_SYSERR; |
1023 | } | 1076 | } |
@@ -1075,15 +1128,17 @@ curl_check_hdr (void *buffer, | |||
1075 | if (GNUNET_OK != check_ssl_certificate (s5r)) | 1128 | if (GNUNET_OK != check_ssl_certificate (s5r)) |
1076 | return 0; | 1129 | return 0; |
1077 | } | 1130 | } |
1078 | 1131 | ndup = GNUNET_strndup (buffer, | |
1079 | ndup = GNUNET_strndup (buffer, bytes); | 1132 | bytes); |
1080 | hdr_type = strtok (ndup, ":"); | 1133 | hdr_type = strtok (ndup, |
1134 | ":"); | ||
1081 | if (NULL == hdr_type) | 1135 | if (NULL == hdr_type) |
1082 | { | 1136 | { |
1083 | GNUNET_free (ndup); | 1137 | GNUNET_free (ndup); |
1084 | return bytes; | 1138 | return bytes; |
1085 | } | 1139 | } |
1086 | hdr_val = strtok (NULL, ""); | 1140 | hdr_val = strtok (NULL, |
1141 | ""); | ||
1087 | if (NULL == hdr_val) | 1142 | if (NULL == hdr_val) |
1088 | { | 1143 | { |
1089 | GNUNET_free (ndup); | 1144 | GNUNET_free (ndup); |
@@ -1105,7 +1160,9 @@ curl_check_hdr (void *buffer, | |||
1105 | domain_matched = GNUNET_NO; /* make sure we match domain at most once */ | 1160 | domain_matched = GNUNET_NO; /* make sure we match domain at most once */ |
1106 | for (tok = strtok (hdr_val, ";"); NULL != tok; tok = strtok (NULL, ";")) | 1161 | for (tok = strtok (hdr_val, ";"); NULL != tok; tok = strtok (NULL, ";")) |
1107 | { | 1162 | { |
1108 | if ( (0 == strncasecmp (tok, " domain", strlen (" domain"))) && | 1163 | if ( (0 == strncasecmp (tok, |
1164 | " domain", | ||
1165 | strlen (" domain"))) && | ||
1109 | (GNUNET_NO == domain_matched) ) | 1166 | (GNUNET_NO == domain_matched) ) |
1110 | { | 1167 | { |
1111 | domain_matched = GNUNET_YES; | 1168 | domain_matched = GNUNET_YES; |
@@ -1113,7 +1170,8 @@ curl_check_hdr (void *buffer, | |||
1113 | if (strlen (cookie_domain) < strlen (s5r->leho)) | 1170 | if (strlen (cookie_domain) < strlen (s5r->leho)) |
1114 | { | 1171 | { |
1115 | delta_cdomain = strlen (s5r->leho) - strlen (cookie_domain); | 1172 | delta_cdomain = strlen (s5r->leho) - strlen (cookie_domain); |
1116 | if (0 == strcasecmp (cookie_domain, s5r->leho + delta_cdomain)) | 1173 | if (0 == strcasecmp (cookie_domain, |
1174 | s5r->leho + delta_cdomain)) | ||
1117 | { | 1175 | { |
1118 | offset += sprintf (new_cookie_hdr + offset, | 1176 | offset += sprintf (new_cookie_hdr + offset, |
1119 | " domain=%s;", | 1177 | " domain=%s;", |
@@ -1121,18 +1179,30 @@ curl_check_hdr (void *buffer, | |||
1121 | continue; | 1179 | continue; |
1122 | } | 1180 | } |
1123 | } | 1181 | } |
1124 | else if (0 == strcmp (cookie_domain, s5r->leho)) | 1182 | else if (0 == strcmp (cookie_domain, |
1183 | s5r->leho)) | ||
1125 | { | 1184 | { |
1126 | offset += sprintf (new_cookie_hdr + offset, | 1185 | offset += sprintf (new_cookie_hdr + offset, |
1127 | " domain=%s;", | 1186 | " domain=%s;", |
1128 | s5r->domain); | 1187 | s5r->domain); |
1129 | continue; | 1188 | continue; |
1130 | } | 1189 | } |
1190 | else if ( ('.' == cookie_domain[0]) && | ||
1191 | (0 == strcmp (&cookie_domain[1], | ||
1192 | s5r->leho)) ) | ||
1193 | { | ||
1194 | offset += sprintf (new_cookie_hdr + offset, | ||
1195 | " domain=.%s;", | ||
1196 | s5r->domain); | ||
1197 | continue; | ||
1198 | } | ||
1131 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1199 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
1132 | _("Cookie domain `%s' supplied by server is invalid\n"), | 1200 | _("Cookie domain `%s' supplied by server is invalid\n"), |
1133 | tok); | 1201 | tok); |
1134 | } | 1202 | } |
1135 | GNUNET_memcpy (new_cookie_hdr + offset, tok, strlen (tok)); | 1203 | GNUNET_memcpy (new_cookie_hdr + offset, |
1204 | tok, | ||
1205 | strlen (tok)); | ||
1136 | offset += strlen (tok); | 1206 | offset += strlen (tok); |
1137 | new_cookie_hdr[offset++] = ';'; | 1207 | new_cookie_hdr[offset++] = ';'; |
1138 | } | 1208 | } |
@@ -1140,7 +1210,14 @@ curl_check_hdr (void *buffer, | |||
1140 | } | 1210 | } |
1141 | 1211 | ||
1142 | new_location = NULL; | 1212 | new_location = NULL; |
1143 | if (0 == strcasecmp (MHD_HTTP_HEADER_LOCATION, hdr_type)) | 1213 | if (0 == strcasecmp (MHD_HTTP_HEADER_TRANSFER_ENCODING, |
1214 | hdr_type)) | ||
1215 | { | ||
1216 | /* Ignore transfer encoding, set automatically by MHD if required */ | ||
1217 | goto cleanup; | ||
1218 | } | ||
1219 | if (0 == strcasecmp (MHD_HTTP_HEADER_LOCATION, | ||
1220 | hdr_type)) | ||
1144 | { | 1221 | { |
1145 | char *leho_host; | 1222 | char *leho_host; |
1146 | 1223 | ||
@@ -1184,6 +1261,7 @@ curl_check_hdr (void *buffer, | |||
1184 | s5r->header_tail, | 1261 | s5r->header_tail, |
1185 | header); | 1262 | header); |
1186 | } | 1263 | } |
1264 | cleanup: | ||
1187 | GNUNET_free (ndup); | 1265 | GNUNET_free (ndup); |
1188 | GNUNET_free_non_null (new_cookie_hdr); | 1266 | GNUNET_free_non_null (new_cookie_hdr); |
1189 | GNUNET_free_non_null (new_location); | 1267 | GNUNET_free_non_null (new_location); |
@@ -1227,7 +1305,9 @@ create_mhd_response_from_s5r (struct Socks5Request *s5r) | |||
1227 | s5r->domain, | 1305 | s5r->domain, |
1228 | s5r->url); | 1306 | s5r->url); |
1229 | s5r->response_code = resp_code; | 1307 | s5r->response_code = resp_code; |
1230 | s5r->response = MHD_create_response_from_callback ((-1 == content_length) ? MHD_SIZE_UNKNOWN : content_length, | 1308 | s5r->response = MHD_create_response_from_callback ((-1 == content_length) |
1309 | ? MHD_SIZE_UNKNOWN | ||
1310 | : content_length, | ||
1231 | IO_BUFFERSIZE, | 1311 | IO_BUFFERSIZE, |
1232 | &mhd_content_cb, | 1312 | &mhd_content_cb, |
1233 | s5r, | 1313 | s5r, |
@@ -1269,6 +1349,7 @@ create_mhd_response_from_s5r (struct Socks5Request *s5r) | |||
1269 | return GNUNET_OK; | 1349 | return GNUNET_OK; |
1270 | } | 1350 | } |
1271 | 1351 | ||
1352 | |||
1272 | /** | 1353 | /** |
1273 | * Handle response payload data from cURL. Copies it into our `io_buf` to make | 1354 | * Handle response payload data from cURL. Copies it into our `io_buf` to make |
1274 | * it available to MHD. | 1355 | * it available to MHD. |
@@ -1288,6 +1369,12 @@ curl_download_cb (void *ptr, | |||
1288 | struct Socks5Request *s5r = ctx; | 1369 | struct Socks5Request *s5r = ctx; |
1289 | size_t total = size * nmemb; | 1370 | size_t total = size * nmemb; |
1290 | 1371 | ||
1372 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1373 | "Receiving %ux%u bytes for `%s%s' from cURL\n", | ||
1374 | (unsigned int) size, | ||
1375 | (unsigned int) nmemb, | ||
1376 | s5r->domain, | ||
1377 | s5r->url); | ||
1291 | if (NULL == s5r->response) | 1378 | if (NULL == s5r->response) |
1292 | GNUNET_assert (GNUNET_OK == | 1379 | GNUNET_assert (GNUNET_OK == |
1293 | create_mhd_response_from_s5r (s5r)); | 1380 | create_mhd_response_from_s5r (s5r)); |
@@ -1302,6 +1389,7 @@ curl_download_cb (void *ptr, | |||
1302 | "Pausing CURL download `%s%s', waiting for UPLOAD to finish\n", | 1389 | "Pausing CURL download `%s%s', waiting for UPLOAD to finish\n", |
1303 | s5r->domain, | 1390 | s5r->domain, |
1304 | s5r->url); | 1391 | s5r->url); |
1392 | s5r->curl_paused = GNUNET_YES; | ||
1305 | return CURL_WRITEFUNC_PAUSE; /* not yet ready for data download */ | 1393 | return CURL_WRITEFUNC_PAUSE; /* not yet ready for data download */ |
1306 | } | 1394 | } |
1307 | if (sizeof (s5r->io_buf) - s5r->io_len < total) | 1395 | if (sizeof (s5r->io_buf) - s5r->io_len < total) |
@@ -1313,6 +1401,7 @@ curl_download_cb (void *ptr, | |||
1313 | (unsigned long long) sizeof (s5r->io_buf), | 1401 | (unsigned long long) sizeof (s5r->io_buf), |
1314 | (unsigned long long) s5r->io_len, | 1402 | (unsigned long long) s5r->io_len, |
1315 | (unsigned long long) total); | 1403 | (unsigned long long) total); |
1404 | s5r->curl_paused = GNUNET_YES; | ||
1316 | return CURL_WRITEFUNC_PAUSE; /* not enough space */ | 1405 | return CURL_WRITEFUNC_PAUSE; /* not enough space */ |
1317 | } | 1406 | } |
1318 | GNUNET_memcpy (&s5r->io_buf[s5r->io_len], | 1407 | GNUNET_memcpy (&s5r->io_buf[s5r->io_len], |
@@ -1367,6 +1456,12 @@ curl_upload_cb (void *buf, | |||
1367 | (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) ) | 1456 | (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) ) |
1368 | { | 1457 | { |
1369 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; | 1458 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; |
1459 | if (GNUNET_YES == s5r->curl_paused) | ||
1460 | { | ||
1461 | s5r->curl_paused = GNUNET_NO; | ||
1462 | curl_easy_pause (s5r->curl, | ||
1463 | CURLPAUSE_CONT); | ||
1464 | } | ||
1370 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1465 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1371 | "Completed CURL UPLOAD %s%s\n", | 1466 | "Completed CURL UPLOAD %s%s\n", |
1372 | s5r->domain, | 1467 | s5r->domain, |
@@ -1381,7 +1476,9 @@ curl_upload_cb (void *buf, | |||
1381 | } | 1476 | } |
1382 | to_copy = GNUNET_MIN (s5r->io_len, | 1477 | to_copy = GNUNET_MIN (s5r->io_len, |
1383 | len); | 1478 | len); |
1384 | GNUNET_memcpy (buf, s5r->io_buf, to_copy); | 1479 | GNUNET_memcpy (buf, |
1480 | s5r->io_buf, | ||
1481 | to_copy); | ||
1385 | memmove (s5r->io_buf, | 1482 | memmove (s5r->io_buf, |
1386 | &s5r->io_buf[to_copy], | 1483 | &s5r->io_buf[to_copy], |
1387 | s5r->io_len - to_copy); | 1484 | s5r->io_len - to_copy); |
@@ -1445,20 +1542,28 @@ curl_download_prepare () | |||
1445 | return; | 1542 | return; |
1446 | } | 1543 | } |
1447 | to = -1; | 1544 | to = -1; |
1448 | GNUNET_break (CURLM_OK == curl_multi_timeout (curl_multi, &to)); | 1545 | GNUNET_break (CURLM_OK == |
1546 | curl_multi_timeout (curl_multi, | ||
1547 | &to)); | ||
1449 | if (-1 == to) | 1548 | if (-1 == to) |
1450 | rtime = GNUNET_TIME_UNIT_FOREVER_REL; | 1549 | rtime = GNUNET_TIME_UNIT_FOREVER_REL; |
1451 | else | 1550 | else |
1452 | rtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, to); | 1551 | rtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, |
1552 | to); | ||
1453 | if (-1 != max) | 1553 | if (-1 != max) |
1454 | { | 1554 | { |
1455 | grs = GNUNET_NETWORK_fdset_create (); | 1555 | grs = GNUNET_NETWORK_fdset_create (); |
1456 | gws = GNUNET_NETWORK_fdset_create (); | 1556 | gws = GNUNET_NETWORK_fdset_create (); |
1457 | GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); | 1557 | GNUNET_NETWORK_fdset_copy_native (grs, |
1458 | GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); | 1558 | &rs, |
1559 | max + 1); | ||
1560 | GNUNET_NETWORK_fdset_copy_native (gws, | ||
1561 | &ws, | ||
1562 | max + 1); | ||
1459 | curl_download_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 1563 | curl_download_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, |
1460 | rtime, | 1564 | rtime, |
1461 | grs, gws, | 1565 | grs, |
1566 | gws, | ||
1462 | &curl_task_download, | 1567 | &curl_task_download, |
1463 | curl_multi); | 1568 | curl_multi); |
1464 | GNUNET_NETWORK_fdset_destroy (gws); | 1569 | GNUNET_NETWORK_fdset_destroy (gws); |
@@ -1495,6 +1600,9 @@ curl_task_download (void *cls) | |||
1495 | running = 0; | 1600 | running = 0; |
1496 | mret = curl_multi_perform (curl_multi, | 1601 | mret = curl_multi_perform (curl_multi, |
1497 | &running); | 1602 | &running); |
1603 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1604 | "Checking CURL multi status: %d\n", | ||
1605 | mret); | ||
1498 | while (NULL != (msg = curl_multi_info_read (curl_multi, | 1606 | while (NULL != (msg = curl_multi_info_read (curl_multi, |
1499 | &msgnum))) | 1607 | &msgnum))) |
1500 | { | 1608 | { |
@@ -1527,7 +1635,12 @@ curl_task_download (void *cls) | |||
1527 | GNUNET_assert (GNUNET_OK == | 1635 | GNUNET_assert (GNUNET_OK == |
1528 | create_mhd_response_from_s5r (s5r)); | 1636 | create_mhd_response_from_s5r (s5r)); |
1529 | } | 1637 | } |
1530 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE; | 1638 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE; |
1639 | if (GNUNET_YES == s5r->suspended) | ||
1640 | { | ||
1641 | MHD_resume_connection (s5r->con); | ||
1642 | s5r->suspended = GNUNET_NO; | ||
1643 | } | ||
1531 | run_mhd_now (s5r->hd); | 1644 | run_mhd_now (s5r->hd); |
1532 | break; | 1645 | break; |
1533 | default: | 1646 | default: |
@@ -1538,6 +1651,11 @@ curl_task_download (void *cls) | |||
1538 | curl_easy_strerror (msg->data.result)); | 1651 | curl_easy_strerror (msg->data.result)); |
1539 | /* FIXME: indicate error somehow? close MHD connection badly as well? */ | 1652 | /* FIXME: indicate error somehow? close MHD connection badly as well? */ |
1540 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE; | 1653 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE; |
1654 | if (GNUNET_YES == s5r->suspended) | ||
1655 | { | ||
1656 | MHD_resume_connection (s5r->con); | ||
1657 | s5r->suspended = GNUNET_NO; | ||
1658 | } | ||
1541 | run_mhd_now (s5r->hd); | 1659 | run_mhd_now (s5r->hd); |
1542 | break; | 1660 | break; |
1543 | } | 1661 | } |
@@ -1600,13 +1718,10 @@ con_val_iter (void *cls, | |||
1600 | struct Socks5Request *s5r = cls; | 1718 | struct Socks5Request *s5r = cls; |
1601 | char *hdr; | 1719 | char *hdr; |
1602 | 1720 | ||
1603 | if ( (0 == strcasecmp (MHD_HTTP_HEADER_HOST, key)) && | 1721 | if ( (0 == strcasecmp (MHD_HTTP_HEADER_HOST, |
1722 | key)) && | ||
1604 | (NULL != s5r->leho) ) | 1723 | (NULL != s5r->leho) ) |
1605 | value = s5r->leho; | 1724 | value = s5r->leho; |
1606 | if (0 == strcasecmp (MHD_HTTP_HEADER_CONTENT_LENGTH, key)) | ||
1607 | return MHD_YES; | ||
1608 | if (0 == strcasecmp (MHD_HTTP_HEADER_ACCEPT_ENCODING, key)) | ||
1609 | return MHD_YES; | ||
1610 | GNUNET_asprintf (&hdr, | 1725 | GNUNET_asprintf (&hdr, |
1611 | "%s: %s", | 1726 | "%s: %s", |
1612 | key, | 1727 | key, |
@@ -1670,7 +1785,7 @@ create_response (void *cls, | |||
1670 | return MHD_NO; | 1785 | return MHD_NO; |
1671 | } | 1786 | } |
1672 | s5r->con = con; | 1787 | s5r->con = con; |
1673 | //Fresh connection. | 1788 | /* Fresh connection. */ |
1674 | if (SOCKS5_SOCKET_WITH_MHD == s5r->state) | 1789 | if (SOCKS5_SOCKET_WITH_MHD == s5r->state) |
1675 | { | 1790 | { |
1676 | /* first time here, initialize curl handle */ | 1791 | /* first time here, initialize curl handle */ |
@@ -1726,21 +1841,40 @@ create_response (void *cls, | |||
1726 | return MHD_queue_response (con, | 1841 | return MHD_queue_response (con, |
1727 | MHD_HTTP_INTERNAL_SERVER_ERROR, | 1842 | MHD_HTTP_INTERNAL_SERVER_ERROR, |
1728 | curl_failure_response); | 1843 | curl_failure_response); |
1729 | curl_easy_setopt (s5r->curl, CURLOPT_HEADERFUNCTION, &curl_check_hdr); | 1844 | curl_easy_setopt (s5r->curl, |
1730 | curl_easy_setopt (s5r->curl, CURLOPT_HEADERDATA, s5r); | 1845 | CURLOPT_HEADERFUNCTION, |
1731 | curl_easy_setopt (s5r->curl, CURLOPT_FOLLOWLOCATION, 0); | 1846 | &curl_check_hdr); |
1847 | curl_easy_setopt (s5r->curl, | ||
1848 | CURLOPT_HEADERDATA, | ||
1849 | s5r); | ||
1850 | curl_easy_setopt (s5r->curl, | ||
1851 | CURLOPT_FOLLOWLOCATION, | ||
1852 | 0); | ||
1732 | if (s5r->is_gns) | 1853 | if (s5r->is_gns) |
1733 | curl_easy_setopt (s5r->curl, | 1854 | curl_easy_setopt (s5r->curl, |
1734 | CURLOPT_IPRESOLVE, | 1855 | CURLOPT_IPRESOLVE, |
1735 | CURL_IPRESOLVE_V4); | 1856 | CURL_IPRESOLVE_V4); |
1736 | curl_easy_setopt (s5r->curl, CURLOPT_CONNECTTIMEOUT, 600L); | 1857 | curl_easy_setopt (s5r->curl, |
1737 | curl_easy_setopt (s5r->curl, CURLOPT_TIMEOUT, 600L); | 1858 | CURLOPT_CONNECTTIMEOUT, |
1738 | curl_easy_setopt (s5r->curl, CURLOPT_NOSIGNAL, 1L); | 1859 | 600L); |
1739 | curl_easy_setopt (s5r->curl, CURLOPT_HTTP_CONTENT_DECODING, 0); | 1860 | curl_easy_setopt (s5r->curl, |
1740 | curl_easy_setopt (s5r->curl, CURLOPT_HTTP_TRANSFER_DECODING, 0); | 1861 | CURLOPT_TIMEOUT, |
1741 | curl_easy_setopt (s5r->curl, CURLOPT_NOSIGNAL, 1L); | 1862 | 600L); |
1742 | curl_easy_setopt (s5r->curl, CURLOPT_PRIVATE, s5r); | 1863 | curl_easy_setopt (s5r->curl, |
1743 | curl_easy_setopt (s5r->curl, CURLOPT_VERBOSE, 0L); | 1864 | CURLOPT_NOSIGNAL, |
1865 | 1L); | ||
1866 | curl_easy_setopt (s5r->curl, | ||
1867 | CURLOPT_HTTP_CONTENT_DECODING, | ||
1868 | 0); | ||
1869 | curl_easy_setopt (s5r->curl, | ||
1870 | CURLOPT_NOSIGNAL, | ||
1871 | 1L); | ||
1872 | curl_easy_setopt (s5r->curl, | ||
1873 | CURLOPT_PRIVATE, | ||
1874 | s5r); | ||
1875 | curl_easy_setopt (s5r->curl, | ||
1876 | CURLOPT_VERBOSE, | ||
1877 | 0L); | ||
1744 | /** | 1878 | /** |
1745 | * Pre-populate cache to resolve Hostname. | 1879 | * Pre-populate cache to resolve Hostname. |
1746 | * This is necessary as the DNS name in the CURLOPT_URL is used | 1880 | * This is necessary as the DNS name in the CURLOPT_URL is used |
@@ -1796,37 +1930,131 @@ create_response (void *cls, | |||
1796 | MHD_HTTP_METHOD_PUT)) | 1930 | MHD_HTTP_METHOD_PUT)) |
1797 | { | 1931 | { |
1798 | s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED; | 1932 | s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED; |
1799 | curl_easy_setopt (s5r->curl, CURLOPT_UPLOAD, 1L); | 1933 | curl_easy_setopt (s5r->curl, |
1800 | curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); | 1934 | CURLOPT_UPLOAD, |
1801 | curl_easy_setopt (s5r->curl, CURLOPT_WRITEDATA, s5r); | 1935 | 1L); |
1802 | curl_easy_setopt (s5r->curl, CURLOPT_READFUNCTION, &curl_upload_cb); | 1936 | curl_easy_setopt (s5r->curl, |
1803 | curl_easy_setopt (s5r->curl, CURLOPT_READDATA, s5r); | 1937 | CURLOPT_WRITEFUNCTION, |
1938 | &curl_download_cb); | ||
1939 | curl_easy_setopt (s5r->curl, | ||
1940 | CURLOPT_WRITEDATA, | ||
1941 | s5r); | ||
1942 | GNUNET_assert (CURLE_OK == | ||
1943 | curl_easy_setopt (s5r->curl, | ||
1944 | CURLOPT_READFUNCTION, | ||
1945 | &curl_upload_cb)); | ||
1946 | curl_easy_setopt (s5r->curl, | ||
1947 | CURLOPT_READDATA, | ||
1948 | s5r); | ||
1949 | { | ||
1950 | const char *us; | ||
1951 | long upload_size = 0; | ||
1952 | |||
1953 | us = MHD_lookup_connection_value (con, | ||
1954 | MHD_HEADER_KIND, | ||
1955 | MHD_HTTP_HEADER_CONTENT_LENGTH); | ||
1956 | if ( (1 == sscanf (us, | ||
1957 | "%ld", | ||
1958 | &upload_size)) && | ||
1959 | (upload_size >= 0) ) | ||
1960 | { | ||
1961 | curl_easy_setopt (s5r->curl, | ||
1962 | CURLOPT_INFILESIZE, | ||
1963 | upload_size); | ||
1964 | } | ||
1965 | } | ||
1804 | } | 1966 | } |
1805 | else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST)) | 1967 | else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST)) |
1806 | { | 1968 | { |
1807 | s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED; | 1969 | s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED; |
1808 | curl_easy_setopt (s5r->curl, CURLOPT_POST, 1L); | 1970 | curl_easy_setopt (s5r->curl, |
1809 | curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); | 1971 | CURLOPT_POST, |
1810 | curl_easy_setopt (s5r->curl, CURLOPT_WRITEDATA, s5r); | 1972 | 1L); |
1811 | curl_easy_setopt (s5r->curl, CURLOPT_READFUNCTION, &curl_upload_cb); | 1973 | curl_easy_setopt (s5r->curl, |
1812 | curl_easy_setopt (s5r->curl, CURLOPT_READDATA, s5r); | 1974 | CURLOPT_WRITEFUNCTION, |
1975 | &curl_download_cb); | ||
1976 | curl_easy_setopt (s5r->curl, | ||
1977 | CURLOPT_WRITEDATA, | ||
1978 | s5r); | ||
1979 | curl_easy_setopt (s5r->curl, | ||
1980 | CURLOPT_READFUNCTION, | ||
1981 | &curl_upload_cb); | ||
1982 | curl_easy_setopt (s5r->curl, | ||
1983 | CURLOPT_READDATA, | ||
1984 | s5r); | ||
1985 | { | ||
1986 | const char *us; | ||
1987 | long upload_size; | ||
1988 | |||
1989 | us = MHD_lookup_connection_value (con, | ||
1990 | MHD_HEADER_KIND, | ||
1991 | MHD_HTTP_HEADER_CONTENT_LENGTH); | ||
1992 | if ( (NULL != us) && | ||
1993 | (1 == sscanf (us, | ||
1994 | "%ld", | ||
1995 | &upload_size)) && | ||
1996 | (upload_size >= 0) ) | ||
1997 | { | ||
1998 | curl_easy_setopt (s5r->curl, | ||
1999 | CURLOPT_INFILESIZE, | ||
2000 | upload_size); | ||
2001 | } else { | ||
2002 | curl_easy_setopt (s5r->curl, | ||
2003 | CURLOPT_INFILESIZE, | ||
2004 | upload_size); | ||
2005 | } | ||
2006 | } | ||
1813 | } | 2007 | } |
1814 | else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_HEAD)) | 2008 | else if (0 == strcasecmp (meth, |
2009 | MHD_HTTP_METHOD_HEAD)) | ||
1815 | { | 2010 | { |
1816 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; | 2011 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; |
1817 | curl_easy_setopt (s5r->curl, CURLOPT_NOBODY, 1L); | 2012 | curl_easy_setopt (s5r->curl, |
2013 | CURLOPT_NOBODY, | ||
2014 | 1L); | ||
1818 | } | 2015 | } |
1819 | else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_OPTIONS)) | 2016 | else if (0 == strcasecmp (meth, |
2017 | MHD_HTTP_METHOD_OPTIONS)) | ||
1820 | { | 2018 | { |
1821 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; | 2019 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; |
1822 | curl_easy_setopt (s5r->curl, CURLOPT_CUSTOMREQUEST, "OPTIONS"); | 2020 | curl_easy_setopt (s5r->curl, |
2021 | CURLOPT_CUSTOMREQUEST, | ||
2022 | "OPTIONS"); | ||
2023 | curl_easy_setopt (s5r->curl, | ||
2024 | CURLOPT_WRITEFUNCTION, | ||
2025 | &curl_download_cb); | ||
2026 | curl_easy_setopt (s5r->curl, | ||
2027 | CURLOPT_WRITEDATA, | ||
2028 | s5r); | ||
2029 | |||
1823 | } | 2030 | } |
1824 | else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_GET)) | 2031 | else if (0 == strcasecmp (meth, |
2032 | MHD_HTTP_METHOD_GET)) | ||
1825 | { | 2033 | { |
1826 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; | 2034 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; |
1827 | curl_easy_setopt (s5r->curl, CURLOPT_HTTPGET, 1L); | 2035 | curl_easy_setopt (s5r->curl, |
1828 | curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); | 2036 | CURLOPT_HTTPGET, |
1829 | curl_easy_setopt (s5r->curl, CURLOPT_WRITEDATA, s5r); | 2037 | 1L); |
2038 | curl_easy_setopt (s5r->curl, | ||
2039 | CURLOPT_WRITEFUNCTION, | ||
2040 | &curl_download_cb); | ||
2041 | curl_easy_setopt (s5r->curl, | ||
2042 | CURLOPT_WRITEDATA, | ||
2043 | s5r); | ||
2044 | } | ||
2045 | else if (0 == strcasecmp (meth, | ||
2046 | MHD_HTTP_METHOD_DELETE)) | ||
2047 | { | ||
2048 | s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; | ||
2049 | curl_easy_setopt (s5r->curl, | ||
2050 | CURLOPT_CUSTOMREQUEST, | ||
2051 | "DELETE"); | ||
2052 | curl_easy_setopt (s5r->curl, | ||
2053 | CURLOPT_WRITEFUNCTION, | ||
2054 | &curl_download_cb); | ||
2055 | curl_easy_setopt (s5r->curl, | ||
2056 | CURLOPT_WRITEDATA, | ||
2057 | s5r); | ||
1830 | } | 2058 | } |
1831 | else | 2059 | else |
1832 | { | 2060 | { |
@@ -1840,31 +2068,47 @@ create_response (void *cls, | |||
1840 | 2068 | ||
1841 | if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_0)) | 2069 | if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_0)) |
1842 | { | 2070 | { |
1843 | curl_easy_setopt (s5r->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | 2071 | curl_easy_setopt (s5r->curl, |
2072 | CURLOPT_HTTP_VERSION, | ||
2073 | CURL_HTTP_VERSION_1_0); | ||
1844 | } | 2074 | } |
1845 | else if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_1)) | 2075 | else if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_1)) |
1846 | { | 2076 | { |
1847 | curl_easy_setopt (s5r->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | 2077 | curl_easy_setopt (s5r->curl, |
2078 | CURLOPT_HTTP_VERSION, | ||
2079 | CURL_HTTP_VERSION_1_1); | ||
1848 | } | 2080 | } |
1849 | else | 2081 | else |
1850 | { | 2082 | { |
1851 | curl_easy_setopt (s5r->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE); | 2083 | curl_easy_setopt (s5r->curl, |
2084 | CURLOPT_HTTP_VERSION, | ||
2085 | CURL_HTTP_VERSION_NONE); | ||
1852 | } | 2086 | } |
1853 | 2087 | ||
1854 | if (HTTPS_PORT == s5r->port) | 2088 | if (HTTPS_PORT == s5r->port) |
1855 | { | 2089 | { |
1856 | curl_easy_setopt (s5r->curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); | 2090 | curl_easy_setopt (s5r->curl, |
2091 | CURLOPT_USE_SSL, | ||
2092 | CURLUSESSL_ALL); | ||
1857 | if (NULL != s5r->dane_data) | 2093 | if (NULL != s5r->dane_data) |
1858 | curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYPEER, 0L); | 2094 | curl_easy_setopt (s5r->curl, |
2095 | CURLOPT_SSL_VERIFYPEER, | ||
2096 | 0L); | ||
1859 | else | 2097 | else |
1860 | curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYPEER, 1L); | 2098 | curl_easy_setopt (s5r->curl, |
2099 | CURLOPT_SSL_VERIFYPEER, | ||
2100 | 1L); | ||
1861 | /* Disable cURL checking the hostname, as we will check ourselves | 2101 | /* Disable cURL checking the hostname, as we will check ourselves |
1862 | as only we have the domain name or the LEHO or the DANE record */ | 2102 | as only we have the domain name or the LEHO or the DANE record */ |
1863 | curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYHOST, 0L); | 2103 | curl_easy_setopt (s5r->curl, |
2104 | CURLOPT_SSL_VERIFYHOST, | ||
2105 | 0L); | ||
1864 | } | 2106 | } |
1865 | else | 2107 | else |
1866 | { | 2108 | { |
1867 | curl_easy_setopt (s5r->curl, CURLOPT_USE_SSL, CURLUSESSL_NONE); | 2109 | curl_easy_setopt (s5r->curl, |
2110 | CURLOPT_USE_SSL, | ||
2111 | CURLUSESSL_NONE); | ||
1868 | } | 2112 | } |
1869 | 2113 | ||
1870 | if (CURLM_OK != | 2114 | if (CURLM_OK != |
@@ -1892,12 +2136,14 @@ create_response (void *cls, | |||
1892 | { | 2136 | { |
1893 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2137 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1894 | "Processing %u bytes UPLOAD\n", | 2138 | "Processing %u bytes UPLOAD\n", |
1895 | (unsigned int) *upload_data_size); | 2139 | (unsigned int) *upload_data_size); |
1896 | 2140 | ||
1897 | /* FIXME: This must be set or a header with Transfer-Encoding: chunked. Else | 2141 | /* FIXME: This must be set or a header with Transfer-Encoding: chunked. Else |
1898 | * upload callback is not called! | 2142 | * upload callback is not called! |
1899 | */ | 2143 | */ |
1900 | curl_easy_setopt (s5r->curl, CURLOPT_POSTFIELDSIZE, *upload_data_size); | 2144 | curl_easy_setopt (s5r->curl, |
2145 | CURLOPT_POSTFIELDSIZE, | ||
2146 | *upload_data_size); | ||
1901 | 2147 | ||
1902 | left = GNUNET_MIN (*upload_data_size, | 2148 | left = GNUNET_MIN (*upload_data_size, |
1903 | sizeof (s5r->io_buf) - s5r->io_len); | 2149 | sizeof (s5r->io_buf) - s5r->io_len); |
@@ -1907,8 +2153,12 @@ create_response (void *cls, | |||
1907 | s5r->io_len += left; | 2153 | s5r->io_len += left; |
1908 | *upload_data_size -= left; | 2154 | *upload_data_size -= left; |
1909 | GNUNET_assert (NULL != s5r->curl); | 2155 | GNUNET_assert (NULL != s5r->curl); |
1910 | curl_easy_pause (s5r->curl, | 2156 | if (GNUNET_YES == s5r->curl_paused) |
1911 | CURLPAUSE_CONT); | 2157 | { |
2158 | s5r->curl_paused = GNUNET_NO; | ||
2159 | curl_easy_pause (s5r->curl, | ||
2160 | CURLPAUSE_CONT); | ||
2161 | } | ||
1912 | return MHD_YES; | 2162 | return MHD_YES; |
1913 | } | 2163 | } |
1914 | if (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) | 2164 | if (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) |
@@ -2286,8 +2536,10 @@ load_file (const char* filename, | |||
2286 | uint64_t fsize; | 2536 | uint64_t fsize; |
2287 | 2537 | ||
2288 | if (GNUNET_OK != | 2538 | if (GNUNET_OK != |
2289 | GNUNET_DISK_file_size (filename, &fsize, | 2539 | GNUNET_DISK_file_size (filename, |
2290 | GNUNET_YES, GNUNET_YES)) | 2540 | &fsize, |
2541 | GNUNET_YES, | ||
2542 | GNUNET_YES)) | ||
2291 | return NULL; | 2543 | return NULL; |
2292 | if (fsize > MAX_PEM_SIZE) | 2544 | if (fsize > MAX_PEM_SIZE) |
2293 | return NULL; | 2545 | return NULL; |
@@ -2319,7 +2571,8 @@ load_key_from_file (gnutls_x509_privkey_t key, | |||
2319 | gnutls_datum_t key_data; | 2571 | gnutls_datum_t key_data; |
2320 | int ret; | 2572 | int ret; |
2321 | 2573 | ||
2322 | key_data.data = load_file (keyfile, &key_data.size); | 2574 | key_data.data = load_file (keyfile, |
2575 | &key_data.size); | ||
2323 | if (NULL == key_data.data) | 2576 | if (NULL == key_data.data) |
2324 | return GNUNET_SYSERR; | 2577 | return GNUNET_SYSERR; |
2325 | ret = gnutls_x509_privkey_import (key, &key_data, | 2578 | ret = gnutls_x509_privkey_import (key, &key_data, |
@@ -2349,15 +2602,18 @@ load_cert_from_file (gnutls_x509_crt_t crt, | |||
2349 | gnutls_datum_t cert_data; | 2602 | gnutls_datum_t cert_data; |
2350 | int ret; | 2603 | int ret; |
2351 | 2604 | ||
2352 | cert_data.data = load_file (certfile, &cert_data.size); | 2605 | cert_data.data = load_file (certfile, |
2606 | &cert_data.size); | ||
2353 | if (NULL == cert_data.data) | 2607 | if (NULL == cert_data.data) |
2354 | return GNUNET_SYSERR; | 2608 | return GNUNET_SYSERR; |
2355 | ret = gnutls_x509_crt_import (crt, &cert_data, | 2609 | ret = gnutls_x509_crt_import (crt, |
2610 | &cert_data, | ||
2356 | GNUTLS_X509_FMT_PEM); | 2611 | GNUTLS_X509_FMT_PEM); |
2357 | if (GNUTLS_E_SUCCESS != ret) | 2612 | if (GNUTLS_E_SUCCESS != ret) |
2358 | { | 2613 | { |
2359 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2614 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2360 | _("Unable to import certificate %s\n"), certfile); | 2615 | _("Unable to import certificate from `%s'\n"), |
2616 | certfile); | ||
2361 | } | 2617 | } |
2362 | GNUNET_free_non_null (cert_data.data); | 2618 | GNUNET_free_non_null (cert_data.data); |
2363 | return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK; | 2619 | return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK; |
@@ -2387,14 +2643,27 @@ generate_gns_certificate (const char *name) | |||
2387 | GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_init (&request)); | 2643 | GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_init (&request)); |
2388 | GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_key (request, proxy_ca.key)); | 2644 | GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_key (request, proxy_ca.key)); |
2389 | pgc = GNUNET_new (struct ProxyGNSCertificate); | 2645 | pgc = GNUNET_new (struct ProxyGNSCertificate); |
2390 | gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_COUNTRY_NAME, | 2646 | gnutls_x509_crt_set_dn_by_oid (request, |
2391 | 0, "ZZ", 2); | 2647 | GNUTLS_OID_X520_COUNTRY_NAME, |
2392 | gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_ORGANIZATION_NAME, | 2648 | 0, |
2393 | 0, "GNU Name System", 4); | 2649 | "ZZ", |
2394 | gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_COMMON_NAME, | 2650 | strlen ("ZZ")); |
2395 | 0, name, strlen (name)); | 2651 | gnutls_x509_crt_set_dn_by_oid (request, |
2396 | GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_version (request, 3)); | 2652 | GNUTLS_OID_X520_ORGANIZATION_NAME, |
2397 | gnutls_rnd (GNUTLS_RND_NONCE, &serial, sizeof (serial)); | 2653 | 0, |
2654 | "GNU Name System", | ||
2655 | strlen ("GNU Name System")); | ||
2656 | gnutls_x509_crt_set_dn_by_oid (request, | ||
2657 | GNUTLS_OID_X520_COMMON_NAME, | ||
2658 | 0, | ||
2659 | name, | ||
2660 | strlen (name)); | ||
2661 | GNUNET_break (GNUTLS_E_SUCCESS == | ||
2662 | gnutls_x509_crt_set_version (request, | ||
2663 | 3)); | ||
2664 | gnutls_rnd (GNUTLS_RND_NONCE, | ||
2665 | &serial, | ||
2666 | sizeof (serial)); | ||
2398 | gnutls_x509_crt_set_serial (request, | 2667 | gnutls_x509_crt_set_serial (request, |
2399 | &serial, | 2668 | &serial, |
2400 | sizeof (serial)); | 2669 | sizeof (serial)); |
@@ -2408,15 +2677,21 @@ generate_gns_certificate (const char *name) | |||
2408 | etime = mktime (tm_data); | 2677 | etime = mktime (tm_data); |
2409 | gnutls_x509_crt_set_expiration_time (request, | 2678 | gnutls_x509_crt_set_expiration_time (request, |
2410 | etime); | 2679 | etime); |
2411 | gnutls_x509_crt_sign (request, | 2680 | gnutls_x509_crt_sign2 (request, |
2412 | proxy_ca.cert, | 2681 | proxy_ca.cert, |
2413 | proxy_ca.key); | 2682 | proxy_ca.key, |
2683 | GNUTLS_DIG_SHA512, | ||
2684 | 0); | ||
2414 | key_buf_size = sizeof (pgc->key); | 2685 | key_buf_size = sizeof (pgc->key); |
2415 | cert_buf_size = sizeof (pgc->cert); | 2686 | cert_buf_size = sizeof (pgc->cert); |
2416 | gnutls_x509_crt_export (request, GNUTLS_X509_FMT_PEM, | 2687 | gnutls_x509_crt_export (request, |
2417 | pgc->cert, &cert_buf_size); | 2688 | GNUTLS_X509_FMT_PEM, |
2418 | gnutls_x509_privkey_export (proxy_ca.key, GNUTLS_X509_FMT_PEM, | 2689 | pgc->cert, |
2419 | pgc->key, &key_buf_size); | 2690 | &cert_buf_size); |
2691 | gnutls_x509_privkey_export (proxy_ca.key, | ||
2692 | GNUTLS_X509_FMT_PEM, | ||
2693 | pgc->key, | ||
2694 | &key_buf_size); | ||
2420 | gnutls_x509_crt_deinit (request); | 2695 | gnutls_x509_crt_deinit (request); |
2421 | return pgc; | 2696 | return pgc; |
2422 | } | 2697 | } |
@@ -2755,8 +3030,10 @@ handle_gns_result (void *cls, | |||
2755 | } | 3030 | } |
2756 | if (GNUNET_YES == got_ip) | 3031 | if (GNUNET_YES == got_ip) |
2757 | break; | 3032 | break; |
3033 | if (GNUNET_YES == disable_v6) | ||
3034 | break; | ||
2758 | if (GNUNET_OK != | 3035 | if (GNUNET_OK != |
2759 | GNUNET_NETWORK_test_pf (PF_INET)) | 3036 | GNUNET_NETWORK_test_pf (PF_INET6)) |
2760 | break; | 3037 | break; |
2761 | /* FIXME: allow user to disable IPv6 per configuration option... */ | 3038 | /* FIXME: allow user to disable IPv6 per configuration option... */ |
2762 | got_ip = GNUNET_YES; | 3039 | got_ip = GNUNET_YES; |
@@ -2857,7 +3134,8 @@ do_s5r_read (void *cls) | |||
2857 | s5r->rtask = NULL; | 3134 | s5r->rtask = NULL; |
2858 | tc = GNUNET_SCHEDULER_get_task_context (); | 3135 | tc = GNUNET_SCHEDULER_get_task_context (); |
2859 | if ( (NULL != tc->read_ready) && | 3136 | if ( (NULL != tc->read_ready) && |
2860 | (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->sock)) ) | 3137 | (GNUNET_NETWORK_fdset_isset (tc->read_ready, |
3138 | s5r->sock)) ) | ||
2861 | { | 3139 | { |
2862 | rlen = GNUNET_NETWORK_socket_recv (s5r->sock, | 3140 | rlen = GNUNET_NETWORK_socket_recv (s5r->sock, |
2863 | &s5r->rbuf[s5r->rbuf_len], | 3141 | &s5r->rbuf[s5r->rbuf_len], |
@@ -2983,7 +3261,8 @@ do_s5r_read (void *cls) | |||
2983 | s5r->domain = GNUNET_strndup (dom_name, | 3261 | s5r->domain = GNUNET_strndup (dom_name, |
2984 | *dom_len); | 3262 | *dom_len); |
2985 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3263 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2986 | "Requested connection is to %s:%d\n", | 3264 | "Requested connection is to http%s://%s:%d\n", |
3265 | (HTTPS_PORT == s5r->port) ? "s" : "", | ||
2987 | s5r->domain, | 3266 | s5r->domain, |
2988 | ntohs (*port)); | 3267 | ntohs (*port)); |
2989 | s5r->state = SOCKS5_RESOLVING; | 3268 | s5r->state = SOCKS5_RESOLVING; |
@@ -3054,17 +3333,22 @@ do_accept (void *cls) | |||
3054 | if (lsock == lsock4) | 3333 | if (lsock == lsock4) |
3055 | ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | 3334 | ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, |
3056 | lsock, | 3335 | lsock, |
3057 | &do_accept, lsock); | 3336 | &do_accept, |
3337 | lsock); | ||
3058 | else if (lsock == lsock6) | 3338 | else if (lsock == lsock6) |
3059 | ltask6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | 3339 | ltask6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, |
3060 | lsock, | 3340 | lsock, |
3061 | &do_accept, lsock); | 3341 | &do_accept, |
3342 | lsock); | ||
3062 | else | 3343 | else |
3063 | GNUNET_assert (0); | 3344 | GNUNET_assert (0); |
3064 | s = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL); | 3345 | s = GNUNET_NETWORK_socket_accept (lsock, |
3346 | NULL, | ||
3347 | NULL); | ||
3065 | if (NULL == s) | 3348 | if (NULL == s) |
3066 | { | 3349 | { |
3067 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "accept"); | 3350 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, |
3351 | "accept"); | ||
3068 | return; | 3352 | return; |
3069 | } | 3353 | } |
3070 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3354 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -3077,7 +3361,8 @@ do_accept (void *cls) | |||
3077 | s5r->state = SOCKS5_INIT; | 3361 | s5r->state = SOCKS5_INIT; |
3078 | s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | 3362 | s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, |
3079 | s5r->sock, | 3363 | s5r->sock, |
3080 | &do_s5r_read, s5r); | 3364 | &do_s5r_read, |
3365 | s5r); | ||
3081 | } | 3366 | } |
3082 | 3367 | ||
3083 | 3368 | ||
@@ -3174,7 +3459,8 @@ bind_v4 () | |||
3174 | if (NULL == ls) | 3459 | if (NULL == ls) |
3175 | return NULL; | 3460 | return NULL; |
3176 | if (GNUNET_OK != | 3461 | if (GNUNET_OK != |
3177 | GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4, | 3462 | GNUNET_NETWORK_socket_bind (ls, |
3463 | (const struct sockaddr *) &sa4, | ||
3178 | sizeof (sa4))) | 3464 | sizeof (sa4))) |
3179 | { | 3465 | { |
3180 | eno = errno; | 3466 | eno = errno; |
@@ -3210,7 +3496,8 @@ bind_v6 () | |||
3210 | if (NULL == ls) | 3496 | if (NULL == ls) |
3211 | return NULL; | 3497 | return NULL; |
3212 | if (GNUNET_OK != | 3498 | if (GNUNET_OK != |
3213 | GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa6, | 3499 | GNUNET_NETWORK_socket_bind (ls, |
3500 | (const struct sockaddr *) &sa6, | ||
3214 | sizeof (sa6))) | 3501 | sizeof (sa6))) |
3215 | { | 3502 | { |
3216 | eno = errno; | 3503 | eno = errno; |
@@ -3265,7 +3552,8 @@ run (void *cls, | |||
3265 | cafile = cafile_cfg; | 3552 | cafile = cafile_cfg; |
3266 | } | 3553 | } |
3267 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3554 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
3268 | "Using %s as CA\n", cafile); | 3555 | "Using `%s' as CA\n", |
3556 | cafile); | ||
3269 | 3557 | ||
3270 | gnutls_global_init (); | 3558 | gnutls_global_init (); |
3271 | gnutls_x509_crt_init (&proxy_ca.cert); | 3559 | gnutls_x509_crt_init (&proxy_ca.cert); |
@@ -3365,8 +3653,8 @@ run (void *cls, | |||
3365 | return; | 3653 | return; |
3366 | } | 3654 | } |
3367 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3655 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
3368 | "Proxy listens on port %llu\n", | 3656 | "Proxy listens on port %u\n", |
3369 | port); | 3657 | (unsigned int) port); |
3370 | 3658 | ||
3371 | /* start MHD daemon for HTTP */ | 3659 | /* start MHD daemon for HTTP */ |
3372 | hd = GNUNET_new (struct MhdHttpList); | 3660 | hd = GNUNET_new (struct MhdHttpList); |
@@ -3400,19 +3688,24 @@ run (void *cls, | |||
3400 | * @return 0 ok, 1 on error | 3688 | * @return 0 ok, 1 on error |
3401 | */ | 3689 | */ |
3402 | int | 3690 | int |
3403 | main (int argc, char *const *argv) | 3691 | main (int argc, |
3692 | char *const *argv) | ||
3404 | { | 3693 | { |
3405 | struct GNUNET_GETOPT_CommandLineOption options[] = { | 3694 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
3406 | GNUNET_GETOPT_option_ulong ('p', | 3695 | GNUNET_GETOPT_option_uint16 ('p', |
3407 | "port", | 3696 | "port", |
3408 | NULL, | 3697 | NULL, |
3409 | gettext_noop ("listen on specified port (default: 7777)"), | 3698 | gettext_noop ("listen on specified port (default: 7777)"), |
3410 | &port), | 3699 | &port), |
3411 | GNUNET_GETOPT_option_string ('a', | 3700 | GNUNET_GETOPT_option_string ('a', |
3412 | "authority", | 3701 | "authority", |
3413 | NULL, | 3702 | NULL, |
3414 | gettext_noop ("pem file to use as CA"), | 3703 | gettext_noop ("pem file to use as CA"), |
3415 | &cafile_opt), | 3704 | &cafile_opt), |
3705 | GNUNET_GETOPT_option_flag ('6', | ||
3706 | "disable-ivp6", | ||
3707 | gettext_noop ("disable use of IPv6"), | ||
3708 | &disable_v6), | ||
3416 | 3709 | ||
3417 | GNUNET_GETOPT_OPTION_END | 3710 | GNUNET_GETOPT_OPTION_END |
3418 | }; | 3711 | }; |
@@ -3421,8 +3714,9 @@ main (int argc, char *const *argv) | |||
3421 | "</head><body>cURL fail</body></html>"; | 3714 | "</head><body>cURL fail</body></html>"; |
3422 | int ret; | 3715 | int ret; |
3423 | 3716 | ||
3424 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, | 3717 | if (GNUNET_OK != |
3425 | &argc, &argv)) | 3718 | GNUNET_STRINGS_get_utf8_args (argc, argv, |
3719 | &argc, &argv)) | ||
3426 | return 2; | 3720 | return 2; |
3427 | GNUNET_log_setup ("gnunet-gns-proxy", | 3721 | GNUNET_log_setup ("gnunet-gns-proxy", |
3428 | "WARNING", | 3722 | "WARNING", |