]> WPIA git - cassiopeia.git/commitdiff
add: Initial code to implement revocation
authorFelix Dörre <felix@dogcraft.de>
Mon, 5 Jan 2015 22:30:34 +0000 (23:30 +0100)
committerBenny Baumann <BenBE@geshi.org>
Sat, 24 Jan 2015 17:33:27 +0000 (18:33 +0100)
src/apps/client.cpp
src/config.cpp
src/record.h
src/recordHandler.cpp
src/remoteSigner.cpp
src/remoteSigner.h
src/signer.h
src/simpleOpensslSigner.cpp
src/simpleOpensslSigner.h
src/sslUtil.cpp
src/sslUtil.h

index 6613c94fd38f24f34a1d2976f063821bf4211c1b..9e85c95e598a4e7c7bb7037898440a2cc29b1848 100644 (file)
@@ -4,6 +4,7 @@
 #include <iostream>
 #include <fstream>
 #include <streambuf>
+#include <unordered_map>
 
 #include "database.h"
 #include "mysql.h"
@@ -22,9 +23,9 @@
 #endif
 
 extern std::string keyDir;
-extern std::vector<Profile> profiles;
 extern std::string sqlHost, sqlUser, sqlPass, sqlDB;
 extern std::string serialPath;
+extern std::unordered_map<std::string, std::shared_ptr<CAConfig>> 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 ) {
index f11edb112838386c74fb970db374397ebd8fe20b..2eb1f491c3bc42ca41e35eefbb183c42e644409d 100644 (file)
@@ -8,6 +8,7 @@
 
 std::string keyDir;
 std::unordered_map<std::string, Profile> profiles;
+std::unordered_map<std::string, std::shared_ptr<CAConfig>> 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<std::unordered_map<std::string, std::shared_ptr<CAConfig>>> CAs( new std::unordered_map<std::string, std::shared_ptr<CAConfig>>() );
+    CAs = std::unordered_map<std::string, std::shared_ptr<CAConfig>>();
 
     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<CAConfig> ca( new CAConfig( "ca/" + map->at( "ca" ) ) );
-            CAs->emplace( map->at( "ca" ), ca );
+        if( CAs.find( map->at( "ca" ) ) == CAs.end() ) {
+            std::shared_ptr<CAConfig> 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;
index d3173b83220422627f6fca36e93fb0c442d14ebe..38794289f6d1df5021946c4aac9b8039c9845d3b 100644 (file)
@@ -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
     };
index 9900496a1a301b4fe31d214e495c1f8435515850..ed453535d846b9b653d9a8cf3a8cff8dfe2938a5 100644 (file)
@@ -10,6 +10,7 @@
 #include <iostream>
 #include <fstream>
 #include <ctime>
+#include <unordered_map>
 
 #include <openssl/ssl.h>
 
@@ -22,6 +23,7 @@
 #include "slipBio.h"
 
 extern std::vector<Profile> profiles;
+extern std::unordered_map<std::string, std::shared_ptr<CAConfig>> 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> 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<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;
+            }
+
+            break;
+        }
+
         default:
             throw "Unimplemented";
         }
index 439bcf8ab44308e298197129e5f625ed2b19e384..a6ea5780c4c5d8ca5a55c1cd656edef766ef9e26 100644 (file)
@@ -90,6 +90,10 @@ std::shared_ptr<SignedCertificate> RemoteSigner::sign( std::shared_ptr<TBSCertif
             case RecordHeader::SignerResult::SAVE_LOG:
                 result->log = 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<SignedCertificate> RemoteSigner::sign( std::shared_ptr<TBSCertif
     return result;
 }
 
+std::shared_ptr<X509_CRL> RemoteSigner::revoke( std::shared_ptr<CAConfig> ca, std::string serial ) {
+    ( void )BIO_reset( target.get() );
+
+    std::shared_ptr<SSL> ssl( SSL_new( ctx.get() ), SSL_free );
+    std::shared_ptr<BIO> 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<OpensslBIOWrapper> 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<char> 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<X509_CRL>();
+    }
+
+    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<X509_CRL>();
+}
+
 void RemoteSigner::setLog( std::shared_ptr<std::ostream> target ) {
     this->log = target;
 }
index 8cc3c72f29631f54732080f98ff3bf04b6d8abfe..333265cfd3d450840d8f0db0e45685ba1377a256 100644 (file)
@@ -20,5 +20,7 @@ public:
     RemoteSigner( std::shared_ptr<BIO> target, std::shared_ptr<SSL_CTX> ctx );
     ~RemoteSigner();
     std::shared_ptr<SignedCertificate> sign( std::shared_ptr<TBSCertificate> cert );
+    std::shared_ptr<X509_CRL> revoke( std::shared_ptr<CAConfig> ca, std::string serial );
+
     void setLog( std::shared_ptr<std::ostream> target );
 };
index feef5da64bbafcb39a70e820e7cefcdd5531c1af..0d671355b58481e50cb99d848467d4998acb1486 100644 (file)
@@ -3,8 +3,10 @@
 #include <memory>
 
 #include "database.h"
+#include "sslUtil.h"
 
 class Signer {
 public:
     virtual std::shared_ptr<SignedCertificate> sign( std::shared_ptr<TBSCertificate> cert ) = 0;
+    virtual std::shared_ptr<X509_CRL> revoke( std::shared_ptr<CAConfig> ca, std::string serial ) = 0;
 };
index ab87057c2096da508cf7c20280b3effb9dfb97fa..cd02a969d6553c2441f8889a55f645af089b7606 100644 (file)
@@ -158,3 +158,68 @@ std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TB
     output->log = signlog.str();
     return output;
 }
+
+
+std::shared_ptr<X509_CRL> SimpleOpensslSigner::revoke( std::shared_ptr<CAConfig> ca, std::string serial ) {
+    std::string crlpath = ca->path + "/ca.crl";
+
+    std::shared_ptr<BIO> bio( BIO_new_file( crlpath.c_str(), "r" ), free );
+    std::shared_ptr<X509_CRL> 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>( X509_CRL_new(), X509_CRL_free );
+    }
+
+    BIGNUM* serBN = 0;
+
+    if( ! BN_hex2bn( &serBN, serial.c_str() ) ) {
+        //error
+    }
+
+    std::shared_ptr<BIGNUM> serBNP( serBN, BN_free );
+    std::shared_ptr<ASN1_INTEGER> ser( BN_to_ASN1_INTEGER( serBN, NULL ), ASN1_INTEGER_free );
+
+    if( !ser ) {
+        // error
+    }
+
+    std::shared_ptr<ASN1_TIME> 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<BIO> 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;
+}
index 944f3d858008b7604d6495629f20cb0d40bd7e37..f8e87298a872110ef51f888c440cb426cefe7a85 100644 (file)
@@ -14,4 +14,5 @@ public:
     SimpleOpensslSigner();
     ~SimpleOpensslSigner();
     std::shared_ptr<SignedCertificate> sign( std::shared_ptr<TBSCertificate> cert );
+    std::shared_ptr<X509_CRL> revoke( std::shared_ptr<CAConfig> ca, std::string serial );
 };
index c7944f298bed9765993183a987589bc9beb1f105..fd00e8fb85a94db8367299a6d52e676c5cd278bb 100644 (file)
@@ -173,8 +173,9 @@ std::shared_ptr<BIO> 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" );
 }
index 3fb54e3362866e9e4ebe544b2a5de174e47d1fe7..7a6850451f81566477930f14791a7223b7e34686 100644 (file)
@@ -7,10 +7,11 @@
 class CAConfig {
 public:
     std::string path;
+    std::string name;
 
     std::shared_ptr<X509> ca;
     std::shared_ptr<EVP_PKEY> caKey;
-    CAConfig( std::string path );
+    CAConfig( std::string name );
 
 };