Exemplo n.º 1
0
cdk_error_t
cdk_stream_flush (cdk_stream_t s)
{
  cdk_error_t rc;

  if (!s)
    {
      gnutls_assert();
      return CDK_Inv_Value;
    }

  /* The user callback does not support flush */
  if (s->cbs_hd)
    return 0;

  /* For read-only streams, no flush is needed. */
  if (!s->flags.write)
    return 0;

  if (!s->flags.filtrated)
    {
      if (!cdk_stream_get_length (s))
	return 0;
      rc = cdk_stream_seek (s, 0);
      if (!rc)
	rc = stream_flush (s);
      if (!rc)
	rc = stream_filter_write (s);
      s->flags.filtrated = 1;
      if (rc)
	{
	  s->error = rc;
          gnutls_assert();
	  return rc;
	}
    }
  return 0;
}
Exemplo n.º 2
0
cdk_error_t
cdk_stream_flush( cdk_stream_t s )
{
    int rc = 0;
  
    if( !s )
        return CDK_Inv_Value;

    if( !s->flags.filtrated ) {
        if( !cdk_stream_get_length( s ) )
            return 0;
        rc = cdk_stream_seek( s, 0 );
        if( !rc )
            rc = stream_flush( s );
        if( !rc ) {
            rc = stream_filter_write( s );
            if( rc )
                s->error = rc;
        }
        s->flags.filtrated = 1;
    }
    return rc;
}
Exemplo n.º 3
0
/* Here all data from the file handle is passed through all filters.
   The scheme works like this:
   Create a tempfile and use it for the output of the filter. Then the
   original file handle will be closed and replace with the temp handle.
   The file pointer will be set to the begin and the game starts again. */
static cdk_error_t
stream_filter_read (cdk_stream_t s)
{
    struct stream_filter_s *f;
    cdk_error_t rc = 0;

    assert (s);

    if (s->flags.filtrated)
        return 0;

    for (f = s->filters; f; f = f->next)
    {
        if (!f->flags.enabled)
            continue;
        if (f->flags.error)
        {
            _cdk_log_debug ("filter %s [read]: has the error flag; skipped\n",
                            s->fname ? s->fname : "[temp]");
            continue;
        }

        f->tmp = _cdk_tmpfile ();
        if (!f->tmp)
        {
            rc = CDK_File_Error;
            break;
        }
        rc = f->fnct (f->opaque, f->ctl, s->fp, f->tmp);
        _cdk_log_debug ("filter %s [read]: type=%d rc=%d\n",
                        s->fname ? s->fname : "[temp]", f->type, rc);
        if (rc)
        {
            f->flags.error = 1;
            break;
        }

        f->flags.error = 0;
        /* If the filter is read-only, do not replace the FP because
           the contents were not altered in any way. */
        if (!f->flags.rdonly)
        {
            rc = stream_fp_replace (s, &f->tmp);
            if (rc)
                break;
        }
        else
        {
            fclose (f->tmp);
            f->tmp = NULL;
        }
        rc = cdk_stream_seek (s, 0);
        if (rc)
            break;
        /* Disable the filter after it was successfully used. The idea
           is the following: let's say the armor filter was pushed and
           later more filters were added. The second time the filter code
           will be executed, only the new filter should be started but
           not the old because we already used it. */
        f->flags.enabled = 0;
    }

    return rc;
}
Exemplo n.º 4
0
/**
 * cdk_stream_mmap_part:
 * @s: the stream
 * @off: the offset where to start
 * @len: how much bytes shall be mapped
 * @ret_buf: the buffer to store the content
 * @ret_buflen: length of the buffer
 *
 * Maps the data of the given stream into a memory section. @ret_count
 * contains the length of the buffer.
 **/
cdk_error_t
cdk_stream_mmap_part (cdk_stream_t s, off_t off, size_t len,
                      byte ** ret_buf, size_t * ret_buflen)
{
    cdk_error_t rc;
    off_t oldpos;
    unsigned int n;

    if (!ret_buf || !ret_buflen)
    {
        gnutls_assert ();
        return CDK_Inv_Value;
    }
    *ret_buf = NULL;
    *ret_buflen = 0;

    if (!s)
    {
        gnutls_assert ();
        return CDK_Inv_Value;
    }

    /* Memory mapping is not supported on custom I/O objects. */
    if (s->cbs_hd)
    {
        _cdk_log_debug ("cdk_stream_mmap_part: not supported on callbacks\n");
        gnutls_assert ();
        return CDK_Inv_Mode;
    }

    oldpos = cdk_stream_tell (s);
    rc = cdk_stream_flush (s);
    if (rc)
    {
        gnutls_assert ();
        return rc;
    }
    rc = cdk_stream_seek (s, off);
    if (rc)
    {
        gnutls_assert ();
        return rc;
    }
    if (!len)
        len = cdk_stream_get_length (s);
    if (!len)
    {
        _cdk_log_debug ("cdk_stream_mmap_part: invalid file size %lu\n", len);
        gnutls_assert ();
        return s->error;
    }
    if (len > MAX_MAP_SIZE)
    {
        gnutls_assert ();
        return CDK_Too_Short;
    }

    *ret_buf = cdk_calloc (1, len + 1);
    *ret_buflen = len;
    n = cdk_stream_read (s, *ret_buf, len);
    if (n != len)
        *ret_buflen = n;
    rc = cdk_stream_seek (s, oldpos);
    if (rc)
        gnutls_assert ();
    return rc;
}
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
Arquivo: kbnode.c Projeto: ares89/vlc
/**
 * cdk_kbnode_write_to_mem:
 * @node: the key node
 * @buf: the buffer to store the node data
 * @r_nbytes: the new length of the buffer.
 *
 * Tries to write the contents of the key node to the buffer @buf and
 * return the length of it in @r_nbytes. If buf is zero, only the
 * length of the node is calculated and returned in @r_nbytes.
 * Whenever it is possible, the cdk_kbnode_write_to_mem_alloc should be used.
 **/
cdk_error_t
cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte * buf, size_t * r_nbytes)
{
  cdk_kbnode_t n;
  cdk_stream_t s;
  cdk_error_t rc;
  size_t len;

  if (!node || !r_nbytes)
    {
      gnutls_assert ();
      return CDK_Inv_Value;
    }

  rc = cdk_stream_tmp_new (&s);
  if (rc)
    {
      gnutls_assert ();
      return rc;
    }

  for (n = node; n; n = n->next)
    {
      /* Skip all packets which cannot occur in a key composition. */
      if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY &&
          n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY &&
          n->pkt->pkttype != CDK_PKT_SECRET_KEY &&
          n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY &&
          n->pkt->pkttype != CDK_PKT_SIGNATURE &&
          n->pkt->pkttype != CDK_PKT_USER_ID &&
          n->pkt->pkttype != CDK_PKT_ATTRIBUTE)
        continue;
      rc = cdk_pkt_write (s, n->pkt);
      if (rc)
        {
          cdk_stream_close (s);
          gnutls_assert ();
          return rc;
        }
    }

  cdk_stream_seek (s, 0);
  len = cdk_stream_get_length (s);
  if (!buf)
    {
      *r_nbytes = len;          /* Only return the length of the buffer */
      cdk_stream_close (s);
      return 0;
    }
  if (*r_nbytes < len)
    {
      *r_nbytes = len;
      rc = CDK_Too_Short;
    }
  if (!rc)
    *r_nbytes = cdk_stream_read (s, buf, len);
  else
    gnutls_assert ();
  cdk_stream_close (s);
  return rc;
}
Exemplo n.º 7
0
/**
 * cdk_keydb_search:
 * @hd: the keydb object
 * @ks: the keydb search object
 * @ret_key: kbnode object to store the key
 *
 * Search for a key in the given keyring. The search mode is handled
 * via @ks. If the key was found, @ret_key contains the key data.
 **/
cdk_error_t
cdk_keydb_search( cdk_keydb_hd_t hd, cdk_kbnode_t * ret_key )
{
    cdk_stream_t kr = NULL;
    cdk_kbnode_t knode = NULL;
    cdk_dbsearch_t ks;
    u32 off = 0;
    size_t pos = 0;
    int key_found = 0, cache_hit = 0;
    int rc = 0;

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

    *ret_key = NULL;
    hd->search = 1;
    rc = cdk_keydb_open( hd, &kr );
    if( rc )
        return rc;
    rc = keydb_pos_from_cache( hd, hd->dbs, &cache_hit, &off );
    if( rc )
        return rc;
    
    ks = hd->dbs;
    while( !key_found && !rc ) {
        if( cache_hit && ks->type != CDK_DBSEARCH_NEXT )
            cdk_stream_seek( kr, off );
        pos = cdk_stream_tell( kr );
        rc = cdk_keydb_get_keyblock( kr, &knode );
        if( rc ) {
            if( rc == CDK_EOF && knode )
                rc = 0;
            if( !knode && rc == CDK_EOF )
                rc = CDK_Error_No_Key;
            if( rc )
                break;
        }

        switch( ks->type ) {
        case CDK_DBSEARCH_SHORT_KEYID:
        case CDK_DBSEARCH_KEYID:
            key_found = find_by_keyid( knode, ks );
            break;

        case CDK_DBSEARCH_FPR:
            key_found = find_by_fpr( knode, ks );
            break;
          
	case CDK_DBSEARCH_EXACT:
	case CDK_DBSEARCH_SUBSTR:
            key_found = find_by_pattern( knode, ks );
            break;

        case CDK_DBSEARCH_NEXT:
            key_found = knode? 1 : 0;
            break;
	}

        if( key_found ) {
            if( !keydb_cache_find( hd->cache, ks ) )
                keydb_cache_add( hd, ks, pos );
            break;
        }

        cdk_kbnode_release( knode );
        knode = NULL;
    }

    hd->search = 0;
    *ret_key = key_found? knode : NULL;
    return rc;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
cdk_error_t
cdk_keydb_get_keyblock( cdk_stream_t inp, cdk_kbnode_t * r_knode )
{
    cdk_packet_t pkt = NULL;
    cdk_kbnode_t knode = NULL, node = NULL;
    cdk_desig_revoker_t revkeys = NULL;
    u32 keyid[2], main_keyid[2];
    int rc = 0, old_off;
    int key_seen = 0, got_key = 0;

    if( !inp || !r_knode )
        return CDK_Inv_Value;

    memset( keyid, 0, sizeof keyid );
    memset( main_keyid, 0, sizeof main_keyid );
  
    while( 1 ) {
        pkt = cdk_calloc( 1, sizeof *pkt );
        if( !pkt )
            return CDK_Out_Of_Core;
        old_off = 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
            || pkt->pkttype == CDK_PKT_SECRET_KEY
            || pkt->pkttype == CDK_PKT_SECRET_SUBKEY) {
            if (key_seen && (pkt->pkttype == CDK_PKT_PUBLIC_KEY
                             || pkt->pkttype == CDK_PKT_SECRET_KEY) ) {
                cdk_stream_seek( inp, old_off );
                break;
	    }
            if( pkt->pkttype == CDK_PKT_PUBLIC_KEY
                || pkt->pkttype == CDK_PKT_SECRET_KEY ) {
                _cdk_pkt_get_keyid( pkt, main_keyid );
                key_seen = 1;
            }
            else if( pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY
                     || pkt->pkttype == CDK_PKT_SECRET_SUBKEY ) {
                if( pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ) {
                    pkt->pkt.public_key->main_keyid[0] = main_keyid[0];
                    pkt->pkt.public_key->main_keyid[1] = main_keyid[1];
		}
                else {
                    pkt->pkt.secret_key->main_keyid[0] = main_keyid[0];
                    pkt->pkt.secret_key->main_keyid[1] = main_keyid[1];
		}
	    }
            /* we save this for the signature */
            _cdk_pkt_get_keyid( pkt, keyid );
            got_key = 1;
	}
        else if( pkt->pkttype == CDK_PKT_USER_ID )
            ;
        else if( pkt->pkttype == CDK_PKT_SIGNATURE ) {
            pkt->pkt.signature->key[0] = keyid[0];
            pkt->pkt.signature->key[1] = keyid[1];
            if( pkt->pkt.signature->sig_class == 0x1F &&
                pkt->pkt.signature->revkeys )
                revkeys = pkt->pkt.signature->revkeys;
	}
        node = cdk_kbnode_new( pkt );
        if( !knode )
            knode = node;
        else
            _cdk_kbnode_add( knode, node );
    }

    if( got_key ) {
        keydb_merge_selfsig( knode, main_keyid );
        rc = keydb_parse_allsigs( knode, NULL, 0 );
        if( revkeys ) {
            node = cdk_kbnode_find( knode, CDK_PKT_PUBLIC_KEY );
            if( node )
                node->pkt->pkt.public_key->revkeys = revkeys;
        }
    }
    *r_knode = got_key ? knode : NULL;
    return rc;
}