00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifdef _WIN32
00017
00018 #include "spf_sys_config.h"
00019
00020 #ifdef HAVE_ERRNO_H
00021 #include <errno.h>
00022 #endif
00023
00024 #ifdef STDC_HEADERS
00025 # include <stdio.h>
00026 # include <stdlib.h>
00027 #endif
00028
00029 #ifdef HAVE_STRING_H
00030 # include <string.h>
00031 #else
00032 # ifdef HAVE_STRINGS_H
00033 # include <strings.h>
00034 # endif
00035 #endif
00036
00037 #include "spf.h"
00038 #include "spf_dns.h"
00039 #include "spf_internal.h"
00040 #include "spf_dns_internal.h"
00041 #include "spf_dns_windns.h"
00042 #pragma comment(lib, "dnsapi.lib")
00043 #include <windns.h>
00044
00045
00046 typedef struct
00047 {
00048 int debug;
00049 SPF_dns_rr_t spfrr;
00050 } SPF_dns_windns_config_t;
00051
00052
00053 #define SPF_h_errno WSAGetLastError()
00054
00055
00056 static inline SPF_dns_windns_config_t *SPF_voidp2spfhook( void *hook )
00057 { return (SPF_dns_windns_config_t *)hook; }
00058 static inline void *SPF_spfhook2voidp( SPF_dns_windns_config_t *spfhook )
00059 { return (void *)spfhook; }
00060
00061
00062 LPSTR SPF_dns_create_error_message_windns(DWORD last_error)
00063 {
00064 LPSTR error_message;
00065
00066 if (!FormatMessageA(
00067 (FORMAT_MESSAGE_ALLOCATE_BUFFER |
00068 FORMAT_MESSAGE_FROM_SYSTEM |
00069 FORMAT_MESSAGE_IGNORE_INSERTS),
00070 NULL,
00071 last_error,
00072 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00073 (LPSTR) &error_message,
00074 0,
00075 NULL))
00076 {
00077 return NULL;
00078 }
00079
00080 return error_message;
00081 }
00082
00083
00084 void SPF_dns_destroy_error_message_windns(LPSTR error_message)
00085 {
00086 LocalFree( error_message );
00087 }
00088
00089
00090 size_t SPF_dns_txt_get_length_windns(DWORD count, PSTR strings[])
00091 {
00092 size_t length;
00093 DWORD i;
00094
00095 length = 0;
00096
00097 for( i = 0; i < count; i++ )
00098 {
00099 length = length + strlen(strings[i]);
00100 }
00101
00102 return length;
00103 }
00104
00105
00106 char *SPF_dns_txt_concat_windns(char *buffer, DWORD count, PSTR strings[])
00107 {
00108 DWORD i;
00109
00110 buffer[0] = 0;
00111
00112 for( i = 0; i < count; i++ )
00113 {
00114 if ( strcat( buffer, strings[i] ) == NULL )
00115 return NULL;
00116 }
00117
00118 return buffer;
00119 }
00120
00121
00122 static SPF_dns_rr_t *SPF_dns_lookup_windns( SPF_dns_config_t spfdcid, const char *domain, ns_type rr_type, int should_cache )
00123 {
00124 SPF_dns_iconfig_t *spfdic = SPF_dcid2spfdic( spfdcid );
00125 SPF_dns_windns_config_t *spfhook = SPF_voidp2spfhook( spfdic->hook );
00126 SPF_dns_rr_t *spfrr;
00127
00128 int cnt;
00129
00130 PDNS_RECORDA pDnsRecord;
00131
00132 DNS_STATUS status;
00133 LPSTR error_message;
00134
00135 char ip4_buf[ INET_ADDRSTRLEN ];
00136 char ip6_buf[ INET6_ADDRSTRLEN ];
00137
00138 int rdlen;
00139
00140 DNS_A_DATA *pA_data;
00141 DNS_AAAA_DATA *pAAAA_data;
00142 DNS_MX_DATAA *pMX_data;
00143 DNS_TXT_DATAA *pTXT_data;
00144 DNS_PTR_DATAA *pPTR_data;
00145
00146 size_t txt_data_len;
00147 char *txt_concat;
00148
00149
00150
00151
00152
00153 spfrr = &spfhook->spfrr;
00154 SPF_dns_reset_rr( spfrr );
00155 spfrr->herrno = NO_RECOVERY;
00156 spfrr->rr_type = rr_type;
00157 if ( domain && domain[0] != '\0' )
00158 {
00159 char *new_domain;
00160 size_t new_len = strlen( domain ) + 1;
00161
00162 if ( spfrr->domain_buf_len < new_len )
00163 {
00164 new_domain = realloc( spfrr->domain, new_len );
00165 if ( new_domain == NULL )
00166 return spfrr;
00167
00168 spfrr->domain = new_domain;
00169 spfrr->domain_buf_len = new_len;
00170 }
00171 strcpy( spfrr->domain, domain );
00172 }
00173 else if ( spfrr->domain )
00174 spfrr->domain[0] = '\0';
00175
00176 cnt = 0;
00177
00178 if ( spfhook->debug )
00179 SPF_debugf( "WinDNS looking for: %s %s (%d)",
00180 domain,
00181 (
00182 (rr_type == ns_t_a) ? "A" :
00183 (rr_type == ns_t_aaaa) ? "AAAA" :
00184 (rr_type == ns_t_mx) ? "MX" :
00185 (rr_type == ns_t_txt) ? "TXT" :
00186 (rr_type == ns_t_ptr) ? "PTR" :
00187 (rr_type == ns_t_any) ? "ANY" :
00188 "??"
00189 ),
00190 rr_type );
00191
00192
00193
00194
00195
00196 status = DnsQuery_A( domain, rr_type,
00197 (DNS_QUERY_STANDARD + DNS_QUERY_TREAT_AS_FQDN),
00198 NULL, &pDnsRecord, NULL );
00199
00200 if ( status != DNS_RCODE_NOERROR )
00201 {
00202 if ( spfhook->debug )
00203 {
00204 error_message = SPF_dns_create_error_message_windns(SPF_h_errno);
00205
00206 SPF_debugf( "query failed: err = %d %s (%d)",
00207 status, error_message, SPF_h_errno );
00208
00209 SPF_dns_destroy_error_message_windns(error_message);
00210 }
00211
00212 if (
00213 ( SPF_h_errno == HOST_NOT_FOUND ) &&
00214 ( spfdic->layer_below )
00215 )
00216 return SPF_dcid2spfdic( spfdic->layer_below )->lookup( spfdic->layer_below, domain, rr_type, should_cache );
00217
00218 spfrr->herrno = SPF_h_errno;
00219 return spfrr;
00220 }
00221 else
00222 spfrr->herrno = NETDB_SUCCESS;
00223
00224 while (pDnsRecord)
00225 {
00226 rdlen = pDnsRecord->wDataLength;
00227
00228 if ( spfhook->debug > 1 )
00229 SPF_debugf( "name: %s type: %d ttl: %d rdlen: %d",
00230 pDnsRecord->pName, pDnsRecord->wType,
00231 pDnsRecord->dwTtl, rdlen );
00232
00233 if ( rdlen <= 0 )
00234 {
00235 pDnsRecord = pDnsRecord->pNext;
00236 continue;
00237 }
00238
00239
00240 if (pDnsRecord->wType == ns_t_txt)
00241 {
00242 pTXT_data = &pDnsRecord->Data.TXT;
00243
00244 txt_data_len =
00245 SPF_dns_txt_get_length_windns(
00246 pTXT_data->dwStringCount,
00247 pTXT_data->pStringArray
00248 );
00249 }
00250
00251 if ( spfhook->debug > 1 )
00252 {
00253 switch( pDnsRecord->wType )
00254 {
00255 case ns_t_a:
00256
00257 pA_data = &pDnsRecord->Data.A;
00258
00259 SPF_debugf( "A: %s",
00260 inet_ntop( AF_INET, &pA_data->IpAddress,
00261 ip4_buf, sizeof( ip4_buf ) ));
00262 break;
00263
00264 case ns_t_aaaa:
00265
00266 pAAAA_data = &pDnsRecord->Data.AAAA;
00267
00268 SPF_debugf( "AAAA: %s",
00269 inet_ntop( AF_INET6, &pAAAA_data->Ip6Address,
00270 ip6_buf, sizeof( ip6_buf ) ));
00271 break;
00272
00273 case ns_t_ns:
00274
00275 SPF_debugf( "NS: %s", pDnsRecord->Data.NS.pNameHost );
00276 break;
00277
00278 case ns_t_cname:
00279
00280 SPF_debugf( "CNAME: %s", pDnsRecord->Data.CNAME.pNameHost );
00281 break;
00282
00283 case ns_t_mx:
00284
00285 pMX_data = &pDnsRecord->Data.MX;
00286
00287 SPF_debugf( "MX: %d %s",
00288 pMX_data->wPreference, pMX_data->pNameExchange );
00289 break;
00290
00291 case ns_t_txt:
00292
00293 txt_concat = malloc(txt_data_len + 1);
00294
00295 if ( txt_concat == NULL )
00296 SPF_debugf( "TXT: (%d) - no memory for concatination",
00297 txt_data_len );
00298 else
00299 {
00300 if ( SPF_dns_txt_concat_windns(
00301 txt_concat,
00302 pTXT_data->dwStringCount,
00303 pTXT_data->pStringArray
00304 ) == NULL )
00305 SPF_debugf( "TXT: (%d) - error in concatination",
00306 txt_data_len );
00307 else
00308 {
00309 SPF_debugf( "TXT: (%d) \"%s\"",
00310 txt_data_len, txt_concat );
00311 }
00312 free( txt_concat );
00313 }
00314 break;
00315
00316 case ns_t_ptr:
00317
00318 pPTR_data = &pDnsRecord->Data.PTR;
00319
00320 SPF_debugf( "PTR: %s", pPTR_data->pNameHost );
00321 break;
00322
00323 default:
00324 SPF_debugf( "not parsed: type: %d", pDnsRecord->wType );
00325 break;
00326 }
00327 }
00328
00329 if (
00330 ( pDnsRecord->Flags.S.Section != DNSREC_ANSWER ) &&
00331 ( spfhook->debug > 1 )
00332 )
00333 {
00334 pDnsRecord = pDnsRecord->pNext;
00335 continue;
00336 }
00337
00338
00339 if (
00340 ( pDnsRecord->wType != spfrr->rr_type ) &&
00341 ( pDnsRecord->wType != ns_t_cname )
00342 )
00343 {
00344 SPF_debugf( "unexpected rr type: %d expected: %d",
00345 pDnsRecord->wType, rr_type );
00346 pDnsRecord = pDnsRecord->pNext;
00347 continue;
00348 }
00349
00350 switch( pDnsRecord->wType )
00351 {
00352 case ns_t_a:
00353
00354 pA_data = &pDnsRecord->Data.A;
00355
00356 if ( SPF_dns_rr_buf_malloc(
00357 spfrr, cnt, sizeof( pA_data->IpAddress )
00358 ) != SPF_E_SUCCESS )
00359 return spfrr;
00360
00361 memmove( &spfrr->rr[cnt]->a, &pA_data->IpAddress,
00362 sizeof( pA_data->IpAddress ) );
00363
00364 cnt++;
00365 break;
00366
00367 case ns_t_aaaa:
00368
00369 pAAAA_data = &pDnsRecord->Data.AAAA;
00370
00371 if ( SPF_dns_rr_buf_malloc(
00372 spfrr, cnt, sizeof( pAAAA_data->Ip6Address )
00373 ) != SPF_E_SUCCESS )
00374 return spfrr;
00375
00376 memmove( &spfrr->rr[cnt]->aaaa, &pAAAA_data->Ip6Address,
00377 sizeof( pAAAA_data->Ip6Address ) );
00378
00379 cnt++;
00380 break;
00381
00382 case ns_t_ns:
00383 break;
00384
00385 case ns_t_cname:
00386
00387 break;
00388
00389 case ns_t_mx:
00390
00391 pMX_data = &pDnsRecord->Data.MX;
00392
00393 if ( SPF_dns_rr_buf_malloc(
00394 spfrr, cnt, strlen( pMX_data->pNameExchange ) + 1
00395 ) != SPF_E_SUCCESS )
00396 return spfrr;
00397
00398 strcpy( spfrr->rr[cnt]->mx, pMX_data->pNameExchange );
00399
00400 cnt++;
00401 break;
00402
00403 case ns_t_txt:
00404
00405 if ( SPF_dns_rr_buf_malloc(
00406 spfrr, cnt, txt_data_len + 1
00407 ) != SPF_E_SUCCESS )
00408 return spfrr;
00409
00410 if ( SPF_dns_txt_concat_windns(
00411 spfrr->rr[cnt]->txt,
00412 pTXT_data->dwStringCount,
00413 pTXT_data->pStringArray
00414 ) == NULL )
00415 return spfrr;
00416
00417 cnt++;
00418 break;
00419
00420 case ns_t_ptr:
00421
00422 pPTR_data = &pDnsRecord->Data.PTR;
00423
00424 if ( SPF_dns_rr_buf_malloc(
00425 spfrr, cnt, strlen( pPTR_data->pNameHost ) + 1
00426 ) != SPF_E_SUCCESS )
00427 return spfrr;
00428
00429 strcpy( spfrr->rr[cnt]->ptr, pPTR_data->pNameHost );
00430
00431 cnt++;
00432 break;
00433
00434 default:
00435 break;
00436 }
00437
00438 spfrr->num_rr = cnt;
00439
00440 pDnsRecord = pDnsRecord->pNext;
00441 }
00442
00443 if ( spfrr->num_rr == 0 )
00444 spfhook->spfrr.herrno = NO_DATA;
00445
00446 return spfrr;
00447 }
00448
00449
00450 SPF_dns_config_t SPF_dns_create_config_windns( SPF_dns_config_t layer_below, int debug )
00451 {
00452 SPF_dns_iconfig_t *spfdic;
00453 SPF_dns_windns_config_t *spfhook;
00454
00455
00456 spfdic = malloc( sizeof( *spfdic ) );
00457 if ( spfdic == NULL )
00458 return NULL;
00459
00460 spfdic->hook = calloc( 1, sizeof( SPF_dns_windns_config_t ) );
00461 if ( spfdic->hook == NULL )
00462 {
00463 free( spfdic );
00464 return NULL;
00465 }
00466
00467 spfdic->destroy = SPF_dns_destroy_config_windns;
00468 spfdic->lookup = SPF_dns_lookup_windns;
00469 spfdic->get_spf = NULL;
00470 spfdic->get_exp = NULL;
00471 spfdic->add_cache = NULL;
00472 spfdic->layer_below = layer_below;
00473 spfdic->name = "windns";
00474
00475 spfhook = SPF_voidp2spfhook( spfdic->hook );
00476
00477 spfhook->debug = debug;
00478 SPF_dns_reset_rr( &spfhook->spfrr );
00479 spfhook->spfrr.source = SPF_spfdic2dcid( spfdic );
00480
00481 return SPF_spfdic2dcid( spfdic );
00482 }
00483
00484 void SPF_dns_reset_config_windns( SPF_dns_config_t spfdcid )
00485 {
00486 SPF_dns_iconfig_t *spfdic = SPF_dcid2spfdic( spfdcid );
00487
00488
00489 if ( spfdcid == NULL )
00490 SPF_error( "spfdcid is NULL" );
00491
00492
00493 SPF_dns_reset_rr( &(SPF_voidp2spfhook( spfdic->hook )->spfrr) );
00494 }
00495
00496 void SPF_dns_destroy_config_windns( SPF_dns_config_t spfdcid )
00497 {
00498 SPF_dns_iconfig_t *spfdic = SPF_dcid2spfdic( spfdcid );
00499
00500 if ( spfdcid == NULL )
00501 SPF_error( "spfdcid is NULL" );
00502
00503 if ( spfdic->hook )
00504 {
00505 SPF_dns_windns_config_t *spfhook = SPF_voidp2spfhook( spfdic->hook );
00506
00507 SPF_dns_destroy_rr_var( &spfhook->spfrr );
00508
00509 free( spfdic->hook );
00510 }
00511
00512 if ( spfdic )
00513 free( spfdic );
00514 }
00515
00516 #endif