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_PENDING (1 << 4)
#define QSE_HTTPD_CLIENT_MUTE (1 << 5) #define QSE_HTTPD_CLIENT_MUTE (1 << 5)
#define QSE_HTTPD_CLIENT_MUTE_DELETED (1 << 6) #define QSE_HTTPD_CLIENT_MUTE_DELETED (1 << 6)
#define QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX (1 << 7) #define QSE_HTTPD_CLIENT_PROTOCOL_SWITCHED (1 << 7) /* 101 Switching Protocols has been received */
#define QSE_HTTPD_CLIENT_HANDLE_WRITE_IN_MUX (1 << 8) #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_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)) /* 'i' must be between 0 and QSE_HTTPD_TASK_TRIGGER_MAX - 1.
#define QSE_HTTPD_CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i) (1 << ((i) + 9 + QSE_HTTPD_TASK_TRIGGER_MAX)) * 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)) #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 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_SECURE = (1 << 1),
QSE_HTTPD_SERVER_BINDTONWIF = (1 << 2) 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) ( typedef void (*qse_httpd_server_detach_t) (
qse_httpd_t* httpd, 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; typedef struct qse_httpd_server_dope_t qse_httpd_server_dope_t;
struct qse_httpd_server_dope_t struct qse_httpd_server_dope_t
{ {
int flags; /* bitwise-ORed of qse_httpd_server_flag_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 the task_proxy_t chunk. explicit
deallocatin is required */ deallocatin is required */
#define PROXY_RESOLVE_PEER_NAME (1 << 6) #define PROXY_RESOLVE_PEER_NAME (1 << 6)
#define PROXY_PEER_NAME_RESOLVED (1 << 7) #define PROXY_PEER_NAME_RESOLVING (1 << 7)
#define PROXY_PEER_NAME_UNRESOLVED (1 << 8) #define PROXY_PEER_NAME_RESOLVED (1 << 8)
#define PROXY_REWRITE_URL (1 << 9) #define PROXY_PEER_NAME_UNRESOLVED (1 << 9)
#define PROXY_URL_PREREWRITTEN (1 << 10) /* URL has been prerewritten in prerewrite(). */ #define PROXY_REWRITE_URL (1 << 10)
#define PROXY_URL_REWRITTEN (1 << 11) #define PROXY_URL_REWRITING (1 << 11)
#define PROXY_URL_REDIRECTED (1 << 12) #define PROXY_URL_PREREWRITTEN (1 << 12) /* URL has been prerewritten in prerewrite(). */
#define PROXY_X_FORWARDED_FOR (1 << 13) /* X-Forwarded-For added */ #define PROXY_URL_REWRITTEN (1 << 13)
#define PROXY_VIA (1 << 14) /* Via added to the request */ #define PROXY_URL_REDIRECTED (1 << 14)
#define PROXY_VIA_RETURNING (1 << 15) /* Via added to the response */ #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; int flags;
qse_httpd_t* httpd; qse_httpd_t* httpd;
qse_httpd_client_t* client; 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. /* 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 && if (qse_mbscasecmp (key, QSE_MT("Transfer-Encoding")) != 0 &&
qse_mbscasecmp (key, QSE_MT("Content-Length")) != 0 /* EXPERIMENTAL */ /* && qse_mbscasecmp (key, QSE_MT("Content-Length")) != 0 /* EXPERIMENTAL */ /* &&
qse_mbscasecmp (key, QSE_MT("Referer")) != 0*/) qse_mbscasecmp (key, QSE_MT("Referer")) != 0*/)
@ -368,11 +370,6 @@ static int proxy_snatch_client_input (
task = (qse_httpd_task_t*)ctx; task = (qse_httpd_task_t*)ctx;
proxy = (task_proxy_t*)task->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) 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; 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; return 0;
@ -481,14 +475,10 @@ static int proxy_snatch_peer_output (
if (ptr == QSE_NULL) if (ptr == QSE_NULL)
{ {
/* content completed */ /* content completed. got the entire response */
QSE_ASSERT (len == 0); 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 || 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_htre_walktrailers (req, proxy_capture_peer_trailer, proxy) <= -1 ||
qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-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) if (proxy->resflags & PROXY_RES_PEER_LENGTH_FAKE)
{ {
qse_mchar_t buf[64];
/* length should be added by force. /* length should be added by force.
* let me add Content-Length event if it's 0 * let me add Content-Length event if it's 0
* for less code */ * 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 || 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) qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1)
{ {
httpd->errnum = QSE_HTTPD_ENOMEM; httpd->errnum = QSE_HTTPD_ENOMEM;
@ -948,8 +931,13 @@ static int task_init_proxy (
proxy->peer.local = arg->rsrc->src.nwad; proxy->peer.local = arg->rsrc->src.nwad;
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR) 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) 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; proxy->peer_name = proxy->pseudonym + len + 1;
qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str); qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str);
adjust_peer_name_and_port (proxy); adjust_peer_name_and_port (proxy);
@ -1031,7 +1019,6 @@ static int task_init_proxy (
else else
{ {
int snatch_needed = 0; int snatch_needed = 0;
/* compose a request to send to the peer using the request /* compose a request to send to the peer using the request
* received from the client */ * 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; task_proxy_t* proxy = (task_proxy_t*)task->ctx;
QSE_ASSERT (proxy->flags & PROXY_RESOLVE_PEER_NAME); 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))); 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) 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; 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); printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
if (new_url[0] == QSE_MT('\0')) if (new_url[0] == QSE_MT('\0'))
@ -2153,25 +2141,36 @@ static int task_main_proxy (
} }
else else
{ {
/* note that url_to_rewrite is URL + extra information. */ if (!(proxy->flags & PROXY_URL_REWRITING))
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; /* 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) && if ((proxy->flags & PROXY_REWRITE_URL) &&
qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops; qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops;
}
} }
return 1; return 1; /* not finished yet */
} }
if (proxy->flags & PROXY_RESOLVE_PEER_NAME) if (proxy->flags & PROXY_RESOLVE_PEER_NAME)
{ {
/* arrange to resolve a host name and return */ /* arrange to resolve a host name and return */
int x; int x;
QSE_ASSERT (proxy->peer_name != QSE_NULL); 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) 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); x = proxy->dns_preresolve_mod->dns_preresolve (proxy->dns_preresolve_mod, client, proxy->peer_name, &proxy->peer.nwad);
else else
@ -2188,6 +2187,17 @@ static int task_main_proxy (
} }
else 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); 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; if (x <= -1) goto oops;
} }
@ -2205,7 +2215,7 @@ static int task_main_proxy (
if (!(proxy->flags & PROXY_PEER_NAME_RESOLVED) && if (!(proxy->flags & PROXY_PEER_NAME_RESOLVED) &&
qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops; qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops;
return 1; return 1; /* not finished yet */
} }
if (!(proxy->flags & PROXY_RAW)) if (!(proxy->flags & PROXY_RAW))

View File

@ -782,7 +782,7 @@ resolved:
else req->prev->next = req->next; else req->prev->next = req->next;
if (req->next) req->next->prev = req->prev; 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); dns_cache_answer (dc, req, resolved_nwad, cache_ttl);
dc->req_count--; dc->req_count--;