Back to index

opendkim  2.6.6
Classes | Defines | Functions | Variables
opendkim-ar.c File Reference
#include "build-config.h"
#include <sys/types.h>
#include <sys/param.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include <dkim-strl.h>
#include "opendkim-ar.h"

Go to the source code of this file.

Classes

struct  lookup

Defines

#define ARES_ENDOF(x)   ((x) + sizeof(x) - 1)
#define ARES_STRORNULL(x)   ((x) == NULL ? "(null)" : (x))
#define ARES_TOKENS   ";=."
#define ARES_TOKENS2   "=."
#define ARES_MAXTOKENS   512

Functions

static int ares_tokenize (u_char *input, u_char *outbuf, size_t outbuflen, u_char **tokens, int ntokens)
static void ares_trimspaces (u_char *str)
static int ares_convert (struct lookup *table, char *str)
int ares_parse (u_char *hdr, struct authres *ar)

Variables

static char opendkim_ar_c_id [] = "@(#)$Id: opendkim-ar.c,v 1.5.58.1 2010/10/27 21:43:09 cm-msk Exp $"

Class Documentation

struct lookup

Definition at line 44 of file opendkim-ar.c.

Class Members
int code
char * str

Define Documentation

#define ARES_ENDOF (   x)    ((x) + sizeof(x) - 1)

Definition at line 36 of file opendkim-ar.c.

#define ARES_MAXTOKENS   512

Definition at line 41 of file opendkim-ar.c.

#define ARES_STRORNULL (   x)    ((x) == NULL ? "(null)" : (x))

Definition at line 37 of file opendkim-ar.c.

#define ARES_TOKENS   ";=."

Definition at line 38 of file opendkim-ar.c.

#define ARES_TOKENS2   "=."

Definition at line 39 of file opendkim-ar.c.


Function Documentation

static int ares_convert ( struct lookup table,
char *  str 
) [static]

Definition at line 325 of file opendkim-ar.c.

{
       int c;

       assert(table != NULL);
       assert(str != NULL);

       for (c = 0; ; c++)
       {
              if (table[c].str == NULL ||
                  strcmp(table[c].str, str) == 0)
                     return table[c].code;
       }

       /* NOTREACHED */
}

Here is the caller graph for this function:

int ares_parse ( u_char *  hdr,
struct authres ar 
)

Definition at line 385 of file opendkim-ar.c.

{
       _Bool quoted;
       int n;
       int ntoks;
       int c;
       int r = 0;
       int state;
       int prevstate;
       u_char tmp[DKIM_MAXHEADER + 2];
       u_char *tokens[ARES_MAXTOKENS];

       assert(hdr != NULL);
       assert(ar != NULL);

       memset(ar, '\0', sizeof *ar);
       memset(tmp, '\0', sizeof tmp);

       ntoks = ares_tokenize(hdr, tmp, sizeof tmp, tokens, ARES_MAXTOKENS);
       if (ntoks == -1 || ntoks > ARES_MAXTOKENS)
              return -1;

       prevstate = -1;
       state = 0;
       n = 0;

       quoted = FALSE;

       for (c = 0; c < ntoks; c++)
       {
              if (tokens[c][0] == '(')           /* comment */
                     continue;

              switch (state)
              {
                case 0:                          /* authserv-id */
                     if (!isascii(tokens[c][0]) ||
                         !isalnum(tokens[c][0]))
                            return -1;

                     strlcat((char *) ar->ares_host, (char *) tokens[c],
                             sizeof ar->ares_host);

                     prevstate = state;
                     state = 1;

                     break;

                case 1:                          /* [version] */
                     if (tokens[c][0] == '.' &&
                         tokens[c][1] == '\0' && prevstate == 0)
                     {
                            strlcat((char *) ar->ares_host,
                                    (char *) tokens[c],
                                    sizeof ar->ares_host);

                            prevstate = state;
                            state = 0;

                            break;
                     }

                     if (tokens[c][0] == ';')
                     {
                            prevstate = state;
                            state = 3;
                     }
                     else if (isascii(tokens[c][0]) &&
                              isdigit(tokens[c][0]))
                     {
                            strlcpy((char *) ar->ares_version,
                                    (char *) tokens[c],
                                    sizeof ar->ares_version);

                            prevstate = state;
                            state = 2;
                     }
                     else
                     {
                            return -1;
                     }

                     break;

                case 2:                          /* ; */
                     if (tokens[c][0] != ';' ||
                         tokens[c][1] != '\0')
                            return -1;

                     prevstate = state;
                     state = 3;

                     break;

                case 3:                          /* method */
                     n++;
                     r = 0;

                     ar->ares_result[n - 1].result_method = ares_convert(methods,
                                                                         (char *) tokens[c]);
                     prevstate = state;
                     state = 4;

                     break;

                case 4:                          /* = */
                     if (tokens[c][0] != '=' ||
                         tokens[c][1] != '\0')
                            return -1;

                     prevstate = state;
                     state = 5;

                     break;

                case 5:                          /* result */
                     ar->ares_result[n - 1].result_result = ares_convert(aresults,
                                                                         (char *) tokens[c]);
                     prevstate = state;
                     state = 6;

                     break;

                case 7:                          /* = (reason) */
                     if (tokens[c][0] != '=' ||
                         tokens[c][1] != '\0')
                            return -1;

                     prevstate = state;
                     state = 8;

                     break;

                case 8:
                     strlcpy((char *) ar->ares_result[n - 1].result_reason,
                             (char *) tokens[c],
                             sizeof ar->ares_result[n - 1].result_reason);

                     prevstate = state;
                     state = 9;

                     break;

                case 6:                          /* reason/propspec */
                     if (tokens[c][0] == ';' &&  /* neither */
                         tokens[c][1] == '\0')
                     {
                            prevstate = state;
                            state = 3;

                            continue;
                     }

                     if (strcasecmp((char *) tokens[c], "reason") == 0)
                     {                           /* reason */
                            prevstate = state;
                            state = 7;

                            continue;
                     }
                     else
                     {
                            prevstate = state;
                            state = 9;
                     }

                     /* FALLTHROUGH */

                case 9:                          /* ptype */
                     if (prevstate == 13 &&
                         strchr(ARES_TOKENS2, tokens[c][0]) != NULL &&
                         tokens[c][1] == '\0')
                     {
                            r--;

                            strlcat((char *) ar->ares_result[n - 1].result_value[r],
                                    (char *) tokens[c],
                                    sizeof ar->ares_result[n - 1].result_value[r]);

                            prevstate = state;
                            state = 13;

                            continue;
                     }

                     if (tokens[c][0] == ';' &&
                         tokens[c][1] == '\0')
                     {
                            prevstate = state;
                            state = 3;

                            continue;
                     }
                     else
                     {
                            ares_ptype_t x;

                            x = ares_convert(ptypes, (char *) tokens[c]);
                            if (x == ARES_PTYPE_UNKNOWN)
                                   return -1;

                            ar->ares_result[n - 1].result_ptype[r] = x;

                            prevstate = state;
                            state = 10;
                     }

                     break;

                case 10:                         /* . */
                     if (tokens[c][0] != '.' ||
                         tokens[c][1] != '\0')
                            return -1;

                     prevstate = state;
                     state = 11;

                     break;

                case 11:                         /* property */
                     strlcpy((char *) ar->ares_result[n - 1].result_property[r],
                             (char *) tokens[c],
                             sizeof ar->ares_result[n - 1].result_property[r]);

                     prevstate = state;
                     state = 12;

                     break;

                case 12:                         /* = */
                     if (tokens[c][0] != '=' ||
                         tokens[c][1] != '\0')
                            return -1;

                     prevstate = state;
                     state = 13;

                     break;

                case 13:                         /* value */
                     strlcat((char *) ar->ares_result[n - 1].result_value[r],
                             (char *) tokens[c],
                             sizeof ar->ares_result[n - 1].result_value[r]);
                     r++;
                     ar->ares_result[n - 1].result_props = r;

                     prevstate = state;
                     state = 9;

                     break;
              }
       }

       /* error out on non-terminal states */
       if (state == 4 || state == 7 || state == 10 ||
           state == 11 || state == 12)
              return -1;

       ar->ares_count = n;

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ares_tokenize ( u_char *  input,
u_char *  outbuf,
size_t  outbuflen,
u_char **  tokens,
int  ntokens 
) [static]

Definition at line 107 of file opendkim-ar.c.

{
       _Bool quoted = FALSE;
       _Bool escaped = FALSE;
       _Bool intok = FALSE;
       int n = 0;
       int parens = 0;
       u_char *p;
       u_char *q;
       u_char *end;

       assert(input != NULL);
       assert(outbuf != NULL);
       assert(outbuflen > 0);
       assert(tokens != NULL);
       assert(ntokens > 0);

       q = outbuf;
       end = outbuf + outbuflen - 1;

       for (p = input; *p != '\0' && q <= end; p++)
       {
              if (escaped)                       /* escape */
              {
                     if (!intok)
                     {
                            if (n < ntokens)
                                   tokens[n] = q;
                            intok = TRUE;
                     }

                     *q = *p;
                     q++;
                     escaped = FALSE;
              }
              else if (*p == '\\')               /* escape */
              {
                     escaped = TRUE;
              }
              else if (*p == '"' && parens == 0) /* quoting */
              {
                     quoted = !quoted;

                     if (!intok)
                     {
                            if (n < ntokens)
                                   tokens[n] = q;
                            intok = TRUE;
                     }
              }
              else if (*p == '(' && !quoted)            /* "(" (comment) */
              {
                     parens++;

                     if (!intok)
                     {
                            if (n < ntokens)
                                   tokens[n] = q;
                            intok = TRUE;
                     }

                     *q = *p;
                     q++;

              }
              else if (*p == ')' && !quoted)            /* ")" (comment) */
              {
                     if (parens > 0)
                     {
                            parens--;

                            if (parens == 0)
                            {
                                   intok = FALSE;
                                   n++;

                                   *q = ')';
                                   q++;
                                   if (q <= end)
                                   {
                                          *q = '\0';
                                          q++;
                                   }
                            }
                     }
              }
              else if (quoted)                   /* quoted character */
              {
                     *q = *p;
                     q++;
              }
              else if (isascii(*p) && isspace(*p))      /* whitespace */
              {
                     if (quoted || parens > 0)
                     {
                            if (intok)
                            {
                                   *q = *p;
                                   q++;
                            }
                     }
                     else if (intok)
                     {
                            intok = FALSE;
                            *q = '\0';
                            q++;
                            n++;
                     }
              }
              else if (strchr(ARES_TOKENS, *p) != NULL) /* delimiter */
              {
                     if (parens > 0)
                     {
                            *q = *p;
                            q++;
                            continue;
                     }

                     if (intok)
                     {
                            intok = FALSE;
                            *q = '\0';
                            q++;
                            n++;
                     }

                     if (q <= end)
                     {
                            *q = *p;
                            if (n < ntokens)
                            {
                                   tokens[n] = q;
                                   n++;
                            }
                            q++;
                     }

                     if (q <= end)
                     {
                            *q = '\0';
                            q++;
                     }
              }
              else                               /* other */
              {
                     if (!intok)
                     {
                            if (n < ntokens)
                                   tokens[n] = q;
                            intok = TRUE;
                     }

                     *q = *p;
                     q++;
              }
       }

       if (q >= end)
              return -1;

       if (intok)
       {
              *q = '\0';
              n++;
       }

       return n;
}

Here is the caller graph for this function:

static void ares_trimspaces ( u_char *  str) [static]

Definition at line 288 of file opendkim-ar.c.

{
       u_char *p;
       u_char *last;

       assert(str != NULL);

       last = NULL;

       for (p = str; *p != '\0'; p++)
       {
              if (isascii(*p) && isspace(*p) && last == NULL)
              {
                     last = p;
                     continue;
              }

              if (!isascii(*p) || !isspace(*p))
                     last = NULL;
       }

       if (last != NULL)
              *last = '\0';
}

Variable Documentation

char opendkim_ar_c_id[] = "@(#)$Id: opendkim-ar.c,v 1.5.58.1 2010/10/27 21:43:09 cm-msk Exp $" [static]

Definition at line 11 of file opendkim-ar.c.