/* libspf - Sender Policy Framework library
*
*  ANSI C implementation of spf-draft-200405.txt
*
*  Author: James Couzens <jcouzens@codeshare.ca>
*
*  File:   spfqtool.c
*  Desc:   SPF Query Tool (an example implementation of libSPF)
*
*  License:
*
*  The libspf Software License, Version 1.0
*
*  Copyright (c) 2004 James Couzens & Sean Comeau  All rights
*  reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*  1. Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*  2. Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in
*     the documentation and/or other materials provided with the
*     distribution.
*
*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
*  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*  DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS MAKING USE OF THIS LICESEN
*  OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
*  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
*  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
*  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*  SUCH DAMAGE.
*
*/

#include "spfqtool.h"


/* SPF_usage
*
*  Author: James Couzens <jcouzens@6o4.ca>
*
*  Date:   07/04/04
*  Date:   07/28/04 - Renamed to spfqtool
*  Date:   09/08/04 - Added SPF_build_header call
*
*  Desc:
*         Main function, allocates memory and makes calls to the libSPF 
*  library which parses the "fake" query.
*
*/
int main(int argc, char *argv[])
{
  u_int8_t i = 0;                      /* utility */
  
  SPF_RESULT res = SPF_UNKNOWN;        /* libSPF result code */

  SPF_BOOL use_explain = SPF_FALSE;    /* T / F provide SPF Explanation */
  SPF_BOOL use_trusted = SPF_FALSE;    /* T / F attempt Trusted Forwarder */
  SPF_BOOL use_guess   = SPF_FALSE;    /* T / F attempt Best Guess */
  SPF_BOOL test_mode   = SPF_FALSE;    /* T / F enable test mode */

  char *margv   = NULL;                /* pointer to current argv element */
  char *ip      = NULL;                /* ip address to test connecting from */
  char *address = NULL;                /* email address to test sending from */
  char *helo    = NULL;                /* helo hostname to test sending from */
  char *tmp     = NULL;                /* utility pointer */
  char *buf     = NULL;                /* buffer to store generated SPF header */
   
  peer_info_t *pinfo = NULL;           /* libSPF peer_info structure */

  if (argc <= 1)
  {
    SPF_usage();

    return(SPF_FALSE);
  }

  for (i = 1; i < argc; i++)
  {
    tmp = argv[i];

    if (*tmp == '-')
    {
      margv = (tmp + 3);
      
      switch (*(tmp + 1))
      {
        /* best guess */
        case 'b' :
        {
          use_guess = atoi(margv);

          break;
        } /* 'b' */

        /* debug */
        case 'd' :
        {
          confg.level = atoi(margv);

          break;
        } /* 'd' */

        /* explanation */
        case 'e' :
        {
          use_explain = atoi(margv);

          break;
        } /* 'e' */

        /* RFC2821 HELO */
        case 'h' :
        {
          helo  = strdup(margv);

          break;
        } /* 'h' */

        /* ip address */
        case 'i' :
        {
          ip  = strdup(margv);

          break;
        } /* 'i' */

        /* source email address */
        case 's' :
        {
          address = strdup(margv);

          break;
        } /* 's' */

        /* trusted forwarder */
        case 't' :
        {
          use_trusted = atoi(margv);

          break;
        } /* 't' */

        /* version */
        case 'v' :
        {
          printf("SPF Query Tool v%s - James Couzens <jcouzens@codeshare.ca>\n\n", 
            SPFQTOOL_VERSION);

          return(0);
        } /* 'v' */

        /* test mode */
        case 'z' :
        {
          test_mode = SPF_TRUE;

          break;
        } /* 'z' */

        default:
        {
          break;
        } /* default */
      }
    }
  } /* for */
 
  if (ip == NULL)
  {
    printf("You need to specify an IP Address to test against\n\n");

    SPF_usage();

    free(address);

    return(SPF_FALSE);
  }
  else if (address == NULL)
  {
    printf("You need to specify a from email address\n\n");
    
    SPF_usage();

    free(ip);

    return(SPF_FALSE);
  }
  else if (helo == NULL)
  {
    helo = strdup(HELO_HOST);

    printf("You didn't give me a helo host, using (%s)\n", helo);
  }

  if (confg.level >= 1)
  {
    printf("SPF Query Tool v%s - James Couzens <jcouzens@codeshare.ca>\n", 
      SPFQTOOL_VERSION);
   
    printf("[DEBUG]: Debugging level:    %u\n", confg.level);
    printf("[DEBUG]: RFC2821 Mail From:  %s\n", address);
    printf("[DEBUG]: RFC2821 HELO:       %s\n", helo);
    printf("[DEBUG]: Purported address:  %s\n", ip);

    printf("[DEBUG]: SPF Explanation:    %s\n",
      use_explain ? "Enabled" : "Disabled");

    printf("[DEBUG]: Trusted Forwarder:  %s\n",
      use_trusted ? "Enabled" : "Disabled");

    printf("[DEBUG]: Best Guess:         %s\n",
      use_guess ? "Enabled" : "Disabled");

    printf("\n");
  }
  
  if ((pinfo = SPF_init(helo, ip, NULL, NULL, NULL,
                        use_trusted, use_guess)) != NULL)
  {
    /* perform fake HELO */
    SPF_smtp_helo(pinfo, helo);
    
    /* perform fake MAIL FROM */
    SPF_smtp_from(pinfo, address);
    
    /* assign and perform SPF parse */
    res = pinfo->RES = SPF_policy_main(pinfo);
    
    /* print the results of the query.  The NULL check on the output is
     * to the benefit of SOLARIS users where printf is unable to handle
     * a NULL variable.  Linux users can omit this check. 
     */

    if (test_mode != SPF_TRUE)
    {
      printf("SPF short result:   %s\n",
        pinfo->rs ? pinfo->rs : "NULL");

      printf("SPF verbose result: %s\n",
        pinfo->error ? pinfo->error : "NULL");
    }
    else
    {
      printf("%s\n%s\n%s\n", 
        pinfo->rs      ? pinfo->rs      : "NULL",
        pinfo->error   ? pinfo->error   : "NULL",
        pinfo->explain ? pinfo->explain : "NULL");
    }

    if (use_explain == SPF_TRUE)
    {
      buf = SPF_get_explain(pinfo);

      printf("SPF explanation:    %s\n",
        pinfo->explain ? pinfo->explain : "NULL");

      free(buf);
    }

    /* for the tests we need to be silent :-) */
    if (test_mode != SPF_TRUE)
    {
      if (use_trusted == SPF_TRUE)
      {
        printf("Trusted Forwarder:  Attempted.\n");
      }
   
      if (use_guess == SPF_TRUE)
      {
        printf("Best Guess:         Attempted.\n");
      }

      if ((buf = SPF_build_header(pinfo)) != NULL)
      {
        printf("RFC2822 header:     %s\n", buf);
        free(buf);
      }
    }

    /* close SPF session (free memory associated with parse) */
    SPF_close(pinfo);
  }   
  
  free(ip);
  free(address);
  free(helo);
  
  return(SPF_FALSE); 
}


/* SPF_usage
*
*  Author: James Couzens <jcouzens@6o4.ca>
*
*  Date:   12/25/03
*  Date:   07/28/04 - Renamed to spfqtool
*
*  Desc:
*         Displays usage help information when the binary is called with
*  no arguments.
*
*/
void SPF_usage()
{
  printf("spfqtool usage:\n");
  printf("\n");
  printf("spfqtool [b|d|e|i|s|t|h|v]\n");
  printf("\n");
  printf("-b [0,1]   - Enable Best Guess support (True (0) or False (1))\n");
  printf("-d [x]     - DEBUG where x is a number between 1 and 255\n");
  printf("-e [0,1]   - Enable SPF explanation (True (0) or False (1))\n");
  printf("-h [host]  - HELO hostname to test with\n");
  printf("-i [addr]  - IP Address where the fake connection will come from\n");
  printf("-s [email] - What email address to test with\n");
  printf("-t [0,1]   - Enable Trusted Forwarder support (True (0) or False (1))\n");
  printf("-v         - Display version string\n");
  printf("\n");
  printf("Example: ./spfqtool -i 10.0.0.2 -s jcouzens@6o4.ca -h spftools.net\n");
  printf("\n");
  printf("Minimum required arguments are 'i', and 's'\n");
  printf("\n");

  return;
}

/* end spfqtool.c */