"Fossies" - the Fresh Open Source Software Archive 
Member "HTTPing-2.9/socks5.c" (29 Oct 2022, 4334 Bytes) of package /linux/www/HTTPing-2.9.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "socks5.c" see the
Fossies "Dox" file reference documentation.
1 #include <libintl.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8 #include <sys/time.h>
9 #include <time.h>
10 #include <netdb.h>
11 #include <arpa/inet.h>
12
13 #include "error.h"
14 #include "gen.h"
15 #include "io.h"
16 #include "res.h"
17 #include "tcp.h"
18
19 int socks5connect(int fd, struct addrinfo *ai, double timeout, const char *socks5_username, const char *socks5_password, const char *host, int port, char abort_on_resolve_failure)
20 {
21 struct sockaddr_in sai;
22 uint32_t addr = 0;
23 unsigned char io_buffer[256] = { 0 };
24 int io_len = 0, rc = -1;
25
26 if ((rc = connect_to(fd, ai, timeout, NULL, NULL, 0, NULL)) == -1)
27 return rc;
28
29 /* inform socks server about the auth. methods we support */
30 if (socks5_username != NULL)
31 {
32 io_buffer[0] = 0x05; /* version */
33 io_buffer[1] = 2; /* 2 authentication methods */
34 io_buffer[2] = 0x00; /* method 1: no authentication */
35 io_buffer[3] = 0x02; /* method 2: username/password */
36 io_len = 4;
37 }
38 else
39 {
40 io_buffer[0] = 0x05; /* version */
41 io_buffer[1] = 1; /* 2 authentication methods */
42 io_buffer[2] = 0x00; /* method 1: no authentication */
43 io_len = 3;
44 }
45
46 if ((rc = mywrite(fd, (char *)io_buffer, io_len, timeout)) < 0)
47 return rc;
48
49 /* wait for reply telling selected authentication method */
50 if ((rc = myread(fd, (char *)io_buffer, 2, timeout)) < 0)
51 return rc;
52
53 if (io_buffer[0] != 0x05)
54 {
55 set_error(gettext("socks5connect: reply with requested authentication method does not say version 5 (%02x)"), io_buffer[0]);
56 return RC_INVAL;
57 }
58
59 if (io_buffer[1] == 0x00)
60 {
61 /* printf("socks5connect: \"no authentication at all\" selected by server\n"); */
62 }
63 else if (io_buffer[1] == 0x02)
64 {
65 /* printf("socks5connect: selected username/password authentication\n"); */
66 }
67 else
68 {
69 set_error(gettext("socks5connect: socks5 refuses our authentication methods: %02x"), io_buffer[1]);
70 return RC_INVAL;
71 }
72
73 /* in case the socks5 server asks us to authenticate, do so */
74 if (io_buffer[1] == 0x02)
75 {
76 int io_len = 0;
77
78 if (socks5_username == NULL || socks5_password == NULL)
79 {
80 set_error(gettext("socks5connect: socks5 server requests username/password authentication"));
81 return RC_INVAL;
82 }
83
84 io_buffer[0] = 0x01; /* version */
85 io_len = snprintf((char *)&io_buffer[1], sizeof io_buffer - 1, "%c%s%c%s", (int)strlen(socks5_username), socks5_username, (int)strlen(socks5_password), socks5_password);
86
87 if ((rc = mywrite(fd, (char *)io_buffer, io_len + 1, timeout)) < 0)
88 {
89 set_error(gettext("socks5connect: failed transmitting username/password to socks5 server"));
90 return rc;
91 }
92
93 if ((rc = myread(fd, (char *)io_buffer, 2, timeout)) < 0)
94 {
95 set_error(gettext("socks5connect: failed receiving authentication reply"));
96 return rc;
97 }
98
99 if (io_buffer[1] != 0x00)
100 {
101 set_error(gettext("socks5connect: password authentication failed"));
102 return RC_INVAL;
103 }
104 }
105
106 /* ask socks5 server to associate with server */
107 io_buffer[0] = 0x05; /* version */
108 io_buffer[1] = 0x01; /* connect to */
109 io_buffer[2] = 0x00; /* reserved */
110 io_buffer[3] = 0x01; /* ipv4 */
111
112 if (resolve_host_ipv4(host, &sai) == -1)
113 {
114 if (abort_on_resolve_failure)
115 error_exit(gettext("Cannot resolve %s"), host);
116
117 return RC_INVAL;
118 }
119
120 addr = ntohl(sai.sin_addr.s_addr);
121
122 io_buffer[4] = (addr >> 24) & 255;
123 io_buffer[5] = (addr >> 16) & 255;
124 io_buffer[6] = (addr >> 8) & 255;
125 io_buffer[7] = (addr ) & 255;
126
127 io_buffer[8] = (port >> 8) & 255;
128 io_buffer[9] = (port ) & 255;
129
130 if ((rc = mywrite(fd, (char *)io_buffer, 10, timeout)) < 0)
131 {
132 set_error(gettext("socks5connect: failed to transmit associate request"));
133 return rc;
134 }
135
136 if ((rc = myread(fd, (char *)io_buffer, 10, timeout)) < 0)
137 {
138 set_error(gettext("socks5connect: command reply receive failure"));
139 return rc;
140 }
141
142 /* verify reply */
143 if (io_buffer[0] != 0x05)
144 {
145 set_error(gettext("socks5connect: bind request replies with version other than 0x05 (%02x)"), io_buffer[0]);
146 return RC_INVAL;
147 }
148
149 if (io_buffer[1] != 0x00)
150 {
151 set_error(gettext("socks5connect: failed to connect (%02x)"), io_buffer[1]);
152 return RC_INVAL;
153 }
154
155 if (io_buffer[3] != 0x01)
156 {
157 set_error(gettext("socks5connect: only accepting bind-replies with IPv4 address (%02x)"), io_buffer[3]);
158 return RC_INVAL;
159 }
160
161 return RC_OK;
162 }