"Fossies" - the Fresh Open Source Software Archive

Member "libspf2-1.2.10/src/spf_example/spf_example.c" (28 Jan 2012, 8972 Bytes) of package /linux/privat/libspf2-1.2.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "spf_example.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  *  spf_example - An example program for how to use libspf2
    3  *  
    4  *  Author: Wayne Schlitt <wayne@midwestcs.com>
    5  *
    6  *  File:   spfquery.c
    7  *  Desc:   SPF command line utility
    8  *
    9  *
   10  * This program is in the public domain, there is no copyright, you
   11  * can do anything you want with it.
   12  */
   13 
   14 
   15 /*
   16  * The libspf2 library uses the GNU autoconf system to help make
   17  * the library more portable.  The config.h file should have the
   18  * HAVE_xxx defines that are appropriate for your system.  Either use
   19  * autconf to create it, or create it by hand.
   20  */
   21 
   22 
   23 #ifdef HAVE_CONFIG_H
   24 # include "config.h"
   25 #endif
   26 
   27 #ifdef STDC_HEADERS
   28 # include <stdio.h>
   29 # include <stdlib.h>       /* malloc / free */
   30 #endif
   31 
   32 #ifdef HAVE_SYS_TYPES_H
   33 #include <sys/types.h>  /* types (u_char .. etc..) */
   34 #endif
   35 
   36 #ifdef HAVE_INTTYPES_H
   37 #include <inttypes.h>
   38 #endif
   39 
   40 #ifdef HAVE_STRING_H
   41 # include <string.h>       /* strstr / strdup */
   42 #else
   43 # ifdef HAVE_STRINGS_H
   44 #  include <strings.h>     /* strstr / strdup */
   45 # endif
   46 #endif
   47 
   48 #ifdef HAVE_SYS_SOCKET_H
   49 # include <sys/socket.h>   /* inet_ functions / structs */
   50 #endif
   51 #ifdef HAVE_NETINET_IN_H
   52 # include <netinet/in.h>   /* inet_ functions / structs */
   53 #endif
   54 #ifdef HAVE_ARPA_INET_H
   55 # include <arpa/inet.h> /* in_addr struct */
   56 #endif
   57 
   58 #ifdef HAVE_ARPA_NAMESER_H
   59 # include <arpa/nameser.h> /* DNS HEADER struct */
   60 #endif
   61 
   62 #ifdef HAVE_UNISTD_H
   63 #include <unistd.h>
   64 #endif
   65 
   66 #ifdef HAVE_GETOPT_H
   67 #include <getopt.h>
   68 #endif
   69 
   70 
   71 
   72 /*
   73  * libspf2 public include files that are needed for this example
   74  * program
   75  */
   76 
   77 #include "spf.h"
   78 
   79 
   80 /*
   81  * usage() just prints out the command line options for this program
   82  */
   83 static void usage()
   84 {
   85     fprintf(
   86     stderr,
   87     "Usage:\n"
   88     "\n"
   89     "spf_example [options]\n"
   90     "\n"
   91     "Valid data options are:\n"
   92     "    -i <IP address>            The IP address that is sending email\n"
   93     "    -s <email address>         The email address used as the\n"
   94     "                               envelope-from.  If no username (local\n"
   95     "                               part) is given, 'postmaster' will be\n"
   96     "                               assumed.\n"
   97     "    -r <email address>         [optional] The email address used as\n"
   98     "                               the envelope-to email address, for\n"
   99     "                               secondary-MX checking.\n"
  100     "    -h <domain name>           The domain name given on the SMTP HELO\n"
  101     "                               command.  This is only needed if the\n"
  102     "                               -sender option is not given.\n"
  103     "    -d [debug level]           debug level.\n"
  104     );
  105 }
  106 
  107 
  108 
  109 /*
  110  * All the code is in the main routine, but most usages of libspf2
  111  * would have the code spread around into various subrotines.
  112  */
  113 
  114 int main( int argc, char *argv[] )
  115 {
  116     int c;
  117     int res = 0;
  118     int i;
  119 
  120     char *opt_ip = NULL;
  121     char *opt_sender = NULL;
  122     char *opt_helo = NULL;
  123     char *opt_rcpt_to = NULL;
  124     int   opt_debug = 0;
  125 
  126     /* You should not indirect on any of these structures, as their
  127      * layout may change between versions of the library. Use the
  128      * accessor functions instead. Definitions of the structs may not
  129      * even be provided. */
  130 
  131     SPF_server_t        *spf_server = NULL;
  132     SPF_request_t       *spf_request = NULL;
  133     SPF_response_t      *spf_response = NULL;
  134     SPF_response_t      *spf_response_2mx = NULL;
  135     
  136 
  137     /*
  138      * check the arguments
  139      */
  140 
  141     while (1)
  142     {
  143     c = getopt(argc, argv, "i:s:h:r:d::" );
  144 
  145     if (c == -1)
  146         break;
  147 
  148     switch (c)
  149     {
  150     case 'i':
  151         opt_ip = optarg;
  152         break;
  153 
  154     case 's':
  155         opt_sender = optarg;
  156         break;
  157 
  158     case 'h':
  159         opt_helo = optarg;
  160         break;
  161 
  162     case 'r':
  163         opt_rcpt_to = optarg;
  164         break;
  165 
  166     case 0:
  167     case '?':
  168         usage();
  169         res = 255;
  170         goto error;
  171         break;
  172 
  173     case 'd':
  174         if (optarg == NULL)
  175         opt_debug = 1;
  176         else
  177         opt_debug = atoi( optarg );
  178         break;
  179 
  180     default:
  181         fprintf( stderr, "Error: getopt returned character code 0%o ??\n", c);
  182     }
  183     }
  184 
  185     if (optind != argc
  186     || opt_ip == NULL
  187     || (opt_helo == NULL && opt_sender == NULL))
  188     {
  189     usage();
  190     res = 255;
  191     goto error;
  192     }
  193 
  194 /*
  195  * Configure the SPF system.
  196  *
  197  * libspf2 is designed so that configurations can be set up once
  198  * and reused many times different emails delivered in a single SMTP
  199  * session or in different SMTP sessions.
  200  */
  201 
  202     /*
  203      * set up the SPF server
  204      *
  205      * Configurations contain malloc'd data so must be
  206      * destroyed when you are finished.
  207      */
  208 
  209     spf_server = SPF_server_new(SPF_DNS_CACHE, 1);
  210 
  211     if (spf_server == NULL) {
  212         fprintf( stderr, "SPF_create_config failed.\n" );
  213         res = 255;
  214         goto error;
  215     }
  216 
  217     /*
  218      * Create a new request.
  219      *
  220      * The SPF request contains all the data needed to process
  221      * the SPF check. Requests are malloc'd so it must be
  222      * destroyed when you are finished with it.
  223      */
  224 
  225     spf_request = SPF_request_new(spf_server);
  226 
  227     /* The domain name of the receiving MTA will default to gethostname() */
  228     /* SPF_request_set_rec_dom( spf_request, opt_name ); */
  229     
  230 
  231 /*
  232  * process the SPF request
  233  *
  234  * Now that the SPF system has been configured, we can process the requests.
  235  * There would normally be a loop around this code or it would be placed
  236  * in a subroutine to be called for each email.
  237  *
  238  * If a single email session sends several emails, you don't need to
  239  * reset the IP address or the HELO domain each time, just change the
  240  * envelope from.
  241  */
  242 
  243     /*
  244      * record the IP address of the client (sending) MTA.
  245      *
  246      * There are other SPF_set_ip*() functionx if you have a structure
  247      * instead of a string.
  248      */
  249 
  250     if ( SPF_request_set_ipv4_str( spf_request, opt_ip ) ) {
  251         printf( "Invalid IP address.\n" );
  252         res = 255;
  253         goto error;
  254     }
  255     
  256 
  257     /*
  258      * record the HELO domain name of the client (sending) MTA from
  259      * the SMTP HELO or EHLO commands
  260      *
  261      * This domain name will be used if the envelope from address is
  262      * null (e.g. MAIL FROM:<>).  This happens when a bounce is being
  263      * sent and, in effect, it is the client MTA that is sending the
  264      * message.
  265      */
  266 
  267     if ( SPF_request_set_helo_dom( spf_request, opt_helo ) ) {
  268         printf( "Invalid HELO domain.\n" );
  269         res = 255;
  270         goto error;
  271     }
  272 
  273     /*
  274      * record the envelope from email address from the SMTP MAIL FROM:
  275      * command.
  276      */
  277 
  278     if ( SPF_request_set_env_from( spf_request, opt_sender ) ) {
  279         printf( "Invalid envelope from address.\n" );
  280         res = 255;
  281         goto error;
  282     }
  283 
  284     /*
  285      * now that we have all the information, see what the result of
  286      * the SPF check is.
  287      */
  288 
  289     SPF_request_query_mailfrom(spf_request, &spf_response);
  290 
  291     /*
  292      * If the sender MAIL FROM check failed, then for each SMTP RCPT TO
  293      * command, the mail might have come from a secondary MX for that
  294      * domain.
  295      *
  296      * Note that most MTAs will also check the RCPT TO command to make sure
  297      * that it is ok to accept. This SPF check won't give a free pass
  298      * to all secondary MXes from all domains, just the one specified by
  299      * the rcpt_to address. It is assumed that the MTA checks (at some
  300      * point) that we are also a valid primary or secondary for the domain.
  301      */
  302     if (SPF_response_result(spf_response) != SPF_RESULT_PASS) {
  303         SPF_request_query_rcptto(spf_request, &spf_response_2mx, opt_rcpt_to);
  304         /*
  305          * We might now have a PASS if the mail came from a client which
  306          * is a secondary MX from the domain specified in opt_rcpt_to.
  307          *
  308          * If not, then the RCPT TO: address must have been a domain for
  309          * which the client is not a secondary MX, AND the MAIL FROM: domain
  310          * doesn't doesn't return 'pass' from SPF_result()
  311          */
  312         if (SPF_response_result(spf_response_2mx) == SPF_RESULT_PASS) {
  313         }
  314     }
  315 
  316     /*
  317      * If the result is something like 'neutral', you probably
  318      * want to accept the email anyway, just like you would
  319      * when SPF_result() returns 'neutral'.
  320      *
  321      * It is possible that you will completely ignore the results
  322      * until the SMPT DATA command.
  323      */
  324 
  325     if ( opt_debug > 0 ) {
  326         printf ( "result = %s (%d)\n",
  327             SPF_strresult(SPF_response_result(spf_response)),
  328                 SPF_response_result(spf_response));
  329         printf ( "err = %s (%d)\n",
  330             SPF_strerror(SPF_response_errcode(spf_response)),
  331                 SPF_response_errcode(spf_response));
  332         for (i = 0; i < SPF_response_messages(spf_response); i++) {
  333             SPF_error_t *err = SPF_response_message(spf_response, i);
  334             printf ( "%s_msg = (%d) %s\n",
  335                 (SPF_error_errorp(err) ? "warn" : "err"),
  336                 SPF_error_code(err),
  337                 SPF_error_message(err));
  338         }
  339     }
  340 
  341 #define VALID_STR(x) (x ? x : "")
  342 
  343     printf( "%s\n%s\n%s\n%s\n",
  344         SPF_strresult( SPF_response_result(spf_response) ),
  345         VALID_STR(SPF_response_get_smtp_comment(spf_response)),
  346         VALID_STR(SPF_response_get_header_comment(spf_response)),
  347         VALID_STR(SPF_response_get_received_spf(spf_response))
  348         );
  349 
  350     res = SPF_response_result(spf_response);
  351 
  352 
  353     /*
  354      * The response from the SPF check contains malloced data, so
  355      * make sure we free it.
  356      */
  357 
  358     SPF_response_free(spf_response);
  359     if (spf_response_2mx)
  360         SPF_response_free(spf_response_2mx);
  361 
  362   error:
  363 
  364     /*
  365      * the SPF configuration variables contain malloced data, so we
  366      * have to vfree them also.
  367      */
  368 
  369     if (spf_request)
  370         SPF_request_free(spf_request);
  371     if (spf_server)
  372         SPF_server_free(spf_server);
  373     return res;
  374 }