Commit | Line | Data |
---|---|---|
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 | ||
19 | srs_t *srs = NULL; | |
20 | uschar *srs_db_forward = NULL; | |
21 | uschar *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 |
27 | int |
28 | eximsrs_init() | |
8523533c | 29 | { |
d7978c0f JH |
30 | const uschar *list = srs_config; |
31 | uschar secret_buf[SRS_MAX_SECRET_LENGTH]; | |
32 | uschar *secret = NULL; | |
33 | uschar sbuf[4]; | |
34 | uschar *sbufp; | |
35 | ||
36 | /* Check if this instance of Exim has not initialized SRS */ | |
37 | if (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 | 115 | return OK; |
8523533c TK |
116 | } |
117 | ||
118 | ||
d7978c0f JH |
119 | int |
120 | eximsrs_done() | |
8523533c | 121 | { |
d7978c0f JH |
122 | if (srs) srs_close(srs); |
123 | srs = NULL; | |
124 | return OK; | |
8523533c TK |
125 | } |
126 | ||
127 | ||
d7978c0f JH |
128 | int |
129 | eximsrs_forward(uschar **result, uschar *orig_sender, uschar *domain) | |
8523533c | 130 | { |
d7978c0f JH |
131 | char res[512]; |
132 | int n; | |
8523533c | 133 | |
d7978c0f | 134 | if ((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); |
142 | return OK; | |
8523533c TK |
143 | } |
144 | ||
145 | ||
d7978c0f JH |
146 | int |
147 | eximsrs_reverse(uschar **result, uschar *address) | |
8523533c | 148 | { |
d7978c0f JH |
149 | char res[512]; |
150 | int n; | |
8523533c | 151 | |
d7978c0f | 152 | if ((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); |
164 | return OK; | |
8523533c TK |
165 | } |
166 | ||
167 | ||
d7978c0f JH |
168 | int |
169 | eximsrs_db_set(BOOL reverse, uschar *srs_db) | |
8523533c | 170 | { |
d7978c0f JH |
171 | if (reverse) |
172 | srs_db_reverse = (srs_db == NULL ? NULL : string_copy(srs_db)); | |
173 | else | |
174 | srs_db_forward = (srs_db == NULL ? NULL : string_copy(srs_db)); | |
8e669ac1 | 175 | |
d7978c0f JH |
176 | if (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 | 180 | return OK; |
8523533c TK |
181 | } |
182 | ||
183 | ||
d7978c0f JH |
184 | srs_result |
185 | eximsrs_db_insert(srs_t *srs, char *data, uint data_len, char *result, uint result_len) | |
8523533c | 186 | { |
d7978c0f JH |
187 | uschar *res; |
188 | uschar buf[64]; | |
384152a6 | 189 | |
d7978c0f JH |
190 | if (srs_db_forward == NULL) |
191 | return SRS_RESULT_DBERROR; | |
8523533c | 192 | |
d7978c0f JH |
193 | srs_db_address = string_copyn(data, data_len); |
194 | if (srs_generate_unique_id(srs, srs_db_address, buf, 64) & SRS_RESULT_FAIL) | |
195 | return SRS_RESULT_DBERROR; | |
8e669ac1 | 196 | |
d7978c0f | 197 | srs_db_key = string_copyn(buf, 16); |
8e669ac1 | 198 | |
d7978c0f JH |
199 | if ((res = expand_string(srs_db_forward)) == NULL) |
200 | return SRS_RESULT_DBERROR; | |
8e669ac1 | 201 | |
d7978c0f JH |
202 | if (result_len < 17) |
203 | return SRS_RESULT_DBERROR; | |
8e669ac1 | 204 | |
d7978c0f | 205 | Ustrncpy(result, srs_db_key, result_len); |
8523533c | 206 | |
d7978c0f | 207 | return SRS_RESULT_OK; |
8523533c TK |
208 | } |
209 | ||
210 | ||
d7978c0f JH |
211 | srs_result |
212 | eximsrs_db_lookup(srs_t *srs, char *data, uint data_len, char *result, uint result_len) | |
8523533c | 213 | { |
d7978c0f | 214 | uschar *res; |
8523533c | 215 | |
d7978c0f JH |
216 | if (srs_db_reverse == NULL) |
217 | return SRS_RESULT_DBERROR; | |
384152a6 | 218 | |
d7978c0f JH |
219 | srs_db_key = string_copyn(data, data_len); |
220 | if ((res = expand_string(srs_db_reverse)) == NULL) | |
221 | return SRS_RESULT_DBERROR; | |
8e669ac1 | 222 | |
d7978c0f JH |
223 | if (Ustrlen(res) >= result_len) |
224 | return SRS_RESULT_ADDRESSTOOLONG; | |
8e669ac1 | 225 | |
d7978c0f | 226 | strncpy(result, res, result_len); |
8523533c | 227 | |
d7978c0f | 228 | return SRS_RESULT_OK; |
8523533c TK |
229 | } |
230 | ||
231 | ||
232 | #endif | |
233 |