/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of either:
*
* a) The GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1, or (at your option) any
* later version,
*
* OR
*
* b) The two-clause BSD license.
*
* These licenses can be found with the distribution in the file LICENSES
*/
#include "spf_alt/spf_sys_config.h"
#ifdef STDC_HEADERS
# include <stdlib.h> /* malloc / free */
# include <stdio.h> /* stdin / stdout */
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include "spf_alt/spf.h"
#include "spf_alt/spf_dns.h"
#include "spf_alt/spf_internal.h"
#include "spf_alt/spf_dns_internal.h"
SPF_err_t SPF_get_exp( SPF_config_t spfcid, SPF_id_t spfid,
SPF_dns_config_t spfdcid,
char **buf, size_t *buf_len )
{
SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );
SPF_dns_iconfig_t *spfdic = SPF_dcid2spfdic( spfdcid );
SPF_dns_rr_t *rr_txt;
SPF_c_results_t c_results;
char *domain;
SPF_err_t err, ret_err;
char *exp_buf = NULL;
size_t exp_buf_len = 0;
/*
* There are lots of places to look for the explanation message,
* some require DNS lookups, some don't.
*/
if ( spfcid == NULL )
SPF_error( "spfcid is NULL" );
if ( spfid == NULL )
SPF_error( "spfid is NULL" );
if ( spfdcid == NULL )
SPF_error( "spfdcid is NULL" );
if ( buf == NULL )
SPF_error( "buf is NULL" );
if ( buf_len == NULL )
SPF_error( "buf_len is NULL" );
domain = spfic->cur_dom;
if ( domain == NULL )
domain = spfic->helo_dom;
if ( domain == NULL )
return SPF_E_NOT_CONFIG;
/*
* start looking... check spfid for exp-text=
*/
err = SPF_find_mod_value( spfcid, spfid, spfdcid, SPF_EXP_MOD_NAME,
buf, buf_len );
if ( err == SPF_E_SUCCESS )
return err;
/*
* still looking... check the spfid for exp=
*/
err = SPF_find_mod_value( spfcid, spfid, spfdcid, "exp",
&exp_buf, &exp_buf_len );
if ( err != SPF_E_SUCCESS )
{
/*
* still looking... try to return default exp from spfcid
*/
if ( exp_buf ) free( exp_buf );
err = SPF_E_SUCCESS;
goto return_default;
}
if ( exp_buf == NULL || exp_buf[0] == '\0' )
{
/*
* still looking... try to return default exp from spfcid
*/
if ( exp_buf ) free( exp_buf );
err = SPF_E_MISSING_OPT;
goto return_default;
}
/*
* still looking... try doing a DNS lookup on the exp= name
*/
if ( spfdic->get_exp )
{
err = spfdic->get_exp( spfcid, spfdcid, exp_buf, buf, buf_len );
free( exp_buf );
return err;
}
rr_txt = SPF_dns_lookup( spfdcid, exp_buf, ns_t_txt, TRUE );
free( exp_buf );
switch( rr_txt->herrno )
{
case HOST_NOT_FOUND:
case NO_DATA:
err = SPF_E_INVALID_OPT;
goto return_default;
break;
case TRY_AGAIN:
err = SPF_E_DNS_ERROR;
goto return_default;
break;
case NETDB_SUCCESS:
break;
default:
SPF_warning( "unknown DNS lookup error code" );
err = SPF_E_DNS_ERROR;
goto return_default;
break;
}
if ( rr_txt->num_rr == 0 )
{
SPF_warning( "No TXT records returned from DNS lookup" );
err = SPF_E_INVALID_OPT;
goto return_default;
}
/*
* still looking... try compiling this TXT record
*/
/* FIXME we are supposed to concatenate the TXT records */
SPF_init_c_results( &c_results );
err = SPF_compile_exp( spfcid, rr_txt->rr[0]->txt, &c_results );
if ( err != SPF_E_SUCCESS )
{
/*
* still looking... try to return default exp from spfcid
*/
if ( err && spfic->debug > 0 )
SPF_warning( c_results.err_msg );
SPF_free_c_results( &c_results );
goto return_default;
}
err = SPF_find_mod_value( spfcid, c_results.spfid, spfdcid,
SPF_EXP_MOD_NAME,
buf, buf_len );
SPF_free_c_results( &c_results );
if( err != SPF_E_SUCCESS )
goto return_default;
return err;
return_default:
ret_err = err;
if ( *buf == NULL || *buf_len < SPF_C_ERR_MSG_SIZE )
{
char *new_err_msg;
new_err_msg = realloc( *buf, SPF_C_ERR_MSG_SIZE );
if ( new_err_msg == NULL )
return SPF_E_NO_MEMORY;
*buf = new_err_msg;
*buf_len = SPF_C_ERR_MSG_SIZE;
}
if ( spfic->exp.spfid == NULL )
{
/* give up looking */
if( *buf )
snprintf( *buf, *buf_len, "SPF failure: %s",
SPF_strerror( SPF_E_UNINIT_VAR ) );
return SPF_E_UNINIT_VAR;
}
err = SPF_find_mod_value( spfcid, spfic->exp.spfid, spfdcid,
SPF_EXP_MOD_NAME,
buf, buf_len );
if ( err && spfic->debug > 0 )
SPF_warning( SPF_strerror( err ) );
if( err != SPF_E_SUCCESS && *buf )
snprintf( *buf, *buf_len, "SPF failure: %s", SPF_strerror( err ) );
return ret_err;
}
syntax highlighted by Code2HTML, v. 0.9.1