Strange as it seems but you can make non-SSL connections using the OpenSSL libraries. The following code is a brief example. I like it because it appears to simplify (arguably) the rather more involved Berkley sockets. It still lets you get at the socket if you want to mangle it yourself. But ultimately its kind of handy to have a library that does SSL and plain transfers without too much of a code change.
Here is a simple example of using the OpenSSL BIO interface to retrieve a root web page. Naturally most of the exception handling is not included so don’t going using it for production purposes as is. Not that it’d be a lot of use as anything other than an exaple of the OpenSSL BIO API usage.
Have fun.
/*
* File: main.cpp
*
* Licence: GPL2
*/
/* Standard headers */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* OpenSSL headers */
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/**
* Initialise OpenSSL
*/
void init_openssl() {
SSL_load_error_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
}
/**
* Close a BIO connection gracefully
*/
int close_connection(BIO* bio) {
int r = 0;
r = BIO_free(bio);
if (r == 0) {
/* Error unable to free BIO */
}
return r;
}
/**
* Connect to a host using an unencrypted stream
*/
BIO* connect_unencrypted(char* host_and_port) {
BIO* bio = NULL;
/* Create a new connection */
bio = BIO_new_connect(host_and_port);
if (bio == NULL) {
printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));
printf("%s\n", ERR_error_string(ERR_get_error(), NULL));
return NULL;
}
/* Verify successful connection */
if (BIO_do_connect(bio) != 1) {
printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));
printf("%s\n", ERR_error_string(ERR_get_error(), NULL));
close_connection(bio);
return NULL;
}
return bio;
}
/**
* Read a from a stream and handle restarts if nessecary
*/
ssize_t read_from_stream(BIO* bio, char* buffer, ssize_t length) {
ssize_t r = -1;
while (r < 0) {
r = BIO_read(bio, buffer, length);
if (r == 0) {
/* Handle closed connection */
continue;
} else if (r < 0) {
if (!BIO_should_retry(bio)) {
/* Handle failed read here */
printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));
printf("%s\n", ERR_error_string(ERR_get_error(), NULL));
continue;
}
/* It would be prudent to check the reason for the retry and handle
* it appropriately here */
}
};
return r;
}
/**
* Write to a stream and handle restarts if nessecary
*/
int write_to_stream(BIO* bio, char* buffer, ssize_t length) {
ssize_t r = -1;
while (r < 0) {
r = BIO_write(bio, buffer, length);
if (r <= 0) {
if (!BIO_should_retry(bio)) {
/* Handle failed write here */
printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));
printf("%s\n", ERR_error_string(ERR_get_error(), NULL));
continue;
}
/* It would be prudent to check the reason for the retry and handle
* it appropriately here */
}
}
return r;
}
/**
* Main SSL demonstration code entry point
*/
int main(int argc, char** argv) {
BIO * bio;
char *addr = "GET / HTTP/1.1\r\nHost: www.home.com\r\n\r\n";
char buffer[4096];
buffer[0] = 0;
init_openssl();
if ((bio = connect_unencrypted(argv[1])) == NULL)
return (EXIT_FAILURE);
write_to_stream(bio, addr, strlen(addr));
read_from_stream(bio, buffer, 4096);
printf("%s", buffer);
if (close_connection(bio) == 0)
return (EXIT_FAILURE);
return (EXIT_SUCCESS);
}