1 /*
2  * gaim
3  *
4  * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  */
21 
22 
23 /*
24  * Modified by Nadeem Riaz (nads@bleh.org) (just rewrote the get_address function)
25  * for use in libtoc
26  */
27 
28 #include <netdb.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <time.h>
37 #include <sys/socket.h>
38 #include "toc.h"
39 #include "proxy.h"
40 
41 int proxy_type = 0;
42 char proxy_host[256];
43 int proxy_port = 3128;
44 char *proxy_realhost = NULL;
45 
get_address(char * hostname)46 unsigned int *get_address(char *hostname)
47 {
48 	struct hostent *hp;
49 	unsigned int *sin=NULL;
50 	if ((hp = proxy_gethostbyname(hostname))) {
51 		sin = (unsigned int *) malloc(sizeof(unsigned int));
52 		bcopy((char *)(*(hp->h_addr_list)),(char *)sin,sizeof(hp->h_addr_list));
53 	}
54 	return sin;
55 }
56 
57 
connect_address(unsigned int addy,unsigned short port)58 int connect_address(unsigned int addy, unsigned short port)
59 {
60         int fd;
61 	struct sockaddr_in sin;
62 
63 	sin.sin_addr.s_addr = addy;
64 	sin.sin_family = AF_INET;
65 	sin.sin_port = htons(port);
66 
67 	fd = socket(AF_INET, SOCK_STREAM, 0);
68 
69 	if (fd > -1) {
70 		quad_addr=strdup(inet_ntoa(sin.sin_addr));
71 		if (proxy_connect(fd, (struct sockaddr *)&sin, sizeof(sin)) > -1) {
72 			return fd;
73 		}
74 	}
75 	return -1;
76 }
77 
78 
79 /*
80  * Proxy stuff
81  */
82 
83 /* this code is borrowed from cvs 1.10 */
84 static int
proxy_recv_line(int sock,char ** resultp)85 proxy_recv_line (int sock, char **resultp)
86 {
87     int c;
88     char *result;
89     size_t input_index = 0;
90     size_t result_size = 80;
91 
92     result = (char *) malloc (result_size);
93 
94     while (1)
95     {
96 	char ch;
97 	if (recv (sock, &ch, 1, 0) < 0)
98 	    fprintf (stderr, "recv() error from  proxy server\n");
99 	c = ch;
100 
101 	if (c == EOF)
102 	{
103 	    free (result);
104 
105 	    /* It's end of file.  */
106 	    fprintf(stderr, "end of file from  server\n");
107 	}
108 
109 	if (c == '\012')
110 	    break;
111 
112 	result[input_index++] = c;
113 	while (input_index + 1 >= result_size)
114 	{
115 	    result_size *= 2;
116 	    result = (char *) realloc (result, result_size);
117 	}
118     }
119 
120     if (resultp)
121 	*resultp = result;
122 
123     /* Terminate it just for kicks, but we *can* deal with embedded NULs.  */
124     result[input_index] = '\0';
125 
126     if (resultp == NULL)
127 	free (result);
128     return input_index;
129 }
130 
131 
proxy_gethostbyname(char * host)132 struct hostent *proxy_gethostbyname(char *host)
133 {
134 
135         if (proxy_type == PROXY_NONE)
136                 return (gethostbyname(host));
137 
138         if (proxy_realhost != NULL)
139                 free(proxy_realhost);
140 
141         /* we keep the real host name for the Connect command */
142         proxy_realhost = (char *) strdup(host);
143 
144         return (gethostbyname(proxy_host));
145 
146 }
147 
148 
proxy_connect(int sockfd,struct sockaddr * serv_addr,int addrlen)149 int proxy_connect(int  sockfd, struct sockaddr *serv_addr, int
150                   addrlen )
151 {
152         struct sockaddr_in name;
153         int ret;
154 
155         switch (proxy_type) {
156         case PROXY_NONE:
157                 /* normal use */
158                 return (connect(sockfd,serv_addr,addrlen));
159                 break;
160         case PROXY_HTTP:  /* Http proxy */
161                 /* do the  tunneling */
162                 /* step one : connect to  proxy */
163                 {
164                         struct hostent *hostinfo;
165                         unsigned short shortport = proxy_port;
166 
167                         memset (&name, 0, sizeof (name));
168                         name.sin_family = AF_INET;
169                         name.sin_port = htons (shortport);
170                         hostinfo = gethostbyname (proxy_host);
171                         if (hostinfo == NULL) {
172                                 fprintf (stderr, "Unknown host %s.\n", proxy_host);
173                                 return (-1);
174                         }
175                         name.sin_addr = *(struct in_addr *) hostinfo->h_addr;
176                 }
177                 toc_debug_printf("Trying to connect ...\n");
178                 if ((ret = connect(sockfd,(struct sockaddr *)&name,sizeof(name)))<0)
179                         return(ret);
180 
181                 /* step two : do  proxy tunneling init */
182                 {
183                         char cmd[80];
184                         char *inputline;
185                         unsigned short realport=ntohs(((struct sockaddr_in *)serv_addr)->sin_port);
186                         sprintf(cmd,"CONNECT %s:%d HTTP/1.1\n\r\n\r",proxy_realhost,realport);
187                         toc_debug_printf("<%s>\n",cmd);
188                         if (send(sockfd,cmd,strlen(cmd),0)<0)
189                                 return(-1);
190                         if (proxy_recv_line(sockfd,&inputline) < 0) {
191                                 return(-1);
192                         }
193                         toc_debug_printf("<%s>\n",inputline);
194                         if (memcmp("HTTP/1.0 200 Connection established",inputline,35))
195                                 if (memcmp("HTTP/1.1 200 Connection established",inputline,35)) {
196                                         free(inputline);
197                                         return(-1);
198                                 }
199 
200                         while (strlen(inputline)>1) {
201                                 free(inputline);
202                                 if (proxy_recv_line(sockfd,&inputline) < 0) {
203                                         return(-1);
204                                 }
205                                 toc_debug_printf("<%s>\n",inputline);
206                         }
207                         free(inputline);
208                 }
209 
210                 return ret;
211                 break;
212         case PROXY_SOCKS:
213                 fprintf(stderr,"Socks proxy is not yet implemented.\n");
214                 return(-1);
215                 break;
216         default:
217                 fprintf(stderr,"Unknown proxy type : %d.\n",proxy_type);
218                 break;
219         }
220         return(-1);
221 }
222 
223 
224