Beginning of TLS workings.
This commit is contained in:
parent
b2bdb522b3
commit
519faa535b
174
TLS.cpp
Normal file
174
TLS.cpp
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
#include "TLS.h"
|
||||||
|
#include "EPoll.h"
|
||||||
|
#include "TCPSession.h"
|
||||||
|
#include "Exception.h"
|
||||||
|
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
static pthread_mutex_t *lockarray;
|
||||||
|
|
||||||
|
static unsigned long thread_id(void) {
|
||||||
|
return ((unsigned long) pthread_self());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lock_callback(int mode, int type, const char *file, int line) {
|
||||||
|
if(mode & CRYPTO_LOCK)
|
||||||
|
pthread_mutex_lock(&(lockarray[type]));
|
||||||
|
else
|
||||||
|
pthread_mutex_unlock(&(lockarray[type]));
|
||||||
|
}
|
||||||
|
|
||||||
|
TLS::TLS() {
|
||||||
|
|
||||||
|
SSL_library_init();
|
||||||
|
SSL_load_error_strings();
|
||||||
|
|
||||||
|
lockarray = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
|
||||||
|
for(int i = 0; i < CRYPTO_num_locks(); ++i)
|
||||||
|
pthread_mutex_init(&(lockarray[i]), NULL);
|
||||||
|
|
||||||
|
CRYPTO_set_id_callback((unsigned long (*)())thread_id);
|
||||||
|
CRYPTO_set_locking_callback((void (*)(int, int, const char *, int))lock_callback);
|
||||||
|
|
||||||
|
SSLeay_add_ssl_algorithms();
|
||||||
|
RAND_load_file("/dev/hwrng", 1024);
|
||||||
|
|
||||||
|
if(!(ctx = SSL_CTX_new(SSLv23_server_method())))
|
||||||
|
throw coreutils::Exception("Error while setting server method SSLv23.");
|
||||||
|
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||||
|
SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
|
||||||
|
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
|
||||||
|
// SSL_CTX_set_generate_session_id(ctx, generate_session_id);
|
||||||
|
SSL_CTX_set_cipher_list(ctx, "ECDH-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA");
|
||||||
|
if(SSL_CTX_use_certificate_file(ctx, sip_cert, SSL_FILETYPE_PEM) <= 0)
|
||||||
|
throw coreutils::Exception("Error looking up certificate.");
|
||||||
|
if(SSL_CTX_use_PrivateKey_file(ctx, sip_key, SSL_FILETYPE_PEM) < 0)
|
||||||
|
throw coreutils::Exception("Error with private key.");
|
||||||
|
if(SSL_CTX_check_private_key(ctx) != 1)
|
||||||
|
throw coreutils::Exception("Private key does not match certificate.");
|
||||||
|
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
||||||
|
SSL_CTX_set_verify_depth(ctx, 1);
|
||||||
|
if(!SSL_CTX_load_verify_locations(ctx, sip_cacert, NULL))
|
||||||
|
throw coreutils::Exception("Cannot verify locations.");
|
||||||
|
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(sip_cacert));
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_1) << "Server key authenticated.";
|
||||||
|
}
|
||||||
|
|
||||||
|
TLS::~TLS() {}
|
||||||
|
|
||||||
|
static int generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len) {
|
||||||
|
char *session_id_prefix = (char *)"BARANT";
|
||||||
|
unsigned int count = 0;
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "Generating unique session id.";
|
||||||
|
do {
|
||||||
|
RAND_bytes(id, *id_len);
|
||||||
|
memcpy(id, session_id_prefix, (strlen(session_id_prefix) < *id_len));
|
||||||
|
} while(SSL_has_matching_session_id(ssl, id, *id_len) && (++count < 10));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handshake_complete(const SSL *ssl, int where, int ret) {
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "==>" << SSL_state_string_long(ssl) << "<==" << ret;
|
||||||
|
if(where & SSL_CB_HANDSHAKE_DONE) {
|
||||||
|
X509 *ssl_client_cert = SSL_get_peer_certificate(ssl);
|
||||||
|
if(!ssl_client_cert)
|
||||||
|
throw std::string("Unable to get peer certificate.");
|
||||||
|
X509_free(ssl_client_cert);
|
||||||
|
if(SSL_get_verify_result(ssl) != X509_V_OK)
|
||||||
|
throw std::string("Certificate verification failed.");
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "Certificate verified successfully.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "No client certificate.";
|
||||||
|
}
|
||||||
|
|
||||||
|
TLSSession::TLSSession(EPoll &ePoll, TCPServer &server) : TCPSession(ePoll, server) {}
|
||||||
|
|
||||||
|
void TLSSession::onRegister() {
|
||||||
|
initialized = true;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "TLS socket initializing on socket " << getDescriptor() << "...";
|
||||||
|
|
||||||
|
fcntl(getDescriptor(), F_SETFL, fcntl(getDescriptor(), F_GETFL, 0) | O_NONBLOCK);
|
||||||
|
|
||||||
|
ssl = SSL_new(static_cast<TLSServer &>(server).ctx);
|
||||||
|
// if(ssl <= 0)
|
||||||
|
// throw std::string("Error creating new TLS socket.");
|
||||||
|
|
||||||
|
SSL_set_info_callback(ssl, handshake_complete);
|
||||||
|
|
||||||
|
if((ret = SSL_set_fd(ssl, getDescriptor())) == 0)
|
||||||
|
throw std::string("Error setting TLS socket descriptor.");
|
||||||
|
|
||||||
|
// if(!SSL_set_generate_session_id(ssl, generate_session_id))
|
||||||
|
// throw std::string("Error setting session identifier callback.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TLSSession::onRegistered() {
|
||||||
|
|
||||||
|
switch (SSL_get_error(ssl, SSL_accept(ssl))) {
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_SSL on ssl_accept. errno=" << errno;
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_WANT_READ on ssl_accept.";
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_WANT_WRITE on ssl_accept.";
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_SYSCALL on ssl_accept. errno=" << errno;
|
||||||
|
shutdown();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "Unknown ERROR on ssl_accept.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TLSSession::~TLSSession() {}
|
||||||
|
|
||||||
|
void TLSSession::protocol(coreutils::ZString &data) {}
|
||||||
|
|
||||||
|
void TLSSession::receiveData(coreutils::ZString &buffer) {
|
||||||
|
|
||||||
|
int len;
|
||||||
|
// int error = -1;
|
||||||
|
//
|
||||||
|
std::cout << "receiveData TLS" << std::endl;
|
||||||
|
|
||||||
|
if((len = ::SSL_read(ssl, buffer.getData(), buffer.getLength())) >= 0) {
|
||||||
|
std::cout << "receiveData TLS...len=" << len << ":" << buffer << std::endl;
|
||||||
|
onDataReceived(buffer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (SSL_get_error(ssl, len)) {
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_SSL on ssl_read. error=" << errno;
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_WANT_READ on ssl_read.";
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_WANT_WRITE on ssl_read.";
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "ERROR_SYSCALL on ssl_read. errno=" << errno;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
coreutils::Log(coreutils::LOG_DEBUG_3) << "Unknown ERROR on ssl_read.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TLSSession::output(std::stringstream &out) {
|
||||||
|
out << "|" << ipAddress.getClientAddressAndPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
65
TLS.h
Normal file
65
TLS.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#ifndef TLSServerSocket_h__
|
||||||
|
#define TLSServerSocket_h__
|
||||||
|
|
||||||
|
#include "Socket.h"
|
||||||
|
#include "TCPServer.h"
|
||||||
|
#include "Command.h"
|
||||||
|
#include "TCPSession.h"
|
||||||
|
#include "IPAddress.h"
|
||||||
|
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
///
|
||||||
|
/// TLS
|
||||||
|
///
|
||||||
|
/// This object provides the support methods to handle TLS on the server core and
|
||||||
|
/// session environment.
|
||||||
|
///
|
||||||
|
|
||||||
|
class TLS {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TLS();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The destructor for this object.
|
||||||
|
///
|
||||||
|
|
||||||
|
~TLS();
|
||||||
|
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
char *sip_cacert = (char *)"../testkeys/certs/pbxca.crt";
|
||||||
|
char *sip_cert = (char *)"../testkeys/certs/pbxserver.crt";
|
||||||
|
char *sip_key = (char *)"../testkeys/certs/pbxserver.key";
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The output method is called by a socket session (Session) and
|
||||||
|
/// will output the detail information for the client socket. When extending
|
||||||
|
/// TLSSocket or Session you can override the method to add attributes
|
||||||
|
/// to the list.
|
||||||
|
///
|
||||||
|
|
||||||
|
virtual void output(std::stringstream &out);
|
||||||
|
virtual void protocol(coreutils::ZString &data) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void receiveData(coreutils::ZString &buffer) override;
|
||||||
|
void onRegister();
|
||||||
|
void onRegistered();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool initialized = false;
|
||||||
|
SSL *ssl;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user