]> WPIA git - cassiopeia.git/blobdiff - src/io/recordHandler.cpp
fix: also send chunks, when body is empty
[cassiopeia.git] / src / io / recordHandler.cpp
index b79d3cc144b96d2c70d210306e989c7846e9792e..551b2c495144e04c4660bc95c45dacaef885bbb3 100644 (file)
@@ -1,12 +1,14 @@
 #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;
@@ -34,24 +37,18 @@ public:
     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(
@@ -62,60 +59,41 @@ public:
         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:
@@ -127,41 +105,51 @@ public:
             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;
 
@@ -171,57 +159,52 @@ public:
                 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() );
             }
-
-            ( *log ) << "]" << std::endl;
-
-            auto reqCA = CAs.at( ca );
-            ( *log ) << "CA found" << std::endl;
-            std::shared_ptr<CRL> crl;
-            std::string date;
-            std::tie<std::shared_ptr<CRL>, std::string>( crl, date ) = signer->revoke( reqCA, serial );
-
-            respondCommand( RecordHeader::SignerResult::REVOKED, date + crl->getSignature() );
-
             break;
-        }
-
-        case RecordHeader::SignerCommand::GET_FULL_CRL: {
-            auto ca = CAs.at( data );
-            CRL c( ca->path + "/ca.crl" );
-            respondCommand( RecordHeader::SignerResult::FULL_CRL, c.toString() );
 
-            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";
@@ -230,13 +213,7 @@ public:
 };
 
 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() {
@@ -245,9 +222,13 @@ 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();
 }