11#include " interconnect_stream.h"
2+ #include " interconnect_common.h"
23#include " logging.h"
34#include " poller_actor.h"
45#include < library/cpp/openssl/init/init.h>
@@ -287,10 +288,12 @@ namespace NInterconnect {
287288
288289 class TSecureSocketContext ::TImpl {
289290 std::unique_ptr<SSL_CTX, TDeleter> Ctx;
291+ TIntrusivePtr<NActors::TInterconnectProxyCommon> Common;
290292
291293 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+ {
294297 int ret;
295298 InitOpenSSL ();
296299#if OPENSSL_VERSION_NUMBER < 0x10100000L
@@ -308,7 +311,7 @@ namespace NInterconnect {
308311 SSL_CTX_set_mode (*this , SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
309312
310313 // apply certificates in SSL context
311- if (certificate) {
314+ if (const TString& certificate = Common-> Settings . Certificate ) {
312315 std::unique_ptr<BIO, TDeleter> bio (BIO_new_mem_buf (certificate.data (), certificate.size ()));
313316 Y_ABORT_UNLESS (bio);
314317
@@ -329,19 +332,19 @@ namespace NInterconnect {
329332 // we must not free memory if certificate was added successfully by SSL_CTX_add0_chain_cert
330333 }
331334 }
332- if (privateKey) {
335+ if (const TString& privateKey = Common-> Settings . PrivateKey ) {
333336 std::unique_ptr<BIO, TDeleter> bio (BIO_new_mem_buf (privateKey.data (), privateKey.size ()));
334337 Y_ABORT_UNLESS (bio);
335338 std::unique_ptr<EVP_PKEY, TDeleter> pkey (PEM_read_bio_PrivateKey (bio.get (), nullptr , nullptr , nullptr ));
336339 Y_ABORT_UNLESS (pkey);
337340 ret = SSL_CTX_use_PrivateKey (Ctx.get (), pkey.get ());
338341 Y_ABORT_UNLESS (ret == 1 );
339342 }
340- if (caFilePath) {
343+ if (const TString& caFilePath = Common-> Settings . CaFilePath ) {
341344 ret = SSL_CTX_load_verify_locations (Ctx.get (), caFilePath.data (), nullptr );
342345 Y_ABORT_UNLESS (ret == 1 );
343346 }
344-
347+ const TString& ciphers = Common-> Settings . CipherList ;
345348 int success = SSL_CTX_set_cipher_list (Ctx.get (), ciphers ? ciphers.data () : " AES128-GCM-SHA256" );
346349 Y_ABORT_UNLESS (success, " failed to set cipher list" );
347350 }
@@ -355,34 +358,55 @@ namespace NInterconnect {
355358 return index;
356359 }
357360
361+ static int GetContextIndex () {
362+ static int index = SSL_get_ex_new_index (0 , nullptr , nullptr , nullptr , nullptr );
363+ return index;
364+ }
365+
358366 private:
359367 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+
360373 if (!preverify) {
361- X509 *badCert = X509_STORE_CTX_get_current_cert (ctx);
362374 int err = X509_STORE_CTX_get_error (ctx);
363375 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 ()));
366376 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));
368378 TStringBuilder s;
369379 s << " Error during certificate validation"
370380 << " error# " << X509_verify_cert_error_string (err)
371381 << " depth# " << depth
372382 << " cert# " << buffer;
373383 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));
375385 s << " issuer# " << buffer;
376386 }
377387 *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 );
378403 }
379404 return preverify;
380405 }
381406 };
382407
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)))
386410 {}
387411
388412 TSecureSocketContext::~TSecureSocketContext ()
@@ -395,12 +419,13 @@ namespace NInterconnect {
395419 bool WantWrite_ = false ;
396420
397421 public:
398- TImpl (SSL_CTX *ctx, int fd)
422+ TImpl (SSL_CTX *ctx, int fd, TSecureSocketContext *secureSocketContext )
399423 : Ssl(SSL_new(ctx))
400424 {
401425 Y_ABORT_UNLESS (Ssl, " SSL_new() failed" );
402426 SSL_set_fd (Ssl, fd);
403427 SSL_set_ex_data (Ssl, TSecureSocketContext::TImpl::GetExIndex (), &ErrorDescription);
428+ SSL_set_ex_data (Ssl, TSecureSocketContext::TImpl::GetContextIndex (), secureSocketContext);
404429 }
405430
406431 ~TImpl () {
@@ -546,18 +571,37 @@ namespace NInterconnect {
546571
547572 TString GetPeerCommonName () const {
548573 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} ) {
550575 char buffer[256 ];
551576 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 () )) {
553578 X509_NAME_get_text_by_NID (name, NID_commonName, buffer, sizeof (buffer));
554579 }
555- X509_free (cert);
556580 res = TString (buffer, strnlen (buffer, sizeof (buffer)));
557581 }
558582 return res;
559583 }
560584
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+
561605 bool WantRead () const {
562606 return WantRead_;
563607 }
@@ -605,7 +649,7 @@ namespace NInterconnect {
605649 TSecureSocket::TSecureSocket (TStreamSocket& socket, TSecureSocketContext::TPtr context)
606650 : TStreamSocket(socket.ReleaseDescriptor())
607651 , Context(std::move(context))
608- , Impl(new TImpl(*Context->Impl, Descriptor))
652+ , Impl(new TImpl(*Context->Impl, Descriptor, Context.get() ))
609653 {}
610654
611655 TSecureSocket::~TSecureSocket ()
@@ -651,6 +695,10 @@ namespace NInterconnect {
651695 return Impl->GetPeerCommonName ();
652696 }
653697
698+ TString TSecureSocket::GetSignatureAlgorithm () const {
699+ return Impl->GetSignatureAlgorithm ();
700+ }
701+
654702 bool TSecureSocket::WantRead () const {
655703 return Impl->WantRead ();
656704 }
0 commit comments