Stop security-manager before unmounting /opt/usr
[platform/core/security/ode.git] / server / internal-encryption.cpp
1 /*
2  *  Copyright (c) 2015-2017 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 <set>
17 #include <algorithm>
18 #include <memory>
19
20 #include <fcntl.h>
21 #include <signal.h>
22 #include <unistd.h>
23 #include <sys/mount.h>
24 #include <sys/reboot.h>
25 #include <limits.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <vconf.h>
30 #include <tzplatform_config.h>
31 #include <klay/process.h>
32 #include <klay/file-user.h>
33 #include <klay/filesystem.h>
34 #include <klay/dbus/connection.h>
35 #include <klay/error.h>
36
37 #include "misc.h"
38 #include "logger.h"
39 #include "progress-bar.h"
40 #include "rmi/common.h"
41
42 #include "internal-encryption.h"
43 #include "internal-encryption-common.h"
44
45 namespace ode {
46
47 namespace {
48
49 const char *PRIVILEGE_PLATFORM  = "http://tizen.org/privilege/internal/default/platform";
50
51 // TODO: see recovery()
52 const std::string PROG_FACTORY_RESET = "/usr/bin/dbus-send";
53 const std::vector<std::string> wipeCommand = {
54     PROG_FACTORY_RESET,
55     "--system",
56     "--type=signal",
57     "--print-reply",
58     "--dest=com.samsung.factoryreset",
59     "/com/samsung/factoryreset",
60     "com.samsung.factoryreset.start.setting"
61 };
62
63 void stopKnownSystemdUnits()
64 {
65         std::vector<std::string> knownSystemdUnits;
66         dbus::Connection& systemDBus = dbus::Connection::getSystem();
67         dbus::VariantIterator iter;
68
69         systemDBus.methodcall("org.freedesktop.systemd1",
70                                                         "/org/freedesktop/systemd1",
71                                                         "org.freedesktop.systemd1.Manager",
72                                                         "ListUnits",
73                                                         -1, "(a(ssssssouso))", "")
74                                                                 .get("(a(ssssssouso))", &iter);
75
76         while (1) {
77                 unsigned int dataUint;
78                 char *dataStr[9];
79                 int ret;
80
81                 ret = iter.get("(ssssssouso)", dataStr, dataStr + 1, dataStr + 2,
82                                                 dataStr + 3, dataStr + 4, dataStr + 5,
83                                                 dataStr + 6, &dataUint, dataStr + 7,
84                                                 dataStr + 8);
85
86                 if (!ret) {
87                         break;
88                 }
89
90                 std::string unit(dataStr[0]);
91                 if (unit == "security-manager.socket") {
92                         knownSystemdUnits.insert(knownSystemdUnits.begin(), unit);
93                 } else if (unit.compare(0, 5, "user@") == 0 ||
94                         unit == "tlm.service" ||
95                         unit == "resourced.service" ||
96                         unit == "security-manager.service") {
97                         knownSystemdUnits.push_back(unit);
98                 }
99         }
100
101         for (const std::string& unit : knownSystemdUnits) {
102                 INFO(SINK, "Stopping unit: " + unit);
103                 systemDBus.methodcall("org.freedesktop.systemd1",
104                                                                 "/org/freedesktop/systemd1",
105                                                                 "org.freedesktop.systemd1.Manager",
106                                                                 "StopUnit",
107                                                                 -1, "", "(ss)", unit.c_str(), "flush");
108         }
109
110         sleep(1); // TODO wait for confirmation from systemd instead
111 }
112
113 void stopDependedSystemdUnits()
114 {
115         dbus::Connection& systemDBus = dbus::Connection::getSystem();
116         std::set<std::string> unitsToStop;
117
118         for (pid_t pid : runtime::FileUser::getList(INTERNAL_PATH, true)) {
119                 try {
120                         char *unit;
121                         systemDBus.methodcall("org.freedesktop.systemd1",
122                                                                         "/org/freedesktop/systemd1",
123                                                                         "org.freedesktop.systemd1.Manager",
124                                                                         "GetUnitByPID",
125                                                                         -1, "(o)", "(u)", (unsigned int)pid)
126                                                                                 .get("(o)", &unit);
127                         unitsToStop.insert(unit);
128                 } catch (runtime::Exception &e) {
129                         INFO(SINK, "Killing process: " + std::to_string(pid));
130                         ::kill(pid, SIGKILL);
131                 }
132         }
133
134         for (const std::string& unit : unitsToStop) {
135                 INFO(SINK, "Stopping unit: " + unit);
136                 systemDBus.methodcall("org.freedesktop.systemd1",
137                                                                 unit,
138                                                                 "org.freedesktop.systemd1.Unit",
139                                                                 "Stop",
140                                                                 -1, "", "(s)", "flush");
141         }
142 }
143
144 void showProgressUI(const std::string type)
145 {
146         ::tzplatform_set_user(::tzplatform_getuid(TZ_SYS_DEFAULT_USER));
147         std::string defaultUserHome(::tzplatform_getenv(TZ_USER_HOME));
148         ::tzplatform_reset_user();
149
150         try {
151                 runtime::File shareDirectory("/opt/home/root/share");
152                 if (!shareDirectory.exists()) {
153                         shareDirectory.makeDirectory(true);
154                 }
155
156                 runtime::File elmConfigDir(shareDirectory.getPath() + "/.elementary");
157                 if (!elmConfigDir.exists()) {
158                         runtime::File defaultElmConfigDir(defaultUserHome + "/share/.elementary");
159                         defaultElmConfigDir.copyTo(shareDirectory.getPath());
160                 }
161         } catch (runtime::Exception &e) {
162                 ERROR(SINK, "Failed to set up elm configuration: " + std::string(e.what()));
163         }
164
165         std::vector<std::string> args = {
166                 "ode", "progress", type, "Internal"
167         };
168
169         runtime::Process proc("/usr/bin/ode", args);
170         proc.execute();
171 }
172
173 unsigned int getOptions()
174 {
175         unsigned int result = 0;
176         int value;
177
178         value = 0;
179         ::vconf_get_bool(VCONFKEY_ODE_FAST_ENCRYPTION, &value);
180         if (value) {
181                 result |= InternalEncryption::Option::IncludeUnusedRegion;
182         }
183
184         return result;
185 }
186
187 void setOptions(unsigned int options)
188 {
189         bool value;
190
191         if (options & InternalEncryption::Option::IncludeUnusedRegion) {
192                 value = true;
193         } else {
194                 value = false;
195         }
196         ::vconf_set_bool(VCONFKEY_ODE_FAST_ENCRYPTION, value);
197 }
198
199 void unmountInternalStorage(const std::string& source)
200 {
201         while(true) {
202                 auto mntPaths = findMountPointsByDevice(source);
203                 if(mntPaths.empty())
204                         break;
205
206                 bool unmounted = true;
207                 for(const auto& path : mntPaths) {
208                         INFO(SINK, "Unmounting " + path);
209                         if (::umount(path.c_str()) == -1) {
210                                 // If it's busy or was already unmounted ignore the error
211                                 if (errno != EBUSY && errno != EINVAL) {
212                                         throw runtime::Exception("umount() error: " + runtime::GetSystemErrorMessage());
213                                 }
214                                 unmounted = false;
215                         }
216                 }
217                 if (!unmounted)
218                         stopDependedSystemdUnits();
219         }
220 }
221
222 }
223
224 InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv,
225                                                                                                    KeyServer& key) :
226         server(srv),
227         keyServer(key)
228 {
229         server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::setMountPassword)(std::string));
230         server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::mount)());
231         server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::umount)());
232         server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::encrypt)(std::string, unsigned int));
233         server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::decrypt)(std::string));
234         server.expose(this, "", (int)(InternalEncryptionServer::isPasswordInitialized)());
235         server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::initPassword)(std::string));
236         server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::cleanPassword)(std::string));
237         server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::changePassword)(std::string, std::string));
238         server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::verifyPassword)(std::string));
239         server.expose(this, "", (int)(InternalEncryptionServer::getState)());
240         server.expose(this, "", (unsigned int)(InternalEncryptionServer::getSupportedOptions)());
241         server.expose(this, "", (std::string)(InternalEncryptionServer::getDevicePath)());
242
243         server.createNotification("InternalEncryptionServer::mount");
244
245         std::string source = findDevPath();
246
247         engine.reset(new INTERNAL_ENGINE(
248                 source, INTERNAL_PATH,
249                 ProgressBar([](int v) {
250                         ::vconf_set_str(VCONFKEY_ODE_ENCRYPT_PROGRESS,
251                                                         std::to_string(v).c_str());
252                 })
253         ));
254 }
255
256 InternalEncryptionServer::~InternalEncryptionServer()
257 {
258 }
259
260 int InternalEncryptionServer::setMountPassword(const std::string& password)
261 {
262         return keyServer.get(engine->getSource(), password, mountKey);
263 }
264
265 int InternalEncryptionServer::mount()
266 {
267         if (mountKey.empty()) {
268                 ERROR(SINK, "You need to call set_mount_password() first.");
269                 return error::NoData;
270         }
271
272         BinaryData key = mountKey;
273         mountKey.clear();
274
275         if (getState() != State::Encrypted) {
276                 INFO(SINK, "Cannot mount, SD partition's state incorrect.");
277                 return error::NoSuchDevice;
278         }
279
280         if (engine->isMounted()) {
281                 INFO(SINK, "Partition already mounted.");
282                 return error::None;
283         }
284
285         INFO(SINK, "Mounting internal storage.");
286         try {
287                 engine->mount(key, getOptions());
288
289                 server.notify("InternalEncryptionServer::mount");
290
291                 runtime::File("/tmp/.lazy_mount").create(O_WRONLY);
292                 runtime::File("/tmp/.unlock_mnt").create(O_WRONLY);
293         } catch (runtime::Exception &e) {
294                 ERROR(SINK, "Mount failed: " + std::string(e.what()));
295                 return error::Unknown;
296         }
297
298         return error::None;
299 }
300
301 int InternalEncryptionServer::umount()
302 {
303         if (getState() != State::Encrypted) {
304                 ERROR(SINK, "Cannot umount, partition's state incorrect.");
305                 return error::NoSuchDevice;
306         }
307
308         if (!engine->isMounted()) {
309                 INFO(SINK, "Partition already umounted.");
310                 return error::None;
311         }
312
313         INFO(SINK, "Closing all processes using internal storage.");
314         try {
315                 stopDependedSystemdUnits();
316                 INFO(SINK, "Umounting internal storage.");
317                 engine->umount();
318         } catch (runtime::Exception &e) {
319                 ERROR(SINK, "Umount failed: " + std::string(e.what()));
320                 return error::Unknown;
321         }
322
323         return error::None;
324 }
325
326 int InternalEncryptionServer::encrypt(const std::string& password, unsigned int options)
327 {
328         if (getState() != State::Unencrypted) {
329                 ERROR(SINK, "Cannot encrypt, partition's state incorrect.");
330                 return error::NoSuchDevice;
331         }
332
333         BinaryData masterKey;
334         int ret = keyServer.get(engine->getSource(), password, masterKey);
335         if (ret != error::None)
336                 return ret;
337
338         auto encryptWorker = [masterKey, options, this]() {
339                 try {
340                         INFO(SINK, "Closing all known systemd services that might be using internal storage.");
341                         stopKnownSystemdUnits();
342
343                         std::string source = engine->getSource();
344                         auto mntPaths = findMountPointsByDevice(source);
345
346                         if (!mntPaths.empty()) {
347                                 INFO(SINK, "Closing all processes using internal storage.");
348                                 stopDependedSystemdUnits();
349
350                                 INFO(SINK, "Unmounting internal storage.");
351                                 unmountInternalStorage(source);
352                         }
353
354                         showProgressUI("Encrypting");
355
356                         INFO(SINK, "Encryption started.");
357                         ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "error_partially_encrypted");
358                         engine->encrypt(masterKey, options);
359                         setOptions(options & getSupportedOptions());
360
361                         INFO(SINK, "Encryption completed.");
362                         ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "encrypted");
363                         server.notify("InternalEncryptionServer::mount");
364
365                         INFO(SINK, "Syncing disk and rebooting.");
366                         ::sync();
367                         ::reboot(RB_AUTOBOOT);
368                 } catch (runtime::Exception &e) {
369                         ERROR(SINK, "Encryption failed: " + std::string(e.what()));
370                 }
371         };
372
373         std::thread asyncWork(encryptWorker);
374         asyncWork.detach();
375
376         return error::None;
377 }
378
379 int InternalEncryptionServer::decrypt(const std::string& password)
380 {
381         if (getState() != State::Encrypted) {
382                 ERROR(SINK, "Cannot decrypt, partition's state incorrect.");
383                 return error::NoSuchDevice;
384         }
385
386         BinaryData masterKey;
387         int ret = keyServer.get(engine->getSource(), password, masterKey);
388         if (ret != error::None)
389                 return ret;
390
391         auto decryptWorker = [masterKey, this]() {
392                 try {
393                         if (engine->isMounted()) {
394                                 INFO(SINK, "Closing all known systemd services that might be using internal storage.");
395                                 stopKnownSystemdUnits();
396                                 INFO(SINK, "Closing all processes using internal storage.");
397                                 stopDependedSystemdUnits();
398
399                                 INFO(SINK, "Umounting internal storage.");
400                                 while (1) {
401                                         try {
402                                                 engine->umount();
403                                                 break;
404                                         } catch (runtime::Exception& e) {
405                                                 stopDependedSystemdUnits();
406                                         }
407                                 }
408                         }
409
410                         showProgressUI("Decrypting");
411
412                         INFO(SINK, "Decryption started.");
413                         ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "error_partially_encrypted");
414                         engine->decrypt(masterKey, getOptions());
415
416                         INFO(SINK, "Decryption complete.");
417                         ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "unencrypted");
418
419                         INFO(SINK, "Syncing disk and rebooting.");
420                         ::sync();
421                         ::reboot(RB_AUTOBOOT);
422                 } catch (runtime::Exception &e) {
423                         ERROR(SINK, "Decryption failed: " + std::string(e.what()));
424                 }
425         };
426
427         std::thread asyncWork(decryptWorker);
428         asyncWork.detach();
429
430         return error::None;
431 }
432
433 int InternalEncryptionServer::recovery()
434 {
435         if (getState() == State::Unencrypted) {
436                 return error::NoSuchDevice;
437         }
438
439         //TODO
440         runtime::Process proc(PROG_FACTORY_RESET, wipeCommand);
441         if (proc.execute() == -1) {
442                 ERROR(SINK, "Failed to launch factory-reset");
443                 return error::WrongPassword;
444         }
445
446         return error::None;
447 }
448
449 int InternalEncryptionServer::isPasswordInitialized()
450 {
451         return keyServer.isInitialized(engine->getSource());
452 }
453
454 int InternalEncryptionServer::initPassword(const std::string& password)
455 {
456         return keyServer.init(engine->getSource(), password, Key::DEFAULT_256BIT);
457 }
458
459 int InternalEncryptionServer::cleanPassword(const std::string& password)
460 {
461         return keyServer.remove(engine->getSource(), password);
462 }
463
464 int InternalEncryptionServer::changePassword(const std::string& oldPassword,
465                                                                                 const std::string& newPassword)
466 {
467         return keyServer.changePassword(engine->getSource(), oldPassword, newPassword);
468 }
469
470 int InternalEncryptionServer::verifyPassword(const std::string& password)
471 {
472         return keyServer.verifyPassword(engine->getSource(), password);
473 }
474
475 int InternalEncryptionServer::getState()
476 {
477         char *value = ::vconf_get_str(VCONFKEY_ODE_CRYPTO_STATE);
478         if (value == NULL) {
479                 throw runtime::Exception("Failed to get vconf value.");
480         }
481
482         std::string valueStr(value);
483         free(value);
484
485         if (valueStr == "encrypted") {
486                 return State::Encrypted;
487         } else if (valueStr == "unencrypted") {
488                 return State::Unencrypted;
489         } else {
490                 return State::Corrupted;
491         }
492 }
493
494 unsigned int InternalEncryptionServer::getSupportedOptions()
495 {
496         return engine->getSupportedOptions();
497 }
498
499 std::string InternalEncryptionServer::getDevicePath() const
500 {
501         return engine->getSource();
502 }
503
504 } // namespace ode