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;
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::shared_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 ) :
48 lastCommandCount( 0 ),
49 tbs( new TBSCertificate() ),
50 logFile(openLogfile( std::string( "logs/log_" ) + std::to_string( [](){
52 if( time( &c_time ) == -1 ) {
53 throw "Error while fetching time?";
58 logger::log_target(std::cout, logger::level::note),
59 //logger::log_target(sessionlog, logger::level::note),
60 logger::log_target(*logFile, logger::level::note)
61 }, logger::auto_register::on) {
62 this->parent = parent;
63 this->signer = signer;
65 ssl = std::shared_ptr<SSL>( SSL_new( ctx.get() ), SSL_free );
66 std::shared_ptr<BIO> bio(
67 BIO_new( BIO_f_ssl() ),
71 SSL_set_accept_state( ssl.get() );
72 SSL_set_bio( ssl.get(), output.get(), output.get() );
73 BIO_set_ssl( bio.get(), ssl.get(), BIO_NOCLOSE );
74 io = std::shared_ptr<OpensslBIOWrapper>( new OpensslBIOWrapper( bio ) );
77 void respondCommand( RecordHeader::SignerResult res, std::string payload ) {
79 rh.command = ( uint16_t ) res;
81 rh.command_count = 0; // TODO i++
82 rh.totalLength = payload.size();
83 sendCommand( rh, payload, io );
87 std::vector<char> buffer( 2048, 0 );
88 int res = io->read( buffer.data(), buffer.capacity() );
91 logger::error( "Stream error, resetting SSL" );
96 std::string content( buffer.data(), res );
100 std::string payload = parseCommand( head, content );
101 execute( head, payload );
102 } catch( const char* msg ) {
103 logger::error( "ERROR: ", msg );
109 void execute( RecordHeader& head, std::string data ) {
110 if( head.totalLength != head.payloadLength || head.offset != 0 ) {
111 throw "Error, chunking not supported yet";
114 switch( ( RecordHeader::SignerCommand ) head.command ) {
115 case RecordHeader::SignerCommand::SET_CSR:
116 tbs->csr_content = data;
117 tbs->csr_type = "CSR";
118 logger::note( "INFO: CSR read:\n", tbs->csr_content );
121 case RecordHeader::SignerCommand::SET_SPKAC:
122 tbs->csr_content = data;
123 tbs->csr_type = "SPKAC";
124 logger::note( "INFO: SPKAC read:\n", tbs->csr_content );
127 case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE:
131 case RecordHeader::SignerCommand::SET_PROFILE:
136 case RecordHeader::SignerCommand::SET_WISH_FROM:
137 tbs->wishFrom = data;
140 case RecordHeader::SignerCommand::SET_WISH_TO:
144 case RecordHeader::SignerCommand::ADD_SAN:
146 size_t pos = data.find( "," );
148 if( pos == std::string::npos ) {
151 std::shared_ptr<SAN> san( new SAN() );
152 san->type = data.substr( 0, pos );
153 san->content = data.substr( pos + 1 );
154 tbs->SANs.push_back( san );
159 case RecordHeader::SignerCommand::ADD_AVA:
161 size_t pos = data.find( "," );
163 if( pos == std::string::npos ) {
166 std::shared_ptr<AVA> ava( new AVA() );
167 ava->name = data.substr( 0, pos );
168 ava->value = data.substr( pos + 1 );
169 tbs->AVAs.push_back( ava );
174 case RecordHeader::SignerCommand::ADD_PROOF_LINE:
177 case RecordHeader::SignerCommand::SIGN:
178 result = signer->sign( tbs );
179 logger::note( "INFO: signlog:\n", result->log );
180 logger::note( "INFO: res:\n", result->certificate );
181 respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log );
184 case RecordHeader::SignerCommand::LOG_SAVED:
186 respondCommand( RecordHeader::SignerResult::SIGNING_CA, result->ca_name );
187 respondCommand( RecordHeader::SignerResult::CERTIFICATE, result->certificate );
190 if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
191 logger::warn( "ERROR: SSL shutdown failed." );
194 parent->reset(); // Connection ended
198 case RecordHeader::SignerCommand::ADD_SERIAL:
199 serials.push_back( data );
202 case RecordHeader::SignerCommand::REVOKE:
204 logger::note("Revoking: ", data);
205 std::string ca = data;
206 auto reqCA = CAs.at( ca );
207 logger::note( "CA found in recordHandler" );
208 std::shared_ptr<CRL> crl;
210 std::tie<std::shared_ptr<CRL>, std::string>( crl, date ) = signer->revoke( reqCA, serials );
212 respondCommand( RecordHeader::SignerResult::REVOKED, date + crl->getSignature() );
216 case RecordHeader::SignerCommand::GET_FULL_CRL:
218 logger::note("Requesting full CRL: ", data);
219 auto ca = CAs.at( data );
220 CRL c( ca->path + "/ca.crl" );
221 respondCommand( RecordHeader::SignerResult::FULL_CRL, c.toString() );
223 if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
224 logger::error( "ERROR: SSL shutdown failed." );
227 parent->reset(); // Connection ended
232 throw "Unimplemented";
237 DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr<Signer> signer, std::shared_ptr<BIO> bio ) :
238 bio( bio ), ctx( generateSSLContext( true ) ), signer( signer ), currentSession() {
241 void DefaultRecordHandler::reset() {
242 currentSession = std::shared_ptr<RecordHandlerSession>();
245 void DefaultRecordHandler::handle() {
246 if( !currentSession ) {
247 logger::note( "New session allocated." );
248 currentSession = std::shared_ptr<RecordHandlerSession>( new RecordHandlerSession( this, signer, ctx, bio ) );
251 currentSession->work();