1 #include "io/recordHandler.h"
7 #include <unordered_map>
9 #include <openssl/ssl.h>
12 #include "io/record.h"
13 #include "io/opensslBIO.h"
14 #include "io/slipBio.h"
16 #include "db/database.h"
17 #include "crypto/remoteSigner.h"
18 #include "crypto/sslUtil.h"
19 #include "crypto/simpleOpensslSigner.h"
21 #include "log/logger.hpp"
23 extern std::vector<Profile> profiles;
24 extern std::unordered_map<std::string, std::shared_ptr<CAConfig>> CAs;
26 class RecordHandlerSession {
29 uint32_t lastCommandCount = 0;
31 std::shared_ptr<TBSCertificate> tbs;
32 std::shared_ptr<SignedCertificate> result;
34 std::shared_ptr<SSL> ssl;
36 std::shared_ptr<OpensslBIOWrapper> io;
37 DefaultRecordHandler *parent;
38 std::shared_ptr<Signer> signer;
40 std::unique_ptr<std::ofstream> logFile;
41 //std::stringstream sessionlog;
42 std::vector<std::string> serials;
43 logger::logger_set logger;
46 RecordHandlerSession( DefaultRecordHandler *parent, std::shared_ptr<Signer> signer, std::shared_ptr<SSL_CTX> ctx, std::shared_ptr<BIO> output ) :
47 tbs( std::make_shared<TBSCertificate>() ),
48 logFile( openLogfile( "logs/log_" + timestamp() ) ),
49 logger{ std::cout, *logFile } {
50 this->parent = parent;
51 this->signer = signer;
53 ssl = std::shared_ptr<SSL>( SSL_new( ctx.get() ), SSL_free );
54 auto freeBIO = [output]( BIO * p ) {
57 std::shared_ptr<BIO> bio( BIO_new( BIO_f_ssl() ), freeBIO );
58 SSL_set_accept_state( ssl.get() );
59 SSL_set_bio( ssl.get(), output.get(), output.get() );
60 BIO_set_ssl( bio.get(), ssl.get(), BIO_NOCLOSE );
61 io = std::make_shared<OpensslBIOWrapper>( bio );
64 void respondCommand( RecordHeader::SignerResult res, std::string payload ) {
66 rh.command = static_cast<uint16_t>( res );
68 rh.command_count = 0; // TODO i++
69 sendCommand( rh, payload, io );
75 std::string all = parseCommandChunked( head, io );
76 execute( static_cast<RecordHeader::SignerCommand>( head.command ), all );
77 } catch( const std::exception& msg ) {
78 logger::error( "ERROR: ", msg.what() );
84 void execute( RecordHeader::SignerCommand command, std::string data ) {
86 case RecordHeader::SignerCommand::SET_CSR:
87 tbs->csr_content = data;
88 tbs->csr_type = "CSR";
89 logger::note( "INFO: CSR read:\n", tbs->csr_content );
92 case RecordHeader::SignerCommand::SET_SPKAC:
93 tbs->csr_content = data;
94 tbs->csr_type = "SPKAC";
95 logger::note( "INFO: SPKAC read:\n", tbs->csr_content );
98 case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE:
102 case RecordHeader::SignerCommand::SET_PROFILE:
107 case RecordHeader::SignerCommand::SET_WISH_FROM:
108 tbs->wishFrom = data;
111 case RecordHeader::SignerCommand::SET_WISH_TO:
115 case RecordHeader::SignerCommand::ADD_SAN: {
116 size_t pos = data.find( "," );
118 if( pos == std::string::npos ) {
121 auto san = std::make_shared<SAN>();
122 san->type = data.substr( 0, pos );
123 san->content = data.substr( pos + 1 );
124 tbs->SANs.push_back( san );
129 case RecordHeader::SignerCommand::ADD_AVA: {
130 size_t pos = data.find( "," );
132 if( pos == std::string::npos ) {
135 auto ava = std::make_shared<AVA>();
136 ava->name = data.substr( 0, pos );
137 ava->value = data.substr( pos + 1 );
138 tbs->AVAs.push_back( ava );
143 case RecordHeader::SignerCommand::ADD_PROOF_LINE:
146 case RecordHeader::SignerCommand::SIGN:
147 result = signer->sign( tbs );
148 logger::note( "INFO: signlog:\n", result->log );
149 logger::note( "INFO: res:\n", result->certificate );
150 respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log );
153 case RecordHeader::SignerCommand::LOG_SAVED:
155 respondCommand( RecordHeader::SignerResult::SIGNING_CA, result->ca_name );
156 respondCommand( RecordHeader::SignerResult::CERTIFICATE, result->certificate );
159 logger::note( "Shutting down SSL" );
161 if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
162 logger::warn( "ERROR: SSL shutdown failed." );
165 io->ctrl( BIO_CTRL_FLUSH, 0, NULL );
166 logger::note( "Shutted down SSL" );
168 parent->reset(); // Connection ended
172 case RecordHeader::SignerCommand::ADD_SERIAL:
173 serials.push_back( data );
176 case RecordHeader::SignerCommand::REVOKE: {
177 logger::note( "Revoking: ", data );
178 std::string ca = data;
179 auto reqCA = CAs.at( ca );
180 logger::note( "CA found in recordHandler" );
181 std::shared_ptr<CRL> crl;
183 std::tie( crl, date ) = signer->revoke( reqCA, serials );
185 respondCommand( RecordHeader::SignerResult::REVOKED, date + crl->getSignature() );
189 case RecordHeader::SignerCommand::GET_FULL_CRL: {
190 logger::note( "Requesting full CRL: ", data );
191 auto ca = CAs.at( data );
192 CRL c( ca->path + "/ca.crl" );
193 respondCommand( RecordHeader::SignerResult::FULL_CRL, c.toString() );
195 logger::note( "Shutting down SSL" );
197 if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
198 logger::error( "ERROR: SSL shutdown failed." );
201 io->ctrl( BIO_CTRL_FLUSH, 0, NULL );
202 logger::note( "Shutted down SSL" );
204 parent->reset(); // Connection ended
209 throw std::runtime_error( "Unimplemented" );
214 DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr<Signer> signer, std::shared_ptr<BIO> bio ) :
215 bio( bio ), ctx( generateSSLContext( true ) ), signer( signer ), currentSession() {
218 void DefaultRecordHandler::reset() {
219 currentSession = std::shared_ptr<RecordHandlerSession>();
222 void DefaultRecordHandler::handle() {
223 if( !currentSession ) {
224 ( void ) BIO_reset( bio.get() );
225 logger::note( "New session allocated." );
226 currentSession = std::make_shared<RecordHandlerSession>( this, signer, ctx, bio );
230 currentSession->work();
231 } catch( eof_exception e ) {