Enable dbus activation
[platform/core/security/ode.git] / server / external-encryption.cpp
1 /*
2  *  Copyright (c) 2015 - 2019 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 <fstream>
17 #include <sstream>
18 #include <cstring>
19
20 #include <unistd.h>
21 #include <sys/mount.h>
22
23 #include <vconf.h>
24 #include <tzplatform_config.h>
25 #include <klay/file-user.h>
26 #include <klay/filesystem.h>
27 #include <klay/dbus/variant.h>
28 #include <klay/dbus/connection.h>
29
30 #include "misc.h"
31 #include "logger.h"
32 #include "progress-bar.h"
33 #include "rmi/common.h"
34 #include "file-footer.h"
35
36 #include "external-encryption.h"
37
38
39 namespace ode {
40
41 namespace {
42
43 bool isBootCompleted = false;
44
45 constexpr const char *DEFAULT_EXTERNAL_PATH = "/media/SDCardA1";
46 const char *PRIVILEGE_PLATFORM = "http://tizen.org/privilege/internal/default/platform";
47
48 void spawnUI()
49 {
50         INFO(SINK, "Launching SD card password popup.");
51         try {
52                 dbus::Connection &systemDBus = dbus::Connection::getSystem();
53
54                 systemDBus.methodcall("org.freedesktop.systemd1",
55                                                                 "/org/freedesktop/systemd1",
56                                                                 "org.freedesktop.systemd1.Manager",
57                                                                 "StartUnit",
58                                                                 -1, "", "(ss)", "ode-external-lock.service", "replace");
59         } catch (runtime::Exception &e) {
60                 ERROR(SINK, "Failed to launch SD card password popup: " + std::string(e.what()));
61         }
62 }
63
64
65 bool isEncrypted()
66 {
67         char *cryptoState = ::vconf_get_str(VCONFKEY_SDE_CRYPTO_STATE);
68         if (cryptoState == NULL)
69                 return false;
70
71         bool encrypted = (strcmp(cryptoState, "encrypted") == 0);
72         free(cryptoState);
73         return encrypted;
74 }
75
76 void externalCallback(dbus::Variant parameters)
77 {
78         int intparams[6];
79         char* strparams[7];
80
81         parameters.get("(issssssisibii)",
82                 &intparams[0], // block type: 0 - scsi, 1 : mmc
83                 &strparams[0], // devnode
84                 &strparams[1], // syspath
85                 &strparams[2], // usage
86                 &strparams[3], // fs type
87                 &strparams[4], // fs version
88                 &strparams[5], // fs uuid enc
89                 &intparams[1], // readonly: 0 - rw, 1 - ro
90                 &strparams[6], // mount point
91                 &intparams[2], // state: 0 - unmount, 1 - mount
92                 &intparams[3], // primary: 0 - flase, 1 - true
93                 &intparams[4], // flags: 1 - unmounted 2 - broken filesystem 4 - no filesystem 8 - not supported 16 - readonly
94                 &intparams[5]); // storage id
95
96         if (intparams[0] != 1 || (std::string(strparams[3]) != "vfat" &&
97                                                           std::string(strparams[3]) != "ext4")) {
98                 DEBUG(SINK, "Storaged says it's not a regular SD card. Ignoring.");
99                 return;
100         }
101
102         if(intparams[2] == 0) {
103                 INFO(SINK, "SD card not mounted, ignoring.");
104                 int ret = ::vconf_unset(VCONFKEY_SDE_MOUNT_POINT);
105                 if (ret != 0)
106                         ERROR(SINK, "vconf_unset() failed with " << ret);
107         } else {
108                 INFO(SINK, "SD card mounted.");
109                 int ret;
110                 ret = ::vconf_set_str(VCONFKEY_SDE_MOUNT_POINT, DEFAULT_EXTERNAL_PATH);
111                 if (ret != 0) {
112                         ERROR(SINK, "vconf_set() failed with " << ret);
113                         return;
114                 }
115
116                 if (isEncrypted() && isBootCompleted)
117                         spawnUI();
118         }
119 }
120
121 void bootCompletionCallback(dbus::Variant parameters)
122 {
123         auto waitForHomescreen = []() {
124                 //For a delay until homescreen is totally loaded
125                 sleep(8);
126
127                 INFO(SINK, "Boot completed.");
128                 int ret = ::vconf_set_str(VCONFKEY_SDE_MOUNT_POINT, DEFAULT_EXTERNAL_PATH);
129                 if (ret != 0) {
130                         ERROR(SINK, "vconf_set() failed with " << ret);
131                 } else if (isEncrypted()) {
132                         spawnUI();
133                 }
134                 isBootCompleted = true;
135         };
136
137         std::thread asyncWork(waitForHomescreen);
138         asyncWork.detach();
139 }
140
141 void externalAddEventReceiver()
142 {
143         dbus::Connection &systemDBus = dbus::Connection::getSystem();
144
145         systemDBus.subscribeSignal("",
146                                                                 "/Org/Tizen/System/Storage/Block/Manager",
147                                                                 "org.tizen.system.storage.BlockManager",
148                                                                 "DeviceChanged",
149                                                                 externalCallback);
150
151         systemDBus.subscribeSignal("",
152                                                                 "/Org/Tizen/System/DeviceD/Core",
153                                                                 "org.tizen.system.deviced.core",
154                                                                 "BootingDone",
155                                                                 bootCompletionCallback);
156 }
157
158 /*
159  * Introspection data for the exported object
160  *
161  * Test:
162  * dbus-send --system --type=method_call --print-reply --dest=org.tizen.ode
163  * /org/tizen/ode/ExternalEncryption org.freedesktop.DBus.Introspectable.Introspect
164  */
165 const gchar introspectionXml[] =
166         "<node>"
167         "  <interface name='org.tizen.ode.ExternalEncryption'>"
168         "    <method name='UpdateCardStatus'>"
169         "      <arg type='s' name='mountpoint' direction='in'/>"
170         "      <arg type='i' name='status' direction='in'/>"
171         "    </method>"
172         "  </interface>"
173         "</node>";
174
175 void dbusMethodCall(GDBusConnection *,
176                     const gchar *sender,
177                     const gchar *object,
178                     const gchar *interface,
179                     const gchar *method,
180                     GVariant *params,
181                     GDBusMethodInvocation *invocation,
182                     gpointer user_data)
183 {
184         DEBUG(SINK, "dbusMethodCall sender: " << sender << ", object: " << object << ", interface: " <<
185                     interface << ", method: " << method);
186
187         static_cast<ExternalEncryptionServer*>(user_data)->dbusMethodCall(method, params, invocation);
188 }
189
190 unsigned int getOptions()
191 {
192         unsigned int result = 0;
193         int value;
194
195         value = 0;
196         ::vconf_get_bool(VCONFKEY_SDE_EXCLUDE_MEDIAFILE, &value);
197         if (value) {
198                 result |= ExternalEncryption::Option::OnlyNewFile;
199         }
200
201         value = 0;
202         ::vconf_get_bool(VCONFKEY_SDE_ENCRYPT_NEWFILE, &value);
203         if (value) {
204                 result |= ExternalEncryption::Option::ExceptForMediaFile;
205         }
206
207         return result;
208 }
209
210 void setOptions(unsigned int options)
211 {
212         bool value;
213
214         if (options & ExternalEncryption::Option::OnlyNewFile) {
215                 value = true;
216         } else {
217                 value = false;
218         }
219         ::vconf_set_bool(VCONFKEY_SDE_EXCLUDE_MEDIAFILE, value);
220
221         if (options & ExternalEncryption::Option::ExceptForMediaFile) {
222                 value = true;
223         } else {
224                 value = false;
225         }
226         ::vconf_set_bool(VCONFKEY_SDE_ENCRYPT_NEWFILE, value);
227 }
228
229 } // namespace
230
231 ExternalEncryptionServer::ExternalEncryptionServer(ServerContext &srv,
232                                                                                                    KeyServer& key) :
233         server(srv),
234         keyServer(key)
235 {
236         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::setMountPassword)(std::string));
237         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::mount)());
238         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::umount)());
239         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::encrypt)(std::string, unsigned int));
240         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::decrypt)(std::string));
241         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::recovery)());
242         server.expose(this, "", (int)(ExternalEncryptionServer::isPasswordInitialized)());
243         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::initPassword)(std::string));
244         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::cleanPassword)(std::string));
245         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::changePassword)(std::string, std::string));
246         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::verifyPassword)(std::string));
247         server.expose(this, "", (int)(ExternalEncryptionServer::getState)());
248         server.expose(this, "", (unsigned int)(ExternalEncryptionServer::getSupportedOptions)());
249         server.expose(this, "", (std::string)(ExternalEncryptionServer::getDevicePath)());
250
251         server.createNotification("ExternalEncryptionServer::mount");
252
253         externalAddEventReceiver();
254 }
255
256 ExternalEncryptionServer::~ExternalEncryptionServer()
257 {
258 }
259
260 int ExternalEncryptionServer::setMountPassword(const std::string& password)
261 {
262         RequestLifetime rl(server);
263
264         return keyServer.get(getEngine().getSource(), password, mountKey);
265 }
266
267 int ExternalEncryptionServer::mount()
268 {
269         RequestLifetime rl(server);
270
271         if (mountKey.empty()) {
272                 ERROR(SINK, "You need to call set_mount_password() first.");
273                 return error::NoData;
274         }
275
276         BinaryData key = mountKey;
277         mountKey.clear();
278
279         if (getStateInternal() != State::Encrypted) {
280                 ERROR(SINK, "Cannot mount, SD card's state incorrect.");
281                 return error::NoSuchDevice;
282         }
283
284         auto& engine = getEngine();
285         if (engine.isMounted()) {
286                 INFO(SINK, "SD card already mounted.");
287                 return error::None;
288         }
289
290         INFO(SINK, "Mounting external storage.");
291         try {
292                 engine.mount(key, getOptions());
293         } catch (runtime::Exception &e) {
294                 ERROR(SINK, "Failed to mount: " + std::string(e.what()));
295                 return error::Unknown;
296         }
297
298         server.notify("ExternalEncryptionServer::mount");
299
300         return error::None;
301 }
302
303 int ExternalEncryptionServer::umount()
304 {
305         RequestLifetime rl(server);
306
307         if (getStateInternal() != State::Encrypted) {
308                 ERROR(SINK, "Cannot umount, SD card's state incorrect.");
309                 return error::NoSuchDevice;
310         }
311
312         auto& engine = getEngine();
313         if (!engine.isMounted()) {
314                 INFO(SINK, "SD card already umounted.");
315                 return error::None;
316         }
317
318         INFO(SINK, "Closing all applications using external storage.");
319         killDependentApplications(engine.getDestination());
320
321         INFO(SINK, "Umounting external storage.");
322         try {
323                 engine.umount();
324         } catch (runtime::Exception &e) {
325                 ERROR(SINK, "Failed to umount: " + std::string(e.what()));
326                 return error::Unknown;
327         }
328
329         return error::None;
330 }
331
332 int ExternalEncryptionServer::encrypt(const std::string &password, unsigned int options)
333 {
334         RequestLifetime rl(server);
335
336         if (getStateInternal() != State::Unencrypted) {
337                 INFO(SINK, "Cannot encrypt, SD card's state incorrect.");
338                 return error::NoSuchDevice;
339         }
340
341         BinaryData masterKey;
342         int ret = keyServer.get(getEngine().getSource(), password, masterKey);
343         if (ret != error::None)
344                 return ret;
345
346         auto encryptWorker = [masterKey, options, this](RequestLifetime&& rl) {
347                 try {
348                         auto& engine = getEngine();
349
350                         INFO(SINK, "Closing all applications using external storage.");
351                         killDependentApplications(engine.getDestination());
352
353                         INFO(SINK, "Encryption started.");
354                         engine.encrypt(masterKey, options);
355                         setOptions(options & engine.getSupportedOptions());
356
357                         INFO(SINK, "Encryption completed.");
358                         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "encrypted");
359                         server.notify("ExternalEncryptionServer::mount");
360
361                         INFO(SINK, "Syncing disk.");
362                         sync();
363                 } catch (runtime::Exception &e) {
364                         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "error_partially_encrypted");
365                         ERROR(SINK, "Encryption failed: " + std::string(e.what()));
366                 }
367         };
368
369         std::thread asyncWork(encryptWorker, std::move(rl));
370         asyncWork.detach();
371
372         return error::None;
373 }
374
375 int ExternalEncryptionServer::decrypt(const std::string &password)
376 {
377         RequestLifetime rl(server);
378
379         if (getStateInternal() != State::Encrypted) {
380                 ERROR(SINK, "Cannot decrypt, SD card's state incorrect.");
381                 return error::NoSuchDevice;
382         }
383
384         BinaryData masterKey;
385         int ret = keyServer.get(getEngine().getSource(), password, masterKey);
386         if (ret != error::None)
387                 return ret;
388
389         auto decryptWorker = [masterKey, this](RequestLifetime&& rl) {
390                 try {
391                         auto& engine = getEngine();
392
393                         INFO(SINK, "Closing all applications using external storage.");
394                         killDependentApplications(engine.getDestination());
395
396                         INFO(SINK, "Umounting external storage.");
397                         while (1) {
398                                 try {
399                                         engine.umount();
400                                         break;
401                                 } catch (runtime::Exception &e) {
402                                         killDependentApplications(engine.getDestination());
403                                 }
404                         }
405
406                         INFO(SINK, "Decryption started.");
407                         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "error_partially_decrypted");
408                         engine.decrypt(masterKey, getOptions());
409
410                         INFO(SINK, "Decryption completed.");
411                         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "unencrypted");
412
413                         INFO(SINK, "Syncing disk.");
414                         sync();
415                 } catch (runtime::Exception &e) {
416                         ERROR(SINK, "Decryption failed: " + std::string(e.what()));
417                 }
418         };
419
420         std::thread asyncWork(decryptWorker, std::move(rl));
421         asyncWork.detach();
422
423         return error::None;
424 }
425
426 int ExternalEncryptionServer::recovery()
427 {
428         RequestLifetime rl(server);
429
430         if (getStateInternal() == State::Unencrypted) {
431                 return error::NoSuchDevice;
432         }
433
434         auto& engine = getEngine();
435         for (runtime::DirectoryIterator iter(engine.getSource()), end;
436                         iter != end; ++iter) {
437                 iter->remove(true);
438         }
439
440         keyServer.removePassword(engine.getSource());
441         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "unencrypted");
442
443         return error::None;
444 }
445
446 int ExternalEncryptionServer::isPasswordInitialized()
447 {
448         return keyServer.isInitialized(getEngine().getSource());
449 }
450
451 int ExternalEncryptionServer::initPassword(const std::string& password)
452 {
453         return keyServer.init(getEngine().getSource(), password, Key::DEFAULT_256BIT);
454 }
455
456 int ExternalEncryptionServer::cleanPassword(const std::string& password)
457 {
458         return keyServer.remove(getEngine().getSource(), password);
459 }
460
461 int ExternalEncryptionServer::changePassword(const std::string &oldPassword,
462                                                                                          const std::string &newPassword)
463 {
464         return keyServer.changePassword(getEngine().getSource(), oldPassword, newPassword);
465 }
466
467 int ExternalEncryptionServer::verifyPassword(const std::string& password)
468 {
469         return keyServer.verifyPassword(getEngine().getSource(), password);
470 }
471
472 int ExternalEncryptionServer::getState()
473 {
474         RequestLifetime rl(server);
475
476         return getStateInternal();
477 }
478
479 unsigned int ExternalEncryptionServer::getSupportedOptions()
480 {
481         RequestLifetime rl(server);
482
483         return getEngine().getSupportedOptions();
484 }
485
486 std::string ExternalEncryptionServer::getDevicePath() const
487 {
488         RequestLifetime rl(server);
489
490         return getEngine().getSource();
491 }
492
493 void ExternalEncryptionServer::dbusRegisterObject(GDBusConnection *connection)
494 {
495         GError *err = NULL;
496         GDBusNodeInfo *dbusIntrospectionData = g_dbus_node_info_new_for_xml(introspectionXml, &err);
497         if (dbusIntrospectionData == NULL) {
498                 ERROR(SINK, "Dbus introspection data creation failed: " << err->message);
499                 return;
500         }
501
502         const GDBusInterfaceVTable interfaceVtable =
503         {
504                 ode::dbusMethodCall,
505                 NULL,
506                 NULL
507         };
508
509         /*
510          * Test:
511          * dbus-send --system --type=method_call --print-reply --dest=org.tizen.ode
512          * /org/tizen/ode/ExternalEncryption org.tizen.ode.ExternalEncryption.UpdateCardStatus
513          * string:"/media/SDCardA1" int32:1
514          */
515         guint registrationId = g_dbus_connection_register_object(connection,
516                                                                  "/org/tizen/ode/ExternalEncryption",
517                                                                  dbusIntrospectionData->interfaces[0],
518                                                                  &interfaceVtable,
519                                                                  this,
520                                                                  NULL,
521                                                                  &err);
522         if (registrationId == 0)
523                 ERROR(SINK, "Dbus object registration failed: " << err->message);
524
525         g_dbus_node_info_unref(dbusIntrospectionData);
526 }
527
528 void ExternalEncryptionServer::dbusMethodCall(const gchar *,
529                                               GVariant *params,
530                                               GDBusMethodInvocation *invocation)
531 {
532         RequestLifetime rl(server);
533
534         const gchar *mountPoint;
535         gint32 cardStatus;
536
537         g_variant_get(params, "(&si)", &mountPoint, &cardStatus);
538
539         switch (cardStatus) {
540         case 0:
541                 DEBUG(SINK, "Card unmounted " << mountPoint);
542                 {
543                         int ret = ::vconf_unset(VCONFKEY_SDE_MOUNT_POINT);
544                         if (ret != 0)
545                                 ERROR(SINK, "vconf_set_str() failed with " << ret);
546
547                         engine.reset();
548                 }
549                 break;
550         case 1:
551                 DEBUG(SINK, "Card mounted " << mountPoint);
552                 {
553                         int ret = ::vconf_set_str(VCONFKEY_SDE_MOUNT_POINT, mountPoint);
554                         if (ret != 0)
555                                 ERROR(SINK, "vconf_set_str() failed with " << ret);
556                         else if (isEncrypted())
557                                 spawnUI();
558                 }
559                 break;
560         default:
561                 ERROR(SINK, "Unsupported card status: " << cardStatus);
562                 g_dbus_method_invocation_return_error(invocation,
563                                                       G_DBUS_ERROR,
564                                                       G_DBUS_ERROR_INVALID_ARGS,
565                                                       "Unsupported card status");
566                 return;
567         }
568         g_dbus_method_invocation_return_value(invocation, NULL);
569 }
570
571 int ExternalEncryptionServer::getStateInternal() const
572 {
573         char *value = ::vconf_get_str(VCONFKEY_SDE_CRYPTO_STATE);
574         if (value == NULL) {
575                 throw runtime::Exception("Failed to get vconf value.");
576         }
577
578         std::string valueStr(value);
579         free(value);
580
581         if (valueStr == "encrypted")
582                 return State::Encrypted;
583         else if (valueStr == "unencrypted")
584                 return State::Unencrypted;
585         else if (valueStr == "error_partially_encrypted" || valueStr == "error_partially_decrypted")
586                 return State::Corrupted;
587
588         return State::NotSupported;
589 }
590
591 EXTERNAL_ENGINE& ExternalEncryptionServer::getEngine() const
592 {
593         if (!engine) {
594                 char *tmp = ::vconf_get_str(VCONFKEY_SDE_MOUNT_POINT);
595
596                 static_assert(DEFAULT_EXTERNAL_PATH);
597
598                 std::string mountPoint(tmp ? tmp : DEFAULT_EXTERNAL_PATH);
599                 free(tmp);
600
601                 runtime::File f(mountPoint);
602                 mountPoint = f.readlink();
603
604                 engine.reset(new EXTERNAL_ENGINE(mountPoint,
605                                                  mountPoint,
606                                                  ProgressBar(VCONFKEY_SDE_ENCRYPT_PROGRESS)));
607
608         }
609         return *engine;
610 }
611
612 } // namespace ode