Skip to content
Snippets Groups Projects
Commit aaaa11eb authored by Arie Peterson's avatar Arie Peterson
Browse files

Add endpoint for removing encryption

parent 20c5c6f8
No related branches found
No related tags found
No related merge requests found
......@@ -53,7 +53,7 @@ int callback_encryption_init(const struct _u_request * request,
}
// Mount the filesystem on the unencrypted device.
r = temporary_mount(ROOT_DEVICE, UNENCRYPTED_MOUNTPOINT,
r = temporary_mount(ROOT_DEVICE, UNENCRYPTED_TMP_MOUNTPOINT,
FILESYSTEM_TYPE);
if (r != 0)
{
......@@ -63,7 +63,7 @@ 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);
unsigned long size = filesystem_usage(UNENCRYPTED_TMP_MOUNTPOINT);
if (size < 0)
{
// Something went wrong in determining the filesystem usage.
......@@ -88,7 +88,8 @@ int callback_encryption_init(const struct _u_request * request,
// Copy device contents to temporary filesystem.
printf("copying existing root device contents to memory\n");
char * command = NULL;
asprintf(&command, "rsync -a %s/ %s", UNENCRYPTED_MOUNTPOINT, TMP_LOCATION);
asprintf(&command, "rsync -a %s/ %s", UNENCRYPTED_TMP_MOUNTPOINT,
TMP_LOCATION);
r = system(command);
if(r != 0)
{
......@@ -99,8 +100,8 @@ int callback_encryption_init(const struct _u_request * request,
}
// Unmount unencrypted device.
printf("unmounting unencrypted device at %s\n", UNENCRYPTED_MOUNTPOINT);
r = umount(UNENCRYPTED_MOUNTPOINT);
printf("unmounting unencrypted device at %s\n", UNENCRYPTED_TMP_MOUNTPOINT);
r = umount(UNENCRYPTED_TMP_MOUNTPOINT);
if (r != 0)
{
printf("unmounting encrypted device failed: return code %d\n", r);
......@@ -166,7 +167,7 @@ int callback_encryption_init(const struct _u_request * request,
// Mount the info partition.
printf("mounting info partition\n");
r = temporary_mount(INFO_PARTITION_DEVICE, INFO_MOUNTPOINT,
r = temporary_mount(INFO_PARTITION_DEVICE, INFO_TMP_MOUNTPOINT,
FILESYSTEM_TYPE);
if (r != 0)
{
......@@ -178,8 +179,8 @@ int callback_encryption_init(const struct _u_request * request,
// Create some directories in the info partition.
printf("creating directories in info partition\n");
command = NULL;
asprintf(&command, "mkdir -p %s%s %s%s", INFO_MOUNTPOINT,
AUTHORIZED_KEYS_DIR, INFO_MOUNTPOINT, SSH_HOST_KEY_DIR);
asprintf(&command, "mkdir -p %s%s %s%s", INFO_TMP_MOUNTPOINT,
AUTHORIZED_KEYS_DIR, INFO_TMP_MOUNTPOINT, SSH_HOST_KEY_DIR);
r = system(command);
if (r != 0)
{
......@@ -192,7 +193,7 @@ int callback_encryption_init(const struct _u_request * request,
printf("copying authorized_keys to info partition\n");
command = NULL;
asprintf(&command, "cp %s %s%s",
AUTHORIZED_KEYS_PATH, INFO_MOUNTPOINT, AUTHORIZED_KEYS_PATH);
AUTHORIZED_KEYS_PATH, INFO_TMP_MOUNTPOINT, AUTHORIZED_KEYS_PATH);
r = system(command);
if (r != 0)
{
......@@ -204,7 +205,7 @@ int callback_encryption_init(const struct _u_request * request,
// Copy dropbear ssh host keys from the initrd to the info partition.
printf("copying dropbear ssh host keys\n");
command = NULL;
asprintf(&command, "cp /etc/dropbear/* %s%s/", INFO_MOUNTPOINT,
asprintf(&command, "cp /etc/dropbear/* %s%s/", INFO_TMP_MOUNTPOINT,
SSH_HOST_KEY_DIR);
r = system(command);
if (r != 0)
......@@ -215,8 +216,8 @@ int callback_encryption_init(const struct _u_request * request,
}
// Unmount info partition.
printf("unmounting info partition at %s\n", INFO_MOUNTPOINT);
r = umount(INFO_MOUNTPOINT);
printf("unmounting info partition at %s\n", INFO_TMP_MOUNTPOINT);
r = umount(INFO_TMP_MOUNTPOINT);
if (r != 0)
{
printf("unmounting failed: return code %d\n", r);
......@@ -259,7 +260,7 @@ int callback_encryption_init(const struct _u_request * request,
// Mount the unlocked container.
printf("mounting new filesystem\n");
r = temporary_mount(MAPPED_DEVICE_PATH, DATA_MOUNTPOINT,
r = temporary_mount(MAPPED_DEVICE_PATH, DATA_TMP_MOUNTPOINT,
FILESYSTEM_TYPE);
if (r != 0)
{
......@@ -271,7 +272,7 @@ int callback_encryption_init(const struct _u_request * request,
// Copy device contents from temporary filesystem to encrypted container.
printf("copying root device contents from memory\n");
command = NULL;
asprintf(&command, "rsync -a %s/ %s", TMP_LOCATION, DATA_MOUNTPOINT);
asprintf(&command, "rsync -a %s/ %s", TMP_LOCATION, DATA_TMP_MOUNTPOINT);
r = system(command);
if (r != 0)
{
......@@ -282,8 +283,8 @@ int callback_encryption_init(const struct _u_request * request,
}
// Unmount filesystem on encrypted data partition.
printf("unmounting encrypted device at %s\n", DATA_MOUNTPOINT);
r = umount(DATA_MOUNTPOINT);
printf("unmounting encrypted device at %s\n", DATA_TMP_MOUNTPOINT);
r = umount(DATA_TMP_MOUNTPOINT);
if (r != 0)
{
printf("unmounting encrypted device failed: return code %d\n", r);
......
/**
* Callback function for permanently decrypting an encrypted device.
* It proceeds as follows:
* 1. read the encryption password from the request body;
* 2. check if the device isn't already encrypted;
* 3. unlock the encrypted container;
* 4. mount the filesystem on the encrypted device;
* 5. check if there is enough available memory to contain all files currently
* stored on the device;
* 6. copy device contents to temporary filesystem;
* 7. unmount encrypted device;
* 8. lock the container;
* 9. unmount info partition;
* 10. remove all partitions from the device;
* 11. create a new filesystem on the unencrypted device;
* 12. mount the new filesystem;
* 13. copy device contents from memory to encrypted container;
* 14. unmount the new filesystem;
* 15. reboot.
* @param[in] request incoming HTTP request
* @param[out] response HTTP response to the request
* @param[in] user_data extra data to pass between handler and main thread
* @return internal status code
*/
int callback_encryption_remove(const struct _u_request * request,
struct _u_response * response, void * user_data)
{
bool * reboot = (bool *)user_data;
int r;
// Read the encryption password from the request body.
json_t * json_input = ulfius_get_json_body_request(request, NULL);
const char * password = password = json_string_value(
json_object_get(json_input, "password"));
if (password == NULL)
{
return send_simple_response(response, 400, "error", "missing password");
}
// Check if the device is encrypted.
if (! is_encrypted_device(DATA_PARTITION_DEVICE))
{
// The device is not encrypted, so this command does not make sense.
return send_simple_response(response, 400, "error",
"not encrypted");
}
// Unlock the container.
printf("unlocking encrypted device\n");
r = encryption_unlock(DATA_PARTITION_DEVICE, MAPPED_DEVICE_NAME,
password);
if (r == -1)
{
// The return code -1 signals that the password is wrong.
return send_simple_response(response, 403, "error",
"incorrect password");
}
if (r != 0)
{
printf("unlocking encrypted container failed: return code %d\n", r);
return send_simple_response(response, 500, "error",
"unlocking encrypted container failed");
}
// Mount the filesystem on the encrypted data partition.
r = temporary_mount(MAPPED_DEVICE_PATH, DATA_TMP_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");
}
// Determine the filesystem usage of the encrypted data partition.
unsigned long size = filesystem_usage(DATA_TMP_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)
{
// Projected memory usage is really high, so abort.
return send_simple_response(response, 500, "error",
"device too large");
}
// Copy device contents to temporary filesystem.
printf("copying existing root device contents to memory\n");
char * command = NULL;
asprintf(&command, "rsync -a %s/ %s", DATA_TMP_MOUNTPOINT, TMP_LOCATION);
r = system(command);
if(r != 0)
{
printf("copying root device contents into memory failed"
": return code %d\n", r);
return send_simple_response(response, 500, "error",
"copying root device contents into memory failed");
}
// Unmount encrypted data partition.
printf("unmounting encrypted device at %s\n", DATA_TMP_MOUNTPOINT);
r = umount(DATA_TMP_MOUNTPOINT);
if (r != 0)
{
printf("unmounting encrypted device failed: return code %d\n", r);
return send_simple_response(response, 500, "error",
"unmounting encrypted device failed");
}
// Lock the container.
printf("locking encrypted device\n");
r = encryption_lock(MAPPED_DEVICE_NAME);
if (r != 0)
{
printf("locking encrypted container failed: return code %d\n", r);
return send_simple_response(response, 500, "error",
"locking encrypted container failed");
}
// Unmount info partition.
// We didn't mount this in cryptops-api, but it was mounted by the initrd
// scripts for use by dropbear.
printf("unmounting info partition at %s\n", INFO_MOUNTPOINT);
r = umount(INFO_MOUNTPOINT);
if (r != 0)
{
printf("unmounting info partition failed: return code %d\n", r);
return send_simple_response(response, 500, "error",
"unmounting info partition failed");
}
// Remove all partitions from the device.
printf("removing partitions from device %s\n", ROOT_DEVICE);
command = NULL;
asprintf(&command, "sgdisk -Z %s", ROOT_DEVICE);
r = system(command);
if (r != 0)
{
printf("removing partitions failed: return code %d\n", r);
return send_simple_response(response, 500, "error",
"removing partitions failed");
}
// Create filesystem on the unencrypted device.
printf("creating filesystem on unencrypted device\n");
command = NULL;
asprintf(&command, "mkfs -t %s %s", FILESYSTEM_TYPE, ROOT_DEVICE);
r = system(command);
if (r != 0)
{
printf("creating filesystem failed: return code %d\n", r);
return send_simple_response(response, 500, "error",
"creating filesystem on unencrypted device failed");
}
// Mount the new filesystem.
printf("mounting new filesystem\n");
r = temporary_mount(ROOT_DEVICE, UNENCRYPTED_TMP_MOUNTPOINT,
FILESYSTEM_TYPE);
if (r != 0)
{
printf("mounting unencrypted device failed: return code %d\n", r);
return send_simple_response(response, 500, "error",
"mounting unencrypted root device failed");
}
// Copy device contents from memory to the unencrypted device.
printf("copying root device contents from memory\n");
command = NULL;
asprintf(&command, "rsync -a %s/ %s",
TMP_LOCATION, UNENCRYPTED_TMP_MOUNTPOINT);
r = system(command);
if (r != 0)
{
printf("copying from memory to unencrypted device failed:"
" return code %d\n", r);
return send_simple_response(response, 500, "error",
"copying root device contents from memory failed");
}
// Unmount filesystem on unencrypted device.
printf("unmounting unencrypted device at %s\n", UNENCRYPTED_TMP_MOUNTPOINT);
r = umount(UNENCRYPTED_TMP_MOUNTPOINT);
if (r != 0)
{
printf("unmounting unencrypted device failed: return code %d\n", r);
return send_simple_response(response, 500, "error",
"unmounting unencrypted device failed");
}
// Record that we want to reboot the machine.
*reboot = true;
r = send_simple_response(response, 200, "status", "ok");
stop_server();
return r;
}
......@@ -8,6 +8,7 @@
#include <api/default.c>
#include <api/encryption.c>
#include <api/encryption_init.c>
#include <api/encryption_remove.c>
#include <api/encryption_unlock.c>
#include <api/encryption_keys_put.c>
#include <api/ssh_keys_get.c>
......@@ -44,6 +45,9 @@ int main(int argc, char ** argv)
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX,
"/encryption/init",
0, &callback_encryption_init, &reboot);
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX,
"/encryption/remove",
0, &callback_encryption_remove, &reboot);
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX,
"/encryption/unlock",
0, &callback_encryption_unlock, NULL);
......
#define PREFIX "/cryptops/v0"
#define PORT 8000
#define BIND_ADDRESS "127.0.0.1"
#define ROOT_DEVICE "/dev/xvda"
#define INFO_PARTITION_DEVICE ROOT_DEVICE "1"
#define DATA_PARTITION_DEVICE ROOT_DEVICE "2"
#define MAPPED_DEVICE_NAME "xvda1_crypt"
#define MAPPED_DEVICE_PATH "/dev/mapper/" MAPPED_DEVICE_NAME
#define FILESYSTEM_TYPE "xfs"
#define MEMORY_USAGE 0.9
#define UNENCRYPTED_MOUNTPOINT "/tmp/mnt-plain"
#define INFO_MOUNTPOINT "/tmp/mnt-info"
#define DATA_MOUNTPOINT "/tmp/mnt-data"
#define UNENCRYPTED_TMP_MOUNTPOINT "/tmp/mnt-plain"
#define INFO_TMP_MOUNTPOINT "/tmp/mnt-info"
#define DATA_TMP_MOUNTPOINT "/tmp/mnt-data"
#define TMP_LOCATION "/tmp/" MAPPED_DEVICE_NAME
#define INFO_MOUNTPOINT "/conf/persistent"
#define AUTHORIZED_KEYS_DIR "/root/.ssh"
#define AUTHORIZED_KEYS_PATH AUTHORIZED_KEYS_DIR "/authorized_keys"
#define SSH_HOST_KEY_DIR "/dropbear"
\ No newline at end of file
#define SSH_HOST_KEY_DIR "/dropbear"
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