libspf2
1.2.10
|
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 size_t 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 }