]> WPIA git - cassiopeia.git/commitdiff
add: Add support for Subject Alternative Names (SANs)
authorFelix Dörre <felix@dogcraft.de>
Sun, 2 Nov 2014 00:32:56 +0000 (01:32 +0100)
committerBenny Baumann <BenBE@geshi.org>
Fri, 7 Nov 2014 22:53:04 +0000 (23:53 +0100)
src/X509.cpp
src/X509.h
src/database.h
src/main.cpp
src/mysql.cpp
src/simpleOpensslSigner.cpp

index 2e441b2c993e008ac3d6d9f9051ffcdee0b7ae5a..5d38e3cb241547561a1336b6281fafbed2330165 100644 (file)
@@ -1,5 +1,7 @@
 #include "X509.h"
 
 #include "X509.h"
 
+#include <iostream>
+
 #include <openssl/ssl.h>
 #include <openssl/bio.h>
 #include <openssl/x509v3.h>
 #include <openssl/ssl.h>
 #include <openssl/bio.h>
 #include <openssl/x509v3.h>
@@ -95,7 +97,40 @@ void X509Cert::setTimes( long before, long after ) {
     X509_gmtime_adj( X509_get_notAfter( target.get() ), after );
 }
 
     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_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" );
@@ -103,6 +138,38 @@ void X509Cert::setExtensions( std::shared_ptr<X509> caCert ) {
     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" );
     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 ) {
 }
 
 std::string X509Cert::sign( std::shared_ptr<EVP_PKEY> caKey ) {
@@ -111,6 +178,7 @@ std::string X509Cert::sign( std::shared_ptr<EVP_PKEY> caKey ) {
     }
 
     X509_print_fp( stdout, target.get() );
     }
 
     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;
     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;
index a9d60e67abd0850f81e7f62d64b97fe6c7aa901c..66165809a2afc2b8813a10e44b6b0803738708fc 100644 (file)
@@ -1,7 +1,12 @@
 #pragma once
 #pragma once
+
 #include <memory>
 #include <memory>
+#include <vector>
+
 #include <openssl/ssl.h>
 
 #include <openssl/ssl.h>
 
+#include "database.h"
+
 class X509Req {
 private:
     std::shared_ptr<EVP_PKEY> pk;
 class X509Req {
 private:
     std::shared_ptr<EVP_PKEY> pk;
@@ -21,8 +26,7 @@ public:
     void setIssuerNameFrom( std::shared_ptr<X509> ca );
     void setPubkeyFrom( std::shared_ptr<X509Req> r );
     void setSerialNumber( int num );
     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 );
 };
     void setTimes( long before, long after );
     std::string sign( std::shared_ptr<EVP_PKEY> caKey );
 };
-
index 46aed6c012ba0fec675371e1fb4890347008359f..a80b73ed69f2703f9292329d90dd9a068f4b9ab8 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <string>
 #include <memory>
 
 #include <string>
 #include <memory>
+#include <vector>
 
 struct Job {
     std::string id;
 
 struct Job {
     std::string id;
@@ -10,6 +11,12 @@ struct Job {
     std::string from;
     std::string to;
 };
     std::string from;
     std::string to;
 };
+
+struct SAN {
+    std::string content;
+    std::string type;
+};
+
 struct TBSCertificate {
     std::string CN;
     std::string subj;
 struct TBSCertificate {
     std::string CN;
     std::string subj;
@@ -18,6 +25,7 @@ struct TBSCertificate {
     std::string csr;
     std::string csr_type;
     std::string csr_content;
     std::string csr;
     std::string csr_type;
     std::string csr_content;
+    std::vector<std::shared_ptr<SAN>> SANs;
 };
 
 class JobProvider {
 };
 
 class JobProvider {
index e03c361be0d91c363f64bb41083086f9469a46bf..2d42e848461e2e34555d3b1f857003ed66cd5047 100644 (file)
@@ -42,12 +42,19 @@ int main( int argc, const char* argv[] ) {
     if( job->task == "sign" ) {
         try {
             std::shared_ptr<TBSCertificate> cert = jp->fetchTBSCert( job );
     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;
             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;
         }
     }
 
         }
     }
 
index ab37553ce1899f1fd00c776264398b24209559c8..66c24427411664c1aceb23605e5679aa63520611 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdio.h>
 
 
 #include <stdio.h>
 
+#include <iostream>
+
 #include <mysql/errmsg.h>
 
 //This static variable exists to handle initializing and finalizing the MySQL driver library
 #include <mysql/errmsg.h>
 
 //This static variable exists to handle initializing and finalizing the MySQL driver library
@@ -93,7 +95,7 @@ std::pair< int, std::shared_ptr<MYSQL_RES> > MySQLJobProvider::query( const std:
     int err = mysql_real_query( this->conn.get(), query.c_str(), query.size() );
 
     if( err ) {
     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;
     }
 
     auto c = conn;
@@ -153,7 +155,7 @@ std::shared_ptr<Job> MySQLJobProvider::fetchJob() {
     return job;
 }
 
     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!";
     }
     if( !conn ) {
         throw "Not connected!";
     }
@@ -185,9 +187,10 @@ bool MySQLJobProvider::finishJob( 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::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;
 
     int err = 0;
+
     std::shared_ptr<MYSQL_RES> res;
 
     std::tie( err, res ) = query( q );
     std::shared_ptr<MYSQL_RES> res;
 
     std::tie( err, res ) = query( q );
@@ -215,5 +218,28 @@ std::shared_ptr<TBSCertificate> MySQLJobProvider::fetchTBSCert( std::shared_ptr<
     cert->csr = std::string( row[4], row[4] + l[4] );
     cert->csr_type = std::string( row[5], row[5] + l[5] );
 
     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;
 }
     return cert;
 }
index 89151a665fa0c9f8214e57ff25ffd33ba6164666..e38aeb1208c9986bd583b50b5ac41b5ec1c6bb83 100644 (file)
 std::shared_ptr<int> SimpleOpensslSigner::lib_ref(
     new int( SSL_library_init() ),
     []( int* ref ) {
 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 ) {
     } );
 
 std::shared_ptr<X509> loadX509FromFile( std::string filename ) {
@@ -92,8 +95,8 @@ void SimpleOpensslSigner::sign( std::shared_ptr<TBSCertificate> cert ) {
     c.setIssuerNameFrom( caCert );
     c.setPubkeyFrom( req );
     c.setSerialNumber( 4711 );
     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 );
 
 
     std::string output = c.sign( caKey );