Skip to content
Snippets Groups Projects
Commit 44b55a0e authored by Maarten de Waard's avatar Maarten de Waard :angel:
Browse files

Merge branch 'master' into 8-add-ssh-key-endpoint

parents 921ac0e6 447668e7
No related branches found
No related tags found
No related merge requests found
/**
* Callback function that shows the current encryption status (encrypted or
* unencrypted).
*
* Example output:
* {"encryption-status":"encrypted"}
*
* @param[in] request incoming HTTP request
* @param[out] response HTTP response to the request
* @param[in] user_data extra data to pass between main thread and callbacks
* @return internal status code
*/
int callback_encryption_get(const struct _u_request * request,
struct _u_response * response, void * user_data)
{
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))
{
encrypted = true;
}
else
{
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);
umount(UNENCRYPTED_MOUNTPOINT);
if (! fits)
{
can_encrypt = false;
json_array_append_new(messages, json_string(
"existing files do not fit in memory"));
}
}
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;
}
......@@ -27,7 +27,7 @@
* @param[in] user_data extra data to pass between handler and main thread
* @return internal status code
*/
int callback_encryption_init(const struct _u_request * request,
int callback_encryption_init_post(const struct _u_request * request,
struct _u_response * response, void * user_data)
{
bool * reboot = (bool *)user_data;
......@@ -43,7 +43,9 @@ int callback_encryption_init(const struct _u_request * request,
}
// Check if the device isn't already encrypted.
if (is_encrypted_device(ROOT_DEVICE))
// Actually we check if the device has any partitions; if so, we're not in
// the expected situation of an unpartitioned unencrypted root device.
if (path_exists(INFO_PARTITION_DEVICE))
{
// The device is already encrypted; we don't want to encrypt it again.
return send_simple_response(response, 500, "error",
......@@ -61,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);
if (! fits)
{
// Projected memory usage is really high, so abort.
return send_simple_response(response, 500, "error",
......
......@@ -6,7 +6,7 @@
* @param[in] user_data extra data to pass between main thread and callbacks
* @return internal status code
*/
int callback_encryption_unlock(const struct _u_request * request,
int callback_encryption_unlock_post(const struct _u_request * request,
struct _u_response * response, void * user_data)
{
json_t * json_input = ulfius_get_json_body_request(request, NULL);
......
......@@ -131,6 +131,34 @@ 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.
* @return Whether the filesystem seems to fit into memory.
*/
bool filesystem_fits_in_memory(const char * path, double safety_margin)
{
// 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.
printf("Determining file system usage failed (size: %lu)\n", size);
return false;
}
printf("file system 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);
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.
......@@ -206,3 +234,14 @@ int add_ssh_command(char ** ssh_key_with_command, const char * ssh_key)
else
return asprintf(ssh_key_with_command, "%s", ssh_key);
}
/*
* Check if the given path already exists (as a (special) file or directory).
* @param path Path to test.
* @return `true` if path exists, `false` otherwise.
*/
bool path_exists(const char * path)
{
struct stat st = {0};
return (stat(path, &st) == 0);
}
......@@ -6,8 +6,9 @@
#include <auxiliary.c>
#include <encryption_functions.c>
#include <api/default.c>
#include <api/encryption_init.c>
#include <api/encryption_unlock.c>
#include <api/encryption_get.c>
#include <api/encryption_init_post.c>
#include <api/encryption_unlock_post.c>
#include <api/encryption_keys_put.c>
#include <api/ssh_keys_get.c>
#include <api/ssh_keys_post.c>
......@@ -38,12 +39,15 @@ int main(int argc, char ** argv)
// Add api endpoints.
bool reboot = false;
ulfius_add_endpoint_by_val(&instance, "GET" , PREFIX,
"/encryption",
0, &callback_encryption_get, NULL);
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX,
"/encryption/init",
0, &callback_encryption_init, &reboot);
0, &callback_encryption_init_post, &reboot);
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX,
"/encryption/unlock",
0, &callback_encryption_unlock, NULL);
0, &callback_encryption_unlock_post, NULL);
ulfius_add_endpoint_by_val(&instance, "PUT" , PREFIX,
"/encryption/keys/:slot",
0, &callback_encryption_keys_put, NULL);
......
......@@ -11,8 +11,7 @@ static int container_initialise(struct crypt_device ** cd, const char * path,
const bool debug)
{
// Check if the device exists.
struct stat st = {0};
if (stat(path, &st) == -1)
if (! path_exists(path))
{
printf("device does not exist: %s.\n", path);
return 1;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment