summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Ruprecht <cmaiku@gmail.com>2016-01-10 03:23:46 -0600
committerMike Ruprecht <cmaiku@gmail.com>2016-01-10 03:23:46 -0600
commitd6331ebb1c3c72c21bb843933ac32b8381231bae (patch)
treee65d166c1412820eca039ffd1fff43c204c84359
parent8d4b677b1b598038a1fff3e75aca9b1a93dd90c9 (diff)
downloadpidgin-d6331ebb1c3c72c21bb843933ac32b8381231bae.tar.gz
Clear ununused functions from proxy.[ch] including purple_proxy_connect_udp()
Since porting libpurple's proxy API to internally use Gio, a lot of functions remain unused. purple_proxy_connect_udp() was added for the QQ prpl (ticket #6589), but no longer appears to be used. This patch removes all of these functions in favor of the Gio versions.
-rw-r--r--libpurple/proxy.c1676
-rw-r--r--libpurple/proxy.h30
2 files changed, 4 insertions, 1702 deletions
diff --git a/libpurple/proxy.c b/libpurple/proxy.c
index 3cae2b9bff..38aec2c63e 100644
--- a/libpurple/proxy.c
+++ b/libpurple/proxy.c
@@ -99,8 +99,6 @@ static PurpleProxyInfo *global_proxy_info = NULL;
static GSList *handles = NULL;
-static void try_connect(PurpleProxyConnectData *connect_data);
-
/*
* TODO: Eventually (GObjectification) this bad boy will be removed, because it is
* a gross fix for a crashy problem.
@@ -639,33 +637,11 @@ purple_proxy_connect_data_disconnect(PurpleProxyConnectData *connect_data, const
{
purple_debug_error("proxy", "Connection attempt failed: %s\n",
error_message);
- if (connect_data->hosts != NULL)
- try_connect(connect_data);
- else
- {
- /* Everything failed! Tell the originator of the request. */
- connect_data->connect_cb(connect_data->data, -1, error_message);
- purple_proxy_connect_data_destroy(connect_data);
- }
- }
-}
-/*
- * This calls purple_proxy_connect_data_disconnect(), but it lets you
- * specify the error_message using a printf()-like syntax.
- */
-static void
-purple_proxy_connect_data_disconnect_formatted(PurpleProxyConnectData *connect_data, const char *format, ...)
-{
- va_list args;
- gchar *tmp;
-
- va_start(args, format);
- tmp = g_strdup_vprintf(format, args);
- va_end(args);
-
- purple_proxy_connect_data_disconnect(connect_data, tmp);
- g_free(tmp);
+ /* Everything failed! Tell the originator of the request. */
+ connect_data->connect_cb(connect_data->data, -1, error_message);
+ purple_proxy_connect_data_destroy(connect_data);
+ }
}
static void
@@ -687,1572 +663,6 @@ purple_proxy_connect_data_connected(PurpleProxyConnectData *connect_data)
purple_proxy_connect_data_destroy(connect_data);
}
-static void
-socket_ready_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
- PurpleProxyConnectData *connect_data = data;
- int error = 0;
- int ret;
-
- /* If the socket-connected message had already been triggered when connect_data
- * was destroyed via purple_proxy_connect_cancel(), we may get here with a freed connect_data.
- */
- if (!PURPLE_PROXY_CONNECT_DATA_IS_VALID(connect_data))
- return;
-
- purple_debug_info("proxy", "Connecting to %s:%d.\n",
- connect_data->host, connect_data->port);
-
- /*
- * purple_input_get_error after a non-blocking connect returns -1 if something is
- * really messed up (bad descriptor, usually). Otherwise, it returns 0 and
- * error holds what connect would have returned if it blocked until now.
- * Thus, error == 0 is success, error == EINPROGRESS means "try again",
- * and anything else is a real error.
- *
- * (error == EINPROGRESS can happen after a select because the kernel can
- * be overly optimistic sometimes. select is just a hint that you might be
- * able to do something.)
- */
- ret = purple_input_get_error(connect_data->fd, &error);
-
- if (ret == 0 && error == EINPROGRESS) {
- /* No worries - we'll be called again later */
- /* TODO: Does this ever happen? */
- purple_debug_info("proxy", "(ret == 0 && error == EINPROGRESS)\n");
- return;
- }
-
- if (ret != 0 || error != 0) {
- if (ret != 0)
- error = errno;
- purple_debug_error("proxy", "Error connecting to %s:%d (%s).\n",
- connect_data->host, connect_data->port, g_strerror(error));
-
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
- return;
- }
-
- purple_proxy_connect_data_connected(connect_data);
-}
-
-static gboolean
-clean_connect(gpointer data)
-{
- purple_proxy_connect_data_connected(data);
-
- return FALSE;
-}
-
-static void
-proxy_connect_udp_none(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
- purple_debug_info("proxy", "UDP Connecting to %s:%d with no proxy\n",
- connect_data->host, connect_data->port);
-
- connect_data->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0);
- if (connect_data->fd < 0)
- {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Unable to create socket: %s"), g_strerror(errno));
- return;
- }
- _purple_network_set_common_socket_flags(connect_data->fd);
-
- if (connect(connect_data->fd, &addr->sa, addrlen) != 0)
- {
- if ((errno == EINPROGRESS) || (errno == EINTR))
- {
- purple_debug_info("proxy", "UDP connection in progress\n");
- connect_data->inpa = purple_input_add(connect_data->fd,
- PURPLE_INPUT_WRITE, socket_ready_cb, connect_data);
- }
- else
- {
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
- }
- }
- else
- {
- /*
- * The connection happened IMMEDIATELY... strange, but whatever.
- */
- int error = ETIMEDOUT;
- int ret;
-
- purple_debug_info("proxy", "UDP Connected immediately.\n");
-
- ret = purple_input_get_error(connect_data->fd, &error);
- if ((ret != 0) || (error != 0))
- {
- if (ret != 0)
- error = errno;
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
- return;
- }
-
- /*
- * We want to call the "connected" callback eventually, but we
- * don't want to call it before we return, just in case.
- */
- purple_timeout_add(10, clean_connect, connect_data);
- }
-}
-
-static void
-proxy_connect_none(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
- purple_debug_info("proxy", "Connecting to %s:%d with no proxy\n",
- connect_data->host, connect_data->port);
-
- connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0);
- if (connect_data->fd < 0)
- {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Unable to create socket: %s"), g_strerror(errno));
- return;
- }
- _purple_network_set_common_socket_flags(connect_data->fd);
-
- if (connect(connect_data->fd, &addr->sa, addrlen) != 0)
- {
- if ((errno == EINPROGRESS) || (errno == EINTR))
- {
- purple_debug_info("proxy", "Connection in progress\n");
- connect_data->inpa = purple_input_add(connect_data->fd,
- PURPLE_INPUT_WRITE, socket_ready_cb, connect_data);
- }
- else
- {
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
- }
- }
- else
- {
- /*
- * The connection happened IMMEDIATELY... strange, but whatever.
- */
- int error = ETIMEDOUT;
- int ret;
-
- purple_debug_info("proxy", "Connected immediately.\n");
-
- ret = purple_input_get_error(connect_data->fd, &error);
- if ((ret != 0) || (error != 0))
- {
- if (ret != 0)
- error = errno;
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
- return;
- }
-
- /*
- * We want to call the "connected" callback eventually, but we
- * don't want to call it before we return, just in case.
- */
- purple_timeout_add(10, clean_connect, connect_data);
- }
-}
-
-/*
- * This is a utility function used by the HTTP, SOCKS4 and SOCKS5
- * connect functions. It writes data from a buffer to a socket.
- * When all the data is written it sets up a watcher to read a
- * response and call a specified function.
- */
-static void
-proxy_do_write(gpointer data, gint source, PurpleInputCondition cond)
-{
- PurpleProxyConnectData *connect_data;
- const guchar *request;
- gsize request_len;
- int ret;
-
- connect_data = data;
- request = connect_data->write_buffer + connect_data->written_len;
- request_len = connect_data->write_buf_len - connect_data->written_len;
-
- ret = write(connect_data->fd, request, request_len);
- if (ret <= 0)
- {
- if (errno == EAGAIN)
- /* No worries */
- return;
-
- /* Error! */
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
- return;
- }
- if ((gsize)ret < request_len) {
- connect_data->written_len += ret;
- return;
- }
-
- /* We're done writing data! Wait for a response. */
- g_free(connect_data->write_buffer);
- connect_data->write_buffer = NULL;
- purple_input_remove(connect_data->inpa);
- connect_data->inpa = purple_input_add(connect_data->fd,
- PURPLE_INPUT_READ, connect_data->read_cb, connect_data);
-}
-
-/*
- * We're using an HTTP proxy for a non-port 80 tunnel. Read the
- * response to the CONNECT request.
- */
-static void
-http_canread(gpointer data, gint source, PurpleInputCondition cond)
-{
- int len, headers_len, status = 0;
- gboolean error;
- PurpleProxyConnectData *connect_data = data;
- char *p;
- gsize max_read;
-
- if (connect_data->read_buffer == NULL) {
- connect_data->read_buf_len = 8192;
- connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
- connect_data->read_len = 0;
- }
-
- p = (char *)connect_data->read_buffer + connect_data->read_len;
- max_read = connect_data->read_buf_len - connect_data->read_len - 1;
-
- len = read(connect_data->fd, p, max_read);
-
- if (len == 0) {
- purple_proxy_connect_data_disconnect(connect_data,
- _("Server closed the connection"));
- return;
- }
-
- if (len < 0) {
- if (errno == EAGAIN)
- /* No worries */
- return;
-
- /* Error! */
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Lost connection with server: %s"), g_strerror(errno));
- return;
- }
-
- connect_data->read_len += len;
- p[len] = '\0';
-
- p = g_strstr_len((const gchar *)connect_data->read_buffer,
- connect_data->read_len, "\r\n\r\n");
- if (p != NULL) {
- *p = '\0';
- headers_len = (p - (char *)connect_data->read_buffer) + 4;
- } else if((gsize)len == max_read)
- headers_len = len;
- else
- return;
-
- error = strncmp((const char *)connect_data->read_buffer, "HTTP/", 5) != 0;
- if (!error) {
- int major;
- p = (char *)connect_data->read_buffer + 5;
- major = strtol(p, &p, 10);
- error = (major == 0) || (*p != '.');
- if(!error) {
- int minor;
- p++;
- minor = strtol(p, &p, 10);
- error = (*p != ' ');
- if(!error) {
- p++;
- status = strtol(p, &p, 10);
- error = (*p != ' ');
- (void)minor; /* we don't need its value */
- }
- }
- }
-
- /* Read the contents */
- p = g_strrstr((const gchar *)connect_data->read_buffer, "Content-Length: ");
- if (p != NULL) {
- gchar *tmp;
- gsize content_len;
- char tmpc;
-
- p += strlen("Content-Length: ");
- tmp = strchr(p, '\r');
- if(tmp)
- *tmp = '\0';
- if (sscanf(p, "%" G_GSIZE_FORMAT, &content_len) != 1) {
- /* Couldn't read content length */
- purple_debug_error("proxy", "Couldn't read content length value "
- "from %s\n", p);
- if(tmp)
- *tmp = '\r';
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Unable to parse response from HTTP proxy: %s"),
- connect_data->read_buffer);
- return;
- }
- if(tmp)
- *tmp = '\r';
-
- /* Compensate for what has already been read */
- content_len -= connect_data->read_len - headers_len;
- /* I'm assuming that we're doing this to prevent the server from
- complaining / breaking since we don't read the whole page */
- while (content_len--) {
- /* TODO: deal with EAGAIN (and other errors) better */
- /* TODO: Reading 1 byte at a time is horrible and stupid. */
- if (read(connect_data->fd, &tmpc, 1) < 0 && errno != EAGAIN)
- break;
- }
- }
-
- if (error) {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Unable to parse response from HTTP proxy: %s"),
- connect_data->read_buffer);
- return;
- }
- else if (status != 200) {
- purple_debug_error("proxy",
- "Proxy server replied with:\n%s\n",
- connect_data->read_buffer);
-
- if (status == 407 /* Proxy Auth */) {
- const char *header;
- gchar *request;
-
- header = g_strrstr((const gchar *)connect_data->read_buffer,
- "Proxy-Authenticate: NTLM");
- if (header != NULL) {
- const char *header_end = header + strlen("Proxy-Authenticate: NTLM");
- const char *domain = purple_proxy_info_get_username(connect_data->gpi);
- char *username = NULL, hostname[256];
- gchar *response;
- int ret;
-
- ret = gethostname(hostname, sizeof(hostname));
- hostname[sizeof(hostname) - 1] = '\0';
- if (ret < 0 || hostname[0] == '\0') {
- purple_debug_warning("proxy", "gethostname() failed -- is your hostname set?");
- g_strlcpy(hostname, "localhost", sizeof(hostname));
- }
-
- if (domain != NULL)
- username = (char*) strchr(domain, '\\');
- if (username == NULL) {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("HTTP proxy connection error %d"), status);
- return;
- }
- *username = '\0';
-
- /* Is there a message? */
- if (*header_end == ' ') {
- /* Check for Type-2 */
- char *tmp = (char*) header;
- guint8 *nonce;
-
- header_end++;
- username++;
- while(*tmp != '\r' && *tmp != '\0') tmp++;
- *tmp = '\0';
- nonce = purple_ntlm_parse_type2(header_end, NULL);
- response = purple_ntlm_gen_type3(username,
- (gchar*) purple_proxy_info_get_password(connect_data->gpi),
- hostname,
- domain, nonce, NULL);
- username--;
- } else /* Empty message */
- response = purple_ntlm_gen_type1(hostname, domain);
-
- *username = '\\';
-
- request = g_strdup_printf(
- "CONNECT %s:%d HTTP/1.1\r\n"
- "Host: %s:%d\r\n"
- "Proxy-Authorization: NTLM %s\r\n"
- "Proxy-Connection: Keep-Alive\r\n\r\n",
- connect_data->host, connect_data->port,
- connect_data->host, connect_data->port,
- response);
-
- g_free(response);
-
- } else if (g_strrstr((const char *)connect_data->read_buffer, "Proxy-Authenticate: Basic") != NULL) {
- gchar *t1, *t2;
- const char *username, *password;
-
- username = purple_proxy_info_get_username(connect_data->gpi);
- password = purple_proxy_info_get_password(connect_data->gpi);
-
- t1 = g_strdup_printf("%s:%s",
- username ? username : "",
- password ? password : "");
- t2 = purple_base64_encode((guchar *)t1, strlen(t1));
- g_free(t1);
-
- request = g_strdup_printf(
- "CONNECT %s:%d HTTP/1.1\r\n"
- "Host: %s:%d\r\n"
- "Proxy-Authorization: Basic %s\r\n",
- connect_data->host, connect_data->port,
- connect_data->host, connect_data->port,
- t2);
-
- g_free(t2);
-
- } else {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("HTTP proxy connection error %d"), status);
- return;
- }
-
- purple_input_remove(connect_data->inpa);
- g_free(connect_data->read_buffer);
- connect_data->read_buffer = NULL;
-
- connect_data->write_buffer = (guchar *)request;
- connect_data->write_buf_len = strlen(request);
- connect_data->written_len = 0;
-
- connect_data->read_cb = http_canread;
-
- connect_data->inpa = purple_input_add(connect_data->fd,
- PURPLE_INPUT_WRITE, proxy_do_write, connect_data);
-
- proxy_do_write(connect_data, connect_data->fd, cond);
-
- return;
- }
-
- if (status == 403) {
- /* Forbidden */
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Access denied: HTTP proxy server forbids port %d tunneling"),
- connect_data->port);
- } else {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("HTTP proxy connection error %d"), status);
- }
- } else {
- purple_input_remove(connect_data->inpa);
- connect_data->inpa = 0;
- g_free(connect_data->read_buffer);
- connect_data->read_buffer = NULL;
- purple_debug_info("proxy", "HTTP proxy connection established\n");
- purple_proxy_connect_data_connected(connect_data);
- return;
- }
-}
-
-static void
-http_start_connect_tunneling(PurpleProxyConnectData *connect_data) {
- GString *request;
- int ret;
-
- purple_debug_info("proxy", "Using CONNECT tunneling for %s:%d\n",
- connect_data->host, connect_data->port);
-
- request = g_string_sized_new(4096);
- g_string_append_printf(request,
- "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n",
- connect_data->host, connect_data->port,
- connect_data->host, connect_data->port);
-
- if (purple_proxy_info_get_username(connect_data->gpi) != NULL)
- {
- char *t1, *t2, *ntlm_type1;
- char hostname[256];
-
- ret = gethostname(hostname, sizeof(hostname));
- hostname[sizeof(hostname) - 1] = '\0';
- if (ret < 0 || hostname[0] == '\0') {
- purple_debug_warning("proxy", "gethostname() failed -- is your hostname set?");
- g_strlcpy(hostname, "localhost", sizeof(hostname));
- }
-
- t1 = g_strdup_printf("%s:%s",
- purple_proxy_info_get_username(connect_data->gpi),
- purple_proxy_info_get_password(connect_data->gpi) ?
- purple_proxy_info_get_password(connect_data->gpi) : "");
- t2 = purple_base64_encode((const guchar *)t1, strlen(t1));
- g_free(t1);
-
- ntlm_type1 = purple_ntlm_gen_type1(hostname, "");
-
- g_string_append_printf(request,
- "Proxy-Authorization: Basic %s\r\n"
- "Proxy-Authorization: NTLM %s\r\n"
- "Proxy-Connection: Keep-Alive\r\n",
- t2, ntlm_type1);
- g_free(ntlm_type1);
- g_free(t2);
- }
-
- g_string_append(request, "\r\n");
-
- connect_data->write_buf_len = request->len;
- connect_data->write_buffer = (guchar *)g_string_free(request, FALSE);
- connect_data->written_len = 0;
- connect_data->read_cb = http_canread;
-
- connect_data->inpa = purple_input_add(connect_data->fd,
- PURPLE_INPUT_WRITE, proxy_do_write, connect_data);
- proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
-}
-
-static void
-http_canwrite(gpointer data, gint source, PurpleInputCondition cond) {
- PurpleProxyConnectData *connect_data = data;
- int ret, error = ETIMEDOUT;
-
- purple_debug_info("proxy", "Connected to %s:%d.\n",
- connect_data->host, connect_data->port);
-
- if (connect_data->inpa > 0) {
- purple_input_remove(connect_data->inpa);
- connect_data->inpa = 0;
- }
-
- ret = purple_input_get_error(connect_data->fd, &error);
- if (ret != 0 || error != 0) {
- if (ret != 0)
- error = errno;
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
- return;
- }
-
- if (connect_data->port == 80) {
- /*
- * If we're trying to connect to something running on
- * port 80 then we assume the traffic using this
- * connection is going to be HTTP traffic. If it's
- * not then this will fail (uglily). But it's good
- * to avoid using the CONNECT method because it's
- * not always allowed.
- */
- purple_debug_info("proxy", "HTTP proxy connection established\n");
- purple_proxy_connect_data_connected(connect_data);
- } else {
- http_start_connect_tunneling(connect_data);
- }
-
-}
-
-static void
-proxy_connect_http(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
- purple_debug_info("proxy",
- "Connecting to %s:%d via %s:%d using HTTP\n",
- connect_data->host, connect_data->port,
- (purple_proxy_info_get_host(connect_data->gpi) ? purple_proxy_info_get_host(connect_data->gpi) : "(null)"),
- purple_proxy_info_get_port(connect_data->gpi));
-
- connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0);
- if (connect_data->fd < 0)
- {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Unable to create socket: %s"), g_strerror(errno));
- return;
- }
- _purple_network_set_common_socket_flags(connect_data->fd);
-
- if (connect(connect_data->fd, &addr->sa, addrlen) != 0) {
- if (errno == EINPROGRESS || errno == EINTR) {
- purple_debug_info("proxy", "HTTP connection in progress\n");
-
- connect_data->inpa = purple_input_add(connect_data->fd,
- PURPLE_INPUT_WRITE, http_canwrite, connect_data);
- } else
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
- } else {
- purple_debug_info("proxy", "Connected immediately.\n");
-
- http_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
- }
-}
-
-static void
-s4_canread(gpointer data, gint source, PurpleInputCondition cond)
-{
- PurpleProxyConnectData *connect_data = data;
- guchar *buf;
- int len, max_read;
-
- /* This is really not going to block under normal circumstances, but to
- * be correct, we deal with the unlikely scenario */
-
- if (connect_data->read_buffer == NULL) {
- connect_data->read_buf_len = 12;
- connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
- connect_data->read_len = 0;
- }
-
- buf = connect_data->read_buffer + connect_data->read_len;
- max_read = connect_data->read_buf_len - connect_data->read_len;
-
- len = read(connect_data->fd, buf, max_read);
-
- if ((len < 0 && errno == EAGAIN) || (len > 0 && len + connect_data->read_len < 4))
- return;
- else if (len + connect_data->read_len >= 4) {
- if (connect_data->read_buffer[1] == 90) {
- purple_proxy_connect_data_connected(connect_data);
- return;
- }
- }
-
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
-}
-
-static void
-s4_host_resolved(GObject *source_object, GAsyncResult *res, gpointer data)
-{
- GInetAddress *address = NULL;
- GError *error = NULL;
- GList *hosts = NULL, *l = NULL;
- PurpleProxyConnectData *connect_data = data;
- unsigned char packet[9];
-
- if(G_IS_CANCELLABLE(connect_data->cancellable)) {
- g_object_unref(G_OBJECT(connect_data->cancellable));
-
- connect_data->cancellable = NULL;
- }
-
- hosts = g_resolver_lookup_by_name_finish(G_RESOLVER(source_object),
- res, &error);
-
- if (error->message != NULL) {
- purple_proxy_connect_data_disconnect(connect_data, error->message);
-
- g_error_free(error);
-
- return;
- }
-
- if (hosts == NULL) {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Error resolving %s"), connect_data->host);
- return;
- }
-
- for(l = hosts; l; l = l->next) {
- address = G_INET_ADDRESS(l->data);
-
- if(!g_inet_address_get_is_loopback(address) && !g_inet_address_get_is_link_local(address))
- break;
-
- address = NULL;
- }
-
- if(address != NULL) {
- packet[0] = 0x04;
- packet[1] = 0x01;
- packet[2] = connect_data->port >> 8;
- packet[3] = connect_data->port & 0xff;
- memcpy(packet + 4, g_inet_address_to_bytes(address), 4);
- packet[8] = 0x00;
-
- connect_data->write_buffer = g_memdup(packet, sizeof(packet));
- connect_data->write_buf_len = sizeof(packet);
- connect_data->written_len = 0;
- connect_data->read_cb = s4_canread;
-
- connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data);
-
- proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
- } else {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Error resolving %s"), connect_data->host);
- }
-
- g_resolver_free_addresses(hosts);
-}
-
-static void
-s4_canwrite(gpointer data, gint source, PurpleInputCondition cond)
-{
- PurpleProxyConnectData *connect_data = data;
- int error = ETIMEDOUT;
- int ret;
-
- purple_debug_info("socks4 proxy", "Connected.\n");
-
- if (connect_data->inpa > 0) {
- purple_input_remove(connect_data->inpa);
- connect_data->inpa = 0;
- }
-
- ret = purple_input_get_error(connect_data->fd, &error);
- if ((ret != 0) || (error != 0)) {
- if (ret != 0)
- error = errno;
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
- return;
- }
-
- /*
- * The socks4 spec doesn't include support for doing host name lookups by
- * the proxy. Many socks4 servers do this via the "socks4a" extension to
- * the protocol. There doesn't appear to be a way to detect if a server
- * supports this, so we require that the user set a global option.
- */
- if (purple_prefs_get_bool("/purple/proxy/socks4_remotedns")) {
- unsigned char packet[9];
- int len;
-
- purple_debug_info("socks4 proxy", "Attempting to use remote DNS.\n");
-
- packet[0] = 0x04;
- packet[1] = 0x01;
- packet[2] = connect_data->port >> 8;
- packet[3] = connect_data->port & 0xff;
- packet[4] = 0x00;
- packet[5] = 0x00;
- packet[6] = 0x00;
- packet[7] = 0x01;
- packet[8] = 0x00;
-
- len = sizeof(packet) + strlen(connect_data->host) + 1;
-
- connect_data->write_buffer = g_malloc0(len);
- memcpy(connect_data->write_buffer, packet, sizeof(packet));
- memcpy(connect_data->write_buffer + sizeof(packet), connect_data->host, strlen(connect_data->host));
- connect_data->write_buf_len = len;
- connect_data->written_len = 0;
- connect_data->read_cb = s4_canread;
-
- connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data);
-
- proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
- } else {
- GResolver *resolver = NULL;
-
- connect_data->cancellable = g_cancellable_new();
-
- resolver = g_resolver_get_default();
-
- g_resolver_lookup_by_name_async(resolver,
- connect_data->host,
- connect_data->cancellable,
- s4_host_resolved,
- connect_data);
-
- g_object_unref(G_OBJECT(resolver));
-
- if (connect_data->cancellable == NULL) {
- purple_debug_error("proxy", "dns query failed unexpectedly.\n");
- purple_proxy_connect_data_destroy(connect_data);
- }
- }
-}
-
-static void
-proxy_connect_socks4(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
- purple_debug_info("proxy",
- "Connecting to %s:%d via %s:%d using SOCKS4\n",
- connect_data->host, connect_data->port,
- purple_proxy_info_get_host(connect_data->gpi),
- purple_proxy_info_get_port(connect_data->gpi));
-
- connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0);
- if (connect_data->fd < 0)
- {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Unable to create socket: %s"), g_strerror(errno));
- return;
- }
- _purple_network_set_common_socket_flags(connect_data->fd);
-
- if (connect(connect_data->fd, &addr->sa, addrlen) != 0)
- {
- if ((errno == EINPROGRESS) || (errno == EINTR))
- {
- purple_debug_info("proxy", "SOCKS4 connection in progress\n");
- connect_data->inpa = purple_input_add(connect_data->fd,
- PURPLE_INPUT_WRITE, s4_canwrite, connect_data);
- }
- else
- {
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
- }
- }
- else
- {
- purple_debug_info("proxy", "Connected immediately.\n");
-
- s4_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
- }
-}
-
-static gboolean
-s5_ensure_buffer_length(PurpleProxyConnectData *connect_data, guint len)
-{
- if(connect_data->read_len < len) {
- if(connect_data->read_buf_len < len) {
- /* it's not just that we haven't read enough, it's that we haven't tried to read enough yet */
- purple_debug_info("s5", "reallocing from %" G_GSIZE_FORMAT
- " to %d\n", connect_data->read_buf_len, len);
- connect_data->read_buf_len = len;
- connect_data->read_buffer = g_realloc(connect_data->read_buffer, connect_data->read_buf_len);
- }
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-s5_canread_again(gpointer data, gint source, PurpleInputCondition cond)
-{
- guchar *dest, *buf;
- PurpleProxyConnectData *connect_data = data;
- int len;
-
- if (connect_data->read_buffer == NULL) {
- connect_data->read_buf_len = 5;
- connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
- connect_data->read_len = 0;
- }
-
- dest = connect_data->read_buffer + connect_data->read_len;
- buf = connect_data->read_buffer;
-
- len = read(connect_data->fd, dest, (connect_data->read_buf_len - connect_data->read_len));
-
- if (len == 0)
- {
- purple_proxy_connect_data_disconnect(connect_data,
- _("Server closed the connection"));
- return;
- }
-
- if (len < 0)
- {
- if (errno == EAGAIN)
- /* No worries */
- return;
-
- /* Error! */
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Lost connection with server: %s"), g_strerror(errno));
- return;
- }
-
- connect_data->read_len += len;
-
- if(connect_data->read_len < 4)
- return;
-
- if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
- if ((buf[0] == 0x05) && (buf[1] < 0x09)) {
- purple_debug_error("socks5 proxy", "%s", socks5errors[buf[1]]);
- purple_proxy_connect_data_disconnect(connect_data,
- socks5errors[buf[1]]);
- } else {
- purple_debug_error("socks5 proxy", "Bad data.\n");
- purple_proxy_connect_data_disconnect(connect_data,
- _("Received invalid data on connection with server"));
- }
- return;
- }
-
- /* Skip past BND.ADDR */
- switch(buf[3]) {
- case 0x01: /* the address is a version-4 IP address, with a length of 4 octets */
- if(!s5_ensure_buffer_length(connect_data, 4 + 4))
- return;
- buf += 4 + 4;
- break;
- case 0x03: /* the address field contains a fully-qualified domain name. The first
- octet of the address field contains the number of octets of name that
- follow, there is no terminating NUL octet. */
- if(!s5_ensure_buffer_length(connect_data, 4 + 1))
- return;
- buf += 4;
- if(!s5_ensure_buffer_length(connect_data, 4 + 1 + buf[0]))
- return;
- buf += buf[0] + 1;
- break;
- case 0x04: /* the address is a version-6 IP address, with a length of 16 octets */
- if(!s5_ensure_buffer_length(connect_data, 4 + 16))
- return;
- buf += 4 + 16;
- break;
- default:
- purple_debug_error("socks5 proxy", "Invalid ATYP received (0x%X)\n", buf[3]);
- purple_proxy_connect_data_disconnect(connect_data,
- _("Received invalid data on connection with server"));
- return;
- }
-
- /* Skip past BND.PORT */
- if(!s5_ensure_buffer_length(connect_data, (buf - connect_data->read_buffer) + 2))
- return;
-
- purple_proxy_connect_data_connected(connect_data);
-}
-
-static void
-s5_sendconnect(gpointer data, int source)
-{
- PurpleProxyConnectData *connect_data = data;
- size_t hlen = strlen(connect_data->host);
- connect_data->write_buf_len = 5 + hlen + 2;
- connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
- connect_data->written_len = 0;
-
- connect_data->write_buffer[0] = 0x05;
- connect_data->write_buffer[1] = 0x01; /* CONNECT */
- connect_data->write_buffer[2] = 0x00; /* reserved */
- connect_data->write_buffer[3] = 0x03; /* address type -- host name */
- connect_data->write_buffer[4] = hlen;
- memcpy(connect_data->write_buffer + 5, connect_data->host, hlen);
- connect_data->write_buffer[5 + hlen] = connect_data->port >> 8;
- connect_data->write_buffer[5 + hlen + 1] = connect_data->port & 0xff;
-
- connect_data->read_cb = s5_canread_again;
-
- connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data);
- proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
-}
-
-static void
-s5_readauth(gpointer data, gint source, PurpleInputCondition cond)
-{
- PurpleProxyConnectData *connect_data = data;
- int len;
-
- if (connect_data->read_buffer == NULL) {
- connect_data->read_buf_len = 2;
- connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
- connect_data->read_len = 0;
- }
-
- purple_debug_info("socks5 proxy", "Got auth response.\n");
-
- len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len,
- connect_data->read_buf_len - connect_data->read_len);
-
- if (len == 0)
- {
- purple_proxy_connect_data_disconnect(connect_data,
- _("Server closed the connection"));
- return;
- }
-
- if (len < 0)
- {
- if (errno == EAGAIN)
- /* No worries */
- return;
-
- /* Error! */
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Lost connection with server: %s"), g_strerror(errno));
- return;
- }
-
- connect_data->read_len += len;
- if (connect_data->read_len < 2)
- return;
-
- purple_input_remove(connect_data->inpa);
- connect_data->inpa = 0;
-
- if ((connect_data->read_buffer[0] != 0x01) || (connect_data->read_buffer[1] != 0x00)) {
- purple_proxy_connect_data_disconnect(connect_data,
- _("Received invalid data on connection with server"));
- return;
- }
-
- g_free(connect_data->read_buffer);
- connect_data->read_buffer = NULL;
-
- s5_sendconnect(connect_data, connect_data->fd);
-}
-
-static void
-hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, unsigned char * response)
-{
- PurpleHash *hash;
- int i;
- unsigned char Kxoripad[65];
- unsigned char Kxoropad[65];
- size_t pwlen;
-
- hash = purple_md5_hash_new();
-
- memset(Kxoripad,0,sizeof(Kxoripad));
- memset(Kxoropad,0,sizeof(Kxoropad));
-
- pwlen=strlen(passwd);
- if (pwlen>64) {
- purple_hash_append(hash, (const guchar *)passwd, strlen(passwd));
- purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad));
- pwlen=16;
- } else {
- memcpy(Kxoripad, passwd, pwlen);
- }
- memcpy(Kxoropad,Kxoripad,pwlen);
-
- for (i=0;i<64;i++) {
- Kxoripad[i]^=0x36;
- Kxoropad[i]^=0x5c;
- }
-
- purple_hash_reset(hash);
- purple_hash_append(hash, Kxoripad, 64);
- purple_hash_append(hash, challenge, challen);
- purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad));
-
- purple_hash_reset(hash);
- purple_hash_append(hash, Kxoropad, 64);
- purple_hash_append(hash, Kxoripad, 16);
- purple_hash_digest(hash, response, 16);
-
- g_object_unref(hash);
-}
-
-static void
-s5_readchap(gpointer data, gint source, PurpleInputCondition cond);
-
-/*
- * Return how many bytes we processed
- * -1 means we've shouldn't keep reading from the buffer
- */
-static gssize
-s5_parse_chap_msg(PurpleProxyConnectData *connect_data)
-{
- guchar *buf, *cmdbuf = connect_data->read_buffer;
- int len, navas, currentav;
-
- purple_debug_misc("socks5 proxy", "Reading CHAP message: %x\n", *cmdbuf);
-
- if (*cmdbuf != 0x01) {
- purple_proxy_connect_data_disconnect(connect_data,
- _("Received invalid data on connection with server"));
- return -1;
- }
- cmdbuf++;
-
- navas = *cmdbuf;
-
- purple_debug_misc("socks5 proxy", "Expecting %d attribute(s).\n", navas);
- if (G_UNLIKELY(navas < 0 || navas > 10000)) { /* XXX: what's the threshold? */
- purple_proxy_connect_data_disconnect(connect_data,
- _("Received invalid data on connection with server"));
- return -1;
- }
-
- cmdbuf++;
-
- for (currentav = 0; currentav < navas; currentav++) {
-
- len = connect_data->read_len - (cmdbuf - connect_data->read_buffer);
- /* We don't have enough data to even know how long the next attribute is,
- * or we don't have the full length of the next attribute. */
- if (len < 2 || len < (cmdbuf[1] + 2)) {
- /* Clear out the attributes that have been read - decrease the attribute count */
- connect_data->read_buffer[1] = navas - currentav;
- /* Move the unprocessed data into the first attribute position */
- memmove((connect_data->read_buffer + 2), cmdbuf, len);
- /* Decrease the read count accordingly */
- connect_data->read_len = len + 2;
-
- purple_debug_info("socks5 proxy", "Need more data to retrieve attribute %d.\n", currentav);
-
- return -1;
- }
-
- buf = cmdbuf + 2;
-
- if (cmdbuf[1] == 0) {
- purple_debug_error("socks5 proxy", "Attribute %x Value length of 0; ignoring.\n", cmdbuf[0]);
- cmdbuf = buf;
- continue;
- }
-
- switch (cmdbuf[0]) {
- case 0x00:
- purple_debug_info("socks5 proxy", "Received STATUS of %x\n", buf[0]);
- /* Did auth work? */
- if (buf[0] == 0x00) {
- purple_input_remove(connect_data->inpa);
- connect_data->inpa = 0;
- g_free(connect_data->read_buffer);
- connect_data->read_buffer = NULL;
- /* Success */
- s5_sendconnect(connect_data, connect_data->fd);
- } else {
- /* Failure */
- purple_debug_warning("proxy",
- "socks5 CHAP authentication "
- "failed. Disconnecting...");
- purple_proxy_connect_data_disconnect(connect_data,
- _("Authentication failed"));
- }
- return -1;
- case 0x01:
- /* We've already validated that cmdbuf[1] is sane. */
- purple_debug_info("socks5 proxy", "Received TEXT-MESSAGE of '%.*s'\n", (int) cmdbuf[1], buf);
- break;
- case 0x03:
- purple_debug_info("socks5 proxy", "Received CHALLENGE\n");
- /* Server wants our credentials */
-
- connect_data->write_buf_len = 16 + 4;
- connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
- connect_data->written_len = 0;
-
- hmacmd5_chap(buf, cmdbuf[1],
- purple_proxy_info_get_password(connect_data->gpi),
- connect_data->write_buffer + 4);
- /* TODO: What about USER-IDENTITY? */
- connect_data->write_buffer[0] = 0x01;
- connect_data->write_buffer[1] = 0x01;
- connect_data->write_buffer[2] = 0x04;
- connect_data->write_buffer[3] = 0x10;
-
- purple_input_remove(connect_data->inpa);
- g_free(connect_data->read_buffer);
- connect_data->read_buffer = NULL;
-
- connect_data->read_cb = s5_readchap;
-
- connect_data->inpa = purple_input_add(connect_data->fd,
- PURPLE_INPUT_WRITE, proxy_do_write, connect_data);
-
- proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
- return -1;
- case 0x11:
- purple_debug_info("socks5 proxy", "Received ALGORIGTHMS of %x\n", buf[0]);
- /* Server wants to select an algorithm */
- if (buf[0] != 0x85) {
- /* Only currently support HMAC-MD5 */
- purple_debug_warning("proxy",
- "Server tried to select an "
- "algorithm that we did not advertise "
- "as supporting. This is a violation "
- "of the socks5 CHAP specification. "
- "Disconnecting...");
- purple_proxy_connect_data_disconnect(connect_data,
- _("Received invalid data on connection with server"));
- return -1;
- }
- break;
- default:
- purple_debug_info("socks5 proxy", "Received unused command %x, length=%d\n", cmdbuf[0], cmdbuf[1]);
- }
- cmdbuf = buf + cmdbuf[1];
- }
-
- return (cmdbuf - connect_data->read_buffer);
-}
-
-static void
-s5_readchap(gpointer data, gint source, PurpleInputCondition cond)
-{
- gssize msg_ret;
- PurpleProxyConnectData *connect_data = data;
- int len;
-
- purple_debug(PURPLE_DEBUG_INFO, "socks5 proxy", "Got CHAP response.\n");
-
- if (connect_data->read_buffer == NULL) {
- /* A big enough butfer to read the message header (2 bytes) and at least one complete attribute and value (1 + 1 + 255). */
- connect_data->read_buf_len = 259;
- connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
- connect_data->read_len = 0;
- }
-
- if (connect_data->read_buf_len - connect_data->read_len == 0) {
- /*If the stuff below is right, this shouldn't be possible. */
- purple_debug_error("socks5 proxy", "This is about to suck because the read buffer is full (shouldn't happen).\n");
- }
-
- len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len,
- connect_data->read_buf_len - connect_data->read_len);
-
- if (len == 0) {
- purple_proxy_connect_data_disconnect(connect_data,
- _("Server closed the connection"));
- return;
- }
-
- if (len < 0) {
- if (errno == EAGAIN)
- /* No worries */
- return;
-
- /* Error! */
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Lost connection with server: %s"), g_strerror(errno));
- return;
- }
-
- connect_data->read_len += len;
-
- /* We may have read more than one message into the buffer, we need to make sure to process them all */
- while (1) {
-
- /* We need more to be able to read this message */
- if (connect_data->read_len < 2)
- return;
-
- msg_ret = s5_parse_chap_msg(connect_data);
-
- if (msg_ret < 0)
- return;
-
- /* See if we have another message already in the buffer */
- if ((len = connect_data->read_len - msg_ret) > 0) {
-
- /* Move on to the next message */
- memmove(connect_data->read_buffer, connect_data->read_buffer + msg_ret, len);
- /* Decrease the read count accordingly */
- connect_data->read_len = len;
-
- /* Try to read the message that connect_data->read_buffer now points to */
- continue;
- }
-
- break;
- }
-
- /* Fell through. We ran out of CHAP events to process, but haven't
- * succeeded or failed authentication - there may be more to come.
- * If this is the case, come straight back here. */
-
- purple_debug_info("socks5 proxy", "Waiting for another message from which to read CHAP info.\n");
-
- /* We've processed all the available attributes, so get ready for a whole new message */
- g_free(connect_data->read_buffer);
- connect_data->read_buffer = NULL;
-}
-
-static void
-s5_canread(gpointer data, gint source, PurpleInputCondition cond)
-{
- PurpleProxyConnectData *connect_data = data;
- int len;
-
- if (connect_data->read_buffer == NULL) {
- connect_data->read_buf_len = 2;
- connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
- connect_data->read_len = 0;
- }
-
- purple_debug_info("socks5 proxy", "Able to read.\n");
-
- len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len,
- connect_data->read_buf_len - connect_data->read_len);
-
- if (len == 0)
- {
- purple_proxy_connect_data_disconnect(connect_data,
- _("Server closed the connection"));
- return;
- }
-
- if (len < 0)
- {
- if (errno == EAGAIN)
- /* No worries */
- return;
-
- /* Error! */
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Lost connection with server: %s"), g_strerror(errno));
- return;
- }
-
- connect_data->read_len += len;
- if (connect_data->read_len < 2)
- return;
-
- purple_input_remove(connect_data->inpa);
- connect_data->inpa = 0;
-
- if ((connect_data->read_buffer[0] != 0x05) || (connect_data->read_buffer[1] == 0xff)) {
- purple_proxy_connect_data_disconnect(connect_data,
- _("Received invalid data on connection with server"));
- return;
- }
-
- if (connect_data->read_buffer[1] == 0x02) {
- size_t i, j;
- const char *u, *p;
-
- u = purple_proxy_info_get_username(connect_data->gpi);
- p = purple_proxy_info_get_password(connect_data->gpi);
-
- i = (u == NULL) ? 0 : strlen(u);
- j = (p == NULL) ? 0 : strlen(p);
-
- connect_data->write_buf_len = 1 + 1 + i + 1 + j;
- connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
- connect_data->written_len = 0;
-
- connect_data->write_buffer[0] = 0x01; /* version 1 */
- connect_data->write_buffer[1] = i;
- if (u != NULL)
- memcpy(connect_data->write_buffer + 2, u, i);
- connect_data->write_buffer[2 + i] = j;
- if (p != NULL)
- memcpy(connect_data->write_buffer + 2 + i + 1, p, j);
-
- g_free(connect_data->read_buffer);
- connect_data->read_buffer = NULL;
-
- connect_data->read_cb = s5_readauth;
-
- connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE,
- proxy_do_write, connect_data);
-
- proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
-
- return;
- } else if (connect_data->read_buffer[1] == 0x03) {
- size_t userlen;
- userlen = strlen(purple_proxy_info_get_username(connect_data->gpi));
-
- connect_data->write_buf_len = 7 + userlen;
- connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
- connect_data->written_len = 0;
-
- connect_data->write_buffer[0] = 0x01;
- connect_data->write_buffer[1] = 0x02;
- connect_data->write_buffer[2] = 0x11;
- connect_data->write_buffer[3] = 0x01;
- connect_data->write_buffer[4] = 0x85;
- connect_data->write_buffer[5] = 0x02;
- connect_data->write_buffer[6] = userlen;
- memcpy(connect_data->write_buffer + 7,
- purple_proxy_info_get_username(connect_data->gpi), userlen);
-
- g_free(connect_data->read_buffer);
- connect_data->read_buffer = NULL;
-
- connect_data->read_cb = s5_readchap;
-
- connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE,
- proxy_do_write, connect_data);
-
- proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
-
- return;
- } else {
- g_free(connect_data->read_buffer);
- connect_data->read_buffer = NULL;
-
- s5_sendconnect(connect_data, connect_data->fd);
- }
-}
-
-static void
-s5_canwrite(gpointer data, gint source, PurpleInputCondition cond)
-{
- unsigned char buf[5];
- int i;
- PurpleProxyConnectData *connect_data = data;
- int error = ETIMEDOUT;
- int ret;
-
- purple_debug_info("socks5 proxy", "Connected.\n");
-
- if (connect_data->inpa > 0)
- {
- purple_input_remove(connect_data->inpa);
- connect_data->inpa = 0;
- }
-
- ret = purple_input_get_error(connect_data->fd, &error);
- if ((ret != 0) || (error != 0))
- {
- if (ret != 0)
- error = errno;
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
- return;
- }
-
- buf[0] = 0x05; /* SOCKS version 5 */
-
- if (purple_proxy_info_get_username(connect_data->gpi) != NULL) {
- buf[1] = 0x03; /* three methods */
- buf[2] = 0x00; /* no authentication */
- buf[3] = 0x03; /* CHAP authentication */
- buf[4] = 0x02; /* username/password authentication */
- i = 5;
- }
- else {
- buf[1] = 0x01;
- buf[2] = 0x00;
- i = 3;
- }
-
- connect_data->write_buf_len = i;
- connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
- memcpy(connect_data->write_buffer, buf, i);
-
- connect_data->read_cb = s5_canread;
-
- connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data);
- proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
-}
-
-static void
-proxy_connect_socks5(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
- purple_debug_info("proxy",
- "Connecting to %s:%d via %s:%d using SOCKS5\n",
- connect_data->host, connect_data->port,
- purple_proxy_info_get_host(connect_data->gpi),
- purple_proxy_info_get_port(connect_data->gpi));
-
- connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0);
- if (connect_data->fd < 0)
- {
- purple_proxy_connect_data_disconnect_formatted(connect_data,
- _("Unable to create socket: %s"), g_strerror(errno));
- return;
- }
- _purple_network_set_common_socket_flags(connect_data->fd);
-
- if (connect(connect_data->fd, &addr->sa, addrlen) != 0)
- {
- if ((errno == EINPROGRESS) || (errno == EINTR))
- {
- purple_debug_info("proxy", "SOCKS5 connection in progress\n");
- connect_data->inpa = purple_input_add(connect_data->fd,
- PURPLE_INPUT_WRITE, s5_canwrite, connect_data);
- }
- else
- {
- purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
- }
- }
- else
- {
- purple_debug_info("proxy", "Connected immediately.\n");
-
- s5_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
- }
-}
-
-/*
- * This function attempts to connect to the next IP address in the list
- * of IP addresses returned to us by purple_dnsquery_a() and attempts
- * to connect to each one. This is called after the hostname is
- * resolved, and each time a connection attempt fails (assuming there
- * is another IP address to try).
- */
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN 46
-#endif
-
-static void try_connect(PurpleProxyConnectData *connect_data)
-{
- GInetAddress *address = NULL;
- GSocketAddress *socket_address = NULL;
- GError *error = NULL;
- char *ipaddr;
-
- common_sockaddr_t addr;
- socklen_t addrlen = 0;
-
- address = G_INET_ADDRESS(connect_data->hosts->data);
- ipaddr = g_inet_address_to_string(address);
-
- purple_debug_info("proxy", "Attempting connection to %s\n", ipaddr);
- g_free(ipaddr);
-
- socket_address = g_inet_socket_address_new(address, connect_data->port);
- addrlen = g_socket_address_get_native_size(socket_address);
-
- g_socket_address_to_native(socket_address, &addr, addrlen, &error);
- if(error != NULL) {
- purple_debug_info("proxy", "failed connnection : %s\n", error->message);
-
- g_error_free(error);
-
- return;
- }
-
- if (connect_data->socket_type == SOCK_DGRAM) {
- proxy_connect_udp_none(connect_data, &addr, addrlen);
-
- return;
- }
-
- switch (purple_proxy_info_get_proxy_type(connect_data->gpi)) {
- case PURPLE_PROXY_NONE:
- proxy_connect_none(connect_data, &addr, addrlen);
- break;
-
- case PURPLE_PROXY_HTTP:
- proxy_connect_http(connect_data, &addr, addrlen);
- break;
-
- case PURPLE_PROXY_SOCKS4:
- proxy_connect_socks4(connect_data, &addr, addrlen);
- break;
-
- case PURPLE_PROXY_SOCKS5:
- case PURPLE_PROXY_TOR:
- proxy_connect_socks5(connect_data, &addr, addrlen);
- break;
-
- case PURPLE_PROXY_USE_ENVVAR:
- proxy_connect_http(connect_data, &addr, addrlen);
- break;
-
- default:
- break;
- }
-
- g_object_unref(G_OBJECT(socket_address));
-}
-
-static void
-connection_host_resolved(GObject *source, GAsyncResult *res, gpointer data) {
- PurpleProxyConnectData *connect_data = (PurpleProxyConnectData *)data;
- GError *error = NULL;
- GList *addresses = NULL;
-
- addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(source),
- res, &error);
-
- if(G_IS_CANCELLABLE(connect_data->cancellable)) {
- g_object_unref(G_OBJECT(connect_data->cancellable));
-
- connect_data->cancellable = NULL;
- }
-
- if (error != NULL) {
- purple_proxy_connect_data_disconnect(connect_data, error->message);
-
- g_error_free(error);
-
- g_resolver_free_addresses(addresses);
-
- return;
- }
-
- if (addresses == NULL) {
- purple_proxy_connect_data_disconnect(connect_data, _("Unable to resolve hostname"));
-
- return;
- }
-
- connect_data->hosts = addresses;
-
- try_connect(connect_data);
-}
-
PurpleProxyInfo *
purple_proxy_get_setup(PurpleAccount *account)
{
@@ -2444,84 +854,6 @@ purple_proxy_connect(void *handle, PurpleAccount *account,
return connect_data;
}
-PurpleProxyConnectData *
-purple_proxy_connect_udp(void *handle, PurpleAccount *account,
- const char *host, int port,
- PurpleProxyConnectFunction connect_cb, gpointer data)
-{
- const char *connecthost = host;
- int connectport = port;
- PurpleProxyConnectData *connect_data;
- GResolver *resolver;
-
- g_return_val_if_fail(host != NULL, NULL);
- g_return_val_if_fail(port > 0, NULL);
- g_return_val_if_fail(connect_cb != NULL, NULL);
-
- connect_data = g_new0(PurpleProxyConnectData, 1);
- connect_data->fd = -1;
- connect_data->socket_type = SOCK_DGRAM;
- connect_data->handle = handle;
- connect_data->connect_cb = connect_cb;
- connect_data->data = data;
- connect_data->host = g_strdup(host);
- connect_data->port = port;
- connect_data->gpi = purple_proxy_get_setup(account);
- connect_data->account = account;
-
- if ((purple_proxy_info_get_proxy_type(connect_data->gpi) != PURPLE_PROXY_NONE) &&
- (purple_proxy_info_get_host(connect_data->gpi) == NULL ||
- purple_proxy_info_get_port(connect_data->gpi) <= 0)) {
-
- purple_notify_error(NULL, NULL, _("Invalid proxy settings"),
- _("Either the host name or port number specified for "
- "your given proxy type is invalid."),
- purple_request_cpar_from_account(account));
- purple_proxy_connect_data_destroy(connect_data);
- return NULL;
- }
-
- switch (purple_proxy_info_get_proxy_type(connect_data->gpi))
- {
- case PURPLE_PROXY_NONE:
- break;
-
- case PURPLE_PROXY_HTTP:
- case PURPLE_PROXY_SOCKS4:
- case PURPLE_PROXY_SOCKS5:
- case PURPLE_PROXY_TOR:
- case PURPLE_PROXY_USE_ENVVAR:
- purple_debug_info("proxy", "Ignoring Proxy type (%d) for UDP.\n",
- purple_proxy_info_get_proxy_type(connect_data->gpi));
- break;
-
- default:
- purple_debug_error("proxy", "Invalid Proxy type (%d) specified.\n",
- purple_proxy_info_get_proxy_type(connect_data->gpi));
- purple_proxy_connect_data_destroy(connect_data);
- return NULL;
- }
-
- connect_data->cancellable = g_cancellable_new();
-
- resolver = g_resolver_get_default();
- g_resolver_lookup_by_name_async(resolver,
- connecthost,
- connect_data->cancellable,
- connection_host_resolved,
- connect_data);
- g_object_unref(resolver);
-
- if (connect_data->cancellable == NULL) {
- purple_proxy_connect_data_destroy(connect_data);
- return NULL;
- }
-
- handles = g_slist_prepend(handles, connect_data);
-
- return connect_data;
-}
-
static void
socks5_proxy_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data)
{
diff --git a/libpurple/proxy.h b/libpurple/proxy.h
index 8ccefbe216..4810e51bc2 100644
--- a/libpurple/proxy.h
+++ b/libpurple/proxy.h
@@ -277,36 +277,6 @@ PurpleProxyConnectData *purple_proxy_connect(void *handle,
PurpleProxyConnectFunction connect_cb, gpointer data);
/**
- * purple_proxy_connect_udp:
- * @handle: A handle that should be associated with this
- * connection attempt. The handle can be used
- * to cancel the connection attempt using the
- * purple_proxy_connect_cancel_with_handle()
- * function.
- * @account: The account making the connection.
- * @host: The destination host.
- * @port: The destination port.
- * @connect_cb: (scope call): The function to call when the connection is
- * established. If the connection failed then
- * fd will be -1 and error message will be set
- * to something descriptive (hopefully).
- * @data: User-defined data.
- *
- * Makes a connection to the specified host and port. Note that this
- * function name can be misleading--although it is called "proxy
- * connect," it is used for establishing any outgoing UDP connection,
- * whether through a proxy or not.
- *
- * Returns: NULL if there was an error, or a reference to an
- * opaque data structure that can be used to cancel
- * the pending connection, if needed.
- */
-PurpleProxyConnectData *purple_proxy_connect_udp(void *handle,
- PurpleAccount *account,
- const char *host, int port,
- PurpleProxyConnectFunction connect_cb, gpointer data);
-
-/**
* purple_proxy_connect_socks5_account:
* @handle: A handle that should be associated with this
* connection attempt. The handle can be used