Exemplo n.º 1
0
static pdkim_pubkey *
pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record)
{
pdkim_pubkey *pub;
char *p;
pdkim_str *cur_tag = NULL;
pdkim_str *cur_val = NULL;
int where = PDKIM_HDR_LIMBO;

if (!(pub = malloc(sizeof(pdkim_pubkey)))) return NULL;
memset(pub, 0, sizeof(pdkim_pubkey));

for (p = raw_record; ; p++)
  {
  char c = *p;

  /* Ignore FWS */
  if (c == '\r' || c == '\n')
    goto NEXT_CHAR;

  if (where == PDKIM_HDR_LIMBO)
    {
    /* In limbo, just wait for a tag-char to appear */
    if (!(c >= 'a' && c <= 'z'))
      goto NEXT_CHAR;

    where = PDKIM_HDR_TAG;
    }

  if (where == PDKIM_HDR_TAG)
    {
    if (!cur_tag)
      cur_tag = pdkim_strnew(NULL);

    if (c >= 'a' && c <= 'z')
      pdkim_strncat(cur_tag, p, 1);

    if (c == '=')
      {
      where = PDKIM_HDR_VALUE;
      goto NEXT_CHAR;
      }
    }

  if (where == PDKIM_HDR_VALUE)
    {
    if (!cur_val)
      cur_val = pdkim_strnew(NULL);

    if (c == '\r' || c == '\n')
      goto NEXT_CHAR;

    if (c == ';' || c == '\0')
      {
      if (cur_tag->len > 0)
        {
	pdkim_strtrim(cur_val);
	DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);

	switch (cur_tag->str[0])
	  {
	  case 'v':
	    /* This tag isn't evaluated because:
	       - We only support version DKIM1.
	       - Which is the default for this value (set below)
	       - Other versions are currently not specified.      */
	    break;
	  case 'h':
	    pub->hashes = strdup(cur_val->str); break;
	  case 'g':
	    pub->granularity = strdup(cur_val->str); break;
	  case 'n':
	    pub->notes = pdkim_decode_qp(cur_val->str); break;
	  case 'p':
	    pdkim_decode_base64(US cur_val->str, &pub->key);
            break;
	  case 'k':
	    pub->hashes = strdup(cur_val->str); break;
	  case 's':
	    pub->srvtype = strdup(cur_val->str); break;
	  case 't':
	    if (strchr(cur_val->str, 'y') != NULL) pub->testing = 1;
	    if (strchr(cur_val->str, 's') != NULL) pub->no_subdomaining = 1;
	    break;
	  default:
	    DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
	    break;
	  }
	}
      pdkim_strclear(cur_tag);
      pdkim_strclear(cur_val);
      where = PDKIM_HDR_LIMBO;
      }
    else
      pdkim_strncat(cur_val, p, 1);
    }

NEXT_CHAR:
  if (c == '\0') break;
  }

/* Set fallback defaults */
if (!pub->version    ) pub->version     = strdup(PDKIM_PUB_RECORD_VERSION);
if (!pub->granularity) pub->granularity = strdup("*");
if (!pub->keytype    ) pub->keytype     = strdup("rsa");
if (!pub->srvtype    ) pub->srvtype     = strdup("*");

/* p= is required */
if (pub->key.data)
  return pub;

pdkim_free_pubkey(pub);
return NULL;
}
Exemplo n.º 2
0
Arquivo: pdkim.c Projeto: ytrezq/exim
static pdkim_pubkey *
pdkim_parse_pubkey_record(pdkim_ctx *ctx, const uschar *raw_record)
{
pdkim_pubkey *pub;
const uschar *p;
uschar * cur_tag = NULL; int ts = 0, tl = 0;
uschar * cur_val = NULL; int vs = 0, vl = 0;
int where = PDKIM_HDR_LIMBO;

pub = store_get(sizeof(pdkim_pubkey));
memset(pub, 0, sizeof(pdkim_pubkey));

for (p = raw_record; ; p++)
  {
  char c = *p;

  /* Ignore FWS */
  if (c == '\r' || c == '\n')
    goto NEXT_CHAR;

  if (where == PDKIM_HDR_LIMBO)
    {
    /* In limbo, just wait for a tag-char to appear */
    if (!(c >= 'a' && c <= 'z'))
      goto NEXT_CHAR;

    where = PDKIM_HDR_TAG;
    }

  if (where == PDKIM_HDR_TAG)
    {
    if (c >= 'a' && c <= 'z')
      cur_tag = string_catn(cur_tag, &ts, &tl, p, 1);

    if (c == '=')
      {
      cur_tag[tl] = '\0';
      where = PDKIM_HDR_VALUE;
      goto NEXT_CHAR;
      }
    }

  if (where == PDKIM_HDR_VALUE)
    {
    if (c == ';' || c == '\0')
      {
      if (tl && vl)
        {
	cur_val[vl] = '\0';
	pdkim_strtrim(cur_val);
	DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag, cur_val);

	switch (cur_tag[0])
	  {
	  case 'v':
	    /* This tag isn't evaluated because:
	       - We only support version DKIM1.
	       - Which is the default for this value (set below)
	       - Other versions are currently not specified.      */
	    break;
	  case 'h':
	  case 'k':
	    pub->hashes = string_copy(cur_val); break;
	  case 'g':
	    pub->granularity = string_copy(cur_val); break;
	  case 'n':
	    pub->notes = pdkim_decode_qp(cur_val); break;
	  case 'p':
	    pdkim_decode_base64(US cur_val, &pub->key);
            break;
	  case 's':
	    pub->srvtype = string_copy(cur_val); break;
	  case 't':
	    if (Ustrchr(cur_val, 'y') != NULL) pub->testing = 1;
	    if (Ustrchr(cur_val, 's') != NULL) pub->no_subdomaining = 1;
	    break;
	  default:
	    DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
	    break;
	  }
	}
      tl = 0;
      vl = 0;
      where = PDKIM_HDR_LIMBO;
      }
    else
      cur_val = string_catn(cur_val, &vs, &vl, p, 1);
    }

NEXT_CHAR:
  if (c == '\0') break;
  }

/* Set fallback defaults */
if (!pub->version    ) pub->version     = string_copy(PDKIM_PUB_RECORD_VERSION);
if (!pub->granularity) pub->granularity = string_copy(US"*");
if (!pub->keytype    ) pub->keytype     = string_copy(US"rsa");
if (!pub->srvtype    ) pub->srvtype     = string_copy(US"*");

/* p= is required */
if (pub->key.data)
  return pub;

return NULL;
}
Exemplo n.º 3
0
static pdkim_signature *
pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr)
{
pdkim_signature *sig ;
char *p, *q;
pdkim_str *cur_tag = NULL;
pdkim_str *cur_val = NULL;
BOOL past_hname = FALSE;
BOOL in_b_val = FALSE;
int where = PDKIM_HDR_LIMBO;
int i;
int old_pool = store_pool;

/* There is a store-reset between header & body reception
so cannot use the main pool. Any allocs done by Exim
memory-handling must use the perm pool. */

store_pool = POOL_PERM;

if (!(sig = malloc(sizeof(pdkim_signature)))) return NULL;
memset(sig, 0, sizeof(pdkim_signature));
sig->bodylength = -1;

if (!(sig->rawsig_no_b_val = malloc(strlen(raw_hdr)+1)))
  {
  free(sig);
  return NULL;
  }

q = sig->rawsig_no_b_val;

for (p = raw_hdr; ; p++)
  {
  char c = *p;

  /* Ignore FWS */
  if (c == '\r' || c == '\n')
    goto NEXT_CHAR;

  /* Fast-forward through header name */
  if (!past_hname)
    {
    if (c == ':') past_hname = TRUE;
    goto NEXT_CHAR;
    }

  if (where == PDKIM_HDR_LIMBO)
    {
    /* In limbo, just wait for a tag-char to appear */
    if (!(c >= 'a' && c <= 'z'))
      goto NEXT_CHAR;

    where = PDKIM_HDR_TAG;
    }

  if (where == PDKIM_HDR_TAG)
    {
    if (!cur_tag)
      cur_tag = pdkim_strnew(NULL);

    if (c >= 'a' && c <= 'z')
      pdkim_strncat(cur_tag, p, 1);

    if (c == '=')
      {
      if (strcmp(cur_tag->str, "b") == 0)
        {
	*q = '='; q++;
	in_b_val = TRUE;
	}
      where = PDKIM_HDR_VALUE;
      goto NEXT_CHAR;
      }
    }

  if (where == PDKIM_HDR_VALUE)
    {
    if (!cur_val)
      cur_val = pdkim_strnew(NULL);

    if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
      goto NEXT_CHAR;

    if (c == ';' || c == '\0')
      {
      if (cur_tag->len > 0)
        {
	pdkim_strtrim(cur_val);

	DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);

	switch (cur_tag->str[0])
	  {
	  case 'b':
	    if (cur_tag->str[1] == 'h')
	      pdkim_decode_base64(US cur_val->str, &sig->bodyhash);
	    else
	      pdkim_decode_base64(US cur_val->str, &sig->sigdata);
	    break;
	  case 'v':
	      /* We only support version 1, and that is currently the
		 only version there is. */
	    if (strcmp(cur_val->str, PDKIM_SIGNATURE_VERSION) == 0)
	      sig->version = 1;
	    break;
	  case 'a':
	    for (i = 0; pdkim_algos[i]; i++)
	      if (strcmp(cur_val->str, pdkim_algos[i]) == 0)
	        {
		sig->algo = i;
		break;
		}
	    break;
	  case 'c':
	    for (i = 0; pdkim_combined_canons[i].str; i++)
	      if (strcmp(cur_val->str, pdkim_combined_canons[i].str) == 0)
	        {
		sig->canon_headers = pdkim_combined_canons[i].canon_headers;
		sig->canon_body    = pdkim_combined_canons[i].canon_body;
		break;
		}
	    break;
	  case 'q':
	    for (i = 0; pdkim_querymethods[i]; i++)
	      if (strcmp(cur_val->str, pdkim_querymethods[i]) == 0)
	        {
		sig->querymethod = i;
		break;
		}
	    break;
	  case 's':
	    sig->selector = strdup(cur_val->str); break;
	  case 'd':
	    sig->domain = strdup(cur_val->str); break;
	  case 'i':
	    sig->identity = pdkim_decode_qp(cur_val->str); break;
	  case 't':
	    sig->created = strtoul(cur_val->str, NULL, 10); break;
	  case 'x':
	    sig->expires = strtoul(cur_val->str, NULL, 10); break;
	  case 'l':
	    sig->bodylength = strtol(cur_val->str, NULL, 10); break;
	  case 'h':
	    sig->headernames = string_copy(cur_val->str); break;
	  case 'z':
	    sig->copiedheaders = pdkim_decode_qp(cur_val->str); break;
	  default:
	    DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
	    break;
	  }
	}
      pdkim_strclear(cur_tag);
      pdkim_strclear(cur_val);
      in_b_val = FALSE;
      where = PDKIM_HDR_LIMBO;
      }
    else
      pdkim_strncat(cur_val, p, 1);
    }

NEXT_CHAR:
  if (c == '\0')
    break;

  if (!in_b_val)
    *q++ = c;
  }

store_pool = old_pool;

/* Make sure the most important bits are there. */
if (!(sig->domain      && (*(sig->domain)      != '\0') &&
      sig->selector    && (*(sig->selector)    != '\0') &&
      sig->headernames && (*(sig->headernames) != '\0') &&
      sig->version))
  {
  pdkim_free_sig(sig);
  return NULL;
  }

*q = '\0';
/* Chomp raw header. The final newline must not be added to the signature. */
q--;
while (q > sig->rawsig_no_b_val  && (*q == '\r' || *q == '\n'))
  *q = '\0'; q--;	/*XXX questionable code layout; possible bug */

DEBUG(D_acl)
  {
  debug_printf(
	  "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  pdkim_quoteprint(sig->rawsig_no_b_val, strlen(sig->rawsig_no_b_val));
  debug_printf(
	  "PDKIM >> Sig size: %4d bits\n", sig->sigdata.len*8);
  debug_printf(
	  "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
  }

exim_sha_init(&sig->body_hash, sig->algo == PDKIM_ALGO_RSA_SHA1);
return sig;
}
Exemplo n.º 4
0
Arquivo: pdkim.c Projeto: ytrezq/exim
static pdkim_signature *
pdkim_parse_sig_header(pdkim_ctx *ctx, uschar * raw_hdr)
{
pdkim_signature *sig ;
uschar *p, *q;
uschar * cur_tag = NULL; int ts = 0, tl = 0;
uschar * cur_val = NULL; int vs = 0, vl = 0;
BOOL past_hname = FALSE;
BOOL in_b_val = FALSE;
int where = PDKIM_HDR_LIMBO;
int i;

sig = store_get(sizeof(pdkim_signature));
memset(sig, 0, sizeof(pdkim_signature));
sig->bodylength = -1;

q = sig->rawsig_no_b_val = store_get(Ustrlen(raw_hdr)+1);

for (p = raw_hdr; ; p++)
  {
  char c = *p;

  /* Ignore FWS */
  if (c == '\r' || c == '\n')
    goto NEXT_CHAR;

  /* Fast-forward through header name */
  if (!past_hname)
    {
    if (c == ':') past_hname = TRUE;
    goto NEXT_CHAR;
    }

  if (where == PDKIM_HDR_LIMBO)
    {
    /* In limbo, just wait for a tag-char to appear */
    if (!(c >= 'a' && c <= 'z'))
      goto NEXT_CHAR;

    where = PDKIM_HDR_TAG;
    }

  if (where == PDKIM_HDR_TAG)
    {
    if (c >= 'a' && c <= 'z')
      cur_tag = string_catn(cur_tag, &ts, &tl, p, 1);

    if (c == '=')
      {
      cur_tag[tl] = '\0';
      if (Ustrcmp(cur_tag, "b") == 0)
        {
	*q++ = '=';
	in_b_val = TRUE;
	}
      where = PDKIM_HDR_VALUE;
      goto NEXT_CHAR;
      }
    }

  if (where == PDKIM_HDR_VALUE)
    {
    if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
      goto NEXT_CHAR;

    if (c == ';' || c == '\0')
      {
      if (tl && vl)
        {
	cur_val[vl] = '\0';
	pdkim_strtrim(cur_val);

	DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag, cur_val);

	switch (*cur_tag)
	  {
	  case 'b':
	    if (cur_tag[1] == 'h')
	      pdkim_decode_base64(cur_val, &sig->bodyhash);
	    else
	      pdkim_decode_base64(cur_val, &sig->sigdata);
	    break;
	  case 'v':
	      /* We only support version 1, and that is currently the
		 only version there is. */
	    if (Ustrcmp(cur_val, PDKIM_SIGNATURE_VERSION) == 0)
	      sig->version = 1;
	    break;
	  case 'a':
	    for (i = 0; pdkim_algos[i]; i++)
	      if (Ustrcmp(cur_val, pdkim_algos[i]) == 0)
	        {
		sig->algo = i;
		break;
		}
	    break;
	  case 'c':
	    for (i = 0; pdkim_combined_canons[i].str; i++)
	      if (Ustrcmp(cur_val, pdkim_combined_canons[i].str) == 0)
	        {
		sig->canon_headers = pdkim_combined_canons[i].canon_headers;
		sig->canon_body    = pdkim_combined_canons[i].canon_body;
		break;
		}
	    break;
	  case 'q':
	    for (i = 0; pdkim_querymethods[i]; i++)
	      if (Ustrcmp(cur_val, pdkim_querymethods[i]) == 0)
	        {
		sig->querymethod = i;
		break;
		}
	    break;
	  case 's':
	    sig->selector = string_copy(cur_val); break;
	  case 'd':
	    sig->domain = string_copy(cur_val); break;
	  case 'i':
	    sig->identity = pdkim_decode_qp(cur_val); break;
	  case 't':
	    sig->created = strtoul(CS cur_val, NULL, 10); break;
	  case 'x':
	    sig->expires = strtoul(CS cur_val, NULL, 10); break;
	  case 'l':
	    sig->bodylength = strtol(CS cur_val, NULL, 10); break;
	  case 'h':
	    sig->headernames = string_copy(cur_val); break;
	  case 'z':
	    sig->copiedheaders = pdkim_decode_qp(cur_val); break;
	  default:
	    DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
	    break;
	  }
	}
      tl = 0;
      vl = 0;
      in_b_val = FALSE;
      where = PDKIM_HDR_LIMBO;
      }
    else
      cur_val = string_catn(cur_val, &vs, &vl, p, 1);
    }

NEXT_CHAR:
  if (c == '\0')
    break;

  if (!in_b_val)
    *q++ = c;
  }

/* Make sure the most important bits are there. */
if (!sig->version)
  return NULL;

*q = '\0';
/* Chomp raw header. The final newline must not be added to the signature. */
while (--q > sig->rawsig_no_b_val  && (*q == '\r' || *q == '\n'))
  *q = '\0';

DEBUG(D_acl)
  {
  debug_printf(
	  "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  pdkim_quoteprint(US sig->rawsig_no_b_val, Ustrlen(sig->rawsig_no_b_val));
  debug_printf(
	  "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sigdata.len*8);
  debug_printf(
	  "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
  }

exim_sha_init(&sig->body_hash, sig->algo == PDKIM_ALGO_RSA_SHA1 ? HASH_SHA1 : HASH_SHA256);
return sig;
}