1
1
#include " interconnect_stream.h"
2
+ #include " interconnect_common.h"
2
3
#include " logging.h"
3
4
#include " poller_actor.h"
4
5
#include < library/cpp/openssl/init/init.h>
@@ -287,10 +288,12 @@ namespace NInterconnect {
287
288
288
289
class TSecureSocketContext ::TImpl {
289
290
std::unique_ptr<SSL_CTX, TDeleter> Ctx;
291
+ TIntrusivePtr<NActors::TInterconnectProxyCommon> Common;
290
292
291
293
public:
292
- TImpl (const TString& certificate, const TString& privateKey, const TString& caFilePath,
293
- const TString& ciphers) {
294
+ TImpl (TIntrusivePtr<NActors::TInterconnectProxyCommon> common)
295
+ : Common(std::move(common))
296
+ {
294
297
int ret;
295
298
InitOpenSSL ();
296
299
#if OPENSSL_VERSION_NUMBER < 0x10100000L
@@ -308,7 +311,7 @@ namespace NInterconnect {
308
311
SSL_CTX_set_mode (*this , SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
309
312
310
313
// apply certificates in SSL context
311
- if (certificate) {
314
+ if (const TString& certificate = Common-> Settings . Certificate ) {
312
315
std::unique_ptr<BIO, TDeleter> bio (BIO_new_mem_buf (certificate.data (), certificate.size ()));
313
316
Y_ABORT_UNLESS (bio);
314
317
@@ -329,19 +332,19 @@ namespace NInterconnect {
329
332
// we must not free memory if certificate was added successfully by SSL_CTX_add0_chain_cert
330
333
}
331
334
}
332
- if (privateKey) {
335
+ if (const TString& privateKey = Common-> Settings . PrivateKey ) {
333
336
std::unique_ptr<BIO, TDeleter> bio (BIO_new_mem_buf (privateKey.data (), privateKey.size ()));
334
337
Y_ABORT_UNLESS (bio);
335
338
std::unique_ptr<EVP_PKEY, TDeleter> pkey (PEM_read_bio_PrivateKey (bio.get (), nullptr , nullptr , nullptr ));
336
339
Y_ABORT_UNLESS (pkey);
337
340
ret = SSL_CTX_use_PrivateKey (Ctx.get (), pkey.get ());
338
341
Y_ABORT_UNLESS (ret == 1 );
339
342
}
340
- if (caFilePath) {
343
+ if (const TString& caFilePath = Common-> Settings . CaFilePath ) {
341
344
ret = SSL_CTX_load_verify_locations (Ctx.get (), caFilePath.data (), nullptr );
342
345
Y_ABORT_UNLESS (ret == 1 );
343
346
}
344
-
347
+ const TString& ciphers = Common-> Settings . CipherList ;
345
348
int success = SSL_CTX_set_cipher_list (Ctx.get (), ciphers ? ciphers.data () : " AES128-GCM-SHA256" );
346
349
Y_ABORT_UNLESS (success, " failed to set cipher list" );
347
350
}
@@ -355,34 +358,55 @@ namespace NInterconnect {
355
358
return index;
356
359
}
357
360
361
+ static int GetContextIndex () {
362
+ static int index = SSL_get_ex_new_index (0 , nullptr , nullptr , nullptr , nullptr );
363
+ return index;
364
+ }
365
+
358
366
private:
359
367
static int Verify (int preverify, X509_STORE_CTX *ctx) {
368
+ X509* const current = X509_STORE_CTX_get_current_cert (ctx);
369
+ auto * const ssl = static_cast <SSL*>(X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()));
370
+ auto * const errp = static_cast <TString*>(SSL_get_ex_data (ssl, GetExIndex ()));
371
+ auto * const secureSocketContext = static_cast <TSecureSocketContext*>(SSL_get_ex_data (ssl, GetContextIndex ()));
372
+
360
373
if (!preverify) {
361
- X509 *badCert = X509_STORE_CTX_get_current_cert (ctx);
362
374
int err = X509_STORE_CTX_get_error (ctx);
363
375
int depth = X509_STORE_CTX_get_error_depth (ctx);
364
- SSL *ssl = static_cast <SSL*>(X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx ()));
365
- TString *errp = static_cast <TString*>(SSL_get_ex_data (ssl, GetExIndex ()));
366
376
char buffer[1024 ];
367
- X509_NAME_oneline (X509_get_subject_name (badCert ), buffer, sizeof (buffer));
377
+ X509_NAME_oneline (X509_get_subject_name (current ), buffer, sizeof (buffer));
368
378
TStringBuilder s;
369
379
s << " Error during certificate validation"
370
380
<< " error# " << X509_verify_cert_error_string (err)
371
381
<< " depth# " << depth
372
382
<< " cert# " << buffer;
373
383
if (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) {
374
- X509_NAME_oneline (X509_get_issuer_name (badCert ), buffer, sizeof (buffer));
384
+ X509_NAME_oneline (X509_get_issuer_name (current ), buffer, sizeof (buffer));
375
385
s << " issuer# " << buffer;
376
386
}
377
387
*errp = s;
388
+ } else if (auto & forbidden = secureSocketContext->Impl ->Common ->Settings .ForbiddenSignatureAlgorithms ) {
389
+ do {
390
+ int pknid;
391
+ if (X509_get_signature_info (current, nullptr , &pknid, nullptr , nullptr ) != 1 ) {
392
+ *errp = TStringBuilder () << " failed to acquire signature info" ;
393
+ } else if (const char *ln = OBJ_nid2ln (pknid); ln && forbidden.contains (ln)) {
394
+ *errp = TStringBuilder () << " forbidden signature algorithm: " << ln;
395
+ } else if (const char *sn = OBJ_nid2ln (pknid); sn && forbidden.contains (sn)) {
396
+ *errp = TStringBuilder () << " forbidden signature algorithm: " << sn;
397
+ } else {
398
+ break ;
399
+ }
400
+ X509_STORE_CTX_set_error (ctx, X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM);
401
+ return 0 ;
402
+ } while (false );
378
403
}
379
404
return preverify;
380
405
}
381
406
};
382
407
383
- TSecureSocketContext::TSecureSocketContext (const TString& certificate, const TString& privateKey,
384
- const TString& caFilePath, const TString& ciphers)
385
- : Impl(new TImpl(certificate, privateKey, caFilePath, ciphers))
408
+ TSecureSocketContext::TSecureSocketContext (TIntrusivePtr<NActors::TInterconnectProxyCommon> common)
409
+ : Impl(new TImpl(std::move(common)))
386
410
{}
387
411
388
412
TSecureSocketContext::~TSecureSocketContext ()
@@ -395,12 +419,13 @@ namespace NInterconnect {
395
419
bool WantWrite_ = false ;
396
420
397
421
public:
398
- TImpl (SSL_CTX *ctx, int fd)
422
+ TImpl (SSL_CTX *ctx, int fd, TSecureSocketContext *secureSocketContext )
399
423
: Ssl(SSL_new(ctx))
400
424
{
401
425
Y_ABORT_UNLESS (Ssl, " SSL_new() failed" );
402
426
SSL_set_fd (Ssl, fd);
403
427
SSL_set_ex_data (Ssl, TSecureSocketContext::TImpl::GetExIndex (), &ErrorDescription);
428
+ SSL_set_ex_data (Ssl, TSecureSocketContext::TImpl::GetContextIndex (), secureSocketContext);
404
429
}
405
430
406
431
~TImpl () {
@@ -546,18 +571,37 @@ namespace NInterconnect {
546
571
547
572
TString GetPeerCommonName () const {
548
573
TString res;
549
- if (X509 *cert = SSL_get_peer_certificate (Ssl)) {
574
+ if (std::unique_ptr< X509, void (*)(X509*)> cert{ SSL_get_peer_certificate (Ssl), &X509_free} ) {
550
575
char buffer[256 ];
551
576
memset (buffer, 0 , sizeof (buffer));
552
- if (X509_NAME *name = X509_get_subject_name (cert)) {
577
+ if (X509_NAME *name = X509_get_subject_name (cert. get () )) {
553
578
X509_NAME_get_text_by_NID (name, NID_commonName, buffer, sizeof (buffer));
554
579
}
555
- X509_free (cert);
556
580
res = TString (buffer, strnlen (buffer, sizeof (buffer)));
557
581
}
558
582
return res;
559
583
}
560
584
585
+ TString GetSignatureAlgorithm () const {
586
+ TString res;
587
+ if (std::unique_ptr<X509, void (*)(X509*)> cert{SSL_get_peer_certificate (Ssl), &X509_free}) {
588
+ int mdnid;
589
+ int pknid;
590
+ int secbits;
591
+ if (X509_get_signature_info (cert.get (), &mdnid, &pknid, &secbits, nullptr ) == 1 ) {
592
+ res = TStringBuilder ()
593
+ << " md: " << OBJ_nid2ln (mdnid)
594
+ << " pk: " << OBJ_nid2ln (pknid)
595
+ << " bits: " << secbits;
596
+ } else {
597
+ res = " <failed to get signature info>" ;
598
+ }
599
+ } else {
600
+ res = " <failed to get peer certificate>" ;
601
+ }
602
+ return res;
603
+ }
604
+
561
605
bool WantRead () const {
562
606
return WantRead_;
563
607
}
@@ -605,7 +649,7 @@ namespace NInterconnect {
605
649
TSecureSocket::TSecureSocket (TStreamSocket& socket, TSecureSocketContext::TPtr context)
606
650
: TStreamSocket(socket.ReleaseDescriptor())
607
651
, Context(std::move(context))
608
- , Impl(new TImpl(*Context->Impl, Descriptor))
652
+ , Impl(new TImpl(*Context->Impl, Descriptor, Context.get() ))
609
653
{}
610
654
611
655
TSecureSocket::~TSecureSocket ()
@@ -651,6 +695,10 @@ namespace NInterconnect {
651
695
return Impl->GetPeerCommonName ();
652
696
}
653
697
698
+ TString TSecureSocket::GetSignatureAlgorithm () const {
699
+ return Impl->GetSignatureAlgorithm ();
700
+ }
701
+
654
702
bool TSecureSocket::WantRead () const {
655
703
return Impl->WantRead ();
656
704
}
0 commit comments