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) 
openSUSE Build Service is sponsored by