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" );
#include <openssl/ssl.h>
#include "database.h"
+#include "sslUtil.h"
class X509Req {
private:
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 );
};
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;
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;
#endif
extern std::string serialPath;
-extern std::vector<Profile> profiles;
int main( int argc, const char* argv[] ) {
( void ) argc;
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;
#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;
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 == "" ) {
return -1;
}
- config.close();
return 0;
}
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;
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] );
#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;
[]( 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;
}
}
- 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;
}
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 );
};
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" );
+}
#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;
#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 );
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;
+}
#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 );