~ubuntu-branches/ubuntu/saucy/resiprocate/saucy-proposed

« back to all changes in this revision

Viewing changes to resip/stack/ssl/DtlsTransport.cxx

  • Committer: Package Import Robot
  • Author(s): Daniel Pocock
  • Date: 2012-05-17 19:29:59 UTC
  • Revision ID: package-import@ubuntu.com-20120517192959-vv00m77isztdy64q
Tags: upstream-1.8.2
ImportĀ upstreamĀ versionĀ 1.8.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#if defined(HAVE_CONFIG_H)
 
3
  #include "config.h"
 
4
#endif
 
5
 
 
6
#ifdef USE_SSL
 
7
#ifdef USE_DTLS
 
8
 
 
9
#include <memory>
 
10
 
 
11
#ifndef RESIP_COMPAT_HXX
 
12
#include "rutil/compat.hxx"
 
13
#endif
 
14
 
 
15
#ifndef RESIP_DATA_HXX
 
16
#include "rutil/Data.hxx"
 
17
#endif
 
18
 
 
19
#ifndef RESIP_DNSUTIL_HXX
 
20
#include "rutil/DnsUtil.hxx"
 
21
#endif
 
22
 
 
23
#ifndef RESIP_SOCKET_HXX
 
24
#include "rutil/Socket.hxx"
 
25
#endif
 
26
 
 
27
#ifndef RESIP_LOGGER_HXX
 
28
#include "rutil/Logger.hxx"
 
29
#endif
 
30
 
 
31
#ifndef RESIP_SIPMESSAGE_HXX
 
32
#include "resip/stack/SipMessage.hxx"
 
33
#endif
 
34
 
 
35
#ifndef RESIP_HELPER_HXX
 
36
#include "resip/stack/Helper.hxx"
 
37
#endif
 
38
 
 
39
#ifndef RESIP_SECURITY_HXX
 
40
#include "resip/stack/ssl/Security.hxx"
 
41
#endif
 
42
 
 
43
#ifndef RESIP_DTLSMESSAGE_HXX
 
44
#include "resip/stack/DtlsMessage.hxx"
 
45
#endif
 
46
 
 
47
#ifndef RESIP_DTLSTRANSPORT_HXX
 
48
#include "resip/stack/ssl/DtlsTransport.hxx"
 
49
#endif
 
50
 
 
51
#include "rutil/WinLeakCheck.hxx"
 
52
 
 
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>
 
61
 
 
62
#ifdef USE_SIGCOMP
 
63
#include <osc/Stack.h>
 
64
#include <osc/StateChanges.h>
 
65
#include <osc/SigcompMessage.h>
 
66
#endif
 
67
 
 
68
#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
 
69
 
 
70
using namespace std;
 
71
using namespace resip;
 
72
 
 
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.
 
75
 
 
76
DtlsTransport::DtlsTransport(Fifo<TransactionMessage>& fifo,
 
77
                             int portNum,
 
78
                             IpVersion version,
 
79
                             const Data& interfaceObj,
 
80
                             Security& security,
 
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 ),
 
88
   mDomain(sipDomain)
 
89
{
 
90
   setTlsDomain(sipDomain);
 
91
   InfoLog ( << "Creating DTLS transport host=" << interfaceObj
 
92
             << " port=" << mTuple.getPort()
 
93
             << " ipv4=" << version ) ;
 
94
 
 
95
   mTxFifo.setDescription("DtlsTransport::mTxFifo");
 
96
 
 
97
   mTuple.setType( transport() );
 
98
 
 
99
   mClientCtx = mSecurity->createDomainCtx(DTLSv1_client_method(), Data::Empty) ;
 
100
   mServerCtx = mSecurity->createDomainCtx(DTLSv1_server_method(), sipDomain) ;
 
101
   assert( mClientCtx ) ;
 
102
   assert( mServerCtx ) ;
 
103
 
 
104
   mDummyBio = BIO_new( BIO_s_mem() ) ;
 
105
   assert( mDummyBio ) ;
 
106
 
 
107
   mSendData = NULL ;
 
108
 
 
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
 
112
    */
 
113
   SSL_CTX_set_read_ahead(mClientCtx, 1);
 
114
   SSL_CTX_set_read_ahead(mServerCtx, 1);
 
115
 
 
116
   /* trying to read from this BIO always returns retry */
 
117
   BIO_set_mem_eof_return( mDummyBio, -1 ) ;
 
118
}
 
119
 
 
120
DtlsTransport::~DtlsTransport()
 
121
{
 
122
   DebugLog (<< "Shutting down " << mTuple);
 
123
 
 
124
   while(mDtlsConnections.begin() != mDtlsConnections.end())
 
125
   {
 
126
       _cleanupConnectionState(mDtlsConnections.begin()->second, mDtlsConnections.begin()->first);
 
127
   }
 
128
   SSL_CTX_free(mClientCtx);mClientCtx=0;
 
129
   SSL_CTX_free(mServerCtx);mServerCtx=0;
 
130
 
 
131
   BIO_free( mDummyBio) ;
 
132
}
 
133
 
 
134
void
 
135
DtlsTransport::_read( FdSet& fdset )
 
136
{
 
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 ] ;
 
146
 
 
147
   SSL *ssl ;
 
148
   BIO *rbio ;
 
149
   BIO *wbio ;
 
150
 
 
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,
 
156
                       buffer,
 
157
                       UdpTransport::MaxBufferSize,
 
158
                       0 /*flags */,
 
159
                       &tuple.getMutableSockaddr(),
 
160
                       &slen ) ;
 
161
   if ( len == SOCKET_ERROR )
 
162
   {
 
163
      int err = getErrno() ;
 
164
      if ( err != EWOULDBLOCK  )
 
165
      {
 
166
         error( err ) ;
 
167
      }
 
168
   }
 
169
 
 
170
   if (len == 0 || len == SOCKET_ERROR)
 
171
   {
 
172
      delete [] buffer ;
 
173
      buffer = 0 ;
 
174
      return ;
 
175
   }
 
176
 
 
177
   if ( len + 1 >= UdpTransport::MaxBufferSize )
 
178
   {
 
179
      InfoLog (<<"Datagram exceeded max length "<<UdpTransport::MaxBufferSize ) ;
 
180
      delete [] buffer ; buffer = 0 ;
 
181
      return ;
 
182
   }
 
183
 
 
184
   //DebugLog ( << "UDP Rcv : " << len << " b" );
 
185
   //DebugLog ( << Data(buffer, len).escaped().c_str());
 
186
 
 
187
   /* begin SSL stuff */
 
188
   struct sockaddr peer = tuple.getMutableSockaddr() ;
 
189
 
 
190
   ssl = mDtlsConnections[ *((struct sockaddr_in *)&peer) ] ;
 
191
 
 
192
   /*
 
193
    * If we don't have a binding for this peer,
 
194
    * then we're a server.
 
195
    */
 
196
   if ( ssl == NULL )
 
197
   {
 
198
      ssl = SSL_new( mServerCtx ) ;
 
199
      assert( ssl ) ;
 
200
 
 
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);
 
203
 
 
204
      InfoLog( << "DTLS handshake starting (Server mode)" );
 
205
 
 
206
      SSL_set_accept_state( ssl ) ;
 
207
 
 
208
      wbio = BIO_new_dgram( (int)mFd, BIO_NOCLOSE ) ;
 
209
      assert( wbio ) ;
 
210
 
 
211
      BIO_dgram_set_peer( wbio, &peer ) ;
 
212
 
 
213
      SSL_set_bio( ssl, NULL, wbio ) ;
 
214
 
 
215
      /* remember this connection */
 
216
      mDtlsConnections[ *((struct sockaddr_in *)&peer) ] = ssl ;
 
217
   }
 
218
 
 
219
   rbio = BIO_new_mem_buf( buffer, len ) ;
 
220
   BIO_set_mem_eof_return( rbio, -1 ) ;
 
221
 
 
222
   ssl->rbio = rbio ;
 
223
 
 
224
   len = SSL_read( ssl, pt, UdpTransport::MaxBufferSize ) ;
 
225
   int err = SSL_get_error( ssl, len ) ;
 
226
 
 
227
   /* done with the rbio */
 
228
   BIO_free( ssl->rbio ) ;
 
229
   ssl->rbio = mDummyBio ;
 
230
   delete [] buffer ;
 
231
   buffer = 0 ;
 
232
 
 
233
   if ( len <= 0 )
 
234
   {
 
235
      char errorString[1024];
 
236
 
 
237
      switch( err )
 
238
      {
 
239
         case SSL_ERROR_NONE:
 
240
            break ;
 
241
         case SSL_ERROR_SSL:
 
242
            {
 
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 );
 
248
            }
 
249
            break ;
 
250
         case SSL_ERROR_WANT_READ:
 
251
            break ;
 
252
         case SSL_ERROR_WANT_WRITE:
 
253
            break ;
 
254
         case SSL_ERROR_SYSCALL:
 
255
            {
 
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 );
 
261
            }
 
262
            break ;
 
263
            /* connection closed */
 
264
         case SSL_ERROR_ZERO_RETURN:
 
265
            {
 
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 );
 
271
 
 
272
               _cleanupConnectionState( ssl, *((struct sockaddr_in *)&peer) ) ;
 
273
            }
 
274
            break ;
 
275
         case SSL_ERROR_WANT_CONNECT:
 
276
            break ;
 
277
         case SSL_ERROR_WANT_ACCEPT:
 
278
            break ;
 
279
         default:
 
280
            break ;
 
281
      }
 
282
   }
 
283
 
 
284
   if ( len <= 0 )
 
285
       return ;
 
286
 
 
287
   if ( SSL_in_init( ssl ) )
 
288
      mTimer.add( ssl, DtlsReceiveTimeout ) ;
 
289
 
 
290
#ifdef USE_SIGCOMP
 
291
   osc::StateChanges *sc = 0;
 
292
#endif
 
293
 
 
294
   if ((pt[0] & 0xf8) == 0xf8)
 
295
   {
 
296
      if(!mCompression.isEnabled())
 
297
      {
 
298
        InfoLog(<< "Discarding unexpected SigComp message");
 
299
        delete [] pt;
 
300
        return;
 
301
      }
 
302
#ifdef USE_SIGCOMP
 
303
      unsigned char *newPt = new unsigned char[ bufferLen ] ;
 
304
      size_t uncompressedLength =
 
305
        mSigcompStack->uncompressMessage(pt, len,
 
306
                                         newPt, UdpTransport::MaxBufferSize,
 
307
                                         sc);
 
308
 
 
309
      DebugLog (<< "Unompressed message from "
 
310
                << len << " bytes to "
 
311
                << uncompressedLength << " bytes");
 
312
 
 
313
      osc::SigcompMessage *nack = mSigcompStack->getNack();
 
314
 
 
315
      if (nack)
 
316
      {
 
317
        mTxFifo.add(new SendData(tuple,
 
318
                                 Data(nack->getDatagramMessage(),
 
319
                                      nack->getDatagramLength()),
 
320
                                 Data::Empty,
 
321
                                 Data::Empty,
 
322
                                 true)
 
323
                   );
 
324
        delete nack;
 
325
      }
 
326
 
 
327
      delete[] buffer;
 
328
      buffer = newBuffer;
 
329
      len = uncompressedLength;
 
330
#endif
 
331
   }
 
332
 
 
333
   SipMessage* message = new SipMessage(this);
 
334
 
 
335
   // set the received from information into the received= parameter in the
 
336
   // via
 
337
 
 
338
   // It is presumed that UDP Datagrams are arriving atomically and that
 
339
   // each one is a unique SIP message
 
340
 
 
341
   // Save all the info where this message came from
 
342
   tuple.transport = this ;
 
343
   message->setSource( tuple ) ;
 
344
   //DebugLog (<< "Received from: " << tuple);
 
345
 
 
346
   // Tell the SipMessage about this datagram buffer.
 
347
   message->addBuffer( (char *)pt ) ;
 
348
 
 
349
   mMsgHeaderScanner.prepareForMessage( message ) ;
 
350
 
 
351
   char *unprocessedCharPtr ;
 
352
   if (mMsgHeaderScanner.scanChunk( (char *)pt,
 
353
                                    len,
 
354
                                    &unprocessedCharPtr ) !=
 
355
       MsgHeaderScanner::scrEnd)
 
356
   {
 
357
      DebugLog( << "Scanner rejecting datagram as unparsable / fragmented from "
 
358
                << tuple ) ;
 
359
      DebugLog( << Data( pt, len ) ) ;
 
360
      delete message ;
 
361
      message = 0 ;
 
362
      return ;
 
363
   }
 
364
 
 
365
   // no pp error
 
366
   int used = int(unprocessedCharPtr - (char *)pt);
 
367
 
 
368
   if ( used < len )
 
369
   {
 
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)
 
376
 
 
377
      message->setBody( (char *)pt + used, len - used ) ;
 
378
      //DebugLog(<<"added " << len-used << " byte body");
 
379
   }
 
380
 
 
381
   if ( ! basicCheck( *message ) )
 
382
   {
 
383
      delete message ; // cannot use it, so, punt on it...
 
384
      // basicCheck queued any response required
 
385
      message = 0 ;
 
386
      return ;
 
387
   }
 
388
 
 
389
   stampReceived( message) ;
 
390
 
 
391
#ifdef USE_SIGCOMP
 
392
      if (mCompression.isEnabled() && sc)
 
393
      {
 
394
        const Via &via = message->header(h_Vias).front();
 
395
        if (message->isRequest())
 
396
        {
 
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))
 
401
          {
 
402
            Data compId = via.param(p_sigcompId);
 
403
            mSigcompStack->provideCompartmentId(
 
404
                             sc, compId.data(), compId.size());
 
405
          }
 
406
          else
 
407
          {
 
408
            mSigcompStack->provideCompartmentId(sc, this, sizeof(this));
 
409
          }
 
410
        }
 
411
        else
 
412
        {
 
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());
 
422
        }
 
423
 
 
424
      }
 
425
#endif
 
426
 
 
427
   mStateMachineFifo.add( message ) ;
 
428
}
 
429
 
 
430
void DtlsTransport::_write( FdSet& fdset )
 
431
{
 
432
   SSL *ssl ;
 
433
   BIO *wBio ;
 
434
   int retry = 0 ;
 
435
 
 
436
   SendData *sendData ;
 
437
   if ( mSendData != NULL )
 
438
       sendData = mSendData ;
 
439
   else
 
440
       sendData = mTxFifo.getNext() ;
 
441
 
 
442
   //DebugLog (<< "Sent: " <<  sendData->data);
 
443
   //DebugLog (<< "Sending message on udp.");
 
444
 
 
445
   assert( &(*sendData) );
 
446
   assert( sendData->destination.getPort() != 0 );
 
447
 
 
448
   sockaddr peer = sendData->destination.getSockaddr();
 
449
 
 
450
   ssl = mDtlsConnections[ *((struct sockaddr_in *)&peer) ] ;
 
451
 
 
452
   /* If we don't have a binding, then we're a client */
 
453
   if ( ssl == NULL )
 
454
   {
 
455
      ssl = SSL_new( mClientCtx ) ;
 
456
      assert( ssl ) ;
 
457
 
 
458
 
 
459
      InfoLog( << "DTLS handshake starting (client mode)" );
 
460
 
 
461
      SSL_set_connect_state( ssl ) ;
 
462
 
 
463
      wBio = BIO_new_dgram( (int)mFd, BIO_NOCLOSE ) ;
 
464
      assert( wBio ) ;
 
465
 
 
466
      BIO_dgram_set_peer( wBio, &peer) ;
 
467
 
 
468
      /* the real rbio will be set by _read */
 
469
      SSL_set_bio( ssl, mDummyBio, wBio ) ;
 
470
 
 
471
      /* we should be ready to take this out if the
 
472
       * connection fails later */
 
473
      mDtlsConnections [ *((struct sockaddr_in *)&peer) ] = ssl ;
 
474
   }
 
475
 
 
476
   int expected;
 
477
   int count;
 
478
 
 
479
#ifdef USE_SIGCOMP
 
480
   // If message needs to be compressed, compress it here.
 
481
   if (mSigcompStack &&
 
482
       sendData->sigcompId.size() > 0 &&
 
483
       !sendData->isAlreadyCompressed )
 
484
   {
 
485
       osc::SigcompMessage *sm = mSigcompStack->compressMessage
 
486
         (sendData->data.data(), sendData->data.size(),
 
487
          sendData->sigcompId.data(), sendData->sigcompId.size(),
 
488
          isReliable());
 
489
 
 
490
       DebugLog (<< "Compressed message from "
 
491
                 << sendData->data.size() << " bytes to "
 
492
                 << sm->getDatagramLength() << " bytes");
 
493
 
 
494
       expected = sm->getDatagramLength();
 
495
 
 
496
       count = SSL_Write(ssl,
 
497
                         sm->getDatagramMessage(),
 
498
                         sm->getDatagramLength());
 
499
       delete sm;
 
500
   }
 
501
   else
 
502
#endif
 
503
   {
 
504
      expected = (int)sendData->data.size();
 
505
 
 
506
      count = SSL_write(ssl, sendData->data.data(),
 
507
                        (int)sendData->data.size());
 
508
   }
 
509
 
 
510
   /*
 
511
    * all reads go through _read, so the most likely result during a handshake
 
512
    * will be SSL_ERROR_WANT_READ
 
513
    */
 
514
 
 
515
   if ( count <= 0 )
 
516
   {
 
517
      /* cache unqueued data */
 
518
      mSendData = sendData ;
 
519
 
 
520
      int err = SSL_get_error( ssl, count ) ;
 
521
 
 
522
      char errorString[1024];
 
523
 
 
524
      switch( err )
 
525
      {
 
526
         case SSL_ERROR_NONE:
 
527
            break;
 
528
         case SSL_ERROR_SSL:
 
529
            {
 
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 );
 
534
            }
 
535
            break;
 
536
         case SSL_ERROR_WANT_READ:
 
537
            retry = 1 ;
 
538
            break;
 
539
         case SSL_ERROR_WANT_WRITE:
 
540
             retry = 1 ;
 
541
             fdset.setWrite(mFd);
 
542
            break;
 
543
         case SSL_ERROR_SYSCALL:
 
544
            {
 
545
               int e = getErrno();
 
546
               error(e);
 
547
 
 
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 );
 
553
 
 
554
               fail(sendData->transactionId);
 
555
            }
 
556
            break;
 
557
         case SSL_ERROR_ZERO_RETURN:
 
558
            {
 
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 );
 
563
 
 
564
               _cleanupConnectionState( ssl, *((struct sockaddr_in *)&peer) ) ;
 
565
            }
 
566
            break ;
 
567
         case SSL_ERROR_WANT_CONNECT:
 
568
            break;
 
569
         case SSL_ERROR_WANT_ACCEPT:
 
570
            break;
 
571
         default:
 
572
            break ;
 
573
      }
 
574
   }
 
575
   else
 
576
   {
 
577
      mSendData = NULL ;
 
578
   }
 
579
 
 
580
   /*
 
581
    * ngm: is sendData deleted by a higher layer?  Seems to be the case after
 
582
    * checking with UdpTransport
 
583
    */
 
584
 
 
585
   if ( ! retry && count != int(sendData->data.size()) )
 
586
   {
 
587
      ErrLog (<< "UDPTransport - send buffer full" );
 
588
      fail(sendData->transactionId);
 
589
   }
 
590
}
 
591
 
 
592
void
 
593
DtlsTransport::_doHandshake( void )
 
594
{
 
595
   DtlsMessage *msg = mHandshakePending.getNext() ;
 
596
   SSL *ssl = msg->getSsl() ;
 
597
 
 
598
   delete msg ;
 
599
 
 
600
   ERR_clear_error();
 
601
 
 
602
   int ret = SSL_do_handshake( ssl ) ;
 
603
 
 
604
   if (ret <= 0) {
 
605
      int err = SSL_get_error(ssl, ret);
 
606
 
 
607
      char errorString[1024];
 
608
 
 
609
      switch (err)
 
610
      {
 
611
         case SSL_ERROR_NONE:
 
612
            break;
 
613
         case SSL_ERROR_SSL:
 
614
            {
 
615
               ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
 
616
               DebugLog( << "Got DTLS handshake code SSL_ERROR_SSL"
 
617
                         << " error = " << errorString );
 
618
            }
 
619
            break;
 
620
         case SSL_ERROR_WANT_READ:
 
621
            break;
 
622
         case SSL_ERROR_WANT_WRITE:
 
623
            break;
 
624
         case SSL_ERROR_SYSCALL:
 
625
            {
 
626
               ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
 
627
               DebugLog( << "Got DTLS handshake code SSL_ERROR_SYSCALL"
 
628
                         << " error = " << errorString );
 
629
            }
 
630
            break;
 
631
         case SSL_ERROR_ZERO_RETURN:
 
632
            {
 
633
               ERR_error_string_n(ERR_get_error(), errorString, sizeof(errorString));
 
634
               DebugLog( << "Got DTLS handshake code SSL_ERROR_ZERO_RETURN"
 
635
                         << " error = " << errorString );
 
636
            }
 
637
            break;
 
638
         case SSL_ERROR_WANT_CONNECT:
 
639
            break;
 
640
         case SSL_ERROR_WANT_ACCEPT:
 
641
            break;
 
642
         default:
 
643
            break ;
 
644
      }
 
645
   }
 
646
}
 
647
 
 
648
void
 
649
DtlsTransport::process(FdSet& fdset)
 
650
{
 
651
   // pull buffers to send out of TxFifo
 
652
   // receive datagrams from fd
 
653
   // preparse and stuff into RxFifo
 
654
 
 
655
   mTimer.process() ;
 
656
 
 
657
   while ( mHandshakePending.messageAvailable() )
 
658
      _doHandshake() ;
 
659
 
 
660
   if ( ( mSendData != NULL || mTxFifo.messageAvailable() )
 
661
       && fdset.readyToWrite( mFd ) )
 
662
      _write( fdset ) ;
 
663
 
 
664
   // !jf! this may have to change - when we read a message that is too big
 
665
   if ( fdset.readyToRead(mFd) )
 
666
      _read( fdset ) ;
 
667
}
 
668
 
 
669
 
 
670
void
 
671
DtlsTransport::buildFdSet( FdSet& fdset )
 
672
{
 
673
   fdset.setRead(mFd);
 
674
 
 
675
   if ( mSendData != NULL || mTxFifo.messageAvailable() )
 
676
   {
 
677
     fdset.setWrite(mFd);
 
678
   }
 
679
}
 
680
 
 
681
void
 
682
DtlsTransport::_cleanupConnectionState( SSL *ssl, struct sockaddr_in peer )
 
683
{
 
684
   /*
 
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
 
687
    */
 
688
   CRYPTO_add(&mDummyBio->references, 1, CRYPTO_LOCK_BIO);
 
689
   SSL_shutdown(ssl);
 
690
   SSL_free(ssl) ;
 
691
   mDtlsConnections.erase(peer) ;
 
692
}
 
693
 
 
694
void
 
695
DtlsTransport::_mapDebug( const char *where, const char *action, SSL *ssl )
 
696
{
 
697
   fprintf( stderr, "%s: %s\t%p\n", where, action, ssl ) ;
 
698
   fprintf( stderr, "map sizet = %d\n", mDtlsConnections.size() ) ;
 
699
}
 
700
 
 
701
void
 
702
DtlsTransport::_printSock( const struct sockaddr_in *sock )
 
703
{
 
704
   fprintf( stderr, "addr = %s\t port = %d\n", inet_ntoa( sock->sin_addr ),
 
705
            ntohs( sock->sin_port ) ) ;
 
706
}
 
707
 
 
708
#endif /* USE_DTLS */
 
709
#endif /* USE_SSL */
 
710
 
 
711
/* ====================================================================
 
712
 * The Vovida Software License, Version 1.0
 
713
 *
 
714
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
 
715
 *
 
716
 * Redistribution and use in source and binary forms, with or without
 
717
 * modification, are permitted provided that the following conditions
 
718
 * are met:
 
719
 *
 
720
 * 1. Redistributions of source code must retain the above copyright
 
721
 *    notice, this list of conditions and the following disclaimer.
 
722
 *
 
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
 
726
 *    distribution.
 
727
 *
 
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.
 
733
 *
 
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.
 
737
 *
 
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
 
750
 * DAMAGE.
 
751
 *
 
752
 * ====================================================================
 
753
 *
 
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/>.
 
758
 *
 
759
 */