* @brief Tests for Cynara's mechanism assuring integrity of database
*/
-#include <dpl/test/test_runner.h>
+#include <cynara_test_admin.h>
+#include <cynara_test_client.h>
#include <cynara_test_commons.h>
+#include <cynara_test_env.h>
+#include <dpl/test/test_runner.h>
+#include <sys/smack.h>
+#include <dbus_access.h>
#include <dirent.h>
-#include <glob.h>
+#include <fcntl.h>
#include <fstream>
+#include <glob.h>
#include <iterator>
#include <memory.h>
#include <set>
#include <string>
+#include <unistd.h>
+
+using namespace CynaraTestAdmin;
+using namespace CynaraTestClient;
namespace
{
+const std::string defDb("default");
+const std::string defDbAllow("defaultAllowed");
+const std::string nonEmptyDb("nonEmptyDatabase");
const std::string cynaraTestPatternsPath("/etc/security-tests/db_patterns/");
const std::string directoryWildcard("/*");
+void createDbFile(const std::string &filename)
+{
+ int fileFd = TEMP_FAILURE_RETRY(creat(filename.c_str(), 0000));
+ RUNNER_ASSERT_ERRNO_MSG(fileFd > 0, "Creating " << filename << " file failed");
+ FdUniquePtr fileFdPtr(&fileFd);
+
+ int ret = smack_fsetlabel(fileFd, CynaraTestConsts::LABEL.c_str(), SMACK_LABEL_ACCESS);
+ RUNNER_ASSERT_MSG(ret == 0, "Setting smack label failed");
+}
+
+void deleteDbFile(const std::string &filename)
+{
+ RUNNER_ASSERT_ERRNO_MSG(!unlink(filename.c_str()), "Unable to unlink " << filename << " file");
+}
+
bool unordered_files_match(const std::string &patternFilePath, const std::string &resultFilePath) {
std::ifstream patternFile(patternFilePath, std::ifstream::in | std::ifstream::binary);
std::ifstream resultFile(resultFilePath, std::ifstream::in | std::ifstream::binary);
}
}
+} // anonymous namespace
+
+/**
+ * @brief Lockdown initialization failure caused by fake guard existence
+ * @test Expected result: refuse to write data to storage as long as guard file creation fails
+ * 1. Create fake guard file with 0000 attributes in policy database
+ * 2. Try to make a change (ALLOW) in default bucket (data dump should fail)
+ * 3. Delete fake guard file from policy database
+ * 4. Retry to make a change (ALLOW) in default bucket (data dump should proceed)
+ * 5. Check if database is saved correctly
+ */
+void tcdb01_lockdown_init_failure_func()
+{
+ Admin admin;
+ Client cynara;
+ DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
+
+ const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
+ const char *extra = nullptr;
+
+ const auto fakeBackupGuard = CynaraTestConsts::DB_DIR + "/guard";
+
+ createDbFile(fakeBackupGuard);
+ admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra, CYNARA_API_OPERATION_FAILED);
+
+ deleteDbFile(fakeBackupGuard);
+ admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra);
+
+ dbusAccess.restartService();
+ compareDbs(defDbAllow);
+}
+
+/**
+ * @brief Failure during writing to backup (before lockdown)
+ * @test Expected result: read from primary policy database
+ * 1. Write ALLOW to default bucket
+ * 2. Check if data is saved correctly
+ * 3. Create fake backup file with 0000 attributes in policy database
+ * 4. Try to make a change (DENY) in default bucket (data dump should fail)
+ * 5. Reload Cynara - policies loaded from default bucket should still be ALLOW
+ */
+void tcdb02_write_to_backup_failure_func()
+{
+ Admin admin;
+ Client cynara;
+ DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
+
+ const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
+ const char *extra = nullptr;
+
+ const auto fakeBucketDumpFile = CynaraTestConsts::DB_DIR + "/_~";
+
+ admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra);
+ compareDbs(defDbAllow);
+
+ createDbFile(fakeBucketDumpFile);
+ admin.setBucket(bucket, CYNARA_ADMIN_DENY, extra, CYNARA_API_OPERATION_FAILED);
+
+ dbusAccess.restartService();
+ compareDbs(defDbAllow);
}
RUNNER_TEST_GROUP_INIT(cynara_db_tests)
+
+RUN_CYNARA_TEST(tcdb01_lockdown_init_failure)
+RUN_CYNARA_TEST(tcdb02_write_to_backup_failure)