Back to index

opendkim  2.6.6
Defines | Functions | Variables
util.c File Reference
#include "build-config.h"
#include <sys/types.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netinet/in.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <resolv.h>
#include <stdlib.h>
#include "dkim-internal.h"
#include "util.h"
#include "dkim-strl.h"

Go to the source code of this file.

Defines

#define RES_UNC_T   unsigned char *

Functions

void dkim_collapse (u_char *str)
_Bool dkim_hdrlist (u_char *buf, size_t buflen, u_char **hdrlist, _Bool first)
void dkim_lowerhdr (unsigned char *str)
int dkim_hexchar (int c)
int dkim_qp_decode (unsigned char *in, unsigned char *out, int outlen)
int dkim_check_dns_reply (unsigned char *ansbuf, size_t anslen, int xclass, int xtype)
void dkim_min_timeval (struct timeval *t1, struct timeval *t2, struct timeval *t, struct timeval **which)
const char ** dkim_copy_array (char **in)
void dkim_clobber_array (char **in)

Variables

static char util_c_id [] = "@(#)$Id: util.c,v 1.12.10.1 2010/10/27 21:43:08 cm-msk Exp $"

Define Documentation

#define RES_UNC_T   unsigned char *

Definition at line 38 of file util.c.


Function Documentation

int dkim_check_dns_reply ( unsigned char *  ansbuf,
size_t  anslen,
int  xclass,
int  xtype 
)

Definition at line 627 of file util.c.

{
       _Bool trunc = FALSE;
       int qdcount;
       int ancount;
       int n;
       uint16_t type = (uint16_t) -1;
       uint16_t class = (uint16_t) -1;
       uint32_t ttl;
       unsigned char *cp;
       unsigned char *eom;
       HEADER hdr;
       unsigned char name[DKIM_MAXHOSTNAMELEN + 1];

       assert(ansbuf != NULL);

       /* set up pointers */
       memcpy(&hdr, ansbuf, sizeof hdr);
       cp = ansbuf + HFIXEDSZ;
       eom = ansbuf + anslen;

       /* skip over the name at the front of the answer */
       for (qdcount = ntohs((unsigned short) hdr.qdcount);
            qdcount > 0;
            qdcount--)
       {
              /* copy it first */
              (void) dn_expand((unsigned char *) ansbuf, eom, cp,
                               (RES_UNC_T) name, sizeof name);

              if ((n = dn_skipname(cp, eom)) < 0)
                     return 2;

              cp += n;

              /* extract the type and class */
              if (cp + INT16SZ + INT16SZ > eom)
                     return 2;

              GETSHORT(type, cp);
              GETSHORT(class, cp);
       }

       if (type != xtype || class != xclass)
              return 0;

       /* if NXDOMAIN, return DKIM_STAT_NOKEY */
       if (hdr.rcode == NXDOMAIN)
              return 0;

       /* if truncated, we can't do it */
       if (hdr.tc)
              trunc = TRUE;

       /* get the answer count */
       ancount = ntohs((unsigned short) hdr.ancount);
       if (ancount == 0)
              return (trunc ? 2 : 0);

       /*
       **  Extract the data from the first TXT answer.
       */

       while (--ancount >= 0 && cp < eom)
       {
              /* grab the label, even though we know what we asked... */
              if ((n = dn_expand((unsigned char *) ansbuf, eom, cp,
                                 (RES_UNC_T) name, sizeof name)) < 0)
                     return 2;

              /* ...and move past it */
              cp += n;

              /* extract the type and class */
              if (cp + INT16SZ + INT16SZ + INT32SZ > eom)
                     return 2;

              GETSHORT(type, cp);
              GETSHORT(class, cp);
              GETLONG(ttl, cp);

              /* skip CNAME if found; assume it was resolved */
              if (type == T_CNAME)
              {
                     if ((n = dn_expand((u_char *) ansbuf, eom, cp,
                                        (RES_UNC_T) name, sizeof name)) < 0)
                            return 2;

                     cp += n;
                     continue;
              }
              else if (type != xtype)
              {
                     return (trunc ? 1 : 0);
              }

              /* found a record we can use; break */
              break;
       }

       /* if ancount went below 0, there were no good records */
       if (ancount < 0)
              return (trunc ? 1 : 0);

       /* get payload length */
       if (cp + INT16SZ > eom)
              return 2;

       GETSHORT(n, cp);

       /*
       **  XXX -- maybe deal with a partial reply rather than require
       **        it all
       */

       if (cp + n > eom)
              return 2;

       return (trunc ? 1 : 0);
}

Here is the caller graph for this function:

void dkim_clobber_array ( char **  in)

Definition at line 858 of file util.c.

{
       unsigned int n;

       assert(in != NULL);

       for (n = 0; in[n] != NULL; n++)
              free(in[n]);

       free(in);
}

Here is the caller graph for this function:

void dkim_collapse ( u_char *  str)

Definition at line 52 of file util.c.

{
       u_char *q;
       u_char *r;

       assert(str != NULL);

       for (q = str, r = str; *q != '\0'; q++)
       {
              if (!isspace(*q))
              {
                     if (q != r)
                            *r = *q;
                     r++;
              }
       }

       *r = '\0';
}

Here is the caller graph for this function:

const char** dkim_copy_array ( char **  in)

Definition at line 817 of file util.c.

{
       unsigned int c;
       unsigned int n;
       char **out;

       assert(in != NULL);

       for (n = 0; in[n] != NULL; n++)
              continue;

       out = malloc(sizeof(char *) * (n + 1));

       for (c = 0; c < n; c++)
       {
              out[c] = strdup(in[c]);
              if (out[c] == NULL)
              {
                     for (n = 0; n < c; n++)
                            free(out[n]);
                     free(out);
                     return NULL;
              }
       }

       out[c] = NULL;

       return (const char **) out;
}

Here is the caller graph for this function:

_Bool dkim_hdrlist ( u_char *  buf,
size_t  buflen,
u_char **  hdrlist,
_Bool  first 
)

Definition at line 86 of file util.c.

{
       _Bool escape = FALSE;
       int c;
       int len;
       u_char *p;
       u_char *q;
       u_char *end;

       assert(buf != NULL);
       assert(hdrlist != NULL);

       for (c = 0; ; c++)
       {
              if (hdrlist[c] == NULL)
                     break;

              if (!first)
              {
                     len = strlcat((char *) buf, "|", buflen);
                     if (len >= buflen)
                            return FALSE;
              }
              else
              {
                     len = strlen((char *) buf);
              }

              first = FALSE;

              q = &buf[len];
              end = &buf[buflen - 1];

              for (p = hdrlist[c]; *p != '\0'; p++)
              {
                     if (q >= end)
                            return FALSE;

                     if (escape)
                     {
                            *q = *p;
                            q++;
                            escape = FALSE;
                     }

                     switch (*p)
                     {
                       case '*':
                            *q = '.';
                            q++;
                            if (q >= end)
                                   return FALSE;
                            *q = '*';
                            q++;
                            break;

                       case '.':
                            *q = '\\';
                            q++;
                            if (q >= end)
                                   return FALSE;
                            *q = '.';
                            q++;
                            break;

                       case '\\':
                            escape = TRUE;
                            break;

                       default:
                            *q = *p;
                            q++;
                            break;
                     }
              }
       }

       return TRUE;
}

Here is the caller graph for this function:

int dkim_hexchar ( int  c)

Definition at line 205 of file util.c.

{
       switch (c)
       {
         case '0':
         case '1':
         case '2':
         case '3':
         case '4':
         case '5':
         case '6':
         case '7':
         case '8':
         case '9':
              return c - '0';

         case 'A':
         case 'B':
         case 'C':
         case 'D':
         case 'E':
         case 'F':
              return 10 + c - 'A';

         case 'a':
         case 'b':
         case 'c':
         case 'd':
         case 'e':
         case 'f':
              return 10 + c - 'a';

         default:
              assert(0);
              return -1;
       }
}

Here is the caller graph for this function:

void dkim_lowerhdr ( unsigned char *  str)

Definition at line 178 of file util.c.

{
       unsigned char *p;

       assert(str != NULL);

       for (p = str; *p != '\0'; p++)
       {
              if (*p == ':')
                     return;

              if (isascii(*p) && isupper(*p))
                     *p = tolower(*p);
       }
}

Here is the caller graph for this function:

void dkim_min_timeval ( struct timeval *  t1,
struct timeval *  t2,
struct timeval *  t,
struct timeval **  which 
)

Definition at line 764 of file util.c.

{
       struct timeval *next;
       struct timeval now;

       assert(t1 != NULL);
       assert(t != NULL);

       if (t2 == NULL ||
           t2->tv_sec > t1->tv_sec ||
           (t2->tv_sec == t1->tv_sec && t2->tv_usec > t1->tv_usec))
              next = t1;
       else
              next = t2;

       (void) gettimeofday(&now, NULL);

       if (next->tv_sec < now.tv_sec ||
           (next->tv_sec == now.tv_sec && next->tv_usec < now.tv_usec))
       {
              t->tv_sec = 0;
              t->tv_usec = 0;
       }
       else
       {
              t->tv_sec = next->tv_sec - now.tv_sec;
              if (next->tv_usec < now.tv_usec)
              {
                     t->tv_sec--;
                     t->tv_usec = next->tv_usec - now.tv_usec + 1000000;
              }
              else
              {
                     t->tv_usec = next->tv_usec - now.tv_usec;
              }
       }

       if (which != NULL)
              *which = next;
}

Here is the caller graph for this function:

int dkim_qp_decode ( unsigned char *  in,
unsigned char *  out,
int  outlen 
)

Definition at line 262 of file util.c.

{
       unsigned char next1;
       unsigned char next2 = 0;
       int xl;
       int decode = 0;
       unsigned char const *p;
       unsigned char *q;
       unsigned char *pos;
       unsigned char const *start;
       unsigned char const *stop;
       unsigned char *end;
       char const *hexdigits = "0123456789ABCDEF";

       assert(in != NULL);
       assert(out != NULL);

       start = NULL;
       stop = NULL;

       end = out + outlen;

       for (p = in, q = out; *p != '\0'; p++)
       {
              switch (*p)
              {
                case '=':
                     next1 = *(p + 1);
                     if (next1 != '\0')
                            next2 = *(p + 2);

                     /* = at EOL */
                     if (next1 == '\n' ||
                         (next1 == '\r' && next2 == '\n'))
                     {
                            stop = p;
                            if (start != NULL)
                            {
                                   unsigned char const *x;

                                   for (x = start; x <= stop; x++)
                                   {
                                          decode++;

                                          if (q <= end)
                                          {
                                                 *q = *x;
                                                 q++;
                                          }
                                   }
                            }
                            start = NULL;
                            stop = NULL;

                            p++;
                            if (next2 == '\n')
                                   p++;
                            break;
                     }

                     /* = elsewhere */
                     pos = (unsigned char *) strchr(hexdigits, next1);
                     if (pos == NULL)
                            return -1;
                     xl = (pos - (unsigned char *) hexdigits) * 16;

                     pos = (unsigned char *) strchr(hexdigits, next2);
                     if (pos == NULL)
                            return -1;
                     xl += (pos - (unsigned char *) hexdigits);

                     stop = p;
                     if (start != NULL)
                     {
                            unsigned char const *x;

                            for (x = start; x < stop; x++)
                            {
                                   decode++;

                                   if (q <= end)
                                   {
                                          *q = *x;
                                          q++;
                                   }
                            }
                     }
                     start = NULL;
                     stop = NULL;

                     if (q <= end)
                     {
                            *q = xl;
                            q++;
                     }

                     decode++;

                     p += 2;

                     break;

                case ' ':
                case '\t':
                     if (start == NULL)
                            start = p;
                     break;

                case '\r':
                     break;

                case '\n':
                     if (stop == NULL)
                            stop = p;
                     if (start != NULL)
                     {
                            unsigned char const *x;

                            for (x = start; x <= stop; x++)
                            {
                                   decode++;

                                   if (q <= end)
                                   {
                                          *q = *x;
                                          q++;
                                   }
                            }
                     }

                     if (p > in && *(p - 1) != '\r')
                     {
                            decode++;

                            if (q <= end)
                            {
                                   *q = '\n';
                                   q++;
                            }
                     }
                     else
                     {
                            decode += 2;
                            if (q <= end)
                            {
                                   *q = '\r';
                                   q++;
                            }
                            if (q <= end)
                            {
                                   *q = '\n';
                                   q++;
                            }
                     }

                     start = NULL;
                     stop = NULL;
                     break;

                default:
                     if (start == NULL)
                            start = p;
                     stop = p;
                     break;
              }
       }

       if (start != NULL)
       {
              unsigned char const *x;

              for (x = start; x < p; x++)
              {
                     decode++;

                     if (q <= end)
                     {
                            *q = *x;
                            q++;
                     }
              }
       }

       return decode;
}

Here is the caller graph for this function:


Variable Documentation

char util_c_id[] = "@(#)$Id: util.c,v 1.12.10.1 2010/10/27 21:43:08 cm-msk Exp $" [static]

Definition at line 9 of file util.c.