Beispiel #1
0
int
socks5_negotiate(int clisock, struct conndesc *conn)
{
	u_int i;
	char hostname[256];
	u_char nmethods, len, junk; 
	struct sockaddr_in rem_in;
	struct socks5_req req5;
	struct socks5_v_repl rep5;
	struct hostent *hent;	
	
	req5.vn = 5;
	req5.rsv = 0;
	
	/*
	 * Start by retrieving number of methods, version number has
	 * already been consumed by the calling procedure
	 */

	if (atomicio(read, clisock, &nmethods, 1) != 1) {
		warnv(1, "read()");
		return (-1);
	}

	/* Eat up methods */

	i = 0;
	while (i++ < nmethods) 
		if (atomicio(read, clisock, &junk, 1) != 1) {
			warnv(1, "read()");
			return (-1);
		}

	/*
	 * We don't support any authentication methods yet, so simply
	 * ignore it and send reply with no authentication required.
	 */

	rep5.ver = 5;
	rep5.res = 0;

	if (atomicio(write, clisock, &rep5, 2) != 2) {
		warnv(1, "write()");
		return (-1);
	}

	/* Receive data up to atyp */
	if (atomicio(read, clisock, &req5, 4) != 4) {
		warnv(1, "read()");
		return (-1);
	}
	if (req5.vn != 5)
		return (-1);

	memset(&rem_in, 0, sizeof(rem_in));

	switch (req5.atyp) {
	case SOCKS5_ATYP_IPV4:
		if (atomicio(read, clisock, &req5.destaddr, 4) != 4) {
			warnv(1, "read()");
			return (-1);
		}
		rem_in.sin_family = AF_INET;
		rem_in.sin_addr.s_addr = req5.destaddr;
		break;
	case SOCKS5_ATYP_FQDN:
		if (atomicio(read, clisock, &len, 1) != 1) {
			warnv(1, "read()");
			return (-1);
		}
		if (atomicio(read, clisock, hostname, len) != len) {
			warnv(1, "read()");
			return (-1);
		}
		hostname[len] = '\0';
		if ((hent = gethostbyname(hostname)) == NULL) {
			/* XXX no hstrerror() on solaris */
#ifndef __sun__			
			warnxv(1, "gethostbyname(): %s", hstrerror(h_errno));
#endif /* __sun__ */
			return (-1);
		}
		rem_in.sin_family = AF_INET;
		rem_in.sin_addr = *(struct in_addr *)hent->h_addr;
		break;
	default:
		return (-1);
	}

	if (atomicio(read, clisock, &req5.destport, 2) != 2) {
		warnv(1, "read()");
		return (-1);
	}

	rem_in.sin_port = req5.destport;

	/*
	 * Now we have a filled in in_addr for the target host:
	 * target_in, no socket yet.  This is provided by the command
	 * specific functions multiplexed in the next switch
	 * statement.
	 */

	switch (req5.cd) {
	case SOCKS5_CD_CONNECT:
		return (socks5_connect(clisock, &rem_in, &req5, conn));
	case SOCKS5_CD_BIND:
	        signal_setup();
	        event_dispatch();
		return (socks5_bind(clisock, &rem_in, &req5));
	case SOCKS5_CD_UDP_ASSOC:
	default:
		return (-1);
	}
}
Beispiel #2
0
int
socks4_negotiate(int clisock, struct conndesc *conn)
{
	u_char data, *addr;
	char hostname[256];
	int ret;
	struct socks4_hdr hdr4;
	struct sockaddr_in rem_in;
	struct hostent *hent;

	/* This is already implied ... */
	hdr4.vn = SOCKS4_VN;

	ret = -1;

	/* Get the seven first bytes after version, until USERID */
	if (atomicio(read, clisock, &hdr4.cd, 7) != 7)
		return (-1);

	switch (hdr4.cd) {
	case SOCKS4_CD_CONNECT:
	case SOCKS4_CD_RESOLVE:
		/* We can only do connect & resolve. */
		break;
	default:
		warnxv(0, "Client attempted unsupported SOCKS4 command %d",
		    hdr4.cd);
		return (-1);
	};

	/* Eat the username; it is not used */
	while ((ret = atomicio(read, clisock, &data, 1)) == 1 && data != 0);

	if (ret != 1)
		return (-1);

	memset(&rem_in, 0, sizeof(rem_in));
	rem_in.sin_family = AF_INET;
	rem_in.sin_port = hdr4.destport;

    	addr = (unsigned char *)&hdr4.destaddr;
    	/* SOCKS4A or tor-resolve? */
 	if ((addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] != 0)
	    || (hdr4.cd == SOCKS4_CD_RESOLVE && hdr4.destport == 0)) {
		if (_getstr(clisock, hostname, sizeof(hostname)) < 0)
			return (-1);

		if ((hent = gethostbyname(hostname)) == NULL) {
			hdr4.cd = SOCKS4_REP_REJECT;
		} else {
			rem_in.sin_addr = *(struct in_addr *)hent->h_addr;
			/*
			 * Send back the resolved address as well, for
			 * tor-resolve.
			 */
			hdr4.destaddr = rem_in.sin_addr.s_addr;
		}
	} else {
		rem_in.sin_addr.s_addr = hdr4.destaddr;
	}

 	return (_socks4_tryconnect(clisock, &rem_in, &hdr4, conn));
}