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