1 /* 2 * libjingle 3 * Copyright 2004--2008, Google Inc. 4 * Copyright 2012, RTFM, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 30 #include <vector> 31 32 #if HAVE_CONFIG_H 33 #include "config.h" 34 #endif // HAVE_CONFIG_H 35 36 #include "talk/base/sslstreamadapterhelper.h" 37 38 #include "talk/base/common.h" 39 #include "talk/base/logging.h" 40 #include "talk/base/stream.h" 41 42 namespace talk_base { 43 44 void SSLStreamAdapterHelper::SetIdentity(SSLIdentity* identity) { 45 ASSERT(identity_.get() == NULL); 46 identity_.reset(identity); 47 } 48 49 void SSLStreamAdapterHelper::SetServerRole(SSLRole role) { 50 role_ = role; 51 } 52 53 int SSLStreamAdapterHelper::StartSSLWithServer(const char* server_name) { 54 ASSERT(server_name != NULL && server_name[0] != '\0'); 55 ssl_server_name_ = server_name; 56 return StartSSL(); 57 } 58 59 int SSLStreamAdapterHelper::StartSSLWithPeer() { 60 ASSERT(ssl_server_name_.empty()); 61 // It is permitted to specify peer_certificate_ only later. 62 return StartSSL(); 63 } 64 65 void SSLStreamAdapterHelper::SetMode(SSLMode mode) { 66 ASSERT(state_ == SSL_NONE); 67 ssl_mode_ = mode; 68 } 69 70 StreamState SSLStreamAdapterHelper::GetState() const { 71 switch (state_) { 72 case SSL_WAIT: 73 case SSL_CONNECTING: 74 return SS_OPENING; 75 case SSL_CONNECTED: 76 return SS_OPEN; 77 default: 78 return SS_CLOSED; 79 }; 80 // not reached 81 } 82 83 void SSLStreamAdapterHelper::SetPeerCertificate(SSLCertificate* cert) { 84 ASSERT(peer_certificate_.get() == NULL); 85 ASSERT(peer_certificate_digest_algorithm_.empty()); 86 ASSERT(ssl_server_name_.empty()); 87 peer_certificate_.reset(cert); 88 } 89 90 bool SSLStreamAdapterHelper::GetPeerCertificate(SSLCertificate** cert) const { 91 if (!peer_certificate_) 92 return false; 93 94 *cert = peer_certificate_->GetReference(); 95 return true; 96 } 97 98 bool SSLStreamAdapterHelper::SetPeerCertificateDigest( 99 const std::string &digest_alg, 100 const unsigned char* digest_val, 101 size_t digest_len) { 102 ASSERT(peer_certificate_.get() == NULL); 103 ASSERT(peer_certificate_digest_algorithm_.empty()); 104 ASSERT(ssl_server_name_.empty()); 105 size_t expected_len; 106 107 if (!GetDigestLength(digest_alg, &expected_len)) { 108 LOG(LS_WARNING) << "Unknown digest algorithm: " << digest_alg; 109 return false; 110 } 111 if (expected_len != digest_len) 112 return false; 113 114 peer_certificate_digest_value_.SetData(digest_val, digest_len); 115 peer_certificate_digest_algorithm_ = digest_alg; 116 117 return true; 118 } 119 120 void SSLStreamAdapterHelper::Error(const char* context, int err, bool signal) { 121 LOG(LS_WARNING) << "SSLStreamAdapterHelper::Error(" 122 << context << ", " << err << "," << signal << ")"; 123 state_ = SSL_ERROR; 124 ssl_error_code_ = err; 125 Cleanup(); 126 if (signal) 127 StreamAdapterInterface::OnEvent(stream(), SE_CLOSE, err); 128 } 129 130 void SSLStreamAdapterHelper::Close() { 131 Cleanup(); 132 ASSERT(state_ == SSL_CLOSED || state_ == SSL_ERROR); 133 StreamAdapterInterface::Close(); 134 } 135 136 int SSLStreamAdapterHelper::StartSSL() { 137 ASSERT(state_ == SSL_NONE); 138 139 if (StreamAdapterInterface::GetState() != SS_OPEN) { 140 state_ = SSL_WAIT; 141 return 0; 142 } 143 144 state_ = SSL_CONNECTING; 145 int err = BeginSSL(); 146 if (err) { 147 Error("BeginSSL", err, false); 148 return err; 149 } 150 151 return 0; 152 } 153 154 } // namespace talk_base 155 156