/*
 * 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/p2p/base/transportchannel.h"
#include "talk/session/tunnel/pseudotcpchannel.h"
#include "talk/session/tunnel/securetunnelsessionclient.h"
#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "webrtc/base/basicdefs.h"
#include "webrtc/base/basictypes.h"
#include "webrtc/base/common.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/sslidentity.h"
#include "webrtc/base/sslstreamadapter.h"
#include "webrtc/base/stringutils.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) {
  }
  virtual ContentDescription* Copy() const {
    return new SecureTunnelContentDescription(*this);
  }
};

// SecureTunnelSessionClient

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

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

bool SecureTunnelSessionClient::GenerateIdentity() {
  ASSERT(identity_.get() == NULL);
  identity_.reset(rtc::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;
}

rtc::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 rtc::SSLCertificate* ParseCertificate(
    const std::string& pem_cert) {
  if (pem_cert.empty())
    return NULL;
  return rtc::SSLCertificate::FromPEMString(pem_cert);
}

TunnelSession* SecureTunnelSessionClient::MakeTunnelSession(
    Session* session, rtc::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
  rtc::scoped_ptr<rtc::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,
                                             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, 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,
    rtc::Thread* stream_thread, TunnelSessionRole role)
    : TunnelSession(client, session, stream_thread),
      role_(role) {
}

rtc::StreamInterface* SecureTunnelSession::MakeSecureStream(
    rtc::StreamInterface* stream) {
  rtc::SSLStreamAdapter* ssl_stream =
      rtc::SSLStreamAdapter::Create(stream);
  rtc::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 rtc::StreamReference(ssl_stream));
  return ssl_stream_reference_->NewReference();
}

rtc::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;
  rtc::scoped_ptr<rtc::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);
  rtc::SSLStreamAdapter* ssl_stream =
      static_cast<rtc::SSLStreamAdapter*>(
          ssl_stream_reference_->GetStream());

  std::string algorithm;
  if (!peer_cert->GetSignatureDigestAlgorithm(&algorithm)) {
    LOG(LS_ERROR) << "Failed to get the algorithm for the peer cert signature";
    return;
  }
  unsigned char digest[rtc::MessageDigest::kMaxSize];
  size_t digest_len;
  peer_cert->ComputeDigest(algorithm, digest, ARRAY_SIZE(digest), &digest_len);
  ssl_stream->SetPeerCertificateDigest(algorithm, digest, digest_len);

  // 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", ICE_CANDIDATE_COMPONENT_DEFAULT));
}

}  // namespace cricket
