File tsocks-1.8beta5-socks4a.diff of Package tsocks
diff -Naurd tsocks-1.8/README.socks4a tsocks-1.8-socks4a/README.socks4a
--- tsocks-1.8/README.socks4a 1970-01-01 01:00:00.000000000 +0100
+++ tsocks-1.8-socks4a/README.socks4a 2005-08-25 20:31:56.000000000 +0200
@@ -0,0 +1,12 @@
+To keep the patch small, the configure script was only modified in configure.in
+for the patch, so you first need to regenerate configure using
+'autoreconf -i -s'.
+gethostbyname and getaddrinfo are intercepted and return virtual addresses in
+the 127.0.0.0/8 space, which are translated back into domain names when sending
+socks connect requests. The domain names are saved in files located at
+~/.tsocks-socks4a/virtual-ips, and are not deleted automatically by tsocks.
+Therefore, a cron script tmpreaper-tsocks-socks4a.cron is provided to clean up
+unused domains after a week. tmpreaper
+(http://ftp.debian.org/debian/pool/main/t/tmpreaper) is needed to run the
+script.
+Send comments to eezyy@gmx.net
diff -Naurd tsocks-1.8/configure.in tsocks-1.8-socks4a/configure.in
--- tsocks-1.8/configure.in 2002-07-16 00:51:03.000000000 +0200
+++ tsocks-1.8-socks4a/configure.in 2005-08-25 20:20:55.000000000 +0200
@@ -327,6 +327,46 @@
AC_MSG_RESULT([poll(${PROTO})])
AC_DEFINE_UNQUOTED(POLL_SIGNATURE, [${PROTO}])
+dnl Find the correct getaddrinfo prototype on this machine
+AC_MSG_CHECKING(for correct getaddrinfo prototype)
+PROTO=
+for testproto in 'const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res'
+do
+ if test "${PROTO}" = ""; then
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int getaddrinfo($testproto);
+ ],,[PROTO="$testproto";],)
+ fi
+done
+if test "${PROTO}" = ""; then
+ AC_MSG_ERROR("no match found!")
+fi
+AC_MSG_RESULT([getaddrinfo(${PROTO})])
+AC_DEFINE_UNQUOTED(GETADDRINFO_SIGNATURE, [${PROTO}],
+ [calling signature for getaddrinfo()])
+
+dnl Find the correct gethostbyname prototype on this machine
+AC_MSG_CHECKING(for correct gethostbyname prototype)
+PROTO=
+for testproto in 'const char *name'
+do
+ if test "${PROTO}" = ""; then
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ struct hostent *gethostbyname($testproto);
+ ],,[PROTO="$testproto";],)
+ fi
+done
+if test "${PROTO}" = ""; then
+ AC_MSG_ERROR("no match found!")
+fi
+AC_MSG_RESULT([gethostbyname(${PROTO})])
+AC_DEFINE_UNQUOTED(GETHOSTBYNAME_SIGNATURE, [${PROTO}],
+ [calling signature for gethostbyname()])
+
dnl Output the special librarys (libdl etc needed for tsocks)
SPECIALLIBS=${LIBS}
AC_SUBST(SPECIALLIBS)
diff -Naurd tsocks-1.8/parser.c tsocks-1.8-socks4a/parser.c
--- tsocks-1.8/parser.c 2002-03-13 13:34:22.000000000 +0100
+++ tsocks-1.8-socks4a/parser.c 2005-08-25 20:20:55.000000000 +0200
@@ -31,7 +31,7 @@
static int handle_local(struct parsedfile *, int, char *);
static int handle_defuser(struct parsedfile *, int, char *);
static int handle_defpass(struct parsedfile *, int, char *);
-static int make_netent(char *value, struct netent **ent);
+static int make_netent(char *value, struct tsocks_netent **ent);
int read_config (char *filename, struct parsedfile *config) {
FILE *conf;
@@ -75,7 +75,7 @@
fclose(conf);
/* Always add the 127.0.0.1/255.0.0.0 subnet to local */
- handle_local(config, 0, "127.0.0.0/255.0.0.0");
+ handle_local(config, 0, "127.0.0.1/255.255.255.255");
/* Check default server */
check_server(&(config->defaultserver));
@@ -242,7 +242,7 @@
static int handle_reaches(struct parsedfile *config, int lineno, char *value) {
int rc;
- struct netent *ent;
+ struct tsocks_netent *ent;
rc = make_netent(value, &ent);
switch(rc) {
@@ -420,7 +420,7 @@
static int handle_local(struct parsedfile *config, int lineno, char *value) {
int rc;
- struct netent *ent;
+ struct tsocks_netent *ent;
if (currentcontext != &(config->defaultserver)) {
show_msg(MSGERR, "Local networks cannot be specified in path "
@@ -485,7 +485,7 @@
/* Construct a netent given a string like */
/* "198.126.0.1[:portno[-portno]]/255.255.255.0" */
-int make_netent(char *value, struct netent **ent) {
+int make_netent(char *value, struct tsocks_netent **ent) {
char *ip;
char *subnet;
char *startport = NULL;
@@ -517,7 +517,7 @@
}
/* Allocate the new entry */
- if ((*ent = (struct netent *) malloc(sizeof(struct netent)))
+ if ((*ent = (struct tsocks_netent *) malloc(sizeof(struct tsocks_netent)))
== NULL) {
/* If we couldn't malloc some storage, leave */
exit(1);
@@ -578,7 +578,7 @@
}
int is_local(struct parsedfile *config, struct in_addr *testip) {
- struct netent *ent;
+ struct tsocks_netent *ent;
for (ent = (config->localnets); ent != NULL; ent = ent -> next) {
if ((testip->s_addr & ent->localnet.s_addr) ==
@@ -593,7 +593,7 @@
/* Find the appropriate server to reach an ip */
int pick_server(struct parsedfile *config, struct serverent **ent,
struct in_addr *ip, unsigned int port) {
- struct netent *net;
+ struct tsocks_netent *net;
char ipbuf[64];
show_msg(MSGDEBUG, "Picking appropriate server for %s\n", inet_ntoa(*ip));
diff -Naurd tsocks-1.8/parser.h tsocks-1.8-socks4a/parser.h
--- tsocks-1.8/parser.h 2002-02-10 08:26:27.000000000 +0100
+++ tsocks-1.8-socks4a/parser.h 2005-08-25 20:20:56.000000000 +0200
@@ -15,22 +15,22 @@
int type; /* Type of server (4/5) */
char *defuser; /* Default username for this socks server */
char *defpass; /* Default password for this socks server */
- struct netent *reachnets; /* Linked list of nets from this server */
+ struct tsocks_netent *reachnets; /* Linked list of nets from this server */
struct serverent *next; /* Pointer to next server entry */
};
/* Structure representing a network */
-struct netent {
+struct tsocks_netent {
struct in_addr localip; /* Base IP of the network */
struct in_addr localnet; /* Mask for the network */
unsigned long startport; /* Range of ports for the */
unsigned long endport; /* network */
- struct netent *next; /* Pointer to next network entry */
+ struct tsocks_netent *next; /* Pointer to next network entry */
};
/* Structure representing a complete parsed file */
struct parsedfile {
- struct netent *localnets;
+ struct tsocks_netent *localnets;
struct serverent defaultserver;
struct serverent *paths;
};
diff -Naurd tsocks-1.8/tmpreaper-tsocks-socks4a.cron tsocks-1.8-socks4a/tmpreaper-tsocks-socks4a.cron
--- tsocks-1.8/tmpreaper-tsocks-socks4a.cron 1970-01-01 01:00:00.000000000 +0100
+++ tsocks-1.8-socks4a/tmpreaper-tsocks-socks4a.cron 2005-08-25 20:20:56.000000000 +0200
@@ -0,0 +1,3 @@
+#!/bin/sh
+/usr/sbin/tmpreaper 168 `locate tsocks-socks4a/clean|sed\
+ 's/clean$/virtual-ips/'`
diff -Naurd tsocks-1.8/tsocks.c tsocks-1.8-socks4a/tsocks.c
--- tsocks-1.8/tsocks.c 2002-07-16 00:50:52.000000000 +0200
+++ tsocks-1.8-socks4a/tsocks.c 2005-08-30 18:03:47.000000000 +0200
@@ -51,6 +51,8 @@
#ifdef USE_SOCKS_DNS
#include <resolv.h>
#endif
+#include <netdb.h>
+#include <time.h>
#include <parser.h>
#include <tsocks.h>
@@ -58,6 +60,8 @@
#ifdef USE_SOCKS_DNS
static int (*realresinit)(void);
#endif
+static int (*realgetaddrinfo)(GETADDRINFO_SIGNATURE);
+static struct hostent*(*realgethostbyname)(GETHOSTBYNAME_SIGNATURE);
static int (*realconnect)(CONNECT_SIGNATURE);
static int (*realselect)(SELECT_SIGNATURE);
static int (*realpoll)(POLL_SIGNATURE);
@@ -66,9 +70,13 @@
static struct connreq *requests = NULL;
static int suid = 0;
static char *conffile = NULL;
+static char *proxy_directory = NULL;
+static int filename_length;
/* Exported Function Prototypes */
void _init(void);
+int getaddrinfo(GETADDRINFO_SIGNATURE);
+struct hostent *gethostbyname(GETHOSTBYNAME_SIGNATURE);
int connect(CONNECT_SIGNATURE);
int select(SELECT_SIGNATURE);
int poll(POLL_SIGNATURE);
@@ -99,8 +107,13 @@
static int read_socksv4_req(struct connreq *conn);
static int read_socksv5_connect(struct connreq *conn);
static int read_socksv5_auth(struct connreq *conn);
+static char*virtual_resolved_ip(const char*domain);
+static int is_numeric_address(const char*domain);
void _init(void) {
+ char*directory_suffix="/.tsocks-socks4a/virtual-ips";
+ char*home=getenv("HOME");
+ char*after_home;
#ifdef USE_OLD_DLSYM
void *lib;
#endif
@@ -113,6 +126,8 @@
suid = (getuid() != geteuid());
#ifndef USE_OLD_DLSYM
+ realgetaddrinfo = dlsym(RTLD_NEXT, "getaddrinfo");
+ realgethostbyname = dlsym(RTLD_NEXT, "gethostbyname");
realconnect = dlsym(RTLD_NEXT, "connect");
realselect = dlsym(RTLD_NEXT, "select");
realpoll = dlsym(RTLD_NEXT, "poll");
@@ -122,6 +137,8 @@
#endif
#else
lib = dlopen(LIBCONNECT, RTLD_LAZY);
+ realgetaddrinfo = dlsym(lib, "getaddrinfo");
+ realgethostbyname = dlsym(lib, "gethostbyname");
realconnect = dlsym(lib, "connect");
realselect = dlsym(lib, "select");
realpoll = dlsym(lib, "poll");
@@ -134,6 +151,18 @@
realclose = dlsym(lib, "close");
dlclose(lib);
#endif
+ srandom(time(0));
+ proxy_directory=malloc(strlen(home)+strlen(directory_suffix)+1);
+ strcpy(proxy_directory,home);
+ after_home=proxy_directory+strlen(home);
+ strcpy(after_home,"/.tsocks-socks4a");
+ mkdir(proxy_directory,0777);
+ strcpy(after_home,"/.tsocks-socks4a/clean");
+ close(creat(proxy_directory,0666));
+ strcpy(after_home,directory_suffix);
+ mkdir(proxy_directory,0777);
+ filename_length=strlen(proxy_directory)+
+ strlen("/127.255.255.255")+1;
}
static int get_environment() {
@@ -187,6 +216,66 @@
}
+char*virtual_resolved_ip(const char*domain) {
+ int proxy_address[3]={0,0,1};
+ int digit;
+ int host_file_descriptor;
+ char*filename;
+ struct stat file_info;
+ size_t name_size;
+ filename=malloc(filename_length);
+ if(strcmp("localhost",domain)) {
+ do {
+ do
+ for(digit=0;digit<3;digit++)
+ proxy_address[digit]=random()%255;
+ while(proxy_address[0]==0&&proxy_address[1]==0&&proxy_address[2]==1);
+ snprintf(filename,filename_length,"%s/127.%d.%d.%d",proxy_directory,
+ proxy_address[0],proxy_address[1],proxy_address[2]);
+ } while(!stat(filename,&file_info));
+ host_file_descriptor=creat(filename,0666);
+ name_size=strlen(domain)+1;
+ write(host_file_descriptor,&name_size,sizeof(name_size));
+ write(host_file_descriptor,domain,name_size);
+ close(host_file_descriptor);
+ }
+ snprintf(filename,filename_length,"127.%d.%d.%d",proxy_address[0],
+ proxy_address[1],proxy_address[2]);
+ return filename;
+}
+
+int is_numeric_address(const char*domain) {
+ char*scanned;
+ for(scanned=domain;*scanned;scanned++)
+ if(((*scanned<'0')||(*scanned>'9'))&&*scanned!='.')
+ return 0;
+ return 1;
+}
+
+int getaddrinfo(GETADDRINFO_SIGNATURE) {
+ int result;
+ if(is_numeric_address(node))
+ result=(*realgetaddrinfo)(node,service,hints,res);
+ else {
+ char*filename=virtual_resolved_ip(node);
+ result=(*realgetaddrinfo)(filename,service,hints,res);
+ free(filename);
+ }
+ return result;
+}
+
+struct hostent*gethostbyname(GETHOSTBYNAME_SIGNATURE) {
+ struct hostent*result;
+ if(is_numeric_address(name))
+ result=(*realgethostbyname)(name);
+ else {
+ char*filename=virtual_resolved_ip(name);
+ result=(*realgethostbyname)(filename);
+ free(filename);
+ }
+ return result;
+}
+
int connect(CONNECT_SIGNATURE) {
struct sockaddr_in *connaddr;
struct sockaddr_in peer_address;
@@ -883,16 +972,33 @@
static int send_socksv4_request(struct connreq *conn) {
struct passwd *user;
struct sockreq *thisreq;
-
+ char*filename;
+ char*hostname=NULL;
+ int host_file_descriptor;
+ size_t hostname_length;
+ char*username;
/* Determine the current username */
user = getpwuid(getuid());
thisreq = (struct sockreq *) conn->buffer;
-
- /* Check the buffer has enough space for the request */
- /* and the user name */
+ filename=malloc(filename_length);
+ snprintf(filename,filename_length,"%s/%d.%d.%d.%d",proxy_directory,
+ ((unsigned char*)(&conn->connaddr.sin_addr.s_addr))[0],
+ ((unsigned char*)(&conn->connaddr.sin_addr.s_addr))[1],
+ ((unsigned char*)(&conn->connaddr.sin_addr.s_addr))[2],
+ ((unsigned char*)(&conn->connaddr.sin_addr.s_addr))[3]);
+ host_file_descriptor=open(filename,O_RDONLY);
+ if(-1!=host_file_descriptor) {
+ read(host_file_descriptor,&hostname_length,sizeof(hostname_length));
+ hostname=malloc(hostname_length);
+ read(host_file_descriptor,hostname,hostname_length);
+ close(host_file_descriptor);
+ }
+ /* Check the buffer has enough space for the request, */
+ /* the user name and the hostname */
conn->datalen = sizeof(struct sockreq) +
- (user == NULL ? 0 : strlen(user->pw_name)) + 1;
+ (user == NULL ? 0 : strlen(user->pw_name)) +
+ (hostname == NULL ? 0 : hostname_length) + 1;
if (sizeof(conn->buffer) < conn->datalen) {
show_msg(MSGERR, "The SOCKS username is too long");
conn->state = FAILED;
@@ -903,11 +1009,15 @@
thisreq->version = 4;
thisreq->command = 1;
thisreq->dstport = conn->connaddr.sin_port;
- thisreq->dstip = conn->connaddr.sin_addr.s_addr;
+ thisreq->dstip = hostname ? htonl(1) : conn->connaddr.sin_addr.s_addr;
/* Copy the username */
- strcpy((char *) thisreq + sizeof(struct sockreq),
- (user == NULL ? "" : user->pw_name));
+ username=(user == NULL ? "" : user->pw_name);
+ strcpy((char *) thisreq + sizeof(struct sockreq), username);
+
+ if(hostname)
+ strcpy((char *) thisreq + sizeof(struct sockreq) +
+ strlen(username) + 1, hostname);
conn->datadone = 0;
conn->state = SENDING;
diff -Naurd tsocks-1.8/validateconf.c tsocks-1.8-socks4a/validateconf.c
--- tsocks-1.8/validateconf.c 2002-02-07 11:49:59.000000000 +0100
+++ tsocks-1.8-socks4a/validateconf.c 2005-08-25 20:20:56.000000000 +0200
@@ -126,7 +126,7 @@
}
void show_conf(struct parsedfile *config) {
- struct netent *net;
+ struct tsocks_netent *net;
struct serverent *server;
/* Show the local networks */
@@ -168,7 +168,7 @@
void show_server(struct parsedfile *config, struct serverent *server, int def) {
struct in_addr res;
- struct netent *net;
+ struct tsocks_netent *net;
/* Show address */
if (server->address != NULL)