Example #1
0
/**
 * gnutls_srtp_get_selected_profile:
 * @session: is a #gnutls_session_t type.
 * @profile: will hold the profile
 *
 * This function allows you to get the negotiated SRTP profile.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 *
 * Since 3.1.4
 **/
int
gnutls_srtp_get_selected_profile(gnutls_session_t session,
				 gnutls_srtp_profile_t * profile)
{
	srtp_ext_st *priv;
	int ret;
	extension_priv_data_t epriv;

	ret =
	    _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP,
					 &epriv);
	if (ret < 0) {
		gnutls_assert();
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	priv = epriv;

	if (priv->selected_profile == 0) {
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	*profile = priv->selected_profile;

	return 0;
}
Example #2
0
/**
 * gnutls_srtp_set_mki:
 * @session: is a #gnutls_session_t type.
 * @mki: holds the MKI
 *
 * This function sets the Master Key Identifier, to be
 * used by this session (if any).
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 *
 * Since 3.1.4
 **/
int
gnutls_srtp_set_mki(gnutls_session_t session, const gnutls_datum_t * mki)
{
	int ret;
	srtp_ext_st *priv;
	extension_priv_data_t epriv;

	ret =
	    _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP,
					 &epriv);
	if (ret < 0) {
		priv = gnutls_calloc(1, sizeof(*priv));
		if (priv == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}
		epriv = priv;
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_SRTP, epriv);
	} else
		priv = epriv;

	if (mki->size > 0 && mki->size <= sizeof(priv->mki)) {
		priv->mki_size = mki->size;
		memcpy(priv->mki, mki->data, mki->size);
	} else
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	return 0;
}
Example #3
0
/**
 * gnutls_srtp_get_mki:
 * @session: is a #gnutls_session_t type.
 * @mki: will hold the MKI
 *
 * This function exports the negotiated Master Key Identifier,
 * received by the peer if any. The returned value in @mki should be 
 * treated as constant and valid only during the session's lifetime.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 *
 * Since 3.1.4
 **/
int gnutls_srtp_get_mki(gnutls_session_t session, gnutls_datum_t * mki)
{
	srtp_ext_st *priv;
	int ret;
	extension_priv_data_t epriv;

	ret =
	    _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP,
					 &epriv);
	if (ret < 0)
		return
		    gnutls_assert_val
		    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);

	priv = epriv;

	if (priv->mki_received == 0)
		return
		    gnutls_assert_val
		    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);

	mki->data = priv->mki;
	mki->size = priv->mki_size;

	return 0;
}
Example #4
0
/**
 * gnutls_ocsp_status_request_get:
 * @session: is a #gnutls_session_t structure.
 * @response: a #gnutls_datum_t with DER encoded OCSP response
 *
 * This function returns the OCSP status response received
 * from the TLS server. The @response should be treated as
 * constant. If no OCSP response is available then
 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 *
 * Since: 3.1.3
 **/
int
gnutls_ocsp_status_request_get(gnutls_session_t session,
			       gnutls_datum_t * response)
{
	status_request_ext_st *priv;
	extension_priv_data_t epriv;
	int ret;

	if (session->security_parameters.entity == GNUTLS_SERVER)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	ret = _gnutls_ext_get_session_data(session,
					   GNUTLS_EXTENSION_STATUS_REQUEST,
					   &epriv);
	if (ret < 0)
		return gnutls_assert_val(ret);

	priv = epriv.ptr;

	if (priv == NULL || priv->response.data == NULL)
		return
		    gnutls_assert_val
		    (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);

	response->data = priv->response.data;
	response->size = priv->response.size;

	return 0;
}
Example #5
0
static int
_gnutls_status_request_send_params(gnutls_session_t session,
				   gnutls_buffer_st * extdata)
{
	extension_priv_data_t epriv;
	status_request_ext_st *priv;
	int ret;

	ret = _gnutls_ext_get_session_data(session,
					   GNUTLS_EXTENSION_STATUS_REQUEST,
					   &epriv);

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		if (ret < 0 || epriv.ptr == NULL)	/* it is ok not to have it */
			return 0;
		priv = epriv.ptr;

		return client_send(session, extdata, priv);
	} else {
		epriv.ptr = priv = gnutls_calloc(1, sizeof(*priv));
		if (priv == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_STATUS_REQUEST,
					     epriv);

		return server_send(session, extdata, priv);
	}
}
Example #6
0
/**
 * gnutls_srtp_set_profile:
 * @session: is a #gnutls_session_t type.
 * @profile: is the profile id to add.
 *
 * This function is to be used by both clients and servers, to declare
 * what SRTP profiles they support, to negotiate with the peer.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 *
 * Since 3.1.4
 **/
int
gnutls_srtp_set_profile(gnutls_session_t session,
			gnutls_srtp_profile_t profile)
{
	int ret;
	srtp_ext_st *priv;
	extension_priv_data_t epriv;

	ret =
	    _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP,
					 &epriv);
	if (ret < 0) {
		priv = gnutls_calloc(1, sizeof(*priv));
		if (priv == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}
		epriv = priv;
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_SRTP, epriv);
	} else
		priv = epriv;

	if (priv->profiles_size < MAX_SRTP_PROFILES)
		priv->profiles_size++;
	priv->profiles[priv->profiles_size - 1] = profile;

	return 0;
}
Example #7
0
/**
 * gnutls_sign_algorithm_get_requested:
 * @session: is a #gnutls_session_t type.
 * @indx: is an index of the signature algorithm to return
 * @algo: the returned certificate type will be stored there
 *
 * Returns the signature algorithm specified by index that was
 * requested by the peer. If the specified index has no data available
 * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.  If
 * the negotiated TLS version does not support signature algorithms
 * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
 * for the first index.  The first index is 0.
 *
 * This function is useful in the certificate callback functions
 * to assist in selecting the correct certificate.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 *
 * Since: 2.10.0
 **/
int
gnutls_sign_algorithm_get_requested(gnutls_session_t session,
				    size_t indx,
				    gnutls_sign_algorithm_t * algo)
{
	const version_entry_st *ver = get_version(session);
	sig_ext_st *priv;
	extension_priv_data_t epriv;
	int ret;

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

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
					 &epriv);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}
	priv = epriv;

	if (!_gnutls_version_has_selectable_sighash(ver)
	    || priv->sign_algorithms_size == 0) {
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	if (indx < priv->sign_algorithms_size) {
		*algo = priv->sign_algorithms[indx];
		return 0;
	} else
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
Example #8
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_ext_etm_send_params(gnutls_session_t session,
			       gnutls_buffer_st * extdata)
{
	if (session->internals.priorities.no_etm != 0)
		return 0;

	/* this function sends the client extension data */
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		if (session->internals.priorities.have_cbc != 0)
			return GNUTLS_E_INT_RET_0;
		else
			return 0;
	} else { /* server side */
		const cipher_entry_st *c;
		int ret;
		extension_priv_data_t epriv;

		c = _gnutls_cipher_suite_get_cipher_algo(session->security_parameters.cipher_suite);
		if (c == NULL || (c->type == CIPHER_AEAD || c->type == CIPHER_STREAM))
			return 0;

		ret = _gnutls_ext_get_session_data(session,
						   GNUTLS_EXTENSION_ETM,
						   &epriv);
		if (ret < 0 || ((intptr_t)epriv) == 0)
			return 0;

		session->security_parameters.etm = 1;
		return GNUTLS_E_INT_RET_0;
	}

	return 0;
}
Example #9
0
/**
 * gnutls_sign_algorithm_get_requested:
 * @session: is a #gnutls_session_t structure.
 * @indx: is an index of the signature algorithm to return
 * @algo: the returned certificate type will be stored there
 *
 * Returns the signature algorithm specified by index that was
 * requested by the peer. If the specified index has no data available
 * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.  If
 * the negotiated TLS version does not support signature algorithms
 * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
 * for the first index.  The first index is 0.
 *
 * This function is useful in the certificate callback functions
 * to assist in selecting the correct certificate.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 *
 * Since: 2.10.0
 **/
int
gnutls_sign_algorithm_get_requested (gnutls_session_t session,
                                     size_t indx,
                                     gnutls_sign_algorithm_t * algo)
{
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
  sig_ext_st *priv;
  extension_priv_data_t epriv;
  int ret;

  ret =
    _gnutls_ext_get_session_data (session,
                                  GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
                                  &epriv);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }
  priv = epriv.ptr;

  if (!_gnutls_version_has_selectable_sighash (ver)
      || priv->sign_algorithms_size == 0)
    {
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    }

  if (indx < priv->sign_algorithms_size)
    {
      *algo = priv->sign_algorithms[indx];
      return 0;
    }
  else
    return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
Example #10
0
static int
_gnutls_heartbeat_recv_params(gnutls_session_t session,
			      const uint8_t * data, size_t _data_size)
{
	unsigned policy;
	extension_priv_data_t epriv;

	if (_gnutls_ext_get_session_data
	    (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0) {
		if (session->security_parameters.entity == GNUTLS_CLIENT)
			return
			    gnutls_assert_val
			    (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
		return 0;	/* Not enabled */
	}

	if (_data_size == 0)
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;

	policy = epriv.num;

	if (data[0] == 1)
		policy |= LOCAL_ALLOWED_TO_SEND;
	else if (data[0] == 2)
		policy |= LOCAL_NOT_ALLOWED_TO_SEND;
	else
		return
		    gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);

	epriv.num = policy;
	_gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_HEARTBEAT,
				     epriv);

	return 0;
}
Example #11
0
/**
 * gnutls_alpn_get_selected_protocol:
 * @session: is a #gnutls_session_t structure.
 * @protocol: will hold the protocol name
 *
 * This function allows you to get the negotiated protocol name. The
 * returned protocol should be treated as opaque, constant value and
 * only valid during the session life.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 *
 * Since 3.1.11
 **/
int
gnutls_alpn_get_selected_protocol (gnutls_session_t session,
                                   gnutls_datum_t * protocol)
{
  alpn_ext_st *priv;
  int ret;
  extension_priv_data_t epriv;

  ret =
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_ALPN,
                                  &epriv);
  if (ret < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    }

  priv = epriv.ptr;

  if (priv->selected_protocol_size == 0)
    return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);

  protocol->data = priv->selected_protocol;
  protocol->size = priv->selected_protocol_size;

  return 0;
}
Example #12
0
static int
_gnutls_max_record_recv_params(gnutls_session_t session,
			       const uint8_t * data, size_t _data_size)
{
	ssize_t new_size;
	ssize_t data_size = _data_size;
	extension_priv_data_t epriv;
	int ret;

	if (session->security_parameters.entity == GNUTLS_SERVER) {
		if (data_size > 0) {
			DECR_LEN(data_size, 1);

			new_size = _gnutls_mre_num2record(data[0]);

			if (new_size < 0) {
				gnutls_assert();
				return new_size;
			}

			session->security_parameters.max_record_send_size =
			    new_size;
			session->security_parameters.max_record_recv_size =
			    new_size;
		}
	} else {		/* CLIENT SIDE - we must check if the sent record size is the right one 
				 */
		if (data_size > 0) {
			ret = _gnutls_ext_get_session_data(session,
							   GNUTLS_EXTENSION_MAX_RECORD_SIZE,
							   &epriv);
			if (ret < 0) {
				gnutls_assert();
				return GNUTLS_E_INTERNAL_ERROR;
			}

			if (data_size != 1) {
				gnutls_assert();
				return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
			}

			new_size = _gnutls_mre_num2record(data[0]);

			if (new_size < 0
			    || new_size != (intptr_t) epriv) {
				gnutls_assert();
				return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
			} else {
				session->security_parameters.
				    max_record_recv_size = (intptr_t)epriv;
			}

		}


	}

	return 0;
}
Example #13
0
/**
 * gnutls_server_name_get:
 * @session: is a #gnutls_session_t type.
 * @data: will hold the data
 * @data_length: will hold the data length. Must hold the maximum size of data.
 * @type: will hold the server name indicator type
 * @indx: is the index of the server_name
 *
 * This function will allow you to get the name indication (if any), a
 * client has sent.  The name indication may be any of the enumeration
 * gnutls_server_name_type_t.
 *
 * If @type is GNUTLS_NAME_DNS, then this function is to be used by
 * servers that support virtual hosting, and the data will be a null
 * terminated IDNA ACE string (prior to GnuTLS 3.4.0 it was a UTF-8 string).
 *
 * If @data has not enough size to hold the server name
 * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
 * hold the required size.
 *
 * @index is used to retrieve more than one server names (if sent by
 * the client).  The first server name has an index of 0, the second 1
 * and so on.  If no name with the given index exists
 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, on UTF-8
 *  decoding error %GNUTLS_E_IDNA_ERROR is returned, otherwise a negative
 *  error code is returned.
 **/
int
gnutls_server_name_get(gnutls_session_t session, void *data,
		       size_t * data_length,
		       unsigned int *type, unsigned int indx)
{
	char *_data = data;
	server_name_ext_st *priv;
	int ret;
	gnutls_datum_t idn_name = {NULL,0};
	extension_priv_data_t epriv;

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SERVER_NAME,
					 &epriv);
	if (ret < 0) {
		gnutls_assert();
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	priv = epriv;

	if (indx + 1 > priv->server_names_size) {
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	*type = priv->server_names[indx].type;

	ret = gnutls_idna_map((char*)priv->server_names[indx].name, priv->server_names[indx].name_length, &idn_name, 0);
	if (ret < 0) {
		 _gnutls_debug_log("unable to convert name %s to IDNA2003 format\n", (char*)priv->server_names[indx].name);
		 return GNUTLS_E_IDNA_ERROR;
	}

	if (*data_length >	/* greater since we need one extra byte for the null */
	    idn_name.size) {
		*data_length = idn_name.size;
		memcpy(data, idn_name.data, *data_length);

		if (*type == GNUTLS_NAME_DNS)	/* null terminate */
			_data[(*data_length)] = 0;

	} else {
		*data_length = idn_name.size + 1;
		ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
		goto cleanup;
	}

	ret = 0;
 cleanup:
	gnutls_free(idn_name.data);
	return ret;
}
Example #14
0
/**
 * gnutls_server_name_set:
 * @session: is a #gnutls_session_t structure.
 * @type: specifies the indicator type
 * @name: is a string that contains the server name.
 * @name_length: holds the length of name
 *
 * This function is to be used by clients that want to inform (via a
 * TLS extension mechanism) the server of the name they connected to.
 * This should be used by clients that connect to servers that do
 * virtual hosting.
 *
 * The value of @name depends on the @type type.  In case of
 * %GNUTLS_NAME_DNS, an ASCII (0)-terminated domain name string,
 * without the trailing dot, is expected.  IPv4 or IPv6 addresses are
 * not permitted.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_server_name_set (gnutls_session_t session,
                        gnutls_server_name_type_t type,
                        const void *name, size_t name_length)
{
  int server_names, ret;
  server_name_ext_st *priv;
  extension_priv_data_t epriv;
  int set = 0;

  if (session->security_parameters.entity == GNUTLS_SERVER)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (name_length > MAX_SERVER_NAME_SIZE)
    return GNUTLS_E_SHORT_MEMORY_BUFFER;

  ret =
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
                                  &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;
    }
  else
    priv = epriv.ptr;

  server_names = priv->server_names_size + 1;

  if (server_names > MAX_SERVER_NAME_EXTENSIONS)
    server_names = MAX_SERVER_NAME_EXTENSIONS;

  priv->server_names[server_names - 1].type = type;
  memcpy (priv->server_names[server_names - 1].name, name, name_length);
  priv->server_names[server_names - 1].name_length = name_length;

  priv->server_names_size++;

  if (set != 0)
    _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
                                  epriv);

  return 0;
}
Example #15
0
/* This does not do any conversion not perform any check */
int
_gnutls_server_name_set_raw(gnutls_session_t session,
		       gnutls_server_name_type_t type,
		       const void *name, size_t name_length)
{
	int server_names, ret;
	server_name_ext_st *priv;
	extension_priv_data_t epriv;
	int set = 0;

	if (name_length > MAX_SERVER_NAME_SIZE) {
		return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SERVER_NAME,
					 &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 = priv;
	} else
		priv = epriv;

	server_names = priv->server_names_size + 1;

	if (server_names > MAX_SERVER_NAME_EXTENSIONS)
		server_names = MAX_SERVER_NAME_EXTENSIONS;

	priv->server_names[server_names - 1].type = type;

	if (name_length > 0) {
		memcpy(priv->server_names[server_names - 1].name, name,
		       name_length);
		priv->server_names[server_names - 1].name[name_length] = 0;
	}
	priv->server_names[server_names - 1].name_length = name_length;

	priv->server_names_size = server_names;

	if (set != 0)
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_SERVER_NAME,
					     epriv);

	return 0;
}
Example #16
0
static int
_gnutls_inner_application_recv_params (gnutls_session_t session,
                                       const opaque * data, size_t data_size)
{
  extension_priv_data_t epriv;
  ia_ext_st *priv;
  int ret;

  if (data_size != 1)
    {
      gnutls_assert ();
      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
    }

  ret =
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_INNER_APPLICATION,
                                  &epriv);
  if (ret < 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_INNER_APPLICATION,
                                    epriv);
    }
  else
    priv = epriv.ptr;

  priv->flags |= IA_PEER_ENABLE;
  priv->flags &= ~IA_PEER_ALLOW_SKIP;

  switch ((unsigned char) *data)
    {
    case NO:                   /* Peer's ia_on_resume == no */
      priv->flags |= IA_PEER_ALLOW_SKIP;
      break;

    case YES:
      break;

    default:
      gnutls_assert ();
    }


  return 0;
}
Example #17
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;
}
Example #18
0
/**
 * gnutls_server_name_get:
 * @session: is a #gnutls_session_t structure.
 * @data: will hold the data
 * @data_length: will hold the data length. Must hold the maximum size of data.
 * @type: will hold the server name indicator type
 * @indx: is the index of the server_name
 *
 * This function will allow you to get the name indication (if any), a
 * client has sent.  The name indication may be any of the enumeration
 * gnutls_server_name_type_t.
 *
 * If @type is GNUTLS_NAME_DNS, then this function is to be used by
 * servers that support virtual hosting, and the data will be a null
 * terminated UTF-8 string.
 *
 * If @data has not enough size to hold the server name
 * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
 * hold the required size.
 *
 * @index is used to retrieve more than one server names (if sent by
 * the client).  The first server name has an index of 0, the second 1
 * and so on.  If no name with the given index exists
 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_server_name_get (gnutls_session_t session, void *data,
                        size_t * data_length,
                        unsigned int *type, unsigned int indx)
{
  char *_data = data;
  server_name_ext_st *priv;
  int ret;
  extension_priv_data_t epriv;

  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  ret =
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
                                  &epriv);
  if (ret < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    }

  priv = epriv.ptr;

  if (indx + 1 > priv->server_names_size)
    {
      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    }

  *type = priv->server_names[indx].type;

  if (*data_length >            /* greater since we need one extra byte for the null */
      priv->server_names[indx].name_length)
    {
      *data_length = priv->server_names[indx].name_length;
      memcpy (data, priv->server_names[indx].name, *data_length);

      if (*type == GNUTLS_NAME_DNS)     /* null terminate */
        _data[(*data_length)] = 0;

    }
  else
    {
      *data_length = priv->server_names[indx].name_length;
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  return 0;
}
Example #19
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;
}
Example #20
0
/* Returns a requested by the peer signature algorithm that
 * matches the given certificate's public key algorithm. 
 */
gnutls_sign_algorithm_t
_gnutls_session_get_sign_algo(gnutls_session_t session,
			      gnutls_pcert_st * cert)
{
	unsigned i;
	int ret;
	const version_entry_st *ver = get_version(session);
	sig_ext_st *priv;
	extension_priv_data_t epriv;
	unsigned int cert_algo;

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

	cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
					 &epriv);
	priv = epriv;

	if (ret < 0 || !_gnutls_version_has_selectable_sighash(ver)
	    || priv->sign_algorithms_size == 0)
		/* none set, allow SHA-1 only */
	{
		ret = gnutls_pk_to_sign(cert_algo, GNUTLS_DIG_SHA1);
		if (_gnutls_session_sign_algo_enabled(session, ret) < 0)
			goto fail;
		return ret;
	}

	for (i = 0; i < priv->sign_algorithms_size; i++) {
		if (gnutls_sign_get_pk_algorithm(priv->sign_algorithms[i])
		    == cert_algo) {
			if (_gnutls_pubkey_compatible_with_sig
			    (session, cert->pubkey, ver,
			     priv->sign_algorithms[i]) < 0)
				continue;

			if (_gnutls_session_sign_algo_enabled
			    (session, priv->sign_algorithms[i]) < 0)
				continue;

			return priv->sign_algorithms[i];
		}
	}

 fail:
	return GNUTLS_SIGN_UNKNOWN;
}
Example #21
0
/**
 * gnutls_srtp_set_profile_direct:
 * @session: is a #gnutls_session_t type.
 * @profiles: is a string that contains the supported SRTP profiles,
 *   separated by colons.
 * @err_pos: In case of an error this will have the position in the string the error occurred, may be NULL.
 *
 * This function is to be used by both clients and servers, to declare
 * what SRTP profiles they support, to negotiate with the peer.
 *
 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
 * %GNUTLS_E_SUCCESS on success, or an error code.
 *
 * Since 3.1.4
 **/
int
gnutls_srtp_set_profile_direct(gnutls_session_t session,
			       const char *profiles, const char **err_pos)
{
	int ret;
	srtp_ext_st *priv;
	extension_priv_data_t epriv;
	int set = 0;
	const char *col;
	gnutls_srtp_profile_t id;

	ret =
	    _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRTP,
					 &epriv);
	if (ret < 0) {
		set = 1;
		priv = gnutls_calloc(1, sizeof(*priv));
		if (priv == NULL) {
			if (err_pos != NULL)
				*err_pos = profiles;
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}
		epriv = priv;
	} else
		priv = epriv;

	do {
		col = strchr(profiles, ':');
		id = find_profile(profiles, col);
		if (id == 0) {
			if (set != 0)
				gnutls_free(priv);
			if (err_pos != NULL)
				*err_pos = profiles;
			return GNUTLS_E_INVALID_REQUEST;
		}

		if (priv->profiles_size < MAX_SRTP_PROFILES) {
			priv->profiles_size++;
		}
		priv->profiles[priv->profiles_size - 1] = id;
		profiles = col + 1;
	} while (col != NULL);

	if (set != 0)
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_SRTP, epriv);

	return 0;
}
Example #22
0
/**
  * gnutls_heartbeat_allowed:
  * @session: is a #gnutls_session_t structure.
  * @type: one of %GNUTLS_HB_LOCAL_ALLOWED_TO_SEND and %GNUTLS_HB_PEER_ALLOWED_TO_SEND
  *
  * This function will check whether heartbeats are allowed
  * to be sent or received in this session. 
  *
  * Returns: Non zero if heartbeats are allowed.
  *
  * Since: 3.1.2
  **/
int gnutls_heartbeat_allowed(gnutls_session_t session, unsigned int type)
{
	extension_priv_data_t epriv;

	if (_gnutls_ext_get_session_data
	    (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0)
		return 0;	/* Not enabled */

	if (type == GNUTLS_HB_LOCAL_ALLOWED_TO_SEND) {
		if (epriv.num & LOCAL_ALLOWED_TO_SEND)
			return 1;
	} else if (epriv.num & GNUTLS_HB_PEER_ALLOWED_TO_SEND)
		return 1;

	return 0;
}
Example #23
0
static int new_record_padding_before_epoch_change(gnutls_session_t session)
{
	extension_priv_data_t epriv;
	int ret;

	ret = _gnutls_ext_get_session_data(session,
					   GNUTLS_EXTENSION_NEW_RECORD_PADDING,
					   &epriv);
	if (ret < 0)
		return 0;	/* fine */

	if (epriv.num != 0)
		session->security_parameters.new_record_padding = 1;

	return 0;
}
Example #24
0
/* Check if the given signature algorithm is accepted by
 * the peer. Returns 0 on success or a negative value
 * on error.
 */
int
_gnutls_session_sign_algo_requested (gnutls_session_t session,
                                     gnutls_sign_algorithm_t sig)
{
    unsigned i;
    int ret, hash;
    gnutls_protocol_t ver = gnutls_protocol_get_version (session);
    sig_ext_st *priv;
    extension_priv_data_t epriv;

    if (!_gnutls_version_has_selectable_sighash (ver))
    {
        return 0;
    }

    ret =
        _gnutls_ext_get_session_data (session,
                                      GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
                                      &epriv);
    if (ret < 0)
    {
        gnutls_assert ();
        /* extension not received allow SHA1 and SHA256 */
        hash = _gnutls_sign_get_hash_algorithm (sig);
        if (hash == GNUTLS_DIG_SHA1 || hash == GNUTLS_DIG_SHA256)
            return 0;
        else
            return ret;
    }
    priv = epriv.ptr;

    if (priv->sign_algorithms_size == 0)
        /* none set, allow all */
    {
        return 0;
    }

    for (i = 0; i < priv->sign_algorithms_size; i++)
    {
        if (priv->sign_algorithms[i] == sig)
        {
            return 0;             /* ok */
        }
    }

    return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
}
Example #25
0
int
_gnutls_ext_sr_finished (gnutls_session_t session, void *vdata,
                         size_t vdata_size, int dir)
{
  int ret;
  sr_ext_st *priv;
  extension_priv_data_t epriv;

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

  ret = _gnutls_ext_get_session_data (session,
                                      GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
                                      &epriv);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }
  priv = epriv.ptr;

  /* Save data for safe renegotiation. 
   */
  if (vdata_size > MAX_VERIFY_DATA_SIZE)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  if ((session->security_parameters.entity == GNUTLS_CLIENT && dir == 0) ||
      (session->security_parameters.entity == GNUTLS_SERVER && dir == 1))
    {
      priv->client_verify_data_len = vdata_size;
      memcpy (priv->client_verify_data, vdata, vdata_size);
    }
  else
    {
      priv->server_verify_data_len = vdata_size;
      memcpy (priv->server_verify_data, vdata, vdata_size);
    }

  return 0;
}
Example #26
0
/**
 * gnutls_alpn_set_protocols:
 * @session: is a #gnutls_session_t structure.
 * @protocols: is the protocol names to add.
 * @protocols_size: the number of protocols to add.
 * @flags: zero or %GNUTLS_ALPN_*
 *
 * This function is to be used by both clients and servers, to declare
 * the supported ALPN protocols, which are used during peer negotiation.
 *
 * If %GNUTLS_ALPN_MAND is specified the connection will be aborted
 * if no matching ALPN protocol is found.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 *
 * Since 3.1.11
 **/
int
gnutls_alpn_set_protocols (gnutls_session_t session,
                           const gnutls_datum_t * protocols, unsigned protocols_size,
                           unsigned int flags)
{
  int ret;
  alpn_ext_st *priv;
  extension_priv_data_t epriv;
  unsigned i;

  ret =
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_ALPN,
                                  &epriv);
  if (ret < 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_ALPN,
                                    epriv);
    }
  else
    priv = epriv.ptr;
    
  if (protocols_size > MAX_ALPN_PROTOCOLS)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

  for (i=0;i<protocols_size;i++)
    {
      if (protocols[i].size >= MAX_ALPN_PROTOCOL_NAME)
        return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
        
      memcpy(priv->protocols[i], protocols[i].data, protocols[i].size);
      priv->protocol_size[i] = protocols[i].size;
      priv->size++;
    }
  priv->flags = flags;

  return 0;
}
Example #27
0
/**
 * gnutls_safe_renegotiation_status:
 * @session: is a #gnutls_session_t structure.
 *
 * Can be used to check whether safe renegotiation is being used
 * in the current session.
 *
 * Returns: 0 when safe renegotiation is not used and non (0) when
 *   safe renegotiation is used.
 *
 * Since: 2.10.0
 **/
int
gnutls_safe_renegotiation_status (gnutls_session_t session)
{
  int ret;
  sr_ext_st *priv;
  extension_priv_data_t epriv;

  ret = _gnutls_ext_get_session_data (session,
                                      GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
                                      &epriv);
  if (ret < 0)
    {
      gnutls_assert ();
      return 0;
    }
  priv = epriv.ptr;

  return priv->connection_using_safe_renegotiation;
}
int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st * packed)
{
	unsigned int i;
	int ret;
	extension_priv_data_t data;
	int cur_size;
	int size_offset;
	int total_exts_pos;
	int exts = 0;

	total_exts_pos = packed->length;
	BUFFER_APPEND_NUM(packed, 0);

	for (i = 0; i < extfunc_size; i++) {
		ret =
		    _gnutls_ext_get_session_data(session, extfunc[i].type,
						 &data);
		if (ret >= 0 && extfunc[i].pack_func != NULL) {
			BUFFER_APPEND_NUM(packed, extfunc[i].type);

			size_offset = packed->length;
			BUFFER_APPEND_NUM(packed, 0);

			cur_size = packed->length;

			ret = extfunc[i].pack_func(data, packed);
			if (ret < 0) {
				gnutls_assert();
				return ret;
			}

			exts++;
			/* write the actual size */
			_gnutls_write_uint32(packed->length - cur_size,
					     packed->data + size_offset);
		}
	}

	_gnutls_write_uint32(exts, packed->data + total_exts_pos);

	return 0;
}
Example #29
0
/* if a server received the special ciphersuite.
 */
int
_gnutls_ext_sr_recv_cs (gnutls_session_t session)
{
  int ret, set = 0;
  sr_ext_st *priv;
  extension_priv_data_t epriv;

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

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

  priv->safe_renegotiation_received = 1;
  priv->connection_using_safe_renegotiation = 1;

  if (set != 0)
    _gnutls_ext_set_session_data (session,
                                  GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);

  return 0;
}
Example #30
0
static int
_gnutls_status_request_recv_params(gnutls_session_t session,
				   const uint8_t * data, size_t size)
{
	extension_priv_data_t epriv;
	status_request_ext_st *priv;
	int ret;

	ret = _gnutls_ext_get_session_data(session,
					   GNUTLS_EXTENSION_STATUS_REQUEST,
					   &epriv);
	if (ret < 0 || epriv.ptr == NULL)	/* it is ok not to have it */
		return 0;

	priv = epriv.ptr;

	if (session->security_parameters.entity == GNUTLS_CLIENT)
		return client_recv(session, priv, data, size);
	return server_recv(session, priv, data, size);
}