]> source.dussan.org Git - rspamd.git/commitdiff
Fix various issues in encrypted messages support.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 5 May 2015 14:10:54 +0000 (15:10 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 5 May 2015 14:10:54 +0000 (15:10 +0100)
src/libutil/http.c
src/libutil/http.h

index 4547aa5f896e37cb6647249e02e571c2680e81cd..fe1120870f6b42e616d789323f54bdb96b3761b7 100644 (file)
@@ -601,43 +601,42 @@ rspamd_http_on_message_complete (http_parser * parser)
 
        priv = conn->priv;
 
-       if (conn->body_handler != NULL) {
+       if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) == 0 && priv->encrypted) {
+               if (priv->local_key == NULL || priv->msg->peer_key == NULL ||
+                               priv->msg->body->len < rspamd_cryptobox_NONCEBYTES +
+                               rspamd_cryptobox_MACBYTES) {
+                       msg_err ("cannot decrypt message");
+                       return -1;
+               }
+               /* We have keys, so we can decrypt message */
+               /* TODO: add pubkey<->privkey pairs to LRU cache */
+               nonce = priv->msg->body->str;
+               m = priv->msg->body->str + rspamd_cryptobox_NONCEBYTES +
+                               rspamd_cryptobox_MACBYTES;
+               dec_len = priv->msg->body->len - rspamd_cryptobox_NONCEBYTES -
+                               rspamd_cryptobox_MACBYTES;
+               peer_key = (struct rspamd_http_keypair *)priv->msg->peer_key;
 
-               if (priv->encrypted) {
-                       if (priv->local_key == NULL || priv->msg->peer_key == NULL ||
-                                       priv->msg->body->len < rspamd_cryptobox_NONCEBYTES +
-                                       rspamd_cryptobox_MACBYTES) {
-                               msg_err ("cannot decrypt message");
+               if (conn->cache) {
+                       if (!rspamd_cryptobox_decrypt_nm_inplace (m, dec_len, nonce,
+                                       peer_key->nm, m - rspamd_cryptobox_MACBYTES) != 0) {
+                               msg_err ("cannot verify encrypted message");
                                return -1;
                        }
-                       /* We have keys, so we can decrypt message */
-                       /* TODO: add pubkey<->privkey pairs to LRU cache */
-                       nonce = priv->msg->body->str;
-                       m = priv->msg->body->str + rspamd_cryptobox_NONCEBYTES +
-                                       rspamd_cryptobox_MACBYTES;
-                       dec_len = priv->msg->body->len - rspamd_cryptobox_NONCEBYTES -
-                                       rspamd_cryptobox_MACBYTES;
-                       peer_key = (struct rspamd_http_keypair *)priv->msg->peer_key;
-
-                       if (conn->cache) {
-                               if (!rspamd_cryptobox_decrypt_nm_inplace (m, dec_len, nonce,
-                                               peer_key->nm, m - rspamd_cryptobox_MACBYTES) != 0) {
-                                       msg_err ("cannot verify encrypted message");
-                                       return -1;
-                               }
-                       }
-                       else {
-                               if (!rspamd_cryptobox_decrypt_inplace (m, dec_len, nonce,
-                                               peer_key->pk, priv->local_key->sk,
-                                               m - rspamd_cryptobox_MACBYTES) != 0) {
-                                       msg_err ("cannot verify encrypted message");
-                                       return -1;
-                               }
+               }
+               else {
+                       if (!rspamd_cryptobox_decrypt_inplace (m, dec_len, nonce,
+                                       peer_key->pk, priv->local_key->sk,
+                                       m - rspamd_cryptobox_MACBYTES) != 0) {
+                               msg_err ("cannot verify encrypted message");
+                               return -1;
                        }
+               }
 
-                       priv->msg->body->str = m;
-                       priv->msg->body->len = dec_len;
+               priv->msg->body->str = m;
+               priv->msg->body->len = dec_len;
 
+               if (conn->body_handler != NULL) {
                        rspamd_http_connection_ref (conn);
                        ret = conn->body_handler (conn,
                                        priv->msg,
@@ -645,14 +644,15 @@ rspamd_http_on_message_complete (http_parser * parser)
                                        dec_len);
                        rspamd_http_connection_unref (conn);
                }
-               else if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) == 0) {
-                       rspamd_http_connection_ref (conn);
-                       ret = conn->body_handler (conn,
-                                       priv->msg,
-                                       priv->msg->body->str,
-                                       priv->msg->body->len);
-                       rspamd_http_connection_unref (conn);
-               }
+       }
+       else if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) == 0 && conn->body_handler) {
+               g_assert (conn->body_handler != NULL);
+               rspamd_http_connection_ref (conn);
+               ret = conn->body_handler (conn,
+                               priv->msg,
+                               priv->msg->body->str,
+                               priv->msg->body->len);
+               rspamd_http_connection_unref (conn);
        }
 
        if (ret == 0) {
@@ -805,9 +805,11 @@ rspamd_http_event_handler (int fd, short what, gpointer ud)
                                conn->error_handler (conn, err);
                                g_error_free (err);
 
-                               REF_RELEASE (pbuf);
-                               rspamd_http_connection_unref (conn);
+
                        }
+                       REF_RELEASE (pbuf);
+                       rspamd_http_connection_unref (conn);
+
                        return;
                }
                else {
@@ -923,6 +925,7 @@ rspamd_http_connection_reset (struct rspamd_http_connection *conn)
        event_del (&priv->ev);
        if (priv->buf != NULL) {
                REF_RELEASE (priv->buf);
+               priv->buf = NULL;
        }
 
        rspamd_http_parser_reset (conn);
@@ -933,6 +936,27 @@ rspamd_http_connection_reset (struct rspamd_http_connection *conn)
        }
 }
 
+struct rspamd_http_message *
+rspamd_http_connection_steal_msg (struct rspamd_http_connection *conn)
+{
+       struct rspamd_http_connection_private *priv;
+       struct rspamd_http_message *msg;
+
+       priv = conn->priv;
+       msg = priv->msg;
+
+       /* Clear request */
+       if (msg != NULL) {
+               if (msg->peer_key) {
+                       priv->peer_key = msg->peer_key;
+                       msg->peer_key = NULL;
+               }
+               priv->msg = NULL;
+       }
+
+       return msg;
+}
+
 void
 rspamd_http_connection_free (struct rspamd_http_connection *conn)
 {
@@ -940,17 +964,21 @@ rspamd_http_connection_free (struct rspamd_http_connection *conn)
        struct rspamd_http_keypair *peer_key;
 
        priv = conn->priv;
-       rspamd_http_connection_reset (conn);
 
-       if (priv->local_key) {
-               REF_RELEASE (priv->local_key);
-       }
-       if (priv->peer_key) {
-               peer_key = (struct rspamd_http_keypair *)priv->peer_key;
-               REF_RELEASE (peer_key);
+       if (priv != NULL) {
+               rspamd_http_connection_reset (conn);
+
+               if (priv->local_key) {
+                       REF_RELEASE (priv->local_key);
+               }
+               if (priv->peer_key) {
+                       peer_key = (struct rspamd_http_keypair *)priv->peer_key;
+                       REF_RELEASE (peer_key);
+               }
+
+               g_slice_free1 (sizeof (struct rspamd_http_connection_private), priv);
        }
 
-       g_slice_free1 (sizeof (struct rspamd_http_connection_private), priv);
        g_slice_free1 (sizeof (struct rspamd_http_connection),             conn);
 }
 
@@ -976,10 +1004,11 @@ rspamd_http_connection_read_message (struct rspamd_http_connection *conn,
        if (timeout == NULL) {
                priv->ptv = NULL;
        }
-       else {
+       else if (&priv->tv != timeout) {
                memcpy (&priv->tv, timeout, sizeof (struct timeval));
                priv->ptv = &priv->tv;
        }
+
        priv->header = NULL;
        priv->buf = g_slice_alloc0 (sizeof (*priv->buf));
        REF_INIT_RETAIN (priv->buf, rspamd_http_privbuf_dtor);
@@ -1023,10 +1052,11 @@ rspamd_http_connection_write_message (struct rspamd_http_connection *conn,
        if (timeout == NULL) {
                priv->ptv = NULL;
        }
-       else {
+       else if (timeout != &priv->tv) {
                memcpy (&priv->tv, timeout, sizeof (struct timeval));
                priv->ptv = &priv->tv;
        }
+
        priv->header = NULL;
        priv->buf = g_slice_alloc0 (sizeof (*priv->buf));
        REF_INIT_RETAIN (priv->buf, rspamd_http_privbuf_dtor);
@@ -1196,7 +1226,10 @@ rspamd_http_connection_write_message (struct rspamd_http_connection *conn,
                priv->wr_total -= 2;
        }
        if (msg->body != NULL) {
-               msg->body_buf.str = msg->body->str;
+
+               if (msg->body_buf.str == NULL) {
+                       msg->body_buf.str = msg->body->str;
+               }
 
                if (encrypted && peer_key != NULL && np != NULL && mp != NULL) {
                        if (conn->cache) {
@@ -1362,7 +1395,7 @@ rspamd_http_message_find_header (struct rspamd_http_message *msg,
                LL_FOREACH (msg->headers, hdr)
                {
                        if (hdr->name->len == slen) {
-                               if (g_ascii_strncasecmp(hdr->name->str, name, slen) == 0) {
+                               if (g_ascii_strncasecmp (hdr->name->str, name, slen) == 0) {
                                        res = hdr->value->str;
                                        break;
                                }
@@ -1373,6 +1406,30 @@ rspamd_http_message_find_header (struct rspamd_http_message *msg,
        return res;
 }
 
+gboolean rspamd_http_message_remove_header (struct rspamd_http_message *msg,
+       const gchar *name)
+{
+       struct rspamd_http_header *hdr, *tmp;
+       gboolean res = FALSE;
+       guint slen = strlen (name);
+
+       if (msg != NULL) {
+               DL_FOREACH_SAFE (msg->headers, hdr, tmp) {
+                       if (hdr->name->len == slen) {
+                               if (g_ascii_strncasecmp (hdr->name->str, name, slen) == 0) {
+                                       res = TRUE;
+                                       DL_DELETE (msg->headers, hdr);
+                                       g_string_free (hdr->name, TRUE);
+                                       g_string_free (hdr->value, TRUE);
+                                       g_slice_free1 (sizeof (*hdr), hdr);
+                               }
+                       }
+               }
+       }
+
+       return res;
+}
+
 /*
  * HTTP router functions
  */
index 0c1515b47ff91e3b56150d359719f4800e7be6dc..41e3bb2bdf52087b4e2482bad9202d6c61e02a30 100644 (file)
@@ -287,6 +287,14 @@ rspamd_http_connection_unref (struct rspamd_http_connection *conn)
  */
 void rspamd_http_connection_reset (struct rspamd_http_connection *conn);
 
+/**
+ * Extract the current message from a connection to deal with separately
+ * @param conn
+ * @return
+ */
+struct rspamd_http_message * rspamd_http_connection_steal_msg (
+               struct rspamd_http_connection *conn);
+
 /**
  * Create new HTTP message
  * @param type request or response
@@ -307,21 +315,30 @@ struct rspamd_http_message* rspamd_http_message_from_url (const gchar *url);
  * @param name
  * @param value
  */
-void rspamd_http_message_add_header (struct rspamd_http_message *rep,
+void rspamd_http_message_add_header (struct rspamd_http_message *msg,
        const gchar *name,
        const gchar *value);
 
 /**
  * Search for a specified header in message
- * @param rep message
+ * @param msg message
  * @param name name of header
  */
-const gchar * rspamd_http_message_find_header (struct rspamd_http_message *rep,
+const gchar * rspamd_http_message_find_header (struct rspamd_http_message *msg,
        const gchar *name);
 
 /**
- * Free HTTP reply
- * @param rep
+ * Remove specific header from a message
+ * @param msg
+ * @param name
+ * @return
+ */
+gboolean rspamd_http_message_remove_header (struct rspamd_http_message *msg,
+       const gchar *name);
+
+/**
+ * Free HTTP message
+ * @param msg
  */
 void rspamd_http_message_free (struct rspamd_http_message *msg);