#
#

# Copyright (C) 2014 Google Inc.
# All rights reserved.
#
# 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR
# CONTRIBUTORS 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.

"""Common functions for tool scripts.

"""

import logging
import OpenSSL
import os
import time
from cStringIO import StringIO

from ganeti import constants
from ganeti import errors
from ganeti import pathutils
from ganeti import utils
from ganeti import serializer
from ganeti import ssconf
from ganeti import ssh


def VerifyOptions(parser, opts, args):
  """Verifies options and arguments for correctness.

  """
  if args:
    parser.error("No arguments are expected")

  return opts


def _VerifyCertificateStrong(cert_pem, error_fn,
                             _check_fn=utils.CheckNodeCertificate):
  """Verifies a certificate against the local node daemon certificate.

  Includes elaborate tests of encodings etc., and returns formatted
  certificate.

  @type cert_pem: string
  @param cert_pem: Certificate and key in PEM format
  @type error_fn: callable
  @param error_fn: function to call in case of an error
  @rtype: string
  @return: Formatted key and certificate

  """
  try:
    cert = \
      OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_pem)
  except Exception, err:
    raise error_fn("(stdin) Unable to load certificate: %s" % err)

  try:
    key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, cert_pem)
  except OpenSSL.crypto.Error, err:
    raise error_fn("(stdin) Unable to load private key: %s" % err)

  # Check certificate with given key; this detects cases where the key given on
  # stdin doesn't match the certificate also given on stdin
  try:
    utils.X509CertKeyCheck(cert, key)
  except OpenSSL.SSL.Error:
    raise error_fn("(stdin) Certificate is not signed with given key")

  # Standard checks, including check against an existing local certificate
  # (no-op if that doesn't exist)
  _check_fn(cert)

  key_encoded = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key)
  cert_encoded = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                                 cert)
  complete_cert_encoded = key_encoded + cert_encoded
  if not cert_pem == complete_cert_encoded:
    logging.error("The certificate differs after being reencoded. Please"
                  " renew the certificates cluster-wide to prevent future"
                  " inconsistencies.")

  # Format for storing on disk
  buf = StringIO()
  buf.write(cert_pem)
  return buf.getvalue()


def _VerifyCertificateSoft(cert_pem, error_fn,
                           _check_fn=utils.CheckNodeCertificate):
  """Verifies a certificate against the local node daemon certificate.

  @type cert_pem: string
  @param cert_pem: Certificate in PEM format (no key)

  """
  try:
    OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, cert_pem)
  except OpenSSL.crypto.Error, err:
    pass
  else:
    raise error_fn("No private key may be given")

  try:
    cert = \
      OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_pem)
  except Exception, err:
    raise errors.X509CertError("(stdin)",
                               "Unable to load certificate: %s" % err)

  _check_fn(cert)


def VerifyCertificateSoft(data, error_fn, _verify_fn=_VerifyCertificateSoft):
  """Verifies cluster certificate if existing.

  @type data: dict
  @type error_fn: callable
  @param error_fn: function to call in case of an error
  @rtype: string
  @return: Formatted key and certificate

  """
  cert = data.get(constants.SSHS_NODE_DAEMON_CERTIFICATE)
  if cert:
    _verify_fn(cert, error_fn)


def VerifyCertificateStrong(data, error_fn,
                            _verify_fn=_VerifyCertificateStrong):
  """Verifies cluster certificate. Throws error when not existing.

  @type data: dict
  @type error_fn: callable
  @param error_fn: function to call in case of an error
  @rtype: string
  @return: Formatted key and certificate

  """
  cert = data.get(constants.NDS_NODE_DAEMON_CERTIFICATE)
  if not cert:
    raise error_fn("Node daemon certificate must be specified")

  return _verify_fn(cert, error_fn)


def VerifyClusterName(data, error_fn, cluster_name_constant,
                      _verify_fn=ssconf.VerifyClusterName):
  """Verifies cluster name.

  @type data: dict

  """
  name = data.get(cluster_name_constant)
  if name:
    _verify_fn(name)
  else:
    raise error_fn("Cluster name must be specified")

  return name


def LoadData(raw, data_check):
  """Parses and verifies input data.

  @rtype: dict

  """
  result = None
  try:
    result = serializer.LoadAndVerifyJson(raw, data_check)
    logging.debug("Received data: %s", serializer.DumpJson(result))
  except Exception as e:
    logging.warn("Received data is not valid json: %s.", str(raw))
    raise e
  return result


def GenerateRootSshKeys(key_type, key_bits, error_fn, _suffix="",
                        _homedir_fn=None):
  """Generates root's SSH keys for this node.

  """
  ssh.InitSSHSetup(key_type, key_bits, error_fn=error_fn,
                   _homedir_fn=_homedir_fn, _suffix=_suffix)


def GenerateClientCertificate(
    data, error_fn, client_cert=pathutils.NODED_CLIENT_CERT_FILE,
    signing_cert=pathutils.NODED_CERT_FILE):
  """Regenerates the client certificate of the node.

  @type data: string
  @param data: the JSON-formated input data

  """
  if not os.path.exists(signing_cert):
    raise error_fn("The signing certificate '%s' cannot be found."
                   % signing_cert)

  # TODO: This sets the serial number to the number of seconds
  # since epoch. This is technically not a correct serial number
  # (in the way SSL is supposed to be used), but it serves us well
  # enough for now, as we don't have any infrastructure for keeping
  # track of the number of signed certificates yet.
  serial_no = int(time.time())

  # The hostname of the node is provided with the input data.
  hostname = data.get(constants.NDS_NODE_NAME)
  if not hostname:
    raise error_fn("No hostname found.")

  utils.GenerateSignedSslCert(client_cert, serial_no, signing_cert,
                              common_name=hostname)
