1 #include "recordHandler.h"
4 #include <sys/socket.h>
5 #include <netinet/in.h>
14 #include <openssl/ssl.h>
18 #include "opensslBIO.h"
19 #include "remoteSigner.h"
20 #include "simpleOpensslSigner.h"
24 extern std::vector<Profile> profiles;
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> log;
42 RecordHandlerSession( DefaultRecordHandler* parent, std::shared_ptr<Signer> signer, std::shared_ptr<SSL_CTX> ctx, std::shared_ptr<BIO> output ) :
43 tbs( new TBSCertificate() ) {
44 this->parent = parent;
45 this->signer = signer;
48 if( time( &c_time ) == -1 ) {
49 throw "Error while fetching time?";
52 log = std::shared_ptr<std::ofstream>(
53 new std::ofstream( std::string( "logs/log_" ) + std::to_string( c_time ) ),
54 []( std::ofstream * ptr ) {
59 ssl = std::shared_ptr<SSL>( SSL_new( ctx.get() ), SSL_free );
60 std::shared_ptr<BIO> bio(
61 BIO_new( BIO_f_ssl() ),
65 SSL_set_accept_state( ssl.get() );
66 SSL_set_bio( ssl.get(), output.get(), output.get() );
67 BIO_set_ssl( bio.get(), ssl.get(), BIO_NOCLOSE );
68 io = std::shared_ptr<OpensslBIOWrapper>( new OpensslBIOWrapper( bio ) );
71 void respondCommand( RecordHeader::SignerResult res, std::string payload ) {
73 rh.command = ( uint16_t ) res;
75 rh.command_count = 0; // TODO i++
76 rh.totalLength = payload.size();
77 sendCommand( rh, payload, io, log );
81 std::vector<char> buffer( 2048, 0 );
82 int res = io->read( buffer.data(), buffer.capacity() );
85 ( *log ) << "Stream error, resetting SSL" << std::endl;
90 std::string content( buffer.data(), res );
94 std::string payload = parseCommand( head, content, log );
95 execute( head, payload );
96 } catch( const char* msg ) {
98 ( *log ) << "ERROR: " << msg << std::endl;
106 void execute( RecordHeader& head, std::string data ) {
107 if( head.totalLength != head.payloadLength || head.offset != 0 ) {
108 throw "Error, chunking not supported yet";
111 switch( ( RecordHeader::SignerCommand ) head.command ) {
112 case RecordHeader::SignerCommand::SET_CSR:
113 tbs->csr_content = data;
114 tbs->csr_type = "CSR";
115 ( *log ) << "INFO: CSR read:" << std::endl << tbs->csr_content;
118 case RecordHeader::SignerCommand::SET_SPKAC:
119 tbs->csr_content = data;
120 tbs->csr_type = "SPKAC";
121 ( *log ) << "INFO: SPKAC read:" << std::endl << tbs->csr_content;
124 case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE:
128 case RecordHeader::SignerCommand::SET_PROFILE:
133 case RecordHeader::SignerCommand::ADD_SAN: {
134 size_t pos = data.find( "," );
136 if( pos == std::string::npos ) {
138 std::shared_ptr<SAN> san( new SAN() );
139 san->type = data.substr( 0, pos );
140 san->content = data.substr( pos + 1 );
141 tbs->SANs.push_back( san );
146 case RecordHeader::SignerCommand::ADD_AVA: {
147 size_t pos = data.find( "," );
149 if( pos == std::string::npos ) {
152 std::shared_ptr<AVA> ava( new AVA() );
153 ava->name = data.substr( 0, pos );
154 ava->value = data.substr( pos + 1 );
155 tbs->AVAs.push_back( ava );
160 case RecordHeader::SignerCommand::ADD_PROOF_LINE:
163 case RecordHeader::SignerCommand::SIGN:
164 result = signer->sign( tbs );
165 ( *log ) << "INFO: signlog: " << result->log << std::endl;
166 ( *log ) << "INFO: res: " << result->certificate << std::endl;
167 respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log );
170 case RecordHeader::SignerCommand::LOG_SAVED:
172 respondCommand( RecordHeader::SignerResult::CERTIFICATE, result->certificate );
175 if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
176 ( *log ) << "ERROR: SSL close failed" << std::endl;
182 throw "Unimplemented";
187 DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr<Signer> signer, std::shared_ptr<BIO> bio ) :
190 this->signer = signer;
192 ctx = generateSSLContext( true );
197 void DefaultRecordHandler::reset() {
198 currentSession = std::shared_ptr<RecordHandlerSession>();
201 void DefaultRecordHandler::handle() {
202 if( !currentSession ) {
203 std::cout << "session allocated" << std::endl;
204 currentSession = std::shared_ptr<RecordHandlerSession>( new RecordHandlerSession( this, signer, ctx, bio ) );
207 currentSession->work();