]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Fix handling of HTTP HEAD methods
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 18 Oct 2016 14:17:42 +0000 (15:17 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 18 Oct 2016 14:17:42 +0000 (15:17 +0100)
contrib/http-parser/http_parser.c
src/libutil/http.c
src/libutil/map.c
src/libutil/ssl_util.c

index 33f5ed301e3b2f888c711707d9a5fcc9d14ebb3f..2984471d438137835f615590b77fdae5c22a35c3 100644 (file)
@@ -95,7 +95,7 @@ do {                                                                 \
     FOR##_mark = NULL;                                               \
   }                                                                  \
 } while (0)
-  
+
 /* Run the data callback FOR and consume the current byte */
 #define CALLBACK_DATA(FOR)                                           \
     CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
index 0df6f190daa82cc2b80061a1b033215b810bd0e5..dedf8572dd7e2dfde6e7c8f01c622ef4e546e877 100644 (file)
@@ -617,6 +617,7 @@ rspamd_http_on_headers_complete (http_parser * parser)
                (struct rspamd_http_connection *)parser->data;
        struct rspamd_http_connection_private *priv;
        struct rspamd_http_message *msg;
+       int ret;
 
        priv = conn->priv;
        msg = priv->msg;
@@ -628,6 +629,21 @@ rspamd_http_on_headers_complete (http_parser * parser)
                priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
        }
 
+       if (msg->method == HTTP_HEAD) {
+               /* We don't care about the rest */
+               if (event_pending (&priv->ev, EV_READ, NULL)) {
+                       event_del (&priv->ev);
+               }
+
+               msg->code = parser->status_code;
+               rspamd_http_connection_ref (conn);
+               ret = conn->finish_handler (conn, msg);
+               conn->finished = TRUE;
+               rspamd_http_connection_unref (conn);
+
+               return ret;
+       }
+
        /*
         * HTTP parser sets content length to (-1) when it doesn't know the real
         * length, for example, in case of chunked encoding.
@@ -758,8 +774,11 @@ rspamd_http_on_headers_complete_decrypted (http_parser *parser)
        struct rspamd_http_connection *conn =
                        (struct rspamd_http_connection *) parser->data;
        struct rspamd_http_connection_private *priv;
+       struct rspamd_http_message *msg;
+       int ret;
 
        priv = conn->priv;
+       msg = priv->msg;
 
        if (priv->header != NULL) {
                rspamd_http_finish_header (conn, priv);
@@ -772,6 +791,21 @@ rspamd_http_on_headers_complete_decrypted (http_parser *parser)
                priv->msg->flags |= RSPAMD_HTTP_FLAG_SPAMC;
        }
 
+       if (msg->method == HTTP_HEAD) {
+               /* We don't care about the rest */
+               if (event_pending (&priv->ev, EV_READ, NULL)) {
+                       event_del (&priv->ev);
+               }
+
+               msg->code = parser->status_code;
+               rspamd_http_connection_ref (conn);
+               ret = conn->finish_handler (conn, msg);
+               conn->finished = TRUE;
+               rspamd_http_connection_unref (conn);
+
+               return ret;
+       }
+
        priv->msg->method = parser->method;
        priv->msg->code = parser->status_code;
 
@@ -920,11 +954,13 @@ rspamd_http_simple_client_helper (struct rspamd_http_connection *conn)
        struct event_base *base;
        struct rspamd_http_connection_private *priv;
        gpointer ssl;
+       gint request_method;
 
        priv = conn->priv;
        base = conn->priv->ev.ev_base;
        ssl = priv->ssl;
        priv->ssl = NULL;
+       request_method = priv->msg->method;
        rspamd_http_connection_reset (conn);
        priv->ssl = ssl;
        /* Plan read message */
@@ -937,6 +973,8 @@ rspamd_http_simple_client_helper (struct rspamd_http_connection *conn)
                rspamd_http_connection_read_message (conn, conn->ud, conn->fd,
                                conn->priv->ptv, base);
        }
+
+       priv->msg->method = request_method;
 }
 
 static void
@@ -1148,8 +1186,6 @@ rspamd_http_event_handler (int fd, short what, gpointer ud)
                                                "IO read error: unexpected EOF");
                                conn->error_handler (conn, err);
                                g_error_free (err);
-
-
                        }
                        REF_RELEASE (pbuf);
                        rspamd_http_connection_unref (conn);
index 11c3ad32a7a5be10d6dda0fb14250e0084b2b7cf..689f1b0c476b1d655f700a0ff637ba7fff1e896d 100644 (file)
@@ -477,8 +477,8 @@ read_data:
                        goto err;
                }
 
-               map->read_callback (in, cbd->data_len, &cbd->periodic->cbdata, TRUE);
                msg_info_map ("read map data from %s", cbd->data->host);
+               map->read_callback (in, cbd->data_len, &cbd->periodic->cbdata, TRUE);
 
                /*
                 * We know that a map is in the locked state
index 55d5a1ad412881cc612247c781111948cae3595f..c320dfd29bdde55ea902020238522cf380150ce3 100644 (file)
@@ -520,6 +520,11 @@ rspamd_ssl_read (struct rspamd_ssl_connection *conn, gpointer buf,
 
        if (conn->state != ssl_conn_connected && conn->state != ssl_next_read) {
                errno = EINVAL;
+               g_set_error (&err, rspamd_ssl_quark (), ECONNRESET,
+                               "ssl state error: cannot read data");
+               conn->err_handler (conn->handler_data, err);
+               g_error_free (err);
+
                return -1;
        }
 
@@ -549,12 +554,13 @@ rspamd_ssl_read (struct rspamd_ssl_connection *conn, gpointer buf,
        else {
                ret = SSL_get_error (conn->ssl, ret);
                conn->state = ssl_next_read;
+               what = 0;
 
                if (ret == SSL_ERROR_WANT_READ) {
-                       what = EV_READ;
+                       what |= EV_READ;
                }
                else if (ret == SSL_ERROR_WANT_WRITE) {
-                       what = EV_WRITE;
+                       what |= EV_WRITE;
                }
                else {
                        g_set_error (&err, rspamd_ssl_quark (), ret,
@@ -603,8 +609,14 @@ rspamd_ssl_write (struct rspamd_ssl_connection *conn, gconstpointer buf,
                ret = SSL_get_error (conn->ssl, ret);
 
                if (ret == SSL_ERROR_ZERO_RETURN) {
+                       g_set_error (&err, rspamd_ssl_quark (), ret,
+                                       "ssl write error: %s", ERR_error_string (ret, NULL));
+                       conn->err_handler (conn->handler_data, err);
+                       g_error_free (err);
+                       errno = ECONNRESET;
                        conn->state = ssl_conn_reset;
-                       return 0;
+
+                       return -1;
                }
                else {
                        g_set_error (&err, rspamd_ssl_quark (), ret,