Use dbus for event notification
[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 <unistd.h>
17 #include <sys/mount.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20
21 #include <climits>
22 #include <cstdlib>
23
24 #include <fstream>
25 #include <sstream>
26
27 #include <vconf.h>
28 #include <tzplatform_config.h>
29 #include <klay/file-user.h>
30 #include <klay/filesystem.h>
31
32 #include "misc.h"
33 #include "logger.h"
34 #include "progress-bar.h"
35 #include "rmi/common.h"
36 #include "file-footer.h"
37
38 #include "external-encryption.h"
39
40
41 namespace ode {
42
43 namespace {
44
45 const char *PRIVILEGE_PLATFORM = "http://tizen.org/privilege/internal/default/platform";
46 const char *SDCARD_UI_ACTIVATOR_PATH = "/run/ode-booting-with-encrypted-sdcard";
47
48 void spawnUI()
49 {
50         INFO(SINK, "Launching SD card password popup.");
51
52         runtime::File act(SDCARD_UI_ACTIVATOR_PATH);
53         try {
54                 act.create(O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // 644
55         } catch (const runtime::Exception& e) {
56                 ERROR(SINK, "Opening sdcard UI activator (" << SDCARD_UI_ACTIVATOR_PATH << ") failed: " <<
57                                         e.what());
58         }
59 }
60
61
62 bool isEncrypted()
63 {
64         char *cryptoState = ::vconf_get_str(VCONFKEY_SDE_CRYPTO_STATE);
65         if (cryptoState == NULL)
66                 return false;
67
68         bool encrypted = (strcmp(cryptoState, "encrypted") == 0);
69         free(cryptoState);
70         return encrypted;
71 }
72
73 /*
74  * Introspection data for the exported object
75  *
76  * Test:
77  * dbus-send --system --type=method_call --print-reply --dest=org.tizen.ode
78  * /org/tizen/ode/ExternalEncryption org.freedesktop.DBus.Introspectable.Introspect
79  */
80 const gchar introspectionXml[] =
81         "<node>"
82         "  <interface name='org.tizen.ode.ExternalEncryption'>"
83         "    <method name='UpdateCardStatus'>"
84         "      <arg type='s' name='mountpoint' direction='in'/>"
85         "      <arg type='i' name='status' direction='in'/>"
86         "    </method>"
87         "  </interface>"
88         "</node>";
89
90 void dbusMethodCall(GDBusConnection *,
91                     const gchar *sender,
92                     const gchar *object,
93                     const gchar *interface,
94                     const gchar *method,
95                     GVariant *params,
96                     GDBusMethodInvocation *invocation,
97                     gpointer user_data)
98 {
99         DEBUG(SINK, "dbusMethodCall sender: " << sender << ", object: " << object << ", interface: " <<
100                     interface << ", method: " << method);
101
102         static_cast<ExternalEncryptionServer*>(user_data)->dbusMethodCall(method, params, invocation);
103 }
104
105 unsigned int getOptions()
106 {
107         unsigned int result = 0;
108         int value;
109
110         value = 0;
111         ::vconf_get_bool(VCONFKEY_SDE_EXCLUDE_MEDIAFILE, &value);
112         if (value) {
113                 result |= ExternalEncryption::Option::OnlyNewFile;
114         }
115
116         value = 0;
117         ::vconf_get_bool(VCONFKEY_SDE_ENCRYPT_NEWFILE, &value);
118         if (value) {
119                 result |= ExternalEncryption::Option::ExceptForMediaFile;
120         }
121
122         return result;
123 }
124
125 void setOptions(unsigned int options)
126 {
127         bool value;
128
129         if (options & ExternalEncryption::Option::OnlyNewFile) {
130                 value = true;
131         } else {
132                 value = false;
133         }
134         ::vconf_set_bool(VCONFKEY_SDE_EXCLUDE_MEDIAFILE, value);
135
136         if (options & ExternalEncryption::Option::ExceptForMediaFile) {
137                 value = true;
138         } else {
139                 value = false;
140         }
141         ::vconf_set_bool(VCONFKEY_SDE_ENCRYPT_NEWFILE, value);
142 }
143
144 } // namespace
145
146 ExternalEncryptionServer::ExternalEncryptionServer(ServerContext &srv,
147                                                                                                    KeyServer& key) :
148         server(srv),
149         keyServer(key)
150 {
151         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::setMountPassword)(std::string));
152         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::mount)());
153         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::umount)());
154         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::encrypt)(std::string, unsigned int));
155         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::decrypt)(std::string));
156         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::recovery)());
157         server.expose(this, "", (int)(ExternalEncryptionServer::isPasswordInitialized)());
158         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::initPassword)(std::string));
159         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::cleanPassword)(std::string));
160         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::changePassword)(std::string, std::string));
161         server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::verifyPassword)(std::string));
162         server.expose(this, "", (int)(ExternalEncryptionServer::getState)());
163         server.expose(this, "", (unsigned int)(ExternalEncryptionServer::getSupportedOptions)());
164         server.expose(this, "", (std::string)(ExternalEncryptionServer::getDevicePath)());
165
166         server.createNotification("ExternalEncryptionServer::mount");
167
168 }
169
170 ExternalEncryptionServer::~ExternalEncryptionServer()
171 {
172 }
173
174 int ExternalEncryptionServer::setMountPassword(const std::string& password)
175 {
176         RequestLifetime rl(server);
177
178         return keyServer.get(getEngine().getSource(), password, mountKey);
179 }
180
181 int ExternalEncryptionServer::mount()
182 {
183         RequestLifetime rl(server);
184
185         if (mountKey.empty()) {
186                 ERROR(SINK, "You need to call set_mount_password() first.");
187                 return error::NoData;
188         }
189
190         BinaryData key = mountKey;
191         mountKey.clear();
192
193         if (getStateInternal() != State::Encrypted) {
194                 ERROR(SINK, "Cannot mount, SD card's state incorrect.");
195                 return error::NoSuchDevice;
196         }
197
198         auto& engine = getEngine();
199         if (engine.isMounted()) {
200                 INFO(SINK, "SD card already mounted.");
201                 return error::None;
202         }
203
204         INFO(SINK, "Mounting external storage.");
205         try {
206                 engine.mount(key, getOptions());
207         } catch (runtime::Exception &e) {
208                 ERROR(SINK, "Failed to mount: " + std::string(e.what()));
209                 return error::Unknown;
210         }
211
212         server.notify("ExternalEncryptionServer::mount");
213
214         return error::None;
215 }
216
217 int ExternalEncryptionServer::umount()
218 {
219         RequestLifetime rl(server);
220
221         if (getStateInternal() != State::Encrypted) {
222                 ERROR(SINK, "Cannot umount, SD card's state incorrect.");
223                 return error::NoSuchDevice;
224         }
225
226         auto& engine = getEngine();
227         if (!engine.isMounted()) {
228                 INFO(SINK, "SD card already umounted.");
229                 return error::None;
230         }
231
232         INFO(SINK, "Closing all applications using external storage.");
233         killDependentApplications(engine.getDestination());
234
235         INFO(SINK, "Umounting external storage.");
236         try {
237                 engine.umount();
238         } catch (runtime::Exception &e) {
239                 ERROR(SINK, "Failed to umount: " + std::string(e.what()));
240                 return error::Unknown;
241         }
242
243         return error::None;
244 }
245
246 int ExternalEncryptionServer::encrypt(const std::string &password, unsigned int options)
247 {
248         RequestLifetime rl(server);
249
250         if (getStateInternal() != State::Unencrypted) {
251                 INFO(SINK, "Cannot encrypt, SD card's state incorrect.");
252                 return error::NoSuchDevice;
253         }
254
255         BinaryData masterKey;
256         int ret = keyServer.get(getEngine().getSource(), password, masterKey);
257         if (ret != error::None)
258                 return ret;
259
260         auto encryptWorker = [masterKey, options, this](RequestLifetime&& rl) {
261                 try {
262                         auto& engine = getEngine();
263
264                         INFO(SINK, "Closing all applications using external storage.");
265                         killDependentApplications(engine.getDestination());
266
267                         INFO(SINK, "Encryption started.");
268                         engine.encrypt(masterKey, options);
269                         setOptions(options & engine.getSupportedOptions());
270
271                         INFO(SINK, "Encryption completed.");
272                         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "encrypted");
273                         server.notify("ExternalEncryptionServer::mount");
274
275                         INFO(SINK, "Syncing disk.");
276                         sync();
277                 } catch (runtime::Exception &e) {
278                         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "error_partially_encrypted");
279                         ERROR(SINK, "Encryption failed: " + std::string(e.what()));
280                 }
281         };
282
283         std::thread asyncWork(encryptWorker, std::move(rl));
284         asyncWork.detach();
285
286         return error::None;
287 }
288
289 int ExternalEncryptionServer::decrypt(const std::string &password)
290 {
291         RequestLifetime rl(server);
292
293         if (getStateInternal() != State::Encrypted) {
294                 ERROR(SINK, "Cannot decrypt, SD card's state incorrect.");
295                 return error::NoSuchDevice;
296         }
297
298         BinaryData masterKey;
299         int ret = keyServer.get(getEngine().getSource(), password, masterKey);
300         if (ret != error::None)
301                 return ret;
302
303         auto decryptWorker = [masterKey, this](RequestLifetime&& rl) {
304                 try {
305                         auto& engine = getEngine();
306
307                         INFO(SINK, "Closing all applications using external storage.");
308                         killDependentApplications(engine.getDestination());
309
310                         INFO(SINK, "Umounting external storage.");
311                         while (1) {
312                                 try {
313                                         engine.umount();
314                                         break;
315                                 } catch (runtime::Exception &e) {
316                                         killDependentApplications(engine.getDestination());
317                                 }
318                         }
319
320                         INFO(SINK, "Decryption started.");
321                         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "error_partially_decrypted");
322                         engine.decrypt(masterKey, getOptions());
323
324                         INFO(SINK, "Decryption completed.");
325                         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "unencrypted");
326
327                         INFO(SINK, "Syncing disk.");
328                         sync();
329                 } catch (runtime::Exception &e) {
330                         ERROR(SINK, "Decryption failed: " + std::string(e.what()));
331                 }
332         };
333
334         std::thread asyncWork(decryptWorker, std::move(rl));
335         asyncWork.detach();
336
337         return error::None;
338 }
339
340 int ExternalEncryptionServer::recovery()
341 {
342         RequestLifetime rl(server);
343
344         if (getStateInternal() == State::Unencrypted) {
345                 return error::NoSuchDevice;
346         }
347
348         auto& engine = getEngine();
349         for (runtime::DirectoryIterator iter(engine.getSource()), end;
350                         iter != end; ++iter) {
351                 iter->remove(true);
352         }
353
354         keyServer.removePassword(engine.getSource());
355         ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "unencrypted");
356
357         return error::None;
358 }
359
360 int ExternalEncryptionServer::isPasswordInitialized()
361 {
362         return keyServer.isInitialized(getEngine().getSource());
363 }
364
365 int ExternalEncryptionServer::initPassword(const std::string& password)
366 {
367         return keyServer.init(getEngine().getSource(), password, Key::DEFAULT_256BIT);
368 }
369
370 int ExternalEncryptionServer::cleanPassword(const std::string& password)
371 {
372         return keyServer.remove(getEngine().getSource(), password);
373 }
374
375 int ExternalEncryptionServer::changePassword(const std::string &oldPassword,
376                                                                                          const std::string &newPassword)
377 {
378         return keyServer.changePassword(getEngine().getSource(), oldPassword, newPassword);
379 }
380
381 int ExternalEncryptionServer::verifyPassword(const std::string& password)
382 {
383         return keyServer.verifyPassword(getEngine().getSource(), password);
384 }
385
386 int ExternalEncryptionServer::getState()
387 {
388         RequestLifetime rl(server);
389
390         return getStateInternal();
391 }
392
393 unsigned int ExternalEncryptionServer::getSupportedOptions()
394 {
395         RequestLifetime rl(server);
396
397         return getEngine().getSupportedOptions();
398 }
399
400 std::string ExternalEncryptionServer::getDevicePath() const
401 {
402         RequestLifetime rl(server);
403
404         return getEngine().getSource();
405 }
406
407 void ExternalEncryptionServer::dbusRegisterObject(GDBusConnection *connection)
408 {
409         GError *err = NULL;
410         GDBusNodeInfo *dbusIntrospectionData = g_dbus_node_info_new_for_xml(introspectionXml, &err);
411         if (dbusIntrospectionData == NULL) {
412                 ERROR(SINK, "Dbus introspection data creation failed: " << err->message);
413                 return;
414         }
415
416         const GDBusInterfaceVTable interfaceVtable =
417         {
418                 ode::dbusMethodCall,
419                 NULL,
420                 NULL
421         };
422
423         /*
424          * Test:
425          * dbus-send --system --type=method_call --print-reply --dest=org.tizen.ode
426          * /org/tizen/ode/ExternalEncryption org.tizen.ode.ExternalEncryption.UpdateCardStatus
427          * string:"/media/SDCardA1" int32:1
428          */
429         guint registrationId = g_dbus_connection_register_object(connection,
430                                                                  "/org/tizen/ode/ExternalEncryption",
431                                                                  dbusIntrospectionData->interfaces[0],
432                                                                  &interfaceVtable,
433                                                                  this,
434                                                                  NULL,
435                                                                  &err);
436         if (registrationId == 0)
437                 ERROR(SINK, "Dbus object registration failed: " << err->message);
438
439         g_dbus_node_info_unref(dbusIntrospectionData);
440 }
441
442 void ExternalEncryptionServer::dbusMethodCall(const gchar *,
443                                               GVariant *params,
444                                               GDBusMethodInvocation *invocation)
445 {
446         RequestLifetime rl(server);
447
448         const gchar *mountPoint;
449         gint32 cardStatus;
450
451         g_variant_get(params, "(&si)", &mountPoint, &cardStatus);
452
453         switch (cardStatus) {
454         case 0:
455                 DEBUG(SINK, "Card unmounted " << mountPoint);
456                 {
457                         int ret = ::vconf_unset(VCONFKEY_SDE_MOUNT_POINT);
458                         if (ret != 0)
459                                 ERROR(SINK, "vconf_set_str() failed with " << ret);
460
461                         engine.reset();
462                 }
463                 break;
464         case 1:
465                 DEBUG(SINK, "Card mounted " << mountPoint);
466                 {
467                         int ret = ::vconf_set_str(VCONFKEY_SDE_MOUNT_POINT, mountPoint);
468                         if (ret != 0)
469                                 ERROR(SINK, "vconf_set_str() failed with " << ret);
470                         else if (isEncrypted())
471                                 spawnUI();
472                 }
473                 break;
474         default:
475                 ERROR(SINK, "Unsupported card status: " << cardStatus);
476                 g_dbus_method_invocation_return_error(invocation,
477                                                       G_DBUS_ERROR,
478                                                       G_DBUS_ERROR_INVALID_ARGS,
479                                                       "Unsupported card status");
480                 return;
481         }
482         g_dbus_method_invocation_return_value(invocation, NULL);
483 }
484
485 int ExternalEncryptionServer::getStateInternal() const
486 {
487         char *value = ::vconf_get_str(VCONFKEY_SDE_CRYPTO_STATE);
488         if (value == NULL) {
489                 throw runtime::Exception("Failed to get vconf value.");
490         }
491
492         std::string valueStr(value);
493         free(value);
494
495         if (valueStr == "encrypted")
496                 return State::Encrypted;
497         else if (valueStr == "unencrypted")
498                 return State::Unencrypted;
499         else if (valueStr == "error_partially_encrypted" || valueStr == "error_partially_decrypted")
500                 return State::Corrupted;
501
502         return State::NotSupported;
503 }
504
505 EXTERNAL_ENGINE& ExternalEncryptionServer::getEngine() const
506 {
507         if (!engine) {
508                 char *tmp = ::vconf_get_str(VCONFKEY_SDE_MOUNT_POINT);
509
510                 if (tmp == NULL) {
511                         ERROR(SINK, "Sd card not mounted");
512                         throw runtime::Exception("Sd card not mounted");
513                 }
514
515                 std::string mountPoint(tmp);
516                 free(tmp);
517
518                 char *realMountPoint = ::realpath(mountPoint.c_str(), NULL);
519                 if (realMountPoint == NULL) {
520                         ERROR(SINK, "Failed to resolve mountpoint.");
521                         throw runtime::Exception("Failed to resolve mountpoint.");
522                 }
523                 mountPoint.assign(realMountPoint);
524                 free(realMountPoint);
525
526                 engine.reset(new EXTERNAL_ENGINE(mountPoint,
527                                                  mountPoint,
528                                                  ProgressBar(VCONFKEY_SDE_ENCRYPT_PROGRESS)));
529
530         }
531         return *engine;
532 }
533
534 } // namespace ode