Beispiel #1
0
int dtls_gnutls_read(struct conn * conn, uint8_t *buffer, int len)
{
	uint8_t seq[8];
	
	struct dtls_gnutls_data * d = conn->dtls_data;
	int rc = gnutls_record_recv_seq(d->session,buffer,len,seq);

	if (rc==0) {
		errno = ECONNRESET;
		return -1;
	}

	if ( rc == GNUTLS_E_AGAIN ){
		errno = EAGAIN;
		return -1;
	}

	if ( rc < 0 ){
		cw_log(LOG_ERR, "DTLS - read error: %s", gnutls_strerror(rc));
		conn->dtls_error=1;
		errno=ECONNRESET;
		return -1;
	}

	return rc;
}
Beispiel #2
0
static void client(int fd)
{
	gnutls_session_t session;
	int ret;
	char buffer[MAX_BUF + 1];
	gnutls_anon_client_credentials_t anoncred;
	unsigned char seq[8];
	uint32_t useq;

	memset(buffer, 0, sizeof(buffer));

	/* Need to enable anonymous KX specifically. */

/*    gnutls_global_set_audit_log_function (tls_audit_log_func); */
	global_init();

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

	gnutls_anon_allocate_client_credentials(&anoncred);

	/* Initialize TLS session
	 */
	gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM);
	gnutls_dtls_set_timeouts(session, 50 * 1000, 600 * 1000);
	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_int(session, 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");
	}

	gnutls_record_send(session, buffer, 1);

	if (debug)
		success("client: DTLS version is: %s\n",
			gnutls_protocol_get_name
			(gnutls_protocol_get_version(session)));
	do {
		ret =
		    gnutls_record_recv_seq(session, buffer, sizeof(buffer),
					   seq);

		if (ret > 0) {
			useq =
			    seq[7] | (seq[6] << 8) | (seq[5] << 16) |
			    (seq[4] << 24);

			if (debug)
				success("received %u\n", (unsigned int)useq);

			if (recv_msg_seq[current] == -1) {
				fail("received message sequence differs\n");
				terminate();
			}
			if (((uint32_t)recv_msg_seq[current]) != useq) {
				fail("received message sequence differs (current: %u, got: %u, expected: %u)\n",
				     (unsigned)current, (unsigned)useq, (unsigned)recv_msg_seq[current]);
				terminate();
			}

			current++;
		}
	}
	while ((ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED
		|| ret > 0));

	gnutls_bye(session, GNUTLS_SHUT_WR);

	close(fd);

	gnutls_deinit(session);

	gnutls_anon_free_client_credentials(anoncred);

	gnutls_global_deinit();
}
Beispiel #3
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);
}
Beispiel #4
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;

}