📄 proxy.c
字号:
/* 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 + -