"Fossies" - the Fresh Open Source Software Archive

Member "libspf2-1.2.10/src/libspf2/spf_id2str.c" (28 Jan 2012, 9935 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_id2str.c" see the Fossies "Dox" file reference documentation.

    1 /* 
    2  * This program is free software; you can redistribute it and/or modify
    3  * it under the terms of either:
    4  * 
    5  *   a) The GNU Lesser General Public License as published by the Free
    6  *    Software Foundation; either version 2.1, or (at your option) any
    7  *    later version, 
    8  * 
    9  *   OR
   10  * 
   11  *   b) The two-clause BSD license.
   12  *
   13  * These licenses can be found with the distribution in the file LICENSES
   14  */
   15 
   16 #include "spf_sys_config.h"
   17 
   18 
   19 
   20 #ifdef STDC_HEADERS
   21 # include <stdio.h>     /* stdin / stdout */
   22 # include <stdlib.h>       /* malloc / free */
   23 # include <ctype.h>     /* isupper / tolower */
   24 #endif
   25 
   26 #ifdef HAVE_INTTYPES_H
   27 #include <inttypes.h>
   28 #endif
   29 
   30 #ifdef HAVE_STRING_H
   31 # include <string.h>       /* strstr / strdup */
   32 #else
   33 # ifdef HAVE_STRINGS_H
   34 #  include <strings.h>     /* strstr / strdup */
   35 # endif
   36 #endif
   37 
   38 
   39 #include "spf.h"
   40 #include "spf_internal.h"
   41 
   42 
   43 static SPF_errcode_t
   44 SPF_record_stringify_data(SPF_data_t *data, SPF_data_t *data_end,
   45                         char **p_p, char *p_end,
   46                         int is_mod, int cidr_ok, int debug )
   47 {
   48     char        *p = *p_p;
   49 
   50     size_t      len;
   51 
   52     SPF_data_t      *cidr_data;
   53 
   54     if (debug)
   55         SPF_debugf(" string data: Building");
   56 
   57     if (p_end - p <= 0)
   58         return SPF_E_INTERNAL_ERROR;
   59 
   60     cidr_data = NULL;
   61     if ( data < data_end && data->dc.parm_type == PARM_CIDR )
   62     {
   63         if (debug)
   64             SPF_debugf(" string data: Found a CIDR at %p", data);
   65         if ( !cidr_ok )
   66             return SPF_E_INTERNAL_ERROR;
   67 
   68         cidr_data = data;
   69         data = SPF_data_next( data );
   70     }
   71         
   72 
   73     for( ; data < data_end; data = SPF_data_next( data ) )
   74     {
   75         if (debug)
   76             SPF_debugf(" string data: Handling data type %d at %p",
   77                             data->ds.parm_type, data);
   78         if ( data->ds.parm_type == PARM_STRING )
   79         {
   80             char *s = SPF_data_str( data );
   81             char *s_end = s + data->ds.len;
   82             if (debug)
   83                 SPF_debugf(" string data: String is [%d] '%*.*s'",
   84                         data->ds.len, data->ds.len, data->ds.len, s);
   85 
   86             if (p_end - (p + data->ds.len) <= 0)
   87                 return SPF_E_INTERNAL_ERROR;
   88 
   89             while (s < s_end) {
   90                 if (*s == ' ') {
   91                     *p++ = '%';
   92                     *p++ = '_';
   93                     s++;
   94                 }
   95                 else if (*s == '%') {
   96                     *p++ = '%';
   97                     s++;
   98                     if (s[0] == '2' && s[1] == '0') {
   99                         *p++ = '-';
  100                         s += 2;
  101                     }
  102                     else {
  103                         *p++ = '%';
  104                         // *p++ = '%';
  105                     }
  106                 }
  107                 else {
  108                     *p++ = *s++;
  109                 }
  110             }
  111 
  112             if (p_end - p <= 0)
  113                 return SPF_E_INTERNAL_ERROR;
  114         }
  115         else if (data->dc.parm_type == PARM_CIDR) {
  116             /* Two CIDRs in a row is invalid. */
  117             return SPF_E_INVALID_CIDR;
  118         }
  119         else {
  120             len = snprintf( p, p_end - p, "%%{" );
  121             p += len;
  122             if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
  123 
  124 
  125             if ( p_end - p <= 1 ) return SPF_E_INTERNAL_ERROR;
  126             switch( data->dv.parm_type )
  127             {
  128             case PARM_LP_FROM:              /* local-part of envelope-sender */
  129                 *p = 'l';
  130                 break;
  131                     
  132             case PARM_ENV_FROM:             /* envelope-sender              */
  133                 *p = 's';
  134                 break;
  135                     
  136             case PARM_DP_FROM:              /* envelope-domain              */
  137                 *p = 'o';
  138                 break;
  139 
  140             case PARM_CUR_DOM:              /* current-domain               */
  141                 *p = 'd';
  142                 break;
  143 
  144             case PARM_CLIENT_IP:        /* SMTP client IP               */
  145                 *p = 'i';
  146                 break;
  147 
  148             case PARM_CLIENT_IP_P:      /* SMTP client IP (pretty)      */
  149                 *p = 'c';
  150                 break;
  151 
  152             case PARM_TIME:             /* time in UTC epoch secs       */
  153                 if ( !is_mod )
  154                     return SPF_E_INVALID_VAR;
  155                 *p = 't';
  156                 break;
  157 
  158             case PARM_CLIENT_DOM:       /* SMTP client domain name      */
  159                 *p = 'p';
  160                 break;
  161 
  162             case PARM_CLIENT_VER:       /* IP ver str - in-addr/ip6     */
  163                 *p = 'v';
  164                 break;
  165 
  166             case PARM_HELO_DOM:             /* HELO/EHLO domain             */
  167                 *p = 'h';
  168                 break;
  169 
  170             case PARM_REC_DOM:              /* receiving domain             */
  171                 *p = 'r';
  172                 break;
  173 
  174             default:
  175                 return SPF_E_INVALID_VAR;
  176                 break;
  177             }
  178             if ( data->dv.url_encode )
  179                 *p = toupper( *p );
  180             p++;
  181             if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
  182                 
  183 
  184             if ( data->dv.num_rhs )
  185             {
  186                 len = snprintf( p, p_end - p, "%d", data->dv.num_rhs );
  187                 p += len;
  188                 if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
  189             }
  190             
  191                 
  192             if ( p_end - p <= 8 ) return SPF_E_INTERNAL_ERROR;
  193             if ( data->dv.rev )
  194                 *p++ = 'r';
  195 
  196             if ( data->dv.delim_dot
  197                  && ( data->dv.delim_dash
  198                       || data->dv.delim_plus
  199                       || data->dv.delim_equal
  200                       || data->dv.delim_bar
  201                       || data->dv.delim_under
  202                      )
  203                 )
  204                 *p++ = '.';
  205             if ( data->dv.delim_dash )
  206                 *p++ = '-';
  207             if ( data->dv.delim_plus )
  208                 *p++ = '+';
  209             if ( data->dv.delim_equal )
  210                 *p++ = '=';
  211             if ( data->dv.delim_bar )
  212                 *p++ = '|';
  213             if ( data->dv.delim_under )
  214                 *p++ = '_';
  215 
  216             *p++ = '}';
  217             if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
  218         }
  219     }
  220 
  221         
  222     if ( cidr_data )
  223     {
  224         if ( cidr_data->dc.ipv4 )
  225         {
  226             len = snprintf( p, p_end - p, "/%d", cidr_data->dc.ipv4 );
  227             p += len;
  228             if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
  229         }
  230             
  231         if ( cidr_data->dc.ipv6 )
  232         {
  233             len = snprintf( p, p_end - p, "//%d", cidr_data->dc.ipv6 );
  234             p += len;
  235             if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
  236         }
  237     }
  238 
  239     *p_p = p;
  240     return SPF_E_SUCCESS;
  241 }
  242 
  243 
  244 SPF_errcode_t
  245 SPF_record_stringify( SPF_record_t *spf_record, char **bufp, size_t *buflenp)
  246 {
  247     int             i;
  248     SPF_mech_t      *mech;
  249     SPF_mod_t       *mod;
  250 
  251     SPF_data_t      *data, *data_end;
  252 
  253     size_t      len;
  254     const char      *p_err;
  255     char        *p, *p_end;
  256     
  257     char        ip4_buf[ INET_ADDRSTRLEN ];
  258     char        ip6_buf[ INET6_ADDRSTRLEN ];
  259 
  260     int             cidr_ok;
  261     SPF_errcode_t   err;
  262     
  263 #define debug spf_record->spf_server->debug
  264 
  265     SPF_ASSERT_NOTNULL(spf_record);
  266 
  267     /*
  268      * make sure the return buffer is big enough
  269      *
  270      * The worse case for the version string:
  271      *   "v=spf1 " = 6                  = 4
  272      * The worst cases for mechanisms
  273      *   "ip4:111.222.333.444/31 " = 23   < 6 * 3.9
  274      *   "ip6:<full-ipv6-spec>/126 " = 49 < 18 * 2.8
  275      *   "-include:x " = 11            = 5 * 2.2
  276      *   "-all " = 5                          = 2 * 2.5
  277      * 
  278      * The worst case for modifiers:
  279      *   "a=%{i15r.-+=|_} " = 16          = 5 * 3.2
  280      */
  281     
  282     len = sizeof( SPF_VER_STR )
  283         + spf_record->mech_len * 4 + spf_record->mod_len * 4 /* data */
  284         + sizeof( "\0" );
  285     
  286     err = SPF_recalloc(bufp, buflenp, len);
  287     if (err != SPF_E_SUCCESS)
  288         return err;
  289 
  290     p = *bufp;
  291     p_end = *bufp + *buflenp;
  292 
  293     if (debug)
  294         SPF_debugf("stringify: Buffer length is %lu\n", (unsigned long)*buflenp);
  295 
  296 
  297     /*
  298      * generate SPF version string
  299      */
  300     len = snprintf(p, p_end - p, "v=spf%d", spf_record->version);
  301     p += len;
  302     if (p_end - p <= 0)
  303         return SPF_E_INTERNAL_ERROR;
  304         
  305 
  306     /*
  307      * generate mechanisms
  308      */
  309     
  310     mech = spf_record->mech_first;
  311     for (i = 0; i < spf_record->num_mech; i++) {
  312         if (debug)
  313             SPF_debugf("stringify: Handling mechanism %d/%d at %p",
  314                             i, spf_record->num_mech, mech);
  315         if ( p_end - p <= 1 ) return SPF_E_INTERNAL_ERROR;
  316         *p++ = ' ';
  317         
  318 
  319         if ( p_end - p <= 1 ) return SPF_E_INTERNAL_ERROR;
  320         switch( mech->prefix_type )
  321         {
  322         case PREFIX_PASS:
  323             /* *p++ = '+'; */
  324             break;
  325             
  326         case PREFIX_FAIL:
  327             *p++ = '-';
  328             break;
  329             
  330         case PREFIX_SOFTFAIL:
  331             *p++ = '~';
  332             break;
  333             
  334         case PREFIX_NEUTRAL:
  335             *p++ = '?';
  336             break;
  337             
  338         case PREFIX_UNKNOWN:
  339             return SPF_E_RESULT_UNKNOWN;
  340             break;
  341 
  342         default:
  343             return SPF_E_INVALID_PREFIX;
  344             break;
  345         }
  346 
  347         if (debug)
  348             SPF_debugf("Mechanism type is %d", mech->mech_type);
  349 
  350         switch( mech->mech_type )
  351         {
  352         case MECH_A:
  353             len = snprintf( p, p_end - p, "a" );
  354             break;
  355             
  356         case MECH_MX:
  357             len = snprintf( p, p_end - p, "mx" );
  358             break;
  359             
  360         case MECH_PTR:
  361             len = snprintf( p, p_end - p, "ptr" );
  362             break;
  363             
  364         case MECH_INCLUDE:
  365             len = snprintf( p, p_end - p, "include" );
  366             break;
  367             
  368         case MECH_IP4:
  369             p_err = inet_ntop( AF_INET, SPF_mech_ip4_data( mech ),
  370                              ip4_buf, sizeof( ip4_buf ) );
  371             if ( p_err == NULL )
  372                 return SPF_E_INTERNAL_ERROR;
  373             if ( mech->mech_len )
  374                 len = snprintf( p, p_end - p, "ip4:%s/%d",
  375                                     ip4_buf, mech->mech_len );
  376             else
  377                 len = snprintf( p, p_end - p, "ip4:%s", ip4_buf );
  378             break;
  379             
  380         case MECH_IP6:
  381             p_err = inet_ntop( AF_INET6, SPF_mech_ip6_data( mech ),
  382                              ip6_buf, sizeof( ip6_buf ) );
  383             if ( p_err == NULL )
  384                 return SPF_E_INTERNAL_ERROR;
  385             if ( mech->mech_len )
  386                 len = snprintf( p, p_end - p, "ip6:%s/%d",
  387                                     ip6_buf, mech->mech_len );
  388             else
  389                 len = snprintf( p, p_end - p, "ip6:%s", ip6_buf );
  390             break;
  391             
  392         case MECH_EXISTS:
  393             len = snprintf( p, p_end - p, "exists" );
  394             break;
  395             
  396         case MECH_ALL:
  397             len = snprintf( p, p_end - p, "all" );
  398             break;
  399             
  400         case MECH_REDIRECT:
  401             len = snprintf( p, p_end - p, "redirect" );
  402             break;
  403 
  404         default:
  405             return SPF_E_UNKNOWN_MECH;
  406             break;
  407         }
  408         p += len;
  409         if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
  410 
  411         if (debug)
  412             SPF_debugf("stringify: Buffer so far is %s", p);
  413 
  414         if ( mech->mech_type != MECH_IP4  &&  mech->mech_type != MECH_IP6 )
  415         {
  416             data = SPF_mech_data( mech );
  417             data_end = SPF_mech_end_data( mech );
  418         
  419             if (SPF_mech_data_len(mech) > 0
  420                  /* We have an immediate string literal */
  421                  && (data->dc.parm_type != PARM_CIDR
  422                      /* Some data follows the CIDR */
  423                      || SPF_data_next( data ) < data_end)
  424                 ) {
  425                 *p++ = ':';
  426             }
  427 
  428             cidr_ok = mech->mech_type == MECH_A || mech->mech_type == MECH_MX;
  429             err = SPF_record_stringify_data(
  430                             data, data_end,
  431                             &p, p_end,
  432                             FALSE, cidr_ok, debug );
  433 
  434             if ( err != SPF_E_SUCCESS )
  435                 return err;
  436         }
  437         
  438         mech = SPF_mech_next( mech );
  439     }
  440 
  441 
  442     /*
  443      * generate modifiers
  444      */
  445 
  446     mod = spf_record->mod_first;
  447     for( i = 0; i < spf_record->num_mod; i++ )
  448     {
  449         if (debug)
  450             SPF_debugf("stringify: Handling modifier %d/%d at %p",
  451                             i, spf_record->num_mod, mod);
  452         if ( p_end - p <= 1 ) return SPF_E_INTERNAL_ERROR;
  453         *p++ = ' ';
  454         
  455         len = snprintf( p, p_end - p, "%.*s=",
  456                             mod->name_len, SPF_mod_name( mod )  );
  457         p += len;
  458         if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
  459             
  460         data = SPF_mod_data( mod );
  461         data_end = SPF_mod_end_data( mod );
  462         
  463         err = SPF_record_stringify_data(
  464                         data, data_end,
  465                         &p, p_end,
  466                         TRUE, TRUE, debug );
  467 
  468         if ( err != SPF_E_SUCCESS )
  469             return err;
  470         
  471         
  472         mod = SPF_mod_next( mod );
  473     }
  474 
  475 
  476 
  477     *p++ = '\0';
  478 
  479     return SPF_E_SUCCESS;
  480 }