continue;
}
+ std::ofstream* logP = new std::ofstream( std::string( "logs/" ) + job->id + std::string( "_" ) + job->warning + std::string( ".log" ) );
+ std::shared_ptr<std::ofstream> logPtr(
+ logP,
+ []( std::ofstream * ptr ) {
+ ( *ptr ).close();
+ delete ptr;
+ } );
+ std::ofstream& log = *logP;
+
+ sign->setLog( logPtr );
+ log << "TASK ID: " << job->id << std::endl;
+ log << "TRY: " << job->warning << std::endl;
+ log << "TARGET: " << job->target << std::endl;
+ log << "TASK: " << job->task << std::endl << std::endl;
+
if( job->task == "sign" ) {
try {
std::shared_ptr<TBSCertificate> cert = jp->fetchTBSCert( job );
+ log << "INFO: message digest: " << cert->md << std::endl;
+ log << "INFO: profile id: " << cert->profile << std::endl;
+
+ for( auto& SAN : cert->SANs ) {
+ log << "INFO: SAN " << SAN->type << ": " << SAN->content;
+ }
+
+ for( auto& AVA : cert->AVAs ) {
+ log << "INFO: AVA " << AVA->name << ": " << AVA->value;
+ }
if( !cert ) {
std::cout << "wasn't able to load CSR" << std::endl;
- return 2;
+ jp->failJob( job );
+ continue;
}
- std::cout << "Found a CSR at '" << cert->csr << "' signing" << std::endl;
+ log << "FINE: Found the CSR at '" << cert->csr << "'" << std::endl;
cert->csr_content = readFile( cert->csr );
- std::cout << cert->csr_content << " content " << std::endl;
+ log << "FINE: CSR is " << std::endl << cert->csr_content << std::endl;
std::shared_ptr<SignedCertificate> res = sign->sign( cert );
if( !res ) {
- std::cout << "Error no cert came back." << std::endl;
+ log << "ERROR: The signer failed. There was no certificate." << std::endl;
+ jp->failJob( job );
continue;
}
- std::cout << "did it!" << res->certificate << std::endl;
+ 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 );
res->crt_name = fn;
jp->writeBack( job, res );
- std::cout << "wrote back" << std::endl;
+ log << "FINE: signing done." << std::endl;
+
+ if( DAEMON ) {
+ jp->finishJob( job );
+ }
+
+ continue;
} catch( const char* c ) {
- std::cerr << "ERROR: " << c << std::endl;
- return 2;
+ log << "ERROR: " << c << std::endl;
} catch( std::string c ) {
- std::cerr << "ERROR: " << c << std::endl;
- return 2;
+ log << "ERROR: " << c << std::endl;
}
- } else {
- std::cout << "Unknown job type" << job->task << std::endl;
- }
- if( DAEMON && !jp->finishJob( job ) ) {
- return 1;
+ try {
+ jp->failJob( job );
+ } catch( const char* c ) {
+ log << "ERROR: " << c << std::endl;
+ } catch( std::string c ) {
+ log << "ERROR: " << c << std::endl;
+ }
+ } else {
+ log << "Unknown job type" << job->task << std::endl;
}
if( !DAEMON || once ) {
#define DAEMON true
#endif
-int handlermain( int argc, const char* argv[] );
-
extern std::string serialPath;
extern std::vector<Profile> profiles;
struct Job {
std::string id;
+ std::string warning;
std::string target;
std::string task;
std::string from;
class JobProvider {
public:
virtual std::shared_ptr<Job> fetchJob() = 0;
- virtual bool finishJob( std::shared_ptr<Job> job ) = 0;
+ virtual void finishJob( std::shared_ptr<Job> job ) = 0;
+ virtual void failJob( std::shared_ptr<Job> job ) = 0;
virtual std::shared_ptr<TBSCertificate> fetchTBSCert( std::shared_ptr<Job> job ) = 0;
virtual void writeBack( std::shared_ptr<Job> job, std::shared_ptr<SignedCertificate> res ) = 0;
};
}
std::shared_ptr<Job> MySQLJobProvider::fetchJob() {
- std::string q = "SELECT id, targetId, task, executeFrom, executeTo FROM jobs WHERE state='open'";
+ std::string q = "SELECT id, targetId, task, executeFrom, executeTo, warning FROM jobs WHERE state='open' AND warning < 3";
int err = 0;
std::shared_ptr<MYSQL_RES> res;
job->task = std::string( row[2], row[2] + l[2] );
job->from = std::string( row[3], row[3] + l[3] );
job->to = std::string( row[4], row[4] + l[4] );
+ job->warning = std::string( row[5], row[5] + l[5] );
for( unsigned int i = 0; i < num; i++ ) {
printf( "[%.*s] ", ( int ) l[i], row[i] ? row[i] : "NULL" );
return result;
}
-bool MySQLJobProvider::finishJob( std::shared_ptr<Job> job ) {
+void MySQLJobProvider::finishJob( std::shared_ptr<Job> job ) {
if( !conn ) {
- return false;
+ throw "Not connected!";
}
std::string q = "UPDATE jobs SET state='done' WHERE id='" + this->escape_string( job->id ) + "' LIMIT 1";
if( query( q ).first ) {
- return false;
+ throw "No database entry found.";
}
- return true;
+}
+
+void MySQLJobProvider::failJob( std::shared_ptr<Job> job ) {
+ if( !conn ) {
+ throw "Not connected!";
+ }
+
+ std::string q = "UPDATE jobs SET warning = warning + 1 WHERE id='" + this->escape_string( job->id ) + "' LIMIT 1";
+
+ if( query( q ).first ) {
+ throw "No database entry found.";
+ }
}
std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<Job> job ) {
public:
std::shared_ptr<Job> fetchJob();
- bool finishJob( std::shared_ptr<Job> job );
+ void finishJob( std::shared_ptr<Job> job );
+ void failJob( std::shared_ptr<Job> job );
std::shared_ptr<TBSCertificate> fetchTBSCert( std::shared_ptr<Job> job );
void writeBack( std::shared_ptr<Job> job, std::shared_ptr<SignedCertificate> res );
};
return ss.str();
}
-void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr<OpensslBIO> bio ) {
+void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr<OpensslBIO> bio, std::shared_ptr<std::ostream> log ) {
head.payloadLength = data.size();
std::string s;
s += head.packToString();
s += data;
std::string res = toHexAndChecksum( s );
+
+ if( log ) {
+ ( *log.get() ) << "FINE: RECORD output: " << res << std::endl;
+ }
+
bio->write( res.data(), res.size() );
}
return res;
}
-std::string parseCommand( RecordHeader& head, const std::string& input ) {
+std::string parseCommand( RecordHeader& head, const std::string input, std::shared_ptr<std::ostream> log ) {
+ if( log ) {
+ ( *log.get() ) << "FINE: RECORD input: " << input << std::endl;
+ }
+
int32_t dlen = ( input.size() - 2 ) / 2;
char checksum = 0;
bool error = false;
};
-std::string parseCommand( RecordHeader& head, const std::string& input );
+std::string parseCommand( RecordHeader& head, const std::string input, std::shared_ptr<std::ostream> log );
-void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr<OpensslBIO> bio );
+void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr<OpensslBIO> bio, std::shared_ptr<std::ostream> log );
#include <unistd.h>
#include <iostream>
+#include <fstream>
+#include <ctime>
#include <openssl/ssl.h>
DefaultRecordHandler* parent;
std::shared_ptr<Signer> signer;
+ std::shared_ptr<std::ofstream> log;
+
RecordHandlerSession( DefaultRecordHandler* parent, std::shared_ptr<Signer> signer, std::shared_ptr<SSL_CTX> ctx, std::shared_ptr<BIO> output ) :
tbs( new TBSCertificate() ) {
this->parent = parent;
this->signer = signer;
+ time_t c_time;
+
+ if( time( &c_time ) == -1 ) {
+ throw "Error while fetching time?";
+ }
+
+ log = std::shared_ptr<std::ofstream>(
+ new std::ofstream( std::string( "logs/log_" ) + std::to_string( c_time ) ),
+ []( std::ofstream * ptr ) {
+ ptr->close();
+ delete ptr;
+ } );
ssl = std::shared_ptr<SSL>( SSL_new( ctx.get() ), SSL_free );
std::shared_ptr<BIO> bio(
rh.flags = 0;
rh.command_count = 0; // TODO i++
rh.totalLength = payload.size();
- sendCommand( rh, payload, io );
+ sendCommand( rh, payload, io, log );
}
void work() {
try {
RecordHeader head;
- std::string payload = parseCommand( head, content );
+ std::string payload = parseCommand( head, content, log );
execute( head, payload );
} catch( const char* msg ) {
- std::cout << msg << std::endl;
+ if( log ) {
+ ( *log ) << "ERROR: " << msg << std::endl;
+ }
+
parent->reset();
return;
}
case RecordHeader::SignerCommand::SET_CSR: // setCSR
tbs->csr_content = data;
tbs->csr_type = "CSR";
- std::cout << "CSR read" << std::endl;
+ ( *log ) << "INFO: CSR read:" << std::endl << tbs->csr_content;
break;
case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE:
case RecordHeader::SignerCommand::SIGN:
result = signer->sign( tbs );
- std::cout << "res: " << result->certificate << std::endl;
- result->log = "I am a dummy log.\nI signed that thing ;-) \n";
+ ( *log ) << "INFO: signlog: " << result->log << std::endl;
+ ( *log ) << "INFO: res: " << result->certificate << std::endl;
respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log );
break;
}
if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
- std::cout << "SSL close failed" << std::endl;
+ ( *log ) << "ERROR: SSL close failed" << std::endl;
}
break;
head.command = ( uint16_t ) cmd;
head.command_count++;
head.totalLength = data.size();
- sendCommand( head, data, bio );
+ sendCommand( head, data, bio, log );
}
}
RecordHeader head;
- std::string payload = parseCommand( head, std::string( buffer.data(), length ) );
+ std::string payload = parseCommand( head, std::string( buffer.data(), length ), log );
switch( ( RecordHeader::SignerResult ) head.command ) {
case RecordHeader::SignerResult::CERTIFICATE:
return result;
}
+void RemoteSigner::setLog( std::shared_ptr<std::ostream> target ) {
+ this->log = target;
+}
private:
std::shared_ptr<BIO> target;
std::shared_ptr<SSL_CTX> ctx;
+ std::shared_ptr<std::ostream> log;
int count = 0;
void send( std::shared_ptr<OpensslBIOWrapper> bio, RecordHeader& head, RecordHeader::SignerCommand cmd, std::string data );
public:
RemoteSigner( std::shared_ptr<BIO> target, std::shared_ptr<SSL_CTX> ctx );
~RemoteSigner();
std::shared_ptr<SignedCertificate> sign( std::shared_ptr<TBSCertificate> cert );
+ void setLog( std::shared_ptr<std::ostream> target );
};
#include "simpleOpensslSigner.h"
#include <iostream>
+#include <sstream>
#include <openssl/ssl.h>
#include <openssl/err.h>
}
std::shared_ptr<SignedCertificate> SimpleOpensslSigner::sign( std::shared_ptr<TBSCertificate> cert ) {
+ std::stringstream signlog;
+
if( !prof.ca ) {
throw "CA-key not found";
}
+ signlog << "FINE: CA-key is correctly loaded." << std::endl;
+
std::shared_ptr<X509Req> req;
if( cert->csr_type == "SPKAC" ) {
} else if( i == 0 ) {
throw "Signature did not match";
} else {
- std::cerr << "Signature ok" << std::endl;
+ signlog << "FINE: Signature ok" << std::endl;
}
// Construct the Certificate
}
for( std::shared_ptr<AVA> a : cert->AVAs ) {
+ signlog << "Addings RDN: " << a->name << ": " << a->value << std::endl;
+
if( a->name == "CN" ) {
c.addRDN( NID_commonName, a->value );
} else if( a->name == "EMAIL" ) {
std::shared_ptr<BIGNUM> ser = nextSerial( profile );
c.setSerialNumber( ser.get() );
c.setTimes( 0, 60 * 60 * 24 * 10 );
+ signlog << "FINE: Setting extensions." << std::endl;
c.setExtensions( prof.ca, cert->SANs );
-
+ signlog << "FINE: Signed" << std::endl;
std::shared_ptr<SignedCertificate> output = c.sign( prof.caKey, cert->md );
-
+ signlog << "FINE: all went well" << std::endl;
+ output->log = signlog.str();
return output;
}