Esempio n. 1
0
/**
 * gnutls_alpn_set_protocols:
 * @session: is a #gnutls_session_t type.
 * @protocols: is the protocol names to add.
 * @protocols_size: the number of protocols to add.
 * @flags: zero or a sequence of %gnutls_alpn_flags_t
 *
 * This function is to be used by both clients and servers, to declare
 * the supported ALPN protocols, which are used during negotiation with peer.
 *
 * See %gnutls_alpn_flags_t description for the documentation of available
 * flags.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 *
 * Since 3.2.0
 **/
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 = priv;
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_ALPN, epriv);
	} else
		priv = epriv;

	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;
}
/* Parses the Signature Algorithm structure and stores data into
 * session->security_parameters.extensions.
 */
int
_gnutls_sign_algorithm_parse_data (gnutls_session_t session,
                                   const uint8_t * data, size_t data_size)
{
  unsigned int sig, i;
  sig_ext_st *priv;
  extension_priv_data_t epriv;

  priv = gnutls_calloc (1, sizeof (*priv));
  if (priv == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  for (i = 0; i < data_size; i += 2)
    {
      sign_algorithm_st aid;

      aid.hash_algorithm = data[i];
      aid.sign_algorithm = data[i + 1];

      sig = _gnutls_tls_aid_to_sign (&aid);

       _gnutls_handshake_log ("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session, aid.hash_algorithm, 
         aid.sign_algorithm, gnutls_sign_get_name(sig));

      if (sig != GNUTLS_SIGN_UNKNOWN)
        {
          priv->sign_algorithms[priv->sign_algorithms_size++] = sig;
          if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS)
            break;
        }
    }

  epriv.ptr = priv;
  _gnutls_ext_set_session_data (session,
                                GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv);

  return 0;
}
Esempio n. 3
0
void _gnutls_ext_restore_resumed_session(gnutls_session_t session)
{
	int i;


	/* clear everything except MANDATORY extensions */
	for (i = 0; i < MAX_EXT_TYPES; i++) {
		if (session->internals.extension_int_data[i].set != 0 &&
		    _gnutls_ext_parse_type(session->
					   internals.extension_int_data[i].
					   type) != GNUTLS_EXT_MANDATORY) {
			_gnutls_ext_unset_session_data(session,
						       session->internals.
						       extension_int_data
						       [i].type);
		}
	}

	/* copy resumed to main */
	for (i = 0; i < MAX_EXT_TYPES; i++) {
		if (session->internals.resumed_extension_int_data[i].set !=
		    0
		    && _gnutls_ext_parse_type(session->internals.
					      resumed_extension_int_data
					      [i].type) !=
		    GNUTLS_EXT_MANDATORY) {
			_gnutls_ext_set_session_data(session,
						     session->internals.
						     resumed_extension_int_data
						     [i].type,
						     session->internals.
						     resumed_extension_int_data
						     [i].priv);
			session->internals.resumed_extension_int_data[i].
			    set = 0;
		}
	}

}
Esempio n. 4
0
int
_gnutls_ext_sr_send_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;
    }

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

  return 0;
}
Esempio n. 5
0
/* Parses the Signature Algorithm structure and stores data into
 * session->security_parameters.extensions.
 */
int
_gnutls_sign_algorithm_parse_data (gnutls_session_t session,
                                   const opaque * data, size_t data_size)
{
    int sig, i;
    sig_ext_st *priv;
    extension_priv_data_t epriv;

    priv = gnutls_calloc (1, sizeof (*priv));
    if (priv == NULL)
    {
        gnutls_assert ();
        return GNUTLS_E_MEMORY_ERROR;
    }

    for (i = 0; i < data_size; i += 2)
    {
        sign_algorithm_st aid;

        aid.hash_algorithm = data[i];
        aid.sign_algorithm = data[i + 1];

        sig = _gnutls_tls_aid_to_sign (&aid);
        if (sig != GNUTLS_SIGN_UNKNOWN)
        {
            priv->sign_algorithms[priv->sign_algorithms_size++] = sig;
            if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS)
                break;
        }
    }

    epriv.ptr = priv;
    _gnutls_ext_set_session_data (session,
                                  GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv);

    return 0;
}
Esempio n. 6
0
/**
 * gnutls_record_set_max_size:
 * @session: is a #gnutls_session_t type.
 * @size: is the new size
 *
 * This function sets the maximum record packet size in this
 * connection.  This property can only be set to clients.  The server
 * may choose not to accept the requested size.
 *
 * Acceptable values are 512(=2^9), 1024(=2^10), 2048(=2^11) and
 * 4096(=2^12).  The requested record size does get in effect
 * immediately only while sending data. The receive part will take
 * effect after a successful handshake.
 *
 * This function uses a TLS extension called 'max record size'.  Not
 * all TLS implementations use or even understand this extension.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
ssize_t gnutls_record_set_max_size(gnutls_session_t session, size_t size)
{
	ssize_t new_size;
	extension_priv_data_t epriv;

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

	new_size = _gnutls_mre_record2num(size);

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

	session->security_parameters.max_record_send_size = size;
	epriv = (void *)(intptr_t)size;

	_gnutls_ext_set_session_data(session,
				     GNUTLS_EXTENSION_MAX_RECORD_SIZE,
				     epriv);

	return 0;
}
Esempio n. 7
0
/**
 * gnutls_session_ticket_enable_client:
 * @session: is a #gnutls_session_t type.
 *
 * Request that the client should attempt session resumption using
 * SessionTicket.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
 * error code.
 *
 * Since: 2.10.0
 **/
int gnutls_session_ticket_enable_client(gnutls_session_t session)
{
    session_ticket_ext_st *priv = NULL;
    extension_priv_data_t epriv;

    if (!session) {
        gnutls_assert();
        return GNUTLS_E_INVALID_REQUEST;
    }

    priv = gnutls_calloc(1, sizeof(*priv));
    if (priv == NULL) {
        gnutls_assert();
        return GNUTLS_E_MEMORY_ERROR;
    }
    priv->session_ticket_enable = 1;
    epriv = priv;

    _gnutls_ext_set_session_data(session,
                                 GNUTLS_EXTENSION_SESSION_TICKET,
                                 epriv);

    return 0;
}
Esempio n. 8
0
/*
 * In case of a server: if a NAME_DNS extension type is received then
 * it stores into the session the value of NAME_DNS. The server may
 * use gnutls_ext_get_server_name(), in order to access it.
 *
 * In case of a client: If a proper NAME_DNS extension type is found
 * in the session then it sends the extension to the peer.
 *
 */
static int
_gnutls_server_name_recv_params(gnutls_session_t session,
				const uint8_t * data, size_t _data_size)
{
	int i;
	const unsigned char *p;
	uint16_t len, type;
	ssize_t data_size = _data_size;
	int server_names = 0;
	server_name_ext_st *priv;
	extension_priv_data_t epriv;

	if (session->security_parameters.entity == GNUTLS_SERVER) {
		DECR_LENGTH_RET(data_size, 2, 0);
		len = _gnutls_read_uint16(data);

		if (len != data_size) {
			/* This is unexpected packet length, but
			 * just ignore it, for now.
			 */
			gnutls_assert();
			return 0;
		}

		p = data + 2;

		/* Count all server_names in the packet. */
		while (data_size > 0) {
			DECR_LENGTH_RET(data_size, 1, 0);
			p++;

			DECR_LEN(data_size, 2);
			len = _gnutls_read_uint16(p);
			p += 2;

			if (len > 0) {
				DECR_LENGTH_RET(data_size, len, 0);
				server_names++;
				p += len;
			} else
				_gnutls_handshake_log
				    ("HSK[%p]: Received (0) size server name (under attack?)\n",
				     session);

		}

		/* we cannot accept more server names.
		 */
		if (server_names > MAX_SERVER_NAME_EXTENSIONS) {
			_gnutls_handshake_log
			    ("HSK[%p]: Too many server names received (under attack?)\n",
			     session);
			server_names = MAX_SERVER_NAME_EXTENSIONS;
		}

		if (server_names == 0)
			return 0;	/* no names found */

		priv = gnutls_calloc(1, sizeof(*priv));
		if (priv == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}

		priv->server_names_size = server_names;

		p = data + 2;
		for (i = 0; i < server_names; i++) {
			type = *p;
			p++;

			len = _gnutls_read_uint16(p);
			p += 2;

			switch (type) {
			case 0:	/* NAME_DNS */
				if (len < MAX_SERVER_NAME_SIZE) {
					memcpy(priv->server_names[i].name,
					       p, len);
					priv->server_names[i].name[len] = 0;
					priv->server_names[i].name_length =
					    len;
					priv->server_names[i].type =
					    GNUTLS_NAME_DNS;
					break;
				}
			}

			/* move to next record */
			p += len;
		}

		epriv = priv;
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_SERVER_NAME,
					     epriv);

	}

	return 0;
}
Esempio n. 9
0
/**
 * gnutls_server_name_set:
 * @session: is a #gnutls_session_t type.
 * @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, a UTF-8 null-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;
	char *idn_name = NULL;
	int set = 0, rc;

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

	if (name_length == 0) { /* unset extension */
		_gnutls_ext_unset_session_data(session, GNUTLS_EXTENSION_SERVER_NAME);
		return 0;
	}

#ifdef HAVE_LIBIDN
	rc = idna_to_ascii_8z (name, &idn_name, IDNA_ALLOW_UNASSIGNED);
	if (rc != IDNA_SUCCESS) {
		 _gnutls_debug_log("unable to convert name %s to IDNA format: %s\n", (char*)name, idna_strerror(rc));
		 return GNUTLS_E_IDNA_ERROR;
	}
	name = idn_name;
	name_length = strlen(idn_name);
#endif

	if (name_length > MAX_SERVER_NAME_SIZE) {
		ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
		goto cleanup;
	}

	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;
	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 = server_names;

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

	ret = 0;
 cleanup:
#ifdef HAVE_LIBIDN
	idn_free(idn_name);
#endif
	return ret;
}
Esempio n. 10
0
static int _proxyinfo_recv_params (gnutls_session_t session, const opaque * data,
                          size_t _data_size)
{
//printf("Recv params\n");
  int i;
  const unsigned char *p;
  uint16_t len, type;
  ssize_t data_size = _data_size;
  int server_names = 0;
  ProxyInfo_ext_st *priv;
  extension_priv_data_t epriv;

  if (session->security_parameters.entity == GNUTLS_SERVER)
    {
      DECR_LENGTH_RET (data_size, 2, 0);
      len = _gnutls_read_uint16 (data);

      if (len != data_size)
        {
          /* This is unexpected packet length, but
           * just ignore it, for now.
           */
          gnutls_assert ();
          return 0;
        }

      p = data + 2;

      
      DECR_LEN (data_size, 2);
      unsigned count = _gnutls_read_uint16 (p);
      p+=2;
      printf("Received Proxy_Info for %d intermediate proxies\n",count+1);
      priv = gnutls_calloc (1, sizeof (*priv));
      if (priv == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_MEMORY_ERROR;
        }
      priv->proxy_cnt=count;
      
      for (int proxy_id=0;proxy_id<count+1;proxy_id++){
      DECR_LEN (data_size, 2);
      unsigned cipher_algo = _gnutls_read_uint16 (p);
      p+=2;
      DECR_LEN (data_size, 2);
      unsigned kx_algo = _gnutls_read_uint16 (p);
      p+=2;
      DECR_LEN (data_size, 2);
      unsigned mac_algo = _gnutls_read_uint16 (p);
      p+=2;
      DECR_LEN (data_size, 2);
      unsigned ip_addr = _gnutls_read_uint16 (p);
      p+=2;
      DECR_LEN (data_size, 2);
      unsigned mac_addr = _gnutls_read_uint16 (p);
      p+=2;
      //printf("%d %d %d %d %d\n",cipher_algo,kx_algo,mac_algo,ip_addr,mac_addr);

      priv->proxy_info[proxy_id].cipher_algo=cipher_algo;
      priv->proxy_info[proxy_id].kx_algo=kx_algo;
      priv->proxy_info[proxy_id].mac_algo=mac_algo;
      priv->proxy_info[proxy_id].ip_addr=ip_addr;
      priv->proxy_info[proxy_id].mac_addr=mac_addr;
}
      printf("Stored the proxy_info to local instance of extension...\n");
      /* Count all server_names in the packet. */
      while (data_size > 0)
        {
          DECR_LENGTH_RET (data_size, 1, 0);
          p++;

          DECR_LEN (data_size, 2);
          len = _gnutls_read_uint16 (p);
          p += 2;

          if (len > 0)
            {
              DECR_LENGTH_RET (data_size, len, 0);
              server_names++;
              p += len;
            }
          else
            _gnutls_handshake_log
              ("HSK[%p]: Received (0) size server name (under attack?)\n",
               session);

        }

      /* we cannot accept more server names.
       */
      if (server_names > MAX_SERVER_NAME_EXTENSIONS)
        {
          _gnutls_handshake_log
            ("HSK[%p]: Too many server names received (under attack?)\n",
             session);
          server_names = MAX_SERVER_NAME_EXTENSIONS;
        }

      if (server_names == 0)
        return 0;               /* no names found */


      priv->server_names_size = server_names;

      p = data + 4;
      p+=10*(count+1);
      for (i = 0; i < server_names; i++)
        {
          type = *p;
          p++;

          len = _gnutls_read_uint16 (p);
          p += 2;

          switch (type)
            {
            case 0:            /* NAME_DNS */
              if (len <= MAX_SERVER_NAME_SIZE)
                {
                  memcpy (priv->server_names[i].name, p, len);
                  priv->server_names[i].name_length = len;
                  priv->server_names[i].type = GNUTLS_NAME_DNS;
                  break;
                }
            }

          /* move to next record */
          p += len;
        }

      epriv.ptr = priv;
      _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_PROXYINFO,
                                    epriv);

    }

  return 0;
     }
Esempio n. 11
0
int
gnutls_proxyinfo_set (gnutls_session_t session,
                        gnutls_server_name_type_t type,
                        const void *name, size_t name_length, void *data,int data_length, int proxy_id)
{
  printf("Set Data locally in the extension...\n");
  int server_names, ret;
  ProxyInfo_ext_st *priv;
  extension_priv_data_t epriv;
  int set = 0;

/*	Fill the contents of foobar_info
 *	in foobar_ext_st structure viz. priv
 *	Temporarily it is filled only for GNUTLS_CLIENT
 */


  if (session->security_parameters.entity == GNUTLS_SERVER)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }
  
  if(data_length/sizeof(gnutls_ProxyInfo_ext) > MAX_PROXIES - 1 )
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
  if (name_length > MAX_SERVER_NAME_SIZE)
    return GNUTLS_E_SHORT_MEMORY_BUFFER;

  ret =
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_PROXYINFO,
                                  &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++;


  int proxy_index=(data_length/sizeof(gnutls_ProxyInfo_ext)); 

  priv->proxy_cnt=proxy_index;//proxy_id;
  for(int i=0;i<proxy_index;i++){
  priv->proxy_info[i].cipher_algo=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext)));
  priv->proxy_info[i].kx_algo=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext))+4);
  priv->proxy_info[i].mac_algo=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext))+8);
  priv->proxy_info[i].ip_addr=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext))+12);
  priv->proxy_info[i].mac_addr=*(int*)(data+(i*sizeof(gnutls_ProxyInfo_ext))+16);
  }
  if(proxy_index>0)
  printf("Past data parsed from data packet and set in Extension...\n");
priv->proxy_info[proxy_index]=get_proxy_info(session);

proxy_id=proxy_index;
printf("Current Proxy Info:\nProxy Index: %d\n%d, %d, %d, %d, %d\n",priv->proxy_cnt,priv->proxy_info[proxy_id].cipher_algo,priv->proxy_info[proxy_id].kx_algo,priv->proxy_info[proxy_id].mac_algo,priv->proxy_info[proxy_id].ip_addr,priv->proxy_info[proxy_id].mac_addr);


  if (set != 0)
    _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_PROXYINFO,
                                  epriv);
  ret =
    _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_PROXYINFO,
                                  &epriv);
  return 0;
}
Esempio n. 12
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;
}
Esempio n. 13
0
static int
_gnutls_sr_recv_params (gnutls_session_t session,
                        const uint8_t * data, size_t _data_size)
{
  unsigned int len = data[0];
  ssize_t data_size = _data_size;
  sr_ext_st *priv;
  extension_priv_data_t epriv;
  int set = 0, ret;

  DECR_LEN (data_size, len + 1 /* count the first byte and payload */ );

  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 && session->security_parameters.entity == GNUTLS_SERVER)
    {
      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;

  /* It is not legal to receive this extension on a renegotiation and
   * not receive it on the initial negotiation.
   */
  if (session->internals.initial_negotiation_completed != 0 &&
      priv->connection_using_safe_renegotiation == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
    }

  if (len > sizeof (priv->ri_extension_data))
    {
      gnutls_assert ();
      return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
    }

  if (len > 0)
    memcpy (priv->ri_extension_data, &data[1], len);
  priv->ri_extension_data_len = len;

  /* "safe renegotiation received" means on *this* handshake; "connection using
   * safe renegotiation" means that the initial hello received on the connection
   * indicated safe renegotiation.
   */
  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;
}
Esempio n. 14
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_inner_application_send_params (gnutls_session_t session,
                                       opaque * data, size_t data_size)
{
  extension_priv_data_t epriv;
  ia_ext_st *priv = NULL;
  int ret;

  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;

  /* Set ext->gnutls_ia_enable depending on whether we have a TLS/IA
     credential in the session. */

  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {
      gnutls_ia_client_credentials_t cred = (gnutls_ia_client_credentials_t)
        _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

      if (cred)
        priv->flags |= IA_ENABLE;
    }
  else                          /* SERVER */
    {
      gnutls_ia_server_credentials_t cred;

      cred = (gnutls_ia_server_credentials_t)
        _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);

      if (cred)
        priv->flags |= IA_PEER_ENABLE;
    }

  /* If we don't want gnutls_ia locally, or we are a server and the
   * client doesn't want it, don't advertise TLS/IA support at all, as
   * required. */

  if (!(priv->flags & IA_ENABLE))
    return 0;

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

  /* We'll advertise. Check if there's room in the hello buffer. */

  if (data_size < 1)
    {
      gnutls_assert ();
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  /* default: require new application phase */

  *data = YES;

  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {

      /* Client: value follows local setting */

      if (priv->flags & IA_ALLOW_SKIP)
        *data = NO;
    }
  else
    {

      /* Server: value follows local setting and client's setting, but only
       * if we are resuming.
       *
       * XXX Can server test for resumption at this stage?
       *
       * Ai! It seems that read_client_hello only calls parse_extensions if
       * we're NOT resuming! That would make us automatically violate the IA
       * draft; if we're resuming, we must first learn what the client wants
       * -- IA or no IA -- and then prepare our response. Right now we'll
       * always skip IA on resumption, because recv_ext isn't even called
       * to record the peer's support for IA at all. Simon? */

      if ((priv->flags & IA_ALLOW_SKIP) &&
          (priv->flags & IA_PEER_ALLOW_SKIP) &&
          session->internals.resumed == RESUME_TRUE)
        *data = NO;
    }

  return 1;
}
Esempio n. 15
0
/**
 * gnutls_ext_set_data:
 * @session: a #gnutls_session_t opaque pointer
 * @type: the numeric id of the extension
 * @data: the private data to set
 *
 * This function allows an extension handler to store data in the current session
 * and retrieve them later on. The set data will be deallocated using
 * the gnutls_ext_deinit_data_func.
 *
 * Since: 3.4.0
 **/
void
gnutls_ext_set_data(gnutls_session_t session, unsigned type,
		    gnutls_ext_priv_data_t data)
{
	_gnutls_ext_set_session_data(session, type, data);
}