OpenSSL: under resumption open ticket DB writable, for record delete
[exim.git] / src / src / srs.c
CommitLineData
8523533c
TK
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
5/* SRS - Sender rewriting scheme support
384152a6 6 (C)2004 Miles Wilton <miles@mirtol.com>
80fea873 7 Copyright (c) The Exim Maintainers 2016
384152a6
TK
8
9 SRS Support Version: 1.0a
10
8523533c
TK
11 License: GPL */
12
13#include "exim.h"
14#ifdef EXPERIMENTAL_SRS
15
16#include <srs_alt.h>
17#include "srs.h"
18
19srs_t *srs = NULL;
20uschar *srs_db_forward = NULL;
21uschar *srs_db_reverse = NULL;
22
23
24/* srs_init just initialises libsrs and creates (if necessary)
25 an srs object to use for all srs calls in this instance */
8e669ac1 26
d7978c0f
JH
27int
28eximsrs_init()
8523533c 29{
d7978c0f
JH
30const uschar *list = srs_config;
31uschar secret_buf[SRS_MAX_SECRET_LENGTH];
32uschar *secret = NULL;
33uschar sbuf[4];
34uschar *sbufp;
35
36/* Check if this instance of Exim has not initialized SRS */
37if (srs == NULL)
8523533c 38 {
d7978c0f
JH
39 int co = 0;
40 int hashlen, maxage;
41 BOOL usetimestamp, usehash;
42
43 /* Copy config vars */
44 hashlen = srs_hashlength;
45 maxage = srs_maxage;
46 usetimestamp = srs_usetimestamp;
47 usehash = srs_usehash;
48
49 /* Pass srs_config var (overrides new config vars) */
50 co = 0;
51 if (srs_config != NULL)
8523533c 52 {
d7978c0f 53 secret = string_nextinlist(&list, &co, secret_buf, SRS_MAX_SECRET_LENGTH);
384152a6 54
d7978c0f
JH
55 if ((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))))
56 maxage = atoi(sbuf);
384152a6 57
d7978c0f
JH
58 if ((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))))
59 hashlen = atoi(sbuf);
384152a6 60
d7978c0f
JH
61 if ((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))))
62 usetimestamp = atoi(sbuf);
384152a6 63
d7978c0f
JH
64 if ((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))))
65 usehash = atoi(sbuf);
8523533c 66 }
8e669ac1 67
d7978c0f
JH
68 if (srs_hashmin == -1)
69 srs_hashmin = hashlen;
384152a6 70
d7978c0f
JH
71 /* First secret specified in secrets? */
72 co = 0;
73 list = srs_secrets;
74 if (secret == NULL || *secret == '\0')
75 if (!(secret = string_nextinlist(&list, &co, secret_buf, SRS_MAX_SECRET_LENGTH)))
384152a6 76 {
d7978c0f
JH
77 log_write(0, LOG_MAIN | LOG_PANIC,
78 "SRS Configuration Error: No secret specified");
79 return DEFER;
384152a6 80 }
8e669ac1 81
d7978c0f
JH
82 /* Check config */
83 if (maxage < 0 || maxage > 365)
8523533c 84 {
d7978c0f
JH
85 log_write(0, LOG_MAIN | LOG_PANIC,
86 "SRS Configuration Error: Invalid maximum timestamp age");
87 return DEFER;
8523533c 88 }
d7978c0f 89 if (hashlen < 1 || hashlen > 20 || srs_hashmin < 1 || srs_hashmin > 20)
8523533c 90 {
d7978c0f
JH
91 log_write(0, LOG_MAIN | LOG_PANIC,
92 "SRS Configuration Error: Invalid hash length");
93 return DEFER;
8523533c 94 }
8e669ac1 95
d7978c0f 96 if (!(srs = srs_open(secret, Ustrlen(secret), maxage, hashlen, srs_hashmin)))
8523533c 97 {
d7978c0f
JH
98 log_write(0, LOG_MAIN | LOG_PANIC,
99 "Failed to allocate SRS memory");
100 return DEFER;
8523533c
TK
101 }
102
d7978c0f
JH
103 srs_set_option(srs, SRS_OPTION_USETIMESTAMP, usetimestamp);
104 srs_set_option(srs, SRS_OPTION_USEHASH, usehash);
8523533c 105
d7978c0f
JH
106 /* Extra secrets? */
107 while((secret = string_nextinlist(&list, &co, secret_buf, SRS_MAX_SECRET_LENGTH)))
108 srs_add_secret(srs, secret,
109 Ustrlen(secret) > SRS_MAX_SECRET_LENGTH ? SRS_MAX_SECRET_LENGTH : Ustrlen(secret));
8523533c 110
d7978c0f
JH
111 DEBUG(D_any)
112 debug_printf("SRS initialized\n");
8523533c
TK
113 }
114
d7978c0f 115return OK;
8523533c
TK
116}
117
118
d7978c0f
JH
119int
120eximsrs_done()
8523533c 121{
d7978c0f
JH
122if (srs) srs_close(srs);
123srs = NULL;
124return OK;
8523533c
TK
125}
126
127
d7978c0f
JH
128int
129eximsrs_forward(uschar **result, uschar *orig_sender, uschar *domain)
8523533c 130{
d7978c0f
JH
131char res[512];
132int n;
8523533c 133
d7978c0f 134if ((n = srs_forward(srs, orig_sender, domain, res, sizeof(res))) & SRS_RESULT_FAIL)
8523533c 135 {
d7978c0f
JH
136 DEBUG(D_any)
137 debug_printf("srs_forward failed (%s, %s): %s\n", orig_sender, domain, srs_geterrormsg(n));
138 return DEFER;
8523533c
TK
139 }
140
d7978c0f
JH
141*result = string_copy(res);
142return OK;
8523533c
TK
143}
144
145
d7978c0f
JH
146int
147eximsrs_reverse(uschar **result, uschar *address)
8523533c 148{
d7978c0f
JH
149char res[512];
150int n;
8523533c 151
d7978c0f 152if ((n = srs_reverse(srs, address, res, sizeof(res))) & SRS_RESULT_FAIL)
8523533c 153 {
d7978c0f
JH
154 DEBUG(D_any)
155 debug_printf("srs_reverse failed (%s): %s\n", address, srs_geterrormsg(n));
156 if (n == SRS_RESULT_NOTSRS || n == SRS_RESULT_BADSRS)
157 return DECLINE;
158 if (n == SRS_RESULT_BADHASH || n == SRS_RESULT_BADTIMESTAMP || n == SRS_RESULT_TIMESTAMPEXPIRED)
159 return FAIL;
160 return DEFER;
8523533c
TK
161 }
162
d7978c0f
JH
163*result = string_copy(res);
164return OK;
8523533c
TK
165}
166
167
d7978c0f
JH
168int
169eximsrs_db_set(BOOL reverse, uschar *srs_db)
8523533c 170{
d7978c0f
JH
171if (reverse)
172 srs_db_reverse = (srs_db == NULL ? NULL : string_copy(srs_db));
173else
174 srs_db_forward = (srs_db == NULL ? NULL : string_copy(srs_db));
8e669ac1 175
d7978c0f
JH
176if (srs_set_db_functions(srs, (srs_db_forward ? eximsrs_db_insert : NULL),
177 (srs_db_reverse ? eximsrs_db_lookup : NULL)) & SRS_RESULT_FAIL)
178 return DEFER;
8e669ac1 179
d7978c0f 180return OK;
8523533c
TK
181}
182
183
d7978c0f
JH
184srs_result
185eximsrs_db_insert(srs_t *srs, char *data, uint data_len, char *result, uint result_len)
8523533c 186{
d7978c0f
JH
187uschar *res;
188uschar buf[64];
384152a6 189
d7978c0f
JH
190if (srs_db_forward == NULL)
191 return SRS_RESULT_DBERROR;
8523533c 192
d7978c0f
JH
193srs_db_address = string_copyn(data, data_len);
194if (srs_generate_unique_id(srs, srs_db_address, buf, 64) & SRS_RESULT_FAIL)
195 return SRS_RESULT_DBERROR;
8e669ac1 196
d7978c0f 197srs_db_key = string_copyn(buf, 16);
8e669ac1 198
d7978c0f
JH
199if ((res = expand_string(srs_db_forward)) == NULL)
200 return SRS_RESULT_DBERROR;
8e669ac1 201
d7978c0f
JH
202if (result_len < 17)
203 return SRS_RESULT_DBERROR;
8e669ac1 204
d7978c0f 205Ustrncpy(result, srs_db_key, result_len);
8523533c 206
d7978c0f 207return SRS_RESULT_OK;
8523533c
TK
208}
209
210
d7978c0f
JH
211srs_result
212eximsrs_db_lookup(srs_t *srs, char *data, uint data_len, char *result, uint result_len)
8523533c 213{
d7978c0f 214uschar *res;
8523533c 215
d7978c0f
JH
216if (srs_db_reverse == NULL)
217 return SRS_RESULT_DBERROR;
384152a6 218
d7978c0f
JH
219srs_db_key = string_copyn(data, data_len);
220if ((res = expand_string(srs_db_reverse)) == NULL)
221 return SRS_RESULT_DBERROR;
8e669ac1 222
d7978c0f
JH
223if (Ustrlen(res) >= result_len)
224 return SRS_RESULT_ADDRESSTOOLONG;
8e669ac1 225
d7978c0f 226strncpy(result, res, result_len);
8523533c 227
d7978c0f 228return SRS_RESULT_OK;
8523533c
TK
229}
230
231
232#endif
233