static void set_proxy_auth(gboolean use_proxy_auth) { char *auth_user; char *auth_pw; auth_user = gconf_client_get_string(gl_client, KEY_GCONF_HTTP_AUTH_USER, NULL); auth_pw = gconf_client_get_string(gl_client, KEY_GCONF_HTTP_AUTH_PW, NULL); if (use_proxy_auth) { /* Christian Kellner: Here are the only changes I made to the proxy sub- * system */ proxy_username = (auth_user != NULL ? g_strdup(auth_user) : NULL); proxy_password = (auth_pw != NULL ? g_strdup(auth_pw) : NULL); DEBUG_HTTP(("New HTTP proxy auth user: '******'", auth_user)); } else { if (proxy_username != NULL) g_free(proxy_username); if (proxy_password != NULL) g_free(proxy_password); proxy_username = proxy_password = NULL; DEBUG_HTTP(("HTTP proxy auth unset")); } g_free(auth_user); g_free(auth_pw); }
void proxy_init(void) { GError *gconf_error = NULL; gboolean use_proxy; gboolean use_proxy_auth; gl_client = gconf_client_get_default(); gl_mutex = g_mutex_new(); gconf_client_add_dir(gl_client, PATH_GCONF_GNOME_VFS, GCONF_CLIENT_PRELOAD_ONELEVEL, &gconf_error); if (gconf_error) { DEBUG_HTTP(("GConf error during client_add_dir '%s'", gconf_error->message)); g_error_free(gconf_error); gconf_error = NULL; } gconf_client_notify_add(gl_client, PATH_GCONF_GNOME_VFS, notify_gconf_value_changed, NULL, NULL, &gconf_error); if (gconf_error) { DEBUG_HTTP(("GConf error during notify_error '%s'", gconf_error->message)); g_error_free(gconf_error); gconf_error = NULL; } /* Load the http proxy setting */ use_proxy = gconf_client_get_bool(gl_client, KEY_GCONF_USE_HTTP_PROXY, &gconf_error); if (gconf_error != NULL) { DEBUG_HTTP(("GConf error during client_get_bool '%s'", gconf_error->message)); g_error_free(gconf_error); gconf_error = NULL; } else { construct_gl_http_proxy(use_proxy); } use_proxy_auth = gconf_client_get_bool(gl_client, KEY_GCONF_HTTP_USE_AUTH, &gconf_error); if (gconf_error != NULL) { DEBUG_HTTP(("GConf error during client_get_bool '%s'", gconf_error->message)); g_error_free(gconf_error); gconf_error = NULL; } else { set_proxy_auth(use_proxy_auth); } }
static void construct_gl_http_proxy(gboolean use_proxy) { g_free(gl_http_proxy); gl_http_proxy = NULL; g_slist_foreach(gl_ignore_hosts, (GFunc) g_free, NULL); g_slist_free(gl_ignore_hosts); gl_ignore_hosts = NULL; g_slist_foreach(gl_ignore_addrs, (GFunc) g_free, NULL); g_slist_free(gl_ignore_addrs); gl_ignore_addrs = NULL; if (use_proxy) { char *proxy_host; int proxy_port; GSList *ignore; proxy_host = gconf_client_get_string(gl_client, KEY_GCONF_HTTP_PROXY_HOST, NULL); proxy_port = gconf_client_get_int(gl_client, KEY_GCONF_HTTP_PROXY_PORT, NULL); if (proxy_host && proxy_host[0] != '\0') { if (0 != proxy_port && 0xffff >= (unsigned) proxy_port) { gl_http_proxy = g_strdup_printf("%s:%u", proxy_host, (unsigned) proxy_port); } else { gl_http_proxy = g_strdup_printf("%s:%u", proxy_host, (unsigned) DEFAULT_HTTP_PROXY_PORT); } DEBUG_HTTP(("New HTTP proxy: '%s'", gl_http_proxy)); } else { DEBUG_HTTP(("HTTP proxy unset")); } g_free(proxy_host); proxy_host = NULL; ignore = gconf_client_get_list(gl_client, KEY_GCONF_HTTP_PROXY_IGNORE_HOSTS, GCONF_VALUE_STRING, NULL); g_slist_foreach(ignore, (GFunc) parse_ignore_host, NULL); g_slist_foreach(ignore, (GFunc) g_free, NULL); g_slist_free(ignore); ignore = NULL; } }
bool BaseHTTPProtocol::HandleChunkedContent(IOBuffer &buffer) { //2. We cycle until we don't have any complete chunks anymore //or we hit the 0 bytes chunks (end of chunked content) uint8_t *pBuffer = NULL; uint32_t chunkSize = 0; uint32_t chunkSizeSize = 0; while (GETAVAILABLEBYTESCOUNT(buffer) >= 3) { //1. Get the raw pointer. We need it almost everywhere pBuffer = GETIBPOINTER(buffer); //FINEST("%s", STR(buffer)); chunkSizeSize = 0; //3. Read the string which represents the number of bytes in the chunk for (uint32_t i = 0; i < GETAVAILABLEBYTESCOUNT(buffer) - 1; i++) { //5. Are we at the end of chunk size string? if ((pBuffer[i] == 0x0d) && (pBuffer[i + 1] == 0x0a)) { chunkSizeSize = i + 2; break; } //4. If the chunk size string has more than 10 bytes, we drop it like //is hot! Also test each char to be a hex number. //This is a bogus request/response if (i >= 10 || (!(((pBuffer[i] >= '0') && (pBuffer[i] <= '9')) || ((pBuffer[i] >= 'a') && (pBuffer[i] <= 'f')) || ((pBuffer[i] >= 'A') && (pBuffer[i] <= 'F'))))) { FATAL("Unable to read chunk size length:\n%s", STR(buffer)); return false; } } //7. Test the newly extracted chunk size if (chunkSizeSize == 0) { return true; } //8. Get its actual value and test it as well chunkSize = strtol((char *) pBuffer, NULL, 16); if (chunkSize > HTTP_MAX_CHUNK_SIZE) { FATAL("Chunk size too large. Maximum allowed is %" PRIu32 " and we got %" PRIu32, (uint32_t) HTTP_MAX_CHUNK_SIZE, chunkSize); return false; } //9. Now, we know the chunk size... do we have enough data? if (GETAVAILABLEBYTESCOUNT(buffer) < chunkSizeSize //length of the chunk size string - 2 //substract the 0x particle + 2 //the \r\n that follows the chunk size string + chunkSize //chunk size itself + 2 //the \r\n that follows the data chunk ) { return true; } //10. Update the session decoded bytes count and decoded bytes count _sessionDecodedBytesCount += chunkSize; _decodedBytesCount += chunkSize; if (chunkSize != 0) { //11. Make the copy _contentLength += chunkSize; _inputBuffer.ReadFromBuffer(GETIBPOINTER(buffer) + chunkSizeSize - 2 + 2, chunkSize); } else { //12. This was the last chunk (0 bytes size) _lastChunk = true; } //12. Call the near protocol if (!_pNearProtocol->SignalInputData(_inputBuffer)) { FATAL("Unable to call the next protocol in stack"); return false; } //13. Ignore the bytes from the input buffer DEBUG_HTTP("available bytes before ignore: %" PRIu32, GETAVAILABLEBYTESCOUNT(buffer)); // if (GETAVAILABLEBYTESCOUNT(buffer) == ((uint32_t) chunkSizeSize - 2 + 2 + chunkSize + 2)) { // DEBUG_HTTP("%s", STR(buffer)); // } buffer.Ignore((uint32_t) chunkSizeSize - 2 + 2 + chunkSize + 2); DEBUG_HTTP("available bytes after ignore: %" PRIu32, GETAVAILABLEBYTESCOUNT(buffer)); //14. reset the state if necessary if (TransferCompleted()) { _headers.Reset(); _chunkedContent = false; _lastChunk = false; _contentLength = 0; _state = HTTP_STATE_HEADERS; _sessionDecodedBytesCount = 0; return true; } } return true; }
bool BaseHTTPProtocol::SignalInputData(IOBuffer &buffer) { DEBUG_HTTP("-------------------"); DEBUG_HTTP("%s", STR(*this)); DEBUG_HTTP("_state: %s", (_state == HTTP_STATE_HEADERS) ? "HTTP_STATE_HEADERS" : (_state == HTTP_STATE_PAYLOAD) ? "HTTP_STATE_PAYLOAD" : "UNKNOWN"); //1. Get the first line and the headers if necessary if (_state == HTTP_STATE_HEADERS) { DEBUG_HTTP("Parse the headers"); if (!ParseHeaders(buffer)) { FATAL("Unable to read response headers: %s", STR(*this)); return false; } } DEBUG_HTTP("_continueAfterParseHeaders: %d", _continueAfterParseHeaders); if (!_continueAfterParseHeaders) return true; //2. Are we still in the "get headers state"? If so, wait for more data DEBUG_HTTP("new value of _state: %s", (_state == HTTP_STATE_HEADERS) ? "HTTP_STATE_HEADERS" : (_state == HTTP_STATE_PAYLOAD) ? "HTTP_STATE_PAYLOAD" : "UNKNOWN"); if (_state != HTTP_STATE_PAYLOAD) { return true; } DEBUG_HTTP("_chunkedContent: %d", _chunkedContent); //3. Turning point in processing if (_chunkedContent) { //4. We deal with chunked content DEBUG_HTTP("begin chunk content handling"); if (!HandleChunkedContent(buffer)) { FATAL("Unable to handle chunked content: %s", STR(*this)); return false; } } else { //5. We deal with length-specified type of content DEBUG_HTTP("begin fixed length content handling"); if (!HandleFixedLengthContent(buffer)) { FATAL("Unable to handle fixed length content: %s", STR(*this)); return false; } } //6. Are we in the get headers state? if so, we might have a new request //on the pipe. DEBUG_HTTP("brand new value of _state: %s", (_state == HTTP_STATE_HEADERS) ? "HTTP_STATE_HEADERS" : (_state == HTTP_STATE_PAYLOAD) ? "HTTP_STATE_PAYLOAD" : "UNKNOWN"); if (_state == HTTP_STATE_HEADERS) { DEBUG_HTTP("Call SignalInputData again"); //7. So, get to work again... return SignalInputData(buffer); } else { //8 We are done :) DEBUG_HTTP("Done"); return true; } }
static void parse_ignore_host(gpointer data, gpointer user_data) { gchar *hostname, *input, *netmask; gboolean ip_addr = FALSE, has_error = FALSE; struct in_addr host; #ifdef ENABLE_IPV6 struct in6_addr host6, mask6; gint i; #endif ProxyHostAddr *elt; input = (gchar *) data; elt = g_new0(ProxyHostAddr, 1); if ((netmask = strchr(input, '/')) != NULL) { hostname = g_strndup(input, netmask - input); ++netmask; } else { hostname = g_ascii_strdown(input, -1); } if (inet_pton(AF_INET, hostname, &host) > 0) { ip_addr = TRUE; elt->type = PROXY_IPv4; elt->addr.s_addr = host.s_addr; if (netmask) { gchar *endptr; gint width = strtol(netmask, &endptr, 10); if (*endptr != '\0' || width < 0 || width > 32) { has_error = TRUE; } elt->mask.s_addr = htonl(~0 << width); elt->addr.s_addr &= elt->mask.s_addr; } else { elt->mask.s_addr = 0xffffffff; } } #ifdef ENABLE_IPV6 else if (have_ipv6() && inet_pton(AF_INET6, hostname, &host6) > 0) { ip_addr = TRUE; elt->type = PROXY_IPv6; for (i = 0; i < 16; ++i) { elt->addr6.s6_addr[i] = host6.s6_addr[i]; } if (netmask) { gchar *endptr; gint width = strtol(netmask, &endptr, 10); if (*endptr != '\0' || width < 0 || width > 128) { has_error = TRUE; } for (i = 0; i < 16; ++i) { elt->mask6.s6_addr[i] = 0; } for (i = 0; i < width / 8; i++) { elt->mask6.s6_addr[i] = 0xff; } elt->mask6.s6_addr[i] = (0xff << (8 - width % 8)) & 0xff; ipv6_network_addr(&elt->addr6, &mask6, &elt->addr6); } else { for (i = 0; i < 16; ++i) { elt->mask6.s6_addr[i] = 0xff; } } } #endif if (ip_addr) { if (!has_error) { gchar *dst = g_new0(gchar, INET_ADDRSTRLEN); gl_ignore_addrs = g_slist_append(gl_ignore_addrs, elt); DEBUG_HTTP(("Host %s/%s does not go through proxy.", hostname, inet_ntop(AF_INET, &elt->mask, dst, INET_ADDRSTRLEN))); g_free(dst); } g_free(hostname); } else { /* It is a hostname. */ gl_ignore_hosts = g_slist_append(gl_ignore_hosts, hostname); DEBUG_HTTP(("Host %s does not go through proxy.", hostname)); g_free(elt); } }
static gboolean proxy_should_for_hostname(const char *hostname) { #ifdef ENABLE_IPV6 struct in6_addr in6, net6; #endif struct in_addr in; GSList *elt; ProxyHostAddr *addr; /* IPv4 address */ if (inet_pton(AF_INET, hostname, &in) > 0) { for (elt = gl_ignore_addrs; elt; elt = g_slist_next(elt)) { addr = (ProxyHostAddr *) (elt->data); if (addr->type == PROXY_IPv4 && (in.s_addr & addr->mask.s_addr) == addr->addr.s_addr) { DEBUG_HTTP(("Host %s using direct connection.", hostname)); return FALSE; } } } #ifdef ENABLE_IPV6 else if (have_ipv6() && inet_pton(AF_INET6, hostname, &in6)) { for (elt = gl_ignore_addrs; elt; elt = g_slist_next(elt)) { addr = (ProxyHostAddr *) (elt->data); ipv6_network_addr(&in6, &addr->mask6, &net6); if (addr->type == PROXY_IPv6 && IN6_ARE_ADDR_EQUAL(&net6, &addr->addr6)) { DEBUG_HTTP(("Host %s using direct connection.", hostname)); return FALSE; } /* Handle IPv6-wrapped IPv4 addresses. */ else if (addr->type == PROXY_IPv4 && IN6_IS_ADDR_V4MAPPED(&net6)) { guint32 v4addr; v4addr = net6.s6_addr[12] << 24 | net6. s6_addr[13] << 16 | net6. s6_addr[14] << 8 | net6.s6_addr[15]; if ((v4addr & addr->mask.s_addr) != addr->addr.s_addr) { DEBUG_HTTP(("Host %s using direct connection.", hostname)); return FALSE; } } } } #endif /* All hostnames (foo.bar.com) -- independent of IPv4 or IPv6 */ /* If there are IPv6 addresses in the ignore_hosts list but we do not * have IPv6 available at runtime, then those addresses will also fall * through to here (and harmlessly fail to match). */ else { gchar *hn = g_ascii_strdown(hostname, -1); for (elt = gl_ignore_hosts; elt; elt = g_slist_next(elt)) { if (*(gchar *) (elt->data) == '*') { if (g_str_has_suffix(hn, (gchar *) (elt->data) + 1)) { DEBUG_HTTP(("Host %s using direct connection.", hn)); g_free(hn); return FALSE; } } else if (strcmp(hn, elt->data) == 0) { DEBUG_HTTP(("Host %s using direct connection.", hn)); g_free(hn); return FALSE; } } g_free(hn); } return TRUE; }