Fix Prevent defect about array_null
[platform/core/security/key-manager.git] / src / manager / service / file-system.cpp
1 /*
2  *  Copyright (c) 2000 - 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  * @file        FileSystem.cpp
18  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19  * @version     1.0
20  * @brief       Sample service implementation.
21  */
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <dirent.h>
27
28 #include <cstdlib>
29 #include <string>
30 #include <sstream>
31 #include <fstream>
32
33 #include <dpl/log/log.h>
34
35 #include <file-system.h>
36
37 namespace {
38
39 static const std::string CKM_DATA_PATH = "/opt/data/ckm/";
40 static const std::string CKM_KEY_PREFIX = "key-";
41 static const std::string CKM_DB_KEY_PREFIX = "db-key-";
42 static const std::string CKM_DB_PREFIX = "db-";
43 static const std::string CKM_REMOVED_APP_PREFIX = "removed-app-";
44
45 } // namespace anonymous
46
47 namespace CKM {
48
49 FileSystem::FileSystem(uid_t uid)
50   : m_uid(uid)
51 {}
52
53 std::string FileSystem::getDBPath() const
54 {
55     std::stringstream ss;
56     ss << CKM_DATA_PATH << CKM_DB_PREFIX << m_uid;
57     return ss.str();
58 }
59
60 std::string FileSystem::getDKEKPath() const {
61     std::stringstream ss;
62     ss << CKM_DATA_PATH << CKM_KEY_PREFIX << m_uid;
63     return ss.str();
64 }
65
66 std::string FileSystem::getDBDEKPath() const {
67     std::stringstream ss;
68     ss << CKM_DATA_PATH << CKM_DB_KEY_PREFIX << m_uid;
69     return ss.str();
70 }
71
72 std::string FileSystem::getRemovedAppsPath() const {
73     std::stringstream ss;
74     ss << CKM_DATA_PATH << CKM_REMOVED_APP_PREFIX << m_uid;
75     return ss.str();
76 }
77
78 RawBuffer FileSystem::loadFile(const std::string &path) const {
79     std::ifstream is(path);
80
81     if (is.fail())
82         return RawBuffer();
83
84     std::istreambuf_iterator<char> begin(is),end;
85     std::vector<char> buff(begin,end); // This trick does not work with boost vector
86
87     RawBuffer buffer(buff.size());
88     memcpy(buffer.data(), buff.data(), buff.size());
89     return buffer;
90 }
91
92 RawBuffer FileSystem::getDKEK() const
93 {
94     return loadFile(getDKEKPath());
95 }
96
97 RawBuffer FileSystem::getDBDEK() const
98 {
99     return loadFile(getDBDEKPath());
100 }
101
102 bool FileSystem::saveFile(const std::string &path, const RawBuffer &buffer) const {
103     std::ofstream os(path, std::ios::out | std::ofstream::binary);
104     std::copy(buffer.begin(), buffer.end(), std::ostreambuf_iterator<char>(os));
105     return !os.fail();
106 }
107
108 bool FileSystem::saveDKEK(const RawBuffer &buffer) const {
109     return saveFile(getDKEKPath(), buffer);
110 }
111
112 bool FileSystem::saveDBDEK(const RawBuffer &buffer) const {
113     return saveFile(getDBDEKPath(), buffer);
114 }
115
116 bool FileSystem::addRemovedApp(const std::string &smackLabel) const
117 {
118     std::ofstream outfile;
119     outfile.open(getRemovedAppsPath(), std::ios_base::app);
120     outfile << smackLabel << std::endl;
121     outfile.close();
122     return !outfile.fail();
123 }
124
125 AppLabelVector FileSystem::clearRemovedsApps() const
126 {
127     // read the contents
128     AppLabelVector removedApps;
129     std::string line;
130     std::ifstream removedAppsFile(getRemovedAppsPath());
131     if (removedAppsFile.is_open()) {
132         while (! removedAppsFile.eof() ) {
133             getline (removedAppsFile,line);
134             if(line.size() > 0)
135                 removedApps.push_back(line);
136         }
137         removedAppsFile.close();
138     }
139     // truncate the contents
140     std::ofstream truncateFile;
141     truncateFile.open(getRemovedAppsPath(), std::ofstream::out | std::ofstream::trunc);
142     truncateFile.close();
143     return removedApps;
144 }
145
146 int FileSystem::init() {
147     errno = 0;
148     if ((mkdir(CKM_DATA_PATH.c_str(), 0700)) && (errno != EEXIST)) {
149         int err = errno;
150         LogError("Error in mkdir. Data directory could not be created. Errno: "
151             << err << " (" << strerror(err) << ")");
152         return -1; // TODO set up some error code
153     }
154     return 0;
155 }
156
157 UidVector FileSystem::getUIDsFromDBFile() {
158     UidVector uids;
159     DIR *dirp = NULL;
160     errno = 0;
161
162     if((dirp = opendir(CKM_DATA_PATH.c_str())) == NULL) {
163         int err = errno;
164         LogError("Error in opendir. Data directory could not be read. Errno: "
165                 << err << " (" << strerror(err) << ")");
166         return UidVector();
167     }
168
169     struct dirent pPrevDirEntry;
170     struct dirent* pDirEntry = NULL;
171
172     while ( (!readdir_r(dirp, &pPrevDirEntry, &pDirEntry)) && pDirEntry ) {
173
174         // Ignore files with diffrent prefix
175         if (strncmp(pDirEntry->d_name, CKM_KEY_PREFIX.c_str(), CKM_KEY_PREFIX.size())) {
176             continue;
177         }
178
179         // We find database. Let's extract user id.
180         try {
181             uids.push_back(static_cast<uid_t>(std::stoi((pDirEntry->d_name)+CKM_KEY_PREFIX.size())));
182         } catch (const std::invalid_argument) {
183             LogError("Error in extracting uid from db file. Error=std::invalid_argument."
184                 "This will be ignored.File=" << pDirEntry->d_name << "");
185         } catch(const std::out_of_range) {
186             LogError("Error in extracting uid from db file. Error=std::out_of_range."
187                 "This will be ignored. File="<< pDirEntry->d_name << "");
188         }
189     }
190
191     closedir(dirp);
192     return uids;
193 }
194
195 int FileSystem::removeUserData() const {
196     int err, retCode = 0;
197
198     if (unlink(getDBPath().c_str())) {
199         retCode = -1;
200         err = errno;
201         LogError("Error in unlink user database: " << getDBPath()
202             << "Errno: " << errno << " " << strerror(err));
203     }
204
205     if (unlink(getDKEKPath().c_str())) {
206         retCode = -1;
207         err = errno;
208         LogError("Error in unlink user DKEK: " << getDKEKPath()
209             << "Errno: " << errno << " " << strerror(err));
210     }
211
212     if (unlink(getDBDEKPath().c_str())) {
213         retCode = -1;
214         err = errno;
215         LogError("Error in unlink user DBDEK: " << getDBDEKPath()
216             << "Errno: " << errno << " " << strerror(err));
217     }
218
219     if (unlink(getRemovedAppsPath().c_str())) {
220         retCode = -1;
221         err = errno;
222         LogError("Error in unlink user's Removed Apps File: " << getRemovedAppsPath()
223             << "Errno: " << errno << " " << strerror(err));
224     }
225
226     return retCode;
227 }
228
229 } // namespace CKM
230