Home | History | Annotate | Download | only in base
      1 /*
      2  * libjingle
      3  * Copyright 2012, Google, Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #ifndef TALK_P2P_BASE_DTLSTRANSPORT_H_
     29 #define TALK_P2P_BASE_DTLSTRANSPORT_H_
     30 
     31 #include "talk/p2p/base/dtlstransportchannel.h"
     32 #include "talk/p2p/base/transport.h"
     33 
     34 namespace talk_base {
     35 class SSLIdentity;
     36 }
     37 
     38 namespace cricket {
     39 
     40 class PortAllocator;
     41 
     42 // Base should be a descendant of cricket::Transport
     43 template<class Base>
     44 class DtlsTransport : public Base {
     45  public:
     46   DtlsTransport(talk_base::Thread* signaling_thread,
     47                 talk_base::Thread* worker_thread,
     48                 const std::string& content_name,
     49                 PortAllocator* allocator,
     50                 talk_base::SSLIdentity* identity)
     51       : Base(signaling_thread, worker_thread, content_name, allocator),
     52         identity_(identity) {
     53   }
     54 
     55   ~DtlsTransport() {
     56     Base::DestroyAllChannels();
     57   }
     58 
     59   virtual void SetIdentity_w(talk_base::SSLIdentity* identity) {
     60     identity_ = identity;
     61   }
     62 
     63   virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl*
     64                                                 channel) {
     65     talk_base::SSLFingerprint* local_fp =
     66         Base::local_description()->identity_fingerprint.get();
     67 
     68     if (local_fp) {
     69       // Sanity check local fingerprint.
     70       if (identity_) {
     71         talk_base::scoped_ptr<talk_base::SSLFingerprint> local_fp_tmp(
     72             talk_base::SSLFingerprint::Create(local_fp->algorithm,
     73                                               identity_));
     74         ASSERT(local_fp_tmp.get() != NULL);
     75         if (!(*local_fp_tmp == *local_fp)) {
     76           LOG(LS_WARNING) << "Local fingerprint does not match identity";
     77           return false;
     78         }
     79       } else {
     80         LOG(LS_WARNING)
     81             << "Local fingerprint provided but no identity available";
     82         return false;
     83       }
     84     } else {
     85       identity_ = NULL;
     86     }
     87 
     88     if (!channel->SetLocalIdentity(identity_))
     89       return false;
     90 
     91     // Apply the description in the base class.
     92     return Base::ApplyLocalTransportDescription_w(channel);
     93   }
     94 
     95   virtual bool NegotiateTransportDescription_w(ContentAction local_role) {
     96     talk_base::SSLFingerprint* local_fp =
     97         Base::local_description()->identity_fingerprint.get();
     98     talk_base::SSLFingerprint* remote_fp =
     99         Base::remote_description()->identity_fingerprint.get();
    100 
    101     if (remote_fp && local_fp) {
    102       remote_fingerprint_.reset(new talk_base::SSLFingerprint(*remote_fp));
    103     } else if (local_fp && (local_role == CA_ANSWER)) {
    104       LOG(LS_ERROR)
    105           << "Local fingerprint supplied when caller didn't offer DTLS";
    106       return false;
    107     } else {
    108       // We are not doing DTLS
    109       remote_fingerprint_.reset(new talk_base::SSLFingerprint(
    110           "", NULL, 0));
    111     }
    112 
    113     // Now run the negotiation for the base class.
    114     return Base::NegotiateTransportDescription_w(local_role);
    115   }
    116 
    117   virtual DtlsTransportChannelWrapper* CreateTransportChannel(int component) {
    118     return new DtlsTransportChannelWrapper(
    119         this, Base::CreateTransportChannel(component));
    120   }
    121 
    122   virtual void DestroyTransportChannel(TransportChannelImpl* channel) {
    123     // Kind of ugly, but this lets us do the exact inverse of the create.
    124     DtlsTransportChannelWrapper* dtls_channel =
    125         static_cast<DtlsTransportChannelWrapper*>(channel);
    126     TransportChannelImpl* base_channel = dtls_channel->channel();
    127     delete dtls_channel;
    128     Base::DestroyTransportChannel(base_channel);
    129   }
    130 
    131  private:
    132   virtual void ApplyNegotiatedTransportDescription_w(
    133       TransportChannelImpl* channel) {
    134     channel->SetRemoteFingerprint(
    135         remote_fingerprint_->algorithm,
    136         reinterpret_cast<const uint8 *>(remote_fingerprint_->
    137                                     digest.data()),
    138         remote_fingerprint_->digest.length());
    139     Base::ApplyNegotiatedTransportDescription_w(channel);
    140   }
    141 
    142   talk_base::SSLIdentity* identity_;
    143   talk_base::scoped_ptr<talk_base::SSLFingerprint> remote_fingerprint_;
    144 };
    145 
    146 }  // namespace cricket
    147 
    148 #endif  // TALK_P2P_BASE_DTLSTRANSPORT_H_
    149