/*
 * libjingle
 * Copyright 2004--2008, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// SecureTunnelSessionClient and SecureTunnelSession implementation.

#include "talk/session/tunnel/securetunnelsessionclient.h"
#include "talk/base/basicdefs.h"
#include "talk/base/basictypes.h"
#include "talk/base/common.h"
#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/base/stringutils.h"
#include "talk/base/sslidentity.h"
#include "talk/base/sslstreamadapter.h"
#include "talk/p2p/base/transportchannel.h"
#include "talk/xmllite/xmlelement.h"
#include "talk/session/tunnel/pseudotcpchannel.h"

namespace cricket {

// XML elements and namespaces for XMPP stanzas used in content exchanges.

const char NS_SECURE_TUNNEL[] = "http://www.google.com/talk/securetunnel";
const buzz::StaticQName QN_SECURE_TUNNEL_DESCRIPTION =
    { NS_SECURE_TUNNEL, "description" };
const buzz::StaticQName QN_SECURE_TUNNEL_TYPE =
    { NS_SECURE_TUNNEL, "type" };
const buzz::StaticQName QN_SECURE_TUNNEL_CLIENT_CERT =
    { NS_SECURE_TUNNEL, "client-cert" };
const buzz::StaticQName QN_SECURE_TUNNEL_SERVER_CERT =
    { NS_SECURE_TUNNEL, "server-cert" };
const char CN_SECURE_TUNNEL[] = "securetunnel";

// SecureTunnelContentDescription

// TunnelContentDescription is extended to hold string forms of the
// client and server certificate, PEM encoded.

struct SecureTunnelContentDescription : public ContentDescription {
  std::string description;
  std::string client_pem_certificate;
  std::string server_pem_certificate;

  SecureTunnelContentDescription(const std::string& desc,
                                 const std::string& client_pem_cert,
                                 const std::string& server_pem_cert)
      : description(desc),
        client_pem_certificate(client_pem_cert),
        server_pem_certificate(server_pem_cert) {
  }
};

// SecureTunnelSessionClient

SecureTunnelSessionClient::SecureTunnelSessionClient(
    const buzz::Jid& jid, SessionManager* manager)
    : TunnelSessionClient(jid, manager, NS_SECURE_TUNNEL) {
}

void SecureTunnelSessionClient::SetIdentity(talk_base::SSLIdentity* identity) {
  ASSERT(identity_.get() == NULL);
  identity_.reset(identity);
}

bool SecureTunnelSessionClient::GenerateIdentity() {
  ASSERT(identity_.get() == NULL);
  identity_.reset(talk_base::SSLIdentity::Generate(
      // The name on the certificate does not matter: the peer will
      // make sure the cert it gets during SSL negotiation matches the
      // one it got from XMPP. It would be neat to put something
      // recognizable in there such as the JID, except this will show
      // in clear during the SSL negotiation and so it could be a
      // privacy issue. Specifying an empty string here causes
      // it to use a random string.
#ifdef _DEBUG
      jid().Str()
#else
      ""
#endif
      ));
  if (identity_.get() == NULL) {
    LOG(LS_ERROR) << "Failed to generate SSL identity";
    return false;
  }
  return true;
}

talk_base::SSLIdentity& SecureTunnelSessionClient::GetIdentity() const {
  ASSERT(identity_.get() != NULL);
  return *identity_;
}

// Parses a certificate from a PEM encoded string.
// Returns NULL on failure.
// The caller is responsible for freeing the returned object.
static talk_base::SSLCertificate* ParseCertificate(
    const std::string& pem_cert) {
  if (pem_cert.empty())
    return NULL;
  return talk_base::SSLCertificate::FromPEMString(pem_cert, NULL);
}

TunnelSession* SecureTunnelSessionClient::MakeTunnelSession(
    Session* session, talk_base::Thread* stream_thread,
    TunnelSessionRole role) {
  return new SecureTunnelSession(this, session, stream_thread, role);
}

bool FindSecureTunnelContent(const cricket::SessionDescription* sdesc,
                             std::string* name,
                             const SecureTunnelContentDescription** content) {
  const ContentInfo* cinfo = sdesc->FirstContentByType(NS_SECURE_TUNNEL);
  if (cinfo == NULL)
    return false;

  *name = cinfo->name;
  *content = static_cast<const SecureTunnelContentDescription*>(
      cinfo->description);
  return true;
}

void SecureTunnelSessionClient::OnIncomingTunnel(const buzz::Jid &jid,
                                                 Session *session) {
  std::string content_name;
  const SecureTunnelContentDescription* content = NULL;
  if (!FindSecureTunnelContent(session->remote_description(),
                               &content_name, &content)) {
    ASSERT(false);
  }

  // Validate the certificate
  talk_base::scoped_ptr<talk_base::SSLCertificate> peer_cert(
      ParseCertificate(content->client_pem_certificate));
  if (peer_cert.get() == NULL) {
    LOG(LS_ERROR)
        << "Rejecting incoming secure tunnel with invalid cetificate";
    DeclineTunnel(session);
    return;
  }
  // If there were a convenient place we could have cached the
  // peer_cert so as not to have to parse it a second time when
  // configuring the tunnel.
  SignalIncomingTunnel(this, jid, content->description, session);
}

// The XML representation of a session initiation request (XMPP IQ),
// containing the initiator's SecureTunnelContentDescription,
// looks something like this:
// <iq from="INITIATOR@gmail.com/pcpE101B7F4"
//       to="RECIPIENT@gmail.com/pcp8B87F0A3"
//       type="set" id="3">
//   <session xmlns="http://www.google.com/session"
//       type="initiate" id="2508605813"
//       initiator="INITIATOR@gmail.com/pcpE101B7F4">
//     <description xmlns="http://www.google.com/talk/securetunnel">
//       <type>send:filename</type>
//       <client-cert>
//         -----BEGIN CERTIFICATE-----
//         INITIATOR'S CERTIFICATE IN PERM FORMAT (ASCII GIBBERISH)
//         -----END CERTIFICATE-----
//       </client-cert>
//     </description>
//     <transport xmlns="http://www.google.com/transport/p2p"/>
//   </session>
// </iq>

// The session accept iq, containing the recipient's certificate and
// echoing the initiator's certificate, looks something like this:
// <iq from="RECIPIENT@gmail.com/pcpE101B7F4"
//     to="INITIATOR@gmail.com/pcpE101B7F4"
//     type="set" id="5">
//   <session xmlns="http://www.google.com/session"
//       type="accept" id="2508605813"
//       initiator="sdoyon911@gmail.com/pcpE101B7F4">
//     <description xmlns="http://www.google.com/talk/securetunnel">
//       <type>send:FILENAME</type>
//       <client-cert>
//         -----BEGIN CERTIFICATE-----
//         INITIATOR'S CERTIFICATE IN PERM FORMAT (ASCII GIBBERISH)
//         -----END CERTIFICATE-----
//       </client-cert>
//       <server-cert>
//         -----BEGIN CERTIFICATE-----
//         RECIPIENT'S CERTIFICATE IN PERM FORMAT (ASCII GIBBERISH)
//         -----END CERTIFICATE-----
//       </server-cert>
//     </description>
//   </session>
// </iq>


bool SecureTunnelSessionClient::ParseContent(SignalingProtocol protocol,
                                             const buzz::XmlElement* elem,
                                             const ContentDescription** content,
                                             ParseError* error) {
  const buzz::XmlElement* type_elem = elem->FirstNamed(QN_SECURE_TUNNEL_TYPE);

  if (type_elem == NULL)
    // Missing mandatory XML element.
    return false;

  // Here we consider the certificate components to be optional. In
  // practice the client certificate is always present, and the server
  // certificate is initially missing from the session description
  // sent during session initiation. OnAccept() will enforce that we
  // have a certificate for our peer.
  const buzz::XmlElement* client_cert_elem =
      elem->FirstNamed(QN_SECURE_TUNNEL_CLIENT_CERT);
  const buzz::XmlElement* server_cert_elem =
      elem->FirstNamed(QN_SECURE_TUNNEL_SERVER_CERT);
  *content = new SecureTunnelContentDescription(
      type_elem->BodyText(),
      client_cert_elem ? client_cert_elem->BodyText() : "",
      server_cert_elem ? server_cert_elem->BodyText() : "");
  return true;
}

bool SecureTunnelSessionClient::WriteContent(
    SignalingProtocol protocol, const ContentDescription* untyped_content,
    buzz::XmlElement** elem, WriteError* error) {
  const SecureTunnelContentDescription* content =
      static_cast<const SecureTunnelContentDescription*>(untyped_content);

  buzz::XmlElement* root =
      new buzz::XmlElement(QN_SECURE_TUNNEL_DESCRIPTION, true);
  buzz::XmlElement* type_elem = new buzz::XmlElement(QN_SECURE_TUNNEL_TYPE);
  type_elem->SetBodyText(content->description);
  root->AddElement(type_elem);
  if (!content->client_pem_certificate.empty()) {
    buzz::XmlElement* client_cert_elem =
        new buzz::XmlElement(QN_SECURE_TUNNEL_CLIENT_CERT);
    client_cert_elem->SetBodyText(content->client_pem_certificate);
    root->AddElement(client_cert_elem);
  }
  if (!content->server_pem_certificate.empty()) {
    buzz::XmlElement* server_cert_elem =
        new buzz::XmlElement(QN_SECURE_TUNNEL_SERVER_CERT);
    server_cert_elem->SetBodyText(content->server_pem_certificate);
    root->AddElement(server_cert_elem);
  }
  *elem = root;
  return true;
}

SessionDescription* NewSecureTunnelSessionDescription(
    const std::string& content_name, const ContentDescription* content) {
  SessionDescription* sdesc = new SessionDescription();
  sdesc->AddContent(content_name, NS_SECURE_TUNNEL, content);
  return sdesc;
}

SessionDescription* SecureTunnelSessionClient::CreateOffer(
    const buzz::Jid &jid, const std::string &description) {
  // We are the initiator so we are the client. Put our cert into the
  // description.
  std::string pem_cert = GetIdentity().certificate().ToPEMString();
  return NewSecureTunnelSessionDescription(
      CN_SECURE_TUNNEL,
      new SecureTunnelContentDescription(description, pem_cert, ""));
}

SessionDescription* SecureTunnelSessionClient::CreateAnswer(
    const SessionDescription* offer) {
  std::string content_name;
  const SecureTunnelContentDescription* offer_tunnel = NULL;
  if (!FindSecureTunnelContent(offer, &content_name, &offer_tunnel))
    return NULL;

  // We are accepting a session request. We need to add our cert, the
  // server cert, into the description. The client cert was validated
  // in OnIncomingTunnel().
  ASSERT(!offer_tunnel->client_pem_certificate.empty());
  return NewSecureTunnelSessionDescription(
      content_name,
      new SecureTunnelContentDescription(
          offer_tunnel->description,
          offer_tunnel->client_pem_certificate,
          GetIdentity().certificate().ToPEMString()));
}

// SecureTunnelSession

SecureTunnelSession::SecureTunnelSession(
    SecureTunnelSessionClient* client, Session* session,
    talk_base::Thread* stream_thread, TunnelSessionRole role)
    : TunnelSession(client, session, stream_thread),
      role_(role) {
}

talk_base::StreamInterface* SecureTunnelSession::MakeSecureStream(
    talk_base::StreamInterface* stream) {
  talk_base::SSLStreamAdapter* ssl_stream =
      talk_base::SSLStreamAdapter::Create(stream);
  talk_base::SSLIdentity* identity =
      static_cast<SecureTunnelSessionClient*>(client_)->
      GetIdentity().GetReference();
  ssl_stream->SetIdentity(identity);
  if (role_ == RESPONDER)
    ssl_stream->SetServerRole();
  ssl_stream->StartSSLWithPeer();

  // SSL negotiation will start on the stream as soon as it
  // opens. However our SSLStreamAdapter still hasn't been told what
  // certificate to allow for our peer. If we are the initiator, we do
  // not have the peer's certificate yet: we will obtain it from the
  // session accept message which we will receive later (see
  // OnAccept()). We won't Connect() the PseudoTcpChannel until we get
  // that, so the stream will stay closed until then.  Keep a handle
  // on the streem so we can configure the peer certificate later.
  ssl_stream_reference_.reset(new talk_base::StreamReference(ssl_stream));
  return ssl_stream_reference_->NewReference();
}

talk_base::StreamInterface* SecureTunnelSession::GetStream() {
  ASSERT(channel_ != NULL);
  ASSERT(ssl_stream_reference_.get() == NULL);
  return MakeSecureStream(channel_->GetStream());
}

void SecureTunnelSession::OnAccept() {
  // We have either sent or received a session accept: it's time to
  // connect the tunnel. First we must set the peer certificate.
  ASSERT(channel_ != NULL);
  ASSERT(session_ != NULL);
  std::string content_name;
  const SecureTunnelContentDescription* remote_tunnel = NULL;
  if (!FindSecureTunnelContent(session_->remote_description(),
                               &content_name, &remote_tunnel)) {
    session_->Reject(STR_TERMINATE_INCOMPATIBLE_PARAMETERS);
    return;
  }

  const std::string& cert_pem =
      role_ == INITIATOR ? remote_tunnel->server_pem_certificate :
                           remote_tunnel->client_pem_certificate;
  talk_base::SSLCertificate* peer_cert =
      ParseCertificate(cert_pem);
  if (peer_cert == NULL) {
    ASSERT(role_ == INITIATOR);  // when RESPONDER we validated it earlier
    LOG(LS_ERROR)
        << "Rejecting secure tunnel accept with invalid cetificate";
    session_->Reject(STR_TERMINATE_INCOMPATIBLE_PARAMETERS);
    return;
  }
  ASSERT(ssl_stream_reference_.get() != NULL);
  talk_base::SSLStreamAdapter* ssl_stream =
      static_cast<talk_base::SSLStreamAdapter*>(
          ssl_stream_reference_->GetStream());
  ssl_stream->SetPeerCertificate(peer_cert);  // pass ownership of certificate.
  // We no longer need our handle to the ssl stream.
  ssl_stream_reference_.reset();
  LOG(LS_INFO) << "Connecting tunnel";
  // This will try to connect the PseudoTcpChannel. If and when that
  // succeeds, then ssl negotiation will take place, and when that
  // succeeds, the tunnel stream will finally open.
  VERIFY(channel_->Connect(content_name, "tcp"));
}

}  // namespace cricket
