2020#include < openssl/bio.h>
2121#include < openssl/x509_vfy.h>
2222
23+ #include < array>
2324#include < iomanip>
2425#include < mutex>
2526#include < sstream>
@@ -50,8 +51,8 @@ class OpenSslInitializer
5051};
5152
5253// Ensure OpenSSL is initialized once
53- static std::once_flag opensslInitFlag;
54- static OpenSslInitializer *opensslInit = nullptr ;
54+ std::once_flag opensslInitFlag;
55+ OpenSslInitializer *opensslInit = nullptr ;
5556
5657void ensureOpenSslInitialized ()
5758{
@@ -67,11 +68,11 @@ std::string getOpenSslErrorString()
6768 unsigned long err;
6869
6970 while ((err = ERR_get_error ()) != 0 ) {
70- char buf[ 256 ] ;
71- ERR_error_string_n (err, buf, sizeof ( buf));
71+ std::array< char , 256 > buf ;
72+ ERR_error_string_n (err, buf. data (), buf. size ( ));
7273 if (!result.empty ())
7374 result += " ; " ;
74- result += buf;
75+ result += buf. data () ;
7576 }
7677
7778 return result.empty () ? " Unknown SSL error" : result;
@@ -87,7 +88,7 @@ std::string x509ToPem(X509 *cert)
8788 PEM_write_bio_X509 (bio, cert);
8889
8990 char *data = nullptr ;
90- long length = BIO_get_mem_data (bio, &data);
91+ const long length = BIO_get_mem_data (bio, &data);
9192 std::string result (data, length);
9293
9394 BIO_free (bio);
@@ -104,14 +105,16 @@ std::string formatCertificateDetails(X509 *cert)
104105 std::stringstream ss;
105106
106107 // Get subject
107- char subjectName[256 ];
108- X509_NAME_oneline (X509_get_subject_name (cert), subjectName, sizeof (subjectName));
109- ss << " Subject: " << subjectName << " \n " ;
108+ char *subjectName = X509_NAME_oneline (X509_get_subject_name (cert), nullptr , 0 );
109+ ss << " Subject: " << (subjectName ? subjectName : " Unknown" ) << " \n " ;
110+ if (subjectName)
111+ OPENSSL_free (subjectName);
110112
111113 // Get issuer
112- char issuerName[256 ];
113- X509_NAME_oneline (X509_get_issuer_name (cert), issuerName, sizeof (issuerName));
114- ss << " Issuer: " << issuerName << " \n " ;
114+ char *issuerName = X509_NAME_oneline (X509_get_issuer_name (cert), nullptr , 0 );
115+ ss << " Issuer: " << (issuerName ? issuerName : " Unknown" ) << " \n " ;
116+ if (issuerName)
117+ OPENSSL_free (issuerName);
115118
116119 // Get validity period
117120 ASN1_TIME *notBefore = X509_get_notBefore (cert);
@@ -135,9 +138,9 @@ std::string formatCertificateDetails(X509 *cert)
135138 }
136139
137140 // Get fingerprint
138- unsigned char md[ EVP_MAX_MD_SIZE ] ;
141+ std::array< unsigned char , EVP_MAX_MD_SIZE > md{} ;
139142 unsigned int md_len;
140- if (X509_digest (cert, EVP_sha256 (), md, &md_len)) {
143+ if (X509_digest (cert, EVP_sha256 (), md. data () , &md_len)) {
141144 ss << " SHA-256 fingerprint: " ;
142145 for (unsigned int i = 0 ; i < md_len; i++) {
143146 ss << std::hex << std::setw (2 ) << std::setfill (' 0' ) << static_cast <int >(md[i]);
@@ -148,12 +151,12 @@ std::string formatCertificateDetails(X509 *cert)
148151 }
149152
150153 // Get Subject Alternative Names (SANs)
151- GENERAL_NAMES *sans = static_cast <GENERAL_NAMES *>(
154+ auto *sans = static_cast <GENERAL_NAMES *>(
152155 X509_get_ext_d2i (cert, NID_subject_alt_name, nullptr , nullptr ));
153156
154157 if (sans) {
155158 ss << " Subject Alternative Names:\n " ;
156- int num_sans = sk_GENERAL_NAME_num (sans);
159+ const int num_sans = sk_GENERAL_NAME_num (sans);
157160
158161 for (int i = 0 ; i < num_sans; i++) {
159162 GENERAL_NAME *current = sk_GENERAL_NAME_value (sans, i);
@@ -246,8 +249,7 @@ class SslSocket::SslSocketPrivate
246249};
247250
248251SslSocket::SslSocket ()
249- : TcpSocket()
250- , d(std::make_unique<SslSocketPrivate>())
252+ : d(std::make_unique<SslSocketPrivate>())
251253{
252254 m_type = SocketType::SslTcp;
253255 ensureOpenSslInitialized ();
@@ -256,9 +258,12 @@ SslSocket::SslSocket()
256258
257259SslSocket::~SslSocket ()
258260{
259- disconnectFromHost ();
261+ // Clean up SSL resources without calling disconnectFromHost() recursively
262+ d->cleanup ();
263+ // TcpSocket base destructor will handle socket closure
260264}
261265
266+ // NOLINTBEGIN(bugprone-use-after-move)
262267SslSocket::SslSocket (SslSocket &&other) noexcept
263268 : TcpSocket(std::move(other))
264269 , handshakeCompleted(std::move(other.handshakeCompleted))
@@ -278,6 +283,7 @@ SslSocket &SslSocket::operator=(SslSocket &&other) noexcept
278283 }
279284 return *this ;
280285}
286+ // NOLINTEND(bugprone-use-after-move)
281287
282288bool SslSocket::initSsl ()
283289{
@@ -338,7 +344,7 @@ void SslSocket::disconnectFromHost()
338344 // If we have an SSL connection, attempt a clean shutdown
339345 if (d->ssl && d->handshakeComplete ) {
340346 // Non-blocking SSL_shutdown
341- int ret = SSL_shutdown (d->ssl );
347+ const int ret = SSL_shutdown (d->ssl );
342348 if (ret == 0 ) {
343349 // First stage of shutdown completed, ideally wait for second stage
344350 // but we'll complete immediately for simplicity
@@ -751,12 +757,12 @@ void SslSocket::handleSslRead()
751757
752758 // Try to decrypt and process data
753759 while (true ) {
754- char buffer[ 4096 ] ;
755- const int decrypted = SSL_read (d->ssl , buffer, sizeof ( buffer));
760+ std::array< char , 4096 > buffer ;
761+ const int decrypted = SSL_read (d->ssl , buffer. data (), buffer. size ( ));
756762
757763 if (decrypted > 0 ) {
758764 // Process decrypted data - add to TcpSocket's read buffer
759- const KDUtils::ByteArray decryptedData (reinterpret_cast <const uint8_t *>(buffer), decrypted);
765+ const KDUtils::ByteArray decryptedData (reinterpret_cast <const uint8_t *>(buffer. data () ), decrypted);
760766 TcpSocket::processReceivedData (decryptedData.constData (), decryptedData.size ());
761767 } else {
762768 const int sslError = SSL_get_error (d->ssl , decrypted);
@@ -824,7 +830,7 @@ bool SslSocket::handleSslWrite()
824830
825831 // First, try to write any data in the pendingWriteBuffer through SSL
826832 while (!d->pendingWriteBuffer .isEmpty ()) {
827- const int written = SSL_write (d->ssl , d->pendingWriteBuffer .constData (), d->pendingWriteBuffer .size ());
833+ const int written = SSL_write (d->ssl , d->pendingWriteBuffer .constData (), static_cast < int >( d->pendingWriteBuffer .size () ));
828834
829835 if (written > 0 ) {
830836 // Successfully encrypted some data
@@ -875,12 +881,12 @@ void SslSocket::flushNetworkBIO()
875881 return ;
876882 }
877883
878- char buffer[ 4096 ] ;
884+ std::array< char , 4096 > buffer ;
879885 int pending = BIO_pending (d->networkBio );
880886
881887 while (pending > 0 ) {
882- const int readSize = std::min (pending, static_cast <int >(sizeof ( buffer)));
883- const int read = BIO_read (d->networkBio , buffer, readSize);
888+ const int readSize = std::min (pending, static_cast <int >(buffer. size ( )));
889+ const int read = BIO_read (d->networkBio , buffer. data () , readSize);
884890
885891 if (read <= 0 ) {
886892 // No more data or error
@@ -894,9 +900,9 @@ void SslSocket::flushNetworkBIO()
894900
895901 // Write the encrypted data to the socket
896902#if defined(KD_PLATFORM_WIN32)
897- const int sent = ::send (m_socketFd, buffer, read, 0 );
903+ const int sent = ::send (m_socketFd, buffer. data () , read, 0 );
898904#else
899- int sent = ::send (m_socketFd, buffer, read, MSG_NOSIGNAL );
905+ int sent = ::send (m_socketFd, buffer. data () , read, MSG_NOSIGNAL );
900906#endif
901907
902908 if (sent <= 0 ) {
@@ -905,7 +911,7 @@ void SslSocket::flushNetworkBIO()
905911 if (error_code == WSAEWOULDBLOCK ) {
906912 // Would block, retry later
907913 // Put the data back into the BIO for later
908- BIO_write (d->networkBio , buffer, read);
914+ BIO_write (d->networkBio , buffer. data () , read);
909915 setWriteNotificationEnabled (true );
910916 break ;
911917 }
@@ -1018,9 +1024,9 @@ bool SslSocket::verifySslCertificate()
10181024 // Extract the Common Name (CN) from the certificate for comparison
10191025 X509_NAME *subject = X509_get_subject_name (cert);
10201026 if (subject) {
1021- char commonName[ 256 ] ;
1022- if (X509_NAME_get_text_by_NID (subject, NID_commonName, commonName, sizeof (commonName)) > 0 ) {
1023- d->verificationError += " (Certificate CN: " + std::string (commonName) + " )" ;
1027+ std::array< char , 256 > commonName{} ;
1028+ if (X509_NAME_get_text_by_NID (subject, NID_commonName, commonName. data (), static_cast < int > (commonName. size () )) > 0 ) {
1029+ d->verificationError += " (Certificate CN: " + std::string (commonName. data () ) + " )" ;
10241030 }
10251031 }
10261032 } else if (verifyResult == X509_V_ERR_CERT_NOT_YET_VALID || verifyResult == X509_V_ERR_CERT_HAS_EXPIRED ) {
@@ -1049,9 +1055,9 @@ bool SslSocket::verifySslCertificate()
10491055 // Get the issuer name to help identify missing CA certificates
10501056 X509_NAME *issuer = X509_get_issuer_name (cert);
10511057 if (issuer) {
1052- char issuerName[ 256 ] ;
1053- X509_NAME_oneline (issuer, issuerName, sizeof (issuerName));
1054- d->verificationError += " (Certificate issuer: " + std::string (issuerName) + " )" ;
1058+ std::array< char , 256 > issuerName{} ;
1059+ X509_NAME_oneline (issuer, issuerName. data (), static_cast < int > (issuerName. size () ));
1060+ d->verificationError += " (Certificate issuer: " + std::string (issuerName. data () ) + " )" ;
10551061 }
10561062 }
10571063
@@ -1086,9 +1092,9 @@ std::string SslSocket::sslCipher() const
10861092 if (d->ssl && d->handshakeComplete ) {
10871093 const SSL_CIPHER *cipher = SSL_get_current_cipher (d->ssl );
10881094 if (cipher) {
1089- char buf[ 128 ] ;
1090- SSL_CIPHER_description (cipher, buf, sizeof ( buf));
1091- return buf;
1095+ std::array< char , 128 > buf{} ;
1096+ SSL_CIPHER_description (cipher, buf. data (), buf. size ( ));
1097+ return buf. data () ;
10921098 }
10931099 }
10941100 return {};
0 commit comments