1 #include "recordHandler.h"
5 #include <openssl/ssl.h>
9 #include "opensslBIO.h"
11 class RecordHandlerSession {
14 uint32_t lastCommandCount;
16 std::shared_ptr<TBSCertificate> tbs;
17 std::shared_ptr<SignedCertificate> result;
21 std::shared_ptr<OpensslBIOWrapper> io;
22 DefaultRecordHandler* parent;
23 std::shared_ptr<Signer> signer;
25 RecordHandlerSession( DefaultRecordHandler* parent, std::shared_ptr<Signer> signer, std::shared_ptr<SSL_CTX> ctx, BIO* output ) :
26 tbs( new TBSCertificate() ) {
27 this->parent = parent;
28 this->signer = signer;
30 ssl = SSL_new( ctx.get() );
31 BIO* bio = BIO_new( BIO_f_ssl() );
32 SSL_set_accept_state( ssl );
33 SSL_set_bio( ssl, output, output );
34 BIO_set_ssl( bio, ssl, BIO_NOCLOSE );
35 io = std::shared_ptr<OpensslBIOWrapper>( new OpensslBIOWrapper( bio ) );
38 void respondCommand( RecordHeader::SignerResult res, std::string payload ) {
40 rh.command = ( uint16_t ) res;
42 rh.command_count = 0; // TODO i++
43 rh.totalLength = payload.size();
44 sendCommand( rh, payload, io );
48 std::vector<char> buffer( 2048, 0 );
49 int res = io->read( buffer.data(), buffer.capacity() );
56 std::string content( buffer.data(), res );
60 std::string payload = parseCommand( head, content );
61 execute( head, payload );
62 } catch( const char* msg ) {
63 std::cout << msg << std::endl;
69 void execute( RecordHeader& head, std::string data ) {
70 if( head.totalLength != head.payloadLength || head.offset != 0 ) {
71 throw "Error, chunking not supported yet";
74 switch( ( RecordHeader::SignerCommand ) head.command ) {
75 case RecordHeader::SignerCommand::SET_CSR: // setCSR
76 tbs->csr_content = data;
77 tbs->csr_type = "CSR";
78 std::cout << "CSR read" << std::endl;
81 case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE:
82 tbs->md = "sha256"; // TODO use content ;-)
85 case RecordHeader::SignerCommand::SET_PROFILE:
90 case RecordHeader::SignerCommand::ADD_SAN: {
91 size_t pos = data.find( "," );
93 if( pos == std::string::npos ) {
95 std::shared_ptr<SAN> san( new SAN() );
96 san->type = data.substr( 0, pos );
97 san->content = data.substr( pos + 1 );
98 tbs->SANs.push_back( san );
103 case RecordHeader::SignerCommand::ADD_AVA: {
104 size_t pos = data.find( "," );
106 if( pos == std::string::npos ) {
109 std::shared_ptr<AVA> ava( new AVA() );
110 ava->name = data.substr( 0, pos );
111 ava->value = data.substr( pos + 1 );
112 tbs->AVAs.push_back( ava );
117 case RecordHeader::SignerCommand::ADD_PROOF_LINE:
120 case RecordHeader::SignerCommand::SIGN:
121 result = signer->sign( tbs );
122 std::cout << "res: " << result->certificate << std::endl;
123 result->log = "I am a dummy log.\nI signed that thing ;-) \n";
124 respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log );
127 case RecordHeader::SignerCommand::LOG_SAVED:
129 respondCommand( RecordHeader::SignerResult::CERTIFICATE, result->certificate );
135 throw "Unimplemented";
140 DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr<Signer> signer, BIO* bio ) :
143 this->signer = signer;
145 ctx = std::shared_ptr<SSL_CTX>( SSL_CTX_new( TLSv1_method() ), SSL_CTX_free );
146 SSL_CTX_use_certificate_file( ctx.get(), "testdata/server.crt", SSL_FILETYPE_PEM );
147 SSL_CTX_use_PrivateKey_file( ctx.get(), "testdata/server.key", SSL_FILETYPE_PEM );
152 void DefaultRecordHandler::reset() {
153 currentSession = std::shared_ptr<RecordHandlerSession>();
156 void DefaultRecordHandler::handle() {
157 if( !currentSession ) {
158 currentSession = std::shared_ptr<RecordHandlerSession>( new RecordHandlerSession( this, signer, ctx, bio ) );
161 currentSession->work();