Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 1 | // Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef SHILL_CRYPTO_UTIL_PROXY_H_ |
| 6 | #define SHILL_CRYPTO_UTIL_PROXY_H_ |
| 7 | |
| 8 | #include <string> |
| 9 | #include <vector> |
| 10 | |
| 11 | #include <base/basictypes.h> |
| 12 | #include <base/cancelable_callback.h> |
| 13 | #include <base/memory/weak_ptr.h> |
| 14 | #include <base/stringprintf.h> |
| 15 | #include <gtest/gtest_prod.h> // for FRIEND_TEST |
| 16 | |
| 17 | #include "shill/callbacks.h" |
| 18 | #include "shill/error.h" |
| 19 | #include "shill/io_handler.h" |
| 20 | #include "shill/minijail.h" |
| 21 | #include "shill/proto_bindings/shims/protos/crypto_util.pb.h" |
| 22 | |
| 23 | namespace shill { |
| 24 | |
| 25 | class EventDispatcher; |
| 26 | class FileIO; |
Christopher Wiley | 5447d2e | 2013-03-19 17:46:03 -0700 | [diff] [blame] | 27 | class GLib; |
Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 28 | class ProcessKiller; |
| 29 | |
| 30 | class CryptoUtilProxy : public base::SupportsWeakPtr<CryptoUtilProxy> { |
| 31 | public: |
| 32 | static const char kCommandVerify[]; |
| 33 | static const char kCommandEncrypt[]; |
| 34 | static const char kCryptoUtilShimPath[]; |
| 35 | |
Christopher Wiley | 5447d2e | 2013-03-19 17:46:03 -0700 | [diff] [blame] | 36 | CryptoUtilProxy(EventDispatcher *dispatcher, GLib *glib); |
Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 37 | virtual ~CryptoUtilProxy(); |
| 38 | |
| 39 | // Verify credentials for the currently connected endpoint of |
| 40 | // |connected_service|. This is a fairly expensive/time consuming operation. |
| 41 | // Returns true if we've succeeded in kicking off a job to an external shim |
| 42 | // to verify credentials. |result_callback| will be called with the actual |
| 43 | // result of the job, either true, or false with a descriptive error. |
Christopher Wiley | 5447d2e | 2013-03-19 17:46:03 -0700 | [diff] [blame] | 44 | // |
| 45 | // |certificate| should be a device certificate in PEM format. |
| 46 | // |public_key| is a base64 encoded DER RSAPublicKey format public key. |
| 47 | // |nonce| has no particular format requirements. |
| 48 | // |signed_data| is the base64 encoded signed string given by the device. |
| 49 | // |destination_udn| has no format requirements. |
| 50 | // |ssid| has no constraints. |
| 51 | // |bssid| should be in the human readable format: 00:11:22:33:44:55. |
Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 52 | virtual bool VerifyDestination(const std::string &certificate, |
| 53 | const std::string &public_key, |
| 54 | const std::string &nonce, |
| 55 | const std::string &signed_data, |
| 56 | const std::string &destination_udn, |
| 57 | const std::vector<uint8_t> &ssid, |
| 58 | const std::string &bssid, |
| 59 | const ResultBoolCallback &result_callback, |
| 60 | Error *error); |
| 61 | |
Christopher Wiley | 5447d2e | 2013-03-19 17:46:03 -0700 | [diff] [blame] | 62 | // Encrypt |data| under |public_key|. This is a fairly time consuming |
Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 63 | // process. Returns true if we've succeeded in kicking off a job to an |
| 64 | // external shim to sign the data. |result_callback| will be called with the |
| 65 | // results of the operation: an empty string and a descriptive error or the |
| 66 | // base64 encoded bytes of the encrypted data. |
Christopher Wiley | 5447d2e | 2013-03-19 17:46:03 -0700 | [diff] [blame] | 67 | // |
| 68 | // |public_key| is a base64 encoded DER RSAPublicKey format public key. |
| 69 | // |data| has no particular format requirements. |
Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 70 | virtual bool EncryptData(const std::string &public_key, |
| 71 | const std::string &data, |
| 72 | const ResultStringCallback &result_callback, |
| 73 | Error *error); |
| 74 | private: |
| 75 | friend class CryptoUtilProxyTest; |
| 76 | friend class MockCryptoUtilProxy; |
| 77 | FRIEND_TEST(CryptoUtilProxyTest, BasicAPIUsage); |
| 78 | FRIEND_TEST(CryptoUtilProxyTest, FailuresReturnValues); |
| 79 | FRIEND_TEST(CryptoUtilProxyTest, OnlyOneInstanceInFlightAtATime); |
| 80 | FRIEND_TEST(CryptoUtilProxyTest, ShimLifeTime); |
| 81 | FRIEND_TEST(CryptoUtilProxyTest, TimeoutsTriggerFailure); |
Christopher Wiley | b3e70d2 | 2013-04-26 17:28:37 -0700 | [diff] [blame] | 82 | FRIEND_TEST(CryptoUtilProxyTest, ShimCleanedBeforeCallback); |
Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 83 | |
| 84 | static const char kDestinationVerificationUser[]; |
| 85 | static const int kShimJobTimeoutMilliseconds; |
| 86 | |
| 87 | // Helper method for parsing the proto buffer return codes sent back by the |
| 88 | // shim. |
| 89 | static bool ParseResponseReturnCode(int proto_return_code, Error *e); |
| 90 | |
| 91 | // Kick off a run of the shim to verify credentials or sign data. Callers |
| 92 | // pass in the command they want to run on the shim (literally a command line |
| 93 | // argument to the shim), and a handler to handle the result. The handler is |
| 94 | // called both on errors, timeouts, and success. Behind the scenes, we first |
| 95 | // send |input| down to the shim through a pipe to its stdin, then wait for |
| 96 | // bytes to comes back over a pipe connected to the shim's stdout. |
| 97 | virtual bool StartShimForCommand(const std::string &command, |
| 98 | const std::string &input, |
| 99 | const StringCallback &result_handler); |
| 100 | // This is the big hammer we use to clean up past shim state. |
Christopher Wiley | 67e425e | 2013-05-02 15:54:51 -0700 | [diff] [blame] | 101 | virtual void CleanupShim(const Error &shim_result); |
Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 102 | virtual void OnShimDeath(); |
| 103 | |
| 104 | // Callbacks that handle IO operations between shill and the shim. Called by |
| 105 | // GLib on changes in file descriptor state. |
| 106 | void HandleShimStdinReady(int fd); |
| 107 | void HandleShimOutput(InputData *data); |
| 108 | void HandleShimError(const Error &error); |
| 109 | void HandleShimTimeout(); |
| 110 | // Used to handle the final result of both operations. |result| is a |
| 111 | // seriallized protocol buffer or an empty string on error. On error, |
| 112 | // |error| is filled in with an appropriate error condition. |
| 113 | // |result_callback| is a callback from the original caller (the manager). |
| 114 | void HandleVerifyResult(const ResultBoolCallback &result_handler, |
| 115 | const std::string &result, |
| 116 | const Error &error); |
| 117 | void HandleEncryptResult(const ResultStringCallback &result_handler, |
| 118 | const std::string &result, |
| 119 | const Error &error); |
| 120 | |
| 121 | EventDispatcher *dispatcher_; |
Christopher Wiley | 5447d2e | 2013-03-19 17:46:03 -0700 | [diff] [blame] | 122 | GLib *glib_; |
Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 123 | Minijail *minijail_; |
| 124 | ProcessKiller *process_killer_; |
| 125 | FileIO *file_io_; |
| 126 | std::string input_buffer_; |
| 127 | std::string::const_iterator next_input_byte_; |
| 128 | std::string output_buffer_; |
| 129 | int shim_stdin_; |
| 130 | int shim_stdout_; |
| 131 | pid_t shim_pid_; |
| 132 | scoped_ptr<IOHandler> shim_stdin_handler_; |
| 133 | scoped_ptr<IOHandler> shim_stdout_handler_; |
Christopher Wiley | 67e425e | 2013-05-02 15:54:51 -0700 | [diff] [blame] | 134 | Error shim_result_; |
Christopher Wiley | 5a3f23a | 2013-02-20 17:29:57 -0800 | [diff] [blame] | 135 | StringCallback result_handler_; |
| 136 | base::CancelableClosure shim_job_timeout_callback_; |
| 137 | |
| 138 | DISALLOW_COPY_AND_ASSIGN(CryptoUtilProxy); |
| 139 | }; |
| 140 | |
| 141 | } // namespace shill |
| 142 | |
| 143 | #endif // SHILL_CRYPTO_UTIL_PROXY_H_ |