// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SHILL_CRYPTO_UTIL_PROXY_H_
#define SHILL_CRYPTO_UTIL_PROXY_H_

#include <memory>
#include <string>
#include <vector>

#include <base/cancelable_callback.h>
#include <base/macros.h>
#include <base/memory/weak_ptr.h>
#include <base/strings/stringprintf.h>
#include <chromeos/minijail/minijail.h>
#include <gtest/gtest_prod.h>  // for FRIEND_TEST

#include "shill/callbacks.h"
#include "shill/error.h"
#include "shill/net/io_handler.h"
#include "shill/proto_bindings/shims/protos/crypto_util.pb.h"

namespace shill {

class EventDispatcher;
class FileIO;
class GLib;
class ProcessKiller;

class CryptoUtilProxy : public base::SupportsWeakPtr<CryptoUtilProxy> {
 public:
  static const char kCommandVerify[];
  static const char kCommandEncrypt[];
  static const char kCryptoUtilShimPath[];

  CryptoUtilProxy(EventDispatcher *dispatcher, GLib *glib);
  virtual ~CryptoUtilProxy();

  // Verify credentials for the currently connected endpoint of
  // |connected_service|.  This is a fairly expensive/time consuming operation.
  // Returns true if we've succeeded in kicking off a job to an external shim
  // to verify credentials.  |result_callback| will be called with the actual
  // result of the job, either true, or false with a descriptive error.
  //
  // |certificate| should be a device certificate in PEM format.
  // |public_key| is a base64 encoded DER RSAPublicKey format public key.
  // |nonce| has no particular format requirements.
  // |signed_data| is the base64 encoded signed string given by the device.
  // |destination_udn| has no format requirements.
  // |ssid| has no constraints.
  // |bssid| should be in the human readable format: 00:11:22:33:44:55.
  virtual bool VerifyDestination(const std::string &certificate,
                                 const std::string &public_key,
                                 const std::string &nonce,
                                 const std::string &signed_data,
                                 const std::string &destination_udn,
                                 const std::vector<uint8_t> &ssid,
                                 const std::string &bssid,
                                 const ResultBoolCallback &result_callback,
                                 Error *error);

  // Encrypt |data| under |public_key|.  This is a fairly time consuming
  // process.  Returns true if we've succeeded in kicking off a job to an
  // external shim to sign the data.  |result_callback| will be called with the
  // results of the operation: an empty string and a descriptive error or the
  // base64 encoded bytes of the encrypted data.
  //
  // |public_key| is a base64 encoded DER RSAPublicKey format public key.
  // |data| has no particular format requirements.
  virtual bool EncryptData(const std::string &public_key,
                           const std::string &data,
                           const ResultStringCallback &result_callback,
                           Error *error);

 private:
  friend class CryptoUtilProxyTest;
  friend class MockCryptoUtilProxy;
  FRIEND_TEST(CryptoUtilProxyTest, BasicAPIUsage);
  FRIEND_TEST(CryptoUtilProxyTest, FailuresReturnValues);
  FRIEND_TEST(CryptoUtilProxyTest, OnlyOneInstanceInFlightAtATime);
  FRIEND_TEST(CryptoUtilProxyTest, ShimLifeTime);
  FRIEND_TEST(CryptoUtilProxyTest, TimeoutsTriggerFailure);
  FRIEND_TEST(CryptoUtilProxyTest, ShimCleanedBeforeCallback);

  static const char kDestinationVerificationUser[];
  static const int kShimJobTimeoutMilliseconds;

  // Helper method for parsing the proto buffer return codes sent back by the
  // shim.
  static bool ParseResponseReturnCode(int proto_return_code, Error *e);

  // Kick off a run of the shim to verify credentials or sign data.  Callers
  // pass in the command they want to run on the shim (literally a command line
  // argument to the shim), and a handler to handle the result.  The handler is
  // called both on errors, timeouts, and success.  Behind the scenes, we first
  // send |input| down to the shim through a pipe to its stdin, then wait for
  // bytes to comes back over a pipe connected to the shim's stdout.
  virtual bool StartShimForCommand(const std::string &command,
                                   const std::string &input,
                                   const StringCallback &result_handler);
  // This is the big hammer we use to clean up past shim state.
  virtual void CleanupShim(const Error &shim_result);
  virtual void OnShimDeath();

  // Callbacks that handle IO operations between shill and the shim.  Called by
  // GLib on changes in file descriptor state.
  void HandleShimStdinReady(int fd);
  void HandleShimOutput(InputData *data);
  void HandleShimReadError(const std::string &error_msg);
  void HandleShimError(const Error &error);
  void HandleShimTimeout();
  // Used to handle the final result of both operations.  |result| is a
  // seriallized protocol buffer or an empty string on error.  On error,
  // |error| is filled in with an appropriate error condition.
  // |result_callback| is a callback from the original caller (the manager).
  void HandleVerifyResult(const ResultBoolCallback &result_handler,
                          const std::string &result,
                          const Error &error);
  void HandleEncryptResult(const ResultStringCallback &result_handler,
                           const std::string &result,
                           const Error &error);

  EventDispatcher *dispatcher_;
  GLib *glib_;
  chromeos::Minijail *minijail_;
  ProcessKiller *process_killer_;
  FileIO *file_io_;
  std::string input_buffer_;
  std::string::const_iterator next_input_byte_;
  std::string output_buffer_;
  int shim_stdin_;
  int shim_stdout_;
  pid_t shim_pid_;
  std::unique_ptr<IOHandler> shim_stdin_handler_;
  std::unique_ptr<IOHandler> shim_stdout_handler_;
  Error shim_result_;
  StringCallback result_handler_;
  base::CancelableClosure shim_job_timeout_callback_;

  DISALLOW_COPY_AND_ASSIGN(CryptoUtilProxy);
};

}  // namespace shill

#endif  // SHILL_CRYPTO_UTIL_PROXY_H_
