diff --git a/nsock/src/Makefile.in b/nsock/src/Makefile.in index 9a07b2754..c33b82b6b 100644 --- a/nsock/src/Makefile.in +++ b/nsock/src/Makefile.in @@ -27,9 +27,9 @@ NBASEDIR=@NBASEDIR@ TARGET = libnsock.a -SRCS = error.c filespace.c gh_list.c nsock_connect.c nsock_core.c nsock_iod.c nsock_proxy.c nsock_read.c nsock_timers.c nsock_write.c nsock_ssl.c nsock_event.c nsock_pool.c netutils.c nsock_pcap.c nsock_engines.c engine_select.c engine_epoll.c engine_kqueue.c engine_poll.c nsock_log.c @COMPAT_SRCS@ +SRCS = error.c filespace.c gh_list.c nsock_connect.c nsock_core.c nsock_iod.c nsock_proxy.c nsock_read.c nsock_timers.c nsock_write.c nsock_ssl.c nsock_event.c nsock_pool.c netutils.c nsock_pcap.c nsock_engines.c engine_select.c engine_epoll.c engine_kqueue.c engine_poll.c nsock_log.c proxy_http.c @COMPAT_SRCS@ -OBJS = error.o filespace.o gh_list.o nsock_connect.o nsock_core.o nsock_iod.o nsock_proxy.o nsock_read.o nsock_timers.o nsock_write.o nsock_ssl.o nsock_event.o nsock_pool.o netutils.o nsock_pcap.o nsock_engines.o engine_select.o engine_epoll.o engine_kqueue.o engine_poll.o nsock_log.o @COMPAT_OBJS@ +OBJS = error.o filespace.o gh_list.o nsock_connect.o nsock_core.o nsock_iod.o nsock_proxy.o nsock_read.o nsock_timers.o nsock_write.o nsock_ssl.o nsock_event.o nsock_pool.o netutils.o nsock_pcap.o nsock_engines.o engine_select.o engine_epoll.o engine_kqueue.o engine_poll.o nsock_log.o proxy_http.o @COMPAT_OBJS@ DEPS = error.h filespace.h gh_list.h nsock_internal.h netutils.h nsock_pcap.h nsock_log.h nsock_proxy.h ../include/nsock.h $(NBASEDIR)/libnbase.a diff --git a/nsock/src/nsock_connect.c b/nsock/src/nsock_connect.c index a0e9fba90..f6614d7a4 100644 --- a/nsock/src/nsock_connect.c +++ b/nsock/src/nsock_connect.c @@ -67,7 +67,7 @@ /* Defined in nsock_proxy.c */ -extern struct proxy_op ProxyOps[]; +extern struct proxy_op *ProxyOps[]; /* Create the actual socket (nse->iod->sd) underlying the iod. This unblocks the diff --git a/nsock/src/nsock_proxy.c b/nsock/src/nsock_proxy.c index d7a0a63d8..2e6608bf1 100644 --- a/nsock/src/nsock_proxy.c +++ b/nsock/src/nsock_proxy.c @@ -85,26 +85,15 @@ static void proxy_parser_delete(struct proxy_parser *parser); static struct proxy_node *proxy_node_new(char *proxystr); static void proxy_node_delete(struct proxy_node *proxy); -static void nsock_proxy_ev_handler(nsock_pool nspool, nsock_event nsevent, void *udata); -static void forward_event(mspool *nsp, msevent *nse, void *udata); - -static void proxy_http_node_init(struct proxy_node *proxy, char *proxystr); -static void proxy_http_ev_handler(nsock_pool nspool, nsock_event nsevent, void *udata); +void nsock_proxy_ev_dispatch(nsock_pool nspool, nsock_event nsevent, void *udata); +void forward_event(mspool *nsp, msevent *nse, void *udata); -static nsock_event_id proxy_http_connect_tcp(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, - int timeout_msecs, void *userdata, struct sockaddr *saddr, - size_t sslen, unsigned short port); -static char *proxy_http_data_encode(const char *src, size_t len, size_t *dlen); -static char *proxy_http_data_decode(const char *src, size_t len, size_t *dlen); +extern struct proxy_op proxy_http; - -const struct proxy_op ProxyOps[PROXY_TYPE_COUNT] = { - [PROXY_TYPE_HTTP] = { - .connect_tcp = proxy_http_connect_tcp, - .data_encode = proxy_http_data_encode, - .data_decode = proxy_http_data_decode - } +/* Ensure that the proxy_op for PROXY_XX is at the PROXY_TYPE_XX index. */ +const struct proxy_op *ProxyOps[PROXY_TYPE_COUNT] = { + [PROXY_TYPE_HTTP] = &proxy_http }; @@ -231,13 +220,12 @@ static struct proxy_node *proxy_node_new(char *proxystr) { proxy = (struct proxy_node *)safe_zalloc(sizeof(struct proxy_node)); - if (strncasecmp(proxystr, "http://", 7) != 0) { + if (strncasecmp(proxystr, "http://", 7) == 0) { + ProxyOps[PROXY_TYPE_HTTP]->init(proxy, proxystr); + } else { fatal("Invalid protocol in proxy specification string: %s", proxystr); } - proxy->px_type = PROXY_TYPE_HTTP; - proxy_http_node_init(proxy, proxystr); - return proxy; } @@ -266,7 +254,7 @@ void forward_event(mspool *nsp, msevent *nse, void *udata) { nse->status = cached_status; } -void nsock_proxy_ev_handler(nsock_pool nspool, nsock_event nsevent, void *udata) { +void nsock_proxy_ev_dispatch(nsock_pool nspool, nsock_event nsevent, void *udata) { msevent *nse = (msevent *)nsevent; struct proxy_node *current; @@ -274,121 +262,8 @@ void nsock_proxy_ev_handler(nsock_pool nspool, nsock_event nsevent, void *udata) fatal("Error, but this is debug only!"); current = PROXY_CTX_CURRENT(nse->iod->px_ctx); - switch (current->px_type) { - case PROXY_TYPE_HTTP: - proxy_http_ev_handler(nspool, nsevent, udata); - break; - default: - fatal("Invalid proxy type (%d)", current->px_type); - } -} - -void proxy_http_node_init(struct proxy_node *proxy, char *proxystr) { - struct sockaddr_in *sin; - char *strhost, *strport, *saveptr; - - strhost = strtok_r(proxystr + 7, ":", &saveptr); - strport = strtok_r(NULL, ":", &saveptr); - if (strport == NULL) - strport = "8080"; - - sin = (struct sockaddr_in *)&proxy->ss; - sin->sin_family = AF_INET; - inet_pton(AF_INET, strhost, &sin->sin_addr); - - proxy->sslen = sizeof(struct sockaddr_in); - proxy->port = (unsigned short)atoi(strport); -} - -void proxy_http_ev_handler(nsock_pool nspool, nsock_event nsevent, void *udata) { - mspool *nsp = (mspool *)nspool; - msevent *nse = (msevent *)nsevent; - struct sockaddr_storage *ss; - size_t sslen; - unsigned short port; - - switch (nse->iod->px_ctx->px_state) { - case PROXY_STATE_INITIAL: - nse->iod->px_ctx->px_state = PROXY_STATE_HTTP_TCP_CONNECTED; - - if (PROXY_CTX_NEXT(nse->iod->px_ctx)) { - struct proxy_node *next; - - next = PROXY_CTX_NEXT(nse->iod->px_ctx); - ss = &next->ss; - sslen = next->sslen; - port = next->port; - } else { - ss = &nse->iod->px_ctx->target_ss; - sslen = nse->iod->px_ctx->target_sslen; - port = nse->iod->px_ctx->target_port; - } - nsock_printf(nspool, (nsock_iod)nse->iod, nsock_proxy_ev_handler, - 4000, udata, "CONNECT %s:%d HTTP/1.1\r\n\r\n", - inet_ntop_ez(ss, sslen), (int)port); - nsock_readlines(nspool, (nsock_iod)nse->iod, nsock_proxy_ev_handler, 4000, udata, 1); - break; - - case PROXY_STATE_HTTP_TCP_CONNECTED: - if (nse->type == NSE_TYPE_READ) { - char *res; - int reslen; - - res = nse_readbuf(nse, &reslen); - - /* TODO string check!! */ - if ((reslen >= 15) && strstr(res, "200 OK")) { - nse->iod->px_ctx->px_state = PROXY_STATE_HTTP_TUNNEL_ESTABLISHED; - } - - if (nse->iod->px_ctx->px_current->next == NULL) { - forward_event(nsp, nse, udata); - } else { - nse->iod->px_ctx->px_current = nse->iod->px_ctx->px_current->next; - nse->iod->px_ctx->px_state = PROXY_STATE_INITIAL; - - nsock_proxy_ev_handler(nsp, nse, udata); - } - } - break; - - case PROXY_STATE_HTTP_TUNNEL_ESTABLISHED: - forward_event(nsp, nse, udata); - break; - - default: - fatal("Invalid proxy state!"); - } -} - -nsock_event_id proxy_http_connect_tcp(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, - int timeout_msecs, void *userdata, struct sockaddr *saddr, - size_t sslen, unsigned short port) { - msiod *nsi = (msiod *)ms_iod; - struct proxy_node *current; - - memcpy(&nsi->px_ctx->target_ss, saddr, sslen); - nsi->px_ctx->target_sslen = sslen; - nsi->px_ctx->target_port = port; - nsi->px_ctx->target_handler = handler; - - current = PROXY_CTX_CURRENT(nsi->px_ctx); - saddr = (struct sockaddr *)¤t->ss; - sslen = current->sslen; - port = current->port; - handler = nsock_proxy_ev_handler; - - return nsock_connect_tcp_direct(nsp, ms_iod, handler, timeout_msecs, userdata, saddr, sslen, port); -} - -char *proxy_http_data_encode(const char *src, size_t len, size_t *dlen) { - // TODO - return NULL; -} - -char *proxy_http_data_decode(const char *src, size_t len, size_t *dlen) { - // TODO - return NULL; + assert(current->px_type > 0 && current->px_type < PROXY_TYPE_COUNT); + ProxyOps[current->px_type]->handler(nspool, nsevent, udata); } diff --git a/nsock/src/nsock_proxy.h b/nsock/src/nsock_proxy.h index fbe33a430..d70417166 100644 --- a/nsock/src/nsock_proxy.h +++ b/nsock/src/nsock_proxy.h @@ -66,9 +66,9 @@ #define PROXY_CTX_NEXT(ctx) ((struct proxy_node *)((GH_LIST_ELEM_NEXT((ctx)->px_current)) ? GH_LIST_ELEM_DATA(GH_LIST_ELEM_NEXT((ctx)->px_current)) : NULL)) #define PROXY_CTX_NODES(ctx) ((ctx)->px_chain->nodes) -#define IOD_PX_TCP_CONNECT(iod) (ProxyOps[PROXY_CTX_CURRENT((iod)->px_ctx)->px_type].connect_tcp) -#define IOD_PX_DATA_ENCODE(iod) (ProxyOps[PROXY_CTX_CURRENT((iod)->px_ctx)->px_type].data_encode) -#define IOD_PX_DATA_DECODE(iod) (ProxyOps[PROXY_CTX_CURRENT((iod)->px_ctx)->px_type].data_decode) +#define IOD_PX_TCP_CONNECT(iod) (ProxyOps[PROXY_CTX_CURRENT((iod)->px_ctx)->px_type]->connect_tcp) +#define IOD_PX_DATA_ENCODE(iod) (ProxyOps[PROXY_CTX_CURRENT((iod)->px_ctx)->px_type]->data_encode) +#define IOD_PX_DATA_DECODE(iod) (ProxyOps[PROXY_CTX_CURRENT((iod)->px_ctx)->px_type]->data_decode) /* ------------------- CONSTANTS ------------------- */ @@ -117,6 +117,8 @@ struct proxy_chain_context { }; struct proxy_op { + void (*init)(struct proxy_node *proxy, char *proxystr); + void (*handler)(nsock_pool nspool, nsock_event nsevent, void *udata); nsock_event_id (*connect_tcp)(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, int mstimeout, void *userdata, struct sockaddr *saddr, size_t sslen, unsigned short port); char *(*data_encode)(const char *src, size_t len, size_t *dlen); diff --git a/nsock/src/proxy_http.c b/nsock/src/proxy_http.c new file mode 100644 index 000000000..83f87f4c8 --- /dev/null +++ b/nsock/src/proxy_http.c @@ -0,0 +1,196 @@ +/*************************************************************************** + * proxy_http.c -- HTTP Connect proxying. * + * * + ***********************IMPORTANT NSOCK LICENSE TERMS*********************** + * * + * The nsock parallel socket event library is (C) 1999-2012 Insecure.Com * + * LLC This library is free software; you may redistribute and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; Version 2. This guarantees * + * your right to use, modify, and redistribute this software under certain * + * conditions. If this license is unacceptable to you, Insecure.Com LLC * + * may be willing to sell alternative licenses (contact * + * sales@insecure.com ). * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement stating * + * terms other than the (GPL) terms above, then that alternative license * + * agreement takes precedence over this comment. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details * + * (http://www.gnu.org/licenses/gpl-2.0.html). * + * * + ***************************************************************************/ + +/* $Id $ */ + +#include "nsock.h" +#include "nsock_internal.h" +#include +#include + +#define DEFAULT_PROXY_PORT_HTTP "8080" + + +/* Defined in nsock_proxy.c */ +void nsock_proxy_ev_dispatch(nsock_pool nspool, nsock_event nsevent, void *udata); +void forward_event(mspool *nsp, msevent *nse, void *udata); + +/* --- PROXY INTERFACE PROTOTYPES --- */ +static void proxy_http_init(struct proxy_node *proxy, char *proxystr); +static void proxy_http_handler(nsock_pool nspool, nsock_event nsevent, void *udata); +static nsock_event_id proxy_http_connect_tcp(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, + int timeout_msecs, void *userdata, struct sockaddr *saddr, + size_t sslen, unsigned short port); +static char *proxy_http_data_encode(const char *src, size_t len, size_t *dlen); +static char *proxy_http_data_decode(const char *src, size_t len, size_t *dlen); + + +/* ---- PROXY DEFINITION ---- */ +struct proxy_op proxy_http = { + .init = proxy_http_init, + .handler = proxy_http_handler, + .connect_tcp = proxy_http_connect_tcp, + .data_encode = proxy_http_data_encode, + .data_decode = proxy_http_data_decode +}; + + +void proxy_http_init(struct proxy_node *proxy, char *proxystr) { + struct sockaddr_in *sin; + char *strhost, *strport, *saveptr; + + strhost = strtok_r(proxystr + 7, ":", &saveptr); + strport = strtok_r(NULL, ":", &saveptr); + if (strport == NULL) + strport = DEFAULT_PROXY_PORT_HTTP; + + sin = (struct sockaddr_in *)&proxy->ss; + sin->sin_family = AF_INET; + inet_pton(AF_INET, strhost, &sin->sin_addr); + + proxy->sslen = sizeof(struct sockaddr_in); + proxy->port = (unsigned short)atoi(strport); +} + +void proxy_http_handler(nsock_pool nspool, nsock_event nsevent, void *udata) { + mspool *nsp = (mspool *)nspool; + msevent *nse = (msevent *)nsevent; + struct sockaddr_storage *ss; + size_t sslen; + unsigned short port; + + switch (nse->iod->px_ctx->px_state) { + case PROXY_STATE_INITIAL: + nse->iod->px_ctx->px_state = PROXY_STATE_HTTP_TCP_CONNECTED; + + if (PROXY_CTX_NEXT(nse->iod->px_ctx)) { + struct proxy_node *next; + + next = PROXY_CTX_NEXT(nse->iod->px_ctx); + ss = &next->ss; + sslen = next->sslen; + port = next->port; + } else { + ss = &nse->iod->px_ctx->target_ss; + sslen = nse->iod->px_ctx->target_sslen; + port = nse->iod->px_ctx->target_port; + } + nsock_printf(nspool, (nsock_iod)nse->iod, nsock_proxy_ev_dispatch, + 4000, udata, "CONNECT %s:%d HTTP/1.1\r\n\r\n", + inet_ntop_ez(ss, sslen), (int)port); + nsock_readlines(nspool, (nsock_iod)nse->iod, nsock_proxy_ev_dispatch, 4000, udata, 1); + break; + + case PROXY_STATE_HTTP_TCP_CONNECTED: + if (nse->type == NSE_TYPE_READ) { + char *res; + int reslen; + + res = nse_readbuf(nse, &reslen); + + /* TODO string check!! */ + if ((reslen >= 15) && strstr(res, "200 OK")) { + nse->iod->px_ctx->px_state = PROXY_STATE_HTTP_TUNNEL_ESTABLISHED; + } + + if (nse->iod->px_ctx->px_current->next == NULL) { + forward_event(nsp, nse, udata); + } else { + nse->iod->px_ctx->px_current = nse->iod->px_ctx->px_current->next; + nse->iod->px_ctx->px_state = PROXY_STATE_INITIAL; + + nsock_proxy_ev_dispatch(nsp, nse, udata); + } + } + break; + + case PROXY_STATE_HTTP_TUNNEL_ESTABLISHED: + forward_event(nsp, nse, udata); + break; + + default: + fatal("Invalid proxy state!"); + } +} + +nsock_event_id proxy_http_connect_tcp(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, + int timeout_msecs, void *userdata, struct sockaddr *saddr, + size_t sslen, unsigned short port) { + msiod *nsi = (msiod *)ms_iod; + struct proxy_node *current; + + memcpy(&nsi->px_ctx->target_ss, saddr, sslen); + nsi->px_ctx->target_sslen = sslen; + nsi->px_ctx->target_port = port; + nsi->px_ctx->target_handler = handler; + + current = PROXY_CTX_CURRENT(nsi->px_ctx); + saddr = (struct sockaddr *)¤t->ss; + sslen = current->sslen; + port = current->port; + handler = nsock_proxy_ev_dispatch; + + return nsock_connect_tcp_direct(nsp, ms_iod, handler, timeout_msecs, userdata, saddr, sslen, port); +} + +char *proxy_http_data_encode(const char *src, size_t len, size_t *dlen) { + // TODO + return NULL; +} + +char *proxy_http_data_decode(const char *src, size_t len, size_t *dlen) { + // TODO + return NULL; +} +