]> WPIA git - cassiopeia.git/blob - src/remoteSigner.cpp
a17f515c566078f1be6b0425fc66f0eece7a57f6
[cassiopeia.git] / src / remoteSigner.cpp
1 #include "remoteSigner.h"
2
3 #include <iostream>
4
5 RemoteSigner::RemoteSigner( std::shared_ptr<BIO> target, std::shared_ptr<SSL_CTX> ctx ) {
6     this->target = target;
7     this->ctx = ctx;
8 }
9 RemoteSigner::~RemoteSigner() {
10 }
11
12 void RemoteSigner::send( std::shared_ptr<OpensslBIOWrapper> bio, RecordHeader& head, RecordHeader::SignerCommand cmd, std::string data ) {
13     head.command = ( uint16_t ) cmd;
14     head.command_count++;
15     head.totalLength = data.size();
16     sendCommand( head, data, bio );
17
18 }
19
20 std::shared_ptr<SignedCertificate> RemoteSigner::sign( std::shared_ptr<TBSCertificate> cert ) {
21     ( void )BIO_reset( target.get() );
22
23     std::shared_ptr<SSL> ssl( SSL_new( ctx.get() ), SSL_free );
24     std::shared_ptr<BIO> bio( BIO_new( BIO_f_ssl() ), BIO_free );
25     SSL_set_connect_state( ssl.get() );
26     SSL_set_bio( ssl.get(), target.get(), target.get() );
27     BIO_set_ssl( bio.get(), ssl.get(), BIO_NOCLOSE );
28     std::shared_ptr<OpensslBIOWrapper> conn( new OpensslBIOWrapper( bio ) );
29     RecordHeader head;
30     head.flags = 0;
31     head.sessid = 13;
32
33     if( cert->csr_type == "CSR" ) {
34         send( conn, head, RecordHeader::SignerCommand::SET_CSR, cert->csr_content );
35     } else {
36         std::cout << "Unknown csr_type: " << cert->csr_type;
37         return std::shared_ptr<SignedCertificate>();
38     }
39
40     send( conn, head, RecordHeader::SignerCommand::SET_SIGNATURE_TYPE, cert->md );
41     send( conn, head, RecordHeader::SignerCommand::SET_PROFILE, cert->profile );
42
43     for( auto ava : cert->AVAs ) {
44         if( ava->name.find( "," ) != std::string::npos ) {
45             // invalid ava
46             return std::shared_ptr<SignedCertificate>();
47         }
48
49         send( conn, head, RecordHeader::SignerCommand::ADD_AVA, ava->name + "," + ava->value );
50     }
51
52     for( auto san : cert->SANs ) {
53         if( san->type.find( "," ) != std::string::npos ) {
54             // invalid ava
55             return std::shared_ptr<SignedCertificate>();
56         }
57
58         send( conn, head, RecordHeader::SignerCommand::ADD_SAN, san->type + "," + san->content );
59     }
60
61     send( conn, head, RecordHeader::SignerCommand::SIGN, "" );
62     send( conn, head, RecordHeader::SignerCommand::LOG_SAVED, "" );
63     std::shared_ptr<SignedCertificate> result = std::shared_ptr<SignedCertificate>( new SignedCertificate() );
64     std::vector<char> buffer( 2048 * 4 );
65
66     for( int i = 0; i < 2; i++ ) {
67         try {
68             int length = conn->read( buffer.data(), buffer.size() );
69
70             if( length == -1 ) {
71                 return std::shared_ptr<SignedCertificate>();
72             }
73
74             RecordHeader head;
75             std::string payload = parseCommand( head, std::string( buffer.data(), length ) );
76
77             switch( ( RecordHeader::SignerResult ) head.command ) {
78             case RecordHeader::SignerResult::CERTIFICATE:
79                 result->certificate = payload;
80                 break;
81
82             case RecordHeader::SignerResult::SAVE_LOG:
83                 result->log = payload;
84                 break;
85             }
86         } catch( const char* msg ) {
87             std::cout << msg << std::endl;
88             return std::shared_ptr<SignedCertificate>();
89         }
90     }
91
92     if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) { // need to close the connection twice
93         std::cout << "SSL shutdown failed" << std::endl;
94     }
95
96     return result;
97 }
98