libSPF v1.0: spf.h Source File

Main Page | Data Structures | File List | Data Fields | Globals | Search for

# spf.h

Go to the documentation of this file.

    00001 /* libspf - Sender Policy Framework library
    00002 *
    00003 *  ANSI C implementation of spf-draft-200405.txt
    00004 *
    00005 *  Author: James Couzens <jcouzens@codeshare.ca>
    00006 *  Author: Sean Comeau   <scomeau@obscurity.org>
    00007 *
    00008 *  FILE: spf.h
    00009 *  DESC: main library header file
    00010 *
    00011 *  License:
    00012 *
    00013 *  The libspf Software License, Version 1.0
    00014 *
    00015 *  Copyright (c) 2004 James Couzens & Sean Comeau  All rights
    00016 *  reserved.
    00017 *
    00018 *  Redistribution and use in source and binary forms, with or without
    00019 *  modification, are permitted provided that the following conditions
    00020 *  are met:
    00021 *
    00022 *  1. Redistributions of source code must retain the above copyright
    00023 *     notice, this list of conditions and the following disclaimer.
    00024 *
    00025 *  2. Redistributions in binary form must reproduce the above copyright
    00026 *     notice, this list of conditions and the following disclaimer in
    00027 *     the documentation and/or other materials provided with the
    00028 *     distribution.
    00029 *
    00030 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    00031 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    00032 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    00033 *  DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS MAKING USE OF THIS LICESEN
    00034 *  OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    00035 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    00036 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    00037 *  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00038 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    00039 *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    00040 *  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    00041 *  SUCH DAMAGE.
    00042 *
    00043 */
    00044
    00045
    00046 #ifndef _SPF_H
    00047 #define _SPF_H 1
    00048
    00049 #include <sys/types.h>    /* typedefs */
    00050 #include <netinet/in.h>   /* in_addr struct fBSD */
    00051 #include <arpa/inet.h>    /* in_addr struct */
    00052
    00053 __BEGIN_DECLS
    00054
    00055
    00056 /* spf protocol version we support */
    00057 #define SPF_VERSION 1
    00058
    00059 /*
    00060 *  For reference purposes commented out are the constants based on
    00061 *  RFC 883, RFC 1034, RFC 1035.
    00062 *
    00063 *  #define PACKETSZ  512   max response packet size
    00064 *  #define MAXDNAME  1025  max uncompressed IN_TXT record
    00065 *  #define MAXCDNAME 255   max compressed IN_TXT record
    00066 *
    00067 */
    00068
    00069 #define SPF_MAX_CNAME      5     /* we follow up max CNAMEs */
    00070 #define SPF_MAX_DEBUG      2048  /* maximum for debug code to malloc */
    00071 #define SPF_MAX_MACRO      1024  /* max length of an expanded macro */
    00072 #define SPF_MAX_STR        4096  /* max length of any dynamically allocated string */
    00073 #define SPF_MAX_DELIM      255   /* used by UTIL_count_delim() */
    00074
    00075 #define SPF_MAX_LOCAL_PART 256   /* local-part, text before @ in email addy */
    00076 #define SPF_MAX_ENV_SENDER 512   /* entire FROM: string passed by MTA */
    00077 #define SPF_MAX_CUR_DOM    256   /* text after @ in email addy for cur query */
    00078 #define SPF_MAX_UTC_TIME   22    /* time since epoch */
    00079 #define SPF_MAX_IP_ADDR    17    /* ip of remote peer - DON'T CHANGE FROM 17!! */
    00080 #define SPF_MAX_IP_VER     8     /* ip protocol version */
    00081 #define SPF_MAX_ENV_HELO   512   /* entire HELO string passed by MTA */
    00082
    00083 #define SPF_MAX_HNAME      256   /* hostname of MTA */
    00084 #define SPF_MAX_RESULT      64   /* human readable SPF result */
    00085 #define SPF_MAX_ERROR       96   /* human readable error reason */
    00086 #define SPF_MAX_EXPLAIN_S  256   /* change to EXPLAIN when cleaning up */
    00087 #define SPF_MAX_ENV_RECV   512   /* maximum length of RFC2821 header string */
    00088 #define SPF_MAX_RES_STR     12   /* maximum legnth of a res str eg: "pass" */
    00089
    00090 #define SPF_MAX_MECHANISM  256   /* maximum length of a mechanism */
    00091 #define SPF_MAX_HEADER     512   /* maximum length of header for prepend */
    00092 #define SPF_MAX_SMTP_RES   256   /* maximum length of smtp resonse string */
    00093
    00094 /* human readable string equivalents of spf responses */
    00095 #define HR_RFC2822  "Received-SPF: "
    00096 #define HR_PASS     "pass"
    00097 #define HR_NONE     "none"
    00098 #define HR_S_FAIL   "softfail"
    00099 #define HR_H_FAIL   "fail"
    00100 #define HR_ERROR    "error"
    00101 #define HR_NEUTRAL  "neutral"
    00102 #define HR_UNKNOWN  "unknown"
    00103 #define HR_UNMECH   "unknown mechanism"
    00104
    00105 /* default explanation */
    00106 #define SPF_EXPLAIN "See http://spf.pobox.com/why.html?sender=%{S}&"      \
    00107                     "ip=%{I}&receiver=%{xR}"
    00108
    00109 /* default best guess */
    00110 #define SPF_GUESS   "v=spf1 a/24 mx/24 ptr "
    00111
    00112 /* trusted forwarder */
    00113 #define SPF_TRUSTED "v=spf1 include:spf.trusted-forwarder.org "
    00114
    00115
    00116 /* SPF_BOOL
    00117 *
    00118 *  Our own internal boolean enumeration, simple true or false.
    00119 *
    00120 *  Sendmail has issues because it makes use of SPF_FALSE and SPF_TRUE
    00121 *  Simple way around it iis to simply check and see if they are
    00122 *  defined or not since we're declaring this enumeration
    00123 *  globally.
    00124 *
    00125 *  A more graceful fix has been implemented in libspf 3.0 where
    00126 *  we now make use of SPF_SPF_TRUE and SPF_SPF_FALSE to steer clear of
    00127 *  problems such as this elsewhere.
    00128 *
    00129 */
    00130
    00131 typedef enum SPF_BOOL
    00132 {
    00133   SPF_FALSE = 0,
    00134   SPF_TRUE
    00135 } SPF_BOOL;
    00136
    00137
    00138 /* SPF_RESULT
    00139 *
    00140 *  Error codes representing the result of an SPF policy examination
    00141 *
    00142 *  sucessful parse (some match was made) (+all)
    00143 *  not participating (no SPF/TXT records)
    00144 *  ~all
    00145 *  failed parse (no match made) (-all)
    00146 *  dns problem / error
    00147 *  ?all
    00148 *  permanent parsing error during record examination
    00149 *
    00150 */
    00151 typedef enum SPF_RESULT
    00152 {
    00153   SPF_PASS = 0,     /* + */
    00154   SPF_NONE,
    00155   SPF_S_FAIL,       /* ~ */
    00156   SPF_H_FAIL,       /* - */
    00157   SPF_ERROR,
    00158   SPF_NEUTRAL,      /* ? */
    00159   SPF_UNKNOWN,
    00160   SPF_UNMECH        /* unknown mechanism */
    00161 } SPF_RESULT;
    00162
    00163
    00164 /* SPF_ACTION
    00165 *
    00166 *  Error codes representing the the action to be taken as a result
    00167 *  of the response the library was able to obtain whilst trying to
    00168 *  obtain or examin an SPF policy
    00169 *
    00170 */
    00171 typedef enum SPF_ACTION
    00172 {
    00173   DEFER = 0,
    00174   TARPIT,
    00175   ALLOW,
    00176   REJECT
    00177 } SPF_ACTION;
    00178
    00179
    00180 /* SPF_MECHANISM
    00181 *
    00182 *  Error codes representing the various mechanism types employed
    00183 *  as defined in the RFC
    00184 *
    00185 */
    00186 #undef VERSION /* autoconf */
    00187 typedef enum SPF_MECHANISM
    00188 {
    00189   NO_POLICY = 0,
    00190   VERSION,
    00191   ALL,
    00192   INCLUDE,
    00193   A,
    00194   MX,
    00195   PTR,
    00196   IP4,
    00197   IP6,
    00198   EXISTS,
    00199   REDIRECT,
    00200   EXPLAIN,
    00201   DEFAULT, /* this is OLD school for early adopters = ~,?,+,- */
    00202   UNMECH
    00203 } SPF_MECHANISM;
    00204
    00205
    00206 /* spf_result_t
    00207 *
    00208 *  Storage container used to store the result of an SPF parse.
    00209 *
    00210 */
    00211 typedef struct spf_result_t
    00212 {
    00213   size_t sl;      /* spf result string length */
    00214   char s[32];     /* spf result type string */
    00215   SPF_RESULT i;   /* spf result type */
    00216   size_t hl;      /* length of header string */
    00217   char h[512];    /* Received-SPF: header string */
    00218   char p;         /* prefix identifier */
    00219 } spf_result_t;
    00220
    00221
    00222 /* policy_addr_t
    00223 *
    00224 *  Storage container used to store parsed out ip addresses in their
    00225 *  binary format (in_addr struct) and an unsigned integer containing
    00226 *  the netmask
    00227 *
    00228 */
    00229 typedef struct policy_addr_s
    00230 {
    00231   SPF_RESULT prefix;      /* spf prefix (-,+,~,?) */
    00232   int8_t cidr;            /* address cidr length */
    00233   struct in_addr addr;    /* in_addr struct (unsigned long) */
    00234 } policy_addr_t;
    00235
    00236
    00237 /* spf_config_t
    00238 *
    00239 * Global config structure
    00240 *
    00241 */
    00242 typedef struct spf_config_s
    00243 {
    00244   int level;    /* debug level bit */
    00245 } spf_config_t;
    00246
    00247
    00248 /* split_str_node_t
    00249 *
    00250 *  This structure is used to store where the head and tail are when
    00251 *  creating a list of split_str_node_t structures.
    00252 *
    00253 */
    00254 typedef struct strbuf_node_s
    00255 {
    00256   size_t                 len;    /* length of string */
    00257   char                   *s;     /* expanded string macro */
    00258   struct strbuf_node_s   *next;  /* pointer to next node */
    00259 } strbuf_node_t;
    00260
    00261
    00262 /* strbuf_t
    00263 *
    00264 *  This structure is used exclusively by marco.c functions and is used
    00265 *  to store macros during parsing.
    00266 *
    00267 */
    00268 typedef struct strbuf_s
    00269 {
    00270   strbuf_node_t   *head;      /* head node */
    00271   u_int8_t        elements;   /* number of nodes in list */
    00272 } strbuf_t;
    00273
    00274
    00275 /* split_str_node_t
    00276 *
    00277 *  This structure is used to store where the head and tail are when
    00278 *  creating a list of split_str_node_t structures.
    00279 *
    00280 */
    00281 typedef struct split_str_node_s
    00282 {
    00283   size_t                   len;    /* length of string */
    00284   char                     *s;     /* expanded string macro */
    00285   struct split_str_node_s  *next;  /* pointer to next node */
    00286 } split_str_node_t;
    00287
    00288
    00289 /* split_str_t
    00290 *
    00291 *  This structure is used exclusively by the UTIL_reverse function and is
    00292 *  used to reverse a string using a semi-arbitrary delimiter (see
    00293 *  UTIL_is_spf_delim for valid delimiters, or the SPF RFC)
    00294 */
    00295 typedef struct split_str_s
    00296 {
    00297   split_str_node_t  *head;      /* head node */
    00298   split_str_node_t  *tail;      /* tail node */
    00299   int               elements;   /* number of nodes in list */
    00300 } split_str_t;
    00301
    00302
    00303 /* peer_info_t
    00304 *
    00305 *  Used to store information about the connected peer.  Only one of
    00306 *  SMTP protocol specific three strings will be necessarily be
    00307 *  populated in the following order of precedence: FROM, EHLO, HELO.
    00308 *
    00309 *  The ip_ver string will contain 'in-addr' if the connecting peer
    00310 *  is using IPv4, or 'ip6' if the connect
    00311 *
    00312 *  Various political and technical pressures have recently led to
    00313 *  the deprecation of the IP6.INT name space in favour of IP6.ARPA.
    00314 *  This makes IPv6 PTR data management difficult, since interim
    00315 *  clients will search IP6.INT while standard clients will search
    00316 *  IP6.ARPA. We present a simple method based on DNAME RR's
    00317 *  (see [RFC2672]) and ISC BIND9 whereby zone information can be
    00318 *  managed in a single location and then made visible in two
    00319 *  namespaces.  (http://www.isc.org/tn/isc-tn-2002-1.html)
    00320 *
    00321 *  RFC 937 (POP) states: The maximum length of a command line is 512
    00322 *  characters (including the command word and the CRLF).
    00323 *  POLICY_MATCH = SPF_TRUE
    00324 *
    00325 *  Note: from can be removed and just work on local_part@cur_dom
    00326 *
    00327 */
    00328 typedef struct peer_info_s
    00329 {
    00330   SPF_BOOL ALL;                           /* Was 'all' mechanism parsed */
    00331
    00332   SPF_RESULT RES;                         /* SPF error codes for result */
    00333   SPF_RESULT RES_P;                       /* prefix behaviour */
    00334
    00335   SPF_BOOL use_trust;                     /* T / F trustedfwder */
    00336   SPF_BOOL use_guess;                     /* T / F best guess */
    00337
    00338   u_int8_t spf_ver;                       /* version of SPF */
    00339
    00340   char *p;                                /* prefix from all mechanism */
    00341   char *rs;                               /* ptr str result of SPF query */
    00342   char *helo;                             /* HELO string */
    00343   char *ehlo;                             /* pointer to HELO string */
    00344   char *from;                             /* FROM string */
    00345   char *explain;                          /* Result of an explain query */
    00346   char *guess;                            /* Query if result is TF fails */
    00347   char *trusted;                          /* Query if primary result is none */
    00348   char *ptr_mhost;                        /* validate against during ptr mech */
    00349   char *current_domain;                   /* @domain of the current query */
    00350   char *mta_hname;                        /* ptr to MTA hname eg: mail.foo.org */
    00351   char *r_ip;                             /* pointer to remote ip from MTA */
    00352   char *r_vhname;                         /* validated hostname of remotehost */
    00353   char *cur_eaddr;                        /* current email address */
    00354
    00355   char ip_ver[SPF_MAX_IP_VER];            /* IP Protocol Version */
    00356   char local_part[SPF_MAX_LOCAL_PART];    /* local part of address (user) */
    00357   char utc_time[SPF_MAX_UTC_TIME];        /* The number of seconds since the Epoch */
    00358   char last_m[SPF_MAX_MECHANISM];         /* last mechanism parsed */
    00359   char error[SPF_MAX_ERROR];              /* error (if any) that caused failure */
    00360
    00361   spf_result_t *spf_result;               /* table of str, see spf_result_t */
    00362
    00363   struct in_addr addr;                    /* IP of the remote host (peer) */
    00364
    00365   /*
    00366   *  Vars below here are specific to recursion through layers of SPF queries
    00367   *  stemming from 'include' and 'redirect' use.  In addition there is a
    00368   *  also a buffer for CNAME records.
    00369  */
    00370
    00371   uint8_t spf_rlevel;                     /* recursion level */
    00372
    00373   char *cname_buf;                        /* buf for CNAME records */
    00374   char *include_buf;                      /* buf for 'include' instances */
    00375   char *redirect_buf;                     /* buf for 'redirect' instances */
    00376
    00377 } peer_info_t;
    00378
    00379 extern spf_config_t confg;
    00380 extern u_int8_t spf_rlevel;
    00381
    00382 /*  Main library functions (main.c) */
    00383 extern peer_info_t  *SPF_init(const char *, const char *, const char *, const char *,
    00384                               const char *, u_int32_t, u_int32_t);
    00385 extern peer_info_t  *SPF_close(peer_info_t *);
    00386 extern SPF_RESULT   SPF_policy_main(peer_info_t *);
    00387 extern SPF_RESULT   SPF_policy_main_rec(peer_info_t *);
    00388 extern SPF_BOOL     SPF_parse_policy(peer_info_t *, const char *);
    00389 extern char         *SPF_result(peer_info_t *);
    00390 extern SPF_BOOL     SPF_smtp_from(peer_info_t *, const char *);
    00391 extern SPF_BOOL     SPF_smtp_helo(peer_info_t *, const char *);
    00392
    00393 /* Functions that alter headers (header.c) */
    00394 extern char         *SPF_build_header(peer_info_t *);
    00395 extern char         *SPF_get_explain(peer_info_t *);
    00396
    00397
    00398
    00399 __END_DECLS /* _SPF_H */
    00400
    00401 #endif /* spf.h */