1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2013 The Android Open Source Project
3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License");
5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License.
6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at
7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//      http://www.apache.org/licenses/LICENSE-2.0
9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software
11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS,
12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and
14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License.
15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
165a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
17cddd2d09878704128d35ddfeec862109b7d7fdc9Alex Deymo#include "shill/crypto_util_proxy.h"
18cddd2d09878704128d35ddfeec862109b7d7fdc9Alex Deymo
195a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <algorithm>
205a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <string>
215a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <vector>
225a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
235a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <base/callback.h>
245a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include <gtest/gtest.h>
255a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
265a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include "shill/callbacks.h"
275a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include "shill/mock_crypto_util_proxy.h"
285a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include "shill/mock_event_dispatcher.h"
295a3f23a122566b53e230b1132c0241411016386aChristopher Wiley#include "shill/mock_file_io.h"
30304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal#include "shill/mock_process_manager.h"
315a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
325a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing base::Bind;
335a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing std::min;
345a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing std::string;
355a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing std::vector;
36304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawalusing testing::AnyOf;
375a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing testing::DoAll;
385a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing testing::InSequence;
395a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing testing::Invoke;
405a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing testing::Mock;
415a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing testing::NotNull;
425a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing testing::Return;
435a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing testing::StrEq;
44b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wileyusing testing::WithoutArgs;
455a3f23a122566b53e230b1132c0241411016386aChristopher Wileyusing testing::_;
465a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
475a3f23a122566b53e230b1132c0241411016386aChristopher Wileynamespace shill {
485a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
495a3f23a122566b53e230b1132c0241411016386aChristopher Wileynamespace {
50be0849f4474f6e97496550187bc4256bf0a91d2bBen Chan
51be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst char kTestBSSID[] = "00:11:22:33:44:55";
52be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst char kTestCertificate[] = "testcertgoeshere";
53be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst char kTestData[] = "thisisthetestdata";
54be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst char kTestDestinationUDN[] = "TEST1234-5678-ABCD";
55be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst char kTestNonce[] = "abort abort abort";
56be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst char kTestPublicKey[] = "YWJvcnQgYWJvcnQgYWJvcnQK";
57be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst char kTestSerializedCommandMessage[] =
58be0849f4474f6e97496550187bc4256bf0a91d2bBen Chan    "Since we're not testing protocol buffer seriallization, and no data "
59be0849f4474f6e97496550187bc4256bf0a91d2bBen Chan    "actually makes it to a shim, we're safe to write whatever we want here.";
60be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst char kTestSerializedCommandResponse[] =
61be0849f4474f6e97496550187bc4256bf0a91d2bBen Chan    "Similarly, we never ask a protocol buffer to deserialize this string.";
6213d581fa047118d065f41eb1d0da203cf0a49b07mukesh agrawalconst char kTestSignedData[] = "Ynl0ZXMgYnl0ZXMgYnl0ZXMK";
63be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst int kTestStdinFd = 9111;
64be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst int kTestStdoutFd = 9119;
65be0849f4474f6e97496550187bc4256bf0a91d2bBen Chanconst pid_t kTestShimPid = 989898;
66be0849f4474f6e97496550187bc4256bf0a91d2bBen Chan
675a3f23a122566b53e230b1132c0241411016386aChristopher Wiley}  // namespace
685a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
695a3f23a122566b53e230b1132c0241411016386aChristopher WileyMATCHER_P(ErrorIsOfType, error_type, "") {
705a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  if (error_type != arg.type()) {
715a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    return false;
725a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
735a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
745a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  return true;
758a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko}
765a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
775a3f23a122566b53e230b1132c0241411016386aChristopher Wileyclass CryptoUtilProxyTest : public testing::Test {
785a3f23a122566b53e230b1132c0241411016386aChristopher Wiley public:
795a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  CryptoUtilProxyTest()
8013d581fa047118d065f41eb1d0da203cf0a49b07mukesh agrawal      : crypto_util_proxy_(&dispatcher_) {
815a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    test_ssid_.push_back(78);
825a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    test_ssid_.push_back(69);
835a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    test_ssid_.push_back(80);
845a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    test_ssid_.push_back(84);
855a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    test_ssid_.push_back(85);
865a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    test_ssid_.push_back(78);
875a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    test_ssid_.push_back(69);
885a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
895a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
905a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  virtual void SetUp() {
91304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    crypto_util_proxy_.process_manager_ = &process_manager_;
925a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    crypto_util_proxy_.file_io_ = &file_io_;
935a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
945a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
955a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  virtual void TearDown() {
96304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    // Note that |crypto_util_proxy_| needs its process manager reference in
975a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // order not to segfault when it tries to kill any outstanding shims on
985a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // shutdown.  Thus we don't clear out those fields here, and we make sure
995a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // to declare the proxy after mocks it consumes.
1005a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
1015a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
102304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  // TODO(quiche): Consider refactoring
103304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  // HandleStartInMinijailWithPipes, HandleStopProcess, and
104304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  // HandleUpdateExitCallback into a FakeProcessManager. b/24210150
105304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  pid_t HandleStartInMinijailWithPipes(
106304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      const tracked_objects::Location& /* spawn_source */,
107304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      const base::FilePath& /* program */,
108304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      vector<string> /* program_args */,
109304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      const std::string& /* run_as_user */,
110304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      const std::string& /* run_as_group */,
111304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      uint64_t /* capabilities_mask */,
112304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      const base::Callback<void(int)>& exit_callback,
113304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      int* stdin,
114304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      int* stdout,
115304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      int* /* stderr */) {
116304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    exit_callback_ = exit_callback;
1175a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    *stdin = kTestStdinFd;
1185a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    *stdout = kTestStdoutFd;
119304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    return kTestShimPid;
1205a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
1215a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
1223b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  void StartAndCheckShim(const std::string& command,
1233b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart                         const std::string& shim_stdin) {
1245a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    InSequence seq;
1255a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // Delegate the start call to the real implementation just for this test.
1265a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(crypto_util_proxy_, StartShimForCommand(_, _, _))
1275a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        .WillOnce(Invoke(&crypto_util_proxy_,
1285a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                         &MockCryptoUtilProxy::RealStartShimForCommand));
1295a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // All shims should be spawned in a Minijail.
130304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    EXPECT_CALL(
131304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal        process_manager_,
132304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal        StartProcessInMinijailWithPipes(
133304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            _,  // caller location
134304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            base::FilePath(CryptoUtilProxy::kCryptoUtilShimPath),
135304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            AnyOf(
136304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal                vector<string>{CryptoUtilProxy::kCommandVerify},
137304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal                vector<string>{CryptoUtilProxy::kCommandEncrypt}),
138304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            "shill-crypto",
139304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            "shill-crypto",
140304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            0,  // no capabilities required
141304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            _,  // exit_callback
142304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            NotNull(),  // stdin
143304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            NotNull(),  // stdout
144304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal            nullptr))  // stderr
145304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal        .WillOnce(Invoke(this,
146304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal                         &CryptoUtilProxyTest::HandleStartInMinijailWithPipes));
1475a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // We should always schedule a shim timeout callback.
1485a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(dispatcher_, PostDelayedTask(_, _));
1495a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // We don't allow file I/O to block.
1505a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(file_io_,
1515a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                SetFdNonBlocking(kTestStdinFd))
1525a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        .WillOnce(Return(0));
1535a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(file_io_,
1545a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                SetFdNonBlocking(kTestStdoutFd))
1555a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        .WillOnce(Return(0));
1565a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // We instead do file I/O through async callbacks registered with the event
1575a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // dispatcher.
1585a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(dispatcher_, CreateInputHandler(_, _, _)).Times(1);
1595a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(dispatcher_, CreateReadyHandler(_, _, _)).Times(1);
1605a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // The shim is left in flight, not killed.
161304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    EXPECT_CALL(process_manager_, StopProcess(_)).Times(0);
1625a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    crypto_util_proxy_.StartShimForCommand(
1635a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        command, shim_stdin,
1645a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        Bind(&MockCryptoUtilProxy::TestResultHandlerCallback,
1655a3f23a122566b53e230b1132c0241411016386aChristopher Wiley             crypto_util_proxy_.base::SupportsWeakPtr<MockCryptoUtilProxy>::
1665a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                AsWeakPtr()));
1675a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_EQ(shim_stdin, crypto_util_proxy_.input_buffer_);
1685a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_TRUE(crypto_util_proxy_.output_buffer_.empty());
1695a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_EQ(crypto_util_proxy_.shim_pid_, kTestShimPid);
1705a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    Mock::VerifyAndClearExpectations(&crypto_util_proxy_);
1715a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    Mock::VerifyAndClearExpectations(&dispatcher_);
172304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    Mock::VerifyAndClearExpectations(&process_manager_);
1735a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
1745a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
1753b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  void ExpectCleanup(const Error& expected_result) {
17667e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley    if (crypto_util_proxy_.shim_stdin_ > -1) {
17767e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley      EXPECT_CALL(file_io_,
17867e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley                  Close(crypto_util_proxy_.shim_stdin_)).Times(1);
17967e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley    }
18067e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley    if (crypto_util_proxy_.shim_stdout_ > -1) {
18167e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley      EXPECT_CALL(file_io_,
18267e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley                  Close(crypto_util_proxy_.shim_stdout_)).Times(1);
18367e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley    }
1845a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    if (crypto_util_proxy_.shim_pid_) {
185304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      EXPECT_CALL(process_manager_, UpdateExitCallback(_, _))
1865a3f23a122566b53e230b1132c0241411016386aChristopher Wiley          .Times(1)
1875a3f23a122566b53e230b1132c0241411016386aChristopher Wiley          .WillOnce(Invoke(this,
188304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal                           &CryptoUtilProxyTest::HandleUpdateExitCallback));
189304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal      EXPECT_CALL(process_manager_, StopProcess(crypto_util_proxy_.shim_pid_))
190304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal          .Times(1)
191304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal          .WillOnce(Invoke(this,
192304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal                           &CryptoUtilProxyTest::HandleStopProcess));
1935a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    }
1945a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
1955a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
196b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  void AssertShimDead() {
197b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    EXPECT_FALSE(crypto_util_proxy_.shim_pid_);
198b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  }
199b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley
200304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  bool HandleUpdateExitCallback(pid_t /*pid*/,
201304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal                                const base::Callback<void(int)>& new_callback) {
202304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    exit_callback_ = new_callback;
203304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    return true;
204304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  }
205304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal
206304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  bool HandleStopProcess(pid_t /*pid*/) {
207304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    const int kExitStatus = -1;
208304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    // NB: in the real world, this ordering is not guaranteed. That
209304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    // is, StopProcess() might return before executing the callback.
210304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    exit_callback_.Run(kExitStatus);
211304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    return true;
2125a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
2135a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
2143b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  void StopAndCheckShim(const Error& error) {
21567e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley    ExpectCleanup(error);
21667e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley    crypto_util_proxy_.CleanupShim(error);
217304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    crypto_util_proxy_.OnShimDeath(-1);
2185a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_EQ(crypto_util_proxy_.shim_pid_, 0);
219304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal    Mock::VerifyAndClearExpectations(&process_manager_);
2205a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
2215a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
2225a3f23a122566b53e230b1132c0241411016386aChristopher Wiley protected:
223304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  MockProcessManager process_manager_;
2245a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  MockEventDispatcher dispatcher_;
2255a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  MockFileIO file_io_;
2265a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  MockCryptoUtilProxy crypto_util_proxy_;
2275a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  std::vector<uint8_t> test_ssid_;
228304afb43643faa19fa3a599a59fbb1574c0a06efmukesh agrawal  base::Callback<void(int)> exit_callback_;
2295a3f23a122566b53e230b1132c0241411016386aChristopher Wiley};
2305a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
2315a3f23a122566b53e230b1132c0241411016386aChristopher WileyTEST_F(CryptoUtilProxyTest, BasicAPIUsage) {
2325a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  {
2335a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    InSequence seq;
2345a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // Delegate the API call to the real implementation for this test.
2355a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(crypto_util_proxy_,
2365a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                VerifyDestination(_, _, _, _, _, _, _, _, _))
2375a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        .WillOnce(Invoke(&crypto_util_proxy_,
2385a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                         &MockCryptoUtilProxy::RealVerifyDestination));
2395a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // API calls are just thin wrappers that write up a message to a shim, then
2405a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // send it via StartShimForCommand.  Expect that a shim will be started in
2415a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // response to the API being called.
2425a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(crypto_util_proxy_,
2435a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                StartShimForCommand(CryptoUtilProxy::kCommandVerify, _, _))
2445a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        .WillOnce(Return(true));
2455a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    ResultBoolCallback result_callback =
2465a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        Bind(&MockCryptoUtilProxy::TestResultBoolCallback,
2475a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        crypto_util_proxy_.
2485a3f23a122566b53e230b1132c0241411016386aChristopher Wiley            base::SupportsWeakPtr<MockCryptoUtilProxy>::AsWeakPtr());
2495a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    Error error;
2505a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_TRUE(crypto_util_proxy_.VerifyDestination(kTestCertificate,
2515a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                                     kTestPublicKey,
2525a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                                     kTestNonce,
2535a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                                     kTestSignedData,
2545a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                                     kTestDestinationUDN,
2555a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                                     test_ssid_,
2565a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                                     kTestBSSID,
2575a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                                     result_callback,
2585a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                                     &error));
2595a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_TRUE(error.IsSuccess());
2605a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
2615a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  {
2625a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // And very similarly...
2635a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    InSequence seq;
2645a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(crypto_util_proxy_, EncryptData(_, _, _, _))
2655a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        .WillOnce(Invoke(&crypto_util_proxy_,
2665a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                         &MockCryptoUtilProxy::RealEncryptData));
2675a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(crypto_util_proxy_,
2685a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                StartShimForCommand(CryptoUtilProxy::kCommandEncrypt, _, _))
2695a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        .WillOnce(Return(true));
2705a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    ResultStringCallback result_callback =
2715a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        Bind(&MockCryptoUtilProxy::TestResultStringCallback,
2725a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        crypto_util_proxy_.
2735a3f23a122566b53e230b1132c0241411016386aChristopher Wiley            base::SupportsWeakPtr<MockCryptoUtilProxy>::AsWeakPtr());
2745a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    Error error;
2755a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // Normally, we couldn't have these two operations run successfully without
2765a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // finishing the first one, since only one shim can be in flight at a time.
2775a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // However, this works because we didn't actually start a shim, we just
2785a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    // trapped the call in our mock.
2795a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_TRUE(crypto_util_proxy_.EncryptData(kTestPublicKey, kTestData,
2805a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                               result_callback, &error));
2815a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_TRUE(error.IsSuccess());
2825a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
2835a3f23a122566b53e230b1132c0241411016386aChristopher Wiley}
2845a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
285b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher WileyTEST_F(CryptoUtilProxyTest, ShimCleanedBeforeCallback) {
286b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  // Some operations, like VerifyAndEncryptData in the manager, chain two
287b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  // shim operations together.  Make sure that we don't call back with results
288b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  // before the shim state is clean.
289b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  {
290b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    StartAndCheckShim(CryptoUtilProxy::kCommandEncrypt,
291b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley                      kTestSerializedCommandMessage);
29267e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley    Error e(Error::kOperationFailed);
29367e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley    ExpectCleanup(e);
294b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    EXPECT_CALL(crypto_util_proxy_,
295b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley                TestResultHandlerCallback(
296b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley                    StrEq(""), ErrorIsOfType(Error::kOperationFailed)))
297b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley        .Times(1)
298b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley        .WillOnce(WithoutArgs(Invoke(this,
299b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley                                     &CryptoUtilProxyTest::AssertShimDead)));
300b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    crypto_util_proxy_.HandleShimError(e);
301b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  }
302b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  {
303b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    StartAndCheckShim(CryptoUtilProxy::kCommandEncrypt,
304b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley                      kTestSerializedCommandMessage);
305b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    EXPECT_CALL(crypto_util_proxy_,
306b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley                TestResultHandlerCallback(
307b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley                    StrEq(""), ErrorIsOfType(Error::kSuccess)))
308b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley        .Times(1)
309b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley        .WillOnce(WithoutArgs(Invoke(this,
310b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley                                     &CryptoUtilProxyTest::AssertShimDead)));
31167e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley    ExpectCleanup(Error(Error::kSuccess));
312b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    InputData data;
313cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    data.buf = nullptr;
314b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    data.len = 0;
315b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    crypto_util_proxy_.HandleShimOutput(&data);
316b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley  }
317b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley}
318b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley
3195a3f23a122566b53e230b1132c0241411016386aChristopher Wiley// Verify that even when we have errors, we'll call the result handler.
3205a3f23a122566b53e230b1132c0241411016386aChristopher Wiley// Ultimately, this is supposed to make sure that we always return something to
3215a3f23a122566b53e230b1132c0241411016386aChristopher Wiley// our callers over DBus.
3225a3f23a122566b53e230b1132c0241411016386aChristopher WileyTEST_F(CryptoUtilProxyTest, FailuresReturnValues) {
3235a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  StartAndCheckShim(CryptoUtilProxy::kCommandEncrypt,
3245a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                    kTestSerializedCommandMessage);
3255a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  EXPECT_CALL(crypto_util_proxy_, TestResultHandlerCallback(
3265a3f23a122566b53e230b1132c0241411016386aChristopher Wiley      StrEq(""), ErrorIsOfType(Error::kOperationFailed))).Times(1);
3275a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  Error e(Error::kOperationFailed);
32867e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley  ExpectCleanup(e);
3295a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  crypto_util_proxy_.HandleShimError(e);
3305a3f23a122566b53e230b1132c0241411016386aChristopher Wiley}
3315a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
3325a3f23a122566b53e230b1132c0241411016386aChristopher WileyTEST_F(CryptoUtilProxyTest, TimeoutsTriggerFailure) {
3335a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  StartAndCheckShim(CryptoUtilProxy::kCommandEncrypt,
3345a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                    kTestSerializedCommandMessage);
3355a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  EXPECT_CALL(crypto_util_proxy_, TestResultHandlerCallback(
3365a3f23a122566b53e230b1132c0241411016386aChristopher Wiley      StrEq(""), ErrorIsOfType(Error::kOperationTimeout))).Times(1);
33767e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley  ExpectCleanup(Error(Error::kOperationTimeout));
3385a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // This timeout is scheduled by StartShimForCommand.
3395a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  crypto_util_proxy_.HandleShimTimeout();
3405a3f23a122566b53e230b1132c0241411016386aChristopher Wiley}
3415a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
3425a3f23a122566b53e230b1132c0241411016386aChristopher WileyTEST_F(CryptoUtilProxyTest, OnlyOneInstanceInFlightAtATime) {
3435a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  StartAndCheckShim(CryptoUtilProxy::kCommandEncrypt,
3445a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                    kTestSerializedCommandMessage);
3455a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Can't start things twice.
3465a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  EXPECT_FALSE(crypto_util_proxy_.RealStartShimForCommand(
3475a3f23a122566b53e230b1132c0241411016386aChristopher Wiley      CryptoUtilProxy::kCommandEncrypt, kTestSerializedCommandMessage,
3485a3f23a122566b53e230b1132c0241411016386aChristopher Wiley      Bind(&MockCryptoUtilProxy::TestResultHandlerCallback,
3495a3f23a122566b53e230b1132c0241411016386aChristopher Wiley           crypto_util_proxy_.
3505a3f23a122566b53e230b1132c0241411016386aChristopher Wiley              base::SupportsWeakPtr<MockCryptoUtilProxy>::AsWeakPtr())));
3515a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // But if some error (or completion) caused us to clean up the shim...
35267e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley  StopAndCheckShim(Error(Error::kSuccess));
3535a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Then we could start the shim again.
3545a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  StartAndCheckShim(CryptoUtilProxy::kCommandEncrypt,
3555a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                    kTestSerializedCommandMessage);
3565a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Clean up after ourselves.
35767e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley  StopAndCheckShim(Error(Error::kOperationFailed));
3585a3f23a122566b53e230b1132c0241411016386aChristopher Wiley}
3595a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
3605a3f23a122566b53e230b1132c0241411016386aChristopher Wiley// This test walks the CryptoUtilProxy through the life time of a shim by
3615a3f23a122566b53e230b1132c0241411016386aChristopher Wiley// simulating the API call, file I/O operations, and the final handler on shim
3625a3f23a122566b53e230b1132c0241411016386aChristopher Wiley// completion.
3635a3f23a122566b53e230b1132c0241411016386aChristopher WileyTEST_F(CryptoUtilProxyTest, ShimLifeTime) {
3645a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  const int kBytesAtATime = 10;
3655a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  StartAndCheckShim(CryptoUtilProxy::kCommandEncrypt,
3665a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                    kTestSerializedCommandMessage);
3675a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Emulate the operating system pulling bytes through the pipe, and the event
3685a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // loop notifying us that the file descriptor is ready.
3695a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  int bytes_left = strlen(kTestSerializedCommandMessage);
3705a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  while (bytes_left > 0) {
3715a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    int bytes_written = min(kBytesAtATime, bytes_left);
3725a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    EXPECT_CALL(file_io_, Write(kTestStdinFd, _, bytes_left))
3735a3f23a122566b53e230b1132c0241411016386aChristopher Wiley        .Times(1).WillOnce(Return(bytes_written));
3745a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    bytes_left -= bytes_written;
3755a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    if (bytes_left < 1) {
3765a3f23a122566b53e230b1132c0241411016386aChristopher Wiley      EXPECT_CALL(file_io_, Close(kTestStdinFd));
3775a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    }
3785a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    crypto_util_proxy_.HandleShimStdinReady(crypto_util_proxy_.shim_stdin_);
3795a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    Mock::VerifyAndClearExpectations(&crypto_util_proxy_);
3805a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
3815a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
3825a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // At this point, the shim goes off and does terribly complex crypto stuff,
3835a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // before responding with a string of bytes over stdout.  Emulate the shim
3845a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // and the event loop to push those bytes back.
3855a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  const int response_length = bytes_left =
3865a3f23a122566b53e230b1132c0241411016386aChristopher Wiley      strlen(kTestSerializedCommandResponse);
3875a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  InputData data;
3885a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  while (bytes_left > 0) {
3895a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    int bytes_written = min(kBytesAtATime, bytes_left);
3905a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    data.len = bytes_written;
3913b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart    data.buf = reinterpret_cast<unsigned char*>(const_cast<char*>(
3925a3f23a122566b53e230b1132c0241411016386aChristopher Wiley          kTestSerializedCommandResponse + response_length - bytes_left));
3935a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    bytes_left -= bytes_written;
3945a3f23a122566b53e230b1132c0241411016386aChristopher Wiley    crypto_util_proxy_.HandleShimOutput(&data);
3955a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  }
3965a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // Write 0 bytes in to signify the end of the stream. This should in turn
3975a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  // cause our callback to be called.
3985a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  data.len = 0;
399cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  data.buf = nullptr;
4005a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  EXPECT_CALL(
4015a3f23a122566b53e230b1132c0241411016386aChristopher Wiley      crypto_util_proxy_,
4025a3f23a122566b53e230b1132c0241411016386aChristopher Wiley      TestResultHandlerCallback(string(kTestSerializedCommandResponse),
4035a3f23a122566b53e230b1132c0241411016386aChristopher Wiley                                ErrorIsOfType(Error::kSuccess))).Times(1);
40467e425e5af9b28ffff2c17f879e70f9f6a4e10e9Christopher Wiley  ExpectCleanup(Error(Error::kSuccess));
4055a3f23a122566b53e230b1132c0241411016386aChristopher Wiley  crypto_util_proxy_.HandleShimOutput(&data);
4065a3f23a122566b53e230b1132c0241411016386aChristopher Wiley}
4075a3f23a122566b53e230b1132c0241411016386aChristopher Wiley
4085a3f23a122566b53e230b1132c0241411016386aChristopher Wiley}  // namespace shill
409