reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
TlsConnection.cxx
Go to the documentation of this file.
1#if defined(HAVE_CONFIG_H)
2#include "config.h"
3#endif
4
5#if defined(USE_SSL)
6
10#include "rutil/Logger.hxx"
11#include "resip/stack/Uri.hxx"
12#include "rutil/DnsUtil.hxx"
13#include "rutil/Socket.hxx"
14
15#include <openssl/opensslv.h>
16#if !defined(LIBRESSL_VERSION_NUMBER)
17#include <openssl/e_os2.h>
18#endif
19#include <openssl/evp.h>
20#include <openssl/crypto.h>
21#include <openssl/err.h>
22#include <openssl/pem.h>
23#include <openssl/pkcs7.h>
24#include <openssl/x509v3.h>
25#include <openssl/ssl.h>
26#endif
27
28using namespace resip;
29
30#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
31
32TlsConnection::TlsConnection(Transport* transport, const Tuple& tuple,
33 Socket fd, Security* security,
34 bool server, Data domain, SecurityTypes::SSLType sslType,
35 Compression& compression) :
36 Connection(transport, tuple, fd, compression, server),
37 mServer(server),
38 mSecurity(security),
39 mSslType(sslType),
40 mDomain(domain)
41{
42#if defined(USE_SSL)
43 InfoLog(<< "Creating TLS connection for domain " << mDomain << " " << tuple << " on " << fd);
44
45 mSsl = NULL;
46 mBio = NULL;
47
48 if (mServer)
49 {
50 DebugLog(<< "Trying to form TLS connection - acting as server");
51 if (mDomain.empty())
52 {
53 ErrLog(<< "Tranport was not created with a server domain so can not act as server");
54 throw Security::Exception("Trying to act as server but no domain specified",
55 __FILE__, __LINE__);
56 }
57 }
58 else
59 {
60 DebugLog(<< "Trying to form TLS connection - acting as client");
61 }
62 resip_assert(mSecurity);
63
64 TlsBaseTransport* t = dynamic_cast<TlsBaseTransport*>(transport);
65 resip_assert(t);
66
67 SSL_CTX* ctx = t->getCtx();
68 resip_assert(ctx);
69
70 mSsl = SSL_new(ctx);
71 resip_assert(mSsl);
72
73 resip_assert(mSecurity);
74
75 if (mServer)
76 {
77 // clear SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE set in SSL_CTX if we are a server
78 int verify_mode = SSL_VERIFY_PEER;
79 switch (t->getClientVerificationMode())
80 {
82 verify_mode = SSL_VERIFY_NONE;
83 DebugLog(<< "Not expecting client certificate");
84 break;
86 verify_mode = SSL_VERIFY_PEER;
87 DebugLog(<< "Optional client certificate mode");
88 break;
90 verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
91 DebugLog(<< "Mandatory client certificate mode");
92 break;
93 default:
94 resip_assert(0);
95 }
96 SSL_set_verify(mSsl, verify_mode, 0); // Modify verify flags, but leave callback same as set in Security.cxx
97 }
98
99 mBio = BIO_new_socket((int)fd, 0/*close flag*/);
100 if (!mBio)
101 {
102 throw Transport::Exception("Failed to create OpenSSL BIO for socket",
103 __FILE__, __LINE__);
104 }
105
106 SSL_set_bio(mSsl, mBio, mBio);
107 // Set application/ex data on context so that this Connection can be queried in certificate validation callback
108 SSL_set_ex_data(mSsl, BaseSecurity::getResipConnectionExDataIdx(), this);
109
110 mTlsState = Initial;
111 mHandShakeWantsRead = false;
112
113#endif // USE_SSL
114}
115
117{
118#if defined(USE_SSL)
119 // Only send a close_notify on a connection that is up: OpenSSL says not to
120 // call SSL_shutdown() after a fatal error, and one before the handshake has
121 // finished just fails and logs an error
122 if (mTlsState == Up)
123 {
124 ERR_clear_error();
125 int ret = SSL_shutdown(mSsl);
126 if (ret < 0)
127 {
128 int err = SSL_get_error(mSsl, ret);
129 switch (err)
130 {
131 case SSL_ERROR_WANT_READ:
132 case SSL_ERROR_WANT_WRITE:
133 case SSL_ERROR_NONE:
134 // WANT_READ or WANT_WRITE can arise for bi-directional shutdown on
135 // non-blocking sockets, safe to ignore
136 StackLog(<< "Got TLS shutdown error condition of " << err);
137 break;
138
139 default:
140 handleOpenSSLErrorQueue(ret, err, "SSL_shutdown");
141 }
142 }
143 }
144 SSL_free(mSsl);
145#endif // USE_SSL
146}
147
148const char*
150{
151 switch(s)
152 {
153 case Initial: return "Initial"; break;
154 case Handshaking: return "Handshaking"; break;
155 case Broken: return "Broken"; break;
156 case Up: return "Up"; break;
157 }
158 resip_assert(false);
159 return "????";
160}
161
163TlsConnection::checkState()
164{
165#if defined(USE_SSL)
166 //DebugLog(<<"state is " << fromTlsState(mTlsState));
167
168 if (mTlsState == Up || mTlsState == Broken)
169 {
170 return mTlsState;
171 }
172
173 int handshakeRet = 0;
174
175 ERR_clear_error();
176
177 if (mTlsState != Handshaking)
178 {
179 if (mServer)
180 {
181 InfoLog(<< "TLS handshake starting (server mode)");
182 SSL_set_accept_state(mSsl);
183 mTlsState = Handshaking;
184 }
185 else
186 {
187 const Data& targetDomain = who().getTargetDomain();
188 // RFC 6066 section 3: SNI carries a host name, never an IP address.
189 // SSL_set_tlsext_host_name() also fails for an empty name, and the
190 // error it leaves queued would make SSL_get_error() report the
191 // handshake below as failed.
192 if (!targetDomain.empty() && !DnsUtil::isIpAddress(targetDomain))
193 {
194 InfoLog(<< "TLS handshake starting (client mode), SNI=" << targetDomain);
195 if (SSL_set_tlsext_host_name(mSsl, targetDomain.c_str()) != 1)
196 {
197 WarningLog(<< "Failed to set SNI " << targetDomain << ", continuing without it");
198 ERR_clear_error();
199 }
200 }
201 else
202 {
203 InfoLog(<< "TLS handshake starting (client mode), no SNI for target <" << targetDomain << ">");
204 }
205 SSL_set_connect_state(mSsl);
206 mTlsState = Handshaking;
207 }
208 }
209
210 mHandShakeWantsRead = false;
211 handshakeRet = SSL_do_handshake(mSsl);
212
213 if (handshakeRet <= 0)
214 {
215 int err = SSL_get_error(mSsl, handshakeRet);
216
217 switch (err)
218 {
219 case SSL_ERROR_WANT_READ:
220 StackLog(<< "TLS handshake want read");
221 mHandShakeWantsRead = true;
222 return mTlsState;
223
224 case SSL_ERROR_WANT_WRITE:
225 StackLog(<< "TLS handshake want write");
227 return mTlsState;
228
229 case SSL_ERROR_ZERO_RETURN:
230 StackLog(<< "TLS connection closed cleanly");
231 return mTlsState;
232
233 case SSL_ERROR_WANT_CONNECT:
234 StackLog(<< "BIO not connected, try later");
235 return mTlsState;
236
237 case SSL_ERROR_WANT_ACCEPT:
238 StackLog(<< "TLS connection want accept");
239 return mTlsState;
240
241 case SSL_ERROR_WANT_X509_LOOKUP:
242 DebugLog(<< "Try later / SSL_ERROR_WANT_X509_LOOKUP");
243 return mTlsState;
244
245 default:
247 int failureSubCode = 0;
248 Data failureString;
249 DataStream ds(failureString);
250 bool addToAdditionalFailureStrings = true;
251 ds << "TLS handshake failed: ";
252 if (err == SSL_ERROR_SYSCALL)
253 {
254 int e = getErrno();
255 switch (e)
256 {
257 case EINTR:
258 case EAGAIN:
259#if EAGAIN != EWOULDBLOCK
260 case EWOULDBLOCK: // Treat EGAIN and EWOULDBLOCK as the same: http://stackoverflow.com/questions/7003234/which-systems-define-eagain-and-ewouldblock-as-different-values
261#endif
262 StackLog(<< "try later: " << e);
263 return mTlsState;
264 }
265 ds << "socket error=" << e << ": " << Transport::errorToString(e);
266 failureSubCode = e;
267 if (e == 0)
268 {
269 TlsBaseTransport* t = dynamic_cast<TlsBaseTransport*>(transport());
270 resip_assert(t);
271 if (mServer && t->getClientVerificationMode() != SecurityTypes::None)
272 {
273 ds << ", client may have disconnected to prompt for user certificate, because it can't supply a certificate (verification mode == " << (t->getClientVerificationMode() == SecurityTypes::Mandatory ? "Mandatory" : "Optional") << " for this transport) or because it does not support using client certificates";
274 }
275 }
276 }
277 else if (err == SSL_ERROR_SSL)
278 {
279 ds << "SSL cipher or certificate failure(SSL_ERROR_SSL), note: ";
280 int verifyErrorCode = SSL_get_verify_result(mSsl);
281 switch (verifyErrorCode)
282 {
283 case X509_V_OK:
284 {
285 // OpenSSL docs: If no peer certificate was presented, the returned result code is X509_V_OK.
286 // This is because no verification error occurred, it does however not indicate success.
287#if OPENSSL_VERSION_NUMBER < 0x30000000L
288 X509* peerCert = SSL_get_peer_certificate(mSsl);
289#else
290 X509* peerCert = SSL_get1_peer_certificate(mSsl);
291#endif
292 if (peerCert)
293 {
294 ds << "peer supplied a certificate, it has either not been checked or it was checked successfully";
295 X509_free(peerCert);
296 }
297 else
298 {
299 ds << "peer did not supply a certificate";
300 }
301 break;
302 }
303
304 default:
305 ds << "peer certificate validation failure: " << X509_verify_cert_error_string(verifyErrorCode);
306 // We will have failure strings already added from the certificate validation callback already (Security.cxx),
307 // adding errors from the SSL error queue doesn't appear to provide any additional information - disable it
308 addToAdditionalFailureStrings = false;
309 break;
310 }
311 if (mServer)
312 {
313 TlsBaseTransport* t = dynamic_cast<TlsBaseTransport*>(transport());
314 resip_assert(t);
316 {
317 ds << "; mandatory client certificate verification required";
318 }
319 }
321 failureSubCode = verifyErrorCode;
322 }
323 else
324 {
325 ds << "unhandled SSL_get_error result: " << err;
326 failureSubCode = err;
327 }
328 if (mServer)
329 {
330 const char* sni = SSL_get_servername(mSsl, TLSEXT_NAMETYPE_host_name);
331 ds << "; SNI received: " << (sni ? sni : "<none>");
332 }
333 ds.flush();
334 ErrLog(<< failureString);
335 handleOpenSSLErrorQueue(handshakeRet, err, "SSL_do_handshake", addToAdditionalFailureStrings);
336 setFailureReason(failureReason, failureSubCode, failureString);
337 mBio = NULL;
338 mTlsState = Broken;
339 return mTlsState;
340 }
341 }
342 else // handshakeRet > 1
343 {
344 if (mServer)
345 {
346 const char* sni = SSL_get_servername(mSsl, TLSEXT_NAMETYPE_host_name);
347 mSni = sni ? Data(sni) : Data::Empty;
348 InfoLog(<< "TLS connected (server mode), SNI received: " << (sni ? sni : "<none>"));
349 }
350 else
351 {
352 InfoLog(<< "TLS connected (client mode)");
353 }
354 }
355
356 // force peer name to get checked and perhaps cert loaded
357 computePeerName();
358
359 //post-connection verification: check that certificate name matches domain name
360 if (!mServer)
361 {
362 bool matches = false;
363 for (std::list<BaseSecurity::PeerName>::iterator it = mPeerNames.begin(); it != mPeerNames.end(); it++)
364 {
365 if (BaseSecurity::matchHostName(it->mName, who().getTargetDomain()))
366 {
367 matches = true;
368 break;
369 }
370 }
371 if (!matches)
372 {
373 mTlsState = Broken;
374 mBio = NULL;
375 Data failureString;
376 {
377 DataStream ds(failureString);
378 ds << "Certificate name mismatch: trying to connect to <"
379 << who().getTargetDomain()
380 << "> remote cert domain(s) are <"
381 << getPeerNamesData() << ">";
382 }
383 ErrLog(<< failureString);
385 return mTlsState;
386 }
387 }
388
389 InfoLog(<< "TLS handshake done for peer " << getPeerNamesData());
390 mTlsState = Up;
391 if (!mOutstandingSends.empty())
392 {
394 }
395#endif // USE_SSL
396 return mTlsState;
397}
398
399bool
400TlsConnection::handleOpenSSLErrorQueue(int ret, unsigned long err, const char* op, bool addToAdditionalFailureStrings)
401{
402 bool hadReason = false;
403 ErrLog(<< op << " error=" << err << ", ret=" << ret);
404 while (true)
405 {
406 const char* file;
407 int line;
408
409#if OPENSSL_VERSION_NUMBER < 0x30000000L
410 unsigned long code = ERR_get_error_line(&file, &line);
411#else
412 unsigned long code = ERR_get_error_all(&file, &line, NULL, NULL, NULL);
413#endif
414 if (code == 0)
415 {
416 break;
417 }
418
419 char buf[256];
420 ERR_error_string_n(code, buf, sizeof(buf));
421 Data errorString;
422 {
423 DataStream ds(errorString);
424 ds << " " << buf << " (file=" << file << ", line=" << line << ")";
425 }
426 ErrLog(<< errorString);
427 if (addToAdditionalFailureStrings)
428 {
429 addAdditionalFailureString(errorString);
430 }
431 hadReason = true;
432 }
433 return hadReason;
434}
435
436int
437TlsConnection::read(char* buf, int count)
438{
439#if defined(USE_SSL)
440 resip_assert(mSsl);
441 resip_assert(buf);
442
443 switch (checkState())
444 {
445 case Broken:
446 return -1;
447 break;
448 case Up:
449 break;
450 default:
451 return 0;
452 break;
453 }
454
455 if (!mBio)
456 {
457 DebugLog(<< "Got TLS read bad bio ");
458 return 0;
459 }
460
461 if (!isGood())
462 {
463 return -1;
464 }
465
466 // SSL_get_error() checks this thread's error queue first, so it must be empty before the
467 // call: an error something else on this thread left there would otherwise turn a
468 // retryable SSL_ERROR_WANT_READ into a fatal SSL_ERROR_SSL
469 ERR_clear_error();
470 int bytesRead = SSL_read(mSsl, buf, count);
471 //StackLog(<< "SSL_read returned " << bytesRead << " bytes [" << Data(Data::Borrow, buf, (bytesRead > 0)?(bytesRead):(0)) << "]");
472
473 if (bytesRead > 0)
474 {
475 int bytesPending = SSL_pending(mSsl);
476 if (bytesPending > 0)
477 {
478 char* buffer = getWriteBufferForExtraBytes(bytesRead, bytesPending);
479 if (buffer)
480 {
481 //StackLog(<< "reading remaining buffered bytes");
482 bytesPending = SSL_read(mSsl, buffer, bytesPending);
483 //StackLog(<< "SSL_read returned " << bytesPending << " bytes [" << Data(Data::Borrow, buffer, (bytesPending > 0)?(bytesPending):(0)) << "]");
484
485 if (bytesPending > 0)
486 {
487 bytesRead += bytesPending;
488 }
489 else
490 {
491 // It's not clear why SSL_read would return an error after SSL_pending returned > 0, however we have
492 // seen a case where it has returned 0 with an error of SSL_ERROR_WANT_READ. So we check the error
493 // code returned, and if it is a retyable error, then we proceed with the bytes we already read in the
494 // in the initial SSL_read call.
495 // Note: SSL_read docs say the following: "Old documentation indicated a difference between 0 and -1 (return code),
496 // and that -1 was retryable. You should instead call SSL_get_error() to find out if it's retryable."
497 int err = SSL_get_error(mSsl, bytesPending);
498 if (err != SSL_ERROR_WANT_READ &&
499 err != SSL_ERROR_WANT_WRITE &&
500 err != SSL_ERROR_NONE)
501 {
502 // Not a retryable error, put the error return code into bytesRead to
503 // be used in the conditional block later in this method.
504 bytesRead = bytesPending;
505 }
506 }
507 }
508 else
509 {
510 resip_assert(0);
511 }
512 }
513 else if (bytesPending < 0)
514 {
515 int err = SSL_get_error(mSsl, bytesPending);
516 handleOpenSSLErrorQueue(bytesPending, err, "SSL_pending");
517 return -1;
518 }
519 }
520
521 if (bytesRead <= 0)
522 {
523 int err = SSL_get_error(mSsl, bytesRead);
524 switch (err)
525 {
526 case SSL_ERROR_WANT_READ:
527 case SSL_ERROR_WANT_WRITE:
528 case SSL_ERROR_NONE:
529 {
530 StackLog(<< "Got TLS read got condition of " << err);
531 return 0;
532 }
533 break;
534 case SSL_ERROR_ZERO_RETURN:
535 {
536 DebugLog(<< "Got SSL_ERROR_ZERO_RETURN (TLS shutdown by peer)");
537 return -1;
538 }
539 break;
540 case SSL_ERROR_SYSCALL:
541 {
542 if (ERR_peek_error() == 0)
543 {
544 // Nothing from OpenSSL itself: the socket failed, or (OpenSSL 1.1.1)
545 // the peer closed the connection without a TLS close_notify
546 const int e = getErrno();
547 if (bytesRead == 0 || e == 0)
548 {
549 InfoLog(<< "TLS connection closed by the peer without a close_notify");
550 }
551 else
552 {
553 InfoLog(<< "TLS read failed, socket error=" << e << ": " << Transport::errorToString(e));
554 }
555 return -1;
556 }
557 handleOpenSSLErrorQueue(bytesRead, err, "SSL_read");
558 return -1;
559 }
560 break;
561 default:
562 {
563#if defined(SSL_R_UNEXPECTED_EOF_WHILE_READING)
564 // How OpenSSL 3 reports a peer closing without a TLS close_notify
565 if (err == SSL_ERROR_SSL &&
566 ERR_GET_REASON(ERR_peek_error()) == SSL_R_UNEXPECTED_EOF_WHILE_READING)
567 {
568 InfoLog(<< "TLS connection closed by the peer without a close_notify");
569 ERR_clear_error();
570 return -1;
571 }
572#endif
573 handleOpenSSLErrorQueue(bytesRead, err, "SSL_read");
574 return -1;
575 }
576 break;
577 }
578 resip_assert(0);
579 }
580 StackLog(<< "SSL bytesRead=" << bytesRead);
581 return bytesRead;
582#endif // USE_SSL
583 return -1;
584}
585
586bool
588{
589 switch(mTlsState)
590 {
591 case Handshaking:
592 case Initial:
593 checkState();
594 if (mTlsState == Handshaking)
595 {
596 DebugLog(<< "transportWrite in Handshaking state, remove from write: " << (mHandShakeWantsRead ? "true" : "false"));
597 return mHandShakeWantsRead;
598 }
599 else
600 {
601 DebugLog(<< "transportWrite in Initial state (Handshake complete), calling write");
602 }
603 case Up:
604 case Broken:
605 default:
606 DebugLog(<< "transportWrite in " << fromState(mTlsState) << " state, calling write");
607 }
608 return false;
609}
610
611int
612TlsConnection::write(const char* buf, int count)
613{
614#if defined(USE_SSL)
615 resip_assert(mSsl);
616 resip_assert(buf);
617 int ret;
618
619 switch (checkState())
620 {
621 case Broken:
622 return -1;
623 break;
624 case Up:
625 break;
626 default:
627 DebugLog(<< "Tried to Tls write, but connection state is not Up");
628 return 0;
629 break;
630 }
631
632 if (!mBio)
633 {
634 DebugLog(<< "Got TLS write bad bio");
635 return 0;
636 }
637
638 if (count <= 0)
639 {
640 // SSL_write() returns 0 for this too, which would read as a failure below
641 return 0;
642 }
643
644 ERR_clear_error(); // SSL_get_error() needs an empty error queue - see read()
645 ret = SSL_write(mSsl, (const char*)buf, count);
646 if (ret <= 0) // 0 is a failure too: SSL_get_error() says whether it can be retried
647 {
648 int err = SSL_get_error(mSsl, ret);
649 switch (err)
650 {
651 case SSL_ERROR_WANT_READ:
652 case SSL_ERROR_WANT_WRITE:
653 case SSL_ERROR_NONE:
654 {
655 StackLog(<< "Got TLS write got condition of " << err);
656 return 0;
657 }
658 break;
659 case SSL_ERROR_ZERO_RETURN:
660 {
661 DebugLog(<< "Got SSL_ERROR_ZERO_RETURN (TLS shutdown by peer)");
662 return -1;
663 }
664 break;
665 default:
666 {
667 handleOpenSSLErrorQueue(ret, err, "SSL_write");
668 return -1;
669 }
670 break;
671 }
672 }
673
674 Data monkey(Data::Borrow, buf, count);
675 StackLog(<< "Did TLS write " << ret << " " << count << " " << "[[" << monkey << "]]");
676
677 return ret;
678#endif // USE_SSL
679 return -1;
680}
681
682bool
683TlsConnection::hasDataToRead() // has data that can be read
684{
685#if defined(USE_SSL)
686 //hack (for now)
687 if (mTlsState == Initial)
688 return false;
689
690 if (checkState() != Up)
691 {
692 return false;
693 }
694
695 int p = SSL_pending(mSsl);
696 //DebugLog(<<"hasDataToRead(): " <<p);
697 return (p > 0);
698#else // USE_SSL
699 return false;
700#endif
701}
702
703bool
704TlsConnection::isGood() // has data that can be read
705{
706#if defined(USE_SSL)
707 if (mBio == 0)
708 {
709 return false;
710 }
711
712 int mode = SSL_get_shutdown(mSsl);
713 if (mode < 0)
714 {
715 int err = SSL_get_error(mSsl, mode);
716 handleOpenSSLErrorQueue(mode, err, "SSL_get_shutdown");
717 return false;
718 }
719
720 if (mode != 0)
721 {
722 return false;
723 }
724
725#endif
726 return true;
727}
728
729bool
731{
732#if defined(USE_SSL)
733 switch (mTlsState)
734 {
735 case Handshaking:
736 return mHandShakeWantsRead ? false : true;
737 case Initial:
738 case Up:
739 return isGood();
740 default:
741 return false;
742 }
743 //dragos -- to remove
744 DebugLog(<< "Current state: " << fromState(mTlsState));
745 //end dragos
746#endif
747 return false;
748}
749
750void
751TlsConnection::getPeerNames(std::list<Data>& peerNames) const
752{
753 for (std::list<BaseSecurity::PeerName>::const_iterator it = mPeerNames.begin(); it != mPeerNames.end(); it++)
754 {
755 peerNames.push_back(it->mName);
756 }
757}
758
759Data
760TlsConnection::getPeerNamesData() const
761{
762 Data peerNamesString;
763 for (std::list<BaseSecurity::PeerName>::const_iterator it = mPeerNames.begin(); it != mPeerNames.end(); it++)
764 {
765 if (it == mPeerNames.begin())
766 {
767 peerNamesString += it->mName;
768 }
769 else
770 {
771 peerNamesString += ", " + it->mName;
772 }
773 }
774 return peerNamesString;
775}
776
777void
778TlsConnection::computePeerName()
779{
780#if defined(USE_SSL)
781 Data commonName;
782
783 resip_assert(mSsl);
784
785 if (!mBio)
786 {
787 ErrLog(<< "bad bio");
788 return;
789 }
790
791 // print session info
792 const SSL_CIPHER* ciph;
793 ciph = SSL_get_current_cipher(mSsl);
794 InfoLog(<< "TLS session set up with "
795 << SSL_get_version(mSsl) << " "
796 << SSL_CIPHER_get_version(ciph) << " "
797 << SSL_CIPHER_get_name(ciph) << " ");
798
799 // get the certificate if other side has one
800#if OPENSSL_VERSION_NUMBER < 0x30000000L
801 X509* cert = SSL_get_peer_certificate(mSsl);
802#else
803 X509* cert = SSL_get1_peer_certificate(mSsl);
804#endif
805 if (!cert)
806 {
807 DebugLog(<< "No peer certificate in TLS connection");
808 return;
809 }
810
811 // check that this certificate is valid
812 if (X509_V_OK != SSL_get_verify_result(mSsl))
813 {
814 DebugLog(<< "Peer certificate in TLS connection is not valid");
815 X509_free(cert); cert = NULL;
816 return;
817 }
818
819 TlsBaseTransport* t = dynamic_cast<TlsBaseTransport*>(mTransport);
820 resip_assert(t);
821
822 mPeerNames.clear();
823 BaseSecurity::getCertNames(cert, mPeerNames, t->isUseEmailAsSIP());
824 if (mPeerNames.empty())
825 {
826 ErrLog(<< "Invalid certificate: no subjectAltName/CommonName found");
827 X509_free(cert); cert = NULL;
828 return;
829 }
830
831 if (!mServer)
832 {
833 // add the certificate to the Security store
834 unsigned char* buf = NULL;
835 int len = i2d_X509(cert, &buf);
836 if (len > 0)
837 {
838 Data derCert(buf, len);
839 for (std::list<BaseSecurity::PeerName>::iterator it = mPeerNames.begin(); it != mPeerNames.end(); it++)
840 {
841 if (!mSecurity->hasDomainCert(it->mName, false /* logErrors? */))
842 {
843 mSecurity->addDomainCertDER(it->mName, derCert);
844 }
845 }
846 }
847 OPENSSL_free(buf); buf = NULL;
848 }
849
850 X509_free(cert); cert = NULL;
851#endif // USE_SSL
852}
853
854/* ====================================================================
855 * The Vovida Software License, Version 1.0
856 *
857 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
858 * Copyright (c) 2000-2005 Vovida Networks, Inc. All rights reserved.
859 *
860 * Redistribution and use in source and binary forms, with or without
861 * modification, are permitted provided that the following conditions
862 * are met:
863 *
864 * 1. Redistributions of source code must retain the above copyright
865 * notice, this list of conditions and the following disclaimer.
866 *
867 * 2. Redistributions in binary form must reproduce the above copyright
868 * notice, this list of conditions and the following disclaimer in
869 * the documentation and/or other materials provided with the
870 * distribution.
871 *
872 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
873 * and "Vovida Open Communication Application Library (VOCAL)" must
874 * not be used to endorse or promote products derived from this
875 * software without prior written permission. For written
876 * permission, please contact vocal@vovida.org.
877 *
878 * 4. Products derived from this software may not be called "VOCAL", nor
879 * may "VOCAL" appear in their name, without prior written
880 * permission of Vovida Networks, Inc.
881 *
882 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
883 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
884 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
885 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
886 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
887 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
888 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
889 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
890 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
891 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
892 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
893 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
894 * DAMAGE.
895 *
896 * ====================================================================
897 *
898 * This software consists of voluntary contributions made by Vovida
899 * Networks, Inc. and many individuals on behalf of Vovida Networks,
900 * Inc. For more information on Vovida Networks, Inc., please see
901 * <http://www.vovida.org/>.
902 *
903 */
struct ssl_ctx_st SSL_CTX
struct x509_st X509
#define DebugLog(args_)
Definition Logger.hxx:128
#define StackLog(args_)
Definition Logger.hxx:125
#define InfoLog(args_)
Definition Logger.hxx:131
#define WarningLog(args_)
Definition Logger.hxx:134
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
Handles cross-platform sockets compatibility.
static int getResipConnectionExDataIdx()
Definition Security.cxx:101
static void getCertNames(X509 *cert, std::list< PeerName > &peerNames, bool useEmailAsSIP=false)
static int matchHostName(const Data &certificateName, const Data &domainName)
Applies the certificate and domain name matching rules.
void addDomainCertDER(const Data &domainName, const Data &certDER)
bool hasDomainCert(const Data &domainName, bool logErrors=true) const
virtual Transport * transport() const
void setFailureReason(TransportFailure::FailureReason failReason, int subCode, const Data &failureString)
char * getWriteBufferForExtraBytes(int bytesRead, int extraBytes)
std::list< SendData * > mOutstandingSends
void addAdditionalFailureString(const Data &additionalFailureString)
Connection implements, via sockets, ConnectionBase for managed connections.
void ensureWritable()
ensure that we are on the writeable list if required
int read()
move data from the connection to the buffer; move this to front of least recently used list.
An iostream that operates on an existing Data.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
@ Borrow
The Data instance is borrowing the memory from the passed in buffer.
Definition Data.hxx:260
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
static bool isIpAddress(const Data &ipAddress)
Definition DnsUtil.cxx:453
SecurityTypes::TlsClientVerificationMode getClientVerificationMode()
static const char * fromState(TlsState)
int write(const char *buf, const int count)
pure virtual, but need concrete Connection for book-ends of lists
virtual bool isGood()
has valid connection
virtual bool hasDataToRead()
always true – always add to fdset as read ready
virtual bool transportWrite()
virtual bool isWritable()
void getPeerNames(std::list< Data > &peerNames) const
General exception class for Transport.
The base class for Transport classes.
Definition Transport.hxx:83
static Data errorToString(int e)
Represents a network address.
Definition Tuple.hxx:59
const Data & getTargetDomain() const
Get the domain name this address tuple intends to represent.
Definition Tuple.hxx:259
SSLType
Note: Before adding to the SSLType enum, please see the comments about mTlsCtx in resip/stack/ssl/Sec...
dcm! – add UnusedChecking(_enum) below;
int Socket
Definition Socket.hxx:94
int getErrno()
Definition Socket.hxx:97