Beispiel #1
0
static int
do_export( strlist_t users, int secret, unsigned int options )
{
  IOBUF out = NULL;
  int any, rc;
  armor_filter_context_t *afx = NULL;
  compress_filter_context_t zfx;
  
  memset( &zfx, 0, sizeof zfx);
  
  rc = open_outfile( NULL, 0, &out );
  if (rc)
    return rc;

  if (!(options & EXPORT_SEXP_FORMAT))
    {
      if ( opt.armor )
        {
          afx = new_armor_context ();
          afx->what = secret? 5 : 1;
          push_armor_filter (afx, out);
        }
      if ( opt.compress_keys )
        push_compress_filter (out,&zfx,default_compress_algo());
    }

  rc = do_export_stream ( out, users, secret, NULL, options, &any );

  if ( rc || !any )
    iobuf_cancel (out);
  else
    iobuf_close (out);
  release_armor_context (afx);
  return rc;
}
Beispiel #2
0
static int
do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
{
    int rc = 0;
    int n, i;
    IOBUF a = iobuf_temp();

    if( !pk->version )
	iobuf_put( a, 3 );
    else
	iobuf_put( a, pk->version );
    write_32(a, pk->timestamp );
    if( pk->version < 4 ) {
	u16 ndays;
	if( pk->expiredate )
	    ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
	else
	    ndays = 0;
	write_16(a, ndays );
    }
    iobuf_put(a, pk->pubkey_algo );
    n = pubkey_get_npkey( pk->pubkey_algo );
    if( !n )
	write_fake_data( a, pk->pkey[0] );
    for(i=0; i < n; i++ )
	mpi_write(a, pk->pkey[i] );

    write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 );
    if( iobuf_write_temp( out, a ) )
	rc = G10ERR_WRITE_FILE;

    iobuf_close(a);
    return rc;
}
Beispiel #3
0
/*
 * Try to open a file without the extension ".sig" or ".asc"
 * Return NULL if such a file is not available.
 */
iobuf_t
open_sigfile (const char *sigfilename, progress_filter_context_t *pfx)
{
  iobuf_t a = NULL;
  char *buf;

  buf = get_matching_datafile (sigfilename);
  if (buf)
    {
      a = iobuf_open (buf);
      if (a && is_secured_file (iobuf_get_fd (a)))
        {
          iobuf_close (a);
          a = NULL;
          gpg_err_set_errno (EPERM);
        }
      if (a)
        log_info (_("assuming signed data in '%s'\n"), buf);
      if (a && pfx)
        handle_progress (pfx, a, buf);
      xfree (buf);
    }

  return a;
}
Beispiel #4
0
static int
do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
{
  int rc = 0;
  int n, i;
  IOBUF a = iobuf_temp();
  
  write_version( a, ctb );
  if ( enc->throw_keyid ) 
    {
      write_32(a, 0 );  /* Don't tell Eve who can decrypt the message.  */
      write_32(a, 0 );
    }
  else
    {
      write_32(a, enc->keyid[0] );
      write_32(a, enc->keyid[1] );
    }
  iobuf_put(a,enc->pubkey_algo );
  n = pubkey_get_nenc( enc->pubkey_algo );
  if ( !n )
    write_fake_data( a, enc->data[0] );
  for (i=0; i < n && !rc ; i++ )
    rc = mpi_write(a, enc->data[i] );

  if (!rc)
    {
      write_header(out, ctb, iobuf_get_temp_length(a) );
      rc = iobuf_write_temp( out, a );
    }
  iobuf_close(a);
  return rc;
}
Beispiel #5
0
static int
do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
{
    int rc = 0;
    IOBUF a = iobuf_temp();

    assert( enc->version == 4 );
    switch( enc->s2k.mode ) {
      case 0: case 1: case 3: break;
      default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode );
    }
    iobuf_put( a, enc->version );
    iobuf_put( a, enc->cipher_algo );
    iobuf_put( a, enc->s2k.mode );
    iobuf_put( a, enc->s2k.hash_algo );
    if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) {
	iobuf_write(a, enc->s2k.salt, 8 );
	if( enc->s2k.mode == 3 )
	    iobuf_put(a, enc->s2k.count);
    }
    if( enc->seskeylen )
	iobuf_write(a, enc->seskey, enc->seskeylen );

    write_header(out, ctb, iobuf_get_temp_length(a) );
    rc = iobuf_write_temp( out, a );

    iobuf_close(a);
    return rc;
}
int
keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
{
    int rc;
    const char *fname;

    if (!hd)
        fname = NULL;
    else if (hd->found.kr)
        fname = hd->found.kr->fname;
    else if (hd->current.kr)
        fname = hd->current.kr->fname;
    else 
        fname = hd->resource? hd->resource->fname:NULL;

    if (!fname)
        return G10ERR_GENERAL; 

    /* close this one otherwise we will lose the position for
     * a next search.  Fixme: it would be better to adjust the position
     * after the write opertions.
     */
    iobuf_close (hd->current.iobuf);
    hd->current.iobuf = NULL;

    /* do the insert */
    rc = do_copy (1, fname, kb, hd->secret, 0, 0 );
    if (!rc && !hd->secret && kr_offtbl)
      {
        update_offset_hash_table_from_kb (kr_offtbl, kb, 0);
      }
      
    return rc;
}
Beispiel #7
0
int main(int argc, char **argv)
{
	gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
	int l;
	int ret;
	armor_filter_context_t *afx = NULL;

	while (fgets(passphrase, N, stdin) != NULL && status == 0) {
		IOBUF a;
		struct stat sb;
		unlink("output");
		l = strlen(passphrase);
		passphrase[l - 1] = 0;
		status = 1;
		a = iobuf_open(argv[1]);
		if( use_armor_filter( a ) ) {
			afx = new_armor_context ();
			push_armor_filter (afx, a);
		}
		proc_packets(NULL, a);
		ret = stat("output", &sb);
		if (status == 1 && sb.st_size > 0 && ret != -1) {
			printf("Found Password : %s\n", passphrase);
			exit(0);
		} else {
			status = 0;
		}
		iobuf_close(a);
	}
	return -1;
}
Beispiel #8
0
/****************
 * Take file and write it out with armor
 */
int
enarmor_file( const char *fname )
{
    armor_filter_context_t *afx;
    IOBUF inp = NULL, out = NULL;
    int rc = 0;
    int c;

    afx = new_armor_context ();

    /* prepare iobufs */
    inp = iobuf_open(fname);
    if (inp && is_secured_file (iobuf_get_fd (inp)))
      {
        iobuf_close (inp);
        inp = NULL;
        errno = EPERM;
      }
    if (!inp) {
        rc = gpg_error_from_syserror ();
	log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]",
                  strerror(errno) );
	goto leave;
    }


    if( (rc = open_outfile( fname, 1, &out )) )
	goto leave;

    afx->what = 4;
    afx->hdrlines = "Comment: Use \"gpg --dearmor\" for unpacking\n";
    push_armor_filter ( afx, out );

    while( (c = iobuf_get(inp)) != -1 )
	iobuf_put( out, c );


  leave:
    if( rc )
	iobuf_cancel(out);
    else
	iobuf_close(out);
    iobuf_close(inp);
    release_armor_context (afx);
    return rc;
}
Beispiel #9
0
/*
 * Insert a new KB into one of the resources.
 */
gpg_error_t
keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
{
  gpg_error_t err;
  int idx;

  if (!hd)
    return gpg_error (GPG_ERR_INV_ARG);

  keyblock_cache_clear ();

  if (opt.dry_run)
    return 0;

  if (hd->found >= 0 && hd->found < hd->used)
    idx = hd->found;
  else if (hd->current >= 0 && hd->current < hd->used)
    idx = hd->current;
  else
    return gpg_error (GPG_ERR_GENERAL);

  err = lock_all (hd);
  if (err)
    return err;

  switch (hd->active[idx].type)
    {
    case KEYDB_RESOURCE_TYPE_NONE:
      err = gpg_error (GPG_ERR_GENERAL); /* oops */
      break;
    case KEYDB_RESOURCE_TYPE_KEYRING:
      err = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
      break;
    case KEYDB_RESOURCE_TYPE_KEYBOX:
      { /* We need to turn our kbnode_t list of packets into a proper
           keyblock first.  This is required by the OpenPGP key parser
           included in the keybox code.  Eventually we can change this
           kludge to have the caller pass the image.  */
        iobuf_t iobuf;
        u32 *sigstatus;

        err = build_keyblock_image (kb, &iobuf, &sigstatus);
        if (!err)
          {
            err = keybox_insert_keyblock (hd->active[idx].u.kb,
                                          iobuf_get_temp_buffer (iobuf),
                                          iobuf_get_temp_length (iobuf),
                                          sigstatus);
            xfree (sigstatus);
            iobuf_close (iobuf);
          }
      }
      break;
    }

  unlock_all (hd);
  return err;
}
Beispiel #10
0
static int
verify_one_file (ctrl_t ctrl, const char *name )
{
    IOBUF fp;
    armor_filter_context_t *afx = NULL;
    progress_filter_context_t *pfx = new_progress_context ();
    int rc;

    print_file_status( STATUS_FILE_START, name, 1 );
    fp = iobuf_open(name);
    if (fp)
      iobuf_ioctl (fp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
    if (fp && is_secured_file (iobuf_get_fd (fp)))
      {
        iobuf_close (fp);
        fp = NULL;
        gpg_err_set_errno (EPERM);
      }
    if( !fp ) {
        rc = gpg_error_from_syserror ();
	log_error(_("can't open '%s': %s\n"),
                  print_fname_stdin(name), strerror (errno));
	print_file_status( STATUS_FILE_ERROR, name, 1 );
        goto leave;
    }
    handle_progress (pfx, fp, name);

    if( !opt.no_armor ) {
	if( use_armor_filter( fp ) ) {
            afx = new_armor_context ();
	    push_armor_filter (afx, fp);
	}
    }

    rc = proc_signature_packets (ctrl, NULL, fp, NULL, name );
    iobuf_close(fp);
    write_status( STATUS_FILE_DONE );

    reset_literals_seen();

 leave:
    release_armor_context (afx);
    release_progress_context (pfx);
    return rc;
}
Beispiel #11
0
static void
keyblock_cache_clear (void)
{
  keyblock_cache.state = KEYBLOCK_CACHE_EMPTY;
  xfree (keyblock_cache.sigstatus);
  keyblock_cache.sigstatus = NULL;
  iobuf_close (keyblock_cache.iobuf);
  keyblock_cache.iobuf = NULL;
}
Beispiel #12
0
int
exec_finish(struct exec_info *info)
{
  int ret=info->progreturn;

  if(info->fromchild)
    iobuf_close(info->fromchild);

  if(info->tochild)
    fclose(info->tochild);

#ifndef EXEC_TEMPFILE_ONLY
  if(info->child>0)
    {
      if(waitpid(info->child,&info->progreturn,0)!=0 &&
	 WIFEXITED(info->progreturn))
	ret=WEXITSTATUS(info->progreturn);
      else
	{
	  log_error(_("unnatural exit of external program\n"));
	  ret=127;
	}
    }
#endif

  if(info->flags.madedir && !info->flags.keep_temp_files)
    {
      if(info->tempfile_in)
	{
	  if(unlink(info->tempfile_in)==-1)
	    log_info(_("WARNING: unable to remove tempfile (%s) `%s': %s\n"),
		     "in",info->tempfile_in,strerror(errno));
	}
  
      if(info->tempfile_out)
	{
	  if(unlink(info->tempfile_out)==-1)
	    log_info(_("WARNING: unable to remove tempfile (%s) `%s': %s\n"),
		     "out",info->tempfile_out,strerror(errno));
	}

      if(rmdir(info->tempdir)==-1)
	log_info(_("WARNING: unable to remove temp directory `%s': %s\n"),
		 info->tempdir,strerror(errno));
    }

  xfree(info->command);
  xfree(info->name);
  xfree(info->tempdir);
  xfree(info->tempfile_in);
  xfree(info->tempfile_out);
  xfree(info);

  return ret;
}
void 
keyring_release (KEYRING_HANDLE hd)
{
    if (!hd)
        return;
    assert (active_handles > 0);
    active_handles--;
    xfree (hd->word_match.name);
    xfree (hd->word_match.pattern);
    iobuf_close (hd->current.iobuf);
    xfree (hd);
}
Beispiel #14
0
int
main(int argc,char *argv[])
{
  unsigned char *fpr;
  size_t fpr_len;
  char *url;
  int rc;
  IOBUF iobuf;

  if(argc!=2)
    {
      printf("cert-test [name]\n");
      return 1;
    }

  printf("CERT lookup on %s\n",argv[1]);

  rc=get_cert(argv[1],16384,&iobuf,&fpr,&fpr_len,&url);
  if(rc==-1)
    printf("error\n");
  else if(rc==0)
    printf("no answer\n");
  else if(rc==1)
    {
      printf("key found: %d bytes\n",(int)iobuf_get_temp_length(iobuf));
      iobuf_close(iobuf);
    }
  else if(rc==2)
    {
      if(fpr)
	{
	  size_t i;
	  printf("Fingerprint found (%d bytes): ",(int)fpr_len);
	  for(i=0;i<fpr_len;i++)
	    printf("%02X",fpr[i]);
	  printf("\n");
	}
      else
	printf("No fingerprint found\n");

      if(url)
	printf("URL found: %s\n",url);
      else
	printf("No URL found\n");

      xfree(fpr);
      xfree(url);
    }

  return 0;
}
/* 
 * Start the next search on this handle right at the beginning
 */
int 
keyring_search_reset (KEYRING_HANDLE hd)
{
    assert (hd);

    hd->current.kr = NULL;
    iobuf_close (hd->current.iobuf);
    hd->current.iobuf = NULL;
    hd->current.eof = 0;
    hd->current.error = 0;
    
    hd->found.kr = NULL;
    hd->found.offset = 0;
    return 0; 
}
static int
do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
{
  int rc = 0;
  int n, i;
  IOBUF a = iobuf_temp();

  if ( !pk->version )
    iobuf_put( a, 3 );
  else
    iobuf_put( a, pk->version );
  write_32(a, pk->timestamp );

  if ( pk->version < 4 )
    {
      u16 ndays;
      if ( pk->expiredate )
        ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
      else
        ndays = 0;
      write_16(a, ndays );
    }
  iobuf_put (a, pk->pubkey_algo );



  if ( pk->pubkey_algo == PUBKEY_ALGO_NTRU){

    rc = sexp_write(a, pk->ntru_pkey);
  }
  else
  {
	  n = pubkey_get_npkey ( pk->pubkey_algo );

	  if ( !n )
	    write_fake_data( a, pk->pkey[0] );
  }

  if (!rc)
    {
      write_header2 (out, ctb, iobuf_get_temp_length(a), pk->hdrbytes);
      printf("write output\n");
      rc = iobuf_write_temp ( out, a );
    }
  printf("finished writing\n");
  iobuf_close(a);
  return rc;
}
Beispiel #17
0
/****************
 * Check if the file is compressed.
 **/
int
is_file_compressed( const char *s, int *ret_rc )
{
    IOBUF a;
    byte buf[4];
    int i, rc = 0;

    struct magic_compress_s {
        size_t len;
        byte magic[4];
    } magic[] = {
        { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
        { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
        { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
    };
    
    if ( !s || *s == '-' || !ret_rc )
        return 0; /* We can't check stdin or no file was given */

    a = iobuf_open( s );
    if ( a == NULL ) {
        *ret_rc = G10ERR_OPEN_FILE;
        return 0;
    }

    if ( iobuf_get_filelength( a ) < 4 ) {
        *ret_rc = 0;
        goto leave;
    }

    if ( iobuf_read( a, buf, 4 ) == -1 ) {
        *ret_rc = G10ERR_READ_FILE;
        goto leave;
    }

    for ( i = 0; i < DIM( magic ); i++ ) {
        if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
            *ret_rc = 0;
            rc = 1;
            break;
        }
    }

leave:    
    iobuf_close( a );
    return rc;
}
Beispiel #18
0
/* Perform a verify operation.  To verify detached signatures, DATA_FD
   shall be the descriptor of the signed data; for regular signatures
   it needs to be -1.  If OUT_FP is not NULL and DATA_FD is not -1 the
   the signed material gets written that stream.

   FIXME: OUTFP is not yet implemented.
*/
int
gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, estream_t out_fp)
{
  int rc;
  iobuf_t fp;
  armor_filter_context_t *afx = NULL;
  progress_filter_context_t *pfx = new_progress_context ();

  (void)ctrl;
  (void)out_fp;

  if (is_secured_file (sig_fd))
    {
      fp = NULL;
      gpg_err_set_errno (EPERM);
    }
  else
    fp = iobuf_fdopen_nc (sig_fd, "rb");
  if (!fp)
    {
      rc = gpg_error_from_syserror ();
      log_error (_("can't open fd %d: %s\n"), sig_fd, strerror (errno));
      goto leave;
    }

  handle_progress (pfx, fp, NULL);

  if ( !opt.no_armor && use_armor_filter (fp) )
    {
      afx = new_armor_context ();
      push_armor_filter (afx, fp);
    }

  rc = proc_signature_packets_by_fd (ctrl, NULL, fp, data_fd);

  if ( afx && afx->no_openpgp_data
       && (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) )
    rc = gpg_error (GPG_ERR_NO_DATA);

 leave:
  iobuf_close (fp);
  release_progress_context (pfx);
  release_armor_context (afx);
  return rc;
}
Beispiel #19
0
int
keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
{
	printf("starting keyring_insert_keyblock\n" );
    int rc;
    const char *fname;

    if (!hd)
        fname = NULL;
    else if (hd->found.kr)
      {
        fname = hd->found.kr->fname;
        if (hd->found.kr->readonly)
          return gpg_error (GPG_ERR_EACCES);
      }
    else if (hd->current.kr)
      {
        fname = hd->current.kr->fname;
        if (hd->current.kr->readonly)
          return gpg_error (GPG_ERR_EACCES);
      }
    else
        fname = hd->resource? hd->resource->fname:NULL;

    if (!fname)
        return G10ERR_GENERAL;

    /* Close this one otherwise we will lose the position for
     * a next search.  Fixme: it would be better to adjust the position
     * after the write opertions.
     */
    iobuf_close (hd->current.iobuf);
    hd->current.iobuf = NULL;
    printf("before do copy\n");
    /* do the insert */
    rc = do_copy (1, fname, kb, hd->secret, 0, 0 );
    printf("after do copy\n");
    if (!rc && !hd->secret && kr_offtbl)
      {
        update_offset_hash_table_from_kb (kr_offtbl, kb, 0);
      }
	printf("finish keyring_insert_keyblock\n" );
    return rc;
}
Beispiel #20
0
int
keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
{
    int rc;
    const char *fname;

    if (!hd)
        fname = NULL;
    else if (hd->found.kr)
      {
        fname = hd->found.kr->fname;
        if (hd->found.kr->read_only)
          return gpg_error (GPG_ERR_EACCES);
      }
    else if (hd->current.kr)
      {
        fname = hd->current.kr->fname;
        if (hd->current.kr->read_only)
          return gpg_error (GPG_ERR_EACCES);
      }
    else
        fname = hd->resource? hd->resource->fname:NULL;

    if (!fname)
        return GPG_ERR_GENERAL;

    /* Close this one otherwise we will lose the position for
     * a next search.  Fixme: it would be better to adjust the position
     * after the write opertions.
     */
    iobuf_close (hd->current.iobuf);
    hd->current.iobuf = NULL;

    /* do the insert */
    rc = do_copy (1, fname, kb, 0, 0 );
    if (!rc && key_present_hash)
      {
        key_present_hash_update_from_kb (key_present_hash, kb);
      }

    return rc;
}
Beispiel #21
0
int
keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb)
{
    int rc;

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

    if (hd->found.kr->readonly)
      return gpg_error (GPG_ERR_EACCES);

    if (!hd->found.n_packets) {
        /* need to know the number of packets - do a dummy get_keyblock*/
        rc = keyring_get_keyblock (hd, NULL);
        if (rc) {
            log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc));
            return rc;
        }
        if (!hd->found.n_packets)
            BUG ();
    }

    /* The open iobuf isn't needed anymore and in fact is a problem when
       it comes to renaming the keyring files on some operating systems,
       so close it here */
    iobuf_close(hd->current.iobuf);
    hd->current.iobuf = NULL;

    /* do the update */
    rc = do_copy (3, hd->found.kr->fname, kb, hd->secret,
                  hd->found.offset, hd->found.n_packets );
    if (!rc) {
      if (!hd->secret && kr_offtbl)
        {
          update_offset_hash_table_from_kb (kr_offtbl, kb, 0);
        }
      /* better reset the found info */
      hd->found.kr = NULL;
      hd->found.offset = 0;
    }
    return rc;
}
Beispiel #22
0
static int
prepare_search (KEYRING_HANDLE hd)
{
    if (hd->current.error)
        return hd->current.error; /* still in error state */

    if (hd->current.kr && !hd->current.eof) {
        if ( !hd->current.iobuf )
            return G10ERR_GENERAL; /* position invalid after a modify */
        return 0; /* okay */
    }

    if (!hd->current.kr && hd->current.eof)
        return -1; /* still EOF */

    if (!hd->current.kr) { /* start search with first keyring */
        hd->current.kr = hd->resource;
        if (!hd->current.kr) {
            hd->current.eof = 1;
            return -1; /* keyring not available */
        }
        assert (!hd->current.iobuf);
    }
    else { /* EOF */
        iobuf_close (hd->current.iobuf);
        hd->current.iobuf = NULL;
        hd->current.kr = NULL;
        hd->current.eof = 1;
        return -1;
    }

    hd->current.eof = 0;
    hd->current.iobuf = iobuf_open (hd->current.kr->fname);
    if (!hd->current.iobuf)
      {
        hd->current.error = gpg_error_from_syserror ();
        log_error(_("can't open `%s'\n"), hd->current.kr->fname );
        return hd->current.error;
      }

    return 0;
}
Beispiel #23
0
/*
 * Start the next search on this handle right at the beginning
 */
int
keyring_search_reset (KEYRING_HANDLE hd)
{
    log_assert (hd);

    iobuf_close (hd->current.iobuf);
    hd->current.iobuf = NULL;
    hd->current.eof = 0;
    hd->current.error = 0;

    hd->found.kr = NULL;
    hd->found.offset = 0;

    if (hd->current.kr)
      iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0,
                   (char*)hd->current.kr->fname);
    hd->current.kr = NULL;

    return 0;
}
Beispiel #24
0
int
keyring_delete_keyblock (KEYRING_HANDLE hd)
{
    int rc;

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

    if (hd->found.kr->readonly)
      return gpg_error (GPG_ERR_EACCES);

    if (!hd->found.n_packets) {
        /* need to know the number of packets - do a dummy get_keyblock*/
        rc = keyring_get_keyblock (hd, NULL);
        if (rc) {
            log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc));
            return rc;
        }
        if (!hd->found.n_packets)
            BUG ();
    }

    /* close this one otherwise we will lose the position for
     * a next search.  Fixme: it would be better to adjust the position
     * after the write opertions.
     */
    iobuf_close (hd->current.iobuf);
    hd->current.iobuf = NULL;

    /* do the delete */
    rc = do_copy (2, hd->found.kr->fname, NULL, hd->secret,
                  hd->found.offset, hd->found.n_packets );
    if (!rc) {
        /* better reset the found info */
        hd->found.kr = NULL;
        hd->found.offset = 0;
        /* Delete is a rare operations, so we don't remove the keys
         * from the offset table */
    }
    return rc;
}
/*
 * 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;
}
Beispiel #26
0
/* Build a keyblock image from KEYBLOCK.  Returns 0 on success and
   only then stores a new iobuf object at R_IOBUF and a signature
   status vecotor at R_SIGSTATUS.  */
static gpg_error_t
build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus)
{
  gpg_error_t err;
  iobuf_t iobuf;
  kbnode_t kbctx, node;
  u32 n_sigs;
  u32 *sigstatus;

  *r_iobuf = NULL;
  *r_sigstatus = NULL;

  /* Allocate a vector for the signature cache.  This is an array of
     u32 values with the first value giving the number of elements to
     follow and each element descriping the cache status of the
     signature.  */
  for (kbctx = NULL, n_sigs = 0; (node = walk_kbnode (keyblock, &kbctx, 0));)
    if (node->pkt->pkttype == PKT_SIGNATURE)
      n_sigs++;
  sigstatus = xtrycalloc (1+n_sigs, sizeof *sigstatus);
  if (!sigstatus)
    return gpg_error_from_syserror ();

  iobuf = iobuf_temp ();
  for (kbctx = NULL, n_sigs = 0; (node = walk_kbnode (keyblock, &kbctx, 0));)
    {
      /* Make sure to use only packets valid on a keyblock.  */
      switch (node->pkt->pkttype)
        {
        case PKT_PUBLIC_KEY:
        case PKT_PUBLIC_SUBKEY:
        case PKT_SIGNATURE:
        case PKT_USER_ID:
        case PKT_ATTRIBUTE:
          /* Note that we don't want the ring trust packets.  They are
             not useful. */
          break;
        default:
          continue;
        }

      err = build_packet (iobuf, node->pkt);
      if (err)
        {
          iobuf_close (iobuf);
          return err;
        }

      /* Build signature status vector.  */
      if (node->pkt->pkttype == PKT_SIGNATURE)
        {
          PKT_signature *sig = node->pkt->pkt.signature;

          n_sigs++;
          /* Fixme: Detect tye "missing key" status.  */
          if (sig->flags.checked)
            {
              if (sig->flags.valid)
                {
                  if (!sig->expiredate)
                    sigstatus[n_sigs] = 0xffffffff;
                  else if (sig->expiredate < 0x1000000)
                    sigstatus[n_sigs] = 0x10000000;
                  else
                    sigstatus[n_sigs] = sig->expiredate;
                }
              else
                sigstatus[n_sigs] = 0x00000002; /* Bad signature.  */
            }
        }
    }
  sigstatus[0] = n_sigs;

  *r_iobuf = iobuf;
  *r_sigstatus = sigstatus;
  return 0;
}
Beispiel #27
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.
 */
gpg_error_t
keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
{
  gpg_error_t err = 0;

  *ret_kb = NULL;

  if (!hd)
    return gpg_error (GPG_ERR_INV_ARG);

  if (keyblock_cache.state == KEYBLOCK_CACHE_FILLED)
    {
      iobuf_seek (keyblock_cache.iobuf, 0);
      err = parse_keyblock_image (keyblock_cache.iobuf,
                                  keyblock_cache.pk_no,
                                  keyblock_cache.uid_no,
                                  keyblock_cache.sigstatus,
                                  ret_kb);
      if (err)
        keyblock_cache_clear ();
      return err;
    }

  if (hd->found < 0 || hd->found >= hd->used)
    return gpg_error (GPG_ERR_VALUE_NOT_FOUND);

  switch (hd->active[hd->found].type)
    {
    case KEYDB_RESOURCE_TYPE_NONE:
      err = gpg_error (GPG_ERR_GENERAL); /* oops */
      break;
    case KEYDB_RESOURCE_TYPE_KEYRING:
      err = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
      break;
    case KEYDB_RESOURCE_TYPE_KEYBOX:
      {
        iobuf_t iobuf;
        u32 *sigstatus;
        int pk_no, uid_no;

        err = keybox_get_keyblock (hd->active[hd->found].u.kb,
                                   &iobuf, &pk_no, &uid_no, &sigstatus);
        if (!err)
          {
            err = parse_keyblock_image (iobuf, pk_no, uid_no, sigstatus,
                                        ret_kb);
            if (!err && keyblock_cache.state == KEYBLOCK_CACHE_PREPARED)
              {
                keyblock_cache.state     = KEYBLOCK_CACHE_FILLED;
                keyblock_cache.sigstatus = sigstatus;
                keyblock_cache.iobuf     = iobuf;
                keyblock_cache.pk_no     = pk_no;
                keyblock_cache.uid_no    = uid_no;
              }
            else
              {
                xfree (sigstatus);
                iobuf_close (iobuf);
              }
          }
      }
      break;
    }

  if (keyblock_cache.state != KEYBLOCK_CACHE_FILLED)
    keyblock_cache_clear ();

  return err;
}
Beispiel #28
0
/* Handle the creation of a keyring or a keybox if it does not yet
   exist.  Take into acount that other processes might have the
   keyring/keybox already locked.  This lock check does not work if
   the directory itself is not yet available. */
static int
maybe_create_keyring_or_box (char *filename, int is_box, int force)
{
  dotlock_t lockhd = NULL;
  IOBUF iobuf;
  int rc;
  mode_t oldmask;
  char *last_slash_in_filename;
  int save_slash;

  /* A quick test whether the filename already exists. */
  if (!access (filename, F_OK))
    return 0;

  /* If we don't want to create a new file at all, there is no need to
     go any further - bail out right here.  */
  if (!force)
    return gpg_error (GPG_ERR_ENOENT);

  /* First of all we try to create the home directory.  Note, that we
     don't do any locking here because any sane application of gpg
     would create the home directory by itself and not rely on gpg's
     tricky auto-creation which is anyway only done for some home
     directory name patterns. */
  last_slash_in_filename = strrchr (filename, DIRSEP_C);
#if HAVE_W32_SYSTEM
  {
    /* Windows may either have a slash or a backslash.  Take care of it.  */
    char *p = strrchr (filename, '/');
    if (!last_slash_in_filename || p > last_slash_in_filename)
      last_slash_in_filename = p;
  }
#endif /*HAVE_W32_SYSTEM*/
  if (!last_slash_in_filename)
    return gpg_error (GPG_ERR_ENOENT);  /* No slash at all - should
                                           not happen though.  */
  save_slash = *last_slash_in_filename;
  *last_slash_in_filename = 0;
  if (access(filename, F_OK))
    {
      static int tried;

      if (!tried)
        {
          tried = 1;
          try_make_homedir (filename);
        }
      if (access (filename, F_OK))
        {
          rc = gpg_error_from_syserror ();
          *last_slash_in_filename = save_slash;
          goto leave;
        }
    }
  *last_slash_in_filename = save_slash;

  /* To avoid races with other instances of gpg trying to create or
     update the keyring (it is removed during an update for a short
     time), we do the next stuff in a locked state. */
  lockhd = dotlock_create (filename, 0);
  if (!lockhd)
    {
      rc = gpg_error_from_syserror ();
      /* A reason for this to fail is that the directory is not
         writable. However, this whole locking stuff does not make
         sense if this is the case. An empty non-writable directory
         with no keyring is not really useful at all. */
      if (opt.verbose)
        log_info ("can't allocate lock for '%s': %s\n",
                  filename, gpg_strerror (rc));

      if (!force)
        return gpg_error (GPG_ERR_ENOENT);
      else
        return rc;
    }

  if ( dotlock_take (lockhd, -1) )
    {
      rc = gpg_error_from_syserror ();
      /* This is something bad.  Probably a stale lockfile.  */
      log_info ("can't lock '%s': %s\n", filename, gpg_strerror (rc));
      goto leave;
    }

  /* Now the real test while we are locked. */
  if (!access (filename, F_OK))
    {
      rc = 0;  /* Okay, we may access the file now.  */
      goto leave;
    }

  /* The file does not yet exist, create it now. */
  oldmask = umask (077);
  if (is_secured_filename (filename))
    {
      iobuf = NULL;
      gpg_err_set_errno (EPERM);
    }
  else
    iobuf = iobuf_create (filename);
  umask (oldmask);
  if (!iobuf)
    {
      rc = gpg_error_from_syserror ();
      if (is_box)
        log_error (_("error creating keybox '%s': %s\n"),
                   filename, gpg_strerror (rc));
      else
        log_error (_("error creating keyring '%s': %s\n"),
                   filename, gpg_strerror (rc));
      goto leave;
    }

  iobuf_close (iobuf);
  /* Must invalidate that ugly cache */
  iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, filename);

  /* Make sure that at least one record is in a new keybox file, so
     that the detection magic will work the next time it is used.  */
  if (is_box)
    {
      FILE *fp = fopen (filename, "w");
      if (!fp)
        rc = gpg_error_from_syserror ();
      else
        {
          rc = _keybox_write_header_blob (fp);
          fclose (fp);
        }
      if (rc)
        {
          if (is_box)
            log_error (_("error creating keybox '%s': %s\n"),
                       filename, gpg_strerror (rc));
          else
            log_error (_("error creating keyring '%s': %s\n"),
                       filename, gpg_strerror (rc));
          goto leave;
        }
    }

  if (!opt.quiet)
    {
      if (is_box)
        log_info (_("keybox '%s' created\n"), filename);
      else
        log_info (_("keyring '%s' created\n"), filename);
    }

  rc = 0;

 leave:
  if (lockhd)
    {
      dotlock_release (lockhd);
      dotlock_destroy (lockhd);
    }
  return rc;
}
Beispiel #29
0
static int
do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
{
  int rc = 0;
  int i, nskey, npkey;
  IOBUF a = iobuf_temp(); /* Build in a self-enlarging buffer.  */

  /* Write the version number - if none is specified, use 3 */
  if ( !sk->version )
    iobuf_put ( a, 3 );
  else
    iobuf_put ( a, sk->version );
  write_32 (a, sk->timestamp );

  /* v3 needs the expiration time. */
  if ( sk->version < 4 )
    {
      u16 ndays;
      if ( sk->expiredate )
        ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
      else
        ndays = 0;
      write_16(a, ndays);
    }
  
  iobuf_put (a, sk->pubkey_algo );
  
  /* Get number of secret and public parameters.  They are held in one
     array first the public ones, then the secret ones.  */
  nskey = pubkey_get_nskey ( sk->pubkey_algo );
  npkey = pubkey_get_npkey ( sk->pubkey_algo );
  
  /* If we don't have any public parameters - which is the case if we
     don't know the algorithm used - the parameters are stored as one
     blob in a faked (opaque) MPI. */
  if ( !npkey ) 
    {
      write_fake_data( a, sk->skey[0] );
      goto leave;
    }
  assert ( npkey < nskey );

  /* Writing the public parameters is easy. */
  for (i=0; i < npkey; i++ )
    if ((rc = mpi_write (a, sk->skey[i])))
      goto leave;
  
  /* Build the header for protected (encrypted) secret parameters.  */
  if ( sk->is_protected ) 
    {
      if ( is_RSA(sk->pubkey_algo) 
           && sk->version < 4
           && !sk->protect.s2k.mode )
        {
          /* The simple rfc1991 (v3) way. */
          iobuf_put (a, sk->protect.algo );
          iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
	}
      else
        {
          /* OpenPGP protection according to rfc2440. */
          iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff );
          iobuf_put(a, sk->protect.algo );
          if ( sk->protect.s2k.mode >= 1000 )
            {
              /* These modes are not possible in OpenPGP, we use them
                 to implement our extensions, 101 can be seen as a
                 private/experimental extension (this is not specified
                 in rfc2440 but the same scheme is used for all other
                 algorithm identifiers) */
              iobuf_put(a, 101 ); 
              iobuf_put(a, sk->protect.s2k.hash_algo );
              iobuf_write(a, "GNU", 3 );
              iobuf_put(a, sk->protect.s2k.mode - 1000 );
	    }
          else 
            {
              iobuf_put(a, sk->protect.s2k.mode );
              iobuf_put(a, sk->protect.s2k.hash_algo );
	    }
          if ( sk->protect.s2k.mode == 1
               || sk->protect.s2k.mode == 3 )
            iobuf_write (a, sk->protect.s2k.salt, 8 );

          if ( sk->protect.s2k.mode == 3 )
            iobuf_put (a, sk->protect.s2k.count ); 

          /* For our special modes 1001, 1002 we do not need an IV. */
          if ( sk->protect.s2k.mode != 1001 
               && sk->protect.s2k.mode != 1002 )
            iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
	}
    }
  else
    iobuf_put (a, 0 );

  if ( sk->protect.s2k.mode == 1001 )
    ; /* GnuPG extension - don't write a secret key at all. */ 
  else if ( sk->protect.s2k.mode == 1002 )
    { 
      /* GnuPG extension - divert to OpenPGP smartcard. */ 
      iobuf_put(a, sk->protect.ivlen ); /* Length of the serial number
                                           or 0 for no serial
                                           number. */
      /* The serial number gets stored in the IV field. */
      iobuf_write(a, sk->protect.iv, sk->protect.ivlen);
    }
  else if ( sk->is_protected && sk->version >= 4 )
    {
      /* The secret key is protected - write it out as it is.  */
      byte *p;
      unsigned int ndatabits;
      
      assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE));
      p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits );
      iobuf_write (a, p, (ndatabits+7)/8 );
    }
  else if ( sk->is_protected ) 
    {
      /* The secret key is protected the old v4 way. */
      for ( ; i < nskey; i++ ) 
        {
          byte *p;
          unsigned int ndatabits;
          
          assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE));
          p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits);
          iobuf_write (a, p, (ndatabits+7)/8);
        }
      write_16(a, sk->csum );
    }
  else
    {
      /* Non-protected key. */
      for ( ; i < nskey; i++ )
        if ( (rc = mpi_write (a, sk->skey[i])))
          goto leave;
      write_16 (a, sk->csum );
    }

 leave:
  if (!rc)
    {
      /* Build the header of the packet - which we must do after
         writing all the other stuff, so that we know the length of
         the packet */
      write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes);
      /* And finally write it out the real stream */
      rc = iobuf_write_temp( out, a );
    }

  iobuf_close(a); /* Close the remporary buffer */
  return rc;
}
Beispiel #30
0
/* Generate a new photo id packet, or return NULL if canceled.
   FIXME:  Should we add a duplicates check similar to generate_user_id? */
PKT_user_id *
generate_photo_id(PKT_public_key *pk,const char *photo_name)
{
  PKT_user_id *uid;
  int error=1,i;
  unsigned int len;
  char *filename;
  byte *photo=NULL;
  byte header[16];
  IOBUF file;
  int overflow;

  header[0]=0x10; /* little side of photo header length */
  header[1]=0;    /* big side of photo header length */
  header[2]=1;    /* 1 == version of photo header */
  header[3]=1;    /* 1 == JPEG */

  for(i=4;i<16;i++) /* The reserved bytes */
    header[i]=0;

#define EXTRA_UID_NAME_SPACE 71
  uid=xmalloc_clear(sizeof(*uid)+71);

  if(photo_name && *photo_name)
    filename=make_filename(photo_name,(void *)NULL);
  else
    {
      tty_printf(_("\nPick an image to use for your photo ID."
		   "  The image must be a JPEG file.\n"
		   "Remember that the image is stored within your public key."
		   "  If you use a\n"
		   "very large picture, your key will become very large"
		   " as well!\n"
		   "Keeping the image close to 240x288 is a good size"
		   " to use.\n"));
      filename=NULL;
    }

  while(photo==NULL)
    {
      if(filename==NULL)
	{
	  char *tempname;

	  tty_printf("\n");

	  tty_enable_completion(NULL);

	  tempname=cpr_get("photoid.jpeg.add",
			   _("Enter JPEG filename for photo ID: "));

	  tty_disable_completion();

	  filename=make_filename(tempname,(void *)NULL);

	  xfree(tempname);

	  if(strlen(filename)==0)
	    goto scram;
	}

      file=iobuf_open(filename);
      if (file && is_secured_file (iobuf_get_fd (file)))
        {
          iobuf_close (file);
          file = NULL;
          errno = EPERM;
        }
      if(!file)
	{
	  log_error(_("unable to open JPEG file `%s': %s\n"),
		    filename,strerror(errno));
	  xfree(filename);
	  filename=NULL;
	  continue;
	}

      
      len=iobuf_get_filelength(file, &overflow);
      if(len>6144 || overflow)
	{
	  tty_printf( _("This JPEG is really large (%d bytes) !\n"),len);
	  if(!cpr_get_answer_is_yes("photoid.jpeg.size",
			    _("Are you sure you want to use it? (y/N) ")))
	  {
	    iobuf_close(file);
	    xfree(filename);
	    filename=NULL;
	    continue;
	  }
	}

      photo=xmalloc(len);
      iobuf_read(file,photo,len);
      iobuf_close(file);

      /* Is it a JPEG? */
      if(photo[0]!=0xFF || photo[1]!=0xD8 ||
	 photo[6]!='J' || photo[7]!='F' || photo[8]!='I' || photo[9]!='F')
	{
	  log_error(_("`%s' is not a JPEG file\n"),filename);
	  xfree(photo);
	  photo=NULL;
	  xfree(filename);
	  filename=NULL;
	  continue;
	}

      /* Build the packet */
      build_attribute_subpkt(uid,1,photo,len,header,16);
      parse_attribute_subpkts(uid);
      make_attribute_uidname(uid, EXTRA_UID_NAME_SPACE);

      /* Showing the photo is not safe when noninteractive since the
         "user" may not be able to dismiss a viewer window! */
      if(opt.command_fd==-1)
	{
	  show_photos(uid->attribs,uid->numattribs,pk,NULL,uid);
	  switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay",
					 _("Is this photo correct (y/N/q)? ")))
	    {
	    case -1:
	      goto scram;
	    case 0:
	      free_attributes(uid);
	      xfree(photo);
	      photo=NULL;
	      xfree(filename);
	      filename=NULL;
	      continue;
	    }
	}
    }

  error=0;
  uid->ref=1;

 scram:
  xfree(filename);
  xfree(photo);

  if(error)
    {
      free_attributes(uid);
      xfree(uid);
      return NULL;
    }

  return uid;
}