1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "md5.h"
#include "message-parser.h"
#include "mbox-md5.h"
struct mbox_md5_context {
struct md5_context hdr_md5_ctx;
bool seen_received_hdr;
};
struct mbox_md5_header_func {
const char *header;
bool (*func)(struct mbox_md5_context *ctx,
struct message_header_line *hdr);
};
static bool parse_date(struct mbox_md5_context *ctx,
struct message_header_line *hdr)
{
if (!ctx->seen_received_hdr) {
/* Received-header contains date too, and more trusted one */
md5_update(&ctx->hdr_md5_ctx, hdr->value, hdr->value_len);
}
return TRUE;
}
static bool parse_delivered_to(struct mbox_md5_context *ctx,
struct message_header_line *hdr)
{
md5_update(&ctx->hdr_md5_ctx, hdr->value, hdr->value_len);
return TRUE;
}
static bool parse_message_id(struct mbox_md5_context *ctx,
struct message_header_line *hdr)
{
if (!ctx->seen_received_hdr) {
/* Received-header contains unique ID too,
and more trusted one */
md5_update(&ctx->hdr_md5_ctx, hdr->value, hdr->value_len);
}
return TRUE;
}
static bool parse_received(struct mbox_md5_context *ctx,
struct message_header_line *hdr)
{
if (!ctx->seen_received_hdr) {
/* get only the first received-header */
md5_update(&ctx->hdr_md5_ctx, hdr->value, hdr->value_len);
if (!hdr->continues)
ctx->seen_received_hdr = TRUE;
}
return TRUE;
}
static bool parse_x_delivery_id(struct mbox_md5_context *ctx,
struct message_header_line *hdr)
{
/* Let the local delivery agent help generate unique ID's but don't
blindly trust this header alone as it could just as easily come from
the remote. */
md5_update(&ctx->hdr_md5_ctx, hdr->value, hdr->value_len);
return TRUE;
}
static struct mbox_md5_header_func md5_header_funcs[] = {
{ "Date", parse_date },
{ "Delivered-To", parse_delivered_to },
{ "Message-ID", parse_message_id },
{ "Received", parse_received },
{ "X-Delivery-ID", parse_x_delivery_id }
};
static int bsearch_header_func_cmp(const void *p1, const void *p2)
{
const char *key = p1;
const struct mbox_md5_header_func *func = p2;
return strcasecmp(key, func->header);
}
static struct mbox_md5_context *mbox_md5_apop3d_init(void)
{
struct mbox_md5_context *ctx;
ctx = i_new(struct mbox_md5_context, 1);
md5_init(&ctx->hdr_md5_ctx);
return ctx;
}
static void mbox_md5_apop3d_more(struct mbox_md5_context *ctx,
struct message_header_line *hdr)
{
struct mbox_md5_header_func *func;
func = bsearch(hdr->name, md5_header_funcs,
N_ELEMENTS(md5_header_funcs), sizeof(*md5_header_funcs),
bsearch_header_func_cmp);
if (func != NULL)
(void)func->func(ctx, hdr);
}
static void mbox_md5_apop3d_finish(struct mbox_md5_context *ctx,
unsigned char result[STATIC_ARRAY 16])
{
md5_final(&ctx->hdr_md5_ctx, result);
i_free(ctx);
}
struct mbox_md5_vfuncs mbox_md5_apop3d = {
mbox_md5_apop3d_init,
mbox_md5_apop3d_more,
mbox_md5_apop3d_finish
};
|