/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef WEBRTC_BASE_OPENSSLSTREAMADAPTER_H__
#define WEBRTC_BASE_OPENSSLSTREAMADAPTER_H__

#include <string>
#include <vector>

#include "webrtc/base/buffer.h"
#include "webrtc/base/sslstreamadapter.h"
#include "webrtc/base/opensslidentity.h"

typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
typedef struct x509_store_ctx_st X509_STORE_CTX;

namespace rtc {

// This class was written with OpenSSLAdapter (a socket adapter) as a
// starting point. It has similar structure and functionality, with
// the peer-to-peer mode added.
//
// Static methods to initialize and deinit the SSL library are in
// OpenSSLAdapter. This class also uses
// OpenSSLAdapter::custom_verify_callback_ (a static field). These
// should probably be moved out to a neutral class.
//
// In a few cases I have factored out some OpenSSLAdapter code into
// static methods so it can be reused from this class. Eventually that
// code should probably be moved to a common support
// class. Unfortunately there remain a few duplicated sections of
// code. I have not done more restructuring because I did not want to
// affect existing code that uses OpenSSLAdapter.
//
// This class does not support the SSL connection restart feature
// present in OpenSSLAdapter. I am not entirely sure how the feature
// is useful and I am not convinced that it works properly.
//
// This implementation is careful to disallow data exchange after an
// SSL error, and it has an explicit SSL_CLOSED state. It should not
// be possible to send any data in clear after one of the StartSSL
// methods has been called.

// Look in sslstreamadapter.h for documentation of the methods.

class OpenSSLIdentity;

///////////////////////////////////////////////////////////////////////////////

class OpenSSLStreamAdapter : public SSLStreamAdapter {
 public:
  explicit OpenSSLStreamAdapter(StreamInterface* stream);
  virtual ~OpenSSLStreamAdapter();

  virtual void SetIdentity(SSLIdentity* identity);

  // Default argument is for compatibility
  virtual void SetServerRole(SSLRole role = SSL_SERVER);
  virtual bool SetPeerCertificateDigest(const std::string& digest_alg,
                                        const unsigned char* digest_val,
                                        size_t digest_len);

  virtual bool GetPeerCertificate(SSLCertificate** cert) const;

  virtual int StartSSLWithServer(const char* server_name);
  virtual int StartSSLWithPeer();
  virtual void SetMode(SSLMode mode);

  virtual StreamResult Read(void* data, size_t data_len,
                            size_t* read, int* error);
  virtual StreamResult Write(const void* data, size_t data_len,
                             size_t* written, int* error);
  virtual void Close();
  virtual StreamState GetState() const;

  // Key Extractor interface
  virtual bool ExportKeyingMaterial(const std::string& label,
                                    const uint8* context,
                                    size_t context_len,
                                    bool use_context,
                                    uint8* result,
                                    size_t result_len);


  // DTLS-SRTP interface
  virtual bool SetDtlsSrtpCiphers(const std::vector<std::string>& ciphers);
  virtual bool GetDtlsSrtpCipher(std::string* cipher);

  // Capabilities interfaces
  static bool HaveDtls();
  static bool HaveDtlsSrtp();
  static bool HaveExporter();

 protected:
  virtual void OnEvent(StreamInterface* stream, int events, int err);

 private:
  enum SSLState {
    // Before calling one of the StartSSL methods, data flows
    // in clear text.
    SSL_NONE,
    SSL_WAIT,  // waiting for the stream to open to start SSL negotiation
    SSL_CONNECTING,  // SSL negotiation in progress
    SSL_CONNECTED,  // SSL stream successfully established
    SSL_ERROR,  // some SSL error occurred, stream is closed
    SSL_CLOSED  // Clean close
  };

  enum { MSG_TIMEOUT = MSG_MAX+1};

  // The following three methods return 0 on success and a negative
  // error code on failure. The error code may be from OpenSSL or -1
  // on some other error cases, so it can't really be interpreted
  // unfortunately.

  // Go from state SSL_NONE to either SSL_CONNECTING or SSL_WAIT,
  // depending on whether the underlying stream is already open or
  // not.
  int StartSSL();
  // Prepare SSL library, state is SSL_CONNECTING.
  int BeginSSL();
  // Perform SSL negotiation steps.
  int ContinueSSL();

  // Error handler helper. signal is given as true for errors in
  // asynchronous contexts (when an error method was not returned
  // through some other method), and in that case an SE_CLOSE event is
  // raised on the stream with the specified error.
  // A 0 error means a graceful close, otherwise there is not really enough
  // context to interpret the error code.
  void Error(const char* context, int err, bool signal);
  void Cleanup();

  // Override MessageHandler
  virtual void OnMessage(Message* msg);

  // Flush the input buffers by reading left bytes (for DTLS)
  void FlushInput(unsigned int left);

  // SSL library configuration
  SSL_CTX* SetupSSLContext();
  // SSL verification check
  bool SSLPostConnectionCheck(SSL* ssl, const char* server_name,
                              const X509* peer_cert,
                              const std::string& peer_digest);
  // SSL certification verification error handler, called back from
  // the openssl library. Returns an int interpreted as a boolean in
  // the C style: zero means verification failure, non-zero means
  // passed.
  static int SSLVerifyCallback(int ok, X509_STORE_CTX* store);

  SSLState state_;
  SSLRole role_;
  int ssl_error_code_;  // valid when state_ == SSL_ERROR or SSL_CLOSED
  // Whether the SSL negotiation is blocked on needing to read or
  // write to the wrapped stream.
  bool ssl_read_needs_write_;
  bool ssl_write_needs_read_;

  SSL* ssl_;
  SSL_CTX* ssl_ctx_;

  // Our key and certificate, mostly useful in peer-to-peer mode.
  scoped_ptr<OpenSSLIdentity> identity_;
  // in traditional mode, the server name that the server's certificate
  // must specify. Empty in peer-to-peer mode.
  std::string ssl_server_name_;
  // The certificate that the peer must present or did present. Initially
  // null in traditional mode, until the connection is established.
  scoped_ptr<OpenSSLCertificate> peer_certificate_;
  // In peer-to-peer mode, the digest of the certificate that
  // the peer must present.
  Buffer peer_certificate_digest_value_;
  std::string peer_certificate_digest_algorithm_;

  // OpenSSLAdapter::custom_verify_callback_ result
  bool custom_verification_succeeded_;

  // The DtlsSrtp ciphers
  std::string srtp_ciphers_;

  // Do DTLS or not
  SSLMode ssl_mode_;
};

/////////////////////////////////////////////////////////////////////////////

}  // namespace rtc

#endif  // WEBRTC_BASE_OPENSSLSTREAMADAPTER_H__
