]> source.dussan.org Git - rspamd.git/commitdiff
Another fix for simple canonicalization for body.
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 14 Aug 2012 14:54:43 +0000 (18:54 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 14 Aug 2012 14:54:43 +0000 (18:54 +0400)
src/dkim.c

index d042f3f7a3724c9e2cfc1715ca25b8ebaf74e6ff..bcdadafdb904fea84627062d8044bb72857c7349 100644 (file)
@@ -866,6 +866,62 @@ rspamd_dkim_relaxed_body_step (GChecksum *ck, const gchar **start, guint remain)
        return !finished;
 }
 
+static gboolean
+rspamd_dkim_simple_body_step (GChecksum *ck, const gchar **start, guint remain)
+{
+       const gchar                                                                     *h;
+       static gchar                                                             buf[BUFSIZ];
+       gchar                                                                           *t;
+       guint                                                                            len, inlen;
+       gboolean                                                                         finished = FALSE;
+
+       if (remain > sizeof (buf)) {
+               len = sizeof (buf);
+       }
+       else {
+               len = remain;
+               finished = TRUE;
+       }
+       inlen = sizeof (buf) - 1;
+       h = *start;
+       t = &buf[0];
+
+       while (len && inlen) {
+               if (*h == '\r' || *h == '\n') {
+                       /* Replace a single \n or \r with \r\n */
+                       if (*h == '\n' && *(h - 1) != '\r') {
+                               *t ++ = '\r';
+                               inlen --;
+                       }
+                       else if (*h == '\r' && *(h + 1) != '\n') {
+                               *t ++ = *h ++;
+                               *t ++ = '\n';
+                               if (inlen > 1) {
+                                       inlen -= 2;
+                               }
+                               else {
+                                       /* It is safe as inlen = sizeof (buf) - 1 */
+                                       inlen = 0;
+                               }
+                               len --;
+                               continue;
+                       }
+               }
+               *t++ = *h++;
+               inlen --;
+               len --;
+       }
+
+       *start = h;
+
+#if 0
+       msg_debug ("update signature with buffer: %*s", t - buf, buf);
+#endif
+       g_checksum_update (ck, buf, t - buf);
+
+       return !finished;
+}
+
 static gboolean
 rspamd_dkim_canonize_body (rspamd_dkim_context_t *ctx, const gchar *start, const gchar *end)
 {
@@ -896,15 +952,10 @@ rspamd_dkim_canonize_body (rspamd_dkim_context_t *ctx, const gchar *start, const
                else {
                        if (ctx->body_canon_type == DKIM_CANON_SIMPLE) {
                                /* Simple canonization */
-                               g_checksum_update (ctx->body_hash, start, end - start + 1);
+                               while (rspamd_dkim_simple_body_step (ctx->body_hash, &start, end - start + 1));
                        }
                        else {
                                while (rspamd_dkim_relaxed_body_step (ctx->body_hash, &start, end - start + 1));
-                               return TRUE;
-                       }
-                       if (*end != '\n' || *(end - 1) != '\r') {
-                               msg_debug ("append CRLF");
-                               g_checksum_update (ctx->body_hash, CRLF, sizeof (CRLF) - 1);
                        }
                }
                return TRUE;
@@ -1032,6 +1083,7 @@ rspamd_dkim_canonize_header_relaxed (rspamd_dkim_context_t *ctx, const gchar *he
 struct rspamd_dkim_sign_chunk {
        const gchar *begin;
        gsize len;
+       gboolean append_crlf;
 };
 
 static gboolean
@@ -1087,7 +1139,15 @@ rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *hea
                        /* c contains the beginning of header */
                        if (*p == '\n' && (!g_ascii_isspace (p[1]) || p[1] == '\0')) {
                                chunk.begin = c;
-                               chunk.len = p - c + 1;
+                               if (*(p - 1) == '\r') {
+                                       chunk.len = p - c + 1;
+                                       chunk.append_crlf = FALSE;
+                               }
+                               else {
+                                       /* Need append CRLF as linefeed is not proper */
+                                       chunk.len = p - c;
+                                       chunk.append_crlf = TRUE;
+                               }
                                g_array_append_val (to_sign, chunk);
                                c = p + 1;
                                state = 0;
@@ -1103,13 +1163,26 @@ rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *hea
 
                        for (i = to_sign->len - 1; i >= 0 && count > 0; i --, count --) {
                                elt = &g_array_index (to_sign, struct rspamd_dkim_sign_chunk, i);
-                               msg_debug ("update signature with header: %*s", elt->len, elt->begin);
-                               g_checksum_update (ctx->headers_hash, elt->begin, elt->len);
+
+                               if (!chunk.append_crlf) {
+                                       msg_debug ("update signature with header: %*s", elt->len, elt->begin);
+                                       g_checksum_update (ctx->headers_hash, elt->begin, elt->len);
+                               }
+                               else {
+                                       msg_debug ("update signature with header: %*s", elt->len + 1, elt->begin);
+                                       g_checksum_update (ctx->headers_hash, elt->begin, elt->len);
+                                       g_checksum_update (ctx->headers_hash, CRLF, sizeof (CRLF) - 1);
+                               }
                        }
                }
                else {
                        elt = &g_array_index (to_sign, struct rspamd_dkim_sign_chunk, 0);
-                       rspamd_dkim_signature_update (ctx, elt->begin, elt->len);
+                       if (elt->append_crlf) {
+                               rspamd_dkim_signature_update (ctx, elt->begin, elt->len + 1);
+                       }
+                       else {
+                               rspamd_dkim_signature_update (ctx, elt->begin, elt->len);
+                       }
                }
        }