#include "io/recordHandler.h"
#include <iostream>
+#include <sstream>
#include <fstream>
#include <ctime>
#include <unordered_map>
#include <openssl/ssl.h>
+#include "util.h"
#include "io/record.h"
#include "io/opensslBIO.h"
#include "io/slipBio.h"
#include "db/database.h"
#include "crypto/remoteSigner.h"
#include "crypto/sslUtil.h"
-
#include "crypto/simpleOpensslSigner.h"
+#include "log/logger.hpp"
+
extern std::vector<Profile> profiles;
extern std::unordered_map<std::string, std::shared_ptr<CAConfig>> CAs;
class RecordHandlerSession {
public:
- uint32_t sessid;
- uint32_t lastCommandCount;
+ uint32_t sessid = 0;
+ uint32_t lastCommandCount = 0;
std::shared_ptr<TBSCertificate> tbs;
std::shared_ptr<SignedCertificate> result;
DefaultRecordHandler* parent;
std::shared_ptr<Signer> signer;
- std::shared_ptr<std::ofstream> log;
+ std::unique_ptr<std::ofstream> logFile;
+ //std::stringstream sessionlog;
+ std::vector<std::string> serials;
+ logger::logger_set logger;
+
RecordHandlerSession( DefaultRecordHandler* parent, std::shared_ptr<Signer> signer, std::shared_ptr<SSL_CTX> ctx, std::shared_ptr<BIO> output ) :
- tbs( new TBSCertificate() ) {
+ tbs( std::make_shared<TBSCertificate>() ),
+ logFile(openLogfile( "logs/log_" + timestamp() ) ),
+ logger{ std::cout, *logFile } {
this->parent = parent;
this->signer = signer;
- time_t c_time;
-
- if( time( &c_time ) == -1 ) {
- throw "Error while fetching time?";
- }
-
- log = std::shared_ptr<std::ofstream>(
- new std::ofstream( std::string( "logs/log_" ) + std::to_string( c_time ) ),
- []( std::ofstream * ptr ) {
- ptr->close();
- delete ptr;
- } );
ssl = std::shared_ptr<SSL>( SSL_new( ctx.get() ), SSL_free );
std::shared_ptr<BIO> bio(
SSL_set_accept_state( ssl.get() );
SSL_set_bio( ssl.get(), output.get(), output.get() );
BIO_set_ssl( bio.get(), ssl.get(), BIO_NOCLOSE );
- io = std::shared_ptr<OpensslBIOWrapper>( new OpensslBIOWrapper( bio ) );
+ io = std::make_shared<OpensslBIOWrapper>( bio );
}
void respondCommand( RecordHeader::SignerResult res, std::string payload ) {
RecordHeader rh;
- rh.command = ( uint16_t ) res;
+ rh.command = static_cast<uint16_t>( res );
rh.flags = 0;
rh.command_count = 0; // TODO i++
- rh.totalLength = payload.size();
- sendCommand( rh, payload, io, log );
+ sendCommand( rh, payload, io );
}
void work() {
- std::vector<char> buffer( 2048, 0 );
- int res = io->read( buffer.data(), buffer.capacity() );
-
- if( res <= 0 ) {
- ( *log ) << "Stream error, resetting SSL" << std::endl;
- parent->reset();
- return;
- }
-
- std::string content( buffer.data(), res );
-
try {
RecordHeader head;
- std::string payload = parseCommand( head, content, log );
- execute( head, payload );
+ std::string all = parseCommandChunked( head, io );
+ execute( static_cast<RecordHeader::SignerCommand>( head.command ), all );
} catch( const char* msg ) {
- if( log ) {
- ( *log ) << "ERROR: " << msg << std::endl;
- }
-
+ logger::error( "ERROR: ", msg );
parent->reset();
return;
}
}
- void execute( RecordHeader& head, std::string data ) {
- if( head.totalLength != head.payloadLength || head.offset != 0 ) {
- throw "Error, chunking not supported yet";
- }
-
- switch( ( RecordHeader::SignerCommand ) head.command ) {
+ void execute( RecordHeader::SignerCommand command, std::string data ) {
+ switch( command ) {
case RecordHeader::SignerCommand::SET_CSR:
tbs->csr_content = data;
tbs->csr_type = "CSR";
- ( *log ) << "INFO: CSR read:" << std::endl << tbs->csr_content;
+ logger::note( "INFO: CSR read:\n", tbs->csr_content );
break;
case RecordHeader::SignerCommand::SET_SPKAC:
tbs->csr_content = data;
tbs->csr_type = "SPKAC";
- ( *log ) << "INFO: SPKAC read:" << std::endl << tbs->csr_content;
+ logger::note( "INFO: SPKAC read:\n", tbs->csr_content );
break;
case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE:
tbs->profile = data;
break;
- case RecordHeader::SignerCommand::ADD_SAN: {
- size_t pos = data.find( "," );
+ case RecordHeader::SignerCommand::SET_WISH_FROM:
+ tbs->wishFrom = data;
+ break;
- if( pos == std::string::npos ) {
- // error
- } else {
- std::shared_ptr<SAN> san( new SAN() );
- san->type = data.substr( 0, pos );
- san->content = data.substr( pos + 1 );
- tbs->SANs.push_back( san );
+ case RecordHeader::SignerCommand::SET_WISH_TO:
+ tbs->wishTo = data;
+ break;
+
+ case RecordHeader::SignerCommand::ADD_SAN:
+ {
+ size_t pos = data.find( "," );
+
+ if( pos == std::string::npos ) {
+ // error
+ } else {
+ auto san = std::make_shared<SAN>();
+ san->type = data.substr( 0, pos );
+ san->content = data.substr( pos + 1 );
+ tbs->SANs.push_back( san );
+ }
}
- }
- break;
-
- case RecordHeader::SignerCommand::ADD_AVA: {
- size_t pos = data.find( "," );
-
- if( pos == std::string::npos ) {
- // error
- } else {
- std::shared_ptr<AVA> ava( new AVA() );
- ava->name = data.substr( 0, pos );
- ava->value = data.substr( pos + 1 );
- tbs->AVAs.push_back( ava );
+ break;
+
+ case RecordHeader::SignerCommand::ADD_AVA:
+ {
+ size_t pos = data.find( "," );
+
+ if( pos == std::string::npos ) {
+ // error
+ } else {
+ auto ava = std::make_shared<AVA>();
+ ava->name = data.substr( 0, pos );
+ ava->value = data.substr( pos + 1 );
+ tbs->AVAs.push_back( ava );
+ }
}
- }
- break;
+ break;
case RecordHeader::SignerCommand::ADD_PROOF_LINE:
break;
case RecordHeader::SignerCommand::SIGN:
result = signer->sign( tbs );
- ( *log ) << "INFO: signlog: " << result->log << std::endl;
- ( *log ) << "INFO: res: " << result->certificate << std::endl;
+ logger::note( "INFO: signlog:\n", result->log );
+ logger::note( "INFO: res:\n", result->certificate );
respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log );
break;
case RecordHeader::SignerCommand::LOG_SAVED:
if( result ) {
+ respondCommand( RecordHeader::SignerResult::SIGNING_CA, result->ca_name );
respondCommand( RecordHeader::SignerResult::CERTIFICATE, result->certificate );
}
+ logger::note( "Shutting down SSL" );
if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
- ( *log ) << "ERROR: SSL close failed" << std::endl;
+ logger::warn( "ERROR: SSL shutdown failed." );
}
+ io->ctrl( BIO_CTRL_FLUSH, 0, NULL );
+ logger::note( "Shutted down SSL" );
- break;
-
- case RecordHeader::SignerCommand::REVOKE: {
- ( *log ) << "got revoking command: " << data.size() << std::endl;
- std::string nullstr( "\0", 1 );
- size_t t = data.find( nullstr );
-
- if( t == std::string::npos ) {
- // error
- ( *log ) << "error while parsing revoking command." << data << std::endl;
- break;
- }
+ parent->reset(); // Connection ended
- std::string ca = data.substr( 0, t );
- std::string serial = data.substr( t + 1 );
- ( *log ) << "revoking " << ca << "<->" << serial << std::endl;
+ break;
- ( *log ) << "[";
+ case RecordHeader::SignerCommand::ADD_SERIAL:
+ serials.push_back( data );
+ break;
- for( auto x : CAs ) {
- ( *log ) << x.first << ", ";
+ case RecordHeader::SignerCommand::REVOKE:
+ {
+ logger::note("Revoking: ", data);
+ std::string ca = data;
+ auto reqCA = CAs.at( ca );
+ logger::note( "CA found in recordHandler" );
+ std::shared_ptr<CRL> crl;
+ std::string date;
+ std::tie( crl, date ) = signer->revoke( reqCA, serials );
+
+ respondCommand( RecordHeader::SignerResult::REVOKED, date + crl->getSignature() );
}
+ break;
- ( *log ) << "]" << std::endl;
-
- auto reqCA = CAs.at( ca );
- ( *log ) << "CA found" << std::endl;
- std::shared_ptr<X509_CRL> crl = signer->revoke( reqCA, serial );
-
- std::shared_ptr<BIO> mem( BIO_new( BIO_s_mem() ), BIO_free );
-
- PEM_write_bio_X509_CRL( mem.get(), crl.get() );
- BUF_MEM* bptr;
- BIO_get_mem_ptr( mem.get(), &bptr );
-
- std::string newCRL( bptr->data, bptr->length );
- respondCommand( RecordHeader::SignerResult::REVOKED, newCRL );
-
- if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
- ( *log ) << "ERROR: SSL close failed" << std::endl;
+ case RecordHeader::SignerCommand::GET_FULL_CRL:
+ {
+ logger::note("Requesting full CRL: ", data);
+ auto ca = CAs.at( data );
+ CRL c( ca->path + "/ca.crl" );
+ respondCommand( RecordHeader::SignerResult::FULL_CRL, c.toString() );
+
+ logger::note( "Shutting down SSL" );
+ if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
+ logger::error( "ERROR: SSL shutdown failed." );
+ }
+ io->ctrl( BIO_CTRL_FLUSH, 0, NULL );
+ logger::note( "Shutted down SSL" );
+
+ parent->reset(); // Connection ended
}
-
break;
- }
default:
throw "Unimplemented";
};
DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr<Signer> signer, std::shared_ptr<BIO> bio ) :
- currentSession() {
-
- this->signer = signer;
-
- ctx = generateSSLContext( true );
-
- this->bio = bio;
+ bio( bio ), ctx( generateSSLContext( true ) ), signer( signer ), currentSession() {
}
void DefaultRecordHandler::reset() {
void DefaultRecordHandler::handle() {
if( !currentSession ) {
- std::cout << "session allocated" << std::endl;
- currentSession = std::shared_ptr<RecordHandlerSession>( new RecordHandlerSession( this, signer, ctx, bio ) );
+ (void) BIO_reset( bio.get() );
+ logger::note( "New session allocated." );
+ currentSession = std::make_shared<RecordHandlerSession>( this, signer, ctx, bio );
+ }
+ try {
+ currentSession->work();
+ } catch( EOFException e ){
+ reset();
}
-
- currentSession->work();
}