示例#1
0
/**
 * Test daemon response to TLS client hello requests containing extensions
 *
 * @param session
 * @param exten_t - the type of extension being appended to client hello request
 * @param ext_count - the number of consecutive extension replicas inserted into request
 * @param ext_length - the length of each appended extension
 * @return 0 on successful test completion, -1 otherwise
 */
static int
test_hello_extension (gnutls_session_t session, extensions_t exten_t,
                      int ext_count, int ext_length)
{
  int i, ret = 0, pos = 0;
  MHD_socket sd;
  int exten_data_len, ciphersuite_len, datalen;
  struct sockaddr_in sa;
  char url[255];
  opaque *data = NULL;
  uint8_t session_id_len = 0;
  opaque rnd[TLS_RANDOM_SIZE];
  opaque extdata[MAX_EXT_DATA_LENGTH];

  /* single, null compression */
  unsigned char comp[] = { 0x01, 0x00 };
  struct CBC cbc;

  sd = -1;
  memset (&cbc, 0, sizeof (struct CBC));
  if (NULL == (cbc.buf = malloc (sizeof (char) * 256)))
    {
      fprintf (stderr, MHD_E_MEM);
      ret = -1;
      goto cleanup;
    }
  cbc.size = 256;

  sd = socket (AF_INET, SOCK_STREAM, 0);
  if (sd == -1)
    {
      fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
      free (cbc.buf);
      return -1;
    }
  memset (&sa, '\0', sizeof (struct sockaddr_in));
  sa.sin_family = AF_INET;
  sa.sin_port = htons (DEAMON_TEST_PORT);
  sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

  enum MHD_GNUTLS_Protocol hver;

  /* init hash functions */
  session->internals.handshake_mac_handle_md5 =
    MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
  session->internals.handshake_mac_handle_sha =
    MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);

  /* version = 2 , random = [4 for unix time + 28 for random bytes] */
  datalen = 2 /* version */ + TLS_RANDOM_SIZE + (session_id_len + 1);

  data = MHD_gnutls_malloc (datalen);
  if (data == NULL)
      {
	 free (cbc.buf);
	 return -1;
      }
  hver = MHD_gtls_version_max (session);
  data[pos++] = MHD_gtls_version_get_major (hver);
  data[pos++] = MHD_gtls_version_get_minor (hver);

  /* Set the version we advertise as maximum (RSA uses it). */
  set_adv_version (session, MHD_gtls_version_get_major (hver),
                   MHD_gtls_version_get_minor (hver));

  session->security_parameters.version = hver;
  session->security_parameters.timestamp = time (NULL);

  /* generate session client random */
  memset (session->security_parameters.client_random, 0, TLS_RANDOM_SIZE);
  gnutls_write_uint32 (time (NULL), rnd);
  if (GC_OK != MHD_gc_nonce ((char *) &rnd[4], TLS_RANDOM_SIZE - 4)) abort ();
  memcpy (session->security_parameters.client_random, rnd, TLS_RANDOM_SIZE);
  memcpy (&data[pos], rnd, TLS_RANDOM_SIZE);
  pos += TLS_RANDOM_SIZE;

  /* Copy the Session ID       */
  data[pos++] = session_id_len;

  /*
   * len = ciphersuite data + 2 bytes ciphersuite length \
   *       1 byte compression length + 1 byte compression data + \
   * 2 bytes extension length, extensions data
   */
  ciphersuite_len = MHD__gnutls_copy_ciphersuites (session, extdata,
                                                   sizeof (extdata));
  exten_data_len = ext_count * (2 + 2 + ext_length);
  datalen += ciphersuite_len + 2 + 2 + exten_data_len;
  data = MHD_gtls_realloc_fast (data, datalen);
  memcpy (&data[pos], extdata, sizeof (ciphersuite_len));
  pos += ciphersuite_len;

  /* set compression */
  memcpy (&data[pos], comp, sizeof (comp));
  pos += 2;

  /* set extensions length = 2 type bytes + 2 length bytes + extension length */
  gnutls_write_uint16 (exten_data_len, &data[pos]);
  pos += 2;
  for (i = 0; i < ext_count; ++i)
    {
      /* write extension type */
      gnutls_write_uint16 (exten_t, &data[pos]);
      pos += 2;
      gnutls_write_uint16 (ext_length, &data[pos]);
      pos += 2;
      /* we might want to generate random data here */
      memset (&data[pos], 0, ext_length);
      pos += ext_length;
    }

  if (connect (sd, &sa, sizeof (struct sockaddr_in)) < 0)
    {
      fprintf (stderr, "%s\n", MHD_E_FAILED_TO_CONNECT);
      ret = -1;
      goto cleanup;
    }

  gnutls_transport_set_ptr (session, (MHD_gnutls_transport_ptr_t) (long) sd);

  if (gen_test_file_url (url, DEAMON_TEST_PORT))
    {
      ret = -1;
      goto cleanup;
    }

  /* this should crash the server */
  ret = gnutls_send_handshake (session, data, datalen,
			       GNUTLS_HANDSHAKE_CLIENT_HELLO);

  /* advance to STATE2 */
  session->internals.handshake_state = STATE2;
  ret = gnutls_handshake (session);
  ret = gnutls_bye (session, GNUTLS_SHUT_WR);

  gnutls_free (data);

  /* make sure daemon is still functioning */
  if (CURLE_OK != send_curl_req (url, &cbc, "AES128-SHA",
                                 MHD_GNUTLS_PROTOCOL_TLS1_2))
    {
      ret = -1;
      goto cleanup;
    }

cleanup:
  if (-1 != sd)
    MHD_socket_close_ (sd);
  gnutls_free (cbc.buf);
  return ret;
}
示例#2
0
/* Read a v2 client hello. Some browsers still use that beast!
 * However they set their version to 3.0 or 3.1.
 */
int
_gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
			     unsigned int datalen)
{
	uint16_t session_id_len = 0;
	int pos = 0;
	int ret = 0, sret = 0;
	uint16_t sizeOfSuites;
	gnutls_protocol_t adv_version;
	uint8_t rnd[GNUTLS_RANDOM_SIZE];
	int len = datalen;
	uint16_t challenge;
	uint8_t session_id[GNUTLS_MAX_SESSION_ID_SIZE];

	DECR_LEN(len, 2);

	_gnutls_handshake_log
	    ("HSK[%p]: SSL 2.0 Hello: Client's version: %d.%d\n", session,
	     data[pos], data[pos + 1]);

	set_adv_version(session, data[pos], data[pos + 1]);

	adv_version = _gnutls_version_get(data[pos], data[pos + 1]);

	ret = _gnutls_negotiate_version(session, adv_version);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	pos += 2;

	/* Read uint16_t cipher_spec_length */
	DECR_LEN(len, 2);
	sizeOfSuites = _gnutls_read_uint16(&data[pos]);
	pos += 2;

	/* read session id length */
	DECR_LEN(len, 2);
	session_id_len = _gnutls_read_uint16(&data[pos]);
	pos += 2;

	if (session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
		gnutls_assert();
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
	}

	/* read challenge length */
	DECR_LEN(len, 2);
	challenge = _gnutls_read_uint16(&data[pos]);
	pos += 2;

	if (challenge < 16 || challenge > GNUTLS_RANDOM_SIZE) {
		gnutls_assert();
		return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
	}

	/* call the user hello callback
	 */
	ret = _gnutls_user_hello_func(session, adv_version);
	if (ret < 0) {
		if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
			sret = GNUTLS_E_INT_RET_0;
		} else {
			gnutls_assert();
			return ret;
		}
	}

	/* find an appropriate cipher suite */

	DECR_LEN(len, sizeOfSuites);
	ret =
	    _gnutls_handshake_select_v2_suite(session, &data[pos],
					      sizeOfSuites);

	pos += sizeOfSuites;
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* check if the credentials (username, public key etc.) are ok
	 */
	if (_gnutls_get_kx_cred
	    (session,
	     _gnutls_cipher_suite_get_kx_algo(session->security_parameters.
					      cipher_suite)) == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	/* set the mod_auth_st to the appropriate struct
	 * according to the KX algorithm. This is needed since all the
	 * handshake functions are read from there;
	 */
	session->internals.auth_struct =
	    _gnutls_kx_auth_struct(_gnutls_cipher_suite_get_kx_algo
				   (session->security_parameters.
				    cipher_suite));
	if (session->internals.auth_struct == NULL) {

		_gnutls_handshake_log
		    ("HSK[%p]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n",
		     session);

		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	/* read random new values -skip session id for now */
	DECR_LEN(len, session_id_len);	/* skip session id for now */
	memcpy(session_id, &data[pos], session_id_len);
	pos += session_id_len;

	DECR_LEN(len, challenge);
	memset(rnd, 0, GNUTLS_RANDOM_SIZE);

	memcpy(&rnd[GNUTLS_RANDOM_SIZE - challenge], &data[pos],
	       challenge);

	ret = _gnutls_set_client_random(session, rnd);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* generate server random value */
	ret = _gnutls_set_server_random(session, NULL);
	if (ret < 0)
		return gnutls_assert_val(ret);

	session->security_parameters.timestamp = gnutls_time(NULL);


	/* RESUME SESSION */

	DECR_LEN(len, session_id_len);
	ret =
	    _gnutls_server_restore_session(session, session_id,
					   session_id_len);

	if (ret == 0) {		/* resumed! */
		/* get the new random values */
		memcpy(session->internals.resumed_security_parameters.
		       server_random,
		       session->security_parameters.server_random,
		       GNUTLS_RANDOM_SIZE);
		memcpy(session->internals.resumed_security_parameters.
		       client_random,
		       session->security_parameters.client_random,
		       GNUTLS_RANDOM_SIZE);

		session->internals.resumed = RESUME_TRUE;
		return 0;
	} else {
		_gnutls_generate_session_id(session->security_parameters.
					    session_id,
					    &session->security_parameters.
					    session_id_size);
		session->internals.resumed = RESUME_FALSE;
	}

	_gnutls_epoch_set_compression(session, EPOCH_NEXT,
				      GNUTLS_COMP_NULL);
	session->security_parameters.compression_method = GNUTLS_COMP_NULL;

	return sret;
}
示例#3
0
/* Read a v2 client hello. Some browsers still use that beast!
 * However they set their version to 3.0 or 3.1.
 */
int
_gnutls_read_client_hello_v2 (gnutls_session_t session, opaque * data,
			      int datalen)
{
  uint16_t session_id_len = 0;
  int pos = 0;
  int ret = 0;
  uint16_t sizeOfSuites;
  gnutls_protocol_t version;
  opaque rnd[TLS_RANDOM_SIZE];
  int len = datalen;
  int err;
  uint16_t challenge;
  opaque session_id[TLS_MAX_SESSION_ID_SIZE];
  gnutls_protocol_t ver;

  /* we only want to get here once - only in client hello */
  session->internals.v2_hello = 0;

  DECR_LEN (len, 2);

  _gnutls_handshake_log
    ("HSK[%x]: SSL 2.0 Hello: Client's version: %d.%d\n", session,
     data[pos], data[pos + 1]);

  set_adv_version (session, data[pos], data[pos + 1]);

  version = _gnutls_version_get (data[pos], data[pos + 1]);

  /* if we do not support that version  
   */
  if (_gnutls_version_is_supported (session, version) == 0)
    {
      ver = _gnutls_version_lowest (session);
    }
  else
    {
      ver = version;
    }

  _gnutls_set_current_version (session, ver);

  pos += 2;


  /* Read uint16_t cipher_spec_length */
  DECR_LEN (len, 2);
  sizeOfSuites = _gnutls_read_uint16 (&data[pos]);
  pos += 2;

  /* read session id length */
  DECR_LEN (len, 2);
  session_id_len = _gnutls_read_uint16 (&data[pos]);
  pos += 2;

  if (session_id_len > TLS_MAX_SESSION_ID_SIZE)
    {
      gnutls_assert ();
      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
    }

  /* read challenge length */
  DECR_LEN (len, 2);
  challenge = _gnutls_read_uint16 (&data[pos]);
  pos += 2;

  if (challenge < 16 || challenge > TLS_RANDOM_SIZE)
    {
      gnutls_assert ();
      return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
    }

  /* find an appropriate cipher suite */

  DECR_LEN (len, sizeOfSuites);
  ret = _gnutls_handshake_select_v2_suite (session, &data[pos], sizeOfSuites);

  pos += sizeOfSuites;
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* check if the credentials (username, public key etc.) are ok
   */
  if (_gnutls_get_kx_cred
      (session,
       _gnutls_cipher_suite_get_kx_algo (&session->security_parameters.
					 current_cipher_suite),
       &err) == NULL && err != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  /* set the mod_auth_st to the appropriate struct
   * according to the KX algorithm. This is needed since all the
   * handshake functions are read from there;
   */
  session->internals.auth_struct =
    _gnutls_kx_auth_struct (_gnutls_cipher_suite_get_kx_algo
			    (&session->security_parameters.
			     current_cipher_suite));
  if (session->internals.auth_struct == NULL)
    {

      _gnutls_handshake_log
	("HSK[%x]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n",
	 session);

      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }



  /* read random new values -skip session id for now */
  DECR_LEN (len, session_id_len);	/* skip session id for now */
  memcpy (session_id, &data[pos], session_id_len);
  pos += session_id_len;

  DECR_LEN (len, challenge);
  memset (rnd, 0, TLS_RANDOM_SIZE);

  memcpy (&rnd[TLS_RANDOM_SIZE - challenge], &data[pos], challenge);

  _gnutls_set_client_random (session, rnd);

  /* generate server random value */

  _gnutls_tls_create_random (rnd);
  _gnutls_set_server_random (session, rnd);

  session->security_parameters.timestamp = time (NULL);


  /* RESUME SESSION */

  DECR_LEN (len, session_id_len);
  ret = _gnutls_server_restore_session (session, session_id, session_id_len);

  if (ret == 0)
    {				/* resumed! */
      /* get the new random values */
      memcpy (session->internals.resumed_security_parameters.
	      server_random, session->security_parameters.server_random,
	      TLS_RANDOM_SIZE);
      memcpy (session->internals.resumed_security_parameters.
	      client_random, session->security_parameters.client_random,
	      TLS_RANDOM_SIZE);

      session->internals.resumed = RESUME_TRUE;
      return 0;
    }
  else
    {
      _gnutls_generate_session_id (session->security_parameters.
				   session_id,
				   &session->security_parameters.
				   session_id_size);
      session->internals.resumed = RESUME_FALSE;
    }

  session->internals.compression_method = GNUTLS_COMP_NULL;

  return 0;
}