Expansions: new ${lheader:<name>}. Bug 2272
[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
8523533c
TK
27int eximsrs_init()
28{
73684885 29 const uschar *list = srs_config;
384152a6 30 uschar secret_buf[SRS_MAX_SECRET_LENGTH];
ec998f2b 31 uschar *secret = NULL;
384152a6
TK
32 uschar sbuf[4];
33 uschar *sbufp;
8523533c 34
130e9641 35 /* Check if this instance of Exim has not initialized SRS */
384152a6 36 if(srs == NULL)
8523533c 37 {
384152a6
TK
38 int co = 0;
39 int hashlen, maxage;
40 BOOL usetimestamp, usehash;
41
42 /* Copy config vars */
43 hashlen = srs_hashlength;
44 maxage = srs_maxage;
45 usetimestamp = srs_usetimestamp;
46 usehash = srs_usehash;
47
48 /* Pass srs_config var (overrides new config vars) */
49 co = 0;
50 if(srs_config != NULL)
8523533c 51 {
384152a6
TK
52 secret = string_nextinlist(&list, &co, secret_buf, SRS_MAX_SECRET_LENGTH);
53
54 if((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))) != NULL)
55 maxage = atoi(sbuf);
56
57 if((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))) != NULL)
58 hashlen = atoi(sbuf);
59
60 if((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))) != NULL)
61 usetimestamp = atoi(sbuf);
62
63 if((sbufp = string_nextinlist(&list, &co, sbuf, sizeof(sbuf))) != NULL)
64 usehash = atoi(sbuf);
8523533c 65 }
8e669ac1 66
384152a6
TK
67 if(srs_hashmin == -1)
68 srs_hashmin = hashlen;
69
70 /* First secret specified in secrets? */
8523533c 71 co = 0;
384152a6 72 list = srs_secrets;
ec998f2b 73 if(secret == NULL || *secret == '\0')
8523533c 74 {
384152a6
TK
75 if((secret = string_nextinlist(&list, &co, secret_buf, SRS_MAX_SECRET_LENGTH)) == NULL)
76 {
77 log_write(0, LOG_MAIN | LOG_PANIC,
78 "SRS Configuration Error: No secret specified");
79 return DEFER;
80 }
8523533c 81 }
8e669ac1 82
384152a6 83 /* Check config */
8523533c
TK
84 if(maxage < 0 || maxage > 365)
85 {
86 log_write(0, LOG_MAIN | LOG_PANIC,
87 "SRS Configuration Error: Invalid maximum timestamp age");
88 return DEFER;
89 }
384152a6 90 if(hashlen < 1 || hashlen > 20 || srs_hashmin < 1 || srs_hashmin > 20)
8523533c
TK
91 {
92 log_write(0, LOG_MAIN | LOG_PANIC,
93 "SRS Configuration Error: Invalid hash length");
94 return DEFER;
95 }
8e669ac1 96
384152a6 97 if((srs = srs_open(secret, Ustrlen(secret), maxage, hashlen, srs_hashmin)) == NULL)
8523533c
TK
98 {
99 log_write(0, LOG_MAIN | LOG_PANIC,
100 "Failed to allocate SRS memory");
101 return DEFER;
102 }
103
384152a6
TK
104 srs_set_option(srs, SRS_OPTION_USETIMESTAMP, usetimestamp);
105 srs_set_option(srs, SRS_OPTION_USEHASH, usehash);
8523533c 106
384152a6
TK
107 /* Extra secrets? */
108 while((secret = string_nextinlist(&list, &co, secret_buf, SRS_MAX_SECRET_LENGTH)) != NULL)
ec998f2b 109 srs_add_secret(srs, secret, (Ustrlen(secret) > SRS_MAX_SECRET_LENGTH) ? SRS_MAX_SECRET_LENGTH : Ustrlen(secret));
8523533c
TK
110
111 DEBUG(D_any)
112 debug_printf("SRS initialized\n");
113 }
114
115 return OK;
116}
117
118
119int eximsrs_done()
120{
384152a6 121 if(srs != NULL)
8523533c 122 srs_close(srs);
8e669ac1 123
8523533c
TK
124 srs = NULL;
125
126 return OK;
127}
128
129
130int eximsrs_forward(uschar **result, uschar *orig_sender, uschar *domain)
131{
132 char res[512];
133 int n;
134
135 if((n = srs_forward(srs, orig_sender, domain, res, sizeof(res))) & SRS_RESULT_FAIL)
136 {
137 DEBUG(D_any)
138 debug_printf("srs_forward failed (%s, %s): %s\n", orig_sender, domain, srs_geterrormsg(n));
139 return DEFER;
140 }
141
142 *result = string_copy(res);
143 return OK;
144}
145
146
147int eximsrs_reverse(uschar **result, uschar *address)
148{
149 char res[512];
150 int n;
151
152 if((n = srs_reverse(srs, address, res, sizeof(res))) & SRS_RESULT_FAIL)
153 {
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;
161 }
162
163 *result = string_copy(res);
164 return OK;
165}
166
167
168int eximsrs_db_set(BOOL reverse, uschar *srs_db)
169{
170 if(reverse)
384152a6 171 srs_db_reverse = (srs_db == NULL ? NULL : string_copy(srs_db));
8523533c 172 else
384152a6 173 srs_db_forward = (srs_db == NULL ? NULL : string_copy(srs_db));
8e669ac1 174
384152a6
TK
175 if(srs_set_db_functions(srs, (srs_db_forward ? eximsrs_db_insert : NULL),
176 (srs_db_reverse ? eximsrs_db_lookup : NULL)) & SRS_RESULT_FAIL)
8523533c 177 return DEFER;
8e669ac1 178
8523533c
TK
179 return OK;
180}
181
182
183srs_result eximsrs_db_insert(srs_t *srs, char *data, uint data_len, char *result, uint result_len)
184{
185 uschar *res;
384152a6
TK
186 uschar buf[64];
187
188 if(srs_db_forward == NULL)
189 return SRS_RESULT_DBERROR;
8523533c
TK
190
191 srs_db_address = string_copyn(data, data_len);
192 if(srs_generate_unique_id(srs, srs_db_address, buf, 64) & SRS_RESULT_FAIL)
384152a6 193 return SRS_RESULT_DBERROR;
8e669ac1 194
8523533c 195 srs_db_key = string_copyn(buf, 16);
8e669ac1 196
8523533c
TK
197 if((res = expand_string(srs_db_forward)) == NULL)
198 return SRS_RESULT_DBERROR;
8e669ac1 199
8523533c
TK
200 if(result_len < 17)
201 return SRS_RESULT_DBERROR;
8e669ac1 202
384152a6 203 Ustrncpy(result, srs_db_key, result_len);
8523533c
TK
204
205 return SRS_RESULT_OK;
206}
207
208
209srs_result eximsrs_db_lookup(srs_t *srs, char *data, uint data_len, char *result, uint result_len)
210{
211 uschar *res;
212
384152a6
TK
213 if(srs_db_reverse == NULL)
214 return SRS_RESULT_DBERROR;
215
8523533c
TK
216 srs_db_key = string_copyn(data, data_len);
217 if((res = expand_string(srs_db_reverse)) == NULL)
218 return SRS_RESULT_DBERROR;
8e669ac1 219
8523533c
TK
220 if(Ustrlen(res) >= result_len)
221 return SRS_RESULT_ADDRESSTOOLONG;
8e669ac1 222
8523533c
TK
223 strncpy(result, res, result_len);
224
225 return SRS_RESULT_OK;
226}
227
228
229#endif
230