1 #include "recordHandler.h"
4 #include <sys/socket.h>
5 #include <netinet/in.h>
13 #include <unordered_map>
15 #include <openssl/ssl.h>
19 #include "opensslBIO.h"
20 #include "remoteSigner.h"
21 #include "simpleOpensslSigner.h"
25 extern std::vector<Profile> profiles;
26 extern std::unordered_map<std::string, std::shared_ptr<CAConfig>> CAs;
28 class RecordHandlerSession {
31 uint32_t lastCommandCount;
33 std::shared_ptr<TBSCertificate> tbs;
34 std::shared_ptr<SignedCertificate> result;
36 std::shared_ptr<SSL> ssl;
38 std::shared_ptr<OpensslBIOWrapper> io;
39 DefaultRecordHandler* parent;
40 std::shared_ptr<Signer> signer;
42 std::shared_ptr<std::ofstream> log;
44 RecordHandlerSession( DefaultRecordHandler* parent, std::shared_ptr<Signer> signer, std::shared_ptr<SSL_CTX> ctx, std::shared_ptr<BIO> output ) :
45 tbs( new TBSCertificate() ) {
46 this->parent = parent;
47 this->signer = signer;
50 if( time( &c_time ) == -1 ) {
51 throw "Error while fetching time?";
54 log = std::shared_ptr<std::ofstream>(
55 new std::ofstream( std::string( "logs/log_" ) + std::to_string( c_time ) ),
56 []( std::ofstream * ptr ) {
61 ssl = std::shared_ptr<SSL>( SSL_new( ctx.get() ), SSL_free );
62 std::shared_ptr<BIO> bio(
63 BIO_new( BIO_f_ssl() ),
67 SSL_set_accept_state( ssl.get() );
68 SSL_set_bio( ssl.get(), output.get(), output.get() );
69 BIO_set_ssl( bio.get(), ssl.get(), BIO_NOCLOSE );
70 io = std::shared_ptr<OpensslBIOWrapper>( new OpensslBIOWrapper( bio ) );
73 void respondCommand( RecordHeader::SignerResult res, std::string payload ) {
75 rh.command = ( uint16_t ) res;
77 rh.command_count = 0; // TODO i++
78 rh.totalLength = payload.size();
79 sendCommand( rh, payload, io, log );
83 std::vector<char> buffer( 2048, 0 );
84 int res = io->read( buffer.data(), buffer.capacity() );
87 ( *log ) << "Stream error, resetting SSL" << std::endl;
92 std::string content( buffer.data(), res );
96 std::string payload = parseCommand( head, content, log );
97 execute( head, payload );
98 } catch( const char* msg ) {
100 ( *log ) << "ERROR: " << msg << std::endl;
108 void execute( RecordHeader& head, std::string data ) {
109 if( head.totalLength != head.payloadLength || head.offset != 0 ) {
110 throw "Error, chunking not supported yet";
113 switch( ( RecordHeader::SignerCommand ) head.command ) {
114 case RecordHeader::SignerCommand::SET_CSR:
115 tbs->csr_content = data;
116 tbs->csr_type = "CSR";
117 ( *log ) << "INFO: CSR read:" << std::endl << tbs->csr_content;
120 case RecordHeader::SignerCommand::SET_SPKAC:
121 tbs->csr_content = data;
122 tbs->csr_type = "SPKAC";
123 ( *log ) << "INFO: SPKAC read:" << std::endl << tbs->csr_content;
126 case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE:
130 case RecordHeader::SignerCommand::SET_PROFILE:
135 case RecordHeader::SignerCommand::ADD_SAN: {
136 size_t pos = data.find( "," );
138 if( pos == std::string::npos ) {
141 std::shared_ptr<SAN> san( new SAN() );
142 san->type = data.substr( 0, pos );
143 san->content = data.substr( pos + 1 );
144 tbs->SANs.push_back( san );
149 case RecordHeader::SignerCommand::ADD_AVA: {
150 size_t pos = data.find( "," );
152 if( pos == std::string::npos ) {
155 std::shared_ptr<AVA> ava( new AVA() );
156 ava->name = data.substr( 0, pos );
157 ava->value = data.substr( pos + 1 );
158 tbs->AVAs.push_back( ava );
163 case RecordHeader::SignerCommand::ADD_PROOF_LINE:
166 case RecordHeader::SignerCommand::SIGN:
167 result = signer->sign( tbs );
168 ( *log ) << "INFO: signlog: " << result->log << std::endl;
169 ( *log ) << "INFO: res: " << result->certificate << std::endl;
170 respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log );
173 case RecordHeader::SignerCommand::LOG_SAVED:
175 respondCommand( RecordHeader::SignerResult::CERTIFICATE, result->certificate );
178 if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
179 ( *log ) << "ERROR: SSL close failed" << std::endl;
184 case RecordHeader::SignerCommand::REVOKE: {
185 ( *log ) << "got revoking command: " << data.size() << std::endl;
186 std::string nullstr( "\0", 1 );
187 size_t t = data.find( nullstr );
189 if( t == std::string::npos ) {
191 ( *log ) << "error while parsing revoking command." << data << std::endl;
195 std::string ca = data.substr( 0, t );
196 std::string serial = data.substr( t + 1 );
197 ( *log ) << "revoking " << ca << "<->" << serial << std::endl;
201 for( auto x : CAs ) {
202 ( *log ) << x.first << ", ";
205 ( *log ) << "]" << std::endl;
207 auto reqCA = CAs.at( ca );
208 ( *log ) << "CA found" << std::endl;
209 std::shared_ptr<X509_CRL> crl = signer->revoke( reqCA, serial );
211 std::shared_ptr<BIO> mem( BIO_new( BIO_s_mem() ), BIO_free );
213 PEM_write_bio_X509_CRL( mem.get(), crl.get() );
215 BIO_get_mem_ptr( mem.get(), &bptr );
217 std::string newCRL( bptr->data, bptr->length );
218 respondCommand( RecordHeader::SignerResult::REVOKED, newCRL );
220 if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
221 ( *log ) << "ERROR: SSL close failed" << std::endl;
228 throw "Unimplemented";
233 DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr<Signer> signer, std::shared_ptr<BIO> bio ) :
236 this->signer = signer;
238 ctx = generateSSLContext( true );
243 void DefaultRecordHandler::reset() {
244 currentSession = std::shared_ptr<RecordHandlerSession>();
247 void DefaultRecordHandler::handle() {
248 if( !currentSession ) {
249 std::cout << "session allocated" << std::endl;
250 currentSession = std::shared_ptr<RecordHandlerSession>( new RecordHandlerSession( this, signer, ctx, bio ) );
253 currentSession->work();