/*
This file is part of GNUnet.
- Copyright (C) 2009-2013 Jeffrey Burdges (and other contributing authors)
+ 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
#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);
}
- printf("Erronious socks.c transmit_ready() callback on step %u with reason %u.\n",
- ih->step, reason );
- /* if (reason == 48) register_sender (ih); */
- /* GNUNET_break(0); */
return 0;
- } else
- printf("Good socks.c transmit_ready() callback on step %u with reason %u.\n",
- ih->step, GNUNET_SCHEDULER_get_reason () );
+ }
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++];
+ 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(b, buf, l);
+ GNUNET_memcpy(buf, b, l);
register_reciever (ih, register_reciever_wants(ih));
return l;
}
{
struct GNUNET_TIME_Relative timeout = GNUNET_TIME_UNIT_MINUTES;
- GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
+ GNUNET_assert (SOCKS5_step_done > ih->step);
+ GNUNET_assert (ih->step >= 0);
if (0 == ih->step)
timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3);
unsigned char * b = ih->outstep[ih->step];
unsigned char * e = ih->outstep[ih->step+1];
GNUNET_assert (ih->outbuf <= b && b < e && e < &ih->outbuf[1024]);
- printf("register_sender on step %u for %u bytes.\n", ih->step, (unsigned)(e - b) );
ih->th = GNUNET_CONNECTION_notify_transmit_ready (ih->socks5_connection,
e - b,
timeout,
/**
* 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 = "";
ih->outstep[SOCKS5_step_cmd] = b;
+ ih->inend = ih->instart = ih->inbuf;
+
return ih;
}
/**
- * 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)
{
if (GNUNET_OK !=
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) ||
service_name,port1,host1);
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);