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