added some protection againt double dns resolution and double url rewriting

This commit is contained in:
hyung-hwan 2014-10-02 06:36:55 +00:00
parent 96f42a0815
commit 8a32cbc4f1
3 changed files with 61 additions and 48 deletions

View File

@ -612,12 +612,15 @@ struct qse_httpd_client_t
#define QSE_HTTPD_CLIENT_PENDING (1 << 4)
#define QSE_HTTPD_CLIENT_MUTE (1 << 5)
#define QSE_HTTPD_CLIENT_MUTE_DELETED (1 << 6)
#define QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX (1 << 7)
#define QSE_HTTPD_CLIENT_HANDLE_WRITE_IN_MUX (1 << 8)
#define QSE_HTTPD_CLIENT_PROTOCOL_SWITCHED (1 << 7) /* 101 Switching Protocols has been received */
#define QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX (1 << 8)
#define QSE_HTTPD_CLIENT_HANDLE_WRITE_IN_MUX (1 << 9)
#define QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX (QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX | QSE_HTTPD_CLIENT_HANDLE_WRITE_IN_MUX)
#define QSE_HTTPD_CLIENT_TASK_TRIGGER_READ_IN_MUX(i) (1 << ((i) + 9))
#define QSE_HTTPD_CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i) (1 << ((i) + 9 + QSE_HTTPD_TASK_TRIGGER_MAX))
/* 'i' must be between 0 and QSE_HTTPD_TASK_TRIGGER_MAX - 1.
* Be careful about potential overflown when QSE_HTTPD_TASK_TRIGGER_MAX is too large. */
#define QSE_HTTPD_CLIENT_TASK_TRIGGER_READ_IN_MUX(i) (1 << ((i) + 10))
#define QSE_HTTPD_CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i) (1 << ((i) + 10 + QSE_HTTPD_TASK_TRIGGER_MAX))
#define QSE_HTTPD_CLIENT_TASK_TRIGGER_RW_IN_MUX(i) (QSE_HTTPD_CLIENT_TASK_TRIGGER_READ_IN_MUX(i) | QSE_HTTPD_CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i))
enum qse_httpd_server_flag_t
@ -626,6 +629,7 @@ enum qse_httpd_server_flag_t
QSE_HTTPD_SERVER_SECURE = (1 << 1),
QSE_HTTPD_SERVER_BINDTONWIF = (1 << 2)
};
typedef enum qse_httpd_server_flag_t qse_httpd_server_flag_t;
typedef void (*qse_httpd_server_detach_t) (
qse_httpd_t* httpd,
@ -633,7 +637,6 @@ typedef void (*qse_httpd_server_detach_t) (
);
typedef struct qse_httpd_server_dope_t qse_httpd_server_dope_t;
struct qse_httpd_server_dope_t
{
int flags; /* bitwise-ORed of qse_httpd_server_flag_t */

View File

@ -45,15 +45,17 @@ struct task_proxy_t
the task_proxy_t chunk. explicit
deallocatin is required */
#define PROXY_RESOLVE_PEER_NAME (1 << 6)
#define PROXY_PEER_NAME_RESOLVED (1 << 7)
#define PROXY_PEER_NAME_UNRESOLVED (1 << 8)
#define PROXY_REWRITE_URL (1 << 9)
#define PROXY_URL_PREREWRITTEN (1 << 10) /* URL has been prerewritten in prerewrite(). */
#define PROXY_URL_REWRITTEN (1 << 11)
#define PROXY_URL_REDIRECTED (1 << 12)
#define PROXY_X_FORWARDED_FOR (1 << 13) /* X-Forwarded-For added */
#define PROXY_VIA (1 << 14) /* Via added to the request */
#define PROXY_VIA_RETURNING (1 << 15) /* Via added to the response */
#define PROXY_PEER_NAME_RESOLVING (1 << 7)
#define PROXY_PEER_NAME_RESOLVED (1 << 8)
#define PROXY_PEER_NAME_UNRESOLVED (1 << 9)
#define PROXY_REWRITE_URL (1 << 10)
#define PROXY_URL_REWRITING (1 << 11)
#define PROXY_URL_PREREWRITTEN (1 << 12) /* URL has been prerewritten in prerewrite(). */
#define PROXY_URL_REWRITTEN (1 << 13)
#define PROXY_URL_REDIRECTED (1 << 14)
#define PROXY_X_FORWARDED_FOR (1 << 15) /* X-Forwarded-For added */
#define PROXY_VIA (1 << 16) /* Via added to the request */
#define PROXY_VIA_RETURNING (1 << 17) /* Via added to the response */
int flags;
qse_httpd_t* httpd;
qse_httpd_client_t* client;
@ -297,7 +299,7 @@ static int proxy_capture_client_header (qse_htre_t* req, const qse_mchar_t* key,
}
/* EXPERIMENTAL: REMOVE HEADERS.
* FOR EXAMPLE, You can remove Referer to make analysis systems harder time */
* FOR EXAMPLE, You can remove Referer or forge it to give analysis systems harder time */
if (qse_mbscasecmp (key, QSE_MT("Transfer-Encoding")) != 0 &&
qse_mbscasecmp (key, QSE_MT("Content-Length")) != 0 /* EXPERIMENTAL */ /* &&
qse_mbscasecmp (key, QSE_MT("Referer")) != 0*/)
@ -368,11 +370,6 @@ static int proxy_snatch_client_input (
task = (qse_httpd_task_t*)ctx;
proxy = (task_proxy_t*)task->ctx;
#if 0
if (ptr) qse_printf (QSE_T("!!!PROXY SNATCHING [%.*hs]\n"), len, ptr);
else qse_printf (QSE_T("!!!PROXY SNATCHING DONE\n"));
#endif
if (ptr == QSE_NULL)
{
/*
@ -448,9 +445,6 @@ else qse_printf (QSE_T("!!!PROXY SNATCHING DONE\n"));
}
task->trigger.v[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
#if 0
qse_printf (QSE_T("!!!PROXY SNATCHED [%.*hs]\n"), len, ptr);
#endif
}
return 0;
@ -481,14 +475,10 @@ static int proxy_snatch_peer_output (
if (ptr == QSE_NULL)
{
/* content completed */
/* content completed. got the entire response */
QSE_ASSERT (len == 0);
#if 0
qse_printf (QSE_T("PROXY GOT ALL RESPONSE>>>>>>>\n"));
#endif
if (qse_mbs_cat (proxy->res, QSE_MT("0\r\n")) == (qse_size_t)-1 ||
qse_htre_walktrailers (req, proxy_capture_peer_trailer, proxy) <= -1 ||
qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1)
@ -673,18 +663,11 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
if (proxy->resflags & PROXY_RES_PEER_LENGTH_FAKE)
{
qse_mchar_t buf[64];
/* length should be added by force.
* let me add Content-Length event if it's 0
* for less code */
qse_fmtuintmaxtombs (
buf, QSE_COUNTOF(buf),
proxy->peer_output_length,
10, -1, QSE_MT('\0'), QSE_NULL);
if (qse_mbs_cat (proxy->res, QSE_MT("Content-Length: ")) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->res, buf) == (qse_size_t)-1 ||
qse_mbs_fcat (proxy->res, QSE_MT("%zu"), (qse_size_t)proxy->peer_output_length) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1)
{
httpd->errnum = QSE_HTTPD_ENOMEM;
@ -948,8 +931,13 @@ static int task_init_proxy (
proxy->peer.local = arg->rsrc->src.nwad;
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR)
{
/* the destination given is a string.
* arrange to make a DNS query in task_main_proxy() */
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_DNS)
{
/* dns service is enabled. carry on with the arrangement */
proxy->peer_name = proxy->pseudonym + len + 1;
qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str);
adjust_peer_name_and_port (proxy);
@ -1031,7 +1019,6 @@ static int task_init_proxy (
else
{
int snatch_needed = 0;
/* compose a request to send to the peer using the request
* received from the client */
@ -1911,9 +1898,10 @@ static void on_peer_name_resolved (qse_httpd_t* httpd, const qse_mchar_t* name,
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
QSE_ASSERT (proxy->flags & PROXY_RESOLVE_PEER_NAME);
QSE_ASSERT (proxy->flags & PROXY_PEER_NAME_RESOLVING);
QSE_ASSERT (!(proxy->flags & (PROXY_PEER_NAME_RESOLVED | PROXY_PEER_NAME_UNRESOLVED)));
proxy->flags &= ~PROXY_RESOLVE_PEER_NAME;
proxy->flags &= ~(PROXY_RESOLVE_PEER_NAME | PROXY_PEER_NAME_RESOLVING);
if (nwad)
{
@ -1959,7 +1947,7 @@ static void on_url_rewritten (qse_httpd_t* httpd, const qse_mchar_t* url, const
{
qse_nwad_t nwad;
proxy->flags &= ~PROXY_REWRITE_URL;
proxy->flags &= ~(PROXY_REWRITE_URL | PROXY_URL_REWRITING);
printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
if (new_url[0] == QSE_MT('\0'))
@ -2153,25 +2141,36 @@ static int task_main_proxy (
}
else
{
/* note that url_to_rewrite is URL + extra information. */
if (qse_httpd_rewriteurl (httpd, proxy->url_to_rewrite, on_url_rewritten,
((proxy->flags & PROXY_URS_SERVER)? &proxy->urs_server: QSE_NULL), task) <= -1) goto oops;
if (!(proxy->flags & PROXY_URL_REWRITING))
{
/* note that url_to_rewrite is URL + extra information. */
proxy->flags |= PROXY_URL_REWRITING; /* to prevent double calls */
if (proxy->flags & PROXY_INIT_FAILED) goto oops;
if (qse_httpd_rewriteurl (httpd, proxy->url_to_rewrite, on_url_rewritten,
((proxy->flags & PROXY_URS_SERVER)? &proxy->urs_server: QSE_NULL), task) <= -1) goto oops;
if (proxy->flags & PROXY_INIT_FAILED) goto oops;
if ((proxy->flags & PROXY_REWRITE_URL) &&
qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops;
if ((proxy->flags & PROXY_REWRITE_URL) &&
qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops;
}
}
return 1;
return 1; /* not finished yet */
}
if (proxy->flags & PROXY_RESOLVE_PEER_NAME)
{
/* arrange to resolve a host name and return */
int x;
QSE_ASSERT (proxy->peer_name != QSE_NULL);
if (proxy->flags & PROXY_PEER_NAME_RESOLVING)
{
return 1; /* not finished yet */
}
if (proxy->dns_preresolve_mod && proxy->dns_preresolve_mod->dns_preresolve)
x = proxy->dns_preresolve_mod->dns_preresolve (proxy->dns_preresolve_mod, client, proxy->peer_name, &proxy->peer.nwad);
else
@ -2188,6 +2187,17 @@ static int task_main_proxy (
}
else
{
/* this function can be called more than once if a socket
* descriptor appears multiple times in the event result
* of a single event polling cycle in the main loop.
* e.g.) the mux implementation doesn't collapse multiple events
* for a socket descriptor into 1 event.
*
* if this happens, qse_http_resolvename() can be called
* multiple times.
*/
proxy->flags |= PROXY_PEER_NAME_RESOLVING;
x = qse_httpd_resolvename (httpd, proxy->peer_name, on_peer_name_resolved, ((proxy->flags & PROXY_DNS_SERVER)? &proxy->dns_server: QSE_NULL), task);
if (x <= -1) goto oops;
}
@ -2205,7 +2215,7 @@ static int task_main_proxy (
if (!(proxy->flags & PROXY_PEER_NAME_RESOLVED) &&
qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops;
return 1;
return 1; /* not finished yet */
}
if (!(proxy->flags & PROXY_RAW))

View File

@ -782,7 +782,7 @@ resolved:
else req->prev->next = req->next;
if (req->next) req->next->prev = req->prev;
/* cache the negative answer instead of destroying it */
/* cache the answer instead of destroying it */
dns_cache_answer (dc, req, resolved_nwad, cache_ttl);
dc->req_count--;