xref: /freebsd/contrib/libevent/sample/le-proxy.c (revision b50261e21f39a6c7249a49e7b60aa878c98512a8)
1c43e99fdSEd Maste /*
2c43e99fdSEd Maste   This example code shows how to write an (optionally encrypting) SSL proxy
3c43e99fdSEd Maste   with Libevent's bufferevent layer.
4c43e99fdSEd Maste 
5c43e99fdSEd Maste   XXX It's a little ugly and should probably be cleaned up.
6c43e99fdSEd Maste  */
7c43e99fdSEd Maste 
8c43e99fdSEd Maste // Get rid of OSX 10.7 and greater deprecation warnings.
9c43e99fdSEd Maste #if defined(__APPLE__) && defined(__clang__)
10c43e99fdSEd Maste #pragma clang diagnostic ignored "-Wdeprecated-declarations"
11c43e99fdSEd Maste #endif
12c43e99fdSEd Maste 
13c43e99fdSEd Maste #include <stdio.h>
14c43e99fdSEd Maste #include <assert.h>
15c43e99fdSEd Maste #include <stdlib.h>
16c43e99fdSEd Maste #include <string.h>
17c43e99fdSEd Maste #include <errno.h>
18c43e99fdSEd Maste 
19c43e99fdSEd Maste #ifdef _WIN32
20c43e99fdSEd Maste #include <winsock2.h>
21c43e99fdSEd Maste #include <ws2tcpip.h>
22c43e99fdSEd Maste #else
23c43e99fdSEd Maste #include <sys/socket.h>
24c43e99fdSEd Maste #include <netinet/in.h>
25c43e99fdSEd Maste #endif
26c43e99fdSEd Maste 
27c43e99fdSEd Maste #include <event2/bufferevent_ssl.h>
28c43e99fdSEd Maste #include <event2/bufferevent.h>
29c43e99fdSEd Maste #include <event2/buffer.h>
30c43e99fdSEd Maste #include <event2/listener.h>
31c43e99fdSEd Maste #include <event2/util.h>
32c43e99fdSEd Maste 
33*b50261e2SCy Schubert #include "util-internal.h"
34c43e99fdSEd Maste #include <openssl/ssl.h>
35c43e99fdSEd Maste #include <openssl/err.h>
36c43e99fdSEd Maste #include <openssl/rand.h>
37c43e99fdSEd Maste #include "openssl-compat.h"
38c43e99fdSEd Maste 
39c43e99fdSEd Maste static struct event_base *base;
40c43e99fdSEd Maste static struct sockaddr_storage listen_on_addr;
41c43e99fdSEd Maste static struct sockaddr_storage connect_to_addr;
42c43e99fdSEd Maste static int connect_to_addrlen;
43c43e99fdSEd Maste static int use_wrapper = 1;
44c43e99fdSEd Maste 
45c43e99fdSEd Maste static SSL_CTX *ssl_ctx = NULL;
46c43e99fdSEd Maste 
47c43e99fdSEd Maste #define MAX_OUTPUT (512*1024)
48c43e99fdSEd Maste 
49c43e99fdSEd Maste static void drained_writecb(struct bufferevent *bev, void *ctx);
50c43e99fdSEd Maste static void eventcb(struct bufferevent *bev, short what, void *ctx);
51c43e99fdSEd Maste 
52c43e99fdSEd Maste static void
readcb(struct bufferevent * bev,void * ctx)53c43e99fdSEd Maste readcb(struct bufferevent *bev, void *ctx)
54c43e99fdSEd Maste {
55c43e99fdSEd Maste 	struct bufferevent *partner = ctx;
56c43e99fdSEd Maste 	struct evbuffer *src, *dst;
57c43e99fdSEd Maste 	size_t len;
58c43e99fdSEd Maste 	src = bufferevent_get_input(bev);
59c43e99fdSEd Maste 	len = evbuffer_get_length(src);
60c43e99fdSEd Maste 	if (!partner) {
61c43e99fdSEd Maste 		evbuffer_drain(src, len);
62c43e99fdSEd Maste 		return;
63c43e99fdSEd Maste 	}
64c43e99fdSEd Maste 	dst = bufferevent_get_output(partner);
65c43e99fdSEd Maste 	evbuffer_add_buffer(dst, src);
66c43e99fdSEd Maste 
67c43e99fdSEd Maste 	if (evbuffer_get_length(dst) >= MAX_OUTPUT) {
68c43e99fdSEd Maste 		/* We're giving the other side data faster than it can
69c43e99fdSEd Maste 		 * pass it on.  Stop reading here until we have drained the
70c43e99fdSEd Maste 		 * other side to MAX_OUTPUT/2 bytes. */
71c43e99fdSEd Maste 		bufferevent_setcb(partner, readcb, drained_writecb,
72c43e99fdSEd Maste 		    eventcb, bev);
73c43e99fdSEd Maste 		bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2,
74c43e99fdSEd Maste 		    MAX_OUTPUT);
75c43e99fdSEd Maste 		bufferevent_disable(bev, EV_READ);
76c43e99fdSEd Maste 	}
77c43e99fdSEd Maste }
78c43e99fdSEd Maste 
79c43e99fdSEd Maste static void
drained_writecb(struct bufferevent * bev,void * ctx)80c43e99fdSEd Maste drained_writecb(struct bufferevent *bev, void *ctx)
81c43e99fdSEd Maste {
82c43e99fdSEd Maste 	struct bufferevent *partner = ctx;
83c43e99fdSEd Maste 
84c43e99fdSEd Maste 	/* We were choking the other side until we drained our outbuf a bit.
85c43e99fdSEd Maste 	 * Now it seems drained. */
86c43e99fdSEd Maste 	bufferevent_setcb(bev, readcb, NULL, eventcb, partner);
87c43e99fdSEd Maste 	bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
88c43e99fdSEd Maste 	if (partner)
89c43e99fdSEd Maste 		bufferevent_enable(partner, EV_READ);
90c43e99fdSEd Maste }
91c43e99fdSEd Maste 
92c43e99fdSEd Maste static void
close_on_finished_writecb(struct bufferevent * bev,void * ctx)93c43e99fdSEd Maste close_on_finished_writecb(struct bufferevent *bev, void *ctx)
94c43e99fdSEd Maste {
95c43e99fdSEd Maste 	struct evbuffer *b = bufferevent_get_output(bev);
96c43e99fdSEd Maste 
97c43e99fdSEd Maste 	if (evbuffer_get_length(b) == 0) {
98c43e99fdSEd Maste 		bufferevent_free(bev);
99c43e99fdSEd Maste 	}
100c43e99fdSEd Maste }
101c43e99fdSEd Maste 
102c43e99fdSEd Maste static void
eventcb(struct bufferevent * bev,short what,void * ctx)103c43e99fdSEd Maste eventcb(struct bufferevent *bev, short what, void *ctx)
104c43e99fdSEd Maste {
105c43e99fdSEd Maste 	struct bufferevent *partner = ctx;
106c43e99fdSEd Maste 
107c43e99fdSEd Maste 	if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
108c43e99fdSEd Maste 		if (what & BEV_EVENT_ERROR) {
109c43e99fdSEd Maste 			unsigned long err;
110c43e99fdSEd Maste 			while ((err = (bufferevent_get_openssl_error(bev)))) {
111c43e99fdSEd Maste 				const char *msg = (const char*)
112c43e99fdSEd Maste 				    ERR_reason_error_string(err);
113c43e99fdSEd Maste 				const char *lib = (const char*)
114c43e99fdSEd Maste 				    ERR_lib_error_string(err);
115c43e99fdSEd Maste 				const char *func = (const char*)
116c43e99fdSEd Maste 				    ERR_func_error_string(err);
117c43e99fdSEd Maste 				fprintf(stderr,
118c43e99fdSEd Maste 				    "%s in %s %s\n", msg, lib, func);
119c43e99fdSEd Maste 			}
120c43e99fdSEd Maste 			if (errno)
121c43e99fdSEd Maste 				perror("connection error");
122c43e99fdSEd Maste 		}
123c43e99fdSEd Maste 
124c43e99fdSEd Maste 		if (partner) {
125c43e99fdSEd Maste 			/* Flush all pending data */
126c43e99fdSEd Maste 			readcb(bev, ctx);
127c43e99fdSEd Maste 
128c43e99fdSEd Maste 			if (evbuffer_get_length(
129c43e99fdSEd Maste 				    bufferevent_get_output(partner))) {
130c43e99fdSEd Maste 				/* We still have to flush data from the other
131c43e99fdSEd Maste 				 * side, but when that's done, close the other
132c43e99fdSEd Maste 				 * side. */
133c43e99fdSEd Maste 				bufferevent_setcb(partner,
134c43e99fdSEd Maste 				    NULL, close_on_finished_writecb,
135c43e99fdSEd Maste 				    eventcb, NULL);
136c43e99fdSEd Maste 				bufferevent_disable(partner, EV_READ);
137c43e99fdSEd Maste 			} else {
138c43e99fdSEd Maste 				/* We have nothing left to say to the other
139c43e99fdSEd Maste 				 * side; close it. */
140c43e99fdSEd Maste 				bufferevent_free(partner);
141c43e99fdSEd Maste 			}
142c43e99fdSEd Maste 		}
143c43e99fdSEd Maste 		bufferevent_free(bev);
144c43e99fdSEd Maste 	}
145c43e99fdSEd Maste }
146c43e99fdSEd Maste 
147c43e99fdSEd Maste static void
syntax(void)148c43e99fdSEd Maste syntax(void)
149c43e99fdSEd Maste {
150c43e99fdSEd Maste 	fputs("Syntax:\n", stderr);
151c43e99fdSEd Maste 	fputs("   le-proxy [-s] [-W] <listen-on-addr> <connect-to-addr>\n", stderr);
152c43e99fdSEd Maste 	fputs("Example:\n", stderr);
153c43e99fdSEd Maste 	fputs("   le-proxy 127.0.0.1:8888 1.2.3.4:80\n", stderr);
154c43e99fdSEd Maste 
155c43e99fdSEd Maste 	exit(1);
156c43e99fdSEd Maste }
157c43e99fdSEd Maste 
158c43e99fdSEd Maste static void
accept_cb(struct evconnlistener * listener,evutil_socket_t fd,struct sockaddr * a,int slen,void * p)159c43e99fdSEd Maste accept_cb(struct evconnlistener *listener, evutil_socket_t fd,
160c43e99fdSEd Maste     struct sockaddr *a, int slen, void *p)
161c43e99fdSEd Maste {
162c43e99fdSEd Maste 	struct bufferevent *b_out, *b_in;
163c43e99fdSEd Maste 	/* Create two linked bufferevent objects: one to connect, one for the
164c43e99fdSEd Maste 	 * new connection */
165c43e99fdSEd Maste 	b_in = bufferevent_socket_new(base, fd,
166c43e99fdSEd Maste 	    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
167c43e99fdSEd Maste 
168c43e99fdSEd Maste 	if (!ssl_ctx || use_wrapper)
169c43e99fdSEd Maste 		b_out = bufferevent_socket_new(base, -1,
170c43e99fdSEd Maste 		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
171c43e99fdSEd Maste 	else {
172c43e99fdSEd Maste 		SSL *ssl = SSL_new(ssl_ctx);
173c43e99fdSEd Maste 		b_out = bufferevent_openssl_socket_new(base, -1, ssl,
174c43e99fdSEd Maste 		    BUFFEREVENT_SSL_CONNECTING,
175c43e99fdSEd Maste 		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
176c43e99fdSEd Maste 	}
177c43e99fdSEd Maste 
178c43e99fdSEd Maste 	assert(b_in && b_out);
179c43e99fdSEd Maste 
180c43e99fdSEd Maste 	if (bufferevent_socket_connect(b_out,
181c43e99fdSEd Maste 		(struct sockaddr*)&connect_to_addr, connect_to_addrlen)<0) {
182c43e99fdSEd Maste 		perror("bufferevent_socket_connect");
183c43e99fdSEd Maste 		bufferevent_free(b_out);
184c43e99fdSEd Maste 		bufferevent_free(b_in);
185c43e99fdSEd Maste 		return;
186c43e99fdSEd Maste 	}
187c43e99fdSEd Maste 
188c43e99fdSEd Maste 	if (ssl_ctx && use_wrapper) {
189c43e99fdSEd Maste 		struct bufferevent *b_ssl;
190c43e99fdSEd Maste 		SSL *ssl = SSL_new(ssl_ctx);
191c43e99fdSEd Maste 		b_ssl = bufferevent_openssl_filter_new(base,
192c43e99fdSEd Maste 		    b_out, ssl, BUFFEREVENT_SSL_CONNECTING,
193c43e99fdSEd Maste 		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
194c43e99fdSEd Maste 		if (!b_ssl) {
195c43e99fdSEd Maste 			perror("Bufferevent_openssl_new");
196c43e99fdSEd Maste 			bufferevent_free(b_out);
197c43e99fdSEd Maste 			bufferevent_free(b_in);
198*b50261e2SCy Schubert 			return;
199c43e99fdSEd Maste 		}
200c43e99fdSEd Maste 		b_out = b_ssl;
201c43e99fdSEd Maste 	}
202c43e99fdSEd Maste 
203c43e99fdSEd Maste 	bufferevent_setcb(b_in, readcb, NULL, eventcb, b_out);
204c43e99fdSEd Maste 	bufferevent_setcb(b_out, readcb, NULL, eventcb, b_in);
205c43e99fdSEd Maste 
206c43e99fdSEd Maste 	bufferevent_enable(b_in, EV_READ|EV_WRITE);
207c43e99fdSEd Maste 	bufferevent_enable(b_out, EV_READ|EV_WRITE);
208c43e99fdSEd Maste }
209c43e99fdSEd Maste 
210c43e99fdSEd Maste int
main(int argc,char ** argv)211c43e99fdSEd Maste main(int argc, char **argv)
212c43e99fdSEd Maste {
213c43e99fdSEd Maste 	int i;
214c43e99fdSEd Maste 	int socklen;
215c43e99fdSEd Maste 
216c43e99fdSEd Maste 	int use_ssl = 0;
217c43e99fdSEd Maste 	struct evconnlistener *listener;
218c43e99fdSEd Maste 
219*b50261e2SCy Schubert #ifdef _WIN32
220*b50261e2SCy Schubert 	WORD wVersionRequested;
221*b50261e2SCy Schubert 	WSADATA wsaData;
222*b50261e2SCy Schubert 	wVersionRequested = MAKEWORD(2, 2);
223*b50261e2SCy Schubert 	(void) WSAStartup(wVersionRequested, &wsaData);
224*b50261e2SCy Schubert #endif
225*b50261e2SCy Schubert 
226c43e99fdSEd Maste 	if (argc < 3)
227c43e99fdSEd Maste 		syntax();
228c43e99fdSEd Maste 
229c43e99fdSEd Maste 	for (i=1; i < argc; ++i) {
230c43e99fdSEd Maste 		if (!strcmp(argv[i], "-s")) {
231c43e99fdSEd Maste 			use_ssl = 1;
232c43e99fdSEd Maste 		} else if (!strcmp(argv[i], "-W")) {
233c43e99fdSEd Maste 			use_wrapper = 0;
234c43e99fdSEd Maste 		} else if (argv[i][0] == '-') {
235c43e99fdSEd Maste 			syntax();
236c43e99fdSEd Maste 		} else
237c43e99fdSEd Maste 			break;
238c43e99fdSEd Maste 	}
239c43e99fdSEd Maste 
240c43e99fdSEd Maste 	if (i+2 != argc)
241c43e99fdSEd Maste 		syntax();
242c43e99fdSEd Maste 
243c43e99fdSEd Maste 	memset(&listen_on_addr, 0, sizeof(listen_on_addr));
244c43e99fdSEd Maste 	socklen = sizeof(listen_on_addr);
245c43e99fdSEd Maste 	if (evutil_parse_sockaddr_port(argv[i],
246c43e99fdSEd Maste 		(struct sockaddr*)&listen_on_addr, &socklen)<0) {
247c43e99fdSEd Maste 		int p = atoi(argv[i]);
248c43e99fdSEd Maste 		struct sockaddr_in *sin = (struct sockaddr_in*)&listen_on_addr;
249c43e99fdSEd Maste 		if (p < 1 || p > 65535)
250c43e99fdSEd Maste 			syntax();
251c43e99fdSEd Maste 		sin->sin_port = htons(p);
252c43e99fdSEd Maste 		sin->sin_addr.s_addr = htonl(0x7f000001);
253c43e99fdSEd Maste 		sin->sin_family = AF_INET;
254c43e99fdSEd Maste 		socklen = sizeof(struct sockaddr_in);
255c43e99fdSEd Maste 	}
256c43e99fdSEd Maste 
257c43e99fdSEd Maste 	memset(&connect_to_addr, 0, sizeof(connect_to_addr));
258c43e99fdSEd Maste 	connect_to_addrlen = sizeof(connect_to_addr);
259c43e99fdSEd Maste 	if (evutil_parse_sockaddr_port(argv[i+1],
260c43e99fdSEd Maste 		(struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0)
261c43e99fdSEd Maste 		syntax();
262c43e99fdSEd Maste 
263c43e99fdSEd Maste 	base = event_base_new();
264c43e99fdSEd Maste 	if (!base) {
265c43e99fdSEd Maste 		perror("event_base_new()");
266c43e99fdSEd Maste 		return 1;
267c43e99fdSEd Maste 	}
268c43e99fdSEd Maste 
269c43e99fdSEd Maste 	if (use_ssl) {
270c43e99fdSEd Maste 		int r;
271*b50261e2SCy Schubert #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
272*b50261e2SCy Schubert 	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
273c43e99fdSEd Maste 		SSL_library_init();
274c43e99fdSEd Maste 		ERR_load_crypto_strings();
275c43e99fdSEd Maste 		SSL_load_error_strings();
276c43e99fdSEd Maste 		OpenSSL_add_all_algorithms();
277c43e99fdSEd Maste #endif
278c43e99fdSEd Maste 		r = RAND_poll();
279c43e99fdSEd Maste 		if (r == 0) {
280c43e99fdSEd Maste 			fprintf(stderr, "RAND_poll() failed.\n");
281c43e99fdSEd Maste 			return 1;
282c43e99fdSEd Maste 		}
283c43e99fdSEd Maste 		ssl_ctx = SSL_CTX_new(TLS_method());
284c43e99fdSEd Maste 	}
285c43e99fdSEd Maste 
286c43e99fdSEd Maste 	listener = evconnlistener_new_bind(base, accept_cb, NULL,
287c43e99fdSEd Maste 	    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_REUSEABLE,
288c43e99fdSEd Maste 	    -1, (struct sockaddr*)&listen_on_addr, socklen);
289c43e99fdSEd Maste 
290c43e99fdSEd Maste 	if (! listener) {
291c43e99fdSEd Maste 		fprintf(stderr, "Couldn't open listener.\n");
292c43e99fdSEd Maste 		event_base_free(base);
293c43e99fdSEd Maste 		return 1;
294c43e99fdSEd Maste 	}
295c43e99fdSEd Maste 	event_base_dispatch(base);
296c43e99fdSEd Maste 
297c43e99fdSEd Maste 	evconnlistener_free(listener);
298c43e99fdSEd Maste 	event_base_free(base);
299c43e99fdSEd Maste 
300*b50261e2SCy Schubert #ifdef _WIN32
301*b50261e2SCy Schubert 	WSACleanup();
302*b50261e2SCy Schubert #endif
303*b50261e2SCy Schubert 
304c43e99fdSEd Maste 	return 0;
305c43e99fdSEd Maste }
306