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

Merge branch '10-remove-encryption-endpoint' into 'master'

Add endpoint for removing encryption

Closes #10

See merge request !11
parents 447668e7 ffd32426
No related branches found
No related tags found
No related merge requests found
......@@ -29,7 +29,7 @@ int callback_encryption_get(const struct _u_request * request,
can_encrypt_nullable = &can_encrypt;
// Mount the filesystem on the unencrypted device.
int r = temporary_mount(ROOT_DEVICE, UNENCRYPTED_MOUNTPOINT,
int r = temporary_mount(ROOT_DEVICE, UNENCRYPTED_TMP_MOUNTPOINT,
FILESYSTEM_TYPE);
if (r != 0)
{
......@@ -37,9 +37,9 @@ int callback_encryption_get(const struct _u_request * request,
return send_simple_response(response, 500, "error",
"mounting root device failed");
}
bool fits = filesystem_fits_in_memory(UNENCRYPTED_MOUNTPOINT,
bool fits = filesystem_fits_in_memory(UNENCRYPTED_TMP_MOUNTPOINT,
MEMORY_USAGE);
umount(UNENCRYPTED_MOUNTPOINT);
umount(UNENCRYPTED_TMP_MOUNTPOINT);
if (! fits)
{
can_encrypt = false;
......
......@@ -53,7 +53,7 @@ int callback_encryption_init_post(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)
{
......@@ -62,8 +62,8 @@ int callback_encryption_init_post(const struct _u_request * request,
"mounting root device failed");
}
// Determine the filesystem usage of the device to be encrypted.
bool fits = filesystem_fits_in_memory(UNENCRYPTED_MOUNTPOINT,
// Determine if the files on the unencrypted device would fit in memory.
bool fits = filesystem_fits_in_memory(UNENCRYPTED_TMP_MOUNTPOINT,
MEMORY_USAGE);
if (! fits)
{
......@@ -75,7 +75,8 @@ int callback_encryption_init_post(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)
{
......@@ -86,8 +87,8 @@ int callback_encryption_init_post(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);
......@@ -153,7 +154,7 @@ int callback_encryption_init_post(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)
{
......@@ -165,8 +166,8 @@ int callback_encryption_init_post(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)
{
......@@ -179,7 +180,7 @@ int callback_encryption_init_post(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)
{
......@@ -191,7 +192,7 @@ int callback_encryption_init_post(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)
......@@ -202,8 +203,8 @@ int callback_encryption_init_post(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);
......@@ -246,7 +247,7 @@ int callback_encryption_init_post(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)
{
......@@ -258,7 +259,7 @@ int callback_encryption_init_post(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)
{
......@@ -269,8 +270,8 @@ int callback_encryption_init_post(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_post(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.
bool fits = filesystem_fits_in_memory(DATA_TMP_MOUNTPOINT, MEMORY_USAGE);
if (! fits)
{
// 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_get.c>
#include <api/encryption_init_post.c>
#include <api/encryption_remove_post.c>
#include <api/encryption_unlock_post.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_post, &reboot);
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX,
"/encryption/remove",
0, &callback_encryption_remove_post, &reboot);
ulfius_add_endpoint_by_val(&instance, "POST", PREFIX,
"/encryption/unlock",
0, &callback_encryption_unlock_post, NULL);
......@@ -97,6 +101,10 @@ int main(int argc, char ** argv)
y_log_message(Y_LOG_LEVEL_DEBUG, "Error starting framework");
}
y_log_message(Y_LOG_LEVEL_DEBUG, "End framework");
// Give request handlers that have called for the stop a chance to
// send their response to the client.
sleep(1);
y_close_logs();
......
// Web interface settings.
#define PREFIX "/cryptops/v0"
#define PORT 8000
#define BIND_ADDRESS "127.0.0.1"
// Device paths.
#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
// Filesystem parameters.
#define FILESYSTEM_TYPE "xfs"
// Mountpoint paths.
#define INFO_MOUNTPOINT "/conf/persistent"
// Resource usage.
#define MEMORY_USAGE 0.9
#define UNENCRYPTED_MOUNTPOINT "/tmp/mnt-plain"
#define INFO_MOUNTPOINT "/tmp/mnt-info"
#define DATA_MOUNTPOINT "/tmp/mnt-data"
// Temporary mountpoints.
#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
// Ssh configuration file locations.
#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