Example #1
0
ssize_t
socket_recv(const socket_st * socket, void *buffer, int buffer_size)
{
	int ret;

	if (socket->secure) {
		do {
			ret =
			    gnutls_record_recv(socket->session, buffer,
					       buffer_size);
			if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED)
				gnutls_heartbeat_pong(socket->session, 0);
		}
		while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN
		       || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED);

	} else
		do {
			ret = recv(socket->fd, buffer, buffer_size, 0);
		}
		while (ret == -1 && errno == EINTR);

	return ret;
}
Example #2
0
static void
client (int fd, int server_init)
{
    gnutls_session_t session;
    int ret, ret2;
    char buffer[MAX_BUF + 1];
    gnutls_anon_client_credentials_t anoncred;
    /* Need to enable anonymous KX specifically. */

    gnutls_global_init ();

    if (debug)
      {
          gnutls_global_set_log_function (client_log_func);
          gnutls_global_set_log_level (4711);
      }

    gnutls_anon_allocate_client_credentials (&anoncred);

    /* Initialize TLS session
     */
    gnutls_init (&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM);
    gnutls_heartbeat_enable (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND);
    gnutls_dtls_set_mtu (session, 1500);

    /* Use default priorities */
    gnutls_priority_set_direct (session,
                                "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
                                NULL);

    /* put the anonymous credentials to the current session
     */
    gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);

    gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd);

    /* Perform the TLS handshake
     */
    do
      {
          ret = gnutls_handshake (session);
      }
    while (ret < 0 && gnutls_error_is_fatal (ret) == 0);

    if (ret < 0)
      {
          fail ("client: Handshake failed\n");
          gnutls_perror (ret);
          exit (1);
      }
    else
      {
          if (debug)
              success ("client: Handshake was completed\n");
      }

    if (debug)
        success ("client: DTLS version is: %s\n",
                 gnutls_protocol_get_name (gnutls_protocol_get_version
                                           (session)));

    if (!server_init)
      {
          do
            {
                ret =
                    gnutls_record_recv (session, buffer, sizeof (buffer));

                if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED)
                  {
                      if (debug)
                          success ("Ping received. Replying with pong.\n");
                      ret2 = gnutls_heartbeat_pong (session, 0);
                      if (ret2 < 0)
                        {
                            fail ("pong: %s\n", gnutls_strerror (ret));
                            terminate ();
                        }
                  }
            }
          while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED
                 || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED);
      }
    else
      {
          do
            {
                ret =
                    gnutls_heartbeat_ping (session, 256, 5,
                                           GNUTLS_HEARTBEAT_WAIT);

                if (debug)
                  success ("Ping sent.\n");
            }
          while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

          if (ret < 0)
            {
                fail ("ping: %s\n", gnutls_strerror (ret));
                terminate ();
            }
      }

    gnutls_bye (session, GNUTLS_SHUT_WR);

    close (fd);

    gnutls_deinit (session);

    gnutls_anon_free_client_credentials (anoncred);

    gnutls_global_deinit ();
}
Example #3
0
static void
server (int fd, int server_init)
{
    int ret, ret2;
    char buffer[MAX_BUF + 1];
    gnutls_session_t session;
    gnutls_anon_server_credentials_t anoncred;
    /* this must be called once in the program
     */
    gnutls_global_init ();

    if (debug)
      {
          gnutls_global_set_log_function (server_log_func);
          gnutls_global_set_log_level (4711);
      }

    gnutls_anon_allocate_server_credentials (&anoncred);

    session = initialize_tls_session ();
    gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);

    gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd);

    do
      {
          ret = gnutls_handshake (session);
      }
    while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
    if (ret < 0)
      {
          close (fd);
          gnutls_deinit (session);
          fail ("server: Handshake has failed (%s)\n\n",
                gnutls_strerror (ret));
          terminate ();
      }
    if (debug)
        success ("server: Handshake was completed\n");

    if (debug)
        success ("server: TLS version is: %s\n",
                 gnutls_protocol_get_name (gnutls_protocol_get_version
                                           (session)));

    /* see the Getting peer's information example */
    /* print_info(session); */

    if (server_init)
      {
          do
            {
                ret =
                    gnutls_record_recv (session, buffer, sizeof (buffer));

                if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED)
                  {
                      if (debug)
                          success ("Ping received. Replying with pong.\n");
                      ret2 = gnutls_heartbeat_pong (session, 0);
                      if (ret2 < 0)
                        {
                            fail ("pong: %s\n", gnutls_strerror (ret));
                            terminate ();
                        }
                  }
            }
          while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED
                 || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED);
      }
    else
      {
          do
            {
                ret =
                    gnutls_heartbeat_ping (session, 256, 5,
                                           GNUTLS_HEARTBEAT_WAIT);

                if (debug)
                  success ("Ping sent.\n");
            }
          while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

          if (ret < 0)
            {
                fail ("ping: %s\n", gnutls_strerror (ret));
                terminate ();
            }
      }

    /* do not wait for the peer to close the connection.
     */
    gnutls_bye (session, GNUTLS_SHUT_WR);

    close (fd);
    gnutls_deinit (session);

    gnutls_anon_free_server_credentials (anoncred);

    gnutls_global_deinit ();

    if (debug)
        success ("server: finished\n");
}
Example #4
0
void udp_server(const char *name, int port, int mtu)
{
	int sock, ret;
	struct sockaddr_storage 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,
						      cli_addr_size,
						      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 = cli_addr_size;

				printf
				    ("Sending hello verify request to %s\n",
				     human_addr((struct sockaddr *)
						&cli_addr,
						cli_addr_size, buffer,
						sizeof(buffer)));
				gnutls_dtls_cookie_send(&cookie_key,
							&cli_addr,
							cli_addr_size,
							&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 = &cli_addr;
		priv.cli_addr_size = cli_addr_size;

		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);
				if (ret ==
				    GNUTLS_E_HEARTBEAT_PING_RECEIVED)
					gnutls_heartbeat_pong(session, 0);
			}
			while (ret == GNUTLS_E_INTERRUPTED
			       || ret == GNUTLS_E_AGAIN
			       || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED);

			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);
}