Exemplo n.º 1
0
pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring,
                            int oppenc_mode)
{
  ADDRESS *r, *p;
  LIST *hints = NULL;

  int multi   = 0;
  int match;

  pgp_key_t keys, k, kn;
  pgp_key_t the_strong_valid_key = NULL;
  pgp_key_t a_valid_addrmatch_key = NULL;
  pgp_key_t matches = NULL;
  pgp_key_t *last = &matches;
  pgp_uid_t *q;

  if (a && a->mailbox)
    hints = pgp_add_string_to_hints (hints, a->mailbox);
  if (a && a->personal)
    hints = pgp_add_string_to_hints (hints, a->personal);

  if (! oppenc_mode )
    mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
  keys = pgp_get_candidates (keyring, hints);

  mutt_free_list (&hints);

  if (!keys)
    return NULL;

  dprint (5, (debugfile, "pgp_getkeybyaddr: looking for %s <%s>.",
	      a->personal, a->mailbox));


  for (k = keys; k; k = kn)
  {
    kn = k->next;

    dprint (5, (debugfile, "  looking at key: %s\n",
		pgp_keyid (k)));

    if (abilities && !(k->flags & abilities))
    {
      dprint (5, (debugfile, "  insufficient abilities: Has %x, want %x\n",
		  k->flags, abilities));
      continue;
    }

    match                = 0;   /* any match 		  */

    for (q = k->address; q; q = q->next)
    {
      r = rfc822_parse_adrlist (NULL, NONULL (q->addr));

      for (p = r; p; p = p->next)
      {
	int validity = pgp_id_matches_addr (a, p, q);

	if (validity & PGP_KV_MATCH)	/* something matches */
	  match = 1;

        if ((validity & PGP_KV_VALID)
            && (validity & PGP_KV_ADDR))
        {
          if (validity & PGP_KV_STRONGID)
          {
            if (the_strong_valid_key && the_strong_valid_key != k)
              multi = 1;
            the_strong_valid_key = k;
          }
          else
          {
            a_valid_addrmatch_key = k;
          }
        }
      }

      rfc822_free_address (&r);
    }

    if (match)
    {
      *last  = pgp_principal_key (k);
      kn     = pgp_remove_key (&keys, *last);
      last   = pgp_get_lastp (k);
    }
  }

  pgp_free_key (&keys);

  if (matches)
  {
    if (oppenc_mode)
    {
      if (the_strong_valid_key)
      {
        pgp_remove_key (&matches, the_strong_valid_key);
        k = the_strong_valid_key;
      }
      else if (a_valid_addrmatch_key)
      {
        pgp_remove_key (&matches, a_valid_addrmatch_key);
        k = a_valid_addrmatch_key;
      }
      else
        k = NULL;
    }
    else if (the_strong_valid_key && !multi)
    {
      /*
       * There was precisely one strong match on a valid ID.
       * 
       * Proceed without asking the user.
       */
      pgp_remove_key (&matches, the_strong_valid_key);
      k = the_strong_valid_key;
    }
    else 
    {
      /* 
       * Else: Ask the user.
       */
      if ((k = pgp_select_key (matches, a, NULL)))
	pgp_remove_key (&matches, k);
    }

    pgp_free_key (&matches);

    return k;
  }

  return NULL;
}
Exemplo n.º 2
0
pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
{
  LIST *hints = NULL;
  pgp_key_t keys;
  pgp_key_t matches = NULL;
  pgp_key_t *last = &matches;
  pgp_key_t k, kn;
  pgp_uid_t *a;
  short match;
  size_t l;
  const char *ps, *pl, *pfcopy, *phint;

  if ((l = mutt_strlen (p)) && p[l-1] == '!')
    p[l-1] = 0;

  mutt_message (_("Looking for keys matching \"%s\"..."), p);

  pfcopy = crypt_get_fingerprint_or_id (p, &phint, &pl, &ps);
  hints = pgp_add_string_to_hints (hints, phint);
  keys = pgp_get_candidates (keyring, hints);
  mutt_free_list (&hints);

  if (!keys)
    goto out;

  for (k = keys; k; k = kn)
  {
    kn = k->next;
    if (abilities && !(k->flags & abilities))
      continue;

    /* This shouldn't happen, but keys without any addresses aren't selectable
     * in pgp_select_key().
     */
    if (!k->address)
      continue;

    match = 0;

    dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s:\n",
                p, pgp_long_keyid (k)));

    if (!*p ||
        (pfcopy && mutt_strcasecmp (pfcopy, k->fingerprint) == 0) ||
        (pl && mutt_strcasecmp (pl, pgp_long_keyid (k)) == 0) ||
        (ps && mutt_strcasecmp (ps, pgp_short_keyid (k)) == 0))
    {
      dprint (5, (debugfile, "\t\tmatch.\n"));
      match = 1;
    }
    else
    {
      for (a = k->address; a; a = a->next)
      {
        dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s, \"%s\":\n",
                    p, pgp_long_keyid (k), NONULL (a->addr)));
        if (mutt_stristr (a->addr, p))
        {
          dprint (5, (debugfile, "\t\tmatch.\n"));
          match = 1;
          break;
        }
      }
    }

    if (match)
    {
      *last = pgp_principal_key (k);
      kn    = pgp_remove_key (&keys, *last);
      last  = pgp_get_lastp (k);
    }
  }

  pgp_free_key (&keys);

  if (matches)
  {
    if ((k = pgp_select_key (matches, NULL, p)))
      pgp_remove_key (&matches, k);

    pgp_free_key (&matches);
    FREE (&pfcopy);
    if (l && !p[l-1])
      p[l-1] = '!';
    return k;
  }

out:
  FREE (&pfcopy);
  if (l && !p[l-1])
    p[l-1] = '!';
  return NULL;
}
Exemplo n.º 3
0
pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
{
  LIST *hints = NULL;
  pgp_key_t keys;
  pgp_key_t matches = NULL;
  pgp_key_t *last = &matches;
  pgp_key_t k, kn;
  pgp_uid_t *a;
  short match;
  size_t l;
  const char *ps, *pl;

  if ((l = mutt_strlen (p)) && p[l-1] == '!')
    p[l-1] = 0;

  mutt_message (_("Looking for keys matching \"%s\"..."), p);

  hints = pgp_add_string_to_hints (hints, p);
  keys = pgp_get_candidates (keyring, hints);
  mutt_free_list (&hints);

  if (!keys)
    goto out;

  /* User input may be short or long key ID, independent of OPTPGPLONGIDS.
   * pgp_key_t->keyid should always contain a long key ID without 0x.
   * Strip leading "0x" before loops so it doesn't have to be done over and
   * over again, and prepare pl and ps to simplify logic in the loop's inner
   * condition.
   */
  pl = (!mutt_strncasecmp (p, "0x", 2) ? p + 2 : p);
  ps = (mutt_strlen (pl) == 16 ? pl + 8 : pl);

  for (k = keys; k; k = kn)
  {
    kn = k->next;
    if (abilities && !(k->flags & abilities))
      continue;

    /* This shouldn't happen, but keys without any addresses aren't selectable
     * in pgp_select_key().
     */
    if (!k->address)
      continue;

    match = 0;

    dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s:\n",
                p, pgp_long_keyid (k)));

    /* If ps != pl it means a long ID (or name of 16 characters) was given, do
     * not attempt to match short IDs then. Also, it is unnecessary to try to
     * match pl against long IDs if ps == pl as pl could not be a long ID. */
    if (!*p ||
        (ps != pl && mutt_strcasecmp (pl, pgp_long_keyid (k)) == 0) ||
        (ps == pl && mutt_strcasecmp (ps, pgp_short_keyid (k)) == 0))
    {
      dprint (5, (debugfile, "\t\tmatch.\n"));
      match = 1;
    }
    else
    {
      for (a = k->address; a; a = a->next)
      {
        dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s, \"%s\":\n",
                    p, pgp_long_keyid (k), NONULL (a->addr)));
        if (mutt_stristr (a->addr, p))
        {
          dprint (5, (debugfile, "\t\tmatch.\n"));
          match = 1;
          break;
        }
      }
    }

    if (match)
    {
      *last = pgp_principal_key (k);
      kn    = pgp_remove_key (&keys, *last);
      last  = pgp_get_lastp (k);
    }
  }

  pgp_free_key (&keys);

  if (matches)
  {
    if ((k = pgp_select_key (matches, NULL, p)))
      pgp_remove_key (&matches, k);

    pgp_free_key (&matches);
    if (l && !p[l-1])
      p[l-1] = '!';
    return k;
  }

out:
  if (l && !p[l-1])
    p[l-1] = '!';
  return NULL;
}