summaryrefslogtreecommitdiff
path: root/src/or/buffers.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2009-08-26 11:27:19 -0400
committerNick Mathewson <nickm@torproject.org>2009-08-26 11:27:19 -0400
commit707a6bd6595024e0b4a998e0a99eb284499a37e3 (patch)
treedd3230c44404c42b7fcab590466b0c2d3ad99c61 /src/or/buffers.c
parentf1b5fd2aaa81daaa9065a7f0193be5855e7d4e32 (diff)
parent903f9ef50e418f6ec1a1ab7ae8146e9d6d2a7767 (diff)
downloadtor-707a6bd6595024e0b4a998e0a99eb284499a37e3.tar.gz
tor-707a6bd6595024e0b4a998e0a99eb284499a37e3.zip
Merge commit 'public/socks-client'
Resolved conflict in: src/or/or.h
Diffstat (limited to 'src/or/buffers.c')
-rw-r--r--src/or/buffers.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 17d3399635..e5123732cf 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1611,6 +1611,132 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
}
}
+/** Inspect a reply from SOCKS server stored in <b>buf</b> according
+ * to <b>state</b>, removing the protocol data upon success. Return 0 on
+ * incomplete response, 1 on success and -1 on error, in which case
+ * <b>reason</b> is set to a descriptive message (free() when finished
+ * with it).
+ *
+ * As a special case, 2 is returned when user/pass is required
+ * during SOCKS5 handshake and user/pass is configured.
+ */
+int
+fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
+{
+ unsigned char *data;
+ size_t addrlen;
+
+ if (buf->datalen < 2)
+ return 0;
+
+ buf_pullup(buf, 128, 0);
+ tor_assert(buf->head && buf->head->datalen >= 2);
+
+ data = (unsigned char *) buf->head->data;
+
+ switch (state) {
+ case PROXY_SOCKS4_WANT_CONNECT_OK:
+ /* Wait for the complete response */
+ if (buf->head->datalen < 8)
+ return 0;
+
+ if (data[1] != 0x5a) {
+ *reason = tor_strdup(socks4_response_code_to_string(data[1]));
+ return -1;
+ }
+
+ /* Success */
+ buf_remove_from_front(buf, 8);
+ return 1;
+
+ case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
+ /* we don't have any credentials */
+ if (data[1] != 0x00) {
+ *reason = tor_strdup("server doesn't support any of our "
+ "available authentication methods");
+ return -1;
+ }
+
+ log_info(LD_NET, "SOCKS 5 client: continuing without authentication");
+ buf_clear(buf);
+ return 1;
+
+ case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
+ /* we have a username and password. return 1 if we can proceed without
+ * providing authentication, or 2 otherwise. */
+ switch (data[1]) {
+ case 0x00:
+ log_info(LD_NET, "SOCKS 5 client: we have auth details but server "
+ "doesn't require authentication.");
+ buf_clear(buf);
+ return 1;
+ case 0x02:
+ log_info(LD_NET, "SOCKS 5 client: need authentication.");
+ buf_clear(buf);
+ return 2;
+ /* fall through */
+ }
+
+ *reason = tor_strdup("server doesn't support any of our available "
+ "authentication methods");
+ return -1;
+
+ case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
+ /* handle server reply to rfc1929 authentication */
+ if (data[1] != 0x00) {
+ *reason = tor_strdup("authentication failed");
+ return -1;
+ }
+
+ log_info(LD_NET, "SOCKS 5 client: authentication successful.");
+ buf_clear(buf);
+ return 1;
+
+ case PROXY_SOCKS5_WANT_CONNECT_OK:
+ /* response is variable length. BND.ADDR, etc, isn't needed
+ * (don't bother with buf_pullup()), but make sure to eat all
+ * the data used */
+
+ /* wait for address type field to arrive */
+ if (buf->datalen < 4)
+ return 0;
+
+ switch (data[3]) {
+ case 0x01: /* ip4 */
+ addrlen = 4;
+ break;
+ case 0x04: /* ip6 */
+ addrlen = 16;
+ break;
+ case 0x03: /* fqdn (can this happen here?) */
+ if (buf->datalen < 5)
+ return 0;
+ addrlen = 1 + data[4];
+ break;
+ default:
+ *reason = tor_strdup("invalid response to connect request");
+ return -1;
+ }
+
+ /* wait for address and port */
+ if (buf->datalen < 6 + addrlen)
+ return 0;
+
+ if (data[1] != 0x00) {
+ *reason = tor_strdup(socks5_response_code_to_string(data[1]));
+ return -1;
+ }
+
+ buf_remove_from_front(buf, 6 + addrlen);
+ return 1;
+ }
+
+ /* shouldn't get here... */
+ tor_assert(0);
+
+ return -1;
+}
+
/** Return 1 iff buf looks more like it has an (obsolete) v0 controller
* command on it than any valid v1 controller command. */
int