2 * This file is part of the Nice GLib ICE library.
4 * (C) 2008 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2008 Nokia Corporation. All rights reserved.
8 * The contents of this file are subject to the Mozilla Public License Version
9 * 1.1 (the "License"); you may not use this file except in compliance with
10 * the License. You may obtain a copy of the License at
11 * http://www.mozilla.org/MPL/
13 * Software distributed under the License is distributed on an "AS IS" basis,
14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15 * for the specific language governing rights and limitations under the
18 * The Original Code is the Nice GLib ICE library.
20 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
21 * Corporation. All Rights Reserved.
24 * Youness Alaoui, Collabora Ltd.
26 * Alternatively, the contents of this file may be used under the terms of the
27 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
28 * case the provisions of LGPL are applicable instead of those above. If you
29 * wish to allow use of your version of this file only under the terms of the
30 * LGPL and not to allow others to use your version of this file under the
31 * MPL, indicate your decision by deleting the provisions above and replace
32 * them with the notice and other provisions required by the LGPL. If you do
33 * not delete the provisions above, a recipient may use your version of this
34 * file under either the MPL or the LGPL.
38 * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
39 * http://en.wikipedia.org/wiki/Berkeley_sockets.)
46 #include "agent-priv.h"
47 #include "socket-priv.h"
59 SOCKS_STATE_CONNECTED,
65 NiceSocket *base_socket;
73 static void socket_close (NiceSocket *sock);
74 static gint socket_recv_messages (NiceSocket *sock,
75 NiceInputMessage *recv_messages, guint n_recv_messages);
76 static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
77 const NiceOutputMessage *messages, guint n_messages);
78 static gint socket_send_messages_reliable (NiceSocket *sock,
79 const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
80 static gboolean socket_is_reliable (NiceSocket *sock);
81 static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
82 static void socket_set_writable_callback (NiceSocket *sock,
83 NiceSocketWritableCb callback, gpointer user_data);
84 static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other);
88 nice_socks5_socket_new (NiceSocket *base_socket,
89 NiceAddress *addr, gchar *username, gchar *password)
92 NiceSocket *sock = NULL;
95 sock = g_slice_new0 (NiceSocket);
96 sock->priv = priv = g_slice_new0 (Socks5Priv);
98 priv->base_socket = base_socket;
100 priv->username = g_strdup (username);
101 priv->password = g_strdup (password);
103 sock->type = NICE_SOCKET_TYPE_SOCKS5;
104 sock->fileno = priv->base_socket->fileno;
105 sock->addr = priv->base_socket->addr;
106 sock->send_messages = socket_send_messages;
107 sock->send_messages_reliable = socket_send_messages_reliable;
108 sock->recv_messages = socket_recv_messages;
109 sock->is_reliable = socket_is_reliable;
110 sock->can_send = socket_can_send;
111 sock->set_writable_callback = socket_set_writable_callback;
112 sock->is_based_on = socket_is_based_on;
113 sock->close = socket_close;
115 /* Send SOCKS5 handshake */
120 msg[0] = 0x05; /* SOCKS version */
121 msg[1] = 0x01; /* number of methods supported */
122 msg[2] = 0x00; /* no authentication method*/
124 g_debug ("user/pass : %s - %s", username, password);
125 /* add support for authentication method */
126 if (username || password) {
127 msg[1] = 0x02; /* number of methods supported */
128 msg[3] = 0x02; /* authentication method */
132 /* We send 'to' NULL because it will always be to an already connected
133 * TCP base socket, which ignores the destination */
134 nice_socket_send_reliable (priv->base_socket, NULL, len, msg);
135 priv->state = SOCKS_STATE_INIT;
144 socket_close (NiceSocket *sock)
146 Socks5Priv *priv = sock->priv;
148 if (priv->base_socket)
149 nice_socket_free (priv->base_socket);
152 g_free (priv->username);
155 g_free (priv->password);
157 nice_socket_free_send_queue (&priv->send_queue);
159 g_slice_free(Socks5Priv, sock->priv);
165 socket_recv_messages (NiceSocket *sock,
166 NiceInputMessage *recv_messages, guint n_recv_messages)
168 Socks5Priv *priv = sock->priv;
172 /* Make sure socket has not been freed: */
173 g_assert (sock->priv != NULL);
175 switch (priv->state) {
176 case SOCKS_STATE_CONNECTED:
177 /* Common case: fast pass-through to the base socket once we’re
179 if (priv->base_socket) {
180 ret = nice_socket_recv_messages (priv->base_socket,
181 recv_messages, n_recv_messages);
187 /* After successfully receiving into at least one NiceInputMessage,
188 * update the from address in each valid NiceInputMessage. */
189 for (i = 0; i < (guint) ret; i++) {
190 if (recv_messages[i].from != NULL)
191 *recv_messages[i].from = priv->addr;
196 case SOCKS_STATE_INIT:
199 GInputVector local_recv_buf = { data, sizeof (data) };
200 NiceInputMessage local_recv_message = { &local_recv_buf, 1, NULL, 0 };
202 nice_debug ("Socks5 state Init");
204 if (priv->base_socket) {
205 ret = nice_socket_recv_messages (priv->base_socket,
206 &local_recv_message, 1);
211 } else if (ret == 1 && local_recv_buf.size == sizeof(data)) {
212 if (data[0] == 0x05) {
213 if (data[1] == 0x02) {
217 if (priv->username || priv->password) {
222 ulen = strlen (priv->username);
224 nice_debug ("Socks5 username length > 255");
229 plen = strlen (priv->password);
231 nice_debug ("Socks5 password length > 255");
235 msg[len++] = 0x01; /* auth version */
236 msg[len++] = ulen; /* username length */
238 memcpy (msg + len, priv->username, ulen); /* Username */
240 msg[len++] = plen; /* Password length */
242 memcpy (msg + len, priv->password, plen); /* Password */
245 nice_socket_send_reliable (priv->base_socket, NULL, len, msg);
246 priv->state = SOCKS_STATE_AUTH;
248 /* Authentication required but no auth info available */
251 } else if (data[1] == 0x00) {
254 /* method not supported by socks server */
258 /* invalid SOCKS server version */
267 case SOCKS_STATE_AUTH:
270 GInputVector local_recv_buf = { data, sizeof (data) };
271 NiceInputMessage local_recv_message = { &local_recv_buf, 1, NULL, 0 };
273 nice_debug ("Socks5 state auth");
274 if (priv->base_socket) {
275 ret = nice_socket_recv_messages (priv->base_socket,
276 &local_recv_message, 1);
281 } else if (ret == 1 && local_recv_buf.size == sizeof(data)) {
282 if (data[0] == 0x01 && data[1] == 0x00) {
286 /* Authentication failed */
292 case SOCKS_STATE_CONNECT:
295 GInputVector local_recv_buf = { data, sizeof (data) };
296 NiceInputMessage local_recv_message = { &local_recv_buf, 1, NULL, 0 };
298 nice_debug ("Socks5 state connect");
299 if (priv->base_socket) {
300 local_recv_buf.size = 4;
301 ret = nice_socket_recv_messages (priv->base_socket,
302 &local_recv_message, 1);
307 } else if (ret == 1 && local_recv_buf.size == 4) {
308 if (data[0] == 0x05) {
311 if (data[2] == 0x00) {
313 case 0x01: /* IPV4 bound address */
314 local_recv_buf.size = 6;
315 ret = nice_socket_recv_messages (priv->base_socket,
316 &local_recv_message, 1);
317 if (ret != 1 || local_recv_buf.size != 6) {
318 /* Could not read server bound address */
322 case 0x04: /* IPV6 bound address */
323 local_recv_buf.size = 18;
324 ret = nice_socket_recv_messages (priv->base_socket,
325 &local_recv_message, 1);
326 if (ret != 1 || local_recv_buf.size != 18) {
327 /* Could not read server bound address */
332 /* Unsupported address type */
335 nice_socket_flush_send_queue (priv->base_socket,
337 priv->state = SOCKS_STATE_CONNECTED;
339 /* Wrong reserved value */
343 case 0x01: /* general SOCKS server failure */
344 case 0x02: /* connection not allowed by ruleset */
345 case 0x03: /* Network unreachable */
346 case 0x04: /* Host unreachable */
347 case 0x05: /* Connection refused */
348 case 0x06: /* TTL expired */
349 case 0x07: /* Command not supported */
350 case 0x08: /* Address type not supported */
351 default: /* Unknown error */
356 /* Wrong server version */
360 /* Invalid data received */
365 case SOCKS_STATE_ERROR:
378 struct sockaddr_storage storage;
379 struct sockaddr addr;
380 struct sockaddr_in in;
381 struct sockaddr_in6 in6;
383 nice_address_copy_to_sockaddr(&priv->addr, &name.addr);
385 msg[len++] = 0x05; /* SOCKS version */
386 msg[len++] = 0x01; /* connect command */
387 msg[len++] = 0x00; /* reserved */
388 if (name.storage.ss_family == AF_INET) {
389 msg[len++] = 0x01; /* IPV4 address type */
391 memcpy (msg + len, &(&name.in)->sin_addr, 4);
394 memcpy (msg + len, &(&name.in)->sin_port, 2);
396 } else if (name.storage.ss_family == AF_INET6) {
397 msg[len++] = 0x04; /* IPV6 address type */
399 memcpy (msg + len, &(&name.in6)->sin6_addr, 16);
402 memcpy (msg + len, &(&name.in6)->sin6_port, 2);
406 nice_socket_send_reliable (priv->base_socket, NULL, len, msg);
407 priv->state = SOCKS_STATE_CONNECT;
412 nice_debug ("Socks5 error");
413 if (priv->base_socket)
414 nice_socket_free (priv->base_socket);
415 priv->base_socket = NULL;
416 priv->state = SOCKS_STATE_ERROR;
422 socket_send_messages (NiceSocket *sock, const NiceAddress *to,
423 const NiceOutputMessage *messages, guint n_messages)
425 Socks5Priv *priv = sock->priv;
427 /* Make sure socket has not been freed: */
428 g_assert (sock->priv != NULL);
430 if (priv->state == SOCKS_STATE_CONNECTED) {
431 /* Fast path: pass through to the base socket once connected. */
432 if (priv->base_socket == NULL)
435 return nice_socket_send_messages (priv->base_socket, to, messages,
437 } else if (priv->state == SOCKS_STATE_ERROR) {
446 socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
447 const NiceOutputMessage *messages, guint n_messages)
449 Socks5Priv *priv = sock->priv;
451 if (priv->state == SOCKS_STATE_CONNECTED) {
452 /* Fast path: pass through to the base socket once connected. */
453 if (priv->base_socket == NULL)
456 return nice_socket_send_messages_reliable (priv->base_socket, to, messages,
458 } else if (priv->state == SOCKS_STATE_ERROR) {
461 nice_socket_queue_send (&priv->send_queue, to, messages, n_messages);
468 socket_is_reliable (NiceSocket *sock)
470 Socks5Priv *priv = sock->priv;
472 return nice_socket_is_reliable (priv->base_socket);
476 socket_can_send (NiceSocket *sock, NiceAddress *addr)
478 Socks5Priv *priv = sock->priv;
480 return nice_socket_can_send (priv->base_socket, addr);
484 socket_set_writable_callback (NiceSocket *sock,
485 NiceSocketWritableCb callback, gpointer user_data)
487 Socks5Priv *priv = sock->priv;
489 nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
493 socket_is_based_on (NiceSocket *sock, NiceSocket *other)
495 Socks5Priv *priv = sock->priv;
497 return (sock == other) ||
498 (priv && nice_socket_is_based_on (priv->base_socket, other));