spf_get_exp.c

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of either:
00004  *
00005  *   a) The GNU Lesser General Public License as published by the Free
00006  *        Software Foundation; either version 2.1, or (at your option) any
00007  *        later version,
00008  *
00009  *   OR
00010  *
00011  *   b) The two-clause BSD license.
00012  *
00013  * These licenses can be found with the distribution in the file LICENSES
00014  */
00015 
00016 #include "spf_sys_config.h"
00017 
00018 #ifdef STDC_HEADERS
00019 # include <stdlib.h>       /* malloc / free */
00020 # include <stdio.h>             /* stdin / stdout */
00021 #endif
00022 
00023 #ifdef HAVE_NETDB_H
00024 #include <netdb.h>
00025 #endif
00026 
00027 #ifdef HAVE_STRING_H
00028 # include <string.h>       /* strstr / strdup */
00029 #else
00030 # ifdef HAVE_STRINGS_H
00031 #  include <strings.h>       /* strstr / strdup */
00032 # endif
00033 #endif
00034 
00035 
00036 #include "spf.h"
00037 #include "spf_dns.h"
00038 #include "spf_internal.h"
00039 #include "spf_dns_internal.h"
00040 
00041 
00042         /* This never happens. We get SPF_DEFAULT_EXP instead.
00043          * This is a panic response which must not contain macros. */
00044 #define SPF_LAME_EXP    "SPF failure: no explanation available"
00045 
00046 static SPF_errcode_t
00047 SPF_server_get_default_explanation(SPF_server_t *spf_server,
00048                                                 SPF_request_t *spf_request,
00049                                                 SPF_response_t *spf_response,
00050                                                 char **bufp, size_t *buflenp)
00051 {
00052         SPF_errcode_t            err;
00053         SPF_macro_t                     *spf_macro;
00054 
00055         spf_macro = spf_server->explanation;
00056         if (spf_macro != NULL) {
00057                 err = SPF_record_expand_data(spf_server,
00058                                                 spf_request, spf_response,
00059                                                 SPF_macro_data(spf_macro), spf_macro->macro_len,
00060                                                 bufp, buflenp);
00061                 return err;
00062         }
00063         else {
00064                 size_t  len = sizeof(SPF_LAME_EXP) + 1;
00065                 if (*buflenp < len) {
00066                         char    *tmp = realloc(*bufp, len);
00067                         if (tmp == NULL)
00068                                 return SPF_E_NO_MEMORY;
00069                         *bufp = tmp;
00070                         *buflenp = len;
00071                 }
00072                 strcpy(*bufp, SPF_LAME_EXP);
00073                 return SPF_E_SUCCESS;
00074         }
00075 }
00076 
00077 #define RETURN_DEFAULT_EXP() do { \
00078                 return SPF_server_get_default_explanation(spf_server, \
00079                                                 spf_request, spf_response, bufp, buflenp); \
00080                                 } while(0)
00081 
00082 SPF_errcode_t
00083 SPF_request_get_exp(SPF_server_t *spf_server,
00084                                                 SPF_request_t *spf_request,
00085                                                 SPF_response_t *spf_response,
00086                                                 SPF_record_t *spf_record,
00087                                                 char **bufp, size_t *buflenp)
00088 {
00089         SPF_macro_t                     *spf_macro;
00090         SPF_dns_server_t        *resolver;
00091         SPF_dns_rr_t            *rr_txt;
00092         SPF_errcode_t            err;
00093         const char                      *domain;
00094 
00095 
00096         /*
00097          * There are lots of places to look for the explanation message,
00098          * some require DNS lookups, some don't.
00099          */
00100 
00101         SPF_ASSERT_NOTNULL(spf_server);
00102         SPF_ASSERT_NOTNULL(spf_request);
00103         SPF_ASSERT_NOTNULL(spf_response);
00104         SPF_ASSERT_NOTNULL(spf_record);
00105         SPF_ASSERT_NOTNULL(bufp);
00106         SPF_ASSERT_NOTNULL(buflenp);
00107 
00108         domain = spf_request->cur_dom;
00109 
00110         if ( domain == NULL )
00111                 return SPF_response_add_warn(spf_response, SPF_E_NOT_CONFIG,
00112                                 "Could not identify current domain for explanation");
00113 
00114         /*
00115          * start looking...  check spfid for exp-text=
00116          */
00117 
00118         err = SPF_record_find_mod_value(spf_server, spf_request,
00119                                         spf_response, spf_record,
00120                                         SPF_EXP_MOD_NAME, bufp, buflenp);
00121         if (err == SPF_E_SUCCESS)
00122                 return err;
00123 
00124 
00125         /*
00126          * still looking...  check the spfid for exp=
00127          */
00128 
00129         err = SPF_record_find_mod_value(spf_server, spf_request,
00130                                         spf_response, spf_record,
00131                                         "exp", bufp, buflenp );
00132         if (err != SPF_E_SUCCESS) {
00133                 /*
00134                  * still looking...  try to return default exp from spfcid
00135                  */
00136                 RETURN_DEFAULT_EXP();
00137         }
00138 
00139         if (*bufp == NULL  ||  (*bufp)[0] == '\0') {
00140                 /*
00141                  * still looking...  try to return default exp from spfcid
00142                  */
00143                 SPF_response_add_warn(spf_response, SPF_E_NOT_SPF,
00144                                                 "Explanation is blank!");
00145                 RETURN_DEFAULT_EXP();
00146         }
00147 
00148 
00149         /*
00150          * still looking...  try doing a DNS lookup on the exp= name
00151          */
00152 
00153         resolver = spf_server->resolver;
00154 
00155         if (resolver->get_exp)
00156                 return resolver->get_exp(spf_server, *bufp, bufp, buflenp);
00157 
00158         rr_txt = SPF_dns_lookup(resolver, *bufp, ns_t_txt, TRUE);
00159         if (rr_txt == NULL) {
00160                 SPF_dns_rr_free(rr_txt);
00161                 RETURN_DEFAULT_EXP();
00162         }
00163 
00164         switch (rr_txt->herrno) {
00165                 case HOST_NOT_FOUND:
00166                 case NO_DATA:
00167                         SPF_dns_rr_free(rr_txt);
00168                         RETURN_DEFAULT_EXP();
00169                         break;
00170 
00171                 case TRY_AGAIN:
00172                         SPF_dns_rr_free(rr_txt);
00173                         RETURN_DEFAULT_EXP();
00174                         break;
00175 
00176                 case NETDB_SUCCESS:
00177                         break;
00178 
00179                 default:
00180                         SPF_warning("Unknown DNS lookup error code");
00181                         SPF_dns_rr_free(rr_txt);
00182                         RETURN_DEFAULT_EXP();
00183                         break;
00184         }
00185 
00186         if (rr_txt->num_rr == 0) {
00187                 SPF_response_add_warn(spf_response, SPF_E_NOT_SPF,
00188                                 "No TXT records returned from DNS lookup");
00189                 RETURN_DEFAULT_EXP();
00190         }
00191 
00192 
00193         /*
00194          * still looking...  try compiling this TXT record
00195          */
00196 
00197         /* FIXME  we are supposed to concatenate the TXT records */
00198 
00199         /* FIXME: If this generates any errors, demote them to warnings. */
00200         spf_macro = NULL;
00201         err = SPF_record_compile_macro(spf_server, spf_response, &spf_macro,
00202                                                                 rr_txt->rr[0]->txt);
00203         if (err != SPF_E_SUCCESS) {
00204                 if (spf_macro)
00205                         SPF_macro_free(spf_macro);
00206                 SPF_dns_rr_free(rr_txt);
00207                 RETURN_DEFAULT_EXP();
00208         }
00209 
00210         err = SPF_record_expand_data(spf_server,
00211                                         spf_request, spf_response,
00212                                         SPF_macro_data(spf_macro), spf_macro->macro_len,
00213                                         bufp, buflenp);
00214         SPF_macro_free(spf_macro);
00215         SPF_dns_rr_free(rr_txt);
00216 
00217         return err;
00218 }

Generated on Tue Nov 4 13:27:39 2008 for libspf2 by  doxygen 1.5.4