Home | History | Annotate | Download | only in common
      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