00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
#ifdef _WITH_PTHREADS
00046 
#include <pthread.h>           
00047 
#endif 
00048 
00049 
#include "../../config.h"      
00050 
#include "main.h"              
00051 
#include "util.h"              
00052 
#include "dns.h"               
00053 
#include "macro.h"             
00054 
00055 
#undef VERSION                 
00056 
00057 spf_config_t confg;            
00058 
00059 int h_errno;                   
00060 
00061 
#ifdef _WITH_PTHREADS
00062 
00063 
extern pthread_mutex_t 
dns_mutex;
00064 
#endif 
00065 
00066 
static SPF_BOOL _SPF_clear_holdbufs(
peer_info_t *);
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 peer_info_t *
SPF_init(
const char *local, 
const char *rip, 
const char *expl,
00082   
const char *tf, 
const char *guess, u_int32_t use_trust, u_int32_t use_guess)
00083 {
00084   time_t curtime;           
00085 
00086   
char *cur_utc_time;       
00087 
00088   
peer_info_t *p = NULL;    
00089 
00090    
00091 
00092 
00093 
00094 
00095 
00096 
00097   
static spf_result_t spf_result[] =
00098   {{
SIZEOF(
HR_PASS),    
HR_PASS,    
SPF_PASS,    
SIZEOF(
HDR_PASS),    
HDR_PASS,    
'+' },
00099    {
SIZEOF(
HR_NONE),    
HR_NONE,    
SPF_NONE,    
SIZEOF(
HDR_NONE),    
HDR_NONE,    
'\0'},
00100    {
SIZEOF(
HR_S_FAIL),  
HR_S_FAIL,  
SPF_S_FAIL,  
SIZEOF(
HDR_S_FAIL),  
HDR_S_FAIL,  
'~' },
00101    {
SIZEOF(
HR_H_FAIL),  
HR_H_FAIL,  
SPF_H_FAIL,  
SIZEOF(
HDR_H_FAIL),  
HDR_H_FAIL,  
'-' },
00102    {
SIZEOF(
HR_ERROR),   
HR_ERROR,   
SPF_ERROR,   
SIZEOF(
HDR_ERROR),   
HDR_ERROR,   
'\0'},
00103    {
SIZEOF(
HR_NEUTRAL), 
HR_NEUTRAL, 
SPF_NEUTRAL, 
SIZEOF(
HDR_NEUTRAL), 
HDR_NEUTRAL, 
'?' },
00104    {
SIZEOF(
HR_UNKNOWN), 
HR_UNKNOWN, 
SPF_UNKNOWN, 
SIZEOF(
HDR_UNKNOWN), 
HDR_UNKNOWN, 
'\0'},
00105    {
SIZEOF(
HR_UNMECH),  
HR_UNMECH,  
SPF_UNMECH,  
SIZEOF(
HDR_UNMECH),  
HDR_UNMECH,  
'\0'}};
00106 
00107    
00108 
00109 
00110 
00111 
00112   p = 
xmalloc(
SIZEOF(
peer_info_t));
00113 
00114   p->
spf_result = spf_result;
00115    
00116 
00117    
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129   p->
spf_rlevel = 0;
00130 
00131    
00132 
00133 
00134 
00135 
00136   p->
helo = NULL;
00137   p->
ehlo = NULL;
00138   p->
from = NULL;
00139 
00140   
if (local != NULL && (*local && *(local + 1)))
00141   {
00142     p->
mta_hname = 
xstrndup(local, 
SPF_MAX_LOCAL_PART);
00143     p->
r_vhname  = 
xstrndup(local, 
SPF_MAX_LOCAL_PART);
00144   }
00145   
else
00146   {
00147     p->
mta_hname = NULL;
00148     p->
r_vhname  = NULL;
00149     
xepprintf(
"Warning: Invalid local-part detected (DSN or NULL?)\n");
00150   }
00151 
00152   
00153   
xvprintf(
"Called with: (%s) (%s) (%s) (%s) (%s) %u:%u\n",
00154      local ? local : 
"NULL",
00155      rip   ? rip   : 
"NULL",
00156      expl  ? expl  : 
"NULL",
00157      tf    ? tf    : 
"NULL",
00158      guess ? guess : 
"NULL",
00159      use_trust, use_guess);
00160 
00161    
00162 
00163 
00164 
00165 
00166 
00167   p->
spf_ver = 0;
00168 
00169    
00170 
00171 
00172 
00173 
00174   
if (use_trust == 
SPF_TRUE)
00175   {
00176     p->
use_trust = 
SPF_TRUE;
00177   }
00178   
else
00179   {
00180     p->
use_trust = 
SPF_FALSE;
00181   }
00182 
00183    
00184 
00185 
00186 
00187 
00188 
00189 
00190   
if (use_guess == 
SPF_TRUE)
00191   {
00192     p->
use_guess = 
SPF_TRUE;
00193   }
00194   
else
00195   {
00196     p->
use_guess = 
SPF_FALSE;
00197   }
00198 
00199   p->
ALL = 
SPF_FALSE;
00200   p->
p   = NULL;
00201 
00202    
00203 
00204 
00205 
00206  
00207   
if (expl != NULL && (*expl && *(expl + 1)))
00208   {
00209     p->
explain = 
xstrndup(expl, (strlen(expl) + 1));
00210   }
00211   
else
00212   {
00213     p->
explain = NULL;
00214   }
00215 
00216   
if (guess != NULL && (*guess && *(guess + 1)))
00217   {
00218     p->
guess = 
xstrndup(guess, (strlen(guess) + 1));
00219   }
00220   
else
00221   {
00222     p->
guess = 
xstrndup(
SPF_GUESS, (
SIZEOF(
SPF_GUESS) + 1));
00223   }
00224 
00225   
if ((tf != NULL) && (*tf && *(tf + 1)))
00226   {
00227     p->
trusted = 
xstrndup(tf, (strlen(tf) + 1));
00228   }
00229   
else
00230   {
00231     p->
trusted = 
xstrndup(
SPF_TRUSTED, (
SIZEOF(
SPF_TRUSTED) + 1));
00232   }
00233 
00234   p->
ptr_mhost        = NULL;    
00235   p->
current_domain   = NULL;    
00236   p->
cur_eaddr        = NULL;    
00237 
00238    
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250   
if (((rip != NULL) && (*rip && *(rip + 1))) && (inet_pton(AF_INET, rip,
00251     &p->
addr) >= 0)) 
00252   {
00253      p->
r_ip = 
xstrndup(rip, 
SPF_MAX_IP_ADDR);
00254   }
00255   
else
00256   {
00257     
xepprintf(
"Warning: Unable to execute inet_print (bad passed ipaddr?)\n");
00258     
SPF_close(p);
00259 
00260     
return(NULL);
00261   }
00262 
00263    
00264 
00265 
00266 
00267 
00268   snprintf(p->
ip_ver, 
SPF_MAX_IP_ADDR, 
"in-addr");
00269 
00270    
00271 
00272 
00273 
00274 
00275   cur_utc_time = 
xmalloc(
SPF_MAX_DATETIME);
00276   snprintf(cur_utc_time, 
SPF_MAX_DATETIME, 
"%lu", time(&curtime));
00277   memcpy(p->
utc_time, cur_utc_time, 
SPF_MAX_DATETIME);
00278   
xfree(cur_utc_time);
00279 
00280    
00281 
00282 
00283 
00284 
00285   
if ((strcmp(rip, 
"127.0.0.1") == 0) || (strcmp(rip, 
"localhost") == 0))
00286   {
00287     
UTIL_assoc_prefix(p, 
SPF_PASS, NULL);
00288   }
00289   
else
00290   {
00291     
UTIL_assoc_prefix(p, 
SPF_NEUTRAL, NULL);
00292   }
00293 
00294   
xprintf(
"libspf initialized succesfully. (%i bytes allocated)\n",
00295     
SIZEOF(
peer_info_t));
00296 
00297   
return(p);
00298 }
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 peer_info_t *
SPF_close(
peer_info_t *p)
00314 {
00315   
if (p == NULL)
00316   {
00317     
xepprintf(
"peer structure null.  Aborting!\n");
00318 
00319     
return(NULL);
00320   }
00321 
00322   
xfree(p->
mta_hname);
00323   
xfree(p->
helo);
00324   
xfree(p->
from);
00325   
xfree(p->
current_domain);
00326   
xfree(p->
r_ip);
00327   
xfree(p->
ptr_mhost);
00328   
xfree(p->
cur_eaddr);
00329   
xfree(p->
trusted);
00330   
xfree(p->
guess);
00331   
xfree(p->
explain);
00332   
xfree(p->
r_vhname);
00333 
00334   
xfree(p);
00335   p = NULL;
00336 
00337   
return(p);
00338 }
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 SPF_RESULT SPF_policy_main(
peer_info_t *p)
00400 {
00401   
SPF_RESULT res;               
00402 
00403   
char *tmp          = NULL;    
00404   
char *cname_buf    = NULL;    
00405   
char *include_buf  = NULL;    
00406   
char *redirect_buf = NULL;    
00407 
00408 
00409   
if (p == NULL)
00410   {
00411     
xepprintf(
"Unable to continue with a NULL peer_info_t structure!\n");
00412 
00413     
return(
SPF_UNKNOWN);
00414   }
00415 
00416   
if (p->
spf_rlevel >= 
SPF_MAX_RECURSE)
00417   {
00418     
xvprintf(
"recursion level exceeded (%u) levels; Aborting.\n", 
00419       p->
spf_rlevel);
00420 
00421     
return(
SPF_UNKNOWN);
00422   }
00423 
00424   
xvprintf(
"[%i] current domain: (%s)\n", p->
spf_rlevel, p->
current_domain);
00425   
xvprintf(
"[%i] include buffer: (%s)\n", p->
spf_rlevel, p->
include_buf);
00426   
xvprintf(
"[%i] redirect buffer: (%s)\n", p->
spf_rlevel, p->
redirect_buf);
00427   
00428   
00429   p->
spf_rlevel++;
00430 
00431    
00432 
00433 
00434 
00435 
00436 
00437   
_SPF_clear_holdbufs(p);
00438 
00439   
00440   res = 
SPF_policy_main_rec(p);
00441 
00442   
xvprintf(
"result of SPF parse is %i\n", res); 
00443 
00444   
00445   cname_buf    = p->
cname_buf;
00446   include_buf  = p->
include_buf;
00447   redirect_buf = p->
redirect_buf;
00448 
00449   
00450   p->
cname_buf     = NULL;
00451   p->
include_buf   = NULL;
00452   p->
redirect_buf  = NULL;
00453 
00454   
if (res != 
SPF_PASS)
00455   {
00456     
00457     tmp = p->
current_domain;
00458 
00459     
xvprintf(
"tmp is holding the current domain: (%s)\n", tmp);
00460 
00461      
00462 
00463 
00464 
00465  
00466     
if (cname_buf != NULL)
00467     {
00468       p->
current_domain = cname_buf;
00469 
00470       
xvprintf(
"Current domain: (%s); CNAME Buffer: (%s)\n",
00471         p->
current_domain, cname_buf);
00472 
00473       res = 
SPF_policy_main(p);
00474     }
00475     
else
00476     {
00477        
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487       
if (include_buf != NULL)
00488       {
00489         p->
current_domain = include_buf;
00490 
00491         
xvprintf(
"current domain is now (%s) from INCLUDE\n",
00492           p->
current_domain);
00493 
00494         res = 
SPF_policy_main(p);
00495      
00496         
xvprintf(
"result of SPF parse was %i\n", res);
00497 
00498          
00499 
00500 
00501 
00502 
00503 
00504         
if (res == 
SPF_NONE)
00505         {
00506           
xpprintf(
"INCLUDE resulted in SPF_NONE, returning UNKNOWN\n");
00507           res = 
SPF_UNKNOWN;
00508           
UTIL_assoc_prefix(p, 
SPF_UNKNOWN, NULL);
00509         }
00510       }
00511 
00512        
00513 
00514 
00515 
00516 
00517 
00518       
if ((res != 
SPF_PASS) && (redirect_buf != NULL))
00519       {
00520         
xvprintf(
"found a redirect buffer with valid data (%s)\n", 
00521           redirect_buf);
00522 
00523         p->
current_domain = redirect_buf;
00524 
00525         
xvprintf(
"current domain is now: (%s) from REDIRECT\n",
00526           p->
current_domain);
00527 
00528         res = 
SPF_policy_main(p);
00529 
00530         
xvprintf(
"result of SPF parse was %i\n", res);
00531       }
00532     }
00533 
00534     
00535     p->
current_domain = tmp;
00536 
00537     
xvprintf(
"current domain is now: (%s); received back from tmp\n",
00538       p->
current_domain);
00539   }
00540 
00541   
00542   p->
cname_buf     = cname_buf;
00543   p->
include_buf   = include_buf;
00544   p->
redirect_buf  = redirect_buf;
00545 
00546   
_SPF_clear_holdbufs(p);
00547 
00548   
xvprintf(
"leaving function; returning with value: (%i)\n", res);
00549 
00550   
return(res);
00551 }
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 SPF_RESULT SPF_policy_main_rec(
peer_info_t *p)
00571 {
00572   
SPF_RESULT res = 
SPF_NEUTRAL;   
00573   
char *rr_data  = NULL;          
00574 
00575 
00576   
if (p == NULL)
00577   {
00578     
xepprintf(
"Error peer structure is NULL.  Aborting\n");
00579 
00580     
UTIL_assoc_prefix(p, 
SPF_ERROR, NULL);
00581     
00582 
#ifdef _SPF_LOGFILE_STATS
00583 
    UTIL_log_result(p);
00584 
#endif 
00585    
00586 
00587     
xepprintf(
"leaving function; returning SPF_ERROR\n");
00588 
00589     
return(
SPF_ERROR);
00590   }
00591   
else if (p->
addr.s_addr <= 0)
00592   {
00593     
xepprintf(
"Error no idea who the remote peer is.  Abort!\n");
00594 
00595     
UTIL_assoc_prefix(p, 
SPF_ERROR, NULL);
00596     
00597 
#ifdef _SPF_LOGFILE_STATS
00598 
    UTIL_log_result(p);
00599 
#endif 
00600 
00601     
xepprintf(
"leaving function; returning SPF_ERROR\n");
00602 
00603     
return(
SPF_ERROR);
00604   }
00605 
00606    
00607 
00608 
00609 
00610 
00611 
00612 
00613   
if (p->
RES == 
SPF_PASS)
00614   {
00615 
#ifdef _SPF_LOGFILE_STATS
00616 
    UTIL_log_result(p);
00617 
#endif 
00618 
00619     
xpprintf(
"localhost exempt from SPF checks; returning SPF_PASS\n");
00620 
00621     
return(
SPF_PASS);
00622   }
00623 
00624   
if ((rr_data = 
DNS_query(p, p->
current_domain, T_TXT, NULL)) != NULL)
00625   {
00626     
xprintf(
"DNS_query returned with answer: (%s)\n", rr_data);
00627 
00628     
SPF_parse_policy(p, rr_data);
00629 
00630     
xfree(rr_data);
00631   }
00632   
else if ((rr_data = 
DNS_query(p, p->
current_domain, T_CNAME, NULL)) != NULL)
00633   {
00634     
xvprintf(
"domain (%s) is CNAME of (%s). Restarting SPF_policy_main.",
00635       p->
current_domain, rr_data);
00636 
00637     
00638     p->
cname_buf = rr_data;
00639   } 
00640 
00641    
00642 
00643 
00644 
00645 
00646   
if (p->
cname_buf || p->
include_buf || p->
redirect_buf)
00647   {
00648     
if (p->
RES != 
SPF_PASS)
00649     {
00650       
xprintf(
"leaving function; returning (%i)\n", p->
RES);
00651 
00652       
return(p->
RES);
00653     }
00654   }
00655 
00656    
00657 
00658 
00659 
00660 
00661   
if ((p->
RES != 
SPF_PASS) && (p->
use_trust == 
SPF_TRUE))
00662   {
00663     
xvprintf(
"Error obtaining record, trying Trusted Fwdr (%s)\n",
00664       p->
trusted);
00665 
00666     res = 
SPF_parse_policy(p, p->
trusted);
00667 
00668     
xvprintf(
"SPF_parse_policy returned %i\n", res);
00669   }
00670 
00671   
if ((p->
RES != 
SPF_PASS) && (p->
include_buf || p->
redirect_buf))
00672   {
00673     
return(p->
RES);
00674   }
00675 
00676   
if ((p->
RES != 
SPF_PASS) && (p->
use_guess == 
SPF_TRUE))
00677   {
00678     
xvprintf(
"Attempting a best guess effort as a last resort "
00679       
"using: (%s)\n", p->
guess);
00680 
00681     res = 
SPF_parse_policy(p, p->
guess);
00682 
00683     
xvprintf(
"SPF_parse_policy returned %i\n", res);
00684   }
00685 
00686   
if ((p->
RES != 
SPF_PASS) && (p->
include_buf || p->
redirect_buf))
00687   {
00688     
return(p->
RES);
00689   }
00690 
00691   
xprintf(
"Return policy %i on mech: (%s) with outcome: (%s)\n",
00692     p->
RES, p->
last_m, p->
rs);
00693 
00694   
00695 
00696 
00697 
00698 
00699 
00700 
#ifdef _SPF_LOGFILE_STATS
00701 
    UTIL_log_result(p);
00702 
#endif 
00703 
00704   
return(p->
RES);
00705 }
00706 
00707 
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 SPF_BOOL SPF_parse_policy(
peer_info_t *p, 
const char *policy)
00722 {
00723   
SPF_MECHANISM POLICY_TYPE;    
00724 
00725   
SPF_RESULT PREFIX_TYPE;       
00726 
00727   
SPF_BOOL POLICY_MATCH;        
00728   
SPF_BOOL POLICY_ERROR;        
00729 
00730   int16_t pos;                  
00731   int16_t s_pos;                
00732 
00733   size_t p_len;                 
00734 
00735   
char *copy;                   
00736   
char *cp;                     
00737 
00738   
char *token;                  
00739   
char *token_ptr;              
00740 
00741   
char *tmp_ptr;                
00742   
char *tmp_ptr2;               
00743   
char *macro;                  
00744 
00745   
00746   
peer_info_t *i_p;             
00747 
00748   
policy_addr_t *policy_ip;     
00749 
00750 
00751   POLICY_MATCH    = 
SPF_FALSE;
00752   POLICY_ERROR    = 
SPF_FALSE;
00753   PREFIX_TYPE     = 
SPF_NEUTRAL;
00754 
00755   policy_ip       = NULL;
00756   i_p             = NULL;
00757   pos             = 0;
00758   token           = NULL;
00759   token_ptr       = NULL;
00760   macro           = NULL;
00761 
00762   
if ((policy == NULL) || (p == NULL))
00763   {
00764     
xepprintf(
"Unable to continue called with NULL structure\n");
00765 
00766     
return(
SPF_FALSE);
00767   }
00768 
00769   
if (p->
spf_rlevel >= 
SPF_MAX_RECURSE)
00770   {
00771     
xvprintf(
"recursion breach (%i levels); Terminated.\n",
00772       p->
spf_rlevel);
00773 
00774     snprintf(p->
error, 
SPF_MAX_ERROR, 
"Recursion loop, terminated.");
00775     
UTIL_assoc_prefix(p, 
SPF_UNKNOWN, NULL);
00776 
00777     
return(
SPF_FALSE);
00778   }
00779 
00780   p_len = strlen(policy);
00781 
00782   
xprintf(
"about to parse (%s) of len: %i (%s)\n",
00783     policy, p_len, p->
spf_result[p->
RES].s);
00784 
00785   
00786   cp = copy = 
xstrndup(policy, (p_len + 1));
00787 
00788   
00789   
while (*cp)
00790   {
00791     
00792     
while ((*cp == 
' ') && (*(cp + 1) == 
' '))
00793     {
00794       cp++;
00795     } 
00796     pos = 
UTIL_index(cp, 
' ');
00797 
00798     
if (!*(cp + 1))
00799     {
00800       
xfree(copy);
00801       
xpprintf(
"leaving function; nothing more to parse, returning SPF_TRUE\n");
00802 
00803       
return(
SPF_TRUE);
00804     }
00805 
00806     token     = 
xstrndup(cp, (pos + 1));
00807     token_ptr = token;
00808     s_pos     = 0;
00809 
00810     
00811     
if (
UTIL_is_spf_result(*token_ptr) ||
00812       (strncmp(token_ptr, 
"default", 7) == 0))
00813     {
00814       PREFIX_TYPE = 
UTIL_get_mech_prefix(p, token_ptr);
00815       snprintf(p->
last_m, 
SPF_MAX_MECHANISM, 
"%s", token_ptr);
00816 
00817       
if  (*token_ptr != 
'd')
00818       {
00819         
00820         token_ptr++;
00821       }
00822     }
00823     
else
00824     {
00825       snprintf(p->
last_m, 
SPF_MAX_MECHANISM, 
"%s", token_ptr);
00826       PREFIX_TYPE = 
SPF_PASS;
00827     }
00828 
00829     
00830     POLICY_TYPE = 
UTIL_get_policy_mech(token_ptr);
00831 
00832     
xprintf(
"SPF Policy Mechanism: %i (token: %s) (pos: %i)\n",
00833       POLICY_TYPE, token_ptr, pos);
00834 
00835     
switch (POLICY_TYPE)
00836     {
00837 
00838        
00839 
00840 
00841       
case NO_POLICY:
00842         
break;
00843 
00844        
00845 
00846 
00847       
case UNMECH:
00848         
UTIL_assoc_prefix(p, 
SPF_UNMECH, NULL);
00849 
00850         
xvprintf(
"Unrecognized mechanism (%s); returning SPF_FALSE\n", token);
00851 
00852         
xfree(token);
00853         
xfree(copy);
00854 
00855         
return(
SPF_FALSE);
00856 
00857        
00858 
00859 
00860       
case VERSION:
00861         
xprintf(
"policy mechanism is version (%s)\n", token_ptr);
00862 
00863         
if ((s_pos = 
UTIL_index(token_ptr, 
'=')) > 0)
00864         {
00865           token_ptr += s_pos + 4; 
00866 
00867           
if (atoi(token_ptr) > 
SPF_VERSION)
00868           {
00869             
UTIL_assoc_prefix(p, 
SPF_NONE, NULL);
00870 
00871             
xfree(token);
00872             
xfree(copy);
00873 
00874             
return(
SPF_FALSE);
00875           }
00876 
00877           p->
spf_ver = atoi(token_ptr);
00878 
00879           
xvprintf(
"SPF Version defined as: %u\n", p->
spf_ver);
00880         }
00881         
else
00882         {
00883            
xvprintf(
"SPF version redefined! (%u)\n", p->
spf_ver);
00884            
UTIL_assoc_prefix(p, 
SPF_S_FAIL, NULL);
00885 
00886            
xfree(token);
00887            
xfree(copy);
00888 
00889            
return(
SPF_FALSE);
00890         }
00891 
00892         
break;
00893 
00894        
00895 
00896 
00897       
case ALL:
00898         
xprintf(
"policy mechanism is all (%s) policy: (%i)\n",
00899           token_ptr, POLICY_TYPE);
00900 
00901         
UTIL_assoc_prefix(p, PREFIX_TYPE, NULL);
00902         POLICY_MATCH = 
SPF_TRUE;
00903         p->
ALL       = 
SPF_TRUE;
00904 
00905         
break;
00906 
00907        
00908 
00909 
00910       
case DEFAULT:
00911         
xprintf(
"policy mechanism is default (%s) policy: (%i)\n",
00912           token_ptr, POLICY_TYPE);
00913 
00914         POLICY_MATCH = 
SPF_TRUE;
00915         p->
ALL       = 
SPF_TRUE;
00916 
00917         
break;
00918 
00919        
00920 
00921 
00922       
case INCLUDE:
00923         
xprintf(
"policy mechanism is include (%s)\n", token_ptr);
00924 
00925         
if ((tmp_ptr = strstr(token_ptr, 
":")) != NULL)
00926         {
00927           tmp_ptr++;
00928 
00929           
if (
UTIL_is_macro(tmp_ptr) == 
SPF_TRUE)
00930           {
00931             
xvprintf(
"this INCLUDE mechanism contained macros (%s)\n", tmp_ptr);
00932 
00933             
if (p->
include_buf == NULL)
00934             {
00935               
if ((macro = 
MACRO_expand(p, tmp_ptr)) != NULL)
00936               {
00937                 p->
include_buf = 
xstrndup(macro, 
SPF_MAX_STR);
00938 
00939                 
xfree(macro);
00940               }
00941             }
00942             
else
00943             {
00944               
xvprintf(
"Got include=%s, but include already set. Ignoring.\n",
00945                 tmp_ptr);
00946             }
00947           }
00948           
else
00949           {
00950             
xvprintf(
"storing INCLUDE (%s) for later...\n", tmp_ptr);
00951 
00952             
if (p->
include_buf == NULL)
00953             {
00954               p->
include_buf = 
xstrndup(tmp_ptr, 
SPF_MAX_STR);
00955             }
00956             
else
00957             {
00958               
xvprintf(
"Got include=%s, but include already set. Ignoring.\n",
00959                 tmp_ptr);
00960             }
00961           }
00962         }
00963         
else
00964         {
00965           
00966           POLICY_MATCH = 
SPF_TRUE;
00967           
UTIL_assoc_prefix(p, 
SPF_UNKNOWN, token_ptr);
00968 
00969           
xfree(token);
00970           
xfree(copy);
00971 
00972           
return(
SPF_TRUE);
00973         }
00974         
break;
00975 
00976        
00977 
00978 
00979       
case A:
00980         
xprintf(
"policy mechanism is A (%s)\n", token_ptr);
00981 
00982         
if ((tmp_ptr = strstr(token_ptr, 
"/")) != NULL)
00983         {
00984           tmp_ptr++;
00985           POLICY_MATCH = 
UTIL_a_cmp(p, token_ptr, atoi(tmp_ptr));
00986         }
00987         
else
00988         {
00989           POLICY_MATCH = 
UTIL_a_cmp(p, token_ptr, 32);
00990         }
00991 
00992         
00993         
if ((PREFIX_TYPE == 
SPF_H_FAIL) && (POLICY_MATCH == 
SPF_TRUE))
00994         {
00995           
xpprintf(
"Found a match on a negative prefix.  Halting parse.\n");
00996           
UTIL_assoc_prefix(p, 
SPF_H_FAIL, token_ptr);
00997 
00998           
xfree(token);
00999           
xfree(copy);
01000 
01001           
return(
SPF_FALSE);
01002         }
01003 
01004         
break;
01005 
01006        
01007 
01008 
01009       
case MX:
01010         
xprintf(
"policy mechanism is mx (%s)\n", token_ptr);
01011 
01012         
01013         
01014         
if ((tmp_ptr = strstr(token_ptr, 
":")) != NULL)
01015         {
01016           tmp_ptr++;
01017           tmp_ptr2 = tmp_ptr;
01018         }
01019         
else
01020         {
01021           tmp_ptr2 = p->
current_domain;
01022         }
01023 
01024         
if ((tmp_ptr = strstr(token_ptr, 
"/")) != NULL)
01025         {
01026           tmp_ptr++;
01027           POLICY_MATCH = 
UTIL_mx_cmp(p, tmp_ptr2, atoi(tmp_ptr));
01028         }
01029         
else
01030         {
01031           POLICY_MATCH = 
UTIL_mx_cmp(p, tmp_ptr2, 32);
01032         }
01033 
01034         
01035         
if ((PREFIX_TYPE == 
SPF_H_FAIL) && (POLICY_MATCH == 
SPF_TRUE))
01036         {
01037           
xpprintf(
"Found a match on a negative prefix.  Halting parse.\n");
01038 
01039           
UTIL_assoc_prefix(p, 
SPF_H_FAIL, token_ptr);
01040 
01041           
xfree(token);
01042           
xfree(copy);
01043 
01044           
return(
SPF_FALSE);
01045         }
01046 
01047         
break;
01048  
01049        
01050 
01051 
01052       
case PTR:
01053         
xprintf(
"policy mechanism is ptr (%s)\n", token_ptr);
01054 
01055         POLICY_MATCH = 
UTIL_ptr_cmp(p, token_ptr);
01056 
01057         
01058         
if ((PREFIX_TYPE == 
SPF_H_FAIL) && (POLICY_MATCH == 
SPF_TRUE))
01059         {
01060           
xpprintf(
"Found a match on a negative prefix.  Halting parse.\n");
01061 
01062           
break;
01063         }
01064 
01065         
break;
01066 
01067 
01068        
01069 
01070 
01071       
case IP4:
01072         
xprintf(
"policy mechanism is ip4 (%s)\n", token_ptr);
01073 
01074         
if ((policy_ip = 
UTIL_expand_ip(token_ptr)) == NULL)
01075         {
01076           
xpprintf(
"ERROR: inet_pton unable to convert ip to binary\n");
01077 
01078           
break;
01079         }
01080 
01081         
xvprintf(
"POL: %lu (%s) PEER: %lu (%s)\n",
01082           policy_ip->
addr.s_addr, token_ptr, p->
addr.s_addr, p->
r_ip);
01083 
01084         POLICY_MATCH = 
UTIL_cidr_cmp(policy_ip, &p->
addr);
01085         
xfree(policy_ip);
01086 
01087         
01088         
if ((PREFIX_TYPE == 
SPF_H_FAIL) && (POLICY_MATCH == 
SPF_TRUE))
01089         {
01090           
xpprintf(
"Found a match on a negative prefix.  Halting parse.\n");
01091           
UTIL_assoc_prefix(p, 
SPF_H_FAIL, token_ptr);
01092 
01093           
xfree(token);
01094           
xfree(copy);
01095 
01096           
return(
SPF_FALSE);
01097         }
01098 
01099         
break;
01100 
01101        
01102 
01103 
01104       
case IP6:
01105         
xprintf(
"policy mechanism is ip6 (%s)\n", token_ptr);
01106 
01107         
break;
01108 
01109        
01110 
01111 
01112       
case EXISTS:
01113         
xprintf(
"policy mechanism is exists (%s)\n", token_ptr);
01114 
01115         
if ((tmp_ptr = strstr(token_ptr, 
":")) != NULL)
01116         {
01117           tmp_ptr++;
01118 
01119           
if ((macro = 
MACRO_expand(p, tmp_ptr)) == NULL)
01120           {
01121             
xvprintf(
"Unable to expand macro (%s). Aborting.\n", tmp_ptr);
01122 
01123             
break;
01124           }
01125 
01126           
if (
DNS_query(p, macro, T_A, NULL) == (
char *)
SPF_TRUE)
01127           {
01128             POLICY_MATCH = 
SPF_TRUE;
01129           }
01130 
01131           
xfree(macro);
01132         }
01133         
break;
01134 
01135        
01136 
01137 
01138       
case REDIRECT:
01139         
xprintf(
"modifier is redirect (%s)\n", token_ptr);
01140 
01141         
if ((tmp_ptr = strstr(token_ptr, 
"=")) != NULL)
01142         {
01143           tmp_ptr++;
01144 
01145           
if (
UTIL_is_macro(tmp_ptr) == 
SPF_TRUE)
01146           {
01147             
if (p->
redirect_buf == NULL)
01148             {
01149               
if ((macro = 
MACRO_expand(p, tmp_ptr)) != NULL)
01150               {
01151                 p->
redirect_buf = 
xstrndup(macro, 
SPF_MAX_STR);
01152                 
xfree(macro);
01153               }
01154             }
01155             
else
01156             {
01157               
xvprintf(
"Got redir=%s, but redirect already set. Ignoring.\n",
01158                 tmp_ptr);
01159             }
01160           }
01161           
else
01162           {
01163             
if (p->
redirect_buf == NULL)
01164             {
01165               
xvprintf(
"setting redirect_buf to %s\n", tmp_ptr);
01166               p->
redirect_buf = 
xstrndup(tmp_ptr, 
SPF_MAX_STR);
01167             }
01168             
else
01169             {
01170               
xvprintf(
"Got redir=%s, but redirect already set. Ignoring.\n",
01171                 tmp_ptr);
01172             }
01173           }
01174         }
01175         
break;
01176 
01177        
01178 
01179 
01180       
case EXPLAIN:
01181         
xprintf(
"policy mechanism is explain (%s)\n", token_ptr);
01182 
01183         
if ((tmp_ptr = strstr(token_ptr, 
"=")) != NULL)
01184         {
01185           tmp_ptr++;
01186 
01187           
if ((macro = 
MACRO_expand(p, tmp_ptr)) == NULL)
01188           {
01189             
xvprintf(
"Unable to expand macro (%s). Aborting.\n", tmp_ptr);
01190 
01191             
break;
01192           }
01193 
01194           p->
explain = 
xstrndup(macro, (strlen(macro) + 1));
01195           
xfree(macro);
01196         }
01197         
else
01198         {
01199           
xpprintf(
"EXPLAIN modifier must be accompanied " \
01200             
"by arguments and I found none.");
01201 
01202           
01203           POLICY_MATCH = 
SPF_TRUE;
01204           
UTIL_assoc_prefix(p, 
SPF_UNKNOWN, token_ptr);
01205 
01206           
xfree(token);
01207           
xfree(copy);
01208 
01209           
return(
SPF_TRUE);
01210         }
01211 
01212         
break;
01213     } 
01214 
01215     
xfree(token);
01216     cp += pos + 1;  
01217 
01218     
if ((POLICY_MATCH == 
SPF_TRUE) && (p->
spf_ver > 0))
01219     {
01220       
01221       
UTIL_assoc_prefix(p, PREFIX_TYPE, p->
last_m);
01222       p->
RES_P = p->
RES;
01223 
01224       
xpprintf(
"returning SPF_TRUE\n");
01225       
xfree(copy);
01226 
01227       
return(
SPF_TRUE);
01228     }
01229   } 
01230 
01231   
xfree(copy);
01232 
01233   
return(
SPF_FALSE);
01234 }
01235 
01236 
01237 
01238 
01239 
01240 
01241 
01242 
01243 
01244 
01245 
01246 
01247 
01248 
01249 char *
SPF_result(
peer_info_t *p)
01250 {
01251   
char  *buf;    
01252 
01253 
01254   buf = 
xmalloc(
SPF_MAX_HEADER);
01255 
01256   
switch (p->
RES)
01257   {
01258     
case SPF_PASS:
01259       snprintf(buf, 
SPF_MAX_SMTP_RES, 
RES_PASS, p->
from, p->
r_ip);
01260       
break;
01261 
01262     
case SPF_NONE:
01263       snprintf(buf, 
SPF_MAX_SMTP_RES, 
RES_NONE, p->
from);
01264       
break;
01265 
01266     
case SPF_S_FAIL:
01267       snprintf(buf, 
SPF_MAX_SMTP_RES, 
RES_S_FAIL, p->
from, p->
r_ip);
01268       
break;
01269 
01270     
case SPF_H_FAIL:
01271       snprintf(buf, 
SPF_MAX_SMTP_RES, 
RES_H_FAIL, p->
from, p->
r_ip);
01272       
break;
01273 
01274     
case SPF_ERROR:
01275       snprintf(buf, 
SPF_MAX_SMTP_RES, 
RES_ERROR, p->
from);
01276       
break;
01277 
01278     
case SPF_NEUTRAL:
01279       snprintf(buf, 
SPF_MAX_SMTP_RES, 
RES_NEUTRAL, p->
r_ip, p->
from);
01280       
break;
01281 
01282     
case SPF_UNKNOWN:
01283       snprintf(buf, 
SPF_MAX_SMTP_RES, 
RES_UNKNOWN, p->
from);
01284       
break;
01285 
01286     
case SPF_UNMECH:
01287       snprintf(buf, 
SPF_MAX_SMTP_RES, 
RES_UNMECH, p->
from);
01288       
break;
01289   }
01290 
01291   
xprintf(
"response: (%s)\n", buf);
01292 
01293   
return(buf);
01294 }
01295 
01296 
01297 
01298 
01299 
01300 
01301 
01302 
01303 
01304 
01305 
01306 
01307 
01308 
01309 
01310 char *
SPF_get_explain(
peer_info_t *p)
01311 {
01312   
char *buf = NULL;    
01313 
01314 
01315   
if (p->
explain != NULL)
01316   {
01317     
if ((buf = 
MACRO_expand(p, 
SPF_EXPLAIN)) != NULL)
01318     {
01319       
xprintf(
"Prepending explain: (%s)\n", buf);
01320 
01321       
return(buf);
01322     }
01323   }
01324 
01325   
return(NULL);
01326 }
01327 
01328 
01329 
01330 
01331 
01332 
01333 
01334 
01335 
01336 
01337 
01338 
01339 
01340 
01341 
01342 char *
SPF_build_header(
peer_info_t *p)
01343 {
01344   
char  *buf;    
01345 
01346   buf = 
xmalloc(
SPF_MAX_HEADER);
01347 
01348   
switch (p->
RES)
01349   {
01350     
01351     
case SPF_PASS:
01352       snprintf(buf, 
SPF_MAX_HEADER, p->
spf_result[
SPF_PASS].h,
01353         p->
mta_hname, p->
from, p->
r_ip, p->
mta_hname,
01354         p->
r_ip, p->
from);
01355       
break;
01356 
01357     
01358     
case SPF_NONE:
01359       snprintf(buf, 
SPF_MAX_HEADER, p->
spf_result[
SPF_NONE].h,
01360         p->
mta_hname, p->
from);
01361       
break;
01362 
01363     
01364     
case SPF_S_FAIL:
01365       snprintf(buf, 
SPF_MAX_HEADER, p->
spf_result[
SPF_S_FAIL].h,
01366         p->
mta_hname, p->
from, p->
r_ip, p->
mta_hname,
01367         p->
r_ip, p->
from);
01368       
break;
01369 
01370     
01371     
case SPF_H_FAIL:
01372       snprintf(buf, 
SPF_MAX_HEADER, p->
spf_result[
SPF_H_FAIL].h,
01373         p->
mta_hname, p->
from, p->
r_ip, p->
mta_hname,
01374         p->
r_ip, p->
from);
01375       
break;
01376 
01377     
01378     
case SPF_ERROR:
01379       snprintf(buf, 
SPF_MAX_HEADER, p->
spf_result[
SPF_ERROR].h,
01380         p->
mta_hname, p->
from, p->
error);
01381       
break;
01382 
01383     
01384     
case SPF_NEUTRAL:
01385       snprintf(buf, 
SPF_MAX_HEADER, p->
spf_result[
SPF_NEUTRAL].h,
01386         p->
mta_hname, p->
from, p->
r_ip);
01387       
break;
01388 
01389     
01390     
case SPF_UNKNOWN:
01391       snprintf(buf, 
SPF_MAX_HEADER, p->
spf_result[
SPF_UNKNOWN].h,
01392         p->
mta_hname, p->
from, p->
current_domain, p->
last_m);
01393       
break;
01394 
01395     
01396     
case SPF_UNMECH:
01397       snprintf(buf, 
SPF_MAX_HEADER, p->
spf_result[
SPF_UNMECH].h,
01398         p->
last_m, p->
mta_hname, p->
from);
01399       
break;
01400   }
01401 
01402   
xvprintf(
"Prepending header string: (%s)\n", buf);
01403 
01404   
return(buf);
01405 }
01406 
01407 
01408 
01409 
01410 
01411 
01412 
01413 
01414 
01415 
01416 
01417 
01418 
01419 
01420 
01421 
01422 
01423 SPF_BOOL SPF_smtp_helo(
peer_info_t *p, 
const char *s)
01424 {
01425 
01426   
xprintf(
"called with (%s)\n", s);
01427 
01428   
if (p->
helo)
01429   {
01430     
xfree(p->
helo);
01431   }
01432 
01433   p->
helo = 
xstrdup(s);
01434   p->
ehlo = p->
helo;
01435 
01436   
return (strlen(p->
helo) > 0);
01437 }
01438 
01439 
01440 
01441 
01442 
01443 
01444 
01445 
01446 
01447 
01448 
01449 
01450 
01451 
01452 
01453 
01454 
01455 
01456 SPF_BOOL SPF_smtp_from(
peer_info_t *p, 
const char *s)
01457 {
01458   
int len;      
01459 
01460   
char *pos;    
01461 
01462 
01463   
xfree(p->
from);
01464   
xfree(p->
current_domain);
01465 
01466   
if (s == NULL)
01467   {
01468     
if (*(p->
helo) == 
'\0')
01469     {
01470       p->
from = 
xstrndup(
"unknown", 7);
01471     } 
01472     
else
01473     {
01474       p->
from = 
xstrndup(p->
helo, 
SPF_MAX_ENV_HELO);
01475     }
01476 
01477     
xvprintf(
"NULL or invalid MAIL FROM rcvd.  Using %s from now on.\n",
01478       p->
from ? p->
from : p->
helo);
01479 
01480     
return(
SPF_FALSE);
01481   }
01482 
01483   p->
from = 
xstrndup(s, 
SPF_MAX_STR);
01484 
01485   
01486   
if (*p->
from == 60)
01487   {
01488     pos = p->
from;
01489     (*(p->
from + strlen(p->
from) - 1)) = 
'\0';
01490     p->
from++;
01491     p->
from = 
xstrndup(p->
from, 
SPF_MAX_STR);
01492 
01493     
xfree(pos);
01494   }
01495 
01496   
if (*p->
from == 
'\0')
01497   {
01498     
if (*(p->
helo) == 
'\0')
01499     {
01500       p->
from = 
xstrndup(
"unknown", 7);
01501     }
01502     
else
01503     {
01504       p->
from = 
xstrndup(p->
helo, 
SPF_MAX_ENV_HELO);
01505     }
01506   }
01507 
01508   pos = p->
from;
01509 
01510   
xprintf(
"MAIL-FROM: (%s) (called with: %s)\n", p->
from, s);
01511 
01512   
if ((pos = strstr(pos, 
"@")) != NULL)
01513   {
01514     len = (pos - p->
from);
01515 
01516     
if (len >= 
SPF_MAX_LOCAL_PART)
01517     {
01518       
xvprintf(
"%i is >= %i causing data overrun\n", len, 
SPF_MAX_LOCAL_PART);
01519     }
01520 
01521     
01522     memcpy(p->
local_part, p->
from, len);
01523     p->
local_part[len] = 
'\0';
01524 
01525     pos++;    
01526     p->
current_domain = 
xstrndup(pos, 
SPF_MAX_STR);
01527 
01528     
xprintf(
"Current domain: (%s)\n", p->
current_domain);
01529 
01530   }
01531   
else
01532   {
01533     snprintf(p->
local_part, 11, 
"postmaster");
01534     p->
current_domain = 
xstrndup(p->
from, 
SPF_MAX_STR);
01535   }
01536 
01537   
xvprintf(
"local-part: (%s); domain: (%s); sender: (%s)\n",
01538     p->
local_part, p->
current_domain, p->
from);
01539 
01540   
return(
SPF_TRUE);
01541 }
01542 
01543 
01544 
01545 
01546 
01547 
01548 
01549 
01550 
01551 
01552 
01553 
01554 
01555 
01556 
01557 
01558 
01559 
01560 
01561 
01562 
01563 
01564 static SPF_BOOL _SPF_clear_holdbufs(
peer_info_t *p)
01565 {
01566   
if (p == NULL)
01567   {
01568     
xepprintf(
"peer_info_t structure was NULL!  Aborting!\n");
01569 
01570     
return(
SPF_FALSE);
01571   }
01572   
01573   
if (p->
cname_buf != NULL)
01574   { 
01575     
xfree(p->
cname_buf);
01576     p->
cname_buf = NULL;
01577   }
01578   
01579   
if (p->
include_buf != NULL)
01580   {
01581     
xfree(p->
include_buf);
01582     p->
include_buf = NULL;
01583   }
01584   
01585   
if (p->
redirect_buf)
01586   {
01587     
xfree(p->
redirect_buf);
01588     p->
redirect_buf = NULL;
01589   }
01590   
01591   
return(
SPF_TRUE);
01592 }
01593 
01594