1 /*
2    ratproxy - SSL worker
3    ---------------------
4 
5    This helper process is launched on CONNECT requests to act as a
6    SSL MITM intermediary.
7 
8    Author: Michal Zalewski <lcamtuf@google.com>
9 
10    Copyright 2007, 2008 by Google Inc. All Rights Reserved.
11 
12    Licensed under the Apache License, Version 2.0 (the "License");
13    you may not use this file except in compliance with the License.
14    You may obtain a copy of the License at
15 
16      http://www.apache.org/licenses/LICENSE-2.0
17 
18    Unless required by applicable law or agreed to in writing, software
19    distributed under the License is distributed on an "AS IS" BASIS,
20    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21    See the License for the specific language governing permissions and
22    limitations under the License.
23 
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <string.h>
35 #include <sys/wait.h>
36 #include <ctype.h>
37 #include <netdb.h>
38 #include <openssl/ssl.h>
39 #include <openssl/err.h>
40 #include <time.h>
41 
42 #include "config.h"
43 #include "types.h"
44 #include "debug.h"
45 #include "ssl.h"
46 
47 _s32 ssl_cli_tap,		/* Client traffic tap      */
48      ssl_srv_tap;		/* Server traffic tap      */
49 
50 static _s32 ssl_cli_tap_b,	/* Rear end of client tap  */
51             ssl_srv_tap_b,	/* Rear end of server tap  */
52 	    ssl_pid;		/* SSL worker PID          */
53 
54 
55 static _u8 rdbuf[MAXLINE],	/* Internal I/O buffer     */
56 	   init_ok;		/* Initialization state    */
57 
58 
59 /* Prepare pipes for SSL worker */
ssl_setup(void)60 void ssl_setup(void) {
61   int p[2];
62 
63   if (init_ok) fatal("ssl_setup() called twice");
64   init_ok = 1;
65 
66   if (socketpair(AF_UNIX,SOCK_STREAM,0,p)) pfatal("socketpair() failed");
67 
68   ssl_cli_tap = p[0];
69   ssl_cli_tap_b = p[1];
70 
71   if (socketpair(AF_UNIX,SOCK_STREAM,0,p)) pfatal("socketpair() failed");
72 
73   ssl_srv_tap = p[0];
74   ssl_srv_tap_b = p[1];
75 
76 }
77 
78 
79 /* Clean up SSL worker */
ssl_shutdown(void)80 void ssl_shutdown(void) {
81   int st;
82 
83   if (init_ok != 2) fatal("ssl_shutdown() called prior to ssl_start()");
84   init_ok = 0;
85 
86   if (ssl_pid > 0) {
87     ssl_pid = 0;
88     close(ssl_cli_tap);
89     close(ssl_srv_tap);
90     wait(&st);
91   }
92 
93 }
94 
95 
96 /* Display SSL-enabled error message */
97 
98 #define ssl_fatal(reason,err) do { \
99     if (init_ok == 2) \
100       ERR_print_errors(err); \
101     fatal("%s", reason); \
102   } while (1)
103 
104 
105 /* Start SSL worker and do the dirty job */
ssl_start(_s32 srv_fd,_s32 cli_fd)106 void ssl_start(_s32 srv_fd, _s32 cli_fd) {
107   SSL_CTX *cli_ctx, *srv_ctx;
108   SSL *cli_ssl, *srv_ssl;
109   BIO* err;
110   _s32 i;
111   _u8 no_client = (cli_fd < 0);
112 
113   if (!init_ok || init_ok == 2) fatal("ssl_start() called out of order");
114   init_ok = 2;
115 
116   ssl_pid = fork();
117 
118   if (ssl_pid < 0) pfatal("fork() failed");
119 
120   /* Make sure that each endpoint has just the right set of pipes */
121 
122   if (ssl_pid) {
123 
124     close(ssl_cli_tap_b);
125     close(ssl_srv_tap_b);
126     ssl_cli_tap_b  = -1;
127     ssl_srv_tap_b  = -1;
128     return;
129 
130   }
131 
132   close(ssl_cli_tap);
133   close(ssl_srv_tap);
134   ssl_cli_tap  = -1;
135   ssl_srv_tap  = -1;
136 
137   SSL_library_init();
138   SSL_load_error_strings();
139 
140   err = BIO_new_fp(stderr,BIO_NOCLOSE);
141   srv_ctx = SSL_CTX_new(SSLv23_client_method()); /* To server */
142   cli_ctx = SSL_CTX_new(SSLv23_server_method()); /* To client */
143 
144   if (!srv_ctx || !cli_ctx || !err) ssl_fatal("unable to create SSL CTX or BIO", err);
145 
146   if (SSL_CTX_use_certificate_chain_file(cli_ctx,"keyfile.pem") != 1)
147     ssl_fatal("certificate load failed", err);
148 
149   if (SSL_CTX_use_PrivateKey_file(cli_ctx,"keyfile.pem",SSL_FILETYPE_PEM) != 1)
150     ssl_fatal("private key load failed", err);
151 
152   cli_ssl = SSL_new(cli_ctx);
153   srv_ssl = SSL_new(srv_ctx);
154 
155   if (!srv_ssl || !cli_ssl) ssl_fatal("unable to create SSL objects", err);
156 
157   SSL_set_fd(srv_ssl, srv_fd);
158   if (SSL_connect(srv_ssl) != 1) ssl_fatal("server SSL handshake failed", err);
159 
160   if (!no_client) {
161     SSL_set_fd(cli_ssl, cli_fd);
162     if (SSL_accept(cli_ssl) != 1) ssl_fatal("client SSL handshake failed", err);
163   }
164 
165   while (1) {
166     _s32 fmax = 0;
167 
168     fd_set fds;
169 
170     FD_ZERO(&fds);
171 
172     if (!no_client) {
173       FD_SET(cli_fd,&fds);
174       fmax = cli_fd;
175       FD_SET(ssl_cli_tap_b,&fds);
176       if (ssl_cli_tap_b > fmax) fmax = ssl_cli_tap_b;
177     }
178 
179     if (ssl_srv_tap_b > 0) {
180       FD_SET(srv_fd,&fds);
181       if (srv_fd > fmax) fmax = srv_fd;
182       FD_SET(ssl_srv_tap_b,&fds);
183       if (ssl_srv_tap_b > fmax) fmax = ssl_srv_tap_b;
184     }
185 
186     if (select(1 + fmax, &fds, 0, 0, 0) <= 0) exit(0);
187 
188     /* Real client sending - send to cli_tap socket. */
189     if (!no_client && FD_ISSET(cli_fd,&fds)) {
190       i = SSL_read(cli_ssl,rdbuf,sizeof(rdbuf));
191       if (i <= 0) exit(0);
192       if (write(ssl_cli_tap_b,rdbuf,i) != i)
193         pfatal("short write to client tap");
194     }
195 
196     /* Real server sending - send to srv_tap socket. */
197     if (ssl_srv_tap_b > 0 && FD_ISSET(srv_fd,&fds)) {
198       i = SSL_read(srv_ssl,rdbuf,sizeof(rdbuf));
199       if (i <= 0) {
200 
201         /* In no_client mode, server shutdown means end of work. */
202 
203         if (no_client) exit(0);
204 
205         /* In client mode, we still want to relay proxy-processed
206            client response before exiting. Just let the proxy
207            know by shutting down the server tap. */
208 
209         close(ssl_srv_tap_b);
210         ssl_srv_tap_b = -1;
211       } else {
212         if (write(ssl_srv_tap_b,rdbuf,i) != i)
213           pfatal("short write to server tap");
214       }
215     }
216 
217     /* Data from srv_tap socket - send to server. */
218     if (ssl_srv_tap_b > 0 && FD_ISSET(ssl_srv_tap_b,&fds)) {
219       i = read(ssl_srv_tap_b,rdbuf,sizeof(rdbuf));
220       if (i <= 0) exit(0);
221       if (SSL_write(srv_ssl,rdbuf,i) != i) exit(0);
222     }
223 
224     /* Data from cli_tap socket - send to client. */
225     if (!no_client && FD_ISSET(ssl_cli_tap_b,&fds)) {
226       i = read(ssl_cli_tap_b,rdbuf,sizeof(rdbuf));
227       if (i <= 0) exit(0);
228       if (SSL_write(cli_ssl,rdbuf,i) != i) exit(0);
229     }
230 
231   }
232 
233 }
234