spf_request.c

Go to the documentation of this file.
00001 /* 
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of either:
00004  * 
00005  *   a) The GNU Lesser General Public License as published by the Free
00006  *      Software Foundation; either version 2.1, or (at your option) any
00007  *      later version, 
00008  * 
00009  *   OR
00010  * 
00011  *   b) The two-clause BSD license.
00012  *
00013  * These licenses can be found with the distribution in the file LICENSES
00014  */
00015 
00016 #include "spf_sys_config.h"
00017 
00018 #ifdef STDC_HEADERS
00019 # include <stdio.h>        /* stdin / stdout */
00020 # include <stdlib.h>       /* malloc / free */
00021 #endif
00022 
00023 #ifdef HAVE_STRING_H
00024 # include <string.h>       /* strstr / strdup */
00025 #else
00026 # ifdef HAVE_STRINGS_H
00027 #  include <strings.h>       /* strstr / strdup */
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         /* set cur_dom and env_from? */
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++; /* "@domain.example" */
00174                 len = sizeof("postmaster@") + strlen(from);
00175                 sr->env_from = malloc(len + 1); /* sizeof("") == 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;       // SPF_E_SUCCESS
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         /* Now, in theory, SPF_response_errors(spf_response) == 0 */
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         /* If we get here, spf_record better not be NULL */
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         /* Give localhost a free ride */
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 /* This interface isn't finalised. */
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         /* Give localhost a free ride */
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 /* FIXME: Check the implementation of this. */
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         /* Give localhost a free ride */
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 }

Generated on Tue Nov 4 13:27:39 2008 for libspf2 by  doxygen 1.5.4