Add security policy
[platform/core/security/dpm-security.git] / plugin / security.cpp
1 /*
2  *  Copyright (c) 2015 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 #include <vconf.h>
17 #include <thread>
18 #include <vector>
19
20 #include <dd-deviced.h>
21 #include <dd-control.h>
22
23 #include <klay/process.h>
24 #include <klay/exception.h>
25 #include <klay/filesystem.h>
26 #include <klay/dbus/variant.h>
27 #include <klay/dbus/connection.h>
28
29 #include <dpm/pil/policy-context.h>
30 #include <dpm/pil/policy-model.h>
31 #include <dpm/pil/policy-storage.h>
32 #include <dpm/pil/launchpad.h>
33
34 namespace {
35
36 const std::string APPID_DEVICE_ENCRYPTION = "org.tizen.ode";
37 const std::string APPID_LOCKSCREEN = "org.tizen.lockscreen";
38
39 const std::string PROG_FACTORY_RESET = "/usr/bin/dbus-send";
40 const std::vector<std::string> wipeCommand = {
41         "/usr/bin/dbus-send",
42         "--system",
43         "--type=signal",
44         "--print-reply",
45         "--dest=com.samsung.factoryreset",
46         "/com/samsung/factoryreset",
47         "com.samsung.factoryreset.start.setting"
48 };
49
50 bool checkEncryptionState(const char* key, bool encrypt)
51 {
52         char *value = ::vconf_get_str(key);
53         if (value == NULL) {
54                 ERROR("Failed to read internal storage encryption state");
55                 return false;
56         }
57
58         std::string state(value);
59         ::free(value);
60         if (encrypt) {
61                 if (state != "unencrypted") {
62                         ERROR("Storage might be already encrypted or it has error");
63                         return false;
64                 }
65         } else {
66                 if (state != "encrypted") {
67                         ERROR("Storage might be already decrypted or it has error");
68                         return false;
69                 }
70         }
71
72         return true;
73 }
74
75 bool getEncryptionState(const char* key)
76 {
77         char *state = ::vconf_get_str(key);
78         if (state == NULL) {
79                 throw runtime::Exception("Failed to read internal storage encryption state");
80         }
81
82         std::string expected("encrypted");
83         if (expected == state) {
84                 ::free(state);
85                 return true;
86         }
87
88         ::free(state);
89         return false;
90 }
91
92 int launchApplication(const std::string& name, const Bundle& bundle)
93 {
94         try {
95                 Launchpad launchpad(rmi::Service::getPeerUid());
96                 if (launchpad.isRunning(name)) {
97                         launchpad.resume(name);
98                         return 0;
99                 }
100
101                 launchpad.launch(name, bundle);
102         } catch (runtime::Exception& e) {
103                 ERROR("Failed to start application: " << name);
104                 return -1;
105         }
106
107         return 0;
108 }
109
110
111 std::vector<std::string> getStorageDeviceList(const std::string& type)
112 {
113         int intparams[6];
114         char* strparams[7];
115         std::vector<std::string> storages;
116
117         dbus::Connection &systemDBus = dbus::Connection::getSystem();
118         const dbus::Variant &var = systemDBus.methodcall("org.tizen.system.storage",
119                                                                                                          "/Org/Tizen/System/Storage/Block/Manager",
120                                                                                                          "org.tizen.system.storage.BlockManager",
121                                                                                                          "GetDeviceList",
122                                                                                                          -1,
123                                                                                                          "(a(issssssisibii))",
124                                                                                                          "(s)",
125                                                                                                          type.c_str());
126         dbus::VariantIterator it;
127         var.get("(a(issssssisibii))", &it);
128         while (it.get("(issssssisibii)",
129                                   &intparams[0], // block type: 0 - scsi, 1 : mmc
130                                   &strparams[0], // devnode
131                                   &strparams[1], // syspath
132                                   &strparams[2], // usage
133                                   &strparams[3], // fs type
134                                   &strparams[4], // fs version
135                                   &strparams[5], // fs uuid enc
136                                   &intparams[1], // readonly: 0 - rw, 1 - ro
137                                   &strparams[6], // mount point
138                                   &intparams[2], // state: 0 - unmount, 1 - mount
139                                   &intparams[3], // primary: 0 - flase, 1 - true
140                                   &intparams[4], // flags: 1 - unmounted
141                                                                  //        2 - broken filesystem
142                                                                  //        4 - no filesystem
143                                                                  //        8 - not supported
144                                                                  //       16 - readonly
145                                   &intparams[5])) { // strage id
146                 storages.push_back(strrchr(strparams[0], '/') + 1);
147                 for (int i = 0; i < 7; i++) {
148                         if (strparams[i]) {
149                                 ::free(strparams[i]);
150                         }
151                 }
152         }
153
154         return storages;
155 }
156
157 void requestDeviceFormat(const std::string& devnode, int option)
158 {
159         int ret;
160         dbus::Connection &systemDBus = dbus::Connection::getSystem();
161         systemDBus.methodcall("org.tizen.system.storage",
162                                                   "/Org/Tizen/System/Storage/Block/Devices/" + devnode,
163                                                   "org.tizen.system.storage.Block",
164                                                   "Format",
165                                                   G_MAXINT,
166                                                   "(i)",
167                                                   "(i)",
168                                                   option).get("(i)", &ret);
169         if (ret != 0) {
170                 throw runtime::Exception("Failed to format " + devnode);
171         }
172 }
173
174 } // namespace
175
176 class Security : public AbstractPolicyProvider {
177 public:
178         enum {
179                 WIPE_INTERNAL_STORAGE = (1 << 0), /**< Wipe internal memory */
180                 WIPE_EXTERNAL_STORAGE = (1 << 1),  /**< Wipe external memory */
181         };
182
183         Security();
184         ~Security();
185
186         int lockoutScreen();
187
188         int wipeData(int id);
189
190         int setInternalStorageEncryption(bool encrypt);
191         bool isInternalStorageEncrypted();
192         int setExternalStorageEncryption(bool encrypt);
193         bool isExternalStorageEncrypted();
194 };
195
196 Security::Security()
197 {
198 }
199
200 Security::~Security()
201 {
202 }
203
204 int Security::lockoutScreen()
205 {
206         return launchApplication(APPID_LOCKSCREEN, Bundle());
207 }
208
209 int Security::setInternalStorageEncryption(bool encrypt)
210 {
211         if (!checkEncryptionState(VCONFKEY_ODE_CRYPTO_STATE, encrypt)) {
212                 return -1;
213         }
214
215         Bundle bundle;
216         bundle.add("viewtype", encrypt ? "ENCRYPT_DEVICE" : "DECRYPT_DEVICE");
217         return launchApplication(APPID_DEVICE_ENCRYPTION, bundle);
218 }
219
220 bool Security::isInternalStorageEncrypted()
221 {
222         return getEncryptionState(VCONFKEY_ODE_CRYPTO_STATE);
223 }
224
225 int Security::setExternalStorageEncryption(bool encrypt)
226 {
227         if (!checkEncryptionState(VCONFKEY_SDE_CRYPTO_STATE, encrypt)) {
228                 return -1;
229         }
230
231         Bundle bundle;
232         bundle.add("viewtype", encrypt ? "ENCRYPT_SD_CARD" : "DECRYPT_SD_CARD");
233         return launchApplication(APPID_DEVICE_ENCRYPTION, bundle);
234 }
235
236 bool Security::isExternalStorageEncrypted()
237 {
238         return getEncryptionState(VCONFKEY_SDE_CRYPTO_STATE);
239 }
240
241 int Security::wipeData(int id)
242 {
243         auto worker = [id, this]() {
244                 if (id & WIPE_EXTERNAL_STORAGE) {
245                         try {
246                                 std::vector<std::string> devices = getStorageDeviceList("mmc");
247                                 for (const std::string& devnode : devices) {
248                                         std::cout << "Erase device: " << devnode << std::endl;
249                                         requestDeviceFormat(devnode, 1);
250                                         std::cout << "Erase device: " << devnode << " completed" << std::endl;
251                                 }
252                         } catch(runtime::Exception& e) {
253                                 ERROR("Failed to enforce external storage policy");
254                                 return -1;
255                         }
256                 }
257
258                 if (id & WIPE_INTERNAL_STORAGE) {
259                         runtime::Process proc(PROG_FACTORY_RESET, wipeCommand);
260                         if (proc.execute() == -1) {
261                                 ERROR("Failed to launch factory-reset");
262                                 return -1;
263                         }
264                 }
265
266                 return 0;
267         };
268
269         std::thread deviceWiper(worker);
270         deviceWiper.detach();
271
272         return 0;
273 }
274
275 extern "C" {
276
277 #define PRIVILEGE_SECURITY "http://tizen.org/privilege/dpm.security"
278 #define PRIVILEGE_WIPE     "http://tizen.org/privilege/dpm.wipe"
279 #define PRIVILEGE_LOCK     "http://tizen.org/privilege/dpm.lock"
280
281 AbstractPolicyProvider *PolicyFactory(PolicyControlContext& context)
282 {
283     Security *policy = new Security();
284
285         context.expose(policy, PRIVILEGE_SECURITY, (int)(Security::setInternalStorageEncryption)(bool));
286         context.expose(policy, PRIVILEGE_SECURITY, (int)(Security::setExternalStorageEncryption)(bool));
287         context.expose(policy, PRIVILEGE_WIPE,     (int)(Security::wipeData)(int));
288         context.expose(policy, PRIVILEGE_LOCK,     (int)(Security::lockoutScreen)());
289
290         context.expose(policy, "", (bool)(Security::isInternalStorageEncrypted)());
291         context.expose(policy, "", (bool)(Security::isExternalStorageEncrypted)());
292
293         return policy;
294 }
295
296 } // extern "C"
297
298