1 /***************************************
2 $Header: /home/amb/CVS/wwwoffle/src/ssl.c,v 1.33 2010-01-19 19:53:29 amb Exp $
3
4 WWWOFFLE - World Wide Web Offline Explorer - Version 2.9f.
5 SSL (Secure Socket Layer) Tunneling functions.
6 ******************/ /******************
7 Written by Andrew M. Bishop
8
9 This file Copyright 1998-2010 Andrew M. Bishop
10 It may be distributed under the GNU Public License, version 2, or
11 any higher version. See section COPYING of the GNU Public license
12 for conditions under which this file may be redistributed.
13 ***************************************/
14
15
16 #include "autoconfig.h"
17
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #if TIME_WITH_SYS_TIME
25 # include <sys/time.h>
26 # include <time.h>
27 #else
28 # if HAVE_SYS_TIME_H
29 # include <sys/time.h>
30 # else
31 # include <time.h>
32 # endif
33 #endif
34
35 #include <errno.h>
36
37 #include "wwwoffle.h"
38 #include "io.h"
39 #include "misc.h"
40 #include "errors.h"
41 #include "config.h"
42 #include "sockets.h"
43 #include "proto.h"
44
45
46 /*+ Set to the name of the proxy if there is one. +*/
47 static URL /*@null@*/ /*@only@*/ *proxyUrl=NULL;
48
49 /*+ The file descriptor of the server. +*/
50 static int server=-1;
51
52
53 /*++++++++++++++++++++++++++++++++++++++
54 Open a connection to get a URL using SSL tunnelling.
55
56 char *SSL_Open Returns NULL on success, a useful message on error.
57
58 URL *Url The URL to open (used for host only).
59 ++++++++++++++++++++++++++++++++++++++*/
60
SSL_Open(URL * Url)61 char *SSL_Open(URL *Url)
62 {
63 char *msg=NULL;
64 char *proxy=NULL;
65 char *server_host=NULL;
66 int server_port=-1;
67
68 /* Sort out the host. */
69
70 if(!IsLocalNetHost(Url->host))
71 proxy=ConfigStringURL(SSLProxy,Url);
72
73 if(proxy)
74 {
75 if(proxyUrl)
76 FreeURL(proxyUrl);
77 proxyUrl=NULL;
78
79 proxyUrl=CreateURL("http",proxy,"/",NULL,NULL,NULL);
80 server_host=proxyUrl->host;
81 server_port=proxyUrl->port;
82 }
83 else
84 {
85 server_host=Url->host;
86 server_port=Url->port;
87 }
88
89 if(server_port==-1)
90 server_port=DefaultPort(Url);
91
92 /* Open the connection. */
93
94 server=-1;
95
96 if(server_port)
97 {
98 server=OpenClientSocket(server_host,server_port);
99
100 if(server==-1)
101 msg=GetPrintMessage(Warning,"Cannot open the https (SSL) connection to %s port %d; [%!s].",server_host,server_port);
102 else
103 {
104 init_io(server);
105 configure_io_timeout(server,ConfigInteger(SocketTimeout),ConfigInteger(SocketTimeout));
106 }
107 }
108 else
109 msg=GetPrintMessage(Warning,"No port given for the https (SSL) connection to %s.",server_host);
110
111 return(msg);
112 }
113
114
115 /*++++++++++++++++++++++++++++++++++++++
116 Write to the server to request the URL and reply to the client.
117
118 char *SSL_Request Returns NULL on success, a useful message on error.
119
120 int client The client socket.
121
122 URL *Url The URL to get (used for host only).
123
124 Header *request_head The head of the HTTP request for the URL.
125 ++++++++++++++++++++++++++++++++++++++*/
126
SSL_Request(int client,URL * Url,Header * request_head)127 char *SSL_Request(int client,URL *Url,Header *request_head)
128 {
129 char *msg=NULL;
130
131 if(proxyUrl)
132 {
133 char *head;
134
135 ModifyRequest(Url,request_head);
136
137 MakeRequestProxyAuthorised(proxyUrl,request_head);
138
139 ChangeURLInHeader(request_head,Url->hostport);
140
141 head=HeaderString(request_head);
142
143 PrintMessage(ExtraDebug,"Outgoing Request Head (to https (SSL) proxy)\n%s",head);
144
145 if(write_string(server,head)==-1)
146 msg=GetPrintMessage(Warning,"Failed to write to remote https (SSL) proxy; [%!s].");
147
148 free(head);
149 }
150 else
151 write_string(client,"HTTP/1.0 200 WWWOFFLE SSL OK\r\n\r\n");
152
153 return(msg);
154 }
155
156
157 /*++++++++++++++++++++++++++++++++++++++
158 Perform the transfer between client and proxy/server.
159
160 int client The client socket.
161 ++++++++++++++++++++++++++++++++++++++*/
162
SSL_Transfer(int client)163 void SSL_Transfer(int client)
164 {
165 int nfd=client>server?client+1:server+1;
166 fd_set readfd;
167 struct timeval tv;
168 int n,nc,ns;
169 char buffer[IO_BUFFER_SIZE];
170
171 while(1)
172 {
173 nc=ns=0;
174
175 FD_ZERO(&readfd);
176
177 FD_SET(server,&readfd);
178 FD_SET(client,&readfd);
179
180 tv.tv_sec=ConfigInteger(SocketTimeout);
181 tv.tv_usec=0;
182
183 n=select(nfd,&readfd,NULL,NULL,&tv);
184
185 if(n<0 && errno==EINTR)
186 continue;
187 else if(n<=0)
188 return;
189
190 if(FD_ISSET(client,&readfd))
191 {
192 nc=read_data(client,buffer,IO_BUFFER_SIZE);
193 if(nc>0)
194 write_data(server,buffer,nc);
195 }
196 if(FD_ISSET(server,&readfd))
197 {
198 ns=read_data(server,buffer,IO_BUFFER_SIZE);
199 if(ns>0)
200 write_data(client,buffer,ns);
201 }
202
203 if(nc==0 && ns==0)
204 return;
205 }
206 }
207
208
209 /*++++++++++++++++++++++++++++++++++++++
210 Close a connection opened using SSL.
211
212 int SSL_Close Return 0 on success, -1 on error.
213 ++++++++++++++++++++++++++++++++++++++*/
214
SSL_Close(void)215 int SSL_Close(void)
216 {
217 unsigned long r,w;
218
219 finish_tell_io(server,&r,&w);
220
221 PrintMessage(Inform,"Server bytes; %d Read, %d Written.",r,w); /* Used in audit-usage.pl */
222
223 if(proxyUrl)
224 FreeURL(proxyUrl);
225 proxyUrl=NULL;
226
227 return(CloseSocket(server));
228 }
229