diff options
Diffstat (limited to 'libraries/ecore/src/lib/ecore_con/ecore_con_socks.c')
-rw-r--r-- | libraries/ecore/src/lib/ecore_con/ecore_con_socks.c | 762 |
1 files changed, 603 insertions, 159 deletions
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_socks.c b/libraries/ecore/src/lib/ecore_con/ecore_con_socks.c index aecaff0..686f73b 100644 --- a/libraries/ecore/src/lib/ecore_con/ecore_con_socks.c +++ b/libraries/ecore/src/lib/ecore_con/ecore_con_socks.c | |||
@@ -10,6 +10,10 @@ | |||
10 | #include <unistd.h> | 10 | #include <unistd.h> |
11 | #include <fcntl.h> | 11 | #include <fcntl.h> |
12 | 12 | ||
13 | #ifdef HAVE_SYS_SOCKET_H | ||
14 | # include <sys/socket.h> | ||
15 | #endif | ||
16 | |||
13 | #ifdef HAVE_NETINET_TCP_H | 17 | #ifdef HAVE_NETINET_TCP_H |
14 | # include <netinet/tcp.h> | 18 | # include <netinet/tcp.h> |
15 | #endif | 19 | #endif |
@@ -36,10 +40,6 @@ | |||
36 | # include <arpa/inet.h> | 40 | # include <arpa/inet.h> |
37 | #endif | 41 | #endif |
38 | 42 | ||
39 | #ifdef HAVE_SYS_SOCKET_H | ||
40 | # include <sys/socket.h> | ||
41 | #endif | ||
42 | |||
43 | #ifdef HAVE_SYS_UN_H | 43 | #ifdef HAVE_SYS_UN_H |
44 | # include <sys/un.h> | 44 | # include <sys/un.h> |
45 | #endif | 45 | #endif |
@@ -57,6 +57,27 @@ | |||
57 | #include "Ecore_Con.h" | 57 | #include "Ecore_Con.h" |
58 | #include "ecore_con_private.h" | 58 | #include "ecore_con_private.h" |
59 | 59 | ||
60 | /* http://tools.ietf.org/html/rfc1928 | ||
61 | o X'00' NO AUTHENTICATION REQUIRED | ||
62 | o X'01' GSSAPI | ||
63 | o X'02' USERNAME/PASSWORD | ||
64 | o X'03' to X'7F' IANA ASSIGNED | ||
65 | o X'80' to X'FE' RESERVED FOR PRIVATE METHODS | ||
66 | o X'FF' NO ACCEPTABLE METHODS | ||
67 | */ | ||
68 | #define ECORE_CON_SOCKS_V5_METHOD_NONE 0 | ||
69 | #define ECORE_CON_SOCKS_V5_METHOD_GSSAPI 1 | ||
70 | #define ECORE_CON_SOCKS_V5_METHOD_USERPASS 2 | ||
71 | |||
72 | static int ECORE_CON_SOCKS_V5_METHODS[] = | ||
73 | { | ||
74 | ECORE_CON_SOCKS_V5_METHOD_NONE, | ||
75 | // ECORE_CON_SOCKS_V5_METHOD_GSSAPI, TODO | ||
76 | ECORE_CON_SOCKS_V5_METHOD_USERPASS | ||
77 | }; | ||
78 | |||
79 | #define ECORE_CON_SOCKS_V5_TOTAL_METHODS sizeof(ECORE_CON_SOCKS_V5_METHODS) | ||
80 | |||
60 | #define _ecore_con_server_kill(svr) do { \ | 81 | #define _ecore_con_server_kill(svr) do { \ |
61 | DBG("KILL %p", (svr)); \ | 82 | DBG("KILL %p", (svr)); \ |
62 | _ecore_con_server_kill((svr)); \ | 83 | _ecore_con_server_kill((svr)); \ |
@@ -65,10 +86,10 @@ | |||
65 | Eina_List *ecore_con_socks_proxies = NULL; | 86 | Eina_List *ecore_con_socks_proxies = NULL; |
66 | 87 | ||
67 | static Ecore_Con_Socks * | 88 | static Ecore_Con_Socks * |
68 | _ecore_con_socks_find(unsigned char version, const char *ip, int port, const char *username) | 89 | _ecore_con_socks_find(unsigned char version, const char *ip, int port, const char *username, size_t ulen, const char *password, size_t plen) |
69 | { | 90 | { |
70 | Eina_List *l; | 91 | Eina_List *l; |
71 | Ecore_Con_Socks *ecs; | 92 | Ecore_Con_Socks_v5 *ecs; |
72 | 93 | ||
73 | if (!ecore_con_socks_proxies) return NULL; | 94 | if (!ecore_con_socks_proxies) return NULL; |
74 | 95 | ||
@@ -77,8 +98,14 @@ _ecore_con_socks_find(unsigned char version, const char *ip, int port, const cha | |||
77 | if (ecs->version != version) continue; | 98 | if (ecs->version != version) continue; |
78 | if (strcmp(ecs->ip, ip)) continue; | 99 | if (strcmp(ecs->ip, ip)) continue; |
79 | if ((port != -1) && (port != ecs->port)) continue; | 100 | if ((port != -1) && (port != ecs->port)) continue; |
101 | if (ulen != ecs->ulen) continue; | ||
80 | if (username && strcmp(ecs->username, username)) continue; | 102 | if (username && strcmp(ecs->username, username)) continue; |
81 | return ecs; | 103 | if (version == 5) |
104 | { | ||
105 | if (plen != ecs->plen) continue; | ||
106 | if (password && strcmp(ecs->password, password)) continue; | ||
107 | } | ||
108 | return (Ecore_Con_Socks*)ecs; | ||
82 | } | 109 | } |
83 | return NULL; | 110 | return NULL; |
84 | } | 111 | } |
@@ -94,146 +121,424 @@ _ecore_con_socks_free(Ecore_Con_Socks *ecs) | |||
94 | eina_stringshare_del(ecs->username); | 121 | eina_stringshare_del(ecs->username); |
95 | free(ecs); | 122 | free(ecs); |
96 | } | 123 | } |
97 | ///////////////////////////////////////////////////////////////////////////////////// | 124 | |
98 | void | 125 | static Eina_Bool |
99 | ecore_con_socks_shutdown(void) | 126 | _ecore_con_socks_svr_init_v4(Ecore_Con_Server *svr, Ecore_Con_Socks_v4 *v4) |
100 | { | 127 | { |
101 | Ecore_Con_Socks *ecs; | 128 | size_t addrlen, buflen, ulen = 1; |
102 | EINA_LIST_FREE(ecore_con_socks_proxies, ecs) | 129 | unsigned char *sbuf; |
103 | _ecore_con_socks_free(ecs); | 130 | |
104 | _ecore_con_proxy_once = NULL; | 131 | addrlen = v4->lookup ? strlen(svr->name) + 1 : 0; |
105 | _ecore_con_proxy_global = NULL; | 132 | if (v4->username) ulen += v4->ulen; |
133 | buflen = sizeof(char) * (8 + ulen + addrlen); | ||
134 | sbuf = malloc(buflen); | ||
135 | if (!sbuf) | ||
136 | { | ||
137 | ecore_con_event_server_error(svr, "Memory allocation failure!"); | ||
138 | _ecore_con_server_kill(svr); | ||
139 | return EINA_FALSE; | ||
140 | } | ||
141 | /* http://en.wikipedia.org/wiki/SOCKS */ | ||
142 | sbuf[0] = 4; | ||
143 | sbuf[1] = v4->bind ? 2 : 1; | ||
144 | sbuf[2] = svr->port >> 8; | ||
145 | sbuf[3] = svr->port & 0xff; | ||
146 | if (addrlen) | ||
147 | { | ||
148 | sbuf[4] = sbuf[5] = sbuf[6] = 0; | ||
149 | sbuf[7] = 1; | ||
150 | } | ||
151 | else | ||
152 | /* SOCKSv4 only handles IPV4, so addrlen is always 4 */ | ||
153 | memcpy(sbuf + 4, svr->ecs_addr, 4); | ||
154 | if (v4->username) | ||
155 | memcpy(sbuf + 8, v4->username, ulen); | ||
156 | else | ||
157 | sbuf[8] = 0; | ||
158 | if (addrlen) memcpy(sbuf + 8 + ulen, svr->name, addrlen); | ||
159 | |||
160 | svr->ecs_buf = eina_binbuf_manage_new_length(sbuf, buflen); | ||
161 | return EINA_TRUE; | ||
106 | } | 162 | } |
107 | 163 | ||
108 | void | 164 | static Eina_Bool |
109 | ecore_con_socks_read(Ecore_Con_Server *svr, unsigned char *buf, int num) | 165 | _ecore_con_socks_svr_init_v5(Ecore_Con_Server *svr, Ecore_Con_Socks_v5 *v5) |
166 | { | ||
167 | size_t buflen; | ||
168 | unsigned int x; | ||
169 | unsigned char *sbuf; | ||
170 | |||
171 | if (v5->username) | ||
172 | buflen = sizeof(char) * (2 + ECORE_CON_SOCKS_V5_TOTAL_METHODS); | ||
173 | else | ||
174 | buflen = 3; | ||
175 | sbuf = malloc(buflen); | ||
176 | if (!sbuf) | ||
177 | { | ||
178 | ecore_con_event_server_error(svr, "Memory allocation failure!"); | ||
179 | _ecore_con_server_kill(svr); | ||
180 | return EINA_FALSE; | ||
181 | } | ||
182 | /* http://en.wikipedia.org/wiki/SOCKS | ||
183 | * http://tools.ietf.org/html/rfc1928 | ||
184 | */ | ||
185 | sbuf[0] = 5; | ||
186 | if (v5->username) | ||
187 | { | ||
188 | sbuf[1] = ECORE_CON_SOCKS_V5_TOTAL_METHODS; | ||
189 | for (x = 2; x < 2 + ECORE_CON_SOCKS_V5_TOTAL_METHODS; x++) | ||
190 | sbuf[x] = ECORE_CON_SOCKS_V5_METHODS[x - 2]; | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | sbuf[1] = 1; | ||
195 | sbuf[2] = ECORE_CON_SOCKS_V5_METHOD_NONE; | ||
196 | } | ||
197 | |||
198 | svr->ecs_buf = eina_binbuf_manage_new_length(sbuf, buflen); | ||
199 | return EINA_TRUE; | ||
200 | } | ||
201 | |||
202 | #define ECORE_CON_SOCKS_READ(EXACT) \ | ||
203 | if (num < EXACT) \ | ||
204 | { \ | ||
205 | if (!svr->ecs_recvbuf) svr->ecs_recvbuf = eina_binbuf_new(); \ | ||
206 | if (!svr->ecs_recvbuf) goto error; \ | ||
207 | eina_binbuf_append_length(svr->ecs_recvbuf, buf, num); \ | ||
208 | /* the slowest connection on earth */ \ | ||
209 | if (eina_binbuf_length_get(svr->ecs_recvbuf) != EXACT) return; \ | ||
210 | data = eina_binbuf_string_get(svr->ecs_recvbuf); \ | ||
211 | } \ | ||
212 | else if (num > EXACT) goto error; \ | ||
213 | else \ | ||
214 | data = buf | ||
215 | |||
216 | static void | ||
217 | _ecore_con_socks_read_v4(Ecore_Con_Server *svr, Ecore_Con_Socks_v4 *v4 __UNUSED__, const unsigned char *buf, unsigned int num) | ||
110 | { | 218 | { |
111 | const unsigned char *data; | 219 | const unsigned char *data; |
112 | ECORE_CON_SOCKS_CAST_ELSE(svr->ecs) return; | 220 | DBG("SOCKS: %d bytes", num); |
221 | ECORE_CON_SOCKS_READ(8); | ||
113 | 222 | ||
114 | if (svr->ecs_state != ECORE_CON_SOCKS_STATE_READ) return; | 223 | /* http://ufasoft.com/doc/socks4_protocol.htm */ |
224 | if (data[0]) goto error; | ||
225 | switch (data[1]) | ||
226 | { | ||
227 | case 90: | ||
228 | /* success! */ | ||
229 | break; | ||
230 | case 91: | ||
231 | ecore_con_event_server_error(svr, "proxy request rejected or failed"); | ||
232 | goto error; | ||
233 | case 92: | ||
234 | ecore_con_event_server_error(svr, "proxying SOCKS server could not perform authentication"); | ||
235 | goto error; | ||
236 | case 93: | ||
237 | ecore_con_event_server_error(svr, "proxy request authentication rejected"); | ||
238 | goto error; | ||
239 | default: | ||
240 | ecore_con_event_server_error(svr, "garbage data from proxy"); | ||
241 | goto error; | ||
242 | } | ||
243 | if (svr->ecs->bind) | ||
244 | { | ||
245 | unsigned int nport; | ||
246 | char naddr[IF_NAMESIZE]; | ||
115 | 247 | ||
116 | if (v4) | 248 | memcpy(&nport, &data[2], 2); |
249 | svr->proxyport = ntohl(nport); | ||
250 | |||
251 | if (!inet_ntop(AF_INET, &data[4], naddr, sizeof(naddr))) goto error; | ||
252 | svr->proxyip = eina_stringshare_add(naddr); | ||
253 | ecore_con_event_proxy_bind(svr); | ||
254 | } | ||
255 | svr->ecs_state = ECORE_CON_PROXY_STATE_DONE; | ||
256 | INF("PROXY CONNECTED"); | ||
257 | if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf); | ||
258 | svr->ecs_recvbuf = NULL; | ||
259 | svr->ecs_buf_offset = svr->ecs_addrlen = 0; | ||
260 | memset(svr->ecs_addr, 0, sizeof(svr->ecs_addr)); | ||
261 | if (!svr->ssl_state) | ||
262 | ecore_con_event_server_add(svr); | ||
263 | if (svr->ssl_state || (svr->buf && eina_binbuf_length_get(svr->buf))) | ||
264 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE); | ||
265 | return; | ||
266 | error: | ||
267 | _ecore_con_server_kill(svr); | ||
268 | } | ||
269 | |||
270 | static Eina_Bool | ||
271 | _ecore_con_socks_auth_v5(Ecore_Con_Server *svr, Ecore_Con_Socks_v5 *v5) | ||
272 | { | ||
273 | size_t size; | ||
274 | unsigned char *data; | ||
275 | switch (v5->method) | ||
276 | { | ||
277 | case ECORE_CON_SOCKS_V5_METHOD_NONE: | ||
278 | svr->ecs_state = ECORE_CON_PROXY_STATE_REQUEST; | ||
279 | return EINA_TRUE; | ||
280 | case ECORE_CON_SOCKS_V5_METHOD_GSSAPI: | ||
281 | return EINA_TRUE; | ||
282 | case ECORE_CON_SOCKS_V5_METHOD_USERPASS: | ||
283 | if (!v5->username) return EINA_FALSE; | ||
284 | if (!v5->password) v5->plen = 1; | ||
285 | /* http://tools.ietf.org/html/rfc1929 */ | ||
286 | size = sizeof(char) * (3 + v5->ulen + v5->plen); | ||
287 | data = malloc(size); | ||
288 | if (!data) break; | ||
289 | data[0] = 1; | ||
290 | data[1] = v5->ulen; | ||
291 | memcpy(&data[2], v5->username, v5->ulen); | ||
292 | data[1 + v5->ulen] = v5->plen; | ||
293 | if (v5->password) | ||
294 | memcpy(&data[2 + v5->ulen], v5->password, v5->plen); | ||
295 | else | ||
296 | data[2 + v5->ulen] = 0; | ||
297 | svr->ecs_buf = eina_binbuf_manage_new_length(data, size); | ||
298 | return EINA_TRUE; | ||
299 | default: | ||
300 | break; | ||
301 | } | ||
302 | return EINA_FALSE; | ||
303 | } | ||
304 | |||
305 | static void | ||
306 | _ecore_con_socks_read_v5(Ecore_Con_Server *svr, Ecore_Con_Socks_v5 *v5, const unsigned char *buf, unsigned int num) | ||
307 | { | ||
308 | const unsigned char *data; | ||
309 | |||
310 | DBG("SOCKS: %d bytes", num); | ||
311 | switch (svr->ecs_state) | ||
117 | { | 312 | { |
118 | DBG("SOCKS: %d bytes", num); | ||
119 | if (num < 8) | ||
120 | { | ||
121 | if (!svr->ecs_recvbuf) svr->ecs_recvbuf = eina_binbuf_new(); | ||
122 | if (!svr->ecs_recvbuf) goto error; | ||
123 | eina_binbuf_append_length(svr->ecs_recvbuf, buf, num); | ||
124 | /* the slowest connection on earth */ | ||
125 | if (eina_binbuf_length_get(svr->ecs_recvbuf) != 8) return; | ||
126 | data = eina_binbuf_string_get(svr->ecs_recvbuf); | ||
127 | } | ||
128 | else if (num > 8) goto error; | ||
129 | else | ||
130 | data = buf; | ||
131 | 313 | ||
132 | /* http://ufasoft.com/doc/socks4_protocol.htm */ | 314 | case ECORE_CON_PROXY_STATE_READ: |
133 | if (data[0]) goto error; | 315 | ECORE_CON_SOCKS_READ(2); |
134 | switch (data[1]) | 316 | /* http://en.wikipedia.org/wiki/SOCKS */ |
317 | if (data[0] != 5) goto error; | ||
318 | if (data[1] == 0xFF) | ||
319 | { | ||
320 | ecore_con_event_server_error(svr, "proxy authentication methods rejected"); | ||
321 | goto error; | ||
322 | } | ||
323 | v5->method = data[1]; | ||
324 | if (!_ecore_con_socks_auth_v5(svr, v5)) goto error; | ||
325 | if (svr->ecs_state == ECORE_CON_PROXY_STATE_REQUEST) | ||
326 | { | ||
327 | /* run again to skip auth reading */ | ||
328 | _ecore_con_socks_read_v5(svr, v5, NULL, 0); | ||
329 | return; | ||
330 | } | ||
331 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
332 | svr->ecs_state = ECORE_CON_PROXY_STATE_AUTH; | ||
333 | break; | ||
334 | case ECORE_CON_PROXY_STATE_AUTH: | ||
335 | ECORE_CON_SOCKS_READ(2); | ||
336 | switch (v5->method) | ||
337 | { | ||
338 | case ECORE_CON_SOCKS_V5_METHOD_NONE: | ||
339 | CRIT("HOW DID THIS HAPPEN?????????"); | ||
340 | goto error; | ||
341 | case ECORE_CON_SOCKS_V5_METHOD_GSSAPI: | ||
342 | /* TODO: this */ | ||
343 | break; | ||
344 | case ECORE_CON_SOCKS_V5_METHOD_USERPASS: | ||
345 | if (data[0] != 1) | ||
346 | { | ||
347 | ecore_con_event_server_error(svr, "protocol error"); | ||
348 | goto error; /* wrong version */ | ||
349 | } | ||
350 | if (data[1]) | ||
351 | { | ||
352 | ecore_con_event_server_error(svr, "proxy request authentication rejected"); | ||
353 | goto error; | ||
354 | } | ||
355 | default: | ||
356 | break; | ||
357 | } | ||
358 | case ECORE_CON_PROXY_STATE_REQUEST: | ||
135 | { | 359 | { |
136 | case 90: | 360 | size_t addrlen, buflen; |
137 | /* success! */ | 361 | unsigned char *sbuf; |
138 | break; | 362 | addrlen = v5->lookup ? strlen(svr->name) + 1 : (unsigned int)svr->ecs_addrlen; |
139 | case 91: | 363 | buflen = sizeof(char) * (6 + addrlen); |
140 | ecore_con_event_server_error(svr, "proxy request rejected or failed"); | 364 | sbuf = malloc(buflen); |
141 | goto error; | 365 | if (!sbuf) |
142 | case 92: | 366 | { |
143 | ecore_con_event_server_error(svr, "proxying SOCKS server could not perform authentication"); | 367 | ecore_con_event_server_error(svr, "Memory allocation failure!"); |
144 | goto error; | 368 | goto error; |
145 | case 93: | 369 | } |
146 | ecore_con_event_server_error(svr, "proxy request authentication rejected"); | 370 | sbuf[0] = 5; |
147 | goto error; | 371 | sbuf[1] = v5->bind ? 2 : 1; /* TODO: 0x03 for UDP port association */ |
148 | default: | 372 | sbuf[2] = 0; |
149 | ecore_con_event_server_error(svr, "garbage data from proxy"); | 373 | if (v5->lookup) /* domain name */ |
150 | goto error; | 374 | { |
375 | sbuf[3] = 3; | ||
376 | sbuf[4] = addrlen - 1; | ||
377 | memcpy(sbuf + 5, svr->name, addrlen - 1); | ||
378 | } | ||
379 | else | ||
380 | { | ||
381 | sbuf[3] = (svr->ecs_addrlen == 4) ? 1 : 4; | ||
382 | memcpy(sbuf + 4, svr->ecs_addr, addrlen); | ||
383 | } | ||
384 | sbuf[addrlen + 4] = svr->port >> 8; | ||
385 | sbuf[addrlen + 5] = svr->port & 0xff; | ||
386 | |||
387 | svr->ecs_buf = eina_binbuf_manage_new_length(sbuf, buflen); | ||
388 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | ||
389 | break; | ||
151 | } | 390 | } |
152 | if (svr->ecs->bind) | 391 | case ECORE_CON_PROXY_STATE_CONFIRM: |
153 | { | 392 | { |
154 | unsigned int nport; | 393 | /* this is ugly because we have to read an exact number of bytes, |
155 | char naddr[IF_NAMESIZE]; | 394 | * but we don't know what that number is until we've already read |
156 | 395 | * at least 5 bytes to determine the length of the unknown stream. | |
157 | memcpy(&nport, &data[2], 2); | 396 | * yep. |
158 | svr->proxyport = ntohl(nport); | 397 | */ |
159 | 398 | size_t to_read, len = svr->ecs_recvbuf ? eina_binbuf_length_get(svr->ecs_recvbuf) : 0; | |
160 | if (!inet_ntop(AF_INET, &data[4], naddr, sizeof(naddr))) goto error; | 399 | if (num + len < 5) |
161 | svr->proxyip = eina_stringshare_add(naddr); | 400 | { |
162 | ecore_con_event_proxy_bind(svr); | 401 | /* guarantees we get called again */ |
402 | ECORE_CON_SOCKS_READ(5); | ||
403 | } | ||
404 | if (len >= 5) | ||
405 | { | ||
406 | data = eina_binbuf_string_get(svr->ecs_recvbuf); | ||
407 | data += 3; | ||
408 | } | ||
409 | else | ||
410 | data = buf + 3 - len; | ||
411 | switch (data[0]) | ||
412 | { | ||
413 | case 1: | ||
414 | to_read = 4; | ||
415 | break; | ||
416 | case 3: | ||
417 | to_read = data[1] + 1; | ||
418 | break; | ||
419 | case 4: | ||
420 | to_read = 16; | ||
421 | /* lazy debugging stub comment */ | ||
422 | break; | ||
423 | default: | ||
424 | ecore_con_event_server_error(svr, "protocol error"); | ||
425 | goto error; | ||
426 | } | ||
427 | /* at this point, we finally know exactly how much we need to read */ | ||
428 | ECORE_CON_SOCKS_READ(6 + to_read); | ||
429 | |||
430 | if (data[0] != 5) | ||
431 | { | ||
432 | ecore_con_event_server_error(svr, "protocol error"); | ||
433 | goto error; /* wrong version */ | ||
434 | } | ||
435 | switch (data[1]) | ||
436 | { | ||
437 | case 0: | ||
438 | break; | ||
439 | case 1: | ||
440 | ecore_con_event_server_error(svr, "general proxy failure"); | ||
441 | goto error; | ||
442 | case 2: | ||
443 | ecore_con_event_server_error(svr, "connection not allowed by ruleset"); | ||
444 | goto error; | ||
445 | case 3: | ||
446 | ecore_con_event_server_error(svr, "network unreachable"); | ||
447 | goto error; | ||
448 | case 4: | ||
449 | ecore_con_event_server_error(svr, "host unreachable"); | ||
450 | goto error; | ||
451 | case 5: | ||
452 | ecore_con_event_server_error(svr, "connection refused by destination host"); | ||
453 | goto error; | ||
454 | case 6: | ||
455 | ecore_con_event_server_error(svr, "TTL expired"); | ||
456 | goto error; | ||
457 | case 7: | ||
458 | ecore_con_event_server_error(svr, "command not supported / protocol error"); | ||
459 | goto error; | ||
460 | case 8: | ||
461 | ecore_con_event_server_error(svr, "address type not supported"); | ||
462 | default: | ||
463 | goto error; | ||
464 | } | ||
465 | if (data[2]) | ||
466 | { | ||
467 | ecore_con_event_server_error(svr, "protocol error"); | ||
468 | goto error; | ||
469 | } | ||
470 | memset(svr->ecs_addr, 0, sizeof(svr->ecs_addr)); | ||
471 | if (!svr->ssl_state) | ||
472 | ecore_con_event_server_add(svr); | ||
473 | if (svr->ssl_state || (svr->buf && eina_binbuf_length_get(svr->buf))) | ||
474 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE); | ||
475 | svr->ecs_buf_offset = svr->ecs_addrlen = 0; | ||
476 | svr->ecs_state = ECORE_CON_PROXY_STATE_DONE; | ||
477 | INF("PROXY CONNECTED"); | ||
478 | break; | ||
163 | } | 479 | } |
164 | svr->ecs_state = ECORE_CON_SOCKS_STATE_DONE; | 480 | default: |
165 | INF("PROXY CONNECTED"); | 481 | break; |
166 | if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf); | ||
167 | svr->ecs_recvbuf = NULL; | ||
168 | svr->ecs_buf_offset = svr->ecs_addrlen = 0; | ||
169 | memset(svr->ecs_addr, 0, sizeof(svr->ecs_addr)); | ||
170 | if (!svr->ssl_state) | ||
171 | ecore_con_event_server_add(svr); | ||
172 | if (svr->ssl_state || (svr->buf && eina_binbuf_length_get(svr->buf))) | ||
173 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE); | ||
174 | } | 482 | } |
483 | if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf); | ||
484 | svr->ecs_recvbuf = NULL; | ||
485 | |||
175 | return; | 486 | return; |
176 | error: | 487 | error: |
177 | _ecore_con_server_kill(svr); | 488 | _ecore_con_server_kill(svr); |
178 | } | 489 | } |
179 | 490 | ||
491 | ///////////////////////////////////////////////////////////////////////////////////// | ||
492 | void | ||
493 | ecore_con_socks_shutdown(void) | ||
494 | { | ||
495 | Ecore_Con_Socks *ecs; | ||
496 | EINA_LIST_FREE(ecore_con_socks_proxies, ecs) | ||
497 | _ecore_con_socks_free(ecs); | ||
498 | _ecore_con_proxy_once = NULL; | ||
499 | _ecore_con_proxy_global = NULL; | ||
500 | } | ||
501 | |||
502 | void | ||
503 | ecore_con_socks_read(Ecore_Con_Server *svr, unsigned char *buf, int num) | ||
504 | { | ||
505 | ECORE_CON_SOCKS_CAST_ELSE(svr->ecs) return; | ||
506 | |||
507 | if (svr->ecs_state < ECORE_CON_PROXY_STATE_READ) return; | ||
508 | |||
509 | if (v4) _ecore_con_socks_read_v4(svr, v4, buf, (unsigned int)num); | ||
510 | else _ecore_con_socks_read_v5(svr, v5, buf, (unsigned int)num); | ||
511 | } | ||
512 | |||
180 | Eina_Bool | 513 | Eina_Bool |
181 | ecore_con_socks_svr_init(Ecore_Con_Server *svr) | 514 | ecore_con_socks_svr_init(Ecore_Con_Server *svr) |
182 | { | 515 | { |
183 | unsigned char *sbuf; | ||
184 | ECORE_CON_SOCKS_CAST_ELSE(svr->ecs) return EINA_FALSE; | 516 | ECORE_CON_SOCKS_CAST_ELSE(svr->ecs) return EINA_FALSE; |
185 | 517 | ||
186 | if (!svr->ip) return EINA_FALSE; | 518 | if (!svr->ip) return EINA_FALSE; |
187 | if (svr->ecs_buf) return EINA_FALSE; | 519 | if (svr->ecs_buf) return EINA_FALSE; |
188 | if (svr->ecs_state != ECORE_CON_SOCKS_STATE_INIT) return EINA_FALSE; | 520 | if (svr->ecs_state != ECORE_CON_PROXY_STATE_INIT) return EINA_FALSE; |
189 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); | 521 | ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); |
190 | if (v4) | 522 | if (v4) return _ecore_con_socks_svr_init_v4(svr, v4); |
191 | { | 523 | return _ecore_con_socks_svr_init_v5(svr, v5); |
192 | size_t addrlen, buflen, ulen = 1; | ||
193 | addrlen = svr->ecs->lookup ? strlen(svr->name) + 1: 0; | ||
194 | if (svr->ecs->username) ulen += strlen(svr->ecs->username); | ||
195 | buflen = sizeof(char) * (8 + ulen + addrlen); | ||
196 | sbuf = malloc(buflen); | ||
197 | if (!sbuf) | ||
198 | { | ||
199 | ecore_con_event_server_error(svr, "Memory allocation failure!"); | ||
200 | _ecore_con_server_kill(svr); | ||
201 | return EINA_FALSE; | ||
202 | } | ||
203 | /* http://en.wikipedia.org/wiki/SOCKS */ | ||
204 | sbuf[0] = 4; | ||
205 | sbuf[1] = v4->bind ? 2 : 1; | ||
206 | sbuf[2] = svr->port >> 8; | ||
207 | sbuf[3] = svr->port & 0xff; | ||
208 | if (addrlen) | ||
209 | { | ||
210 | sbuf[4] = sbuf[5] = sbuf[6] = 0; | ||
211 | sbuf[7] = 1; | ||
212 | } | ||
213 | else | ||
214 | memcpy(sbuf + 4, svr->ecs_addr, 4); | ||
215 | if (svr->ecs->username) | ||
216 | memcpy(sbuf + 8, svr->ecs->username, ulen); | ||
217 | else | ||
218 | sbuf[8] = 0; | ||
219 | if (addrlen) memcpy(sbuf + 8 + ulen, svr->name, addrlen); | ||
220 | |||
221 | svr->ecs_buf = eina_binbuf_manage_new_length(sbuf, buflen); | ||
222 | } | ||
223 | return EINA_TRUE; | ||
224 | } | 524 | } |
225 | 525 | ||
226 | void | 526 | void |
227 | ecore_con_socks_dns_cb(const char *canonname __UNUSED__, const char *ip, struct sockaddr *addr, int addrlen, Ecore_Con_Server *svr) | 527 | ecore_con_socks_dns_cb(const char *canonname __UNUSED__, const char *ip, struct sockaddr *addr, int addrlen __UNUSED__, Ecore_Con_Server *svr) |
228 | { | 528 | { |
229 | svr->ip = eina_stringshare_add(ip); | 529 | svr->ip = eina_stringshare_add(ip); |
230 | svr->ecs_addrlen = addrlen; | ||
231 | svr->ecs_state++; | 530 | svr->ecs_state++; |
232 | if (addr->sa_family == AF_INET) | 531 | if (addr->sa_family == AF_INET) |
233 | memcpy(svr->ecs_addr, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4); | 532 | { |
533 | memcpy(svr->ecs_addr, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4); | ||
534 | svr->ecs_addrlen = 4; | ||
535 | } | ||
234 | #ifdef HAVE_IPV6 | 536 | #ifdef HAVE_IPV6 |
235 | else | 537 | else |
236 | memcpy(svr->ecs_addr, &((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, addrlen); | 538 | { |
539 | memcpy(svr->ecs_addr, &((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, 16); | ||
540 | svr->ecs_addrlen = 16; | ||
541 | } | ||
237 | #endif | 542 | #endif |
238 | ecore_con_socks_svr_init(svr); | 543 | ecore_con_socks_svr_init(svr); |
239 | } | 544 | } |
@@ -242,36 +547,57 @@ void | |||
242 | ecore_con_socks_init(void) | 547 | ecore_con_socks_init(void) |
243 | { | 548 | { |
244 | const char *socks; | 549 | const char *socks; |
245 | char *u, *h, *p, *l; | 550 | char *h, *p, *l, *u = NULL; |
246 | char buf[64]; | 551 | char buf[512]; |
247 | int port, lookup = 0; | 552 | int port, lookup = 0; |
553 | Eina_Bool v5 = EINA_FALSE; | ||
248 | Ecore_Con_Socks *ecs; | 554 | Ecore_Con_Socks *ecs; |
249 | unsigned char addr[sizeof(struct in_addr)]; | 555 | unsigned char addr[sizeof(struct in_addr)]; |
556 | #ifdef HAVE_IPV6 | ||
557 | unsigned char addr6[sizeof(struct in6_addr)]; | ||
558 | #endif | ||
250 | 559 | ||
251 | /* ECORE_CON_SOCKS_V4=user@host:port:[1|0] */ | 560 | /* ECORE_CON_SOCKS_V4=[user@]host:port-[1|0] */ |
252 | socks = getenv("ECORE_CON_SOCKS_V4"); | 561 | socks = getenv("ECORE_CON_SOCKS_V4"); |
253 | if ((!socks) || (!socks[0]) || (strlen(socks) > 64)) return; | 562 | if (!socks) |
563 | { | ||
564 | /* ECORE_CON_SOCKS_V5=[user@]host-port:[1|0] */ | ||
565 | socks = getenv("ECORE_CON_SOCKS_V5"); | ||
566 | v5 = EINA_TRUE; | ||
567 | } | ||
568 | if ((!socks) || (!socks[0]) || (strlen(socks) > 512)) return; | ||
254 | strncpy(buf, socks, sizeof(buf)); | 569 | strncpy(buf, socks, sizeof(buf)); |
255 | h = strchr(buf, '@'); | 570 | h = strchr(buf, '@'); |
256 | u = NULL; | ||
257 | /* username */ | 571 | /* username */ |
258 | if (h && (h - buf > 0)) *h++ = 0, u = buf; | 572 | if (h && (h - buf > 0)) *h++ = 0, u = buf; |
259 | else h = buf; | 573 | else h = buf; |
260 | 574 | ||
261 | /* host ip; I ain't resolvin shit here */ | 575 | /* host ip; I ain't resolvin shit here */ |
262 | p = strchr(h, ':'); | 576 | p = strchr(h, '-'); |
263 | if (!p) return; | 577 | if (!p) return; |
264 | *p++ = 0; | 578 | *p++ = 0; |
265 | if (!inet_pton(AF_INET, h, addr)) return; | 579 | if (!inet_pton(AF_INET, h, addr)) |
580 | #ifdef HAVE_IPV6 | ||
581 | { | ||
582 | if (!v5) return; | ||
583 | if (!inet_pton(AF_INET6, h, addr6)) | ||
584 | return; | ||
585 | } | ||
586 | #else | ||
587 | return; | ||
588 | #endif | ||
266 | 589 | ||
267 | errno = 0; | 590 | errno = 0; |
268 | port = strtol(p, &l, 10); | 591 | port = strtol(p, &l, 10); |
269 | if (errno || (port < 0) || (port > 65535)) return; | 592 | if (errno || (port < 0) || (port > 65535)) return; |
270 | if (l && (l[0] == ':')) | 593 | if (l && (l[0] == ':')) |
271 | lookup = (l[1] == '1'); | 594 | lookup = (l[1] == '1'); |
272 | ecs = ecore_con_socks4_remote_add(h, port, u); | 595 | if (v5) |
596 | ecs = ecore_con_socks5_remote_add(h, port, u, NULL); | ||
597 | else | ||
598 | ecs = ecore_con_socks4_remote_add(h, port, u); | ||
273 | if (!ecs) return; | 599 | if (!ecs) return; |
274 | ecore_con_socks4_lookup_set(ecs, lookup); | 600 | ecore_con_socks_lookup_set(ecs, lookup); |
275 | ecore_con_socks_apply_always(ecs); | 601 | ecore_con_socks_apply_always(ecs); |
276 | INF("Added global proxy server %s%s%s:%d - DNS lookup %s", | 602 | INF("Added global proxy server %s%s%s:%d - DNS lookup %s", |
277 | u ?: "", u ? "@" : "", h, port, lookup ? "ENABLED" : "DISABLED"); | 603 | u ?: "", u ? "@" : "", h, port, lookup ? "ENABLED" : "DISABLED"); |
@@ -300,10 +626,17 @@ EAPI Ecore_Con_Socks * | |||
300 | ecore_con_socks4_remote_add(const char *ip, int port, const char *username) | 626 | ecore_con_socks4_remote_add(const char *ip, int port, const char *username) |
301 | { | 627 | { |
302 | Ecore_Con_Socks *ecs; | 628 | Ecore_Con_Socks *ecs; |
629 | size_t ulen = 0; | ||
303 | 630 | ||
304 | if ((!ip) || (!ip[0]) || (port < 0) || (port > 65535)) return NULL; | 631 | if ((!ip) || (!ip[0]) || (port < 0) || (port > 65535)) return NULL; |
305 | 632 | ||
306 | ecs = _ecore_con_socks_find(4, ip, port, username); | 633 | if (username) |
634 | { | ||
635 | ulen = strlen(username); | ||
636 | /* max length for protocol */ | ||
637 | if ((!ulen) || (ulen > 255)) return NULL; | ||
638 | } | ||
639 | ecs = _ecore_con_socks_find(4, ip, port, username, ulen, NULL, 0); | ||
307 | if (ecs) return ecs; | 640 | if (ecs) return ecs; |
308 | 641 | ||
309 | ecs = calloc(1, sizeof(Ecore_Con_Socks_v4)); | 642 | ecs = calloc(1, sizeof(Ecore_Con_Socks_v4)); |
@@ -313,92 +646,194 @@ ecore_con_socks4_remote_add(const char *ip, int port, const char *username) | |||
313 | ecs->ip = eina_stringshare_add(ip); | 646 | ecs->ip = eina_stringshare_add(ip); |
314 | ecs->port = port; | 647 | ecs->port = port; |
315 | ecs->username = eina_stringshare_add(username); | 648 | ecs->username = eina_stringshare_add(username); |
649 | ecs->ulen = ulen; | ||
316 | ecore_con_socks_proxies = eina_list_append(ecore_con_socks_proxies, ecs); | 650 | ecore_con_socks_proxies = eina_list_append(ecore_con_socks_proxies, ecs); |
317 | return ecs; | 651 | return ecs; |
318 | } | 652 | } |
319 | 653 | ||
320 | /** | 654 | /** |
321 | * Set DNS lookup mode on an existing SOCKS v4 proxy | 655 | * Find a SOCKS v4 proxy in the proxy list |
322 | * | 656 | * |
323 | * According to RFC, SOCKS v4 does not require that a proxy perform | 657 | * Use this to determine if a SOCKS proxy was previously added by checking |
324 | * its own DNS lookups for addresses. SOCKS v4a specifies the protocol | 658 | * the proxy list against the parameters given. |
325 | * for this. If you want to enable remote DNS lookup and are sure that your | 659 | * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.) |
326 | * proxy supports it, use this function. | 660 | * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip |
327 | * @param ecs The proxy object | 661 | * @param username The username used for the proxy (OPTIONAL) |
328 | * @param enable If true, the proxy will perform the dns lookup | 662 | * @return true only if a proxy exists matching the given params |
329 | * @note By default, this setting is DISABLED. | 663 | * @note This function matches slightly more loosely than ecore_con_socks4_remote_add(), and |
664 | * ecore_con_socks4_remote_add() should be used to return the actual object. | ||
330 | * @since 1.2 | 665 | * @since 1.2 |
331 | */ | 666 | */ |
332 | EAPI void | 667 | EAPI Eina_Bool |
333 | ecore_con_socks4_lookup_set(Ecore_Con_Socks *ecs, Eina_Bool enable) | 668 | ecore_con_socks4_remote_exists(const char *ip, int port, const char *username) |
334 | { | 669 | { |
335 | ECORE_CON_SOCKS_CAST_ELSE(ecs) return; | 670 | if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0]))) |
336 | if (v4) v4->lookup = !!enable; | 671 | return EINA_FALSE; |
672 | return !!_ecore_con_socks_find(4, ip, port, username, username ? strlen(username) : 0, NULL, 0); | ||
337 | } | 673 | } |
338 | 674 | ||
339 | /** | 675 | /** |
340 | * Get DNS lookup mode on an existing SOCKS v4 proxy | 676 | * Remove a SOCKS v4 proxy from the proxy list and delete it |
341 | * | 677 | * |
342 | * According to RFC, SOCKS v4 does not require that a proxy perform | 678 | * Use this to remove a SOCKS proxy from the proxy list by checking |
343 | * its own DNS lookups for addresses. SOCKS v4a specifies the protocol | 679 | * the list against the parameters given. The proxy will then be deleted. |
344 | * for this. This function returns whether lookups are enabled on a proxy object. | 680 | * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.) |
345 | * @param ecs The proxy object | 681 | * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip |
346 | * @return If true, the proxy will perform the dns lookup | 682 | * @param username The username used for the proxy (OPTIONAL) |
347 | * @note By default, this setting is DISABLED. | 683 | * @note This function matches in the same way as ecore_con_socks4_remote_exists(). |
684 | * @warning Be aware that deleting a proxy which is being used WILL ruin your life. | ||
348 | * @since 1.2 | 685 | * @since 1.2 |
349 | */ | 686 | */ |
350 | EAPI Eina_Bool | 687 | EAPI void |
351 | ecore_con_socks4_lookup_get(Ecore_Con_Socks *ecs) | 688 | ecore_con_socks4_remote_del(const char *ip, int port, const char *username) |
352 | { | 689 | { |
353 | ECORE_CON_SOCKS_CAST_ELSE(ecs) return EINA_FALSE; | 690 | Ecore_Con_Socks_v4 *v4; |
354 | return v4 ? v4->lookup : EINA_FALSE; | 691 | |
692 | if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0]))) return; | ||
693 | if (!ecore_con_socks_proxies) return; | ||
694 | |||
695 | v4 = (Ecore_Con_Socks_v4*)_ecore_con_socks_find(4, ip, port, username, username ? strlen(username) : 0, NULL, 0); | ||
696 | if (!v4) return; | ||
697 | ecore_con_socks_proxies = eina_list_remove(ecore_con_socks_proxies, v4); | ||
698 | _ecore_con_socks_free((Ecore_Con_Socks*)v4); | ||
699 | } | ||
700 | /** | ||
701 | * Add a SOCKS v5 proxy to the proxy list | ||
702 | * | ||
703 | * Use this to create (or return, if previously added) a SOCKS proxy | ||
704 | * object which can be used by any ecore_con servers. | ||
705 | * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.) | ||
706 | * @param port The port to connect to on the proxy | ||
707 | * @param username The username to use for the proxy (OPTIONAL) | ||
708 | * @param password The password to use for the proxy (OPTIONAL) | ||
709 | * @return An allocated proxy object, or NULL on failure | ||
710 | * @note This object NEVER needs to be explicitly freed. | ||
711 | * @since 1.2 | ||
712 | */ | ||
713 | EAPI Ecore_Con_Socks * | ||
714 | ecore_con_socks5_remote_add(const char *ip, int port, const char *username, const char *password) | ||
715 | { | ||
716 | Ecore_Con_Socks_v5 *ecs5; | ||
717 | size_t ulen = 0, plen = 0; | ||
718 | |||
719 | if ((!ip) || (!ip[0]) || (port < 0) || (port > 65535)) return NULL; | ||
720 | |||
721 | if (username) | ||
722 | { | ||
723 | ulen = strlen(username); | ||
724 | /* max length for protocol */ | ||
725 | if ((!ulen) || (ulen > 255)) return NULL; | ||
726 | } | ||
727 | if (password) | ||
728 | { | ||
729 | plen = strlen(password); | ||
730 | /* max length for protocol */ | ||
731 | if ((!plen) || (plen > 255)) return NULL; | ||
732 | } | ||
733 | ecs5 = (Ecore_Con_Socks_v5*)_ecore_con_socks_find(5, ip, port, username, ulen, password, plen); | ||
734 | if (ecs5) return (Ecore_Con_Socks*)ecs5; | ||
735 | |||
736 | ecs5 = calloc(1, sizeof(Ecore_Con_Socks_v5)); | ||
737 | if (!ecs5) return NULL; | ||
738 | |||
739 | ecs5->version = 5; | ||
740 | ecs5->ip = eina_stringshare_add(ip); | ||
741 | ecs5->port = port; | ||
742 | ecs5->username = eina_stringshare_add(username); | ||
743 | ecs5->ulen = ulen; | ||
744 | ecs5->password = eina_stringshare_add(password); | ||
745 | ecs5->plen = plen; | ||
746 | ecore_con_socks_proxies = eina_list_append(ecore_con_socks_proxies, ecs5); | ||
747 | return (Ecore_Con_Socks*)ecs5; | ||
355 | } | 748 | } |
356 | 749 | ||
357 | /** | 750 | /** |
358 | * Find a SOCKS v4 proxy in the proxy list | 751 | * Find a SOCKS v5 proxy in the proxy list |
359 | * | 752 | * |
360 | * Use this to determine if a SOCKS proxy was previously added by checking | 753 | * Use this to determine if a SOCKS proxy was previously added by checking |
361 | * the proxy list against the parameters given. | 754 | * the proxy list against the parameters given. |
362 | * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.) | 755 | * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.) |
363 | * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip | 756 | * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip |
364 | * @param username The username used for the proxy (OPTIONAL) | 757 | * @param username The username used for the proxy (OPTIONAL) |
758 | * @param password The password used for the proxy (OPTIONAL) | ||
365 | * @return true only if a proxy exists matching the given params | 759 | * @return true only if a proxy exists matching the given params |
366 | * @note This function matches slightly more loosely than ecore_con_socks4_remote_add(), and | 760 | * @note This function matches slightly more loosely than ecore_con_socks5_remote_add(), and |
367 | * ecore_con_socks4_remote_add() should be used to return the actual object. | 761 | * ecore_con_socks5_remote_add() should be used to return the actual object. |
368 | * @since 1.2 | 762 | * @since 1.2 |
369 | */ | 763 | */ |
370 | EAPI Eina_Bool | 764 | EAPI Eina_Bool |
371 | ecore_con_socks4_remote_exists(const char *ip, int port, const char *username) | 765 | ecore_con_socks5_remote_exists(const char *ip, int port, const char *username, const char *password) |
372 | { | 766 | { |
373 | if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0]))) | 767 | if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0])) || (password && (!password[0]))) |
374 | return EINA_FALSE; | 768 | return EINA_FALSE; |
375 | return !!_ecore_con_socks_find(4, ip, port, username); | 769 | return !!_ecore_con_socks_find(5, ip, port, username, username ? strlen(username) : 0, password, password ? strlen(password) : 0); |
376 | } | 770 | } |
377 | 771 | ||
378 | /** | 772 | /** |
379 | * Remove a SOCKS v4 proxy from the proxy list and delete it | 773 | * Remove a SOCKS v5 proxy from the proxy list and delete it |
380 | * | 774 | * |
381 | * Use this to remove a SOCKS proxy from the proxy list by checking | 775 | * Use this to remove a SOCKS proxy from the proxy list by checking |
382 | * the list against the parameters given. The proxy will then be deleted. | 776 | * the list against the parameters given. The proxy will then be deleted. |
383 | * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.) | 777 | * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.) |
384 | * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip | 778 | * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip |
385 | * @param username The username used for the proxy (OPTIONAL) | 779 | * @param username The username used for the proxy (OPTIONAL) |
780 | * @param password The password used for the proxy (OPTIONAL) | ||
386 | * @note This function matches in the same way as ecore_con_socks4_remote_exists(). | 781 | * @note This function matches in the same way as ecore_con_socks4_remote_exists(). |
387 | * @warning Be aware that deleting a proxy which is being used WILL ruin your life. | 782 | * @warning Be aware that deleting a proxy which is being used WILL ruin your life. |
388 | * @since 1.2 | 783 | * @since 1.2 |
389 | */ | 784 | */ |
390 | EAPI void | 785 | EAPI void |
391 | ecore_con_socks4_remote_del(const char *ip, int port, const char *username) | 786 | ecore_con_socks5_remote_del(const char *ip, int port, const char *username, const char *password) |
392 | { | 787 | { |
393 | Ecore_Con_Socks_v4 *v4; | 788 | Ecore_Con_Socks_v5 *v5; |
394 | 789 | ||
395 | if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0]))) return; | 790 | if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0])) || (password && (!password[0]))) |
791 | return; | ||
396 | if (!ecore_con_socks_proxies) return; | 792 | if (!ecore_con_socks_proxies) return; |
397 | 793 | ||
398 | v4 = (Ecore_Con_Socks_v4*)_ecore_con_socks_find(4, ip, port, username); | 794 | v5 = (Ecore_Con_Socks_v5*)_ecore_con_socks_find(5, ip, port, username, username ? strlen(username) : 0, password, password ? strlen(password) : 0); |
399 | if (!v4) return; | 795 | if (!v5) return; |
400 | ecore_con_socks_proxies = eina_list_remove(ecore_con_socks_proxies, v4); | 796 | ecore_con_socks_proxies = eina_list_remove(ecore_con_socks_proxies, v5); |
401 | _ecore_con_socks_free((Ecore_Con_Socks*)v4); | 797 | _ecore_con_socks_free((Ecore_Con_Socks*)v5); |
798 | } | ||
799 | |||
800 | /** | ||
801 | * Set DNS lookup mode on an existing SOCKS proxy | ||
802 | * | ||
803 | * According to RFC, SOCKS v4 does not require that a proxy perform | ||
804 | * its own DNS lookups for addresses. SOCKS v4a specifies the protocol | ||
805 | * for this. SOCKS v5 allows DNS lookups. | ||
806 | * If you want to enable remote DNS lookup and are sure that your | ||
807 | * proxy supports it, use this function. | ||
808 | * @param ecs The proxy object | ||
809 | * @param enable If true, the proxy will perform the dns lookup | ||
810 | * @note By default, this setting is DISABLED. | ||
811 | * @since 1.2 | ||
812 | */ | ||
813 | EAPI void | ||
814 | ecore_con_socks_lookup_set(Ecore_Con_Socks *ecs, Eina_Bool enable) | ||
815 | { | ||
816 | ECORE_CON_SOCKS_CAST_ELSE(ecs) return; | ||
817 | ecs->lookup = !!enable; | ||
818 | } | ||
819 | |||
820 | /** | ||
821 | * Get DNS lookup mode on an existing SOCKS proxy | ||
822 | * | ||
823 | * According to RFC, SOCKS v4 does not require that a proxy perform | ||
824 | * its own DNS lookups for addresses. SOCKS v4a specifies the protocol | ||
825 | * for this. SOCKS v5 allows DNS lookups. | ||
826 | * This function returns whether lookups are enabled on a proxy object. | ||
827 | * @param ecs The proxy object | ||
828 | * @return If true, the proxy will perform the dns lookup | ||
829 | * @note By default, this setting is DISABLED. | ||
830 | * @since 1.2 | ||
831 | */ | ||
832 | EAPI Eina_Bool | ||
833 | ecore_con_socks_lookup_get(Ecore_Con_Socks *ecs) | ||
834 | { | ||
835 | ECORE_CON_SOCKS_CAST_ELSE(ecs) return EINA_FALSE; | ||
836 | return ecs->lookup; | ||
402 | } | 837 | } |
403 | 838 | ||
404 | /** | 839 | /** |
@@ -434,6 +869,14 @@ ecore_con_socks_bind_get(Ecore_Con_Socks *ecs) | |||
434 | return ecs->bind; | 869 | return ecs->bind; |
435 | } | 870 | } |
436 | 871 | ||
872 | /** | ||
873 | * Return SOCKS version of a SOCKS proxy | ||
874 | * | ||
875 | * Use this function to return the SOCKS protocol version of a proxy | ||
876 | * @param ecs The proxy object | ||
877 | * @return 0 on error, else 4/5 | ||
878 | * @since 1.2 | ||
879 | */ | ||
437 | EAPI unsigned int | 880 | EAPI unsigned int |
438 | ecore_con_socks_version_get(Ecore_Con_Socks *ecs) | 881 | ecore_con_socks_version_get(Ecore_Con_Socks *ecs) |
439 | { | 882 | { |
@@ -482,7 +925,8 @@ ecore_con_socks_apply_once(Ecore_Con_Socks *ecs) | |||
482 | * @see ecore_con_socks_apply_once() | 925 | * @see ecore_con_socks_apply_once() |
483 | * @since 1.2 | 926 | * @since 1.2 |
484 | * @note ecore-con supports setting this through environment variables like so: | 927 | * @note ecore-con supports setting this through environment variables like so: |
485 | * ECORE_CON_SOCKS_V4=[user@]server:port:lookup | 928 | * ECORE_CON_SOCKS_V4=[user@]server-port:lookup |
929 | * ECORE_CON_SOCKS_V5=[user@]server-port:lookup | ||
486 | * user is the OPTIONAL string that would be passed to the proxy as the username | 930 | * user is the OPTIONAL string that would be passed to the proxy as the username |
487 | * server is the IP_ADDRESS of the proxy server | 931 | * server is the IP_ADDRESS of the proxy server |
488 | * port is the port to connect to on the proxy server | 932 | * port is the port to connect to on the proxy server |