-const char gateway_rcs[] = "$Id: gateway.c,v 1.20 2007/05/14 10:23:48 fabiankeil Exp $";
+const char gateway_rcs[] = "$Id: gateway.c,v 1.21 2007/07/28 12:30:03 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/gateway.c,v $
*
* Revisions :
* $Log: gateway.c,v $
+ * Revision 1.21 2007/07/28 12:30:03 fabiankeil
+ * Modified patch from Song Weijia (#1762559) to
+ * fix socks requests on big-endian platforms.
+ *
* Revision 1.20 2007/05/14 10:23:48 fabiankeil
* - Use strlcpy() instead of strcpy().
* - Use the same buffer for socks requests and socks responses.
int target_port,
struct client_state *csp);
+static jb_socket socks5_connect(const struct forward_spec *fwd,
+ const char *target_host,
+ int target_port,
+ struct client_state *csp);
+
#define SOCKS_REQUEST_GRANTED 90
#define SOCKS_REQUEST_REJECT 91
#define SOCKS_REQUEST_IDENT_FAILED 92
#define SOCKS_REQUEST_IDENT_CONFLICT 93
+#define SOCKS5_REQUEST_GRANTED 0
+#define SOCKS5_REQUEST_FAILED 1
+#define SOCKS5_REQUEST_DENIED 2
+#define SOCKS5_REQUEST_NETWORK_UNREACHABLE 3
+#define SOCKS5_REQUEST_HOST_UNREACHABLE 4
+#define SOCKS5_REQUEST_CONNECTION_REFUSEDD 5
+#define SOCKS5_REQUEST_TTL_EXPIRED 6
+#define SOCKS5_REQUEST_PROTOCOL_ERROR 7
+#define SOCKS5_REQUEST_BAD_ADDRESS_TYPE 8
+
/* structure of a socks client operation */
struct socks_op {
unsigned char vn; /* socks version number */
case SOCKS_4A:
return (socks4_connect(fwd, dest_host, dest_port, csp));
+ case SOCKS_5:
+ return (socks5_connect(fwd, dest_host, dest_port, csp));
+
default:
/* Should never get here */
log_error(LOG_LEVEL_FATAL, "SOCKS4 impossible internal error - bad SOCKS type.");
}
+/*********************************************************************
+ *
+ * Function : socks5_connect
+ *
+ * Description : Connect to the SOCKS server, and connect through
+ * it to the specified server. This handles
+ * all the SOCKS negotiation, and returns a file
+ * descriptor for a socket which can be treated as a
+ * normal (non-SOCKS) socket.
+ *
+ * Parameters :
+ * 1 : fwd = Specifies the SOCKS proxy to use.
+ * 2 : target_host = The final server to connect to.
+ * 3 : target_port = The final port to connect to.
+ * 4 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : JB_INVALID_SOCKET => failure, else a socket file descriptor.
+ *
+ *********************************************************************/
+static jb_socket socks5_connect(const struct forward_spec *fwd,
+ const char *target_host,
+ int target_port,
+ struct client_state *csp)
+{
+ int err = 0;
+ char cbuf[BUFFER_SIZE];
+ char sbuf[BUFFER_SIZE];
+ size_t client_pos = 0;
+ int server_size = 0;
+ size_t hostlen = 0;
+ jb_socket sfd;
+
+ if ((fwd->gateway_host == NULL) || (*fwd->gateway_host == '\0'))
+ {
+ log_error(LOG_LEVEL_CONNECT, "socks5_connect: NULL gateway host specified");
+ err = 1;
+ }
+
+ if (fwd->gateway_port <= 0)
+ {
+ log_error(LOG_LEVEL_CONNECT, "socks5_connect: invalid gateway port specified");
+ err = 1;
+ }
+
+ hostlen = strlen(target_host);
+ if (hostlen > 255)
+ {
+ log_error(LOG_LEVEL_CONNECT, "socks5_connect: target host name is longer than 255 characters.");
+ err = 1;
+ }
+
+ if (fwd->type != SOCKS_5)
+ {
+ /* Should never get here */
+ log_error(LOG_LEVEL_FATAL, "SOCKS5 impossible internal error - bad SOCKS type.");
+ err = 1;
+ }
+
+ if (err)
+ {
+ errno = EINVAL;
+ return(JB_INVALID_SOCKET);
+ }
+
+ /* pass the request to the socks server */
+ sfd = connect_to(fwd->gateway_host, fwd->gateway_port, csp);
+
+ if (sfd == JB_INVALID_SOCKET)
+ {
+ return(JB_INVALID_SOCKET);
+ }
+
+ client_pos = 0;
+ cbuf[client_pos++] = '\x05'; /* Version */
+ cbuf[client_pos++] = '\x01'; /* One authentication method supported */
+ cbuf[client_pos++] = '\x00'; /* The no authentication authentication method */
+
+ if (write_socket(sfd, cbuf, client_pos))
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation write failed...");
+ close_socket(sfd);
+ return(JB_INVALID_SOCKET);
+ }
+
+ if (read_socket(sfd, sbuf, sizeof(sbuf)) != 2)
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation read failed...");
+ err = 1;
+ }
+
+ if (!err && (sbuf[0] != '\x05'))
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol version error");
+ err = 1;
+ }
+
+ if (!err && (sbuf[1] == '\xff'))
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 authentication required");
+ err = 1;
+ }
+
+ if (!err && (sbuf[1] != '\x00'))
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol error");
+ err = 1;
+ }
+
+ if (err)
+ {
+ close_socket(sfd);
+ errno = EINVAL;
+ return(JB_INVALID_SOCKET);
+ }
+
+ client_pos = 0;
+ cbuf[client_pos++] = '\x05'; /* Version */
+ cbuf[client_pos++] = '\x01'; /* TCP connect */
+ cbuf[client_pos++] = '\x00'; /* Reserved, must be 0x00 */
+ cbuf[client_pos++] = '\x03'; /* Address is domain name */
+ cbuf[client_pos++] = (char)(hostlen & 0xffu);
+ strncpy(cbuf + client_pos, target_host, 0xffu);
+ client_pos += (hostlen & 0xffu);
+ cbuf[client_pos++] = (char)((target_port >> 8) & 0xffu);
+ cbuf[client_pos++] = (char)((target_port ) & 0xffu);
+
+ if (write_socket(sfd, cbuf, client_pos))
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation write failed...");
+ close_socket(sfd);
+ errno = EINVAL;
+ return(JB_INVALID_SOCKET);
+ }
+
+ server_size = read_socket(sfd, sbuf, sizeof(sbuf));
+ if (server_size < 3)
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation read failed...");
+ err = 1;
+ }
+
+ if (!err && (sbuf[0] != '\x05'))
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol version error");
+ err = 1;
+ }
+
+ if (!err && (sbuf[2] != '\x00'))
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol error");
+ err = 1;
+ }
+
+ if (!err)
+ {
+ switch (sbuf[1])
+ {
+ case SOCKS5_REQUEST_GRANTED:
+ return(sfd);
+ break;
+ case SOCKS5_REQUEST_FAILED:
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 request failed");
+ break;
+ case SOCKS5_REQUEST_DENIED:
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 request denied");
+ break;
+ case SOCKS5_REQUEST_NETWORK_UNREACHABLE:
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - network unreachable");
+ break;
+ case SOCKS5_REQUEST_HOST_UNREACHABLE:
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - host unreachable");
+ break;
+ case SOCKS5_REQUEST_CONNECTION_REFUSEDD:
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - connection refused");
+ break;
+ case SOCKS5_REQUEST_TTL_EXPIRED:
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - TTL expired");
+ break;
+ case SOCKS5_REQUEST_PROTOCOL_ERROR:
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - client protocol error");
+ break;
+ case SOCKS5_REQUEST_BAD_ADDRESS_TYPE:
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 request - domain names unsupported");
+ break;
+ default:
+ log_error(LOG_LEVEL_CONNECT, "SOCKS5 negotiation protocol error");
+ break;
+ }
+ err = 1;
+ }
+
+ close_socket(sfd);
+ errno = EINVAL;
+ return(JB_INVALID_SOCKET);
+}
+
/*
Local Variables:
tab-width: 3
-const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.70 2007/12/15 14:24:05 fabiankeil Exp $";
+const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.71 2007/12/23 15:24:56 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
*
* Revisions :
* $Log: loadcfg.c,v $
+ * Revision 1.71 2007/12/23 15:24:56 fabiankeil
+ * Reword "unrecognized directive" warning, use better
+ * mark up and add a <br>. Fixes parts of #1856559.
+ *
* Revision 1.70 2007/12/15 14:24:05 fabiankeil
* Plug memory leak if listen-address only specifies the port.
*
#define hash_forward 2029845ul /* "forward" */
#define hash_forward_socks4 3963965521ul /* "forward-socks4" */
#define hash_forward_socks4a 2639958518ul /* "forward-socks4a" */
+#define hash_forward_socks5 3963965522ul /* "forward-socks5" */
#define hash_forwarded_connect_retries 101465292ul /* "forwarded-connect-retries" */
#define hash_jarfile 2046641ul /* "jarfile" */
#define hash_listen_address 1255650842ul /* "listen-address" */
struct forward_spec *cur_fwd;
int vec_count;
char *vec[3];
+ unsigned long directive_hash;
strlcpy(tmp, buf, sizeof(tmp));
/* Save the argument for show-proxy-args */
savearg(cmd, arg, config);
-
- switch( hash_string( cmd ) )
+ directive_hash = hash_string(cmd);
+ switch (directive_hash)
{
/* *************************************************************************
* actionsfile actions-file-name
* forward-socks4a url-pattern socks-proxy[:port] (.|http-proxy[:port])
* *************************************************************************/
case hash_forward_socks4a:
+ case hash_forward_socks5:
vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
if (vec_count != 3)
continue;
}
- cur_fwd->type = SOCKS_4A;
+ if (directive_hash == hash_forward_socks4a)
+ {
+ cur_fwd->type = SOCKS_4A;
+ }
+ else
+ {
+ cur_fwd->type = SOCKS_5;
+ }
/* Save the URL pattern */
if (create_url_spec(cur_fwd->url, vec[0]))