From 890efd9eb1d32033fe3afd088838bde707f3a2bb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Mon, 5 Jan 2015 23:30:34 +0100 Subject: [PATCH] add: Initial code to implement revocation --- src/apps/client.cpp | 13 +++++++- src/config.cpp | 11 ++++--- src/record.h | 2 ++ src/recordHandler.cpp | 46 ++++++++++++++++++++++++++ src/remoteSigner.cpp | 47 +++++++++++++++++++++++++++ src/remoteSigner.h | 2 ++ src/signer.h | 2 ++ src/simpleOpensslSigner.cpp | 65 +++++++++++++++++++++++++++++++++++++ src/simpleOpensslSigner.h | 1 + src/sslUtil.cpp | 5 +-- src/sslUtil.h | 3 +- 11 files changed, 188 insertions(+), 9 deletions(-) diff --git a/src/apps/client.cpp b/src/apps/client.cpp index 6613c94..9e85c95 100644 --- a/src/apps/client.cpp +++ b/src/apps/client.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "database.h" #include "mysql.h" @@ -22,9 +23,9 @@ #endif extern std::string keyDir; -extern std::vector profiles; extern std::string sqlHost, sqlUser, sqlPass, sqlDB; extern std::string serialPath; +extern std::unordered_map> CAs; int main( int argc, const char* argv[] ) { ( void ) argc; @@ -140,8 +141,18 @@ int main( int argc, const char* argv[] ) { } catch( std::string c ) { log << "ERROR: " << c << std::endl; } + } else if( job->task == "revoke" ) { + std::cout << "Revoking!" << std::endl; + + for( auto& x : CAs ) { + std::cout << " [" << x.first << ']' << std::endl; + } + + sign->revoke( CAs.at( "unassured" ), "12345" ); + jp->finishJob( job ); } else { log << "Unknown job type" << job->task << std::endl; + jp->failJob( job ); } if( !DAEMON || once ) { diff --git a/src/config.cpp b/src/config.cpp index f11edb1..2eb1f49 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -8,6 +8,7 @@ std::string keyDir; std::unordered_map profiles; +std::unordered_map> CAs; std::string sqlHost, sqlUser, sqlPass, sqlDB; std::string serialPath; @@ -56,7 +57,7 @@ int parseConfig( std::string path ) { sqlDB = masterConf->at( "sql.database" ); serialPath = masterConf->at( "serialPath" ); - std::shared_ptr>> CAs( new std::unordered_map>() ); + CAs = std::unordered_map>(); DIR* dp; struct dirent* ep; @@ -97,12 +98,12 @@ int parseConfig( std::string path ) { prof.eku = map->at( "eku" ); prof.ku = map->at( "ku" ); - if( CAs->find( map->at( "ca" ) ) == CAs->end() ) { - std::shared_ptr ca( new CAConfig( "ca/" + map->at( "ca" ) ) ); - CAs->emplace( map->at( "ca" ), ca ); + if( CAs.find( map->at( "ca" ) ) == CAs.end() ) { + std::shared_ptr ca( new CAConfig( map->at( "ca" ) ) ); + CAs.emplace( map->at( "ca" ), ca ); } - prof.ca = CAs->at( map->at( "ca" ) ); + prof.ca = CAs.at( map->at( "ca" ) ); profiles.emplace( profileName, prof ); std::cout << "Profile: " << profileName << " up and running." << std::endl; diff --git a/src/record.h b/src/record.h index d3173b8..3879428 100644 --- a/src/record.h +++ b/src/record.h @@ -21,11 +21,13 @@ public: ADD_PROOF_LINE = 0x40, SIGN = 0x80, LOG_SAVED = 0x81, + REVOKE = 0x100, GET_TIMESTAMP = 0xC0, GET_STATUS_REPORT = 0xD0 }; enum class SignerResult : uint16_t { + REVOKED = 0x100, SAVE_LOG = 0x80, CERTIFICATE = 0x81 }; diff --git a/src/recordHandler.cpp b/src/recordHandler.cpp index 9900496..ed45353 100644 --- a/src/recordHandler.cpp +++ b/src/recordHandler.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -22,6 +23,7 @@ #include "slipBio.h" extern std::vector profiles; +extern std::unordered_map> CAs; class RecordHandlerSession { public: @@ -134,6 +136,7 @@ public: size_t pos = data.find( "," ); if( pos == std::string::npos ) { + // error } else { std::shared_ptr san( new SAN() ); san->type = data.substr( 0, pos ); @@ -178,6 +181,49 @@ public: 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; + } + + std::string ca = data.substr( 0, t ); + std::string serial = data.substr( t + 1 ); + ( *log ) << "revoking " << ca << "<->" << serial << std::endl; + + ( *log ) << "["; + + for( auto x : CAs ) { + ( *log ) << x.first << ", "; + } + + ( *log ) << "]" << std::endl; + + auto reqCA = CAs.at( ca ); + ( *log ) << "CA found" << std::endl; + std::shared_ptr crl = signer->revoke( reqCA, serial ); + + std::shared_ptr 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; + } + + break; + } + default: throw "Unimplemented"; } diff --git a/src/remoteSigner.cpp b/src/remoteSigner.cpp index 439bcf8..a6ea578 100644 --- a/src/remoteSigner.cpp +++ b/src/remoteSigner.cpp @@ -90,6 +90,10 @@ std::shared_ptr RemoteSigner::sign( std::shared_ptrlog = payload; break; + + default: + std::cout << "Invalid Message" << std::endl; + break; } } catch( const char* msg ) { std::cout << msg << std::endl; @@ -135,6 +139,49 @@ std::shared_ptr RemoteSigner::sign( std::shared_ptr RemoteSigner::revoke( std::shared_ptr ca, std::string serial ) { + ( void )BIO_reset( target.get() ); + + std::shared_ptr ssl( SSL_new( ctx.get() ), SSL_free ); + std::shared_ptr bio( BIO_new( BIO_f_ssl() ), BIO_free ); + SSL_set_connect_state( ssl.get() ); + SSL_set_bio( ssl.get(), target.get(), target.get() ); + BIO_set_ssl( bio.get(), ssl.get(), BIO_NOCLOSE ); + std::shared_ptr conn( new OpensslBIOWrapper( bio ) ); + + RecordHeader head; + head.flags = 0; + head.sessid = 13; + + std::string payload = ca->name + std::string( "\0", 1 ) + serial; + send( conn, head, RecordHeader::SignerCommand::REVOKE, payload ); + + std::vector buffer( 2048 * 4 ); + int length = conn->read( buffer.data(), buffer.size() ); + + if( length <= 0 ) { + std::cout << "Error, no response data" << std::endl; + return std::shared_ptr(); + } + + payload = parseCommand( head, std::string( buffer.data(), length ), log ); + + switch( ( RecordHeader::SignerResult ) head.command ) { + case RecordHeader::SignerResult::REVOKED: + std::cout << "CRL: " << std::endl << payload << std::endl; + break; + + default: + throw "Invalid response command."; + } + + if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) { // need to close the connection twice + std::cout << "SSL shutdown failed" << std::endl; + } + + return std::shared_ptr(); +} + void RemoteSigner::setLog( std::shared_ptr target ) { this->log = target; } diff --git a/src/remoteSigner.h b/src/remoteSigner.h index 8cc3c72..333265c 100644 --- a/src/remoteSigner.h +++ b/src/remoteSigner.h @@ -20,5 +20,7 @@ public: RemoteSigner( std::shared_ptr target, std::shared_ptr ctx ); ~RemoteSigner(); std::shared_ptr sign( std::shared_ptr cert ); + std::shared_ptr revoke( std::shared_ptr ca, std::string serial ); + void setLog( std::shared_ptr target ); }; diff --git a/src/signer.h b/src/signer.h index feef5da..0d67135 100644 --- a/src/signer.h +++ b/src/signer.h @@ -3,8 +3,10 @@ #include #include "database.h" +#include "sslUtil.h" class Signer { public: virtual std::shared_ptr sign( std::shared_ptr cert ) = 0; + virtual std::shared_ptr revoke( std::shared_ptr ca, std::string serial ) = 0; }; diff --git a/src/simpleOpensslSigner.cpp b/src/simpleOpensslSigner.cpp index ab87057..cd02a96 100644 --- a/src/simpleOpensslSigner.cpp +++ b/src/simpleOpensslSigner.cpp @@ -158,3 +158,68 @@ std::shared_ptr SimpleOpensslSigner::sign( std::shared_ptrlog = signlog.str(); return output; } + + +std::shared_ptr SimpleOpensslSigner::revoke( std::shared_ptr ca, std::string serial ) { + std::string crlpath = ca->path + "/ca.crl"; + + std::shared_ptr bio( BIO_new_file( crlpath.c_str(), "r" ), free ); + std::shared_ptr crl( PEM_read_bio_X509_CRL( bio.get(), 0, NULL, 0 ), X509_CRL_free ); + std::cout << "Starting revocation" << std::endl; + + if( !crl ) { + std::cout << "CRL was not loaded" << std::endl; + crl = std::shared_ptr( X509_CRL_new(), X509_CRL_free ); + } + + BIGNUM* serBN = 0; + + if( ! BN_hex2bn( &serBN, serial.c_str() ) ) { + //error + } + + std::shared_ptr serBNP( serBN, BN_free ); + std::shared_ptr ser( BN_to_ASN1_INTEGER( serBN, NULL ), ASN1_INTEGER_free ); + + if( !ser ) { + // error + } + + std::shared_ptr tmptm( ASN1_TIME_new(), ASN1_TIME_free ); + + if( !tmptm ) { + // error + } + + X509_gmtime_adj( tmptm.get(), 0 ); + + X509_REVOKED* rev = X509_REVOKED_new(); + X509_REVOKED_set_serialNumber( rev, ser.get() ); + X509_REVOKED_set_revocationDate( rev, tmptm.get() ); + + X509_CRL_add0_revoked( crl.get(), rev ); + + if( !X509_CRL_set_issuer_name( crl.get(), X509_get_subject_name( ca->ca.get() ) ) ) { + // error + } + + X509_CRL_set_lastUpdate( crl.get(), tmptm.get() ); + + if( !X509_time_adj_ex( tmptm.get(), 1, 10, NULL ) ) { + // error + } + + X509_CRL_set_nextUpdate( crl.get(), tmptm.get() ); + + + std::cout << "Signing" << std::endl; + X509_CRL_sort( crl.get() ); + X509_CRL_sign( crl.get(), ca->caKey.get(), EVP_sha256() ); + + std::cout << "writing bio" << std::endl; + std::shared_ptr bioOut( BIO_new_file( crlpath.c_str(), "w" ), BIO_free ); + PEM_write_bio_X509_CRL( bioOut.get(), crl.get() ); + std::cout << "finished crl" << std::endl; + + return crl; +} diff --git a/src/simpleOpensslSigner.h b/src/simpleOpensslSigner.h index 944f3d8..f8e8729 100644 --- a/src/simpleOpensslSigner.h +++ b/src/simpleOpensslSigner.h @@ -14,4 +14,5 @@ public: SimpleOpensslSigner(); ~SimpleOpensslSigner(); std::shared_ptr sign( std::shared_ptr cert ); + std::shared_ptr revoke( std::shared_ptr ca, std::string serial ); }; diff --git a/src/sslUtil.cpp b/src/sslUtil.cpp index c7944f2..fd00e8f 100644 --- a/src/sslUtil.cpp +++ b/src/sslUtil.cpp @@ -173,8 +173,9 @@ std::shared_ptr openSerial( const std::string name ) { return b; } -CAConfig::CAConfig( std::string path ) { - this->path = path; +CAConfig::CAConfig( std::string name ) { + this->name = name; + this->path = "ca/" + name; ca = loadX509FromFile( path + "/ca.crt" ); caKey = loadPkeyFromFile( path + "/ca.key" ); } diff --git a/src/sslUtil.h b/src/sslUtil.h index 3fb54e3..7a68504 100644 --- a/src/sslUtil.h +++ b/src/sslUtil.h @@ -7,10 +7,11 @@ class CAConfig { public: std::string path; + std::string name; std::shared_ptr ca; std::shared_ptr caKey; - CAConfig( std::string path ); + CAConfig( std::string name ); }; -- 2.39.2