1/*
2 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12#include <vector>
13
14#if HAVE_CONFIG_H
15#include "config.h"
16#endif  // HAVE_CONFIG_H
17
18#include "webrtc/base/sslstreamadapterhelper.h"
19
20#include "webrtc/base/common.h"
21#include "webrtc/base/logging.h"
22#include "webrtc/base/stream.h"
23
24namespace rtc {
25
26void SSLStreamAdapterHelper::SetIdentity(SSLIdentity* identity) {
27  ASSERT(identity_.get() == NULL);
28  identity_.reset(identity);
29}
30
31void SSLStreamAdapterHelper::SetServerRole(SSLRole role) {
32  role_ = role;
33}
34
35int SSLStreamAdapterHelper::StartSSLWithServer(const char* server_name) {
36  ASSERT(server_name != NULL && server_name[0] != '\0');
37  ssl_server_name_ = server_name;
38  return StartSSL();
39}
40
41int SSLStreamAdapterHelper::StartSSLWithPeer() {
42  ASSERT(ssl_server_name_.empty());
43  // It is permitted to specify peer_certificate_ only later.
44  return StartSSL();
45}
46
47void SSLStreamAdapterHelper::SetMode(SSLMode mode) {
48  ASSERT(state_ == SSL_NONE);
49  ssl_mode_ = mode;
50}
51
52StreamState SSLStreamAdapterHelper::GetState() const {
53  switch (state_) {
54    case SSL_WAIT:
55    case SSL_CONNECTING:
56      return SS_OPENING;
57    case SSL_CONNECTED:
58      return SS_OPEN;
59    default:
60      return SS_CLOSED;
61  };
62  // not reached
63}
64
65bool SSLStreamAdapterHelper::GetPeerCertificate(SSLCertificate** cert) const {
66  if (!peer_certificate_)
67    return false;
68
69  *cert = peer_certificate_->GetReference();
70  return true;
71}
72
73bool SSLStreamAdapterHelper::SetPeerCertificateDigest(
74    const std::string &digest_alg,
75    const unsigned char* digest_val,
76    size_t digest_len) {
77  ASSERT(peer_certificate_.get() == NULL);
78  ASSERT(peer_certificate_digest_algorithm_.empty());
79  ASSERT(ssl_server_name_.empty());
80  size_t expected_len;
81
82  if (!GetDigestLength(digest_alg, &expected_len)) {
83    LOG(LS_WARNING) << "Unknown digest algorithm: " << digest_alg;
84    return false;
85  }
86  if (expected_len != digest_len)
87    return false;
88
89  peer_certificate_digest_value_.SetData(digest_val, digest_len);
90  peer_certificate_digest_algorithm_ = digest_alg;
91
92  return true;
93}
94
95void SSLStreamAdapterHelper::Error(const char* context, int err, bool signal) {
96  LOG(LS_WARNING) << "SSLStreamAdapterHelper::Error("
97                  << context << ", " << err << "," << signal << ")";
98  state_ = SSL_ERROR;
99  ssl_error_code_ = err;
100  Cleanup();
101  if (signal)
102    StreamAdapterInterface::OnEvent(stream(), SE_CLOSE, err);
103}
104
105void SSLStreamAdapterHelper::Close() {
106  Cleanup();
107  ASSERT(state_ == SSL_CLOSED || state_ == SSL_ERROR);
108  StreamAdapterInterface::Close();
109}
110
111int SSLStreamAdapterHelper::StartSSL() {
112  ASSERT(state_ == SSL_NONE);
113
114  if (StreamAdapterInterface::GetState() != SS_OPEN) {
115    state_ = SSL_WAIT;
116    return 0;
117  }
118
119  state_ = SSL_CONNECTING;
120  int err = BeginSSL();
121  if (err) {
122    Error("BeginSSL", err, false);
123    return err;
124  }
125
126  return 0;
127}
128
129}  // namespace rtc
130
131