Пример #1
0
/**
 * gnutls_openpgp_crt_print:
 * @cert: The structure to be printed
 * @format: Indicate the format to use
 * @out: Newly allocated datum with (0) terminated string.
 *
 * This function will pretty print an OpenPGP certificate, suitable
 * for display to a human.
 *
 * The format should be (0) for future compatibility.
 *
 * The output @out needs to be deallocate using gnutls_free().
 *
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
 **/
int
gnutls_openpgp_crt_print(gnutls_openpgp_crt_t cert,
			 gnutls_certificate_print_formats_t format,
			 gnutls_datum_t * out)
{
	gnutls_buffer_st str;
	int ret;

	_gnutls_buffer_init(&str);

	if (format == GNUTLS_CRT_PRINT_ONELINE)
		print_oneline(&str, cert);
	else if (format == GNUTLS_CRT_PRINT_COMPACT) {
		print_oneline(&str, cert);

		_gnutls_buffer_append_data(&str, "\n", 1);
		print_key_fingerprint(&str, cert);
	} else {
		_gnutls_buffer_append_str(&str,
					  _
					  ("OpenPGP Certificate Information:\n"));
		print_cert(&str, cert);
	}

	_gnutls_buffer_append_data(&str, "\0", 1);

	ret = _gnutls_buffer_to_datum(&str, out);
	if (out->size > 0)
		out->size--;

	return ret;
}
Пример #2
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_max_record_send_params (gnutls_session_t session, gnutls_buffer_st* extdata)
{
  uint8_t p;
  int ret;

  /* this function sends the client extension data (dnsname) */
  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {
      extension_priv_data_t epriv;

      ret = _gnutls_ext_get_session_data (session,
                                          GNUTLS_EXTENSION_MAX_RECORD_SIZE,
                                          &epriv);
      if (ret < 0)              /* it is ok not to have it */
        {
          return 0;
        }

      if (epriv.num != DEFAULT_MAX_RECORD_SIZE)
        {
          p = (uint8_t) _gnutls_mre_record2num (epriv.num);
          ret = _gnutls_buffer_append_data( extdata, &p, 1);
          if (ret < 0)
            return gnutls_assert_val(ret);

          return 1;
        }

    }
  else
    {                           /* server side */

      if (session->security_parameters.max_record_recv_size !=
          DEFAULT_MAX_RECORD_SIZE)
        {
          p =
            (uint8_t)
            _gnutls_mre_record2num
            (session->security_parameters.max_record_recv_size);

          ret = _gnutls_buffer_append_data( extdata, &p, 1);
          if (ret < 0)
            return gnutls_assert_val(ret);

          return 1;
        }
    }

  return 0;
}
Пример #3
0
/**
 * gnutls_openpgp_crt_print:
 * @cert: The structure to be printed
 * @format: Indicate the format to use
 * @out: Newly allocated datum with zero terminated string.
 *
 * This function will pretty print an OpenPGP certificate, suitable
 * for display to a human.
 *
 * The format should be zero for future compatibility.
 *
 * The output @out needs to be deallocate using gnutls_free().
 *
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
 **/
int
gnutls_openpgp_crt_print (gnutls_openpgp_crt_t cert,
                          gnutls_certificate_print_formats_t format,
                          gnutls_datum_t * out)
{
  gnutls_buffer_st str;

  _gnutls_buffer_init (&str);

  if (format == GNUTLS_CRT_PRINT_ONELINE)
    print_oneline (&str, cert);
  else
    {
      _gnutls_buffer_append_str (&str,
                                 _("OpenPGP Certificate Information:\n"));
      print_cert (&str, cert);
    }

  _gnutls_buffer_append_data (&str, "\0", 1);

  out->data = str.data;
  out->size = strlen (str.data);

  return 0;
}
Пример #4
0
int
_gnutls_buffer_append_prefix (gnutls_buffer_st * buf, int pfx_size, size_t data_size)
{
  opaque ss[4];

  if (pfx_size == 32)
    {
      _gnutls_write_uint32 (data_size, ss);
      pfx_size = 4;
    }
  else if (pfx_size == 24)
    {
      _gnutls_write_uint24 (data_size, ss);
      pfx_size = 3;
    }
  else if (pfx_size == 16)
    {
      _gnutls_write_uint16 (data_size, ss);
      pfx_size = 2;
    }
  else if (pfx_size == 8)
    {
      ss[0] = data_size;
      pfx_size = 1;
    }
  else
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

  return _gnutls_buffer_append_data (buf, ss, pfx_size);
}
Пример #5
0
static int gen_supplemental(gnutls_session_t session, const gnutls_supplemental_entry_st *supp,
			    gnutls_buffer_st * buf)
{
	int ret;
	gnutls_supp_send_func supp_send = supp->supp_send_func;
	size_t sizepos = buf->length;

	/* Make room for supplement type and length byte length field. */
	ret = _gnutls_buffer_append_data(buf, "\0\0\0\0", 4);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = supp_send(session, buf);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* If data were added, store type+length, otherwise reset. */
	if (buf->length > sizepos + 4) {
		buf->data[sizepos] = (supp->type >> 8) & 0xFF;
		buf->data[sizepos + 1] = supp->type & 0xFF;
		buf->data[sizepos + 2] =
		    ((buf->length - sizepos - 4) >> 8) & 0xFF;
		buf->data[sizepos + 3] =
		    (buf->length - sizepos - 4) & 0xFF;
	} else
Пример #6
0
/**
 * gnutls_record_send:
 * @session: is a #gnutls_session_t structure.
 * @data: contains the data to send
 * @data_size: is the length of the data
 *
 * This function has the similar semantics with send().  The only
 * difference is that it accepts a GnuTLS session, and uses different
 * error codes.
 * Note that if the send buffer is full, send() will block this
 * function.  See the send() documentation for more information.  
 *
 * You can replace the default push function which is send(), by using
 * gnutls_transport_set_push_function().
 *
 * If the EINTR is returned by the internal push function 
 * then %GNUTLS_E_INTERRUPTED will be returned. If
 * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must
 * call this function again, with the exact same parameters; alternatively
 * you could provide a %NULL pointer for data, and 0 for
 * size. cf. gnutls_record_get_direction(). 
 *
 * Note that in DTLS this function will return the %GNUTLS_E_LARGE_PACKET
 * error code if the send data exceed the data MTU value - as returned
 * by gnutls_dtls_get_data_mtu(). The errno value EMSGSIZE
 * also maps to %GNUTLS_E_LARGE_PACKET. 
 * Note that since 3.2.13 this function can be called under cork in DTLS
 * mode, and will refuse to send data over the MTU size by returning
 * %GNUTLS_E_LARGE_PACKET.
 *
 * Returns: The number of bytes sent, or a negative error code.  The
 *   number of bytes sent might be less than @data_size.  The maximum
 *   number of bytes this function can send in a single call depends
 *   on the negotiated maximum record size.
 **/
ssize_t
gnutls_record_send(gnutls_session_t session, const void *data,
		   size_t data_size)
{
	if (session->internals.record_flush_mode == RECORD_FLUSH) {
		return _gnutls_send_int(session, GNUTLS_APPLICATION_DATA,
					-1, EPOCH_WRITE_CURRENT, data,
					data_size, MBUFFER_FLUSH);
	} else {		/* GNUTLS_CORKED */

		int ret;

		if (IS_DTLS(session)) {
			if (data_size + session->internals.record_presend_buffer.length >
				gnutls_dtls_get_data_mtu(session)) {
				return gnutls_assert_val(GNUTLS_E_LARGE_PACKET);
			}
		}

		ret =
		    _gnutls_buffer_append_data(&session->internals.
					       record_presend_buffer, data,
					       data_size);
		if (ret < 0)
			return gnutls_assert_val(ret);

		return data_size;
	}
}
Пример #7
0
/**
 * gnutls_ocsp_req_print:
 * @req: The structure to be printed
 * @format: Indicate the format to use
 * @out: Newly allocated datum with (0) terminated string.
 *
 * This function will pretty print a OCSP request, suitable for
 * display to a human.
 *
 * If the format is %GNUTLS_OCSP_PRINT_FULL then all fields of the
 * request will be output, on multiple lines.
 *
 * The output @out->data needs to be deallocate using gnutls_free().
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_ocsp_req_print (gnutls_ocsp_req_t req,
                       gnutls_ocsp_print_formats_t format,
                       gnutls_datum_t * out)
{
  gnutls_buffer_st str;
  int rc;

  if (format != GNUTLS_OCSP_PRINT_FULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  _gnutls_buffer_init (&str);

  _gnutls_buffer_append_str (&str, _("OCSP Request Information:\n"));

  print_req (&str, req);

  _gnutls_buffer_append_data (&str, "\0", 1);

  rc = _gnutls_buffer_to_datum (&str, out);
  if (rc != GNUTLS_E_SUCCESS)
    {
      gnutls_assert ();
      return rc;
    }

  return GNUTLS_E_SUCCESS;
}
Пример #8
0
/* Buffer for handshake packets. Keeps the packets in order
 * for finished messages to use them. Used in HMAC calculation
 * and finished messages.
 */
int
_gnutls_handshake_hash_buffer_put (gnutls_session_t session, opaque * data,
                              size_t length)
{

  if (length == 0)
    return 0;

  if ((session->internals.max_handshake_data_buffer_size > 0) &&
      ((length + session->internals.handshake_hash_buffer.length) >
       session->internals.max_handshake_data_buffer_size))
    {
      gnutls_assert ();
      return GNUTLS_E_HANDSHAKE_TOO_LARGE;
    }

  _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data\n", (int) length);
  if (_gnutls_buffer_append_data (&session->internals.handshake_hash_buffer,
                                  data, length) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  return 0;
}
Пример #9
0
/**
 * gnutls_ocsp_resp_print:
 * @resp: The structure to be printed
 * @format: Indicate the format to use
 * @out: Newly allocated datum with (0) terminated string.
 *
 * This function will pretty print a OCSP response, suitable for
 * display to a human.
 *
 * If the format is %GNUTLS_OCSP_PRINT_FULL then all fields of the
 * response will be output, on multiple lines.
 *
 * The output @out->data needs to be deallocate using gnutls_free().
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_ocsp_resp_print (gnutls_ocsp_resp_t resp,
			gnutls_ocsp_print_formats_t format,
			gnutls_datum_t * out)
{
  gnutls_buffer_st str;
  int rc;

  _gnutls_buffer_init (&str);

  _gnutls_buffer_append_str (&str, _("OCSP Response Information:\n"));

  print_resp (&str, resp, format);

  _gnutls_buffer_append_data (&str, "\0", 1);

  rc = _gnutls_buffer_to_datum (&str, out);
  if (rc != GNUTLS_E_SUCCESS)
    {
      gnutls_assert ();
      return rc;
    }

  return GNUTLS_E_SUCCESS;
}
Пример #10
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_signature_algorithm_send_params (gnutls_session_t session,
                                         gnutls_buffer_st* extdata)
{
  int ret;
  size_t init_length = extdata->length;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  /* this function sends the client extension data */
  if (session->security_parameters.entity == GNUTLS_CLIENT
      && _gnutls_version_has_selectable_sighash (ver))
    {
      if (session->internals.priorities.sign_algo.algorithms > 0)
        {
          uint8_t p[MAX_SIGN_ALGO_SIZE];

          ret =
            _gnutls_sign_algorithm_write_params (session, p, sizeof(p));
          if (ret < 0)
            return gnutls_assert_val(ret);

          ret = _gnutls_buffer_append_data(extdata, p, ret);
          if (ret < 0)
            return gnutls_assert_val(ret);
            
          return extdata->length - init_length;
        }
    }

  /* if we are here it means we don't send the extension */
  return 0;
}
Пример #11
0
static int
unescape_string(char *output, const char *input, size_t * size,
		char terminator)
{
	gnutls_buffer_st str;
	int ret = 0;
	char *p;
	int len;

	_gnutls_buffer_init(&str);

	/* find terminator */
	p = strchr(input, terminator);
	if (p != NULL)
		len = p - input;
	else
		len = strlen(input);

	ret = _gnutls_buffer_append_data(&str, input, len);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = _gnutls_buffer_unescape(&str);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = _gnutls_buffer_append_data(&str, "", 1);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = _gnutls_buffer_pop_data(&str, output, str.length);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_buffer_clear(&str);

	return ret;
}
Пример #12
0
/* If the psk flag is set, then an empty psk_identity_hint will
 * be inserted */
int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session,
					gnutls_buffer_st * data,
					gnutls_ecc_curve_t curve)
{
	uint8_t p;
	int ret;
	gnutls_datum_t out;

	if (curve == GNUTLS_ECC_CURVE_INVALID)
		return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);

	/* just in case we are resuming a session */
	gnutls_pk_params_release(&session->key.ecdh_params);

	gnutls_pk_params_init(&session->key.ecdh_params);

	/* curve type */
	p = 3;

	ret = _gnutls_buffer_append_data(data, &p, 1);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_buffer_append_prefix(data, 16,
					 _gnutls_ecc_curve_get_tls_id
					 (curve));
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* generate temporal key */
	ret =
	    _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve,
				     &session->key.ecdh_params);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_ecc_ansi_x963_export(curve,
					 session->key.ecdh_params.
					 params[ECC_X] /* x */ ,
					 session->key.ecdh_params.
					 params[ECC_Y] /* y */ , &out);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);

	_gnutls_free_datum(&out);

	if (ret < 0)
		return gnutls_assert_val(ret);

	return data->length;
}
Пример #13
0
/* returns a positive number if we send the extension data, (0) if we
   do not want to send it, and a negative number on failure.
 */
static int
session_ticket_send_params(gnutls_session_t session,
                           gnutls_buffer_st * extdata)
{
    session_ticket_ext_st *priv = NULL;
    extension_priv_data_t epriv;
    int ret;

    ret =
        _gnutls_ext_get_session_data(session,
                                     GNUTLS_EXTENSION_SESSION_TICKET,
                                     &epriv);
    if (ret >= 0)
        priv = epriv;

    if (priv == NULL || !priv->session_ticket_enable)
        return 0;

    if (session->security_parameters.entity == GNUTLS_SERVER) {
        if (priv && priv->session_ticket_renew) {
            return GNUTLS_E_INT_RET_0;
        }
    } else {
        ret =
            _gnutls_ext_get_resumed_session_data(session,
                    GNUTLS_EXTENSION_SESSION_TICKET,
                    &epriv);
        if (ret >= 0)
            priv = epriv;

        /* no previous data. Just advertize it */
        if (ret < 0)
            return GNUTLS_E_INT_RET_0;

        /* previous data had session tickets disabled. Don't advertize. Ignore. */
        if (!priv->session_ticket_enable)
            return 0;

        if (priv->session_ticket_len > 0) {
            ret =
                _gnutls_buffer_append_data(extdata,
                                           priv->
                                           session_ticket,
                                           priv->
                                           session_ticket_len);
            if (ret < 0)
                return gnutls_assert_val(ret);

            return priv->session_ticket_len;
        }
    }
    return 0;
}
Пример #14
0
int _gnutls_krb5_der_to_principal(const gnutls_datum_t * der,
				  gnutls_datum_t * name)
{
	int ret, result;
	ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
	gnutls_buffer_st str;

	_gnutls_buffer_init(&str);

	result =
	    asn1_create_element(_gnutls_get_gnutls_asn(),
				"GNUTLS.KRB5PrincipalName", &c2);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		ret = _gnutls_asn2err(result);
		goto cleanup;
	}

	result = asn1_der_decoding(&c2, der->data, der->size, NULL);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		ret = _gnutls_asn2err(result);
		goto cleanup;
	}

	ret = principal_to_str(c2, &str);
	if (ret < 0) {
		/* for some reason we cannot convert to a human readable string
		 * the principal. Then we use the #HEX format.
		 */
		_gnutls_buffer_reset(&str);
		ret = _gnutls_buffer_append_data(&str, "#", 1);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		_gnutls_buffer_hexprint(&str, der->data, der->size);
	}

	asn1_delete_structure(&c2);
	return _gnutls_buffer_to_datum(&str, name, 1);

 cleanup:
	_gnutls_buffer_clear(&str);
	asn1_delete_structure(&c2);
	return ret;
}
Пример #15
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_supported_ecc_pf_send_params(gnutls_session_t session,
				     gnutls_buffer_st * extdata)
{
	const uint8_t p[2] = { 0x01, 0x00 };	/* only support uncompressed point format */

	if (session->security_parameters.entity == GNUTLS_SERVER
	    && !_gnutls_session_is_ecc(session))
		return 0;

	if (session->internals.priorities.supported_ecc.algorithms > 0) {
		_gnutls_buffer_append_data(extdata, p, 2);
		return 2;
	}
	return 0;
}
Пример #16
0
int
_gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, 
    int pfx_size, const void *data, size_t data_size)
{
int ret = 0, ret1;

  ret1 = _gnutls_buffer_append_prefix (buf, pfx_size, data_size);
  if (ret1 < 0)
    return gnutls_assert_val(ret1);

  if (data_size > 0)
    {
      ret = _gnutls_buffer_append_data (buf, data, data_size);

      if (ret < 0)
        return gnutls_assert_val(ret);
    }

  return ret + ret1;
}
Пример #17
0
/**
 * gnutls_record_send:
 * @session: is a #gnutls_session_t structure.
 * @data: contains the data to send
 * @data_size: is the length of the data
 *
 * This function has the similar semantics with send().  The only
 * difference is that it accepts a GnuTLS session, and uses different
 * error codes.
 * Note that if the send buffer is full, send() will block this
 * function.  See the send() documentation for full information.  You
 * can replace the default push function by using
 * gnutls_transport_set_ptr2() with a call to send() with a
 * MSG_DONTWAIT flag if blocking is a problem.
 * If the EINTR is returned by the internal push function (the
 * default is send()) then %GNUTLS_E_INTERRUPTED will be returned. If
 * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must
 * call this function again, with the same parameters; alternatively
 * you could provide a %NULL pointer for data, and 0 for
 * size. cf. gnutls_record_get_direction(). 
 *
 * Note that in DTLS this function will return the %GNUTLS_E_LARGE_PACKET
 * error code if the send data exceed the data MTU value - as returned
 * by gnutls_dtls_get_data_mtu(). The errno value EMSGSIZE
 * also maps to %GNUTLS_E_LARGE_PACKET.
 *
 * Returns: The number of bytes sent, or a negative error code.  The
 *   number of bytes sent might be less than @data_size.  The maximum
 *   number of bytes this function can send in a single call depends
 *   on the negotiated maximum record size.
 **/
ssize_t
gnutls_record_send (gnutls_session_t session, const void *data,
                    size_t data_size)
{
  if (session->internals.record_flush_mode == RECORD_FLUSH)
    {
      return _gnutls_send_int (session, GNUTLS_APPLICATION_DATA, -1,
                               EPOCH_WRITE_CURRENT, data, data_size,
                               MBUFFER_FLUSH);
    }
  else /* GNUTLS_CORKED */
    {
      int ret;

      ret = _gnutls_buffer_append_data(&session->internals.record_presend_buffer, data, data_size);
      if (ret < 0)
        return gnutls_assert_val(ret);
      
      return data_size;
    }
}
Пример #18
0
static int
_gnutls_heartbeat_send_params(gnutls_session_t session,
			      gnutls_buffer_st * extdata)
{
	extension_priv_data_t epriv;
	uint8_t p;

	if (_gnutls_ext_get_session_data
	    (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0)
		return 0;	/* nothing to send - not enabled */

	if (epriv.num & GNUTLS_HB_PEER_ALLOWED_TO_SEND)
		p = 1;
	else			/*if (epriv.num & GNUTLS_HB_PEER_NOT_ALLOWED_TO_SEND) */
		p = 2;

	if (_gnutls_buffer_append_data(extdata, &p, 1) < 0)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	return 1;
}
Пример #19
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_cert_type_send_params(gnutls_session_t session,
			      gnutls_buffer_st * extdata)
{
	unsigned len, i;
	int ret;
	uint8_t p;

	/* this function sends the client extension data (dnsname) */
	if (session->security_parameters.entity == GNUTLS_CLIENT) {

		if (session->internals.priorities.cert_type.algorithms > 0) {

			len =
			    session->internals.priorities.cert_type.
			    algorithms;

			if (len == 1 &&
			    session->internals.priorities.cert_type.
			    priority[0] == GNUTLS_CRT_X509) {
				/* We don't use this extension if X.509 certificates
				 * are used.
				 */
				return 0;
			}

			/* this is a vector!
			 */
			p = (uint8_t) len;
			ret = _gnutls_buffer_append_data(extdata, &p, 1);
			if (ret < 0)
				return gnutls_assert_val(ret);

			for (i = 0; i < len; i++) {
				p = _gnutls_cert_type2num(session->
							  internals.
							  priorities.cert_type.
							  priority[i]);
				ret =
				    _gnutls_buffer_append_data(extdata, &p,
							       1);
				if (ret < 0)
					return gnutls_assert_val(ret);
			}
			return len + 1;
		}

	} else {		/* server side */
		if (session->security_parameters.cert_type !=
		    DEFAULT_CERT_TYPE) {
			len = 1;

			p = _gnutls_cert_type2num(session->
						  security_parameters.
						  cert_type);
			ret = _gnutls_buffer_append_data(extdata, &p, 1);
			if (ret < 0)
				return gnutls_assert_val(ret);

			return len;
		}


	}

	return 0;
}
Пример #20
0
static
int append_status_request(void *_ctx, gnutls_buffer_st *buf)
{
	struct ocsp_req_ctx_st *ctx = _ctx;
	gnutls_session_t session = ctx->session;
	int ret;
	gnutls_datum_t resp;
	unsigned free_resp = 0;

	assert(session->internals.selected_ocsp_func != NULL ||
	       session->internals.selected_ocsp_length != 0);

	/* The global ocsp callback function can only be used to return
	 * a single certificate request */
	if (session->internals.selected_ocsp_length == 1 && ctx->cert_index != 0)
		return 0;

	if (session->internals.selected_ocsp_length > 0) {
		if (ctx->cert_index < session->internals.selected_ocsp_length) {
			if ((session->internals.selected_ocsp[ctx->cert_index].exptime != 0 &&
			    gnutls_time(0) >= session->internals.selected_ocsp[ctx->cert_index].exptime) ||
			    session->internals.selected_ocsp[ctx->cert_index].response.data == NULL) {
				return 0;
			}

			resp.data = session->internals.selected_ocsp[ctx->cert_index].response.data;
			resp.size = session->internals.selected_ocsp[ctx->cert_index].response.size;
			ret = 0;
		} else {
			return 0;
		}
	} else if (session->internals.selected_ocsp_func) {
		if (ctx->cert_index == 0) {
			ret = session->internals.selected_ocsp_func(session, session->internals.selected_ocsp_func_ptr, &resp);
			free_resp = 1;
		} else {
			return 0;
		}
	} else
		return 0;

	if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS || resp.data == 0) {
		return 0;
	} else if (ret < 0) {
		return gnutls_assert_val(ret);
	}

	ret = _gnutls_buffer_append_data(buf, "\x01", 1);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_buffer_append_data_prefix(buf, 24, resp.data, resp.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = 0;
 cleanup:
	if (free_resp)
		gnutls_free(resp.data);
	return ret;
}
Пример #21
0
static
int get_win_urls(const CERT_CONTEXT * cert, char **cert_url, char **key_url,
		 char **label, gnutls_datum_t * der)
{
	BOOL r;
	int ret;
	DWORD tl_size;
	gnutls_datum_t tmp_label = { NULL, 0 };
	char name[MAX_CN * 2];
	char hex[MAX_WID_SIZE * 2 + 1];
	gnutls_buffer_st str;
#ifdef WORDS_BIGENDIAN
	const unsigned bigendian = 1;
#else
	const unsigned bigendian = 0;
#endif

	if (cert == NULL)
		return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);

	if (der) {
		der->data = gnutls_malloc(cert->cbCertEncoded);
		if (der->data == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		memcpy(der->data, cert->pbCertEncoded, cert->cbCertEncoded);
		der->size = cert->cbCertEncoded;
	}

	_gnutls_buffer_init(&str);
	if (label)
		*label = NULL;
	if (key_url)
		*key_url = NULL;
	if (cert_url)
		*cert_url = NULL;

	tl_size = sizeof(name);
	r = CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
					      name, &tl_size);
	if (r != 0) {		/* optional */
		ret =
		    _gnutls_ucs2_to_utf8(name, tl_size, &tmp_label, bigendian);
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}
		if (label)
			*label = (char *)tmp_label.data;
	}

	tl_size = sizeof(name);
	r = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID,
					      name, &tl_size);
	if (r == 0) {
		gnutls_assert();
		ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
		goto fail;
	}

	if (_gnutls_bin2hex(name, tl_size, hex, sizeof(hex), 0) == NULL) {
		ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
		goto fail;
	}

	ret =
	    _gnutls_buffer_append_printf(&str, WIN_URL "id=%s;type=cert", hex);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (tmp_label.data) {
		ret = _gnutls_buffer_append_str(&str, ";name=");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}

		ret =
		    _gnutls_buffer_append_escape(&str, tmp_label.data,
						 tmp_label.size, " ");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}
	}

	ret = _gnutls_buffer_append_data(&str, "\x00", 1);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (cert_url)
		*cert_url = (char *)str.data;
	_gnutls_buffer_init(&str);

	ret =
	    _gnutls_buffer_append_printf(&str, WIN_URL "id=%s;type=privkey",
					 hex);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (tmp_label.data) {
		ret = _gnutls_buffer_append_str(&str, ";name=");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}

		ret =
		    _gnutls_buffer_append_escape(&str, tmp_label.data,
						 tmp_label.size, " ");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}
	}

	ret = _gnutls_buffer_append_data(&str, "\x00", 1);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (key_url)
		*key_url = (char *)str.data;
	_gnutls_buffer_init(&str);

	ret = 0;
	goto cleanup;

 fail:
	if (der)
		gnutls_free(der->data);
	if (cert_url)
		gnutls_free(*cert_url);
	if (key_url)
		gnutls_free(*key_url);
	if (label)
		gnutls_free(*label);
 cleanup:
	_gnutls_buffer_clear(&str);
	return ret;
}
Пример #22
0
/* This is a receive function for the gnutls handshake 
 * protocol. Makes sure that we have received all data.
 */
static int
parse_record_buffered_msgs (gnutls_session_t session,
                               gnutls_handshake_description_t htype,
                               handshake_buffer_st * hsk)
{
  gnutls_datum_t msg;
  mbuffer_st* bufel = NULL, *prev = NULL;
  int ret;
  size_t data_size;
  handshake_buffer_st* recv_buf = session->internals.handshake_recv_buffer;

  bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg);
  if (bufel == NULL)
    return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;

  if (!IS_DTLS(session))
    {
      ssize_t remain, append, header_size;

      do
        {
          if (bufel->type != GNUTLS_HANDSHAKE)
            return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);

          /* if we have a half received message the complete it.
           */
          remain =  recv_buf[0].length -
                recv_buf[0].data.length;

          /* this is the rest of a previous message */
          if (session->internals.handshake_recv_buffer_size > 0 && recv_buf[0].length > 0 && remain > 0)
            {
              if (msg.size <= remain)
                append = msg.size;
              else
                append = remain;
                  
              ret = _gnutls_buffer_append_data(&recv_buf[0].data, msg.data, append);
              if (ret < 0)
                return gnutls_assert_val(ret);

              _mbuffer_head_remove_bytes(&session->internals.record_buffer, append);
            }
          else /* received new message */
            {
              ret = parse_handshake_header(session, bufel, htype, &recv_buf[0]);
              if (ret < 0)
                return gnutls_assert_val(ret);

              header_size = ret;
              session->internals.handshake_recv_buffer_size = 1;

              _mbuffer_set_uhead_size(bufel, header_size);

              data_size = MIN(recv_buf[0].length, _mbuffer_get_udata_size(bufel));
              ret = _gnutls_buffer_append_data(&recv_buf[0].data, _mbuffer_get_udata_ptr(bufel), data_size);
              if (ret < 0)
                return gnutls_assert_val(ret);
              _mbuffer_set_uhead_size(bufel, 0);
              _mbuffer_head_remove_bytes(&session->internals.record_buffer, data_size+header_size);

              if (cmp_hsk_types(htype, recv_buf[0].htype) == 0)
                { /* an unexpected packet */
                  hsk->htype = recv_buf[0].htype;
                  return gnutls_assert_val(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET);
                }

            }

          /* if packet is complete then return it
           */
          if (recv_buf[0].length ==
                recv_buf[0].data.length)
            {
              return get_last_packet(session, htype, hsk);
            }
          bufel = _mbuffer_head_get_first(&session->internals.record_buffer, &msg);
        } 
      while(bufel != NULL);
    
      /* if we are here it means that the received packets were not
       * enough to complete the handshake packet.
       */
      return gnutls_assert_val(GNUTLS_E_AGAIN);
    }
  else /* DTLS */
    {
      handshake_buffer_st tmp;

      do
        {
          /* we now 
           * 0. parse headers
           * 1. insert to handshake_recv_buffer
           * 2. sort handshake_recv_buffer on sequence numbers
           * 3. return first packet if completed or GNUTLS_E_AGAIN.
           */
          do
            {
              if (bufel->type != GNUTLS_HANDSHAKE)
                {
                  gnutls_assert();
                  goto next; /* ignore packet */
                }

              _gnutls_handshake_buffer_init(&tmp);

              ret = parse_handshake_header(session, bufel, htype, &tmp);
              if (ret < 0)
                {
                  gnutls_assert();
                  _gnutls_audit_log("Invalid handshake packet headers. Discarding.\n");
                  break;
                }

              _mbuffer_consume(&session->internals.record_buffer, bufel, ret);

              data_size = MIN(tmp.length, tmp.end_offset-tmp.start_offset+1);

              ret = _gnutls_buffer_append_data(&tmp.data, _mbuffer_get_udata_ptr(bufel), data_size);
              if (ret < 0)
                return gnutls_assert_val(ret);

              _mbuffer_consume(&session->internals.record_buffer, bufel, data_size);

              ret = merge_handshake_packet(session, &tmp);
              if (ret < 0)
                return gnutls_assert_val(ret);

            }
          while(_mbuffer_get_udata_size(bufel) > 0);

          prev = bufel;
          bufel = _mbuffer_dequeue(&session->internals.record_buffer, bufel);

          _mbuffer_xfree(&prev);
          continue;

next:
          bufel = _mbuffer_head_get_next(bufel, NULL);
        }
      while(bufel != NULL);

      /* sort in descending order */
      if (session->internals.handshake_recv_buffer_size > 1)
        qsort(recv_buf, session->internals.handshake_recv_buffer_size,
          sizeof(recv_buf[0]), handshake_compare);

      while(session->internals.handshake_recv_buffer_size > 0 &&
        recv_buf[LAST_ELEMENT].sequence < session->internals.dtls.hsk_read_seq)
        {
          _gnutls_audit_log("Discarded replayed handshake packet with sequence %d\n", recv_buf[LAST_ELEMENT].sequence);
          _gnutls_handshake_buffer_clear(&recv_buf[LAST_ELEMENT]);
          session->internals.handshake_recv_buffer_size--;
        }

        return get_last_packet(session, htype, hsk);
    }
}
Пример #23
0
static int
gen_srp_cert_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	ssize_t ret;
	gnutls_datum_t signature, ddata;
	gnutls_certificate_credentials_t cred;
	gnutls_pcert_st *apr_cert_list;
	gnutls_privkey_t apr_pkey;
	int apr_cert_list_length;
	gnutls_sign_algorithm_t sign_algo;
	const version_entry_st *ver = get_version(session);

	if (unlikely(ver == NULL))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	ret = _gnutls_gen_srp_server_kx(session, data);

	if (ret < 0)
		return ret;

	ddata.data = data->data;
	ddata.size = data->length;

	cred = (gnutls_certificate_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	/* find the appropriate certificate */
	if ((ret =
	     _gnutls_get_selected_cert(session, &apr_cert_list,
				       &apr_cert_list_length,
				       &apr_pkey)) < 0) {
		gnutls_assert();
		return ret;
	}

	if ((ret =
	     _gnutls_handshake_sign_data(session, &apr_cert_list[0],
					 apr_pkey, &ddata, &signature,
					 &sign_algo)) < 0) {
		gnutls_assert();
		return ret;
	}

	if (_gnutls_version_has_selectable_sighash(ver)) {
		const sign_algorithm_st *aid;
		uint8_t p[2];

		if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
			ret = GNUTLS_E_UNKNOWN_ALGORITHM;
			goto cleanup;
		}

		aid = _gnutls_sign_to_tls_aid(sign_algo);
		if (aid == NULL) {
			gnutls_assert();
			ret = GNUTLS_E_UNKNOWN_ALGORITHM;
			goto cleanup;
		}

		p[0] = aid->hash_algorithm;
		p[1] = aid->sign_algorithm;

		ret = _gnutls_buffer_append_data(data, p, 2);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	ret =
	    _gnutls_buffer_append_data_prefix(data, 16, signature.data,
					      signature.size);

	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = data->length;

      cleanup:
	_gnutls_free_datum(&signature);
	return ret;
}
Пример #24
0
/* Load session data from a buffer.
 */
int
_gnutls_session_unpack (gnutls_session_t session,
                        const gnutls_datum_t * packed_session)
{
  int ret;
  gnutls_buffer_st sb;
  opaque id;

  _gnutls_buffer_init (&sb);

  if (packed_session == NULL || packed_session->size == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ret =
    _gnutls_buffer_append_data (&sb, packed_session->data,
                                packed_session->size);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if (_gnutls_get_auth_info (session) != NULL)
    {
      _gnutls_free_auth_info (session);
    }

  BUFFER_POP (&sb, &id, 1);

  switch (id)
    {
#ifdef ENABLE_SRP
    case GNUTLS_CRD_SRP:
      ret = unpack_srp_auth_info (session, &sb);
      if (ret < 0)
        {
          gnutls_assert ();
          goto error;
        }
      break;
#endif
#ifdef ENABLE_PSK
    case GNUTLS_CRD_PSK:
      ret = unpack_psk_auth_info (session, &sb);
      if (ret < 0)
        {
          gnutls_assert ();
          goto error;
        }
      break;
#endif
#ifdef ENABLE_ANON
    case GNUTLS_CRD_ANON:
      ret = unpack_anon_auth_info (session, &sb);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }
      break;
#endif
    case GNUTLS_CRD_CERTIFICATE:
      ret = unpack_certificate_auth_info (session, &sb);
      if (ret < 0)
        {
          gnutls_assert ();
          goto error;
        }
      break;
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto error;

    }

  /* Auth_info structures copied. Now copy security_parameters_st. 
   * packed_session must have allocated space for the security parameters.
   */
  ret = unpack_security_parameters (session, &sb);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }

  ret = _gnutls_ext_unpack (session, &sb);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }

  ret = 0;

error:
  _gnutls_buffer_clear (&sb);

  return ret;
}
Пример #25
0
static int principal_to_str(ASN1_TYPE c2, gnutls_buffer_st * str)
{
	gnutls_datum_t realm = { NULL, 0 };
	gnutls_datum_t component = { NULL, 0 };
	unsigned char name_type[2];
	int ret, result, len;
	unsigned i;
	char val[128];

	ret = _gnutls_x509_read_value(c2, "realm", &realm);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	len = sizeof(name_type);
	result =
	    asn1_read_value(c2, "principalName.name-type", name_type, &len);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		ret = _gnutls_asn2err(result);
		goto cleanup;
	}

	if (len != 1
	    || (name_type[0] != 1 && name_type[0] != 2 && name_type[0] != 10)) {
		ret = GNUTLS_E_INVALID_REQUEST;
		goto cleanup;
	}

	for (i = 0;; i++) {
		snprintf(val, sizeof(val), "principalName.name-string.?%u",
			 i + 1);
		ret = _gnutls_x509_read_value(c2, val, &component);
		if (ret == GNUTLS_E_ASN1_VALUE_NOT_FOUND
		    || ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
			break;
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		if (i > 0) {
			ret = _gnutls_buffer_append_data(str, "/", 1);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
		}

		ret =
		    _gnutls_buffer_append_data(str, component.data,
					       component.size);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		_gnutls_free_datum(&component);
	}

	ret = _gnutls_buffer_append_data(str, "@", 1);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_buffer_append_data(str, realm.data, realm.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = 0;
 cleanup:
	_gnutls_free_datum(&component);
	gnutls_free(realm.data);
	return ret;
}
Пример #26
0
int
_gnutls_buffer_append_str (gnutls_buffer_st * dest, const char *src)
{
  return _gnutls_buffer_append_data (dest, src, strlen (src));
}
Пример #27
0
Файл: dhe.c Проект: intgr/gnutls
static int
gen_dhe_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  bigint_t g, p;
  const bigint_t *mpis;
  int ret = 0, data_size;
  gnutls_pcert_st *apr_cert_list;
  gnutls_privkey_t apr_pkey;
  int apr_cert_list_length;
  gnutls_datum_t signature = { NULL, 0 }, ddata;
  gnutls_certificate_credentials_t cred;
  gnutls_dh_params_t dh_params;
  gnutls_sign_algorithm_t sign_algo;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  cred = (gnutls_certificate_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
  if (cred == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  /* find the appropriate certificate */
  if ((ret =
       _gnutls_get_selected_cert (session, &apr_cert_list,
                                  &apr_cert_list_length, &apr_pkey)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
                                    sizeof (cert_auth_info_st), 0)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  if (!_gnutls_session_is_ecc (session))
    {
      dh_params =
        _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
      mpis = _gnutls_dh_params_to_mpi (dh_params);
      if (mpis == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
        }

      p = mpis[0];
      g = mpis[1];

      _gnutls_dh_set_group (session, g, p);

      ret = _gnutls_dh_common_print_server_kx (session, g, p, dh_params->q_bits, data);
    }
  else
    {
      ret = _gnutls_ecdh_common_print_server_kx (session, data, _gnutls_session_ecc_curve_get(session));
    }

  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }
  data_size = ret;

  /* Generate the signature. */

  ddata.data = data->data;
  ddata.size = data->length;

  if (apr_cert_list_length > 0)
    {
      if ((ret =
           _gnutls_handshake_sign_data (session, &apr_cert_list[0],
                                        apr_pkey, &ddata, &signature,
                                        &sign_algo)) < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }
    }
  else
    {
      gnutls_assert ();
      ret = data_size;         /* do not put a signature - ILLEGAL! */
      goto cleanup;
    }

  if (_gnutls_version_has_selectable_sighash (ver))
    {
      const sign_algorithm_st *aid;
      uint8_t p[2];

      if (sign_algo == GNUTLS_SIGN_UNKNOWN)
        {
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }

      aid = _gnutls_sign_to_tls_aid (sign_algo);
      if (aid == NULL)
        {
          gnutls_assert();
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }
      
      p[0] = aid->hash_algorithm;
      p[1] = aid->sign_algorithm;
      
      ret = _gnutls_buffer_append_data(data, p, 2);
      if (ret < 0)
        {
          gnutls_assert();
          goto cleanup;
        }
    }

  ret = _gnutls_buffer_append_data_prefix(data, 16, signature.data, signature.size);
  if (ret < 0)
    {
      gnutls_assert();
    }

  ret = data->length;

cleanup:
  _gnutls_free_datum (&signature);
  return ret;

}
Пример #28
0
/* This is a receive function for the gnutls handshake 
 * protocol. Makes sure that we have received all data.
 *
 * htype is the next handshake packet expected.
 */
int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
{
	gnutls_datum_t msg;
	mbuffer_st *bufel = NULL, *prev = NULL;
	int ret;
	size_t data_size;
	handshake_buffer_st *recv_buf =
	    session->internals.handshake_recv_buffer;

	bufel =
	    _mbuffer_head_get_first(&session->internals.record_buffer,
				    &msg);
	if (bufel == NULL)
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;

	if (!IS_DTLS(session)) {
		ssize_t append, header_size;

		do {
			if (bufel->type != GNUTLS_HANDSHAKE)
				return
				    gnutls_assert_val
				    (GNUTLS_E_UNEXPECTED_PACKET);

			if (unlikely
			    (session->internals.handshake_recv_buffer_size == 0 &&
			     msg.size < HANDSHAKE_HEADER_SIZE(session) &&
			     session->internals.handshake_header_recv_buffer.byte_length <
			     HANDSHAKE_HEADER_SIZE(session) - msg.size)) {
				bufel = _mbuffer_head_pop_first(&session->internals.record_buffer);
				_mbuffer_enqueue(&session->internals.handshake_header_recv_buffer,
						 bufel);
				break;
			} else if (session->internals.handshake_recv_buffer_size >
				   0 && recv_buf[0].length > recv_buf[0].data.length) {
				/* this is the rest of a previous message */
				append = MIN(msg.size,
					     recv_buf[0].length -
					     recv_buf[0].data.length);

				ret =
				    _gnutls_buffer_append_data(&recv_buf
							       [0].data,
							       msg.data,
							       append);
				if (ret < 0)
					return gnutls_assert_val(ret);

				_mbuffer_head_remove_bytes(&session->
							   internals.
							   record_buffer,
							   append);
			} else {	/* received new message */
				if (unlikely
				    (session->internals.
				     handshake_header_recv_buffer.length > 0)) {
					bufel = _mbuffer_head_pop_first(&session->internals.
									record_buffer);
					_mbuffer_enqueue(&session->internals.
							 handshake_header_recv_buffer,
							 bufel);
					ret = _mbuffer_linearize_align16(&session->internals.
									 handshake_header_recv_buffer,
									 get_total_headers(session));
					if (ret < 0)
						return gnutls_assert_val(ret);
					bufel = _mbuffer_head_pop_first(&session->internals.
									handshake_header_recv_buffer);
					_mbuffer_head_push_first(&session->internals.
								 record_buffer,
								 bufel);
				}

				ret =
				    parse_handshake_header(session, bufel,
							   &recv_buf[0]);
				if (ret < 0)
					return gnutls_assert_val(ret);

				header_size = ret;
				session->internals.
				    handshake_recv_buffer_size = 1;

				_mbuffer_set_uhead_size(bufel,
							header_size);

				data_size =
				    MIN(recv_buf[0].length,
					_mbuffer_get_udata_size(bufel));
				ret =
				    _gnutls_buffer_append_data(&recv_buf
							       [0].data,
							       _mbuffer_get_udata_ptr
							       (bufel),
							       data_size);
				if (ret < 0)
					return gnutls_assert_val(ret);
				_mbuffer_set_uhead_size(bufel, 0);
				_mbuffer_head_remove_bytes(&session->
							   internals.
							   record_buffer,
							   data_size +
							   header_size);
			}

			/* if packet is complete then return it
			 */
			if (recv_buf[0].length == recv_buf[0].data.length) {
				return 0;
			}
			bufel =
			    _mbuffer_head_get_first(&session->internals.
						    record_buffer, &msg);
		}
		while (bufel != NULL);

		/* if we are here it means that the received packets were not
		 * enough to complete the handshake packet.
		 */
		return gnutls_assert_val(GNUTLS_E_AGAIN);
	} else {		/* DTLS */

		handshake_buffer_st tmp;

		do {
			/* we now 
			 * 0. parse headers
			 * 1. insert to handshake_recv_buffer
			 * 2. sort handshake_recv_buffer on sequence numbers
			 * 3. return first packet if completed or GNUTLS_E_AGAIN.
			 */
			do {
				if (bufel->type != GNUTLS_HANDSHAKE) {
					gnutls_assert();
					goto next;	/* ignore packet */
				}

				_gnutls_handshake_buffer_init(&tmp);

				ret =
				    parse_handshake_header(session, bufel,
							   &tmp);
				if (ret < 0) {
					gnutls_assert();
					_gnutls_audit_log(session,
							  "Invalid handshake packet headers. Discarding.\n");
					break;
				}

				_mbuffer_consume(&session->internals.
						 record_buffer, bufel,
						 ret);

				data_size =
				    MIN(tmp.length,
					tmp.end_offset - tmp.start_offset +
					1);

				ret =
				    _gnutls_buffer_append_data(&tmp.data,
							       _mbuffer_get_udata_ptr
							       (bufel),
							       data_size);
				if (ret < 0)
					return gnutls_assert_val(ret);

				_mbuffer_consume(&session->internals.
						 record_buffer, bufel,
						 data_size);

				ret =
				    merge_handshake_packet(session, &tmp);
				if (ret < 0)
					return gnutls_assert_val(ret);

			}
			while (_mbuffer_get_udata_size(bufel) > 0);

			prev = bufel;
			bufel =
			    _mbuffer_dequeue(&session->internals.
					     record_buffer, bufel);

			_mbuffer_xfree(&prev);
			continue;

		      next:
			bufel = _mbuffer_head_get_next(bufel, NULL);
		}
		while (bufel != NULL);

		/* sort in descending order */
		if (session->internals.handshake_recv_buffer_size > 1)
			qsort(recv_buf,
			      session->internals.
			      handshake_recv_buffer_size,
			      sizeof(recv_buf[0]), handshake_compare);

		while (session->internals.handshake_recv_buffer_size > 0 &&
		       recv_buf[LAST_ELEMENT].sequence <
		       session->internals.dtls.hsk_read_seq) {
			_gnutls_audit_log(session,
					  "Discarded replayed handshake packet with sequence %d\n",
					  recv_buf[LAST_ELEMENT].sequence);
			_gnutls_handshake_buffer_clear(&recv_buf
						       [LAST_ELEMENT]);
			session->internals.handshake_recv_buffer_size--;
		}

		return 0;
	}
}
Пример #29
0
static int
_gnutls_sr_send_params (gnutls_session_t session, gnutls_buffer_st* extdata)
{
  /* The format of this extension is a one-byte length of verify data followed
   * by the verify data itself. Note that the length byte does not include
   * itself; IOW, empty verify data is represented as a length of 0. That means
   * the minimum extension is one byte: 0x00.
   */
  sr_ext_st *priv;
  int ret, set = 0, len;
  extension_priv_data_t epriv;
  size_t init_length = extdata->length;

  if (session->internals.priorities.sr == SR_DISABLED)
    {
      gnutls_assert ();
      return 0;
    }

  ret = _gnutls_ext_get_session_data (session,
                                      GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
                                      &epriv);
  if (ret < 0)
    {
      set = 1;
    }

  if (set != 0)
    {
      priv = gnutls_calloc (1, sizeof (*priv));
      if (priv == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_MEMORY_ERROR;
        }
      epriv.ptr = priv;

      _gnutls_ext_set_session_data (session,
                                    GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
                                    epriv);
    }
  else
    priv = epriv.ptr;

  /* Always offer the extension if we're a client */
  if (priv->connection_using_safe_renegotiation ||
      session->security_parameters.entity == GNUTLS_CLIENT)
    {
      len = priv->client_verify_data_len;
      if (session->security_parameters.entity == GNUTLS_SERVER)
        len += priv->server_verify_data_len;
      
      ret = _gnutls_buffer_append_prefix(extdata, 8, len);
      if (ret < 0)
        return gnutls_assert_val(ret);

      ret = _gnutls_buffer_append_data(extdata, priv->client_verify_data,
        priv->client_verify_data_len);
      if (ret < 0)
        return gnutls_assert_val(ret);

      if (session->security_parameters.entity == GNUTLS_SERVER)
        {
          ret = _gnutls_buffer_append_data(extdata, priv->server_verify_data,
            priv->server_verify_data_len);
          if (ret < 0)
            return gnutls_assert_val(ret);
        }
    }
  else
    return 0;

  return extdata->length - init_length;
}