Start&stop support added to DBusAccess
[platform/core/test/security-tests.git] / tests / cynara-tests / common / cynara_test_env.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 #include <cynara_test_env.h>
18 #include <tests_common.h>
19 #include <dbus_access.h>
20 #include <memory.h>
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/sendfile.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <ftw.h>
28 #include <fcntl.h>
29 #include <pwd.h>
30 #include <dirent.h>
31
32 namespace
33 {
34
35 typedef CStringPtr PwBufPtr;
36
37 DEFINE_SMARTPTR(closedir, DIR, DirPtr);
38
39 const std::string cynaraDbDir = CYNARA_DB_DIR;
40 const std::string tmpDir = "/tmp/";
41 const std::string cynaraUser = "cynara";
42 const std::string cynaraLabel = "System";
43
44 int removeContents(const char *fpath, const struct stat * /*sb*/,
45                    int tflag, struct FTW * /*ftwbuf*/)
46 {
47     if (tflag == FTW_F)
48         RUNNER_ASSERT_ERRNO_MSG(!unlink(fpath), "Unable to unlink " << fpath << " file");
49     else
50         RUNNER_ASSERT_MSG(tflag == FTW_DP, "Visited file should not exist. Path: " << fpath);
51     return 0;
52 }
53
54 void copyFile(const std::string &src, const std::string &dst)
55 {
56     int inFd = TEMP_FAILURE_RETRY(open(src.c_str(), O_RDONLY));
57     RUNNER_ASSERT_ERRNO_MSG(inFd > 0, "Opening " << src << " file failed");
58     FdUniquePtr inFdPtr(&inFd);
59
60     int outFd = TEMP_FAILURE_RETRY(creat(dst.c_str(), 0700));
61     RUNNER_ASSERT_ERRNO_MSG(outFd > 0, "Creating " << dst << " file failed");
62     FdUniquePtr outFdPtr(&outFd);
63
64     long int len = sysconf(_SC_GETPW_R_SIZE_MAX);
65     RUNNER_ASSERT_MSG(len != -1, "No suggested buflen");
66     size_t buflen = len;
67     char *buf = static_cast<char*>(malloc(buflen));
68
69     PwBufPtr pwBufPtr(buf);
70
71     struct passwd pwbuf, *pwbufp = nullptr;
72     int ret = TEMP_FAILURE_RETRY(getpwnam_r(cynaraUser.c_str(),
73                                             &pwbuf, buf, buflen, &pwbufp));
74     RUNNER_ASSERT_ERRNO_MSG(ret == 0, "getpwnam_r failed on " << cynaraUser << " user");
75     RUNNER_ASSERT_MSG(pwbufp, "User " << cynaraUser << " does not exist");
76
77     ret = fchown(outFd, pwbufp->pw_uid, pwbufp->pw_gid);
78     RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fchown failed");
79
80     ret = smack_fsetlabel(outFd, cynaraLabel.c_str(), SMACK_LABEL_ACCESS);
81     RUNNER_ASSERT_MSG(ret == 0, "Setting smack label failed");
82
83     struct stat statSrc;
84     ret = fstat(inFd, &statSrc);
85     RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fstat failed");
86
87     ret = sendfile(outFd, inFd, 0, statSrc.st_size);
88     RUNNER_ASSERT_ERRNO_MSG(ret != -1, "sendfile failed");
89 }
90
91 void copyDir(const std::string &source, const std::string &destination)
92 {
93     DIR *dirPtr = nullptr;
94     struct dirent *direntPtr;
95
96     RUNNER_ASSERT_ERRNO_MSG(dirPtr = opendir(source.c_str()),
97                                "opening " << source << " dir failed");
98     DirPtr dirScopedPtr(dirPtr);
99
100     while((direntPtr = readdir(dirPtr)) != nullptr) {
101         if (!strcmp(direntPtr->d_name, ".")
102          || !strcmp(direntPtr->d_name, ".."))
103             continue;
104         std::string tempDest = destination + "/" + direntPtr->d_name;
105         std::string tempSrc = source + "/" + direntPtr->d_name;
106         copyFile(tempSrc, tempDest);
107     }
108 }
109
110 void clear(const std::string &dir)
111 {
112     int ret = nftw(dir.c_str(), removeContents, 2, FTW_DEPTH | FTW_PHYS);
113     if (ret == -1)
114         RUNNER_ASSERT_ERRNO_MSG(errno == ENOENT, "nftw failed");
115 }
116
117 void removeDirIfExists(const std::string &dir)
118 {
119     RUNNER_ASSERT_ERRNO_MSG(!rmdir(dir.c_str()) || errno == ENOENT,
120                                "Removing " << dir << " dir failed");
121 }
122
123 bool cynaraDbExists()
124 {
125     struct stat st;
126     int ret = stat(cynaraDbDir.c_str(), &st);
127     if (ret == -1 && errno == ENOENT) {
128         return false;
129     } else if (ret == -1) {
130         RUNNER_ASSERT_ERRNO_MSG(false, "Cannot stat " << cynaraDbDir
131                                           << " not due to its nonexistence");
132     }
133     RUNNER_ASSERT_MSG(st.st_mode & S_IFDIR, cynaraDbDir << " is not a directory");
134     return true;
135 }
136
137 }
138
139 CynaraTestEnv::CynaraTestEnv(const char *dirName)
140     : m_dbPresent(false)
141 {
142     m_dir = tmpDir + dirName;
143 }
144
145 CynaraTestEnv::~CynaraTestEnv()
146 {
147 }
148
149 void CynaraTestEnv::save()
150 {
151     clear(m_dir);
152     removeDirIfExists(m_dir);
153
154     DBusAccess dbusAccess("cynara.service");
155     dbusAccess.stop();
156
157     m_dbPresent = cynaraDbExists();
158     if (m_dbPresent) {
159         RUNNER_ASSERT_ERRNO_MSG(!mkdir(m_dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO),
160                                    "Unable to make " << m_dir << " test directory");
161         copyDir(cynaraDbDir, m_dir);
162     }
163
164     dbusAccess.start();
165 }
166
167 void CynaraTestEnv::restore()
168 {
169     DBusAccess dbusAccess("cynara.service");
170     dbusAccess.stop();
171
172     clear(cynaraDbDir);
173     if (m_dbPresent)
174         copyDir(m_dir, cynaraDbDir);
175     else
176         removeDirIfExists(cynaraDbDir);
177
178     dbusAccess.start();
179
180     clear(m_dir);
181     removeDirIfExists(m_dir);
182 }