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