Qsmtp  0.30dev
Macros | Enumerations | Functions | Variables
spf.c File Reference

functions to query and parse SPF entries More...

#include <qsmtpd/antispam.h>
#include <fmt.h>
#include <libowfatconn.h>
#include <match.h>
#include <mime_chars.h>
#include <netio.h>
#include <qsmtpd/qsmtpd.h>
#include <sstring.h>
#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

Macros

#define _GNU_SOURCE   /* for strcasestr() */
 
#define WRITEl(fd, s, l)   if ( (rc = write((fd), (s), (l))) < 0 ) return rc
 
#define WRITE(fd, s)   WRITEl((fd), (s), strlen(s))
 
#define APPEND(addlen, addstr)
 
#define PARSEERR   do { free(*res); return -SPF_PERMERROR; } while (0)
 
#define APPEND(addlen, addstr)
 

Enumerations

enum  spf_makro_expansion {
  SPF_MAKRO_NONE, SPF_MAKRO_PERCENT, SPF_MAKRO_BRACE, SPF_MAKRO_LETTER,
  SPF_MAKRO_TRANSFORMER, SPF_MAKRO_DELIMITER
}
 

Functions

int spfreceived (int fd, const int spf)
 
static int spf_makroparam (const char *token, int *num, int *r, int *delim)
 
static int urlencode (const char *token, char **result)
 URL-encode a given string. More...
 
static int spf_appendmakro (char **res, unsigned int *l, const char *const s, const unsigned int sl, int num, const int r, const int delim)
 
static int validate_domain (char ***domainlist)
 
static int spf_makroletter (const char *p, const char *domain, int ex, char **res, unsigned int *l)
 
int spf_makro (const char *token, const char *domain, int ex, char **result)
 
static int spf_domainspec (const char *domain, const char *token, char **domainspec, int *ip4cidr, int *ip6cidr)
 parse the domainspec More...
 
static int may_have_domainspec (const char *token)
 check if a domainspec is present More...
 
static int spfmx (const char *domain, const char *token)
 
static int spfa (const char *domain, const char *token)
 
static int spfexists (const char *domain, const char *token)
 
static int spfptr (const char *domain, const char *token)
 
static int spfip4 (const char *domain)
 
static int spfip6 (const char *domain)
 
static int txtlookup (char **txt, const char *domain)
 lookup TXT record taking SPF specialities into account More...
 
static size_t match_mechanism (const char *token, const char *mechanism, const char *delimiters)
 check if the token matches the given mechanism More...
 
static size_t spf_modifier_name (const char *token)
 
static void record_bad_token (const char *token)
 
static const char * find_modifier (const char *s, const char *mod)
 find the given modifier in the given string More...
 
static int spflookup (const char *domain, unsigned int *queries)
 
int check_host (const char *domain)
 

Variables

static const char spf_delimiters [] = ".-+,/_="
 

Detailed Description

functions to query and parse SPF entries

Macro Definition Documentation

#define APPEND (   addlen,
  addstr 
)
Value:
{\
char *r2;\
unsigned int oldl = *l;\
\
*l += addlen;\
r2 = realloc(*res, *l);\
if (!r2) { free(*res); return -1;}\
*res = r2;\
memcpy(*res + oldl, addstr, addlen);\
}
#define APPEND (   addlen,
  addstr 
)
Value:
{\
char *r2;\
unsigned int oldl = l;\
\
l += addlen;\
r2 = realloc(res, l);\
if (!r2) { free(res); return -1;}\
res = r2;\
memcpy(res + oldl, addstr, addlen);\
}

Function Documentation

int check_host ( const char *  domain)

look up SPF records for domain

This works a like the check_host in the SPF draft but takes two arguments less. The remote ip and the full sender address can be taken directly from xmitstat.

Parameters
domainno idea what this might be for ;)
Returns
one of the SPF_* constants defined in include/antispam.h
static const char* find_modifier ( const char *  s,
const char *  mod 
)
static

find the given modifier in the given string

Parameters
sthe string to search
modthe modifier to search
Returns
the first modifier match
Return values
NULLmodifier was not found
static size_t match_mechanism ( const char *  token,
const char *  mechanism,
const char *  delimiters 
)
static

check if the token matches the given mechanism

Parameters
tokencurrent token to match
mechanismthe mechanism string to match
delimitersthe delimiters that may be present after the token
Returns
length of the matched mechanism on success
Return values
0mechanism did not match
static int may_have_domainspec ( const char *  token)
static

check if a domainspec is present

Parameters
tokenthe token to check
Returns
if domainspec is present
Return values
0no domainspec present
1domainspec is present
-SPF_PERMERRORinvalid characters detected

This does not check the domainspec itself, it only checks if one is given.

static void record_bad_token ( const char *  token)
static

write the bad token to the SPF explanation record

Parameters
tokenthe current token string
static int spf_appendmakro ( char **  res,
unsigned int *  l,
const char *const  s,
const unsigned int  sl,
int  num,
const int  r,
const int  delim 
)
static

append a makro content to the result

Parameters
resresult string
lcurrent length of res
sthe raw string to appended, does not need to be terminated by '\0'
slstrlen(s), must not be 0
numDIGIT
rBit 1: reverse of not; Bit 2: use URL encoding
delimbit mask of delimiters
Returns
0 on success, -1 on error
static int spf_domainspec ( const char *  domain,
const char *  token,
char **  domainspec,
int *  ip4cidr,
int *  ip6cidr 
)
static

parse the domainspec

Parameters
domainthe current domain string
tokenpointer to the string after the token
domainspechere the expanded domain string is stored (memory will be malloced)
ip4cidrthe length of the IPv4 net (parsed if present in token, -1 if none given)
ip6cidrsame for IPv6 net length
Returns
if domainspec is valid or not
Return values
-1error (ENOMEM)
SPF_PERMERRORdomainspec is syntactically invalid
0everything is fine, domainspec is set
int spf_makro ( const char *  token,
const char *  domain,
int  ex,
char **  result 
)

expand a SPF makro

Parameters
tokenthe token to parse
domainthe current domain string
exif this is an exp string
resultthe resulting string is stored here
Returns
if makro is valid or not
Return values
0makro is valid, result is set
-1internal error (ENOMEM)
SPF_PERMERRORsyntax error

not static, is called from targets/testspf.c

static int spf_makroletter ( const char *  p,
const char *  domain,
int  ex,
char **  res,
unsigned int *  l 
)
static

expand a SPF makro letter

Parameters
pthe token to parse
domainthe current domain string
exif this is an exp string
resthe resulting string is stored here
loffset into res
Returns
number of bytes parsed, -1 on error
static int spf_makroparam ( const char *  token,
int *  num,
int *  r,
int *  delim 
)
static

parse the options in an SPF macro

Parameters
tokentoken to parse
numDIGIT
rif reverse is given
delimbitmask of delimiters
Returns
number of bytes parsed, -1 on error
static size_t spf_modifier_name ( const char *  token)
static

check if the given token is a valid SPF modifier-name

Parameters
tokenthe token to parse
Returns
the length of the modifier-name, i.e. the position of the terminating '='
Return values
0the given token is no valid modifier-name
static int spflookup ( const char *  domain,
unsigned int *  queries 
)
static

look up SPF records for domain

Parameters
domainno idea what this might be for
queriesnumber of DNS queries done
Returns
one of the SPF_* constants defined in include/antispam.h or -1 on ENOMEM
int spfreceived ( int  fd,
const int  spf 
)

print "Received-SPF:" to message header

Parameters
fdfile descriptor of message body
spfSPF status of mail transaction
Returns
0 if everything goes right, -1 on write error
static int txtlookup ( char **  txt,
const char *  domain 
)
static

lookup TXT record taking SPF specialities into account

Parameters
txtresult pointer
domaindomain token to look up
Returns
the same error codes as dnstxt()

This will take two SPF specific contraints into account:

  • trailing dots are ignored
  • if domain is longer than 253 characters parts are removed until it is shorter
static int urlencode ( const char *  token,
char **  result 
)
static

URL-encode a given string.

Parameters
tokenthe token to encode
resultstorage of the result
Returns
if the conversion was successful
Return values
0the string was recoded
1the string does not need to be recoded
-1memory allocation error
static int validate_domain ( char ***  domainlist)
static

build a list of validated domain names for the connected host

Parameters
domainlistwhere to store the array
Returns
how many entries are in domainlist, negative on error

If this functions returns 0 all lookups were successfully, but no validated domain names were found.