From c7f2cead9ad48debc5fd9eaca974beeef1d4dedf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Thu, 18 Dec 2014 16:45:23 +0100 Subject: [PATCH] add: simple, signer-side record handling --- src/database.h | 4 ++ src/recordHandler.cpp | 162 ++++++++++++++++++++++++++++++++++++++++++ src/recordHandler.h | 30 ++++++++ 3 files changed, 196 insertions(+) create mode 100644 src/recordHandler.cpp create mode 100644 src/recordHandler.h diff --git a/src/database.h b/src/database.h index b438187..081e925 100644 --- a/src/database.h +++ b/src/database.h @@ -30,6 +30,9 @@ struct AVA { struct TBSCertificate { std::string md; std::string profile; + /** + * CSR path + */ std::string csr; std::string csr_type; std::string csr_content; @@ -46,6 +49,7 @@ struct SignedCertificate { std::string pkHash; std::string certHash; std::string crt_name; + std::string log; }; class JobProvider { diff --git a/src/recordHandler.cpp b/src/recordHandler.cpp new file mode 100644 index 0000000..c9949a4 --- /dev/null +++ b/src/recordHandler.cpp @@ -0,0 +1,162 @@ +#include "recordHandler.h" + +#include + +#include + +#include "database.h" +#include "record.h" +#include "opensslBIO.h" + +class RecordHandlerSession { +public: + uint32_t sessid; + uint32_t lastCommandCount; + + std::shared_ptr tbs; + std::shared_ptr result; + + SSL* ssl; + + std::shared_ptr io; + DefaultRecordHandler* parent; + std::shared_ptr signer; + + RecordHandlerSession( DefaultRecordHandler* parent, std::shared_ptr signer, std::shared_ptr ctx, BIO* output ) : + tbs( new TBSCertificate() ) { + this->parent = parent; + this->signer = signer; + + ssl = SSL_new( ctx.get() ); + BIO* bio = BIO_new( BIO_f_ssl() ); + SSL_set_accept_state( ssl ); + SSL_set_bio( ssl, output, output ); + BIO_set_ssl( bio, ssl, BIO_NOCLOSE ); + io = std::shared_ptr( new OpensslBIOWrapper( bio ) ); + } + + void respondCommand( RecordHeader::SignerResult res, std::string payload ) { + RecordHeader rh; + rh.command = ( uint16_t ) res; + rh.flags = 0; + rh.command_count = 0; // TODO i++ + rh.totalLength = payload.size(); + sendCommand( rh, payload, io ); + } + + void work() { + std::vector buffer( 2048, 0 ); + int res = io->read( buffer.data(), buffer.capacity() ); + + if( res <= 0 ) { + parent->reset(); + return; + } + + std::string content( buffer.data(), res ); + + try { + RecordHeader head; + std::string payload = parseCommand( head, content ); + execute( head, payload ); + } catch( const char* msg ) { + std::cout << msg << std::endl; + parent->reset(); + return; + } + } + + void execute( RecordHeader& head, std::string data ) { + if( head.totalLength != head.payloadLength || head.offset != 0 ) { + throw "Error, chunking not supported yet"; + } + + switch( ( RecordHeader::SignerCommand ) head.command ) { + case RecordHeader::SignerCommand::SET_CSR: // setCSR + tbs->csr_content = data; + tbs->csr_type = "CSR"; + std::cout << "CSR read" << std::endl; + break; + + case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE: + tbs->md = "sha256"; // TODO use content ;-) + break; + + case RecordHeader::SignerCommand::SET_PROFILE: + // TODO + tbs->profile = data; + break; + + case RecordHeader::SignerCommand::ADD_SAN: { + size_t pos = data.find( "," ); + + if( pos == std::string::npos ) { + } else { + std::shared_ptr san( new SAN() ); + san->type = data.substr( 0, pos ); + san->content = data.substr( pos + 1 ); + tbs->SANs.push_back( san ); + } + } + break; + + case RecordHeader::SignerCommand::ADD_AVA: { + size_t pos = data.find( "," ); + + if( pos == std::string::npos ) { + // error + } else { + std::shared_ptr ava( new AVA() ); + ava->name = data.substr( 0, pos ); + ava->value = data.substr( pos + 1 ); + tbs->AVAs.push_back( ava ); + } + } + break; + + case RecordHeader::SignerCommand::ADD_PROOF_LINE: + break; + + case RecordHeader::SignerCommand::SIGN: + result = signer->sign( tbs ); + std::cout << "res: " << result->certificate << std::endl; + result->log = "I am a dummy log.\nI signed that thing ;-) \n"; + respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log ); + break; + + case RecordHeader::SignerCommand::LOG_SAVED: + if( result ) { + respondCommand( RecordHeader::SignerResult::CERTIFICATE, result->certificate ); + } + + break; + + default: + throw "Unimplemented"; + } + } +}; + +DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr signer, BIO* bio ) : + currentSession() { + + this->signer = signer; + + ctx = std::shared_ptr( SSL_CTX_new( TLSv1_method() ), SSL_CTX_free ); + SSL_CTX_use_certificate_file( ctx.get(), "testdata/server.crt", SSL_FILETYPE_PEM ); + SSL_CTX_use_PrivateKey_file( ctx.get(), "testdata/server.key", SSL_FILETYPE_PEM ); + + this->bio = bio; +} + +void DefaultRecordHandler::reset() { + currentSession = std::shared_ptr(); +} + +void DefaultRecordHandler::handle() { + if( !currentSession ) { + currentSession = std::shared_ptr( new RecordHandlerSession( this, signer, ctx, bio ) ); + } + + currentSession->work(); +} diff --git a/src/recordHandler.h b/src/recordHandler.h new file mode 100644 index 0000000..5212272 --- /dev/null +++ b/src/recordHandler.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +#include +#include + +#include "record.h" +#include "signer.h" + +class RecordHandler { +public: + virtual void handle( std::string data ) = 0; + virtual void reset() = 0; +}; + +class RecordHandlerSession; + +class DefaultRecordHandler { +private: + BIO* bio; + std::shared_ptr ctx; + std::shared_ptr signer; + std::shared_ptr currentSession; +public: + DefaultRecordHandler( std::shared_ptr signer, BIO* bio ); + void handle(); + void reset(); +}; -- 2.39.5