Exemple #1
0
void ssl_init(gnutls_session_t *session,
              gnutls_certificate_credentials_t *xcred,
                  void *push_cb,
                  void *pull_cb,
                  void *pull_timeout_cb)
{
    /* X509 */
    gnutls_certificate_allocate_credentials(xcred);
    gnutls_certificate_set_verify_function(*xcred, _verify_certificate_callback);

    /* init things! */
    gnutls_init(session, GNUTLS_CLIENT);
    gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, *xcred);
    gnutls_transport_set_push_function(*session, push_cb);
    gnutls_transport_set_pull_function(*session, pull_cb);
    gnutls_transport_set_pull_timeout_function(*session, pull_timeout_cb);

    /* handshake */
    gnutls_handshake(*session);
}
Exemple #2
0
my_bool ma_ssl_connect(MARIADB_SSL *cssl)
{
  gnutls_session_t ssl = (gnutls_session_t)cssl->ssl;
  my_bool blocking;
  MYSQL *mysql;
  MARIADB_PVIO *pvio;
  int ret;
  mysql= (MYSQL *)gnutls_session_get_ptr(ssl);

  if (!mysql)
    return 1;

  pvio= mysql->net.pvio;

  /* Set socket to blocking if not already set */
  if (!(blocking= pvio->methods->is_blocking(pvio)))
    pvio->methods->blocking(pvio, TRUE, 0);

  /* we don't use GnuTLS read/write functions */
  gnutls_transport_set_ptr(ssl, pvio);
  gnutls_transport_set_push_function(ssl, ma_ssl_push);
  gnutls_transport_set_pull_function(ssl, ma_ssl_pull);
  gnutls_transport_set_pull_timeout_function(ssl, ma_ssl_pull_timeout);
  gnutls_handshake_set_timeout(ssl, pvio->timeout[PVIO_CONNECT_TIMEOUT]);

  do {
    ret = gnutls_handshake(ssl);
  } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);

  if (ret < 0)
  {
    ma_ssl_set_error(mysql, ret);
    /* restore blocking mode */
    if (!blocking)
      pvio->methods->blocking(pvio, FALSE, 0);
    return 1;
  }
  cssl->ssl= (void *)ssl;

  return 0;
}
Exemple #3
0
/**
 * gnutls_transport_set_fastopen:
 * @session: is a #gnutls_session_t type.
 * @fd: is the session's socket descriptor
 * @connect_addr: is the address we want to connect to
 * @connect_addrlen: is the length of @connect_addr
 * @flags: must be zero
 *
 * Enables TCP Fast Open (TFO) for the specified TLS client session.
 * That means that TCP connection establishment and the transmission
 * of the first TLS client hello packet are combined. The
 * peer's address must be  specified in @connect_addr and @connect_addrlen,
 * and the socket specified by @fd should not be connected.
 *
 * TFO only works for TCP sockets of type AF_INET and AF_INET6.
 * If the OS doesn't support TCP fast open this function will result
 * to gnutls using connect() transparently during the first write.
 *
 * Note: This function overrides all the transport callback functions.
 * If this is undesirable, TCP Fast Open must be implemented on the user
 * callback functions without calling this function. When using
 * this function, transport callbacks must not be set, and 
 * gnutls_transport_set_ptr() or gnutls_transport_set_int()
 * must not be called.
 *
 * On GNU/Linux TFO has to be enabled at the system layer, that is
 *   in /proc/sys/net/ipv4/tcp_fastopen, bit 0 has to be set.
 *
 * This function has no effect on server sessions.
 *
 * Since: 3.5.3
 **/
void
gnutls_transport_set_fastopen(gnutls_session_t session,
			      int fd, struct sockaddr *connect_addr, socklen_t connect_addrlen,
			      unsigned int flags)
{
	if (connect_addrlen > (socklen_t)sizeof(session->internals.tfo.connect_addr)) {
		gnutls_assert();
		abort();
	}

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

	memcpy(&session->internals.tfo.connect_addr, connect_addr, connect_addrlen);
	session->internals.tfo.connect_addrlen = connect_addrlen;
	session->internals.tfo.fd = fd;

	gnutls_transport_set_pull_function(session, tfo_read);
	gnutls_transport_set_pull_timeout_function(session, tfo_recv_timeout);
	gnutls_transport_set_ptr(session, &session->internals.tfo);

	session->internals.tfo.flags = 0;
#ifdef MSG_NOSIGNAL
	if (session->internals.flags & GNUTLS_NO_SIGNAL)
		session->internals.tfo.flags |= MSG_NOSIGNAL;
#endif

#ifdef _WIN32
	gnutls_transport_set_vec_push_function(session, NULL);
	gnutls_transport_set_push_function(session, tfo_send);
#else
	gnutls_transport_set_vec_push_function(session, tfo_writev);
#endif
}
Exemple #4
0
struct dtls_gnutls_data *dtls_gnutls_data_create(struct conn *conn,int config)
{
	const char *errpos;
	int rc;
	gnutls_datum_t key;
	int bits;
	struct dtls_gnutls_data *d = malloc(sizeof(struct dtls_gnutls_data));
	if (!d)
		return 0;

	gnutls_global_set_log_level(10);
	gnutls_global_set_log_function(dtls_log_cb);
	
	rc = gnutls_init(&d->session, config); 
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't init session: %s", gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}


	gnutls_certificate_allocate_credentials(&d->x509_cred);




	/* Set credentials */

	if (conn->dtls_cert_file && conn->dtls_key_file){

		rc = gnutls_certificate_set_x509_key_file(d->x509_cred, conn->dtls_cert_file,
							  conn->dtls_key_file, GNUTLS_X509_FMT_PEM);

		if (rc < 0) {
			cw_log(LOG_ERR, "DTLS - Can't set cert/key: %s", gnutls_strerror(rc));
			dtls_gnutls_data_destroy(d);
			return 0;
		}
	}



/*
#if GNUTLS_VERSION_NUMBER >= 0x030100
	bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_INSECURE);
#else
*/	bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY);
/*#endif*/






	/* Set ciphers */
/*
	rc = gnutls_priority_init(&d->priority_cache, conn->dtls_cipher, &errpos);
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't init ciphers '%s' at '%s' : %s", conn->dtls_cipher,
		       errpos, gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}


	rc = gnutls_priority_set(d->session, d->priority_cache);
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't set priority: %s", gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}

*/
	rc = gnutls_priority_set_direct(d->session,conn->dtls_cipher,&errpos);
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't init ciphers '%s' at '%s' : %s", conn->dtls_cipher,
		       errpos, gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}

	


	rc = gnutls_credentials_set(d->session, GNUTLS_CRD_CERTIFICATE, d->x509_cred);
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't set x.509 credentials: %s", gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}

	gnutls_certificate_set_verify_function(d->x509_cred,verify_cert);
	gnutls_session_set_ptr(d->session, conn);
	gnutls_transport_set_ptr(d->session, conn);
	gnutls_transport_set_pull_function(d->session, dtls_gnutls_bio_read);
	gnutls_transport_set_push_function(d->session, dtls_gnutls_bio_write);
	gnutls_transport_set_pull_timeout_function(d->session, dtls_gnutls_bio_wait);


#if GNUTLS_VERSION_NUMBER >= 0x030100
	gnutls_handshake_set_timeout(d->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
	gnutls_dtls_set_data_mtu(d->session, conn->dtls_mtu);
#endif
	gnutls_dtls_set_mtu(d->session, conn->dtls_mtu);




	return d;
}
Exemple #5
0
void
doit (void)
{
  /* Server stuff. */
  gnutls_anon_server_credentials_t s_anoncred;
  const gnutls_datum_t p3 = { (void *) pkcs3, strlen (pkcs3) };
  static gnutls_dh_params_t dh_params;
  gnutls_session_t server;
  int sret, cret;
  /* Client stuff. */
  gnutls_anon_client_credentials_t c_anoncred;
  gnutls_session_t client;
  /* Need to enable anonymous KX specifically. */
  char buffer[MAX_BUF + 1];
  ssize_t ns;
  int ret, transferred = 0, msglen;

  /* General init. */
  gnutls_global_init ();
  gnutls_global_set_log_function (tls_log_func);
  if (debug)
    gnutls_global_set_log_level (99);

  /* Init server */
  gnutls_anon_allocate_server_credentials (&s_anoncred);
  gnutls_dh_params_init (&dh_params);
  gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
  gnutls_anon_set_server_dh_params (s_anoncred, dh_params);
  gnutls_init (&server, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
  ret = gnutls_priority_set_direct (server, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL);
  if (ret < 0)
    exit(1);
  gnutls_credentials_set (server, GNUTLS_CRD_ANON, s_anoncred);
  gnutls_dh_set_prime_bits (server, 1024);
  gnutls_transport_set_push_function (server, server_push);
  gnutls_transport_set_pull_function (server, server_pull);
  gnutls_transport_set_pull_timeout_function (server, server_pull_timeout_func);
  gnutls_transport_set_ptr (server, (gnutls_transport_ptr_t)server);

  /* Init client */
  gnutls_anon_allocate_client_credentials (&c_anoncred);
  gnutls_init (&client, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
  cret = gnutls_priority_set_direct (client, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL);
  if (cret < 0)
    exit(1);
  gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred);
  gnutls_transport_set_push_function (client, client_push);
  gnutls_transport_set_pull_function (client, client_pull);
  gnutls_transport_set_pull_timeout_function (client, client_pull_timeout_func);
  gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t)client);

  handshake = 1;
  HANDSHAKE(client, server);

  handshake = 0;
  if (debug)
    success ("Handshake established\n");

  do
    {
      ret = gnutls_record_send (client, MSG, strlen (MSG));
    }
  while(ret == GNUTLS_E_AGAIN);
  //success ("client: sent %d\n", ns);

  msglen = strlen(MSG);
  TRANSFER(client, server, MSG, msglen, buffer, MAX_BUF);

  if (debug)
    fputs ("\n", stdout);

  gnutls_bye (client, GNUTLS_SHUT_WR);
  gnutls_bye (server, GNUTLS_SHUT_WR);

  gnutls_deinit (client);
  gnutls_deinit (server);

  gnutls_anon_free_client_credentials (c_anoncred);
  gnutls_anon_free_server_credentials (s_anoncred);

  gnutls_dh_params_deinit (dh_params);

  gnutls_global_deinit ();
}
Exemple #6
0
void udp_server(const char* name, int port, int mtu)
{
    int sock, ret;
    struct sockaddr_in cli_addr;
    socklen_t cli_addr_size;
    char buffer[MAX_BUFFER];
    priv_data_st priv;
    gnutls_session_t session;
    gnutls_datum_t cookie_key;
    gnutls_dtls_prestate_st prestate;
    unsigned char sequence[8];

    ret = gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE);
    if (ret < 0)
      {
        fprintf(stderr, "Cannot generate key\n");
        exit(1);
      }

    ret = listen_socket (name, port, SOCK_DGRAM);
    if (ret < 0)
      {
        fprintf(stderr, "Cannot listen\n");
        exit (1);
      }

    for (;;)
      {
        printf("Waiting for connection...\n");
        sock = wait_for_connection();
        if (sock < 0)
          continue;

        cli_addr_size = sizeof(cli_addr);
        ret = recvfrom(sock, buffer, sizeof(buffer), MSG_PEEK, (struct sockaddr*)&cli_addr, &cli_addr_size);
        if (ret > 0)
          {
            memset(&prestate, 0, sizeof(prestate));
            ret = gnutls_dtls_cookie_verify(&cookie_key, &cli_addr, sizeof(cli_addr), buffer, ret, &prestate);
            if (ret < 0) /* cookie not valid */
              {
                priv_data_st s;
                
                memset(&s,0,sizeof(s));
                s.fd = sock;
                s.cli_addr = (void*)&cli_addr;
                s.cli_addr_size = sizeof(cli_addr);
                
                printf("Sending hello verify request to %s\n", human_addr ((struct sockaddr *)
                  &cli_addr, sizeof(cli_addr), buffer, sizeof(buffer)));
                gnutls_dtls_cookie_send(&cookie_key, &cli_addr, sizeof(cli_addr), &prestate, (gnutls_transport_ptr_t)&s, push_func);

                /* discard peeked data*/
                recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&cli_addr, &cli_addr_size);
                continue;
              }
            printf ("Accepted connection from %s\n",
                            human_addr ((struct sockaddr *)
                                        &cli_addr, sizeof(cli_addr), buffer,
                                        sizeof (buffer)));
          }
        else
          continue;

        session = initialize_session(1);
        gnutls_dtls_prestate_set(session, &prestate);
        if (mtu) gnutls_dtls_set_mtu(session, mtu);

        priv.session = session;
        priv.fd = sock;
        priv.cli_addr = (struct sockaddr *)&cli_addr;
        priv.cli_addr_size = sizeof(cli_addr);

        gnutls_transport_set_ptr (session, &priv);
        gnutls_transport_set_push_function (session, push_func);
        gnutls_transport_set_pull_function (session, pull_func);
        gnutls_transport_set_pull_timeout_function (session, pull_timeout_func);

        do
          {
            ret = gnutls_handshake(session);
          }
        while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

        if (ret < 0)
          {
            fprintf(stderr, "Error in handshake(): %s\n", gnutls_strerror(ret));
            gnutls_deinit(session);
            continue;
          }

        for(;;)
          {
            do {
              ret = gnutls_record_recv_seq(session, buffer, MAX_BUFFER, sequence);
            } while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

            if (ret == GNUTLS_E_REHANDSHAKE)
              {
                fprintf (stderr, "*** Received hello message\n");
                do
                  {
                    ret = gnutls_handshake (session);
                  }
                while (ret == GNUTLS_E_INTERRUPTED ||
                       ret == GNUTLS_E_AGAIN);
                
                if (ret == 0) continue;
              }
            if (ret < 0)
              {
                fprintf(stderr, "Error in recv(): %s\n", gnutls_strerror(ret));
                break;
              }
            if (ret == 0)
              {
                printf("EOF\n\n");
                break;
              }
              
            buffer[ret] = 0;
            printf("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n", sequence[0], sequence[1], sequence[2],
                   sequence[3], sequence[4], sequence[5], sequence[6], sequence[7], buffer);

            if (check_command(session, buffer) == 0)
              {
                /* reply back */
                ret = gnutls_record_send(session, buffer, ret);
                if (ret < 0)
                  {
                    fprintf(stderr, "Error in send(): %s\n", gnutls_strerror(ret));
                    break;
                  }
              }
          }
      }
    gnutls_deinit(session);
}
/**
 * gnutls_init:
 * @session: is a pointer to a #gnutls_session_t structure.
 * @flags: indicate if this session is to be used for server or client.
 *
 * This function initializes the current session to null. Every
 * session must be initialized before use, so internal structures can
 * be allocated.  This function allocates structures which can only
 * be free'd by calling gnutls_deinit().  Returns %GNUTLS_E_SUCCESS (0) on success.
 *
 * @flags can be one of %GNUTLS_CLIENT and %GNUTLS_SERVER. For a DTLS
 * entity, the flags %GNUTLS_DATAGRAM and  %GNUTLS_NONBLOCK are
 * also available. The latter flag will enable a non-blocking
 * operation of the DTLS timers. 
 *
 * The flag %GNUTLS_NO_REPLAY_PROTECTION will disable any 
 * replay protection in DTLS mode. That must only used when 
 * replay protection is achieved using other means.
 *
 * Note that since version 3.1.2 this function enables some common
 * TLS extensions such as session tickets and OCSP certificate status
 * request in client side by default. To prevent that use the %GNUTLS_NO_EXTENSIONS
 * flag.
 *
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
 **/
int gnutls_init(gnutls_session_t * session, unsigned int flags)
{
	int ret;
	record_parameters_st *epoch;
	
	FAIL_IF_LIB_ERROR;

	*session = gnutls_calloc(1, sizeof(struct gnutls_session_int));
	if (*session == NULL)
		return GNUTLS_E_MEMORY_ERROR;

	ret = _gnutls_epoch_alloc(*session, 0, &epoch);
	if (ret < 0) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	/* Set all NULL algos on epoch 0 */
	_gnutls_epoch_set_null_algos(*session, epoch);

	(*session)->security_parameters.epoch_next = 1;

	(*session)->security_parameters.entity =
	    (flags & GNUTLS_SERVER ? GNUTLS_SERVER : GNUTLS_CLIENT);

	/* the default certificate type for TLS */
	(*session)->security_parameters.cert_type = DEFAULT_CERT_TYPE;

	/* Initialize buffers */
	_gnutls_buffer_init(&(*session)->internals.handshake_hash_buffer);
	_gnutls_buffer_init(&(*session)->internals.hb_remote_data);
	_gnutls_buffer_init(&(*session)->internals.hb_local_data);
	_gnutls_buffer_init(&(*session)->internals.record_presend_buffer);

	_mbuffer_head_init(&(*session)->internals.record_buffer);
	_mbuffer_head_init(&(*session)->internals.record_send_buffer);
	_mbuffer_head_init(&(*session)->internals.record_recv_buffer);

	_mbuffer_head_init(&(*session)->internals.handshake_send_buffer);
	_gnutls_handshake_recv_buffer_init(*session);

	(*session)->internals.expire_time = DEFAULT_EXPIRE_TIME;	/* one hour default */

	gnutls_handshake_set_max_packet_length((*session),
					       MAX_HANDSHAKE_PACKET_SIZE);

	/* set the socket pointers to -1;
	 */
	(*session)->internals.transport_recv_ptr =
	    (gnutls_transport_ptr_t) - 1;
	(*session)->internals.transport_send_ptr =
	    (gnutls_transport_ptr_t) - 1;

	/* set the default maximum record size for TLS
	 */
	(*session)->security_parameters.max_record_recv_size =
	    DEFAULT_MAX_RECORD_SIZE;
	(*session)->security_parameters.max_record_send_size =
	    DEFAULT_MAX_RECORD_SIZE;

	/* everything else not initialized here is initialized
	 * as NULL or 0. This is why calloc is used.
	 */

	_gnutls_handshake_internal_state_init(*session);

	/* emulate old gnutls behavior for old applications that do not use the priority_*
	 * functions.
	 */
	(*session)->internals.priorities.sr = SR_PARTIAL;

#ifdef HAVE_WRITEV
	gnutls_transport_set_vec_push_function(*session, system_writev);
#else
	gnutls_transport_set_push_function(*session, system_write);
#endif
	gnutls_transport_set_pull_function(*session, system_read);
	gnutls_transport_set_errno_function(*session, system_errno);
	gnutls_transport_set_pull_timeout_function(*session,
						   system_recv_timeout);

	(*session)->internals.hb_retrans_timeout_ms = 1000;
	(*session)->internals.hb_total_timeout_ms = 60000;

	if (flags & GNUTLS_DATAGRAM) {
		(*session)->internals.dtls.mtu = DTLS_DEFAULT_MTU;
		(*session)->internals.transport = GNUTLS_DGRAM;

		(*session)->internals.dtls.retrans_timeout_ms = 1000;
		(*session)->internals.dtls.total_timeout_ms = 60000;
	} else
		(*session)->internals.transport = GNUTLS_STREAM;

	if (flags & GNUTLS_NONBLOCK)
		(*session)->internals.dtls.blocking = 0;
	else
		(*session)->internals.dtls.blocking = 1;

	/* Enable useful extensions */
	if ((flags & GNUTLS_CLIENT) && !(flags & GNUTLS_NO_EXTENSIONS)) {
#ifdef ENABLE_SESSION_TICKETS
		gnutls_session_ticket_enable_client(*session);
#endif
#ifdef ENABLE_OCSP
		gnutls_ocsp_status_request_enable_client(*session, NULL, 0,
							 NULL);
#endif
	}

	if (flags & GNUTLS_NO_REPLAY_PROTECTION)
		(*session)->internals.no_replay_protection = 1;

	return 0;
}
Exemple #8
0
int
main (void)
{
    int listen_sd;
    int sock, ret;
    struct sockaddr_in sa_serv;
    struct sockaddr_in cli_addr;
    socklen_t cli_addr_size;
    gnutls_session_t session;
    char buffer[MAX_BUFFER];
    priv_data_st priv;
    gnutls_datum_t cookie_key;
    gnutls_dtls_prestate_st prestate;
    int mtu = 1400;
    unsigned char sequence[8];

    /* this must be called once in the program
     */
    gnutls_global_init ();

    gnutls_certificate_allocate_credentials (&x509_cred);
    gnutls_certificate_set_x509_trust_file (x509_cred, CAFILE,
                                            GNUTLS_X509_FMT_PEM);

    gnutls_certificate_set_x509_crl_file (x509_cred, CRLFILE,
                                          GNUTLS_X509_FMT_PEM);

    ret = gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE,
            GNUTLS_X509_FMT_PEM);
    if (ret < 0)
    {
        printf("No certificate or key were found\n");
        exit(1);
    }

    generate_dh_params ();

    gnutls_certificate_set_dh_params (x509_cred, dh_params);

    gnutls_priority_init (&priority_cache,
                          "PERFORMANCE:-VERS-TLS-ALL:+VERS-DTLS1.0:%SERVER_PRECEDENCE",
                          NULL);

    gnutls_key_generate (&cookie_key, GNUTLS_COOKIE_KEY_SIZE);

    /* Socket operations
     */
    listen_sd = socket (AF_INET, SOCK_DGRAM, 0);

    memset (&sa_serv, '\0', sizeof (sa_serv));
    sa_serv.sin_family = AF_INET;
    sa_serv.sin_addr.s_addr = INADDR_ANY;
    sa_serv.sin_port = htons (PORT);

    {   /* DTLS requires the IP don't fragment (DF) bit to be set */
#if defined(IP_DONTFRAG)
        int optval = 1;
        setsockopt (listen_sd, IPPROTO_IP, IP_DONTFRAG,
                    (const void *) &optval, sizeof (optval));
#elif defined(IP_MTU_DISCOVER)
        int optval = IP_PMTUDISC_DO;
        setsockopt(listen_sd, IPPROTO_IP, IP_MTU_DISCOVER,
                   (const void*) &optval, sizeof (optval));
#endif
    }

    bind (listen_sd, (struct sockaddr *) &sa_serv, sizeof (sa_serv));

    printf ("UDP server ready. Listening to port '%d'.\n\n", PORT);

    for (;;)
    {
        printf ("Waiting for connection...\n");
        sock = wait_for_connection (listen_sd);
        if (sock < 0)
            continue;

        cli_addr_size = sizeof (cli_addr);
        ret = recvfrom (sock, buffer, sizeof (buffer), MSG_PEEK,
                        (struct sockaddr *) &cli_addr, &cli_addr_size);
        if (ret > 0)
        {
            memset (&prestate, 0, sizeof (prestate));
            ret = gnutls_dtls_cookie_verify (&cookie_key, &cli_addr,
                                             sizeof (cli_addr), buffer, ret,
                                             &prestate);
            if (ret < 0)          /* cookie not valid */
            {
                priv_data_st s;

                memset (&s, 0, sizeof (s));
                s.fd = sock;
                s.cli_addr = (void *) &cli_addr;
                s.cli_addr_size = sizeof (cli_addr);

                printf ("Sending hello verify request to %s\n",
                        human_addr ((struct sockaddr *) &cli_addr,
                                    sizeof (cli_addr), buffer,
                                    sizeof (buffer)));

                gnutls_dtls_cookie_send (&cookie_key, &cli_addr,
                                         sizeof (cli_addr), &prestate,
                                         (gnutls_transport_ptr_t) & s,
                                         push_func);

                /* discard peeked data */
                recvfrom (sock, buffer, sizeof (buffer), 0,
                          (struct sockaddr *) &cli_addr, &cli_addr_size);
                usleep (100);
                continue;
            }
            printf ("Accepted connection from %s\n",
                    human_addr ((struct sockaddr *)
                                &cli_addr, sizeof (cli_addr), buffer,
                                sizeof (buffer)));
        }
        else
            continue;

        session = initialize_tls_session ();
        gnutls_dtls_prestate_set (session, &prestate);
        gnutls_dtls_set_mtu (session, mtu);

        priv.session = session;
        priv.fd = sock;
        priv.cli_addr = (struct sockaddr *) &cli_addr;
        priv.cli_addr_size = sizeof (cli_addr);

        gnutls_transport_set_ptr (session, &priv);
        gnutls_transport_set_push_function (session, push_func);
        gnutls_transport_set_pull_function (session, pull_func);
        gnutls_transport_set_pull_timeout_function (session, pull_timeout_func);

        do
        {
            ret = gnutls_handshake (session);
        }
        while (ret < 0 && gnutls_error_is_fatal (ret) == 0);

        if (ret < 0)
        {
            fprintf (stderr, "Error in handshake(): %s\n",
                     gnutls_strerror (ret));
            gnutls_deinit (session);
            continue;
        }

        printf ("- Handshake was completed\n");

        for (;;)
        {
            do
            {
                ret = gnutls_record_recv_seq (session, buffer, MAX_BUFFER,
                                              sequence);
            }
            while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

            if (ret < 0)
            {
                fprintf (stderr, "Error in recv(): %s\n",
                         gnutls_strerror (ret));
                break;
            }
            if (ret == 0)
            {
                printf ("EOF\n\n");
                break;
            }
            buffer[ret] = 0;
            printf ("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n",
                    sequence[0], sequence[1], sequence[2], sequence[3],
                    sequence[4], sequence[5], sequence[6], sequence[7], buffer);

            /* reply back */
            ret = gnutls_record_send (session, buffer, ret);
            if (ret < 0)
            {
                fprintf (stderr, "Error in send(): %s\n",
                         gnutls_strerror (ret));
                break;
            }
        }

        gnutls_bye (session, GNUTLS_SHUT_WR);
        gnutls_deinit (session);

    }
    close (listen_sd);

    gnutls_certificate_free_credentials (x509_cred);
    gnutls_priority_deinit (priority_cache);

    gnutls_global_deinit ();

    return 0;

}
Exemple #9
0
void doit(void)
{
	global_init();

	int ret;
	char buf[1024];
	/* Server stuff. */
	gnutls_certificate_credentials_t serverx509cred;
	gnutls_session_t server;
	int sret = GNUTLS_E_AGAIN;
	/* Client stuff. */
	gnutls_certificate_credentials_t clientx509cred;
	gnutls_session_t client;
	int cret = GNUTLS_E_AGAIN;

	/* General init. */
	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(6);

	/* Init server */
	gnutls_certificate_allocate_credentials(&serverx509cred);
	gnutls_certificate_set_x509_key_mem(serverx509cred,
					    &server2_cert, &server2_key,
					    GNUTLS_X509_FMT_PEM);

	gnutls_init(&server, GNUTLS_SERVER);
	gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
			       serverx509cred);

	gnutls_priority_set_direct(server,
				   "NORMAL",
				   NULL);
	gnutls_transport_set_push_function(server, server_push);
	gnutls_transport_set_pull_function(server, server_pull);
	gnutls_transport_set_pull_timeout_function(server,
						   server_pull_timeout_func);
	gnutls_transport_set_ptr(server, server);

	/* Init client */

	ret = gnutls_certificate_allocate_credentials(&clientx509cred);
	if (ret < 0)
		exit(1);

	ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca2_cert, GNUTLS_X509_FMT_PEM);
	if (ret < 0)
		exit(1);

	ret = gnutls_init(&client, GNUTLS_CLIENT);
	if (ret < 0)
		exit(1);

	ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
			       clientx509cred);
	if (ret < 0)
		exit(1);

	ret = gnutls_priority_set_direct(client, "NORMAL", NULL);
	if (ret < 0)
		exit(1);

	gnutls_record_set_max_size(client, 512);
	gnutls_transport_set_push_function(client, client_push);
	gnutls_transport_set_pull_function(client, client_pull);
	gnutls_transport_set_pull_timeout_function(client,
						   client_pull_timeout_func);
	gnutls_transport_set_ptr(client, client);

	HANDSHAKE(client, server);

	memset(buf, 1, sizeof(buf));
	ret = gnutls_record_send(server, buf, 513);
	if (ret != 512 || ret < 0) {
		gnutls_perror(ret);
		exit(1);
	}
	success("did not send a 513-byte packet\n");

	ret = gnutls_record_send(server, buf, 512);
	if (ret < 0) {
		gnutls_perror(ret);
		exit(1);
	}
	success("did send a 512-byte packet\n");

	gnutls_bye(client, GNUTLS_SHUT_RDWR);
	gnutls_bye(server, GNUTLS_SHUT_RDWR);

	gnutls_deinit(client);
	gnutls_deinit(server);

	gnutls_certificate_free_credentials(serverx509cred);
	gnutls_certificate_free_credentials(clientx509cred);

	gnutls_global_deinit();
}
Exemple #10
0
/**
 * gnutls_init:
 * @session: is a pointer to a #gnutls_session_t structure.
 * @flags: indicate if this session is to be used for server or client.
 *
 * This function initializes the current session to null. Every
 * session must be initialized before use, so internal structures can
 * be allocated.  This function allocates structures which can only
 * be free'd by calling gnutls_deinit().  Returns zero on success.
 *
 * @flags can be one of %GNUTLS_CLIENT and %GNUTLS_SERVER. For a DTLS
 * entity, the flags %GNUTLS_DATAGRAM and  %GNUTLS_NONBLOCK are
 * also available. The latter flag will enable a non-blocking
 * operation of the DTLS timers.
 *
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
 **/
int
gnutls_init (gnutls_session_t * session, unsigned int flags)
{
  int ret;
  record_parameters_st *epoch;

  *session = gnutls_calloc (1, sizeof (struct gnutls_session_int));
  if (*session == NULL)
    return GNUTLS_E_MEMORY_ERROR;

  ret = _gnutls_epoch_alloc (*session, 0, &epoch);
  if (ret < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* Set all NULL algos on epoch 0 */
  _gnutls_epoch_set_null_algos (*session, epoch);

  (*session)->security_parameters.epoch_next = 1;

  (*session)->security_parameters.entity = (flags&GNUTLS_SERVER?GNUTLS_SERVER:GNUTLS_CLIENT);

  /* the default certificate type for TLS */
  (*session)->security_parameters.cert_type = DEFAULT_CERT_TYPE;

  /* Initialize buffers */
  _gnutls_buffer_init (&(*session)->internals.handshake_hash_buffer);

  _mbuffer_head_init (&(*session)->internals.record_buffer);
  _mbuffer_head_init (&(*session)->internals.record_send_buffer);
  _mbuffer_head_init (&(*session)->internals.record_recv_buffer);

  _mbuffer_head_init (&(*session)->internals.handshake_send_buffer);
  _gnutls_handshake_recv_buffer_init(*session);

  (*session)->key = gnutls_calloc (1, sizeof (struct gnutls_key_st));
  if ((*session)->key == NULL)
    {
      gnutls_free (*session);
      *session = NULL;
      return GNUTLS_E_MEMORY_ERROR;
    }

  (*session)->internals.expire_time = DEFAULT_EXPIRE_TIME;      /* one hour default */

  gnutls_dh_set_prime_bits ((*session), MIN_DH_BITS);

  gnutls_handshake_set_max_packet_length ((*session),
                                          MAX_HANDSHAKE_PACKET_SIZE);

  /* set the socket pointers to -1;
   */
  (*session)->internals.transport_recv_ptr = (gnutls_transport_ptr_t) - 1;
  (*session)->internals.transport_send_ptr = (gnutls_transport_ptr_t) - 1;

  /* set the default maximum record size for TLS
   */
  (*session)->security_parameters.max_record_recv_size =
    DEFAULT_MAX_RECORD_SIZE;
  (*session)->security_parameters.max_record_send_size =
    DEFAULT_MAX_RECORD_SIZE;

  /* everything else not initialized here is initialized
   * as NULL or 0. This is why calloc is used.
   */

  _gnutls_handshake_internal_state_init (*session);

  /* emulate old gnutls behavior for old applications that do not use the priority_*
   * functions.
   */
  (*session)->internals.priorities.sr = SR_PARTIAL;

#ifdef HAVE_WRITEV
  gnutls_transport_set_vec_push_function (*session, system_writev);
#else
  gnutls_transport_set_push_function (*session, system_write);
#endif
  gnutls_transport_set_pull_function (*session, system_read);
  gnutls_transport_set_errno_function (*session, system_errno);
  gnutls_transport_set_pull_timeout_function (*session, system_recv_timeout);

  if (flags & GNUTLS_DATAGRAM)
    {
      (*session)->internals.dtls.mtu = DTLS_DEFAULT_MTU;
      (*session)->internals.transport = GNUTLS_DGRAM;

      (*session)->internals.dtls.retrans_timeout = 1000;
      (*session)->internals.dtls.total_timeout = 60000;

      (*session)->internals.dtls.record_sw_size = 0;
    }
  else
    (*session)->internals.transport = GNUTLS_STREAM;
  
  if (flags & GNUTLS_NONBLOCK)
    (*session)->internals.dtls.blocking = 0;
  else
    (*session)->internals.dtls.blocking = 1;

  return 0;
}
Exemple #11
0
int					/* O - 0 on success, -1 on failure */
_httpTLSStart(http_t *http)		/* I - Connection to server */
{
  char			hostname[256],	/* Hostname */
			*hostptr;	/* Pointer into hostname */
  int			status;		/* Status of handshake */
  gnutls_certificate_credentials_t *credentials;
					/* TLS credentials */
  char			priority_string[1024];
					/* Priority string */


  DEBUG_printf(("3_httpTLSStart(http=%p)", http));

  if (tls_options < 0)
  {
    DEBUG_puts("4_httpTLSStart: Setting defaults.");
    _cupsSetDefaults();
    DEBUG_printf(("4_httpTLSStart: tls_options=%x", tls_options));
  }

  if (http->mode == _HTTP_MODE_SERVER && !tls_keypath)
  {
    DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called.");
    http->error  = errno = EINVAL;
    http->status = HTTP_STATUS_ERROR;
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Server credentials not set."), 1);

    return (-1);
  }

  credentials = (gnutls_certificate_credentials_t *)
                    malloc(sizeof(gnutls_certificate_credentials_t));
  if (credentials == NULL)
  {
    DEBUG_printf(("8_httpStartTLS: Unable to allocate credentials: %s",
                  strerror(errno)));
    http->error  = errno;
    http->status = HTTP_STATUS_ERROR;
    _cupsSetHTTPError(HTTP_STATUS_ERROR);

    return (-1);
  }

  gnutls_certificate_allocate_credentials(credentials);
  status = gnutls_init(&http->tls, http->mode == _HTTP_MODE_CLIENT ? GNUTLS_CLIENT : GNUTLS_SERVER);
  if (!status)
    status = gnutls_set_default_priority(http->tls);

  if (status)
  {
    http->error  = EIO;
    http->status = HTTP_STATUS_ERROR;

    DEBUG_printf(("4_httpTLSStart: Unable to initialize common TLS parameters: %s", gnutls_strerror(status)));
    _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0);

    gnutls_deinit(http->tls);
    gnutls_certificate_free_credentials(*credentials);
    free(credentials);
    http->tls = NULL;

    return (-1);
  }

  if (http->mode == _HTTP_MODE_CLIENT)
  {
   /*
    * Client: get the hostname to use for TLS...
    */

    if (httpAddrLocalhost(http->hostaddr))
    {
      strlcpy(hostname, "localhost", sizeof(hostname));
    }
    else
    {
     /*
      * Otherwise make sure the hostname we have does not end in a trailing dot.
      */

      strlcpy(hostname, http->hostname, sizeof(hostname));
      if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
	  *hostptr == '.')
	*hostptr = '\0';
    }

    status = gnutls_server_name_set(http->tls, GNUTLS_NAME_DNS, hostname, strlen(hostname));
  }
  else
  {
   /*
    * Server: get certificate and private key...
    */

    char	crtfile[1024],		/* Certificate file */
		keyfile[1024];		/* Private key file */
    int		have_creds = 0;		/* Have credentials? */

    if (http->fields[HTTP_FIELD_HOST][0])
    {
     /*
      * Use hostname for TLS upgrade...
      */

      strlcpy(hostname, http->fields[HTTP_FIELD_HOST], sizeof(hostname));
    }
    else
    {
     /*
      * Resolve hostname from connection address...
      */

      http_addr_t	addr;		/* Connection address */
      socklen_t		addrlen;	/* Length of address */

      addrlen = sizeof(addr);
      if (getsockname(http->fd, (struct sockaddr *)&addr, &addrlen))
      {
	DEBUG_printf(("4_httpTLSStart: Unable to get socket address: %s", strerror(errno)));
	hostname[0] = '\0';
      }
      else if (httpAddrLocalhost(&addr))
	hostname[0] = '\0';
      else
      {
	httpAddrLookup(&addr, hostname, sizeof(hostname));
        DEBUG_printf(("4_httpTLSStart: Resolved socket address to \"%s\".", hostname));
      }
    }

    if (isdigit(hostname[0] & 255) || hostname[0] == '[')
      hostname[0] = '\0';		/* Don't allow numeric addresses */

    if (hostname[0])
    {
      http_gnutls_make_path(crtfile, sizeof(crtfile), tls_keypath, hostname, "crt");
      http_gnutls_make_path(keyfile, sizeof(keyfile), tls_keypath, hostname, "key");

      have_creds = !access(crtfile, 0) && !access(keyfile, 0);
    }
    else if (tls_common_name)
    {
      http_gnutls_make_path(crtfile, sizeof(crtfile), tls_keypath, tls_common_name, "crt");
      http_gnutls_make_path(keyfile, sizeof(keyfile), tls_keypath, tls_common_name, "key");

      have_creds = !access(crtfile, 0) && !access(keyfile, 0);
    }

    if (!have_creds && tls_auto_create && (hostname[0] || tls_common_name))
    {
      DEBUG_printf(("4_httpTLSStart: Auto-create credentials for \"%s\".", hostname[0] ? hostname : tls_common_name));

      if (!cupsMakeServerCredentials(tls_keypath, hostname[0] ? hostname : tls_common_name, 0, NULL, time(NULL) + 365 * 86400))
      {
	DEBUG_puts("4_httpTLSStart: cupsMakeServerCredentials failed.");
	http->error  = errno = EINVAL;
	http->status = HTTP_STATUS_ERROR;
	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1);

	return (-1);
      }
    }

    DEBUG_printf(("4_httpTLSStart: Using certificate \"%s\" and private key \"%s\".", crtfile, keyfile));

    status = gnutls_certificate_set_x509_key_file(*credentials, crtfile, keyfile, GNUTLS_X509_FMT_PEM);
  }

  if (!status)
    status = gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials);

  if (status)
  {
    http->error  = EIO;
    http->status = HTTP_STATUS_ERROR;

    DEBUG_printf(("4_httpTLSStart: Unable to complete client/server setup: %s", gnutls_strerror(status)));
    _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0);

    gnutls_deinit(http->tls);
    gnutls_certificate_free_credentials(*credentials);
    free(credentials);
    http->tls = NULL;

    return (-1);
  }

  strlcpy(priority_string, "NORMAL", sizeof(priority_string));

  if (tls_options & _HTTP_TLS_DENY_TLS10)
    strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-TLS1.0:-VERS-SSL3.0", sizeof(priority_string));
  else if (tls_options & _HTTP_TLS_ALLOW_SSL3)
    strlcat(priority_string, ":+VERS-TLS-ALL", sizeof(priority_string));
  else
    strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-SSL3.0", sizeof(priority_string));

  if (!(tls_options & _HTTP_TLS_ALLOW_RC4))
    strlcat(priority_string, ":-ARCFOUR-128", sizeof(priority_string));

  if (!(tls_options & _HTTP_TLS_ALLOW_DH))
    strlcat(priority_string, ":!ANON-DH", sizeof(priority_string));

#ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT
  gnutls_priority_set_direct(http->tls, priority_string, NULL);

#else
  gnutls_priority_t priority;		/* Priority */

  gnutls_priority_init(&priority, priority_string, NULL);
  gnutls_priority_set(http->tls, priority);
  gnutls_priority_deinit(priority);
#endif /* HAVE_GNUTLS_PRIORITY_SET_DIRECT */

  gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr_t)http);
  gnutls_transport_set_pull_function(http->tls, http_gnutls_read);
#ifdef HAVE_GNUTLS_TRANSPORT_SET_PULL_TIMEOUT_FUNCTION
  gnutls_transport_set_pull_timeout_function(http->tls, (gnutls_pull_timeout_func)httpWait);
#endif /* HAVE_GNUTLS_TRANSPORT_SET_PULL_TIMEOUT_FUNCTION */
  gnutls_transport_set_push_function(http->tls, http_gnutls_write);

  while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS)
  {
    DEBUG_printf(("5_httpStartTLS: gnutls_handshake returned %d (%s)",
                  status, gnutls_strerror(status)));

    if (gnutls_error_is_fatal(status))
    {
      http->error  = EIO;
      http->status = HTTP_STATUS_ERROR;

      _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0);

      gnutls_deinit(http->tls);
      gnutls_certificate_free_credentials(*credentials);
      free(credentials);
      http->tls = NULL;

      return (-1);
    }
  }

  http->tls_credentials = credentials;

  return (0);
}
Exemple #12
0
static int setup_dtls_connection(struct worker_st *ws)
{
	int ret;
	gnutls_session_t session;
	gnutls_datum_t master =
	    { ws->master_secret, sizeof(ws->master_secret) };
	gnutls_datum_t sid = { ws->session_id, sizeof(ws->session_id) };

	if (ws->req.selected_ciphersuite == NULL) {
		oclog(ws, LOG_ERR, "no DTLS ciphersuite negotiated");
		return -1;
	}

	oclog(ws, LOG_DEBUG, "setting up DTLS connection");
	/* DTLS cookie verified.
	 * Initialize session.
	 */
	ret = gnutls_init(&session, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
	if (ret < 0) {
		oclog(ws, LOG_ERR, "could not initialize TLS session: %s",
		      gnutls_strerror(ret));
		return -1;
	}

	ret =
	    gnutls_priority_set_direct(session,
				       ws->req.
				       selected_ciphersuite->gnutls_name, NULL);
	if (ret < 0) {
		oclog(ws, LOG_ERR, "could not set TLS priority: %s",
		      gnutls_strerror(ret));
		goto fail;
	}

	ret = gnutls_session_set_premaster(session, GNUTLS_SERVER,
					   ws->req.
					   selected_ciphersuite->gnutls_version,
					   GNUTLS_KX_RSA,
					   ws->req.
					   selected_ciphersuite->gnutls_cipher,
					   ws->req.
					   selected_ciphersuite->gnutls_mac,
					   GNUTLS_COMP_NULL, &master, &sid);
	if (ret < 0) {
		oclog(ws, LOG_ERR, "could not set TLS premaster: %s",
		      gnutls_strerror(ret));
		goto fail;
	}

	ret =
	    gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
				   ws->creds->xcred);
	if (ret < 0) {
		oclog(ws, LOG_ERR, "could not set TLS credentials: %s",
		      gnutls_strerror(ret));
		goto fail;
	}

	gnutls_transport_set_push_function(session, dtls_push);
	gnutls_transport_set_pull_function(session, dtls_pull);
	gnutls_transport_set_pull_timeout_function(session, dtls_pull_timeout);
	gnutls_transport_set_ptr(session, &ws->dtls_tptr);

	gnutls_session_set_ptr(session, ws);
	gnutls_certificate_server_set_request(session, GNUTLS_CERT_IGNORE);

	gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);

	ws->udp_state = UP_HANDSHAKE;

	ws->dtls_session = session;

	return 0;
 fail:
	gnutls_deinit(session);
	return -1;
}
void dtls_try_with_key_mtu(const char *name, const char *client_prio, gnutls_kx_algorithm_t client_kx,
		gnutls_sign_algorithm_t server_sign_algo,
		gnutls_sign_algorithm_t client_sign_algo,
		const gnutls_datum_t *serv_cert,
		const gnutls_datum_t *serv_key,
		const gnutls_datum_t *client_cert,
		const gnutls_datum_t *client_key,
		unsigned cert_flags,
		unsigned smtu)
{
	int ret;
	char buffer[256];
	/* Server stuff. */
	gnutls_certificate_credentials_t serverx509cred;
	gnutls_anon_server_credentials_t s_anoncred;
	gnutls_dh_params_t dh_params;
	const gnutls_datum_t p3 =
	    { (unsigned char *) pkcs3, strlen(pkcs3) };
	gnutls_session_t server;
	int sret = GNUTLS_E_AGAIN;
	/* Client stuff. */
	gnutls_certificate_credentials_t clientx509cred;
	gnutls_anon_client_credentials_t c_anoncred;
	gnutls_session_t client;
	int cret = GNUTLS_E_AGAIN, version;

	/* General init. */
	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(6);

	reset_buffers();
	/* Init server */
	gnutls_anon_allocate_server_credentials(&s_anoncred);
	gnutls_certificate_allocate_credentials(&serverx509cred);

	ret = gnutls_certificate_set_x509_key_mem(serverx509cred,
					    serv_cert, serv_key,
					    GNUTLS_X509_FMT_PEM);
	if (ret < 0) {
		fail("Could not set key/cert: %s\n", gnutls_strerror(ret));
	}

	gnutls_dh_params_init(&dh_params);
	gnutls_dh_params_import_pkcs3(dh_params, &p3, GNUTLS_X509_FMT_PEM);
	gnutls_certificate_set_dh_params(serverx509cred, dh_params);
	gnutls_anon_set_server_dh_params(s_anoncred, dh_params);

	assert(gnutls_init(&server, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK)>=0);
	assert(gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
				      serverx509cred)>=0);
	assert(gnutls_credentials_set(server, GNUTLS_CRD_ANON, s_anoncred)>=0);

	assert(gnutls_priority_set_direct(server,
					  "NORMAL:+ANON-ECDH:+ANON-DH:+ECDHE-RSA:+DHE-RSA:+RSA:+ECDHE-ECDSA:+CURVE-X25519",
					   NULL)>=0);
	gnutls_transport_set_push_function(server, server_push);
	gnutls_transport_set_pull_function(server, server_pull);
	gnutls_transport_set_pull_timeout_function(server, server_pull_timeout_func);
	gnutls_transport_set_ptr(server, server);
	if (smtu)
		gnutls_dtls_set_mtu (server, smtu);

	/* Init client */

	ret = gnutls_certificate_allocate_credentials(&clientx509cred);
	if (ret < 0)
		exit(1);

	if (cert_flags == USE_CERT) {
		ret = gnutls_certificate_set_x509_key_mem(clientx509cred,
						    client_cert, client_key,
						    GNUTLS_X509_FMT_PEM);
		if (ret < 0) {
			fail("Could not set key/cert: %s\n", gnutls_strerror(ret));
		}
		gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUIRE);
	} else if (cert_flags == ASK_CERT) {
		gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST);
	}

#if 0
	ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM);
	if (ret < 0)
		exit(1);
#endif

	ret = gnutls_init(&client, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
	if (ret < 0)
		exit(1);

	assert(gnutls_anon_allocate_client_credentials(&c_anoncred)>=0);
	assert(gnutls_credentials_set(client, GNUTLS_CRD_ANON, c_anoncred)>=0);
	ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
				clientx509cred);
	if (ret < 0)
		exit(1);

	gnutls_transport_set_push_function(client, client_push);
	gnutls_transport_set_pull_function(client, client_pull);
	gnutls_transport_set_pull_timeout_function(client, client_pull_timeout_func);

	gnutls_transport_set_ptr(client, client);
	if (smtu)
		gnutls_dtls_set_mtu (client, smtu);

	ret = gnutls_priority_set_direct(client, client_prio, NULL);
	if (ret < 0) {
		exit(1);
	}
	success("negotiating %s\n", name);
	HANDSHAKE_DTLS(client, server);

	if (gnutls_kx_get(client) != client_kx) {
		fail("%s: got unexpected key exchange algorithm: %s (expected %s)\n", name, gnutls_kx_get_name(gnutls_kx_get(client)),
			gnutls_kx_get_name(client_kx));
		exit(1);
	}


	/* test signature algorithm match */
	version = gnutls_protocol_get_version(client);
	if (version >= GNUTLS_DTLS1_2) {
		ret = gnutls_sign_algorithm_get(server);
		if (ret != (int)server_sign_algo) {
			fail("%s: got unexpected server signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret));
			exit(1);
		}

		ret = gnutls_sign_algorithm_get_client(server);
		if (ret != (int)client_sign_algo) {
			fail("%s: got unexpected client signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret));
			exit(1);
		}

		ret = gnutls_sign_algorithm_get(client);
		if (ret != (int)server_sign_algo) {
			fail("%s: cl: got unexpected server signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret));
			exit(1);
		}

		ret = gnutls_sign_algorithm_get_client(client);
		if (ret != (int)client_sign_algo) {
			fail("%s: cl: got unexpected client signature algorithm: %d/%s\n", name, ret, gnutls_sign_get_name(ret));
			exit(1);
		}
	}

	gnutls_record_send(server, MSG, strlen(MSG));

	ret = gnutls_record_recv(client, buffer, sizeof(buffer));
	if (ret == 0) {
		fail("client: Peer has closed the TLS connection\n");
		exit(1);
	} else if (ret < 0) {
		fail("client: Error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	if (ret != strlen(MSG) || memcmp(MSG, buffer, ret) != 0) {
		fail("client: Error in data received. Expected %d, got %d\n", (int)strlen(MSG), ret);
		exit(1);
	}

	gnutls_bye(client, GNUTLS_SHUT_RDWR);
	gnutls_bye(server, GNUTLS_SHUT_RDWR);

	gnutls_deinit(client);
	gnutls_deinit(server);

	gnutls_certificate_free_credentials(serverx509cred);
	gnutls_certificate_free_credentials(clientx509cred);
	gnutls_anon_free_server_credentials(s_anoncred);
	gnutls_anon_free_client_credentials(c_anoncred);
	gnutls_dh_params_deinit(dh_params);
}
static void SetupNewSession(int index, NetworkAddress * networkAddress, bool client)
{
    DTLS_Session * session = &sessions[index];
    session->NetworkAddress = networkAddress;
    unsigned int flags;
#if GNUTLS_VERSION_MAJOR >= 3
    if (client)
        flags = GNUTLS_CLIENT | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK;
    else
        flags = GNUTLS_SERVER | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK;
#else
    if (client)
        flags = GNUTLS_CLIENT;
    else
        flags = GNUTLS_SERVER;
#endif
    if (gnutls_init(&session->Session, flags) == GNUTLS_E_SUCCESS)
    {
        gnutls_transport_set_pull_function(session->Session, DecryptCallBack);
        gnutls_transport_set_push_function(session->Session, SSLSendCallBack);
#if GNUTLS_VERSION_MAJOR >= 3
        gnutls_transport_set_pull_timeout_function(session->Session, ReceiveTimeout);
#endif
        gnutls_transport_set_ptr(session->Session, session);

        if (certificate || !pskIdentity)
        {
            if (_CertCredentials)
            {
                gnutls_credentials_set(session->Session, GNUTLS_CRD_CERTIFICATE, _CertCredentials);
            }
            else if (gnutls_certificate_allocate_credentials(&_CertCredentials) == GNUTLS_E_SUCCESS)
            {
                if (certificate)
                {
                    gnutls_datum_t certificateData;
                    certificateData.data = certificate;
                    certificateData.size = certificateLength;
                    int format = GNUTLS_X509_FMT_PEM;
                    if (certificateFormat == AwaCertificateFormat_ASN1)
                        format = GNUTLS_X509_FMT_DER;
    //                if (client)
    //                    gnutls_certificate_set_x509_trust_mem(session->Credentials, &certificateData, format);
    //                else
                    gnutls_certificate_set_x509_key_mem(_CertCredentials, &certificateData, &certificateData, format);
                }
#if GNUTLS_VERSION_MAJOR >= 3
                    gnutls_certificate_set_verify_function(_CertCredentials, CertificateVerify);
                    //gnutls_certificate_set_retrieve_function(xcred, cert_callback);
                    //gnutls_session_set_verify_cert(session->Session, NULL, GNUTLS_VERIFY_DISABLE_CA_SIGN);
#else
                    gnutls_certificate_set_verify_flags(_CertCredentials, GNUTLS_VERIFY_DISABLE_CA_SIGN);
#endif
                gnutls_credentials_set(session->Session, GNUTLS_CRD_CERTIFICATE, _CertCredentials);
            }
        }
        else if (pskIdentity)
        {
            if (client)
            {
                gnutls_psk_client_credentials_t credentials;
                if (gnutls_psk_allocate_client_credentials(&credentials) == GNUTLS_E_SUCCESS)
                {
                    if (gnutls_psk_set_client_credentials(credentials, pskIdentity, &pskKey, GNUTLS_PSK_KEY_RAW) == GNUTLS_E_SUCCESS)
                    {
                        gnutls_credentials_set(session->Session, GNUTLS_CRD_PSK, credentials);
                        session->Credentials = credentials;
                        session->CredentialType = CredentialType_ClientPSK;
                    }
                    else
                    {
                        gnutls_psk_set_client_credentials_function(credentials, PSKClientCallBack);
                        session->Credentials = credentials;
                        session->CredentialType = CredentialType_ClientPSK;
                    }
                }
            }
            else
            {
                gnutls_psk_server_credentials_t credentials;
                if (gnutls_psk_allocate_server_credentials(&credentials) == GNUTLS_E_SUCCESS)
                {
                    gnutls_psk_set_server_credentials_function(credentials, PSKCallBack);
                    gnutls_credentials_set(session->Session, GNUTLS_CRD_PSK, credentials);
                    session->Credentials = credentials;
                    session->CredentialType = CredentialType_ServerPSK;
                }
            }
        }


        gnutls_priority_set(session->Session, _PriorityCache);
        if (!client)
        {
            gnutls_certificate_server_set_request(session->Session, GNUTLS_CERT_REQUEST); // GNUTLS_CERT_IGNORE  Don't require Client Cert
        }

#if GNUTLS_VERSION_MAJOR >= 3
        gnutls_handshake_set_timeout(session->Session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
#endif
    }
}
Exemple #15
0
static void dtls_mtu_try(const char *name, const char *client_prio,
		unsigned link_mtu, unsigned tunnel_mtu)
{
	int ret;
	/* Server stuff. */
	gnutls_certificate_credentials_t serverx509cred;
	gnutls_session_t server;
	int sret = GNUTLS_E_AGAIN;
	/* Client stuff. */
	gnutls_certificate_credentials_t clientx509cred;
	gnutls_session_t client;
	int cret = GNUTLS_E_AGAIN;
	unsigned dmtu;
	unsigned i;

	/* General init. */
	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(6);

	reset_buffers();
	/* Init server */
	assert(gnutls_certificate_allocate_credentials(&serverx509cred)>=0);

	assert(gnutls_certificate_set_x509_key_mem(serverx509cred,
					    &server_cert, &server_key,
					    GNUTLS_X509_FMT_PEM) >= 0);

	assert(gnutls_init(&server, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK) >= 0);
	gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
				serverx509cred);

	assert(gnutls_priority_set_direct(server,
				   "NORMAL:+ANON-ECDH:+ANON-DH:+ECDHE-RSA:+DHE-RSA:+RSA:+ECDHE-ECDSA:+CURVE-X25519",
				   NULL) >= 0);
	gnutls_transport_set_push_function(server, server_push);
	gnutls_transport_set_pull_function(server, server_pull);
	gnutls_transport_set_pull_timeout_function(server, server_pull_timeout_func);
	gnutls_transport_set_ptr(server, server);

	/* Init client */

	ret = gnutls_init(&client, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
	if (ret < 0)
		exit(1);

	assert(gnutls_certificate_allocate_credentials(&clientx509cred) >= 0);
	assert(gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM)>=0);

	assert(gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
				clientx509cred) >= 0);

	gnutls_transport_set_push_function(client, client_push);
	gnutls_transport_set_pull_function(client, client_pull);
	gnutls_transport_set_pull_timeout_function(client, client_pull_timeout_func);
	
	gnutls_transport_set_ptr(client, client);

	ret = gnutls_priority_set_direct(client, client_prio, NULL);
	if (ret < 0) {
		fail("%s: error in priority setting\n", name);
		exit(1);
	}
	success("negotiating %s\n", name);
	HANDSHAKE_DTLS(client, server);

	gnutls_dtls_set_mtu(client, link_mtu);
	dmtu = gnutls_dtls_get_data_mtu(client);
	if (dmtu != tunnel_mtu) {
		fail("%s: Calculated MTU (%d) does not match expected (%d)\n", name, dmtu, tunnel_mtu);
	}

	{
		char msg[dmtu+1];
		memset(msg, 1, sizeof(msg));
		ret = gnutls_record_send(client, msg, dmtu+1);
		if (ret != (int)GNUTLS_E_LARGE_PACKET) {
			myfail("could send larger packet than MTU (%d), ret: %d\n", dmtu, ret);
		}

		ret = gnutls_record_send(client, msg, dmtu);
		if (ret != (int)dmtu) {
			myfail("could not send %d bytes (sent %d)\n", dmtu, ret);
		}

		memset(msg, 2, dmtu);
		ret = gnutls_record_recv(server, msg, dmtu);
		if (ret != (int)dmtu) {
			myfail("could not receive %d bytes (received %d)\n", dmtu, ret);
		}

		for (i=0;i<dmtu;i++)
			assert(msg[i]==1);
	}

	gnutls_bye(client, GNUTLS_SHUT_RDWR);
	gnutls_bye(server, GNUTLS_SHUT_RDWR);

	gnutls_deinit(client);
	gnutls_deinit(server);

	gnutls_certificate_free_credentials(serverx509cred);
	gnutls_certificate_free_credentials(clientx509cred);
}