]> WPIA git - cassiopeia.git/blobdiff - src/crypto/X509.cpp
fix: better choose CAcert if multiple are available
[cassiopeia.git] / src / crypto / X509.cpp
index ba39b4bcef68287bd15ef8ce5247c44b853f6ccd..caa2a9dfe0ff52435570faee628d9a7c8b88f1b0 100644 (file)
@@ -7,8 +7,7 @@
 #include <openssl/bio.h>
 #include <openssl/x509v3.h>
 
-X509Req::X509Req( X509_REQ* csr ) {
-    req = std::shared_ptr<X509_REQ>( csr, X509_REQ_free );
+X509Req::X509Req( X509_REQ* csr ) : req( csr, X509_REQ_free ) {
     EVP_PKEY* pkt = X509_REQ_get_pubkey( req.get() );
 
     if( !pkt ) {
@@ -48,7 +47,7 @@ int X509Req::verify() {
     return X509_REQ_verify( req.get(), pk.get() );
 }
 
-std::shared_ptr<EVP_PKEY> X509Req::getPkey() {
+std::shared_ptr<EVP_PKEY> X509Req::getPkey() const {
     return pk;
 }
 
@@ -60,7 +59,7 @@ std::shared_ptr<X509Req> X509Req::parseCSR( std::string content ) {
         throw "Error parsing CSR";
     }
 
-    return std::shared_ptr<X509Req>( new X509Req( req ) );
+    return std::shared_ptr<X509Req>( new X509Req( req )); // TODO ask
 }
 
 std::shared_ptr<X509Req> X509Req::parseSPKAC( std::string content ) {
@@ -107,7 +106,7 @@ X509Cert::X509Cert() {
     X509_NAME* subjectP = X509_NAME_new();
 
     if( !subjectP ) {
-        throw "malloc failure";
+        throw "malloc failure in construct.";
     }
 
     subject = std::shared_ptr<X509_NAME>( subjectP, X509_NAME_free );
@@ -115,7 +114,7 @@ X509Cert::X509Cert() {
 
 void X509Cert::addRDN( int nid, std::string data ) {
     if( ! X509_NAME_add_entry_by_NID( subject.get(), nid, MBSTRING_UTF8, ( unsigned char* )const_cast<char*>( data.data() ), data.size(), -1, 0 ) ) {
-        throw "malloc failure";
+        throw "malloc failure in RDN";
     }
 }
 
@@ -175,17 +174,17 @@ merr:
     throw "memerr";
 }
 
-void X509Cert::setExtensions( std::shared_ptr<X509> caCert, std::vector<std::shared_ptr<SAN>>& sans, Profile& prof ) {
+void X509Cert::setExtensions( std::shared_ptr<X509> caCert, std::vector<std::shared_ptr<SAN>>& sans, Profile& prof, std::string crlURL, std::string crtURL ) {
     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" );
     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" );
+    add_ext( caCert, target, NID_info_access, ("OCSP;URI:http://ocsp.cacert.org,caIssuers;URI:" + crtURL).c_str() );
+    add_ext( caCert, target, NID_crl_distribution_points, ("URI:" + crlURL).c_str() );
 
-    if( sans.size() == 0 ) {
+    if( sans.empty() ) {
         return;
     }
 
@@ -248,15 +247,31 @@ std::shared_ptr<SignedCertificate> X509Cert::sign( std::shared_ptr<EVP_PKEY> caK
     //X509_print_fp( stdout, target.get() );
 
     std::shared_ptr<BIO> mem = std::shared_ptr<BIO>( BIO_new( BIO_s_mem() ), BIO_free );
+
+    if( !mem ) {
+        throw "Failed to allocate memory for the signed certificate.";
+    }
+
     PEM_write_bio_X509( mem.get(), target.get() );
-    BUF_MEM* buf;
+
+    BUF_MEM* buf = NULL;
     BIO_get_mem_ptr( mem.get(), &buf );
-    std::shared_ptr<SignedCertificate> res = std::shared_ptr<SignedCertificate>( new SignedCertificate() );
+
+    auto res = std::make_shared<SignedCertificate>();
     res->certificate = std::string( buf->data, buf->data + buf->length );
-    BIGNUM* ser = ASN1_INTEGER_to_BN( target->cert_info->serialNumber, NULL );
-    char* serStr = BN_bn2hex( ser );
-    res->serial = std::string( serStr );
-    OPENSSL_free( serStr );
-    BN_free( ser );
+
+    std::shared_ptr<BIGNUM> ser( ASN1_INTEGER_to_BN( target->cert_info->serialNumber, NULL ), BN_free );
+
+    if( !ser ) {
+        throw "Failed to retrieve certificate serial of signed certificate.";
+    }
+
+    std::shared_ptr<char> serStr(
+        BN_bn2hex( ser.get() ),
+        []( char* p ) {
+            OPENSSL_free( p );
+        } ); // OPENSSL_free is a macro...
+    res->serial = serStr ? std::string( serStr.get() ) : "";
+
     return res;
 }