1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-21 15:09:02 +00:00

Added skeletton for having px_info list in each Nsock IOD.

When establishing the tunnel through proxy chain, we need to track status of
each proxy (storing R/W buffers, stats, retries...).

This patch lets proxies store and manage whatever structure they want to have
for this in a Nsock IOD. Since types can differ between proxy types, the
proxy_info are stored as a list of void *, ordered like the proxy nodes.
This commit is contained in:
henri
2013-04-22 19:31:30 +00:00
parent 21327ee56c
commit 4d5bb41361
3 changed files with 114 additions and 42 deletions

View File

@@ -82,9 +82,6 @@ static struct proxy_parser *proxy_parser_new(const char *proxychainstr);
static void proxy_parser_next(struct proxy_parser *parser); static void proxy_parser_next(struct proxy_parser *parser);
static void proxy_parser_delete(struct proxy_parser *parser); 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);
/* --- Implemented proxy backends --- */ /* --- Implemented proxy backends --- */
extern const struct proxy_op proxy_http_ops; extern const struct proxy_op proxy_http_ops;
@@ -133,7 +130,7 @@ void nsock_proxychain_delete(nsock_proxychain chain) {
free(pchain->specstr); free(pchain->specstr);
while ((node = (struct proxy_node *)gh_list_pop(&pchain->nodes)) != NULL) { while ((node = (struct proxy_node *)gh_list_pop(&pchain->nodes)) != NULL) {
proxy_node_delete(node); node->ops->node_delete(node);
} }
gh_list_free(&pchain->nodes); gh_list_free(&pchain->nodes);
@@ -157,17 +154,69 @@ int nsp_set_proxychain(nsock_pool nspool, nsock_proxychain chain) {
struct proxy_chain_context *proxy_chain_context_new(nsock_pool nspool) { struct proxy_chain_context *proxy_chain_context_new(nsock_pool nspool) {
mspool *nsp = (mspool *)nspool; mspool *nsp = (mspool *)nspool;
struct proxy_chain_context *ctx; struct proxy_chain_context *ctx;
gh_list_elem *elt;
ctx = (struct proxy_chain_context *)safe_malloc(sizeof(struct proxy_chain_context)); ctx = (struct proxy_chain_context *)safe_malloc(sizeof(struct proxy_chain_context));
ctx->px_chain = nsp->px_chain; ctx->px_chain = nsp->px_chain;
ctx->px_state = PROXY_STATE_INITIAL; ctx->px_state = PROXY_STATE_INITIAL;
ctx->px_current = GH_LIST_FIRST_ELEM(&nsp->px_chain->nodes); ctx->px_current = GH_LIST_FIRST_ELEM(&nsp->px_chain->nodes);
gh_list_init(&ctx->px_info);
for (elt = GH_LIST_FIRST_ELEM(&nsp->px_chain->nodes); elt != NULL; elt = GH_LIST_ELEM_NEXT(elt)) {
struct proxy_node *px = (struct proxy_node *)GH_LIST_ELEM_DATA(elt);
void *pinfo = NULL;
px->ops->info_new(&pinfo);
gh_list_append(&ctx->px_info, pinfo);
}
return ctx; return ctx;
} }
void proxy_chain_context_delete(struct proxy_chain_context *ctx) { void proxy_chain_context_delete(struct proxy_chain_context *ctx) {
if (ctx) if (ctx) {
gh_list_elem *pxe;
assert(GH_LIST_COUNT(&ctx->px_chain->nodes) == GH_LIST_COUNT(&ctx->px_info));
for (pxe = GH_LIST_FIRST_ELEM(&ctx->px_chain->nodes); pxe != NULL; pxe = GH_LIST_ELEM_NEXT(pxe)) {
struct proxy_node *pxn;
void *px_info;
pxn = (struct proxy_node *)GH_LIST_ELEM_DATA(pxe);
px_info = gh_list_pop(&ctx->px_info);
pxn->ops->info_delete(px_info);
}
gh_list_free(&ctx->px_info);
free(ctx); free(ctx);
}
}
/* XXX
* This function is just an ugly PoC.
*
* A clean version should handle:
* - both v4 and v6 adresses
* - hostnames (how do we want to resolve them though??)
* - user:pass@ prefix before host specification
*/
static struct proxy_node *proxy_node_new(char *proxystr) {
int i;
for (i = 0; ProxyBackends[i] != NULL; i++) {
const struct proxy_op *pxop;
pxop = ProxyBackends[i];
if (strncasecmp(proxystr, pxop->prefix, strlen(pxop->prefix)) == 0) {
struct proxy_node *proxy;
pxop->node_new(&proxy, proxystr);
return proxy;
}
}
fatal("Invalid protocol in proxy specification string: %s", proxystr);
} }
struct proxy_parser *proxy_parser_new(const char *proxychainstr) { struct proxy_parser *proxy_parser_new(const char *proxychainstr) {
@@ -206,37 +255,6 @@ void proxy_parser_delete(struct proxy_parser *parser) {
} }
} }
/* XXX
* This function is just an ugly PoC.
*
* A clean version should handle:
* - both v4 and v6 adresses
* - hostnames (how do we want to resolve them though??)
* - user:pass@ prefix before host specification
*/
static struct proxy_node *proxy_node_new(char *proxystr) {
int i;
for (i = 0; ProxyBackends[i] != NULL; i++) {
const struct proxy_op *pxop;
pxop = ProxyBackends[i];
if (strncasecmp(proxystr, pxop->prefix, strlen(pxop->prefix)) == 0) {
struct proxy_node *proxy;
proxy = (struct proxy_node *)safe_zalloc(sizeof(struct proxy_node));
pxop->init(proxy, proxystr);
return proxy;
}
}
fatal("Invalid protocol in proxy specification string: %s", proxystr);
}
static void proxy_node_delete(struct proxy_node *proxy) {
if (proxy)
free(proxy);
}
void forward_event(nsock_pool nspool, nsock_event nsevent, void *udata) { void forward_event(nsock_pool nspool, nsock_event nsevent, void *udata) {
mspool *nsp = (mspool *)nspool; mspool *nsp = (mspool *)nspool;
msevent *nse = (msevent *)nsevent; msevent *nse = (msevent *)nsevent;

View File

@@ -85,6 +85,9 @@ enum nsock_proxy_state {
/* ------------------- STRUCTURES ------------------- */ /* ------------------- STRUCTURES ------------------- */
/* Static information about a proxy node in the chain. This is generated by
* parsing the proxy specification string given by user. Those structures are
* then read-only and stored in the nsock_pool. */
struct proxy_node { struct proxy_node {
enum nsock_proxy_type px_type; enum nsock_proxy_type px_type;
@@ -95,19 +98,26 @@ struct proxy_node {
unsigned short port; unsigned short port;
}; };
/* Ordered list of proxy nodes, as specified in the proxy specification string. */
struct proxy_chain { struct proxy_chain {
char *specstr; char *specstr;
gh_list nodes; gh_list nodes;
}; };
/* IOD-specific context. For each IOD we establish a tunnel through the chain of
* proxies. This structure stores all the related information. */
struct proxy_chain_context { struct proxy_chain_context {
struct proxy_chain *px_chain; const struct proxy_chain *px_chain;
/* Those fields are used to store current state during the tunnel /* Those fields are used to store current state during the tunnel
* establishment phase. */ * establishment phase. */
gh_list_elem *px_current; gh_list_elem *px_current;
enum nsock_proxy_state px_state; enum nsock_proxy_state px_state;
/* Each proxy in the chain maintains a data structure. This can contains r/w
* buffers for instance. */
gh_list px_info;
struct sockaddr_storage target_ss; struct sockaddr_storage target_ss;
size_t target_sslen; size_t target_sslen;
unsigned short target_port; unsigned short target_port;
@@ -118,10 +128,17 @@ struct proxy_op {
const char *prefix; const char *prefix;
enum nsock_proxy_type type; enum nsock_proxy_type type;
void (*init)(struct proxy_node *proxy, char *proxystr); int (*node_new)(struct proxy_node **node, char *proxystr);
void (*node_delete)(struct proxy_node *node);
int (*info_new)(void **info);
void (*info_delete)(void *info);
void (*handler)(nsock_pool nspool, nsock_event nsevent, void *udata); 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, 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); void *userdata, struct sockaddr *saddr, size_t sslen, unsigned short port);
char *(*encode)(const char *src, size_t len, size_t *dlen); char *(*encode)(const char *src, size_t len, size_t *dlen);
char *(*decode)(const char *src, size_t len, size_t *dlen); char *(*decode)(const char *src, size_t len, size_t *dlen);
}; };

View File

@@ -61,9 +61,16 @@
#define DEFAULT_PROXY_PORT_HTTP "8080" #define DEFAULT_PROXY_PORT_HTTP "8080"
struct http_proxy_info {
void *dummy;
};
/* --- PROXY INTERFACE PROTOTYPES --- */
static void proxy_http_init(struct proxy_node *proxy, char *proxystr); /* ---- PROTOTYPES ---- */
static int proxy_http_node_new(struct proxy_node **node, char *proxystr);
static void proxy_http_node_delete(struct proxy_node *node);
static int proxy_http_info_new(void **info);
static void proxy_http_info_delete(void *info);
static void proxy_http_handler(nsock_pool nspool, nsock_event nsevent, void *udata); 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, 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, int timeout_msecs, void *userdata, struct sockaddr *saddr,
@@ -76,7 +83,10 @@ static char *proxy_http_decode(const char *src, size_t len, size_t *dlen);
const struct proxy_op proxy_http_ops = { const struct proxy_op proxy_http_ops = {
.prefix = "http://", .prefix = "http://",
.type = PROXY_TYPE_HTTP, .type = PROXY_TYPE_HTTP,
.init = proxy_http_init, .node_new = proxy_http_node_new,
.node_delete = proxy_http_node_delete,
.info_new = proxy_http_info_new,
.info_delete = proxy_http_info_delete,
.handler = proxy_http_handler, .handler = proxy_http_handler,
.connect_tcp = proxy_http_connect_tcp, .connect_tcp = proxy_http_connect_tcp,
.encode = proxy_http_encode, .encode = proxy_http_encode,
@@ -84,10 +94,12 @@ const struct proxy_op proxy_http_ops = {
}; };
void proxy_http_init(struct proxy_node *proxy, char *proxystr) { int proxy_http_node_new(struct proxy_node **node, char *proxystr) {
struct sockaddr_in *sin; struct sockaddr_in *sin;
struct proxy_node *proxy;
char *strhost, *strport, *saveptr; char *strhost, *strport, *saveptr;
proxy = (struct proxy_node *)safe_zalloc(sizeof(struct proxy_node));
proxy->ops = &proxy_http_ops; proxy->ops = &proxy_http_ops;
strhost = strtok_r(proxystr + 7, ":", &saveptr); strhost = strtok_r(proxystr + 7, ":", &saveptr);
@@ -101,6 +113,31 @@ void proxy_http_init(struct proxy_node *proxy, char *proxystr) {
proxy->sslen = sizeof(struct sockaddr_in); proxy->sslen = sizeof(struct sockaddr_in);
proxy->port = (unsigned short)atoi(strport); proxy->port = (unsigned short)atoi(strport);
*node = proxy;
return 1;
}
void proxy_http_node_delete(struct proxy_node *node) {
if (node)
free(node);
}
int proxy_http_info_new(void **info) {
struct http_proxy_info *pxi;
pxi = (struct http_proxy_info *)safe_zalloc(sizeof(struct http_proxy_info));
pxi->dummy = NULL; // TODO
*info = pxi;
return 1;
}
void proxy_http_info_delete(void *info) {
if (info)
free(info);
} }
void proxy_http_handler(nsock_pool nspool, nsock_event nsevent, void *udata) { void proxy_http_handler(nsock_pool nspool, nsock_event nsevent, void *udata) {