139

I wrote simple C programs, which are using sockets ('client' and 'server'). (UNIX/Linux usage)

The server side simply creates a socket:

sockfd = socket(AF_INET, SOCK_STREAM, 0);

And then binds it to sockaddr:

bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

And listens (and accepts and reads):

listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
read(newsockfd,buffer,255);

The client creates the socket, and then writes to it.

Now, I want to convert this simple connection into an SSL connection, in the plainest, most idyllic, neatest and quickest way.

I've tried to add OpenSSL to my project, but I can't find an easy way to implement what I want.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David Mape
  • 1,407
  • 2
  • 10
  • 3
  • If you're looking for "a secure connection" rather than SSL in particular, you could look at something like http://proxychains.sourceforge.net/ which resides outside your application, and set that up to send traffic over an SSH connection. As far as in-application SSL, OpenSSL is pretty easy if you understand how SSL/TLS is supposed to work. If you want an alternative, try yaSSL or gnuTLS . – Borealid Oct 08 '11 at 17:23
  • 3
    Define 'easy way'. OpenSSl is the standard for C programmers. If you're having difficulty with it you should ask about that. – user207421 Apr 25 '13 at 01:57
  • Check this one [An Introduction to OpenSSL Programming (Par t I)](https://www.cs.cmu.edu/~srini/15-441/F02/Projects/lab01/reference/part1.pdf). Part II is too advanced and difficult for me. But part2 is worth taking a look. – Rick Nov 21 '19 at 14:18
  • Also check [Secure programming with the OpenSSL API](https://developer.ibm.com/tutorials/l-openssl/#). But I just heard opinions about how bad Openssl is and other alternatives worth a try. – Rick Nov 21 '19 at 15:08
  • 1
    Another option is to use an external SSL wrapper tool such as `stunnel`, the `stunnel4` package is in Debian-based distros and it's easy to use. There are some limitations compared to adding proper SSL support in your server, but it can be good for a quick solution. I like stunnel because it seems to fit with the UNIX software tools approach. – Sam Watkins Jul 05 '20 at 05:06

5 Answers5

185

There are several steps when using OpenSSL. You must have an SSL certificate made which can contain the certificate with the private key be sure to specify the exact location of the certificate (this example has it in the root). There are a lot of good tutorials out there.

Some includes:

#include <openssl/applink.c>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

You will need to initialize OpenSSL:

void InitializeSSL()
{
    SSL_load_error_strings();
    SSL_library_init();
    OpenSSL_add_all_algorithms();
}

void DestroySSL()
{
    ERR_free_strings();
    EVP_cleanup();
}

void ShutdownSSL()
{
    SSL_shutdown(cSSL);
    SSL_free(cSSL);
}

Now for the bulk of the functionality. You may want to add a while loop on connections.

int sockfd, newsockfd;
SSL_CTX *sslctx;
SSL *cSSL;

InitializeSSL();
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd< 0)
{
    //Log and Error
    return;
}
struct sockaddr_in saiServerAddress;
bzero((char *) &saiServerAddress, sizeof(saiServerAddress));
saiServerAddress.sin_family = AF_INET;
saiServerAddress.sin_addr.s_addr = serv_addr;
saiServerAddress.sin_port = htons(aPortNumber);

bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

sslctx = SSL_CTX_new( SSLv23_server_method());
SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE);
int use_cert = SSL_CTX_use_certificate_file(sslctx, "/serverCertificate.pem" , SSL_FILETYPE_PEM);

int use_prv = SSL_CTX_use_PrivateKey_file(sslctx, "/serverCertificate.pem", SSL_FILETYPE_PEM);

cSSL = SSL_new(sslctx);
SSL_set_fd(cSSL, newsockfd );
//Here is the SSL Accept portion.  Now all reads and writes must use SSL
ssl_err = SSL_accept(cSSL);
if(ssl_err <= 0)
{
    //Error occurred, log and close down ssl
    ShutdownSSL();
}

You are then able read or write using:

SSL_read(cSSL, (char *)charBuffer, nBytesToRead);
SSL_write(cSSL, "Hi :3\n", 6);

Update The SSL_CTX_new should be called with the TLS method that best fits your needs in order to support the newer versions of security, instead of SSLv23_server_method(). See: OpenSSL SSL_CTX_new description

TLS_method(), TLS_server_method(), TLS_client_method(). These are the general-purpose version-flexible SSL/TLS methods. The actual protocol version used will be negotiated to the highest version mutually supported by the client and the server. The supported protocols are SSLv3, TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3.

CaptainBli
  • 4,121
  • 4
  • 39
  • 58
  • 12
    not so "simple" as I thought, but finally (thanks God!) I see some code. Is this cross-platform or just for unix/unix-like systems? – juliomalegria May 01 '13 at 23:55
  • No problem. I just recently used code similar to this in production. But the links will be the most help. – CaptainBli May 02 '13 at 01:47
  • 3
    I have used similar code on multiple platforms: arm, linux and windows. – CaptainBli Sep 15 '13 at 16:11
  • 2
    Last `if` is wrong though. It should be `if (ssl_err <= 0) {` only then it's an error. `SSL_accept()` returns `1` on success, `0` on "controlled failure" and `-1` on "fatal failure". See man page. – Jite Aug 25 '14 at 12:02
  • 2
    Also, DH ciphers will not work if `SSL_CTX_set_tmp_dh[_callback]()` is not called. Just discovered the hard way that aNULL ciphers won't work without it, producing alert number 40. – Roman Dmitrienko Jul 19 '15 at 15:37
  • 2
    Why are you including a .c file? – Iharob Al Asimi Jul 25 '15 at 16:46
  • 1
    How would I modify the example above to enforce TLS v1.1 or v1.2 and fail if not supported? – Cloud Apr 05 '16 at 16:10
  • 6
    @DevNull The `SSLv23_server_method()` states that the server understands SSLv2 and v3 and is now deprecated. To support TLS 1.1 and 1.2 replace that method with `TLS_server_method()`. [source](https://www.openssl.org/docs/manmaster/ssl/SSL_CTX_new.html) – ezPaint Jun 23 '16 at 15:21
  • Hi , could you mention the steps to generate the various certificate and key files used in this example ? – Haswell Oct 02 '16 at 08:49
  • 1
    I receive this error: `error: ‘ssl’ undeclared`. What am I supposed to do about this? There are literally no other sources for establishing a connection using OpenSSL! – Larrimus Jun 12 '17 at 05:34
  • @Larrimus Sounds like you don't have OpenSSL in your include path. Though just stating you received this error doesn't help us help you very much. Need a little more detail. – CaptainBli Jun 12 '17 at 17:30
  • No, I use three of your includes (applink.c doesn't exist on my system apparently), but ssl is an undefined variable according to gcc. Though, I don't know that this will work for me as I'm trying to download an image over an HTTPS connection, a QR code from google to be specific. This is the implementation I was trying to use until I realized I'm a moron: https://stackoverflow.com/a/42627602/4988264 – Larrimus Jun 12 '17 at 19:36
  • 1
    That may be the variable "ssl" used in ShutdownSSL(). I guess it should be "cSSL" (hand over to function), but i haven't tested it yet. – Tanix Jan 25 '18 at 12:11
  • `#include ` looks quite wrong. It must be some special windows-only gunk. – President James K. Polk May 16 '18 at 18:05
  • instead of `struct sockaddr_in saiServerAddress; bzero((char *) &saiServerAddress, sizeof(saiServerAddress));` , why don't you just do `struct sockaddr_in saiServerAddress = {};` ? that will make the compiler zero out all members you didn't specify in `{}` , which is all of them – hanshenrik Jul 22 '18 at 17:30
  • @ezPaint your source link is gone – LtWorf Dec 07 '18 at 21:35
  • 1
    @LtWorf The link should now be: https://www.openssl.org/docs/man1.1.0/ssl/SSLv23_server_method.html which takes you to the same place as: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_new.html – CaptainBli Dec 13 '18 at 17:07
  • 1
    Regarding the Windows specific [`applink.c`](https://www.openssl.org/docs/manmaster/man3/OPENSSL_Applink.html) - It's probably not a good idea to `#include` it, but to do what the doc says: "_... compile provided module with compiler of their choice and link it into the target application_" - If you happen to include it in more than one TU, there will probably be trouble. – Ted Lyngmo Aug 31 '21 at 20:06
22

OpenSSL is quite difficult. It's easy to accidentally throw away all your security by not doing negotiation exactly right. (Heck, I've been personally bitten by a bug where curl wasn't reading the OpenSSL alerts exactly right, and couldn't talk to some sites.)

If you really want quick and simple, put stud in front of your program an call it a day. Having SSL in a different process won't slow you down: http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html

BraveNewCurrency
  • 12,654
  • 2
  • 42
  • 50
11

For others like me:

There was once an example in the SSL source in the directory demos/ssl/ with example code in C++. Now it's available only via the history: https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

You probably will have to find a working version, I originally posted this answer at Nov 6 2015. And I had to edit the source -- not much.

Certificates: .pem in demos/certs/apps/: https://github.com/openssl/openssl/tree/master/demos/certs/apps

Captain Man
  • 6,997
  • 6
  • 48
  • 74
18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
0

Like you've seen it's pretty hairy. But the "easy" part is, after you've set up your SSL/TLS session with OpenSSL, the pattern you follow to read/write on a socket for HTTPS is the same as the one you follow for HTTP.

The difference is you use the SSL_read/SSL_write functions, instead of the read/write functions. The SSL_read/SSL_write functions take an SSL pointer as their first argument instead of a file descriptor.

Anyways, here is a full working OpenSSL example for a Unix environment, with compile/run instructions, APT dependencies, and references. It's just some more working code for you to cut your teeth on.

On successful compilation, you will see one warning about a deprecated OpenSSL function.

On successful run, you will see example.com's TLS certificate subject printed to standard output, followed by the HTML content of example.com.

https://github.com/angstyloop/c-web/blob/main/openssl-fetch-example.c

Tested on Ubuntu 22.04.

angstyloop
  • 117
  • 6
-3

Here my example ssl socket server threads (multiple connection) https://github.com/breakermind/CppLinux/blob/master/QtSslServerThreads/breakermindsslserver.cpp

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <iostream>

#include <breakermindsslserver.h>

using namespace std;

int main(int argc, char *argv[])
{
    BreakermindSslServer boom;
    boom.Start(123,"/home/user/c++/qt/BreakermindServer/certificate.crt", "/home/user/c++/qt/BreakermindServer/private.key");
    return 0;
}
Fanex
  • 1