* limitations under the License.
*/
#include "config.h"
+#include "../../contrib/mumhash/mum.h"
#include "http_private.h"
#include "utlist.h"
#include "util.h"
rspamd_http_connection_reset (conn);
priv->ssl = ssl;
/* Plan read message */
- rspamd_http_connection_read_message (conn, conn->ud, conn->fd,
- conn->priv->ptv, base);
+
+ if (priv->flags & RSPAMD_HTTP_CLIENT_SHARED) {
+ rspamd_http_connection_read_message_shared (conn, conn->ud, conn->fd,
+ conn->priv->ptv, base);
+ }
+ else {
+ rspamd_http_connection_read_message (conn, conn->ud, conn->fd,
+ conn->priv->ptv, base);
+ }
}
static void
rspamd_http_message_set_body_from_fstring_steal (msg, cpy_str);
}
+gint
+rspamd_http_message_write_header (const gchar* mime_type, gboolean encrypted,
+ gchar *repbuf, gsize replen, gsize bodylen, gsize enclen, const gchar* host,
+ struct rspamd_http_connection* conn, struct rspamd_http_message* msg,
+ rspamd_fstring_t** buf,
+ struct rspamd_http_connection_private* priv,
+ struct rspamd_cryptobox_pubkey* peer_key)
+{
+ gchar datebuf[64];
+ gint meth_len = 0;
+ struct tm t, *ptm;
+
+ if (conn->type == RSPAMD_HTTP_SERVER) {
+ /* Format reply */
+ if (msg->method < HTTP_SYMBOLS) {
+ ptm = gmtime (&msg->date);
+ t = *ptm;
+ rspamd_snprintf (datebuf, sizeof(datebuf),
+ "%s, %02d %s %4d %02d:%02d:%02d GMT", http_week[t.tm_wday],
+ t.tm_mday, http_month[t.tm_mon], t.tm_year + 1900,
+ t.tm_hour, t.tm_min, t.tm_sec);
+ if (mime_type == NULL) {
+ mime_type =
+ encrypted ? "application/octet-stream" : "text/plain";
+ }
+ if (encrypted) {
+ /* Internal reply (encrypted) */
+ meth_len =
+ rspamd_snprintf (repbuf, replen,
+ "HTTP/1.1 %d %V\r\n"
+ "Connection: close\r\n"
+ "Server: %s\r\n"
+ "Date: %s\r\n"
+ "Content-Length: %z\r\n"
+ "Content-Type: %s", /* NO \r\n at the end ! */
+ msg->code, msg->status, "rspamd/1.3.0", datebuf,
+ bodylen, mime_type);
+ enclen += meth_len;
+ /* External reply */
+ rspamd_printf_fstring (buf,
+ "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Server: rspamd\r\n"
+ "Date: %s\r\n"
+ "Content-Length: %z\r\n"
+ "Content-Type: application/octet-stream\r\n",
+ datebuf, enclen);
+ }
+ else {
+ meth_len =
+ rspamd_printf_fstring (buf,
+ "HTTP/1.1 %d %V\r\n"
+ "Connection: close\r\n"
+ "Server: %s\r\n"
+ "Date: %s\r\n"
+ "Content-Length: %z\r\n"
+ "Content-Type: %s\r\n",
+ msg->code, msg->status, "rspamd/1.3.0", datebuf,
+ bodylen, mime_type);
+ }
+ }
+ else {
+ /* Legacy spamd reply */
+ if (msg->flags & RSPAMD_HTTP_FLAG_SPAMC) {
+ rspamd_printf_fstring (buf, "SPAMD/1.1 0 EX_OK\r\n");
+ }
+ else {
+ rspamd_printf_fstring (buf, "RSPAMD/1.3 0 EX_OK\r\n");
+ }
+ }
+ }
+ else {
+ /* Format request */
+ enclen += msg->url->len + strlen (http_method_str (msg->method)) + 1;
+
+ if (host == NULL && msg->host == NULL) {
+ /* Fallback to HTTP/1.0 */
+ if (encrypted) {
+ rspamd_printf_fstring (buf,
+ "%s %s HTTP/1.0\r\nContent-Length: %z\r\n", "POST",
+ "/post", enclen);
+ }
+ else {
+ rspamd_printf_fstring (buf,
+ "%s %V HTTP/1.0\r\nContent-Length: %z\r\n",
+ http_method_str (msg->method), msg->url, bodylen);
+ }
+ }
+ else {
+ if (encrypted) {
+ if (host != NULL) {
+ rspamd_printf_fstring (buf,
+ "%s %s HTTP/1.1\r\n"
+ "Connection: close\r\n"
+ "Host: %s\r\n"
+ "Content-Length: %z\r\n",
+ "POST", "/post", host, enclen);
+ }
+ else {
+ rspamd_printf_fstring (buf,
+ "%s %s HTTP/1.1\r\n"
+ "Connection: close\r\n"
+ "Host: %V\r\n"
+ "Content-Length: %z\r\n",
+ "POST", "/post", msg->host, enclen);
+ }
+ }
+ else {
+ if (host != NULL) {
+ rspamd_printf_fstring (buf,
+ "%s %V HTTP/1.1\r\nConnection: close\r\nHost: %s\r\nContent-Length: %z\r\n",
+ http_method_str (msg->method), msg->url, host,
+ bodylen);
+ }
+ else {
+ rspamd_printf_fstring (buf,
+ "%s %V HTTP/1.1\r\n"
+ "Connection: close\r\n"
+ "Host: %V\r\n"
+ "Content-Length: %z\r\n",
+ http_method_str (msg->method), msg->url, msg->host,
+ bodylen);
+ }
+ }
+ }
+ if (encrypted) {
+ GString *b32_key, *b32_id;
+
+ b32_key = rspamd_keypair_print (priv->local_key,
+ RSPAMD_KEYPAIR_PUBKEY | RSPAMD_KEYPAIR_BASE32);
+ b32_id = rspamd_pubkey_print (peer_key,
+ RSPAMD_KEYPAIR_ID_SHORT | RSPAMD_KEYPAIR_BASE32);
+ /* XXX: add some fuzz here */
+ rspamd_printf_fstring (&*buf, "Key: %v=%v\r\n", b32_id, b32_key);
+ g_string_free (b32_key, TRUE);
+ g_string_free (b32_id, TRUE);
+ }
+ }
+
+ return meth_len;
+}
+
static void
rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn,
struct rspamd_http_message *msg, const gchar *host, const gchar *mime_type,
{
struct rspamd_http_connection_private *priv = conn->priv;
struct rspamd_http_header *hdr, *htmp;
- struct tm t, *ptm;
- gchar datebuf[64], repbuf[512], *pbody;
+ gchar repbuf[512], *pbody;
gint i, hdrcount, meth_len = 0, preludelen = 0;
gsize bodylen, enclen = 0;
rspamd_fstring_t *buf;
}
if (allow_shared) {
+ gchar tmpbuf[64];
+
if (!(msg->flags & RSPAMD_HTTP_FLAG_SHMEM) ||
msg->body_buf.c.shared.name == NULL) {
allow_shared = FALSE;
/* Insert new headers */
rspamd_http_message_add_header (msg, "Shm",
msg->body_buf.c.shared.name->shm_name);
- rspamd_snprintf (datebuf, sizeof (datebuf), "%d",
+ rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%d",
(int)(msg->body_buf.begin - msg->body_buf.str));
rspamd_http_message_add_header (msg, "Shm-Offset",
- datebuf);
- rspamd_snprintf (datebuf, sizeof (datebuf), "%z",
+ tmpbuf);
+ rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%z",
msg->body_buf.len);
rspamd_http_message_add_header (msg, "Shm-Length",
- datebuf);
+ tmpbuf);
}
}
}
else {
/* Invalid body for spamc method */
- return;
+ g_assert (0);
}
}
priv->out = g_slice_alloc (sizeof (struct iovec) * priv->outlen);
priv->wr_pos = 0;
- if (conn->type == RSPAMD_HTTP_SERVER) {
- /* Format reply */
- if (msg->method < HTTP_SYMBOLS) {
- ptm = gmtime (&msg->date);
- t = *ptm;
- rspamd_snprintf (datebuf,
- sizeof (datebuf),
- "%s, %02d %s %4d %02d:%02d:%02d GMT",
- http_week[t.tm_wday],
- t.tm_mday,
- http_month[t.tm_mon],
- t.tm_year + 1900,
- t.tm_hour,
- t.tm_min,
- t.tm_sec);
- if (mime_type == NULL) {
- mime_type = encrypted ? "application/octet-stream" : "text/plain";
- }
- if (encrypted) {
- /* Internal reply (encrypted) */
- meth_len = rspamd_snprintf (repbuf, sizeof (repbuf),
- "HTTP/1.1 %d %V\r\n"
- "Connection: close\r\n"
- "Server: %s\r\n"
- "Date: %s\r\n"
- "Content-Length: %z\r\n"
- "Content-Type: %s", /* NO \r\n at the end ! */
- msg->code,
- msg->status,
- "rspamd/" RVERSION,
- datebuf,
- bodylen,
- mime_type);
- enclen += meth_len;
- /* External reply */
- rspamd_printf_fstring (&buf, "HTTP/1.1 200 OK\r\n"
- "Connection: close\r\n"
- "Server: rspamd\r\n"
- "Date: %s\r\n"
- "Content-Length: %z\r\n"
- "Content-Type: application/octet-stream\r\n",
- datebuf,
- enclen);
- }
- else {
- meth_len = rspamd_printf_fstring (&buf, "HTTP/1.1 %d %V\r\n"
- "Connection: close\r\n"
- "Server: %s\r\n"
- "Date: %s\r\n"
- "Content-Length: %z\r\n"
- "Content-Type: %s\r\n",
- msg->code,
- msg->status,
- "rspamd/" RVERSION,
- datebuf,
- bodylen,
- mime_type);
- }
- }
- else {
- /* Legacy spamd reply */
- if (msg->flags & RSPAMD_HTTP_FLAG_SPAMC) {
- rspamd_printf_fstring (&buf, "SPAMD/1.1 0 EX_OK\r\n");
- }
- else {
- rspamd_printf_fstring (&buf, "RSPAMD/1.3 0 EX_OK\r\n");
- }
- }
- }
- else {
- /* Format request */
- enclen += msg->url->len +
- strlen (http_method_str (msg->method)) + 1 /* method + space */;
- if (host == NULL && msg->host == NULL) {
- /* Fallback to HTTP/1.0 */
- if (encrypted) {
- rspamd_printf_fstring (&buf, "%s %s HTTP/1.0\r\n"
- "Content-Length: %z\r\n",
- "POST",
- "/post",
- enclen);
- }
- else {
- rspamd_printf_fstring (&buf, "%s %V HTTP/1.0\r\n"
- "Content-Length: %z\r\n",
- http_method_str (msg->method),
- msg->url,
- bodylen);
- }
- }
- else {
- if (encrypted) {
- if (host != NULL) {
- rspamd_printf_fstring (&buf, "%s %s HTTP/1.1\r\n"
- "Connection: close\r\n"
- "Host: %s\r\n"
- "Content-Length: %z\r\n",
- "POST",
- "/post",
- host,
- enclen);
- }
- else {
- rspamd_printf_fstring (&buf, "%s %s HTTP/1.1\r\n"
- "Connection: close\r\n"
- "Host: %V\r\n"
- "Content-Length: %z\r\n",
- "POST",
- "/post",
- msg->host,
- enclen);
- }
- }
- else {
- if (host != NULL) {
- rspamd_printf_fstring (&buf, "%s %V HTTP/1.1\r\n"
- "Connection: close\r\n"
- "Host: %s\r\n"
- "Content-Length: %z\r\n",
- http_method_str (msg->method),
- msg->url,
- host,
- bodylen);
- }
- else {
- rspamd_printf_fstring (&buf, "%s %V HTTP/1.1\r\n"
- "Connection: close\r\n"
- "Host: %V\r\n"
- "Content-Length: %z\r\n",
- http_method_str (msg->method),
- msg->url,
- msg->host,
- bodylen);
- }
- }
-
- }
- if (encrypted) {
- GString *b32_key, *b32_id;
-
- b32_key = rspamd_keypair_print (priv->local_key,
- RSPAMD_KEYPAIR_PUBKEY|RSPAMD_KEYPAIR_BASE32);
- b32_id = rspamd_pubkey_print (peer_key,
- RSPAMD_KEYPAIR_ID_SHORT|RSPAMD_KEYPAIR_BASE32);
- /* XXX: add some fuzz here */
- rspamd_printf_fstring (&buf, "Key: %v=%v\r\n", b32_id, b32_key);
- g_string_free (b32_key, TRUE);
- g_string_free (b32_id, TRUE);
- }
- }
+ meth_len = rspamd_http_message_write_header (mime_type, encrypted,
+ repbuf, sizeof (repbuf), bodylen, enclen,
+ host, conn, msg,
+ &buf, priv, peer_key);
/* Setup external request body */
priv->out[0].iov_base = buf->str;
static void
rspamd_http_shname_dtor (void *p)
{
- struct _rspamd_storage_shmem_s *n = p;
+ struct rspamd_storage_shmem *n = p;
shm_unlink (n->shm_name);
g_free (n->shm_name);
g_slice_free1 (sizeof (*n), n);
}
-void *
+struct rspamd_storage_shmem *
rspamd_http_message_shmem_ref (struct rspamd_http_message *msg)
{
if ((msg->flags & RSPAMD_HTTP_FLAG_SHMEM) && msg->body_buf.c.shared.name) {
}
void
-rspamd_http_message_shmem_unref (void *p)
+rspamd_http_message_shmem_unref (struct rspamd_storage_shmem *p)
{
- struct _rspamd_storage_shmem_s *n = p;
-
- if (n) {
- REF_RELEASE (n);
- }
+ REF_RELEASE (p);
}
gboolean
}
/* Check if we need to grow */
- if (st.st_size < msg->body_buf.len + len) {
+ if ((gsize)st.st_size < msg->body_buf.len + len) {
/* Need to grow */
newlen = rspamd_fstring_suggest_size (msg->body_buf.len, st.st_size,
len);