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

📄 proxy.c

📁 dtelent是开源的开发项目
💻 C
📖 第 1 页 / 共 2 页
字号:
/* proxy.c
 * 2001-10-27 Enrique Grandes
 * Manage Proxy protocols and Proxy dialog
 */
#include <windows.h>
#include <stdio.h>
#include <string.h>

#include "resource.h"
#include "proxy.h"
#include "socksdef.h"
#include "utils.h"
#include "dtelnet.h"
#include "term.h"
#include "dialog.h"
#include "socket.h"

#define HOSTNAME_LEN 	128
#define USERNAME_LEN 	24
#define PASSWORD_LEN 	24
#define PORT_LEN 	6

/* Protocol state handler
 */
typedef int (StateHandler)(void);

/* dialog variables
 */
typedef enum {
    PP_DISABLED,    /* Direct connection */
    PP_SOCKS4,	    /* SOCKS v4 */
    PP_SOCKS4A,	    /* SOCKS v4 with A Extension */
    PP_SOCKS5,	    /* SOCKS v5 */
    PP_HTTP	    /* HTTP Proxy */
} ProxyProtocol;

typedef struct {
    ProxyProtocol protocol;	  /* protocol */
    char host[HOSTNAME_LEN];      /* proxy server address */
    char username[USERNAME_LEN];  /* username */
    char password[PASSWORD_LEN];  /* password */
    char port[PORT_LEN]; 	  /* proxy server port */
} Proxy;

/* Protocol strings
 */
static char disabledStr[]  = "Disabled";
static char socks4Str[]    = "SOCKS v4";
static char socks4aStr[]   = "SOCKS v4A";
static char socks5Str[]    = "SOCKS v5";
static char httpStr[]	   = "HTTP Proxy";

/* .INI file Strings 
 */
static char proxyStr[]     = "Proxy";
static char protocolStr[]  = "Protocol";
static char hostStr[]      = "Host";
static char usernameStr[]  = "Username";
static char passwordStr[]  = "Password";
static char portStr[]      = "Port";

static HWND hProxyDlg = NULL; 		/* dialog handle */
static Proxy proxy;			/* dialog variables */
static char dstHost[HOSTNAME_LEN]; 	/* host for the connect request */
static int dstPort; 			/* port for the connect request */
static int handlerIndex = 0; 		/* state handler index */
static int emptyLine;			/* for skip HTTP Proxy mime header */
static StateHandler **curProto = NULL;	/* pointer to current protocol handlers */

/* Error definitions
 */
typedef enum {
    PE_DATA,
    PE_VERSION,
    PE_CLOSE,
    PE_FAILED,
    PE_USERID,
    PE_IDENT,
    PE_METHODS,
    PE_AUTH,
    PE_SERVFAULT,
    PE_ACCESS,
    PE_NETUNREACH,
    PE_CONNREFUSED,
    PE_TLLEXPIRED,
    PE_OPNOTSUP,
    PE_ATNOTSUP,
    PE_HTTP
} ProxyError ;

static char *errorString[] = {
    "Invalid data from Proxy server.",
    "Proxy server has given an invalid version.",
    "Proxy server has closed the connection unexpectedly.",
    "SOCKS: conection failed.",
    "SOCKS: bad userid.",
    "SOCKS: ident error.",
    "SOCKS: no acceptable autentication methods.",
    "SOCKS: invalid username/password.",
    "SOCKS: undefined server error.",
    "SOCKS: access denied.",
    "SOCKS: network unreachable.",
    "SOCKS: connection refused.",
    "SOCKS: connection timedout.",
    "SOCKS: operation not supported.",
    "SOCKS: address type not supported.",
    "HTTP Proxy error.\nResponse: %s %s %s "
};

/* Report a error to the user
 */
static void proxyError(ProxyError error) 
{
    MessageBox(
	termGetWnd(), 
	errorString[error], 
	telnetAppName(), 
	MB_APPLMODAL | MB_ICONHAND | MB_OK
    );
}

/* Send the SOCKS4 CONNECT request
 */
static int socks4SendConnectRequest(void) 
{
    int ret, len;
    struct s4Packet req;
    /* fill the packet */
    req.version = S4_VERSION;
    req.command = S4_REQ_CONNECT;
    req.port = htons((u_short) dstPort);
    req.addr = inet_addr(dstHost);
    /* copy the userid */
    strcpy(req.userid, proxy.username);
    len = strlen(proxy.username) + 1;
    /* if socks4a extension is enabled, copy the hostname */
    if (proxy.protocol == PP_SOCKS4A) {
	if (req.addr == INADDR_NONE) { 
	    req.addr = inet_addr("0.0.0.1");
	    strcpy(&req.userid[len], dstHost);
	    len += strlen(dstHost) + 1;
	}
    }
    len += 8;
    /* send to server */
    ret = send(socketGetHandle(), (char *) &req, len, 0);
    if (ret == -1) {
	socketError("send()", WSAGetLastError());
	return PROXY_ERROR;
    }
    handlerIndex++;
    return PROXY_OK;
}

/* Get the SOCKS4 CONNECT reply
 */
static int socks4GetConnectReply(void)
{
    int ret, len;
    struct s4Packet rep;
    /* receive the packet */
    len = sizeof(rep) - sizeof(rep.userid);
    ret = recv(socketGetHandle(), (char *) &rep, len, 0);
    if (ret == -1) {
	socketError("recv()", WSAGetLastError());
	return PROXY_ERROR;
    }
    /* size check */
    if (ret != len) {
	proxyError(PE_DATA);
	return PROXY_ERROR;
    }
    /* eval server reply */
    switch (rep.command)
    {
    case S4_REP_SUCCESS:
	return PROXY_CONNECTED;
    case S4_REP_EFAILED:
	proxyError(PE_FAILED);
	break;
    case S4_REP_EIDENT:
	proxyError(PE_IDENT);
	break;
    case S4_REP_EBADUSRID:
	proxyError(PE_USERID);
	break;
    default:
	proxyError(PE_DATA);
	break;
    }
    return PROXY_ERROR;
}

/* State machine for SOCKS4
 */
static StateHandler *socks4Handler[] = {
    socks4SendConnectRequest, 
    socks4GetConnectReply
};

/* Send the SOCKS5 CONNECT request
 */
static int socks5SendConnectRequest(void)
{
    char* ptr;
    int ret, len;
    struct s5Packet req;
    unsigned short *ptr16;
    unsigned long *ptr32;
    /* fill the packet */
    req.version = S5_VERSION;
    req.command = S5_REQ_CONNECT;
    req.reserved = 0;
    if (inet_addr(dstHost) == INADDR_NONE) {
	/* fill req.dst with hostname length, hostname and the port */
	req.addr_type = S5_AT_DOMAINNAME;
	ptr = req.dst;
	len = strlen(dstHost);
	*ptr++ = (char)len;
	memcpy(ptr, dstHost, len);
	ptr += len;
	ptr16 = (unsigned short*) ptr;
	*ptr16 = htons((u_short) dstPort);
	len = 4 + 1 + len + 2;
    }
    else {
	/* fill req.dst with the ip address and the port */
	req.addr_type = S5_AT_IPV4;
	ptr32 = (unsigned long *) &req.dst;
	*ptr32++ = inet_addr(dstHost);
	ptr16 = (unsigned short *) ptr32;
	*ptr16 = htons((u_short) dstPort);
	len = 4 + 4 + 2;
    }
    /* send to server */
    ret = send(socketGetHandle(), (char *) &req, len, 0);
    if (ret == -1) {
	socketError("send()", WSAGetLastError());
	return PROXY_ERROR;
    }
    handlerIndex++;
    return PROXY_OK;
}

/* Get the SOCKS5 CONNECT reply
 */
static int socks5GetConnectReply(void)
{
    int ret;
    struct s5Packet rep;
    /* receive the packet */
    ret = recv(socketGetHandle(), (char *) &rep, sizeof(rep), 0);
    if (ret == -1) {
	socketError("recv()", WSAGetLastError());
	return PROXY_ERROR;
    }
    /* min size check */
    if (ret < 10) {
	proxyError(PE_DATA);
	return PROXY_ERROR;
    }
    /* eval server reply */
    switch (rep.command)
    {
    case S5_REPLY_SUCCESS:
	return PROXY_CONNECTED;
    case S5_REPLY_ESERVFAULT:
	proxyError(PE_SERVFAULT);
	break;
    case S5_REPLY_EACCESS:
	proxyError(PE_ACCESS);
	break;
    case S5_REPLY_ENETUNREACH:
	proxyError(PE_NETUNREACH);
	break;
    case S5_REPLY_ECONNREFUSED:
	proxyError(PE_CONNREFUSED);
	break;
    case S5_REPLY_ETLLEXPIRED:
	proxyError(PE_TLLEXPIRED);
	break;
    case S5_REPLY_EOPNOTSUP:
	proxyError(PE_OPNOTSUP);
	break;
    case S5_REPLY_EATNOTSUP:
	proxyError(PE_ATNOTSUP);
	break;
    default:
	proxyError(PE_DATA);
	break;
    }
    return PROXY_ERROR;
}

/* Send the SOCKS5 username/password autentication
 */
static int socks5SendAuthRequest(void)
{
    char *ptr;
    int ret, len, packlen = 3;
    char buf[256];
    /* fill the packet, length is variable */
    ptr = buf;
    /* set username/password version */
    *ptr++ = S5_AUTH_UP_VERSION;
    /* set  username length */
    len = strlen(proxy.username);
    *ptr++ = (char)len;
    /* set username */
    memcpy(ptr, proxy.username, len);
    ptr += len;
    packlen += len;
    /* set password length */
    len = strlen(proxy.password);
    *ptr++ = (char)len;
    /* set password */
    memcpy(ptr, proxy.password, len);
    packlen += len;
    /* send to server */
    ret = send(socketGetHandle(), buf, packlen, 0);
    if (ret == -1) {
	socketError("send()", WSAGetLastError());
	return PROXY_ERROR;
    }
    handlerIndex++;
    return PROXY_OK;
}

/* Get the SOCKS5 autentication method selected by server
 */
static int socks5GetAuthMethod(void)
{
    int ret;
    struct s5AuthMethodRep rep;
    /* receive the packet */
    ret = recv(socketGetHandle(), (char *) &rep, sizeof(rep), 0);
    if (ret == -1) {
	socketError("recv()", WSAGetLastError());
	return PROXY_ERROR;
    }
    /* size check */
    if (ret != sizeof(rep)) {
	proxyError(PE_DATA);
	return PROXY_ERROR;
    }
    /* eval server reply */
    switch (rep.method)
    {
    case S5_AUTH_NOACCEPTABLE:
	proxyError(PE_METHODS);
	break;
    case S5_AUTH_NOTREQUIRED:
	handlerIndex++;
	return socks5SendConnectRequest();
    case S5_AUTH_USERPASSWORD:
	return socks5SendAuthRequest();
    default:
	proxyError(PE_DATA);
	break;
    }
    return PROXY_ERROR;
}

/* Get the SOCKS5 username/password autentication reply
 */
static int socks5GetAuthReply(void)
{
    int ret;
    struct s5UPAuthRep rep;
    /* receive the packet */
    ret = recv(socketGetHandle(), (char *) &rep, sizeof(rep), 0);
    if (ret == -1) {

⌨️ 快捷键说明

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