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 "spf.h"
00046
#include "util.h"
00047
#include "dns.h"
00048
#include "error.h"
00049
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 char *
DNS_query(
peer_info_t *peer_info,
const char *s,
const int T_TYPE,
00190
const char *mta)
00191 {
00192 int16_t r_len;
00193 int16_t rc;
00194
00195 u_char *msg_ptr;
00196 u_char *eom_ptr;
00197
00198 u_char *rd_ptr;
00199
00200 int8_t ancount;
00201
00202 HEADER *hdr;
00203
00204
char buf[
SPF_MAXDNAME];
00205
char answer[
SPF_PACKETSZ];
00206
00207
char *rr_data = NULL;
00208
00209
int ttl;
00210
00211
if (s == NULL)
00212 {
00213
xeprintf(
"Passed a NULL char. Aborting.\n");
00214
return(NULL);
00215 }
00216
00217
xvprintf(
"Called with (%s) and type: %i\n", s, T_TYPE);
00218
00219 memset(answer,
'\0',
SPF_PACKETSZ);
00220 memset(buf,
'\0',
SPF_MAXDNAME);
00221 r_len = res_search(s, C_IN, T_TYPE, (u_char *)answer,
SPF_PACKETSZ);
00222
00223
if (r_len <= 0)
00224 {
00225
switch (
h_errno)
00226 {
00227
case HOST_NOT_FOUND:
00228 snprintf(peer_info->
error,
MAX_ERROR,
"DNS failure (Host not found)");
00229
UTIL_assoc_prefix(peer_info,
SPF_NONE, NULL);
00230
xvprintf(
"%s", peer_info->
error);
00231
00232
return(NULL);
00233
00234
case TRY_AGAIN:
00235 snprintf(peer_info->
error,
MAX_ERROR,
"DNS failure (Non-Authoritative Host not "
00236
"found, or SERFAIL.)");
00237
UTIL_assoc_prefix(peer_info,
SPF_NONE, NULL);
00238
xvprintf(
"%s", peer_info->
error);
00239
00240
return(NULL);
00241
00242
case NO_RECOVERY:
00243 snprintf(peer_info->
error,
MAX_ERROR,
"DNS failure (Non recoverable errors, "
00244
"FORMERR, REFUSED, NOTIMP.)");
00245
UTIL_assoc_prefix(peer_info,
SPF_ERROR, NULL);
00246
xvprintf(
"%s", peer_info->
error);
00247
00248
return(NULL);
00249
00250
case NO_DATA:
00251 snprintf(peer_info->
error,
MAX_ERROR,
"DNS failure (Valid name, no data record "
00252
"of requested type.)");
00253
UTIL_assoc_prefix(peer_info,
SPF_NONE, NULL);
00254
xvprintf(
"%s", peer_info->
error);
00255
00256
return(NULL);
00257
00258
default:
00259 snprintf(peer_info->
error,
MAX_ERROR,
"DNS failure (internal error)");
00260
UTIL_assoc_prefix(peer_info,
SPF_ERROR, NULL);
00261
xvprintf(
"%s", peer_info->
error);
00262
return(NULL);
00263 }
00264 }
00265
00266 hdr = (HEADER *)&answer;
00267 ancount = ntohs(hdr->ancount);
00268
00269
xvprintf(
"Received packet size of %i bytes which contains %i answers.\n",
00270 r_len, ancount);
00271
xvprintf(
"ANSWERS: %i\n", ancount);
00272
xvprintf(
"QUESTIONS: %i\n", ntohs(hdr->qdcount));
00273
00274
if (ancount > 0)
00275 {
00276 msg_ptr = (u_char *)&answer;
00277 eom_ptr = (u_char *)&answer + r_len;
00278 rd_ptr = (u_char *)&answer + HFIXEDSZ;
00279
00280
if ((rc = dn_skipname(rd_ptr, eom_ptr)) < 0)
00281 {
00282
xeprintf(
"Error obtaining QUESTION!\n");
00283
return(NULL);
00284 }
00285
00286 rd_ptr += rc + QFIXEDSZ;
00287
00288
switch (T_TYPE)
00289 {
00290
case T_A:
00291
return((
char *)
TRUE);
00292
00293
case T_TXT:
00294
if ((rr_data =
DNS_txt_answer(ancount, (u_char *)msg_ptr, (u_char *)eom_ptr,
00295 (u_char *)rd_ptr, buf, &ttl)) == NULL)
00296 {
00297
00298
return(NULL);
00299 }
00300
break;
00301
00302
case T_MX:
00303
if ((rr_data =
DNS_mx_answer(ancount, (u_char *)msg_ptr, (u_char *)eom_ptr,
00304 (u_char *)rd_ptr, buf, &ttl)) == NULL)
00305 {
00306
00307
return(NULL);
00308 }
00309
break;
00310
00311
case T_PTR:
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
if (
DNS_ptr_answer(peer_info, ancount, (u_char *)msg_ptr, (u_char *)eom_ptr,
00322 (u_char *)rd_ptr, buf, mta, &ttl) ==
FALSE)
00323 {
00324
return((
char *)
FALSE);
00325 }
00326
else
00327 {
00328
return((
char *)
TRUE);
00329 }
00330
break;
00331
case T_CNAME:
00332
if ((rr_data =
DNS_cname_answer(ancount, (u_char *)msg_ptr, (u_char *)eom_ptr,
00333 (u_char *)rd_ptr, buf, &ttl)) == NULL)
00334 {
00335
00336
return(NULL);
00337 }
00338
break;
00339 }
00340
00341
return(rr_data);
00342 }
00343
00344
return(NULL);
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 char *
DNS_txt_answer(int16_t ancount,
const u_char *msg_ptr,
00365
const u_char *eom_ptr, u_char *rd_ptr,
char *buf,
int *ttl)
00366 {
00367 int16_t i;
00368 int16_t j;
00369 int16_t rc;
00370 int16_t rd_type;
00371 int16_t rd_len;
00372 int32_t rd_ttl;
00373
00374
char *rr_data = NULL;
00375
char *r_buf = NULL;
00376
char *pos = NULL;
00377
00378
if (msg_ptr == NULL || eom_ptr == NULL || rd_ptr == NULL || buf == NULL)
00379 {
00380
xeprintf(
"Called with NULL pointers\n");
00381
return(NULL);
00382 }
00383
00384 i = 0;
00385 j = ancount;
00386
while (ancount > 0 && rd_ptr < eom_ptr)
00387 {
00388
if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf,
SPF_MAXCDNAME)) < 0)
00389 {
00390
xeprintf(
"Error obtaining ANSWER!\n");
00391
return(NULL);
00392 }
00393
00394
00395 rd_ptr += rc;
00396 GETSHORT(rd_type, rd_ptr);
00397 rd_ptr += INT16SZ;
00398
00399 GETLONG(rd_ttl, rd_ptr);
00400 GETSHORT(rd_len, rd_ptr);
00401
00402 *ttl = rd_ttl;
00403
00404
if (rd_type != T_TXT)
00405 {
00406
xvprintf(
"Ignoring record not of T_TXT type. (%i)\n", rd_type);
00407 rd_ptr += rd_len;
00408
continue;
00409 }
00410
00411 rd_ptr++;
00412 rd_ptr[rd_len] =
'\0';
00413 rd_ptr[rd_len - 1] =
' ';
00414 i += rd_len;
00415
00416
xvprintf(
"Answer %i has length %i. (%i)\n", ancount, rd_len, i);
00417
00418
00419
00420
00421
if (j == 1 && (*rd_ptr !=
'v' && *(rd_ptr + 1) !=
'='))
00422 {
00423
xvprintf(
"INVALID Answer Data: (%s) len: %i\n", rd_ptr, rd_len);
00424
return(NULL);
00425 }
00426
00427
xvprintf(
"Answer Data: (%s) len: %i\n", rd_ptr, rd_len);
00428
00429
if (rd_len <=
SPF_MAXDNAME)
00430 {
00431
if (rr_data == NULL)
00432 {
00433 rr_data =
xmalloc(i + 1);
00434 memset(rr_data,
'\0', (i + 1));
00435 }
00436
else
00437 {
00438 rr_data =
xrealloc(rr_data, (i + 1));
00439 }
00440
00441
xvprintf(
"REALLOCATE memory: %i bytes\n", i);
00442
00443 strncat(rr_data, (
char *)rd_ptr, rd_len);
00444 rr_data[i - 1] =
' ';
00445 rr_data[i] =
'\0';
00446 }
00447
00448 rd_ptr += rd_len;
00449 ancount--;
00450 }
00451
00452
if (rr_data == NULL)
00453 {
00454
return(NULL);
00455 }
00456
00457 rr_data[i] =
'\0';
00458
00459
xvprintf(
"RR_DATA: (%s)\n", rr_data);
00460
00461
if (*rr_data ==
'v' && *(rr_data + 1) ==
'=' && *(rr_data + 2) ==
's' &&
00462 *(rr_data + 3) ==
'p' && *(rr_data + 4) ==
'f' && *(rr_data + 5) ==
'1')
00463 {
00464
xvprintf(
"Returning with valid SPFv1 record\n", rr_data);
00465
return(rr_data);
00466 }
00467
else
00468 {
00469
00470
if ((pos = strstr(rr_data,
"v=spf1")) != NULL)
00471 {
00472
xvprintf(
"Found SPFv1 version mechanism: (%s)\n", pos);
00473 r_buf =
xstrndup(pos, strlen(pos) + 1);
00474 r_buf[strlen(pos)] =
'\0';
00475
xvprintf(
"Old buffer: (%s)\n", rr_data);
00476
xvprintf(
"New buffer: (%s)\n", r_buf);
00477
xfree(rr_data);
00478 pos = NULL;
00479 }
00480
00481
return(r_buf);
00482 }
00483
00484
xeprintf(
"Returning NULL\n");
00485
return(NULL);
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 char *
DNS_mx_answer(int16_t ancount,
const u_char *msg_ptr,
00505
const u_char *eom_ptr, u_char *rd_ptr,
char *buf,
int *ttl)
00506 {
00507 int16_t i;
00508 int16_t rc;
00509 int16_t rd_len = 0;
00510 int16_t rd_pref;
00511 int16_t rd_type;
00512 int32_t rd_ttl;
00513 size_t buf_len;
00514
00515
char *rr_data = NULL;
00516
00517 i = 0;
00518
while ((ancount > 0) && (rd_ptr < eom_ptr))
00519 {
00520
if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf,
SPF_MAXCDNAME)) < 0)
00521 {
00522
xeprintf(
"Error obtaining ANSWER!\n");
00523
return(NULL);
00524 }
00525
00526
00527 rd_ptr += rc;
00528 GETSHORT(rd_type, rd_ptr);
00529 rd_ptr += INT16SZ;
00530
00531 GETLONG(rd_ttl, rd_ptr);
00532 GETSHORT(rd_len, rd_ptr);
00533
00534 *ttl = rd_ttl;
00535
00536
if (rd_type != T_MX)
00537 {
00538
xprintf(
"Forged packet?! We requested T_MX (15) but got %i\n", rd_type);
00539 rd_ptr += rd_len;
00540
continue;
00541 }
00542
00543 GETSHORT(rd_pref, rd_ptr);
00544
00545
if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf,
SPF_MAXCDNAME)) < 0)
00546 {
00547
xeprintf(
"Error obtaining ANSWER!\n");
00548
return(NULL);
00549 }
00550
00551
xvprintf(
"MX: %s Preference: %i\n", buf, rd_pref);
00552
00553 buf_len = strlen(buf);
00554 i += (buf_len + 1);
00555
00556
if (rd_len <=
SPF_MAXDNAME)
00557 {
00558
if (rr_data == NULL)
00559 {
00560 rr_data =
xmalloc(i + 1);
00561 memset(rr_data,
'\0', (i + 1));
00562 }
00563
else
00564 {
00565 rr_data =
xrealloc(rr_data, (i + 1));
00566 }
00567
00568
xvprintf(
"REALLOCATE memory: %i bytes\n", (i + 1));
00569
00570 strncat(rr_data, buf, buf_len);
00571 rr_data[i - 1] =
' ';
00572 rr_data[i] =
'\0';
00573 }
00574
00575 rd_ptr += rc;
00576 ancount--;
00577 }
00578
00579 rr_data[i - 1] =
'\0';
00580
return(rr_data);
00581 }
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 SPF_BOOL DNS_ptr_answer(
peer_info_t *peer_info, int16_t ancount,
00600
const u_char *msg_ptr,
const u_char *eom_ptr, u_char *rd_ptr,
char *buf,
00601
const char *mta,
int *ttl)
00602 {
00603 int16_t rc;
00604 int16_t rd_len = 0;
00605 int16_t rd_type;
00606 int32_t rd_ttl;
00607
00608
char *cp = NULL;
00609
char *copy = NULL;
00610
char *ptr_dom = NULL;
00611
char *cur_dom = NULL;
00612
00613
while ((ancount > 0) && (rd_ptr < eom_ptr))
00614 {
00615
if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf,
SPF_MAXCDNAME)) < 0)
00616 {
00617
xeprintf(
"Error obtaining ANSWER!\n");
00618
return(
FALSE);
00619 }
00620
00621
00622 rd_ptr += rc;
00623 GETSHORT(rd_type, rd_ptr);
00624 rd_ptr += INT16SZ;
00625
00626 GETLONG(rd_ttl, rd_ptr);
00627 GETSHORT(rd_len, rd_ptr);
00628
00629 *ttl = rd_ttl;
00630
00631
if (rd_type != T_PTR)
00632 {
00633
xvprintf(
"Forged packet?! We requested T_PTR (12) but got %i\n",
00634 rd_type);
00635 rd_ptr += rd_len;
00636
continue;
00637 }
00638
00639
if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf,
SPF_MAXCDNAME)) < 0)
00640 {
00641
xeprintf(
"Error obtaining ANSWER!\n");
00642
return(
FALSE);
00643 }
00644
00645
xvprintf(
"Answer %i has length %i.\n", ancount, rd_len);
00646
xvprintf(
"Answer Data: (%s) len: %i\n", buf, strlen(buf));
00647
00648
if (rd_len <=
SPF_MAXDNAME)
00649 {
00650
if ((ptr_dom =
UTIL_get_dname(buf)) == NULL)
00651 {
00652
xvprintf(
"Invalid hostname (%s)\n", buf);
00653
return(
FALSE);
00654 }
00655
00656 cp = copy =
xstrndup(mta, (strlen(mta) + 1));
00657
00658
if ((cp = strstr(mta,
":")) != NULL)
00659 {
00660 cp++;
00661 }
00662
else
00663 {
00664 cp = (
char *)mta;
00665 }
00666
00667
if ((cur_dom =
UTIL_get_dname(cp)) == NULL)
00668 {
00669
xvprintf(
"Invalid hostname (%s)\n", mta);
00670
xfree(ptr_dom);
00671
xfree(copy);
00672
return(
FALSE);
00673 }
00674
00675
if (
UTIL_validate_hostname(peer_info, buf, 32) ==
FALSE)
00676 {
00677
xvprintf(
"Unable to validate hostname (%s [%s]) with (%s [%s])\n",
00678 buf, ptr_dom, mta, cur_dom);
00679
00680
xfree(ptr_dom);
00681
xfree(cur_dom);
00682
xfree(copy);
00683
return(
FALSE);
00684 }
00685
00686
if (strcasecmp(ptr_dom, cur_dom) == 0)
00687 {
00688
xprintf(
"Validated (%s [%s]) against(%s [%s])\n", buf, ptr_dom,
00689 mta, cur_dom);
00690
00691 peer_info->
r_vhname =
xstrndup(mta, (strlen(mta) + 1));
00692
xfree(ptr_dom);
00693
xfree(cur_dom);
00694
xfree(copy);
00695
return(
TRUE);
00696 }
00697
else
00698 {
00699
xprintf(
"Unable to validate (%s : %s)\n", buf, mta);
00700
xfree(ptr_dom);
00701
xfree(cur_dom);
00702
xfree(copy);
00703 }
00704 }
00705
else
00706 {
00707
xeprintf(
"Answer length is too long!\n");
00708 }
00709
00710 rd_ptr += rc;
00711 ancount--;
00712 }
00713
00714
return(
FALSE);
00715 }
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 char *
DNS_cname_answer(int16_t ancount,
const u_char *msg_ptr,
00734
const u_char *eom_ptr, u_char *rd_ptr,
char *buf,
int *ttl)
00735 {
00736 int16_t i;
00737 int16_t rc;
00738 int16_t rd_type;
00739 int16_t rd_len;
00740 int32_t rd_ttl;
00741 size_t buf_len;
00742
00743
char *rr_data = NULL;
00744
00745
if (msg_ptr == NULL || eom_ptr == NULL || rd_ptr == NULL || buf == NULL)
00746 {
00747
xeprintf(
"Called with NULL pointers\n");
00748
return(NULL);
00749 }
00750
00751 i = 0;
00752
while (ancount > 0 && rd_ptr < eom_ptr)
00753 {
00754
if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf,
SPF_MAXCDNAME)) < 0)
00755 {
00756
xeprintf(
"Error obtaining ANSWER!\n");
00757
return(NULL);
00758 }
00759
00760
00761 rd_ptr += rc;
00762 GETSHORT(rd_type, rd_ptr);
00763 rd_ptr += INT16SZ;
00764
00765 GETLONG(rd_ttl, rd_ptr);
00766 GETSHORT(rd_len, rd_ptr);
00767
00768 *ttl = rd_ttl;
00769
00770
if (rd_type != T_CNAME)
00771 {
00772
xvprintf(
"Ignoring record not of T_CNAME type. (%i)\n", rd_type);
00773 rd_ptr += rd_len;
00774
continue;
00775 }
00776
00777
if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf,
SPF_MAXCDNAME)) < 0)
00778 {
00779
xeprintf(
"Error obtaining ANSWER!\n");
00780
return(NULL);
00781 }
00782
00783 buf_len = strlen(buf);
00784 i += (buf_len + 1);
00785
00786
if (rd_len <=
SPF_MAXDNAME)
00787 {
00788
if (rr_data == NULL)
00789 {
00790 rr_data =
xmalloc(i + 1);
00791 memset(rr_data,
'\0', (i + 1));
00792 }
00793
else
00794 {
00795 rr_data =
xrealloc(rr_data, (i + 1));
00796 }
00797
00798
xvprintf(
"REALLOCATE memory: %i bytes\n", (i + 1));
00799
00800 strncat(rr_data, buf, buf_len);
00801 rr_data[i - 1] =
' ';
00802 rr_data[i] =
'\0';
00803 }
00804
00805 rd_ptr += rc;
00806 ancount--;
00807 }
00808
00809 rr_data[i - 1] =
'\0';
00810
return(rr_data);
00811 }
00812
00813