Mercurial > hg > th-libs
changeset 121:8c39e8e90dbd
More work on proxy handling.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 22 Jun 2014 02:12:17 +0300 |
parents | 41c2638ee537 |
children | 452adc41ccf5 |
files | th_network.c th_network.h |
diffstat | 2 files changed, 152 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/th_network.c Sun Jun 22 01:25:35 2014 +0300 +++ b/th_network.c Sun Jun 22 02:12:17 2014 +0300 @@ -16,11 +16,18 @@ enum { - TH_SOCKS5_AUTH_NONE = 0, - TH_SOCKS5_AUTH_USER = 2, + SOCKS5_AUTH_NONE = 0, + SOCKS5_AUTH_USER = 2, }; +enum +{ + SOCKS5_ADDR_IPV4 = 0x01, + SOCKS5_ADDR_DOMAIN = 0x03, + SOCKS5_ADDR_IPV6 = 0x04, +}; + static const char *th_proxy_types[] = { "none", @@ -31,6 +38,23 @@ }; +static const char *th_socks5_results_msgs[] = +{ + "Succeeded", + "General SOCKS server failure", + "Connection not allowed by ruleset", + "Network unreachable", + "Host unreachable", + "Connection refused", + "TTL expired", + "Command not supported", + "Address type not supported", +}; + +static const int th_socks5_results_msgs_num = sizeof(th_socks5_results_msgs) / sizeof(th_socks5_results_msgs[0]); + + + static int th_get_socket_errno(void) { return errno; @@ -152,6 +176,28 @@ } +int th_conn_set_proxy_mode(th_conn_t *conn, const int mode) +{ + if (conn == NULL) + return THERR_NULLPTR; + + conn->proxy.mode = mode; + + return THERR_OK; +} + + +int th_conn_set_proxy_addr_type(th_conn_t *conn, const int atype) +{ + if (conn == NULL) + return THERR_NULLPTR; + + conn->proxy.addr_type = atype; + + return THERR_OK; +} + + int th_conn_set_proxy_auth_user(th_conn_t *conn, const char *userid, const char *passwd) { if (conn == NULL) @@ -213,23 +259,54 @@ { th_growbuf_t buf; uint8_t *ptr; - int err = THERR_INIT_FAIL; + int cmd, err = THERR_INIT_FAIL; (void) host; th_growbuf_init(&buf, 128); th_conn_msg(conn, THLOG_INFO, "Initializing SOCKS 4/a proxy negotiation.\n"); + switch (conn->proxy.mode) + { + case TH_PROXY_CMD_CONNECT: cmd = 1; break; + case TH_PROXY_CMD_BIND: cmd = 2; break; + default: + err = THERR_NOT_SUPPORTED; + th_conn_err(conn, err, "Invalid SOCKS 4 command/mode, unsupported.\n"); + goto out; + } + // Create SOCKS 4 handshake th_growbuf_put_u8(&buf, 4); // Protocol version - th_growbuf_put_u8(&buf, TH_PROXY_CMD_CONNECT); // Command + th_growbuf_put_u8(&buf, cmd); // Command th_growbuf_put_u16_be(&buf, port); - if (conn->proxy.type == TH_PROXY_SOCKS4A) - th_growbuf_put_u32_be(&buf, 0x00000032); - else - th_growbuf_put_str(&buf, (uint8_t *) &(conn->addr.s_addr), sizeof(conn->addr.s_addr)); + + switch (conn->proxy.addr_type) + { + case TH_PROXY_ADDR_IPV4: + th_growbuf_put_str(&buf, (uint8_t *) &(conn->addr.s_addr), sizeof(conn->addr.s_addr)); + break; + + case TH_PROXY_ADDR_DOMAIN: + if (conn->proxy.type == TH_PROXY_SOCKS4A) + th_growbuf_put_u32_be(&buf, 0x00000032); + else + { + err = THERR_INIT_FAIL; + th_conn_err(conn, err, + "Invalid proxy settings, SOCKS 4 in use, but domain address type requested. SOCKS 4a or 5 required for host atype.\n"); + goto out; + } + break; + + default: + err = THERR_INIT_FAIL; + th_conn_err(conn, err, + "Invalid proxy settings for SOCKS 4, unsupported address type requrested.\n"); + goto out; + } th_growbuf_puts(&buf, conn->proxy.userid, TRUE); - if (conn->proxy.type == TH_PROXY_SOCKS4A) + if (conn->proxy.addr_type == TH_PROXY_ADDR_DOMAIN) th_growbuf_puts(&buf, conn->host, TRUE); // Send request @@ -277,24 +354,34 @@ static int th_conn_socks5_negotiate(th_conn_t *conn, const int port, const char *host) { - size_t userid_len = 0, passwd_len = 0; th_growbuf_t buf; uint8_t *ptr; - int avail, auth, err = THERR_INIT_FAIL; + int cmd, avail, auth, err = THERR_INIT_FAIL; th_growbuf_init(&buf, 256); th_conn_msg(conn, THLOG_INFO, "Initializing SOCKS 5 proxy negotiation.\n"); + switch (conn->proxy.mode) + { + case TH_PROXY_CMD_CONNECT: cmd = 1; break; + case TH_PROXY_CMD_BIND: cmd = 2; break; + case TH_PROXY_CMD_ASSOC_UDP: cmd = 3; break; + default: + err = THERR_NOT_SUPPORTED; + th_conn_err(conn, err, "Invalid SOCKS 5 command/mode, unsupported.\n"); + goto out; + } + switch (conn->proxy.auth_type) { case TH_PROXY_AUTH_NONE: avail = 1; - auth = TH_SOCKS5_AUTH_NONE; + auth = SOCKS5_AUTH_NONE; break; case TH_PROXY_AUTH_USER: avail = 2; - auth = TH_SOCKS5_AUTH_USER; + auth = SOCKS5_AUTH_USER; if (conn->proxy.userid == NULL || conn->proxy.passwd == NULL) { err = THERR_INVALID_DATA; @@ -303,9 +390,8 @@ goto out; } - userid_len = strlen(conn->proxy.userid); - passwd_len = strlen(conn->proxy.passwd); - if (userid_len > 255 || passwd_len > 255) + if (strlen(conn->proxy.userid) > 255 || + strlen(conn->proxy.passwd) > 255) { err = THERR_INVALID_DATA; th_conn_err(conn, err, @@ -356,15 +442,15 @@ goto out; } else - if (auth == TH_SOCKS5_AUTH_USER) + if (auth == SOCKS5_AUTH_USER) { // Attempt user/pass authentication (RFC 1929) th_growbuf_clear(&buf); th_growbuf_put_u8(&buf, 0x01); - th_growbuf_put_u8(&buf, userid_len); + th_growbuf_put_u8(&buf, strlen(conn->proxy.userid)); th_growbuf_puts(&buf, conn->proxy.userid, FALSE); - th_growbuf_put_u8(&buf, passwd_len); + th_growbuf_put_u8(&buf, strlen(conn->proxy.passwd)); th_growbuf_puts(&buf, conn->proxy.passwd, FALSE); // Send request @@ -393,25 +479,50 @@ } } else - if (auth != TH_SOCKS5_AUTH_NONE) + if (auth != SOCKS5_AUTH_NONE) { err = THERR_NOT_SUPPORTED; - th_conn_err(conn, THERR_NOT_SUPPORTED, + th_conn_err(conn, err, "Proxy server chose an unsupported SOCKS 5 authentication method %d.\n", auth); goto out; } - -#if 0 +#if 1 // Form client connection request packet th_growbuf_clear(&buf); + th_growbuf_put_u8(&buf, 0x05); // Protocol version + th_growbuf_put_u8(&buf, cmd); // Command + th_growbuf_put_u8(&buf, 0x00); // Reserved - th_growbuf_put_u8(&buf, 0x05); // Protocol version - th_growbuf_put_u8(&buf, cmd); - th_growbuf_put_u8(&buf, 0x00); - th_growbuf_put_u8(&buf, SOCKS5_ADDR_IPV4); - th_growbuf_put_str(&buf, conn->addr.s_addr, sizeof(conn->addr.s_addr)); + switch (conn->proxy.addr_type) + { + case TH_PROXY_ADDR_IPV4: + th_growbuf_put_u8(&buf, SOCKS5_ADDR_IPV4); + th_growbuf_put_str(&buf, (uint8_t *) &(conn->addr.s_addr), sizeof(conn->addr.s_addr)); + break; + + case TH_PROXY_ADDR_IPV6: + th_growbuf_put_u8(&buf, SOCKS5_ADDR_IPV6); + //th_growbuf_put_str(&buf, (uint8_t *) &(conn->addr.s_addr), sizeof(conn->addr.s_addr)); + break; + + case TH_PROXY_ADDR_DOMAIN: + cmd = strlen(conn->host); + if (cmd < 1 || cmd > 255) + { + err = THERR_NOT_SUPPORTED; + th_conn_err(conn, err, + "Domain address type requested, but domain name longer than 255 characters (%d).\n", cmd); + goto out; + } + + th_growbuf_put_u8(&buf, SOCKS5_ADDR_DOMAIN); + th_growbuf_put_u8(&buf, cmd); + th_growbuf_put_str(&buf, conn->host, cmd); + break; + } + th_growbuf_put_u16_be(&buf, port); // Send request @@ -434,10 +545,10 @@ if (*ptr != 0) { err = THERR_INIT_FAIL; - if (*ptr >= 0 && *ptr < sizeof()) - th_conn_err(conn, err, "%s.\n", th_socks5_results_msgs[*ptr]); + if (*ptr < th_socks5_results_msgs_num) + th_conn_err(conn, err, "SOCKS 5 error: %s.\n", th_socks5_results_msgs[*ptr]); else - th_conn_err(conn, err ".Unknown\n"); + th_conn_err(conn, err, "Unknown SOCKS 5 result code 0x02x.\n", *ptr); goto out; } ptr++;
--- a/th_network.h Sun Jun 22 01:25:35 2014 +0300 +++ b/th_network.h Sun Jun 22 02:12:17 2014 +0300 @@ -66,6 +66,13 @@ enum { + TH_PROXY_ADDR_IPV4 = 0, + TH_PROXY_ADDR_DOMAIN, + TH_PROXY_ADDR_IPV6, +}; + +enum +{ TH_PROXY_AUTH_NONE, TH_PROXY_AUTH_USER, }; @@ -89,6 +96,7 @@ int port; struct in_addr addr; char *userid, *passwd; + int mode, addr_type; } proxy; // Target host data @@ -129,6 +137,8 @@ void th_conn_msg(th_conn_t *conn, int loglevel, const char *fmt, ...); int th_conn_set_proxy(th_conn_t *conn, int type, int port, const char *host, int auth_type); +int th_conn_set_proxy_mode(th_conn_t *conn, const int mode); +int th_conn_set_proxy_addr_type(th_conn_t *conn, const int atype); int th_conn_set_proxy_auth_user(th_conn_t *conn, const char *userid, const char *passwd); int th_conn_open(th_conn_t *conn, const int port, const char *host); int th_conn_close(th_conn_t *);