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

📄 proxy.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	    off++;	    /* is that the only thing on this line? */	    if (off <= 2) return off;	    /* if not, then there is the possibility that this header	     * continues onto the next line, if it starts with a space	     * or a tab.	     */	    if (off + 1 < len &&		data[off+1] != ' ' &&		data[off+1] != '\t') return off;	    /* the line does continue, so we have to keep going	     * until we see an the header's "real" end of line.	     */	    off++;	}	off++;    }    return -1;}int proxy_http_negotiate (Proxy_Socket p, int change){    if (p->state == PROXY_STATE_NEW) {	/* we are just beginning the proxy negotiate process,	 * so we'll send off the initial bits of the request.	 * for this proxy method, it's just a simple HTTP	 * request	 */	char *buf, dest[512];	sk_getaddr(p->remote_addr, dest, lenof(dest));	buf = dupprintf("CONNECT %s:%i HTTP/1.1\r\nHost: %s:%i\r\n",			dest, p->remote_port, dest, p->remote_port);	sk_write(p->sub_socket, buf, strlen(buf));	sfree(buf);	if (p->cfg.proxy_username[0] || p->cfg.proxy_password[0]) {	    char buf[sizeof(p->cfg.proxy_username)+sizeof(p->cfg.proxy_password)];	    char buf2[sizeof(buf)*4/3 + 100];	    int i, j, len;	    sprintf(buf, "%s:%s", p->cfg.proxy_username, p->cfg.proxy_password);	    len = strlen(buf);	    sprintf(buf2, "Proxy-Authorization: Basic ");	    for (i = 0, j = strlen(buf2); i < len; i += 3, j += 4)		base64_encode_atom((unsigned char *)(buf+i),				   (len-i > 3 ? 3 : len-i), buf2+j);	    strcpy(buf2+j, "\r\n");	    sk_write(p->sub_socket, buf2, strlen(buf2));	}	sk_write(p->sub_socket, "\r\n", 2);	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.	 */	char *data, *datap;	int len;	int eol;	if (p->state == 1) {	    int min_ver, maj_ver, status;	    /* get the status line */	    len = bufchain_size(&p->pending_input_data);	    assert(len > 0);	       /* or we wouldn't be here */	    data = snewn(len+1, char);	    bufchain_fetch(&p->pending_input_data, data, len);	    /*	     * We must NUL-terminate this data, because Windows	     * sscanf appears to require a NUL at the end of the	     * string because it strlens it _first_. Sigh.	     */	    data[len] = '\0';	    eol = get_line_end(data, len);	    if (eol < 0) {		sfree(data);		return 1;	    }	    status = -1;	    /* We can't rely on whether the %n incremented the sscanf return */	    if (sscanf((char *)data, "HTTP/%i.%i %n",		       &maj_ver, &min_ver, &status) < 2 || status == -1) {		plug_closing(p->plug, "Proxy error: HTTP response was absent",			     PROXY_ERROR_GENERAL, 0);		sfree(data);		return 1;	    }	    /* remove the status line from the input buffer. */	    bufchain_consume(&p->pending_input_data, eol);	    if (data[status] != '2') {		/* error */		char *buf;		data[eol] = '\0';		while (eol > status &&		       (data[eol-1] == '\r' || data[eol-1] == '\n'))		    data[--eol] = '\0';		buf = dupprintf("Proxy error: %s", data+status);		plug_closing(p->plug, buf, PROXY_ERROR_GENERAL, 0);		sfree(buf);		sfree(data);		return 1;	    }	    sfree(data);	    p->state = 2;	}	if (p->state == 2) {	    /* get headers. we're done when we get a	     * header of length 2, (ie. just "\r\n")	     */	    len = bufchain_size(&p->pending_input_data);	    assert(len > 0);	       /* or we wouldn't be here */	    data = snewn(len, char);	    datap = data;	    bufchain_fetch(&p->pending_input_data, data, len);	    eol = get_line_end(datap, len);	    if (eol < 0) {		sfree(data);		return 1;	    }	    while (eol > 2)	    {		bufchain_consume(&p->pending_input_data, eol);		datap += eol;		len   -= eol;		eol = get_line_end(datap, len);	    }	    if (eol == 2) {		/* we're done */		bufchain_consume(&p->pending_input_data, 2);		proxy_activate(p);		/* proxy activate will have dealt with		 * whatever is left of the buffer */		sfree(data);		return 1;	    }	    sfree(data);	    return 1;	}    }    plug_closing(p->plug, "Proxy error: unexpected proxy error",		 PROXY_ERROR_UNEXPECTED, 0);    return 1;}/* ---------------------------------------------------------------------- * SOCKS proxy type. *//* SOCKS version 4 */int proxy_socks4_negotiate (Proxy_Socket p, int change){    if (p->state == PROXY_CHANGE_NEW) {	/* request format:	 *  version number (1 byte) = 4	 *  command code (1 byte)	 *    1 = CONNECT	 *    2 = BIND	 *  dest. port (2 bytes) [network order]	 *  dest. address (4 bytes)	 *  user ID (variable length, null terminated string)	 */	int length, type, namelen;	char *command, addr[4], hostname[512];	type = sk_addrtype(p->remote_addr);	if (type == ADDRTYPE_IPV6) {	    plug_closing(p->plug, "Proxy error: SOCKS version 4 does"			 " not support IPv6", PROXY_ERROR_GENERAL, 0);	    return 1;	} else if (type == ADDRTYPE_IPV4) {	    namelen = 0;	    sk_addrcopy(p->remote_addr, addr);	} else {		       /* type == ADDRTYPE_NAME */	    assert(type == ADDRTYPE_NAME);	    sk_getaddr(p->remote_addr, hostname, lenof(hostname));	    namelen = strlen(hostname) + 1;   /* include the NUL */	    addr[0] = addr[1] = addr[2] = 0;	    addr[3] = 1;	}	length = strlen(p->cfg.proxy_username) + namelen + 9;	command = snewn(length, char);	strcpy(command + 8, p->cfg.proxy_username);	command[0] = 4; /* version 4 */	command[1] = 1; /* CONNECT command */	/* port */	command[2] = (char) (p->remote_port >> 8) & 0xff;	command[3] = (char) p->remote_port & 0xff;	/* address */	memcpy(command + 4, addr, 4);	/* hostname */	memcpy(command + 8 + strlen(p->cfg.proxy_username) + 1,	       hostname, namelen);	sk_write(p->sub_socket, command, length);	sfree(command);	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.	 */	if (p->state == 1) {	    /* response format:	     *  version number (1 byte) = 4	     *  reply code (1 byte)	     *    90 = request granted	     *    91 = request rejected or failed	     *    92 = request rejected due to lack of IDENTD on client	     *    93 = request rejected due to difference in user ID 	     *         (what we sent vs. what IDENTD said)	     *  dest. port (2 bytes)	     *  dest. address (4 bytes)	     */	    char data[8];	    if (bufchain_size(&p->pending_input_data) < 8)		return 1;	       /* not got anything yet */	    	    /* get the response */	    bufchain_fetch(&p->pending_input_data, data, 8);	    if (data[0] != 0) {		plug_closing(p->plug, "Proxy error: SOCKS proxy responded with "				      "unexpected reply code version",			     PROXY_ERROR_GENERAL, 0);		return 1;	    }	    if (data[1] != 90) {		switch (data[1]) {		  case 92:		    plug_closing(p->plug, "Proxy error: SOCKS server wanted IDENTD on client",				 PROXY_ERROR_GENERAL, 0);		    break;		  case 93:		    plug_closing(p->plug, "Proxy error: Username and IDENTD on client don't agree",				 PROXY_ERROR_GENERAL, 0);		    break;		  case 91:		  default:		    plug_closing(p->plug, "Proxy error: Error while communicating with proxy",				 PROXY_ERROR_GENERAL, 0);		    break;		}		return 1;	    }	    bufchain_consume(&p->pending_input_data, 8);	    /* 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;}/* SOCKS version 5 */int proxy_socks5_negotiate (Proxy_Socket p, int change){    if (p->state == PROXY_CHANGE_NEW) {	/* initial command:	 *  version number (1 byte) = 5	 *  number of available authentication methods (1 byte)	 *  available authentication methods (1 byte * previous value)	 *    authentication methods:	 *     0x00 = no authentication	 *     0x01 = GSSAPI	 *     0x02 = username/password	 *     0x03 = CHAP	 */	char command[5];	int len;	command[0] = 5; /* version 5 */	if (p->cfg.proxy_username[0] || p->cfg.proxy_password[0]) {	    command[2] = 0x00;	       /* no authentication */	    len = 3;	    proxy_socks5_offerencryptedauth (command, &len);	    command[len++] = 0x02;	       /* username/password */	    command[1] = len - 2;	/* Number of methods supported */	} else {	    command[1] = 1;	       /* one methods supported: */	    command[2] = 0x00;	       /* no authentication */	    len = 3;	}	sk_write(p->sub_socket, command, len);	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.	 */	if (p->state == 1) {	    /* initial response:	     *  version number (1 byte) = 5	     *  authentication method (1 byte)	     *    authentication methods:	     *     0x00 = no authentication	     *     0x01 = GSSAPI	     *     0x02 = username/password	     *     0x03 = CHAP	     *     0xff = no acceptable methods	     */	    char data[2];	    if (bufchain_size(&p->pending_input_data) < 2)		return 1;	       /* not got anything yet */	    /* get the response */	    bufchain_fetch(&p->pending_input_data, data, 2);	    if (data[0] != 5) {		plug_closing(p->plug, "Proxy error: SOCKS proxy returned unexpected version",			     PROXY_ERROR_GENERAL, 0);		return 1;	    }	    if (data[1] == 0x00) p->state = 2; /* no authentication needed */	    else if (data[1] == 0x01) p->state = 4; /* GSSAPI authentication */	    else if (data[1] == 0x02) p->state = 5; /* username/password authentication */	    else if (data[1] == 0x03) p->state = 6; /* CHAP authentication */	    else {		plug_closing(p->plug, "Proxy error: SOCKS proxy did not accept our authentication",			     PROXY_ERROR_GENERAL, 0);		return 1;	    }	    bufchain_consume(&p->pending_input_data, 2);	}	if (p->state == 7) {	    /* password authentication reply format:	     *  version number (1 bytes) = 1	     *  reply code (1 byte)	     *    0 = succeeded	     *    >0 = failed	     */	    char data[2];	    if (bufchain_size(&p->pending_input_data) < 2)		return 1;	       /* not got anything yet */

⌨️ 快捷键说明

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