summaryrefslogtreecommitdiff
path: root/src/bytestream-socks5.c
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2009-03-04 18:18:53 +0000
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2009-03-24 14:28:54 +0000
commitd79c2d729450a70da05434dca1cdc20160576539 (patch)
treeeb9efb2d86e18844925b5cb8f9eda9f76c3b1a8b /src/bytestream-socks5.c
parent97bbf399417752eba5860ff304d1ca503581efb6 (diff)
downloadtelepathy-gabble-d79c2d729450a70da05434dca1cdc20160576539.tar.gz
SOCKS5: accept buggy CONNECT reply to interop with bugged ejabberd proxy
Diffstat (limited to 'src/bytestream-socks5.c')
-rw-r--r--src/bytestream-socks5.c76
1 files changed, 55 insertions, 21 deletions
diff --git a/src/bytestream-socks5.c b/src/bytestream-socks5.c
index 9ccfd03e2..0fb144382 100644
--- a/src/bytestream-socks5.c
+++ b/src/bytestream-socks5.c
@@ -110,8 +110,8 @@ typedef enum _Socks5State Socks5State;
#define SHA1_LENGTH 40
#define SOCKS5_CONNECT_LENGTH (7 + SHA1_LENGTH)
-/* VER + CMD/REP + RSV + ATYP + DOMAIN_LEN + PORT (2) */
-#define SOCKS5_MIN_LENGTH 7
+/* VER + CMD/REP + RSV + ATYP + PORT (2) */
+#define SOCKS5_MIN_LENGTH 6
#define CONNECT_REPLY_TIMEOUT 30
#define CONNECT_TIMEOUT 30
@@ -853,7 +853,8 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
guint auth_len;
guint i;
gchar *domain;
- guint8 domain_len;
+ /* the length of the BND.ADDR field */
+ guint8 addr_len;
gsize len;
switch (priv->socks5_state)
@@ -925,21 +926,48 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
if (string->len < SOCKS5_MIN_LENGTH)
return 0;
- domain_len = (guint8) string->str[4];
- if ((guint8) string->len < SOCKS5_MIN_LENGTH + domain_len)
+ if (string->str[0] != SOCKS5_VERSION ||
+ string->str[1] != SOCKS5_STATUS_OK ||
+ string->str[2] != SOCKS5_RESERVED)
+ {
+ DEBUG ("Connection refused");
+
+ socks5_error (self);
+ return string->len;
+ }
+
+ if (string->str[3] == SOCKS5_ATYP_DOMAIN)
+ {
+ /* correct domain. The first byte of the domain contains its
+ * length */
+ addr_len = (guint8) string->str[4];
+ addr_len += 1;
+ }
+ else if (string->str[3] == 0x00)
+ {
+ DEBUG ("Got 0x00 as domain. Pretend it's ok to be able to interop "
+ "with ejabber < 2.0.2");
+ addr_len = 0;
+ }
+ else
+ {
+ DEBUG ("Wrong domain");
+
+ socks5_error (self);
+ return string->len;
+ }
+
+ if ((guint8) string->len < SOCKS5_MIN_LENGTH + addr_len)
/* We didn't receive the full packet yet */
return 0;
stop_timer (self);
- if (string->str[0] != SOCKS5_VERSION ||
- string->str[1] != SOCKS5_STATUS_OK ||
- string->str[2] != SOCKS5_RESERVED ||
- string->str[3] != SOCKS5_ATYP_DOMAIN ||
+ if (
/* first half of the port number */
- string->str[5 + domain_len] != 0 ||
+ string->str[4 + addr_len] != 0 ||
/* second half of the port number */
- string->str[6 + domain_len] != 0)
+ string->str[5 + addr_len] != 0)
{
DEBUG ("Connection refused");
@@ -958,10 +986,13 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
priv->peer_jid);
}
- if (!check_domain (&string->str[5], domain_len, domain))
+ if (addr_len > 0)
{
- /* Thanks Pidgin... */
- DEBUG ("Ignoring to interop with buggy implementations");
+ if (!check_domain (&string->str[5], addr_len - 1, domain))
+ {
+ /* Thanks Pidgin... */
+ DEBUG ("Ignoring to interop with buggy implementations");
+ }
}
g_free (domain);
@@ -971,7 +1002,7 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
else
initiator_got_connect_reply (self);
- return SOCKS5_MIN_LENGTH + domain_len;
+ return SOCKS5_MIN_LENGTH + addr_len;
case SOCKS5_STATE_INITIATOR_AWAITING_AUTH_REQUEST:
/* A client connected to us and we are awaiting for the authorization
@@ -1027,8 +1058,11 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
if (string->len < SOCKS5_MIN_LENGTH)
return 0;
- domain_len = (guint8) string->str[4];
- if ((guint8) string->len < SOCKS5_MIN_LENGTH + domain_len)
+ addr_len = (guint8) string->str[4];
+ /* the first byte is the length */
+ addr_len += 1;
+
+ if ((guint8) string->len < SOCKS5_MIN_LENGTH + addr_len)
/* We didn't receive the full packet yet */
return 0;
@@ -1037,9 +1071,9 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
string->str[2] != SOCKS5_RESERVED ||
string->str[3] != SOCKS5_ATYP_DOMAIN ||
/* first half of the port number */
- string->str[5 + domain_len] != 0 ||
+ string->str[4 + addr_len] != 0 ||
/* second half of the port number */
- string->str[5 + domain_len] != 0)
+ string->str[5 + addr_len] != 0)
{
DEBUG ("Invalid SOCKS5 connect message");
@@ -1050,7 +1084,7 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
domain = compute_domain (priv->stream_id, priv->self_full_jid,
priv->peer_jid);
- if (!check_domain (&string->str[5], domain_len, domain))
+ if (!check_domain (&string->str[5], addr_len - 1, domain))
{
DEBUG ("Reject connection to prevent spoofing");
socks5_close_transport (self);
@@ -1086,7 +1120,7 @@ socks5_handle_received_data (GabbleBytestreamSocks5 *self,
g_object_unref (priv->listener);
priv->listener = NULL;
- return SOCKS5_MIN_LENGTH + domain_len;
+ return SOCKS5_MIN_LENGTH + addr_len;
case SOCKS5_STATE_CONNECTED:
/* We are connected, everything we receive now is data */