]> WPIA git - cassiopeia.git/commitdiff
upd: Better configuration, respecting profiles
authorFelix Dörre <felix@dogcraft.de>
Mon, 5 Jan 2015 02:57:19 +0000 (03:57 +0100)
committerBenny Baumann <BenBE@geshi.org>
Sat, 24 Jan 2015 17:32:18 +0000 (18:32 +0100)
12 files changed:
src/X509.cpp
src/X509.h
src/apps/client.cpp
src/apps/signer.cpp
src/config.cpp
src/mysql.cpp
src/simpleOpensslSigner.cpp
src/simpleOpensslSigner.h
src/sslUtil.cpp
src/sslUtil.h
src/util.cpp
src/util.h

index d5f8bc50d52d33970ea436094c28cebb75d9c8ea..71060e99ebb143f73af05eb444fdd03851346438 100644 (file)
@@ -175,12 +175,13 @@ merr:
     throw "memerr";
 }
 
-void X509Cert::setExtensions( std::shared_ptr<X509> caCert, std::vector<std::shared_ptr<SAN>>& sans ) {
+void X509Cert::setExtensions( std::shared_ptr<X509> caCert, std::vector<std::shared_ptr<SAN>>& sans, Profile& prof ) {
     add_ext( caCert, target, NID_basic_constraints, "critical,CA:FALSE" );
     add_ext( caCert, target, NID_subject_key_identifier, "hash" );
     add_ext( caCert, target, NID_authority_key_identifier, "keyid,issuer:always" );
-    add_ext( caCert, target, NID_key_usage, "critical,nonRepudiation,digitalSignature,keyEncipherment" );
-    add_ext( caCert, target, NID_ext_key_usage, "clientAuth, serverAuth" );
+    std::string ku = std::string( "critical," ) + prof.ku;
+    add_ext( caCert, target, NID_key_usage, ku.c_str() );
+    add_ext( caCert, target, NID_ext_key_usage, prof.eku.c_str() );
     add_ext( caCert, target, NID_info_access, "OCSP;URI:http://ocsp.cacert.org" );
     add_ext( caCert, target, NID_crl_distribution_points, "URI:http://crl.cacert.org/class3-revoke.crl" );
 
index 5f1b76fe282adeda0ccc7605ad8531494f5de62e..79aabc1f2333516937f89c786527a79a335bc654 100644 (file)
@@ -6,6 +6,7 @@
 #include <openssl/ssl.h>
 
 #include "database.h"
+#include "sslUtil.h"
 
 class X509Req {
 private:
@@ -31,7 +32,7 @@ public:
     void setIssuerNameFrom( std::shared_ptr<X509> ca );
     void setPubkeyFrom( std::shared_ptr<X509Req> r );
     void setSerialNumber( BIGNUM* num );
-    void setExtensions( std::shared_ptr<X509> caCert, std::vector<std::shared_ptr<SAN>>& sans );
+    void setExtensions( std::shared_ptr<X509> caCert, std::vector<std::shared_ptr<SAN>>& sans, Profile& prof );
     void setTimes( uint32_t before, uint32_t after );
     std::shared_ptr<SignedCertificate> sign( std::shared_ptr<EVP_PKEY> caKey, std::string signAlg );
 };
index 6e21d6e7f8e18742871cd03249547a58b7149e23..6613c94fd38f24f34a1d2976f063821bf4211c1b 100644 (file)
@@ -26,19 +26,6 @@ extern std::vector<Profile> profiles;
 extern std::string sqlHost, sqlUser, sqlPass, sqlDB;
 extern std::string serialPath;
 
-std::string writeBackFile( uint32_t serial, std::string cert ) {
-    std::string filename = keyDir;
-    mkdir( filename.c_str(), 0755 );
-    filename += "/crt";
-    mkdir( filename.c_str(), 0755 );
-    filename += "/" + std::to_string( serial / 1000 );
-    mkdir( filename.c_str(), 0755 );
-    filename += "/" + std::to_string( serial ) + ".crt";
-    writeFile( filename, cert );
-    std::cout << "wrote to " << filename << std::endl;
-    return filename;
-}
-
 int main( int argc, const char* argv[] ) {
     ( void ) argc;
     ( void ) argv;
@@ -130,7 +117,7 @@ int main( int argc, const char* argv[] ) {
 
                 log << "FINE: CERTIFICATE LOG: " << res->log << std::endl;
                 log << "FINE: CERTIFICATE:" << std::endl << res->certificate << std::endl;
-                std::string fn = writeBackFile( atoi( job->target.c_str() ), res->certificate );
+                std::string fn = writeBackFile( job->target.c_str(), res->certificate, keyDir );
                 res->crt_name = fn;
                 jp->writeBack( job, res );
                 log << "FINE: signing done." << std::endl;
index 44f05d686f9862069aaf40cedcc13e91f4c8ccc5..6dddf027aa1b6ef0078f6d77b4a9ac9f3109bb74 100644 (file)
@@ -20,7 +20,6 @@
 #endif
 
 extern std::string serialPath;
-extern std::vector<Profile> profiles;
 
 int main( int argc, const char* argv[] ) {
     ( void ) argc;
@@ -49,14 +48,16 @@ int main( int argc, const char* argv[] ) {
     std::shared_ptr<BIO> slip1( BIO_new( toBio<SlipBIO>() ), BIO_free );
     ( ( SlipBIO* )slip1->ptr )->setTarget( std::shared_ptr<OpensslBIO>( new OpensslBIOWrapper( conn ) ) );
 
-    try {
-        DefaultRecordHandler* dh = new DefaultRecordHandler( std::shared_ptr<Signer>( new SimpleOpensslSigner( profiles[5] ) ), slip1 );
+    DefaultRecordHandler* dh = new DefaultRecordHandler( std::shared_ptr<Signer>( new SimpleOpensslSigner( ) ), slip1 );
 
-        while( true ) {
+    while( true ) {
+        try {
             dh->handle();
+            //} catch( const std::exception &ch ) {
+            //std::cout << "Real exception: " << typeid(ch).name() << ", " << ch.what() << std::endl;
+        } catch( char const* ch ) {
+            std::cout << "Exception: " << ch << std::endl;
         }
-    } catch( char const* ch ) {
-        std::cout << "Exception: " << ch << std::endl;
     }
 
     return -1;
index 5556e9331a6ad35069e08424498d5b754a59de73..f11edb112838386c74fb970db374397ebd8fe20b 100644 (file)
@@ -1,21 +1,24 @@
 #include <iostream>
 #include <vector>
 #include <fstream>
+#include <dirent.h>
+#include <unordered_map>
 
 #include "sslUtil.h"
 
 std::string keyDir;
-std::vector<Profile> profiles;
+std::unordered_map<std::string, Profile> profiles;
 std::string sqlHost, sqlUser, sqlPass, sqlDB;
 std::string serialPath;
 
-int parseConfig( std::string path ) {
+std::shared_ptr<std::unordered_map<std::string, std::string>> parseConf( std::string path ) {
+    std::shared_ptr<std::unordered_map<std::string, std::string>> map( new std::unordered_map<std::string, std::string>() );
     std::ifstream config;
     config.open( path );
 
     if( !config.is_open() ) {
-        std::cerr << "config missing" << std::endl;
-        return 1;
+        std::cout << "Where is " << path << "?" << std::endl;
+        throw "Config missing";
     }
 
     std::string line1;
@@ -34,58 +37,80 @@ int parseConfig( std::string path ) {
 
         std::string key = line1.substr( 0, splitter );
         std::string value = line1.substr( splitter + 1 );
+        map->emplace( key, value );
+    }
+
+    config.close();
+
+    return map;
+}
+
+int parseConfig( std::string path ) {
+
+    auto masterConf = parseConf( path );
 
-        if( key == "key.directory" ) {
-            keyDir = value;
+    keyDir = masterConf->at( "key.directory" );
+    sqlHost = masterConf->at( "sql.host" );
+    sqlUser = masterConf->at( "sql.user" );
+    sqlPass = masterConf->at( "sql.password" );
+    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>>() );
+
+    DIR* dp;
+    struct dirent* ep;
+    dp = opendir( "profiles" );
+
+    if( dp == NULL ) {
+        std::cerr << "Profiles not found " << std::endl;
+        return -1;
+    }
+
+    while( ( ep = readdir( dp ) ) ) {
+        if( ep->d_name[0] == '.' ) {
             continue;
-        } else if( key == "sql.host" ) {
-            sqlHost = value;
-        } else if( key == "sql.user" ) {
-            sqlUser = value;
-        } else if( key == "sql.password" ) {
-            sqlPass = value;
-        } else if( key == "sql.database" ) {
-            sqlDB = value;
-        } else if( key == "serialPath" ) {
-            serialPath = value;
-        } else  if( key.compare( 0, 8, "profile." ) == 0 ) {
-            int numE = key.find( ".", 9 );
-
-            if( numE == 0 ) {
-                std::cout << "invalid line: " << line1 << std::endl;
-                continue;
-            }
-
-            unsigned int i = atoi( key.substr( 8, numE - 8 ).c_str() );
-            std::string rest = key.substr( numE + 1 );
-
-            if( i + 1 > profiles.size() ) {
-                profiles.resize( i + 1 );
-            }
-
-            if( rest == "key" ) {
-                profiles[i].key = value;
-            } else if( rest == "cert" ) {
-                profiles[i].cert = value;
-            } else if( rest == "ku" ) {
-                profiles[i].ku = value;
-            } else if( rest == "eku" ) {
-                profiles[i].eku = value;
-            } else {
-                std::cout << "invalid line: " << line1 << std::endl;
-                continue;
-            }
         }
-    }
 
-    for( auto& prof : profiles ) {
-        if( prof.cert != "" && prof.key != "" ) {
-            std::cout << "Loading profile... " << std::endl;
-            prof.ca = loadX509FromFile( prof.cert );
-            prof.caKey = loadPkeyFromFile( prof.key );
+        std::string profileName( ep->d_name );
+
+        int splitter = profileName.find( "-" );
+
+        if( splitter == -1 ) {
+            std::cerr << "Ignoring malformed profile: " << profileName << std::endl;
+            continue;
         }
+
+        std::string id = profileName.substr( 0, splitter );
+
+        if( profileName.substr( profileName.size() - 4 ) != ".cfg" ) {
+            std::cerr << "Ignoring malformed profile: " << profileName << std::endl;
+            continue;
+        }
+
+        auto map = parseConf( std::string( "profiles/" ) + profileName );
+
+        profileName = profileName.substr( 0, profileName.size() - 4 );
+
+        Profile prof;
+        prof.id = std::stoi( id );
+        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 );
+        }
+
+        prof.ca = CAs->at( map->at( "ca" ) );
+
+        profiles.emplace( profileName, prof );
+        std::cout << "Profile: " << profileName << " up and running." << std::endl;
     }
 
+    ( void ) closedir( dp );
+
+
     std::cout << profiles.size() << " profiles loaded." << std::endl;
 
     if( keyDir == "" ) {
@@ -93,6 +118,5 @@ int parseConfig( std::string path ) {
         return -1;
     }
 
-    config.close();
     return 0;
 }
index 15478acb553743c315197a95110acd52fe405dd3..973e9d0fb68f06ba13f8d57f29e07485ba632c88 100644 (file)
@@ -199,7 +199,7 @@ void MySQLJobProvider::failJob( std::shared_ptr<Job> job ) {
 
 std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<Job> job ) {
     std::shared_ptr<TBSCertificate> cert = std::shared_ptr<TBSCertificate>( new TBSCertificate() );
-    std::string q = "SELECT md, profile, csr_name, csr_type FROM certs WHERE id='" + this->escape_string( job->target ) + "'";
+    std::string q = "SELECT md, profile, csr_name, csr_type, keyname FROM certs INNER JOIN profiles ON profiles.id = certs.profile WHERE certs.id='" + this->escape_string( job->target ) + "'";
 
     int err = 0;
 
@@ -223,8 +223,17 @@ std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<
         return std::shared_ptr<TBSCertificate>();
     }
 
+    std::string profileName = std::string( row[4], row[4] + l[4] );
+
     cert->md = std::string( row[0], row[0] + l[0] );
-    cert->profile = std::string( row[1], row[1] + l[1] );
+    std::string profileId = std::string( row[1], row[1] + l[1] );
+
+    while( profileId.size() < 4 ) {
+        profileId = "0" + profileId;
+    }
+
+    cert->profile = profileId + "-" + profileName;
+
     cert->csr = std::string( row[2], row[2] + l[2] );
     cert->csr_type = std::string( row[3], row[3] + l[3] );
 
index 83c560974f1cb3b6b13ec77cb6878790ef815766..ab87057c2096da508cf7c20280b3effb9dfb97fa 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <iostream>
 #include <sstream>
+#include <unordered_map>
 
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include "util.h"
 #include "sslUtil.h"
 
-extern std::vector<Profile> profiles;
+extern std::unordered_map<std::string, Profile> profiles;
 
 std::shared_ptr<int> SimpleOpensslSigner::lib_ref = ssl_lib_ref;
 
-SimpleOpensslSigner::SimpleOpensslSigner( Profile& prof ) : prof( prof ) {
+SimpleOpensslSigner::SimpleOpensslSigner() {
 }
 
 SimpleOpensslSigner::~SimpleOpensslSigner() {
 }
 
-std::shared_ptr<BIGNUM> SimpleOpensslSigner::nextSerial( uint16_t profile ) {
-    std::string res = readFile( "serial" );
+std::pair<std::shared_ptr<BIGNUM>, std::string> SimpleOpensslSigner::nextSerial( Profile& prof ) {
+    uint16_t profile = prof.id;
+    std::string res = readFile( prof.ca->path + "/serial" );
 
     BIGNUM* bn = 0;
 
@@ -61,19 +63,26 @@ std::shared_ptr<BIGNUM> SimpleOpensslSigner::nextSerial( uint16_t profile ) {
         []( char* ref ) {
             OPENSSL_free( ref );
         } );
-    writeFile( "serial", serStr.get() );
+    writeFile( prof.ca->path + "/serial", serStr.get() );
 
-    return std::shared_ptr<BIGNUM>( BN_bin2bn( data.get(), len + 4 + 16 , 0 ), BN_free );
+    return std::pair<std::shared_ptr<BIGNUM>, std::string>( std::shared_ptr<BIGNUM>( BN_bin2bn( data.get(), len + 4 + 16 , 0 ), BN_free ), std::string( serStr.get() ) );
 }
 
 std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TBSCertificate> cert ) {
     std::stringstream signlog;
 
+    signlog << "FINE: profile is " << cert->profile << std::endl;
+
+    Profile& prof = profiles.at( cert->profile );
+
     if( !prof.ca ) {
         throw "CA-key not found";
     }
 
     signlog << "FINE: CA-key is correctly loaded." << std::endl;
+    signlog << "FINE: Profile id is: " << prof.id << std::endl;
+    signlog << "FINE: ku is: " << prof.ku << std::endl;
+    signlog << "FINE: eku is: " << prof.eku << std::endl;
 
     std::shared_ptr<X509Req> req;
 
@@ -132,22 +141,20 @@ std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TB
         }
     }
 
-    c.setIssuerNameFrom( prof.ca );
+    c.setIssuerNameFrom( prof.ca->ca );
     c.setPubkeyFrom( req );
-    long int profile = strtol( cert->profile.c_str(), 0, 10 );
-
-    if( profile > 0xFFFF || profile < 0 || ( profile == 0 && cert->profile != "0" ) ) {
-        throw "invalid profile id";
-    }
 
-    std::shared_ptr<BIGNUM> ser = nextSerial( profile );
+    std::shared_ptr<BIGNUM> ser;
+    std::string num;
+    std::tie( ser, num ) = nextSerial( prof );
     c.setSerialNumber( ser.get() );
     c.setTimes( 0, 60 * 60 * 24 * 10 );
     signlog << "FINE: Setting extensions." << std::endl;
-    c.setExtensions( prof.ca, cert->SANs );
+    c.setExtensions( prof.ca->ca, cert->SANs, prof );
     signlog << "FINE: Signed" << std::endl;
-    std::shared_ptr<SignedCertificate> output = c.sign( prof.caKey, cert->md );
+    std::shared_ptr<SignedCertificate> output = c.sign( prof.ca->caKey, cert->md );
     signlog << "FINE: all went well" << std::endl;
+    signlog << "FINE: crt went to: " << writeBackFile( num, output->certificate, prof.ca->path ) << std::endl;
     output->log = signlog.str();
     return output;
 }
index e1c912bfa8b49125124d17a993b28a457ec6273f..944f3d858008b7604d6495629f20cb0d40bd7e37 100644 (file)
@@ -9,10 +9,9 @@
 class SimpleOpensslSigner : public Signer {
 private:
     static std::shared_ptr<int> lib_ref;
-    Profile& prof;
-    std::shared_ptr<BIGNUM> nextSerial( uint16_t profile );
+    std::pair<std::shared_ptr<BIGNUM>, std::string> nextSerial( Profile& prof );
 public:
-    SimpleOpensslSigner( Profile& prof );
+    SimpleOpensslSigner();
     ~SimpleOpensslSigner();
     std::shared_ptr<SignedCertificate> sign( std::shared_ptr<TBSCertificate> cert );
 };
index 414bf3a3c32faa126dc753bbc6f7b21564ed610f..c7944f298bed9765993183a987589bc9beb1f105 100644 (file)
@@ -172,3 +172,9 @@ std::shared_ptr<BIO> openSerial( const std::string name ) {
     std::shared_ptr<BIO> b( BIO_new_fd( fileno( f ), 0 ), BIO_free );
     return b;
 }
+
+CAConfig::CAConfig( std::string path ) {
+    this->path = path;
+    ca = loadX509FromFile( path + "/ca.crt" );
+    caKey = loadPkeyFromFile( path + "/ca.key" );
+}
index 2bffc1427a491f2bf5263156ee9f684f75e58766..3fb54e3362866e9e4ebe544b2a5de174e47d1fe7 100644 (file)
@@ -2,15 +2,26 @@
 #include <openssl/ssl.h>
 #include <memory>
 #include <string>
+#include <cinttypes>
+
+class CAConfig {
+public:
+    std::string path;
+
+    std::shared_ptr<X509> ca;
+    std::shared_ptr<EVP_PKEY> caKey;
+    CAConfig( std::string path );
+
+};
+
 
 struct Profile {
-    std::string cert;
-    std::string key;
+    uint16_t id;
+
     std::string eku;
     std::string ku;
 
-    std::shared_ptr<X509> ca;
-    std::shared_ptr<EVP_PKEY> caKey;
+    std::shared_ptr<CAConfig> ca;
 };
 
 extern std::shared_ptr<int> ssl_lib_ref;
index 13443af321f7f183cb5c907e744e98740c775bfc..36f2261d62e9852477c15b2a034f091b26def049 100644 (file)
@@ -1,8 +1,10 @@
 #include "util.h"
 
+#include <sys/stat.h>
+
 #include <fstream>
 
-void writeFile( const std::string& name, const std::string& content ) {
+void writeFile( std::string name, std::string content ) {
     std::ofstream file;
 
     file.open( name );
@@ -17,3 +19,24 @@ std::string readFile( const std::string& name ) {
 
     return res;
 }
+
+std::string writeBackFile( std::string serial, std::string cert, std::string keydir ) {
+    std::string filename = keydir;
+    mkdir( filename.c_str(), 0755 );
+    filename += "/crt";
+    mkdir( filename.c_str(), 0755 );
+    std::string first;
+
+    if( serial.length() < 3 ) {
+        first = "0";
+    } else {
+        first = serial.substr( 0, serial.length() - 3 );
+    }
+
+    filename += "/" + first;
+    mkdir( filename.c_str(), 0755 );
+    filename += "/" + serial + ".crt";
+    writeFile( filename, cert );
+
+    return filename;
+}
index 94ca64fa96b8117cc988916f28fabac34c05b2c4..367d245d785418897c61f30f0072be0fa947c5af 100644 (file)
@@ -2,5 +2,7 @@
 
 #include <string>
 
-void writeFile( const std::string& name, const std::string& content );
-std::string readFile( const std::string& name );
+void writeFile( std::string name, std::string content );
+std::string readFile( std::string name );
+
+std::string writeBackFile( std::string serial, std::string cert, std::string keydir );