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

📄 proxy.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	    /* get the response */	    bufchain_fetch(&p->pending_input_data, data, 2);	    if (data[0] != 1) {		plug_closing(p->plug, "Proxy error: SOCKS password "			     "subnegotiation contained wrong version number",			     PROXY_ERROR_GENERAL, 0);		return 1;	    }	    if (data[1] != 0) {		plug_closing(p->plug, "Proxy error: SOCKS proxy refused"			     " password authentication",			     PROXY_ERROR_GENERAL, 0);		return 1;	    }	    bufchain_consume(&p->pending_input_data, 2);	    p->state = 2;	       /* now proceed as authenticated */	}	if (p->state == 8) {	    int ret;	    ret = proxy_socks5_handlechap(p);	    if (ret) return ret;	}	if (p->state == 2) {	    /* request format:	     *  version number (1 byte) = 5	     *  command code (1 byte)	     *    1 = CONNECT	     *    2 = BIND	     *    3 = UDP ASSOCIATE	     *  reserved (1 byte) = 0x00	     *  address type (1 byte)	     *    1 = IPv4	     *    3 = domainname (first byte has length, no terminating null)	     *    4 = IPv6	     *  dest. address (variable)	     *  dest. port (2 bytes) [network order]	     */	    char command[512];	    int len;	    int type;	    type = sk_addrtype(p->remote_addr);	    if (type == ADDRTYPE_IPV4) {		len = 10;	       /* 4 hdr + 4 addr + 2 trailer */		command[3] = 1; /* IPv4 */		sk_addrcopy(p->remote_addr, command+4);	    } else if (type == ADDRTYPE_IPV6) {		len = 22;	       /* 4 hdr + 16 addr + 2 trailer */		command[3] = 4; /* IPv6 */		sk_addrcopy(p->remote_addr, command+4);	    } else {		assert(type == ADDRTYPE_NAME);		command[3] = 3;		sk_getaddr(p->remote_addr, command+5, 256);		command[4] = strlen(command+5);		len = 7 + command[4];  /* 4 hdr, 1 len, N addr, 2 trailer */	    }	    command[0] = 5; /* version 5 */	    command[1] = 1; /* CONNECT command */	    command[2] = 0x00;	    /* port */	    command[len-2] = (char) (p->remote_port >> 8) & 0xff;	    command[len-1] = (char) p->remote_port & 0xff;	    sk_write(p->sub_socket, command, len);	    p->state = 3;	    return 1;	}	if (p->state == 3) {	    /* reply format:	     *  version number (1 bytes) = 5	     *  reply code (1 byte)	     *    0 = succeeded	     *    1 = general SOCKS server failure	     *    2 = connection not allowed by ruleset	     *    3 = network unreachable	     *    4 = host unreachable	     *    5 = connection refused	     *    6 = TTL expired	     *    7 = command not supported	     *    8 = address type not supported	     * reserved (1 byte) = x00	     * address type (1 byte)	     *    1 = IPv4	     *    3 = domainname (first byte has length, no terminating null)	     *    4 = IPv6	     * server bound address (variable)	     * server bound port (2 bytes) [network order]	     */	    char data[5];	    int len;	    /* First 5 bytes of packet are enough to tell its length. */ 	    if (bufchain_size(&p->pending_input_data) < 5)		return 1;	       /* not got anything yet */	    /* get the response */	    bufchain_fetch(&p->pending_input_data, data, 5);	    if (data[0] != 5) {		plug_closing(p->plug, "Proxy error: SOCKS proxy returned wrong version number",			     PROXY_ERROR_GENERAL, 0);		return 1;	    }	    if (data[1] != 0) {		char buf[256];		strcpy(buf, "Proxy error: ");		switch (data[1]) {		  case 1: strcat(buf, "General SOCKS server failure"); break;		  case 2: strcat(buf, "Connection not allowed by ruleset"); break;		  case 3: strcat(buf, "Network unreachable"); break;		  case 4: strcat(buf, "Host unreachable"); break;		  case 5: strcat(buf, "Connection refused"); break;		  case 6: strcat(buf, "TTL expired"); break;		  case 7: strcat(buf, "Command not supported"); break;		  case 8: strcat(buf, "Address type not supported"); break;		  default: sprintf(buf+strlen(buf),				   "Unrecognised SOCKS error code %d",				   data[1]);		    break;		}		plug_closing(p->plug, buf, PROXY_ERROR_GENERAL, 0);		return 1;	    }	    /*	     * Eat the rest of the reply packet.	     */	    len = 6;		       /* first 4 bytes, last 2 */	    switch (data[3]) {	      case 1: len += 4; break; /* IPv4 address */	      case 4: len += 16; break;/* IPv6 address */	      case 3: len += (unsigned char)data[4]; break; /* domain name */	      default:		plug_closing(p->plug, "Proxy error: SOCKS proxy returned "			     "unrecognised address format",			     PROXY_ERROR_GENERAL, 0);		return 1;	    }	    if (bufchain_size(&p->pending_input_data) < len)		return 1;	       /* not got whole reply yet */	    bufchain_consume(&p->pending_input_data, len);	    /* we're done */	    proxy_activate(p);	    return 1;	}	if (p->state == 4) {	    /* TODO: Handle GSSAPI authentication */	    plug_closing(p->plug, "Proxy error: We don't support GSSAPI authentication",			 PROXY_ERROR_GENERAL, 0);	    return 1;	}	if (p->state == 5) {	    if (p->cfg.proxy_username[0] || p->cfg.proxy_password[0]) {		char userpwbuf[514];		int ulen, plen;		ulen = strlen(p->cfg.proxy_username);		if (ulen > 255) ulen = 255; if (ulen < 1) ulen = 1;		plen = strlen(p->cfg.proxy_password);		if (plen > 255) plen = 255; if (plen < 1) plen = 1;		userpwbuf[0] = 1;      /* version number of subnegotiation */		userpwbuf[1] = ulen;		memcpy(userpwbuf+2, p->cfg.proxy_username, ulen);		userpwbuf[ulen+2] = plen;		memcpy(userpwbuf+ulen+3, p->cfg.proxy_password, plen);		sk_write(p->sub_socket, userpwbuf, ulen + plen + 3);		p->state = 7;	    } else 		plug_closing(p->plug, "Proxy error: Server chose "			     "username/password authentication but we "			     "didn't offer it!",			 PROXY_ERROR_GENERAL, 0);	    return 1;	}	if (p->state == 6) {	    int ret;	    ret = proxy_socks5_selectchap(p);	    if (ret) return ret;	}    }    plug_closing(p->plug, "Proxy error: Unexpected proxy error",		 PROXY_ERROR_UNEXPECTED, 0);    return 1;}/* ---------------------------------------------------------------------- * `Telnet' proxy type. * * (This is for ad-hoc proxies where you connect to the proxy's * telnet port and send a command such as `connect host port'. The * command is configurable, since this proxy type is typically not * standardised or at all well-defined.) */char *format_telnet_command(SockAddr addr, int port, const Config *cfg){    char *ret = NULL;    int retlen = 0, retsize = 0;    int so = 0, eo = 0;#define ENSURE(n) do { \    if (retsize < retlen + n) { \	retsize = retlen + n + 512; \	ret = sresize(ret, retsize, char); \    } \} while (0)    /* we need to escape \\, \%, \r, \n, \t, \x??, \0???,      * %%, %host, %port, %user, and %pass     */    while (cfg->proxy_telnet_command[eo] != 0) {	/* scan forward until we hit end-of-line,	 * or an escape character (\ or %) */	while (cfg->proxy_telnet_command[eo] != 0 &&	       cfg->proxy_telnet_command[eo] != '%' &&	       cfg->proxy_telnet_command[eo] != '\\') eo++;	/* if we hit eol, break out of our escaping loop */	if (cfg->proxy_telnet_command[eo] == 0) break;	/* if there was any unescaped text before the escape	 * character, send that now */	if (eo != so) {	    ENSURE(eo - so);	    memcpy(ret + retlen, cfg->proxy_telnet_command + so, eo - so);	    retlen += eo - so;	}	so = eo++;	/* if the escape character was the last character of	 * the line, we'll just stop and send it. */	if (cfg->proxy_telnet_command[eo] == 0) break;	if (cfg->proxy_telnet_command[so] == '\\') {	    /* we recognize \\, \%, \r, \n, \t, \x??.	     * anything else, we just send unescaped (including the \).	     */	    switch (cfg->proxy_telnet_command[eo]) {	      case '\\':		ENSURE(1);		ret[retlen++] = '\\';		eo++;		break;	      case '%':		ENSURE(1);		ret[retlen++] = '%';		eo++;		break;	      case 'r':		ENSURE(1);		ret[retlen++] = '\r';		eo++;		break;	      case 'n':		ENSURE(1);		ret[retlen++] = '\n';		eo++;		break;	      case 't':		ENSURE(1);		ret[retlen++] = '\t';		eo++;		break;	      case 'x':	      case 'X':		{		    /* escaped hexadecimal value (ie. \xff) */		    unsigned char v = 0;		    int i = 0;		    for (;;) {			eo++;			if (cfg->proxy_telnet_command[eo] >= '0' &&			    cfg->proxy_telnet_command[eo] <= '9')			    v += cfg->proxy_telnet_command[eo] - '0';			else if (cfg->proxy_telnet_command[eo] >= 'a' &&				 cfg->proxy_telnet_command[eo] <= 'f')			    v += cfg->proxy_telnet_command[eo] - 'a' + 10;			else if (cfg->proxy_telnet_command[eo] >= 'A' &&				 cfg->proxy_telnet_command[eo] <= 'F')			    v += cfg->proxy_telnet_command[eo] - 'A' + 10;			else {			    /* non hex character, so we abort and just			     * send the whole thing unescaped (including \x)			     */			    ENSURE(1);			    ret[retlen++] = '\\';			    eo = so + 1;			    break;			}			/* we only extract two hex characters */			if (i == 1) {			    ENSURE(1);			    ret[retlen++] = v;			    eo++;			    break;			}			i++;			v <<= 4;		    }		}		break;	      default:		ENSURE(2);		memcpy(ret+retlen, cfg->proxy_telnet_command + so, 2);		retlen += 2;		eo++;		break;	    }	} else {	    /* % escape. we recognize %%, %host, %port, %user, %pass.	     * anything else, we just send unescaped (including the %).	     */	    if (cfg->proxy_telnet_command[eo] == '%') {		ENSURE(1);		ret[retlen++] = '%';		eo++;	    }	    else if (strnicmp(cfg->proxy_telnet_command + eo,			      "host", 4) == 0) {		char dest[512];		int destlen;		sk_getaddr(addr, dest, lenof(dest));		destlen = strlen(dest);		ENSURE(destlen);		memcpy(ret+retlen, dest, destlen);		retlen += destlen;		eo += 4;	    }	    else if (strnicmp(cfg->proxy_telnet_command + eo,			      "port", 4) == 0) {		char portstr[8], portlen;		portlen = sprintf(portstr, "%i", port);		ENSURE(portlen);		memcpy(ret + retlen, portstr, portlen);		retlen += portlen;		eo += 4;	    }	    else if (strnicmp(cfg->proxy_telnet_command + eo,			      "user", 4) == 0) {		int userlen = strlen(cfg->proxy_username);		ENSURE(userlen);		memcpy(ret+retlen, cfg->proxy_username, userlen);		retlen += userlen;		eo += 4;	    }	    else if (strnicmp(cfg->proxy_telnet_command + eo,			      "pass", 4) == 0) {		int passlen = strlen(cfg->proxy_password);		ENSURE(passlen);		memcpy(ret+retlen, cfg->proxy_password, passlen);		retlen += passlen;		eo += 4;	    }	    else {		/* we don't escape this, so send the % now, and		 * don't advance eo, so that we'll consider the		 * text immediately following the % as unescaped.		 */		ENSURE(1);		ret[retlen++] = '%';	    }	}	/* resume scanning for additional escapes after this one. */	so = eo;    }    /* if there is any unescaped text at the end of the line, send it */    if (eo != so) {	ENSURE(eo - so);	memcpy(ret + retlen, cfg->proxy_telnet_command + so, eo - so);	retlen += eo - so;    }    ENSURE(1);    ret[retlen] = '\0';    return ret;#undef ENSURE}int proxy_telnet_negotiate (Proxy_Socket p, int change){    if (p->state == PROXY_CHANGE_NEW) {	char *formatted_cmd;	formatted_cmd = format_telnet_command(p->remote_addr, p->remote_port,					      &p->cfg);	sk_write(p->sub_socket, formatted_cmd, strlen(formatted_cmd));	sfree(formatted_cmd);	p->state = 1;	return 0;    }    if (change == PROXY_CHANGE_CLOSING) {	/* if our proxy negotiation process involves closing and opening	 * new sockets, then we would want to intercept this closing	 * callback when we were expecting it. if we aren't anticipating	 * a socket close, then some error must have occurred. we'll	 * just pass those errors up to the backend.	 */	return plug_closing(p->plug, p->closing_error_msg,			    p->closing_error_code,			    p->closing_calling_back);    }    if (change == PROXY_CHANGE_SENT) {	/* some (or all) of what we wrote to the proxy was sent.	 * we don't do anything new, however, until we receive the	 * proxy's response. we might want to set a timer so we can	 * timeout the proxy negotiation after a while...	 */	return 0;    }    if (change == PROXY_CHANGE_ACCEPTING) {	/* we should _never_ see this, as we are using our socket to	 * connect to a proxy, not accepting inbound connections.	 * what should we do? close the socket with an appropriate	 * error message?	 */	return plug_accepting(p->plug, p->accepting_sock);    }    if (change == PROXY_CHANGE_RECEIVE) {	/* we have received data from the underlying socket, which	 * we'll need to parse, process, and respond to appropriately.	 */	/* we're done */	proxy_activate(p);	/* proxy activate will have dealt with	 * whatever is left of the buffer */	return 1;    }    plug_closing(p->plug, "Proxy error: Unexpected proxy error",		 PROXY_ERROR_UNEXPECTED, 0);    return 1;}

⌨️ 快捷键说明

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