File gnutls_client.c of Package 3net


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <ddebug/debuglib.h>


#define MAX_BUF 1024
#define CAFILE "/etc/ssl/certs/ca-certificates.crt"
#define MSG "Test message from "

char *host = "google.fi";
int port = 443;
int use_tls = 1;

int sockfd = -1;
gnutls_session_t session;
gnutls_certificate_credentials_t xcred;


int tls_setup(int sockfd)
{
	int err = 0;
	const char *err_str;

	gnutls_global_init();

	/* Initialize TLS session */
	gnutls_init(&session, GNUTLS_CLIENT);
	//gnutls_session_set_ptr(session, (void *)mydata); // userdata

	/* Use default priorities */
	err = gnutls_priority_set_direct(session, "NORMAL", &err_str);
	if (err < 0)
	{
		if (err == GNUTLS_E_INVALID_REQUEST)
		{
		  ERROR_MSG("syntax error at: %s\n", err_str);
		}
		OUT(-1);
	}
	err = 0;

	gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)sockfd);

	/* X509 stuff */
	gnutls_certificate_allocate_credentials(&xcred);
	/* sets the trusted cas file */
	//gnutls_certificate_set_x509_trust_file(xcred, CAFILE, GNUTLS_X509_FMT_PEM);
	/* put the x509 credentials to the current session */
	gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);

	/* Perform the TLS handshake
	*/
	do
	{
		err = gnutls_handshake(session);
	}
	while (err < 0 && gnutls_error_is_fatal(err) == 0);
	IF_ERR(err < 0, -1, "handshake failed, reason: %s", gnutls_strerror(err));
	DEBUG_MSG("handshake was completed");
	err = 0;

out_err:
	return err;
}


int send_str(const char *msg)
{
	if (use_tls)
	{
		gnutls_record_send(session, msg, strlen(msg) + 1);
	}
	else
	{
		write(sockfd, msg, strlen(msg) + 1);
	}
}


ssize_t recv_str(char *buffer)
{
	ssize_t err = 0;

	if (use_tls)
	{
		err = gnutls_record_recv(session, buffer, MAX_BUF);
		IF_ERR(err < 1, -1, "read failed");
	}
	else
	{
		err = read(sockfd, buffer, MAX_BUF);
		IF_ERR(err < 1, -1, "read failed");
	}

out_err:
	return err;
}


int main(int argc, char *argv[])
{
	int err = 0;
	char buffer[MAX_BUF + 1];

	if (argc > 1) use_tls = atoi(argv[1]);

	/* connect to the peer */
	sockfd = tcp_connect();

	if (use_tls)
	{
		/* setup ecnryption */
		IF_ERR(tls_setup(sockfd), -1, "TLS setup failed");
	}

	/* send some data */
	send_str("Test message from client!");

	/* receive some data */
	memset(buffer, 0, sizeof(buffer));
	ssize_t n = recv_str(buffer);
	IF_ERR(n < 1, -1, "receive failed");

	DEBUG_MSG("received %d bytes", n);
	DEBUG_MSG("%s", buffer);

	if (use_tls) gnutls_bye(session, GNUTLS_SHUT_RDWR);

out_err:
	close(sockfd);
	if (use_tls)
	{
		gnutls_deinit(session);
		gnutls_certificate_free_credentials(xcred);
		gnutls_global_deinit();
	}
	return 0;
}


/*
 * Connects to the peer and returns a socket
 * descriptor.
 */
int tcp_connect(void)
{
	int err, fd;
	struct sockaddr_in sa;

	/* connects to server */
	fd = socket(AF_INET, SOCK_STREAM, 0);
	IF_ERR(fd < 0, -1, "socket() failed");

	memset(&sa, '\0', sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_port = htons(port);
	inet_pton(AF_INET, host, &sa.sin_addr);

	err = connect(fd, (struct sockaddr *)&sa, sizeof(sa));
	IF_ERR(err < 0, -1, "connect() failed");

out_err:
	if (err) fd = -1;
	return fd;
}

openSUSE Build Service is sponsored by