The issue is that `rspamd_http_message_get_http_host` actually returns non zero-terminated string in the case where `Host` header is found in a message. Hence, we *cannot* treat it as a zero terminated string. The proper approach is to use `rspamd_ftok_t` everywhere for strings but the change will be too intrusive, since it also involves many libraries, e.g. `rdns` and others. The current approach is much simplier: just copy a string into a temporary buffer ensuring that it is zero terminated in all the cases. Issue: #4051tags/3.2
@@ -693,7 +693,8 @@ rspamd_http_message_remove_header (struct rspamd_http_message *msg, | |||
} | |||
const gchar* | |||
rspamd_http_message_get_http_host (struct rspamd_http_message *msg) | |||
rspamd_http_message_get_http_host (struct rspamd_http_message *msg, | |||
gsize *hostlen) | |||
{ | |||
if (msg->flags & RSPAMD_HTTP_FLAG_HAS_HOST_HEADER) { | |||
rspamd_ftok_t srch; | |||
@@ -703,14 +704,17 @@ rspamd_http_message_get_http_host (struct rspamd_http_message *msg) | |||
khiter_t k = kh_get (rspamd_http_headers_hash, msg->headers, &srch); | |||
if (k != kh_end (msg->headers)) { | |||
*hostlen = (kh_value (msg->headers, k)->value).len; | |||
return (kh_value (msg->headers, k)->value).begin; | |||
} | |||
else if (msg->host) { | |||
*hostlen = msg->host->len; | |||
return msg->host->str; | |||
} | |||
} | |||
else { | |||
if (msg->host) { | |||
*hostlen = msg->host->len; | |||
return msg->host->str; | |||
} | |||
} |
@@ -233,9 +233,11 @@ guint rspamd_http_message_get_flags (struct rspamd_http_message *msg); | |||
* Returns an HTTP hostname for a message, derived from a header if it has it | |||
* or from a url if it doesn't | |||
* @param msg | |||
* @param hostlen output of the host length | |||
* @return | |||
*/ | |||
const gchar* rspamd_http_message_get_http_host (struct rspamd_http_message *msg); | |||
const gchar* rspamd_http_message_get_http_host (struct rspamd_http_message *msg, | |||
gsize *hostlen); | |||
#ifdef __cplusplus | |||
} |
@@ -75,7 +75,7 @@ struct lua_http_cbdata { | |||
struct rspamd_cryptobox_pubkey *peer_pk; | |||
rspamd_inet_addr_t *addr; | |||
gchar *mime_type; | |||
const gchar *host; | |||
gchar *host; | |||
gchar *auth; | |||
const gchar *url; | |||
gsize max_size; | |||
@@ -134,6 +134,10 @@ lua_http_fin (gpointer arg) | |||
g_free (cbd->auth); | |||
} | |||
if (cbd->host) { | |||
g_free (cbd->host); | |||
} | |||
if (cbd->local_kp) { | |||
rspamd_keypair_unref (cbd->local_kp); | |||
} | |||
@@ -1060,13 +1064,18 @@ lua_http_request (lua_State *L) | |||
bool numeric_ip = false; | |||
/* Check if we can skip resolving */ | |||
cbd->host = rspamd_http_message_get_http_host (msg); | |||
gsize hostlen = 0; | |||
const gchar *host = rspamd_http_message_get_http_host (msg, &hostlen); | |||
if (host) { | |||
cbd->host = malloc (hostlen + 1); | |||
rspamd_strlcpy (cbd->host, host, hostlen + 1); | |||
if (cbd->host) { | |||
if (cbd->flags & RSPAMD_LUA_HTTP_FLAG_KEEP_ALIVE) { | |||
const rspamd_inet_addr_t *ka_addr = rspamd_http_context_has_keepalive(NULL, | |||
rspamd_http_message_get_http_host (msg), | |||
msg->port, msg->flags & RSPAMD_HTTP_FLAG_WANT_SSL); | |||
cbd->host, | |||
msg->port, | |||
msg->flags & RSPAMD_HTTP_FLAG_WANT_SSL); | |||
if (ka_addr) { | |||
cbd->addr = rspamd_inet_address_copy(ka_addr); | |||
@@ -1083,6 +1092,9 @@ lua_http_request (lua_State *L) | |||
} | |||
} | |||
} | |||
else { | |||
cbd->host = NULL; | |||
} | |||
if (numeric_ip) { | |||
/* Host is numeric IP, no need to resolve */ |