reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
FlowDtlsSocketContext.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#ifdef USE_SSL
6#include <asio.hpp>
7#include <asio/ssl.hpp>
8#include <iostream>
9
10#include <rutil/Log.hxx>
11#include <rutil/Logger.hxx>
12#include <rutil/Timer.hxx>
13
16
17using namespace flowmanager;
18using namespace resip;
19using namespace dtls;
20using namespace std;
21
22#define RESIPROCATE_SUBSYSTEM FlowManagerSubsystem::FLOWMANAGER
23
24FlowDtlsSocketContext::FlowDtlsSocketContext(Flow& flow, const asio::ip::address& address, unsigned short port)
25 : mFlow(flow), mAddress(address), mPort(port), mSrtpInitialized(false)
26{
27}
28
30{
31 destroySrtpSessions();
32}
33
34void
35FlowDtlsSocketContext::write(const unsigned char* data, unsigned int len)
36{
37 InfoLog(<< "Dtls write to " << mAddress.to_string() << ":" << mPort << " called. ComponentId=" << mFlow.getComponentId());
38 mFlow.rawSendTo(mAddress, mPort, (const char*)data, len);
39}
40
41void
43{
44 InfoLog(<< "Flow Dtls Handshake Completed! ComponentId=" << mFlow.getComponentId());
45
46 char fprint[DtlsSocket::FingerprintSize];
47 if(mSocket->getRemoteFingerprint("sha-256", fprint, sizeof(fprint)))
48 {
49 InfoLog(<< "Remote fingerprint (SHA-256) = " << fprint << " ComponentId=" << mFlow.getComponentId());
50 }
51
52 SRTP_PROTECTION_PROFILE* srtp_profile = mSocket->getSrtpProfile();
53 if(srtp_profile)
54 {
55 InfoLog(<< "SRTP Extension negotiated profile=" << srtp_profile->name << " ComponentId=" << mFlow.getComponentId());
56 }
57
58 // The Flow calls us with its mutex held, so read its fingerprint directly. If the remote SDP
59 // hasn't arrived yet, SRTP is set up when Flow::setRemoteSDPFingerprint is called
60 checkRemoteFingerprint(mFlow.mRemoteSDPFingerprintHashFunction, mFlow.mRemoteSDPFingerprint);
61}
62
63void
65{
66 ErrLog(<< "Flow Dtls Handshake failed: " << err << " ComponentId=" << mFlow.getComponentId());
67}
68
69std::shared_ptr<std::mutex>
71{
72 // The Flow's mutex, which it holds whenever it uses its DtlsSockets
73 return mFlow.mSharedMutex;
74}
75
76void
78{
80 {
81 return;
82 }
83
84 if(fingerprint.empty())
85 {
86 InfoLog(<< "Waiting for the remote SDP fingerprint before setting up SRTP. ComponentId=" << mFlow.getComponentId());
87 return;
88 }
89
90 if(mSocket->checkFingerprint(hashFunction.c_str(), fingerprint.c_str()))
91 {
92 if(!mSrtpInitialized)
93 {
94 InfoLog(<< "Remote certificate matches the SDP fingerprint (" << hashFunction << " " << fingerprint << "), setting up SRTP. ComponentId=" << mFlow.getComponentId());
95 if(!createSrtpSessions())
96 {
97 ErrLog(<< "Unable to set up SRTP from the Dtls handshake. ComponentId=" << mFlow.getComponentId());
98 }
99 }
100 }
101 else
102 {
103 // Log the certificate's fingerprint computed with the SDP's hash function, so the two can be compared
104 char fprint[EVP_MAX_MD_SIZE * 3];
105 Data remoteFingerprint = mSocket->getRemoteFingerprint(hashFunction.c_str(), fprint, sizeof(fprint)) ?
106 Data(fprint) : Data("unavailable (unsupported hash function)");
107 WarningLog(<< "Remote certificate does not match the SDP fingerprint, "
108 << (mSrtpInitialized ? "tearing down SRTP" : "not setting up SRTP")
109 << ". SDP fingerprint=" << hashFunction << " " << fingerprint
110 << ", certificate fingerprint=" << remoteFingerprint << " ComponentId=" << mFlow.getComponentId());
111 // Ensure Srtp is not initalized, so we will not process media packets from this endpoint
112 destroySrtpSessions();
113 }
114}
115
116bool
117FlowDtlsSocketContext::createSrtpSessions()
118{
119 srtp_policy_t policyIn;
120 srtp_policy_t policyOut;
121 if(!mSocket->createSrtpSessionPolicies(policyOut, policyIn))
122 {
123 return false;
124 }
125
126 bool created = false;
127 if(srtp_create(&mSRTPSessionIn, &policyIn) == srtp_err_status_ok)
128 {
129 if(srtp_create(&mSRTPSessionOut, &policyOut) == srtp_err_status_ok)
130 {
131 created = true;
132 }
133 else
134 {
135 srtp_dealloc(mSRTPSessionIn);
136 }
137 }
138
139 // srtp_create has derived the session keys, so the master keys DtlsSocket::createSrtpSessionPolicies
140 // allocated are no longer needed
141 delete[] policyIn.key;
142 delete[] policyOut.key;
143
144 mSrtpInitialized = created;
145 return created;
146}
147
148void
149FlowDtlsSocketContext::destroySrtpSessions()
150{
151 if(mSrtpInitialized)
152 {
153 mSrtpInitialized = false;
154 srtp_dealloc(mSRTPSessionIn);
155 srtp_dealloc(mSRTPSessionOut);
156 }
157}
158
159srtp_err_status_t
160FlowDtlsSocketContext::srtpProtect(void* data, int* size, bool rtcp)
161{
162 srtp_err_status_t status = srtp_err_status_no_ctx;
163 if(mSrtpInitialized)
164 {
165 if(rtcp)
166 {
167 status = srtp_protect_rtcp(mSRTPSessionOut, data, size);
168 }
169 else
170 {
171 status = srtp_protect(mSRTPSessionOut, data, size);
172 }
173 }
174 return status;
175}
176
177srtp_err_status_t
178FlowDtlsSocketContext::srtpUnprotect(void* data, int* size, bool rtcp)
179{
180 srtp_err_status_t status = srtp_err_status_no_ctx;
181 if(mSrtpInitialized)
182 {
183 if(rtcp)
184 {
185 status = srtp_unprotect_rtcp(mSRTPSessionIn, data, size);
186 }
187 else
188 {
189 status = srtp_unprotect(mSRTPSessionIn, data, size);
190 }
191 }
192 return status;
193}
194
195#endif
196/* ====================================================================
197
198 Copyright (c) 2008-2026 SIP Spectrum, Inc. https://www.sipspectrum.com
199 Copyright (c) 2007-2008, Plantronics, Inc.
200 All rights reserved.
201
202 Redistribution and use in source and binary forms, with or without
203 modification, are permitted provided that the following conditions are
204 met:
205
206 1. Redistributions of source code must retain the above copyright
207 notice, this list of conditions and the following disclaimer.
208
209 2. Redistributions in binary form must reproduce the above copyright
210 notice, this list of conditions and the following disclaimer in the
211 documentation and/or other materials provided with the distribution.
212
213 3. Neither the name of Plantronics nor the names of its contributors
214 may be used to endorse or promote products derived from this
215 software without specific prior written permission.
216
217 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
218 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
219 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
220 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
221 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
224 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
225 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
226 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
227 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
228
229 ==================================================================== */
#define InfoLog(args_)
Definition Logger.hxx:131
#define WarningLog(args_)
Definition Logger.hxx:134
#define ErrLog(args_)
Definition Logger.hxx:137
static const size_t FingerprintSize
bool createSrtpSessionPolicies(srtp_policy_t &outboundPolicy, srtp_policy_t &inboundPolicy)
bool checkFingerprint(const char *hashFunction, const char *fingerprint)
SRTP_PROTECTION_PROFILE * getSrtpProfile()
bool getRemoteFingerprint(const char *hashFunction, char *fingerprint, size_t fingerprintSize)
bool handshakeCompleted()
srtp_err_status_t srtpUnprotect(void *data, int *size, bool rtcp)
virtual void handshakeFailed(const char *err)
virtual std::shared_ptr< std::mutex > timerLock()
void checkRemoteFingerprint(const resip::Data &hashFunction, const resip::Data &fingerprint)
virtual void write(const unsigned char *data, unsigned int len)
srtp_err_status_t srtpProtect(void *data, int *size, bool rtcp)
FlowDtlsSocketContext(Flow &flow, const asio::ip::address &address, unsigned short port)
This class represents a Flow that is created by the Flow Manager.
Definition Flow.hxx:45
void rawSendTo(const asio::ip::address &address, unsigned short port, const char *buffer, unsigned int size)
Definition Flow.cxx:307
unsigned int getComponentId()
Definition Flow.hxx:129
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
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
This class is used during media sessions that use Dtls-Srtp for a media transport.
Definition ErrorCode.hxx:4
dcm! – add UnusedChecking(_enum) below;