Mercurial > pidgin.yaz
comparison src/proxy.c @ 1881:a02584b98823
[gaim-migrate @ 1891]
C:)
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Wed, 23 May 2001 07:59:05 +0000 |
parents | a49ed23b3c02 |
children | 3366311426df |
comparison
equal
deleted
inserted
replaced
1880:b8245bcce7e6 | 1881:a02584b98823 |
---|---|
38 #include <errno.h> | 38 #include <errno.h> |
39 #include <gtk/gtk.h> | 39 #include <gtk/gtk.h> |
40 #include "gaim.h" | 40 #include "gaim.h" |
41 #include "proxy.h" | 41 #include "proxy.h" |
42 | 42 |
43 char proxyhost[128] = { 0 }; | |
44 int proxyport = 0; | |
45 int proxytype = 0; | |
46 char proxyuser[128] = { 0 }; | |
47 char proxypass[128] = { 0 }; | |
48 | |
43 struct PHB { | 49 struct PHB { |
44 GdkInputFunction func; | 50 GdkInputFunction func; |
45 gpointer data; | 51 gpointer data; |
46 char *host; | 52 char *host; |
47 int port; | 53 int port; |
48 char *user; | |
49 char *pass; | |
50 gint inpa; | 54 gint inpa; |
51 }; | 55 }; |
52 | 56 |
53 static void no_one_calls(gpointer data, gint source, GdkInputCondition cond) | 57 static void no_one_calls(gpointer data, gint source, GdkInputCondition cond) |
54 { | 58 { |
155 debug_printf("Proxy says: %s\n", inputline); | 159 debug_printf("Proxy says: %s\n", inputline); |
156 | 160 |
157 if ((memcmp(HTTP_GOODSTRING , inputline, strlen(HTTP_GOODSTRING )) == 0) || | 161 if ((memcmp(HTTP_GOODSTRING , inputline, strlen(HTTP_GOODSTRING )) == 0) || |
158 (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) { | 162 (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) { |
159 phb->func(phb->data, source, GDK_INPUT_READ); | 163 phb->func(phb->data, source, GDK_INPUT_READ); |
160 if (phb->user) { | |
161 g_free(phb->user); | |
162 g_free(phb->pass); | |
163 } | |
164 g_free(phb->host); | 164 g_free(phb->host); |
165 g_free(phb); | 165 g_free(phb); |
166 return; | 166 return; |
167 } | 167 } |
168 | 168 |
169 close(source); | 169 close(source); |
170 phb->func(phb->data, -1, GDK_INPUT_READ); | 170 phb->func(phb->data, -1, GDK_INPUT_READ); |
171 if (phb->user) { | |
172 g_free(phb->user); | |
173 g_free(phb->pass); | |
174 } | |
175 g_free(phb->host); | 171 g_free(phb->host); |
176 g_free(phb); | 172 g_free(phb); |
177 return; | 173 return; |
178 } | 174 } |
179 | 175 |
187 gdk_input_remove(phb->inpa); | 183 gdk_input_remove(phb->inpa); |
188 len = sizeof(error); | 184 len = sizeof(error); |
189 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 185 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
190 close(source); | 186 close(source); |
191 phb->func(phb->data, -1, GDK_INPUT_READ); | 187 phb->func(phb->data, -1, GDK_INPUT_READ); |
192 if (phb->user) { | |
193 g_free(phb->user); | |
194 g_free(phb->pass); | |
195 } | |
196 g_free(phb->host); | 188 g_free(phb->host); |
197 g_free(phb); | 189 g_free(phb); |
198 return; | 190 return; |
199 } | 191 } |
200 fcntl(source, F_SETFL, 0); | 192 fcntl(source, F_SETFL, 0); |
201 | 193 |
202 g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\n", phb->host, phb->port); | 194 g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\n", phb->host, phb->port); |
203 if (send(source, cmd, strlen(cmd), 0) < 0) { | 195 if (send(source, cmd, strlen(cmd), 0) < 0) { |
204 close(source); | 196 close(source); |
205 phb->func(phb->data, -1, GDK_INPUT_READ); | 197 phb->func(phb->data, -1, GDK_INPUT_READ); |
206 if (phb->user) { | 198 g_free(phb->host); |
207 g_free(phb->user); | 199 g_free(phb); |
208 g_free(phb->pass); | 200 return; |
209 } | 201 } |
210 g_free(phb->host); | 202 |
211 g_free(phb); | 203 if (proxyuser) { |
212 return; | |
213 } | |
214 | |
215 if (phb->user) { | |
216 char *t1, *t2; | 204 char *t1, *t2; |
217 t1 = g_strdup_printf("%s:%s", phb->user, phb->pass); | 205 t1 = g_strdup_printf("%s:%s", proxyuser, proxypass); |
218 t2 = tobase64(t1); | 206 t2 = tobase64(t1); |
219 g_free(t1); | 207 g_free(t1); |
220 g_snprintf(cmd, sizeof(cmd), "Proxy-Authorization: Basic %s\r\n", t2); | 208 g_snprintf(cmd, sizeof(cmd), "Proxy-Authorization: Basic %s\r\n", t2); |
221 g_free(t2); | 209 g_free(t2); |
222 if (send(source, cmd, strlen(cmd), 0) < 0) { | 210 if (send(source, cmd, strlen(cmd), 0) < 0) { |
223 close(source); | 211 close(source); |
224 phb->func(phb->data, -1, GDK_INPUT_READ); | 212 phb->func(phb->data, -1, GDK_INPUT_READ); |
225 g_free(phb->user); | |
226 g_free(phb->pass); | |
227 g_free(phb->host); | 213 g_free(phb->host); |
228 g_free(phb); | 214 g_free(phb); |
229 return; | 215 return; |
230 } | 216 } |
231 } | 217 } |
232 | 218 |
233 g_snprintf(cmd, sizeof(cmd), "\r\n"); | 219 g_snprintf(cmd, sizeof(cmd), "\r\n"); |
234 if (send(source, cmd, strlen(cmd), 0) < 0) { | 220 if (send(source, cmd, strlen(cmd), 0) < 0) { |
235 close(source); | 221 close(source); |
236 phb->func(phb->data, -1, GDK_INPUT_READ); | 222 phb->func(phb->data, -1, GDK_INPUT_READ); |
237 if (phb->user) { | |
238 g_free(phb->user); | |
239 g_free(phb->pass); | |
240 } | |
241 g_free(phb->host); | 223 g_free(phb->host); |
242 g_free(phb); | 224 g_free(phb); |
243 return; | 225 return; |
244 } | 226 } |
245 | 227 |
246 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, http_canread, phb); | 228 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, http_canread, phb); |
247 } | 229 } |
248 | 230 |
249 static int proxy_connect_http(char *host, unsigned short port, | 231 static int proxy_connect_http(char *host, unsigned short port, struct PHB *phb) |
250 char *proxyhost, unsigned short proxyport, | |
251 char *user, char *pass, | |
252 struct PHB *phb) | |
253 { | 232 { |
254 struct hostent *hp; | 233 struct hostent *hp; |
255 struct sockaddr_in sin; | 234 struct sockaddr_in sin; |
256 int fd = -1; | 235 int fd = -1; |
257 | 236 |
272 return -1; | 251 return -1; |
273 } | 252 } |
274 | 253 |
275 phb->host = g_strdup(host); | 254 phb->host = g_strdup(host); |
276 phb->port = port; | 255 phb->port = port; |
277 if (user && pass && user[0] && pass[0]) { | |
278 phb->user = g_strdup(user); | |
279 phb->pass = g_strdup(pass); | |
280 } | |
281 | 256 |
282 fcntl(fd, F_SETFL, O_NONBLOCK); | 257 fcntl(fd, F_SETFL, O_NONBLOCK); |
283 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { | 258 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { |
284 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 259 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
285 debug_printf("Connect would have blocked\n"); | 260 debug_printf("Connect would have blocked\n"); |
286 phb->inpa = gdk_input_add(fd, GDK_INPUT_WRITE, http_canwrite, phb); | 261 phb->inpa = gdk_input_add(fd, GDK_INPUT_WRITE, http_canwrite, phb); |
287 } else { | 262 } else { |
288 close(fd); | 263 close(fd); |
289 if (phb->user) { | |
290 g_free(phb->user); | |
291 g_free(phb->pass); | |
292 } | |
293 g_free(phb->host); | 264 g_free(phb->host); |
294 g_free(phb); | 265 g_free(phb); |
295 return -1; | 266 return -1; |
296 } | 267 } |
297 } else { | 268 } else { |
298 int len, error = ETIMEDOUT; | 269 int len, error = ETIMEDOUT; |
299 debug_printf("Connect didn't block\n"); | 270 debug_printf("Connect didn't block\n"); |
300 len = sizeof(error); | 271 len = sizeof(error); |
301 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 272 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
302 close(fd); | 273 close(fd); |
303 if (phb->user) { | |
304 g_free(phb->user); | |
305 g_free(phb->pass); | |
306 } | |
307 g_free(phb->host); | 274 g_free(phb->host); |
308 g_free(phb); | 275 g_free(phb); |
309 return -1; | 276 return -1; |
310 } | 277 } |
311 fcntl(fd, F_SETFL, 0); | 278 fcntl(fd, F_SETFL, 0); |
382 } | 349 } |
383 | 350 |
384 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, s4_canread, phb); | 351 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, s4_canread, phb); |
385 } | 352 } |
386 | 353 |
387 static int proxy_connect_socks4(char *host, unsigned short port, | 354 static int proxy_connect_socks4(char *host, unsigned short port, struct PHB *phb) |
388 char *proxyhost, unsigned short proxyport, | |
389 struct PHB *phb) | |
390 { | 355 { |
391 struct sockaddr_in sin; | 356 struct sockaddr_in sin; |
392 struct hostent *hp; | 357 struct hostent *hp; |
393 int fd = -1; | 358 int fd = -1; |
394 | 359 |
487 buf[5 + strlen(phb->host) + 1] = phb->port & 0xff; | 452 buf[5 + strlen(phb->host) + 1] = phb->port & 0xff; |
488 | 453 |
489 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { | 454 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { |
490 close(source); | 455 close(source); |
491 phb->func(phb->data, -1, GDK_INPUT_READ); | 456 phb->func(phb->data, -1, GDK_INPUT_READ); |
492 if (phb->user) { | |
493 g_free(phb->user); | |
494 g_free(phb->pass); | |
495 } | |
496 g_free(phb->host); | 457 g_free(phb->host); |
497 g_free(phb); | 458 g_free(phb); |
498 return; | 459 return; |
499 } | 460 } |
500 | 461 |
510 debug_printf("got auth response\n"); | 471 debug_printf("got auth response\n"); |
511 | 472 |
512 if (read(source, buf, 2) < 2) { | 473 if (read(source, buf, 2) < 2) { |
513 close(source); | 474 close(source); |
514 phb->func(phb->data, -1, GDK_INPUT_READ); | 475 phb->func(phb->data, -1, GDK_INPUT_READ); |
515 if (phb->user) { | |
516 g_free(phb->user); | |
517 g_free(phb->pass); | |
518 } | |
519 g_free(phb->host); | 476 g_free(phb->host); |
520 g_free(phb); | 477 g_free(phb); |
521 return; | 478 return; |
522 } | 479 } |
523 | 480 |
524 if ((buf[0] != 0x01) || (buf[1] == 0x00)) { | 481 if ((buf[0] != 0x01) || (buf[1] == 0x00)) { |
525 close(source); | 482 close(source); |
526 phb->func(phb->data, -1, GDK_INPUT_READ); | 483 phb->func(phb->data, -1, GDK_INPUT_READ); |
527 if (phb->user) { | |
528 g_free(phb->user); | |
529 g_free(phb->pass); | |
530 } | |
531 g_free(phb->host); | 484 g_free(phb->host); |
532 g_free(phb); | 485 g_free(phb); |
533 return; | 486 return; |
534 } | 487 } |
535 | 488 |
545 debug_printf("able to read\n"); | 498 debug_printf("able to read\n"); |
546 | 499 |
547 if (read(source, buf, 2) < 2) { | 500 if (read(source, buf, 2) < 2) { |
548 close(source); | 501 close(source); |
549 phb->func(phb->data, -1, GDK_INPUT_READ); | 502 phb->func(phb->data, -1, GDK_INPUT_READ); |
550 if (phb->user) { | |
551 g_free(phb->user); | |
552 g_free(phb->pass); | |
553 } | |
554 g_free(phb->host); | 503 g_free(phb->host); |
555 g_free(phb); | 504 g_free(phb); |
556 return; | 505 return; |
557 } | 506 } |
558 | 507 |
559 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { | 508 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { |
560 close(source); | 509 close(source); |
561 phb->func(phb->data, -1, GDK_INPUT_READ); | 510 phb->func(phb->data, -1, GDK_INPUT_READ); |
562 if (phb->user) { | |
563 g_free(phb->user); | |
564 g_free(phb->pass); | |
565 } | |
566 g_free(phb->host); | 511 g_free(phb->host); |
567 g_free(phb); | 512 g_free(phb); |
568 return; | 513 return; |
569 } | 514 } |
570 | 515 |
571 if (buf[1] == 0x02) { | 516 if (buf[1] == 0x02) { |
572 unsigned int i = strlen(phb->user), j = strlen(phb->pass); | 517 unsigned int i = strlen(proxyuser), j = strlen(proxypass); |
573 buf[0] = 0x01; /* version 1 */ | 518 buf[0] = 0x01; /* version 1 */ |
574 buf[1] = i; | 519 buf[1] = i; |
575 memcpy(buf+2, phb->user, i); | 520 memcpy(buf+2, proxyuser, i); |
576 buf[2+i] = j; | 521 buf[2+i] = j; |
577 memcpy(buf+2+i+1, phb->pass, j); | 522 memcpy(buf+2+i+1, proxypass, j); |
578 if (write(source, buf, 3+i+j) < 3+i+j) { | 523 if (write(source, buf, 3+i+j) < 3+i+j) { |
579 close(source); | 524 close(source); |
580 phb->func(phb->data, -1, GDK_INPUT_READ); | 525 phb->func(phb->data, -1, GDK_INPUT_READ); |
581 g_free(phb->user); | |
582 g_free(phb->pass); | |
583 g_free(phb->host); | 526 g_free(phb->host); |
584 g_free(phb); | 527 g_free(phb); |
585 return; | 528 return; |
586 } | 529 } |
587 | 530 |
602 gdk_input_remove(phb->inpa); | 545 gdk_input_remove(phb->inpa); |
603 len = sizeof(error); | 546 len = sizeof(error); |
604 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 547 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
605 close(source); | 548 close(source); |
606 phb->func(phb->data, -1, GDK_INPUT_READ); | 549 phb->func(phb->data, -1, GDK_INPUT_READ); |
607 if (phb->user) { | |
608 g_free(phb->user); | |
609 g_free(phb->pass); | |
610 } | |
611 g_free(phb->host); | 550 g_free(phb->host); |
612 g_free(phb); | 551 g_free(phb); |
613 return; | 552 return; |
614 } | 553 } |
615 fcntl(source, F_SETFL, 0); | 554 fcntl(source, F_SETFL, 0); |
616 | 555 |
617 i = 0; | 556 i = 0; |
618 buf[0] = 0x05; /* SOCKS version 5 */ | 557 buf[0] = 0x05; /* SOCKS version 5 */ |
619 if (phb->user) { | 558 if (proxyuser[0]) { |
620 buf[1] = 0x02; /* two methods */ | 559 buf[1] = 0x02; /* two methods */ |
621 buf[2] = 0x00; /* no authentication */ | 560 buf[2] = 0x00; /* no authentication */ |
622 buf[3] = 0x02; /* username/password authentication */ | 561 buf[3] = 0x02; /* username/password authentication */ |
623 i = 4; | 562 i = 4; |
624 } else { | 563 } else { |
629 | 568 |
630 if (write(source, buf, i) < i) { | 569 if (write(source, buf, i) < i) { |
631 debug_printf("unable to write\n"); | 570 debug_printf("unable to write\n"); |
632 close(source); | 571 close(source); |
633 phb->func(phb->data, -1, GDK_INPUT_READ); | 572 phb->func(phb->data, -1, GDK_INPUT_READ); |
634 if (phb->user) { | |
635 g_free(phb->user); | |
636 g_free(phb->pass); | |
637 } | |
638 g_free(phb->host); | 573 g_free(phb->host); |
639 g_free(phb); | 574 g_free(phb); |
640 return; | 575 return; |
641 } | 576 } |
642 | 577 |
643 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, s5_canread, phb); | 578 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, s5_canread, phb); |
644 } | 579 } |
645 | 580 |
646 static int proxy_connect_socks5(char *host, unsigned short port, | 581 static int proxy_connect_socks5(char *host, unsigned short port, struct PHB *phb) |
647 char *proxyhost, unsigned short proxyport, | |
648 char *user, char *pass, | |
649 struct PHB *phb) | |
650 { | 582 { |
651 int fd = -1; | 583 int fd = -1; |
652 struct sockaddr_in sin; | 584 struct sockaddr_in sin; |
653 struct hostent *hp; | 585 struct hostent *hp; |
654 | 586 |
667 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { | 599 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { |
668 g_free(phb); | 600 g_free(phb); |
669 return -1; | 601 return -1; |
670 } | 602 } |
671 | 603 |
672 if (user && pass && user[0] && pass[0]) { | |
673 phb->user = g_strdup(user); | |
674 phb->pass = g_strdup(pass); | |
675 } | |
676 phb->host = g_strdup(host); | 604 phb->host = g_strdup(host); |
677 phb->port = port; | 605 phb->port = port; |
678 | 606 |
679 fcntl(fd, F_SETFL, O_NONBLOCK); | 607 fcntl(fd, F_SETFL, O_NONBLOCK); |
680 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { | 608 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { |
681 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 609 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
682 debug_printf("Connect would have blocked\n"); | 610 debug_printf("Connect would have blocked\n"); |
683 phb->inpa = gdk_input_add(fd, GDK_INPUT_WRITE, s5_canwrite, phb); | 611 phb->inpa = gdk_input_add(fd, GDK_INPUT_WRITE, s5_canwrite, phb); |
684 } else { | 612 } else { |
685 close(fd); | 613 close(fd); |
686 if (phb->user) { | |
687 g_free(phb->user); | |
688 g_free(phb->pass); | |
689 } | |
690 g_free(phb->host); | 614 g_free(phb->host); |
691 g_free(phb); | 615 g_free(phb); |
692 return -1; | 616 return -1; |
693 } | 617 } |
694 } else { | 618 } else { |
695 int len, error = ETIMEDOUT; | 619 int len, error = ETIMEDOUT; |
696 debug_printf("Connect didn't block\n"); | 620 debug_printf("Connect didn't block\n"); |
697 len = sizeof(error); | 621 len = sizeof(error); |
698 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 622 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
699 close(fd); | 623 close(fd); |
700 if (phb->user) { | |
701 g_free(phb->user); | |
702 g_free(phb->pass); | |
703 } | |
704 g_free(phb->host); | 624 g_free(phb->host); |
705 g_free(phb); | 625 g_free(phb); |
706 return -1; | 626 return -1; |
707 } | 627 } |
708 fcntl(fd, F_SETFL, 0); | 628 fcntl(fd, F_SETFL, 0); |
710 } | 630 } |
711 | 631 |
712 return fd; | 632 return fd; |
713 } | 633 } |
714 | 634 |
715 int proxy_connect(char *host, int port, | 635 int proxy_connect(char *host, int port, GdkInputFunction func, gpointer data) |
716 char *proxyhost, int proxyport, int proxytype, | |
717 char *user, char *pass, | |
718 GdkInputFunction func, gpointer data) | |
719 { | 636 { |
720 struct PHB *phb = g_new0(struct PHB, 1); | 637 struct PHB *phb = g_new0(struct PHB, 1); |
721 phb->func = func; | 638 phb->func = func; |
722 phb->data = data; | 639 phb->data = data; |
723 | 640 |
729 if ((proxytype == PROXY_NONE) || | 646 if ((proxytype == PROXY_NONE) || |
730 !proxyhost || !proxyhost[0] || | 647 !proxyhost || !proxyhost[0] || |
731 !proxyport || (proxyport == -1)) | 648 !proxyport || (proxyport == -1)) |
732 return proxy_connect_none(host, port, phb); | 649 return proxy_connect_none(host, port, phb); |
733 else if (proxytype == PROXY_HTTP) | 650 else if (proxytype == PROXY_HTTP) |
734 return proxy_connect_http(host, port, proxyhost, proxyport, user, pass, phb); | 651 return proxy_connect_http(host, port, phb); |
735 else if (proxytype == PROXY_SOCKS4) | 652 else if (proxytype == PROXY_SOCKS4) |
736 return proxy_connect_socks4(host, port, proxyhost, proxyport, phb); | 653 return proxy_connect_socks4(host, port, phb); |
737 else if (proxytype == PROXY_SOCKS5) | 654 else if (proxytype == PROXY_SOCKS5) |
738 return proxy_connect_socks5(host, port, proxyhost, proxyport, user, pass, phb); | 655 return proxy_connect_socks5(host, port, phb); |
739 | 656 |
740 g_free(phb); | 657 g_free(phb); |
741 return -1; | 658 return -1; |
742 } | 659 } |