]> WPIA git - cassiopeia.git/blob - src/recordHandler.cpp
chg: Tamper with the signature more efficiently
[cassiopeia.git] / src / recordHandler.cpp
1 #include "recordHandler.h"
2
3 #include <sys/types.h>
4 #include <sys/socket.h>
5 #include <netinet/in.h>
6 #include <arpa/inet.h>
7 #include <termios.h>
8 #include <unistd.h>
9
10 #include <iostream>
11
12 #include <openssl/ssl.h>
13
14 #include "database.h"
15 #include "record.h"
16 #include "opensslBIO.h"
17 #include "remoteSigner.h"
18 #include "simpleOpensslSigner.h"
19 #include "sslUtil.h"
20 #include "slipBio.h"
21
22 extern std::vector<Profile> profiles;
23
24 class RecordHandlerSession {
25 public:
26     uint32_t sessid;
27     uint32_t lastCommandCount;
28
29     std::shared_ptr<TBSCertificate> tbs;
30     std::shared_ptr<SignedCertificate> result;
31
32     SSL* ssl;
33
34     std::shared_ptr<OpensslBIOWrapper> io;
35     DefaultRecordHandler* parent;
36     std::shared_ptr<Signer> signer;
37
38     RecordHandlerSession( DefaultRecordHandler* parent, std::shared_ptr<Signer> signer, std::shared_ptr<SSL_CTX> ctx, std::shared_ptr<BIO> output ) :
39         tbs( new TBSCertificate() ) {
40         this->parent = parent;
41         this->signer = signer;
42
43         ssl = SSL_new( ctx.get() );
44         std::shared_ptr<BIO> bio(
45             BIO_new( BIO_f_ssl() ),
46             [output]( BIO * p ) {
47                 BIO_free( p );
48             } );
49         SSL_set_accept_state( ssl );
50         SSL_set_bio( ssl, output.get(), output.get() );
51         BIO_set_ssl( bio.get(), ssl, BIO_NOCLOSE );
52         io = std::shared_ptr<OpensslBIOWrapper>( new OpensslBIOWrapper( bio ) );
53     }
54
55     void respondCommand( RecordHeader::SignerResult res, std::string payload ) {
56         RecordHeader rh;
57         rh.command = ( uint16_t ) res;
58         rh.flags = 0;
59         rh.command_count = 0; // TODO i++
60         rh.totalLength = payload.size();
61         sendCommand( rh, payload, io );
62     }
63
64     void work() {
65         std::vector<char> buffer( 2048, 0 );
66         int res = io->read( buffer.data(), buffer.capacity() );
67
68         if( res <= 0 ) {
69             parent->reset();
70             return;
71         }
72
73         std::string content( buffer.data(), res );
74
75         try {
76             RecordHeader head;
77             std::string payload = parseCommand( head, content );
78             execute( head, payload );
79         } catch( const char* msg ) {
80             std::cout << msg << std::endl;
81             parent->reset();
82             return;
83         }
84     }
85
86     void execute( RecordHeader& head, std::string data ) {
87         if( head.totalLength != head.payloadLength || head.offset != 0 ) {
88             throw "Error, chunking not supported yet";
89         }
90
91         switch( ( RecordHeader::SignerCommand ) head.command ) {
92         case RecordHeader::SignerCommand::SET_CSR: // setCSR
93             tbs->csr_content = data;
94             tbs->csr_type = "CSR";
95             std::cout << "CSR read" << std::endl;
96             break;
97
98         case RecordHeader::SignerCommand::SET_SIGNATURE_TYPE:
99             tbs->md = data;
100             break;
101
102         case RecordHeader::SignerCommand::SET_PROFILE:
103             // TODO
104             tbs->profile = data;
105             break;
106
107         case RecordHeader::SignerCommand::ADD_SAN: {
108             size_t pos = data.find( "," );
109
110             if( pos == std::string::npos ) {
111             } else {
112                 std::shared_ptr<SAN> san( new SAN() );
113                 san->type = data.substr( 0, pos );
114                 san->content = data.substr( pos + 1 );
115                 tbs->SANs.push_back( san );
116             }
117         }
118         break;
119
120         case RecordHeader::SignerCommand::ADD_AVA: {
121             size_t pos = data.find( "," );
122
123             if( pos == std::string::npos ) {
124                 // error
125             } else {
126                 std::shared_ptr<AVA> ava( new AVA() );
127                 ava->name = data.substr( 0, pos );
128                 ava->value = data.substr( pos + 1 );
129                 tbs->AVAs.push_back( ava );
130             }
131         }
132         break;
133
134         case RecordHeader::SignerCommand::ADD_PROOF_LINE:
135             break;
136
137         case RecordHeader::SignerCommand::SIGN:
138             result = signer->sign( tbs );
139             std::cout << "res: " << result->certificate << std::endl;
140             result->log = "I am a dummy log.\nI signed that thing ;-) \n";
141             respondCommand( RecordHeader::SignerResult::SAVE_LOG, result->log );
142             break;
143
144         case RecordHeader::SignerCommand::LOG_SAVED:
145             if( result ) {
146                 respondCommand( RecordHeader::SignerResult::CERTIFICATE, result->certificate );
147             }
148
149             break;
150
151         default:
152             throw "Unimplemented";
153         }
154     }
155 };
156
157 DefaultRecordHandler::DefaultRecordHandler( std::shared_ptr<Signer> signer, std::shared_ptr<BIO> bio ) :
158     currentSession() {
159
160     this->signer = signer;
161
162     ctx = generateSSLContext( true );
163
164     this->bio = bio;
165 }
166
167 void DefaultRecordHandler::reset() {
168     currentSession = std::shared_ptr<RecordHandlerSession>();
169 }
170
171 void DefaultRecordHandler::handle() {
172     if( !currentSession ) {
173         std::cout << "session allocated" << std::endl;
174         currentSession = std::shared_ptr<RecordHandlerSession>( new RecordHandlerSession( this, signer, ctx, bio ) );
175     }
176
177     currentSession->work();
178 }
179
180 int handlermain( int argc, const char* argv[] ) {
181     ( void ) argc;
182     ( void ) argv;
183
184     std::shared_ptr<OpensslBIOWrapper> bio( new OpensslBIOWrapper( std::shared_ptr<BIO>( BIO_new_fd( 0, 0 ), BIO_free ) ) );
185     std::string data =
186         "-----BEGIN CERTIFICATE REQUEST-----\n"
187         "MIIBSzCBtQIBADAMMQowCAYDVQQDDAFhMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\n"
188         "iQKBgQDerBEpIShJlx3zzl4AOS1NcwEg4iAWknQeTtI8B5dnk+l5HkOdTxqeehZn\n"
189         "iZnuIuYXA+JWmoECg/w69+N5zw2BabelgK3cSvRqycwPEU/gceGJZTaBfkkN0hBk\n"
190         "rpXDiLSlox5oeR150MrsHvVc+W2e+0jW1tuhz4QLzn8/uI/toQIDAQABoAAwDQYJ\n"
191         "KoZIhvcNAQELBQADgYEATQU5VrgQAkvpCvIwRUyjj9YAa9E014tNY0jMcBdv95fy\n"
192         "/f49zIcVtUJuZuEwY6uDZQqfAm+8CLNpOCICH/Qw7YOe+s/Yw7a8rk5VqLtgxR4M\n"
193         "z6DUeVL0zYFoLUxIje9yDU3pWmPvyVaBPdo0DguZwFMfiWwzhkUDeQgyeaiMvQA=\n"
194         "-----END CERTIFICATE REQUEST-----";
195
196     RecordHeader head;
197     head.flags = 0;
198     head.sessid = 13;
199
200     //---
201
202     std::shared_ptr<int> ssl_lib = ssl_lib_ref;
203
204     if( argc >= 2 ) {
205         std::shared_ptr<BIO> b = openSerial( "/dev/ttyUSB0" );
206         std::shared_ptr<BIO> slip1( BIO_new( toBio<SlipBIO>() ), BIO_free );
207         ( ( SlipBIO* )slip1->ptr )->setTarget( std::shared_ptr<OpensslBIO>( new OpensslBIOWrapper( b ) ) );
208         std::shared_ptr<RemoteSigner> sign( new RemoteSigner( slip1, generateSSLContext( false ) ) );
209
210         std::shared_ptr<TBSCertificate> cert( new TBSCertificate() );
211         cert->csr_type = "csr";
212         cert->csr_content = data;
213         cert->md = "sha256";
214         cert->profile = "1";
215         std::shared_ptr<AVA> ava( new AVA() );
216         ava->name = "CN";
217         ava->value = "Dummy user certificates";
218         cert->AVAs.push_back( ava );
219         std::shared_ptr<SAN> san( new SAN() );
220         san->type = "DNS";
221         san->content = "n42.example.com";
222         cert->SANs.push_back( san );
223
224         auto res = sign->sign( cert );
225         std::cout << "log: " << res->log << std::endl;
226         std::cout << "cert things: " << res->certificate << std::endl;
227         return 0;
228     }
229
230     std::shared_ptr<BIO> conn = openSerial( "/dev/ttyS0" );
231     std::shared_ptr<BIO> slip1( BIO_new( toBio<SlipBIO>() ), BIO_free );
232
233     ( ( SlipBIO* )slip1->ptr )->setTarget( std::shared_ptr<OpensslBIO>( new OpensslBIOWrapper( conn ) ) );
234
235     try {
236         DefaultRecordHandler* dh = new DefaultRecordHandler( std::shared_ptr<Signer>( new SimpleOpensslSigner( profiles[0] ) ), slip1 );
237
238         while( true ) {
239             dh->handle();
240         }
241     } catch( char const* ch ) {
242         std::cout << "Exception: " << ch << std::endl;
243     }
244
245     return 0;
246 }