comparison libpurple/proxy.c @ 25480:e859785b49d8

Implement support for resolving DNS via the SOCKS4 proxy in use. Currently this relies on a global preference, which I'm not super happy about. Ideally, we'd just try to always do this and fall back to a local DNS lookup when the SOCKS4 server doesn't like it, but I don't think we can reliably detect that. Fixes #3230
author Daniel Atallah <daniel.atallah@gmail.com>
date Tue, 17 Feb 2009 23:42:49 +0000
parents 8fa011906ac3
children 4b8c4870b13a
comparison
equal deleted inserted replaced
25479:8fa011906ac3 25480:e859785b49d8
1199 /* Discard the length... */ 1199 /* Discard the length... */
1200 hosts = g_slist_delete_link(hosts, hosts); 1200 hosts = g_slist_delete_link(hosts, hosts);
1201 addr = hosts->data; 1201 addr = hosts->data;
1202 hosts = g_slist_delete_link(hosts, hosts); 1202 hosts = g_slist_delete_link(hosts, hosts);
1203 1203
1204 packet[0] = 4; 1204 packet[0] = 0x04;
1205 packet[1] = 1; 1205 packet[1] = 0x01;
1206 packet[2] = connect_data->port >> 8; 1206 packet[2] = connect_data->port >> 8;
1207 packet[3] = connect_data->port & 0xff; 1207 packet[3] = connect_data->port & 0xff;
1208 memcpy(packet + 4, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4); 1208 memcpy(packet + 4, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4);
1209 packet[8] = 0; 1209 packet[8] = 0x00;
1210 1210
1211 g_free(addr); 1211 g_free(addr);
1212 1212
1213 /* We could try the other hosts, but hopefully that shouldn't be necessary */ 1213 /* We could try the other hosts, but hopefully that shouldn't be necessary */
1214 while (hosts != NULL) { 1214 while (hosts != NULL) {
1250 purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); 1250 purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
1251 return; 1251 return;
1252 } 1252 }
1253 1253
1254 /* 1254 /*
1255 * The socks4 spec doesn't include support for doing host name 1255 * The socks4 spec doesn't include support for doing host name lookups by
1256 * lookups by the proxy. Some socks4 servers do this via 1256 * the proxy. Many socks4 servers do this via the "socks4a" extension to
1257 * extensions to the protocol. Since we don't know if a 1257 * the protocol. There doesn't appear to be a way to detect if a server
1258 * server supports this, it would need to be implemented 1258 * supports this, so we require that the user set a global option.
1259 * with an option, or some detection mechanism - in the
1260 * meantime, stick with plain old SOCKS4.
1261 */ 1259 */
1262 connect_data->query_data = purple_dnsquery_a(connect_data->host, 1260 if (purple_prefs_get_bool("/purple/proxy/socks4_remotedns")) {
1263 connect_data->port, s4_host_resolved, connect_data); 1261 unsigned char packet[9];
1264 1262 int len;
1265 if (connect_data->query_data == NULL) { 1263
1266 purple_debug_error("proxy", "dns query failed unexpectedly.\n"); 1264 purple_debug_info("socks4 proxy", "Attempting to use remote DNS.\n");
1267 purple_proxy_connect_data_destroy(connect_data); 1265
1266 packet[0] = 0x04;
1267 packet[1] = 0x01;
1268 packet[2] = connect_data->port >> 8;
1269 packet[3] = connect_data->port & 0xff;
1270 packet[4] = 0x00;
1271 packet[5] = 0x00;
1272 packet[6] = 0x00;
1273 packet[7] = 0x01;
1274 packet[8] = 0x00;
1275
1276 len = sizeof(packet) + strlen(connect_data->host) + 1;
1277
1278 connect_data->write_buffer = g_malloc0(len);
1279 memcpy(connect_data->write_buffer, packet, sizeof(packet));
1280 memcpy(connect_data->write_buffer + sizeof(packet), connect_data->host, strlen(connect_data->host));
1281 connect_data->write_buf_len = len;
1282 connect_data->written_len = 0;
1283 connect_data->read_cb = s4_canread;
1284
1285 connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data);
1286
1287 proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
1288 } else {
1289 connect_data->query_data = purple_dnsquery_a(connect_data->host,
1290 connect_data->port, s4_host_resolved, connect_data);
1291
1292 if (connect_data->query_data == NULL) {
1293 purple_debug_error("proxy", "dns query failed unexpectedly.\n");
1294 purple_proxy_connect_data_destroy(connect_data);
1295 }
1268 } 1296 }
1269 } 1297 }
1270 1298
1271 static void 1299 static void
1272 proxy_connect_socks4(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) 1300 proxy_connect_socks4(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen)
2321 purple_prefs_add_string("/purple/proxy/type", "none"); 2349 purple_prefs_add_string("/purple/proxy/type", "none");
2322 purple_prefs_add_string("/purple/proxy/host", ""); 2350 purple_prefs_add_string("/purple/proxy/host", "");
2323 purple_prefs_add_int("/purple/proxy/port", 0); 2351 purple_prefs_add_int("/purple/proxy/port", 0);
2324 purple_prefs_add_string("/purple/proxy/username", ""); 2352 purple_prefs_add_string("/purple/proxy/username", "");
2325 purple_prefs_add_string("/purple/proxy/password", ""); 2353 purple_prefs_add_string("/purple/proxy/password", "");
2354 purple_prefs_add_bool("/purple/proxy/socks4_remotedns", FALSE);
2326 2355
2327 /* Setup callbacks for the preferences. */ 2356 /* Setup callbacks for the preferences. */
2328 handle = purple_proxy_get_handle(); 2357 handle = purple_proxy_get_handle();
2329 purple_prefs_connect_callback(handle, "/purple/proxy/type", proxy_pref_cb, 2358 purple_prefs_connect_callback(handle, "/purple/proxy/type", proxy_pref_cb,
2330 NULL); 2359 NULL);