tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

getUserDB_unittest.cc (4783B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 #include "gtest/gtest.h"
      7 #include "prenv.h"
      8 #include "seccomon.h"
      9 
     10 #include <stdlib.h>
     11 #include <string>
     12 #include <unistd.h>
     13 #include <sys/stat.h>
     14 
     15 namespace nss_test {
     16 
     17 // Return the path to user's NSS database.
     18 extern "C" char *getUserDB(void);
     19 
     20 class Sysinit : public ::testing::Test {
     21 protected:
     22  void SetUp() {
     23    home_var_ = PR_GetEnvSecure("HOME");
     24    if (home_var_) {
     25      old_home_dir_ = home_var_;
     26    }
     27    xdg_data_home_var_ = PR_GetEnvSecure("XDG_DATA_HOME");
     28    if (xdg_data_home_var_) {
     29      old_xdg_data_home_ = xdg_data_home_var_;
     30      ASSERT_EQ(0, unsetenv("XDG_DATA_HOME"));
     31    }
     32    char tmp[] = "/tmp/nss-tmp.XXXXXX";
     33    tmp_home_ = mkdtemp(tmp);
     34    ASSERT_EQ(0, setenv("HOME", tmp_home_.c_str(), 1));
     35  }
     36 
     37  void TearDown() {
     38    // Set HOME back to original
     39    if (home_var_) {
     40      ASSERT_EQ(0, setenv("HOME", old_home_dir_.c_str(), 1));
     41    } else {
     42      ASSERT_EQ(0, unsetenv("HOME"));
     43    }
     44    // Set XDG_DATA_HOME back to original
     45    if (xdg_data_home_var_) {
     46      ASSERT_EQ(0, setenv("XDG_DATA_HOME", old_xdg_data_home_.c_str(), 1));
     47    }
     48    // Remove test dirs.
     49    if (!nssdir_.empty()) {
     50      ASSERT_EQ(0, RemoveEmptyDirsFromStart(nssdir_, tmp_home_));
     51    }
     52  }
     53 
     54  // Remove all dirs within @start from @path containing only empty dirs.
     55  // Assumes @start already exists.
     56  // Upon successful completion, return 0. Otherwise, -1.
     57  static int RemoveEmptyDirsFromStart(std::string path, std::string start) {
     58    if (path.find(start) == std::string::npos) {
     59      return -1;
     60    }
     61    std::string temp = path;
     62    if (rmdir(temp.c_str())) {
     63      return -1;
     64    }
     65    for (size_t i = temp.length() - 1; i > start.length(); --i) {
     66      if (temp[i] == '/') {
     67        temp[i] = '\0';
     68        if (rmdir(temp.c_str())) {
     69          return -1;
     70        }
     71      }
     72    }
     73    if (rmdir(start.c_str())) {
     74      return -1;
     75    }
     76    return 0;
     77  }
     78 
     79  // Create empty dirs appending @path to @start with mode @mode.
     80  // Assumes @start already exists.
     81  // Upon successful completion, return the string @start + @path.
     82  static std::string CreateEmptyDirsFromStart(std::string start,
     83                                              std::string path, mode_t mode) {
     84    std::string temp = start + "/";
     85    for (size_t i = 1; i < path.length(); ++i) {
     86      if (path[i] == '/') {
     87        EXPECT_EQ(0, mkdir(temp.c_str(), mode));
     88      }
     89      temp += path[i];
     90    }
     91    // We reach the end of string before the last dir is created
     92    EXPECT_EQ(0, mkdir(temp.c_str(), mode));
     93    return temp;
     94  }
     95 
     96  char *home_var_;
     97  char *xdg_data_home_var_;
     98  std::string old_home_dir_;
     99  std::string old_xdg_data_home_;
    100  std::string nssdir_;
    101  std::string tmp_home_;
    102 };
    103 
    104 class SysinitSetXdgUserDataHome : public Sysinit {
    105 protected:
    106  void SetUp() {
    107    Sysinit::SetUp();
    108    ASSERT_EQ(0, setenv("XDG_DATA_HOME", tmp_home_.c_str(), 1));
    109  }
    110 };
    111 
    112 class SysinitSetTrashXdgUserDataHome : public Sysinit {
    113 protected:
    114  void SetUp() {
    115    Sysinit::SetUp();
    116    std::string trashPath = tmp_home_ + "/this/path/does/not/exist";
    117    ASSERT_EQ(0, setenv("XDG_DATA_HOME", trashPath.c_str(), 1));
    118  }
    119 
    120  void TearDown() {
    121    ASSERT_EQ(0, rmdir(tmp_home_.c_str()));
    122    Sysinit::TearDown();
    123  }
    124 };
    125 
    126 // Check if $HOME/.pki/nssdb is used if it exists
    127 TEST_F(Sysinit, LegacyPath) {
    128  nssdir_ = CreateEmptyDirsFromStart(tmp_home_, "/.pki/nssdb", 0760);
    129  char *nssdb = getUserDB();
    130  ASSERT_EQ(nssdir_, nssdb);
    131  PORT_Free(nssdb);
    132 }
    133 
    134 // Check if $HOME/.local/share/pki/nssdb is used if:
    135 // - $HOME/.pki/nssdb does not exist;
    136 // - XDG_DATA_HOME is not set.
    137 TEST_F(Sysinit, XdgDefaultPath) {
    138  nssdir_ = CreateEmptyDirsFromStart(tmp_home_, "/.local/share", 0755);
    139  nssdir_ = CreateEmptyDirsFromStart(nssdir_, "/pki/nssdb", 0760);
    140  char *nssdb = getUserDB();
    141  ASSERT_EQ(nssdir_, nssdb);
    142  PORT_Free(nssdb);
    143 }
    144 
    145 // Check if ${XDG_DATA_HOME}/pki/nssdb is used if:
    146 // - $HOME/.pki/nssdb does not exist;
    147 // - XDG_DATA_HOME is set and the path exists.
    148 TEST_F(SysinitSetXdgUserDataHome, XdgSetPath) {
    149  // XDG_DATA_HOME is set to HOME
    150  nssdir_ = CreateEmptyDirsFromStart(tmp_home_, "/pki/nssdb", 0760);
    151  char *nssdb = getUserDB();
    152  ASSERT_EQ(nssdir_, nssdb);
    153  PORT_Free(nssdb);
    154 }
    155 
    156 // Check if it fails when:
    157 // - XDG_DATA_HOME is set to a path that does not exist;
    158 // - $HOME/.pki/nssdb also does not exist. */
    159 TEST_F(SysinitSetTrashXdgUserDataHome, XdgSetToTrashPath) {
    160  char *nssdb = getUserDB();
    161  ASSERT_EQ(nullptr, nssdb);
    162 }
    163 
    164 }  // namespace nss_test