Ticket #14293: patch-socks5.diff

File patch-socks5.diff, 11.7 KB (added by simon@…, 16 years ago)
  • config

    diff -r 6ce92f2e919b config
     
    10971097#
    10981098#
    10991099#
    1100 #  5.2. forward-socks4 and forward-socks4a
     1100#  5.2. forward-socks4, forward-socks4a and forward-socks5
    11011101#
    11021102#  Specifies:
    11031103#
     
    11281128#      Multiple lines are OK, they are checked in sequence, and the
    11291129#      last match wins.
    11301130#
    1131 #      The difference between forward-socks4 and forward-socks4a
    1132 #      is that in the SOCKS 4A protocol, the DNS resolution of the
    1133 #      target hostname happens on the SOCKS server, while in SOCKS 4
    1134 #      it happens locally.
     1131
     1132#      The difference between forward-socks4 and either
     1133#      forward-socks4a or forward-socks5 is that in the SOCKS 4A and
     1134#      SOCKS 5 protocols, the DNS resolution of the target hostname
     1135#      happens on the SOCKS server, while in SOCKS 4 it happens
     1136#      locally.
    11351137#
    11361138#      If http_parent is ".", then requests are not forwarded to another
    11371139#      HTTP proxy but are made (HTTP-wise) directly to the web servers,
     
    11531155#
    11541156#        forward-socks4   /               socks-gw.example.com:1080  .
    11551157#
     1158#      ssh dynamic forwarding can handle either SOCKS 4 or SOCKS 5
     1159#      requests.  But name lookups on the server can only be done with
     1160#      SOCKS 5.  To chain Privoxy and ssh dynamic forwarding using
     1161#      SOCKS5 when they are both running on the same system, you
     1162#      should use the rule:
     1163#
     1164#        forward-socks5             /     127.0.0.1:3129 .
     1165#
     1166#      This presumes, of course, that you've configured your ssh
     1167#      connection with 'DynamicForward 3129'.
     1168#
    11561169#
    11571170#      To chain Privoxy and Tor, both running on the same system,
    11581171#      you would use something like:
  • gateway.c

    diff -r 6ce92f2e919b gateway.c
     
    176176                                int target_port,
    177177                                struct client_state *csp);
    178178
     179static jb_socket socks5_connect(const struct forward_spec * fwd,
     180                                const char * target_host,
     181                                int target_port,
     182                                struct client_state *csp);
     183
    179184
    180185#define SOCKS_REQUEST_GRANTED          90
    181186#define SOCKS_REQUEST_REJECT           91
    182187#define SOCKS_REQUEST_IDENT_FAILED     92
    183188#define SOCKS_REQUEST_IDENT_CONFLICT   93
     189#define SOCKS5_REQUEST_GRANTED             0
     190#define SOCKS5_REQUEST_FAILED              1
     191#define SOCKS5_REQUEST_DENIED              2
     192#define SOCKS5_REQUEST_NETWORK_UNREACHABLE 3
     193#define SOCKS5_REQUEST_HOST_UNREACHABLE    4
     194#define SOCKS5_REQUEST_CONNECTION_REFUSEDD 5
     195#define SOCKS5_REQUEST_TTL_EXPIRED         6
     196#define SOCKS5_REQUEST_PROTOCOL_ERROR      7
     197#define SOCKS5_REQUEST_BAD_ADDRESS_TYPE    8
    184198
    185199/* structure of a socks client operation */
    186200struct socks_op {
     
    250264      case SOCKS_4A:
    251265         return (socks4_connect(fwd, dest_host, dest_port, csp));
    252266
     267      case SOCKS_5:
     268         return (socks5_connect(fwd, dest_host, dest_port, csp));
     269
    253270      default:
    254271         /* Should never get here */
    255272         log_error(LOG_LEVEL_FATAL, "SOCKS4 impossible internal error - bad SOCKS type.");
     
    454471}
    455472
    456473
     474/*********************************************************************
     475 *
     476 * Function    :  socks4_connect
     477 *
     478 * Description :  Connect to the SOCKS server, and connect through
     479 *                it to the specified server.   This handles
     480 *                all the SOCKS negotiation, and returns a file
     481 *                descriptor for a socket which can be treated as a
     482 *                normal (non-SOCKS) socket.
     483 *
     484 * Parameters  :
     485 *          1  :  fwd = Specifies the SOCKS proxy to use.
     486 *          2  :  target_host = The final server to connect to.
     487 *          3  :  target_port = The final port to connect to.
     488 *          4  :  csp = Current client state (buffers, headers, etc...)
     489 *
     490 * Returns     :  JB_INVALID_SOCKET => failure, else a socket file descriptor.
     491 *
     492 *********************************************************************/
     493static jb_socket socks5_connect(const struct forward_spec * fwd,
     494                                const char * target_host,
     495                                int target_port,
     496                                struct client_state *csp)
     497{
     498   int err = 0;
     499   char cbuf[BUFFER_SIZE];
     500   char sbuf[BUFFER_SIZE];
     501   size_t client_pos = 0;
     502   ssize_t server_size = 0;
     503   size_t hostlen = 0;
     504   jb_socket sfd;
     505
     506   if ((fwd->gateway_host == NULL) || (*fwd->gateway_host == '\0'))
     507   {
     508      log_error(LOG_LEVEL_CONNECT, "socks5_connect: NULL gateway host specified");
     509      err = 1;
     510   }
     511
     512   if (fwd->gateway_port <= 0)
     513   {
     514      log_error(LOG_LEVEL_CONNECT, "socks5_connect: invalid gateway port specified");
     515      err = 1;
     516   }
     517
     518   hostlen = strlen(target_host);
     519   if (hostlen > 0xff)
     520   {
     521      log_error(LOG_LEVEL_CONNECT, "socks5_connect: target host name is longer than 255 characters.");
     522      err = 1;
     523   }
     524
     525   if (fwd->type != SOCKS_5)
     526   {
     527      /* Should never get here */
     528      log_error(LOG_LEVEL_FATAL, "SOCKS4 impossible internal error - bad SOCKS type.");
     529      err = 1;
     530   }
     531
     532   if (err)
     533   {
     534      errno = EINVAL;
     535      return(JB_INVALID_SOCKET);
     536   }
     537
     538   /* pass the request to the socks server */
     539   sfd = connect_to(fwd->gateway_host, fwd->gateway_port, csp);
     540
     541   if (sfd == JB_INVALID_SOCKET)
     542   {
     543      return(JB_INVALID_SOCKET);
     544   }
     545
     546   cbuf[client_pos++] = '\x05'; // Version
     547   cbuf[client_pos++] = '\x01'; // One authentication method supported
     548   cbuf[client_pos++] = '\x00'; // The no authentication authentication method
     549
     550   if (write_socket(sfd, cbuf, client_pos))
     551   {
     552      log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation write failed...");
     553      close_socket(sfd);
     554      return(JB_INVALID_SOCKET);
     555   }
     556
     557   if (read_socket(sfd, sbuf, sizeof(sbuf)) != 2)
     558   {
     559      log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation read failed...");
     560      err = 1;
     561   }
     562
     563   if (!err && (sbuf[0] != '\x05'))
     564   {
     565      log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol version error");
     566      err = 1;
     567   }
     568
     569   if (!err && (sbuf[1] == '\xff'))
     570   {
     571      log_error(LOG_LEVEL_CONNECT, "SOCKS5 authentication required");
     572      err = 1;
     573   }
     574
     575   if (!err && (sbuf[1] != '\x00'))
     576   {
     577      log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol error");
     578      err = 1;
     579   }
     580
     581   if (err)
     582   {
     583      close_socket(sfd);
     584      errno = EINVAL;
     585      return(JB_INVALID_SOCKET);
     586   }
     587
     588   client_pos = 0;
     589   cbuf[client_pos++] = '\x05'; // Version
     590   cbuf[client_pos++] = '\x01'; // TCP connect
     591   cbuf[client_pos++] = '\x00'; // Reserved, must be 0x00
     592   cbuf[client_pos++] = '\x03'; // Address is domain name
     593   cbuf[client_pos++] = (char)(hostlen & 0xffu);
     594   strncpy(cbuf + client_pos, target_host, 0xffu);
     595   client_pos += (hostlen & 0xffu);
     596   cbuf[client_pos++] = (char)((target_port >> 8) & 0xffu);
     597   cbuf[client_pos++] = (char)((target_port     ) & 0xffu);
     598
     599   if (write_socket(sfd, cbuf, client_pos))
     600   {
     601      log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation write failed...");
     602      close_socket(sfd);
     603      errno = EINVAL;
     604      return(JB_INVALID_SOCKET);
     605   }
     606
     607   server_size = read_socket(sfd, sbuf, sizeof(sbuf));
     608   if (server_size < 3)
     609   {
     610      log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation read failed...");
     611      err = 1;
     612   }
     613
     614   if (!err && (sbuf[0] != '\x05'))
     615   {
     616      log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol version error");
     617      err = 1;
     618   }
     619
     620   if (!err && (sbuf[2] != '\x00'))
     621   {
     622      log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol error");
     623      err = 1;
     624   }
     625
     626   if (!err)
     627   {
     628      switch (sbuf[1]) {
     629       case SOCKS5_REQUEST_GRANTED:
     630         return(sfd);
     631         break;
     632       case SOCKS5_REQUEST_FAILED:
     633         log_error(LOG_LEVEL_CONNECT, "SOCKS5 request failed");
     634         break;
     635       case SOCKS5_REQUEST_DENIED:
     636         log_error(LOG_LEVEL_CONNECT, "SOCKS5 request denied");
     637         break;
     638       case SOCKS5_REQUEST_NETWORK_UNREACHABLE:
     639         log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - network unreachable");
     640         break;
     641       case SOCKS5_REQUEST_HOST_UNREACHABLE:
     642         log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - host unreachable");
     643         break;
     644       case SOCKS5_REQUEST_CONNECTION_REFUSEDD:
     645         log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - connection refused");
     646         break;
     647       case SOCKS5_REQUEST_TTL_EXPIRED:
     648         log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - TTL expired");
     649         break;
     650       case SOCKS5_REQUEST_PROTOCOL_ERROR:
     651         log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - client protocol error");
     652         break;
     653       case SOCKS5_REQUEST_BAD_ADDRESS_TYPE:
     654         log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - domain names unsupported");
     655         break;
     656       default:
     657         log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol error");
     658         break;
     659      }
     660      err = 1;
     661   }
     662
     663   close_socket(sfd);
     664   errno = EINVAL;
     665   return(JB_INVALID_SOCKET);
     666}
     667
    457668/*
    458669  Local Variables:
    459670  tab-width: 3
  • loadcfg.c

    diff -r 6ce92f2e919b loadcfg.c
     
    535535#define hash_forward                        2029845ul /* "forward" */
    536536#define hash_forward_socks4              3963965521ul /* "forward-socks4" */
    537537#define hash_forward_socks4a             2639958518ul /* "forward-socks4a" */
     538#define hash_forward_socks5              3963965522ul /* "forward-socks5" */
    538539#define hash_forwarded_connect_retries    101465292ul /* "forwarded-connect-retries" */
    539540#define hash_jarfile                        2046641ul /* "jarfile" */
    540541#define hash_listen_address              1255650842ul /* "listen-address" */
     
    774775      struct forward_spec *cur_fwd;
    775776      int vec_count;
    776777      char *vec[3];
     778      unsigned long int directive_hash = 0ul;
    777779
    778780      strlcpy(tmp, buf, sizeof(tmp));
    779781
     
    814816      savearg(cmd, arg, config);
    815817
    816818
    817       switch( hash_string( cmd ) )
     819      directive_hash = hash_string( cmd );
     820      switch( directive_hash )
    818821      {
    819822/* *************************************************************************
    820823 * actionsfile actions-file-name
     
    12031206 * forward-socks4a url-pattern socks-proxy[:port] (.|http-proxy[:port])
    12041207 * *************************************************************************/
    12051208         case hash_forward_socks4a:
     1209         case hash_forward_socks5:
    12061210            vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
    12071211
    12081212            if (vec_count != 3)
     
    12241228               continue;
    12251229            }
    12261230
     1231            if (directive_hash == hash_forward_socks4a) {
    12271232            cur_fwd->type = SOCKS_4A;
     1233            } else {
     1234               cur_fwd->type = SOCKS_5;
     1235            }
    12281236
    12291237            /* Save the URL pattern */
    12301238            if (create_url_spec(cur_fwd->url, vec[0]))
  • project.h

    diff -r 6ce92f2e919b project.h
     
    14741474#define SOCKS_NONE    0    /**< Don't use a SOCKS server               */
    14751475#define SOCKS_4      40    /**< original SOCKS 4 protocol              */
    14761476#define SOCKS_4A     41    /**< as modified for hosts w/o external DNS */
     1477#define SOCKS_5      50    /**< as modified for hosts w/o external DNS */
    14771478
    14781479
    14791480/**
     
    14841485   /** URL pattern that this forward_spec is for. */
    14851486   struct url_spec url[1];
    14861487
    1487    /** Connection type.  Must be SOCKS_NONE, SOCKS_4, or SOCKS_4A. */
     1488   /** Connection type.  Must be SOCKS_NONE, SOCKS_4, SOCKS_4A or SOCKS_5. */
    14881489   int   type;
    14891490
    14901491   /** SOCKS server hostname.  Only valid if "type" is SOCKS_4 or SOCKS_4A. */