예제 #1
0
파일: keylist.c 프로젝트: BridgeNY/purdue
static void
fingerprint( PKT_public_key *pk, PKT_secret_key *sk )
{
    byte *array, *p;
    size_t i, n;

    p = array = pk? fingerprint_from_pk( pk, NULL, &n )
		   : fingerprint_from_sk( sk, NULL, &n );
    if( opt.with_colons ) {
	printf("fpr:::::::::");
	for(i=0; i < n ; i++, p++ )
	    printf("%02X", *p );
	putchar(':');
    }
    else {
	printf("     Key fingerprint =");
	if( n == 20 ) {
	    for(i=0; i < n ; i++, i++, p += 2 ) {
		if( i == 10 )
		    putchar(' ');
		printf(" %02X%02X", *p, p[1] );
	    }
	}
	else {
	    for(i=0; i < n ; i++, p++ ) {
		if( i && !(i%8) )
		    putchar(' ');
		printf(" %02X", *p );
	    }
	}
    }
    putchar('\n');
    m_free(array);
}
예제 #2
0
/* Helper function to check whether the subkey at NODE actually
   matches the description at DESC.  The function returns true if the
   key under question has been specified by an exact specification
   (keyID or fingerprint) and does match the one at NODE.  It is
   assumed that the packet at NODE is either a public or secret
   subkey. */
static int
exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
{
  u32 kid[2];
  byte fpr[MAX_FINGERPRINT_LEN];
  size_t fprlen;
  int result = 0;

  switch(desc->mode)
    {
    case KEYDB_SEARCH_MODE_SHORT_KID:
    case KEYDB_SEARCH_MODE_LONG_KID:
      if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
        keyid_from_pk (node->pkt->pkt.public_key, kid);
      else
        keyid_from_sk (node->pkt->pkt.secret_key, kid);
      break;
      
    case KEYDB_SEARCH_MODE_FPR16:
    case KEYDB_SEARCH_MODE_FPR20:
    case KEYDB_SEARCH_MODE_FPR:
      if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
        fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
      else
        fingerprint_from_sk (node->pkt->pkt.secret_key, fpr,&fprlen);
      break;
      
    default:
      break;
    }
  
  switch(desc->mode)
    {
    case KEYDB_SEARCH_MODE_SHORT_KID:
      if (desc->u.kid[1] == kid[1])
        result = 1;
      break;

    case KEYDB_SEARCH_MODE_LONG_KID:
      if (desc->u.kid[0] == kid[0] && desc->u.kid[1] == kid[1])
        result = 1;
      break;

    case KEYDB_SEARCH_MODE_FPR16:
      if (!memcmp (desc->u.fpr, fpr, 16))
        result = 1;
      break;

    case KEYDB_SEARCH_MODE_FPR20:
    case KEYDB_SEARCH_MODE_FPR:
      if (!memcmp (desc->u.fpr, fpr, 20))
        result = 1;
      break;

    default:
      break;
    }

  return result;
}
예제 #3
0
파일: pkclist.c 프로젝트: FMayzek/gnupg
/****************
 * Return a malloced string with a default recipient if there is any
 */
static char *
default_recipient(void)
{
    PKT_public_key *pk;
    byte fpr[MAX_FINGERPRINT_LEN+1];
    size_t n;
    char *p;
    int i;

    if( opt.def_recipient )
	return xstrdup( opt.def_recipient );
    if( !opt.def_recipient_self )
	return NULL;
    pk = xmalloc_clear( sizeof *pk );
    i = get_seckey_byname (pk, NULL);
    if( i ) {
	free_public_key( pk );
	return NULL;
    }
    n = MAX_FINGERPRINT_LEN;
    fingerprint_from_pk( pk, fpr, &n );
    free_public_key( pk );
    p = xmalloc( 2*n+3 );
    *p++ = '0';
    *p++ = 'x';
    for(i=0; i < n; i++ )
	sprintf( p+2*i, "%02X", fpr[i] );
    p -= 2;
    return p;
}
void
show_revocation_reason( PKT_public_key *pk, int mode )
{
    /* Hmmm, this is not so easy becuase we have to duplicate the code
     * used in the trustbd to calculate the keyflags.  We need to find
     * a clean way to check revocation certificates on keys and
     * signatures.  And there should be no duplicate code.  Because we
     * enter this function only when the trustdb told us that we have
     * a revoked key, we could simply look for a revocation cert and
     * display this one, when there is only one. Let's try to do this
     * until we have a better solution.  */
    KBNODE node, keyblock = NULL;
    byte fingerprint[MAX_FINGERPRINT_LEN];
    size_t fingerlen;
    int rc;

    /* get the keyblock */
    fingerprint_from_pk( pk, fingerprint, &fingerlen );
    rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
    if( rc ) { /* that should never happen */
	log_debug( "failed to get the keyblock\n");
	return;
    }

    for( node=keyblock; node; node = node->next ) {
        if( (mode && node->pkt->pkttype == PKT_PUBLIC_KEY) ||
	  ( ( node->pkt->pkttype == PKT_PUBLIC_KEY
	      || node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
	    && !cmp_public_keys( node->pkt->pkt.public_key, pk ) ) )
	    break;
    }
    if( !node ) {
	log_debug("Oops, PK not in keyblock\n");
	release_kbnode( keyblock );
	return;
    }
    /* now find the revocation certificate */
    for( node = node->next; node ; node = node->next ) {
	if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
	    break;
	if( node->pkt->pkttype == PKT_SIGNATURE
	    && (node->pkt->pkt.signature->sig_class == 0x20
		|| node->pkt->pkt.signature->sig_class == 0x28 ) ) {
		/* FIXME: we should check the signature here */
		do_show_revocation_reason ( node->pkt->pkt.signature );
		break;
	}
    }

    /* We didn't find it, so check if the whole key is revoked */
    if(!node && !mode)
      show_revocation_reason(pk,1);

    release_kbnode( keyblock );
}
int
tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
{
    byte fingerprint[MAX_FINGERPRINT_LEN];
    size_t fingerlen;

    fingerprint_from_pk( pk, fingerprint, &fingerlen );
    for (; fingerlen < 20; fingerlen++ )
      fingerprint[fingerlen] = 0;
    return tdbio_search_trust_byfpr (fingerprint, rec);
}
예제 #6
0
파일: passphrase.c 프로젝트: cuidi/gnupg
/*
 * Clear the cached passphrase.  If CACHEID is not NULL, it will be
 * used instead of a cache ID derived from KEYID.
 */
void
passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
{
  int rc;

  (void)algo;

  if (!cacheid)
    {
      PKT_public_key *pk;
#     if MAX_FINGERPRINT_LEN < 20
#       error agent needs a 20 byte fingerprint
#     endif
      byte fpr[MAX_FINGERPRINT_LEN];
      char hexfprbuf[2*20+1];
      size_t dummy;

      pk = xcalloc (1, sizeof *pk);
      if ( !keyid || get_pubkey( pk, keyid ) )
        {
          log_error ("key not found in passphrase_clear_cache\n");
          free_public_key (pk);
          return;
        }
      memset (fpr, 0, MAX_FINGERPRINT_LEN );
      fingerprint_from_pk ( pk, fpr, &dummy );
      bin2hex (fpr, 20, hexfprbuf);
      rc = agent_clear_passphrase (hexfprbuf);
      free_public_key ( pk );
    }
  else
    rc = agent_clear_passphrase (cacheid);

  if (rc)
    log_error (_("problem with the agent: %s\n"), gpg_strerror (rc));
}
예제 #7
0
/* 
 * Search through the keyring(s), starting at the current position,
 * for a keyblock which contains one of the keys described in the DESC array.
 */
int 
keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
		size_t ndesc, size_t *descindex)
{
  int rc;
  PACKET pkt;
  int save_mode;
  off_t offset, main_offset;
  size_t n;
  int need_uid, need_words, need_keyid, need_fpr, any_skip;
  int pk_no, uid_no;
  int initial_skip;
  int use_offtbl;
  PKT_user_id *uid = NULL;
  PKT_public_key *pk = NULL;
  PKT_secret_key *sk = NULL;
  u32 aki[2];

  /* figure out what information we need */
  need_uid = need_words = need_keyid = need_fpr = any_skip = 0;
  for (n=0; n < ndesc; n++) 
    {
      switch (desc[n].mode) 
        {
        case KEYDB_SEARCH_MODE_EXACT: 
        case KEYDB_SEARCH_MODE_SUBSTR:
        case KEYDB_SEARCH_MODE_MAIL:
        case KEYDB_SEARCH_MODE_MAILSUB:
        case KEYDB_SEARCH_MODE_MAILEND:
          need_uid = 1;
          break;
        case KEYDB_SEARCH_MODE_WORDS: 
          need_uid = 1;
          need_words = 1;
          break;
        case KEYDB_SEARCH_MODE_SHORT_KID: 
        case KEYDB_SEARCH_MODE_LONG_KID:
          need_keyid = 1;
          break;
        case KEYDB_SEARCH_MODE_FPR16: 
        case KEYDB_SEARCH_MODE_FPR20:
        case KEYDB_SEARCH_MODE_FPR: 
          need_fpr = 1;
          break;
        case KEYDB_SEARCH_MODE_FIRST:
          /* always restart the search in this mode */
          keyring_search_reset (hd);
          break;
        default: break;
	}
      if (desc[n].skipfnc) 
        {
          any_skip = 1;
          need_keyid = 1;
        }
    }

  rc = prepare_search (hd);
  if (rc)
    return rc;

  use_offtbl = !hd->secret && kr_offtbl;
  if (!use_offtbl)
    ;
  else if (!kr_offtbl_ready)
    need_keyid = 1;
  else if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID)
    {
      struct off_item *oi;
            
      oi = lookup_offset_hash_table (kr_offtbl, desc[0].u.kid);
      if (!oi)
        { /* We know that we don't have this key */
          hd->found.kr = NULL;
          hd->current.eof = 1;
          return -1;
        }
      /* We could now create a positive search status and return.
       * However the problem is that another instance of gpg may 
       * have changed the keyring so that the offsets are not valid
       * anymore - therefore we don't do it 
       */
    }

  if (need_words)
    {
      const char *name = NULL;

      log_debug ("word search mode does not yet work\n");
      /* FIXME: here is a long standing bug in our function and in addition we
         just use the first search description */
      for (n=0; n < ndesc && !name; n++) 
        {
          if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS) 
            name = desc[n].u.name;
        }
      assert (name);
      if ( !hd->word_match.name || strcmp (hd->word_match.name, name) ) 
        {
          /* name changed */
          xfree (hd->word_match.name);
          xfree (hd->word_match.pattern);
          hd->word_match.name = xstrdup (name);
          hd->word_match.pattern = prepare_word_match (name);
        }
      name = hd->word_match.pattern;
    }

  init_packet(&pkt);
  save_mode = set_packet_list_mode(0);

  hd->found.kr = NULL;
  main_offset = 0;
  pk_no = uid_no = 0;
  initial_skip = 1; /* skip until we see the start of a keyblock */
  while (!(rc=search_packet (hd->current.iobuf, &pkt, &offset, need_uid))) 
    {
      byte afp[MAX_FINGERPRINT_LEN];
      size_t an;

      if (pkt.pkttype == PKT_PUBLIC_KEY  || pkt.pkttype == PKT_SECRET_KEY) 
        {
          main_offset = offset;
          pk_no = uid_no = 0;
          initial_skip = 0;
        }
      if (initial_skip) 
        {
          free_packet (&pkt);
          continue;
        }
	
      pk = NULL;
      sk = NULL;
      uid = NULL;
      if (   pkt.pkttype == PKT_PUBLIC_KEY
             || pkt.pkttype == PKT_PUBLIC_SUBKEY)
        {
          pk = pkt.pkt.public_key;
          ++pk_no;

          if (need_fpr) {
            fingerprint_from_pk (pk, afp, &an);
            while (an < 20) /* fill up to 20 bytes */
              afp[an++] = 0;
          }
          if (need_keyid)
            keyid_from_pk (pk, aki);

          if (use_offtbl && !kr_offtbl_ready)
            update_offset_hash_table (kr_offtbl, aki, main_offset);
        }
      else if (pkt.pkttype == PKT_USER_ID) 
        {
          uid = pkt.pkt.user_id;
          ++uid_no;
        }
      else if (    pkt.pkttype == PKT_SECRET_KEY
                   || pkt.pkttype == PKT_SECRET_SUBKEY) 
        {
          sk = pkt.pkt.secret_key;
          ++pk_no;

          if (need_fpr) {
            fingerprint_from_sk (sk, afp, &an);
            while (an < 20) /* fill up to 20 bytes */
              afp[an++] = 0;
          }
          if (need_keyid)
            keyid_from_sk (sk, aki);
            
        }

      for (n=0; n < ndesc; n++) 
        {
          switch (desc[n].mode) {
          case KEYDB_SEARCH_MODE_NONE: 
            BUG ();
            break;
          case KEYDB_SEARCH_MODE_EXACT: 
          case KEYDB_SEARCH_MODE_SUBSTR:
          case KEYDB_SEARCH_MODE_MAIL:
          case KEYDB_SEARCH_MODE_MAILSUB:
          case KEYDB_SEARCH_MODE_MAILEND:
          case KEYDB_SEARCH_MODE_WORDS: 
            if ( uid && !compare_name (desc[n].mode,
                                       desc[n].u.name,
                                       uid->name, uid->len)) 
              goto found;
            break;
                
          case KEYDB_SEARCH_MODE_SHORT_KID: 
            if ((pk||sk) && desc[n].u.kid[1] == aki[1])
              goto found;
            break;
          case KEYDB_SEARCH_MODE_LONG_KID:
            if ((pk||sk) && desc[n].u.kid[0] == aki[0]
                && desc[n].u.kid[1] == aki[1])
              goto found;
            break;
          case KEYDB_SEARCH_MODE_FPR16:
            if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 16))
              goto found;
            break;
          case KEYDB_SEARCH_MODE_FPR20:
          case KEYDB_SEARCH_MODE_FPR: 
            if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 20))
              goto found;
            break;
          case KEYDB_SEARCH_MODE_FIRST: 
            if (pk||sk)
              goto found;
            break;
          case KEYDB_SEARCH_MODE_NEXT: 
            if (pk||sk)
              goto found;
            break;
          default: 
            rc = G10ERR_INV_ARG;
            goto found;
          }
	}
      free_packet (&pkt);
      continue;
    found:
      /* Record which desc we matched on.  Note this value is only
	 meaningful if this function returns with no errors. */
      if(descindex)
	*descindex=n;
      for (n=any_skip?0:ndesc; n < ndesc; n++) 
        {
          if (desc[n].skipfnc
              && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid))
            break;
        }
      if (n == ndesc)
        goto real_found;
      free_packet (&pkt);
    }
 real_found:
  if (!rc)
    {
      hd->found.offset = main_offset;
      hd->found.kr = hd->current.kr;
      hd->found.pk_no = (pk||sk)? pk_no : 0;
      hd->found.uid_no = uid? uid_no : 0;
    }
  else if (rc == -1)
    {
      hd->current.eof = 1;
      /* if we scanned all keyrings, we are sure that
       * all known key IDs are in our offtbl, mark that. */
      if (use_offtbl && !kr_offtbl_ready)
        {
          KR_NAME kr;
          
          /* First set the did_full_scan flag for this keyring (ignore
             secret keyrings) */
          for (kr=kr_names; kr; kr = kr->next)
            {
              if (!kr->secret && hd->resource == kr) 
                {
                  kr->did_full_scan = 1;
                  break;
                }
            }
          /* Then check whether all flags are set and if so, mark the
             offtbl ready */
          for (kr=kr_names; kr; kr = kr->next)
            {
              if (!kr->secret && !kr->did_full_scan) 
                break;
            }
          if (!kr)
            kr_offtbl_ready = 1;
        }
    }
  else 
    hd->current.error = rc;

  free_packet(&pkt);
  set_packet_list_mode(save_mode);
  return rc;
}
예제 #8
0
파일: passphrase.c 프로젝트: cuidi/gnupg
/*
 * Ask the GPG Agent for the passphrase.
 * Mode 0:  Allow cached passphrase
 *      1:  No cached passphrase; that is we are asking for a new passphrase
 *          FIXME: Only partially implemented
 *
 * Note that TRYAGAIN_TEXT must not be translated.  If CANCELED is not
 * NULL, the function does set it to 1 if the user canceled the
 * operation.  If CACHEID is not NULL, it will be used as the cacheID
 * for the gpg-agent; if is NULL and a key fingerprint can be
 * computed, this will be used as the cacheid.
 */
static char *
passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
                 const char *tryagain_text,
                 const char *custom_description,
                 const char *custom_prompt, int *canceled)
{
  int rc;
  char *atext = NULL;
  char *pw = NULL;
  PKT_public_key *pk = xmalloc_clear( sizeof *pk );
  byte fpr[MAX_FINGERPRINT_LEN];
  int have_fpr = 0;
  char *orig_codeset;
  char *my_prompt;
  char hexfprbuf[20*2+1];
  const char *my_cacheid;
  int check = (mode == 1);

  if (canceled)
    *canceled = 0;

#if MAX_FINGERPRINT_LEN < 20
#error agent needs a 20 byte fingerprint
#endif

  memset (fpr, 0, MAX_FINGERPRINT_LEN );
  if( keyid && get_pubkey( pk, keyid ) )
    {
      free_public_key (pk);
      pk = NULL; /* oops: no key for some reason */
    }

  orig_codeset = i18n_switchto_utf8 ();

  if (custom_description)
    atext = native_to_utf8 (custom_description);
  else if ( !mode && pk && keyid )
    {
      char *uid;
      size_t uidlen;
      const char *algo_name = openpgp_pk_algo_name ( pk->pubkey_algo );
      const char *timestr;
      char *maink;

      if ( !algo_name )
        algo_name = "?";

      if (keyid[2] && keyid[3]
          && keyid[0] != keyid[2]
          && keyid[1] != keyid[3] )
        maink = xasprintf (_(" (main key ID %s)"), keystr (&keyid[2]));
      else
        maink = xstrdup ("");

      uid = get_user_id ( keyid, &uidlen );
      timestr = strtimestamp (pk->timestamp);

      atext = xasprintf (_("Please enter the passphrase to unlock the"
                           " secret key for the OpenPGP certificate:\n"
                           "\"%.*s\"\n"
                           "%u-bit %s key, ID %s,\n"
                           "created %s%s.\n"),
                         (int)uidlen, uid,
                         nbits_from_pk (pk), algo_name, keystr(&keyid[0]),
                         timestr, maink);
      xfree (uid);
      xfree (maink);

      {
        size_t dummy;
        fingerprint_from_pk( pk, fpr, &dummy );
        have_fpr = 1;
      }

    }
  else
    atext = xstrdup ( _("Enter passphrase\n") );


  if (!mode && cacheid)
    my_cacheid = cacheid;
  else if (!mode && have_fpr)
    my_cacheid = bin2hex (fpr, 20, hexfprbuf);
  else
    my_cacheid = NULL;

  if (tryagain_text)
    tryagain_text = _(tryagain_text);

  my_prompt = custom_prompt ? native_to_utf8 (custom_prompt): NULL;

  rc = agent_get_passphrase (my_cacheid, tryagain_text, my_prompt, atext,
                             repeat, check, &pw);

  xfree (my_prompt);
  xfree (atext); atext = NULL;

  i18n_switchback (orig_codeset);


  if (!rc)
    ;
  else if (gpg_err_code (rc) == GPG_ERR_CANCELED
            || gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
    {
      log_info (_("cancelled by user\n") );
      if (canceled)
        *canceled = 1;
    }
  else
    {
      log_error (_("problem with the agent: %s\n"), gpg_strerror (rc));
      /* Due to limitations in the API of the upper layers they
         consider an error as no passphrase entered.  This works in
         most cases but not during key creation where this should
         definitely not happen and let it continue without requiring a
         passphrase.  Given that now all the upper layers handle a
         cancel correctly, we simply set the cancel flag now for all
         errors from the agent.  */
      if (canceled)
        *canceled = 1;

      write_status_errcode ("get_passphrase", rc);
    }

  free_public_key (pk);
  if (rc)
    {
      xfree (pw);
      return NULL;
    }
  return pw;
}
/****************
 * Check whether we can trust this signature.
 * Returns: Error if we shall not trust this signatures.
 */
int
check_signatures_trust( PKT_signature *sig )
{
  PKT_public_key *pk = xmalloc_clear( sizeof *pk );
  unsigned int trustlevel;
  int rc=0;

  rc = get_pubkey( pk, sig->keyid );
  if (rc) 
    { /* this should not happen */
      log_error("Ooops; the key vanished  - can't check the trust\n");
      rc = G10ERR_NO_PUBKEY;
      goto leave;
    }

  if ( opt.trust_model==TM_ALWAYS )
    {
      if( !opt.quiet )
        log_info(_("WARNING: Using untrusted key!\n"));
      if (opt.with_fingerprint)
        print_fingerprint (pk, NULL, 1);
      goto leave;
    }

  if(pk->maybe_revoked && !pk->is_revoked)
    log_info(_("WARNING: this key might be revoked (revocation key"
	       " not present)\n"));

  trustlevel = get_validity (pk, NULL);

  if ( (trustlevel & TRUST_FLAG_REVOKED) ) 
    {
      write_status( STATUS_KEYREVOKED );
      if(pk->is_revoked==2)
	log_info(_("WARNING: This key has been revoked by its"
		   " designated revoker!\n"));
      else
	log_info(_("WARNING: This key has been revoked by its owner!\n"));
      log_info(_("         This could mean that the signature is forged.\n"));
      show_revocation_reason( pk, 0 );
    }
  else if ((trustlevel & TRUST_FLAG_SUB_REVOKED) ) 
    {
      write_status( STATUS_KEYREVOKED );
      log_info(_("WARNING: This subkey has been revoked by its owner!\n"));
      show_revocation_reason( pk, 0 );
    }
  
  if ((trustlevel & TRUST_FLAG_DISABLED))
    log_info (_("Note: This key has been disabled.\n"));

  /* If we have PKA information adjust the trustlevel. */
  if (sig->pka_info && sig->pka_info->valid)
    {
      unsigned char fpr[MAX_FINGERPRINT_LEN];
      PKT_public_key *primary_pk;
      size_t fprlen;
      int okay;


      primary_pk = xmalloc_clear (sizeof *primary_pk);
      get_pubkey (primary_pk, pk->main_keyid);
      fingerprint_from_pk (primary_pk, fpr, &fprlen);
      free_public_key (primary_pk);

      if ( fprlen == 20 && !memcmp (sig->pka_info->fpr, fpr, 20) )
        {
          okay = 1;
          write_status_text (STATUS_PKA_TRUST_GOOD, sig->pka_info->email);
          log_info (_("Note: Verified signer's address is `%s'\n"),
                    sig->pka_info->email);
        }
      else
        {
          okay = 0;
          write_status_text (STATUS_PKA_TRUST_BAD, sig->pka_info->email);
          log_info (_("Note: Signer's address `%s' "
                      "does not match DNS entry\n"), sig->pka_info->email);
        }

      switch ( (trustlevel & TRUST_MASK) ) 
        {
        case TRUST_UNKNOWN: 
        case TRUST_UNDEFINED:
        case TRUST_MARGINAL:
          if (okay && opt.verify_options&VERIFY_PKA_TRUST_INCREASE)
            {
              trustlevel = ((trustlevel & ~TRUST_MASK) | TRUST_FULLY);
              log_info (_("trustlevel adjusted to FULL"
                          " due to valid PKA info\n"));
            }
          /* (fall through) */
        case TRUST_FULLY:
          if (!okay)
            {
              trustlevel = ((trustlevel & ~TRUST_MASK) | TRUST_NEVER);
              log_info (_("trustlevel adjusted to NEVER"
                          " due to bad PKA info\n"));
            }
          break;
        }
    }

  /* Now let the user know what up with the trustlevel. */
  switch ( (trustlevel & TRUST_MASK) ) 
    {
    case TRUST_EXPIRED:
      log_info(_("Note: This key has expired!\n"));
      print_fingerprint (pk, NULL, 1);
      break;
        
    default:
      log_error ("invalid trustlevel %u returned from validation layer\n",
                 trustlevel);
      /* fall thru */
    case TRUST_UNKNOWN: 
    case TRUST_UNDEFINED:
      write_status( STATUS_TRUST_UNDEFINED );
      log_info(_("WARNING: This key is not certified with"
                 " a trusted signature!\n"));
      log_info(_("         There is no indication that the "
                 "signature belongs to the owner.\n" ));
      print_fingerprint (pk, NULL, 1);
      break;

    case TRUST_NEVER:
      /* currently we won't get that status */
      write_status( STATUS_TRUST_NEVER );
      log_info(_("WARNING: We do NOT trust this key!\n"));
      log_info(_("         The signature is probably a FORGERY.\n"));
      if (opt.with_fingerprint)
        print_fingerprint (pk, NULL, 1);
      rc = G10ERR_BAD_SIGN;
      break;

    case TRUST_MARGINAL:
      write_status( STATUS_TRUST_MARGINAL );
      log_info(_("WARNING: This key is not certified with"
                 " sufficiently trusted signatures!\n"));
      log_info(_("         It is not certain that the"
                 " signature belongs to the owner.\n" ));
      print_fingerprint (pk, NULL, 1);
      break;

    case TRUST_FULLY:
      write_status( STATUS_TRUST_FULLY );
      if (opt.with_fingerprint)
        print_fingerprint (pk, NULL, 1);
      break;

    case TRUST_ULTIMATE:
      write_status( STATUS_TRUST_ULTIMATE );
      if (opt.with_fingerprint)
        print_fingerprint (pk, NULL, 1);
      break;
    }

 leave:
  free_public_key( pk );
  return rc;
}
예제 #10
0
static gpg_error_t
get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
{
  gpg_error_t err;
  byte *frame = NULL;
  unsigned int n;
  size_t nframe;
  u16 csum, csum2;
  int card = 0;
  gcry_sexp_t s_data;
  char *desc;
  char *keygrip;
  byte fp[MAX_FINGERPRINT_LEN];
  size_t fpn;
  const int pkalgo = map_pk_openpgp_to_gcry (sk->pubkey_algo);

  /* Get the keygrip.  */
  err = hexkeygrip_from_pk (sk, &keygrip);
  if (err)
    goto leave;

  /* Convert the data to an S-expression.  */
  if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E)
    {
      if (!enc->data[0] || !enc->data[1])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))",
                               enc->data[0], enc->data[1]);
    }
  else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_E)
    {
      if (!enc->data[0])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))",
                               enc->data[0]);
    }
  else if (pkalgo == GCRY_PK_ECDH)
    {
      if (!enc->data[0] || !enc->data[1])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(s%m)(e%m)))",
                               enc->data[0], enc->data[1]);
    }
  else
    err = gpg_error (GPG_ERR_BUG);

  if (err)
    goto leave;

  if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      fingerprint_from_pk (sk, fp, &fpn);
      assert (fpn == 20);
    }

  /* Decrypt. */
  desc = gpg_format_keydesc (sk, 0, 1);
  err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe);
  xfree (desc);
  gcry_sexp_release (s_data);
  if (err)
    goto leave;

  /* Now get the DEK (data encryption key) from the frame
   *
   * Old versions encode the DEK in in this format (msb is left):
   *
   *     0  1  DEK(16 bytes)  CSUM(2 bytes)  0  RND(n bytes) 2
   *
   * Later versions encode the DEK like this:
   *
   *     0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
   *
   * (mpi_get_buffer already removed the leading zero).
   *
   * RND are non-zero randow bytes.
   * A   is the cipher algorithm
   * DEK is the encryption key (session key) with length k
   * CSUM
   */
  if (DBG_CIPHER)
    log_printhex ("DEK frame:", frame, nframe);
  n = 0;

  if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      gcry_mpi_t shared_mpi;
      gcry_mpi_t decoded;

      /* At the beginning the frame are the bytes of shared point MPI.  */
      err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL);
      if (err)
        {
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
          goto leave;
        }

      err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/,
                             shared_mpi, sk->pkey);
      mpi_release (shared_mpi);
      if(err)
        goto leave;

      /* Reuse NFRAME, which size is sufficient to include the session key.  */
      err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded);
      mpi_release (decoded);
      if (err)
        goto leave;

      /* Now the frame are the bytes decrypted but padded session key.  */

      /* Allow double padding for the benefit of DEK size concealment.
         Higher than this is wasteful. */
      if (!nframe || frame[nframe-1] > 8*2 || nframe <= 8
          || frame[nframe-1] > nframe)
        {
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
          goto leave;
        }
      nframe -= frame[nframe-1]; /* Remove padding.  */
      assert (!n); /* (used just below) */
    }
  else
    {
      if (!card)
        {
          if (n + 7 > nframe)
            {
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
              goto leave;
            }
          if (frame[n] == 1 && frame[nframe - 1] == 2)
            {
              log_info (_("old encoding of the DEK is not supported\n"));
              err = gpg_error (GPG_ERR_CIPHER_ALGO);
              goto leave;
            }
          if (frame[n] != 2) /* Something went wrong.  */
            {
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
              goto leave;
            }
          for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes.  */
            ;
          n++; /* Skip the zero byte.  */
        }
    }

  if (n + 4 > nframe)
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }

  dek->keylen = nframe - (n + 1) - 2;
  dek->algo = frame[n++];
  if (dek->algo == CIPHER_ALGO_IDEA)
    write_status (STATUS_RSA_OR_IDEA);
  err = openpgp_cipher_test_algo (dek->algo);
  if (err)
    {
      if (!opt.quiet && gpg_err_code (err) == GPG_ERR_CIPHER_ALGO)
        {
          log_info (_("cipher algorithm %d%s is unknown or disabled\n"),
                    dek->algo,
                    dek->algo == CIPHER_ALGO_IDEA ? " (IDEA)" : "");
          if (dek->algo == CIPHER_ALGO_IDEA)
            idea_cipher_warn (0);
        }
      dek->algo = 0;
      goto leave;
    }
  if (dek->keylen != openpgp_cipher_get_algo_keylen (dek->algo))
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }

  /* Copy the key to DEK and compare the checksum.  */
  csum = frame[nframe - 2] << 8;
  csum |= frame[nframe - 1];
  memcpy (dek->key, frame + n, dek->keylen);
  for (csum2 = 0, n = 0; n < dek->keylen; n++)
    csum2 += dek->key[n];
  if (csum != csum2)
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }
  if (DBG_CIPHER)
    log_printhex ("DEK is:", dek->key, dek->keylen);

  /* Check that the algo is in the preferences and whether it has expired.  */
  {
    PKT_public_key *pk = NULL;
    KBNODE pkb = get_pubkeyblock (keyid);

    if (!pkb)
      {
        err = -1;
        log_error ("oops: public key not found for preference check\n");
      }
    else if (pkb->pkt->pkt.public_key->selfsigversion > 3
             && dek->algo != CIPHER_ALGO_3DES
             && !opt.quiet
             && !is_algo_in_prefs (pkb, PREFTYPE_SYM, dek->algo))
      log_info (_("WARNING: cipher algorithm %s not found in recipient"
                  " preferences\n"), openpgp_cipher_algo_name (dek->algo));
    if (!err)
      {
        KBNODE k;

        for (k = pkb; k; k = k->next)
          {
            if (k->pkt->pkttype == PKT_PUBLIC_KEY
                || k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
              {
                u32 aki[2];
                keyid_from_pk (k->pkt->pkt.public_key, aki);

                if (aki[0] == keyid[0] && aki[1] == keyid[1])
                  {
                    pk = k->pkt->pkt.public_key;
                    break;
                  }
              }
          }
        if (!pk)
          BUG ();
        if (pk->expiredate && pk->expiredate <= make_timestamp ())
          {
            log_info (_("NOTE: secret key %s expired at %s\n"),
                      keystr (keyid), asctimestamp (pk->expiredate));
          }
      }

    if (pk && pk->flags.revoked)
      {
        log_info (_("NOTE: key has been revoked"));
        log_printf ("\n");
        show_revocation_reason (pk, 1);
      }

    release_kbnode (pkb);
    err = 0;
  }

 leave:
  xfree (frame);
  xfree (keygrip);
  return err;
}
예제 #11
0
파일: keyserver.c 프로젝트: Juul/gnupg
/* code mostly stolen from do_export_stream */
static int
keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
{
  int rc=0,ndesc,num=100;
  KBNODE keyblock=NULL,node;
  KEYDB_HANDLE kdbhd;
  KEYDB_SEARCH_DESC *desc;
  strlist_t sl;

  *count=0;

  *klist=xmalloc(sizeof(KEYDB_SEARCH_DESC)*num);

  kdbhd=keydb_new ();

  if(!users)
    {
      ndesc = 1;
      desc = xmalloc_clear ( ndesc * sizeof *desc);
      desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
    }
  else
    {
      for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
	;
      desc = xmalloc ( ndesc * sizeof *desc);

      for (ndesc=0, sl=users; sl; sl = sl->next)
	{
          gpg_error_t err;
	  if (!(err = classify_user_id (sl->d, desc+ndesc, 1)))
	    ndesc++;
	  else
	    log_error (_("key \"%s\" not found: %s\n"),
		       sl->d, gpg_strerror (err));
	}
    }

  while (!(rc = keydb_search (kdbhd, desc, ndesc)))
    {
      if (!users)
	desc[0].mode = KEYDB_SEARCH_MODE_NEXT;

      /* read the keyblock */
      rc = keydb_get_keyblock (kdbhd, &keyblock );
      if( rc )
	{
	  log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
	  goto leave;
	}

      if((node=find_kbnode(keyblock,PKT_PUBLIC_KEY)))
	{
	  /* This is to work around a bug in some keyservers (pksd and
             OKS) that calculate v4 RSA keyids as if they were v3 RSA.
             The answer is to refresh both the correct v4 keyid
             (e.g. 99242560) and the fake v3 keyid (e.g. 68FDDBC7).
             This only happens for key refresh using the HKP scheme
             and if the refresh-add-fake-v3-keyids keyserver option is
             set. */
	  if(fakev3 && is_RSA(node->pkt->pkt.public_key->pubkey_algo) &&
	     node->pkt->pkt.public_key->version>=4)
	    {
	      (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID;
	      v3_keyid (node->pkt->pkt.public_key->pkey[0],
                        (*klist)[*count].u.kid);
	      (*count)++;

	      if(*count==num)
		{
		  num+=100;
		  *klist=xrealloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num);
		}
	    }

	  /* v4 keys get full fingerprints.  v3 keys get long keyids.
             This is because it's easy to calculate any sort of keyid
             from a v4 fingerprint, but not a v3 fingerprint. */

	  if(node->pkt->pkt.public_key->version<4)
	    {
	      (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID;
	      keyid_from_pk(node->pkt->pkt.public_key,
			    (*klist)[*count].u.kid);
	    }
	  else
	    {
	      size_t dummy;

	      (*klist)[*count].mode=KEYDB_SEARCH_MODE_FPR20;
	      fingerprint_from_pk(node->pkt->pkt.public_key,
				  (*klist)[*count].u.fpr,&dummy);
	    }

	  /* This is a little hackish, using the skipfncvalue as a
	     void* pointer to the keyserver spec, but we don't need
	     the skipfnc here, and it saves having an additional field
	     for this (which would be wasted space most of the
	     time). */

	  (*klist)[*count].skipfncvalue=NULL;

	  /* Are we honoring preferred keyservers? */
	  if(opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL)
	    {
	      PKT_user_id *uid=NULL;
	      PKT_signature *sig=NULL;

	      merge_keys_and_selfsig(keyblock);

	      for(node=node->next;node;node=node->next)
		{
		  if(node->pkt->pkttype==PKT_USER_ID
		     && node->pkt->pkt.user_id->is_primary)
		    uid=node->pkt->pkt.user_id;
		  else if(node->pkt->pkttype==PKT_SIGNATURE
			  && node->pkt->pkt.signature->
			  flags.chosen_selfsig && uid)
		    {
		      sig=node->pkt->pkt.signature;
		      break;
		    }
		}

	      /* Try and parse the keyserver URL.  If it doesn't work,
		 then we end up writing NULL which indicates we are
		 the same as any other key. */
	      if(sig)
		(*klist)[*count].skipfncvalue=parse_preferred_keyserver(sig);
	    }

	  (*count)++;

	  if(*count==num)
	    {
	      num+=100;
	      *klist=xrealloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num);
	    }
	}
    }

  if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
    rc = 0;

 leave:
  if(rc)
    xfree(*klist);
  xfree(desc);
  keydb_release(kdbhd);
  release_kbnode(keyblock);

  return rc;
}
예제 #12
0
파일: pubkey-enc.c 프로젝트: larryv/gnupg
static gpg_error_t
get_it (ctrl_t ctrl,
        PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
{
  gpg_error_t err;
  byte *frame = NULL;
  unsigned int n;
  size_t nframe;
  u16 csum, csum2;
  int padding;
  gcry_sexp_t s_data;
  char *desc;
  char *keygrip;
  byte fp[MAX_FINGERPRINT_LEN];
  size_t fpn;

  if (DBG_CLOCK)
    log_clock ("decryption start");

  /* Get the keygrip.  */
  err = hexkeygrip_from_pk (sk, &keygrip);
  if (err)
    goto leave;

  /* Convert the data to an S-expression.  */
  if (sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
      || sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E)
    {
      if (!enc->data[0] || !enc->data[1])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))",
                               enc->data[0], enc->data[1]);
    }
  else if (sk->pubkey_algo == PUBKEY_ALGO_RSA
           || sk->pubkey_algo == PUBKEY_ALGO_RSA_E)
    {
      if (!enc->data[0])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))",
                               enc->data[0]);
    }
  else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      if (!enc->data[0] || !enc->data[1])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(s%m)(e%m)))",
                               enc->data[1], enc->data[0]);
    }
  else
    err = gpg_error (GPG_ERR_BUG);

  if (err)
    goto leave;

  if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      fingerprint_from_pk (sk, fp, &fpn);
      log_assert (fpn == 20);
    }

  /* Decrypt. */
  desc = gpg_format_keydesc (ctrl, sk, FORMAT_KEYDESC_NORMAL, 1);
  err = agent_pkdecrypt (NULL, keygrip,
                         desc, sk->keyid, sk->main_keyid, sk->pubkey_algo,
                         s_data, &frame, &nframe, &padding);
  xfree (desc);
  gcry_sexp_release (s_data);
  if (err)
    goto leave;

  /* Now get the DEK (data encryption key) from the frame
   *
   * Old versions encode the DEK in this format (msb is left):
   *
   *     0  1  DEK(16 bytes)  CSUM(2 bytes)  0  RND(n bytes) 2
   *
   * Later versions encode the DEK like this:
   *
   *     0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
   *
   * (mpi_get_buffer already removed the leading zero).
   *
   * RND are non-zero randow bytes.
   * A   is the cipher algorithm
   * DEK is the encryption key (session key) with length k
   * CSUM
   */
  if (DBG_CRYPTO)
    log_printhex (frame, nframe, "DEK frame:");
  n = 0;

  if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      gcry_mpi_t shared_mpi;
      gcry_mpi_t decoded;

      /* At the beginning the frame are the bytes of shared point MPI.  */
      err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL);
      if (err)
        {
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
          goto leave;
        }

      err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/,
                             shared_mpi, sk->pkey);
      mpi_release (shared_mpi);
      if(err)
        goto leave;

      xfree (frame);
      err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, decoded);
      mpi_release (decoded);
      if (err)
        goto leave;

      /* Now the frame are the bytes decrypted but padded session key.  */

      /* Allow double padding for the benefit of DEK size concealment.
         Higher than this is wasteful. */
      if (!nframe || frame[nframe-1] > 8*2 || nframe <= 8
          || frame[nframe-1] > nframe)
        {
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
          goto leave;
        }
      nframe -= frame[nframe-1]; /* Remove padding.  */
      log_assert (!n); /* (used just below) */
    }
  else
    {
      if (padding)
        {
          if (n + 7 > nframe)
            {
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
              goto leave;
            }
          if (frame[n] == 1 && frame[nframe - 1] == 2)
            {
              log_info (_("old encoding of the DEK is not supported\n"));
              err = gpg_error (GPG_ERR_CIPHER_ALGO);
              goto leave;
            }
          if (frame[n] != 2) /* Something went wrong.  */
            {
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
              goto leave;
            }
          for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes.  */
            ;
          n++; /* Skip the zero byte.  */
        }
    }

  if (n + 4 > nframe)
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }

  dek->keylen = nframe - (n + 1) - 2;
  dek->algo = frame[n++];
  err = openpgp_cipher_test_algo (dek->algo);
  if (err)
    {
      if (!opt.quiet && gpg_err_code (err) == GPG_ERR_CIPHER_ALGO)
        {
          log_info (_("cipher algorithm %d%s is unknown or disabled\n"),
                    dek->algo,
                    dek->algo == CIPHER_ALGO_IDEA ? " (IDEA)" : "");
        }
      dek->algo = 0;
      goto leave;
    }
  if (dek->keylen != openpgp_cipher_get_algo_keylen (dek->algo))
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }

  /* Copy the key to DEK and compare the checksum.  */
  csum = buf16_to_u16 (frame+nframe-2);
  memcpy (dek->key, frame + n, dek->keylen);
  for (csum2 = 0, n = 0; n < dek->keylen; n++)
    csum2 += dek->key[n];
  if (csum != csum2)
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }
  if (DBG_CLOCK)
    log_clock ("decryption ready");
  if (DBG_CRYPTO)
    log_printhex (dek->key, dek->keylen, "DEK is:");

  /* Check that the algo is in the preferences and whether it has
   * expired.  Also print a status line with the key's fingerprint.  */
  {
    PKT_public_key *pk = NULL;
    PKT_public_key *mainpk = NULL;
    KBNODE pkb = get_pubkeyblock (ctrl, keyid);

    if (!pkb)
      {
        err = -1;
        log_error ("oops: public key not found for preference check\n");
      }
    else if (pkb->pkt->pkt.public_key->selfsigversion > 3
             && dek->algo != CIPHER_ALGO_3DES
             && !opt.quiet
             && !is_algo_in_prefs (pkb, PREFTYPE_SYM, dek->algo))
      log_info (_("WARNING: cipher algorithm %s not found in recipient"
                  " preferences\n"), openpgp_cipher_algo_name (dek->algo));

    if (!err)
      {
        kbnode_t k;
        int first = 1;

        for (k = pkb; k; k = k->next)
          {
            if (k->pkt->pkttype == PKT_PUBLIC_KEY
                || k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
              {
                u32 aki[2];

                if (first)
                  {
                    first = 0;
                    mainpk = k->pkt->pkt.public_key;
                  }

                keyid_from_pk (k->pkt->pkt.public_key, aki);
                if (aki[0] == keyid[0] && aki[1] == keyid[1])
                  {
                    pk = k->pkt->pkt.public_key;
                    break;
                  }
              }
          }
        if (!pk)
          BUG ();
        if (pk->expiredate && pk->expiredate <= make_timestamp ())
          {
            log_info (_("Note: secret key %s expired at %s\n"),
                      keystr (keyid), asctimestamp (pk->expiredate));
          }
      }

    if (pk && pk->flags.revoked)
      {
        log_info (_("Note: key has been revoked"));
        log_printf ("\n");
        show_revocation_reason (ctrl, pk, 1);
      }

    if (is_status_enabled () && pk && mainpk)
      {
        char pkhex[MAX_FINGERPRINT_LEN*2+1];
        char mainpkhex[MAX_FINGERPRINT_LEN*2+1];

        hexfingerprint (pk, pkhex, sizeof pkhex);
        hexfingerprint (mainpk, mainpkhex, sizeof mainpkhex);

        /* Note that we do not want to create a trustdb just for
         * getting the ownertrust: If there is no trustdb there can't
         * be ulitmately trusted key anyway and thus the ownertrust
         * value is irrelevant.  */
        write_status_printf (STATUS_DECRYPTION_KEY, "%s %s %c",
                             pkhex, mainpkhex,
                             get_ownertrust_info (ctrl, mainpk, 1));

      }

    release_kbnode (pkb);
    err = 0;
  }

 leave:
  xfree (frame);
  xfree (keygrip);
  return err;
}
예제 #13
0
/*
 * Search through the keyring(s), starting at the current position,
 * for a keyblock which contains one of the keys described in the DESC array.
 */
int
keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
		size_t ndesc, size_t *descindex, int ignore_legacy)
{
  int rc;
  PACKET pkt;
  struct parse_packet_ctx_s parsectx;
  int save_mode;
  off_t offset, main_offset;
  size_t n;
  int need_uid, need_words, need_keyid, need_fpr, any_skip;
  int pk_no, uid_no;
  int initial_skip;
  int scanned_from_start;
  int use_key_present_hash;
  PKT_user_id *uid = NULL;
  PKT_public_key *pk = NULL;
  u32 aki[2];

  /* figure out what information we need */
  need_uid = need_words = need_keyid = need_fpr = any_skip = 0;
  for (n=0; n < ndesc; n++)
    {
      switch (desc[n].mode)
        {
        case KEYDB_SEARCH_MODE_EXACT:
        case KEYDB_SEARCH_MODE_SUBSTR:
        case KEYDB_SEARCH_MODE_MAIL:
        case KEYDB_SEARCH_MODE_MAILSUB:
        case KEYDB_SEARCH_MODE_MAILEND:
          need_uid = 1;
          break;
        case KEYDB_SEARCH_MODE_WORDS:
          need_uid = 1;
          need_words = 1;
          break;
        case KEYDB_SEARCH_MODE_SHORT_KID:
        case KEYDB_SEARCH_MODE_LONG_KID:
          need_keyid = 1;
          break;
        case KEYDB_SEARCH_MODE_FPR16:
        case KEYDB_SEARCH_MODE_FPR20:
        case KEYDB_SEARCH_MODE_FPR:
          need_fpr = 1;
          break;
        case KEYDB_SEARCH_MODE_FIRST:
          /* always restart the search in this mode */
          keyring_search_reset (hd);
          break;
        default: break;
	}
      if (desc[n].skipfnc)
        {
          any_skip = 1;
          need_keyid = 1;
        }
    }

  if (DBG_LOOKUP)
    log_debug ("%s: need_uid = %d; need_words = %d; need_keyid = %d; need_fpr = %d; any_skip = %d\n",
               __func__, need_uid, need_words, need_keyid, need_fpr, any_skip);

  rc = prepare_search (hd);
  if (rc)
    {
      if (DBG_LOOKUP)
        log_debug ("%s: prepare_search failed: %s (%d)\n",
                   __func__, gpg_strerror (rc), gpg_err_code (rc));
      return rc;
    }

  use_key_present_hash = !!key_present_hash;
  if (!use_key_present_hash)
    {
      if (DBG_LOOKUP)
        log_debug ("%s: no offset table.\n", __func__);
    }
  else if (!key_present_hash_ready)
    {
      if (DBG_LOOKUP)
        log_debug ("%s: initializing offset table. (need_keyid: %d => 1)\n",
                   __func__, need_keyid);
      need_keyid = 1;
    }
  else if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID)
    {
      struct key_present *oi;

      if (DBG_LOOKUP)
        log_debug ("%s: look up by long key id, checking cache\n", __func__);

      oi = key_present_hash_lookup (key_present_hash, desc[0].u.kid);
      if (!oi)
        { /* We know that we don't have this key */
          if (DBG_LOOKUP)
            log_debug ("%s: cache says not present\n", __func__);
          hd->found.kr = NULL;
          hd->current.eof = 1;
          return -1;
        }
      /* We could now create a positive search status and return.
       * However the problem is that another instance of gpg may
       * have changed the keyring so that the offsets are not valid
       * anymore - therefore we don't do it
       */
    }

  if (need_words)
    {
      const char *name = NULL;

      log_debug ("word search mode does not yet work\n");
      /* FIXME: here is a long standing bug in our function and in addition we
         just use the first search description */
      for (n=0; n < ndesc && !name; n++)
        {
          if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS)
            name = desc[n].u.name;
        }
      log_assert (name);
      if ( !hd->word_match.name || strcmp (hd->word_match.name, name) )
        {
          /* name changed */
          xfree (hd->word_match.name);
          xfree (hd->word_match.pattern);
          hd->word_match.name = xstrdup (name);
          hd->word_match.pattern = prepare_word_match (name);
        }
      /*  name = hd->word_match.pattern; */
    }

  init_packet(&pkt);
  save_mode = set_packet_list_mode(0);

  hd->found.kr = NULL;
  main_offset = 0;
  pk_no = uid_no = 0;
  initial_skip = 1; /* skip until we see the start of a keyblock */
  scanned_from_start = iobuf_tell (hd->current.iobuf) == 0;
  if (DBG_LOOKUP)
    log_debug ("%s: %ssearching from start of resource.\n",
               __func__, scanned_from_start ? "" : "not ");
  init_parse_packet (&parsectx, hd->current.iobuf);
  while (1)
    {
      byte afp[MAX_FINGERPRINT_LEN];
      size_t an;

      rc = search_packet (&parsectx, &pkt, &offset, need_uid);
      if (ignore_legacy && gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
        {
          free_packet (&pkt, &parsectx);
          continue;
        }
      if (rc)
        break;

      if (pkt.pkttype == PKT_PUBLIC_KEY  || pkt.pkttype == PKT_SECRET_KEY)
        {
          main_offset = offset;
          pk_no = uid_no = 0;
          initial_skip = 0;
        }
      if (initial_skip)
        {
          free_packet (&pkt, &parsectx);
          continue;
        }

      pk = NULL;
      uid = NULL;
      if (   pkt.pkttype == PKT_PUBLIC_KEY
             || pkt.pkttype == PKT_PUBLIC_SUBKEY
             || pkt.pkttype == PKT_SECRET_KEY
             || pkt.pkttype == PKT_SECRET_SUBKEY)
        {
          pk = pkt.pkt.public_key;
          ++pk_no;

          if (need_fpr) {
            fingerprint_from_pk (pk, afp, &an);
            while (an < 20) /* fill up to 20 bytes */
              afp[an++] = 0;
          }
          if (need_keyid)
            keyid_from_pk (pk, aki);

          if (use_key_present_hash
              && !key_present_hash_ready
              && scanned_from_start)
            key_present_hash_update (key_present_hash, aki);
        }
      else if (pkt.pkttype == PKT_USER_ID)
        {
          uid = pkt.pkt.user_id;
          ++uid_no;
        }

      for (n=0; n < ndesc; n++)
        {
          switch (desc[n].mode) {
          case KEYDB_SEARCH_MODE_NONE:
            BUG ();
            break;
          case KEYDB_SEARCH_MODE_EXACT:
          case KEYDB_SEARCH_MODE_SUBSTR:
          case KEYDB_SEARCH_MODE_MAIL:
          case KEYDB_SEARCH_MODE_MAILSUB:
          case KEYDB_SEARCH_MODE_MAILEND:
          case KEYDB_SEARCH_MODE_WORDS:
            if ( uid && !compare_name (desc[n].mode,
                                       desc[n].u.name,
                                       uid->name, uid->len))
              goto found;
            break;

          case KEYDB_SEARCH_MODE_SHORT_KID:
            if (pk && desc[n].u.kid[1] == aki[1])
              goto found;
            break;
          case KEYDB_SEARCH_MODE_LONG_KID:
            if (pk && desc[n].u.kid[0] == aki[0]
                && desc[n].u.kid[1] == aki[1])
              goto found;
            break;
          case KEYDB_SEARCH_MODE_FPR16:
            if (pk && !memcmp (desc[n].u.fpr, afp, 16))
              goto found;
            break;
          case KEYDB_SEARCH_MODE_FPR20:
          case KEYDB_SEARCH_MODE_FPR:
            if (pk && !memcmp (desc[n].u.fpr, afp, 20))
              goto found;
            break;
          case KEYDB_SEARCH_MODE_FIRST:
            if (pk)
              goto found;
            break;
          case KEYDB_SEARCH_MODE_NEXT:
            if (pk)
              goto found;
            break;
          default:
            rc = GPG_ERR_INV_ARG;
            goto found;
          }
	}
      free_packet (&pkt, &parsectx);
      continue;
    found:
      if (rc)
        goto real_found;

      if (DBG_LOOKUP)
        log_debug ("%s: packet starting at offset %lld matched descriptor %zu\n"
                   , __func__, (long long)offset, n);

      /* Record which desc we matched on.  Note this value is only
	 meaningful if this function returns with no errors. */
      if(descindex)
	*descindex=n;
      for (n=any_skip?0:ndesc; n < ndesc; n++)
        {
          if (desc[n].skipfnc
              && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid_no))
            {
              if (DBG_LOOKUP)
                log_debug ("%s: skipping match: desc %zd's skip function returned TRUE\n",
                           __func__, n);
              break;
            }
        }
      if (n == ndesc)
        goto real_found;
      free_packet (&pkt, &parsectx);
    }
 real_found:
  if (!rc)
    {
      if (DBG_LOOKUP)
        log_debug ("%s: returning success\n", __func__);
      hd->found.offset = main_offset;
      hd->found.kr = hd->current.kr;
      hd->found.pk_no = pk? pk_no : 0;
      hd->found.uid_no = uid? uid_no : 0;
    }
  else if (rc == -1)
    {
      if (DBG_LOOKUP)
        log_debug ("%s: no matches (EOF)\n", __func__);

      hd->current.eof = 1;
      /* if we scanned all keyrings, we are sure that
       * all known key IDs are in our offtbl, mark that. */
      if (use_key_present_hash
          && !key_present_hash_ready
          && scanned_from_start)
        {
          KR_RESOURCE kr;

          /* First set the did_full_scan flag for this keyring.  */
          for (kr=kr_resources; kr; kr = kr->next)
            {
              if (hd->resource == kr)
                {
                  kr->did_full_scan = 1;
                  break;
                }
            }
          /* Then check whether all flags are set and if so, mark the
             offtbl ready */
          for (kr=kr_resources; kr; kr = kr->next)
            {
              if (!kr->did_full_scan)
                break;
            }
          if (!kr)
            key_present_hash_ready = 1;
        }
    }
  else
    {
      if (DBG_LOOKUP)
        log_debug ("%s: error encountered during search: %s (%d)\n",
                   __func__, gpg_strerror (rc), rc);
      hd->current.error = rc;
    }

  free_packet (&pkt, &parsectx);
  deinit_parse_packet (&parsectx);
  set_packet_list_mode(save_mode);
  return rc;
}