Exemple #1
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;
}
Exemple #2
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;
}
Exemple #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;
}
Exemple #4
0
BODY *pgp_make_key_attachment (char *tempf)
{
  BODY *att;
  char buff[LONG_STRING];
  char tempfb[_POSIX_PATH_MAX], tmp[STRING];
  FILE *tempfp;
  FILE *devnull;
  struct stat sb;
  pid_t thepid;
  pgp_key_t key;
  unset_option (OPTPGPCHECKTRUST);

  key = pgp_ask_for_key (_("Please enter the key ID: "), NULL, 0, PGP_PUBRING);

  if (!key)    return NULL;

  snprintf (tmp, sizeof (tmp), "0x%s", pgp_fpr_or_lkeyid (pgp_principal_key (key)));
  pgp_free_key (&key);

  if (!tempf)
  {
    mutt_mktemp (tempfb, sizeof (tempfb));
    tempf = tempfb;
  }

  if ((tempfp = safe_fopen (tempf, tempf == tempfb ? "w" : "a")) == NULL)
  {
    mutt_perror _("Can't create temporary file");
    return NULL;
  }

  if ((devnull = fopen ("/dev/null", "w")) == NULL)	/* __FOPEN_CHECKED__ */
  {
    mutt_perror _("Can't open /dev/null");
    safe_fclose (&tempfp);
    if (tempf == tempfb)
      unlink (tempf);
    return NULL;
  }

  mutt_message _("Invoking PGP...");


  if ((thepid = 
       pgp_invoke_export (NULL, NULL, NULL, -1,
			   fileno (tempfp), fileno (devnull), tmp)) == -1)
  {
    mutt_perror _("Can't create filter");
    unlink (tempf);
    safe_fclose (&tempfp);
    safe_fclose (&devnull);
    return NULL;
  }

  mutt_wait_filter (thepid);

  safe_fclose (&tempfp);
  safe_fclose (&devnull);

  att = mutt_new_body ();
  att->filename = safe_strdup (tempf);
  att->unlink = 1;
  att->use_disp = 0;
  att->type = TYPEAPPLICATION;
  att->subtype = safe_strdup ("pgp-keys");
  snprintf (buff, sizeof (buff), _("PGP Key %s."), tmp);
  att->description = safe_strdup (buff);
  mutt_update_encoding (att);

  stat (tempf, &sb);
  att->length = sb.st_size;

  return att;
}
static int pgp_send_menu (int bits, int *redraw)
{
  pgp_key_t *p;
  char input_signas[SHORT_STRING];
  char input_micalg[SHORT_STRING];

  switch (mutt_multi_choice (_("(e)ncrypt, (s)ign, sign (a)s, (b)oth, select (m)ic algorithm, or (f)orget it? "),
			     _("esabmf")))
  {
  case 1: /* (e)ncrypt */
    bits |= PGPENCRYPT;
    break;

  case 2: /* (s)ign */
    bits |= PGPSIGN;
    break;

  case 3: /* sign (a)s */

    unset_option(OPTPGPCHECKTRUST);

    if ((p = pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN, PGP_PUBRING)))
    {
      snprintf (input_signas, sizeof (input_signas), "0x%s", pgp_keyid (p));
      mutt_str_replace (&PgpSignAs, input_signas);
      mutt_str_replace (&PgpSignMicalg, pgp_pkalg_to_mic (p->algorithm));
      pgp_free_key (&p);
      
      bits |= PGPSIGN;
	
      pgp_void_passphrase ();	/* probably need a different passphrase */
    }
    else
    {
      bits &= ~PGPSIGN;
    }

    *redraw = REDRAW_FULL;
    break;

  case 4: /* (b)oth */
    bits = PGPENCRYPT | PGPSIGN;
    break;

  case 5: /* select (m)ic algorithm */
    if (!(bits & PGPSIGN))
      mutt_error _("This doesn't make sense if you don't want to sign the message.");
    else
    {
      /* Copy the existing MIC algorithm into place */
      strfcpy(input_micalg, NONULL (PgpSignMicalg), sizeof (input_micalg));

      if (mutt_get_field (_("MIC algorithm: "), input_micalg, sizeof (input_micalg), 0) == 0)
      {
	if (mutt_strcasecmp (input_micalg, "pgp-md5") && mutt_strcasecmp (input_micalg, "pgp-sha1")
	   && mutt_strcasecmp (input_micalg, "pgp-rmd160"))
	{
	  mutt_error _("Unknown MIC algorithm, valid ones are: pgp-md5, pgp-sha1, pgp-rmd160");
	}
	else 
	  mutt_str_replace (&PgpSignMicalg, input_micalg);
      }
    }
    break;

  case 6: /* (f)orget it */
    bits = 0;
    break;
  }
  if (!*redraw)
    redraw_pgp_lines (bits);
  return (bits);
}