-
Notifications
You must be signed in to change notification settings - Fork 0
/
socks5.c
148 lines (108 loc) · 3.28 KB
/
socks5.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// Created by Administrator on 2023-10-05.
//
#include "socks5.h"
#include "util.h"
#include "socks.h"
#include "relay.h"
int socks5_auth(int socket_fd, int methods) {
int supported = -1;
for (int i = 0; i < methods; i++) {
char method;
int n = readn(socket_fd, &method, 1);
if (n < 1) {
log_message("socks_auth() less than 1 byte read.");
return -1;
}
if (method == SOCKS_AUTH_NOAUTH) {
// support only SOCKS_AUTH_NOAUTH
supported = 0;
}
}
return supported;
}
int socks5_auth_not_supported(int socket_fd) {
char answer[2] = {SOCKS_VERSION5, SOCKS_AUTH_NOMETHOD};
if (writen(socket_fd, (void *) answer, ARRAY_SIZE(answer)) != 0) {
return -1;
}
return 0;
}
int socks5_auth_reply(int socket_fd) {
char answer[] = {SOCKS_VERSION5, SOCKS_AUTH_NOAUTH};
if (writen(socket_fd, answer, ARRAY_SIZE(answer)) != 0) {
return -1;
}
return 0;
}
int socks5_command(int socket_fd, int *command) {
char cmd[4];
int n = readn(socket_fd, cmd, ARRAY_SIZE(cmd));
if (n < 4) {
log_message("socks5_command() less than 4 bytes read.");
return -1;
}
log_message("Command %hhX %hhX %hhX %hhX", cmd[0], cmd[1],cmd[2], cmd[3]);
if (cmd[0] != SOCKS_VERSION5) {
log_message("socks5_command() invalid version: %d.", cmd[0]);
return -1;
}
if (cmd[1] != SOCKS_CMD_CONNECT) {
log_message("socks5_command() invalid command: %d.", cmd[1]);
return -1;
}
// cmd[2] is a reserved byte
if (cmd[3] != SOCKS_ADDR_IPV4 && cmd[3] != SOCKS_ADDR_DOMAINNAME) {
log_message("socks5_command() invalid address type: %d.", cmd[3]);
return -1;
}
*command = (int) cmd[3];
return 0;
}
int socks5_read_domain(int socket_fd, char **domain, int *domain_len) {
int len;
int n = readn(socket_fd, &len, 1);
if (n < 1) {
log_message("socks5_read_domain() less than 1 byte read.");
return -1;
}
char *buf = calloc(len + 1, sizeof(char));
n = readn(socket_fd, buf, len);
if (n < len) {
log_message("socks5_read_domain() less than %d bytes read.", len);
return -1;
}
buf[len] = 0;
*domain = buf;
*domain_len = len;
return 0;
}
int socks5_domain_send_response(int socket_fd, char *domain, int domain_len, unsigned short int port) {
char response[] = {SOCKS_VERSION5, SOCKS_CONN_SUCCEEDED, 0, SOCKS_ADDR_DOMAINNAME};
if (writen(socket_fd, response, ARRAY_SIZE(response)) != 0) {
return -1;
}
if (writen(socket_fd, &domain_len, sizeof(char)) != 0) {
return -1;
}
if (writen(socket_fd, domain, domain_len * sizeof(char)) != 0) {
return -1;
}
if (writen(socket_fd, &port, sizeof(port)) != 0) {
return -1;
}
return 0;
}
int socks5_ip_send_response(int socket_fd, char *ip, unsigned short int port) {
char response[] = {SOCKS_VERSION5, SOCKS_CONN_SUCCEEDED, 0, SOCKS_ADDR_IPV4};
if (writen(socket_fd, response, ARRAY_SIZE(response)) != 0) {
return -1;
}
if (writen(socket_fd, ip, IPSIZE * sizeof(char)) != 0) {
return -1;
}
if (writen(socket_fd, &port, sizeof(port)) != 0) {
return -1;
}
return 0;
}