commit f4f9ee87e4ab0aec3ce683c9be0131e68da96688 Author: David Goulet dgoulet@ev0ke.net Date: Mon Mar 31 21:23:51 2014 -0400
Delete old source directory
Signed-off-by: David Goulet dgoulet@ev0ke.net --- src.old/Makefile.am | 18 - src.old/common.c | 224 --------- src.old/common.h | 104 ----- src.old/darwin_warts.c | 59 --- src.old/dead_pool.c | 805 -------------------------------- src.old/dead_pool.h | 67 --- src.old/expansion_table.h | 125 ----- src.old/parser.c | 872 ----------------------------------- src.old/parser.h | 69 --- src.old/socks.c | 633 -------------------------- src.old/socks.h | 116 ----- src.old/torsocks.c | 1108 --------------------------------------------- src.old/torsocks.in | 167 ------- src.old/usewithtor.in | 113 ----- 14 files changed, 4480 deletions(-)
diff --git a/src.old/Makefile.am b/src.old/Makefile.am deleted file mode 100644 index e3a01c9..0000000 --- a/src.old/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -# Makefile used by configure to create real Makefile - -libdir = @libdir@/torsocks - -# Install invocation scripts -bin_SCRIPTS = torsocks usewithtor -INSTALL_SCRIPT = $(install_sh) -c -m 755 - -libtorsocks_la_LDFLAGS= $(TORSOCKSLDFLAGS) -# Install main library to $(prefix)/lib/tor (must match torsocks.in) -lib_LTLIBRARIES = libtorsocks.la -libtorsocks_la_SOURCES = torsocks.c common.c parser.c dead_pool.c darwin_warts.c socks.c\ - common.h dead_pool.h expansion_table.h parser.h socks.h - -DISTCLEANFILES=parser.lo dead_pool.lo common.lo libtorsocks.lo torsocks.lo darwin_warts.lo socks.lo\ - config.cache config.log config.h Makefile \ - aclocal.m4 config.status usewithtor torsocks \ - autom4te.cache .libs .deps diff --git a/src.old/common.c b/src.old/common.c deleted file mode 100644 index 8fe3303..0000000 --- a/src.old/common.c +++ /dev/null @@ -1,224 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2000-2008 Shaun Clowes delius@progsoc.org * - * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * * - * Some code taken from Tor: * - * Copyright (c) 2003, Roger Dingledine * - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. * - * Copyright (c) 2007-2008, The Tor Project, Inc. * - * * - ***************************************************************************/ -/* - - commmon.c - Common routines for the torsocks package - -*/ - -#include <config.h> -#include <stdio.h> -#include <netdb.h> -#include <stdarg.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <arpa/inet.h> -#include <sys/types.h> -#include <netinet/in.h> - -#include "common.h" - -/* Globals */ -int loglevel = MSGERR; /* The default logging level is to only log - error messages */ -char logfilename[256]; /* Name of file to which log messages should - be redirected */ -FILE *logfile = NULL; /* File to which messages should be logged */ -int logstamp = 0; /* Timestamp (and pid stamp) messages */ - - -/** - * Read a 16-bit value beginning at <b>cp</b>. Equivalent to - * *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid - * unaligned memory access. - */ -uint16_t -get_uint16(const char *cp) -{ - uint16_t v; - memcpy(&v,cp,2); - return v; -} -/** - * Read a 32-bit value beginning at <b>cp</b>. Equivalent to - * *(uint32_t*)(cp), but will not cause segfaults on platforms that forbid - * unaligned memory access. - */ -uint32_t -get_uint32(const char *cp) -{ - uint32_t v; - memcpy(&v,cp,4); - return v; -} -/** - * Set a 16-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to - * *(uint16_t)(cp) = v, but will not cause segfaults on platforms that forbid - * unaligned memory access. */ -void -set_uint16(char *cp, uint16_t v) -{ - memcpy(cp,&v,2); -} -/** - * Set a 32-bit value beginning at <b>cp</b> to <b>v</b>. Equivalent to - * *(uint32_t)(cp) = v, but will not cause segfaults on platforms that forbid - * unaligned memory access. */ -void -set_uint32(char *cp, uint32_t v) -{ - memcpy(cp,&v,4); -} - -unsigned int resolve_ip(char *host, int showmsg, int allownames) { - struct hostent *new; - unsigned int hostaddr; - struct in_addr *ip; - - if ((hostaddr = inet_addr(host)) == (unsigned int) -1) { - /* We couldn't convert it as a numerical ip so */ - /* try it as a dns name */ - if (allownames) { - #ifdef HAVE_GETHOSTBYNAME - if ((new = gethostbyname(host)) == (struct hostent *) 0) { - #endif - return(0); - #ifdef HAVE_GETHOSTBYNAME - } else { - ip = ((struct in_addr *) * new->h_addr_list); - hostaddr = ip -> s_addr; - if (showmsg) - printf("Connecting to %s...\n", inet_ntoa(*ip)); - } - #endif - } else - return(0); - } - - return (hostaddr); -} - -/* Set logging options, the options are as follows: */ -/* level - This sets the logging threshold, messages with */ -/* a higher level (i.e lower importance) will not be */ -/* output. For example, if the threshold is set to */ -/* MSGWARN a call to log a message of level MSGDEBUG */ -/* would be ignored. This can be set to -1 to disable */ -/* messages entirely */ -/* filename - This is a filename to which the messages should */ -/* be logged instead of to standard error */ -/* timestamp - This indicates that messages should be prefixed */ -/* with timestamps (and the process id) */ -void set_log_options(int level, char *filename, int timestamp) { - - loglevel = level; - if (loglevel < MSGERR) - loglevel = MSGNONE; - - if (filename) { - strncpy(logfilename, filename, sizeof(logfilename)); - logfilename[sizeof(logfilename) - 1] = '\0'; - } - - logstamp = timestamp; -} - -/* Count the bits in a netmask. This is a little bit buggy; it assumes - all the zeroes are on the right... */ - -int count_netmask_bits(uint32_t mask) -{ - int i; - int nbits = 0; - - for(i=0; i<32; i++) { - if((mask >> i) & 1) { - nbits++; - } - } - mask = ~mask; - mask = ntohl(mask); - if(mask & (mask+1)) { - return -1; /* Noncontiguous */ - } - return nbits; -} - -void show_msg(int level, const char *fmt, ...) { - va_list ap; - int saveerr; - extern char *torsocks_progname; - char timestring[20]; - time_t timestamp; - - if ((loglevel == MSGNONE) || (level > loglevel)) - return; - - if (!logfile) { - if (logfilename[0]) { - logfile = fopen(logfilename, "a"); - if (logfile == NULL) { - logfile = stderr; - show_msg(MSGERR, "Could not open log file, %s, %s\n", - logfilename, strerror(errno)); - } - } else - logfile = stderr; - } - - if (logstamp) { - timestamp = time(NULL); - strftime(timestring, sizeof(timestring), "%H:%M:%S", - localtime(×tamp)); - fprintf(logfile, "%s ", timestring); - } - - fputs(torsocks_progname, logfile); - - if (logstamp) { - fprintf(logfile, "(%d)", getpid()); - } - - fputs(": ", logfile); - - va_start(ap, fmt); - - /* Save errno */ - saveerr = errno; - - vfprintf(logfile, fmt, ap); - - fflush(logfile); - - errno = saveerr; - - va_end(ap); -} - diff --git a/src.old/common.h b/src.old/common.h deleted file mode 100644 index f84a2f7..0000000 --- a/src.old/common.h +++ /dev/null @@ -1,104 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2000-2008 Shaun Clowes delius@progsoc.org * - * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -/* Common functions provided in common.c */ -/* GCC has several useful attributes. */ -#include <sys/types.h> - -#if defined(__GNUC__) && __GNUC__ >= 3 -#define ATTR_NORETURN __attribute__((noreturn)) -#define ATTR_PURE __attribute__((pure)) -#define ATTR_CONST __attribute__((const)) -#define ATTR_MALLOC __attribute__((malloc)) -#define ATTR_NORETURN __attribute__((noreturn)) -#define ATTR_NONNULL(x) __attribute__((nonnull x)) -/** Macro: Evaluates to <b>exp</b> and hints the compiler that the value - * of <b>exp</b> will probably be true. */ -#define PREDICT_LIKELY(exp) __builtin_expect((exp), 1) -/** Macro: Evaluates to <b>exp</b> and hints the compiler that the value - * of <b>exp</b> will probably be false. */ -#define PREDICT_UNLIKELY(exp) __builtin_expect((exp), 0) -#else -#define ATTR_NORETURN -#define ATTR_PURE -#define ATTR_CONST -#define ATTR_MALLOC -#define ATTR_NORETURN -#define ATTR_NONNULL(x) -#define PREDICT_LIKELY(exp) (exp) -#define PREDICT_UNLIKELY(exp) (exp) -#endif - -/** Try to find the symbol that is either m or __m. - * If one of them exists, in that order, then save its address in r, - * otherwise we want to print a message at log level l stating that - * we could not find it. - */ -#define torsocks_find_library(m,l,r) \ - do { \ - char * dl_error_msg = ""; \ - char * dl_error_msg2 = ""; \ - dlerror(); \ - if ((r = dlsym(RTLD_NEXT, m)) == NULL) { \ - dl_error_msg = dlerror(); \ - if (dl_error_msg != NULL) { \ - dl_error_msg = strdup(dl_error_msg); \ - } \ - if ((r = dlsym(RTLD_NEXT, "__" m)) == NULL) { \ - dl_error_msg2 = dlerror(); \ - show_msg(l, "WARNING: The symbol %s() was not found in any shared " \ - "library with the reported error: %s!\n" \ - " Also, we failed to find the symbol %s() with the reported error:" \ - " %s\n", m, (dl_error_msg ? dl_error_msg : "Not Found"), \ - "__"m, (dl_error_msg2 ? dl_error_msg2 : "Not Found")); \ - } \ - if (dl_error_msg) \ - free(dl_error_msg); \ - } \ - } while (0) - -uint16_t get_uint16(const char *cp) ATTR_PURE ATTR_NONNULL((1)); -uint32_t get_uint32(const char *cp) ATTR_PURE ATTR_NONNULL((1)); -void set_uint16(char *cp, uint16_t v) ATTR_NONNULL((1)); -void set_uint32(char *cp, uint32_t v) ATTR_NONNULL((1)); - -int is_internal_IP(uint32_t ip, int for_listening) ATTR_PURE; -int parse_addr_port(int severity, const char *addrport, char **address, - uint32_t *addr, uint16_t *port_out); - -void set_log_options(int, char *, int); -void show_msg(int level, const char *, ...); -int count_netmask_bits(uint32_t mask); -unsigned int resolve_ip(char *, int, int); - -#define MSGNONE -1 -#define MSGERR 0 -#define MSGWARN 1 -#define MSGTEST 2 -#define MSGNOTICE 3 -#define MSGDEBUG 3 - -/* Required by some BSDs */ -#ifndef MAP_ANONYMOUS -#ifdef MAP_ANON -#define MAP_ANONYMOUS MAP_ANON -#endif -#endif diff --git a/src.old/darwin_warts.c b/src.old/darwin_warts.c deleted file mode 100644 index 65bdd04..0000000 --- a/src.old/darwin_warts.c +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2010 Alex Rosenberg alex@ohmantics.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -/* Mac OS X 10.6 forces any function named "select" to be named "_select$1050" - * in the output to the assembler. We need to patch select as well, so this - * isolated code exists without tripping over the Darwin header that causes the - * probkem. - */ - -#if defined(__APPLE__) || defined(__darwin__) - -#include <AvailabilityMacros.h> - -#if defined(MAC_OS_X_VERSION_10_6) - -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> -#include <dlfcn.h> -#include <string.h> -#include <errno.h> -#include "common.h" - -#define SELECT_SIGNATURE int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout -#define SELECT_ARGNAMES n, readfds, writefds, exceptfds, timeout - -/* forward declare opaque structures instead of bringing in real Darwin decls. */ -typedef struct fd_set fd_set; -struct timeval; - -int (*realselect)(SELECT_SIGNATURE); -int torsocks_select_guts(SELECT_SIGNATURE, int (*original_select)(SELECT_SIGNATURE)); - -int select(SELECT_SIGNATURE) { - if (!realselect) { - torsocks_find_library("select", MSGERR, realselect); - } - return torsocks_select_guts(SELECT_ARGNAMES, realselect); -} - -#endif /* 10.6 */ -#endif /* darwin */ diff --git a/src.old/dead_pool.c b/src.old/dead_pool.c deleted file mode 100644 index 13e5740..0000000 --- a/src.old/dead_pool.c +++ /dev/null @@ -1,805 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2005 Total Information Security Ltd. * - * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include <stdio.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> - -#include "common.h" -#include "dead_pool.h" - -int store_pool_entry(dead_pool *pool, char *hostname, struct in_addr *addr); -void get_next_dead_address(dead_pool *pool, uint32_t *result); - -static int -do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, - uint32_t *result_addr, const void *addr, - int version, int reverse, char **result_hostname); - -/* Compares the last strlen(s2) characters of s1 with s2. Returns as for - strcasecmp. */ -static int -strcasecmpend(const char *s1, const char *s2) -{ - size_t n1 = strlen(s1), n2 = strlen(s2); - if (n2>n1) /* then they can't be the same; figure out which is bigger */ - return strcasecmp(s1,s2); - else - return strncasecmp(s1+(n1-n2), s2, n2); -} - -dead_pool * -init_pool(unsigned int pool_size, struct in_addr deadrange_base, - struct in_addr deadrange_mask, char *sockshost, uint16_t socksport) -{ - unsigned int i, deadrange_size, deadrange_width; - int deadrange_bits; - struct in_addr socks_server; - dead_pool *newpool = NULL; - - /* Count bits in netmask and determine deadrange width. */ - deadrange_bits = count_netmask_bits(deadrange_mask.s_addr); - if(deadrange_bits == -1) { - show_msg(MSGERR, "init_pool: invalid netmask for deadrange\n"); - return NULL; - } - deadrange_width = 32 - deadrange_bits; - - show_msg(MSGDEBUG, "deadrange width is %d bits\n", deadrange_width); - - /* Now work out how many IPs are available in the deadrange and check - that this number makes sense. If the deadpool is bigger than the - deadrange we shrink the pool. */ - - for(i=0, deadrange_size = 1; i < deadrange_width; i++) { - deadrange_size *= 2; - } - - if(deadrange_size < pool_size) { - show_msg(MSGWARN, "tordns cache size was %d, but deadrange size is %d: " - "shrinking pool size to %d entries\n", pool_size, - deadrange_size, deadrange_size); - pool_size = deadrange_size; - } - if(pool_size < 1) { - show_msg(MSGERR, "tordns cache size is 0, disabling tordns\n"); - return NULL; - } - - /* Allocate space for the dead_pool structure */ - newpool = (dead_pool *) mmap(0, sizeof(dead_pool), - PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if(!newpool) { - show_msg(MSGERR, "init_pool: unable to mmap deadpool " - "(tried to map %d bytes)\n", sizeof(dead_pool)); - return NULL; - } - - show_msg(MSGDEBUG, "init_pool: sockshost %s \n", sockshost); - - /* Initialize the dead_pool structure */ -#ifdef HAVE_INET_ATON - inet_aton(sockshost, &socks_server); -#elif defined(HAVE_INET_ADDR) - socks_server.s_addr = inet_addr(sockshost); -#endif - newpool->sockshost = ntohl(socks_server.s_addr); - newpool->socksport = socksport; - newpool->deadrange_base = ntohl(deadrange_base.s_addr); - newpool->deadrange_mask = ntohl(deadrange_mask.s_addr); - newpool->deadrange_size = deadrange_size; - newpool->write_pos = 0; - newpool->dead_pos = 0; - newpool->n_entries = pool_size; - - /* Allocate space for the entries */ - newpool->entries = (pool_ent *) mmap(0, newpool->n_entries * sizeof(pool_ent), - PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if(!newpool->entries) { - munmap((void *)newpool, sizeof(dead_pool)); - show_msg(MSGERR, "init_pool: unable to mmap deadpool entries " - "(tried to map %d bytes)\n", - newpool->n_entries * sizeof(pool_ent)); - return NULL; - } - - /* Initialize the entries */ - for(i=0; i < newpool->n_entries; i++) { - newpool->entries[i].ip = -1; - newpool->entries[i].name[0] = '\0'; - } - - return newpool; -} - -int -is_dead_address(dead_pool *pool, uint32_t addr) -{ - uint32_t haddr = ntohl(addr); - if(pool == NULL) { - return 0; - } - return (pool->deadrange_base == (haddr & pool->deadrange_mask)); -} - -void -get_next_dead_address(dead_pool *pool, uint32_t *result) -{ - *result = htonl(pool->deadrange_base + pool->dead_pos++); - if(pool->dead_pos >= pool->deadrange_size) { - pool->dead_pos = 0; - } -} - -int -store_pool_entry(dead_pool *pool, char *hostname, struct in_addr *addr) -{ - int position = pool->write_pos; - int oldpos; - int rc; - uint32_t intaddr; - char *result_hostname; - - show_msg(MSGDEBUG, "store_pool_entry: storing '%s'\n", hostname); - show_msg(MSGDEBUG, "store_pool_entry: write pos is: %d\n", pool->write_pos); - - /* Check to see if name already exists in pool */ - oldpos = search_pool_for_name(pool, hostname); - if(oldpos != -1){ - show_msg(MSGDEBUG, "store_pool_entry: not storing (entry exists)\n"); - addr->s_addr = pool->entries[oldpos].ip; - return oldpos; - } - - /* If this is a .onion host, then we return a bogus ip from our deadpool, - otherwise we try to resolve it and store the 'real' IP */ - if(strcasecmpend(hostname, ".onion") == 0) { - get_next_dead_address(pool, &pool->entries[position].ip); - } else { - rc = do_resolve(hostname, pool->sockshost, pool->socksport, &intaddr, 0, - 4 /*SOCKS5*/, 0 /*Reverse*/, &result_hostname); - - if(rc != 0) { - show_msg(MSGWARN, "failed to resolve: %s\n", hostname); - return -1; - } - if(is_dead_address(pool, intaddr)) { - show_msg(MSGERR, "resolved %s -> %d (deadpool address) IGNORED\n"); - return -1; - } - pool->entries[position].ip = intaddr; - } - - strncpy(pool->entries[position].name, hostname, 255); - pool->entries[position].name[255] = '\0'; - pool->write_pos++; - if(pool->write_pos >= pool->n_entries) { - pool->write_pos = 0; - } - addr->s_addr = pool->entries[position].ip; - - show_msg(MSGDEBUG, "store_pool_entry: stored entry in slot '%d'\n", position); - - return position; -} - -int -search_pool_for_name(dead_pool *pool, const char *name) -{ - unsigned int i; - for(i=0; i < pool->n_entries; i++){ - if(strcmp(name, pool->entries[i].name) == 0){ - return i; - } - } - return -1; -} - -char * -get_pool_entry(dead_pool *pool, struct in_addr *addr) -{ - unsigned int i; - uint32_t intaddr = addr->s_addr; - - if(pool == NULL) { - return NULL; - } - - show_msg(MSGDEBUG, "get_pool_entry: searching for: %s\n", inet_ntoa(*addr)); - for(i=0; i<pool->n_entries; i++) { - if(intaddr == pool->entries[i].ip) { - show_msg(MSGDEBUG, "get_pool_entry: found: %s\n", pool->entries[i].name); - return pool->entries[i].name; - } - } - show_msg(MSGDEBUG, "get_pool_entry: address not found\n"); - - return NULL; -} - -static int -build_socks4a_resolve_request(char **out, - const char *username, - const char *hostname) -{ - size_t len; - uint16_t port = htons(0); /* port: 0. */ - uint32_t addr = htonl(0x00000001u); /* addr: 0.0.0.1 */ - - len = 8 + strlen(username) + 1 + strlen(hostname) + 1; - *out = malloc(len); - (*out)[0] = 4; /* SOCKS version 4 */ - (*out)[1] = '\xF0'; /* Command: resolve. */ - - memcpy((*out)+2, &port, sizeof(port)); - memcpy((*out)+4, &addr, sizeof(addr)); - strcpy((*out)+8, username); - strcpy((*out)+8+strlen(username)+1, hostname); - - return len; -} - -static int -build_socks5_resolve_ptr_request(char **out, const void *_addr) -{ - size_t len; - const struct in_addr *addr=_addr; - - len = 12; - *out = malloc(len); - (*out)[0] = 5; /* SOCKS version 5 */ - (*out)[1] = '\xF1'; /* Command: reverse resolve. - see doc/socks-extensions.txt*/ - (*out)[2] = '\x00'; /* RSV */ - (*out)[3] = '\x01'; /* ATYP: IP V4 address: X'01' */ - - set_uint32((*out)+4, addr->s_addr);/*IP*/ - set_uint16((*out)+4+4, 0); /* port */ - - return len; -} - -#define RESPONSE_LEN 8 -#define SOCKS5_LEN 4 -#define METHODRESPONSE_LEN 2 - -static int -parse_socks4a_resolve_response(const char *response, size_t len, - uint32_t *addr_out) -{ - uint8_t status; - uint16_t port; - - if (len < RESPONSE_LEN) { - show_msg(MSGWARN,"Truncated socks response.\n"); - return -1; - } - if (((uint8_t)response[0])!=0) { /* version: 0 */ - show_msg(MSGWARN,"Nonzero version in socks response: bad format.\n"); - return -1; - } - status = (uint8_t)response[1]; - - memcpy(&port, response+2, sizeof(port)); - if (port!=0) { /* port: 0 */ - show_msg(MSGWARN,"Nonzero port in socks response: bad format.\n"); - return -1; - } - if (status != 90) { - show_msg(MSGWARN,"Bad status: socks request failed.\n"); - return -1; - } - - memcpy(addr_out, response+4, sizeof(*addr_out)); - - return 0; -} - -static int -parse_socks5_resolve_ptr_response(int s,const char *response, size_t len, - uint32_t *result_addr, char ***result_hostname) -{ - char reply_buf[4]; - int r; - - len=0; - while (len < SOCKS5_LEN) { - r = recv(s, reply_buf+len, SOCKS5_LEN-len, 0); - if (r==0) { - show_msg(MSGWARN, "do_resolve: EOF while reading SOCKS5 response\n"); - return -1; - } - if (r<0) { - show_msg(MSGWARN, "do_resolve: error reading SOCKS5 response\n"); - return -1; - } - len += r; - } - - if (reply_buf[0] != 5) { - show_msg(MSGWARN, "Bad SOCKS5 reply version."); - return -1; - } - if (reply_buf[1] != 0) { - show_msg(MSGWARN,"Got status response '%u': SOCKS5 request failed.", - (unsigned)reply_buf[1]); - return -1; - } - if (reply_buf[3] == 1) { - /* IPv4 address */ - len=0; - while (len < SOCKS5_LEN) { - r = recv(s, reply_buf+len, SOCKS5_LEN-len, 0); - if (r==0) { - show_msg(MSGWARN, "do_resolve: EOF while reading SOCKS5 response\n"); - return -1; - } - if (r<0) { - show_msg(MSGWARN, "do_resolve: error reading address in SOCKS5 response\n"); - return -1; - } - len += r; - } - *result_addr = ntohl(get_uint32(reply_buf)); - } else if (reply_buf[3] == 3) { - size_t result_len; - len=0; - while (len < 1) { - r = recv(s, reply_buf+len, 1-len, 0); - if (r==0) { - show_msg(MSGWARN, "do_resolve: EOF while reading SOCKS5 response\n"); - return -1; - } - if (r<0) { - show_msg(MSGWARN, "do_resolve: error reading address length in SOCKS5 response\n"); - return -1; - } - len += r; - } - result_len = *(uint8_t*)(reply_buf); - **result_hostname = malloc(result_len+1); - len=0; - while (len < (int) result_len) { - r = recv(s, **result_hostname+len, result_len-len, 0); - if (r==0) { - show_msg(MSGWARN, "do_resolve: EOF while reading SOCKS5 response\n"); - return -1; - } - if (r<0) { - show_msg(MSGWARN, "do_resolve: error reading hostname in SOCKS5 response\n"); - return -1; - } - len += r; - } - - (**result_hostname)[result_len] = '\0'; - } - - return 0; -} - -static int -do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport, - uint32_t *result_addr, const void *addr, - int version, int reverse, char **result_hostname) -{ - int s; - struct sockaddr_in socksaddr; - char *req, *cp=NULL; - int r, len, hslen; - char response_buf[RESPONSE_LEN]; - const char *handshake="\x05\x01\x00"; - - show_msg(MSGDEBUG, "do_resolve: resolving %s\n", hostname); - - /* Create SOCKS connection */ - s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (s<0) { - show_msg(MSGWARN, "do_resolve: problem creating socket\n"); - return -1; - } - - /* Connect to SOCKS server */ - memset(&socksaddr, 0, sizeof(socksaddr)); - socksaddr.sin_family = AF_INET; - socksaddr.sin_port = htons(socksport); - socksaddr.sin_addr.s_addr = htonl(sockshost); - if (realconnect(s, (struct sockaddr*)&socksaddr, sizeof(socksaddr))) { - show_msg(MSGWARN, "do_resolve: error connecting to SOCKS server\n"); - realclose(s); - return -1; - } - - /* If a SOCKS5 connection, perform handshake */ - if (version == 5) { - char method_buf[2]; - hslen=3; - while (hslen) { - r = send(s, handshake, hslen, 0); - if (r<0) { - show_msg(MSGWARN, "do_resolve: error sending SOCKS5 method list.\n"); - realclose(s); - return -1; - } - hslen -= r; - handshake += r; - } - - len = 0; - while (len < METHODRESPONSE_LEN) { - r = recv(s, method_buf+len, METHODRESPONSE_LEN-len, 0); - if (r==0) { - show_msg(MSGWARN, "do_resolve: EOF while reading SOCKS response\n"); - realclose(s); - return -1; - } - if (r<0) { - show_msg(MSGWARN, "do_resolve: error reading SOCKS response\n"); - realclose(s); - return -1; - } - len += r; - } - - if (method_buf[0] != '\x05') { - show_msg(MSGWARN, "Unrecognized socks version: %u", - (unsigned)method_buf[0]); - realclose(s); - return -1; - } - if (method_buf[1] != '\x00') { - show_msg(MSGWARN, "Unrecognized socks authentication method: %u", - (unsigned)method_buf[1]); - realclose(s); - return -1; - } - } - - /* Create SOCKS request */ - if (reverse) { - if ((len = build_socks5_resolve_ptr_request(&req, addr))<0) { - show_msg(MSGWARN, "do_resolve: error generating reverse SOCKS request\n"); - realclose(s); - return -1; - } - }else{ - if ((len = build_socks4a_resolve_request(&req, "", hostname))<0) { - show_msg(MSGWARN, "do_resolve: error generating SOCKS request\n"); - realclose(s); - return -1; - } - } - - /* Send SOCKS request */ - cp = req; - while (len) { - r = send(s, cp, len, 0); - if (r<0) { - show_msg(MSGWARN, "do_resolve: error sending SOCKS request\n"); - free(req); - realclose(s); - return -1; - } - len -= r; - cp += r; - } - free(req); - - /* Handle SOCKS Response */ - if (reverse) { - if (parse_socks5_resolve_ptr_response(s, response_buf, RESPONSE_LEN, - result_addr, &result_hostname) < 0){ - show_msg(MSGWARN, "do_resolve: error parsing SOCKS response\n"); - realclose(s); - return -1; - } - }else{ - /* Process SOCKS response */ - len = 0; - while (len < RESPONSE_LEN) { - r = recv(s, response_buf+len, RESPONSE_LEN-len, 0); - if (r==0) { - show_msg(MSGWARN, "do_resolve: EOF while reading SOCKS response\n"); - realclose(s); - return -1; - } - if (r<0) { - show_msg(MSGWARN, "do_resolve: error reading SOCKS response\n"); - realclose(s); - return -1; - } - len += r; - } - realclose(s); - - /* Parse SOCKS response */ - if (parse_socks4a_resolve_response(response_buf, RESPONSE_LEN, result_addr) < 0){ - show_msg(MSGWARN, "do_resolve: error parsing SOCKS response\n"); - return -1; - } - } - - - show_msg(MSGDEBUG, "do_resolve: success\n"); - - return 0; -} - -struct hostent * -our_gethostbyaddr(dead_pool *pool, const void *_addr, socklen_t len, int type) -{ - const struct in_addr *addr=_addr; - static struct hostent he; - uint32_t intaddr=0; - char *result_hostname=NULL; - int rc=0; - static char *addrs[2]; - static char *aliases[2]; - - rc = do_resolve("", pool->sockshost, pool->socksport, &intaddr, addr, - 5 /*SOCKS5*/, 1 /*Reverse*/, &result_hostname); - - - if(rc != 0) { - show_msg(MSGWARN, "failed to reverse resolve: %s\n", - inet_ntoa(*((struct in_addr *)addr))); - result_hostname=NULL; - addrs[0] = NULL; - addrs[1] = NULL; - }else{ - addrs[0] = (char *)addr; - addrs[1] = NULL; - } - - if (result_hostname) - he.h_name = result_hostname; - else - he.h_name = inet_ntoa(*((struct in_addr *)addr)); - - aliases[0] = NULL; - aliases[1] = NULL; - - he.h_aliases = aliases; - he.h_length = len; - he.h_addrtype = type; - he.h_addr_list = addrs; - - if (result_hostname) - show_msg(MSGTEST, "our_gethostbyaddr: resolved '%s' to: '%s'\n", - inet_ntoa(*((struct in_addr *)he.h_addr)), result_hostname); - - return &he; - -} - -struct hostent * -our_gethostbyname(dead_pool *pool, const char *name) -{ - int pos; - static struct in_addr addr; - static struct hostent he; - static char *addrs[2]; - - show_msg(MSGTEST, "our_gethostbyname: '%s' requested\n", name); - - pos = store_pool_entry(pool,(char *) name, &addr); - if(pos == -1) { - h_errno = HOST_NOT_FOUND; - return NULL; - } - - addrs[0] = (char *)&addr; - addrs[1] = NULL; - - he.h_name = pool->entries[pos].name; - he.h_aliases = NULL; - he.h_length = 4; - he.h_addrtype = AF_INET; - he.h_addr_list = addrs; - - show_msg(MSGDEBUG, "our_gethostbyname: resolved '%s' to: '%s'\n", - name, inet_ntoa(*((struct in_addr *)he.h_addr))); - - return &he; -} - -static struct hostent * -alloc_hostent(int af) -{ - struct hostent *he = NULL; - char **addr_list = NULL; - void *addr = NULL; - char **aliases = NULL; - - if(af != AF_INET && af != AF_INET6) { - return NULL; - } - - /* Since the memory we allocate here will be free'd by freehostent and - that function is opaque to us, it's likely that we'll leak a little - bit of memory here. */ - - he = malloc(sizeof(struct hostent)); - addr_list = malloc(2 * sizeof(char *)); - if(af == AF_INET6) { - addr = malloc(sizeof(struct in6_addr)); - } else { - addr = malloc(sizeof(struct in_addr)); - } - aliases = malloc(sizeof(char *)); - - if(he == NULL || addr_list == NULL || addr == NULL || aliases == NULL) { - if(he) - free(he); - if(addr_list) - free(addr_list); - if(addr) - free(addr); - if(aliases) - free(aliases); - } - - he->h_name = NULL; - he->h_addr_list = addr_list; - he->h_addr_list[0] = addr; - he->h_addr_list[1] = NULL; - he->h_aliases = aliases; - he->h_aliases[0] = NULL; - he->h_length = af == AF_INET ? 4 : 16; - he->h_addrtype = af; - - return he; -} - -/* On Linux, there's no freehostent() anymore; we might as well implement - this ourselves. */ - -static void -free_hostent(struct hostent *he) -{ - int i; - if(he->h_name) { - free(he->h_name); - } - if(he->h_aliases) { - for(i=0; he->h_aliases[i] != NULL; i++) { - free(he->h_aliases[i]); - } - free(he->h_aliases); - } - if(he->h_addr_list) { - free(he->h_addr_list); - } - free(he); -} - -int -our_getaddrinfo(dead_pool *pool, const char *node, const char *service, - void *hints, void *res) -{ - int pos; - struct in_addr addr; - char *ipstr; - int ret; - - /* If "node" looks like a dotted-decimal ip address, then just call - the real getaddrinfo; otherwise we'll need to get an address from - our pool. */ - - /* TODO: work out what to do with AF_INET6 requests */ - -#ifdef HAVE_INET_ATON - if(node && inet_aton(node, &addr) == 0 && memcmp(node,"*",1)) { -#elif defined(HAVE_INET_ADDR) - /* If we're stuck with inet_addr, then getaddrinfo() won't work - properly with 255.255.255.255 (= -1). There's not much we can - do about this */ - in_addr_t is_valid; - is_valid = inet_addr(node); - if(is_valid == -1) { -#endif - pos = store_pool_entry(pool, (char *) node, &addr); - if(pos == -1) { - return EAI_NONAME; - } else { - ipstr = strdup(inet_ntoa(addr)); - ret = realgetaddrinfo(ipstr, service, hints, res); - free(ipstr); - } - } else { - ret = realgetaddrinfo(node, service, hints, res); - } - - show_msg(MSGTEST, "our_getaddrinfo: '%s' requested\n", service); - return ret; -} - -struct hostent * -our_getipnodebyname(dead_pool *pool, const char *name, int af, int flags, - int *error_num) -{ - int pos; - struct hostent *he = NULL; - int want_4in6 = 0; - char addr_convert_buf[80]; - struct in_addr pool_addr; - - if(af == AF_INET6) { - /* Caller has requested an AF_INET6 address, and is not prepared to - accept IPv4-mapped IPV6 addresses. There's nothing we can do to - service their request. */ -#ifdef OPENBSD - /* OpenBSD doesn't support the AI_V4MAPPED flag, so just return. */ - return NULL; -#else - if((flags & AI_V4MAPPED) == 0) { - show_msg(MSGWARN, "getipnodebyname: asked for V6 addresses only, " - "but torsocks can't handle that\n"); - *error_num = NO_RECOVERY; - return NULL; - } else { - want_4in6 = 1; - } -#endif - } - - pos = store_pool_entry(pool, (char *)name, &pool_addr); - if(pos == -1) { - *error_num = HOST_NOT_FOUND; - return NULL; - } - - he = alloc_hostent(af); - if(he == NULL) { - show_msg(MSGERR, "getipnodebyname: failed to allocate hostent\n"); - *error_num = NO_RECOVERY; - return NULL; - } - - if(want_4in6) { - /* Convert the ipv4 address in *addr to an IPv4 in IPv6 mapped - address. TODO: inet_ntoa() is thread-safe on Solaris but might - not be on other platforms. */ - strcpy(addr_convert_buf, "::FFFF:"); - strcpy(addr_convert_buf+7, inet_ntoa(pool_addr)); - if(inet_pton(AF_INET6, addr_convert_buf, he->h_addr_list[0]) != 1) { - show_msg(MSGERR, "getipnodebyname: inet_pton() failed!\n"); - free_hostent(he); - *error_num = NO_RECOVERY; - return NULL; - } - } else { - ((struct in_addr *) he->h_addr_list[0])->s_addr = pool_addr.s_addr; - } - he->h_name = strdup(name); - - return he; -} - - diff --git a/src.old/dead_pool.h b/src.old/dead_pool.h deleted file mode 100644 index d6e3e10..0000000 --- a/src.old/dead_pool.h +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2005 Total Information Security Ltd. * - * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#ifndef _DEAD_POOL_H -#define _DEAD_POOL_H - -#include <config.h> - -extern int (*realconnect)(CONNECT_SIGNATURE); -extern int (*realclose)(CLOSE_SIGNATURE); -extern int (*realgetaddrinfo)(GETADDRINFO_SIGNATURE); - -struct struct_pool_ent { - unsigned int ip; - char name[256]; -}; - -typedef struct struct_pool_ent pool_ent; - -struct struct_dead_pool { - pool_ent *entries; /* Points to array of pool entries */ - unsigned int n_entries; /* Number of entries in the deadpool */ - unsigned int deadrange_base; /* Deadrange start IP in host byte order */ - unsigned int deadrange_mask; /* Deadrange netmask in host byte order */ - unsigned int deadrange_size; /* Number of IPs in the deadrange */ - unsigned int write_pos; /* Next position to use in the pool array */ - unsigned int dead_pos; /* Next 'unused' deadpool IP */ - uint32_t sockshost; - uint16_t socksport; - char pad[2]; -}; - -typedef struct struct_dead_pool dead_pool; - -dead_pool *init_pool(unsigned int deadpool_size, struct in_addr deadrange_base, - struct in_addr deadrange_mask, char *sockshost, uint16_t socksport); -int is_dead_address(dead_pool *pool, uint32_t addr); -char *get_pool_entry(dead_pool *pool, struct in_addr *addr); -int search_pool_for_name(dead_pool *pool, const char *name); -struct hostent *our_gethostbyname(dead_pool *pool, const char *name); -struct hostent *our_gethostbyaddr(dead_pool *pool, const void *addr, - socklen_t len, int type); -int our_getaddrinfo(dead_pool *pool, const char *node, const char *service, - void *hints, void *res); -struct hostent *our_getipnodebyname(dead_pool *pool, const char *name, - int af, int flags, int *error_num); - -#endif /* _DEAD_POOL_H */ - diff --git a/src.old/expansion_table.h b/src.old/expansion_table.h deleted file mode 100644 index 14fabe1..0000000 --- a/src.old/expansion_table.h +++ /dev/null @@ -1,125 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2010 Alex Rosenberg alex@ohmantics.net * - * Copyright (C) 2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#undef FUNC -#undef FUNCD -#undef FUND32 -#undef FUNCD64 - -#ifdef SUPPORT_RES_API -#define RES_FUNC FUNC -#define RES_FUNCD FUNCD -#define RES_FUNCD32 FUNCD32 -#define RES_FUNCD64 FUNCD64 -#else -#define RES_FUNC EMPTY_FUNC -#define RES_FUNCD EMPTY_FUNC -#define RES_FUNCD32 EMPTY_FUNC -#define RES_FUNCD64 EMPTY_FUNC -#endif /* SUPPORT_RES_API */ - -#define DNS_FUNC FUNC -#define DNS_FUNCD FUNCD -#define DNS_FUNCD32 FUNCD32 -#define DNS_FUNCD64 FUNCD64 - -#define EMPTY_FUNC(e,r,s,n,b,m) - -#if defined(__APPLE__) || defined(__darwin__) -#ifndef DARWIN_EXPANSION -#define DARWIN_EXPANSION PATCH_TABLE_EXPANSION -#endif /* DARWIN_EXPANSION */ -#define FUNCD(e,r,s,n,b,m) DARWIN_EXPANSION(e,r,s,n,b,m) -#if (__LP64__) -#define FUNCD32(e,r,s,n,b,m) EMPTY_FUNC(e,r,s,n,b,m) -#define FUNCD64(e,r,s,n,b,m) DARWIN_EXPANSION(e,r,s,n,b,m) -/* This tests if we're building with 10.6 or later headers, not - if we're running on 10.6. We'd rather do the latter. */ -#ifdef MAC_OS_X_VERSION_10_6 -#define FUNCD64_106(e,r,s,n,b,m) DARWIN_EXPANSION(e,r,s,n,b,m) -#else -#define FUNCD64_106(e,r,s,n,b,m) EMPTY_FUNC(e,r,s,n,b,m) -#endif /* MAC_OS_X_VERSION_10_6 */ -#else -#define FUNCD32(e,r,s,n,b,m) DARWIN_EXPANSION(e,r,s,n,b,m) -#define FUNCD64(e,r,s,n,b,m) EMPTY_FUNC(e,r,s,n,b,m) -#define FUNCD64_106(e,r,s,n,b,m) EMPTY_FUNC(e,r,s,n,b,m) -#endif /* (__LP64__) */ -#else -#define FUNCD(e,r,s,n,b,m) EMPTY_FUNC(e,r,s,n,b,m) -#define FUNCD32(e,r,s,n,b,m) EMPTY_FUNC(e,r,s,n,b,m) -#define FUNCD64(e,r,s,n,b,m) EMPTY_FUNC(e,r,s,n,b,m) -#define FUNCD64_106(e,r,s,n,b,m) EMPTY_FUNC(e,r,s,n,b,m) -#endif /* defined(__APPLE__) || defined(__darwin__) */ -#define FUNC(e,r,s,n,b,m) PATCH_TABLE_EXPANSION(e,r,s,n,b,m) - -/* dlsym return type SIG/ARGS C name base name asm name */ -/* res_init takes void, so we do that one manually. */ -/*RES_FUNC (ERR, int, RES_INIT_, res_init, res_init, "res_init") */ -RES_FUNC (ERR, int, RES_QUERY_, res_query, res_query, "res_query") -RES_FUNC (ERR, int, RES_SEARCH_, res_search, res_search, "res_search") -RES_FUNC (ERR, int, RES_SEND_, res_send, res_send, "res_send") -RES_FUNC (ERR, int, RES_QUERYDOMAIN_, res_querydomain, res_querydomain, "res_querydomain") - -DNS_FUNC (ERR, struct hostent *, GETHOSTBYNAME_, gethostbyname, gethostbyname, "gethostbyname") -DNS_FUNC (ERR, struct hostent *, GETHOSTBYADDR_, gethostbyaddr, gethostbyaddr, "gethostbyaddr") -DNS_FUNC (ERR, int, GETADDRINFO_, getaddrinfo, getaddrinfo, "getaddrinfo") -/* getipnodebyname is deprecated so do not report an error if it is not available.*/ -DNS_FUNC (WARN, struct hostent *, GETIPNODEBYNAME_, getipnodebyname, getipnodebyname, "getipnodebyname") - -DNS_FUNC (ERR, ssize_t, SENDTO_, sendto, sendto, "sendto") -DNS_FUNCD32 (ERR, ssize_t, SENDTO_, sendto_unix2003, sendto, "sendto$UNIX2003") -DNS_FUNCD32 (ERR, ssize_t, SENDTO_, sendto_nocancel_unix2003, sendto, "sendto$NOCANCEL$UNIX2003") -DNS_FUNCD64 (ERR, ssize_t, SENDTO_, sendto_nocancel, sendto, "sendto$NOCANCEL") - -DNS_FUNC (ERR, ssize_t, SENDMSG_, sendmsg, sendmsg, "sendmsg") -DNS_FUNCD32 (ERR, ssize_t, SENDMSG_, sendmsg_unix2003, sendmsg, "sendmsg$UNIX2003") -DNS_FUNCD32 (ERR, ssize_t, SENDMSG_, sendmsg_nocancel_unix2003, sendmsg, "sendmsg$NOCANCEL$UNIX2003") -DNS_FUNCD64 (ERR, ssize_t, SENDMSG_, sendmsg_nocancel, sendmsg, "sendmsg$NOCANCEL") - -FUNC (ERR, int, CONNECT_, connect, connect, "connect") -FUNCD32 (ERR, int, CONNECT_, connect_unix2003, connect, "connect$UNIX2003") -FUNCD32 (ERR, int, CONNECT_, connect_nocancel_unix2003, connect, "connect$NOCANCEL$UNIX2003") -FUNCD64 (ERR, int, CONNECT_, connect_nocancel, connect, "connect$NOCANCEL") - -#if !(defined(__APPLE__) || defined(__darwin__) && defined(MAX_OS_X_VERSION_10_6)) -/* see darwin_warts.c */ -FUNC (ERR, int, SELECT_, select, select, "select") -#endif -FUNCD (ERR, int, SELECT_, select_darwinextsn, select, "select$DARWIN_EXTSN") -FUNCD (ERR, int, SELECT_, select_darwinextsn_nocancel, select, "select$DARWIN_EXTSN$NOCANCEL") -FUNCD32 (ERR, int, SELECT_, select_unix2003, select, "select$UNIX2003") -FUNCD32 (ERR, int, SELECT_, select_nocancel_unix2003, select, "select$NOCANCEL$UNIX2003") -FUNCD64 (ERR, int, SELECT_, select_nocancel, select, "select$NOCANCEL") -FUNCD64_106 (ERR, int, SELECT_, select_1050, select, "select$1050") - -FUNC (ERR, int, POLL_, poll, poll, "poll") -FUNCD32 (ERR, int, POLL_, poll_unix2003, poll, "poll$UNIX2003") -FUNCD32 (ERR, int, POLL_, poll_nocancel_unix2003, poll, "poll$NOCANCEL$UNIX2003") -FUNCD64 (ERR, int, POLL_, poll_nocancel, poll, "poll$NOCANCEL") - -FUNC (ERR, int, CLOSE_, close, close, "close") -FUNCD32 (ERR, int, CLOSE_, close_unix2003, close, "close$UNIX2003") -FUNCD32 (ERR, int, CLOSE_, close_nocancel_unix2003, close, "close$NOCANCEL$UNIX2003") -FUNCD64 (ERR, int, CLOSE_, close_nocancel, close, "close$NOCANCEL") - -FUNC (ERR, int, GETPEERNAME_, getpeername, getpeername, "getpeername") -FUNCD32 (ERR, int, GETPEERNAME_, getpeername_unix2003, getpeername, "getpeername$UNIX2003") diff --git a/src.old/parser.c b/src.old/parser.c deleted file mode 100644 index 8f24be6..0000000 --- a/src.old/parser.c +++ /dev/null @@ -1,872 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2000-2008 Shaun Clowes delius@progsoc.org * - * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* - - parser.c - Parsing routines for torsocks.conf - -*/ - -#include <sys/types.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <config.h> - -#include "common.h" -#include "parser.h" - -/* Global configuration variables */ -#define MAXLINE BUFSIZ /* Max length of conf line */ -static struct serverent *currentcontext = NULL; - -static int handle_line(struct parsedfile *, char *, int); -static int check_server(struct serverent *); -static int tokenize(char *, int, char *[]); -static int handle_path(struct parsedfile *, int, int, char *[]); -static int handle_endpath(struct parsedfile *, int, int); -static int handle_reaches(int, char *); -static int handle_server(struct parsedfile *, int, char *); -static int handle_type(struct parsedfile *config, int, char *); -static int handle_port(struct parsedfile *config, int, char *); -static int handle_local(struct parsedfile *, int, const char *); -static int handle_tordns_enabled(struct parsedfile *, int, char *); -static int handle_tordns_deadpool_range(struct parsedfile *, int, const char *); -static int handle_tordns_cache_size(struct parsedfile *, 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); - -int read_config (char *filename, struct parsedfile *config) { - FILE *conf; - char line[MAXLINE]; - int rc = 0; - int lineno = 1; - struct serverent *server; - - /* Clear out the structure */ - memset(config, 0x0, sizeof(*config)); - - /* Initialization */ - currentcontext = &(config->defaultserver); - - /* Tordns defaults */ - config->tordns_cache_size = 256; - config->tordns_enabled = 1; - - - /* If a filename wasn't provided, use the default */ - if (filename == NULL) { - strncpy(line, CONF_FILE, sizeof(line) - 1); - /* Insure null termination */ - line[sizeof(line) - 1] = (char) 0; - filename = line; - show_msg(MSGDEBUG, "Configuration file not provided by TORSOCKS_CONF_FILE " - "environment variable, attempting to use defaults in %s.\n", filename); - } - - /* If there is no configuration file use reasonable defaults for Tor */ - if ((conf = fopen(filename, "r")) == NULL) { - show_msg(MSGERR, "Could not open socks configuration file " - "(%s) errno (%d), assuming sensible defaults for Tor.\n", filename, errno); - memset(&(config->defaultserver), 0x0, sizeof(config->defaultserver)); - check_server(&(config->defaultserver)); - handle_local(config, 0, "127.0.0.0/255.0.0.0"); - handle_local(config, 0, "10.0.0.0/255.0.0.0"); - handle_local(config, 0, "192.168.0.0/255.255.0.0"); - handle_local(config, 0, "172.16.0.0/255.240.0.0"); - handle_local(config, 0, "169.254.0.0/255.255.0.0"); - rc = 1; /* Severe errors reading configuration */ - } else { - memset(&(config->defaultserver), 0x0, sizeof(config->defaultserver)); - - while (NULL != fgets(line, MAXLINE, conf)) { - /* This line _SHOULD_ end in \n so we */ - /* just chop off the \n and hand it on */ - if (strlen(line) > 0) - line[strlen(line) - 1] = '\0'; - handle_line(config, line, lineno); - lineno++; - } - 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"); - /* We always consider this local, because many users' dsl - routers act as their DNS. */ - handle_local(config, 0, "10.0.0.0/255.0.0.0"); - handle_local(config, 0, "192.168.0.0/255.255.0.0"); - handle_local(config, 0, "172.16.0.0/255.240.0.0"); - handle_local(config, 0, "169.254.0.0/255.255.0.0"); - handle_local(config, 0, "192.168.0.0/255.255.0.0"); - - /* Check default server */ - check_server(&(config->defaultserver)); - server = (config->paths); - while (server != NULL) { - check_server(server); - server = server->next; - } - } - - /* Initialize tordns deadpool_range if not supplied */ - if(config->tordns_deadpool_range == NULL) { - handle_tordns_deadpool_range(config, 0, "127.0.69.0/255.255.255.0"); - } - - return(rc); -} - -/* Check server entries (and establish defaults) */ -static int check_server(struct serverent *server) { - - /* Default to the default Tor Socks port */ - if (server->port == 0) { - server->port = 9050; - } - - /* Default to a presumably local installation of Tor */ - if (server->address == NULL) { - server->address = strdup("127.0.0.1"); - } - - /* Default to SOCKS V4 */ - if (server->type == 0) { - server->type = 4; - } - - return(0); -} - - - -static int handle_line(struct parsedfile *config, char *line, int lineno) { - char *words[10]; - static char savedline[MAXLINE]; - int nowords = 0, i; - - /* Save the input string */ - strncpy(savedline, line, MAXLINE - 1); - savedline[MAXLINE - 1] = (char) 0; - /* Tokenize the input string */ - nowords = tokenize(line, 10, words); - - /* Set the spare slots to an empty string to simplify */ - /* processing */ - for (i = nowords; i < 10; i++) - words[i] = NULL; - - if (nowords > 0) { - /* Now this can either be a "path" block starter or */ - /* ender, otherwise it has to be a pair (<name> = */ - /* <value>) */ - if (!strcmp(words[0], "path")) { - handle_path(config, lineno, nowords, words); - } else if (!strcmp(words[0], "}")) { - handle_endpath(config, lineno, nowords); - } else { - /* Has to be a pair */ - if ((nowords != 3) || (strcmp(words[1], "="))) { - show_msg(MSGERR, "Malformed configuration pair " - "on line %d in configuration " - "file, "%s"\n", lineno, savedline); - } else if (!strcmp(words[0], "reaches")) { - handle_reaches(lineno, words[2]); - } else if (!strcmp(words[0], "server")) { - handle_server(config, lineno, words[2]); - } else if (!strcmp(words[0], "server_port")) { - handle_port(config, lineno, words[2]); - } else if (!strcmp(words[0], "server_type")) { - handle_type(config, lineno, words[2]); - } else if (!strcmp(words[0], "default_user")) { - handle_defuser(config, lineno, words[2]); - } else if (!strcmp(words[0], "default_pass")) { - handle_defpass(config, lineno, words[2]); - } else if (!strcmp(words[0], "local")) { - handle_local(config, lineno, words[2]); - } else if (!strcmp(words[0], "tordns_enable")) { - handle_tordns_enabled(config, lineno, words[2]); - } else if (!strcmp(words[0], "tordns_deadpool_range")) { - handle_tordns_deadpool_range(config, lineno, words[2]); - } else if (!strcmp(words[0], "tordns_cache_size")) { - handle_tordns_cache_size(config, words[2]); - } else { - show_msg(MSGERR, "Invalid pair type (%s) specified " - "on line %d in configuration file, " - ""%s"\n", words[0], lineno, - savedline); - } - } - } - - return(0); -} - -/* This routines breaks up input lines into tokens */ -/* and places these tokens into the array specified */ -/* by tokens */ -static int tokenize(char *line, int arrsize, char *tokens[]) { - int tokenno = -1; - int finished = 0; - - /* Whitespace is ignored before and after tokens */ - while ((tokenno < (arrsize - 1)) && - (line = line + strspn(line, " \t")) && - (*line != (char) 0) && - (!finished)) { - tokenno++; - tokens[tokenno] = line; - line = line + strcspn(line, " \t"); - *line = (char) 0; - line++; - - /* We ignore everything after a # */ - if (*tokens[tokenno] == '#') { - finished = 1; - tokenno--; - } - } - - return(tokenno + 1); -} - -static int handle_path(struct parsedfile *config, int lineno, int nowords, char *words[]) { - struct serverent *newserver; - - if ((nowords != 2) || (strcmp(words[1], "{"))) { - show_msg(MSGERR, "Badly formed path open statement on line %d " - "in configuration file (should look like " - ""path {")\n", lineno); - } else if (currentcontext != &(config->defaultserver)) { - /* You cannot nest path statements so check that */ - /* the current context is defaultserver */ - show_msg(MSGERR, "Path statements cannot be nested on line %d " - "in configuration file\n", lineno); - } else { - /* Open up a new serverent, put it on the list */ - /* then set the current context */ - if ((newserver = malloc(sizeof(*newserver))) == NULL) - exit(-1); - - /* Initialize the structure */ - show_msg(MSGDEBUG, "New server structure from line %d in configuration file going " - "to 0x%08x\n", lineno, newserver); - memset(newserver, 0x0, sizeof(*newserver)); - newserver->next = config->paths; - newserver->lineno = lineno; - config->paths = newserver; - currentcontext = newserver; - } - - return(0); -} - -static int handle_endpath(struct parsedfile *config, int lineno, int nowords) { - - if (nowords != 1) { - show_msg(MSGERR, "Badly formed path close statement on line " - "%d in configuration file (should look like " - ""}")\n", lineno); - } else { - currentcontext = &(config->defaultserver); - } - - /* We could perform some checking on the validty of data in */ - /* the completed path here, but thats what verifyconf is */ - /* designed to do, no point in weighing down libtorsocks */ - - return(0); -} - -static int handle_reaches(int lineno, char *value) { - int rc; - struct netent *ent; - - rc = make_netent(value, &ent); - switch(rc) { - case 1: - show_msg(MSGERR, "Local network specification (%s) is not validly " - "constructed in reach statement on line " - "%d in configuration " - "file\n", value, lineno); - return(0); - break; - case 2: - show_msg(MSGERR, "IP in reach statement " - "network specification (%s) is not valid on line " - "%d in configuration file\n", value, lineno); - return(0); - break; - case 3: - show_msg(MSGERR, "SUBNET in reach statement " - "network specification (%s) is not valid on " - "line %d in configuration file\n", value, - lineno); - return(0); - break; - case 4: - show_msg(MSGERR, "IP (%s) & ", inet_ntoa(ent->localip)); - show_msg(MSGERR, "SUBNET (%s) != IP on line %d in " - "configuration file, ignored\n", - inet_ntoa(ent->localnet), lineno); - return(0); - break; - case 5: - show_msg(MSGERR, "Start port in reach statement " - "network specification (%s) is not valid on line " - "%d in configuration file\n", value, lineno); - return(0); - break; - case 6: - show_msg(MSGERR, "End port in reach statement " - "network specification (%s) is not valid on line " - "%d in configuration file\n", value, lineno); - return(0); - break; - case 7: - show_msg(MSGERR, "End port in reach statement " - "network specification (%s) is less than the start " - "port on line %d in configuration file\n", value, - lineno); - return(0); - break; - } - - /* The entry is valid so add it to linked list */ - ent -> next = currentcontext -> reachnets; - currentcontext -> reachnets = ent; - - return(0); -} - -static int handle_server(struct parsedfile *config, int lineno, char *value) { - char *ip; - - ip = strsplit(NULL, &value, " "); - - /* We don't verify this ip/hostname at this stage, */ - /* its resolved immediately before use in torsocks.c */ - if (currentcontext->address == NULL) - currentcontext->address = strdup(ip); - else { - if (currentcontext == &(config->defaultserver)) - show_msg(MSGERR, "Only one default SOCKS server " - "may be specified at line %d in " - "configuration file\n", lineno); - else - show_msg(MSGERR, "Only one SOCKS server may be specified " - "per path on line %d in configuration " - "file. (Path begins on line %d)\n", - lineno, currentcontext->lineno); - } - - return(0); -} - -static int handle_port(struct parsedfile *config, int lineno, char *value) { - - if (currentcontext->port != 0) { - if (currentcontext == &(config->defaultserver)) - show_msg(MSGERR, "Server port may only be specified " - "once for default server, at line %d " - "in configuration file\n", lineno); - else - show_msg(MSGERR, "Server port may only be specified " - "once per path on line %d in configuration " - "file. (Path begins on line %d)\n", - lineno, currentcontext->lineno); - } else { - errno = 0; - currentcontext->port = (unsigned short int) - (strtol(value, (char **)NULL, 10)); - if ((errno != 0) || (currentcontext->port == 0)) { - show_msg(MSGERR, "Invalid server port number " - "specified in configuration file " - "(%s) on line %d\n", value, lineno); - currentcontext->port = 0; - } - } - - return(0); -} - -static int handle_defuser(struct parsedfile *config, int lineno, char *value) { - - if (currentcontext->defuser != NULL) { - if (currentcontext == &(config->defaultserver)) - show_msg(MSGERR, "Default username may only be specified " - "once for default server, at line %d " - "in configuration file\n", lineno); - else - show_msg(MSGERR, "Default username may only be specified " - "once per path on line %d in configuration " - "file. (Path begins on line %d)\n", - lineno, currentcontext->lineno); - } else { - currentcontext->defuser = strdup(value); - } - - return(0); -} - -static int handle_defpass(struct parsedfile *config, int lineno, char *value) { - - if (currentcontext->defpass != NULL) { - if (currentcontext == &(config->defaultserver)) - show_msg(MSGERR, "Default password may only be specified " - "once for default server, at line %d " - "in configuration file\n", lineno); - else - show_msg(MSGERR, "Default password may only be specified " - "once per path on line %d in configuration " - "file. (Path begins on line %d)\n", - lineno, currentcontext->lineno); - } else { - currentcontext->defpass = strdup(value); - } - - return(0); -} - -static int handle_type(struct parsedfile *config, int lineno, char *value) { - - if (currentcontext->type != 0) { - if (currentcontext == &(config->defaultserver)) - show_msg(MSGERR, "Server type may only be specified " - "once for default server, at line %d " - "in configuration file\n", lineno); - else - show_msg(MSGERR, "Server type may only be specified " - "once per path on line %d in configuration " - "file. (Path begins on line %d)\n", - lineno, currentcontext->lineno); - } else { - errno = 0; - currentcontext->type = (int) strtol(value, (char **)NULL, 10); - if ((errno != 0) || (currentcontext->type == 0) || - ((currentcontext->type != 4) && (currentcontext->type != 5))) { - show_msg(MSGERR, "Invalid server type (%s) " - "specified in configuration file " - "on line %d, only 4 or 5 may be " - "specified\n", value, lineno); - currentcontext->type = 0; - } - } - - return(0); -} - -static int handle_flag(char *value) -{ - if(!strcasecmp(value, "true") || !strcasecmp(value, "yes") - || !strcmp(value, "1")) { - return 1; - } else if (!strcasecmp(value, "false") || !strcasecmp(value, "no") - || !strcmp(value, "0")) { - return 0; - } else { - return -1; - } -} - -static int handle_tordns_enabled(struct parsedfile *config, int lineno, - char *value) -{ - int val = handle_flag(value); - if(val == -1) { - show_msg(MSGERR, "Invalid value %s supplied for tordns_enabled at " - "line %d in config file, IGNORED\n", value, lineno); - } else { - config->tordns_enabled = val; - } - return 0; -} - -static int handle_tordns_cache_size(struct parsedfile *config, - char *value) -{ - char *endptr; - long size = strtol(value, &endptr, 10); - if(*endptr != '\0') { - show_msg(MSGERR, "Error parsing integer value for " - "tordns_cache_size (%s), using default %d\n", - value, config->tordns_cache_size); - } else if(size < 128) { - show_msg(MSGERR, "The value supplied for tordns_cache_size (%d) " - "is too small (<128), using default %d\n", size, - config->tordns_cache_size); - } else if(size > 4096) { - show_msg(MSGERR, "The value supplied for tordns_cache_range (%d) " - "is too large (>4096), using default %d\n", size, - config->tordns_cache_size); - } else { - config->tordns_cache_size = size; - } - return 0; -} - -static int handle_tordns_deadpool_range(struct parsedfile *config, int lineno, - const char *value) -{ - int rc; - struct netent *ent; - - if (config->tordns_deadpool_range != NULL) { - show_msg(MSGERR, "Only one 'deadpool' entry permitted, found a " - "second at line %d in configuration file.\n"); - return(0); - } - - if (currentcontext != &(config->defaultserver)) { - show_msg(MSGERR, "Deadpool cannot be specified in path " - "block at line %d in configuration file. " - "(Path block started at line %d)\n", - lineno, currentcontext->lineno); - return(0); - } - - rc = make_netent((char *)value, &ent); - /* This is copied from handle_local and should probably be folded into - a generic whinge() function or something */ - switch(rc) { - case 1: - show_msg(MSGERR, "The deadpool specification (%s) is not validly " - "constructed on line %d in configuration " - "file\n", value, lineno); - return(0); - break; - case 2: - show_msg(MSGERR, "IP for deadpool " - "network specification (%s) is not valid on line " - "%d in configuration file\n", value, lineno); - return(0); - break; - case 3: - show_msg(MSGERR, "SUBNET for " - "deadpool network specification (%s) is not valid on " - "line %d in configuration file\n", value, - lineno); - return(0); - break; - case 4: - show_msg(MSGERR, "IP (%s) & ", inet_ntoa(ent->localip)); - show_msg(MSGERR, "SUBNET (%s) != IP on line %d in " - "configuration file, ignored\n", - inet_ntoa(ent->localnet), lineno); - return(0); - case 5: - case 6: - case 7: - show_msg(MSGERR, "Port specification is invalid and " - "not allowed in deadpool specification " - "(%s) on line %d in configuration file\n", - value, lineno); - return(0); - break; - } - if (ent->startport || ent->endport) { - show_msg(MSGERR, "Port specification is " - "not allowed in deadpool specification " - "(%s) on line %d in configuration file\n", - value, lineno); - return(0); - } - - config->tordns_deadpool_range = ent; - return 0; -} - -static int handle_local(struct parsedfile *config, int lineno, const char *value) { - int rc; - struct netent *ent; - - if (currentcontext != &(config->defaultserver)) { - show_msg(MSGERR, "Local networks cannot be specified in path " - "block at line %d in configuration file. " - "(Path block started at line %d)\n", - lineno, currentcontext->lineno); - return(0); - } - - rc = make_netent((char *)value, &ent); - switch(rc) { - case 1: - show_msg(MSGERR, "Local network specification (%s) is not validly " - "constructed on line %d in configuration " - "file\n", value, lineno); - return(0); - break; - case 2: - show_msg(MSGERR, "IP for local " - "network specification (%s) is not valid on line " - "%d in configuration file\n", value, lineno); - return(0); - break; - case 3: - show_msg(MSGERR, "SUBNET for " - "local network specification (%s) is not valid on " - "line %d in configuration file\n", value, - lineno); - return(0); - break; - case 4: - show_msg(MSGERR, "IP (%s) & ", inet_ntoa(ent->localip)); - show_msg(MSGERR, "SUBNET (%s) != IP on line %d in " - "configuration file, ignored\n", - inet_ntoa(ent->localnet), lineno); - return(0); - case 5: - case 6: - case 7: - show_msg(MSGERR, "Port specification is invalid and " - "not allowed in local network specification " - "(%s) on line %d in configuration file\n", - value, lineno); - return(0); - break; - } - - if (ent->startport || ent->endport) { - show_msg(MSGERR, "Port specification is " - "not allowed in local network specification " - "(%s) on line %d in configuration file\n", - value, lineno); - return(0); - } - - /* The entry is valid so add it to linked list */ - ent -> next = config->localnets; - (config->localnets) = ent; - - return(0); -} - -/* 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) { - char *ip; - char *subnet; - char *startport = NULL; - char *endport = NULL; - char *badchar; - char separator; - static char buf[200]; - char *split; - - /* Get a copy of the string so we can modify it */ - strncpy(buf, value, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = (char) 0; - split = buf; - - /* Now rip it up */ - ip = strsplit(&separator, &split, "/:"); - if (separator == ':') { - /* We have a start port */ - startport = strsplit(&separator, &split, "-/"); - if (separator == '-') - /* We have an end port */ - endport = strsplit(&separator, &split, "/"); - } - subnet = strsplit(NULL, &split, " \n"); - - if ((ip == NULL) || (subnet == NULL)) { - /* Network specification not validly constructed */ - return(1); - } - - /* Allocate the new entry */ - if ((*ent = (struct netent *) malloc(sizeof(struct netent))) - == NULL) { - /* If we couldn't malloc some storage, leave */ - exit(1); - } - - show_msg(MSGDEBUG, "New network entry for %s going to 0x%08x\n", ip, *ent); - - if (!startport) - (*ent)->startport = 0; - if (!endport) - (*ent)->endport = 0; - -#ifdef HAVE_INET_ADDR - if (((*ent)->localip.s_addr = inet_addr(ip)) == -1) { -#elif defined(HAVE_INET_ATON) - if (!(inet_aton(ip, &((*ent)->localip)))) { -#endif - /* Badly constructed IP */ - free(*ent); - return(2); - } -#ifdef HAVE_INET_ADDR - else if (((*ent)->localnet.s_addr = inet_addr(subnet)) == -1) { -#elif defined(HAVE_INET_ATON) - else if (!(inet_aton(subnet, &((*ent)->localnet)))) { -#endif - /* Badly constructed subnet */ - free(*ent); - return(3); - } else if (((*ent)->localip.s_addr & - (*ent)->localnet.s_addr) != - (*ent)->localip.s_addr) { - /* Subnet and Ip != Ip */ - free(*ent); - return(4); - } else if (startport && - (!((*ent)->startport = strtol(startport, &badchar, 10)) || - (*badchar != 0) || ((*ent)->startport > 65535))) { - /* Bad start port */ - free(*ent); - return(5); - } else if (endport && - (!((*ent)->endport = strtol(endport, &badchar, 10)) || - (*badchar != 0) || ((*ent)->endport > 65535))) { - /* Bad end port */ - free(*ent); - return(6); - } else if (((*ent)->startport > (*ent)->endport) && !(startport && !endport)) { - /* End port is less than start port */ - free(*ent); - return(7); - } - - if (startport && !endport) - (*ent)->endport = (*ent)->startport; - - return(0); -} - -int is_local(struct parsedfile *config, struct in_addr *testip) { - struct netent *ent; - char buf[16]; - inet_ntop(AF_INET, testip, buf, sizeof(buf)); - show_msg(MSGDEBUG, "checking if address: %s is local" - "\n", - buf); - - for (ent = (config->localnets); ent != NULL; ent = ent -> next) { - inet_ntop(AF_INET, &ent->localnet, buf, sizeof(buf)); - show_msg(MSGDEBUG, "localnet addr: %s" - "\n", - buf); - inet_ntop(AF_INET, &ent->localip, buf, sizeof(buf)); - show_msg(MSGDEBUG, "localip addr: %s" - "\n", - buf); - show_msg(MSGDEBUG, "result testip->s_addr & ent->localnet.s_addr : %i" - "\n", - testip->s_addr & ent->localnet.s_addr); - show_msg(MSGDEBUG, "result ent->localip.s_addr & ent->localnet.s_addr : %i" - "\n", - ent->localip.s_addr & ent->localnet.s_addr); - show_msg(MSGDEBUG, "result ent->localip.s_addr : %i" - "\n", - ent->localip.s_addr); - if ((testip->s_addr & ent->localnet.s_addr) == - (ent->localip.s_addr & ent->localnet.s_addr)) { - show_msg(MSGDEBUG, "address: %s is local" - "\n", - buf); - return(0); - } - } - - inet_ntop(AF_INET, testip, buf, sizeof(buf)); - show_msg(MSGDEBUG, "address: %s is not local" - "\n", - buf); - return(1); -} - -/* 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; - char ipbuf[64]; - - show_msg(MSGDEBUG, "Picking appropriate server for %s\n", inet_ntoa(*ip)); - *ent = (config->paths); - while (*ent != NULL) { - /* Go through all the servers looking for one */ - /* with a path to this network */ - show_msg(MSGDEBUG, "Checking SOCKS server %s\n", - ((*ent)->address ? (*ent)->address : "(No Address)")); - net = (*ent)->reachnets; - while (net != NULL) { - strcpy(ipbuf, inet_ntoa(net->localip)); - show_msg(MSGDEBUG, "Server can reach %s/%s\n", - ipbuf, inet_ntoa(net->localnet)); - if (((ip->s_addr & net->localnet.s_addr) == - (net->localip.s_addr & net->localnet.s_addr)) && - (!net->startport || - ((net->startport <= port) && (net->endport >= port)))) - { - show_msg(MSGDEBUG, "This server can reach target\n"); - /* Found the net, return */ - return(0); - } - net = net->next; - } - (*ent) = (*ent)->next; - } - - *ent = &(config->defaultserver); - - return(0); -} - -/* This function is very much like strsep, it looks in a string for */ -/* a character from a list of characters, when it finds one it */ -/* replaces it with a \0 and returns the start of the string */ -/* (basically spitting out tokens with arbitrary separators). If no */ -/* match is found the remainder of the string is returned and */ -/* the start pointer is set to be NULL. The difference between */ -/* standard strsep and this function is that this one will */ -/* set *separator to the character separator found if it isn't null */ -char *strsplit(char *separator, char **text, const char *search) { - unsigned int len; - char *ret; - - ret = *text; - - if (*text == NULL) { - if (separator) - *separator = '\0'; - return(NULL); - } else { - len = strcspn(*text, search); - if (len == strlen(*text)) { - if (separator) - *separator = '\0'; - *text = NULL; - } else { - *text = *text + len; - if (separator) - *separator = **text; - **text = '\0'; - *text = *text + 1; - } - } - - return(ret); -} diff --git a/src.old/parser.h b/src.old/parser.h deleted file mode 100644 index 91e6d04..0000000 --- a/src.old/parser.h +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2000-2008 Shaun Clowes delius@progsoc.org * - * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -/* parser.h - Structures, functions and global variables for the - torsocks parsing routines */ - -#ifndef _PARSER_H - -#define _PARSER_H 1 - -/* Structure definitions */ - -/* Structure representing one server specified in the config */ -struct serverent { - int lineno; /* Line number in conf file this path started on */ - char *address; /* Address/hostname of server */ - int port; /* Port number of server */ - 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 serverent *next; /* Pointer to next server entry */ -}; - -/* Structure representing a network */ -struct 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 */ -}; - -/* Structure representing a complete parsed file */ -struct parsedfile { - struct netent *localnets; - struct serverent defaultserver; - struct serverent *paths; - int tordns_enabled; - int tordns_failopen; - unsigned int tordns_cache_size; - struct netent *tordns_deadpool_range; -}; - -/* Functions provided by parser module */ -int read_config(char *, struct parsedfile *); -int is_local(struct parsedfile *, struct in_addr *); -int pick_server(struct parsedfile *, struct serverent **, struct in_addr *, unsigned int port); -char *strsplit(char *separator, char **text, const char *search); - -#endif diff --git a/src.old/socks.c b/src.old/socks.c deleted file mode 100644 index 8497728..0000000 --- a/src.old/socks.c +++ /dev/null @@ -1,633 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2000-2008 Shaun Clowes delius@progsoc.org * - * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* PreProcessor Defines */ -#include <config.h> - -/*Defining _NONSTD_SOURCE causes library and kernel calls to behave as closely -to Mac OS X 10.3's library and kernel calls as possible.*/ -#if defined(__APPLE__) || defined(__darwin__) -/* -From 'man compat' in OSX: -64-BIT COMPILATION - When compiling for 64-bit architectures, the __LP64__ macro will be defined to 1, and UNIX conformance - is always on (the _DARWIN_FEATURE_UNIX_CONFORMANCE macro will also be defined to the SUS conformance - level). Defining _NONSTD_SOURCE will cause a compilation error. -*/ -#if !defined(__LP64__) -#define _NONSTD_SOURCE 1 -#endif -#include <sys/socket.h> -#endif - - -#ifdef USE_GNU_SOURCE -#define _GNU_SOURCE -#endif - -/* Header Files */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <dlfcn.h> -#include <sys/types.h> -#include <string.h> -#include <strings.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/poll.h> -#include <sys/time.h> -#include <pwd.h> -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdarg.h> -#if !defined(__APPLE__) && !defined(__darwin__) -#include <sys/socket.h> -#endif -#include <resolv.h> - -#include "common.h" -#include "dead_pool.h" -#include "parser.h" -#include "socks.h" - -static int connect_server(struct connreq *conn); -static int send_socks_request(struct connreq *conn); -static int send_socksv4_request(struct connreq *conn); -static int send_socksv5_method(struct connreq *conn); -static int send_socksv5_connect(struct connreq *conn); -static int send_buffer(struct connreq *conn); -static int recv_buffer(struct connreq *conn); -static int read_socksv5_method(struct connreq *conn); -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 int send_socksv4a_request(struct connreq *conn, const char *onion_host); - - -dead_pool *pool = NULL; -struct connreq *requests = NULL; - -struct connreq *new_socks_request(int sockid, struct sockaddr_in *connaddr, - struct sockaddr_in *serveraddr, - struct serverent *path) -{ - struct connreq *newconn; - - if ((newconn = malloc(sizeof(*newconn))) == NULL) { - /* Could not malloc, we're stuffed */ - show_msg(MSGERR, "Could not allocate memory for new socks request\n"); - return(NULL); - } - - /* Add this connection to be proxied to the list */ - memset(newconn, 0x0, sizeof(*newconn)); - newconn->sockid = sockid; - newconn->state = UNSTARTED; - newconn->path = path; - memcpy(&(newconn->connaddr), connaddr, sizeof(newconn->connaddr)); - memcpy(&(newconn->serveraddr), serveraddr, sizeof(newconn->serveraddr)); - newconn->next = requests; - requests = newconn; - - return(newconn); -} - -void kill_socks_request(struct connreq *conn) -{ - struct connreq *connnode; - - if (requests == conn) - requests = conn->next; - else { - for (connnode = requests; connnode != NULL; connnode = connnode->next) { - if (connnode->next == conn) { - connnode->next = conn->next; - break; - } - } - } - - free(conn); -} - -struct connreq *find_socks_request(int sockid, int includefinished) -{ - struct connreq *connnode; - - for (connnode = requests; connnode != NULL; connnode = connnode->next) { - if (connnode->sockid == sockid) { - if (((connnode->state == FAILED) || (connnode->state == DONE)) && - !includefinished) - break; - else - return(connnode); - } - } - - return(NULL); -} - -int handle_request(struct connreq *conn) -{ - int rc = 0; - int i = 0; - - show_msg(MSGDEBUG, "Beginning handle loop for socket %d\n", conn->sockid); - - while ((rc == 0) && - (conn->state != FAILED) && - (conn->state != DONE) && - (i++ < 20)) { - show_msg(MSGDEBUG, "In request handle loop for socket %d, " - "current state of request is %d\n", conn->sockid, - conn->state); - switch(conn->state) { - case UNSTARTED: - case CONNECTING: - rc = connect_server(conn); - break; - case CONNECTED: - rc = send_socks_request(conn); - break; - case SENDING: - rc = send_buffer(conn); - break; - case RECEIVING: - rc = recv_buffer(conn); - break; - case SENTV4REQ: - show_msg(MSGDEBUG, "Receiving reply to SOCKS V4 connect request\n"); - conn->datalen = sizeof(struct sockrep); - conn->datadone = 0; - conn->state = RECEIVING; - conn->nextstate = GOTV4REQ; - break; - case GOTV4REQ: - rc = read_socksv4_req(conn); - break; - case SENTV5METHOD: - show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 method negotiation\n"); - conn->datalen = 2; - conn->datadone = 0; - conn->state = RECEIVING; - conn->nextstate = GOTV5METHOD; - break; - case GOTV5METHOD: - rc = read_socksv5_method(conn); - break; - case SENTV5AUTH: - show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 authentication negotiation\n"); - conn->datalen = 2; - conn->datadone = 0; - conn->state = RECEIVING; - conn->nextstate = GOTV5AUTH; - break; - case GOTV5AUTH: - rc = read_socksv5_auth(conn); - break; - case SENTV5CONNECT: - show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 connect request\n"); - conn->datalen = 10; - conn->datadone = 0; - conn->state = RECEIVING; - conn->nextstate = GOTV5CONNECT; - break; - case GOTV5CONNECT: - rc = read_socksv5_connect(conn); - break; - } - conn->err = errno; - } - - if (i == 20) - show_msg(MSGERR, "Ooops, state loop while handling request %d\n", - conn->sockid); - - show_msg(MSGDEBUG, "Handle loop completed for socket %d in state %d, " - "returning %d\n", conn->sockid, conn->state, rc); - return(rc); -} - -static int connect_server(struct connreq *conn) -{ - int rc; - - /* Connect this socket to the socks server */ - show_msg(MSGDEBUG, "Connecting to %s port %d\n", - inet_ntoa(conn->serveraddr.sin_addr), ntohs(conn->serveraddr.sin_port)); - - rc = realconnect(conn->sockid, (CONNECT_SOCKARG) &(conn->serveraddr), - sizeof(conn->serveraddr)); - - show_msg(MSGDEBUG, "Connect returned %d, errno is %d\n", rc, errno); - if (rc && errno == EISCONN) { - rc = 0; - show_msg(MSGDEBUG, "Socket %d already connected to SOCKS server\n", conn->sockid); - conn->state = CONNECTED; - } else if (rc) { - if (errno != EINPROGRESS) { - show_msg(MSGERR, "Error %d attempting to connect to SOCKS " - "server (%s)\n", errno, strerror(errno)); - conn->state = FAILED; - } else { - show_msg(MSGDEBUG, "Connection in progress\n"); - conn->state = CONNECTING; - } - } else { - show_msg(MSGDEBUG, "Socket %d connected to SOCKS server\n", conn->sockid); - conn->state = CONNECTED; - } - - return((rc ? errno : 0)); -} - -static int send_socks_request(struct connreq *conn) -{ - int rc = 0; - - if (conn->path->type == 4) { - char *name = get_pool_entry(pool, &(conn->connaddr.sin_addr)); - if(name != NULL) - rc = send_socksv4a_request(conn,name); - else - rc = send_socksv4_request(conn); - } else - rc = send_socksv5_method(conn); - return(rc); -} - -static int send_socksv4a_request(struct connreq *conn,const char *onion_host) -{ - struct passwd *user; - struct sockreq *thisreq; - int endOfUser; - /* Determine the current username */ - user = getpwuid(getuid()); - - thisreq = (struct sockreq *) conn->buffer; - endOfUser=sizeof(struct sockreq) + - (user == NULL ? 0 : strlen(user->pw_name)) + 1; - - /* Check the buffer has enough space for the request */ - /* and the user name */ - conn->datalen = endOfUser+ - (onion_host == NULL ? 0 : strlen(onion_host)) + 1; - if (sizeof(conn->buffer) < conn->datalen) { - show_msg(MSGERR, "The SOCKS username is too long"); - conn->state = FAILED; - return(ECONNREFUSED); - } - - /* Create the request */ - thisreq->version = 4; - thisreq->command = 1; - thisreq->dstport = conn->connaddr.sin_port; - thisreq->dstip = htonl(1); - - /* Copy the username */ - strcpy((char *) thisreq + sizeof(struct sockreq), - (user == NULL ? "" : user->pw_name)); - - /* Copy the onion host */ - strcpy((char *) thisreq + endOfUser, - (onion_host == NULL ? "" : onion_host)); - - conn->datadone = 0; - conn->state = SENDING; - conn->nextstate = SENTV4REQ; - - return(0); -} - -static int send_socksv4_request(struct connreq *conn) -{ - struct passwd *user; - struct sockreq *thisreq; - - /* 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 */ - conn->datalen = sizeof(struct sockreq) + - (user == NULL ? 0 : strlen(user->pw_name)) + 1; - if (sizeof(conn->buffer) < conn->datalen) { - show_msg(MSGERR, "The SOCKS username is too long"); - conn->state = FAILED; - return(ECONNREFUSED); - } - - /* Create the request */ - thisreq->version = 4; - thisreq->command = 1; - thisreq->dstport = conn->connaddr.sin_port; - thisreq->dstip = conn->connaddr.sin_addr.s_addr; - - /* Copy the username */ - strcpy((char *) thisreq + sizeof(struct sockreq), - (user == NULL ? "" : user->pw_name)); - - conn->datadone = 0; - conn->state = SENDING; - conn->nextstate = SENTV4REQ; - - return(0); -} - -static int send_socksv5_method(struct connreq *conn) -{ - char verstring[] = { 0x05, /* Version 5 SOCKS */ - 0x02, /* No. Methods */ - 0x00, /* Null Auth */ - 0x02 }; /* User/Pass Auth */ - - show_msg(MSGDEBUG, "Constructing V5 method negotiation\n"); - conn->state = SENDING; - conn->nextstate = SENTV5METHOD; - memcpy(conn->buffer, verstring, sizeof(verstring)); - conn->datalen = sizeof(verstring); - conn->datadone = 0; - - return(0); -} - -static int send_socksv5_connect(struct connreq *conn) -{ - int namelen = 0; - char *name = NULL; - char constring[] = { 0x05, /* Version 5 SOCKS */ - 0x01, /* Connect request */ - 0x00, /* Reserved */ - 0x01 }; /* IP Version 4 */ - - show_msg(MSGDEBUG, "Constructing V5 connect request\n"); - conn->datadone = 0; - conn->state = SENDING; - conn->nextstate = SENTV5CONNECT; - memcpy(conn->buffer, constring, sizeof(constring)); - conn->datalen = sizeof(constring); - - show_msg(MSGDEBUG, "send_socksv5_connect: looking for: %s\n", - inet_ntoa(conn->connaddr.sin_addr)); - - name = get_pool_entry(pool, &(conn->connaddr.sin_addr)); - if(name != NULL) { - namelen = strlen(name); - if(namelen > 255) /* "Can't happen" */ - name = NULL; - } - if(name != NULL) { - show_msg(MSGDEBUG, "send_socksv5_connect: found it!\n"); - /* Substitute the domain name from the pool into the SOCKS request. */ - conn->buffer[3] = 0x03; /* Change the ATYP field */ - conn->buffer[4] = namelen; /* Length of name */ - conn->datalen++; - memcpy(&conn->buffer[conn->datalen], name, namelen); - conn->datalen += namelen; - } else { - show_msg(MSGDEBUG, "send_socksv5_connect: ip address not found\n"); - /* Use the raw IP address */ - memcpy(&conn->buffer[conn->datalen], &(conn->connaddr.sin_addr.s_addr), - sizeof(conn->connaddr.sin_addr.s_addr)); - conn->datalen += sizeof(conn->connaddr.sin_addr.s_addr); - } - memcpy(&conn->buffer[conn->datalen], &(conn->connaddr.sin_port), - sizeof(conn->connaddr.sin_port)); - conn->datalen += sizeof(conn->connaddr.sin_port); - - return(0); -} - -static int send_buffer(struct connreq *conn) -{ - int rc = 0; - - show_msg(MSGDEBUG, "Writing to server (sending %d bytes)\n", conn->datalen); - while ((rc == 0) && (conn->datadone != conn->datalen)) { - rc = send(conn->sockid, conn->buffer + conn->datadone, - conn->datalen - conn->datadone, 0); - if (rc > 0) { - conn->datadone += rc; - rc = 0; - } else { - if (errno != EWOULDBLOCK) - show_msg(MSGDEBUG, "Write failed, %s\n", strerror(errno)); - rc = errno; - } - } - - if (conn->datadone == conn->datalen) - conn->state = conn->nextstate; - - show_msg(MSGDEBUG, "Sent %d bytes of %d bytes in buffer, return code is %d\n", - conn->datadone, conn->datalen, rc); - return(rc); -} - -static int recv_buffer(struct connreq *conn) -{ - int rc = 0; - - show_msg(MSGDEBUG, "Reading from server (expecting %d bytes)\n", conn->datalen); - while ((rc == 0) && (conn->datadone != conn->datalen)) { - rc = recv(conn->sockid, conn->buffer + conn->datadone, - conn->datalen - conn->datadone, 0); - if (rc > 0) { - conn->datadone += rc; - rc = 0; - } else if (rc == 0) { - show_msg(MSGDEBUG, "Peer has shutdown but we only read %d of %d bytes.\n", - conn->datadone, conn->datalen); - rc = ENOTCONN; /* ENOTCONN seems like the most fitting error message */ - } else { - if (errno != EWOULDBLOCK) - show_msg(MSGDEBUG, "Read failed, %s\n", strerror(errno)); - rc = errno; - } - } - - if (conn->datadone == conn->datalen) - conn->state = conn->nextstate; - - show_msg(MSGDEBUG, "Received %d bytes of %d bytes expected, return code is %d\n", - conn->datadone, conn->datalen, rc); - return(rc); -} - -static int read_socksv5_method(struct connreq *conn) -{ - struct passwd *nixuser; - char *uname, *upass; - - /* See if we offered an acceptable method */ - if (conn->buffer[1] == '\xff') { - show_msg(MSGERR, "SOCKS V5 server refused authentication methods\n"); - conn->state = FAILED; - return(ECONNREFUSED); - } - - /* If the socks server chose username/password authentication */ - /* (method 2) then do that */ - if ((unsigned short int) conn->buffer[1] == 2) { - show_msg(MSGDEBUG, "SOCKS V5 server chose username/password authentication\n"); - - /* Determine the current *nix username */ - nixuser = getpwuid(getuid()); - - if (((uname = conn->path->defuser) == NULL) && - ((uname = getenv("TORSOCKS_USERNAME")) == NULL) && - ((uname = (nixuser == NULL ? NULL : nixuser->pw_name)) == NULL)) { - show_msg(MSGERR, "Could not get SOCKS username from " - "local passwd file, torsocks.conf " - "or $TORSOCKS_USERNAME to authenticate " - "with"); - conn->state = FAILED; - return(ECONNREFUSED); - } - - if (((upass = getenv("TORSOCKS_PASSWORD")) == NULL) && - ((upass = conn->path->defpass) == NULL)) { - show_msg(MSGERR, "Need a password in torsocks.conf or " - "$TORSOCKS_PASSWORD to authenticate with"); - conn->state = FAILED; - return(ECONNREFUSED); - } - - /* Check that the username / pass specified will */ - /* fit into the buffer */ - if ((3 + strlen(uname) + strlen(upass)) >= sizeof(conn->buffer)) { - show_msg(MSGERR, "The supplied socks username or " - "password is too long"); - conn->state = FAILED; - return(ECONNREFUSED); - } - - conn->datalen = 0; - conn->buffer[conn->datalen] = '\x01'; - conn->datalen++; - conn->buffer[conn->datalen] = (int8_t) strlen(uname); - conn->datalen++; - memcpy(&(conn->buffer[conn->datalen]), uname, strlen(uname)); - conn->datalen = conn->datalen + strlen(uname); - conn->buffer[conn->datalen] = (int8_t) strlen(upass); - conn->datalen++; - memcpy(&(conn->buffer[conn->datalen]), upass, strlen(upass)); - conn->datalen = conn->datalen + strlen(upass); - - conn->state = SENDING; - conn->nextstate = SENTV5AUTH; - conn->datadone = 0; - } else - return(send_socksv5_connect(conn)); - - return(0); -} - -static int read_socksv5_auth(struct connreq *conn) -{ - - if (conn->buffer[1] != '\x00') { - show_msg(MSGERR, "SOCKS authentication failed, check username and password\n"); - conn->state = FAILED; - return(ECONNREFUSED); - } - - /* Ok, we authenticated ok, send the connection request */ - return(send_socksv5_connect(conn)); -} - -static int read_socksv5_connect(struct connreq *conn) -{ - - /* See if the connection succeeded */ - if (conn->buffer[1] != '\x00') { - show_msg(MSGERR, "SOCKS V5 connect failed: "); - conn->state = FAILED; - switch ((int8_t) conn->buffer[1]) { - case 1: - show_msg(MSGERR, "General SOCKS server failure\n"); - return(ECONNABORTED); - case 2: - show_msg(MSGERR, "Connection denied by rule\n"); - return(ECONNABORTED); - case 3: - show_msg(MSGERR, "Network unreachable\n"); - return(ENETUNREACH); - case 4: - show_msg(MSGERR, "Host unreachable\n"); - return(EHOSTUNREACH); - case 5: - show_msg(MSGERR, "Connection refused\n"); - return(ECONNREFUSED); - case 6: - show_msg(MSGERR, "TTL Expired\n"); - return(ETIMEDOUT); - case 7: - show_msg(MSGERR, "Command not supported\n"); - return(ECONNABORTED); - case 8: - show_msg(MSGERR, "Address type not supported\n"); - return(ECONNABORTED); - default: - show_msg(MSGERR, "Unknown error\n"); - return(ECONNABORTED); - } - } - conn->state = DONE; - - return(0); -} - -static int read_socksv4_req(struct connreq *conn) -{ - struct sockrep *thisrep; - - thisrep = (struct sockrep *) conn->buffer; - - if (thisrep->result != 90) { - show_msg(MSGERR, "SOCKS V4 connect rejected:\n"); - conn->state = FAILED; - switch(thisrep->result) { - case 91: - show_msg(MSGERR, "SOCKS server refused connection\n"); - return(ECONNREFUSED); - case 92: - show_msg(MSGERR, "SOCKS server refused connection " - "because of failed connect to identd " - "on this machine\n"); - return(ECONNREFUSED); - case 93: - show_msg(MSGERR, "SOCKS server refused connection " - "because identd and this library " - "reported different user-ids\n"); - return(ECONNREFUSED); - default: - show_msg(MSGERR, "Unknown reason\n"); - return(ECONNREFUSED); - } - } - conn->state = DONE; - - return(0); -} diff --git a/src.old/socks.h b/src.old/socks.h deleted file mode 100644 index 6dd497f..0000000 --- a/src.old/socks.h +++ /dev/null @@ -1,116 +0,0 @@ -/*************************************************************************** - * * - * Copyright (C) 2000-2008 Shaun Clowes delius@progsoc.org * - * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* socks.h - Structures used by torsocks to form SOCKS requests */ - -#ifndef _SOCKS_H - -#define _SOCKS_H 1 - -#include "parser.h" -#include "dead_pool.h" - -/* Structure representing a socks connection request */ -struct sockreq { - int8_t version; - int8_t command; - int16_t dstport; - int32_t dstip; - /* A null terminated username goes here */ -}; - -/* Structure representing a socks connection request response */ -struct sockrep { - int8_t version; - int8_t result; - int16_t ignore1; - int32_t ignore2; -}; - -/* Structure representing a socket which we are currently proxying */ -struct connreq { - /* Information about the socket and target */ - int sockid; - struct sockaddr_in connaddr; - struct sockaddr_in serveraddr; - - /* Pointer to the config entry for the socks server */ - struct serverent *path; - - /* Current state of this proxied socket */ - int state; - - /* Next state to go to when the send or receive is finished */ - int nextstate; - - /* When connections fail but an error number cannot be reported - * because the socket is non blocking we keep the connreq struct until - * the status is queried with connect() again, we then return - * this value */ - int err; - - /* Events that were set for this socket upon call to select() or - * poll() */ - int selectevents; - - /* Buffer for sending and receiving on the socket */ - unsigned int datalen; - unsigned int datadone; - char buffer[2048]; - - struct connreq *next; -}; - -/* Connection statuses */ -#define UNSTARTED 0 -#define CONNECTING 1 -#define CONNECTED 2 -#define SENDING 3 -#define RECEIVING 4 -#define SENTV4REQ 5 -#define GOTV4REQ 6 -#define SENTV5METHOD 7 -#define GOTV5METHOD 8 -#define SENTV5AUTH 9 -#define GOTV5AUTH 10 -#define SENTV5CONNECT 11 -#define GOTV5CONNECT 12 -#define DONE 13 -#define FAILED 14 - -/* Flags to indicate what events a socket was select()ed for */ -#define READ (1<<0) -#define WRITE (1<<1) -#define EXCEPT (1<<2) -#define READWRITE (READ|WRITE) -#define READWRITEEXCEPT (READ|WRITE|EXCEPT) - -/* Global Declarations */ -extern dead_pool *pool; -extern struct connreq *requests; - -struct connreq *new_socks_request(int sockid, struct sockaddr_in *connaddr, - struct sockaddr_in *serveraddr, - struct serverent *path); -void kill_socks_request(struct connreq *conn); -struct connreq *find_socks_request(int sockid, int includefailed); -int handle_request(struct connreq *conn); - -#endif diff --git a/src.old/torsocks.c b/src.old/torsocks.c deleted file mode 100644 index 597c107..0000000 --- a/src.old/torsocks.c +++ /dev/null @@ -1,1108 +0,0 @@ -/*************************************************************************** - * * - * * - * Copyright (C) 2000-2008 Shaun Clowes delius@progsoc.org * - * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -/* PreProcessor Defines */ -#include <config.h> - -/*Defining _NONSTD_SOURCE causes library and kernel calls to behave as closely -to Mac OS X 10.3's library and kernel calls as possible.*/ -#if defined(__APPLE__) || defined(__darwin__) -/* -From 'man compat' in OSX: -64-BIT COMPILATION - When compiling for 64-bit architectures, the __LP64__ macro will be defined to 1, and UNIX conformance - is always on (the _DARWIN_FEATURE_UNIX_CONFORMANCE macro will also be defined to the SUS conformance - level). Defining _NONSTD_SOURCE will cause a compilation error. -*/ -#if !defined(__LP64__) -#define _NONSTD_SOURCE 1 -#endif -#include <sys/socket.h> -#endif - - -#ifdef USE_GNU_SOURCE -#define _GNU_SOURCE -#endif - -/* Global configuration variables */ -const char *torsocks_progname = "libtorsocks"; /* Name used in err msgs */ - -/* Header Files */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <dlfcn.h> -#include <sys/types.h> -#include <string.h> -#include <strings.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/poll.h> -#include <sys/time.h> -#include <pwd.h> -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdarg.h> -#if !defined(__APPLE__) && !defined(__darwin__) -#include <sys/socket.h> -#endif -#include <resolv.h> - -#include "common.h" -#include "dead_pool.h" -#include "parser.h" -#include "socks.h" - -/* Some function names are macroized on Darwin. Allow those names - to expand accordingly. */ -#define EXPAND_GUTS(x) torsocks_##x##_guts -#define EXPAND_GUTS_NAME(x) EXPAND_GUTS(x) - -/* Function prototypes for original functions that we patch */ -#ifdef SUPPORT_RES_API -int (*realres_init)(void); -#endif -#define PATCH_TABLE_EXPANSION(e,r,s,n,b,m) r (*real##n)(s##SIGNATURE); -#include "expansion_table.h" -#undef PATCH_TABLE_EXPANSION -#undef DARWIN_EXPANSION - -static struct parsedfile config; -static int suid = 0; -static char *conffile = NULL; - -/* Exported Function Prototypes */ -void __attribute__ ((constructor)) torsocks_init(void); - -/* Function prototypes for our patches */ -#ifdef SUPPORT_RES_API -int res_init(void); -#endif - -#define PATCH_TABLE_EXPANSION(e,r,s,n,b,m) r n(s##SIGNATURE); -#define DARWIN_EXPANSION(e,r,s,n,b,m) r n(s##SIGNATURE) __asm("_" m); -#include "expansion_table.h" -#undef PATCH_TABLE_EXPANSION -#undef DARWIN_EXPANSION - -/* Private Function Prototypes */ -/* no torsocks_res_init_guts */ -#define PATCH_TABLE_EXPANSION(e,r,s,n,b,m) r torsocks_##b##_guts(s##SIGNATURE, r (*original_##b)(s##SIGNATURE)); -#include "expansion_table.h" -#undef PATCH_TABLE_EXPANSION - -static int get_config(); -static int get_environment(); -static int deadpool_init(void); - -static pthread_mutex_t torsocks_init_mutex = PTHREAD_MUTEX_INITIALIZER; - -void torsocks_init(void) -{ - pthread_mutex_lock(&torsocks_init_mutex); - - show_msg(MSGDEBUG, "In torsocks_init \n"); - - get_environment(); - get_config(); - -#ifdef USE_OLD_DLSYM - void *lib; -#endif - - /* We could do all our initialization here, but to be honest */ - /* most programs that are run won't use our services, so */ - /* we do our general initialization on first call */ - - /* Determine the logging level */ - suid = (getuid() != geteuid()); - - dlerror(); -#ifndef USE_OLD_DLSYM - #ifdef SUPPORT_RES_API - torsocks_find_library("res_init", MSGERR, realres_init); - #endif - #define PATCH_TABLE_EXPANSION(e,r,s,n,b,m) torsocks_find_library(m, MSG##e, real##n); - #include "expansion_table.h" - #undef PATCH_TABLE_EXPANSION -#else - lib = dlopen(LIBCONNECT, RTLD_LAZY); - realconnect = dlsym(lib, "connect"); - realselect = dlsym(lib, "select"); - realpoll = dlsym(lib, "poll"); - realgethostbyname = dlsym(lib, "gethostbyname"); - realgethostbyaddr = dlsym(lib, "gethostbyaddr"); - realgetaddrinfo = dlsym(lib, "getaddrinfo"); - realgetipnodebyname = dlsym(lib, "getipnodebyname"); - realsendto = dlsym(lib, "sendto"); - realsendmsg = dlsym(lib, "sendmsg"); - dlclose(lib); - lib = dlopen(LIBC, RTLD_LAZY); - realclose = dlsym(lib, "close"); - dlclose(lib); - #ifdef SUPPORT_RES_API - lib = dlopen(LIBRESOLV, RTLD_LAZY); - realres_init = dlsym(lib, "res_init"); - realresquery = dlsym(lib, "res_query"); - realressend = dlsym(lib, "res_send"); - realresquerydomain = dlsym(lib, "res_querydomain"); - realressearch = dlsym(lib, "res_search"); - dlclose(lib); - #endif -#endif - /* Unfortunately, we can't do this lazily because otherwise our mmap'd - area won't be shared across fork()s. */ - if (!deadpool_init()) { - show_msg(MSGERR, "Fatal error: exiting\n"); - exit(1); - } - - pthread_mutex_unlock(&torsocks_init_mutex); - - show_msg(MSGDEBUG, "Exit torsocks_init \n"); -} - -static int get_environment() -{ - static int done = 0; - int loglevel = MSGERR; - char *logfile = NULL; - char *env; - - if (done) - return(0); - - /* Determine the logging level */ - if ((env = getenv("TORSOCKS_DEBUG"))) - loglevel = atoi(env); - if (((env = getenv("TORSOCKS_DEBUG_FILE"))) && !suid) - logfile = env; - set_log_options(loglevel, logfile, (loglevel == MSGTEST) ? 0 : 1); - - done = 1; - - return(0); -} - -static int get_config () -{ - static int done = 0; - - if (done) - return(0); - - /* Determine the location of the config file */ -#ifdef ALLOW_ENV_CONFIG - if (!suid) - conffile = getenv("TORSOCKS_CONF_FILE"); -#endif - - /* Read in the config file */ - read_config(conffile, &config); - if (config.paths) - show_msg(MSGDEBUG, "First lineno for first path is %d\n", config.paths->lineno); - - done = 1; - - return(0); -} - -/* Patch trampoline functions */ -/* no torsocks_res_init_guts */ -#define PATCH_TABLE_EXPANSION(e,r,s,n,b,m) \ - r n(s##SIGNATURE) { \ - if (!real##n) { \ - torsocks_find_library(m, MSG##e, real##n);\ - } \ - return torsocks_##b##_guts(s##ARGNAMES, real##n); \ - } -#include "expansion_table.h" -#undef PATCH_TABLE_EXPANSION - -int torsocks_connect_guts(CONNECT_SIGNATURE, int (*original_connect)(CONNECT_SIGNATURE)) -{ - struct sockaddr_in *connaddr; - struct sockaddr_in peer_address; - struct sockaddr_in server_address; - int gotvalidserver = 0, rc; - socklen_t namelen = sizeof(peer_address); - int sock_type = -1; - socklen_t sock_type_len = sizeof(sock_type); - int res = -1; - struct serverent *path; - struct connreq *newconn; - - /* If the real connect doesn't exist, we're stuffed */ - if (original_connect == NULL) { - show_msg(MSGERR, "Unresolved symbol: connect\n"); - return(-1); - } - - show_msg(MSGTEST, "Got connection request\n"); - - connaddr = (struct sockaddr_in *) __addr; - - /* Get the type of the socket */ - getsockopt(__fd, SOL_SOCKET, SO_TYPE, - (void *) &sock_type, &sock_type_len); - - show_msg(MSGDEBUG, "sin_family: %i\n", connaddr->sin_family); - - show_msg(MSGDEBUG, "sockopt: %i \n", sock_type); - - /* If the address is local refuse it. We do this because it could - be a TCP DNS request to a local DNS server.*/ - if (!(is_local(&config, &(connaddr->sin_addr))) && - !is_dead_address(pool, connaddr->sin_addr.s_addr)) { - char buf[16]; - inet_ntop(AF_INET, &(connaddr->sin_addr), buf, sizeof(buf)); - show_msg(MSGERR, "connect: Connection is to a local address (%s), may be a " - "TCP DNS request to a local DNS server so have to reject to be safe. " - "Please report a bug to http://code.google.com/p/torsocks/issues/entry if " - "this is preventing a program from working properly with torsocks.\n", buf); - return -1; - } - - /* If this is an INET6, we'll refuse it. */ - if ((connaddr->sin_family == AF_INET6)) { - show_msg(MSGERR, "connect: Connection is IPv6: rejecting.\n"); - errno = EAFNOSUPPORT; - return -1; - } - - /* If this isn't an INET socket we can't */ - /* handle it, just call the real connect now */ - if ((connaddr->sin_family != AF_INET)) { - show_msg(MSGDEBUG, "connect: Connection isn't IPv4, ignoring\n"); - return(original_connect(__fd, __addr, __len)); - } - - /* If this a UDP socket */ - /* then we refuse it, since it is probably a DNS request */ - if ((sock_type != SOCK_STREAM)) { - show_msg(MSGERR, "connect: Connection is a UDP or ICMP stream, may be a " - "DNS request or other form of leak: rejecting.\n"); - return -1; - } - - /* If we haven't initialized yet, do it now */ - get_config(); - - /* Are we already handling this connect? */ - if ((newconn = find_socks_request(__fd, 1))) { - if (memcmp(&newconn->connaddr, connaddr, sizeof(*connaddr))) { - /* Ok, they're calling connect on a socket that is in our - * queue but this connect() isn't to the same destination, - * they're obviously not trying to check the status of - * they're non blocking connect, they must have close()d - * the other socket and created a new one which happens - * to have the same fd as a request we haven't had the chance - * to delete yet, so we delete it here. */ - show_msg(MSGDEBUG, "Call to connect received on old " - "torsocks request for socket %d but to " - "new destination, deleting old request\n", - newconn->sockid); - kill_socks_request(newconn); - } else { - /* Ok, this call to connect() is to check the status of - * a current non blocking connect(). */ - if (newconn->state == FAILED) { - show_msg(MSGDEBUG, "Call to connect received on failed " - "request %d, returning %d\n", - newconn->sockid, newconn->err); - errno = newconn->err; - rc = -1; - } else if (newconn->state == DONE) { - show_msg(MSGERR, "Call to connect received on completed " - "request %d\n", - newconn->sockid, newconn->err); - rc = 0; - } else { - show_msg(MSGDEBUG, "Call to connect received on current request %d\n", - newconn->sockid); - rc = handle_request(newconn); - errno = rc; - } - if ((newconn->state == FAILED) || (newconn->state == DONE)) - kill_socks_request(newconn); - return((rc ? -1 : 0)); - } - } - - /* If the socket is already connected, just call connect */ - /* and get its standard reply */ - if (!getpeername(__fd, (struct sockaddr *) &peer_address, &namelen)) { - show_msg(MSGDEBUG, "Socket is already connected, defering to " - "real connect\n"); - return(original_connect(__fd, __addr, __len)); - } - - show_msg(MSGDEBUG, "Got connection request for socket %d to " - "%s\n", __fd, inet_ntoa(connaddr->sin_addr)); - - /* Ok, so its not local, we need a path to the net */ - pick_server(&config, &path, &(connaddr->sin_addr), ntohs(connaddr->sin_port)); - - show_msg(MSGDEBUG, "Picked server %s for connection\n", - (path->address ? path->address : "(Not Provided)")); - if (path->address == NULL) { - if (path == &(config.defaultserver)) - show_msg(MSGERR, "Connection needs to be made " - "via default server but " - "the default server has not " - "been specified\n"); - else - show_msg(MSGERR, "Connection needs to be made " - "via path specified at line " - "%d in configuration file but " - "the server has not been " - "specified for this path\n", - path->lineno); - } else if ((res = resolve_ip(path->address, 0, 0)) == -1) { - show_msg(MSGERR, "The SOCKS server (%s) listed in the configuration " - "file which needs to be used for this connection " - "is invalid\n", path->address); - } else { - /* Construct the addr for the socks server */ - server_address.sin_family = AF_INET; /* host byte order */ - server_address.sin_addr.s_addr = res; - server_address.sin_port = htons(path->port); - bzero(&(server_address.sin_zero), 8); - - /* Complain if this server isn't on a localnet */ - if (is_local(&config, &server_address.sin_addr)) { - show_msg(MSGERR, "SOCKS server %s (%s) is not on a local subnet!\n", - path->address, inet_ntoa(server_address.sin_addr)); - } else - gotvalidserver = 1; - } - - /* If we haven't found a valid server we return connection refused */ - if (!gotvalidserver || - !(newconn = new_socks_request(__fd, connaddr, &server_address, path))) { - errno = ECONNREFUSED; - return(-1); - } else { - /* Now we call the main function to handle the connect. */ - rc = handle_request(newconn); - /* If the request completed immediately it mustn't have been - * a non blocking socket, in this case we don't need to know - * about this socket anymore. */ - if ((newconn->state == FAILED) || (newconn->state == DONE)) - kill_socks_request(newconn); - errno = rc; - /* We may get either of these if there are no bytes to read from - the non-blocking connection in handle_request(). Since we are - wrapping connect() here we can't return EWOULDBLOCK/EAGAIN - so override it with something the client will accept.*/ - if (errno == EWOULDBLOCK || errno == EAGAIN) - errno = EINPROGRESS; - return((rc ? -1 : 0)); - } -} - -int torsocks_select_guts(SELECT_SIGNATURE, int (*original_select)(SELECT_SIGNATURE)) -{ - int nevents = 0; - int rc = 0; - int setevents = 0; - int monitoring = 0; - struct connreq *conn, *nextconn; - fd_set mywritefds, myreadfds, myexceptfds; - - /* If we're not currently managing any requests we can just - * leave here */ - if (!requests) { - show_msg(MSGDEBUG, "No requests waiting, calling real select\n"); - return(original_select(n, readfds, writefds, exceptfds, timeout)); - } - - show_msg(MSGTEST, "Intercepted call to select\n"); - show_msg(MSGDEBUG, "Intercepted call to select with %d fds, " - "0x%08x 0x%08x 0x%08x, timeout %08x\n", n, - readfds, writefds, exceptfds, timeout); - - for (conn = requests; conn != NULL; conn = conn->next) { - if ((conn->state == FAILED) || (conn->state == DONE)) - continue; - conn->selectevents = 0; - show_msg(MSGDEBUG, "Checking requests for socks enabled socket %d\n", - conn->sockid); - conn->selectevents |= (writefds ? (FD_ISSET(conn->sockid, writefds) ? WRITE : 0) : 0); - conn->selectevents |= (readfds ? (FD_ISSET(conn->sockid, readfds) ? READ : 0) : 0); - conn->selectevents |= (exceptfds ? (FD_ISSET(conn->sockid, exceptfds) ? EXCEPT : 0) : 0); - if (conn->selectevents) { - show_msg(MSGDEBUG, "Socket %d was set for events\n", conn->sockid); - monitoring = 1; - } - } - - if (!monitoring) - return(original_select(n, readfds, writefds, exceptfds, timeout)); - - /* This is our select loop. In it we repeatedly call select(). We - * pass select the same fdsets as provided by the caller except we - * modify the fdsets for the sockets we're managing to get events - * we're interested in (while negotiating with the socks server). When - * events we're interested in happen we go off and process the result - * ourselves, without returning the events to the caller. The loop - * ends when an event which isn't one we need to handle occurs or - * the select times out */ - do { - /* Copy the clients fd events, we'll change them as we wish */ - if (readfds) - memcpy(&myreadfds, readfds, sizeof(myreadfds)); - else - FD_ZERO(&myreadfds); - if (writefds) - memcpy(&mywritefds, writefds, sizeof(mywritefds)); - else - FD_ZERO(&mywritefds); - if (exceptfds) - memcpy(&myexceptfds, exceptfds, sizeof(myexceptfds)); - else - FD_ZERO(&myexceptfds); - - /* Now enable our sockets for the events WE want to hear about */ - for (conn = requests; conn != NULL; conn = conn->next) { - if ((conn->state == FAILED) || (conn->state == DONE) || - (conn->selectevents == 0)) - continue; - /* We always want to know about socket exceptions */ - FD_SET(conn->sockid, &myexceptfds); - /* If we're waiting for a connect or to be able to send - * on a socket we want to get write events */ - if ((conn->state == SENDING) || (conn->state == CONNECTING)) - FD_SET(conn->sockid,&mywritefds); - else - FD_CLR(conn->sockid,&mywritefds); - /* If we're waiting to receive data we want to get - * read events */ - if (conn->state == RECEIVING) - FD_SET(conn->sockid,&myreadfds); - else - FD_CLR(conn->sockid,&myreadfds); - } - - nevents = original_select(n, &myreadfds, &mywritefds, &myexceptfds, timeout); - /* If there were no events we must have timed out or had an error */ - if (nevents <= 0) - break; - - /* Loop through all the sockets we're monitoring and see if - * any of them have had events */ - for (conn = requests; conn != NULL; conn = nextconn) { - nextconn = conn->next; - if ((conn->state == FAILED) || (conn->state == DONE)) - continue; - show_msg(MSGDEBUG, "Checking socket %d for events\n", conn->sockid); - /* Clear all the events on the socket (if any), we'll reset - * any that are necessary later. */ - setevents = 0; - if (FD_ISSET(conn->sockid, &mywritefds)) { - nevents--; - setevents |= WRITE; - show_msg(MSGDEBUG, "Socket had write event\n"); - FD_CLR(conn->sockid, &mywritefds); - } - if (FD_ISSET(conn->sockid, &myreadfds)) { - nevents--; - setevents |= READ; - show_msg(MSGDEBUG, "Socket had write event\n"); - FD_CLR(conn->sockid, &myreadfds); - } - if (FD_ISSET(conn->sockid, &myexceptfds)) { - nevents--; - setevents |= EXCEPT; - show_msg(MSGDEBUG, "Socket had except event\n"); - FD_CLR(conn->sockid, &myexceptfds); - } - - if (!setevents) { - show_msg(MSGDEBUG, "No events on socket %d\n", conn->sockid); - continue; - } - - if (setevents & EXCEPT) - conn->state = FAILED; - else - rc = handle_request(conn); - - /* If the connection hasn't failed or completed there is nothing - * to report to the client */ - if ((conn->state != FAILED) && - (conn->state != DONE)) - continue; - - /* Ok, the connection is completed, for good or for bad. We now - * hand back the relevant events to the caller. We don't delete the - * connection though since the caller should call connect() to - * check the status, we delete it then */ - - if (conn->state == FAILED) { - /* Damn, the connection failed. Whatever the events the socket - * was selected for we flag */ - if (conn->selectevents & EXCEPT) { - FD_SET(conn->sockid, &myexceptfds); - nevents++; - } - if (conn->selectevents & READ) { - FD_SET(conn->sockid, &myreadfds); - nevents++; - } - if (conn->selectevents & WRITE) { - FD_SET(conn->sockid, &mywritefds); - nevents++; - } - /* We should use setsockopt to set the SO_ERROR errno for this - * socket, but this isn't allowed for some silly reason which - * leaves us a bit hamstrung. - * We don't delete the request so that hopefully we can - * return the error on the socket if they call connect() on it */ - } else { - /* The connection is done, if the client selected for - * writing we can go ahead and signal that now (since the socket must - * be ready for writing), otherwise we'll just let the select loop - * come around again (since we can't flag it for read, we don't know - * if there is any data to be read and can't be bothered checking) */ - if (conn->selectevents & WRITE) { - FD_SET(conn->sockid, &mywritefds); - nevents++; - } - } - } - } while (nevents == 0); - - show_msg(MSGDEBUG, "Finished intercepting select(), %d events\n", nevents); - - /* Now copy our event blocks back to the client blocks */ - if (readfds) - memcpy(readfds, &myreadfds, sizeof(myreadfds)); - if (writefds) - memcpy(writefds, &mywritefds, sizeof(mywritefds)); - if (exceptfds) - memcpy(exceptfds, &myexceptfds, sizeof(myexceptfds)); - - return(nevents); -} - -int torsocks_poll_guts(POLL_SIGNATURE, int (*original_poll)(POLL_SIGNATURE)) -{ - int nevents = 0; - int rc = 0; - unsigned int i; - int setevents = 0; - int monitoring = 0; - struct connreq *conn, *nextconn; - - /* If we're not currently managing any requests we can just - * leave here */ - if (!requests) - return(original_poll(ufds, nfds, timeout)); - - show_msg(MSGTEST, "Intercepted call to poll\n"); - show_msg(MSGDEBUG, "Intercepted call to poll with %d fds, " - "0x%08x timeout %d\n", nfds, ufds, timeout); - - for (conn = requests; conn != NULL; conn = conn->next) - conn->selectevents = 0; - - /* Record what events on our sockets the caller was interested - * in */ - for (i = 0; i < nfds; i++) { - if (!(conn = find_socks_request(ufds[i].fd, 0))) - continue; - show_msg(MSGDEBUG, "Have event checks for socks enabled socket %d\n", - conn->sockid); - conn->selectevents = ufds[i].events; - monitoring = 1; - } - - if (!monitoring) - return(original_poll(ufds, nfds, timeout)); - - /* This is our poll loop. In it we repeatedly call poll(). We - * pass select the same event list as provided by the caller except we - * modify the events for the sockets we're managing to get events - * we're interested in (while negotiating with the socks server). When - * events we're interested in happen we go off and process the result - * ourselves, without returning the events to the caller. The loop - * ends when an event which isn't one we need to handle occurs or - * the poll times out */ - do { - /* Enable our sockets for the events WE want to hear about */ - for (i = 0; i < nfds; i++) { - if (!(conn = find_socks_request(ufds[i].fd, 0))) - continue; - - /* We always want to know about socket exceptions but they're - * always returned (i.e they don't need to be in the list of - * wanted events to be returned by the kernel */ - ufds[i].events = 0; - - /* If we're waiting for a connect or to be able to send - * on a socket we want to get write events */ - if ((conn->state == SENDING) || (conn->state == CONNECTING)) - ufds[i].events |= POLLOUT; - /* If we're waiting to receive data we want to get - * read events */ - if (conn->state == RECEIVING) - ufds[i].events |= POLLIN; - } - - nevents = original_poll(ufds, nfds, timeout); - /* If there were no events we must have timed out or had an error */ - if (nevents <= 0) - break; - - /* Loop through all the sockets we're monitoring and see if - * any of them have had events */ - for (conn = requests; conn != NULL; conn = nextconn) { - nextconn = conn->next; - if ((conn->state == FAILED) || (conn->state == DONE)) - continue; - - /* Find the socket in the poll list */ - for (i = 0; ((i < nfds) && (ufds[i].fd != conn->sockid)); i++) - /* Empty Loop */; - if (i == nfds) - continue; - - show_msg(MSGDEBUG, "Checking socket %d for events\n", conn->sockid); - - if (!ufds[i].revents) { - show_msg(MSGDEBUG, "No events on socket\n"); - continue; - } - - /* Clear any read or write events on the socket, we'll reset - * any that are necessary later. */ - setevents = ufds[i].revents; - if (setevents & POLLIN) { - show_msg(MSGDEBUG, "Socket had read event\n"); - ufds[i].revents &= ~POLLIN; - nevents--; - } - if (setevents & POLLOUT) { - show_msg(MSGDEBUG, "Socket had write event\n"); - ufds[i].revents &= ~POLLOUT; - nevents--; - } - if (setevents & (POLLERR | POLLNVAL | POLLHUP)) - show_msg(MSGDEBUG, "Socket had error event\n"); - - /* Now handle this event */ - if (setevents & (POLLERR | POLLNVAL | POLLHUP)) { - conn->state = FAILED; - } else { - rc = handle_request(conn); - } - /* If the connection hasn't failed or completed there is nothing - * to report to the client */ - if ((conn->state != FAILED) && - (conn->state != DONE)) - continue; - - /* Ok, the connection is completed, for good or for bad. We now - * hand back the relevant events to the caller. We don't delete the - * connection though since the caller should call connect() to - * check the status, we delete it then */ - - if (conn->state == FAILED) { - /* Damn, the connection failed. Just copy back the error events - * from the poll call, error events are always valid even if not - * requested by the client */ - /* We should use setsockopt to set the SO_ERROR errno for this - * socket, but this isn't allowed for some silly reason which - * leaves us a bit hamstrung. - * We don't delete the request so that hopefully we can - * return the error on the socket if they call connect() on it */ - } else { - /* The connection is done, if the client polled for - * writing we can go ahead and signal that now (since the socket must - * be ready for writing), otherwise we'll just let the select loop - * come around again (since we can't flag it for read, we don't know - * if there is any data to be read and can't be bothered checking) */ - if (conn->selectevents & POLLOUT) { - setevents |= POLLOUT; - nevents++; - } - } - } - } while (nevents == 0); - - show_msg(MSGDEBUG, "Finished intercepting poll(), %d events\n", nevents); - - /* Now restore the events polled in each of the blocks */ - for (i = 0; i < nfds; i++) { - if (!(conn = find_socks_request(ufds[i].fd, 1))) - continue; - ufds[i].events = conn->selectevents; - } - - return(nevents); -} - -int torsocks_close_guts(CLOSE_SIGNATURE, int (*original_close)(CLOSE_SIGNATURE)) -{ - int rc; - struct connreq *conn; - - /* If we're not currently managing any requests we can just - * leave here */ - if (!requests) { - show_msg(MSGDEBUG, "No requests waiting, calling real close\n"); - return(original_close(fd)); - } - - if (original_close == NULL) { - show_msg(MSGERR, "Unresolved symbol: close\n"); - return(-1); - } - - show_msg(MSGTEST, "Got call to close()\n"); - show_msg(MSGDEBUG, "Call to close(%d)\n", fd); - - rc = original_close(fd); - - /* If we have this fd in our request handling list we - * remove it now */ - if ((conn = find_socks_request(fd, 1))) { - show_msg(MSGDEBUG, "Call to close() received on file descriptor " - "%d which is a connection request of status %d\n", - conn->sockid, conn->state); - kill_socks_request(conn); - } - - return(rc); -} - -/* If we are not done setting up the connection yet, return - * -1 and ENOTCONN, otherwise call getpeername - * - * This is necessary since some applications, when using non-blocking connect, - * (like ircII) use getpeername() to find out if they are connected already. - * - * This results in races sometimes, where the client sends data to the socket - * before we are done with the socks connection setup. Another solution would - * be to intercept send(). - * - * This could be extended to actually set the peername to the peer the - * client application has requested, but not for now. - * - * PP, Sat, 27 Mar 2004 11:30:23 +0100 - */ - -int torsocks_getpeername_guts(GETPEERNAME_SIGNATURE, - int (*original_getpeername)(GETPEERNAME_SIGNATURE)) -{ - struct connreq *conn; - int rc; - - if (original_getpeername == NULL) { - show_msg(MSGERR, "Unresolved symbol: getpeername\n"); - return(-1); - } - - show_msg(MSGTEST, "Intercepted call to getpeername\n"); - show_msg(MSGDEBUG, "Call to getpeername for fd %d\n", __fd); - - - rc = original_getpeername(__fd, __name, __namelen); - if (rc == -1) - return rc; - - /* Are we handling this connect? */ - if ((conn = find_socks_request(__fd, 1))) { - /* While we are at it, we might was well try to do something useful */ - handle_request(conn); - - if (conn->state != DONE) { - errno = ENOTCONN; - return(-1); - } - } - return rc; -} - -#ifdef SUPPORT_RES_API -int res_init(void) -{ - int rc; - - if (!realres_init) { - torsocks_find_library("res_init", MSGERR, realres_init); - } - - show_msg(MSGTEST, "Got res_init request\n"); - - if (realres_init == NULL) { - show_msg(MSGERR, "Unresolved symbol: res_init\n"); - return(-1); - } - /* Call normal res_init */ - rc = realres_init(); - - /* Force using TCP protocol for DNS queries */ - _res.options |= RES_USEVC; - return(rc); -} - -int EXPAND_GUTS_NAME(res_query)(RES_QUERY_SIGNATURE, int (*original_res_query)(RES_QUERY_SIGNATURE)) -{ - int rc; - - if (!original_res_query) { - torsocks_find_library("res_query", MSGERR, original_res_query); - } - - show_msg(MSGTEST, "Got res_query request\n"); - - if (original_res_query == NULL) { - show_msg(MSGERR, "Unresolved symbol: res_query\n"); - return(-1); - } - - /* Ensure we force using TCP for DNS queries by calling res_init - above if it has not already been called.*/ - if (!(_res.options & RES_INIT) || !(_res.options & RES_USEVC)) - res_init(); - - /* Call normal res_query */ - rc = original_res_query(dname, class, type, answer, anslen); - - return(rc); -} - -int EXPAND_GUTS_NAME(res_querydomain)(RES_QUERYDOMAIN_SIGNATURE, int (*original_res_querydomain)(RES_QUERYDOMAIN_SIGNATURE)) -{ - int rc; - - if (!original_res_querydomain) { - torsocks_find_library("res_querydomain", MSGERR, original_res_querydomain); - } - - show_msg(MSGDEBUG, "Got res_querydomain request\n"); - - if (original_res_querydomain == NULL) { - show_msg(MSGERR, "Unresolved symbol: res_querydomain\n"); - return(-1); - } - - /* Ensure we force using TCP for DNS queries by calling res_init - above if it has not already been called.*/ - if (!(_res.options & RES_INIT) || !(_res.options & RES_USEVC)) - res_init(); - - /* Call normal res_querydomain */ - rc = original_res_querydomain(name, domain, class, type, answer, anslen); - - return(rc); -} - -int EXPAND_GUTS_NAME(res_search)(RES_SEARCH_SIGNATURE, int (*original_res_search)(RES_SEARCH_SIGNATURE)) -{ - int rc; - - if (!original_res_search) { - torsocks_find_library("res_search", MSGERR, original_res_search); - } - - show_msg(MSGTEST, "Got res_search request\n"); - - if (original_res_search == NULL) { - show_msg(MSGERR, "Unresolved symbol: res_search\n"); - return(-1); - } - - /* Ensure we force using TCP for DNS queries by calling res_init - above if it has not already been called.*/ - if (!(_res.options & RES_INIT) || !(_res.options & RES_USEVC)) - res_init(); - - /* Call normal res_search */ - rc = original_res_search(dname, class, type, answer, anslen); - - return(rc); -} - -int EXPAND_GUTS_NAME(res_send)(RES_SEND_SIGNATURE, int (*original_res_send)(RES_SEND_SIGNATURE)) -{ - int rc; - - if (!original_res_send) { - torsocks_find_library("res_send", MSGERR, original_res_send); - } - - show_msg(MSGTEST, "Got res_send request\n"); - - if (original_res_send == NULL) { - show_msg(MSGERR, "Unresolved symbol: res_send\n"); - return(-1); - } - - /* Ensure we force using TCP for DNS queries by calling res_init - above if it has not already been called.*/ - if (!(_res.options & RES_INIT) || !(_res.options & RES_USEVC)) - res_init(); - - /* Call normal res_send */ - rc = original_res_send(msg, msglen, answer, anslen); - - return(rc); -} -#endif - -static int deadpool_init(void) -{ - if (pool) - return 1; - - if (!config.tordns_enabled) { - show_msg(MSGERR, "Tor DNS is disabled. Check your configuration.\n"); - return 0; - } - - get_environment(); - get_config(); - pool = init_pool(config.tordns_cache_size, - config.tordns_deadpool_range->localip, - config.tordns_deadpool_range->localnet, - config.defaultserver.address, - config.defaultserver.port); - - if (!pool) { - show_msg(MSGERR, "Could not initialize reserved addresses for " - ".onion addresses. Torsocks will not work properly.\n"); - return 0; - } - return 1; -} - -struct hostent *torsocks_gethostbyname_guts(GETHOSTBYNAME_SIGNATURE, struct hostent *(*original_gethostbyname)(GETHOSTBYNAME_SIGNATURE)) -{ - if (pool) - return our_gethostbyname(pool, name); - return original_gethostbyname(name); -} - -struct hostent *torsocks_gethostbyaddr_guts(GETHOSTBYADDR_SIGNATURE, struct hostent *(*original_gethostbyaddr)(GETHOSTBYADDR_SIGNATURE)) -{ - if (pool) - return our_gethostbyaddr(pool, addr, len, type); - return original_gethostbyaddr(addr, len, type); -} - -int torsocks_getaddrinfo_guts(GETADDRINFO_SIGNATURE, int (*original_getaddrinfo)(GETADDRINFO_SIGNATURE)) -{ - if (pool) - return our_getaddrinfo(pool, node, service, hints, res); - return original_getaddrinfo(node, service, hints, res); -} - -struct hostent *torsocks_getipnodebyname_guts(GETIPNODEBYNAME_SIGNATURE, struct hostent *(*original_getipnodebyname)(GETIPNODEBYNAME_SIGNATURE)) -{ - if (pool) - return our_getipnodebyname(pool, name, af, flags, error_num); - return original_getipnodebyname(name, af, flags, error_num); -} - -ssize_t torsocks_sendto_guts(SENDTO_SIGNATURE, ssize_t (*original_sendto)(SENDTO_SIGNATURE)) -{ - int sock_type = -1; - unsigned int sock_type_len = sizeof(sock_type); - struct sockaddr_in *connaddr; - - /* If the real sendto doesn't exist, we're stuffed */ - if (original_sendto == NULL) { - show_msg(MSGERR, "Unresolved symbol: sendto\n"); - return(-1); - } - - show_msg(MSGTEST, "Got sendto request\n"); - - /* Get the type of the socket */ - getsockopt(s, SOL_SOCKET, SO_TYPE, - (void *) &sock_type, &sock_type_len); - - show_msg(MSGDEBUG, "sockopt: %i\n", sock_type); - - /* If this a UDP socket then we refuse it, since it is probably a DNS - request */ - if ((sock_type != SOCK_STREAM)) { - show_msg(MSGERR, "sendto: Connection is a UDP or ICMP stream, may be a " - "DNS request or other form of leak: rejecting.\n"); - return -1; - } - - connaddr = (struct sockaddr_in *) to; - - /* If there is no address in 'to', sendto will only work if we - already allowed the socket to connect(), so we let it through. - Likewise if the socket is not an Internet connection. */ - if (connaddr && (connaddr->sin_family != AF_INET)) { - show_msg(MSGDEBUG, "Connection isn't an Internet socket ignoring\n"); - } - - return (ssize_t) original_sendto(s, buf, len, flags, to, tolen); -} - -ssize_t torsocks_sendmsg_guts(SENDMSG_SIGNATURE, ssize_t (*original_sendmsg)(SENDMSG_SIGNATURE)) -{ - int sock_type = -1; - unsigned int sock_type_len = sizeof(sock_type); - struct sockaddr_in *connaddr; - - /* If the real sendmsg doesn't exist, we're stuffed */ - if (original_sendmsg == NULL) { - show_msg(MSGERR, "Unresolved symbol: sendmsg\n"); - return(-1); - } - - show_msg(MSGTEST, "Got sendmsg request\n"); - - /* Get the type of the socket */ - getsockopt(s, SOL_SOCKET, SO_TYPE, - (void *) &sock_type, &sock_type_len); - - show_msg(MSGDEBUG, "sockopt: %i\n", sock_type); - - if ((sock_type != SOCK_STREAM)) { - show_msg(MSGERR, "sendmsg: Connection is a UDP or ICMP stream, may be a " - "DNS request or other form of leak: rejecting.\n"); - return -1; - } - - connaddr = (struct sockaddr_in *) msg->msg_name; - - /* If there is no address in msg_name, sendmsg will only work if we - already allowed the socket to connect(), so we let it through. - Likewise if the socket is not an Internet connection. */ - if (connaddr && (connaddr->sin_family != AF_INET)) { - show_msg(MSGDEBUG, "Connection isn't an Internet socket\n"); - } - - return (ssize_t) original_sendmsg(s, msg, flags); -} - diff --git a/src.old/torsocks.in b/src.old/torsocks.in deleted file mode 100755 index 4eaed8f..0000000 --- a/src.old/torsocks.in +++ /dev/null @@ -1,167 +0,0 @@ -#!/bin/sh -# *************************************************************************** -# * * -# * * -# * Copyright (C) 2008 by Robert Hogan * -# * robert@roberthogan.net * -# * Copyright (C) 2012 by Jacob Appelbaum jacob@torproject.org * -# * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU General Public License as published by * -# * the Free Software Foundation; either version 2 of the License, or * -# * (at your option) any later version. * -# * * -# * This program is distributed in the hope that it will be useful, * -# * but WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -# * GNU General Public License for more details. * -# * * -# * You should have received a copy of the GNU General Public License * -# * along with this program; if not, write to the * -# * Free Software Foundation, Inc., * -#* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -# *************************************************************************** -# * * -# * This is a modified version of a source file from the Tor project. * -# * Original copyright information follows: * -# *************************************************************************** -# Wrapper script for use of the torsocks(8) transparent socksification library -# -# There are three forms of usage for this script: -# -# @prefix@/bin/torsocks program [program arguments...] -# -# This form sets the users @LDPRELOAD@ environment variable so that torsocks(8) -# will be loaded to socksify the application then executes the specified -# program (with the provided arguments). The following simple example might -# be used to telnet to www.foo.org via a torsocks.conf(5) configured socks server: -# -# @prefix@/bin/torsocks telnet www.foo.org -# -# The second form allows for torsocks(8) to be switched on and off for a -# session (that is, it adds and removes torsocks from the @LDPRELOAD@ environment -# variable). This form must be _sourced_ into the user's existing session -# (and will only work with bourne shell users): -# -# . @prefix@/bin/torsocks on -# telnet www.foo.org -# . @prefix@/bin/torsocks off -# -# Or -# -# source @prefix@/bin/torsocks on -# telnet www.foo.org -# source @prefix@/bin/torsocks off -# -# The third form creates a new shell with @LDPRELOAD@ set and is achieved -# simply by running the script with no arguments -# -# @prefix@/bin/torsocks -# -# When finished the user can simply terminate the shell with 'exit' -# -# This script is originally from the debian torsocks package by -# Tamas Szerb toma@rulez.org -# Modified by Robert Hogan robert@roberthogan.net April 16th 2006 - -not_found () { - echo "ERROR: $1 cannot be found in PATH." >&2 - exit 1 -} - -set_id () { - echo "ERROR: $1 is set${2}id. torsocks will not work on a set${2}id executable." >&2 - exit 1 -} - -if [ $# = 0 ] ; then - echo "$0: insufficient arguments" - exit -fi - -LIBDIR="@prefix@/lib/torsocks" -LIB_NAME="libtorsocks" -SHLIB_EXT="@SHLIB_EXT@" -SHLIB="${LIBDIR}/${LIB_NAME}.${SHLIB_EXT}" - -# Check for libtorsocks and if set the 64bit variant -if [ ! -f $SHLIB ]; then - LIBDIR="@prefix@/lib64/torsocks" - SHLIB="${LIBDIR}/${LIB_NAME}.${SHLIB_EXT}" -fi - -# Ensure libtorsocks exists, -if [ ! -f $SHLIB ]; then - echo "$0: $SHLIB does not exist! Try re-installing torsocks." - exit -fi - -case "$1" in - on) - if [ -z "$@LDPRELOAD@" ] - then - export @LDPRELOAD@="${SHLIB}" - else - echo $@LDPRELOAD@ | grep -q "${SHLIB}" || \ - export @LDPRELOAD@="${SHLIB} $@LDPRELOAD@" - fi - # FIXME: This env variable is only meaningful on Mac OSX, so it would be better - # not to set it at all on other platforms. - export DYLD_FORCE_FLAT_NAMESPACE=1 - ;; - off) - #replace '/' with '/' in @prefix@ - # escprefix=`echo '@prefix@' |sed 's/\//\\//g'` - # export @LDPRELOAD@=`echo -n $@LDPRELOAD@ | sed "s/$escprefix/lib/torsocks/libtorsocks.so ?//"` - export @LDPRELOAD@=`echo -n $@LDPRELOAD@ | sed "s#@prefix@/lib/torsocks/libtorsocks.@SHLIB_EXT@ *##"` - if [ -z "$@LDPRELOAD@" ] - then - unset @LDPRELOAD@ - # FIXME: This env variable is only meaningful on Mac OSX, so it would be better - # not to set it at all on other platforms. - unset DYLD_FORCE_FLAT_NAMESPACE=1 - fi - ;; - show|sh) - echo "@LDPRELOAD@="$@LDPRELOAD@"" - ;; - -h|-?) - echo "$0: Please see torsocks(1) or read comment at top of $0" - ;; - --shell) - if [ -z "$@LDPRELOAD@" ] - then - export @LDPRELOAD@="${SHLIB}" - else - echo $@LDPRELOAD@ | grep -q "${SHLIB}" || \ - export @LDPRELOAD@="${SHLIB} $@LDPRELOAD@" - fi - export DYLD_FORCE_FLAT_NAMESPACE=1 - echo "torsocks: new torified shell coming right up..." - ${SHELL:-/bin/sh} - ;; - *) - if [ -z "$@LDPRELOAD@" ] - then - export @LDPRELOAD@="${SHLIB}" - else - echo $@LDPRELOAD@ | grep -q "${SHLIB}" || \ - export @LDPRELOAD@="${SHLIB} $@LDPRELOAD@" - fi - export DYLD_FORCE_FLAT_NAMESPACE=1 - - if [ $# -gt 0 ] - then - if ! which "$1" >/dev/null 2>&1; then - not_found $1 - elif [ -u `which "$1"` ]; then - set_id $1 u - elif [ -g `which "$1"` ]; then - set_id $1 g - fi - exec "$@" - fi - ;; -esac - -#EOF diff --git a/src.old/usewithtor.in b/src.old/usewithtor.in deleted file mode 100644 index e606760..0000000 --- a/src.old/usewithtor.in +++ /dev/null @@ -1,113 +0,0 @@ -#! /bin/sh -# *************************************************************************** -# * * -# * Copyright (C) 2008-2011 Robert Hogan robert@roberthogan.net * -# * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU General Public License as published by * -# * the Free Software Foundation; either version 2 of the License, or * -# * (at your option) any later version. * -# * * -# * This program is distributed in the hope that it will be useful, * -# * but WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -# * GNU General Public License for more details. * -# * * -# * You should have received a copy of the GNU General Public License * -# * along with this program; if not, write to the * -# * Free Software Foundation, Inc., * -#* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -# *************************************************************************** -# * * -# * This is a modified version of a source file from the Tor project. * -# * Original copyright notice from tsocks source file follows: * -# *************************************************************************** - -# Wrapper script for use of the tsocks(8) transparent socksification library -# See the tsocks(1) and torify(1) manpages. - -# Copyright (c) 2004, 2006 Peter Palfrader -# Modified by Jacob Appelbaum jacob@appelbaum.net April 16th 2006 -# Modified by Marcus Griep marcus@griep.us June 16 2009 -# May be distributed under the same terms as Tor itself - - -# Define and ensure we have tsocks -# XXX: what if we don't have which? -TORSOCKS="`which torsocks`" -PROG= -VERBOSE= - -usage () { - echo "Usage: $0 [-hv] <command> [<options>...]" -} - -not_found () { - echo "ERROR: $1 cannot be found in PATH." >&2 - exit 1 -} - -set_id () { - echo "ERROR: $1 is set${2}id. usewithtor will not work on a set${2}id executable." >&2 - exit 1 -} - -# Check for any argument list -if [ "$#" = 0 ]; then - usage >&2 - exit 1 -fi - -while [ "$1" ]; do - case "$1" in - -h|--h*) - usage - exit 0 - ;; - -v|--v*) - VERBOSE=YesPlease - shift - ;; - *) - break; - esac -done - -if ! which "$1" >/dev/null 2>&1; then - not_found $1 -elif [ -u `which "$1"` ]; then - set_id $1 u -elif [ -g `which "$1"` ]; then - set_id $1 g -fi - -if [ -x "$TORSOCKS" ]; then - PROG=torsocks -else - echo "$0: Unable to find torsocks in PATH." >&2 - echo " Perhaps you haven't installed it?" >&2 - exit 1 -fi - -if [ "$VERBOSE" ]; then - echo "We're armed with the following torsocks: $TORSOCKS" - echo "We're attempting to use $PROG for all tor action." -fi - -if [ "$PROG" = "torsocks" ]; then - # Define our torsocks config file - TORSOCKS_CONF_FILE="@CONFDIR@/torsocks.conf" - export TORSOCKS_CONF_FILE - - # Check that we've got a torsocks config file - if [ -r "$TORSOCKS_CONF_FILE" ]; then - exec torsocks "$@" - else - echo "$0: Missing torsocks configuration file "$TORSOCKS_CONF_FILE" - torsocks will use defaults sensible for Tor." >&2 - exec torsocks "$@" - fi -fi - -# We should have hit an exec. If we get here, we didn't exec -echo "$0: failed to exec $PROG $@" >&2 -exit 1