1 // Copyright (c) 2012 The Chromium 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 #import <Cocoa/Cocoa.h> 6 7 #include "base/files/file_util.h" 8 #include "base/files/scoped_file.h" 9 #include "base/logging.h" 10 #include "base/strings/sys_string_conversions.h" 11 #include "content/common/sandbox_mac.h" 12 #include "content/common/sandbox_mac_unittest_helper.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 #if defined(USE_OPENSSL) 16 #include <openssl/rand.h> 17 #include "crypto/openssl_util.h" 18 #else 19 #include "crypto/nss_util.h" 20 #endif 21 22 namespace content { 23 24 //--------------------- Clipboard Sandboxing ---------------------- 25 // Test case for checking sandboxing of clipboard access. 26 class MacSandboxedClipboardTestCase : public MacSandboxTestCase { 27 public: 28 MacSandboxedClipboardTestCase(); 29 virtual ~MacSandboxedClipboardTestCase(); 30 31 virtual bool SandboxedTest() OVERRIDE; 32 33 virtual void SetTestData(const char* test_data) OVERRIDE; 34 private: 35 NSString* clipboard_name_; 36 }; 37 38 REGISTER_SANDBOX_TEST_CASE(MacSandboxedClipboardTestCase); 39 40 MacSandboxedClipboardTestCase::MacSandboxedClipboardTestCase() : 41 clipboard_name_(nil) {} 42 43 MacSandboxedClipboardTestCase::~MacSandboxedClipboardTestCase() { 44 [clipboard_name_ release]; 45 } 46 47 bool MacSandboxedClipboardTestCase::SandboxedTest() { 48 // Shouldn't be able to open the pasteboard in the sandbox. 49 50 if ([clipboard_name_ length] == 0) { 51 LOG(ERROR) << "Clipboard name is empty"; 52 return false; 53 } 54 55 NSPasteboard* pb = [NSPasteboard pasteboardWithName:clipboard_name_]; 56 if (pb != nil) { 57 LOG(ERROR) << "Was able to access named clipboard"; 58 return false; 59 } 60 61 pb = [NSPasteboard generalPasteboard]; 62 if (pb != nil) { 63 LOG(ERROR) << "Was able to access system clipboard"; 64 return false; 65 } 66 67 return true; 68 } 69 70 void MacSandboxedClipboardTestCase::SetTestData(const char* test_data) { 71 clipboard_name_ = [base::SysUTF8ToNSString(test_data) retain]; 72 } 73 74 TEST_F(MacSandboxTest, ClipboardAccess) { 75 NSPasteboard* pb = [NSPasteboard pasteboardWithUniqueName]; 76 EXPECT_EQ([[pb types] count], 0U); 77 78 std::string pasteboard_name = base::SysNSStringToUTF8([pb name]); 79 EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedClipboardTestCase", 80 pasteboard_name.c_str())); 81 82 // After executing the test, the clipboard should still be empty. 83 EXPECT_EQ([[pb types] count], 0U); 84 } 85 86 //--------------------- File Access Sandboxing ---------------------- 87 // Test case for checking sandboxing of filesystem apis. 88 class MacSandboxedFileAccessTestCase : public MacSandboxTestCase { 89 public: 90 virtual bool SandboxedTest() OVERRIDE; 91 }; 92 93 REGISTER_SANDBOX_TEST_CASE(MacSandboxedFileAccessTestCase); 94 95 bool MacSandboxedFileAccessTestCase::SandboxedTest() { 96 base::ScopedFD fdes(HANDLE_EINTR(open("/etc/passwd", O_RDONLY))); 97 return !fdes.is_valid(); 98 } 99 100 TEST_F(MacSandboxTest, FileAccess) { 101 EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedFileAccessTestCase", NULL)); 102 } 103 104 //--------------------- /dev/urandom Sandboxing ---------------------- 105 // /dev/urandom is available to any sandboxed process. 106 class MacSandboxedUrandomTestCase : public MacSandboxTestCase { 107 public: 108 virtual bool SandboxedTest() OVERRIDE; 109 }; 110 111 REGISTER_SANDBOX_TEST_CASE(MacSandboxedUrandomTestCase); 112 113 bool MacSandboxedUrandomTestCase::SandboxedTest() { 114 base::ScopedFD fdes(HANDLE_EINTR(open("/dev/urandom", O_RDONLY))); 115 116 // Opening /dev/urandom succeeds under the sandbox. 117 if (!fdes.is_valid()) 118 return false; 119 120 char buf[16]; 121 int rc = HANDLE_EINTR(read(fdes.get(), buf, sizeof(buf))); 122 return rc == sizeof(buf); 123 } 124 125 TEST_F(MacSandboxTest, UrandomAccess) { 126 EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedUrandomTestCase", NULL)); 127 } 128 129 #if defined(USE_OPENSSL) 130 131 //--------------------- OpenSSL Sandboxing ---------------------- 132 // Test case for checking sandboxing of OpenSSL initialization. 133 class MacSandboxedOpenSSLTestCase : public MacSandboxTestCase { 134 public: 135 virtual bool SandboxedTest() OVERRIDE; 136 }; 137 138 REGISTER_SANDBOX_TEST_CASE(MacSandboxedOpenSSLTestCase); 139 140 bool MacSandboxedOpenSSLTestCase::SandboxedTest() { 141 crypto::EnsureOpenSSLInit(); 142 143 // Ensure that RAND_bytes is functional within the sandbox. 144 uint8_t byte; 145 return RAND_bytes(&byte, 1) == 1; 146 } 147 148 TEST_F(MacSandboxTest, OpenSSLAccess) { 149 EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedOpenSSLTestCase", NULL)); 150 } 151 152 #else // !defined(USE_OPENSSL) 153 154 //--------------------- NSS Sandboxing ---------------------- 155 // Test case for checking sandboxing of NSS initialization. 156 class MacSandboxedNSSTestCase : public MacSandboxTestCase { 157 public: 158 virtual bool SandboxedTest() OVERRIDE; 159 }; 160 161 REGISTER_SANDBOX_TEST_CASE(MacSandboxedNSSTestCase); 162 163 bool MacSandboxedNSSTestCase::SandboxedTest() { 164 // If NSS cannot read from /dev/urandom, NSS initialization will call abort(), 165 // which will cause this test case to fail. 166 crypto::ForceNSSNoDBInit(); 167 crypto::EnsureNSSInit(); 168 return true; 169 } 170 171 TEST_F(MacSandboxTest, NSSAccess) { 172 EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedNSSTestCase", NULL)); 173 } 174 175 #endif // defined(USE_OPENSSL) 176 177 } // namespace content 178