00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "spf_sys_config.h"
00017
00018 #ifdef STDC_HEADERS
00019 # include <stdio.h>
00020 # include <stdlib.h>
00021 #endif
00022
00023 #ifdef HAVE_STRING_H
00024 # include <string.h>
00025 #else
00026 # ifdef HAVE_STRINGS_H
00027 # include <strings.h>
00028 # endif
00029 #endif
00030
00031
00032 #include "spf.h"
00033 #include "spf_dns.h"
00034 #include "spf_request.h"
00035 #include "spf_internal.h"
00036
00037 #define SPF_FREE(x) \
00038 do { if (x) free(x); (x) = NULL; } while(0)
00039
00040 SPF_request_t *
00041 SPF_request_new(SPF_server_t *spf_server)
00042 {
00043 SPF_request_t *sr;
00044
00045 sr = (SPF_request_t *)malloc(sizeof(SPF_request_t));
00046 if (! sr)
00047 return sr;
00048 memset(sr, 0, sizeof(SPF_request_t));
00049
00050 sr->spf_server = spf_server;
00051 sr->client_ver = AF_UNSPEC;
00052 sr->ipv4.s_addr = htonl(INADDR_ANY);
00053 sr->ipv6 = in6addr_any;
00054
00055 return sr;
00056 }
00057
00058 void
00059 SPF_request_free(SPF_request_t *sr)
00060 {
00061 SPF_ASSERT_NOTNULL(sr);
00062 SPF_FREE(sr->client_dom);
00063 SPF_FREE(sr->helo_dom);
00064 SPF_FREE(sr->env_from);
00065 SPF_FREE(sr->env_from_lp);
00066 SPF_FREE(sr->env_from_dp);
00067 free(sr);
00068 }
00069
00070 SPF_errcode_t
00071 SPF_request_set_ipv4(SPF_request_t *sr, struct in_addr addr)
00072 {
00073 if (sr->client_dom) {
00074 free(sr->client_dom);
00075 sr->client_dom = NULL;
00076 }
00077 sr->client_ver = AF_INET;
00078 sr->ipv4 = addr;
00079 return SPF_E_SUCCESS;
00080 }
00081
00082 SPF_errcode_t
00083 SPF_request_set_ipv6(SPF_request_t *sr, struct in6_addr addr)
00084 {
00085 if (sr->client_dom) {
00086 free(sr->client_dom);
00087 sr->client_dom = NULL;
00088 }
00089 sr->client_ver = AF_INET6;
00090 sr->ipv6 = addr;
00091 return SPF_E_SUCCESS;
00092 }
00093
00094 SPF_errcode_t
00095 SPF_request_set_ipv4_str(SPF_request_t *sr, const char *astr)
00096 {
00097 struct in_addr addr;
00098 if (astr == NULL)
00099 astr = "0.0.0.0";
00100 if (inet_pton(AF_INET, astr, &addr) <= 0)
00101 return SPF_E_INVALID_IP4;
00102 return SPF_request_set_ipv4(sr, addr);
00103 }
00104
00105 SPF_errcode_t
00106 SPF_request_set_ipv6_str(SPF_request_t *sr, const char *astr)
00107 {
00108 struct in6_addr addr;
00109 if (astr == NULL)
00110 astr = "::";
00111 if (inet_pton(AF_INET6, astr, &addr) <= 0)
00112 return SPF_E_INVALID_IP6;
00113 return SPF_request_set_ipv6(sr, addr);
00114 }
00115
00116 SPF_errcode_t
00117 SPF_request_set_helo_dom(SPF_request_t *sr, const char *dom)
00118 {
00119 SPF_ASSERT_NOTNULL(dom);
00120 SPF_FREE(sr->helo_dom);
00121 sr->helo_dom = strdup(dom);
00122 if (! sr->helo_dom)
00123 return SPF_E_NO_MEMORY;
00124
00125 if (sr->env_from == NULL)
00126 return SPF_request_set_env_from(sr, dom);
00127 return SPF_E_SUCCESS;
00128 }
00129
00130 const char *
00131 SPF_request_get_rec_dom(SPF_request_t *sr)
00132 {
00133 SPF_server_t *spf_server;
00134 spf_server = sr->spf_server;
00135 return spf_server->rec_dom;
00136 }
00137
00138 int
00139 SPF_request_set_env_from(SPF_request_t *sr, const char *from)
00140 {
00141 char *cp;
00142 int len;
00143
00144 SPF_ASSERT_NOTNULL(from);
00145 SPF_FREE(sr->env_from);
00146 SPF_FREE(sr->env_from_lp);
00147 SPF_FREE(sr->env_from_dp);
00148
00149 if (*from == '\0' && sr->helo_dom != NULL)
00150 from = sr->helo_dom;
00151 cp = strrchr(from, '@');
00152 if (cp && (cp != from)) {
00153 sr->env_from = strdup(from);
00154 if (! sr->env_from)
00155 return SPF_E_NO_MEMORY;
00156
00157 len = cp - from;
00158 sr->env_from_lp = malloc(len + 1);
00159 if (!sr->env_from_lp) {
00160 SPF_FREE(sr->env_from);
00161 return SPF_E_NO_MEMORY;
00162 }
00163 strncpy(sr->env_from_lp, from, len);
00164 sr->env_from_lp[len] = '\0';
00165 sr->env_from_dp = strdup(cp + 1);
00166 if (!sr->env_from_dp) {
00167 SPF_FREE(sr->env_from);
00168 SPF_FREE(sr->env_from_lp);
00169 return SPF_E_NO_MEMORY;
00170 }
00171 }
00172 else {
00173 if (cp == from) from++;
00174 len = sizeof("postmaster@") + strlen(from);
00175 sr->env_from = malloc(len + 1);
00176 if (! sr->env_from)
00177 return SPF_E_NO_MEMORY;
00178 sprintf(sr->env_from, "postmaster@%s", from);
00179 sr->env_from_lp = strdup("postmaster");
00180 if (!sr->env_from_lp) {
00181 SPF_FREE(sr->env_from);
00182 return SPF_E_NO_MEMORY;
00183 }
00184 sr->env_from_dp = strdup(from);
00185 if (!sr->env_from_dp) {
00186 SPF_FREE(sr->env_from);
00187 SPF_FREE(sr->env_from_lp);
00188 return SPF_E_NO_MEMORY;
00189 }
00190 }
00191
00192 return 0;
00193 }
00194
00195 const char *
00196 SPF_request_get_client_dom(SPF_request_t *sr)
00197 {
00198 SPF_server_t *spf_server;
00199
00200 SPF_ASSERT_NOTNULL(sr);
00201 spf_server = sr->spf_server;
00202 SPF_ASSERT_NOTNULL(spf_server);
00203
00204 if (sr->client_dom == NULL) {
00205 sr->client_dom = SPF_dns_get_client_dom(spf_server->resolver,
00206 sr);
00207 }
00208 return sr->client_dom;
00209 }
00210
00211 int
00212 SPF_request_is_loopback(SPF_request_t *sr)
00213 {
00214 if (sr->client_ver == AF_INET) {
00215 if ((ntohl(sr->ipv4.s_addr) & IN_CLASSA_NET) ==
00216 (IN_LOOPBACKNET << 24)) {
00217 return TRUE;
00218 }
00219 }
00220 else if (sr->client_ver == AF_INET6) {
00221 if (IN6_IS_ADDR_LOOPBACK(&sr->ipv6))
00222 return TRUE;
00223 }
00224 return FALSE;
00225 }
00226
00227 static SPF_errcode_t
00228 SPF_request_prepare(SPF_request_t *sr)
00229 {
00230 if (sr->use_helo)
00231 sr->cur_dom = sr->helo_dom;
00232 else
00233 sr->cur_dom = sr->env_from_dp;
00234 return SPF_E_SUCCESS;
00235 }
00236
00240 static SPF_errcode_t
00241 SPF_request_query_record(SPF_request_t *spf_request,
00242 SPF_response_t *spf_response,
00243 SPF_record_t *spf_record,
00244 SPF_errcode_t err)
00245 {
00246 if (err != SPF_E_SUCCESS) {
00247 if (spf_record)
00248 SPF_record_free(spf_record);
00249 return err;
00250 }
00251
00252 if (SPF_response_errors(spf_response) > 0)
00253 SPF_infof("Warning: %d errors in response, "
00254 "but no error code. Evaluating.",
00255 SPF_response_errors(spf_response));
00256
00257 spf_response->spf_record_exp = spf_record;
00258 err = SPF_record_interpret(spf_record,
00259 spf_request, spf_response, 0);
00260 SPF_record_free(spf_record);
00261
00262 return err;
00263 }
00264
00268 SPF_errcode_t
00269 SPF_request_query_mailfrom(SPF_request_t *spf_request,
00270 SPF_response_t **spf_responsep)
00271 {
00272 SPF_server_t *spf_server;
00273 SPF_record_t *spf_record;
00274 SPF_errcode_t err;
00275
00276 SPF_ASSERT_NOTNULL(spf_request);
00277 spf_server = spf_request->spf_server;
00278 SPF_ASSERT_NOTNULL(spf_server);
00279
00280 *spf_responsep = SPF_response_new(spf_request);
00281 if (! *spf_responsep)
00282 return SPF_E_NO_MEMORY;
00283
00284
00285 if (SPF_request_is_loopback(spf_request))
00286 return SPF_i_done(*spf_responsep, SPF_RESULT_PASS,
00287 SPF_REASON_LOCALHOST, SPF_E_SUCCESS);
00288
00289 SPF_request_prepare(spf_request);
00290
00291 err = SPF_server_get_record(spf_server, spf_request,
00292 *spf_responsep, &spf_record);
00293 return SPF_request_query_record(spf_request, *spf_responsep,
00294 spf_record, err);
00295 }
00296
00297
00298 SPF_errcode_t
00299 SPF_request_query_fallback(SPF_request_t *spf_request,
00300 SPF_response_t **spf_responsep,
00301 const char *record)
00302 {
00303 SPF_server_t *spf_server;
00304 SPF_record_t *spf_record;
00305 SPF_errcode_t err;
00306
00307 SPF_ASSERT_NOTNULL(spf_request);
00308 spf_server = spf_request->spf_server;
00309 SPF_ASSERT_NOTNULL(spf_server);
00310
00311 *spf_responsep = SPF_response_new(spf_request);
00312 if (! *spf_responsep)
00313 return SPF_E_NO_MEMORY;
00314
00315
00316 if (SPF_request_is_loopback(spf_request))
00317 return SPF_i_done(*spf_responsep, SPF_RESULT_PASS,
00318 SPF_REASON_LOCALHOST, SPF_E_SUCCESS);
00319
00320 SPF_request_prepare(spf_request);
00321
00322 err = SPF_record_compile(spf_server,
00323 *spf_responsep, &spf_record,
00324 record);
00325 return SPF_request_query_record(spf_request, *spf_responsep,
00326 spf_record, err);
00327 }
00328
00337
00338 SPF_errcode_t
00339 SPF_request_query_rcptto(SPF_request_t *spf_request,
00340 SPF_response_t **spf_responsep,
00341 const char *rcpt_to)
00342 {
00343 SPF_server_t *spf_server;
00344 SPF_record_t *spf_record;
00345 SPF_errcode_t err;
00346 const char *rcpt_to_dom;
00347 char *record;
00348 size_t len;
00349
00350 SPF_ASSERT_NOTNULL(spf_request);
00351 spf_server = spf_request->spf_server;
00352 SPF_ASSERT_NOTNULL(spf_server);
00353
00354 *spf_responsep = SPF_response_new(spf_request);
00355 if (! *spf_responsep)
00356 return SPF_E_NO_MEMORY;
00357
00358
00359 if (SPF_request_is_loopback(spf_request))
00360 return SPF_i_done(*spf_responsep, SPF_RESULT_PASS,
00361 SPF_REASON_LOCALHOST, SPF_E_SUCCESS);
00362
00363 rcpt_to_dom = strchr(rcpt_to, '@');
00364 if (rcpt_to_dom == NULL)
00365 rcpt_to_dom = rcpt_to;
00366 spf_request->cur_dom = rcpt_to_dom;
00367
00368 len = sizeof(SPF_VER_STR) + 64 + strlen(rcpt_to_dom);
00369 record = malloc(len);
00370 if (! record)
00371 return SPF_E_NO_MEMORY;
00372 snprintf(record, len, SPF_VER_STR " mx:%s", rcpt_to_dom);
00373 err = SPF_record_compile(spf_server,
00374 *spf_responsep, &spf_record,
00375 record);
00376 free(record);
00377 return SPF_request_query_record(spf_request, *spf_responsep,
00378 spf_record, err);
00379 }