/*
* 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
*/
#ifndef INC_SPF
#define INC_SPF
/*
* we use the in_addr and in6_addr structs all over the place. Every file
* that includes spf.h needs them.
*/
/* #include <sys/types.h> */
/* #include <sys/socket.h> */
/* #include <arpa/inet.h> */
#include "spf_lib_version.h"
#define SPF_VERSION 1
#define SPF_VER_STR "v=spf1"
/*
* object ids for SPF related data
*/
/* SPF record (byte-compiled) */
typedef struct SPF_id_struct *SPF_id_t;
/* SPF configuration (IP address, domain names, options, etc.) */
typedef struct SPF_config_struct *SPF_config_t;
/* SPF DNS layer configuration */
typedef struct SPF_dns_config_struct *SPF_dns_config_t;
/*
* error codes returned by various SPF functions. (including SPF_compile()
* and SPF_id2str(), spf_result(), etc.).
*
* The function SPF_strerror() will return a longer explanation of these
* errors.
*/
typedef int SPF_err_t;
#define SPF_E_SUCCESS 0 /* No errors */
#define SPF_E_NO_MEMORY 1 /* Out of memory */
#define SPF_E_NOT_SPF 2 /* Could not find a valid SPF record */
#define SPF_E_SYNTAX 3 /* Syntax error */
#define SPF_E_MOD_W_PREF 4 /* Modifiers can not have prefixes */
#define SPF_E_INVALID_CHAR 5 /* Invalid character found */
#define SPF_E_UNKNOWN_MECH 6 /* Unknown mechanism found */
#define SPF_E_INVALID_OPT 7 /* Invalid option found */
#define SPF_E_INVALID_CIDR 8 /* Invalid CIDR length */
#define SPF_E_MISSING_OPT 9 /* Required option is missing */
#define SPF_E_INTERNAL_ERROR 10 /* Internal programming error */
#define SPF_E_INVALID_ESC 11 /* Invalid %-escape character */
#define SPF_E_INVALID_VAR 12 /* Invalid macro variable */
#define SPF_E_BIG_SUBDOM 13 /* Subdomain truncation depth too large */
#define SPF_E_INVALID_DELIM 14 /* Invalid delimiter character */
#define SPF_E_BIG_STRING 15 /* Option string too long */
#define SPF_E_BIG_MECH 16 /* Too many mechanisms */
#define SPF_E_BIG_MOD 17 /* Too many modifiers */
#define SPF_E_BIG_DNS 18 /* Mechanisms used too many DNS lookups */
#define SPF_E_INVALID_IP4 19 /* Invalid IPv4 address literal */
#define SPF_E_INVALID_IP6 20 /* Invalid IPv6 address literal */
#define SPF_E_INVALID_PREFIX 21 /* Invalid mechanism prefix */
#define SPF_E_RESULT_UNKNOWN 22 /* SPF result is \"unknown\" */
#define SPF_E_UNINIT_VAR 23 /* Uninitialized variable */
#define SPF_E_MOD_NOT_FOUND 24 /* Modifier not found */
#define SPF_E_NOT_CONFIG 25 /* Not configured */
#define SPF_E_DNS_ERROR 26 /* DNS lookup failure */
#define SPF_E_BAD_HOST_IP 27 /* Invalid hostname (possibly an IP address?) */
#define SPF_E_BAD_HOST_TLD 28 /* Hostname has a missing or invalid TLD */
#define SPF_E_MECH_AFTER_ALL 29 /* Mechanisms found after the \"all:\" mechanism will be ignored */
/* ********************************************************************* */
/*
* SPF record object management
*/
/*
* These routines take care of creating/destroying/etc. the objects
* that hold the byte-compiled SPF records. spfid objects contain
* malloc'ed data, so they must be destroyed when you are finished
* with them, or you will leak memory. This is true even if the spfid
* was created for you by a subroutine, such as SPF_compile().
*/
SPF_id_t SPF_create_id( void ); /* create a new spfid */
void SPF_reset_id( SPF_id_t spfid ); /* reset the spfid to a newly */
/* created state */
void SPF_destroy_id( SPF_id_t spfid ); /* free all memory and clean up.*/
/* spfid is invalid afterwards */
SPF_id_t SPF_dup_id( SPF_id_t src_spfid ); /* create a duplicate of a spfid */
/*
* SPF record byte-compiler
*/
typedef struct
{
SPF_id_t spfid; /* byte compiled SPF record */
SPF_err_t err; /* compiler error */
char *err_msg; /* first compiler error message */
size_t err_msg_len; /* malloc'ed size of err_msg */
int num_errs; /* number of errors */
char **err_msgs; /* all compilter error info */
size_t *err_msgs_len; /* malloc'ed size of err_msgs */
/*
* these pointers refer to places in the text SPF record and will
* become invalid when the caller of spf_compile chooses. This
* detailed info is available only for the first error message.
*
* don't use them if you don't control the text SPF record!
*/
const char *expression; /* the complete mech/mod with the error */
int expression_len;
const char *token; /* the token within the expression */
int token_len;
const char *error_loc; /* exact char within the token */
} SPF_c_results_t;
/*
* The SPF compiler translates the SPF record in text form (passed in
* 'record' argument) into a byte-compiled form. The compiled results are left
* in the c_results structure as described above.
*
* The SPF configuration, while passed as a argument, doesn't effect
* the byte-compiled results. It is used only to determine how
* certain errors are handled, such as the maximum DNS lookups and
* whether the error messages should be sanitized.
*
* An SPF record that is byte-compiled using one configuration can be
* safely evaluated with a completely different configuration.
*/
SPF_err_t SPF_compile( SPF_config_t spfcid, const char *record, SPF_c_results_t *c_results );
/* finds questionable constructs in the SPF record */
void SPF_lint( SPF_id_t spfid, SPF_c_results_t *c_results );
/* SPF_strerror() translates the SPF error number into a readable string */
const char *SPF_strerror( SPF_err_t spf_err );
/*
* SPF_verify() can be used to make sure that the byte-compiled object is
* valid. This is important when the byte-compiled results are obtained
* via an outside source, such as a file or via a DNS lookup. Basically
* any time you call the SPF_mem2id() function, you probably want to call
* SPF_verify().
*/
SPF_err_t SPF_verify( SPF_config_t spfcid, SPF_id_t spfid );
/*
* The SPF optimizer hasn't been written yet, but the intent is to do
* things like converting 'a' and 'mx' mechanisms into the equivalent
* ip4/ip6 mechanisms, inlining include mechanisms, etc.
*/
SPF_err_t SPF_optimize( SPF_config_t spfcid, SPF_id_t *dst_spfid, SPF_id_t src_spfid );
/*
* These routines take care of initializing/freeing/etc. the compiler
* results structure. The c_results structure contains malloc'ed
* variables (including an spfid), so it must be freed when you are
* finished with it.
*/
void SPF_init_c_results( SPF_c_results_t *c_results );
void SPF_reset_c_results( SPF_c_results_t *c_results );
SPF_c_results_t SPF_dup_c_results( SPF_c_results_t c_results );
void SPF_free_c_results( SPF_c_results_t *c_results );
/* FYI only -- can't be changed without recompiling the library
* Most error messages are under 80 characters and we don't want
* bad/malicious input to cause huge error messages */
#define SPF_C_ERR_MSG_SIZE (2*80)
#define SPF_SMTP_COMMENT_SIZE (4*80)
#define SPF_RECEIVED_SPF_SIZE (6*80)
#define SPF_SYSLOG_SIZE (10*80)
/* ********************************************************************* */
/*
* SPF configuration object management
*/
/*
* These routines take care of creating/destroying/etc. the objects
* that hold the SPF configuration. spfcid objects contain
* malloc'ed data, so they must be destroyed when you are finished
* with them, or you will leak memory.
*/
SPF_config_t SPF_create_config( void );
void SPF_reset_config( SPF_config_t spfcid );
void SPF_destroy_config( SPF_config_t spfcid );
SPF_config_t SPF_dup_config( SPF_config_t src_spfcid );
/*
* SPF_destroy_default_config() is useful only at the very end of the
* program to free up all internally malloc'ed variables. These
* variables include such things as the default explanation, that get
* created automatically, Calling this will keep valgrind quiet.
*/
void SPF_destroy_default_config( void );
/*
* The following routines get or set the SPF configuration variables.
*
* All of the functions that set configuration return 0 or
* SPF_E_SUCCESS if there were no errors encountered.
*/
/*
* The 'ip' variables are for the IP address of the client MTA that is
* trying to send you email.
*/
/* SPF_set_ip_str() calls the appropriate IPv4/IPv6 routine, depending
* on the input */
int SPF_set_ip_str( SPF_config_t spfcid, const char *ip_address );
int SPF_set_ipv4_str( SPF_config_t spfcid, const char *ipv4_address );
int SPF_set_ipv4( SPF_config_t spfcid, struct in_addr ipv4 );
struct in_addr SPF_get_ipv4( SPF_config_t spfcid );
int SPF_set_ipv6_str( SPF_config_t spfcid, const char *ipv6_address );
int SPF_set_ipv6( SPF_config_t spfcid, struct in6_addr ipv6 );
struct in6_addr SPF_get_ipv6( SPF_config_t spfcid );
/* SPF_get_client_ver() returns AF_INET or AF_INET6, depending on which
* kind of IP address was set. */
int SPF_get_client_ver( SPF_config_t spfcid );
/*
* SPF needs both an IP address and a domain name to do it's checking.
* The IP address is set by one of the above routines, but the domain
* name is not so simple.
*
* The domain name is normally obtained from the envelope-from (SMTP
* MAIL FROM: command), but if that is null (MAIL FROM:<>), then the
* HELO domain is used (SMTP HELO or EHLO commands).
*
* If there is no local part to the envelope-from email address, the
* name "postmaster" is used instead. This is the case when the HELO
* domain has to be used, but it might be able to happen with the
* envelope-from also, depending on how the MTA works.
*
* Whatever the source of the domain name, the SPF spec defines this
* as the "current domain". Normally, you wouldn't set this directly,
* you would call the SPF_set_helo_dom() and SPF_set_env_from()
* routines. However, when an SPF record is being evaluated, the
* current domain is changed when an include or redirect mechanism is
* executed.
*/
int SPF_set_helo_dom( SPF_config_t spfcid, const char *helo_domain );
char *SPF_get_helo_dom( SPF_config_t spfcid );
int SPF_set_env_from( SPF_config_t spfcid, const char *envelope_from );
char *SPF_get_env_from( SPF_config_t spfcid );
int SPF_set_cur_dom( SPF_config_t spfcid, const char *current_domain );
char *SPF_get_cur_dom( SPF_config_t spfcid );
/*
* While evaluating the SPF record, the number of mechanisms that
* require DNS lookups is kept track of. In order to prevent abusive
* behavior, there is a limit to how many of these mechanisms can be
* executed. It is initial set to the maximum, but you might want to
* lower it in some cases.
*/
int SPF_set_max_dns_mech( SPF_config_t spfcid, int max_dns_mech );
int SPF_get_max_dns_mech( SPF_config_t spfcid );
int SPF_set_max_dns_ptr( SPF_config_t spfcid, int max_dns_ptr );
int SPF_get_max_dns_ptr( SPF_config_t spfcid );
int SPF_set_max_dns_mx( SPF_config_t spfcid, int max_dns_mx );
int SPF_get_max_dns_mx( SPF_config_t spfcid );
/*
* Some of the data for error messages and mail headers is obtained
* from sources on the Internet. In order to prevent accidental or
* malicious strings from being passed on, there is an option to
* sanitize all strings. The default defined by SPF_DEFAULT_SANITIZE
*/
int SPF_set_sanitize( SPF_config_t spfcid, int sanitize );
int SPF_get_sanitize( SPF_config_t spfcid );
/*
* Part of the Received-SPF: email header requires the domain name of
* the receiving MTA.
*/
int SPF_set_rec_dom( SPF_config_t spfcid, const char *receiving_hostname );
char *SPF_get_rec_dom( SPF_config_t spfcid );
/*
* When the SPF check fails, an "explanation" string is generated for
* use by the MTA during the 4xx or 5xx reject code.
*
* This explanation string can be any string with macro variables
* included. It is first byte compiled, and then the result can be
* set in the configuration. If an SPF record does not use the "exp="
* modifier to specify a more appropriate explanation string, this
* default explanation string will be used.
*/
SPF_err_t SPF_compile_exp( SPF_config_t spfcid, const char *exp, SPF_c_results_t *c_results );
int SPF_set_exp( SPF_config_t spfcid, SPF_c_results_t c_results );
/*
* Several of the SPF specifications support a "local policy" option.
* This is both very important, and not particularly obvious how it
* works.
*
* Email may come from many sources, sometimes these sources are not
* direct, and not all of these indirect sources correctly rewrite the
* envelope-from to specify the new domain that is resending the
* email. This can happen on incorrectly configured mailing lists, or
* from people who have set up unix-like .forward files.
*
* Often, you want to accept these emails, even if they would
* technically fail the SPF check. So, you can set up a "local
* policy" that lists these sources of known-ok emails. If a local
* policy is set, it will allow you to whitelist these sources. There
* is a default globally maintained whitelist of known trusted email
* forwarders that is generally a good idea to use.
*
* SPF checks that pass due to local policies will be noted in the
* messages generated from SPF_result(). As such, it is best if the
* local policy option is check only right before the SPF check is
* sure to fail. SPF records that say that a domain never sends email
* should not do any checking of the local policy.
*
* The exact spot in the evaluation of the SPF record was defined in a
* message sent to the SPF-devel mailing list. It said in part:
*
* Philip Gladstone says:
* Message-ID: <400B56AB.30702@gladstonefamily.net>
* Date: Sun, 18 Jan 2004 23:01:47 -0500
*
*
* I think that the localpolicy should only be inserted if the
* final mechanism is '-all', and it should be inserted after
* the last mechanism which is not '-'.
*
* Thus for the case of 'v=spf1 +a +mx -all', this would be
* interpreted as 'v=spf1 +a +mx +localpolicy -all'. Whereas
* 'v=spf1 -all' would remain the same (no non-'-'
* mechanism). 'v=spf1 +a +mx -exists:%stuff -all' would
* become 'v=spf1 +a +mx +localpolicy -exists:%stuff -all'.
*
*
* This local policy string can be any string with macro variables
* included. It is first byte compiled, and then the result can be
* set in the configuration.
*/
SPF_err_t SPF_compile_local_policy( SPF_config_t spfcid, const char *spf_record,
int use_default_whitelist,
SPF_c_results_t *c_results );
int SPF_set_local_policy( SPF_config_t spfcid,
SPF_c_results_t c_results );
SPF_c_results_t SPF_get_local_policy( SPF_config_t spfcid );
/*
* The SPF library allows a certain amount of debugging output to be
* generated for help in determining why things succeeded or failed.
* Currently, only the following debug levels are implemented:
*
* 0 Be completely silent, no debugging information will be generated.
* 1 Moderate amount of debugging information.
* 2 Include some detailed information about the DNS lookups. Usually
* this is not needed.
*/
int SPF_set_debug( SPF_config_t spfcid, int debug_level );
int SPF_get_debug( SPF_config_t spfcid );
/* FYI only -- defaults can't be changed without recompiling the library */
#define SPF_DEFAULT_EXP "Please see http://spf.pobox.com/why.html?sender=%{S}&ip=%{C}&receiver=%{R}"
#define SPF_DEFAULT_MAX_DNS_MECH 10 /* DoS limit on SPF mechanisms */
#define SPF_DEFAULT_MAX_DNS_PTR 5 /* DoS limit on PTR records */
#define SPF_DEFAULT_MAX_DNS_MX 5 /* DoS limit on MX records */
#define SPF_DEFAULT_SANITIZE 1
#define SPF_DEFAULT_WHITELIST "include:spf.trusted-forwarder.org"
/* ********************************************************************* */
/*
* Results from an SPF check
*/
/*
* The results of the SPF check (as defined by the official SPF spec)
*
* To quote from doc/draft-mengwong-spf-00.txt Section 3:
*
* 3. SPF Record Evaluation
*
* An SPF client evaluates an SPF record and produces one of seven
* results:
*
* None: The domain does not publish SPF data.
*
* Neutral (?): The SPF client MUST proceed as if a domain did not
* publish SPF data. This result occurs if the domain explicitly
* specifies a "?" value, or if processing "falls off the end" of
* the SPF record.
*
* Pass (+): the message meets the publishing domain's definition of
* legitimacy. MTAs proceed to apply local policy and MAY accept or
* reject the message accordingly.
*
* Fail (-): the message does not meet a domain's definition of
* legitimacy. MTAs MAY reject the message using a permanent
* failure reply code. (Code 550 is RECOMMENDED. See RFC2821
* section 7.1.)
*
* Softfail (~): the message does not meet a domain's strict
* definition of legitimacy, but the domain cannot confidently state
* that the message is a forgery. MTAs SHOULD accept the message
* but MAY subject it to a higher transaction cost, deeper scrutiny,
* or an unfavourable score.
*
* There are two error conditions, one temporary and one permanent.
*
* Error: indicates an error during lookup; an MTA MAY reject the
* message using a transient failure code, such as 450.
*
* Unknown: indicates incomplete processing: an MTA MUST proceed as
* if a domain did not publish SPF data.
*
* When SPF-aware SMTP receivers accept a message, they SHOULD prepend a
* Received-SPF header. See section 6.
*
* SPF clients MUST use the algorithm described in this section
* or its functional equivalent.
*
* If an SPF client encounters a syntax error in an
* SPF record, it must terminate processing and return a result
* of "unknown".
*
*
* note: SPF_RESULT_* values are constrained by the internal PREFIX_* values
*/
typedef int SPF_result_t;
#define SPF_RESULT_PASS 0 /* + */
#define SPF_RESULT_FAIL 1 /* - */
#define SPF_RESULT_SOFTFAIL 2 /* ~ */
#define SPF_RESULT_NEUTRAL 3 /* ? */
#define SPF_RESULT_UNKNOWN 4 /* permanent error */
#define SPF_RESULT_ERROR 5 /* temp error */
#define SPF_RESULT_NONE 6 /* no SPF record exists */
/*
* The reason that the result was returned
*
* This is what triggered the SPF result. Usually, it is a mechanism in the
* SPF record that causes the result, but if it was something else, the
* calling program will often want to take a different action or issue
* a different message.
*/
typedef int SPF_reason_t;
#define SPF_REASON_NONE 0
#define SPF_REASON_LOCALHOST 1 /* localhost always gets a free ride */
#define SPF_REASON_LOCAL_POLICY 2 /* local policy caused the match */
#define SPF_REASON_MECH 3 /* mechanism caused the match */
#define SPF_REASON_DEFAULT 4 /* ran off the end of the rec */
#define SPF_REASON_2MX 5 /* sent from a secondary MX */
/* FIXME the relationships between result, reason and err is too murky */
/*
* The SPF_output_t structure contains the results from an SPF check. These
* results can then be used by the calling program to reject the email, or
* add headers to the email, or whatever is appropriate.
*
* result See SPF_result_t for details
* reason See SPF_reason_t for details
* err See SPF_err_t for details
*
* err_msg The first error message from compiling/evaluating the record
* num_errs The number of error messages
* err_msgs All of the error messages from compiling/evaluating the record
*
* smtp_comment The MTA should return this message when rejecting an email
* due to the SPF check failure. This comment is created via
* the explanation modifier (exp=) or a default explanation
* if no modifier is found on the SPF record. See section
* 5.2 of the SPF spec for details.
* received_spf The MTA should add this header to the email at the very top
* of the headers. (Before the Received: header generated by
* this MTA) See section 6.3 of the SPF spec for details.
* header_comment This is the "comment" part of the received_spf header.
* This is useful if you want to build your onw received_spf
* header.
*/
typedef struct
{
SPF_result_t result; /* pass/fail/softfail/etc. */
SPF_reason_t reason; /* mech match, local policy, etc*/
SPF_err_t err; /* DNS error, out of memory, etc*/
char *err_msg; /* first syntax error info */
int num_errs; /* number of errors */
char **err_msgs; /* all syntax error info */
char *smtp_comment; /* MTA rejection explanation */
char *received_spf; /* to be added to the email */
char *header_comment; /* comment part of received_spf*/
} SPF_output_t;
/*
* These routines take care of initializing/freeing/etc. the SPF check
* output structure. The output structure contains malloc'ed
* variables, so it must be freed when you are finished with it.
*/
void SPF_init_output( SPF_output_t *output );
SPF_output_t SPF_dup_output( SPF_output_t output );
void SPF_free_output( SPF_output_t *output );
/* SPF_result() just calls SPF_result_id() with the SPF record found
* using the envelope from or HELO domain in the SPF_config_t. */
/*
* The SPF_result() function does most of the real, important work.
*
* SPF_result() checks the IP address and the envelope-from (or HELO
* domain) as was configured using the spfcid variable and sees if it
* is valid. It returns all the info that the caller will need to use
* the SPF check results. See the description of the structure
* SPF_output_t for details about the return value of SPF_result() and
* how they should be used.
*
* It may use the DNS configuration to fetch additional information.
*
* Actually, SPF_result() is just an easy-to-use wrapper around
* SPF_get_spf(), SPF_eval_id() and SPF_result_comments().
*/
SPF_output_t SPF_result( SPF_config_t spfcid, SPF_dns_config_t spfdcid );
/*
* SPF_result_helo() is just like SPF_result(), only it checks the
* HELO domain instead of the envelope from
*/
SPF_output_t SPF_result_helo( SPF_config_t spfcid, SPF_dns_config_t spfdcid );
/*
* SPF_result_2mx() does everything that SPF_result() does, but it first
* checks to see if the sending system is a recognized MX
* secondary for the email recipient. If so, then it returns "pass"
* and does not perform the SPF query. Note that the sending
* system may be a MX secondary for some (but not all) of the
* recipients for a multi-recipient message, which is why
* SPF_result_2mx may be called many times with the final result being
* obtained from SPF_result_2mx_msg().
*
* In effect, SPF_result_2mx() adds the mechanism "mx:<rcpt-to domain>" to
* the beginning of the SPF record for the mail from domain.
*
* If you do not know what a secondary MX is, you probably don't have
* one. Use the SPF_result() function instead.
*
*/
SPF_output_t SPF_result_2mx( SPF_config_t spfcid, SPF_dns_config_t spfdcid,
const char *rcpt_to );
SPF_output_t SPF_result_2mx_msg( SPF_config_t spfcid,
SPF_dns_config_t spfdcid );
/*
* SPF_eval_id() is a low-level runction that does the actual SPF
* checking.
*
* It takes the IP address and domain, the SPF record, and a way to do
* the DNS lookups that the SPF record may require, does the
* evaluation and returns the results.
*
* The IP address and domain are found found in the SPF config. The
* SPF record is found in spfid variable. The way to do the DNS
* lookups is found in the DNS config.
*
* The three different inputs can be mixed and matched in any way you
* want. You can take the same SPF config and evaluate many different
* SPF records with it, or you can take the same SPF record and
* evaluate many different configurations with it. (And the same goes
* for changing the DNS config whenever you want.)
*
* In addition, SPF_eval_id() gets passed a few bookkeeping variables.
*
* The use_local_policy variable determines if the local_policy
* mechanisms should be applied. Normally, the top level call to
* SPF_eval_id() would pass TRUE, but recursive calls caused by the
* include: mechanism would pass FALSE.
*
* The use_helo variable determins if the "responsible sender" (as
* defined in the SPF spec) should be the HELO domain instead of the
* envelope-from. Normally, the HELO domain is used as a fallback if
* the envelope-from is empty, but this variable lets you explicitly
* check the HELO domain.
*
* The "num_dns_mech" keeps track of the number of mechanisms that
* have required DNS lookups. Normally, the top level call to
* SPF_eval_id() pass NULL for num_dns_mech, while recursive calls
* caused by the include: mechanism pass an internal counter.
*/
SPF_output_t SPF_eval_id( SPF_config_t spfcid, SPF_id_t spfid,
SPF_dns_config_t spfdcid,
int use_local_policy, int use_helo,
int *num_dns_mech );
/*
* SPF_result_comments filles out the smtp_comment (if appropriate),
* received_spf and header_comment fields of the SPF_output_t
* structure.
*/
void SPF_result_comments( SPF_config_t spfcid, SPF_dns_config_t spfdcid,
SPF_c_results_t c_results, SPF_output_t *output );
/* SPF_smtp_comment() may requre DNS lookups, so call on when needed */
char *SPF_smtp_comment( SPF_config_t spfcid, SPF_id_t spfid, SPF_dns_config_t spfdcid, SPF_output_t output );
/* SPF_received_spf() depends on the header_comment being set */
char *SPF_received_spf( SPF_config_t spfcid, SPF_c_results_t c_results, SPF_output_t output );
char *SPF_header_comment( SPF_config_t spfcid, SPF_output_t output );
/* SPF_strresult() translates the SPF result number into a readable string */
const char *SPF_strresult( SPF_result_t result );
/* SPF_strreason() translates the SPF reason number into a readable string */
const char *SPF_strreason( SPF_reason_t reason );
/* Extract value of modifier from the SPF record. The value will have
* any macro-variables expanded. */
SPF_err_t SPF_find_mod_value( SPF_config_t spfcid, SPF_id_t spfid,
SPF_dns_config_t spfdcid, const char *mod_name,
char **buf, size_t *buf_len );
SPF_err_t SPF_find_mod_cidr( SPF_config_t spfcid, SPF_id_t spfid,
SPF_dns_config_t spfdcid, const char *mod_name,
int *ipv4_cidr, int *ipv6_cidr );
/* ********************************************************************* */
/*
* misc functions
*/
/* converts the byte-compiled SPF record between the library format and
* a network portable block of data */
SPF_err_t SPF_id2mem( void *dst_mem, int *dst_len, SPF_id_t src_spfid );
SPF_err_t SPF_mem2id( SPF_id_t dst_spfid, void *src_mem, int src_len );
/* convert the byte-compiled SPF record in the equivalent text format.
* The results may not exactly match the original text record before
* it was compiled due to changes in whitespaces, optional arguments,
* etc. */
SPF_err_t SPF_id2str( char **dst_rec, size_t *dst_len, SPF_id_t src_spfid );
/* SPF_err_t SPF_str2id() See: SPF_compile() */
/* print the byte-compiled SPF record, along with a little debugging info */
void SPF_print( SPF_id_t spfid );
/* Get an SPF record from the given domain and return the compiled results.
* If the domain is NULL, SPF_get_spf() will use the envelope-from domain
* if it exists, or the HELO domain as the last resort.
*/
SPF_err_t SPF_get_spf( SPF_config_t spfcid, SPF_dns_config_t spfdcid,
const char *domain, SPF_c_results_t *c_results );
/* Get an SPF explanation string from the given domain and return the
* compiled results */
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 );
/* The client domain is the validated domain name of the client IP
* address. This is not just the domain name(s) found in the reverse
* DNS tree, but involves checking to make sure these name(s) use the
* client IP address. The complete validation procedure is described
* in section 5.4 of the SPF spec.
*/
char *SPF_get_client_dom( SPF_config_t spfcid, SPF_dns_config_t spfdcid );
/* Since determining the client domain can be somewhat expensive, you
* can explicitly make sure it is set, rather than just waiting until
* SPF_get_client_dom() is called. */
void SPF_set_client_dom( SPF_config_t spfcid, SPF_dns_config_t spfdcid );
/* This returns the version information library. Useful if the library
* is a shared library and may differ from when the application was compiled.
*/
void SPF_get_lib_version( int *major, int *minor, int *patch );
/*
* Error messages and warnings generated internally by the library call
* these routines. By default, the messages go to stderr, but you can
* define your own routines to deal with the messages instead.
*/
#include <stdarg.h>
#define SPF_error(errmsg) SPF_errorx( __FILE__, __LINE__, "%s", errmsg )
void SPF_errorx( const char *file, int line, const char *format, ... ) __attribute__ ((noreturn)) __attribute__ ((format (printf, 3, 4)));
void SPF_errorx2( const char *format, ... );
void SPF_errorv( const char *file, int line, const char *format, va_list ap ) __attribute__ ((noreturn)) __attribute__ ((format (printf, 3, 0)));
#define SPF_warning(errmsg) SPF_warningx( __FILE__, __LINE__, "%s", errmsg )
void SPF_warningx( const char *file, int line, const char *format, ... ) __attribute__ ((format (printf, 3, 4)));
void SPF_warningx2( const char *format, ... );
void SPF_warningv( const char *file, int line, const char *format, va_list ap ) __attribute__ ((format (printf, 3, 0)));
#define SPF_info(errmsg) SPF_infox( __FILE__, __LINE__, "%s", errmsg )
void SPF_infox( const char *file, int line, const char *format, ... ) __attribute__ ((format (printf, 3, 4)));
void SPF_infox2( const char *format, ... );
void SPF_infov( const char *file, int line, const char *format, va_list ap ) __attribute__ ((format (printf, 3, 0)));
#define SPF_debug(errmsg) SPF_debugx( __FILE__, __LINE__, "%s", errmsg )
void SPF_debugx( const char *file, int line, const char *format, ... ) __attribute__ ((format (printf, 3, 4)));
void SPF_debugx2( const char *format, ... );
void SPF_debugv( const char *file, int line, const char *format, va_list ap ) __attribute__ ((format (printf, 3, 0)));
#if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L
#define SPF_errorf(format, ... ) SPF_errorx( __FILE__, __LINE__, format, __VA_ARGS__ )
#define SPF_warningf(format, ... ) SPF_warningx( __FILE__, __LINE__, format, __VA_ARGS__ )
#define SPF_infof(format, ... ) SPF_infox( __FILE__, __LINE__, format, __VA_ARGS__ )
#define SPF_debugf(format, ... ) SPF_debugx( __FILE__, __LINE__, format, __VA_ARGS__ )
#elif defined( __GNUC__ )
#define SPF_errorf(format... ) SPF_errorx( __FILE__, __LINE__, format )
#define SPF_warningf(format... ) SPF_warningx( __FILE__, __LINE__, format )
#define SPF_infof(format... ) SPF_infox( __FILE__, __LINE__, format )
#define SPF_debugf(format... ) SPF_debugx( __FILE__, __LINE__, format )
#else
#define SPF_errorf SPF_errorx2
#define SPF_warningf SPF_warningx2
#define SPF_infof SPF_infox2
#define SPF_debugf SPF_debugx2
#endif
/* These message handler routines print to stderr or stdout, as appropriate. */
void SPF_error_stdio( const char *file, int line, const char *errmsg ) __attribute__ ((noreturn));
void SPF_warning_stdio( const char *file, int line, const char *errmsg );
void SPF_info_stdio( const char *file __attribute__ ((unused)), int line __attribute__ ((unused)), const char *errmsg );
void SPF_debug_stdio( const char *file, int line, const char *errmsg );
/* These message handler routines send messages to syslog */
void SPF_error_syslog( const char *file, int line, const char *errmsg ) __attribute__ ((noreturn));
void SPF_warning_syslog( const char *file, int line, const char *errmsg );
void SPF_info_syslog( const char *file __attribute__ ((unused)), int line __attribute__ ((unused)), const char *errmsg );
void SPF_debug_syslog( const char *file, int line, const char *errmsg );
#if 0
/* to use the syslog routines, add code such as: */
openlog(logPrefix,LOG_PID|LOG_CONS|LOG_NDELAY|LOG_NOWAIT,LOG_MAIL);
SPF_error_handler = SPF_error_syslog;
SPF_warning_handler = SPF_warning_syslog;
SPF_info_handler = SPF_info_syslog;
SPF_debug_handler = SPF_debug_syslog;
#endif
/* FYI only -- can't be changed without recompiling the library */
#define SPF_DEFAULT_ERROR_HANDLER SPF_error_stdio
#define SPF_DEFAULT_WARNING_HANDLER SPF_warning_stdio
#define SPF_DEFAULT_INFO_HANDLER SPF_info_stdio
#define SPF_DEFAULT_DEBUG_HANDLER SPF_debug_stdio
/*
* You can assign these global function pointers to whatever routines
* you want to handle the various types of messages. Setting them to NULL
* will cause the messages to be ignored.
*/
extern void (*SPF_error_handler)( const char *, int, const char * ) __attribute__ ((noreturn));
extern void (*SPF_warning_handler)( const char *, int, const char * );
extern void (*SPF_info_handler)( const char *, int, const char * );
extern void (*SPF_debug_handler)( const char *, int, const char * );
#endif
syntax highlighted by Code2HTML, v. 0.9.1