Post by R.WieserI will "most likely" also try to find example code using just those SSL_*
calls. But currently first had/have to find out which TLS versions v1.0.2
all supports (read: if I can access all websites I can reach with my FF v52
browser).
From what I've dug up, 0.9.8 does not support TLS 1.2, while 1.0.1 probably
does.
Post by R.WieserBut ... do you perhaps have a link to example code using only SSL_* calls ?
I could use it.
Here's the code I use to start and stop SSL on an existing connection.
From here you can use SSL_read() and SSL_write(), which are pretty
straightforward.
/*----------------------------------------------------------------------
Negotiate an SSL connection.
If "server" is TRUE, call SSL_accept() to
wait for an SSL handshake from the client.
If "server" is FALSE, call SSL_connect() to
initiate an SSL handshake with the server.
"certfile" is the name of a file containing certificates
(or NULL if no certificates are provided).
If errors occur, build an error string and
return a pointer to it; otherwise return NULL.
----------------------------------------------------------------------*/
#ifdef PROTOTYPE
char *socksslstart(struct socktag *sc, BOOL server, char *certfile)
#else
char *socksslstart(sc, server, certfile)
struct socktag *sc;
BOOL server;
char *certfile;
#endif
{
static char errmsg[MAXLEN];
X509 *cert;
X509_NAME *certname;
FILE *fp;
extern char *logfilename;
long templong;
char *s;
int i;
if(sc == NULL) {
strcpy(errmsg, "socksslstart: NULL argument");
return(errmsg);
}
sc->socksslcontext = NULL;
sc->socksslhandle = NULL;
#ifndef _INC__MINGW_H
/* Register the available ciphers and digests. */
SSL_library_init();
/* Register the error strings for libcrypto & libssl. */
SSL_load_error_strings();
#endif
#ifdef DELETE_THIS
OPENSSL_config(NULL);
#endif
/* Create a new context. */
if(server)
sc->socksslcontext = SSL_CTX_new(SSLv23_server_method());
else
sc->socksslcontext = SSL_CTX_new(SSLv23_client_method());
if(sc->socksslcontext == NULL) {
strcpy(errmsg, "SSL_CTX_new() failed: ");
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
return(errmsg);
}
#ifdef NEW_STUFF
/* Disable older methods if desired. Setting all of the options below
(they can be ORed together) will disable anything less than TLS v1.2. */
SSL_CTX_set_options(sc->socksslcontext, SSL_OP_NO_SSLv2);
SSL_CTX_set_options(sc->socksslcontext, SSL_OP_NO_SSLv3);
SSL_CTX_set_options(sc->socksslcontext, SSL_OP_NO_COMPRESSION);
SSL_CTX_set_options(sc->socksslcontext, SSL_OP_NO_TLSv1);
SSL_CTX_set_options(sc->socksslcontext, SSL_OP_NO_TLSv1_1);
#endif
/* Process certificates. */
if(certfile != NULL) {
/* Set default locations for trusted CA certificates.
"certfile" is the name of a file containing one or more CA certificates
in PEM format. The optional third argument names a path containing
PEM-format files, each of which contains one CA certificate. */
if(!SSL_CTX_load_verify_locations(sc->socksslcontext,certfile,NULL)) {
strcpy(errmsg, "SSL_CTX_load_verify_locations() failed: ");
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
socksslstop(sc);
return(errmsg);
}
/* If we're a server, send the list of CAs to the client. */
if(server) {
SSL_CTX_set_client_CA_list(
sc->socksslcontext, SSL_load_client_CA_file(certfile));
}
/* Load the certificates in the file SSL_SERVER_CRT (if server)
or the file SSL_CLIENT_CRT (if client) into the SSL context. */
if(!SSL_CTX_use_certificate_file(sc->socksslcontext,
certfile, SSL_FILETYPE_PEM)) {
strcpy(errmsg, "SSL_CTX_use_certificate_file() failed: ");
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
socksslstop(sc);
return(errmsg);
}
/* Load the private keys into the SSL context. */
if(!SSL_CTX_use_PrivateKey_file(sc->socksslcontext,
certfile, SSL_FILETYPE_PEM)) {
strcpy(errmsg, "SSL_CTX_use_PrivateKey_file() failed: ");
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
socksslstop(sc);
return(errmsg);
}
/* Check the consistency of a private key with the
corresponding certificate loaded into the SSL context. */
if(!SSL_CTX_check_private_key(sc->socksslcontext)) {
strcpy(errmsg, "SSL_CTX_check_private_key() failed: ");
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
socksslstop(sc);
return(errmsg);
}
SSL_CTX_set_mode(sc->socksslcontext, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_verify(sc->socksslcontext,
SSL_VERIFY_PEER | (server & SSL_VERIFY_FAIL_IF_NO_PEER_CERT), NULL);
SSL_CTX_set_verify_depth(sc->socksslcontext, 1);
}
/* Create an SSL structure for the connection. */
sc->socksslhandle = SSL_new(sc->socksslcontext);
if(sc->socksslhandle == NULL) {
strcpy(errmsg, "SSL_new() failed: ");
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
socksslstop(sc);
return(errmsg);
}
/* Connect the SSL structure to our connection. */
if(!SSL_set_fd(sc->socksslhandle, sc->sockfd)) {
strcpy(errmsg, "SSL_set_fd() failed: ");
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
socksslstop(sc);
return(errmsg);
}
/* If we're the server, wait for an SSL handshake from the client. */
if(server) {
if(SSL_accept(sc->socksslhandle) != 1) {
strcpy(errmsg, "SSL_accept() failed: ");
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
socksslstop(sc);
return(errmsg);
}
/* If we're the client, initiate an SSL handshake with the server. */
} else {
if(SSL_connect(sc->socksslhandle) != 1) {
strcpy(errmsg, "SSL_connect() failed: ");
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
socksslstop(sc);
return(errmsg);
}
}
/* Get the remote certificate into an X509 structure. */
if(!server && (certfile != NULL)) {
cert = SSL_get1_peer_certificate(sc->socksslhandle);
if(cert == NULL) {
sprintf(errmsg,
"socksslstart(%s): SSL_get1_peer_certificate() returned NULL: ",
sc->sockname);
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
writetolog(errmsg, FALSE, -9);
}
if(cert != NULL) {
templong = SSL_get_verify_result(sc->socksslhandle);
if(templong != X509_V_OK) {
sprintf(errmsg,
"socksslstart(%s): SSL_get_verify_result() failed: %ld",
sc->sockname, templong);
s = ERR_error_string(ERR_get_error(), NULL);
i = sizeof(errmsg) - strlen(errmsg) - 1;
strncpy(errmsg + strlen(errmsg), s, i);
errmsg[sizeof(errmsg)-1] = '\0';
writetolog(errmsg, FALSE, -9);
} else {
fp = fopen(logfilename, "a");
if(fp != NULL) {
#ifdef DELETE_THIS
certname = X509_NAME_new();
#endif
certname = X509_get_subject_name(cert);
X509_NAME_print_ex_fp(fp, certname, 4,
XN_FLAG_MULTILINE & ~ASN1_STRFLGS_ESC_MSB);
certname = X509_get_issuer_name(cert);
X509_NAME_print_ex_fp(fp, certname, 4,
XN_FLAG_MULTILINE & ~ASN1_STRFLGS_ESC_MSB);
fclose(fp);
}
}
X509_free(cert);
}
}
/* If all went well, we've successfully set up an SSL connection. */
return(NULL);
}
/*----------------------------------------------------------------------
Stop an SSL connection.
----------------------------------------------------------------------*/
#ifdef PROTOTYPE
void socksslstop(struct socktag *sc)
#else
void socksslstop(sc) struct socktag *sc;
#endif
{
if(sc == NULL)
return; /* Connection is missing! */
if(sc->socksslhandle != NULL) {
SSL_shutdown(sc->socksslhandle);
SSL_free(sc->socksslhandle);
sc->socksslhandle = NULL;
}
if(sc->socksslcontext != NULL) {
SSL_CTX_free(sc->socksslcontext);
sc->socksslcontext = NULL;
}
}
--
/~\ Charlie Gibbs | We'll go down in history as the
\ / <***@kltpzyxm.invalid> | first society that wouldn't save
X I'm really at ac.dekanfrus | itself because it wasn't cost-
/ \ if you read it the right way. | effective. -- Kurt Vonnegut