1 //
2 // Copyright (C) 2013 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef SHILL_CRYPTO_UTIL_PROXY_H_
18 #define SHILL_CRYPTO_UTIL_PROXY_H_
19 
20 #include <memory>
21 #include <string>
22 #include <vector>
23 
24 #include <base/cancelable_callback.h>
25 #include <base/macros.h>
26 #include <base/memory/weak_ptr.h>
27 #include <base/strings/stringprintf.h>
28 #include <brillo/minijail/minijail.h>
29 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
30 
31 #include "shill/callbacks.h"
32 #include "shill/error.h"
33 #include "shill/net/io_handler.h"
34 #include "shill/shims/protos/crypto_util.pb.h"
35 
36 namespace shill {
37 
38 class EventDispatcher;
39 class FileIO;
40 class ProcessManager;
41 
42 class CryptoUtilProxy : public base::SupportsWeakPtr<CryptoUtilProxy> {
43  public:
44   static const char kCommandVerify[];
45   static const char kCommandEncrypt[];
46   static const char kCryptoUtilShimPath[];
47 
48   explicit CryptoUtilProxy(EventDispatcher* dispatcher);
49   virtual ~CryptoUtilProxy();
50 
51   // Verify credentials for the currently connected endpoint of
52   // |connected_service|.  This is a fairly expensive/time consuming operation.
53   // Returns true if we've succeeded in kicking off a job to an external shim
54   // to verify credentials.  |result_callback| will be called with the actual
55   // result of the job, either true, or false with a descriptive error.
56   //
57   // |certificate| should be a device certificate in PEM format.
58   // |public_key| is a base64 encoded DER RSAPublicKey format public key.
59   // |nonce| has no particular format requirements.
60   // |signed_data| is the base64 encoded signed string given by the device.
61   // |destination_udn| has no format requirements.
62   // |ssid| has no constraints.
63   // |bssid| should be in the human readable format: 00:11:22:33:44:55.
64   virtual bool VerifyDestination(const std::string& certificate,
65                                  const std::string& public_key,
66                                  const std::string& nonce,
67                                  const std::string& signed_data,
68                                  const std::string& destination_udn,
69                                  const std::vector<uint8_t>& ssid,
70                                  const std::string& bssid,
71                                  const ResultBoolCallback& result_callback,
72                                  Error* error);
73 
74   // Encrypt |data| under |public_key|.  This is a fairly time consuming
75   // process.  Returns true if we've succeeded in kicking off a job to an
76   // external shim to sign the data.  |result_callback| will be called with the
77   // results of the operation: an empty string and a descriptive error or the
78   // base64 encoded bytes of the encrypted data.
79   //
80   // |public_key| is a base64 encoded DER RSAPublicKey format public key.
81   // |data| has no particular format requirements.
82   virtual bool EncryptData(const std::string& public_key,
83                            const std::string& data,
84                            const ResultStringCallback& result_callback,
85                            Error* error);
86 
87  private:
88   friend class CryptoUtilProxyTest;
89   friend class MockCryptoUtilProxy;
90   FRIEND_TEST(CryptoUtilProxyTest, BasicAPIUsage);
91   FRIEND_TEST(CryptoUtilProxyTest, FailuresReturnValues);
92   FRIEND_TEST(CryptoUtilProxyTest, OnlyOneInstanceInFlightAtATime);
93   FRIEND_TEST(CryptoUtilProxyTest, ShimLifeTime);
94   FRIEND_TEST(CryptoUtilProxyTest, TimeoutsTriggerFailure);
95   FRIEND_TEST(CryptoUtilProxyTest, ShimCleanedBeforeCallback);
96 
97   static const char kDestinationVerificationUser[];
98   static const uint64_t kRequiredCapabilities;
99   static const int kShimJobTimeoutMilliseconds;
100 
101   // Helper method for parsing the proto buffer return codes sent back by the
102   // shim.
103   static bool ParseResponseReturnCode(int proto_return_code, Error* e);
104 
105   // Kick off a run of the shim to verify credentials or sign data.  Callers
106   // pass in the command they want to run on the shim (literally a command line
107   // argument to the shim), and a handler to handle the result.  The handler is
108   // called both on errors, timeouts, and success.  Behind the scenes, we first
109   // send |input| down to the shim through a pipe to its stdin, then wait for
110   // bytes to comes back over a pipe connected to the shim's stdout.
111   virtual bool StartShimForCommand(const std::string& command,
112                                    const std::string& input,
113                                    const StringCallback& result_handler);
114   // This is the big hammer we use to clean up past shim state.
115   virtual void CleanupShim(const Error& shim_result);
116   virtual void OnShimDeath(int exit_status);
117 
118   // Callbacks that handle IO operations between shill and the shim.
119   // Called on changes in file descriptor state.
120   void HandleShimStdinReady(int fd);
121   void HandleShimOutput(InputData* data);
122   void HandleShimReadError(const std::string& error_msg);
123   void HandleShimError(const Error& error);
124   void HandleShimTimeout();
125   // Used to handle the final result of both operations.  |result| is a
126   // seriallized protocol buffer or an empty string on error.  On error,
127   // |error| is filled in with an appropriate error condition.
128   // |result_callback| is a callback from the original caller (the manager).
129   void HandleVerifyResult(const ResultBoolCallback& result_handler,
130                           const std::string& result,
131                           const Error& error);
132   void HandleEncryptResult(const ResultStringCallback& result_handler,
133                            const std::string& result,
134                            const Error& error);
135 
136   EventDispatcher* dispatcher_;
137   ProcessManager* process_manager_;
138   FileIO* file_io_;
139   std::string input_buffer_;
140   std::string::const_iterator next_input_byte_;
141   std::string output_buffer_;
142   int shim_stdin_;
143   int shim_stdout_;
144   pid_t shim_pid_;
145   std::unique_ptr<IOHandler> shim_stdin_handler_;
146   std::unique_ptr<IOHandler> shim_stdout_handler_;
147   Error shim_result_;
148   StringCallback result_handler_;
149   base::CancelableClosure shim_job_timeout_callback_;
150 
151   DISALLOW_COPY_AND_ASSIGN(CryptoUtilProxy);
152 };
153 
154 }  // namespace shill
155 
156 #endif  // SHILL_CRYPTO_UTIL_PROXY_H_
157