147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <vector>
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if HAVE_CONFIG_H
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "config.h"
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // HAVE_CONFIG_H
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/sslstreamadapterhelper.h"
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/common.h"
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h"
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stream.h"
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SSLStreamAdapterHelper::SetIdentity(SSLIdentity* identity) {
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(identity_.get() == NULL);
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  identity_.reset(identity);
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SSLStreamAdapterHelper::SetServerRole(SSLRole role) {
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  role_ = role;
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SSLStreamAdapterHelper::StartSSLWithServer(const char* server_name) {
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(server_name != NULL && server_name[0] != '\0');
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ssl_server_name_ = server_name;
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return StartSSL();
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SSLStreamAdapterHelper::StartSSLWithPeer() {
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(ssl_server_name_.empty());
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // It is permitted to specify peer_certificate_ only later.
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return StartSSL();
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SSLStreamAdapterHelper::SetMode(SSLMode mode) {
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(state_ == SSL_NONE);
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ssl_mode_ = mode;
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgStreamState SSLStreamAdapterHelper::GetState() const {
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  switch (state_) {
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case SSL_WAIT:
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case SSL_CONNECTING:
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return SS_OPENING;
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    case SSL_CONNECTED:
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return SS_OPEN;
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    default:
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return SS_CLOSED;
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  };
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // not reached
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SSLStreamAdapterHelper::GetPeerCertificate(SSLCertificate** cert) const {
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!peer_certificate_)
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  *cert = peer_certificate_->GetReference();
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SSLStreamAdapterHelper::SetPeerCertificateDigest(
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    const std::string &digest_alg,
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    const unsigned char* digest_val,
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t digest_len) {
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(peer_certificate_.get() == NULL);
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(peer_certificate_digest_algorithm_.empty());
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(ssl_server_name_.empty());
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t expected_len;
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!GetDigestLength(digest_alg, &expected_len)) {
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_WARNING) << "Unknown digest algorithm: " << digest_alg;
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (expected_len != digest_len)
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  peer_certificate_digest_value_.SetData(digest_val, digest_len);
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  peer_certificate_digest_algorithm_ = digest_alg;
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SSLStreamAdapterHelper::Error(const char* context, int err, bool signal) {
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_WARNING) << "SSLStreamAdapterHelper::Error("
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  << context << ", " << err << "," << signal << ")";
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  state_ = SSL_ERROR;
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ssl_error_code_ = err;
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Cleanup();
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (signal)
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    StreamAdapterInterface::OnEvent(stream(), SE_CLOSE, err);
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SSLStreamAdapterHelper::Close() {
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Cleanup();
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(state_ == SSL_CLOSED || state_ == SSL_ERROR);
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  StreamAdapterInterface::Close();
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint SSLStreamAdapterHelper::StartSSL() {
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(state_ == SSL_NONE);
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (StreamAdapterInterface::GetState() != SS_OPEN) {
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    state_ = SSL_WAIT;
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  state_ = SSL_CONNECTING;
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int err = BeginSSL();
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (err) {
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Error("BeginSSL", err, false);
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return err;
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return 0;
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
131