diff options
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/oe-git-proxy-command | 10 | ||||
| -rwxr-xr-x | scripts/oe-git-proxy-socks-command | 23 | ||||
| -rw-r--r-- | scripts/oe-git-proxy-socks.c | 2982 | 
3 files changed, 0 insertions, 3015 deletions
| diff --git a/scripts/oe-git-proxy-command b/scripts/oe-git-proxy-command deleted file mode 100755 index d31f85abd8..0000000000 --- a/scripts/oe-git-proxy-command +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/bash - -(echo "CONNECT $1:$2 HTTP/1.0";  - echo;  - cat ) | nc $GIT_PROXY_HOST $GIT_PROXY_PORT |  -   -(read a;  - read a;  - read a;  - cat )
\ No newline at end of file diff --git a/scripts/oe-git-proxy-socks-command b/scripts/oe-git-proxy-socks-command deleted file mode 100755 index 8acffb5248..0000000000 --- a/scripts/oe-git-proxy-socks-command +++ /dev/null @@ -1,23 +0,0 @@ -#! /bin/bash -SCRIPTDIR=`dirname $0` -# Check oe-git-proxy-socks exists -PROXYSOCKS=`which oe-git-proxy-socks 2> /dev/null` -if [ -z "$PROXYSOCKS" -a -e "$SCRIPTDIR/oe-git-proxy-socks.c" ]; then -	# If not try and build it -	gcc $SCRIPTDIR/oe-git-proxy-socks.c -o $SCRIPTDIR/oe-git-proxy-socks -fi -PROXYSOCKS=`which oe-git-proxy-socks 2> /dev/null` -if [ ! -x "$PROXYSOCKS" ]; then -	# If that fails, we can see if netcat (nc) is available -	NETCAT=`which nc 2> /dev/null` -	if [ ! -x "$NETCAT" ]; then -		# If that fails, explain to the user -		echo "Unable to find oe-git-proxy-socks. This is usually created with the command" -		echo "'gcc scripts/oe-git-proxy-socks.c -o scripts/oe-git-proxy-socks' which we tried" -		echo "but it doesn't seem to have worked. Please compile the binary manually." -		echo "Alternativly, install nc (netcat) on this machine." -		exit 1 -	fi -	exec $NETCAT -x $GIT_PROXY_HOST:$GIT_PROXY_PORT "$@" -fi -oe-git-proxy-socks -S $GIT_PROXY_HOST:$GIT_PROXY_PORT $@ diff --git a/scripts/oe-git-proxy-socks.c b/scripts/oe-git-proxy-socks.c deleted file mode 100644 index f5747117ab..0000000000 --- a/scripts/oe-git-proxy-socks.c +++ /dev/null @@ -1,2982 +0,0 @@ -/*********************************************************************** - * connect.c -- Make socket connection using SOCKS4/5 and HTTP tunnel. - * - * Copyright (c) 2000-2006 Shun-ichi Goto - * Copyright (c) 2002, J. Grant (English Corrections) - * - * 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. - * - * --------------------------------------------------------- - * PROJECT:  My Test Program - * AUTHOR:   Shun-ichi GOTO <gotoh@taiyo.co.jp> - * CREATE:   Wed Jun 21, 2000 - * REVISION: $Revision: 100 $ - * --------------------------------------------------------- - * - * Getting Source - * ============== - * - *   Recent version of 'connect.c' is available from - *     http://www.taiyo.co.jp/~gotoh/ssh/connect.c - * - *   Related tool, ssh-askpass.exe (alternative ssh-askpass on UNIX) - *   is available: - *     http://www.taiyo.co.jp/~gotoh/ssh/ssh-askpass.exe.gz - * - *   See more detail: - *     http://www.taiyo.co.jp/~gotoh/ssh/connect.html - * - * How To Compile - * ============== - * - *  On UNIX environment: - *      $ gcc connect.c -o connect - * - *  On SOLARIS: - *      $ gcc -o connect -lresolv -lsocket -lnsl connect.c - * - *  on Win32 environment: - *      $ cl connect.c wsock32.lib advapi32.lib - *    or - *      $ bcc32 connect.c wsock32.lib advapi32.lib - *    or - *      $ gcc connect.c -o connect - * - *  on Mac OS X environment: - *      $ gcc connect.c -o connect -lresolv - *    or - *      $ gcc connect.c -o connect -DBIND_8_COMPAT=1 - * - * How To Use - * ========== - * - *   You can specify proxy method in an environment variable or in a - *   command line option. - * - *   usage:  connect [-dnhst45] [-R resolve] [-p local-port] [-w sec] - *                   [-H [user@]proxy-server[:port]] - *                   [-S [user@]socks-server[:port]] - *                   [-T proxy-server[:port]] - *                   [-c telnet proxy command] - *                   host port - * - *   "host" and "port" is for the target hostname and port-number to - *   connect to. - * - *   The -H option specifys a hostname and port number of the http proxy - *   server to relay. If port is omitted, 80 is used. You can specify this - *   value in the environment variable HTTP_PROXY and pass the -h option - *   to use it. - * - *   The -S option specifys the hostname and port number of the SOCKS - *   server to relay.  Like -H, port number can be omitted and the default - *   is 1080. You can also specify this value pair in the environment - *   variable SOCKS5_SERVER and give the -s option to use it. - * - *   The '-4' and the '-5' options are for specifying SOCKS relaying and - *   indicates protocol version to use. It is valid only when used with - *   '-s' or '-S'. Default is '-5' (protocol version 5) - * - *   The '-R' option is for specifying method to resolve the - *   hostname. Three keywords ("local", "remote", "both") or dot-notation - *   IP address are acceptable.  The keyword "both" means, "Try local - *   first, then remote". If a dot-notation IP address is specified, use - *   this host as nameserver. The default is "remote" for SOCKS5 or - *   "local" for others. On SOCKS4 protocol, remote resolving method - *   ("remote" and "both") requires protocol 4a supported server. - * - *   The '-p' option will forward a local TCP port instead of using the - *   standard input and output. - * - *   The '-P' option is same to '-p' except keep remote session. The - *   program repeats waiting the port with holding remote session without - *   disconnecting. To disconnect the remote session, send EOF to stdin or - *   kill the program. - * - *   The '-w' option specifys timeout seconds for making connection with - *   TARGET host. - * - *   The '-d' option is used for debug. If you fail to connect, use this - *   and check request to and response from server. - * - *   You can omit the "port" argument when program name is special format - *   containing port number itself. For example, - *     $ ln -s connect connect-25 - *   means this connect-25 command is spcifying port number 25 already - *   so you need not 2nd argument (and ignored if specified). - * - *   To use proxy, this example is for SOCKS5 connection to connect to - *   'host' at port 25 via SOCKS5 server on 'firewall' host. - *     $ connect -S firewall  host 25 - *   or - *     $ SOCKS5_SERVER=firewall; export SOCKS5_SERVER - *     $ connect -s host 25 - * - *   For a HTTP-PROXY connection: - *     $ connect -H proxy-server:8080  host 25 - *   or - *     $ HTTP_PROXY=proxy-server:8080; export HTTP_PROXY - *     $ connect -h host 25 - *   To forward a local port, for example to use ssh: - *     $ connect -p 5550 -H proxy-server:8080  host 22 - *    ($ ssh -l user -p 5550 localhost ) - * - * TIPS - * ==== - * - *   Connect.c doesn't have any configuration to specify the SOCKS server. - *   If you are a mobile user, this limitation might bother you.  However, - *   You can compile connect.c and link with other standard SOCKS library - *   like the NEC SOCKS5 library or Dante. This means connect.c is - *   socksified and uses a configration file like to other SOCKSified - *   network commands and you can switch configuration file any time - *   (ex. when ppp startup) that brings you switching of SOCKS server for - *   connect.c in same way with other commands. For this case, you can - *   write ~/.ssh/config like this: - * - *     ProxyCommand connect -n %h %p - * - * SOCKS5 authentication - * ===================== - * - *   Only USER/PASS authentication is supported. - * - * Proxy authentication - * ==================== - * - *   Only BASIC scheme is supported. - * - * Authentication informations - * =========================== - * - *   User name for authentication is specifed by an environment variable - *   or system login name.  And password is specified from environment - *   variable or external program (specified in $SSH_ASKPASS) or tty. - * - *   Following environment variable is used for specifying user name. - *     SOCKS: $SOCKS5_USER, $LOGNAME, $USER - *     HTTP Proxy: $HTTP_PROXY_USER, $LOGNAME, $USER - * - * ssh-askpass support - * =================== -  * - *   You can use ssh-askpass (came from OpenSSH or else) to specify - *   password on graphical environment (X-Window or MS Windows). To use - *   this, set program name to environment variable SSH_ASKPASS. On UNIX, - *   X-Window must be required, so $DISPLAY environment variable is also - *   needed.  On Win32 environment, $DISPLAY is not mentioned. - * - * Related Informations - * ==================== - * - *   SOCKS5 -- RFC 1928, RFC 1929, RFC 1961 - *             NEC SOCKS Reference Implementation is available from: - *               http://www.socks.nec.com - *             DeleGate version 5 or earlier can be SOCKS4 server, - *             and version 6 can be SOCKS5 and SOCKS4 server. - *             and version 7.7.0 or later can be SOCKS5 and SOCKS4a server. - *               http://www.delegate.org/delegate/ - * - *   HTTP-Proxy -- - *             Many http proxy servers supports this, but https should - *             be allowed as configuration on your host. - *             For example on DeleGate, you should add "https" to the - *             "REMITTABLE" parameter to allow HTTP-Proxy like this: - *               delegated -Pxxxx ...... REMITTABLE="+,https" ... - * - *  Hypertext Transfer Protocol -- HTTP/1.1  -- RFC 2616 - *  HTTP Authentication: Basic and Digest Access Authentication -- RFC 2617 - *             For proxy authentication, refer these documents. - * - ***********************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <memory.h> -#include <errno.h> -#include <assert.h> -#include <sys/types.h> -#include <stdarg.h> -#include <fcntl.h> -#include <signal.h> - -#ifdef __CYGWIN32__ -#undef _WIN32 -#endif - -#ifdef _WIN32 -#include <windows.h> -#include <winsock.h> -#include <sys/stat.h> -#include <io.h> -#include <conio.h> -#else /* !_WIN32 */ -#include <unistd.h> -#include <pwd.h> -#include <termios.h> -#include <sys/time.h> -#ifndef __hpux -#include <sys/select.h> -#endif /* __hpux */ -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#if !defined(_WIN32) && !defined(__CYGWIN32__) -#define WITH_RESOLVER 1 -#include <arpa/nameser.h> -#include <resolv.h> -#else  /* not ( not _WIN32 && not __CYGWIN32__) */ -#undef WITH_RESOLVER -#endif /* not ( not _WIN32 && not __CYGWIN32__) */ -#endif /* !_WIN32 */ - -#ifdef _WIN32 -#define ECONNRESET WSAECONNRESET -#endif /* _WI32 */ - - - -#ifndef LINT -static char *vcid = "$Id: connect.c 100 2007-07-03 10:48:26Z gotoh $"; -#endif - -/* Microsoft Visual C/C++ has _snprintf() and _vsnprintf() */ -#ifdef _MSC_VER -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#endif - -/* consider Borland C */ -#ifdef __BORLANDC__ -#define _kbhit kbhit -#define _setmode setmode -#endif - -/* help message. -   Win32 environment does not support -R option (vc and cygwin) -   Win32 native compilers does not support -w option, yet (vc) -*/ -static char *usage = "usage: %s [-dnhst45] [-p local-port]" -#ifdef _WIN32 -#ifdef __CYGWIN32__ -"[-w timeout] \n"                               /* cygwin cannot -R */ -#else  /* not __CYGWIN32__ */ -" \n"                                           /* VC cannot -w nor -R  */ -#endif /* not __CYGWIN32__ */ -#else  /* not _WIN32 */ -/* help message for UNIX */ -"[-R resolve] [-w timeout] \n" -#endif /* not _WIN32 */ -"          [-H proxy-server[:port]] [-S [user@]socks-server[:port]] \n" -"          [-T proxy-server[:port]]\n" -"          [-c telnet-proxy-command]\n" -"          host port\n"; - -/* name of this program */ -char *progname = NULL; -char *progdesc = "connect --- simple relaying command via proxy."; -char *rcs_revstr = "$Revision: 100 $"; -char *revstr = NULL; -int major_version = 1; -int minor_version = 0; - -/* set of character for strspn() */ -const char *digits    = "0123456789"; -const char *dotdigits = "0123456789."; - -/* options */ -int f_debug = 0; - -/* report flag to hide secure information */ -int f_report = 1; - -int connect_timeout = 0; - -/* local input type */ -#define LOCAL_STDIO     0 -#define LOCAL_SOCKET    1 -char *local_type_names[] = { "stdio", "socket" }; -int   local_type = LOCAL_STDIO; -u_short local_port = 0;                         /* option 'p' */ -int f_hold_session = 0;                         /* option 'P' */ - -char *telnet_command = "telnet %h %p"; - -/* utiity types, pair holder of number and string */ -typedef struct { -    int num; -    const char *str; -} LOOKUP_ITEM; - -/* relay method, server and port */ -#define METHOD_UNDECIDED 0 -#define METHOD_DIRECT    1 -#define METHOD_SOCKS     2 -#define METHOD_HTTP      3 -#define METHOD_TELNET    4 -char *method_names[] = { "UNDECIDED", "DIRECT", "SOCKS", "HTTP", "TELNET" }; - -int   relay_method = METHOD_UNDECIDED;          /* relaying method */ -char *relay_host = NULL;                        /* hostname of relay server */ -u_short relay_port = 0;                         /* port of relay server */ -char *relay_user = NULL;                        /* user name for auth */ - -/* destination target host and port */ -char *dest_host = NULL; -struct sockaddr_in dest_addr; -u_short dest_port = 0; - -/* informations for SOCKS */ -#define SOCKS5_REP_SUCCEEDED    0x00    /* succeeded */ -#define SOCKS5_REP_FAIL         0x01    /* general SOCKS serer failure */ -#define SOCKS5_REP_NALLOWED     0x02    /* connection not allowed by ruleset */ -#define SOCKS5_REP_NUNREACH     0x03    /* Network unreachable */ -#define SOCKS5_REP_HUNREACH     0x04    /* Host unreachable */ -#define SOCKS5_REP_REFUSED      0x05    /* connection refused */ -#define SOCKS5_REP_EXPIRED      0x06    /* TTL expired */ -#define SOCKS5_REP_CNOTSUP      0x07    /* Command not supported */ -#define SOCKS5_REP_ANOTSUP      0x08    /* Address not supported */ -#define SOCKS5_REP_INVADDR      0x09    /* Inalid address */ - -LOOKUP_ITEM socks5_rep_names[] = { -    { SOCKS5_REP_SUCCEEDED, "succeeded"}, -    { SOCKS5_REP_FAIL,      "general SOCKS server failure"}, -    { SOCKS5_REP_NALLOWED,  "connection not allowed by ruleset"}, -    { SOCKS5_REP_NUNREACH,  "Network unreachable"}, -    { SOCKS5_REP_HUNREACH,  "Host unreachable"}, -    { SOCKS5_REP_REFUSED,   "connection refused"}, -    { SOCKS5_REP_EXPIRED,   "TTL expired"}, -    { SOCKS5_REP_CNOTSUP,   "Command not supported"}, -    { SOCKS5_REP_ANOTSUP,   "Address not supported"}, -    { SOCKS5_REP_INVADDR,   "Invalid address"}, -    { -1, NULL } -}; - -/* SOCKS5 authentication methods */ -#define SOCKS5_AUTH_REJECT      0xFF    /* No acceptable auth method */ -#define SOCKS5_AUTH_NOAUTH      0x00    /* without authentication */ -#define SOCKS5_AUTH_GSSAPI      0x01    /* GSSAPI */ -#define SOCKS5_AUTH_USERPASS    0x02    /* User/Password */ -#define SOCKS5_AUTH_CHAP        0x03    /* Challenge-Handshake Auth Proto. */ -#define SOCKS5_AUTH_EAP         0x05    /* Extensible Authentication Proto. */ -#define SOCKS5_AUTH_MAF         0x08    /* Multi-Authentication Framework */ - -#define SOCKS4_REP_SUCCEEDED    90      /* rquest granted (succeeded) */ -#define SOCKS4_REP_REJECTED     91      /* request rejected or failed */ -#define SOCKS4_REP_IDENT_FAIL   92      /* cannot connect identd */ -#define SOCKS4_REP_USERID       93      /* user id not matched */ - -LOOKUP_ITEM socks4_rep_names[] = { -    { SOCKS4_REP_SUCCEEDED,  "request granted (succeeded)"}, -    { SOCKS4_REP_REJECTED,   "request rejected or failed"}, -    { SOCKS4_REP_IDENT_FAIL, "cannot connect identd"}, -    { SOCKS4_REP_USERID,     "user id not matched"}, -    { -1, NULL } -}; - -#define RESOLVE_UNKNOWN 0 -#define RESOLVE_LOCAL   1 -#define RESOLVE_REMOTE  2 -#define RESOLVE_BOTH    3 -char *resolve_names[] = { "UNKNOWN", "LOCAL", "REMOTE", "BOTH" }; - -int socks_version = 5;                          /* SOCKS protocol version */ -int socks_resolve = RESOLVE_UNKNOWN; -struct sockaddr_in socks_ns; -char *socks5_auth = NULL; - -/* Environment variable names */ -#define ENV_SOCKS_SERVER  "SOCKS_SERVER"        /* SOCKS server */ -#define ENV_SOCKS5_SERVER "SOCKS5_SERVER" -#define ENV_SOCKS4_SERVER "SOCKS4_SERVER" - -#define ENV_SOCKS_RESOLVE  "SOCKS_RESOLVE"      /* resolve method */ -#define ENV_SOCKS5_RESOLVE "SOCKS5_RESOLVE" -#define ENV_SOCKS4_RESOLVE "SOCKS4_RESOLVE" - -#define ENV_SOCKS5_USER     "SOCKS5_USER"       /* auth user for SOCKS5 */ -#define ENV_SOCKS4_USER     "SOCKS4_USER"       /* auth user for SOCKS4 */ -#define ENV_SOCKS_USER      "SOCKS_USER"        /* auth user for SOCKS */ -#define ENV_SOCKS5_PASSWD   "SOCKS5_PASSWD"     /* auth password for SOCKS5 */ -#define ENV_SOCKS5_PASSWORD "SOCKS5_PASSWORD"   /* old style */ - -#define ENV_HTTP_PROXY          "HTTP_PROXY"    /* common env var */ -#define ENV_HTTP_PROXY_USER     "HTTP_PROXY_USER" /* auth user */ -#define ENV_HTTP_PROXY_PASSWORD "HTTP_PROXY_PASSWORD" /* auth password */ - -#define ENV_TELNET_PROXY          "TELNET_PROXY"    /* common env var */ - -#define ENV_CONNECT_USER     "CONNECT_USER"     /* default auth user name */ -#define ENV_CONNECT_PASSWORD "CONNECT_PASSWORD" /* default auth password */ - -#define ENV_SOCKS_DIRECT   "SOCKS_DIRECT"       /* addr-list for non-proxy */ -#define ENV_SOCKS5_DIRECT  "SOCKS5_DIRECT" -#define ENV_SOCKS4_DIRECT  "SOCKS4_DIRECT" -#define ENV_HTTP_DIRECT    "HTTP_DIRECT" -#define ENV_CONNECT_DIRECT "CONNECT_DIRECT" - -#define ENV_SOCKS5_AUTH "SOCKS5_AUTH" -#define ENV_SSH_ASKPASS "SSH_ASKPASS"           /* askpass program */ - -/* Prefix string of HTTP_PROXY */ -#define HTTP_PROXY_PREFIX "http://" -#define PROXY_AUTH_NONE 0 -#define PROXY_AUTH_BASIC 1 -#define PROXY_AUTH_DIGEST 2 -int proxy_auth_type = PROXY_AUTH_NONE; - -/* reason of end repeating */ -#define REASON_UNK              -2 -#define REASON_ERROR            -1 -#define REASON_CLOSED_BY_LOCAL  0 -#define REASON_CLOSED_BY_REMOTE 1 - -/* return value of relay start function. */ -#define START_ERROR -1 -#define START_OK     0 -#define START_RETRY  1 - -/* socket related definitions */ -#ifndef _WIN32 -#define SOCKET int -#endif -#ifndef SOCKET_ERROR -#define SOCKET_ERROR -1 -#endif - -#ifdef _WIN32 -#define socket_errno() WSAGetLastError() -#else /* !_WIN32 */ -#define closesocket close -#define socket_errno() (errno) -#endif /* !_WIN32 */ - -#ifdef _WIN32 -#define popen _popen -#endif /* WIN32 */ - -/* packet operation macro */ -#define PUT_BYTE(ptr,data) (*(unsigned char*)ptr = data) - -/* debug message output */ -void -debug( const char *fmt, ... ) -{ -    va_list args; -    if ( f_debug ) { -        va_start( args, fmt ); -        fprintf(stderr, "DEBUG: "); -        vfprintf( stderr, fmt, args ); -        va_end( args ); -    } -} - -void -debug_( const char *fmt, ... )                  /* without prefix */ -{ -    va_list args; -    if ( f_debug ) { -        va_start( args, fmt ); -        vfprintf( stderr, fmt, args ); -        va_end( args ); -    } -} - -/* error message output */ -void -error( const char *fmt, ... ) -{ -    va_list args; -    va_start( args, fmt ); -    fprintf(stderr, "ERROR: "); -    vfprintf( stderr, fmt, args ); -    va_end( args ); -} - -void -fatal( const char *fmt, ... ) -{ -    va_list args; -    va_start( args, fmt ); -    fprintf(stderr, "FATAL: "); -    vfprintf( stderr, fmt, args ); -    va_end( args ); -    exit (EXIT_FAILURE); -} - - -void * -xmalloc (size_t size) -{ -    void *ret = malloc(size); -    if (ret == NULL) -	fatal("Cannot allocate memory: %d bytes.\n", size); -    return ret; -} - -char * -downcase( char *str ) -{ -    char *buf = str; -    while ( *buf ) { -        if ( isupper(*buf) ) -            *buf += 'a'-'A'; -        buf++; -    } -    return str;                                 /* return converted arg */ -} - -char * -expand_host_and_port (const char *fmt, const char *host, int port) -{ -    const char *src; -    char *buf, *dst, *ptr; -    size_t len = strlen(fmt) + strlen(host) + 20; -    buf = xmalloc (len); -    dst = buf; -    src = fmt; -     -    while (*src) { -	if (*src == '%') { -	    switch (src[1]) { -	    case 'h': -		strcpy (dst, host); -		src += 2; -		break; -	    case 'p': -		snprintf (dst, len, "%d", port); -		src += 2; -		break; -	    default: -		src ++; -		break; -	    } -	    dst = buf + strlen (buf); -	} else if (*src == '\\') { -	    switch (src[1]) { -	    case 'r':				/* CR */ -		*dst++ = '\r'; -		src += 2; -		break; -	    case 'n':				/* LF */ -		*dst++ = '\n'; -		src += 2; -		break; -	    case 't':				/* TAB */ -		*dst++ = '\t'; -		src += 2; -		break; -	    default: -		src ++; -		break; -	    } -	} else { -	    /* usual */ -	    *dst++ = *src++; -	} -	*dst = '\0'; -    } -    assert (strlen(buf) < len); -    return buf; -} - - -int -lookup_resolve( const char *str ) -{ -    char *buf = strdup( str ); -    int ret; - -    downcase( buf ); -    if ( strcmp( buf, "both" ) == 0 ) -        ret = RESOLVE_BOTH; -    else if ( strcmp( buf, "remote" ) == 0 ) -        ret = RESOLVE_REMOTE; -    else if ( strcmp( buf, "local" ) == 0 ) -        ret = RESOLVE_LOCAL; -    else if ( strspn(buf, dotdigits) == strlen(buf) ) { -#ifndef WITH_RESOLVER -        fatal("Sorry, you can't specify to resolve the hostname with the -R option on Win32 environment."); -#endif /* not WITH_RESOLVER */ -        ret = RESOLVE_LOCAL;                    /* this case is also 'local' */ -        socks_ns.sin_addr.s_addr = inet_addr(buf); -        socks_ns.sin_family = AF_INET; -    } -    else -        ret = RESOLVE_UNKNOWN; -    free(buf); -    return ret; -} - -char * -getusername(void) -{ -#ifdef _WIN32 -    static char buf[1024]; -    DWORD size = sizeof(buf); -    buf[0] = '\0'; -    GetUserName( buf, &size); -    return buf; -#else  /* not _WIN32 */ -    struct passwd *pw = getpwuid(getuid()); -    if ( pw == NULL ) -        fatal("getpwuid() failed for uid: %d\n", getuid()); -    return pw->pw_name; -#endif /* not _WIN32 */ -} - -/* expect -   check STR is begin with substr with case-ignored comparison. -   Return 1 if matched, otherwise 0. -*/ -int -expect( char *str, char *substr) -{ -    int len = strlen(substr); -    while ( 0 < len-- ) { -        if ( toupper(*str) != toupper(*substr) ) -            return 0;                           /* not matched */ -        str++, substr++; -    } -    return 1;                   /* good, matched */ -} - - -/** PARAMETER operation **/ -#define PARAMETER_FILE "/etc/connectrc" -#define PARAMETER_DOTFILE ".connectrc" -typedef struct { -    char* name; -    char* value; -} PARAMETER_ITEM; -PARAMETER_ITEM parameter_table[] = { -    { ENV_SOCKS_SERVER, NULL }, -    { ENV_SOCKS5_SERVER, NULL }, -    { ENV_SOCKS4_SERVER, NULL }, -    { ENV_SOCKS_RESOLVE, NULL }, -    { ENV_SOCKS5_RESOLVE, NULL }, -    { ENV_SOCKS4_RESOLVE, NULL }, -    { ENV_SOCKS5_USER, NULL }, -    { ENV_SOCKS5_PASSWD, NULL }, -    { ENV_SOCKS5_PASSWORD, NULL }, -    { ENV_HTTP_PROXY, NULL }, -    { ENV_HTTP_PROXY_USER, NULL }, -    { ENV_HTTP_PROXY_PASSWORD, NULL }, -    { ENV_CONNECT_USER, NULL }, -    { ENV_CONNECT_PASSWORD, NULL }, -    { ENV_SSH_ASKPASS, NULL }, -    { ENV_SOCKS5_DIRECT, NULL }, -    { ENV_SOCKS4_DIRECT, NULL }, -    { ENV_SOCKS_DIRECT, NULL }, -    { ENV_HTTP_DIRECT, NULL }, -    { ENV_CONNECT_DIRECT, NULL }, -    { ENV_SOCKS5_AUTH, NULL }, -    { NULL, NULL } -}; - -PARAMETER_ITEM* -find_parameter_item(const char* name) -{ -    int i; -    for( i = 0; parameter_table[i].name != NULL; i++ ){ -        if ( strcmp(name, parameter_table[i].name) == 0 ) -            return ¶meter_table[i]; -    } -    return NULL; -} - -void -read_parameter_file_1(const char* name) -{ -    FILE* f; -    int line; -    char lbuf[1025]; -    f = fopen(name, "r"); -    if( f ){ -        debug("Reading parameter file(%s)\n", name); -        for ( line = 1; fgets(lbuf, 1024, f); line++ ) { -            char *p, *q, *param, *value; -            p = strchr(lbuf, '\n'); -            if ( p == NULL ) -                fatal("%s:%d: buffer overflow\n", name, line); -            *p = '\0'; -            p = strchr(lbuf, '#'); -            if ( p ) -                *p = '\0'; -            for ( p = lbuf; *p; p++ ) -                if( *p != ' ' && *p != '\t' ) break; -            if ( *p == '\0' ) continue; -            param = p; -            p = strchr(p, '='); -            if ( p == NULL ) { -                error("%s:%d: missing equal sign\n", name, line); -                continue; -            } -            for ( q = p - 1; q >= lbuf; q-- ) -                if ( *q != ' ' && *q != '\t' ) break; -            *++q = '\0'; -            for ( ++p; *p; p++ ) -                if ( *p != ' ' && *p != '\t' ) break; -            value = p; -            for ( ; *p; p++ ); -            for ( p--; p >= lbuf; p-- ) -                if ( *p != ' ' && *p != '\t' ) break; -            *++p = '\0'; -            if ( param && value ) { -                PARAMETER_ITEM *item; -                item = find_parameter_item(param); -                if ( item == NULL ) { -                    error("%s:%d: unknown parameter `%s'\n", name, line, param); -                    continue; -                } -                item->value = strdup(value); -                debug("Parameter `%s' is set to `%s'\n", param, value); -            } -        } -    } -} - -void -read_parameter_file(void) -{ -#if !defined(_WIN32) || defined(cygwin) -    char *name; -    struct passwd *pw; -#endif - -    read_parameter_file_1(PARAMETER_FILE); -#if !defined(_WIN32) || defined(cygwin) -    pw = getpwuid(getuid()); -    if ( pw == NULL ) -        fatal("getpwuid() failed for uid: %d\n", getuid()); -    name = xmalloc(strlen(pw->pw_dir) + strlen(PARAMETER_DOTFILE) + 2); -    strcpy(name, pw->pw_dir); -    strcat(name, "/" PARAMETER_DOTFILE); -    read_parameter_file_1(name); -    free(name); -#endif /* _WIN32 */ -} - -char* -getparam(const char* name) -{ -    char *value = getenv(name); -    if ( value == NULL ){ -        PARAMETER_ITEM *item = find_parameter_item(name); -        if ( item != NULL ) -            value = item->value; -    } -    return value; -} - - -/** DIRECT connection **/ -#define MAX_DIRECT_ADDR_LIST 256 - -struct ADDRPAIR { -    struct in_addr addr; -    struct in_addr mask; -    char *name; -    int negative; -}; - -struct ADDRPAIR direct_addr_list[MAX_DIRECT_ADDR_LIST]; -int n_direct_addr_list = 0; - -void -mask_addr (void *addr, void *mask, int addrlen) -{ -    char *a, *m; -    a = addr; -    m = mask; -    while ( 0 < addrlen-- ) -        *a++ &= *m++; -} - -int -add_direct_addr (struct in_addr *addr, struct in_addr *mask, int negative) -{ -    struct in_addr iaddr; -    char *s; -    if ( MAX_DIRECT_ADDR_LIST <= n_direct_addr_list ) { -        error("direct address table is full!\n"); -        return -1; -    } -    iaddr = *addr; -    mask_addr(&iaddr, mask, sizeof(iaddr)); -    s = strdup(inet_ntoa(iaddr)); -    debug("adding direct addr entry: %s%s/%s\n", -          negative? "!": "", s, inet_ntoa(*mask)); -    free(s); -    memcpy( &direct_addr_list[n_direct_addr_list].addr, -            &iaddr, sizeof(iaddr)); -    memcpy( &direct_addr_list[n_direct_addr_list].mask, -            mask, sizeof(*mask)); -    direct_addr_list[n_direct_addr_list].name = NULL; -    direct_addr_list[n_direct_addr_list].negative = negative; -    n_direct_addr_list++; -    return 0; -} - - -/* add domain/host name entry to direct name table */ -int -add_direct_host( const char *name, int negative) -{ -    if ( MAX_DIRECT_ADDR_LIST <= n_direct_addr_list ) { -        error("direct address table is full!\n"); -        return -1; -    } -    if (*name == '*') -        name++; -    if (*name == '.') -        name++; -    debug("adding direct name entry: %s%s\n", negative? "!": "", name); -    direct_addr_list[n_direct_addr_list].name = downcase(strdup(name)); -    direct_addr_list[n_direct_addr_list].negative = negative; -    n_direct_addr_list++; -    return 0; -} - - -int -parse_addr_pair (const char *str, struct in_addr *addr, struct in_addr *mask) -{ -    /* NOTE: */ -    /* Assume already be splitted by separator -       and formatted as folowing: -       1)  12.34.56.789/255.255.255.0 -       2)  12.34.56.789/24 -       3)  12.34.56. -       All above generates same addr/mask pair 12.34.56.0 and 255.255.255.0 -    */ -    const char *ptr; -    u_char *dsta, *dstm; -    int i, n; - -    assert( str != NULL ); -    addr->s_addr = 0; -    mask->s_addr = 0; -    ptr = str; -    dsta = (u_char*)&addr->s_addr; -    dstm = (u_char*)&mask->s_addr; -    for (i=0; i<4; i++ ) { -        if ( *ptr == '\0' ) -            break;              /* case of format #3 */ -        if ( !isdigit(*ptr) ) -            return -1;          /* format error: */ -        *dsta++ = atoi( ptr ); -        *dstm++ = 255;          /* automatic mask for format #3 */ -        while ( isdigit(*ptr) ) /* skip digits */ -            ptr++; -        if ( *ptr == '.' ) -            ptr++; -        else -            break; -    } -    /* At this point, *ptr points '/' or EOS ('\0') */ -    if ( *ptr == '\0' ) -        return 0;                       /* complete as format #3 */ -    if ( *ptr != '/' ) -        return -1;                      /* format error */ -    /* Now parse mask for format #1 or #2 */ -    ptr++; -    mask->s_addr = 0;                   /* clear automatic mask */ - -    if ( strchr( ptr, '.') ) { -        /* case of format #1 */ -        dstm = (u_char*)&mask->s_addr; -        for (i=0; i<4; i++) { -            if ( !isdigit(*ptr) ) -                return -1;              /* format error: */ -            *dstm++ = atoi(ptr); -            while ( isdigit(*ptr) )     /* skip digits */ -                ptr++; -            if ( *ptr == '.' ) -                ptr++; -            else -                break;                  /* from for loop */ -        } -        /* complete as format #1 */ -    } else { -        /* case of format #2 */ -        if ( !isdigit(*ptr) ) -            return -1;                  /* format error: */ -        n = atoi(ptr); -        if ( n<0 || 32<n) -            return -1;                  /* format error */ -        mask->s_addr = (n==0)? 0: htonl(((u_long)0xFFFFFFFF)<<(32-n)); -        /* complete as format #1 */ -    } -    return 0; -} - -void -initialize_direct_addr (void) -{ -    int negative; -    int n_entries; -    char *env = NULL, *beg, *next, *envkey = NULL; -    struct in_addr addr, mask; - -    if ( relay_method == METHOD_SOCKS ){ -        if ( socks_version == 5 ) -            envkey = ENV_SOCKS5_DIRECT; -        else -            envkey = ENV_SOCKS4_DIRECT; -        env = getparam(envkey); -        if ( env == NULL ) -            env = getparam(ENV_SOCKS_DIRECT); -    } else if ( relay_method == METHOD_HTTP ){ -        env = getparam(ENV_HTTP_DIRECT); -    } - -    if ( env == NULL ) -        env = getparam(ENV_CONNECT_DIRECT); - -    if ( env == NULL ) -        return;                 /* no entry */ -    debug("making direct addr list from: '%s'\n", env); -    env = strdup( env );        /* reallocate to modify */ -    beg = next = env; -    n_entries = 0; -    do { -        if ( MAX_DIRECT_ADDR_LIST <= n_entries ) { -            error("too many entries in %s", envkey); -            break;              /* from do loop */ -        } -        next = strchr( beg, ','); -        if ( next != NULL ) -            *next++ = '\0'; -        addr.s_addr = 0; -        mask.s_addr = 0; -        if (*beg == '!') { -            negative = 1; -            beg++; -        } else -            negative = 0; -        if ( !parse_addr_pair( beg, &addr, &mask ) ) { -            add_direct_addr( &addr, &mask, negative ); -        } else { -            add_direct_host( beg, negative ); -        } -        if ( next != NULL ) -            beg = next; -    } while ( next != NULL ); - -    free( env ); -    return; -} - -int -cmp_addr (void *addr1, void *addr2, int addrlen) -{ -    return memcmp( addr1, addr2, addrlen ); -} - -int -is_direct_address (const struct in_addr addr) -{ -    int i, neg; -    struct in_addr iaddr; - -    /* Note: assume IPV4 address !! */ -    for (i=0; i<n_direct_addr_list; i++ ) { -        if (direct_addr_list[i].name != NULL) -            continue;                           /* it's name entry */ -        neg = direct_addr_list[i].negative; -        iaddr = addr; -        mask_addr( &iaddr, &direct_addr_list[i].mask, -                   sizeof(struct in_addr)); -        if (cmp_addr(&iaddr, &direct_addr_list[i].addr, -                     sizeof(struct in_addr)) == 0) { -            char *a, *m; -            a = strdup(inet_ntoa(direct_addr_list[i].addr)); -            m = strdup(inet_ntoa(direct_addr_list[i].mask)); -            debug("match with: %s/%s%s\n", a, m, neg? " (negative)": ""); -            free(a); -            free(m); -            return !neg? 1: 0; -        } -    } -    debug("not matched, addr to be relayed: %s\n", inet_ntoa(addr)); -    return 0;                   /* not direct */ -} - - -/* check s1 is ends with s2. -   return 1 if exact match or domain part match. -   return 0 if s1 is shorter than s2 or partial match. -   For example,  -    ends_with("bar.com", "bar.com")        => 1 (exact match) -    ends_with("foo.bar.com", "bar.com")    => 1 (domain match) -    ends_with("foo.beebar.com", "bar.com") => 0 (partial match) -    ends_with("bar", "bar.com")            => 0 (shorter) - */ -domain_match(const char *s1, const char *s2) -{ -    int len1, len2; -    const char *tail1, *tail2; -    len1 = strlen(s1); -    len2 = strlen(s2); -    if (len1 < len2 || len1 == 0 || len2 == 0) -        return 0;                               /* not match */ -    tail1 = s1 + len1; -    tail2 = s2 + len2; -    while (0 < len1 && 0 < len2) { -        if (*--tail1 != *--tail2) -            break;                              /* not match */ -        len1--, len2--; -    } -    if (len2 != 0) -        return 0;                               /* not match */ -    /* Now exact match, domain match or partial match. -       Return true if exact or domain match. -       Or continue checking. */ -    if (tail1 == s1 || tail1[-1] == '.') -        return 1;                               /* match! */ -    return 0;                                   /* not match */ -} - -/* Check given NAME is ends with one of  -   registered direct name entry. -   Return 1 if matched, or 0. -*/ -int -is_direct_name (const char *name) -{ -    int len, i; -    const char *tail; -    debug("checking %s is for direct?\n", name); -    name = downcase(strdup(name)); -    len = strlen(name); -    if (len < 1) -        return 0;                               /* false */ -    tail = &name[len]; -    for (i=0; i<n_direct_addr_list; i++ ) { -        int dlen, neg; -        const char *dname; -        const char *n, *d; -        dname = direct_addr_list[i].name; -        if (dname == NULL) -            continue;                           /* it's addr/mask entry */ -        neg = direct_addr_list[i].negative; -        if (domain_match(name, dname)) { -            debug("match with: %s%s\n", dname, neg? " (negative)": ""); -            if (neg) { -                return 0;       /* not direct */ -            } else { -                return 1;       /* direct*/ -            } -        } -    } -    return 0;                                   /* not matched */ -} - -/* check to connect to HOST directyly? -   return 1 if to be direct, 0 for else. */ -int -check_direct(const char *host) -{ -    struct in_addr addr; -    addr.s_addr = inet_addr(host); -    if (addr.s_addr != INADDR_NONE) { -        /* case of IP address */ -        if (is_direct_address(addr)) { -            debug("%s is for direct.\n", host); -            return 1;                           /* true */ -        } -    } else { -        /* case of hostname */ -        if (is_direct_name(host)) { -            debug("%s is for direct.\n", host); -            return 1;                           /* true */ -        } -    } -    debug("%s is for not direct.\n", host); -    return 0;                                    /* false */ -} - - -/** TTY operation **/ - -int intr_flag = 0; - -#ifndef _WIN32 -void -intr_handler(int sig) -{ -    intr_flag = 1; -} - -void -tty_change_echo(int fd, int enable) -{ -    static struct termios ntio, otio;           /* new/old termios */ -    static sigset_t nset, oset;                 /* new/old sigset */ -    static struct sigaction nsa, osa;           /* new/old sigaction */ -    static int disabled = 0; - -    if ( disabled && enable ) { -        /* enable echo */ -        tcsetattr(fd, TCSANOW, &otio); -        disabled = 0; -        /* resotore sigaction */ -        sigprocmask(SIG_SETMASK, &oset, NULL); -        sigaction(SIGINT, &osa, NULL); -        if ( intr_flag != 0 ) { -            /* re-generate signal  */ -            kill(getpid(), SIGINT); -            sigemptyset(&nset); -            sigsuspend(&nset); -            intr_flag = 0; -        } -    } else if (!disabled && !enable) { -        /* set SIGINTR handler and break syscall on singal */ -        sigemptyset(&nset); -        sigaddset(&nset, SIGTSTP); -        sigprocmask(SIG_BLOCK, &nset, &oset); -        intr_flag = 0; -        memset(&nsa, 0, sizeof(nsa)); -        nsa.sa_handler = intr_handler; -        sigaction(SIGINT, &nsa, &osa); -        /* disable echo */ -        if (tcgetattr(fd, &otio) == 0 && (otio.c_lflag & ECHO)) { -            disabled = 1; -            ntio = otio; -            ntio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); -            (void) tcsetattr(fd, TCSANOW, &ntio); -        } -    } - -    return; -} - -#define TTY_NAME "/dev/tty" -int -tty_readpass( const char *prompt, char *buf, size_t size ) -{ -    int tty, ret = 0; - -    tty = open(TTY_NAME, O_RDWR); -    if ( tty < 0 ) { -        error("Unable to open %s\n", TTY_NAME); -        return -1;                              /* can't open tty */ -    } -    if ( size <= 0 ) -        return -1;                              /* no room */ -    write(tty, prompt, strlen(prompt)); -    buf[0] = '\0'; -    tty_change_echo(tty, 0);                    /* disable echo */ -    ret = read(tty,buf, size-1); -    tty_change_echo(tty, 1);                    /* restore */ -    write(tty, "\n", 1);                        /* new line */ -    close(tty); -    if ( strchr(buf,'\n') == NULL  ) -        return -1; -    if ( 0 < ret ) -        buf[ret] = '\0'; -    return ret; -} - -#else  /* _WIN32 */ - -BOOL __stdcall -w32_intr_handler(DWORD dwCtrlType) -{ -    if ( dwCtrlType == CTRL_C_EVENT ) { -        intr_flag = 1; -        return TRUE; -    } else { -        return FALSE; -    } -} - -#define tty_readpass w32_tty_readpass -int -w32_tty_readpass( const char *prompt, char *buf, size_t size ) -{ -    HANDLE in = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE, -                           0, NULL, OPEN_EXISTING, 0, NULL); -    HANDLE out = CreateFile("CONOUT$", GENERIC_WRITE, -                            0, NULL, OPEN_EXISTING, 0, NULL); -    DWORD mode; -    DWORD ret, bytes; - -    if (in == INVALID_HANDLE_VALUE || out == INVALID_HANDLE_VALUE) -        fatal("Cannot open console. (errno=%d)", GetLastError()); - -    WriteFile(out, prompt, strlen(prompt), &bytes, 0); -    SetConsoleCtrlHandler(w32_intr_handler, TRUE ); /* add handler */ -    GetConsoleMode(in, &mode); -    SetConsoleMode(in, mode&~ENABLE_ECHO_INPUT); /* disable echo */ -    ret = ReadFile(in, buf, size, &bytes, 0); -    SetConsoleMode(in, mode);                   /* enable echo */ -    SetConsoleCtrlHandler( w32_intr_handler, FALSE ); /* remove handler */ -    if ( intr_flag ) -        GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); /* re-signal */ -    WriteFile(out,"\n", 1, &bytes, 0); -    CloseHandle(in); -    CloseHandle(out); -    return ret; -} - -#endif /* _WIN32 */ - -/*** User / Password ***/ - -/* SOCKS5 and HTTP Proxy authentication may requires username and -   password. We ll give it via environment variable or tty. -   Username and password for authentication are decided by -   following rules: - -   Username is taken from -     1) server location spec (i.e. user@host:port) -     2) environment variables (see tables.1) -     3) system account name currently logged in. - -     Table.1 Order of environment variables for username - -        |  SOCKS v5   |  SOCKS v4   |   HTTP proxy    | -      --+-------------+-------------+-----------------+ -      1 | SOCKS45_USER | SOCKS4_USER | HTTP_PROXY_USER | -      --+-------------+-------------+                 | -      2 |        SOCKS_USER         |                 | -      --+---------------------------+-----------------+ -      3 |              CONNECT_USER                   | -      --+---------------------------------------------+ - -   Password is taken from -     1) by environment variables (see table.2) -     2) by entering from tty. - -     Table.2 Order of environment variables for password - -        |    SOCKS v5     |     HTTP proxy      | -      --+-----------------+---------------------+ -      1 | SOCKS5_PASSWD   |                     | -      --+-----------------+ HTTP_PROXY_PASSWORD | -      2 | SOCKS5_PASSWORD |                     | -      --+-----------------+---------------------+ -      3 |           CONNECT_PASSWORD            | -      --+---------------------------------------+ - -      Note: SOCKS5_PASSWD which is added in rev. 1.79 -            to share value with NEC SOCKS implementation. - */ - -char * -determine_relay_user () -{ -    char *user = NULL; -    /* get username from environment variable, or system. */ -    if (relay_method == METHOD_SOCKS) { -        if (user == NULL && socks_version == 5) -            user = getparam (ENV_SOCKS5_USER); -        if (user == NULL && socks_version == 4) -            user = getparam (ENV_SOCKS4_USER); -        if (user == NULL) -            user = getparam (ENV_SOCKS_USER); -    } else if (relay_method == METHOD_HTTP) { -        if (user == NULL) -            user = getparam (ENV_HTTP_PROXY_USER); -    } -    if (user == NULL) -        user = getparam (ENV_CONNECT_USER); -    /* determine relay user by system call if not yet. */ -    if (user == NULL) -        user = getusername(); -    return user; -} - -char * -determine_relay_password () -{ -    char *pass = NULL; -    if (pass == NULL && relay_method == METHOD_HTTP) -        pass = getparam(ENV_HTTP_PROXY_PASSWORD); -    if (pass == NULL && relay_method == METHOD_SOCKS) -        pass = getparam(ENV_SOCKS5_PASSWD); -    if (pass == NULL && relay_method == METHOD_SOCKS) -        pass = getparam(ENV_SOCKS5_PASSWORD); -    if (pass == NULL) -        pass = getparam(ENV_CONNECT_PASSWORD); -    return pass; -} - - -/*** network operations ***/ - - -/* set_relay() -   Determine relay informations: -   method, host, port, and username. -   1st arg, METHOD should be METHOD_xxx. -   2nd arg, SPEC is hostname or hostname:port or user@hostame:port. -   hostname is domain name or dot notation. -   If port is omitted, use 80 for METHOD_HTTP method, -   use 1080 for METHOD_SOCKS method. -   Username is also able to given by 3rd. format. -   2nd argument SPEC can be NULL. if NULL, use environment variable. - */ -int -set_relay( int method, char *spec ) -{ -    char *buf, *sep, *resolve; - -    relay_method = method; - -    read_parameter_file(); -    initialize_direct_addr(); -    if (n_direct_addr_list == 0) { -        debug ("No direct address are specified.\n"); -    } else { -        debug ("%d direct address entries.\n", n_direct_addr_list); -    } - -    switch ( method ) { -    case METHOD_DIRECT: -        return -1;                              /* nothing to do */ - -    case METHOD_SOCKS: -        if ( spec == NULL ) { -            switch ( socks_version ) { -            case 5: -                spec = getparam(ENV_SOCKS5_SERVER); -                break; -            case 4: -                spec = getparam(ENV_SOCKS4_SERVER); -                break; -            } -        } -        if ( spec == NULL ) -            spec = getparam(ENV_SOCKS_SERVER); - -        if ( spec == NULL ) -            fatal("Failed to determine SOCKS server.\n"); -        relay_port = 1080;                      /* set default first */ - -        /* determine resolve method */ -        if ( socks_resolve == RESOLVE_UNKNOWN ) { -            if ( ((socks_version == 5) && -                  ((resolve = getparam(ENV_SOCKS5_RESOLVE)) != NULL)) || -                 ((socks_version == 4) && -                  ((resolve = getparam(ENV_SOCKS4_RESOLVE)) != NULL)) || -                 ((resolve = getparam(ENV_SOCKS_RESOLVE)) != NULL) ) { -                socks_resolve = lookup_resolve( resolve ); -                if ( socks_resolve == RESOLVE_UNKNOWN ) -                    fatal("Invalid resolve method: %s\n", resolve); -            } else { -                /* default */ -                if ( socks_version == 5 ) -                    socks_resolve = RESOLVE_REMOTE; -                else -                    socks_resolve = RESOLVE_LOCAL; -            } -        } -        break; - -    case METHOD_HTTP: -        if ( spec == NULL ) -            spec = getparam(ENV_HTTP_PROXY); -        if ( spec == NULL ) -            fatal("You must specify http proxy server\n"); -        relay_port = 80;                        /* set default first */ -        break; -    case METHOD_TELNET: -        if ( spec == NULL ) -            spec = getparam(ENV_TELNET_PROXY); -        if ( spec == NULL ) -            fatal("You must specify telnet proxy server\n"); -        relay_port = 23;                        /* set default first */ -    } - -    if (expect( spec, HTTP_PROXY_PREFIX)) { -        /* URL format like: "http://server:port/" */ -        /* extract server:port part */ -        buf = strdup( spec + strlen(HTTP_PROXY_PREFIX)); -        buf[strcspn(buf, "/")] = '\0'; -    } else { -        /* assume spec is aready "server:port" format */ -        buf = strdup( spec ); -    } -    spec = buf; - -    /* check username in spec */ -    sep = strchr( spec, '@' ); -    if ( sep != NULL ) { -        *sep = '\0'; -        relay_user = strdup( spec ); -        spec = sep +1; -    } -    if (relay_user == NULL) -        relay_user = determine_relay_user(); - -    /* split out hostname and port number from spec */ -    sep = strchr(spec,':'); -    if ( sep == NULL ) { -        /* hostname only, port is already set as default */ -        relay_host = strdup( spec ); -    } else { -        /* hostname and port */ -        relay_port = atoi(sep+1); -        *sep = '\0'; -        relay_host = strdup( spec ); -    } -    free(buf); -    return 0; -} - - -u_short -resolve_port( const char *service ) -{ -    int port; -    if ( service[strspn (service, digits)] == '\0'  ) { -        /* all digits, port number */ -        port = atoi(service); -    } else { -        /* treat as service name */ -        struct servent *ent; -        ent = getservbyname( service, NULL ); -        if ( ent == NULL ) { -            debug("Unknown service, '%s'\n", service); -            port = 0; -        } else { -            port = ntohs(ent->s_port); -            debug("service: %s => %d\n", service, port); -        } -    } -    return (u_short)port; -} - -void -make_revstr(void) -{ -    char *ptr; -    size_t len; -    ptr = strstr(rcs_revstr, ": "); -    if (!ptr) { -        revstr = strdup("unknown"); -        return; -    } -    ptr += 2; -    /* assume subversion's keyword expansion like "Revision: 96". */ -    minor_version = atoi(ptr); -    revstr = xmalloc(20); -    snprintf(revstr, 20, "%d.%d", major_version, minor_version); -} - -int -getarg( int argc, char **argv ) -{ -    int err = 0; -    char *ptr, *server = (char*)NULL; -    int method = METHOD_DIRECT; - -    progname = *argv; -    argc--, argv++; - -    /* check optinos */ -    while ( (0 < argc) && (**argv == '-') ) { -        ptr = *argv + 1; -        while ( *ptr ) { -            switch ( *ptr ) { -            case 's':                           /* use SOCKS */ -                method = METHOD_SOCKS; -                break; - -            case 'n':                           /* no proxy */ -                method = METHOD_DIRECT; -                break; - -            case 'h':                           /* use http-proxy */ -                method = METHOD_HTTP; -                break; -            case 't': -                method = METHOD_TELNET; -                break; - -            case 'S':                           /* specify SOCKS server */ -                if ( 1 < argc ) { -                    argv++, argc--; -                    method = METHOD_SOCKS; -                    server = *argv; -                } else { -                    error("option '-%c' needs argument.\n", *ptr); -                    err++; -                } -                break; - -            case 'H':                           /* specify http-proxy server */ -                if ( 1 < argc ) { -                    argv++, argc--; -                    method = METHOD_HTTP; -                    server = *argv; -                } else { -                    error("option '-%c' needs argument.\n", *ptr); -                    err++; -                } -                break; -            case 'T':                           /* specify telnet proxy server */ -                if ( 1 < argc ) { -                    argv++, argc--; -                    method = METHOD_TELNET; -                    server = *argv; -                } else { -                    error("option '-%c' needs argument.\n", *ptr); -                    err++; -                } -                break; - -            case 'c': -                 if (1 < argc) { -                      argv++, argc--; -                      telnet_command = *argv; -                 } else { -                      error("option '%c' needs argument.\n", *ptr); -                      err++; -                 } -                 break; - -            case 'P': -                f_hold_session = 1; -                /* without break */ -            case 'p':                          /* specify port to forward */ -                if ( 1 < argc ) { -                    argv++, argc--; -                    local_type = LOCAL_SOCKET; -                    local_port = resolve_port(*argv); -                } else { -                    error("option '-%c' needs argument.\n", *ptr); -                    err++; -                } -                break; - -#ifndef _WIN32 -            case 'w': -                if ( 1 < argc ) { -                    argv++, argc--; -                    connect_timeout = atoi(*argv); -                } else { -                    error("option '-%c' needs argument.\n", *ptr); -                    err++; -                } -                break; -#endif /* not _WIN32 */ - -            case '4': -                socks_version = 4; -                break; - -            case '5': -                socks_version = 5; -                break; - -            case 'a': -                if ( 1 < argc ) { -                    argv++, argc--; -                    socks5_auth = *argv; -                } else { -                    error("option '-%c' needs argument.\n", *ptr); -                    err++; -                } -                break; - -            case 'R':                           /* specify resolve method */ -                if ( 1 < argc ) { -                    argv++, argc--; -                    socks_resolve = lookup_resolve( *argv ); -                } else { -                    error("option '-%c' needs argument.\n", *ptr); -                    err++; -                } -                break; - -            case 'V':                           /* print version */ -                fprintf(stderr, "%s\nVersion %s\n", progdesc, revstr); -                exit(0); - -            case 'd':                           /* debug mode */ -                f_debug++; -                break; - -            default: -                error("unknown option '-%c'\n", *ptr); -                err++; -            } -            ptr++; -        } -        argc--, argv++; -    } - -    /* check error */ -    if ( 0 < err ) -        goto quit; - -    set_relay( method, server ); - -    /* check destination HOST (MUST) */ -    if ( argc == 0  ) { -        fprintf(stderr, "%s\nVersion %s\n", progdesc, revstr); -        fprintf(stderr, usage, progname); -        exit(0); -    } -    dest_host = argv[0]; -    /* decide port or service name from programname or argument */ -    if ( ((ptr=strrchr( progname, '/' )) != NULL) || -         ((ptr=strchr( progname, '\\')) != NULL) ) -        ptr++; -    else -        ptr = progname; -    if ( dest_port == 0 ) { -        /* accept only if -P is not specified. */ -        if ( 1 < argc ) { -            /* get port number from argument (prior to progname) */ -            /* NOTE: This way is for cvs ext method. */ -            dest_port = resolve_port(argv[1]); -        } else if ( strncmp( ptr, "connect-", 8) == 0 ) { -            /* decide port number from program name */ -            char *str = strdup( ptr+8 ); -            str[strcspn( str, "." )] = '\0'; -            dest_port = resolve_port(str); -            free(str); -        } -    } -    /* check port number */ -    if ( dest_port <= 0 ) { -        error( "You must specify the destination port correctly.\n"); -        err++; -        goto quit; -    } -    if ( (relay_method != METHOD_DIRECT) && (relay_port <= 0) ) { -        error("Invalid relay port: %d\n", dest_port); -        err++; -        goto quit; -    } - -quit: -    /* report for debugging */ -    debug("relay_method = %s (%d)\n", -          method_names[relay_method], relay_method); -    if ( relay_method != METHOD_DIRECT ) { -        debug("relay_host=%s\n", relay_host); -        debug("relay_port=%d\n", relay_port); -        debug("relay_user=%s\n", relay_user); -    } -    if ( relay_method == METHOD_SOCKS ) { -        debug("socks_version=%d\n", socks_version); -        debug("socks_resolve=%s (%d)\n", -              resolve_names[socks_resolve], socks_resolve); -    } -    debug("local_type=%s\n", local_type_names[local_type]); -    if ( local_type == LOCAL_SOCKET ) { -        debug("local_port=%d\n", local_port); -        if (f_hold_session) -            debug ("  with holding remote session.\n"); -    } -    debug("dest_host=%s\n", dest_host); -    debug("dest_port=%d\n", dest_port); -    if ( 0 < err ) { -        fprintf(stderr, usage, progname); -        exit(1); -    } -    return 0; -} - -#ifndef _WIN32 -/* Time-out feature is not allowed for Win32 native compilers. */ -/* MSVC and Borland C cannot but Cygwin and UNIXes can. */ - -/* timeout signal hander */ -void -sig_timeout(void) -{ -    signal( SIGALRM, SIG_IGN ); -    alarm( 0 ); -    error( "timed out\n" ); -    exit(1); -} - -/* set timeout param = seconds, 0 clears */ -void -set_timeout(int timeout) -{ -    /* This feature is allowed for UNIX or cygwin environments, currently */ -    if ( timeout == 0 ) { -        debug( "clearing timeout\n" ); -        signal( SIGALRM, SIG_IGN ); -        alarm( 0 ); -    } else { -        debug( "setting timeout: %d seconds\n", timeout ); -        signal(SIGALRM, (void *)sig_timeout); -        alarm( timeout ); -    } -} -#endif - -#if !defined(_WIN32) && !defined(__CYGWIN32__) -void -switch_ns (struct sockaddr_in *ns) -{ -    res_init(); -    memcpy (&_res.nsaddr_list[0], ns, sizeof(*ns)); -    _res.nscount = 1; -    debug("Using nameserver at %s\n", inet_ntoa(ns->sin_addr)); -} -#endif /* !_WIN32 && !__CYGWIN32__ */ - -/* TODO: IPv6 -   TODO: fallback if askpass execution failed. - */ - -int -local_resolve (const char *host, struct sockaddr_in *addr) -{ -    struct hostent *ent; -    if ( strspn(host, dotdigits) == strlen(host) ) { -        /* given by IPv4 address */ -        addr->sin_family = AF_INET; -        addr->sin_addr.s_addr = inet_addr(host); -    } else { -        debug("resolving host by name: %s\n", host); -        ent = gethostbyname (host); -        if ( ent ) { -            memcpy (&addr->sin_addr, ent->h_addr, ent->h_length); -            addr->sin_family = ent->h_addrtype; -            debug("resolved: %s (%s)\n", -                  host, inet_ntoa(addr->sin_addr)); -        } else { -            debug("failed to resolve locally.\n"); -            return -1;                          /* failed */ -        } -    } -    return 0;                                   /* good */ -} - -int -open_connection( const char *host, u_short port ) -{ -    SOCKET s; -    struct sockaddr_in saddr; - -    /* resolve address of proxy or direct target */ -    if (local_resolve (host, &saddr) < 0) { -        error("can't resolve hostname: %s\n", host); -        return SOCKET_ERROR; -    } -    saddr.sin_port = htons(port); - -    debug("connecting to %s:%u\n", inet_ntoa(saddr.sin_addr), port); -    s = socket( AF_INET, SOCK_STREAM, 0 ); -    if ( connect( s, (struct sockaddr *)&saddr, sizeof(saddr)) -         == SOCKET_ERROR) { -        debug( "connect() failed.\n"); -        return SOCKET_ERROR; -    } -    return s; -} - -void -report_text( char *prefix, char *buf ) -{ -    static char work[1024]; -    char *tmp; - -    if ( !f_debug ) -        return; -    if ( !f_report ) -        return;                                 /* don't report */ -    debug("%s \"", prefix); -    while ( *buf ) { -        memset( work, 0, sizeof(work)); -        tmp = work; -        while ( *buf && ((tmp-work) < (int)sizeof(work)-5) ) { -            switch ( *buf ) { -            case '\t': *tmp++ = '\\'; *tmp++ = 't'; break; -            case '\r': *tmp++ = '\\'; *tmp++ = 'r'; break; -            case '\n': *tmp++ = '\\'; *tmp++ = 'n'; break; -            case '\\': *tmp++ = '\\'; *tmp++ = '\\'; break; -            default: -                if ( isprint(*buf) ) { -                    *tmp++ = *buf; -                } else { -		    int consumed = tmp - work; -                    snprintf( tmp, sizeof(work)-consumed, -			      "\\x%02X", (unsigned char)*buf); -                    tmp += strlen(tmp); -                } -            } -            buf++; -            *tmp = '\0'; -        } -        debug_("%s", work); -    } - -    debug_("\"\n"); -} - - -void -report_bytes( char *prefix, char *buf, int len ) -{ -    if ( ! f_debug ) -        return; -    debug( "%s", prefix ); -    while ( 0 < len ) { -        fprintf( stderr, " %02x", *(unsigned char *)buf); -        buf++; -        len--; -    } -    fprintf(stderr, "\n"); -    return; -} - -int -atomic_out( SOCKET s, char *buf, int size ) -{ -    int ret, len; - -    assert( buf != NULL ); -    assert( 0<=size ); -    /* do atomic out */ -    ret = 0; -    while ( 0 < size ) { -        len = send( s, buf+ret, size, 0 ); -        if ( len == -1 ) -            fatal("atomic_out() failed to send(), %d\n", socket_errno()); -        ret += len; -        size -= len; -    } -    if (!f_report) { -        debug("atomic_out()  [some bytes]\n"); -        debug(">>> xx xx xx xx ...\n"); -    } else { -        debug("atomic_out()  [%d bytes]\n", ret); -        report_bytes(">>>", buf, ret); -    } -    return ret; -} - -int -atomic_in( SOCKET s, char *buf, int size ) -{ -    int ret, len; - -    assert( buf != NULL ); -    assert( 0<=size ); - -    /* do atomic in */ -    ret = 0; -    while ( 0 < size ) { -        len = recv( s, buf+ret, size, 0 ); -        if ( len == -1 ) { -            fatal("atomic_in() failed to recv(), %d\n", socket_errno()); -        } else if ( len == 0 ) { -            fatal( "Connection closed by peer.\n"); -        } -        ret += len; -        size -= len; -    } -    if (!f_report) { -        debug("atomic_in()  [some bytes]\n"); -        debug("<<< xx xx xx xx ...\n"); -    } else { -        debug("atomic_in() [%d bytes]\n", ret); -        report_bytes("<<<", buf, ret); -    } -    return ret; -} - -int -line_input( SOCKET s, char *buf, int size ) -{ -    char *dst = buf; -    if ( size == 0 ) -        return 0;                               /* no error */ -    size--; -    while ( 0 < size ) { -        switch ( recv( s, dst, 1, 0) ) {        /* recv one-by-one */ -        case SOCKET_ERROR: -            error("recv() error\n"); -            return -1;                          /* error */ -        case 0: -            size = 0;                           /* end of stream */ -            break; -        default: -            /* continue reading until last 1 char is EOL? */ -            if ( *dst == '\n' ) { -                /* finished */ -                size = 0; -            } else { -                /* more... */ -                size--; -            } -            dst++; -        } -    } -    *dst = '\0'; -    report_text( "<<<", buf); -    return 0; -} - -/* cut_token() -   Span token in given string STR until char in DELIM is appeared. -   Then replace contiguous DELIMS with '\0' for string termination -   and returns next pointer. -   If no next token, return NULL. -*/ -char * -cut_token( char *str, char *delim) -{ -    char *ptr = str + strcspn(str, delim); -    char *end = ptr + strspn(ptr, delim); -    if ( ptr == str ) -        return NULL; -    while ( ptr < end ) -        *ptr++ = '\0'; -    return ptr; -} - -const char * -lookup(int num, LOOKUP_ITEM *items) -{ -    int i = 0; -    while (0 <= items[i].num) { -        if (items[i].num == num) -            return items[i].str; -        i++; -    } -    return "(unknown)"; -} - -/* readpass() -   password input routine -   Use ssh-askpass (same mechanism to OpenSSH) -*/ -char * -readpass( const char* prompt, ...) -{ -    static char buf[1000];                      /* XXX, don't be fix length */ -    va_list args; -    va_start(args, prompt); -    vsnprintf(buf, sizeof(buf), prompt, args); -    va_end(args); - -    if ( getparam(ENV_SSH_ASKPASS) -#if !defined(_WIN32) && !defined(__CYGWIN32__) -         && getenv("DISPLAY") -#endif /* not _WIN32 && not __CYGWIN32__ */ -        ) { -        /* use ssh-askpass to get password */ -        FILE *fp; -        char *askpass = getparam(ENV_SSH_ASKPASS), *cmd; -	int cmd_size = strlen(askpass) +1 +1 +strlen(buf) +1 +1; -        cmd = xmalloc(cmd_size); -        snprintf(cmd, cmd_size, "%s \"%s\"", askpass, buf); -        fp = popen(cmd, "r"); -        free(cmd); -        if ( fp == NULL ) -            return NULL;                        /* fail */ -        buf[0] = '\0'; -        if (fgets(buf, sizeof(buf), fp) == NULL) -            return NULL;                        /* fail */ -        fclose(fp); -    } else { -        tty_readpass( buf, buf, sizeof(buf)); -    } -    buf[strcspn(buf, "\r\n")] = '\0'; -    return buf; -} - -static int -socks5_do_auth_userpass( int s ) -{ -    unsigned char buf[1024], *ptr; -    char *pass = NULL; -    int len; - -    /* do User/Password authentication. */ -    /* This feature requires username and password from -       command line argument or environment variable, -       or terminal. */ -    if (relay_user == NULL) -        fatal("cannot determine user name.\n"); - -    /* get password from environment variable if exists. */ -    if ((pass=determine_relay_password()) == NULL && -        (pass=readpass("Enter SOCKS5 password for %s@%s: ", -                       relay_user, relay_host)) == NULL) -        fatal("Cannot get password for user: %s\n", relay_user); - -    /* make authentication packet */ -    ptr = buf; -    PUT_BYTE( ptr++, 1 );                       /* subnegotiation ver.: 1 */ -    len = strlen( relay_user );                 /* ULEN and UNAME */ -    PUT_BYTE( ptr++, len ); -    strcpy( ptr, relay_user ); -    ptr += len; -    len = strlen( pass );                       /* PLEN and PASSWD */ -    PUT_BYTE( ptr++, strlen(pass)); -    strcpy( ptr, pass ); -    ptr += len; -    memset (pass, 0, strlen(pass));             /* erase password */ - -    /* send it and get answer */ -    f_report = 0; -    atomic_out( s, buf, ptr-buf ); -    f_report = 1; -    atomic_in( s, buf, 2 ); - -    /* check status */ -    if ( buf[1] == 0 ) -        return 0;                               /* success */ -    else -        return -1;                              /* fail */ -} - -static const char * -socks5_getauthname( int auth ) -{ -    switch ( auth ) { -    case SOCKS5_AUTH_REJECT: return "REJECTED"; -    case SOCKS5_AUTH_NOAUTH: return "NO-AUTH"; -    case SOCKS5_AUTH_GSSAPI: return "GSSAPI"; -    case SOCKS5_AUTH_USERPASS: return "USERPASS"; -    case SOCKS5_AUTH_CHAP: return "CHAP"; -    case SOCKS5_AUTH_EAP: return "EAP"; -    case SOCKS5_AUTH_MAF: return "MAF"; -    default: return "(unknown)"; -    } -} - -typedef struct { -    char* name; -    unsigned char auth; -} AUTH_METHOD_ITEM; - -AUTH_METHOD_ITEM socks5_auth_table[] = { -    { "none", SOCKS5_AUTH_NOAUTH }, -    { "gssapi", SOCKS5_AUTH_GSSAPI }, -    { "userpass", SOCKS5_AUTH_USERPASS }, -    { "chap", SOCKS5_AUTH_CHAP }, -    { NULL, -1 }, -}; - -int -socks5_auth_parse_1(char *start, char *end){ -    int i, len; -    for ( ; *start; start++ ) -        if ( *start != ' ' && *start != '\t') break; -    for ( end--; end >= start; end-- ) { -        if ( *end != ' ' && *end != '\t'){ -            end++; -            break; -        } -    } -    len = end - start; -    for ( i = 0; socks5_auth_table[i].name != NULL; i++ ){ -        if ( strncmp(start, socks5_auth_table[i].name, len) == 0) { -            return socks5_auth_table[i].auth; -        } -    } -    fatal("Unknown auth method: %s\n", start); -    return -1; -} - -int -socks5_auth_parse(char *start, unsigned char *auth_list, int max_auth){ -    char *end; -    int i = 0; -    while ( i < max_auth ) { -        end = strchr(start, ','); -        if (*start && end) { -            auth_list[i++] = socks5_auth_parse_1(start, end); -            start = ++end; -        } else { -            break; -        } -    } -    if ( *start && ( i < max_auth ) ){ -        for( end = start; *end; end++ ); -        auth_list[i++] = socks5_auth_parse_1(start, end); -    } else { -        fatal("Too much auth method.\n"); -    } -    return i; -} - -/* begin SOCKS5 relaying -   And no authentication is supported. - */ -int -begin_socks5_relay( SOCKET s ) -{ -    unsigned char buf[256], *ptr, *env = socks5_auth; -    unsigned char n_auth = 0; unsigned char auth_list[10], auth_method; -    int len, auth_result, i; - -    debug( "begin_socks_relay()\n"); - -    /* request authentication */ -    ptr = buf; -    PUT_BYTE( ptr++, 5);                        /* SOCKS version (5) */ - -    if ( env == NULL ) -        env = getparam(ENV_SOCKS5_AUTH); -    if ( env == NULL ) { -        /* add no-auth authentication */ -        auth_list[n_auth++] = SOCKS5_AUTH_NOAUTH; -        /* add user/pass authentication */ -        auth_list[n_auth++] = SOCKS5_AUTH_USERPASS; -    } else { -        n_auth = socks5_auth_parse(env, auth_list, 10); -    } -    PUT_BYTE( ptr++, n_auth);                   /* num auth */ -    for (i=0; i<n_auth; i++) { -        debug("available auth method[%d] = %s (0x%02x)\n", -              i, socks5_getauthname(auth_list[i]), auth_list[i]); -        PUT_BYTE( ptr++, auth_list[i]);         /* authentications */ -    } -    atomic_out( s, buf, ptr-buf );              /* send requst */ -    atomic_in( s, buf, 2 );                     /* recv response */ -    if ( (buf[0] != 5) ||                       /* ver5 response */ -         (buf[1] == 0xFF) ) {                   /* check auth method */ -        error("No auth method accepted.\n"); -        return -1; -    } -    auth_method = buf[1]; - -    debug("auth method: %s\n", socks5_getauthname(auth_method)); - -    switch ( auth_method ) { -    case SOCKS5_AUTH_REJECT: -        error("No acceptable authentication method\n"); -        return -1;                              /* fail */ - -    case SOCKS5_AUTH_NOAUTH: -        /* nothing to do */ -        auth_result = 0; -        break; - -    case SOCKS5_AUTH_USERPASS: -        auth_result = socks5_do_auth_userpass(s); -        break; - -    default: -        error("Unsupported authentication method: %s\n", -              socks5_getauthname( auth_method )); -        return -1;                              /* fail */ -    } -    if ( auth_result != 0 ) { -        error("Authentication failed.\n"); -        return -1; -    } -    /* request to connect */ -    ptr = buf; -    PUT_BYTE( ptr++, 5);                        /* SOCKS version (5) */ -    PUT_BYTE( ptr++, 1);                        /* CMD: CONNECT */ -    PUT_BYTE( ptr++, 0);                        /* FLG: 0 */ -    if ( dest_addr.sin_addr.s_addr == 0 ) { -        /* resolved by SOCKS server */ -        PUT_BYTE( ptr++, 3);                    /* ATYP: DOMAINNAME */ -        len = strlen(dest_host); -        PUT_BYTE( ptr++, len);                  /* DST.ADDR (len) */ -        memcpy( ptr, dest_host, len );          /* (hostname) */ -        ptr += len; -    } else { -        /* resolved localy */ -        PUT_BYTE( ptr++, 1 );                   /* ATYP: IPv4 */ -        memcpy( ptr, &dest_addr.sin_addr.s_addr, sizeof(dest_addr.sin_addr)); -        ptr += sizeof(dest_addr.sin_addr); -    } -    PUT_BYTE( ptr++, dest_port>>8);     /* DST.PORT */ -    PUT_BYTE( ptr++, dest_port&0xFF); -    atomic_out( s, buf, ptr-buf);               /* send request */ -    atomic_in( s, buf, 4 );                     /* recv response */ -    if ( (buf[1] != SOCKS5_REP_SUCCEEDED) ) {   /* check reply code */ -        error("Got error response from SOCKS server: %d (%s).\n", -              buf[1], lookup(buf[1], socks5_rep_names)); -        return -1; -    } -    ptr = buf + 4; -    switch ( buf[3] ) {                         /* case by ATYP */ -    case 1:                                     /* IP v4 ADDR*/ -        atomic_in( s, ptr, 4+2 );               /* recv IPv4 addr and port */ -        break; -    case 3:                                     /* DOMAINNAME */ -        atomic_in( s, ptr, 1 );                 /* recv name and port */ -        atomic_in( s, ptr+1, *(unsigned char*)ptr + 2); -        break; -    case 4:                                     /* IP v6 ADDR */ -        atomic_in( s, ptr, 16+2 );              /* recv IPv6 addr and port */ -        break; -    } - -    /* Conguraturation, connected via SOCKS5 server! */ -    return 0; -} - -/* begin SOCKS protocol 4 relaying -   And no authentication is supported. - -   There's SOCKS protocol version 4 and 4a. Protocol version -   4a has capability to resolve hostname by SOCKS server, so -   we don't need resolving IP address of destination host on -   local machine. - -   Environment variable SOCKS_RESOLVE directs how to resolve -   IP addess. There's 3 keywords allowed; "local", "remote" -   and "both" (case insensitive). Keyword "local" means taht -   target host name is resolved by localhost resolver -   (usualy with gethostbyname()), "remote" means by remote -   SOCKS server, "both" means to try resolving by localhost -   then remote. - -   SOCKS4 protocol and authentication of SOCKS5 protocol -   requires user name on connect request. -   User name is determined by following method. - -   1. If server spec has user@hostname:port format then -      user part is used for this SOCKS server. - -   2. Get user name from environment variable LOGNAME, USER -      (in this order). - -*/ -int -begin_socks4_relay( SOCKET s ) -{ -    unsigned char buf[256], *ptr; - -    debug( "begin_socks_relay()\n"); - -    /* make connect request packet -       protocol v4: -         VN:1, CD:1, PORT:2, ADDR:4, USER:n, NULL:1 -       protocol v4a: -         VN:1, CD:1, PORT:2, DUMMY:4, USER:n, NULL:1, HOSTNAME:n, NULL:1 -    */ -    ptr = buf; -    PUT_BYTE( ptr++, 4);                        /* protocol version (4) */ -    PUT_BYTE( ptr++, 1);                        /* CONNECT command */ -    PUT_BYTE( ptr++, dest_port>>8);     /* destination Port */ -    PUT_BYTE( ptr++, dest_port&0xFF); -    /* destination IP */ -    memcpy(ptr, &dest_addr.sin_addr, sizeof(dest_addr.sin_addr)); -    ptr += sizeof(dest_addr.sin_addr); -    if ( dest_addr.sin_addr.s_addr == 0 ) -        *(ptr-1) = 1;                           /* fake, protocol 4a */ -    /* username */ -    if (relay_user == NULL) -        fatal( "Cannot determine user name.\n"); -    strcpy( ptr, relay_user ); -    ptr += strlen( relay_user ) +1; -    /* destination host name (for protocol 4a) */ -    if ( (socks_version == 4) && (dest_addr.sin_addr.s_addr == 0)) { -        strcpy( ptr, dest_host ); -        ptr += strlen( dest_host ) +1; -    } -    /* send command and get response -       response is: VN:1, CD:1, PORT:2, ADDR:4 */ -    atomic_out( s, buf, ptr-buf);               /* send request */ -    atomic_in( s, buf, 8 );                     /* recv response */ -    if ( (buf[1] != SOCKS4_REP_SUCCEEDED) ) {   /* check reply code */ -        error("Got error response: %d: '%s'.\n", -              buf[1], lookup(buf[1], socks4_rep_names)); -        return -1;                              /* failed */ -    } - -    /* Conguraturation, connected via SOCKS4 server! */ -    return 0; -} - -int -sendf(SOCKET s, const char *fmt,...) -{ -    static char buf[10240];                     /* xxx, enough? */ - -    va_list args; -    va_start( args, fmt ); -    vsnprintf( buf, sizeof(buf), fmt, args ); -    va_end( args ); - -    report_text(">>>", buf); -    if ( send(s, buf, strlen(buf), 0) == SOCKET_ERROR ) { -        debug("failed to send http request. errno=%d\n", socket_errno()); -        return -1; -    } -    return 0; -} - -const char *base64_table = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -char * -make_base64_string(const char *str) -{ -    static char *buf; -    unsigned char *src; -    char *dst; -    int bits, data, src_len, dst_len; -    /* make base64 string */ -    src_len = strlen(str); -    dst_len = (src_len+2)/3*4; -    buf = xmalloc(dst_len+1); -    bits = data = 0; -    src = (unsigned char *)str; -    dst = (unsigned char *)buf; -    while ( dst_len-- ) { -        if ( bits < 6 ) { -            data = (data << 8) | *src; -            bits += 8; -            if ( *src != 0 ) -                src++; -        } -        *dst++ = base64_table[0x3F & (data >> (bits-6))]; -        bits -= 6; -    } -    *dst = '\0'; -    /* fix-up tail padding */ -    switch ( src_len%3 ) { -    case 1: -        *--dst = '='; -    case 2: -        *--dst = '='; -    } -    return buf; -} - - -int -basic_auth (SOCKET s) -{ -    char *userpass; -    char *cred; -    const char *user = relay_user; -    char *pass = NULL; -    int len, ret; - -    /* Get username/password for authentication */ -    if (user == NULL) -        fatal("Cannot decide username for proxy authentication."); -    if ((pass = determine_relay_password ()) == NULL && -        (pass = readpass("Enter proxy authentication password for %s@%s: ", -                         relay_user, relay_host)) == NULL) -        fatal("Cannot decide password for proxy authentication."); - -    len = strlen(user)+strlen(pass)+1; -    userpass = xmalloc(len+1); -    snprintf(userpass, len+1, "%s:%s", user, pass); -    memset (pass, 0, strlen(pass)); -    cred = make_base64_string(userpass); -    memset (userpass, 0, len); - -    f_report = 0;                               /* don't report for security */ -    ret = sendf(s, "Proxy-Authorization: Basic %s\r\n", cred); -    f_report = 1; -    report_text(">>>", "Proxy-Authorization: Basic xxxxx\r\n"); - -    memset(cred, 0, strlen(cred)); -    free(cred); - -    return ret; -} - -/* begin relaying via HTTP proxy -   Directs CONNECT method to proxy server to connect to -   destination host (and port). It may not be allowed on your -   proxy server. - */ -int -begin_http_relay( SOCKET s ) -{ -    char buf[1024]; -    int result; -    char *auth_what; - -    debug("begin_http_relay()\n"); - -    if (sendf(s,"CONNECT %s:%d HTTP/1.0\r\n", dest_host, dest_port) < 0) -        return START_ERROR; -    if (proxy_auth_type == PROXY_AUTH_BASIC && basic_auth (s) < 0) -        return START_ERROR; -    if (sendf(s,"\r\n") < 0) -        return START_ERROR; - -    /* get response */ -    if ( line_input(s, buf, sizeof(buf)) < 0 ) { -        debug("failed to read http response.\n"); -        return START_ERROR; -    } - -    /* check status */ -    if (!strchr(buf, ' ')) { -	error ("Unexpected http response: '%s'.\n", buf); -	return START_ERROR; -    } -    result = atoi(strchr(buf,' ')); - -    switch ( result ) { -    case 200: -        /* Conguraturation, connected via http proxy server! */ -        debug("connected, start user session.\n"); -        break; -    case 302:                                   /* redirect */ -        do { -            if (line_input(s, buf, sizeof(buf))) -                break; -            downcase(buf); -            if (expect(buf, "Location: ")) { -                relay_host = cut_token(buf, "//"); -                cut_token(buf, "/"); -                relay_port = atoi(cut_token(buf, ":")); -            } -        } while (strcmp(buf,"\r\n") != 0); -        return START_RETRY; - -    /* We handle both 401 and 407 codes here: 401 is WWW-Authenticate, which -     * not strictly the correct response, but some proxies do send this (e.g. -     * Symantec's Raptor firewall) */ -    case 401:                                   /* WWW-Auth required */ -    case 407:                                   /* Proxy-Auth required */ -        /** NOTE: As easy implementation, we support only BASIC scheme -            and ignore realm. */ -        /* If proxy_auth_type is PROXY_AUTH_BASIC and get -         this result code, authentication was failed. */ -        if (proxy_auth_type != PROXY_AUTH_NONE) { -            error("Authentication failed.\n"); -            return START_ERROR; -        } -        auth_what = (result == 401) ? "WWW-Authenticate:" : "Proxy-Authenticate:"; -        do { -            if ( line_input(s, buf, sizeof(buf)) ) { -                break; -            } -            downcase(buf); -            if (expect(buf, auth_what)) { -                /* parse type and realm */ -                char *scheme, *realm; -                scheme = cut_token(buf, " "); -                realm = cut_token(scheme, " "); -                if ( scheme == NULL || realm == NULL ) { -                    debug("Invalid format of %s field.", auth_what); -                    return START_ERROR;         /* fail */ -                } -                /* check supported auth type */ -                if (expect(scheme, "basic")) { -                    proxy_auth_type = PROXY_AUTH_BASIC; -                } else { -                    debug("Unsupported authentication type: %s", scheme); -                } -            } -        } while (strcmp(buf,"\r\n") != 0); -        if ( proxy_auth_type == PROXY_AUTH_NONE ) { -            debug("Can't find %s in response header.", auth_what); -            return START_ERROR; -        } else { -            return START_RETRY; -        } - -    default: -        /* Not allowed */ -        debug("http proxy is not allowed.\n"); -        return START_ERROR; -    } -    /* skip to end of response header */ -    do { -        if ( line_input(s, buf, sizeof(buf) ) ) { -            debug("Can't skip response headers\n"); -            return START_ERROR; -        } -    } while ( strcmp(buf,"\r\n") != 0 ); - -    return START_OK; -} - -/* begin relaying via TELNET proxy. -   Sends string specified by telnet_command (-c option) with -   replacing host name and port number to the socket.  */ -int -begin_telnet_relay( SOCKET s ) -{ -    char buf[1024]; -    char *cmd; -    char *good_phrase = "connected to"; -    char *bad_phrase_list[] = { -	" failed", " refused", " rejected", " closed" -    }; -    char sep = ' '; -    int i; - -    debug("begin_telnet_relay()\n"); - -    /* report phrase */ -    debug("good phrase: '%s'\n", good_phrase); -    debug("bad phrases"); -    sep = ':'; -    for (i=0; i< (sizeof(bad_phrase_list) / sizeof(char*)); i++) { -	debug_("%c '%s'", sep, bad_phrase_list[i]); -	sep = ','; -    } -    debug_("\n"); - -    /* make request string with replacing %h by destination hostname -       and %p by port number, etc. */ -    cmd = expand_host_and_port(telnet_command, dest_host, dest_port); -     -    /* Sorry, we send request string now without waiting a prompt. */ -    if (sendf(s, "%s\r\n", cmd) < 0) { -	free(cmd); -        return START_ERROR; -    } -    free(cmd); - -    /* Process answer from proxy until good or bad phrase is detected.  We -       assume that the good phrase should be appeared only in the final -       line of proxy responses. Bad keywods in the line causes operation -       fail. First checks a good phrase, then checks bad phrases. -       If no match, continue reading line from proxy. */ -    while (!line_input(s, buf, sizeof(buf)) && buf[0] != '\0') { -	downcase(buf); -	/* first, check good phrase */ -        if (strstr(buf, good_phrase)) { -	    debug("good phrase is detected: '%s'\n", good_phrase); -            return START_OK; -        } -	/* then, check bad phrase */ -	for (i=0; i<(sizeof(bad_phrase_list)/sizeof(char*)); i++) { -	    if (strstr(buf, bad_phrase_list[i]) != NULL) { -		debug("bad phrase is detected: '%s'\n", bad_phrase_list[i]); -		return START_ERROR; -	    } -        } -    } -    debug("error reading from telnet proxy\n"); - -    return START_ERROR; -} - - -#ifdef _WIN32 -/* ddatalen() -   Returns 1 if data is available, otherwise return 0 - */ -int -stdindatalen (void) -{ -    DWORD len = 0; -    struct stat st; -    fstat( 0, &st ); -    if ( st.st_mode & _S_IFIFO ) { -        /* in case of PIPE */ -        if ( !PeekNamedPipe( GetStdHandle(STD_INPUT_HANDLE), -                             NULL, 0, NULL, &len, NULL) ) { -            if ( GetLastError() == ERROR_BROKEN_PIPE ) { -                /* PIPE source is closed */ -                /* read() will detects EOF */ -                len = 1; -            } else { -                fatal("PeekNamedPipe() failed, errno=%d\n", -                      GetLastError()); -            } -        } -    } else if ( st.st_mode & _S_IFREG ) { -        /* in case of regular file (redirected) */ -        len = 1;                        /* always data ready */ -    } else if ( _kbhit() ) { -        /* in case of console */ -        len = 1; -    } -    return len; -} -#endif /* _WIN32 */ - -/* relay byte from stdin to socket and fro socket to stdout. -   returns reason of termination */ -int -do_repeater( SOCKET local_in, SOCKET local_out, SOCKET remote ) -{ -    /** vars for local input data **/ -    char lbuf[1024];                            /* local input buffer */ -    int lbuf_len;                               /* available data in lbuf */ -    int f_local;                                /* read local input more? */ -    /** vars for remote input data **/ -    char rbuf[1024];                            /* remote input buffer */ -    int rbuf_len;                               /* available data in rbuf */ -    int f_remote;                               /* read remote input more? */ -    int close_reason = REASON_UNK;              /* reason of end repeating */ -    /** other variables **/ -    int nfds, len; -    fd_set ifds, ofds; -    struct timeval *tmo; -#ifdef _WIN32 -    struct timeval win32_tmo; -#endif /* _WIN32 */ - -    /* repeater between stdin/out and socket  */ -    nfds = ((local_in<remote)? remote: local_in) +1; -    f_local = 1;                                /* yes, read from local */ -    f_remote = 1;                               /* yes, read from remote */ -    lbuf_len = 0; -    rbuf_len = 0; - -    while ( f_local || f_remote ) { -        FD_ZERO(&ifds ); -        FD_ZERO(&ofds ); -        tmo = NULL; - -        /** prepare for reading local input **/ -        if ( f_local && (lbuf_len < (int)sizeof(lbuf)) ) { -#ifdef _WIN32 -            if ( local_type != LOCAL_SOCKET ) { -                /* select() on Winsock is not accept standard handle. -                   So use select() with short timeout and checking data -                   in stdin by another method. */ -                win32_tmo.tv_sec = 0; -                win32_tmo.tv_usec = 10*1000;    /* 10 ms */ -                tmo = &win32_tmo; -            } else -#endif /* !_WIN32 */ -            FD_SET( local_in, &ifds ); -        } - -        /** prepare for reading remote input **/ -        if ( f_remote && (rbuf_len < (int)sizeof(rbuf)) ) { -            FD_SET( remote, &ifds ); -        } - -        /* FD_SET( local_out, ofds ); */ -        /* FD_SET( remote, ofds ); */ - -        if ( select( nfds, &ifds, &ofds, (fd_set*)NULL, tmo ) == -1 ) { -            /* some error */ -            error( "select() failed, %d\n", socket_errno()); -            return REASON_ERROR; -        } -#ifdef _WIN32 -        /* fake ifds if local is stdio handle because -           select() of Winsock does not accept stdio -           handle. */ -        if (f_local && (local_type!=LOCAL_SOCKET) && (0<stdindatalen())) -            FD_SET(0,&ifds);            /* data ready */ -#endif - -        /* remote => local */ -        if ( FD_ISSET(remote, &ifds) && (rbuf_len < (int)sizeof(rbuf)) ) { -            len = recv( remote, rbuf + rbuf_len, sizeof(rbuf)-rbuf_len, 0); -            if ( len == 0 || (len == -1 && socket_errno() == ECONNRESET)) { -                debug("connection %s by peer\n", -                      (len==0)? "closed": "reset"); -                close_reason = REASON_CLOSED_BY_REMOTE; -                f_remote = 0;                   /* no more read from socket */ -                f_local = 0; -            } else if ( len == -1 ) { -                /* error */ -                fatal("recv() failed, %d\n", socket_errno()); -            } else { -                debug("recv %d bytes\n", len); -                if ( 1 < f_debug )              /* more verbose */ -                    report_bytes( "<<<", rbuf+rbuf_len, len); -                rbuf_len += len; -            } -        } - -        /* local => remote */ -        if ( FD_ISSET(local_in, &ifds) && (lbuf_len < (int)sizeof(lbuf)) ) { -            if (local_type == LOCAL_SOCKET) -                len = recv(local_in, lbuf + lbuf_len, -                           sizeof(lbuf)-lbuf_len, 0); -            else -                len = read(local_in, lbuf + lbuf_len, sizeof(lbuf)-lbuf_len); -            if ( len == 0 ) { -                /* stdin is EOF */ -                debug("local input is EOF\n"); -                if (!f_hold_session) -                    shutdown(remote, 1);        /* no-more writing */ -                f_local = 0; -                close_reason = REASON_CLOSED_BY_LOCAL; -            } else if ( len == -1 ) { -                /* error on reading from stdin */ -                if (f_hold_session) { -                    debug ("failed to read from local\n"); -                    f_local = 0; -                    close_reason = REASON_CLOSED_BY_LOCAL; -                } else -                    fatal("recv() failed, errno = %d\n", errno); -            } else { -                /* repeat */ -                lbuf_len += len; -            } -        } - -        /* flush data in buffer to socket */ -        if ( 0 < lbuf_len ) { -            len = send(remote, lbuf, lbuf_len, 0); -            if ( len == -1 ) { -                fatal("send() failed, %d\n", socket_errno()); -            } else if ( 0 < len ) { -                if ( 1 < f_debug )              /* more verbose */ -                    report_bytes( ">>>", lbuf, len); -                /* move data on to top of buffer */ -                debug("sent %d bytes\n", len); -                lbuf_len -= len; -                if ( 0 < lbuf_len ) -                    memcpy( lbuf, lbuf+len, lbuf_len ); -                assert( 0 <= lbuf_len ); -            } -        } - -        /* flush data in buffer to local output */ -        if ( 0 < rbuf_len ) { -            if (local_type == LOCAL_SOCKET) -                len = send( local_out, rbuf, rbuf_len, 0); -            else -                len = write( local_out, rbuf, rbuf_len); -            if ( len == -1 ) { -                fatal("output (local) failed, errno=%d\n", errno); -            } -            rbuf_len -= len; -            if ( len < rbuf_len ) -                memcpy( rbuf, rbuf+len, rbuf_len ); -            assert( 0 <= rbuf_len ); -        } -        if (f_local == 0 && f_hold_session) { -            debug ("closing local port without disconnecting from remote\n"); -            f_remote = 0; -            shutdown (local_out, 2); -            close (local_out); -            break; -        } -    } - -    return close_reason; -} - -int -accept_connection (u_short port) -{ -    static int sock = -1; -    int connection; -    struct sockaddr_in name; -    struct sockaddr client; -    int socklen; -    fd_set ifds; -    int nfds; -    int sockopt; - -    /* Create the socket. */ -    debug("Creating source port to forward.\n"); -    sock = socket (PF_INET, SOCK_STREAM, 0); -    if (sock < 0) -        fatal("socket() failed, errno=%d\n", socket_errno()); -    sockopt = 1; -    setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, -                (void*)&sockopt, sizeof(sockopt)); - -    /* Give the socket a name. */ -    name.sin_family = AF_INET; -    name.sin_port = htons (port); -    name.sin_addr.s_addr = htonl (INADDR_ANY); -    if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) -        fatal ("bind() failed, errno=%d\n", socket_errno()); - -    if (listen( sock, 1) < 0) -        fatal ("listen() failed, errno=%d\n", socket_errno()); - -    /* wait for new connection with watching EOF of stdin. */ -    debug ("waiting new connection at port %d (socket=%d)\n", port, sock); -    nfds = sock + 1; -    do { -        int n; -        struct timeval *ptmo = NULL; -#ifdef _WIN32 -        struct timeval tmo; -        tmo.tv_sec = 0; -        tmo.tv_usec = 100*1000;                 /* On Windows, 100ms timeout */ -        ptmo = &tmo; -#endif /* _WIN32 */ -        FD_ZERO (&ifds); -        FD_SET ((SOCKET)sock, &ifds); -#ifndef _WIN32 -        FD_SET (0, &ifds);                      /* watch stdin */ -#endif -        n = select (nfds, &ifds, NULL, NULL, ptmo); -        if (n == -1) { -            fatal ("select() failed, %d\n", socket_errno()); -            exit (1); -        } -#ifdef _WIN32 -        if (0 < stdindatalen()) { -            FD_SET (0, &ifds);          /* fake */ -            n++; -        } -#endif -        if (0 < n) { -            if (FD_ISSET(0, &ifds) && (getchar() <= 0)) { -                /* EOF */ -                debug ("Give-up waiting port because stdin is closed."); -                exit(0); -            } -            if (FD_ISSET(sock, &ifds)) -                break;                          /* socket is stimulated */ -        } -    } while (1); -    socklen = sizeof(client); -    connection = accept( sock, &client, &socklen); -    if ( connection < 0 ) -        fatal ("accept() failed, errno=%d\n", socket_errno()); -    return connection; -} - - - -/** Main of program **/ -int -main( int argc, char **argv ) -{ -    int ret; -    int remote;                                 /* socket */ -    int local_in;                               /* Local input */ -    int local_out;                              /* Local output */ -    int reason; -#ifdef _WIN32 -    WSADATA wsadata; -    WSAStartup( 0x101, &wsadata); -#endif /* _WIN32 */ - -    /* initialization */ -    make_revstr(); -    getarg( argc, argv ); -    debug("Program is $Revision: 100 $\n"); - -    /* Open local_in and local_out if forwarding a port */ -    if ( local_type == LOCAL_SOCKET ) { -        /* Relay between local port and destination */ -        local_in = local_out = accept_connection( local_port ); -    } else { -        /* Relay between stdin/stdout and desteination */ -        local_in = 0; -        local_out = 1; -#ifdef _WIN32 -        _setmode(local_in, O_BINARY); -        _setmode(local_out, O_BINARY); -#endif -    } - -retry: -#ifndef _WIN32 -    if (0 < connect_timeout) -        set_timeout (connect_timeout); -#endif /* not _WIN32 */ - -    if (check_direct(dest_host)) -        relay_method = METHOD_DIRECT; -    /* make connection */ -    if ( relay_method == METHOD_DIRECT ) { -        remote = open_connection (dest_host, dest_port); -        if ( remote == SOCKET_ERROR ) -            fatal( "Unable to connect to destination host, errno=%d\n", -                   socket_errno()); -    } else { -        remote = open_connection (relay_host, relay_port); -        if ( remote == SOCKET_ERROR ) -            fatal( "Unable to connect to relay host, errno=%d\n", -                   socket_errno()); -    } - -    /** resolve destination host (SOCKS) **/ -#if !defined(_WIN32) && !defined(__CYGWIN32__) -    if (socks_ns.sin_addr.s_addr != 0) -        switch_ns (&socks_ns); -#endif /* not _WIN32 && not __CYGWIN32__ */ -    if (relay_method == METHOD_SOCKS && -        socks_resolve == RESOLVE_LOCAL && -        local_resolve (dest_host, &dest_addr) < 0) { -        fatal("Unknown host: %s", dest_host); -    } - -    /** relay negociation **/ -    switch ( relay_method ) { -    case METHOD_SOCKS: -        if ( ((socks_version == 5) && (begin_socks5_relay(remote) < 0)) || -             ((socks_version == 4) && (begin_socks4_relay(remote) < 0)) ) -            fatal( "failed to begin relaying via SOCKS.\n"); -        break; - -    case METHOD_HTTP: -        ret = begin_http_relay(remote); -        switch (ret) { -        case START_ERROR: -            close (remote); -            fatal("failed to begin relaying via HTTP.\n"); -        case START_OK: -            break; -        case START_RETRY: -            /* retry with authentication */ -            close (remote); -            goto retry; -        } -        break; -    case METHOD_TELNET: -        if (begin_telnet_relay(remote) < 0) -             fatal("failed to begin relaying via telnet.\n"); -        break; -    } -    debug("connected\n"); - -#ifndef _WIN32 -    if (0 < connect_timeout) -        set_timeout (0); -#endif /* not _WIN32 */ - -    /* main loop */ -    debug ("start relaying.\n"); -do_repeater: -    reason = do_repeater(local_in, local_out, remote); -    debug ("relaying done.\n"); -    if (local_type == LOCAL_SOCKET && -        reason == REASON_CLOSED_BY_LOCAL && -        f_hold_session) { -        /* re-wait at local port without closing remote session */ -        debug ("re-waiting at local port %d\n", local_port); -        local_in = local_out = accept_connection( local_port ); -        debug ("re-start relaying\n"); -        goto do_repeater; -    } -    closesocket(remote); -    if ( local_type == LOCAL_SOCKET) -        closesocket(local_in); -#ifdef _WIN32 -    WSACleanup(); -#endif /* _WIN32 */ -    debug ("that's all, bye.\n"); - -    return 0; -} - -/* ------------------------------------------------------------ -   Local Variables: -   compile-command: "cc connect.c -o connect" -   tab-width: 8 -   fill-column: 74 -   comment-column: 48 -   End: -   ------------------------------------------------------------ */ - -/*** end of connect.c ***/ | 
