Esempio n. 1
0
/*
 * Return the last found keyring.  Caller must free it.
 * The returned keyblock has the kbode flag bit 0 set for the node with
 * the public key used to locate the keyblock or flag bit 1 set for 
 * the user ID node.
 */
int
keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
{
    PACKET *pkt;
    int rc;
    KBNODE keyblock = NULL, node, lastnode;
    IOBUF a;
    int in_cert = 0;
    int pk_no = 0;
    int uid_no = 0;
    int save_mode;

    if (ret_kb)
        *ret_kb = NULL;

    if (!hd->found.kr)
        return -1; /* no successful search */

    a = iobuf_open (hd->found.kr->fname);
    if (!a)
      {
	log_error(_("can't open `%s'\n"), hd->found.kr->fname);
	return G10ERR_KEYRING_OPEN;
      }

    if (iobuf_seek (a, hd->found.offset) ) {
        log_error ("can't seek `%s'\n", hd->found.kr->fname);
	iobuf_close(a);
	return G10ERR_KEYRING_OPEN;
    }

    pkt = xmalloc (sizeof *pkt);
    init_packet (pkt);
    hd->found.n_packets = 0;;
    lastnode = NULL;
    save_mode = set_packet_list_mode(0);
    while ((rc=parse_packet (a, pkt)) != -1) {
        hd->found.n_packets++;
        if (rc == G10ERR_UNKNOWN_PACKET) {
	    free_packet (pkt);
	    init_packet (pkt);
	    continue;
	}
	if (rc) {  
            log_error ("keyring_get_keyblock: read error: %s\n",
                       g10_errstr(rc) );
            rc = G10ERR_INV_KEYRING;
            break;
        }
	if (pkt->pkttype == PKT_COMPRESSED) {
	    log_error ("skipped compressed packet in keyring\n");
	    free_packet(pkt);
	    init_packet(pkt);
	    continue;
        }

        if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
                        || pkt->pkttype == PKT_SECRET_KEY)) {
            hd->found.n_packets--; /* fix counter */
            break; /* ready */
        }

        in_cert = 1;
        if (pkt->pkttype == PKT_RING_TRUST) {
            /*(this code is duplicated after the loop)*/
            if ( lastnode 
                 && lastnode->pkt->pkttype == PKT_SIGNATURE
                 && (pkt->pkt.ring_trust->sigcache & 1) ) {
                /* this is a ring trust packet with a checked signature 
                 * status cache following directly a signature paket.
                 * Set the cache status into that signature packet */
                PKT_signature *sig = lastnode->pkt->pkt.signature;
                
                sig->flags.checked = 1;
                sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
            }
            /* reset lastnode, so that we set the cache status only from
             * the ring trust packet immediately folling a signature */
            lastnode = NULL;
        }
        else {
            node = lastnode = new_kbnode (pkt);
            if (!keyblock)
                keyblock = node;
            else
                add_kbnode (keyblock, node);

            if ( pkt->pkttype == PKT_PUBLIC_KEY
                 || pkt->pkttype == PKT_PUBLIC_SUBKEY
                 || pkt->pkttype == PKT_SECRET_KEY
                 || pkt->pkttype == PKT_SECRET_SUBKEY) {
                if (++pk_no == hd->found.pk_no)
                    node->flag |= 1;
            }
            else if ( pkt->pkttype == PKT_USER_ID) {
                if (++uid_no == hd->found.uid_no)
                    node->flag |= 2;
            }
        }

        pkt = xmalloc (sizeof *pkt);
        init_packet(pkt);
    }
    set_packet_list_mode(save_mode);

    if (rc == -1 && keyblock) 
	rc = 0; /* got the entire keyblock */

    if (rc || !ret_kb)
	release_kbnode (keyblock);
    else {
        /*(duplicated form the loop body)*/
        if ( pkt && pkt->pkttype == PKT_RING_TRUST
             && lastnode 
             && lastnode->pkt->pkttype == PKT_SIGNATURE
             && (pkt->pkt.ring_trust->sigcache & 1) ) {
            PKT_signature *sig = lastnode->pkt->pkt.signature;
            sig->flags.checked = 1;
            sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
        }
	*ret_kb = keyblock;
    }
    free_packet (pkt);
    xfree (pkt);
    iobuf_close(a);

    /* Make sure that future search operations fail immediately when
     * we know that we are working on a invalid keyring 
     */
    if (rc == G10ERR_INV_KEYRING)
        hd->current.error = rc;

    return rc;
}
Esempio n. 2
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;
}
Esempio n. 3
0
int
main( int argc, char **argv )
{
    ARGPARSE_ARGS pargs;
    int rc=0;
    STRLIST sl;
    STRLIST nrings=NULL;
    unsigned configlineno;

    log_set_name("gpgv");
    init_signals();
    i18n_init();
    opt.command_fd = -1; /* no command fd */
    opt.pgp2_workarounds = 1;
    opt.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE;
    opt.trust_model = TM_ALWAYS;
    opt.batch = 1;
    opt.weak_digests = NULL;

    opt.homedir = default_homedir ();

    tty_no_terminal(1);
    tty_batchmode(1);
    dotlock_disable ();

    set_native_charset (NULL); /* Try to auto set the character set */
    additional_weak_digest("MD5");

    pargs.argc = &argc;
    pargs.argv = &argv;
    pargs.flags=  1;  /* do not remove the args */
    while( optfile_parse( NULL, NULL, &configlineno, &pargs, opts) ) {
	switch( pargs.r_opt ) {
	  case oQuiet: opt.quiet = 1; break;
          case oVerbose: g10_opt_verbose++;
		  opt.verbose++; opt.list_sigs=1; break;
          case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
	  case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
	  case oLoggerFD: log_set_logfile( NULL, pargs.r.ret_int ); break;
	  case oHomedir: opt.homedir = pargs.r.ret_str; break;
	  case oWeakDigest: additional_weak_digest(pargs.r.ret_str); break;
	  case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
	  default : pargs.err = 2; break;
	}
    }

    if( log_get_errorcount(0) )
	g10_exit(2);

    g10_opt_homedir = opt.homedir;

    if( opt.verbose > 1 )
	set_packet_list_mode(1);

    if( !nrings )  /* no keyring given: use default one */
        keydb_add_resource ("trustedkeys" EXTSEP_S "gpg", 8, 0);
    for(sl = nrings; sl; sl = sl->next )
        keydb_add_resource (sl->d, 8, 0 );

    FREE_STRLIST(nrings);

    if( (rc = verify_signatures( argc, argv ) ))
        log_error("verify signatures failed: %s\n", g10_errstr(rc) );

    /* cleanup */
    g10_exit(0);
    return 8; /*NEVER REACHED*/
}
Esempio n. 4
0
static gpg_error_t
parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
                      const u32 *sigstatus, kbnode_t *r_keyblock)
{
  gpg_error_t err;
  PACKET *pkt;
  kbnode_t keyblock = NULL;
  kbnode_t node, *tail;
  int in_cert, save_mode;
  u32 n_sigs;
  int pk_count, uid_count;

  *r_keyblock = NULL;

  pkt = xtrymalloc (sizeof *pkt);
  if (!pkt)
    return gpg_error_from_syserror ();
  init_packet (pkt);
  save_mode = set_packet_list_mode (0);
  in_cert = 0;
  n_sigs = 0;
  tail = NULL;
  pk_count = uid_count = 0;
  while ((err = parse_packet (iobuf, pkt)) != -1)
    {
      if (gpg_err_code (err) == GPG_ERR_UNKNOWN_PACKET)
        {
          free_packet (pkt);
          init_packet (pkt);
          continue;
	}
      if (err)
        {
          log_error ("parse_keyblock_image: read error: %s\n",
                     gpg_strerror (err));
          err = gpg_error (GPG_ERR_INV_KEYRING);
          break;
        }
      if (pkt->pkttype == PKT_COMPRESSED)
        {
          log_error ("skipped compressed packet in keybox blob\n");
          free_packet(pkt);
          init_packet(pkt);
          continue;
        }
      if (pkt->pkttype == PKT_RING_TRUST)
        {
          log_info ("skipped ring trust packet in keybox blob\n");
          free_packet(pkt);
          init_packet(pkt);
          continue;
        }

      if (!in_cert && pkt->pkttype != PKT_PUBLIC_KEY)
        {
          log_error ("parse_keyblock_image: first packet in a keybox blob "
                     "is not a public key packet\n");
          err = gpg_error (GPG_ERR_INV_KEYRING);
          break;
        }
      if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
                      || pkt->pkttype == PKT_SECRET_KEY))
        {
          log_error ("parse_keyblock_image: "
                     "multiple keyblocks in a keybox blob\n");
          err = gpg_error (GPG_ERR_INV_KEYRING);
          break;
        }
      in_cert = 1;

      if (pkt->pkttype == PKT_SIGNATURE && sigstatus)
        {
          PKT_signature *sig = pkt->pkt.signature;

          n_sigs++;
          if (n_sigs > sigstatus[0])
            {
              log_error ("parse_keyblock_image: "
                         "more signatures than found in the meta data\n");
              err = gpg_error (GPG_ERR_INV_KEYRING);
              break;

            }
          if (sigstatus[n_sigs])
            {
              sig->flags.checked = 1;
              if (sigstatus[n_sigs] == 1 )
                ; /* missing key */
              else if (sigstatus[n_sigs] == 2 )
                ; /* bad signature */
              else if (sigstatus[n_sigs] < 0x10000000)
                ; /* bad flag */
              else
                {
                  sig->flags.valid = 1;
                  /* Fixme: Shall we set the expired flag here?  */
                }
            }
        }

      node = new_kbnode (pkt);

      switch (pkt->pkttype)
        {
        case PKT_PUBLIC_KEY:
        case PKT_PUBLIC_SUBKEY:
        case PKT_SECRET_KEY:
        case PKT_SECRET_SUBKEY:
          if (++pk_count == pk_no)
            node->flag |= 1;
          break;

        case PKT_USER_ID:
          if (++uid_count == uid_no)
            node->flag |= 2;
          break;

        default:
          break;
        }

      if (!keyblock)
        keyblock = node;
      else
        *tail = node;
      tail = &node->next;
      pkt = xtrymalloc (sizeof *pkt);
      if (!pkt)
        {
          err = gpg_error_from_syserror ();
          break;
        }
      init_packet (pkt);
    }
  set_packet_list_mode (save_mode);

  if (err == -1 && keyblock)
    err = 0; /* Got the entire keyblock.  */

  if (!err && sigstatus && n_sigs != sigstatus[0])
    {
      log_error ("parse_keyblock_image: signature count does not match\n");
      err = gpg_error (GPG_ERR_INV_KEYRING);
    }

  if (err)
    release_kbnode (keyblock);
  else
    *r_keyblock = keyblock;
  free_packet (pkt);
  xfree (pkt);
  return err;
}
Esempio n. 5
0
File: gpgv.c Progetto: gpg/gnupg
int
main( int argc, char **argv )
{
  ARGPARSE_ARGS pargs;
  int rc=0;
  strlist_t sl;
  strlist_t nrings = NULL;
  unsigned configlineno;
  ctrl_t ctrl;

  early_system_init ();
  set_strusage (my_strusage);
  log_set_prefix ("gpgv", 1);

  /* Make sure that our subsystems are ready.  */
  i18n_init();
  init_common_subsystems (&argc, &argv);

  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
    {
      log_fatal ( _("%s is too old (need %s, have %s)\n"), "libgcrypt",
                  NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
    }
  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);

  gnupg_init_signals (0, NULL);

  opt.command_fd = -1; /* no command fd */
  opt.keyserver_options.options |= KEYSERVER_AUTO_KEY_RETRIEVE;
  opt.trust_model = TM_ALWAYS;
  opt.batch = 1;

  opt.weak_digests = NULL;

  tty_no_terminal(1);
  tty_batchmode(1);
  dotlock_disable ();
  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
  additional_weak_digest("MD5");

  pargs.argc = &argc;
  pargs.argv = &argv;
  pargs.flags=  1;  /* do not remove the args */
  while (optfile_parse( NULL, NULL, &configlineno, &pargs, opts))
    {
      switch (pargs.r_opt)
        {
        case oQuiet: opt.quiet = 1; break;
        case oVerbose:
          opt.verbose++;
          opt.list_sigs=1;
          gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
          break;
        case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
        case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
        case oLoggerFD:
          log_set_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1));
          break;
        case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
        case oWeakDigest:
          additional_weak_digest(pargs.r.ret_str);
          break;
        case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
        default : pargs.err = ARGPARSE_PRINT_ERROR; break;
	}
    }

  if (log_get_errorcount (0))
    g10_exit(2);

  if (opt.verbose > 1)
    set_packet_list_mode(1);

  /* Note: We open all keyrings in read-only mode.  */
  if (!nrings)  /* No keyring given: use default one. */
    keydb_add_resource ("trustedkeys" EXTSEP_S "kbx",
                        (KEYDB_RESOURCE_FLAG_READONLY
                         |KEYDB_RESOURCE_FLAG_GPGVDEF));
  for (sl = nrings; sl; sl = sl->next)
    keydb_add_resource (sl->d, KEYDB_RESOURCE_FLAG_READONLY);

  FREE_STRLIST (nrings);

  ctrl = xcalloc (1, sizeof *ctrl);

  if ((rc = verify_signatures (ctrl, argc, argv)))
    log_error("verify signatures failed: %s\n", gpg_strerror (rc) );

  xfree (ctrl);

  /* cleanup */
  g10_exit (0);
  return 8; /*NOTREACHED*/
}
Esempio n. 6
0
/*
 * Return the last found keyring.  Caller must free it.
 * The returned keyblock has the kbode flag bit 0 set for the node with
 * the public key used to locate the keyblock or flag bit 1 set for
 * the user ID node.
 */
int
keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
{
    PACKET *pkt;
    int rc;
    KBNODE keyblock = NULL, node, lastnode;
    IOBUF a;
    int in_cert = 0;
    int pk_no = 0;
    int uid_no = 0;
    int save_mode;

    if (ret_kb)
        *ret_kb = NULL;

    if (!hd->found.kr)
        return -1; /* no successful search */

    a = iobuf_open (hd->found.kr->fname);
    if (!a)
      {
	log_error(_("can't open `%s'\n"), hd->found.kr->fname);
	return G10ERR_KEYRING_OPEN;
      }

    if (iobuf_seek (a, hd->found.offset) ) {
        log_error ("can't seek `%s'\n", hd->found.kr->fname);
	iobuf_close(a);
	return G10ERR_KEYRING_OPEN;
    }

    pkt = xmalloc (sizeof *pkt);
    init_packet (pkt);
    hd->found.n_packets = 0;;
    lastnode = NULL;
    save_mode = set_packet_list_mode(0);
    while ((rc=parse_packet (a, pkt)) != -1) {
        hd->found.n_packets++;
        if (rc == G10ERR_UNKNOWN_PACKET) {
	    free_packet (pkt);
	    init_packet (pkt);
	    continue;
	}
	if (rc) {
            log_error ("keyring_get_keyblock: read error: %s\n",
                       g10_errstr(rc) );
            rc = G10ERR_INV_KEYRING;
            break;
        }

        /* Filter allowed packets.  */
        switch (pkt->pkttype){
          case PKT_PUBLIC_KEY:
          case PKT_PUBLIC_SUBKEY:
          case PKT_SECRET_KEY:
          case PKT_SECRET_SUBKEY:
          case PKT_USER_ID:
          case PKT_ATTRIBUTE:
          case PKT_SIGNATURE:
            break; /* Allowed per RFC.  */
          case PKT_RING_TRUST:
          case PKT_OLD_COMMENT:
          case PKT_COMMENT:
          case PKT_GPG_CONTROL:
            break; /* Allowed by us.  */

          default:
	    log_error ("skipped packet of type %d in keyring\n",
                       (int)pkt->pkttype);
	    free_packet(pkt);
	    init_packet(pkt);
	    continue;
        }

        if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
                        || pkt->pkttype == PKT_SECRET_KEY)) {
            hd->found.n_packets--; /* fix counter */
            break; /* ready */
        }

        in_cert = 1;
        if (pkt->pkttype == PKT_RING_TRUST)
          {
            /*(this code is duplicated after the loop)*/
            if ( lastnode
                 && lastnode->pkt->pkttype == PKT_SIGNATURE
                 && (pkt->pkt.ring_trust->sigcache & 1) ) {
                /* This is a ring trust packet with a checked signature
                 * status cache following directly a signature paket.
                 * Set the cache status into that signature packet.
                 *
                 * We do not use cached signatures made with MD5 to
                 * avoid using a cached status created with an older
                 * version of gpg.  */
                PKT_signature *sig = lastnode->pkt->pkt.signature;

                if (sig->digest_algo != DIGEST_ALGO_MD5)
                  {
                    sig->flags.checked = 1;
                    sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
                  }
            }
            /* Reset LASTNODE, so that we set the cache status only from
             * the ring trust packet immediately following a signature. */
            lastnode = NULL;
	    free_packet(pkt);
	    init_packet(pkt);
	    continue;
          }


        node = lastnode = new_kbnode (pkt);
        if (!keyblock)
          keyblock = node;
        else
          add_kbnode (keyblock, node);
        switch (pkt->pkttype)
          {
          case PKT_PUBLIC_KEY:
          case PKT_PUBLIC_SUBKEY:
          case PKT_SECRET_KEY:
          case PKT_SECRET_SUBKEY:
            if (++pk_no == hd->found.pk_no)
              node->flag |= 1;
            break;

          case PKT_USER_ID:
            if (++uid_no == hd->found.uid_no)
              node->flag |= 2;
            break;

          default:
            break;
          }

        pkt = xmalloc (sizeof *pkt);
        init_packet(pkt);
    }
    set_packet_list_mode(save_mode);

    if (rc == -1 && keyblock)
	rc = 0; /* got the entire keyblock */

    if (rc || !ret_kb)
	release_kbnode (keyblock);
    else {
        /*(duplicated from the loop body)*/
        if ( pkt && pkt->pkttype == PKT_RING_TRUST
             && lastnode
             && lastnode->pkt->pkttype == PKT_SIGNATURE
             && (pkt->pkt.ring_trust->sigcache & 1) ) {
            PKT_signature *sig = lastnode->pkt->pkt.signature;
            if (sig->digest_algo != DIGEST_ALGO_MD5)
              {
                sig->flags.checked = 1;
                sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
              }
        }
	*ret_kb = keyblock;
    }
    free_packet (pkt);
    xfree (pkt);
    iobuf_close(a);

    /* Make sure that future search operations fail immediately when
     * we know that we are working on a invalid keyring
     */
    if (rc == G10ERR_INV_KEYRING)
        hd->current.error = rc;

    return rc;
}
Esempio n. 7
0
int
main( int argc, char **argv )
{
  ARGPARSE_ARGS pargs;
  int rc=0;
  strlist_t sl;
  strlist_t nrings=NULL;
  unsigned configlineno;
  
  set_strusage (my_strusage);
  log_set_prefix ("gpgv", 1);
  
  /* Make sure that our subsystems are ready.  */
  i18n_init();
  init_common_subsystems ();
  
  gnupg_init_signals (0, NULL);

  opt.command_fd = -1; /* no command fd */
  opt.pgp2_workarounds = 1;
  opt.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE;
  opt.trust_model = TM_ALWAYS;
  opt.batch = 1;

  opt.homedir = default_homedir ();

  tty_no_terminal(1);
  tty_batchmode(1);
  disable_dotlock();
  
  pargs.argc = &argc;
  pargs.argv = &argv;
  pargs.flags=  1;  /* do not remove the args */
  while (optfile_parse( NULL, NULL, &configlineno, &pargs, opts))
    {
      switch (pargs.r_opt)
        {
        case oQuiet: opt.quiet = 1; break;
        case oVerbose: 
          opt.verbose++; 
          opt.list_sigs=1;
          gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
          break;
        case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
        case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
        case oLoggerFD: 
          log_set_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1));
          break;
        case oHomedir: opt.homedir = pargs.r.ret_str; break;
        case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
        default : pargs.err = ARGPARSE_PRINT_ERROR; break;
	}
    }
  
  if (log_get_errorcount (0))
    g10_exit(2);

  if (opt.verbose > 1)
    set_packet_list_mode(1);

  /* Note: We open all keyrings in read-only mode (flag value: 8).  */
  if (!nrings)  /* No keyring given: use default one. */
    keydb_add_resource ("trustedkeys" EXTSEP_S "gpg", 8, 0);
  for (sl = nrings; sl; sl = sl->next)
    keydb_add_resource (sl->d, 8, 0 );
   
  FREE_STRLIST (nrings);
    
  if ( (rc = verify_signatures( argc, argv ) ))
    log_error("verify signatures failed: %s\n", g10_errstr(rc) );
  
  /* cleanup */
  g10_exit (0);
  return 8; /*NOTREACHED*/
}
Esempio n. 8
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;
}
Esempio n. 9
0
/*
 * Return the last found keyblock.  Caller must free it.
 * The returned keyblock has the kbode flag bit 0 set for the node with
 * the public key used to locate the keyblock or flag bit 1 set for
 * the user ID node.
 */
int
keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
{
    PACKET *pkt;
    struct parse_packet_ctx_s parsectx;
    int rc;
    KBNODE keyblock = NULL, node, lastnode;
    IOBUF a;
    int in_cert = 0;
    int pk_no = 0;
    int uid_no = 0;
    int save_mode;

    if (ret_kb)
        *ret_kb = NULL;

    if (!hd->found.kr)
        return -1; /* no successful search */

    a = iobuf_open (hd->found.kr->fname);
    if (!a)
      {
	log_error(_("can't open '%s'\n"), hd->found.kr->fname);
	return GPG_ERR_KEYRING_OPEN;
      }

    if (iobuf_seek (a, hd->found.offset) ) {
        log_error ("can't seek '%s'\n", hd->found.kr->fname);
	iobuf_close(a);
	return GPG_ERR_KEYRING_OPEN;
    }

    pkt = xmalloc (sizeof *pkt);
    init_packet (pkt);
    init_parse_packet (&parsectx, a);
    hd->found.n_packets = 0;
    lastnode = NULL;
    save_mode = set_packet_list_mode(0);
    while ((rc=parse_packet (&parsectx, pkt)) != -1) {
        hd->found.n_packets = parsectx.n_parsed_packets;
        if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) {
	    free_packet (pkt, &parsectx);
	    init_packet (pkt);
	    continue;
	}
        if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
          {
            if (in_cert)
              /* It is not this key that is problematic, but the
                 following key.  */
              {
                rc = 0;
                hd->found.n_packets --;
              }
            else
              /* Upper layer needs to handle this.  */
              {
              }
            break;
          }
	if (rc) {
            log_error ("keyring_get_keyblock: read error: %s\n",
                       gpg_strerror (rc) );
            rc = GPG_ERR_INV_KEYRING;
            break;
        }

        /* Filter allowed packets.  */
        switch (pkt->pkttype)
          {
          case PKT_PUBLIC_KEY:
          case PKT_PUBLIC_SUBKEY:
          case PKT_SECRET_KEY:
          case PKT_SECRET_SUBKEY:
          case PKT_USER_ID:
          case PKT_ATTRIBUTE:
          case PKT_SIGNATURE:
            break; /* Allowed per RFC.  */
          case PKT_RING_TRUST:
          case PKT_OLD_COMMENT:
          case PKT_COMMENT:
          case PKT_GPG_CONTROL:
            break; /* Allowed by us.  */

          default:
	    log_info ("skipped packet of type %d in keyring\n",
                      (int)pkt->pkttype);
	    free_packet(pkt, &parsectx);
	    init_packet(pkt);
	    continue;
          }

        if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
                        || pkt->pkttype == PKT_SECRET_KEY)) {
            hd->found.n_packets--; /* fix counter */
            break; /* ready */
        }

        in_cert = 1;
        node = lastnode = new_kbnode (pkt);
        if (!keyblock)
          keyblock = node;
        else
          add_kbnode (keyblock, node);
        switch (pkt->pkttype)
          {
          case PKT_PUBLIC_KEY:
          case PKT_PUBLIC_SUBKEY:
          case PKT_SECRET_KEY:
          case PKT_SECRET_SUBKEY:
            if (++pk_no == hd->found.pk_no)
              node->flag |= 1;
            break;

          case PKT_USER_ID:
            if (++uid_no == hd->found.uid_no)
              node->flag |= 2;
            break;

          default:
            break;
          }

        pkt = xmalloc (sizeof *pkt);
        init_packet(pkt);
    }
    set_packet_list_mode(save_mode);

    if (rc == -1 && keyblock)
	rc = 0; /* got the entire keyblock */

    if (rc || !ret_kb)
	release_kbnode (keyblock);
    else {
        *ret_kb = keyblock;
    }
    free_packet (pkt, &parsectx);
    deinit_parse_packet (&parsectx);
    xfree (pkt);
    iobuf_close(a);

    /* Make sure that future search operations fail immediately when
     * we know that we are working on a invalid keyring
     */
    if (gpg_err_code (rc) == GPG_ERR_INV_KEYRING)
        hd->current.error = rc;

    return rc;
}