Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A C++ Client That Sends Data Over TLS Using OpenSSL
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <resolv.h>
#include <netdb.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
//Not sure what headers are needed or not
//This code (theoretically) writes "Hello World, 123" to a socket over a secure TLS connection
//compiled with g++ -Wall -o client.out client.cpp -L/usr/lib -lssl -lcrypto
//Based off of: https://www.cs.utah.edu/~swalton/listings/articles/ssl_client.c
//Some of the code was taken from this post: https://stackoverflow.com/questions/52727565/client-in-c-use-gethostbyname-or-getaddrinfo
const int ERROR_STATUS = -1;
SSL_CTX *InitSSL_CTX(void)
{
const SSL_METHOD *method = TLS_client_method(); /* Create new client-method instance */
SSL_CTX *ctx = SSL_CTX_new(method);
if (ctx == nullptr)
{
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
return ctx;
}
int OpenConnection(const char *hostname, const char *port)
{
struct hostent *host;
if ((host = gethostbyname(hostname)) == nullptr)
{
perror(hostname);
exit(EXIT_FAILURE);
}
struct addrinfo hints = {0}, *addrs;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
const int status = getaddrinfo(hostname, port, &hints, &addrs);
if (status != 0)
{
fprintf(stderr, "%s: %s\n", hostname, gai_strerror(status));
exit(EXIT_FAILURE);
}
int sfd, err;
for (struct addrinfo *addr = addrs; addr != nullptr; addr = addr->ai_next)
{
sfd = socket(addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
if (sfd == ERROR_STATUS)
{
err = errno;
continue;
}
if (connect(sfd, addr->ai_addr, addr->ai_addrlen) == 0)
{
break;
}
err = errno;
sfd = ERROR_STATUS;
close(sfd);
}
freeaddrinfo(addrs);
if (sfd == ERROR_STATUS)
{
fprintf(stderr, "%s: %s\n", hostname, strerror(err));
exit(EXIT_FAILURE);
}
return sfd;
}
void DisplayCerts(SSL *ssl)
{
X509 *cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
if (cert != nullptr)
{
printf("Server certificates:\n");
char *line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
delete line;
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
delete line;
X509_free(cert);
}
else
{
printf("Info: No client certificates configured.\n");
}
}
int main(int argc, char const *argv[])
{
SSL_CTX *ctx = InitSSL_CTX();
SSL *ssl = SSL_new(ctx);
if (ssl == nullptr)
{
fprintf(stderr, "SSL_new() failed\n");
exit(EXIT_FAILURE);
}
//Host is hardcoded to localhost for testing purposes
const int sfd = OpenConnection("127.0.0.1", argv[1]);
SSL_set_fd(ssl, sfd);
const int status = SSL_connect(ssl);
if (status != 1)
{
SSL_get_error(ssl, status);
ERR_print_errors_fp(stderr); //High probability this doesn't do anything
fprintf(stderr, "SSL_connect failed with SSL_get_error code %d\n", status);
exit(EXIT_FAILURE);
}
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
DisplayCerts(ssl);
const char *chars = "Hello World, 123!";
SSL_write(ssl, chars, strlen(chars));
SSL_free(ssl);
close(sfd);
SSL_CTX_free(ctx);
return 0;
}
@talregev
Copy link

talregev commented Jun 18, 2021

Can you implement the server? that server will support tls and non tls, and the client send the message first.

@jkrause1
Copy link

jkrause1 commented Mar 10, 2022

At which point does this client check for the validity of the certificate that the server send?
It is my understanding, that the client checks the certificate for trustworthiness as part of the Handshake, but where does it actually happen?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment