1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2008, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifndef TALK_BASE_OPENSSLSTREAMADAPTER_H__
29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define TALK_BASE_OPENSSLSTREAMADAPTER_H__
30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <string>
32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/sslstreamadapter.h"
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/opensslidentity.h"
34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef struct ssl_st SSL;
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef struct ssl_ctx_st SSL_CTX;
37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef struct x509_store_ctx_st X509_STORE_CTX;
38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base {
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// This class was written with OpenSSLAdapter (a socket adapter) as a
42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// starting point. It has similar structure and functionality, with
43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// the peer-to-peer mode added.
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Static methods to initialize and deinit the SSL library are in
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// OpenSSLAdapter. This class also uses
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// OpenSSLAdapter::custom_verify_callback_ (a static field). These
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// should probably be moved out to a neutral class.
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// In a few cases I have factored out some OpenSSLAdapter code into
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// static methods so it can be reused from this class. Eventually that
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// code should probably be moved to a common support
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// class. Unfortunately there remain a few duplicated sections of
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// code. I have not done more restructuring because I did not want to
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// affect existing code that uses OpenSSLAdapter.
56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// This class does not support the SSL connection restart feature
58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// present in OpenSSLAdapter. I am not entirely sure how the feature
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// is useful and I am not convinced that it works properly.
60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// This implementation is careful to disallow data exchange after an
62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// SSL error, and it has an explicit SSL_CLOSED state. It should not
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// be possible to send any data in clear after one of the StartSSL
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// methods has been called.
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Look in sslstreamadapter.h for documentation of the methods.
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass OpenSSLIdentity;
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch///////////////////////////////////////////////////////////////////////////////
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass OpenSSLStreamAdapter : public SSLStreamAdapter {
73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public:
74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  explicit OpenSSLStreamAdapter(StreamInterface* stream);
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual ~OpenSSLStreamAdapter();
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void SetIdentity(SSLIdentity* identity);
78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void SetServerRole();
79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void SetPeerCertificate(SSLCertificate* cert);
80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual int StartSSLWithServer(const char* server_name);
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual int StartSSLWithPeer();
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual StreamResult Read(void* data, size_t data_len,
85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                            size_t* read, int* error);
86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual StreamResult Write(const void* data, size_t data_len,
87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                             size_t* written, int* error);
88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void Close();
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual StreamState GetState() const;
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch protected:
92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  virtual void OnEvent(StreamInterface* stream, int events, int err);
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch private:
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  enum SSLState {
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Before calling one of the StartSSL methods, data flows
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // in clear text.
98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_NONE,
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_WAIT,  // waiting for the stream to open to start SSL negotiation
100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_CONNECTING,  // SSL negotiation in progress
101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_CONNECTED,  // SSL stream successfully established
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_ERROR,  // some SSL error occurred, stream is closed
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_CLOSED  // Clean close
104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  };
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  enum SSLRole {
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_CLIENT, SSL_SERVER
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  };
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // The following three methods return 0 on success and a negative
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // error code on failure. The error code may be from OpenSSL or -1
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // on some other error cases, so it can't really be interpreted
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // unfortunately.
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Go from state SSL_NONE to either SSL_CONNECTING or SSL_WAIT,
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // depending on whether the underlying stream is already open or
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // not.
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int StartSSL();
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Prepare SSL library, state is SSL_CONNECTING.
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int BeginSSL();
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Perform SSL negotiation steps.
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int ContinueSSL();
122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Error handler helper. signal is given as true for errors in
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // asynchronous contexts (when an error method was not returned
125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // through some other method), and in that case an SE_CLOSE event is
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // raised on the stream with the specified error.
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // A 0 error means a graceful close, otherwise there is not really enough
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // context to interpret the error code.
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  void Error(const char* context, int err, bool signal);
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  void Cleanup();
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // SSL library configuration
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_CTX* SetupSSLContext();
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // SSL verification check
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool SSLPostConnectionCheck(SSL* ssl, const char* server_name,
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                              const X509* peer_cert);
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // SSL certification verification error handler, called back from
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // the openssl library. Returns an int interpreted as a boolean in
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // the C style: zero means verification failure, non-zero means
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // passed.
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  static int SSLVerifyCallback(int ok, X509_STORE_CTX* store);
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSLState state_;
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSLRole role_;
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int ssl_error_code_;  // valid when state_ == SSL_ERROR or SSL_CLOSED
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Whether the SSL negotiation is blocked on needing to read or
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // write to the wrapped stream.
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ssl_read_needs_write_;
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ssl_write_needs_read_;
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL* ssl_;
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_CTX* ssl_ctx_;
154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // in traditional mode, the server name that the server's certificate
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // must specify. Empty in peer-to-peer mode.
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Our key and certificate, mostly useful in peer-to-peer mode.
157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  scoped_ptr<OpenSSLIdentity> identity_;
158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string ssl_server_name_;
159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // In peer-to-peer mode, the certificate that the peer must
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // present. Empty in traditional mode.
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  scoped_ptr<OpenSSLCertificate> peer_certificate_;
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // OpenSSLAdapter::custom_verify_callback_ result
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool custom_verification_succeeded_;
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////
168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}  // namespace talk_base
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // TALK_BASE_OPENSSLSTREAMADAPTER_H__
172