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
#include "main.h"
00046
#include "util.h"
00047
#include "dns.h"
00048
#include "macro.h"
00049
#include "error.h"
00050
00051 spf_config_t confg;
00052 u_int8_t
spf_rlevel;
00053 int h_errno;
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 peer_info_t *
SPF_init(
const char *local,
const char *rip,
const char *expl,
00070
const char *tf,
const char *guess, u_int32_t use_trust, u_int32_t use_guess)
00071 {
00072 time_t curtime;
00073
char *cur_utc_time;
00074
00075
peer_info_t *peer_info;
00076
00077
00078
static spf_result_t spf_result[] =
00079 {
00080 {
sizeof(
HR_PASS),
HR_PASS,
SPF_PASS,
sizeof(
HDR_PASS),
HDR_PASS,
'+' },
00081 {
sizeof(
HR_NONE),
HR_NONE,
SPF_NONE,
sizeof(
HDR_NONE),
HDR_NONE,
'\0' },
00082 {
sizeof(
HR_S_FAIL),
HR_S_FAIL,
SPF_S_FAIL,
sizeof(
HDR_S_FAIL),
HDR_S_FAIL,
'~' },
00083 {
sizeof(
HR_H_FAIL),
HR_H_FAIL,
SPF_H_FAIL,
sizeof(
HDR_H_FAIL),
HDR_H_FAIL,
'-' },
00084 {
sizeof(
HR_ERROR),
HR_ERROR,
SPF_ERROR,
sizeof(
HDR_ERROR),
HDR_ERROR,
'\0' },
00085 {
sizeof(
HR_NEUTRAL),
HR_NEUTRAL,
SPF_NEUTRAL,
sizeof(
HDR_NEUTRAL),
HDR_NEUTRAL,
'?' },
00086 {
sizeof(
HR_UNKNOWN),
HR_UNKNOWN,
SPF_UNKNOWN,
sizeof(
HDR_UNKNOWN),
HDR_UNKNOWN,
'\0' },
00087 {
sizeof(
HR_UNMECH),
HR_UNMECH,
SPF_UNMECH,
sizeof(
HDR_UNMECH),
HDR_UNMECH,
'\0' }
00088 };
00089
00090
xvprintf(
"Called with: (%s) (%s) (%s) (%s) (%s) %u:%u\n",
00091 local, rip, expl, tf, guess, use_trust, use_guess);
00092
00093
00094 peer_info =
xmalloc(
sizeof(
peer_info_t));
00095
00096
if (use_trust ==
TRUE)
00097 {
00098 peer_info->
use_trust =
TRUE;
00099 }
00100
else
00101 {
00102 peer_info->
use_trust =
FALSE;
00103 }
00104
00105
if (use_guess ==
TRUE)
00106 {
00107 peer_info->
use_guess =
TRUE;
00108 }
00109
else
00110 {
00111 peer_info->
use_guess =
FALSE;
00112 }
00113
00114 peer_info->
spf_result = spf_result;
00115
00116 peer_info->
ALL =
FALSE;
00117 peer_info->
p = NULL;
00118
00119 peer_info->
spf_ver = 0;
00120
00121 peer_info->
helo = NULL;
00122 peer_info->
ehlo = NULL;
00123 peer_info->
from = NULL;
00124
00125
if (expl != NULL && (*expl && *(expl + 1)))
00126 {
00127 peer_info->
explain =
xstrndup(expl, (strlen(expl) + 1));
00128 }
00129
else
00130 {
00131 peer_info->
explain = NULL;
00132 }
00133
00134
if (guess != NULL && (*guess && *(guess + 1)))
00135 {
00136 peer_info->
guess =
xstrndup(guess, (strlen(guess) + 1));
00137 }
00138
else
00139 {
00140 peer_info->
guess =
xstrndup(
SPF_GUESS, (
sizeof(
SPF_GUESS) + 1));
00141 }
00142
00143
if (tf != NULL && (*tf && *(tf + 1)))
00144 {
00145 peer_info->
trusted =
xstrndup(tf, (strlen(tf) + 1));
00146 }
00147
else
00148 {
00149 peer_info->
trusted =
xstrndup(
SPF_TRUSTED, (
sizeof(
SPF_TRUSTED) + 1));
00150 }
00151
00152 peer_info->
ptr_mhost = NULL;
00153 peer_info->
cur_dom = NULL;
00154 peer_info->
cur_eaddr = NULL;
00155 peer_info->
mta_hname =
xstrndup(local, (strlen(local) + 1));
00156
00157
00158
if (inet_pton(AF_INET, rip, &peer_info->
addr) <= 0)
00159 {
00160
xeprintf(
"Unable to execute inet_print\n");
00161 }
00162
00163 peer_info->
r_ip =
xstrndup(rip, (strlen(rip) + 1));
00164 peer_info->
r_vhname =
xstrndup(local, (strlen(local) + 1));
00165
00166 sprintf(peer_info->
ip_ver,
"in-addr");
00167
00168 memset(peer_info->
local_part,
'\0',
LOCAL_PART);
00169
00170 cur_utc_time =
xmalloc(22);
00171 snprintf(cur_utc_time, 22,
"%lu", time(&curtime));
00172 memcpy(peer_info->
utc_time, cur_utc_time, 22);
00173
xfree(cur_utc_time);
00174
00175 memset(peer_info->
last_m,
'\0',
MAX_MECHANISM);
00176 memset(peer_info->
error,
'\0',
MAX_ERROR);
00177
00178
00179
if ((strcmp(rip,
"127.0.0.1") == 0) || (strcmp(rip,
"localhost") == 0))
00180 {
00181
UTIL_assoc_prefix(peer_info,
SPF_PASS, NULL);
00182 }
00183
else
00184 {
00185
UTIL_assoc_prefix(peer_info,
SPF_NEUTRAL, NULL);
00186 }
00187
00188
xprintf(
"libspf initialized succesfully. (%i bytes allocated)\n",
00189
sizeof(
peer_info_t));
00190
00191
return(peer_info);
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 peer_info_t *
SPF_close(
peer_info_t *peer_info)
00208 {
00209
if (peer_info == NULL)
00210 {
00211
xeprintf(
"peer structure null. Aborting!\n");
00212
return(NULL);
00213 }
00214
00215
xfree(peer_info->
mta_hname);
00216
xfree(peer_info->
helo);
00217
xfree(peer_info->
from);
00218
xfree(peer_info->
cur_dom);
00219
xfree(peer_info->
r_ip);
00220
xfree(peer_info->
ptr_mhost);
00221
xfree(peer_info->
cur_eaddr);
00222
xfree(peer_info->
trusted);
00223
xfree(peer_info->
guess);
00224
xfree(peer_info->
explain);
00225
xfree(peer_info->
r_vhname);
00226
00227
xfree(peer_info);
00228 peer_info = NULL;
00229
00230
return(peer_info);
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 SPF_RESULT SPF_policy_main(
peer_info_t *peer_info)
00248 {
00249
return SPF_policy_main_rec(peer_info, 0);
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 SPF_RESULT SPF_policy_main_rec(
peer_info_t *peer_info,
int rec)
00269 {
00270
char *rr_data = NULL;
00271
char *domain = NULL;
00272
SPF_RESULT result;
00273
00274
00275
if (peer_info->
RES ==
SPF_PASS)
00276 {
00277
return(
SPF_PASS);
00278 }
00279
00280
if (
spf_rlevel >=
SPF_RECURSE)
00281 {
00282 snprintf(peer_info->
error,
MAX_ERROR,
"INCLUDE loop, terminated.");
00283
UTIL_assoc_prefix(peer_info,
SPF_UNKNOWN, NULL);
00284
return(
SPF_UNKNOWN);
00285 }
00286
00287
if (peer_info == NULL)
00288 {
00289
xeprintf(
"Error peer structure is NULL. Aborting\n");
00290 }
00291
else if (peer_info->
addr.s_addr <= 0)
00292 {
00293
xvprintf(
"(QID: %u) :: Error no idea who the remote peer is. Abort!\n",
00294
spf_rlevel);
00295
UTIL_assoc_prefix(peer_info,
SPF_ERROR, NULL);
00296
return(
SPF_ERROR);
00297 }
00298
00299
00300
if ((rr_data =
DNS_query(peer_info, peer_info->
cur_dom, T_CNAME, NULL)) != NULL)
00301 {
00302
if (
MAX_CNAME > rec)
00303 {
00304
xvprintf(
"Domain (%s) is CNAME of (%s). Restarting SPF_policy_main.",
00305 peer_info->
cur_dom, rr_data);
00306 domain = peer_info->
cur_dom;
00307 peer_info->
cur_dom = rr_data;
00308 result =
SPF_policy_main_rec(peer_info, rec + 1);
00309
xfree(peer_info->
cur_dom);
00310 peer_info->
cur_dom = domain;
00311
return result;
00312 }
00313
else
00314 {
00315
xvprintf(
"(QID: %u) :: Error: Maximum of recursion reached. Abort!\n",
spf_rlevel);
00316
UTIL_assoc_prefix(peer_info,
SPF_ERROR, NULL);
00317
xfree(rr_data);
00318
return(
SPF_ERROR);
00319 }
00320 }
00321
if ((rr_data =
DNS_query(peer_info, peer_info->
cur_dom, T_TXT, NULL)) != NULL)
00322 {
00323
xprintf(
"(QID: %u) :: Error parsing ANSWER(s)\n",
spf_rlevel);
00324
00325
UTIL_assoc_prefix(peer_info,
SPF_NONE, NULL);
00326
SPF_parse_policy(peer_info, rr_data);
00327
xfree(rr_data);
00328 }
00329
else if (peer_info->
RES ==
SPF_NONE && peer_info->
use_trust ==
TRUE)
00330 {
00331
xvprintf(
"(QID: %u) :: Error obtaining record, trying trusted forwarder (%s)\n",
00332
spf_rlevel, peer_info->
trusted);
00333
00334
SPF_parse_policy(peer_info, peer_info->
trusted);
00335 }
00336
00337
if (peer_info->
RES !=
SPF_PASS && peer_info->
use_guess ==
TRUE)
00338 {
00339
xvprintf(
"(QID: %u) :: Attempting a best guess effort as a last resort "
00340
"using: (%s)\n",
spf_rlevel, peer_info->
guess);
00341
00342
SPF_parse_policy(peer_info, peer_info->
guess);
00343 }
00344
00345
if (peer_info->
RES !=
SPF_PASS && peer_info->
explain == NULL)
00346 {
00347
if ((peer_info->
explain =
MACRO_expand(peer_info,
SPF_EXPLAIN)) == NULL)
00348 {
00349
xeprintf(
"Unable to obtain explanation\n");
00350 }
00351 }
00352
00353
xprintf(
"(QID: %u) :: Return policy %i on mech: (%s) with outcome: (%s)\n",
00354
spf_rlevel, peer_info->
RES, peer_info->
last_m, peer_info->
rs);
00355
00356
UTIL_log_result(peer_info);
00357
00358
return(peer_info->
RES);
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 SPF_BOOL SPF_parse_policy(
peer_info_t *peer_info,
const char *policy)
00376 {
00377
SPF_MECHANISM POLICY_TYPE;
00378
SPF_RESULT PREFIX_TYPE;
00379
SPF_BOOL POLICY_MATCH;
00380
SPF_BOOL POLICY_ERROR;
00381
00382
00383
policy_addr_t *policy_ip;
00384
00385
00386
peer_info_t *i_peer_info;
00387
00388 size_t p_len;
00389 int16_t pos;
00390 int16_t s_pos;
00391 int16_t i;
00392
00393
char *copy;
00394
char *cp;
00395
00396
char *token;
00397
char *token_ptr;
00398
00399
char *tmp_ptr;
00400
char *tmp_ptr2;
00401
char *macro;
00402
00403 u_int8_t ver_c;
00404
00405 POLICY_MATCH =
FALSE;
00406 POLICY_ERROR =
FALSE;
00407 PREFIX_TYPE =
SPF_NEUTRAL;
00408
00409 policy_ip = NULL;
00410 i_peer_info = NULL;
00411 macro = NULL;
00412
00413
if ((policy == NULL) || (peer_info == NULL))
00414 {
00415
xeprintf(
"Unable to continue called with NULL structure\n");
00416
return(
SPF_ERROR);
00417 }
00418
00419 p_len = strlen(policy);
00420
00421
xprintf(
"(QID: %u) :: about to parse (%s) of len: %i (%s)\n",
00422
spf_rlevel, policy, p_len, peer_info->
spf_result[peer_info->
RES].s);
00423
00424
00425 cp = copy =
xstrndup(policy, (p_len + 1));
00426
00427 i = strlen(cp);
00428
00429
00430
while (*cp)
00431 {
00432
while (*(cp + 1) && (pos =
UTIL_index(cp,
' ')) == 0)
00433 {
00434 cp++;
00435 }
00436
00437
if (!*(cp + 1))
00438 {
00439
xfree(copy);
00440
00441
00442
if (peer_info->
spf_ver ==
SPF_VERSION)
00443 {
00444
UTIL_assoc_prefix(peer_info,
SPF_NEUTRAL, NULL);
00445
return(
TRUE);
00446 }
00447
00448
return(
FALSE);
00449 }
00450
00451 token =
xstrndup(cp, (pos + 1));
00452 token_ptr = token;
00453 s_pos = 0;
00454
00455
00456
if (
UTIL_is_spf_result(*token_ptr) ||
00457 (strncmp(token_ptr,
"default", 7) == 0))
00458 {
00459 PREFIX_TYPE =
UTIL_get_mech_prefix(peer_info, token_ptr);
00460 snprintf(peer_info->
last_m,
MAX_MECHANISM,
"%s", token_ptr);
00461
00462
if (*token_ptr !=
'd')
00463 {
00464
00465 token_ptr++;
00466 }
00467 }
00468
else
00469 {
00470 snprintf(peer_info->
last_m,
MAX_MECHANISM,
"%s", token_ptr);
00471 PREFIX_TYPE =
SPF_PASS;
00472 }
00473
00474
00475 POLICY_TYPE =
UTIL_get_policy_mech(token_ptr);
00476
00477
xprintf(
"(QID: %u) :: SPF Policy Mechanism: %i (token: %s) (pos: %i)\n",
00478
spf_rlevel, POLICY_TYPE, token_ptr, pos);
00479
00480
switch (POLICY_TYPE)
00481 {
00482
case NO_POLICY:
00483
break;
00484
case UNMECH:
00485
UTIL_assoc_prefix(peer_info,
SPF_UNMECH, NULL);
00486
xfree(token);
00487
xfree(copy);
00488
return(
FALSE);
00489
case VERSION:
00490
xprintf(
"(QID: %u) :: policy mechanism is version (%s)\n",
00491
spf_rlevel, token_ptr);
00492
00493
if ((s_pos =
UTIL_index(token_ptr,
'=')) > 0)
00494 {
00495 token_ptr += s_pos + 4;
00496
00497
if (atoi(token_ptr) >
SPF_VERSION)
00498 {
00499
UTIL_assoc_prefix(peer_info,
SPF_NONE, NULL);
00500
xfree(token);
00501
xfree(copy);
00502
return(
FALSE);
00503 }
00504
00505 peer_info->
spf_ver = atoi(token_ptr);
00506
00507
xvprintf(
"(QID: %u) :: SPF Version defined as: %u\n",
00508
spf_rlevel, peer_info->
spf_ver);
00509
00510 }
00511
else
00512 {
00513
xvprintf(
"(QID: %u) :: SPF version redefined! (%u)\n",
00514
spf_rlevel, peer_info->
spf_ver);
00515
00516
UTIL_assoc_prefix(peer_info,
SPF_S_FAIL, NULL);
00517
xfree(token);
00518
xfree(copy);
00519
return(
FALSE);
00520 }
00521
00522
break;
00523
case ALL:
00524
xprintf(
"(QID: %u) :: policy mechanism is all (%s) policy: (%i)\n",
00525
spf_rlevel, token_ptr, POLICY_TYPE);
00526
00527
UTIL_assoc_prefix(peer_info, PREFIX_TYPE, NULL);
00528 POLICY_MATCH =
TRUE;
00529 peer_info->
ALL =
TRUE;
00530
00531
00532
break;
00533
case DEFAULT:
00534
xprintf(
"(QID: %u) :: policy mechanism is default (%s) policy: (%i)\n",
00535
spf_rlevel, token_ptr, POLICY_TYPE);
00536
00537 POLICY_MATCH =
TRUE;
00538 peer_info->
ALL =
TRUE;
00539
break;
00540
case INCLUDE:
00541
xprintf(
"(QID: %u) :: policy mechanism is include (%s)\n",
00542
spf_rlevel, token_ptr);
00543
00544
if ((tmp_ptr = strstr(token_ptr,
":")) != NULL)
00545 {
00546 tmp_ptr++;
00547
00548 ver_c = peer_info->
spf_ver;
00549
if (
UTIL_is_macro(tmp_ptr) ==
TRUE)
00550 {
00551
if ((macro =
MACRO_expand(peer_info, tmp_ptr)) != NULL)
00552 {
00553 peer_info->
cur_dom =
xstrndup(macro, (strlen(macro) + 1));
00554
xfree(macro);
00555 }
00556 }
00557
else
00558 {
00559 peer_info->
cur_dom =
xstrndup(tmp_ptr, (strlen(tmp_ptr) + 1));
00560 }
00561
00562
spf_rlevel++;
00563 peer_info->
RES =
SPF_NEUTRAL;
00564 PREFIX_TYPE =
SPF_policy_main(peer_info);
00565 peer_info->
spf_ver = ver_c;
00566
xvprintf(
"(QID: %u) :: include returned result %i (%s)\n",
00567
spf_rlevel, PREFIX_TYPE, peer_info->
last_m);
00568
00569
switch (PREFIX_TYPE)
00570 {
00571
case SPF_PASS:
00572 POLICY_MATCH =
TRUE;
00573
break;
00574
case SPF_NONE:
00575
00576
00577
00578 POLICY_ERROR =
TRUE;
00579 PREFIX_TYPE =
SPF_UNKNOWN;
00580
break;
00581
case SPF_S_FAIL:
00582
break;
00583
case SPF_H_FAIL:
00584
break;
00585
case SPF_ERROR:
00586 POLICY_ERROR =
TRUE;
00587
break;
00588
case SPF_NEUTRAL:
00589
break;
00590
case SPF_UNKNOWN:
00591 POLICY_ERROR =
TRUE;
00592
break;
00593
case SPF_UNMECH:
00594
break;
00595 }
00596
00597
if (POLICY_ERROR ==
TRUE)
00598 {
00599
UTIL_assoc_prefix(peer_info, PREFIX_TYPE, token_ptr);
00600
xfree(token);
00601
xfree(copy);
00602
return(
FALSE);
00603 }
00604 }
00605
else
00606 {
00607
00608 POLICY_MATCH =
TRUE;
00609
UTIL_assoc_prefix(peer_info,
SPF_UNKNOWN, token_ptr);
00610
xfree(token);
00611
xfree(copy);
00612
return(
TRUE);
00613 }
00614
break;
00615
00616
case A:
00617
xprintf(
"(QID: %u) :: policy mechanism is A (%s)\n",
spf_rlevel, token_ptr);
00618
00619
if ((tmp_ptr = strstr(token_ptr,
"/")) != NULL)
00620 {
00621 tmp_ptr++;
00622 POLICY_MATCH =
UTIL_a_cmp(peer_info, token_ptr, atoi(tmp_ptr));
00623 }
00624
else
00625 {
00626 POLICY_MATCH =
UTIL_a_cmp(peer_info, token_ptr, 32);
00627 }
00628
00629
00630
if ((PREFIX_TYPE ==
SPF_H_FAIL) && (POLICY_MATCH ==
TRUE))
00631 {
00632
xvprintf(
"(QID: %u) :: Found a match on a negative prefix. Halting"
00633
"parse.\n",
spf_rlevel);
00634
00635
UTIL_assoc_prefix(peer_info,
SPF_H_FAIL, token_ptr);
00636
xfree(token);
00637
xfree(copy);
00638
return(
FALSE);
00639 }
00640
00641
break;
00642
00643
case MX:
00644
xprintf(
"(QID: %u) :: policy mechanism is mx (%s)\n",
00645
spf_rlevel, token_ptr);
00646
00647
00648
if ((tmp_ptr = strstr(token_ptr,
":")) != NULL)
00649 {
00650 tmp_ptr++;
00651 tmp_ptr2 = tmp_ptr;
00652 }
00653
else
00654 {
00655 tmp_ptr2 = peer_info->
cur_dom;
00656 }
00657
00658
if ((tmp_ptr = strstr(token_ptr,
"/")) != NULL)
00659 {
00660 tmp_ptr++;
00661 POLICY_MATCH =
UTIL_mx_cmp(peer_info, tmp_ptr2, atoi(tmp_ptr));
00662 }
00663
else
00664 {
00665 POLICY_MATCH =
UTIL_mx_cmp(peer_info, tmp_ptr2, 32);
00666 }
00667
00668
00669
if ((PREFIX_TYPE ==
SPF_H_FAIL) && (POLICY_MATCH ==
TRUE))
00670 {
00671
xvprintf(
"(QID: %u) :: Found a match on a negative prefix. Halting"
00672
"parse.\n",
spf_rlevel);
00673
00674
UTIL_assoc_prefix(peer_info,
SPF_H_FAIL, token_ptr);
00675
xfree(token);
00676
xfree(copy);
00677
return(
FALSE);
00678 }
00679
00680
break;
00681
case PTR:
00682
xprintf(
"(QID: %u) :: policy mechanism is ptr (%s)\n",
00683
spf_rlevel, token_ptr);
00684
00685 POLICY_MATCH =
UTIL_ptr_cmp(peer_info, token_ptr);
00686
00687
00688
if ((PREFIX_TYPE ==
SPF_H_FAIL) && (POLICY_MATCH ==
TRUE))
00689 {
00690
xvprintf(
"(QID: %u) :: Found a match on a negative prefix. Halting"
00691
"parse.\n",
spf_rlevel);
00692
00693
break;
00694 }
00695
00696
break;
00697
case IP4:
00698
xprintf(
"(QID: %u) :: policy mechanism is ip4 (%s)\n",
00699
spf_rlevel, token_ptr);
00700
00701
if ((policy_ip =
UTIL_expand_ip(token_ptr)) == NULL)
00702 {
00703
xprintf(
"(QID: %u) :: ERROR: inet_pton unable to convert ip to "
00704
"binary\n",
spf_rlevel);
00705
00706
break;
00707 }
00708
00709
xvprintf(
"(QID: %i) :: POL: %lu (%s) PEER: %lu (%s)\n",
00710
spf_rlevel, policy_ip->
addr.s_addr, token_ptr, peer_info->
addr.s_addr,
00711 peer_info->
r_ip);
00712 POLICY_MATCH =
UTIL_cidr_cmp(peer_info, policy_ip, &peer_info->
addr);
00713
xfree(policy_ip);
00714
00715
00716
if ((PREFIX_TYPE ==
SPF_H_FAIL) && (POLICY_MATCH ==
TRUE))
00717 {
00718
xvprintf(
"(QID: %u) :: Found a match on a negative prefix. Halting "
00719
"parse.\n",
spf_rlevel);
00720
00721
UTIL_assoc_prefix(peer_info,
SPF_H_FAIL, token_ptr);
00722
xfree(token);
00723
xfree(copy);
00724
return(
FALSE);
00725 }
00726
00727
break;
00728
case IP6:
00729
xprintf(
"(QID: %u) :: policy mechanism is ip6 (%s)\n",
00730
spf_rlevel, token_ptr);
00731
break;
00732
case EXISTS:
00733
xprintf(
"(QID: %u) :: policy mechanism is exists (%s)\n",
00734
spf_rlevel, token_ptr);
00735
00736
if ((tmp_ptr = strstr(token_ptr,
":")) != NULL)
00737 {
00738 tmp_ptr++;
00739
00740
if ((macro =
MACRO_expand(peer_info, tmp_ptr)) == NULL)
00741 {
00742
xvprintf(
"(QID: %u) :: Unable to expand macro (%s). "
00743
"Aborting.\n",
spf_rlevel, tmp_ptr);
00744
00745
break;
00746 }
00747
00748
if (
DNS_query(peer_info, macro, T_A, NULL) == (
char *)
TRUE)
00749 {
00750 POLICY_MATCH =
TRUE;
00751 }
00752
00753
xfree(macro);
00754 }
00755
break;
00756
case REDIRECT:
00757
xprintf(
"(QID: %u) :: policy mechanism is redirect (%s)\n",
00758
spf_rlevel, token_ptr);
00759
00760
if ((tmp_ptr = strstr(token_ptr,
"=")) != NULL)
00761 {
00762 tmp_ptr++;
00763
00764 ver_c = peer_info->
spf_ver;
00765
if (
UTIL_is_macro(tmp_ptr) ==
TRUE)
00766 {
00767
if ((macro =
MACRO_expand(peer_info, tmp_ptr)) != NULL)
00768 {
00769
xfree(peer_info->
cur_dom);
00770 peer_info->
cur_dom =
xstrndup(macro, (strlen(macro) + 1));
00771
xfree(macro);
00772 }
00773 }
00774
else
00775 {
00776
xfree(peer_info->
cur_dom);
00777 peer_info->
cur_dom =
xstrndup(tmp_ptr, (strlen(tmp_ptr) + 1));
00778 }
00779
00780
spf_rlevel++;
00781 peer_info->
RES =
SPF_NEUTRAL;
00782 PREFIX_TYPE =
SPF_policy_main(peer_info);
00783 peer_info->
spf_ver = ver_c;
00784
xvprintf(
"(QID: %u) :: redirect returned result %i (%s)\n",
00785
spf_rlevel, PREFIX_TYPE, peer_info->
last_m);
00786
00787
switch (PREFIX_TYPE)
00788 {
00789
case SPF_PASS:
00790 POLICY_MATCH =
TRUE;
00791
break;
00792
case SPF_NONE:
00793
00794
00795
00796 POLICY_ERROR =
TRUE;
00797 PREFIX_TYPE =
SPF_UNKNOWN;
00798
break;
00799
case SPF_S_FAIL:
00800
break;
00801
case SPF_H_FAIL:
00802
break;
00803
case SPF_ERROR:
00804 POLICY_ERROR =
TRUE;
00805
break;
00806
case SPF_NEUTRAL:
00807
break;
00808
case SPF_UNKNOWN:
00809 POLICY_ERROR =
TRUE;
00810
break;
00811
case SPF_UNMECH:
00812
break;
00813 }
00814
00815
if (POLICY_ERROR ==
TRUE)
00816 {
00817
UTIL_assoc_prefix(peer_info, PREFIX_TYPE, token_ptr);
00818
xfree(token);
00819
xfree(copy);
00820
return(
FALSE);
00821 }
00822 }
00823
else
00824 {
00825
00826 POLICY_MATCH =
TRUE;
00827
UTIL_assoc_prefix(peer_info,
SPF_UNKNOWN, token_ptr);
00828
xfree(token);
00829
xfree(copy);
00830
return(
TRUE);
00831 }
00832
break;
00833
case EXPLAIN:
00834
xprintf(
"(QID: %u) :: policy mechanism is explain (%s)\n",
00835
spf_rlevel, token_ptr);
00836
00837
if ((tmp_ptr = strstr(token_ptr,
":")) != NULL)
00838 {
00839 tmp_ptr++;
00840
00841
if ((macro =
MACRO_expand(peer_info, tmp_ptr)) == NULL)
00842 {
00843
xvprintf(
"(QID: %u) :: Unable to expand macro (%s). Aborting.\n",
00844
spf_rlevel, tmp_ptr);
00845
00846
break;
00847 }
00848
00849 peer_info->
explain =
xstrndup(macro, (strlen(macro) + 1));
00850
xfree(macro);
00851 }
00852
00853
break;
00854 }
00855
00856
xfree(token);
00857 cp += pos + 1;
00858
00859
if ((POLICY_MATCH ==
TRUE) && (peer_info->
spf_ver > 0))
00860 {
00861
00862
UTIL_assoc_prefix(peer_info, PREFIX_TYPE, peer_info->
last_m);
00863 peer_info->
RES_P = peer_info->
RES;
00864
xfree(copy);
00865
return(
TRUE);
00866 }
00867 }
00868
00869
xfree(copy);
00870
return(
FALSE);
00871 }
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 char *
SPF_result(
peer_info_t *peer_info)
00887 {
00888
char *buf;
00889
00890 buf =
xmalloc(
MAX_HEADER);
00891 memset(buf,
'\0',
MAX_HEADER);
00892
00893
switch (peer_info->
RES)
00894 {
00895
case SPF_PASS:
00896 snprintf(buf,
MAX_SMTP_RES,
RES_PASS, peer_info->
from,
00897 peer_info->
r_ip);
00898
break;
00899
case SPF_NONE:
00900 snprintf(buf,
MAX_SMTP_RES,
RES_NONE, peer_info->
from);
00901
break;
00902
case SPF_S_FAIL:
00903 snprintf(buf,
MAX_SMTP_RES,
RES_S_FAIL, peer_info->
from,
00904 peer_info->
r_ip);
00905
break;
00906
case SPF_H_FAIL:
00907 snprintf(buf,
MAX_SMTP_RES,
RES_H_FAIL, peer_info->
from,
00908 peer_info->
r_ip);
00909
break;
00910
case SPF_ERROR:
00911 snprintf(buf,
MAX_SMTP_RES,
RES_ERROR, peer_info->
from);
00912
break;
00913
case SPF_NEUTRAL:
00914 snprintf(buf,
MAX_SMTP_RES,
RES_NEUTRAL, peer_info->
r_ip,
00915 peer_info->
from);
00916
break;
00917
case SPF_UNKNOWN:
00918 snprintf(buf,
MAX_SMTP_RES,
RES_UNKNOWN, peer_info->
from);
00919
break;
00920
case SPF_UNMECH:
00921 snprintf(buf,
MAX_SMTP_RES,
RES_UNMECH, peer_info->
from);
00922
break;
00923 }
00924
00925
xprintf(
"response: (%s)\n", buf);
00926
00927
return(buf);
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944 char *
SPF_get_explain(
peer_info_t *peer_info)
00945 {
00946
char *buf = NULL;
00947
00948
if (peer_info->
explain != NULL)
00949 {
00950
if ((buf =
MACRO_expand(peer_info,
SPF_EXPLAIN)) != NULL)
00951 {
00952
xprintf(
"Prepending explain: (%s)\n",
00953 buf);
00954
return(buf);
00955 }
00956 }
00957
00958
return(NULL);
00959 }
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 char *
SPF_build_header(
peer_info_t *peer_info)
00976 {
00977
char *buf;
00978
00979 buf =
xmalloc(
MAX_HEADER);
00980 memset(buf,
'\0',
MAX_HEADER);
00981
00982
switch (peer_info->
RES)
00983 {
00984
case SPF_PASS:
00985 snprintf(buf,
MAX_HEADER, peer_info->
spf_result[
SPF_PASS].h,
00986 peer_info->
mta_hname, peer_info->
from, peer_info->
r_ip,
00987 peer_info->
mta_hname, peer_info->
r_ip, peer_info->
from);
00988
break;
00989
case SPF_NONE:
00990 snprintf(buf,
MAX_HEADER, peer_info->
spf_result[
SPF_NONE].h,
00991 peer_info->
mta_hname, peer_info->
from);
00992
break;
00993
case SPF_S_FAIL:
00994 snprintf(buf,
MAX_HEADER, peer_info->
spf_result[
SPF_S_FAIL].h,
00995 peer_info->
mta_hname, peer_info->
from, peer_info->
r_ip,
00996 peer_info->
mta_hname, peer_info->
r_ip, peer_info->
from);
00997
break;
00998
case SPF_H_FAIL:
00999 snprintf(buf,
MAX_HEADER, peer_info->
spf_result[
SPF_H_FAIL].h,
01000 peer_info->
mta_hname, peer_info->
from, peer_info->
r_ip,
01001 peer_info->
mta_hname, peer_info->
r_ip, peer_info->
from);
01002
break;
01003
case SPF_ERROR:
01004 snprintf(buf,
MAX_HEADER, peer_info->
spf_result[
SPF_ERROR].h,
01005 peer_info->
mta_hname, peer_info->
from, peer_info->
error);
01006
break;
01007
case SPF_NEUTRAL:
01008 snprintf(buf,
MAX_HEADER, peer_info->
spf_result[
SPF_NEUTRAL].h,
01009 peer_info->
mta_hname, peer_info->
from, peer_info->
r_ip);
01010
break;
01011
case SPF_UNKNOWN:
01012 snprintf(buf,
MAX_HEADER, peer_info->
spf_result[
SPF_UNKNOWN].h,
01013 peer_info->
mta_hname, peer_info->
from, peer_info->
cur_dom,
01014 peer_info->
last_m);
01015
break;
01016
case SPF_UNMECH:
01017 snprintf(buf,
MAX_HEADER, peer_info->
spf_result[
SPF_UNMECH].h,
01018 peer_info->
last_m, peer_info->
mta_hname, peer_info->
from);
01019
break;
01020 }
01021
01022
xvprintf(
"Prepending header string: (%s)\n", buf);
01023
01024
return(buf);
01025 }
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 SPF_BOOL SPF_smtp_helo(
peer_info_t *peer_info,
const char *s)
01044 {
01045
01046
xprintf(
"called with (%s)\n", s);
01047
01048
if (peer_info->
helo)
01049 {
01050
xfree(peer_info->
helo);
01051 }
01052
01053 peer_info->
helo =
xstrdup(s);
01054 peer_info->
ehlo = peer_info->
helo;
01055
01056
return (strlen(peer_info->
helo) > 0);
01057 }
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077 SPF_BOOL SPF_smtp_from(
peer_info_t *peer_info,
const char *s)
01078 {
01079
int len;
01080
char *pos;
01081
01082
xfree(peer_info->
from);
01083
xfree(peer_info->
cur_dom);
01084
01085
if (s == NULL)
01086 {
01087
if (*(peer_info->
helo) ==
'\0')
01088 {
01089 peer_info->
from =
xstrdup(
"unknown");
01090 }
01091
else
01092 {
01093 peer_info->
from =
xstrdup(peer_info->
helo);
01094 }
01095
01096
xvprintf(
"NULL or invalid MAIL FROM received. Working with %s from now on.\n",
01097 peer_info->
from ? peer_info->
from : peer_info->
helo);
01098
01099
return(
FALSE);
01100 }
01101
01102 peer_info->
from =
xstrdup(s);
01103
01104
01105
if (*peer_info->
from == 60) {
01106 pos = peer_info->
from;
01107 *(peer_info->
from + strlen(peer_info->
from) - 1) = 0;
01108 peer_info->
from++;
01109 peer_info->
from =
xstrdup(peer_info->
from);
01110
xfree(pos);
01111 }
01112
01113
if (*peer_info->
from ==
'\0')
01114 {
01115
if (*(peer_info->
helo) ==
'\0')
01116 {
01117 peer_info->
from =
xstrdup(
"unknown");
01118 }
01119
else
01120 {
01121 peer_info->
from =
xstrdup(peer_info->
helo);
01122 }
01123 }
01124
01125 pos = peer_info->
from;
01126
01127
xprintf(
"FROM: (%s) (called with: %s)\n", peer_info->
from, s);
01128
01129
if ((pos = strstr(pos,
"@")))
01130 {
01131 len = (pos - peer_info->
from);
01132
01133
if (len >=
LOCAL_PART)
01134 {
01135
xvprintf(
"%s is >= %s causing data overrun\n", len,
LOCAL_PART);
01136
01137 }
01138
01139
01140 memcpy(peer_info->
local_part, peer_info->
from, len);
01141 peer_info->
local_part[len] = 0;
01142
01143 pos++;
01144 peer_info->
cur_dom =
xstrdup(pos);
01145
01146
xprintf(
"CUR DOM: (%s)\n", peer_info->
cur_dom);
01147
01148 }
01149
else
01150 {
01151 strcpy(peer_info->
local_part,
"postmaster");
01152 peer_info->
cur_dom =
xstrdup(peer_info->
from);
01153 }
01154
01155
xvprintf(
"LOCAL: (%s) DOMAIN (%s) SENDER: (%s)\n", peer_info->
local_part,
01156 peer_info->
cur_dom, peer_info->
from);
01157
01158
return(
TRUE);
01159 }
01160
01161