From 4c2a06deba76e8be4098059b860e76db3cf4ae7e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 27 Jun 2019 12:14:19 +0200 Subject: [PATCH] memcpy fits better --- src/util/socks.c | 393 ++++++++++++++++++++++++----------------------- 1 file changed, 203 insertions(+), 190 deletions(-) diff --git a/src/util/socks.c b/src/util/socks.c index 9e974e6bb..0e8583afa 100644 --- a/src/util/socks.c +++ b/src/util/socks.c @@ -29,9 +29,10 @@ #include "gnunet_util_lib.h" -#define LOG(kind,...) GNUNET_log_from (kind, "util-socks", __VA_ARGS__) +#define LOG(kind, ...) GNUNET_log_from (kind, "util-socks", __VA_ARGS__) -#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-socks", syscall) +#define LOG_STRERROR(kind, syscall) \ + GNUNET_log_from_strerror (kind, "util-socks", syscall) /* SOCKS5 authentication methods */ @@ -56,20 +57,33 @@ #define SOCKS5_REP_ANOTSUP 0x08 /* Address not supported */ #define SOCKS5_REP_INVADDR 0x09 /* Inalid address */ -const char * SOCKS5_REP_names(int rep) +const char * +SOCKS5_REP_names (int rep) { - switch (rep) { - case SOCKS5_REP_SUCCEEDED: return "succeeded"; - case SOCKS5_REP_FAIL: return "general SOCKS server failure"; - case SOCKS5_REP_NALLOWED: return "connection not allowed by ruleset"; - case SOCKS5_REP_NUNREACH: return "Network unreachable"; - case SOCKS5_REP_HUNREACH: return "Host unreachable"; - case SOCKS5_REP_REFUSED: return "connection refused"; - case SOCKS5_REP_EXPIRED: return "TTL expired"; - case SOCKS5_REP_CNOTSUP: return "Command not supported"; - case SOCKS5_REP_ANOTSUP: return "Address not supported"; - case SOCKS5_REP_INVADDR: return "Invalid address"; - default: return NULL; + switch (rep) + { + case SOCKS5_REP_SUCCEEDED: + return "succeeded"; + case SOCKS5_REP_FAIL: + return "general SOCKS server failure"; + case SOCKS5_REP_NALLOWED: + return "connection not allowed by ruleset"; + case SOCKS5_REP_NUNREACH: + return "Network unreachable"; + case SOCKS5_REP_HUNREACH: + return "Host unreachable"; + case SOCKS5_REP_REFUSED: + return "connection refused"; + case SOCKS5_REP_EXPIRED: + return "TTL expired"; + case SOCKS5_REP_CNOTSUP: + return "Command not supported"; + case SOCKS5_REP_ANOTSUP: + return "Address not supported"; + case SOCKS5_REP_INVADDR: + return "Invalid address"; + default: + return NULL; } }; @@ -84,30 +98,26 @@ const char * SOCKS5_REP_names(int rep) * @return pointer to the end of the encoded string in the buffer */ unsigned char * -SOCK5_proto_string(unsigned char * b, - const char * s) +SOCK5_proto_string (unsigned char *b, const char *s) { - size_t l = strlen(s); + size_t l = strlen (s); if (l > 255) { LOG (GNUNET_ERROR_TYPE_WARNING, "SOCKS5 cannot handle hostnames, usernames, or passwords over 255 bytes, truncating.\n"); - l=255; + l = 255; } *(b++) = (unsigned char) l; - /* - * intentionally use strncpy (trailing zero byte must be stripped in b) - */ - strncpy ((char*)b, s, l); - return b+l; + memcpy (b, s, l); + return b + l; } #define SOCKS5_step_greet 0 -#define SOCKS5_step_auth 1 -#define SOCKS5_step_cmd 2 -#define SOCKS5_step_done 3 +#define SOCKS5_step_auth 1 +#define SOCKS5_step_cmd 2 +#define SOCKS5_step_done 3 /** * State of the SOCKS5 handshake. @@ -143,7 +153,7 @@ struct GNUNET_SOCKS_Handshake /** * Pointers delineating protoocol steps in the outbut buffer */ - unsigned char * (outstep[4]); + unsigned char *(outstep[4]); /** * SOCKS5 handshake input buffer @@ -153,8 +163,8 @@ struct GNUNET_SOCKS_Handshake /** * Pointers delimiting the current step in the input buffer */ - unsigned char * instart; - unsigned char * inend; + unsigned char *instart; + unsigned char *inend; }; @@ -163,7 +173,7 @@ struct GNUNET_SOCKS_Handshake void register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want); - /* In fact, the client sends first rule in GNUNet suggests one could take +/* In fact, the client sends first rule in GNUNet suggests one could take * large mac read sizes without fear of screwing up the proxied protocol, * but we make a proper SOCKS5 client. */ #define register_reciever_wants(ih) ((SOCKS5_step_cmd == ih->step) ? 10 : 2) @@ -181,7 +191,7 @@ register_sender (struct GNUNET_SOCKS_Handshake *ih); * @return Connection handle that becomes usable when the handshake completes. */ void -SOCKS5_handshake_done(struct GNUNET_SOCKS_Handshake *ih) +SOCKS5_handshake_done (struct GNUNET_SOCKS_Handshake *ih) { GNUNET_CONNECTION_acivate_proxied (ih->target_connection); } @@ -195,91 +205,93 @@ SOCKS5_handshake_done(struct GNUNET_SOCKS_Handshake *ih) void SOCKS5_handshake_step (struct GNUNET_SOCKS_Handshake *ih) { - unsigned char * b = ih->instart; + unsigned char *b = ih->instart; size_t available = ih->inend - b; - int want = register_reciever_wants(ih); - if (available < want) { + int want = register_reciever_wants (ih); + if (available < want) + { register_reciever (ih, want - available); return; } 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) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Not a SOCKS5 server\n"); - GNUNET_assert (0); - } - switch (b[1]) { - case SOCKS5_AUTH_NOAUTH: - ih->step=SOCKS5_step_cmd; /* no authentication to do */ - break; - case SOCKS5_AUTH_USERPASS: - ih->step=SOCKS5_step_auth; - break; - case SOCKS5_AUTH_REJECT: - LOG (GNUNET_ERROR_TYPE_ERROR, - "No authentication method accepted\n"); - return; - default: - LOG (GNUNET_ERROR_TYPE_ERROR, - "Not a SOCKS5 server / Nonsensical authentication\n"); - return; - } - b += 2; + switch (ih->step) + { + case SOCKS5_step_greet: /* SOCKS5 server's greeting */ + if (b[0] != 5) + { + LOG (GNUNET_ERROR_TYPE_ERROR, "Not a SOCKS5 server\n"); + GNUNET_assert (0); + } + switch (b[1]) + { + case SOCKS5_AUTH_NOAUTH: + ih->step = SOCKS5_step_cmd; /* no authentication to do */ break; - case SOCKS5_step_auth: /* SOCKS5 server's responce to authentication */ - if (b[1] != 0) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "SOCKS5 authentication failed\n"); - GNUNET_assert (0); - } - ih->step=SOCKS5_step_cmd; - b += 2; + case SOCKS5_AUTH_USERPASS: + ih->step = SOCKS5_step_auth; break; - case SOCKS5_step_cmd: /* SOCKS5 server's responce to command */ - if (b[0] != 5) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "SOCKS5 protocol error\n"); - GNUNET_assert (0); - } - if (0 != b[1]) { - LOG (GNUNET_ERROR_TYPE_ERROR, - "SOCKS5 connection error : %s\n", - SOCKS5_REP_names(b[1])); - return; - } - b += 3; - /* There is no reason to verify host and port afaik. */ - switch (*(b++)) { - case 1: /* IPv4 */ - b += sizeof(struct in_addr); /* 4 */ - break; - case 4: /* IPv6 */ - b += sizeof(struct in6_addr); /* 16 */ - break; - case 3: /* hostname */ - b += *b; - break; - } - b += 2; /* port */ - if (b > ih->inend) { - register_reciever (ih, b - ih->inend); - return; - } - ih->step = SOCKS5_step_done; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "SOCKS5 server : %s\n", - SOCKS5_REP_names(b[1])); - ih->instart = b; - SOCKS5_handshake_done (ih); + case SOCKS5_AUTH_REJECT: + LOG (GNUNET_ERROR_TYPE_ERROR, "No authentication method accepted\n"); return; - case SOCKS5_step_done: + default: + LOG (GNUNET_ERROR_TYPE_ERROR, + "Not a SOCKS5 server / Nonsensical authentication\n"); + return; + } + b += 2; + break; + case SOCKS5_step_auth: /* SOCKS5 server's responce to authentication */ + if (b[1] != 0) + { + LOG (GNUNET_ERROR_TYPE_ERROR, "SOCKS5 authentication failed\n"); GNUNET_assert (0); + } + ih->step = SOCKS5_step_cmd; + b += 2; + break; + case SOCKS5_step_cmd: /* SOCKS5 server's responce to command */ + if (b[0] != 5) + { + LOG (GNUNET_ERROR_TYPE_ERROR, "SOCKS5 protocol error\n"); + GNUNET_assert (0); + } + if (0 != b[1]) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "SOCKS5 connection error : %s\n", + SOCKS5_REP_names (b[1])); + return; + } + b += 3; + /* There is no reason to verify host and port afaik. */ + switch (*(b++)) + { + case 1: /* IPv4 */ + b += sizeof (struct in_addr); /* 4 */ + break; + case 4: /* IPv6 */ + b += sizeof (struct in6_addr); /* 16 */ + break; + case 3: /* hostname */ + b += *b; + break; + } + b += 2; /* port */ + if (b > ih->inend) + { + register_reciever (ih, b - ih->inend); + return; + } + ih->step = SOCKS5_step_done; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "SOCKS5 server : %s\n", + SOCKS5_REP_names (b[1])); + ih->instart = b; + SOCKS5_handshake_done (ih); + return; + case SOCKS5_step_done: + GNUNET_assert (0); } ih->instart = b; /* Do not reschedule the sender unless we're done reading. @@ -297,13 +309,15 @@ SOCKS5_handshake_step (struct GNUNET_SOCKS_Handshake *ih) */ void reciever (void *cls, - const void *buf, size_t available, - const struct sockaddr * addr, - socklen_t addrlen, int errCode) + const void *buf, + size_t available, + const struct sockaddr *addr, + socklen_t addrlen, + int errCode) { - struct GNUNET_SOCKS_Handshake * ih = cls; + struct GNUNET_SOCKS_Handshake *ih = cls; GNUNET_assert (&ih->inend[available] < &ih->inbuf[1024]); - GNUNET_memcpy(ih->inend, buf, available); + GNUNET_memcpy (ih->inend, buf, available); ih->inend += available; SOCKS5_handshake_step (ih); } @@ -336,11 +350,9 @@ register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want) * @return number of bytes written to @a buf */ size_t -transmit_ready (void *cls, - size_t size, - void *buf) +transmit_ready (void *cls, size_t size, void *buf) { - struct GNUNET_SOCKS_Handshake * ih = cls; + struct GNUNET_SOCKS_Handshake *ih = cls; /* connection.c has many routines that call us with buf == NULL : * signal_transmit_error() - DNS, etc. active @@ -362,31 +374,28 @@ transmit_ready (void *cls, if (0 == ih->step) { LOG (GNUNET_ERROR_TYPE_WARNING, - "Timeout contacting SOCKS server, retrying indefinitely, but probably hopeless.\n"); + "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); + "Timeout during mid SOCKS handshake (step %u), probably not a SOCKS server.\n", + ih->step); GNUNET_break (0); } return 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 ((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 int l = e - b; GNUNET_assert (size >= l); - GNUNET_memcpy (buf, - b, - l); - register_reciever (ih, - register_reciever_wants (ih)); + GNUNET_memcpy (buf, b, l); + register_reciever (ih, register_reciever_wants (ih)); return l; } @@ -407,8 +416,8 @@ register_sender (struct GNUNET_SOCKS_Handshake *ih) 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]; + 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]); ih->th = GNUNET_CONNECTION_notify_transmit_ready (ih->socks5_connection, e - b, @@ -431,18 +440,20 @@ register_sender (struct GNUNET_SOCKS_Handshake *ih) struct GNUNET_SOCKS_Handshake * GNUNET_SOCKS_init_handshake (const char *user, const char *pass) { - struct GNUNET_SOCKS_Handshake *ih = GNUNET_new (struct GNUNET_SOCKS_Handshake); - unsigned char * b = ih->outbuf; + struct GNUNET_SOCKS_Handshake *ih = + GNUNET_new (struct GNUNET_SOCKS_Handshake); + unsigned char *b = ih->outbuf; ih->outstep[SOCKS5_step_greet] = b; *(b++) = 5; /* SOCKS5 */ - unsigned char * n = b++; + 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. * And some SOCKS5 servers might require this. */ *(b++) = SOCKS5_AUTH_NOAUTH; - if (NULL != user) { + if (NULL != user) + { *(b++) = SOCKS5_AUTH_USERPASS; (*n)++; } @@ -458,8 +469,8 @@ GNUNET_SOCKS_init_handshake (const char *user, const char *pass) ih->outstep[SOCKS5_step_auth] = b; *(b++) = 1; /* subnegotiation ver.: 1 */ - b = SOCK5_proto_string(b,user); - b = SOCK5_proto_string(b,pass); + b = SOCK5_proto_string (b, user); + b = SOCK5_proto_string (b, pass); ih->outstep[SOCKS5_step_cmd] = b; @@ -478,7 +489,7 @@ GNUNET_SOCKS_init_handshake (const char *user, const char *pass) struct GNUNET_SOCKS_Handshake * GNUNET_SOCKS_init_handshake_noauth () { - return GNUNET_SOCKS_init_handshake (NULL,NULL); + return GNUNET_SOCKS_init_handshake (NULL, NULL); } @@ -492,34 +503,41 @@ GNUNET_SOCKS_init_handshake_noauth () */ void GNUNET_SOCKS_set_handshake_destination (struct GNUNET_SOCKS_Handshake *ih, - const char *host, uint16_t port) + const char *host, + uint16_t port) { - union { + union + { struct in_addr in4; struct in6_addr in6; } ia; - unsigned char * b = ih->outstep[SOCKS5_step_cmd]; + unsigned char *b = ih->outstep[SOCKS5_step_cmd]; - *(b++) = 5; /* SOCKS5 */ - *(b++) = 1; /* Establish a TCP/IP stream */ - *(b++) = 0; /* reserved */ + *(b++) = 5; /* SOCKS5 */ + *(b++) = 1; /* Establish a TCP/IP stream */ + *(b++) = 0; /* reserved */ /* Specify destination */ - if (1 == inet_pton(AF_INET,host,&ia.in4)) { - *(b++)= 1; /* IPv4 */ - 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 */ - GNUNET_memcpy (b, &ia.in6, sizeof(struct in6_addr)); - b += sizeof(struct in6_addr); /* 16 */ - } else { - *(b++)= 3; /* hostname */ + if (1 == inet_pton (AF_INET, host, &ia.in4)) + { + *(b++) = 1; /* IPv4 */ + 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 */ + GNUNET_memcpy (b, &ia.in6, sizeof (struct in6_addr)); + b += sizeof (struct in6_addr); /* 16 */ + } + else + { + *(b++) = 3; /* hostname */ b = SOCK5_proto_string (b, host); } /* Specify port */ - *(uint16_t*)b = htons (port); + *(uint16_t *) b = htons (port); b += 2; ih->outstep[SOCKS5_step_done] = b; @@ -534,10 +552,10 @@ GNUNET_SOCKS_set_handshake_destination (struct GNUNET_SOCKS_Handshake *ih, * @return Connection handle that becomes usable when the SOCKS5 handshake completes. */ struct GNUNET_CONNECTION_Handle * -GNUNET_SOCKS_run_handshake(struct GNUNET_SOCKS_Handshake *ih, +GNUNET_SOCKS_run_handshake (struct GNUNET_SOCKS_Handshake *ih, struct GNUNET_CONNECTION_Handle *c) { - ih->socks5_connection=c; + ih->socks5_connection = c; ih->target_connection = GNUNET_CONNECTION_create_proxied_from_handshake (c); register_sender (ih); @@ -583,53 +601,51 @@ GNUNET_SOCKS_do_connect (const char *service_name, unsigned long long port0; unsigned long long port1; - if (GNUNET_YES != - GNUNET_SOCKS_check_service (service_name, cfg)) + 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)) + 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 * 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, + _ ( + "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) || - (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - service_name, - "HOSTNAME", - &host1))) + 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))) { LOG (GNUNET_ERROR_TYPE_WARNING, - _("Attempting to proxy service `%s' to invalid port %d or hostname.\n"), - service_name, + _ ( + "Attempting to proxy service `%s' to invalid port %d or hostname.\n"), + service_name, port1); return NULL; } /* 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)) + 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", + (host0 != NULL) ? host0 + : "127.0.0.1", port0); GNUNET_free_non_null (host0); @@ -642,16 +658,13 @@ GNUNET_SOCKS_do_connect (const char *service_name, service_name, "SOCKSPASS", &pass); - ih = GNUNET_SOCKS_init_handshake(user,pass); + ih = GNUNET_SOCKS_init_handshake (user, 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 */ -- 2.25.1