⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockd_protocol.c

📁 sock protocol ,it is useful!
💻 C
字号:
/* * Copyright (c) 1997, 1998, 1999 *      Inferno Nettverk A/S, Norway.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. The above copyright notice, this list of conditions and the following *    disclaimer must appear in all copies of the software, derivative works *    or modified versions, and any portions thereof, aswell as in all *    supporting documentation. * 2. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by *      Inferno Nettverk A/S, Norway. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Inferno Nettverk A/S requests users of this software to return to * *  Software Distribution Coordinator  or  sdc@inet.no *  Inferno Nettverk A/S *  Oslo Research Park *  Gaustadal閑n 21 *  N-0349 Oslo *  Norway * * any improvements or extensions that they make and grant Inferno Nettverk A/S * the rights to redistribute these changes. * */#include "common.h"static const char rcsid[] ="$Id: sockd_protocol.c,v 1.79 1999/12/12 18:13:56 michaels Exp $";__BEGIN_DECLSstatic intrecv_v4req __P((int s, struct request_t *request,					 struct negotiate_state_t *state));static intrecv_v5req __P((int s, struct request_t *request,					 struct negotiate_state_t *state));static intrecv_methods __P((int s, struct request_t *request,						struct negotiate_state_t *state));static intrecv_ver __P((int s, struct request_t *request,				  struct negotiate_state_t *state));static intrecv_cmd __P((int s, struct request_t *request,				  struct negotiate_state_t *state));static intrecv_flag __P((int s, struct request_t *request,					struct negotiate_state_t *state));static intrecv_sockshost __P((int s, struct request_t *request,						  struct negotiate_state_t *state));static intrecv_atyp __P((int s, struct request_t *request,					struct negotiate_state_t *state));static intrecv_port __P((int s, struct request_t *request,					struct negotiate_state_t *state));static intrecv_address __P((int s, struct request_t *request,					   struct negotiate_state_t *state));static intrecv_domain __P((int s, struct request_t *request,					  struct negotiate_state_t *state));static intrecv_username __P((int s, struct request_t *request,						 struct negotiate_state_t *state));static intmethodnegotiate __P((int s, struct request_t *request,							struct negotiate_state_t *state));__END_DECLSintrecv_request(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	int rc;	if (state->complete)		return 1;	if (state->rcurrent != NULL)	/* not first call on this client. */		rc = state->rcurrent(s, request, state);	else {		INIT(sizeof(request->version));		CHECK(&request->version, NULL);		switch (request->version) {			case SOCKS_V4:				state->rcurrent = recv_v4req;				break;			case SOCKS_V5:				state->rcurrent = recv_v5req;				break;			default:				slog(LOG_DEBUG, "unknown version %d in request", request->version);				return -1;		}		rc = state->rcurrent(s, request, state);	}	state->complete = rc > 0; /* complete request read? */	return rc;}intrecv_sockspacket(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	return recv_ver(s, request, state);}static intrecv_v4req (s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	/*	 * v4 request:	 * VN   CD   DSTPORT  DSTIP  USERID   NUL	 * 1  + 1  +  2     +  4   +  ?     +  1	 *	 * so minimum length is 9.    */	/* CD */	state->rcurrent = recv_cmd;	return state->rcurrent(s, request, state);}static intrecv_v5req (s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	/*	 * method negotiation;	 *		client first sends method selection message:	 *	 *	+----+----------+----------+	 *	|VER | NMETHODS | METHODS  |	 *	+----+----------+----------+	 *	| 1  |    1     | 1 to 255 |	 *	+----+----------+----------+	 */	/*	 * then the request:	 *	 *	+----+-----+-------+------+----------+----------+	 *	|VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |	 *	+----+-----+-------+------+----------+----------+	 *	| 1  |  1  | X'00' |  1   | Variable |    2     |	 *	+----+-----+-------+------+----------+----------+	 *	 *	  1     1      1      1        ?          2	 *	 * Since the request can contain different address types	 * we do not know how long the request is before we have	 * read the address type (ATYP) field.	 *	 */	/* NMETHODS */	INIT(sizeof(char));	CHECK(&state->mem[start], NULL);	OCTETIFY(state->mem[start]);	state->rcurrent = recv_methods;	return state->rcurrent(s, request, state);}static intrecv_methods(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	const char *function = "recv_methods()";	const unsigned char methodc = state->mem[state->reqread - 1];	/* NMETHODS */	char reply[ 1 /* VERSION	*/				 + 1 /* METHOD		*/				 ];	INIT(methodc);	CHECK(&state->mem[start], NULL);	request->auth->method = selectmethod(&state->mem[start], (size_t)methodc);	/* send reply:	 *	 *	+----+--------+	 *	|VER | METHOD |	 *	+----+--------+	 *	| 1  |   1    |	 *	+----+--------+    */	slog(LOG_DEBUG, "%s: sending authentication reply: VER: %d METHOD: %d",	function, request->version, request->auth->method);	reply[AUTH_VERSION]	= request->version;	reply[AUTH_METHOD]	= (char)request->auth->method;	if (writen(s, reply, sizeof(reply)) != sizeof(reply))		return -1;	if (request->auth->method == AUTHMETHOD_NOACCEPT)		return -1;	state->rcurrent = methodnegotiate;	return state->rcurrent(s, request, state);}static intmethodnegotiate(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	/* authentication method dependent negotiation */	switch (request->auth->method) {		case AUTHMETHOD_NONE:			state->rcurrent = recv_sockspacket;			break;		case AUTHMETHOD_UNAME:			state->rcurrent = method_uname;			break;		default:			SERRX(request->auth->method);	}	return state->rcurrent(s, request, state);}static intrecv_ver(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	/* VER */	{		INIT(sizeof(request->version));		CHECK(&request->version, NULL);		switch (request->version) {			case SOCKS_V4:			case SOCKS_V5:				break;			default:				slog(LOG_DEBUG, "unknown version %d in request", request->version);				return -1;		}	}	state->rcurrent = recv_cmd;	return state->rcurrent(s, request, state);}static intrecv_cmd(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	INIT(sizeof(request->command));	CHECK(&request->command, NULL);	switch (request->version) {		case SOCKS_V4:			state->rcurrent = recv_sockshost;			break;		case SOCKS_V5:			state->rcurrent = recv_flag;			break;		default:			SERRX(request->version);	}	return state->rcurrent(s, request, state);}static intrecv_flag(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	INIT(sizeof(request->flag));	CHECK(&request->flag, recv_sockshost);	SERRX(0); /* NOTREACHED */}static intrecv_sockshost(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	switch (request->version) {		case SOCKS_V4:			state->rcurrent = recv_port;			break;		case SOCKS_V5:			state->rcurrent = recv_atyp;			break;		default:			SERRX(request->version);	}	return state->rcurrent(s, request, state);}static intrecv_atyp(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	INIT(sizeof(request->host.atype));	CHECK(&request->host.atype, recv_address);	SERRX(0); /* NOTREACHED */}static intrecv_address(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	switch (request->version) {		case SOCKS_V4: {			INIT(sizeof(request->host.addr.ipv4));			request->host.atype = SOCKS_ADDR_IPV4; /* only one supported in v4. */			CHECK(&request->host.addr.ipv4, recv_username);			SERRX(0); /* NOTREACHED */		}		case SOCKS_V5:			switch(request->host.atype) {				case SOCKS_ADDR_IPV4: {					INIT(sizeof(request->host.addr.ipv4));					CHECK(&request->host.addr.ipv4, recv_port);					SERRX(0); /* NOTREACHED */				}				case SOCKS_ADDR_IPV6: {					INIT(sizeof(request->host.addr.ipv6));					CHECK(&request->host.addr.ipv6, recv_port);					SERRX(0); /* NOTREACHED */				}				case SOCKS_ADDR_DOMAIN: {					INIT(sizeof(*request->host.addr.domain));					CHECK(request->host.addr.domain, NULL);					OCTETIFY(*request->host.addr.domain);					state->rcurrent = recv_domain;					return state->rcurrent(s, request, state);				}				default:					slog(LOG_DEBUG, "unknown address format %d in reply",					request->host.atype);					return -1;			}		default:			SERRX(request->version);	}	SERRX(0); /* NOTREACHED */}static intrecv_domain(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	size_t alen;	INIT(*request->host.addr.domain);	/* first byte gives length. */	CHECK(request->host.addr.domain + 1, NULL);	alen = (size_t)*request->host.addr.domain;	/* convert to C string. */	memmove(request->host.addr.domain, request->host.addr.domain + 1, alen);	request->host.addr.domain[alen] = NUL;	state->rcurrent = recv_port;	return state->rcurrent(s, request, state);}static intrecv_port(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	INIT(sizeof(request->host.port));	CHECK(&request->host.port, NULL);	switch (request->version) {		case SOCKS_V4:			state->rcurrent = recv_address;	/* in v4, address after port. */			return state->rcurrent(s, request, state);		case SOCKS_V5:			return 1;	/* all done. */		default:			SERRX(request->version);	}	SERRX(0); /* NOTREACHED */}static intrecv_username(s, request, state)	int s;	struct request_t *request;	struct negotiate_state_t *state;{	const char *function = "recv_username()";	char *username = &state->mem[sizeof(request->version)										+ sizeof(request->command)										+ sizeof(request->host.port)										+ sizeof(request->host.addr.ipv4)];	/* read until 0. */	do {		INIT(MIN(1, MEMLEFT()));		if (MEMLEFT() == 0) {			/*			 * Normally this would indicate an internal error and thus			 * be caught in CHECK(), but for the v4 case it could be			 * someone sending a really long username, which is strange			 * enough to log a warning about but not an internal error.			 */			state->mem[state->reqread - 1] = NUL;			slog(LOG_WARNING, "%s: too long username (> %d): \"%s\"",			function, strlen(username),			strcheck(username = str2vis(username, strlen(username))));			free(username);			return -1;		}		CHECK(&state->mem[start], NULL);	} while (state->mem[state->reqread - 1] != 0);	state->mem[state->reqread - 1] = NUL;	/* style. */	slog(LOG_DEBUG, "%s: got socks v4 username: %s",	function, strcheck(username = str2vis(username, strlen(username))));	free(username);	return 1;	/* end of request. */}voidsend_failure(s, response, failure)	int s;	const struct response_t *response;	int failure;{	struct response_t newresponse;	/* keep const. */	newresponse = *response;	newresponse.reply = (char)sockscode(newresponse.version, failure);	send_response(s, &newresponse);}intsend_response(s, response)	int s;	const struct response_t *response;{	const char *function = "send_response()";	size_t length;	char responsemem[sizeof(*response)];	char *p = responsemem;	switch (response->version) {		case SOCKS_V4REPLY_VERSION:			/*			 * socks V4 reply packet:			 *			 *  VN   CD  DSTPORT  DSTIP			 *  1  + 1  +  2    +  4			 *			 *  Always 8 octets long.			 */			memcpy(p, &response->version, sizeof(response->version));			p += sizeof(response->version);			/* CD (reply) */			memcpy(p, &response->reply, sizeof(response->reply));			p += sizeof(response->reply);			break;		case SOCKS_V5:			/*			 * socks V5 reply:			 *			 * +----+-----+-------+------+----------+----------+			 * |VER | REP |  FLAG | ATYP | BND.ADDR | BND.PORT |			 * +----+-----+-------+------+----------+----------+			 * | 1  |  1  |   1   |  1   | Variable |    2     |			 * +----+-----+-------+------+----------+----------+			 *   1     1      1      1                   2			 *			 * Which gives a fixed size of atleast 6 octets.			 * The first octet of DST.ADDR when it is SOCKS_ADDR_DOMAINNAME			 * contains the length.			 *			 */			/* VER */			memcpy(p, &response->version, sizeof(response->version));			p += sizeof(response->version);			/* REP */			memcpy(p, &response->reply, sizeof(response->reply));			p += sizeof(response->reply);			/* FLAG */			memcpy(p, &response->flag, sizeof(response->flag));			p += sizeof(response->flag);			break;		default:			SERRX(response->version);	}	p = sockshost2mem(&response->host, p, response->version);	length = p - responsemem;	slog(LOG_DEBUG, "%s: sending response: %s",	function, socks_packet2string(response, SOCKS_RESPONSE));	if (writen(s, responsemem, length) != (ssize_t)length) {		swarn("%s: writen()", function);		return -1;	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -