From: Felix Dörre Date: Tue, 26 Jan 2016 15:34:47 +0000 (+0100) Subject: add: implement command chunking especially for FULL_CRL-commands X-Git-Url: https://code.wpia.club/?p=cassiopeia.git;a=commitdiff_plain;h=f8d1606423c351f2003ce18258ef047e0d2af326 add: implement command chunking especially for FULL_CRL-commands --- diff --git a/src/crypto/remoteSigner.cpp b/src/crypto/remoteSigner.cpp index 6c003c3..4b1e630 100644 --- a/src/crypto/remoteSigner.cpp +++ b/src/crypto/remoteSigner.cpp @@ -73,7 +73,7 @@ std::shared_ptr RemoteSigner::sign( std::shared_ptrreadLine() ); + std::string payload = parseCommandChunked( head, conn ); switch( static_cast( head.command )) { case RecordHeader::SignerResult::CERTIFICATE: @@ -162,7 +162,7 @@ std::pair, std::string> RemoteSigner::revoke( std::shared_p std::string payload = ca->name; send( conn, head, RecordHeader::SignerCommand::REVOKE, payload ); - payload = parseCommand( head, conn->readLine() ); + payload = parseCommandChunked( head, conn ); std::string tgtName = ca->path + std::string( "/ca.crl" ); auto crl = std::make_shared( tgtName ); @@ -193,7 +193,7 @@ std::pair, std::string> RemoteSigner::revoke( std::shared_p logger::warn( "CRL is broken, trying to recover" ); send( conn, head, RecordHeader::SignerCommand::GET_FULL_CRL, ca->name ); - payload = parseCommand( head, conn->readLine() ); + payload = parseCommandChunked( head, conn ); if( static_cast( head.command ) != RecordHeader::SignerResult::FULL_CRL ) { throw "Protocol violation"; diff --git a/src/io/record.cpp b/src/io/record.cpp index 97e6015..422244e 100644 --- a/src/io/record.cpp +++ b/src/io/record.cpp @@ -28,19 +28,26 @@ void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr 0xFFFF){ - logger::warn( "Data too big, need chunking" ); - } - head.payloadLength = data.size(); - std::string s; - s += head.packToString(); - s += data; + size_t pos = 0; + head.offset = 0; + head.totalLength = data.size(); + while(pos < data.size()){ + size_t toTransfer = std::min(static_cast(0xF000), data.size() - pos); + head.payloadLength = toTransfer; + + std::string s; + s += head.packToString(); + s += data.substr(pos, toTransfer); - std::string res = toHexAndChecksum( s ); + std::string res = toHexAndChecksum( s ); - logger::debug( "FINE: RECORD output: ", res ); + logger::debug( "FINE: RECORD output: ", res ); - bio->write( res.data(), res.size() ); + bio->write( res.data(), res.size() ); + + pos += toTransfer; + head.offset += 1; + } } int32_t fromHexDigit( char c ) { @@ -99,31 +106,20 @@ std::string parseCommand( RecordHeader& head, const std::string& input) { return data; } - -/* -int main( int argc, char* argv[] ) { - OpensslBIOWrapper *bio = new OpensslBIOWrapper(BIO_new_fd(0, 0)); - std::string data = "halloPayload"; - RecordHeader head; - head.command = 0x7; - head.flags = 1; - head.sessid = 13; - head.command_count = 0xA0B; - head.totalLength = 9; - sendCommand( head, data, std::shared_ptr(bio) ); - head.command = 0x8; - - try { - std::string c = parseCommand( head, ":0700010D0000000B0A0900000000000C0068616C6C6F5061796C6F6164E6\n" ); - - std::cout << "res: " << std::endl; - std::cout << head.payloadLength << std::endl; - std::cout << c << std::endl; - } catch( char const* c ) { - std::cout << "err: " << c << std::endl; +std::string parseCommandChunked( RecordHeader& head, std::shared_ptr io){ + logger::note("reading"); + std::string payload = parseCommand( head, io->readLine() ); + std::string all(head.totalLength, ' '); + auto target = all.begin(); + size_t pos = 0; + while(true) { + pos += head.payloadLength; + target = std::copy ( payload.begin(), payload.end(), target); + if(pos >= head.totalLength) { + break; + } + logger::note("chunk digested, reading next one"); + payload = parseCommand( head, io->readLine() ); } - - - return 0; + return all; } -*/ diff --git a/src/io/record.h b/src/io/record.h index 28a9b1e..d56708a 100644 --- a/src/io/record.h +++ b/src/io/record.h @@ -6,6 +6,7 @@ #include #include "bios.h" +#include "io/opensslBIO.h" #define RECORD_HEADER_SIZE 17 @@ -105,5 +106,6 @@ public: }; std::string parseCommand( RecordHeader& head, const std::string& input ); +std::string parseCommandChunked( RecordHeader& head, std::shared_ptr conn); void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr bio ); diff --git a/src/io/recordHandler.cpp b/src/io/recordHandler.cpp index 2d58be0..551b2c4 100644 --- a/src/io/recordHandler.cpp +++ b/src/io/recordHandler.cpp @@ -67,17 +67,14 @@ public: rh.command = static_cast( res ); rh.flags = 0; rh.command_count = 0; // TODO i++ - rh.totalLength = payload.size(); sendCommand( rh, payload, io ); } void work() { - std::string content = io->readLine(); - try { RecordHeader head; - std::string payload = parseCommand( head, content ); - execute( head, payload ); + std::string all = parseCommandChunked( head, io ); + execute( static_cast( head.command ), all ); } catch( const char* msg ) { logger::error( "ERROR: ", msg ); parent->reset(); @@ -85,12 +82,8 @@ public: } } - void execute( RecordHeader& head, std::string data ) { - if( head.totalLength != head.payloadLength || head.offset != 0 ) { - throw "Error, chunking not supported yet"; - } - - switch( static_cast( 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";