Пример #1
0
cdk_error_t
cdk_stream_seek (cdk_stream_t s, off_t offset)
{
    off_t len;

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

    if (s->cbs_hd)
    {
        if (s->cbs.seek)
            return s->cbs.seek (s->cbs_hd, offset);
        return 0;
    }

    /* Set or reset the EOF flag. */
    len = cdk_stream_get_length (s);
    if (len == offset)
        s->flags.eof = 1;
    else
        s->flags.eof = 0;

    if (fseek (s->fp, offset, SEEK_SET))
    {
        gnutls_assert ();
        return CDK_File_Error;
    }
    return 0;
}
Пример #2
0
/**
 * cdk_stream_mmap:
 * @s: the stream
 * @ret_buf: the buffer to store the content
 * @ret_count: length of the buffer
 *
 * Map the data of the given stream into a memory section. @ret_count
 * contains the length of the buffer.
 **/
cdk_error_t
cdk_stream_mmap( cdk_stream_t s, byte ** ret_buf, size_t * ret_count )
{
    const u32 max_filesize = 16777216;
    u32 len, oldpos;
    int n, rc;
    char * p;

    if( !s || !ret_buf || !ret_count )
        return CDK_Inv_Value;

    *ret_count = 0;
    *ret_buf = NULL;
    oldpos = cdk_stream_tell( s );
    rc = cdk_stream_flush( s );
    if( !rc )
        rc = cdk_stream_seek( s, 0 );
    if( rc )
        return rc;
    len = cdk_stream_get_length( s );
    if( !len || len > max_filesize )
        return 0;
    p = *ret_buf = cdk_calloc( 1, len+1 );
    if( !p )
        return 0;
    *ret_count = len;
    n = cdk_stream_read( s, p, len );
    if( n != len )
        *ret_count = n;
    rc = cdk_stream_seek( s, oldpos );
    return rc;
}
Пример #3
0
cdk_error_t
cdk_stream_mmap (cdk_stream_t inp, byte ** buf, size_t * buflen)
{
    off_t len;

    /* We need to make sure all data is flushed before we retrieve the size. */
    cdk_stream_flush (inp);
    len = cdk_stream_get_length (inp);
    return cdk_stream_mmap_part (inp, 0, len, buf, buflen);
}
Пример #4
0
/**
 * cdk_kbnode_write_to_mem_alloc:
 * @node: the key node
 * @r_buf: buffer to hold the raw data
 * @r_buflen: buffer length of the allocated raw data.
 * 
 * The function acts similar to cdk_kbnode_write_to_mem but
 * it allocates the buffer to avoid the lengthy second run.
 */
cdk_error_t
cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node,
                               byte ** r_buf, size_t * r_buflen)
{
  cdk_kbnode_t n;
  cdk_stream_t s;
  cdk_error_t rc;
  size_t len;

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

  *r_buf = NULL;
  *r_buflen = 0;

  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);
  *r_buf = cdk_calloc (1, len);
  *r_buflen = cdk_stream_read (s, *r_buf, len);
  cdk_stream_close (s);
  return 0;
}
Пример #5
0
static cdk_error_t
literal_encode (void *data, FILE * in, FILE * out)
{
    literal_filter_t *pfx = data;
    cdk_pkt_literal_t pt;
    cdk_stream_t si;
    cdk_packet_t pkt;
    size_t filelen;
    cdk_error_t rc;

    _cdk_log_debug ("literal filter: encode\n");

    if (!pfx || !in || !out)
        return CDK_Inv_Value;
    if (!pfx->filename)
    {
        pfx->filename = cdk_strdup ("_CONSOLE");
        if (!pfx->filename)
            return CDK_Out_Of_Core;
    }

    rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si);
    if (rc)
        return rc;

    filelen = strlen (pfx->filename);
    cdk_pkt_new (&pkt);
    pt = pkt->pkt.literal = cdk_calloc (1, sizeof *pt + filelen);
    pt->name = (char *) pt + sizeof (*pt);
    if (!pt)
    {
        cdk_pkt_release (pkt);
        cdk_stream_close (si);
        return CDK_Out_Of_Core;
    }
    memcpy (pt->name, pfx->filename, filelen);
    pt->namelen = filelen;
    pt->name[pt->namelen] = '\0';
    pt->timestamp = (u32) time (NULL);
    pt->mode = intmode_to_char (pfx->mode);
    pt->len = cdk_stream_get_length (si);
    pt->buf = si;
    pkt->old_ctb = 1;
    pkt->pkttype = CDK_PKT_LITERAL;
    pkt->pkt.literal = pt;
    rc = _cdk_pkt_write_fp (out, pkt);

    cdk_pkt_release (pkt);
    cdk_stream_close (si);
    return rc;
}
Пример #6
0
cdk_error_t
cdk_stream_seek( cdk_stream_t s, long offset )
{
    int rc;

    if( !s )
        return CDK_Inv_Value;    
    if( offset < cdk_stream_get_length( s ) )
        s->flags.eof = 0;
    rc = fseek( s->fp, offset, SEEK_SET );
    if( rc )
        rc = CDK_File_Error;
    return rc;
}
Пример #7
0
static int
literal_encode (void * opaque, FILE * in, FILE * out)
{
    literal_filter_t * pfx = opaque;
    cdk_pkt_literal_t pt;
    cdk_stream_t si;
    CDK_PACKET pkt;
    size_t filelen;
    int rc;

    _cdk_log_debug ("literal filter: encode\n");
  
    if (!pfx || !in || !out)
        return CDK_Inv_Value;
  
    if (!pfx->filename) {
        pfx->filename = cdk_strdup ("_CONSOLE");
        if( !pfx->filename )
            return CDK_Out_Of_Core;
    }

    si = _cdk_stream_fpopen (in, STREAMCTL_READ);
    if (!si)
        return CDK_Out_Of_Core;

    filelen = strlen (pfx->filename);
    pt = cdk_calloc (1, sizeof *pt + filelen - 1);
    if (!pt)
        return CDK_Out_Of_Core;
    memcpy (pt->name, pfx->filename, filelen);
    pt->namelen = filelen;
    pt->name[pt->namelen] = '\0';
    pt->timestamp = _cdk_timestamp ();
    pt->mode = pfx->mode ? 't' : 'b';
    pt->len = cdk_stream_get_length (si);
    pt->buf = si;
    cdk_pkt_init (&pkt);
    pkt.old_ctb = pfx->rfc1991? 1 : 0;
    pkt.pkttype = CDK_PKT_LITERAL;
    pkt.pkt.literal = pt;
    rc = _cdk_pkt_write_fp (out, &pkt);

    cdk_free (pt);
    cdk_stream_close (si);
    return rc;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
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;
}
Пример #11
0
/**
 * gnutls_openpgp_keyring_import:
 * @keyring: The structure to store the parsed key.
 * @data: The RAW or BASE64 encoded keyring.
 * @format: One of #gnutls_openpgp_keyring_fmt elements.
 *
 * This function will convert the given RAW or Base64 encoded keyring
 * to the native #gnutls_openpgp_keyring_t format.  The output will be
 * stored in 'keyring'.
 *
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
 **/
int
gnutls_openpgp_keyring_import(gnutls_openpgp_keyring_t keyring,
			      const gnutls_datum_t * data,
			      gnutls_openpgp_crt_fmt_t format)
{
	cdk_error_t err;
	cdk_stream_t input = NULL;
	size_t raw_len = 0;
	uint8_t *raw_data = NULL;
	unsigned free_data = 0;

	if (data->data == NULL || data->size == 0) {
		gnutls_assert();
		return GNUTLS_E_OPENPGP_GETKEY_FAILED;
	}

	_gnutls_debug_log("PGP: keyring import format '%s'\n",
			  format ==
			  GNUTLS_OPENPGP_FMT_RAW ? "raw" : "base64");

	/* Create a new stream from the given data, decode it, and import
	 * the raw database. This to avoid using opencdk streams which are
	 * not thread safe.
	 */
	if (format == GNUTLS_OPENPGP_FMT_BASE64) {
		size_t seen = 0;

		err =
		    cdk_stream_tmp_from_mem(data->data, data->size,
					    &input);
		if (err == 0)
			err = cdk_stream_set_armor_flag(input, 0);
		if (err) {
			gnutls_assert();
			err = _gnutls_map_cdk_rc(err);
			goto error;
		}

		raw_len = cdk_stream_get_length(input);
		if (raw_len == 0) {
			gnutls_assert();
			err = GNUTLS_E_BASE64_DECODING_ERROR;
			goto error;
		}

		raw_data = gnutls_malloc(raw_len);
		if (raw_data == NULL) {
			gnutls_assert();
			err = GNUTLS_E_MEMORY_ERROR;
			goto error;
		}

		do {
			err =
			    cdk_stream_read(input, raw_data + seen,
					    raw_len - seen);

			if (err > 0)
				seen += err;
		}
		while (seen < raw_len && err != EOF && err > 0);

		raw_len = seen;
		if (raw_len == 0) {
			gnutls_assert();
			err = GNUTLS_E_BASE64_DECODING_ERROR;
			goto error;
		}

		free_data = 1;
	} else {		/* RAW */
		raw_len = data->size;
		raw_data = data->data;
	}

	err =
	    cdk_keydb_new_from_mem(&keyring->db, 0, 0, raw_data, raw_len);
	if (err)
		gnutls_assert();

	if (free_data) {
		err = _gnutls_map_cdk_rc(err);
		goto error;
	}

	return _gnutls_map_cdk_rc(err);

      error:
	gnutls_free(raw_data);
	cdk_stream_close(input);

	return err;
}
Пример #12
0
/**
 * 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;
}
Пример #13
0
/**
  * gnutls_openpgp_key_export - This function will export a RAW or BASE64 encoded key
  * @key: Holds the key.
  * @format: One of gnutls_openpgp_key_fmt_t elements.
  * @output_data: will contain the key base64 encoded or raw
  * @output_data_size: holds the size of output_data (and will be replaced by the actual size of parameters)
  *
  * This function will convert the given key to RAW or Base64 format.
  * If the buffer provided is not long enough to hold the output, then
  * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
  *
  * Returns 0 on success.
  *
  **/
int
gnutls_openpgp_key_export (gnutls_openpgp_key_t key,
			   gnutls_openpgp_key_fmt_t format,
			   void *output_data, size_t * output_data_size)
{
  int rc;
  size_t input_data_size = *output_data_size;

  rc = cdk_kbnode_write_to_mem (key->knode, output_data, output_data_size);
  if (rc)
    {
      rc = _gnutls_map_cdk_rc (rc);
      gnutls_assert ();
      return rc;
    }

  if (format == GNUTLS_OPENPGP_FMT_BASE64)
    {
      cdk_stream_t s;

      s = cdk_stream_tmp_from_mem (output_data, *output_data_size);
      if (s == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_MEMORY_ERROR;
	}

      cdk_stream_tmp_set_mode (s, 1);
      rc = cdk_stream_set_armor_flag (s, CDK_ARMOR_PUBKEY);
      if (rc)
	{
	  rc = _gnutls_map_cdk_rc (rc);
	  gnutls_assert ();
	  cdk_stream_close (s);
	  return rc;
	}


      *output_data_size = input_data_size;

      rc = cdk_stream_read (s, output_data, *output_data_size);
      if (rc == EOF)
	{
	  gnutls_assert ();
	  cdk_stream_close (s);
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      *output_data_size = rc;
      if (*output_data_size != cdk_stream_get_length (s))
	{
	  *output_data_size = cdk_stream_get_length (s);
	  cdk_stream_close (s);
	  gnutls_assert ();
	  return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}

      cdk_stream_close (s);
    }

  return 0;
}