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