#include "X509.h"
+#include <iostream>
+
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/x509v3.h>
X509_gmtime_adj( X509_get_notAfter( target.get() ), after );
}
-void X509Cert::setExtensions( std::shared_ptr<X509> caCert ) {
+static X509_EXTENSION* do_ext_i2d( int ext_nid, int crit, ASN1_VALUE* ext_struc ) {
+ unsigned char* ext_der;
+ int ext_len;
+ ASN1_OCTET_STRING* ext_oct;
+ X509_EXTENSION* ext;
+ /* Convert internal representation to DER */
+ ext_der = NULL;
+ ext_len = ASN1_item_i2d( ext_struc, &ext_der, ASN1_ITEM_ptr( ASN1_ITEM_ref( GENERAL_NAMES ) ) );
+
+ if( ext_len < 0 ) {
+ goto merr;
+ }
+
+ if( !( ext_oct = M_ASN1_OCTET_STRING_new() ) ) {
+ goto merr;
+ }
+
+ ext_oct->data = ext_der;
+ ext_oct->length = ext_len;
+
+ ext = X509_EXTENSION_create_by_NID( NULL, ext_nid, crit, ext_oct );
+
+ if( !ext ) {
+ goto merr;
+ }
+
+ M_ASN1_OCTET_STRING_free( ext_oct );
+ return ext;
+
+merr:
+ throw "memerr";
+}
+
+void X509Cert::setExtensions( std::shared_ptr<X509> caCert, std::vector<std::shared_ptr<SAN>>& sans ) {
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_ext_key_usage, "clientAuth, serverAuth" );
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" );
+
+ std::shared_ptr<GENERAL_NAMES> gens = std::shared_ptr<GENERAL_NAMES>(
+ sk_GENERAL_NAME_new_null(),
+ []( GENERAL_NAMES * ref ) {
+ if( ref ) {
+ sk_GENERAL_NAME_pop_free( ref, GENERAL_NAME_free );
+ }
+ } );
+
+ for( auto& name : sans ) {
+ GENERAL_NAME* gen = GENERAL_NAME_new();
+
+ if( !gen ) {
+ throw "Malloc failure.";
+ }
+
+ gen->type = name->type == "DNS" ? GEN_DNS : name->type == "email" ? GEN_EMAIL : 0; // GEN_EMAIL;
+
+ if( !gen->type
+ || !( gen->d.ia5 = M_ASN1_IA5STRING_new() )
+ || !ASN1_STRING_set( gen->d.ia5, name->content.data(), name->content.size() ) ) {
+ GENERAL_NAME_free( gen );
+ throw "initing iasting5 failed";
+ }
+
+ sk_GENERAL_NAME_push( gens.get(), gen );
+ }
+
+ X509_EXTENSION* ext = do_ext_i2d( NID_subject_alt_name, 0/*critical*/, ( ASN1_VALUE* )gens.get() );
+
+ X509_add_ext( target.get(), ext, -1 );
+ X509_EXTENSION_free( ext );
}
std::string X509Cert::sign( std::shared_ptr<EVP_PKEY> caKey ) {
}
X509_print_fp( stdout, target.get() );
+
std::shared_ptr<BIO> mem = std::shared_ptr<BIO>( BIO_new( BIO_s_mem() ), BIO_free );
PEM_write_bio_X509( mem.get(), target.get() );
BUF_MEM* buf;
#pragma once
+
#include <memory>
+#include <vector>
+
#include <openssl/ssl.h>
+#include "database.h"
+
class X509Req {
private:
std::shared_ptr<EVP_PKEY> pk;
void setIssuerNameFrom( std::shared_ptr<X509> ca );
void setPubkeyFrom( std::shared_ptr<X509Req> r );
void setSerialNumber( int num );
- void setExtensions( std::shared_ptr<X509> caCert );
+ void setExtensions( std::shared_ptr<X509> caCert, std::vector<std::shared_ptr<SAN>>& sans );
void setTimes( long before, long after );
std::string sign( std::shared_ptr<EVP_PKEY> caKey );
};
-
#include <string>
#include <memory>
+#include <vector>
struct Job {
std::string id;
std::string from;
std::string to;
};
+
+struct SAN {
+ std::string content;
+ std::string type;
+};
+
struct TBSCertificate {
std::string CN;
std::string subj;
std::string csr;
std::string csr_type;
std::string csr_content;
+ std::vector<std::shared_ptr<SAN>> SANs;
};
class JobProvider {
if( job->task == "sign" ) {
try {
std::shared_ptr<TBSCertificate> cert = jp->fetchTBSCert( job );
+
+ if( !cert ) {
+ std::cout << "wasn't able to load CSR" << std::endl;
+ return 2;
+ }
+
std::cout << "Found a CSR at '" << cert->csr << "' signing" << std::endl;
std::ifstream t( cert->csr );
cert->csr_content = std::string( std::istreambuf_iterator<char>( t ), std::istreambuf_iterator<char>() );
sign->sign( cert );
} catch( const char* c ) {
std::cerr << c << std::endl;
+ return 2;
}
}
#include <stdio.h>
+#include <iostream>
+
#include <mysql/errmsg.h>
//This static variable exists to handle initializing and finalizing the MySQL driver library
int err = mysql_real_query( this->conn.get(), query.c_str(), query.size() );
if( err ) {
- return std::make_pair( err, std::shared_ptr<MYSQL_RES>() );
+ throw( std::string( "MySQL error: " ) + mysql_error( this->conn.get() ) ).c_str();
}
auto c = conn;
return job;
}
-std::string MySQLJobProvider::escape_string( const std::string& target ) {
+std::string MySQLJobProvider::escape_string( const std::string & target ) {
if( !conn ) {
throw "Not connected!";
}
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 CN, subject, md, profile, csr_name, csr_type FROM certs WHERE id='" + this->escape_string( job->id ) + "'";
+ std::string q = "SELECT CN, subject, md, profile, csr_name, csr_type FROM certs WHERE id='" + this->escape_string( job->target ) + "'";
int err = 0;
+
std::shared_ptr<MYSQL_RES> res;
std::tie( err, res ) = query( q );
cert->csr = std::string( row[4], row[4] + l[4] );
cert->csr_type = std::string( row[5], row[5] + l[5] );
+ cert->SANs = std::vector<std::shared_ptr<SAN>>();
+
+ q = "SELECT contents, type FROM subjectAlternativeNames WHERE certId='" + this->escape_string( job->target ) + "'";
+ std::tie( err, res ) = query( q );
+
+ if( err ) {
+ std::cout << mysql_error( this->conn.get() );
+ return std::shared_ptr<TBSCertificate>();
+ }
+
+ while( ( row = mysql_fetch_row( res.get() ) ) ) {
+ unsigned long* l = mysql_fetch_lengths( res.get() );
+
+ if( !l ) {
+ return std::shared_ptr<TBSCertificate>();
+ }
+
+ std::shared_ptr<SAN> nSAN = std::shared_ptr<SAN>( new SAN() );
+ nSAN->content = std::string( row[0], row[0] + l[0] );
+ nSAN->type = std::string( row[1], row[1] + l[1] );
+ cert->SANs.push_back( nSAN );
+ }
+
return cert;
}
std::shared_ptr<int> SimpleOpensslSigner::lib_ref(
new int( SSL_library_init() ),
[]( int* ref ) {
- ( void ) ref;
+ delete ref;
+
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
} );
std::shared_ptr<X509> loadX509FromFile( std::string filename ) {
c.setIssuerNameFrom( caCert );
c.setPubkeyFrom( req );
c.setSerialNumber( 4711 );
- c.setTimes( 0, 1000 * 60 * 60 * 24 * 10 );
- c.setExtensions( caCert );
+ c.setTimes( 0, 60 * 60 * 24 * 10 );
+ c.setExtensions( caCert, cert->SANs );
std::string output = c.sign( caKey );