1*709c21c4SNick Mathewson 2*709c21c4SNick Mathewson #include <stdio.h> 3*709c21c4SNick Mathewson #include <assert.h> 4*709c21c4SNick Mathewson #include <stdlib.h> 5*709c21c4SNick Mathewson #include <string.h> 6*709c21c4SNick Mathewson #include <errno.h> 7*709c21c4SNick Mathewson 8*709c21c4SNick Mathewson #include <sys/socket.h> 9*709c21c4SNick Mathewson #include <netinet/in.h> 10*709c21c4SNick Mathewson 11*709c21c4SNick Mathewson #include <event2/bufferevent_ssl.h> 12*709c21c4SNick Mathewson #include <event2/bufferevent.h> 13*709c21c4SNick Mathewson #include <event2/buffer.h> 14*709c21c4SNick Mathewson #include <event2/listener.h> 15*709c21c4SNick Mathewson #include <event2/util.h> 16*709c21c4SNick Mathewson 17*709c21c4SNick Mathewson #include <openssl/ssl.h> 18*709c21c4SNick Mathewson #include <openssl/err.h> 19*709c21c4SNick Mathewson #include <openssl/rand.h> 20*709c21c4SNick Mathewson 21*709c21c4SNick Mathewson static struct event_base *base; 22*709c21c4SNick Mathewson static struct sockaddr_storage listen_on_addr; 23*709c21c4SNick Mathewson static struct sockaddr_storage connect_to_addr; 24*709c21c4SNick Mathewson static int connect_to_addrlen; 25*709c21c4SNick Mathewson static int use_wrapper = 1; 26*709c21c4SNick Mathewson 27*709c21c4SNick Mathewson static SSL_CTX *ssl_ctx = NULL; 28*709c21c4SNick Mathewson 29*709c21c4SNick Mathewson static void 30*709c21c4SNick Mathewson readcb(struct bufferevent *bev, void *ctx) 31*709c21c4SNick Mathewson { 32*709c21c4SNick Mathewson struct bufferevent *partner = ctx; 33*709c21c4SNick Mathewson struct evbuffer *src, *dst; 34*709c21c4SNick Mathewson src = bufferevent_get_input(bev); 35*709c21c4SNick Mathewson if (!partner) { 36*709c21c4SNick Mathewson evbuffer_drain(src, evbuffer_get_length(src)); 37*709c21c4SNick Mathewson return; 38*709c21c4SNick Mathewson } 39*709c21c4SNick Mathewson dst = bufferevent_get_output(partner); 40*709c21c4SNick Mathewson 41*709c21c4SNick Mathewson evbuffer_add_buffer(dst, src); 42*709c21c4SNick Mathewson } 43*709c21c4SNick Mathewson 44*709c21c4SNick Mathewson static void 45*709c21c4SNick Mathewson close_on_finished_writecb(struct bufferevent *bev, void *ctx) 46*709c21c4SNick Mathewson { 47*709c21c4SNick Mathewson struct evbuffer *b = bufferevent_get_output(bev); 48*709c21c4SNick Mathewson if (evbuffer_get_length(b) == 0) { 49*709c21c4SNick Mathewson bufferevent_free(bev); 50*709c21c4SNick Mathewson } 51*709c21c4SNick Mathewson } 52*709c21c4SNick Mathewson 53*709c21c4SNick Mathewson static void 54*709c21c4SNick Mathewson eventcb(struct bufferevent *bev, short what, void *ctx) 55*709c21c4SNick Mathewson { 56*709c21c4SNick Mathewson struct bufferevent *partner = ctx; 57*709c21c4SNick Mathewson 58*709c21c4SNick Mathewson if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) { 59*709c21c4SNick Mathewson if (what & BEV_EVENT_ERROR) 60*709c21c4SNick Mathewson perror("maybe an error"); 61*709c21c4SNick Mathewson 62*709c21c4SNick Mathewson if (partner) { 63*709c21c4SNick Mathewson /* Flush all pending data */ 64*709c21c4SNick Mathewson readcb(bev, ctx); 65*709c21c4SNick Mathewson 66*709c21c4SNick Mathewson /* Disconnect this one from the partner. */ 67*709c21c4SNick Mathewson bufferevent_setcb(partner, 68*709c21c4SNick Mathewson NULL, close_on_finished_writecb, 69*709c21c4SNick Mathewson eventcb, NULL); 70*709c21c4SNick Mathewson } 71*709c21c4SNick Mathewson bufferevent_free(bev); 72*709c21c4SNick Mathewson } 73*709c21c4SNick Mathewson } 74*709c21c4SNick Mathewson 75*709c21c4SNick Mathewson static void 76*709c21c4SNick Mathewson syntax(void) 77*709c21c4SNick Mathewson { 78*709c21c4SNick Mathewson fputs("Syntax:\n", stderr); 79*709c21c4SNick Mathewson fputs(" le-proxy [-s] [-W] <listen-on-addr> <connect-to-addr>\n", stderr); 80*709c21c4SNick Mathewson fputs("Example:\n", stderr); 81*709c21c4SNick Mathewson fputs(" le-proxy 127.0.0.1:8888 1.2.3.4:80\n", stderr); 82*709c21c4SNick Mathewson 83*709c21c4SNick Mathewson exit(1); 84*709c21c4SNick Mathewson } 85*709c21c4SNick Mathewson 86*709c21c4SNick Mathewson static void 87*709c21c4SNick Mathewson accept_cb(struct evconnlistener *listener, evutil_socket_t fd, 88*709c21c4SNick Mathewson struct sockaddr *a, int slen, void *p) 89*709c21c4SNick Mathewson { 90*709c21c4SNick Mathewson struct bufferevent *b_out, *b_in; 91*709c21c4SNick Mathewson /* Create two linked bufferevent objects: one to connect, one for the 92*709c21c4SNick Mathewson * new connection */ 93*709c21c4SNick Mathewson b_in = bufferevent_socket_new(base, fd, 94*709c21c4SNick Mathewson BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); 95*709c21c4SNick Mathewson 96*709c21c4SNick Mathewson if (!ssl_ctx || use_wrapper) 97*709c21c4SNick Mathewson b_out = bufferevent_socket_new(base, -1, 98*709c21c4SNick Mathewson BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); 99*709c21c4SNick Mathewson else { 100*709c21c4SNick Mathewson SSL *ssl = SSL_new(ssl_ctx); 101*709c21c4SNick Mathewson b_out = bufferevent_openssl_socket_new(base, -1, ssl, 102*709c21c4SNick Mathewson BUFFEREVENT_SSL_CONNECTING, 103*709c21c4SNick Mathewson BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); 104*709c21c4SNick Mathewson } 105*709c21c4SNick Mathewson 106*709c21c4SNick Mathewson assert(b_in && b_out); 107*709c21c4SNick Mathewson 108*709c21c4SNick Mathewson if (bufferevent_socket_connect(b_out, 109*709c21c4SNick Mathewson (struct sockaddr*)&connect_to_addr, connect_to_addrlen)<0) { 110*709c21c4SNick Mathewson perror("bufferevent_socket_connect"); 111*709c21c4SNick Mathewson bufferevent_free(b_out); 112*709c21c4SNick Mathewson bufferevent_free(b_in); 113*709c21c4SNick Mathewson return; 114*709c21c4SNick Mathewson } 115*709c21c4SNick Mathewson 116*709c21c4SNick Mathewson if (ssl_ctx && use_wrapper) { 117*709c21c4SNick Mathewson struct bufferevent *b_ssl; 118*709c21c4SNick Mathewson SSL *ssl = SSL_new(ssl_ctx); 119*709c21c4SNick Mathewson b_ssl = bufferevent_openssl_filter_new(base, 120*709c21c4SNick Mathewson b_out, ssl, BUFFEREVENT_SSL_CONNECTING, 121*709c21c4SNick Mathewson BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); 122*709c21c4SNick Mathewson if (!b_ssl) { 123*709c21c4SNick Mathewson perror("Bufferevent_openssl_new"); 124*709c21c4SNick Mathewson bufferevent_free(b_out); 125*709c21c4SNick Mathewson bufferevent_free(b_in); 126*709c21c4SNick Mathewson } 127*709c21c4SNick Mathewson b_out = b_ssl; 128*709c21c4SNick Mathewson } 129*709c21c4SNick Mathewson 130*709c21c4SNick Mathewson bufferevent_setcb(b_in, readcb, NULL, eventcb, b_out); 131*709c21c4SNick Mathewson bufferevent_setcb(b_out, readcb, NULL, eventcb, b_in); 132*709c21c4SNick Mathewson 133*709c21c4SNick Mathewson bufferevent_enable(b_in, EV_READ|EV_WRITE); 134*709c21c4SNick Mathewson bufferevent_enable(b_out, EV_READ|EV_WRITE); 135*709c21c4SNick Mathewson } 136*709c21c4SNick Mathewson 137*709c21c4SNick Mathewson int 138*709c21c4SNick Mathewson main(int argc, char **argv) 139*709c21c4SNick Mathewson { 140*709c21c4SNick Mathewson int i; 141*709c21c4SNick Mathewson int socklen; 142*709c21c4SNick Mathewson 143*709c21c4SNick Mathewson int use_ssl = 0; 144*709c21c4SNick Mathewson struct evconnlistener *listener; 145*709c21c4SNick Mathewson 146*709c21c4SNick Mathewson if (argc < 3) 147*709c21c4SNick Mathewson syntax(); 148*709c21c4SNick Mathewson 149*709c21c4SNick Mathewson for (i=1; i < argc; ++i) { 150*709c21c4SNick Mathewson if (!strcmp(argv[i], "-s")) { 151*709c21c4SNick Mathewson use_ssl = 1; 152*709c21c4SNick Mathewson } else if (!strcmp(argv[i], "-W")) { 153*709c21c4SNick Mathewson use_wrapper = 0; 154*709c21c4SNick Mathewson } else if (argv[i][0] == '-') { 155*709c21c4SNick Mathewson syntax(); 156*709c21c4SNick Mathewson } else 157*709c21c4SNick Mathewson break; 158*709c21c4SNick Mathewson } 159*709c21c4SNick Mathewson 160*709c21c4SNick Mathewson if (i+2 != argc) 161*709c21c4SNick Mathewson syntax(); 162*709c21c4SNick Mathewson 163*709c21c4SNick Mathewson memset(&listen_on_addr, 0, sizeof(listen_on_addr)); 164*709c21c4SNick Mathewson socklen = sizeof(listen_on_addr); 165*709c21c4SNick Mathewson if (evutil_parse_sockaddr_port(argv[i], 166*709c21c4SNick Mathewson (struct sockaddr*)&listen_on_addr, &socklen)<0) { 167*709c21c4SNick Mathewson int p = atoi(argv[i]); 168*709c21c4SNick Mathewson struct sockaddr_in *sin = (struct sockaddr_in*)&listen_on_addr; 169*709c21c4SNick Mathewson if (p < 1 || p > 65535) 170*709c21c4SNick Mathewson syntax(); 171*709c21c4SNick Mathewson sin->sin_port = htons(p); 172*709c21c4SNick Mathewson sin->sin_addr.s_addr = htonl(0x7f000001); 173*709c21c4SNick Mathewson sin->sin_family = AF_INET; 174*709c21c4SNick Mathewson socklen = sizeof(struct sockaddr_in); 175*709c21c4SNick Mathewson } 176*709c21c4SNick Mathewson 177*709c21c4SNick Mathewson memset(&connect_to_addr, 0, sizeof(connect_to_addr)); 178*709c21c4SNick Mathewson connect_to_addrlen = sizeof(connect_to_addr); 179*709c21c4SNick Mathewson if (evutil_parse_sockaddr_port(argv[i+1], 180*709c21c4SNick Mathewson (struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0) 181*709c21c4SNick Mathewson syntax(); 182*709c21c4SNick Mathewson 183*709c21c4SNick Mathewson base = event_base_new(); 184*709c21c4SNick Mathewson if (!base) { 185*709c21c4SNick Mathewson perror("event_base_new()"); 186*709c21c4SNick Mathewson return 1; 187*709c21c4SNick Mathewson } 188*709c21c4SNick Mathewson 189*709c21c4SNick Mathewson if (use_ssl) { 190*709c21c4SNick Mathewson int r; 191*709c21c4SNick Mathewson SSL_library_init(); 192*709c21c4SNick Mathewson ERR_load_crypto_strings(); 193*709c21c4SNick Mathewson SSL_load_error_strings(); 194*709c21c4SNick Mathewson OpenSSL_add_all_algorithms(); 195*709c21c4SNick Mathewson r = RAND_poll(); 196*709c21c4SNick Mathewson if (r == 0) { 197*709c21c4SNick Mathewson fprintf(stderr, "RAND_poll() failed.\n"); 198*709c21c4SNick Mathewson return 1; 199*709c21c4SNick Mathewson } 200*709c21c4SNick Mathewson ssl_ctx = SSL_CTX_new(SSLv23_method()); 201*709c21c4SNick Mathewson } 202*709c21c4SNick Mathewson 203*709c21c4SNick Mathewson listener = evconnlistener_new_bind(base, accept_cb, NULL, 204*709c21c4SNick Mathewson LEV_OPT_CLOSE_ON_FREE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_REUSEABLE, 205*709c21c4SNick Mathewson -1, (struct sockaddr*)&listen_on_addr, socklen); 206*709c21c4SNick Mathewson 207*709c21c4SNick Mathewson event_base_dispatch(base); 208*709c21c4SNick Mathewson 209*709c21c4SNick Mathewson return 0; 210*709c21c4SNick Mathewson } 211