#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <openssl/ssl.h>
#include <openssl/err.h>

int main(int argc, char *argv[])
{
    SSL_CTX *ctx;
    SSL *ssl;
    struct sockaddr_in server_addr;
    int sock_fd;

    if (argc != 3) {
	fprintf(stderr, "USAGE: %s <client_cert> <client_key>\n", argv[0]);
	exit(__LINE__);
    }

    SSL_load_error_strings();
    SSL_library_init();

    if ((ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
    }

    if (SSL_CTX_use_certificate_chain_file(ctx, argv[1]) != 1) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
    }

    if (SSL_CTX_use_PrivateKey_file(ctx, argv[2], SSL_FILETYPE_PEM) != 1) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
    }

    if (SSL_CTX_check_private_key(ctx) != 1) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
    }

    memset(&server_addr, 0, sizeof server_addr);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(44443);
    server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
	perror("socket");
	exit(__LINE__);
    }

    if (connect(sock_fd, (struct sockaddr *)&server_addr,
		sizeof server_addr) == -1) {
	perror("connect");
	exit(__LINE__);
    }

    puts("Connected.  Starting SSL handshake.");

    if ((ssl = SSL_new(ctx)) == NULL) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
    }

    if (SSL_set_fd(ssl, sock_fd) == 0) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
    }

    if (SSL_connect(ssl) != 1) {
	ERR_print_errors_fp(stderr);
	exit(__LINE__);
    }

    puts("SSL handshake successful.  Shutting down.");

    return 0;
}
