1 #include "remoteSigner.h"
3 #include "log/logger.hpp"
8 #include <openssl/ssl.h>
9 #include <openssl/bn.h>
11 RemoteSigner::RemoteSigner( std::shared_ptr<BIO> target, std::shared_ptr<SSL_CTX> ctx ) : target( target ), ctx( ctx ) {
14 RemoteSigner::~RemoteSigner() {
17 void RemoteSigner::send( std::shared_ptr<OpensslBIOWrapper> bio, RecordHeader& head, RecordHeader::SignerCommand cmd, std::string data ) {
18 head.command = ( uint16_t ) cmd;
20 head.totalLength = data.size();
21 sendCommand( head, data, bio );
24 std::shared_ptr<SignedCertificate> RemoteSigner::sign( std::shared_ptr<TBSCertificate> cert ) {
25 ( void )BIO_reset( target.get() );
27 std::shared_ptr<SSL> ssl( SSL_new( ctx.get() ), SSL_free );
28 std::shared_ptr<BIO> bio( BIO_new( BIO_f_ssl() ), BIO_free );
29 SSL_set_connect_state( ssl.get() );
30 SSL_set_bio( ssl.get(), target.get(), target.get() );
31 BIO_set_ssl( bio.get(), ssl.get(), BIO_NOCLOSE );
32 std::shared_ptr<OpensslBIOWrapper> conn( new OpensslBIOWrapper( bio ) );
37 if( cert->csr_type == "CSR" ) {
38 send( conn, head, RecordHeader::SignerCommand::SET_CSR, cert->csr_content );
39 } else if( cert->csr_type == "SPKAC" ) {
40 send( conn, head, RecordHeader::SignerCommand::SET_SPKAC, cert->csr_content );
42 logger::error( "Unknown csr_type: ", cert->csr_type );
43 return std::shared_ptr<SignedCertificate>();
46 send( conn, head, RecordHeader::SignerCommand::SET_SIGNATURE_TYPE, cert->md );
47 send( conn, head, RecordHeader::SignerCommand::SET_PROFILE, cert->profile );
48 send( conn, head, RecordHeader::SignerCommand::SET_WISH_FROM, cert->wishFrom );
49 send( conn, head, RecordHeader::SignerCommand::SET_WISH_TO, cert->wishTo );
51 for( auto ava : cert->AVAs ) {
52 if( ava->name.find( "," ) != std::string::npos ) {
54 return std::shared_ptr<SignedCertificate>();
57 send( conn, head, RecordHeader::SignerCommand::ADD_AVA, ava->name + "," + ava->value );
60 for( auto san : cert->SANs ) {
61 if( san->type.find( "," ) != std::string::npos ) {
63 return std::shared_ptr<SignedCertificate>();
66 send( conn, head, RecordHeader::SignerCommand::ADD_SAN, san->type + "," + san->content );
69 send( conn, head, RecordHeader::SignerCommand::SIGN, "" );
70 send( conn, head, RecordHeader::SignerCommand::LOG_SAVED, "" );
71 std::shared_ptr<SignedCertificate> result = std::shared_ptr<SignedCertificate>( new SignedCertificate() );
72 std::vector<char> buffer( 2048 * 4 );
74 for( int i = 0; i < 3; i++ ) {
76 int length = conn->read( buffer.data(), buffer.size() );
79 logger::error( "Error, no response data" );
80 result = std::shared_ptr<SignedCertificate>();
85 std::string payload = parseCommand( head, std::string( buffer.data(), length ) );
87 switch( ( RecordHeader::SignerResult ) head.command ) {
88 case RecordHeader::SignerResult::CERTIFICATE:
89 result->certificate = payload;
92 case RecordHeader::SignerResult::SAVE_LOG:
93 result->log = payload;
96 case RecordHeader::SignerResult::SIGNING_CA:
97 result->ca_name = payload;
101 logger::error( "Invalid Message" );
104 } catch( const char* msg ) {
105 logger::error( msg );
106 return std::shared_ptr<SignedCertificate>();
111 std::shared_ptr<BIO> bios( BIO_new( BIO_s_mem() ), BIO_free );
112 const char* buf = result->certificate.data();
113 unsigned int len = result->certificate.size();
116 int dlen = BIO_write( bios.get(), buf, len );
119 throw "Memory error.";
126 std::shared_ptr<X509> pem( PEM_read_bio_X509( bios.get(), NULL, 0, NULL ) );
129 throw "Pem was not readable";
132 std::shared_ptr<BIGNUM> ser( ASN1_INTEGER_to_BN( pem->cert_info->serialNumber, NULL ), BN_free );
133 std::shared_ptr<char> serStr(
134 BN_bn2hex( ser.get() ),
137 } ); // OPENSSL_free is a macro...
139 extractTimes( pem, result );
141 result->serial = std::string( serStr.get() );
144 if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) { // need to close the connection twice
145 logger::warn( "SSL shutdown failed" );
151 std::pair<std::shared_ptr<CRL>, std::string> RemoteSigner::revoke( std::shared_ptr<CAConfig> ca, std::vector<std::string> serials ) {
152 ( void )BIO_reset( target.get() );
154 std::shared_ptr<SSL> ssl( SSL_new( ctx.get() ), SSL_free );
155 std::shared_ptr<BIO> bio( BIO_new( BIO_f_ssl() ), BIO_free );
156 SSL_set_connect_state( ssl.get() );
157 SSL_set_bio( ssl.get(), target.get(), target.get() );
158 BIO_set_ssl( bio.get(), ssl.get(), BIO_NOCLOSE );
159 std::shared_ptr<OpensslBIOWrapper> conn( new OpensslBIOWrapper( bio ) );
165 for( std::string serial : serials ) {
166 send( conn, head, RecordHeader::SignerCommand::ADD_SERIAL, serial );
169 std::string payload = ca->name;
170 send( conn, head, RecordHeader::SignerCommand::REVOKE, payload );
172 std::vector<char> buffer( 2048 * 4 );
173 int length = conn->read( buffer.data(), buffer.size() );
176 throw "Error, no response data";
179 payload = parseCommand( head, std::string( buffer.data(), length ) );
181 std::shared_ptr<CRL> crl( new CRL( ca->path + std::string( "/ca.crl" ) ) );
184 if( ( RecordHeader::SignerResult ) head.command != RecordHeader::SignerResult::REVOKED ) {
185 throw "Protocol violation";
188 const unsigned char* buffer2 = ( const unsigned char* ) payload.data();
189 const unsigned char* pos = buffer2;
190 ASN1_TIME* time = d2i_ASN1_TIME( NULL, &pos, payload.size() );
191 ASN1_TIME_free( time );
192 date = payload.substr( 0, pos - buffer2 );
193 std::string rest = payload.substr( pos - buffer2 );
195 for( std::string serial : serials ) {
196 crl->revoke( serial, date );
199 crl->setSignature( rest );
200 bool ok = crl->verify( ca );
203 logger::note( "CRL verificated successfully" );
204 writeFile( ca->path + std::string( "/ca.crl" ), crl->toString() );
206 logger::warn( "CRL is broken, trying to recover" );
207 send( conn, head, RecordHeader::SignerCommand::GET_FULL_CRL, ca->name );
208 length = conn->read( buffer.data(), buffer.size() );
211 throw "Error, no response data";
214 payload = parseCommand( head, std::string( buffer.data(), length ) );
216 if( ( RecordHeader::SignerResult ) head.command != RecordHeader::SignerResult::FULL_CRL ) {
217 throw "Protocol violation";
220 writeFile( ca->path + std::string( "/ca.crl.bak" ), payload );
221 crl = std::shared_ptr<CRL>( new CRL( ca->path + std::string( "/ca.crl.bak" ) ) );
223 if( crl->verify( ca ) ) {
224 writeFile( ca->path + std::string( "/ca.crl" ), crl->toString() );
225 logger::note( "CRL is now valid again" );
227 logger::warn( "CRL is still broken... Please, help me" );
231 logger::debug( "CRL:\n", crl->toString() );
233 if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) { // need to close the connection twice
234 logger::warn( "SSL shutdown failed" );
237 return std::pair<std::shared_ptr<CRL>, std::string>( crl, date );
240 void RemoteSigner::setLog( std::shared_ptr<std::ostream> target ) {