This file is part of GNUnet.
Copyright (C) 2009-2013 GNUnet e.V.
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
+ SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
#include "gnunet_util_lib.h"
-#define LOG(kind,...) GNUNET_log_from (kind, "socks", __VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "util-socks", __VA_ARGS__)
-#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "socks", syscall)
+#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-socks", syscall)
/* SOCKS5 authentication methods */
* @param s string to encode
* @return pointer to the end of the encoded string in the buffer
*/
-unsigned char * SOCK5_proto_string(unsigned char * b, const char * s)
+unsigned char *
+SOCK5_proto_string(unsigned char * b,
+ const char * s)
{
size_t l = strlen(s);
- if (l>255) {
+
+ if (l > 255)
+ {
LOG (GNUNET_ERROR_TYPE_WARNING,
"SOCKS5 cannot handle hostnames, usernames, or passwords over 255 bytes, truncating.\n");
l=255;
}
- *(b++) = (unsigned char)l;
- strncpy((char *)b,s,l);
+ *(b++) = (unsigned char) l;
+ strncpy ((char *)b, s, l);
return b+l;
}
/**
* State of the SOCKS5 handshake.
*/
-struct GNUNET_SOCKS_Handshake
+struct GNUNET_SOCKS_Handshake
{
/**
struct GNUNET_CONNECTION_TransmitHandle *th;
/**
- * Our stage in the SOCKS5 handshake
+ * Our stage in the SOCKS5 handshake
*/
int step;
GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
switch (ih->step) {
case SOCKS5_step_greet: /* SOCKS5 server's greeting */
- if (b[0] != 5)
+ if (b[0] != 5)
{
LOG (GNUNET_ERROR_TYPE_ERROR,
"Not a SOCKS5 server\n");
b += 2;
break;
case SOCKS5_step_cmd: /* SOCKS5 server's responce to command */
- if (b[0] != 5)
+ if (b[0] != 5)
{
LOG (GNUNET_ERROR_TYPE_ERROR,
"SOCKS5 protocol error\n");
ih->instart = b;
SOCKS5_handshake_done (ih);
return;
- case SOCKS5_step_done:
+ case SOCKS5_step_done:
GNUNET_assert (0);
}
ih->instart = b;
- /* Do not reschedule the sender unless we're done reading.
+ /* Do not reschedule the sender unless we're done reading.
* I imagine this lets us avoid ever cancelling the transmit handle. */
register_sender (ih);
}
* @param handler_cls closure for @a handler
*/
void
-reciever (void *cls,
+reciever (void *cls,
const void *buf, size_t available,
const struct sockaddr * addr,
socklen_t addrlen, int errCode)
{
struct GNUNET_SOCKS_Handshake * ih = cls;
GNUNET_assert (&ih->inend[available] < &ih->inbuf[1024]);
- memcpy(ih->inend, buf, available);
+ GNUNET_memcpy(ih->inend, buf, available);
ih->inend += available;
SOCKS5_handshake_step (ih);
}
* @param buf where the callee should write the message
* @return number of bytes written to @a buf
*/
-
size_t
-transmit_ready (void *cls,
+transmit_ready (void *cls,
size_t size,
void *buf)
{
* GNUNET_CONNECTION_notify_transmit_ready() can schedule :
* transmit_timeout() - DNS still working
* connect_error() - DNS done but no socket?
- * transmit_ready() - scheduler shutdown or timeout, or signal_transmit_error()
+ * transmit_ready() - scheduler shutdown or timeout, or signal_transmit_error()
* We'd need to dig into the scheduler to guess at the reason, as
* connection.c tells us nothing itself, but mostly its timouts.
* Initially, we'll simply ignore this and leave massive timeouts, but
* maybe that should change for error handling pruposes. It appears that
* successful operations, including DNS resolution, do not use this. */
- if (NULL==buf)
+ if (NULL == buf)
{
- enum GNUNET_SCHEDULER_Reason reason = GNUNET_SCHEDULER_get_reason ();
- if (0 != (reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return 0;
- if (0 != (reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) {
- if (0==ih->step) {
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "Timeout contacting SOCKS server, retrying indefinitely, but probably hopeless.\n");
- register_sender (ih);
- } else {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- "Timeout during mid SOCKS handshake (step %u), probably not a SOCKS server.\n",
- ih->step);
- GNUNET_break (0);
- }
- return 0;
+ if (0 == ih->step)
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Timeout contacting SOCKS server, retrying indefinitely, but probably hopeless.\n");
+ register_sender (ih);
+ }
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Timeout during mid SOCKS handshake (step %u), probably not a SOCKS server.\n",
+ ih->step);
+ GNUNET_break (0);
}
- /* if (reason == 48) register_sender (ih); */
- /* GNUNET_break(0); */
return 0;
}
- GNUNET_assert (1024 >= size && size > 0);
- GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
+ GNUNET_assert ( (1024 >= size) && (size > 0) );
+ GNUNET_assert ( (SOCKS5_step_done > ih->step) && (ih->step >= 0) );
unsigned char * b = ih->outstep[ih->step];
unsigned char * e = ih->outstep[ih->step+1];
GNUNET_assert (e <= &ih->outbuf[1024]);
- unsigned l = e - b;
- GNUNET_assert (size >= l && l >= 0);
- memcpy(buf, b, l);
- register_reciever (ih, register_reciever_wants(ih));
+ unsigned int l = e - b;
+ GNUNET_assert (size >= l);
+ GNUNET_memcpy (buf,
+ b,
+ l);
+ register_reciever (ih,
+ register_reciever_wants (ih));
return l;
}
/**
* Initialize a SOCKS5 handshake for authentication via username and
* password. Tor uses SOCKS username and password authentication to assign
- * programs unique circuits.
+ * programs unique circuits.
*
* @param user username for the proxy
* @param pass password for the proxy
unsigned char * n = b++;
*n = 1; /* Number of authentication methods */
/* We support no authentication even when requesting authentication,
- * but this appears harmless, given the way that Tor uses authentication.
+ * but this appears harmless, given the way that Tor uses authentication.
* And some SOCKS5 servers might require this. */
*(b++) = SOCKS5_AUTH_NOAUTH;
if (NULL != user) {
/* There is no apperent reason to support authentication methods beyond
* username and password since afaik Tor does not support them. */
- /* We authenticate with an empty username and password if the server demands
+ /* We authenticate with an empty username and password if the server demands
* them but we do not have any. */
if (user == NULL)
user = "";
/**
- * Initialize a SOCKS5 handshake without authentication, thereby possibly
+ * Initialize a SOCKS5 handshake without authentication, thereby possibly
* sharing a Tor circuit with another process.
*
* @return Valid SOCKS5 hanbdshake handle
/**
* Build request that the SOCKS5 proxy open a TCP/IP stream to the given host
- * and port.
+ * and port.
*
* @param ih SOCKS5 handshake
- * @param hostname
- * @param port
+ * @param hostname
+ * @param port
*/
void
GNUNET_SOCKS_set_handshake_destination (struct GNUNET_SOCKS_Handshake *ih,
/* Specify destination */
if (1 == inet_pton(AF_INET,host,&ia.in4)) {
*(b++)= 1; /* IPv4 */
- memcpy (b, &ia.in4, sizeof(struct in_addr));
+ GNUNET_memcpy (b, &ia.in4, sizeof(struct in_addr));
b += sizeof(struct in_addr); /* 4 */
} else if (1 == inet_pton(AF_INET6,host,&ia.in6)) {
*(b++)= 4; /* IPv6 */
- memcpy (b, &ia.in6, sizeof(struct in6_addr));
+ GNUNET_memcpy (b, &ia.in6, sizeof(struct in6_addr));
b += sizeof(struct in6_addr); /* 16 */
} else {
*(b++)= 3; /* hostname */
* @param c open unused connection, consumed here.
* @return Connection handle that becomes usable when the SOCKS5 handshake completes.
*/
-struct GNUNET_CONNECTION_Handle *
+struct GNUNET_CONNECTION_Handle *
GNUNET_SOCKS_run_handshake(struct GNUNET_SOCKS_Handshake *ih,
struct GNUNET_CONNECTION_Handle *c)
{
*/
struct GNUNET_CONNECTION_Handle *
GNUNET_SOCKS_do_connect (const char *service_name,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct GNUNET_SOCKS_Handshake *ih;
struct GNUNET_CONNECTION_Handle *socks5; /* *proxied */
- char *host0,*host1,*user,*pass;
- unsigned long long port0,port1;
-
- if (GNUNET_YES != GNUNET_SOCKS_check_service (service_name, cfg))
+ char *host0;
+ char *host1;
+ char *user;
+ char *pass;
+ unsigned long long port0;
+ unsigned long long port1;
+
+ if (GNUNET_YES !=
+ GNUNET_SOCKS_check_service (service_name, cfg))
return NULL;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "SOCKSPORT", &port0))
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ service_name,
+ "SOCKSPORT",
+ &port0))
port0 = 9050;
- /* A typical Tor client should usually try port 9150 for the TBB too, but
- * GUNNet can probably assume a system Tor instalation. */
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "SOCKSHOST", &host0))
- host0 = "127.0.0.1";
+ /* A typical Tor client should usually try port 9150 for the TBB too, but
+ * GNUnet can probably assume a system Tor installation. */
if (port0 > 65535 || port0 <= 0)
{
LOG (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Attempting to use invalid port %d as SOCKS proxy for service `%s'.\n"),
- port0,service_name);
+ _("Attempting to use invalid port %d as SOCKS proxy for service `%s'.\n"),
+ port0,
+ service_name);
return NULL;
}
-
- if ((GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port1))
- || (port1 > 65535) || (port1 <= 0) ||
+ if ( (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ service_name,
+ "PORT",
+ &port1)) ||
+ (port1 > 65535) ||
+ (port1 <= 0) ||
(GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME", &host1)))
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ service_name,
+ "HOSTNAME",
+ &host1)))
{
LOG (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Attempting to proxy service `%s' to invalid port %d or hostname `%s'.\n"),
- service_name,port1,host1);
+ _("Attempting to proxy service `%s' to invalid port %d or hostname.\n"),
+ service_name,
+ port1);
return NULL;
}
-
- socks5 = GNUNET_CONNECTION_create_from_connect (cfg, host0, port0);
- GNUNET_free (host0);
+ /* Appeared to still work after host0 corrupted, so either test case is broken, or
+ this whole routine is not being called. */
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "SOCKSHOST", &host0))
+ host0 = NULL;
+ socks5 = GNUNET_CONNECTION_create_from_connect (cfg,
+ (host0 != NULL)
+ ? host0
+ :"127.0.0.1",
+ port0);
+ GNUNET_free_non_null (host0);
/* Sets to NULL if they do not exist */
- GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "SOCKSUSER", &user);
- GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "SOCKSPASS", &pass);
+ (void) GNUNET_CONFIGURATION_get_value_string (cfg,
+ service_name,
+ "SOCKSUSER",
+ &user);
+ (void) GNUNET_CONFIGURATION_get_value_string (cfg,
+ service_name,
+ "SOCKSPASS",
+ &pass);
ih = GNUNET_SOCKS_init_handshake(user,pass);
- if (NULL != user) GNUNET_free (user);
- if (NULL != pass) GNUNET_free (pass);
+ GNUNET_free_non_null (user);
+ GNUNET_free_non_null (pass);
- GNUNET_SOCKS_set_handshake_destination (ih,host1,port1);
+ GNUNET_SOCKS_set_handshake_destination (ih,
+ host1,
+ port1);
GNUNET_free (host1);
-
- return GNUNET_SOCKS_run_handshake(ih,socks5);
+ return GNUNET_SOCKS_run_handshake (ih,
+ socks5);
}
/* socks.c */