2
#if defined(HAVE_CONFIG_H)
11
#ifndef RESIP_COMPAT_HXX
12
#include "rutil/compat.hxx"
15
#ifndef RESIP_DATA_HXX
16
#include "rutil/Data.hxx"
19
#ifndef RESIP_DNSUTIL_HXX
20
#include "rutil/DnsUtil.hxx"
23
#ifndef RESIP_SOCKET_HXX
24
#include "rutil/Socket.hxx"
27
#ifndef RESIP_LOGGER_HXX
28
#include "rutil/Logger.hxx"
31
#ifndef RESIP_SIPMESSAGE_HXX
32
#include "resip/stack/SipMessage.hxx"
35
#ifndef RESIP_HELPER_HXX
36
#include "resip/stack/Helper.hxx"
39
#ifndef RESIP_SECURITY_HXX
40
#include "resip/stack/ssl/Security.hxx"
43
#ifndef RESIP_DTLSMESSAGE_HXX
44
#include "resip/stack/DtlsMessage.hxx"
47
#ifndef RESIP_DTLSTRANSPORT_HXX
48
#include "resip/stack/ssl/DtlsTransport.hxx"
51
#include "rutil/WinLeakCheck.hxx"
53
#include <openssl/e_os2.h>
54
#include <openssl/evp.h>
55
#include <openssl/crypto.h>
56
#include <openssl/err.h>
57
#include <openssl/pem.h>
58
#include <openssl/pkcs7.h>
59
#include <openssl/x509v3.h>
60
#include <openssl/ssl.h>
63
#include <osc/Stack.h>
64
#include <osc/StateChanges.h>
65
#include <osc/SigcompMessage.h>
68
#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
71
using namespace resip;
73
// .slg. Note that DTLS handshakes were really broken in older versions of OpenSSL 0.9.8
74
// You should use at least version 0.9.8g for both client and server.
76
DtlsTransport::DtlsTransport(Fifo<TransactionMessage>& fifo,
79
const Data& interfaceObj,
81
const Data& sipDomain,
82
AfterSocketCreationFuncPtr socketFunc,
83
Compression& compression)
84
: UdpTransport( fifo, portNum, version,
85
StunDisabled, interfaceObj, socketFunc, compression ),
86
mTimer( mHandshakePending ),
87
mSecurity( &security ),
90
setTlsDomain(sipDomain);
91
InfoLog ( << "Creating DTLS transport host=" << interfaceObj
92
<< " port=" << mTuple.getPort()
93
<< " ipv4=" << version ) ;
95
mTxFifo.setDescription("DtlsTransport::mTxFifo");
97
mTuple.setType( transport() );
99
mClientCtx = mSecurity->createDomainCtx(DTLSv1_client_method(), Data::Empty) ;
100
mServerCtx = mSecurity->createDomainCtx(DTLSv1_server_method(), sipDomain) ;
101
assert( mClientCtx ) ;
102
assert( mServerCtx ) ;
104
mDummyBio = BIO_new( BIO_s_mem() ) ;
105
assert( mDummyBio ) ;
109
/* DTLS: partial reads end up discarding unread UDP bytes :-(
110
* Setting read ahead solves this problem.
111
* Source of this comment is: apps/s_client.c from OpenSSL source
113
SSL_CTX_set_read_ahead(mClientCtx, 1);
114
SSL_CTX_set_read_ahead(mServerCtx, 1);
116
/* trying to read from this BIO always returns retry */
117
BIO_set_mem_eof_return( mDummyBio, -1 ) ;
120
DtlsTransport::~DtlsTransport()
122
DebugLog (<< "Shutting down " << mTuple);
124
while(mDtlsConnections.begin() != mDtlsConnections.end())
126
_cleanupConnectionState(mDtlsConnections.begin()->second, mDtlsConnections.begin()->first);
128
SSL_CTX_free(mClientCtx);mClientCtx=0;
129
SSL_CTX_free(mServerCtx);mServerCtx=0;
131
BIO_free( mDummyBio) ;
135
DtlsTransport::_read( FdSet& fdset )
137
//should this buffer be allocated on the stack and then copied out, as it
138
//needs to be deleted every time EWOULDBLOCK is encountered
139
// .dlb. can we determine the size of the buffer before we allocate?
140
// something about MSG_PEEK|MSG_TRUNC in Stevens..
141
// .dlb. RFC3261 18.1.1 MUST accept 65K datagrams. would have to attempt to
142
// adjust the UDP buffer as well...
143
unsigned int bufferLen = UdpTransport::MaxBufferSize + 5 ;
144
char* buffer = new char[ bufferLen ] ;
145
unsigned char *pt = new unsigned char[ bufferLen ] ;
151
// !jf! how do we tell if it discarded bytes
152
// !ah! we use the len-1 trick :-(
153
Tuple tuple(mTuple) ;
154
socklen_t slen = tuple.length() ;
155
int len = recvfrom( mFd,
157
UdpTransport::MaxBufferSize,
159
&tuple.getMutableSockaddr(),
161
if ( len == SOCKET_ERROR )
163
int err = getErrno() ;
164
if ( err != EWOULDBLOCK )
170
if (len == 0 || len == SOCKET_ERROR)
177
if ( len + 1 >= UdpTransport::MaxBufferSize )
179
InfoLog (<<"Datagram exceeded max length "<<UdpTransport::MaxBufferSize ) ;
180
delete [] buffer ; buffer = 0 ;
184
//DebugLog ( << "UDP Rcv : " << len << " b" );
185
//DebugLog ( << Data(buffer, len).escaped().c_str());
187
/* begin SSL stuff */
188
struct sockaddr peer = tuple.getMutableSockaddr() ;
190
ssl = mDtlsConnections[ *((struct sockaddr_in *)&peer) ] ;
193
* If we don't have a binding for this peer,
194
* then we're a server.
198
ssl = SSL_new( mServerCtx ) ;
201
// clear SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE set in SSL_CTX if we are a server
202
SSL_set_verify(ssl, 0, 0);
204
InfoLog( << "DTLS handshake starting (Server mode)" );
206
SSL_set_accept_state( ssl ) ;
208
wbio = BIO_new_dgram( (int)mFd, BIO_NOCLOSE ) ;
211
BIO_dgram_set_peer( wbio, &peer ) ;
213
SSL_set_bio( ssl, NULL, wbio ) ;
215
/* remember this connection */
216
mDtlsConnections[ *((struct sockaddr_in *)&peer) ] = ssl ;
219
rbio = BIO_new_mem_buf( buffer, len ) ;
220
BIO_set_mem_eof_return( rbio, -1 ) ;
224
len = SSL_read( ssl, pt, UdpTransport::MaxBufferSize ) ;
225
int err = SSL_get_error( ssl, len ) ;
227
/* done with the rbio */
228
BIO_free( ssl->rbio ) ;
229
ssl->rbio = mDummyBio ;
235
char errorString[1024];
243
ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
244
DebugLog( << "Got DTLS read condition SSL_ERROR_SSL on"
245
<< " addr = " << inet_ntoa(((struct sockaddr_in *)&peer)->sin_addr)
246
<< " port = " << ntohs(((struct sockaddr_in *)&peer)->sin_port)
247
<< " error = " << errorString );
250
case SSL_ERROR_WANT_READ:
252
case SSL_ERROR_WANT_WRITE:
254
case SSL_ERROR_SYSCALL:
256
ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
257
DebugLog( << "Got DTLS read condition SSL_ERROR_SYSCALL on"
258
<< " addr = " << inet_ntoa(((struct sockaddr_in *)&peer)->sin_addr)
259
<< " port = " << ntohs(((struct sockaddr_in *)&peer)->sin_port)
260
<< " error = " << errorString );
263
/* connection closed */
264
case SSL_ERROR_ZERO_RETURN:
266
ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
267
DebugLog( << "Got DTLS read condition SSL_ERROR_ZERO_RETURN on"
268
<< " addr = " << inet_ntoa(((struct sockaddr_in *)&peer)->sin_addr)
269
<< " port = " << ntohs(((struct sockaddr_in *)&peer)->sin_port)
270
<< " error = " << errorString );
272
_cleanupConnectionState( ssl, *((struct sockaddr_in *)&peer) ) ;
275
case SSL_ERROR_WANT_CONNECT:
277
case SSL_ERROR_WANT_ACCEPT:
287
if ( SSL_in_init( ssl ) )
288
mTimer.add( ssl, DtlsReceiveTimeout ) ;
291
osc::StateChanges *sc = 0;
294
if ((pt[0] & 0xf8) == 0xf8)
296
if(!mCompression.isEnabled())
298
InfoLog(<< "Discarding unexpected SigComp message");
303
unsigned char *newPt = new unsigned char[ bufferLen ] ;
304
size_t uncompressedLength =
305
mSigcompStack->uncompressMessage(pt, len,
306
newPt, UdpTransport::MaxBufferSize,
309
DebugLog (<< "Unompressed message from "
310
<< len << " bytes to "
311
<< uncompressedLength << " bytes");
313
osc::SigcompMessage *nack = mSigcompStack->getNack();
317
mTxFifo.add(new SendData(tuple,
318
Data(nack->getDatagramMessage(),
319
nack->getDatagramLength()),
329
len = uncompressedLength;
333
SipMessage* message = new SipMessage(this);
335
// set the received from information into the received= parameter in the
338
// It is presumed that UDP Datagrams are arriving atomically and that
339
// each one is a unique SIP message
341
// Save all the info where this message came from
342
tuple.transport = this ;
343
message->setSource( tuple ) ;
344
//DebugLog (<< "Received from: " << tuple);
346
// Tell the SipMessage about this datagram buffer.
347
message->addBuffer( (char *)pt ) ;
349
mMsgHeaderScanner.prepareForMessage( message ) ;
351
char *unprocessedCharPtr ;
352
if (mMsgHeaderScanner.scanChunk( (char *)pt,
354
&unprocessedCharPtr ) !=
355
MsgHeaderScanner::scrEnd)
357
DebugLog( << "Scanner rejecting datagram as unparsable / fragmented from "
359
DebugLog( << Data( pt, len ) ) ;
366
int used = int(unprocessedCharPtr - (char *)pt);
370
// body is present .. add it up.
371
// NB. The Sip Message uses an overlay (again)
372
// for the body. It ALSO expects that the body
373
// will be contiguous (of course).
374
// it doesn't need a new buffer in UDP b/c there
375
// will only be one datagram per buffer. (1:1 strict)
377
message->setBody( (char *)pt + used, len - used ) ;
378
//DebugLog(<<"added " << len-used << " byte body");
381
if ( ! basicCheck( *message ) )
383
delete message ; // cannot use it, so, punt on it...
384
// basicCheck queued any response required
389
stampReceived( message) ;
392
if (mCompression.isEnabled() && sc)
394
const Via &via = message->header(h_Vias).front();
395
if (message->isRequest())
397
// For requests, the compartment ID is read out of the
398
// top via header field; if not present, we use the
399
// TCP connection for identification purposes.
400
if (via.exists(p_sigcompId))
402
Data compId = via.param(p_sigcompId);
403
mSigcompStack->provideCompartmentId(
404
sc, compId.data(), compId.size());
408
mSigcompStack->provideCompartmentId(sc, this, sizeof(this));
413
// For responses, the compartment ID is supposed to be
414
// the same as the compartment ID of the request. We
415
// *could* dig down into the transaction layer to try to
416
// figure this out, but that's a royal pain, and a rather
417
// severe layer violation. In practice, we're going to ferret
418
// the ID out of the the Via header field, which is where we
419
// squirreled it away when we sent this request in the first place.
420
Data compId = via.param(p_branch).getSigcompCompartment();
421
mSigcompStack->provideCompartmentId(sc, compId.data(), compId.size());
427
mStateMachineFifo.add( message ) ;
430
void DtlsTransport::_write( FdSet& fdset )
437
if ( mSendData != NULL )
438
sendData = mSendData ;
440
sendData = mTxFifo.getNext() ;
442
//DebugLog (<< "Sent: " << sendData->data);
443
//DebugLog (<< "Sending message on udp.");
445
assert( &(*sendData) );
446
assert( sendData->destination.getPort() != 0 );
448
sockaddr peer = sendData->destination.getSockaddr();
450
ssl = mDtlsConnections[ *((struct sockaddr_in *)&peer) ] ;
452
/* If we don't have a binding, then we're a client */
455
ssl = SSL_new( mClientCtx ) ;
459
InfoLog( << "DTLS handshake starting (client mode)" );
461
SSL_set_connect_state( ssl ) ;
463
wBio = BIO_new_dgram( (int)mFd, BIO_NOCLOSE ) ;
466
BIO_dgram_set_peer( wBio, &peer) ;
468
/* the real rbio will be set by _read */
469
SSL_set_bio( ssl, mDummyBio, wBio ) ;
471
/* we should be ready to take this out if the
472
* connection fails later */
473
mDtlsConnections [ *((struct sockaddr_in *)&peer) ] = ssl ;
480
// If message needs to be compressed, compress it here.
482
sendData->sigcompId.size() > 0 &&
483
!sendData->isAlreadyCompressed )
485
osc::SigcompMessage *sm = mSigcompStack->compressMessage
486
(sendData->data.data(), sendData->data.size(),
487
sendData->sigcompId.data(), sendData->sigcompId.size(),
490
DebugLog (<< "Compressed message from "
491
<< sendData->data.size() << " bytes to "
492
<< sm->getDatagramLength() << " bytes");
494
expected = sm->getDatagramLength();
496
count = SSL_Write(ssl,
497
sm->getDatagramMessage(),
498
sm->getDatagramLength());
504
expected = (int)sendData->data.size();
506
count = SSL_write(ssl, sendData->data.data(),
507
(int)sendData->data.size());
511
* all reads go through _read, so the most likely result during a handshake
512
* will be SSL_ERROR_WANT_READ
517
/* cache unqueued data */
518
mSendData = sendData ;
520
int err = SSL_get_error( ssl, count ) ;
522
char errorString[1024];
530
ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
531
DebugLog( << "Got DTLS write condition SSL_ERROR_SSL on "
532
<< sendData->destination
533
<< " error = " << errorString );
536
case SSL_ERROR_WANT_READ:
539
case SSL_ERROR_WANT_WRITE:
543
case SSL_ERROR_SYSCALL:
548
ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
549
DebugLog( << "Got DTLS write condition SSL_ERROR_SYSCALL "
550
<< "Failed (" << e << ") sending to "
551
<< sendData->destination
552
<< " error = " << errorString );
554
fail(sendData->transactionId);
557
case SSL_ERROR_ZERO_RETURN:
559
ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
560
DebugLog( << "Got DTLS write condition SSL_ERROR_ZERO_RETURN on "
561
<< sendData->destination
562
<< " error = " << errorString );
564
_cleanupConnectionState( ssl, *((struct sockaddr_in *)&peer) ) ;
567
case SSL_ERROR_WANT_CONNECT:
569
case SSL_ERROR_WANT_ACCEPT:
581
* ngm: is sendData deleted by a higher layer? Seems to be the case after
582
* checking with UdpTransport
585
if ( ! retry && count != int(sendData->data.size()) )
587
ErrLog (<< "UDPTransport - send buffer full" );
588
fail(sendData->transactionId);
593
DtlsTransport::_doHandshake( void )
595
DtlsMessage *msg = mHandshakePending.getNext() ;
596
SSL *ssl = msg->getSsl() ;
602
int ret = SSL_do_handshake( ssl ) ;
605
int err = SSL_get_error(ssl, ret);
607
char errorString[1024];
615
ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
616
DebugLog( << "Got DTLS handshake code SSL_ERROR_SSL"
617
<< " error = " << errorString );
620
case SSL_ERROR_WANT_READ:
622
case SSL_ERROR_WANT_WRITE:
624
case SSL_ERROR_SYSCALL:
626
ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
627
DebugLog( << "Got DTLS handshake code SSL_ERROR_SYSCALL"
628
<< " error = " << errorString );
631
case SSL_ERROR_ZERO_RETURN:
633
ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
634
DebugLog( << "Got DTLS handshake code SSL_ERROR_ZERO_RETURN"
635
<< " error = " << errorString );
638
case SSL_ERROR_WANT_CONNECT:
640
case SSL_ERROR_WANT_ACCEPT:
649
DtlsTransport::process(FdSet& fdset)
651
// pull buffers to send out of TxFifo
652
// receive datagrams from fd
653
// preparse and stuff into RxFifo
657
while ( mHandshakePending.messageAvailable() )
660
if ( ( mSendData != NULL || mTxFifo.messageAvailable() )
661
&& fdset.readyToWrite( mFd ) )
664
// !jf! this may have to change - when we read a message that is too big
665
if ( fdset.readyToRead(mFd) )
671
DtlsTransport::buildFdSet( FdSet& fdset )
675
if ( mSendData != NULL || mTxFifo.messageAvailable() )
682
DtlsTransport::_cleanupConnectionState( SSL *ssl, struct sockaddr_in peer )
685
* SSL_free decrements the ref-count for mDummyBio by 1, so
686
* add 1 to the ref-count to make sure it does not get free'd
688
CRYPTO_add(&mDummyBio->references, 1, CRYPTO_LOCK_BIO);
691
mDtlsConnections.erase(peer) ;
695
DtlsTransport::_mapDebug( const char *where, const char *action, SSL *ssl )
697
fprintf( stderr, "%s: %s\t%p\n", where, action, ssl ) ;
698
fprintf( stderr, "map sizet = %d\n", mDtlsConnections.size() ) ;
702
DtlsTransport::_printSock( const struct sockaddr_in *sock )
704
fprintf( stderr, "addr = %s\t port = %d\n", inet_ntoa( sock->sin_addr ),
705
ntohs( sock->sin_port ) ) ;
708
#endif /* USE_DTLS */
711
/* ====================================================================
712
* The Vovida Software License, Version 1.0
714
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
716
* Redistribution and use in source and binary forms, with or without
717
* modification, are permitted provided that the following conditions
720
* 1. Redistributions of source code must retain the above copyright
721
* notice, this list of conditions and the following disclaimer.
723
* 2. Redistributions in binary form must reproduce the above copyright
724
* notice, this list of conditions and the following disclaimer in
725
* the documentation and/or other materials provided with the
728
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
729
* and "Vovida Open Communication Application Library (VOCAL)" must
730
* not be used to endorse or promote products derived from this
731
* software without prior written permission. For written
732
* permission, please contact vocal@vovida.org.
734
* 4. Products derived from this software may not be called "VOCAL", nor
735
* may "VOCAL" appear in their name, without prior written
736
* permission of Vovida Networks, Inc.
738
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
739
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
740
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
741
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
742
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
743
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
744
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
745
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
746
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
747
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
748
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
749
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
752
* ====================================================================
754
* This software consists of voluntary contributions made by Vovida
755
* Networks, Inc. and many individuals on behalf of Vovida Networks,
756
* Inc. For more information on Vovida Networks, Inc., please see
757
* <http://www.vovida.org/>.