Exemplo n.º 1
0
/**
 * cdk_file_verify:
 * @hd: the session handle
 * @file: the input file
 * @data_file: for detached signature this is the data file and @file is the sig.
 * @output: the output file
 *
 * Verify a signature.
 **/
cdk_error_t
cdk_file_verify (cdk_ctx_t hd, const char *file, const char *data_file,
		 const char *output)
{
  struct stat stbuf;
  cdk_stream_t inp, data;
  char buf[4096];
  int n;
  cdk_error_t rc;

  if (!hd || !file)
    return CDK_Inv_Value;
  if (output && !hd->opt.overwrite && !stat (output, &stbuf))
    return CDK_Inv_Mode;

  rc = cdk_stream_open (file, &inp);
  if (rc)
    return rc;
  if (cdk_armor_filter_use (inp))
    {
      n = cdk_stream_peek (inp, (byte *) buf, DIM (buf) - 1);
      if (!n || n == -1)
	return CDK_EOF;
      buf[n] = '\0';
      if (strstr (buf, "BEGIN PGP SIGNED MESSAGE"))
	{
	  cdk_stream_close (inp);
	  return file_verify_clearsign (hd, file, output);
	}
      cdk_stream_set_armor_flag (inp, 0);
    }

  if (data_file)
    {
      rc = cdk_stream_open (data_file, &data);
      if (rc)
	{
	  cdk_stream_close (inp);
	  return rc;
	}
    }
  else
    data = NULL;

  rc = _cdk_proc_packets (hd, inp, data, NULL, NULL, NULL);

  if (data != NULL)
    cdk_stream_close (data);
  cdk_stream_close (inp);
  return rc;
}
Exemplo n.º 2
0
/* This functions builds an index of the keyring into a separate file
   with the name keyring.ext.idx. It contains the offset of all public-
   and public subkeys. The format of the file is:
   --------
    4 octets offset of the packet
    8 octets keyid
   20 octets fingerprint
   --------
   We store the keyid and the fingerprint due to the fact we can't get
   the keyid from a v3 fingerprint directly.
*/
static int
keydb_idx_build( const char * file )
{
    cdk_packet_t pkt;
    cdk_stream_t inp, out = NULL;
    byte buf[8], fpr[20];
    char * fname;
    u32 keyid[2];
    int rc, pos;

    if( !file )
        return CDK_Inv_Value;

    pkt = cdk_calloc( 1, sizeof * pkt );
    if( !pkt )
        return CDK_Out_Of_Core;
    
    fname = keydb_idx_mkname( file );
    if( !fname ) {
        rc = CDK_Out_Of_Core;
        goto leave;
    }
  
    rc = cdk_stream_open( file, &inp );
    if( !rc )
        rc = cdk_stream_create( fname, &out );
    if( rc )
        goto leave;

    while( !cdk_stream_eof( inp ) ) {
        pos = cdk_stream_tell( inp );
        rc = cdk_pkt_read( inp, pkt );
        if( rc )
            break;
        if( pkt->pkttype == CDK_PKT_PUBLIC_KEY
            || pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ) {
            _cdk_u32tobuf( pos, buf );
            cdk_stream_write( out, buf, 4 );
            cdk_pk_get_keyid( pkt->pkt.public_key, keyid );
            _cdk_u32tobuf( keyid[0], buf );
            _cdk_u32tobuf( keyid[1], buf + 4 );
            cdk_stream_write( out, buf, 8 );
            cdk_pk_get_fingerprint( pkt->pkt.public_key, fpr );
            cdk_stream_write( out, fpr, 20 );
        }
        cdk_pkt_free( pkt );
        cdk_pkt_init( pkt );
    }
    cdk_stream_close( out );
 leave:
    cdk_stream_close( inp );
    cdk_free( fname );
    cdk_free( pkt );
    return rc;
}
Exemplo n.º 3
0
/**
 * cdk_keydb_idx_rebuild:
 * @hd: key database handle
 *
 * Rebuild the key index files for the given key database.
 **/
cdk_error_t
cdk_keydb_idx_rebuild( cdk_keydb_hd_t hd )
{
    int rc;
  
    if( !hd || !hd->name )
        return CDK_Inv_Value;
    if( hd->secret )
        return 0;
  
    cdk_stream_close( hd->idx );
    if( !hd->idx_name ) {
        hd->idx_name = keydb_idx_mkname( hd->name );
        if( !hd->idx_name )
            return CDK_Out_Of_Core;
    }
    rc = keydb_idx_build( hd->name );
    if( !rc )
        rc = cdk_stream_open( hd->idx_name, &hd->idx );
    return rc;
}
Exemplo n.º 4
0
cdk_error_t
_cdk_stream_append( const char * file, cdk_stream_t * ret_s )
{
    cdk_stream_t s;
    FILE * fp;
    int rc;

    if( !ret_s )
        return CDK_Inv_Value;
    rc = cdk_stream_open( file, &s );
    if( rc )
        return rc;
    fp = fopen( file, "a+b" );
    if( !fp ) {
        cdk_stream_close( s );
        return CDK_File_Error;
    }
    fclose( s->fp );
    s->fp = fp;
    s->flags.write = 1;
    *ret_s = s;
    return 0;
}
Exemplo n.º 5
0
static cdk_error_t
file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output)
{
  cdk_stream_t inp = NULL, out = NULL, tmp = NULL;
  digest_hd_st md;
  char buf[512], chk[512];
  const char *s;
  int i, is_signed = 0, nbytes;
  int digest_algo = 0;
  int err;
  cdk_error_t rc;

  memset(&md, 0, sizeof(md));

  if (output)
    {
      rc = cdk_stream_create (output, &out);
      if (rc)
	return rc;
    }

  rc = cdk_stream_open (file, &inp);
  if (rc)
    {
      if (output)
	cdk_stream_close (out);
      return rc;
    }

  s = "-----BEGIN PGP SIGNED MESSAGE-----";
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (!strncmp (buf, s, strlen (s)))
	{
	  is_signed = 1;
	  break;
	}
    }

  if (cdk_stream_eof (inp) && !is_signed)
    {
      rc = CDK_Armor_Error;
      goto leave;
    }

  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (nbytes == 1)		/* Empty line */
	break;
      else if (!strncmp (buf, "Hash: ", 6))
	{
	  for (i = 0; digest_table[i].name; i++)
	    {
	      if (!strcmp (buf + 6, digest_table[i].name))
		{
		  digest_algo = digest_table[i].algo;
		  break;
		}
	    }
	}
    }

  if (digest_algo && _gnutls_hash_get_algo_len (digest_algo) <= 0)
    {
      rc = CDK_Inv_Algo;
      goto leave;
    }

  if (!digest_algo)
    digest_algo = GNUTLS_DIG_MD5;

  err = _gnutls_hash_init (&md, digest_algo);
  if (err < 0)
    {
      rc = map_gnutls_error (err);
      goto leave;
    }

  s = "-----BEGIN PGP SIGNATURE-----";
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (!strncmp (buf, s, strlen (s)))
	break;
      else
	{
	  cdk_stream_peek (inp, (byte *) chk, DIM (chk) - 1);
	  i = strncmp (chk, s, strlen (s));
	  if (strlen (buf) == 0 && i == 0)
	    continue;		/* skip last '\n' */
	  _cdk_trim_string (buf, i == 0 ? 0 : 1);
	  _gnutls_hash (&md, buf, strlen (buf));
	}
      if (!strncmp (buf, "- ", 2))	/* FIXME: handle it recursive. */
	memmove (buf, buf + 2, nbytes - 2);
      if (out)
	{
	  if (strstr (buf, "\r\n"))
	    buf[strlen (buf) - 2] = '\0';
	  cdk_stream_write (out, buf, strlen (buf));
	  _cdk_stream_puts (out, _cdk_armor_get_lineend ());
	}
    }

  /* We create a temporary stream object to store the
     signature data in there. */
  rc = cdk_stream_tmp_new (&tmp);
  if (rc)
    goto leave;

  s = "-----BEGIN PGP SIGNATURE-----\n";
  _cdk_stream_puts (tmp, s);
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (nbytes < (int) (DIM (buf) - 3))
	{
	  buf[nbytes - 1] = '\n';
	  buf[nbytes] = '\0';
	}
      cdk_stream_write (tmp, buf, nbytes);
    }

  /* FIXME: This code is not very elegant. */
  cdk_stream_tmp_set_mode (tmp, STREAMCTL_READ);
  cdk_stream_seek (tmp, 0);
  cdk_stream_set_armor_flag (tmp, 0);
  cdk_stream_read (tmp, NULL, 0);

  /* the digest handle will be closed there. */
  rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, &md);

leave:
  _gnutls_hash_deinit (&md, NULL);
  cdk_stream_close (out);
  cdk_stream_close (tmp);
  cdk_stream_close (inp);
  return rc;
}
Exemplo n.º 6
0
/**
 * cdk_keydb_open:
 * @hd: keydb object
 * @ret_kr: the STREAM object which contains the data of the keyring
 *
 * Open a STREAM with the contents of the keyring from @hd
 **/
cdk_error_t
cdk_keydb_open( cdk_keydb_hd_t hd, cdk_stream_t * ret_kr )
{
    int rc = 0, ec;

    if( !hd || !ret_kr )
        return CDK_Inv_Value;

    if( hd->type == CDK_DBTYPE_DATA && hd->buf )
        cdk_stream_seek( hd->buf, 0 );
    else if( hd->type == CDK_DBTYPE_PK_KEYRING
             || hd->type == CDK_DBTYPE_SK_KEYRING ) {
        if( !hd->isopen && hd->name ) {
            rc = cdk_stream_open( hd->name, &hd->buf );
            if( rc )
                goto leave;
            if( cdk_armor_filter_use( hd->buf ) )
                cdk_stream_set_armor_flag( hd->buf, 0 );
            hd->isopen = 1;
            cdk_free( hd->idx_name );
            hd->idx_name = keydb_idx_mkname( hd->name );
            if( !hd->idx_name ) {
                rc = CDK_Out_Of_Core;
                goto leave;
            }
            ec = cdk_stream_open( hd->idx_name, &hd->idx );
            if( ec && !hd->secret ) {
                rc = keydb_idx_build( hd->name );
                if( !rc )
                    rc = cdk_stream_open( hd->idx_name, &hd->idx );
                if( !rc )
                    _cdk_log_debug( "create key index table\n" );
                if( rc ) {
                    /* this is no real error, it just means we can't create
                       the index at the given directory. maybe we've no write
                       access. in this case, we simply disable the index. */
                    _cdk_log_debug( "disable key index table\n" );
                    rc = 0;
                    hd->no_cache = 1;
                }
            }
        }
        else {
            /* We use the cache to search keys, so we always rewind the
               STREAM. Except when the _NEXT search mode is used because
               this mode is an enumeration and no seeking is needed. */
            if( !hd->search ||
                (hd->search && hd->dbs->type != CDK_DBSEARCH_NEXT) )
                cdk_stream_seek( hd->buf, 0 );
        }
    }
    else
        return CDK_Inv_Mode;
  
 leave:
    if( rc ) {
        cdk_stream_close( hd->buf );
        hd->buf = NULL;
    }
    *ret_kr = hd->buf;
    return rc;
}