From bc8bc3a310e72289a316657537764bf02e6480f7 Mon Sep 17 00:00:00 2001 From: Arie Peterson <arie@greenhost.nl> Date: Wed, 12 Jul 2017 16:58:19 +0200 Subject: [PATCH] Extend encryption status to give more info In case the device is unencrypted, check whether encryption seems possible (depending on filesystem usage and available memory), and report that in the response. --- src/api/encryption.c | 47 ++++++++++++++++++++++++++++++++++----- src/api/encryption_init.c | 19 +++------------- src/auxiliary.c | 39 ++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 21 deletions(-) diff --git a/src/api/encryption.c b/src/api/encryption.c index e576c3d..0951f06 100644 --- a/src/api/encryption.c +++ b/src/api/encryption.c @@ -13,16 +13,53 @@ int callback_encryption(const struct _u_request * request, struct _u_response * response, void * user_data) { - char * encryption_status; + bool encrypted; + bool * can_encrypt_nullable = NULL; + bool can_encrypt = true; + json_t * messages = json_array(); + if (path_exists(DATA_PARTITION_DEVICE) && is_encrypted_device(DATA_PARTITION_DEVICE)) { - encryption_status = "encrypted"; + encrypted = true; } else { - encryption_status = "unencrypted"; + encrypted = false; + can_encrypt_nullable = &can_encrypt; + + // Mount the filesystem on the unencrypted device. + int r = temporary_mount(ROOT_DEVICE, UNENCRYPTED_MOUNTPOINT, + FILESYSTEM_TYPE); + if (r != 0) + { + printf("mounting root device failed: return code %d\n", r); + return send_simple_response(response, 500, "error", + "mounting root device failed"); + } + bool fits = filesystem_fits_in_memory(UNENCRYPTED_MOUNTPOINT, + MEMORY_USAGE, true); + umount(UNENCRYPTED_MOUNTPOINT); + if (! fits) + { + can_encrypt = false; + json_array_append_new(messages, json_string( + "existing files do not fit in memory")); + } } - return send_simple_response(response, 200, - "encryption-status", encryption_status); + + json_t * json_body = NULL; + json_body = json_object(); + + json_object_set_new(json_body, "encrypted", + encrypted ? json_true() : json_false()); + + json_object_set_new(json_body, "can-encrypt", + can_encrypt_nullable == NULL ? json_null() : + (can_encrypt ? json_true() : json_false())); + json_object_set_new(json_body, "messages", messages); + + ulfius_set_json_body_response(response, 200, json_body); + json_decref(json_body); + return U_CALLBACK_CONTINUE; } diff --git a/src/api/encryption_init.c b/src/api/encryption_init.c index f708cd0..92d1d0f 100644 --- a/src/api/encryption_init.c +++ b/src/api/encryption_init.c @@ -63,22 +63,9 @@ int callback_encryption_init(const struct _u_request * request, } // Determine the filesystem usage of the device to be encrypted. - unsigned long size = filesystem_usage(UNENCRYPTED_MOUNTPOINT); - if (size < 0) - { - // Something went wrong in determining the filesystem usage. - printf("determining filesystem usage failed: return code %lu\n", size); - return send_simple_response(response, 500, "error", - "determining filesystem usage failed"); - } - printf("root device usage: %lu bytes\n", size); - - // Determine the available memory. - unsigned long memory = available_memory(); - - double projected_usage = (double)size / (double)memory; - printf("projected memory usage: %.3f\n", projected_usage); - if (projected_usage > MEMORY_USAGE) + bool fits = filesystem_fits_in_memory(UNENCRYPTED_MOUNTPOINT, + MEMORY_USAGE, true); + if (! fits) { // Projected memory usage is really high, so abort. return send_simple_response(response, 500, "error", diff --git a/src/auxiliary.c b/src/auxiliary.c index 6b833d8..9773c09 100644 --- a/src/auxiliary.c +++ b/src/auxiliary.c @@ -111,6 +111,45 @@ unsigned long filesystem_usage(const char * path) return (s.f_blocks - s.f_bfree) * s.f_bsize; } +/** + * Check if the files on the given filesystem would fit into memory. + * @param path Path of the mounted filesystem. + * @param safety_margin Fraction (between zero and one) of free memory to + deem available for containing the files. + * @param debug Whether to print debug messages. + * @return Whether the filesystem seems to fit into memory. + */ +bool filesystem_fits_in_memory(const char * path, double safety_margin, + bool debug) +{ + // Determine the filesystem usage of the device to be encrypted. + unsigned long size = filesystem_usage(path); + if (size < 0) + { + // Something went wrong in determining the filesystem usage. + // Return false as a precaution. + if (debug) + { + printf("Determining file system usage failed (size: %lu)\n", size); + } + return false; + } + if (debug) + { + printf("file system usage: %lu bytes\n", size); + } + + // Determine the available memory. + unsigned long memory = available_memory(); + + double projected_usage = (double)size / (double)memory; + if (debug) + { + printf("projected memory usage: %.3f\n", projected_usage); + } + return (projected_usage <= safety_margin); +} + /** * Mount a filesystem; create the mount target if it doesn't exist. * @param device_path Path to the device to mount. -- GitLab