Commit 8de743ac authored by Maarten de Waard's avatar Maarten de Waard 🤘🏻
Browse files

Merge branch 'master' into '6-delete-luks-key-endpoint'

# Conflicts:
#   src/cryptops-api.c
parents cba1ebe6 babda843
......@@ -9,30 +9,34 @@ SRCDIR = src
OBJDIR = obj
BINDIR = bin
DEPS=$(wildcard $(SRCDIR)/*/*.c) $(wildcard $(SRCDIR)/*.c)
SOURCES := $(SRCDIR)/$(TARGET).c
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(BINDIR)/$(TARGET): $(BINDIR)
$(BINDIR):
mkdir -p $(BINDIR)
# Make binary linking .o files and libraries
$(BINDIR)/$(TARGET): $(OBJECTS)
@$(LINKER) $(OBJECTS) $(LFLAGS) -o $@
@echo "Linking complete."
$(OBJECTS): | $(OBJDIR)
$(OBJDIR):
# Compile an object for a c file in SRCDIR
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(DEPS)
mkdir -p $(OBJDIR)
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
@$(CC) $(CFLAGS) -c $< -o $@
@echo "Compiled "$<" successfully."
# Remove intermediate files
.PHONY: clean
clean:
@rm -f $(OBJECTS)
@rm -rf $(OBJDIR)
@echo "Cleanup complete."
# Remove all compiled files
.PHONY: remove
remove: clean
@rm -f $(BINDIR)/$(TARGET)
@rm -rf $(BINDIR)
@echo "Executable removed."
......@@ -33,7 +33,7 @@ int callback_encryption_get(const struct _u_request * request,
FILESYSTEM_TYPE);
if (r != 0)
{
printf("mounting root device failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR, "mounting root device failed: return code %d", r);
return send_simple_response(response, 500, "error",
"mounting root device failed");
}
......
......@@ -57,9 +57,10 @@ int callback_encryption_init_post(const struct _u_request * request,
FILESYSTEM_TYPE);
if (r != 0)
{
printf("mounting root device failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"mounting root device failed: return code %d", r);
return send_simple_response(response, 500, "error",
"mounting root device failed");
"mounting root device failed");
}
// Determine if the files on the unencrypted device would fit in memory.
......@@ -73,27 +74,32 @@ 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");
y_log_message(Y_LOG_LEVEL_DEBUG,
"copying existing root device contents to memory");
char * command = NULL;
asprintf(&command, "rsync -a %s/ %s", UNENCRYPTED_TMP_MOUNTPOINT,
TMP_LOCATION);
r = system(command);
if (r != 0)
{
printf("copying root device contents into memory failed"
": return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"copying root device contents into memory failed: return code %d",
r);
return send_simple_response(response, 500, "error",
"copying root device contents into memory failed");
}
// Unmount unencrypted device.
printf("unmounting unencrypted device at %s\n", UNENCRYPTED_TMP_MOUNTPOINT);
y_log_message(Y_LOG_LEVEL_ERROR,
"unmounting unencrypted device at %s",
UNENCRYPTED_TMP_MOUNTPOINT);
r = umount(UNENCRYPTED_TMP_MOUNTPOINT);
if (r != 0)
{
printf("unmounting encrypted device failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"unmounting encrypted device failed: return code %d", r);
return send_simple_response(response, 500, "error",
"unmounting unencrypted device failed");
"unmounting unencrypted device failed");
}
// Check whether the authorized_keys file exists on root device.
......@@ -103,188 +109,208 @@ int callback_encryption_init_post(const struct _u_request * request,
struct stat st = {0};
if (stat(authorized_keys_path, &st) == -1)
{
printf("authorized_keys not found on root device at %s\n",
y_log_message(Y_LOG_LEVEL_ERROR,
"authorized_keys not found on root device at %s",
authorized_keys_path);
return send_simple_response(response, 500, "error",
"authorized_keys not found on root device");
"authorized_keys not found on root device");
}
// Re-partition device.
printf("repartitioning device %s\n", ROOT_DEVICE);
y_log_message(Y_LOG_LEVEL_ERROR, "repartitioning device %s", ROOT_DEVICE);
command = NULL;
asprintf(&command, "sgdisk -a 8192 -n 1:0:48M -N 2 %s", ROOT_DEVICE);
r = system(command);
if (r != 0)
{
printf("partitioning root device failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"partitioning root device failed: return code %d", r);
return send_simple_response(response, 500, "error",
"partitioning root device failed");
"partitioning root device failed");
}
// Inform kernel of partitioning changes.
printf("running partprobe\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "running partprobe");
command = NULL;
asprintf(&command, "partprobe");
r = system(command);
if (r != 0)
{
printf("partprobe: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR, "partprobe failed: return code %d",
r);
return send_simple_response(response, 500, "error",
"partprobe failed");
"partprobe failed");
}
// Sleep for a little while.
// This seems necessary for the newly created partitions to appear as
// devices.
printf("waiting a bit...\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "waiting a bit...");
sleep(2);
// Create filesystem on the info partition.
printf("creating filesystem on info partition\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "creating filesystem on info partition");
command = NULL;
asprintf(&command, "mkfs -t %s %s", FILESYSTEM_TYPE,
INFO_PARTITION_DEVICE);
printf("command: %s\n", command);
y_log_message(Y_LOG_LEVEL_DEBUG, "command: %s", command);
r = system(command);
if (r != 0)
{
printf("creating filesystem failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"creating filesystem failed: return code %d", r);
return send_simple_response(response, 500, "error",
"creating filesystem inside encrypted container failed");
"creating filesystem inside encrypted container failed");
}
// Mount the info partition.
printf("mounting info partition\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "mounting info partition");
r = temporary_mount(INFO_PARTITION_DEVICE, INFO_TMP_MOUNTPOINT,
FILESYSTEM_TYPE);
if (r != 0)
{
printf("mounting encrypted device failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"mounting encrypted device failed: return code %d", r);
return send_simple_response(response, 500, "error",
"mounting encrypted root device failed");
"mounting encrypted root device failed");
}
// Create some directories in the info partition.
printf("creating directories in info partition\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "creating directories in info partition");
command = NULL;
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)
{
printf("creating directories failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"creating directories failed: return code %d", r);
return send_simple_response(response, 500, "error",
"creating directories in info partition failed");
"creating directories in info partition failed");
}
// Copy authorized_keys file to the info partition.
printf("copying authorized_keys to info partition\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "copying authorized_keys to info partition");
command = NULL;
asprintf(&command, "cp %s %s%s",
AUTHORIZED_KEYS_PATH, INFO_TMP_MOUNTPOINT, AUTHORIZED_KEYS_PATH);
r = system(command);
if (r != 0)
{
printf("copying authorized_keys failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"copying authorized_keys failed: return code %d", r);
return send_simple_response(response, 500, "error",
"copying authorized_keys failed");
"copying authorized_keys failed");
}
// Copy dropbear ssh host keys from the initrd to the info partition.
printf("copying dropbear ssh host keys\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "copying dropbear ssh host keys");
command = NULL;
asprintf(&command, "cp /etc/dropbear/* %s%s/", INFO_TMP_MOUNTPOINT,
SSH_HOST_KEY_DIR);
r = system(command);
if (r != 0)
{
printf("copying dropbear ssh host keys failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_DEBUG,
"copying dropbear ssh host keys failed: return code %d", r);
return send_simple_response(response, 500, "error",
"copying dropbear ssh host keys failed");
"copying dropbear ssh host keys failed");
}
// Unmount info partition.
printf("unmounting info partition at %s\n", INFO_TMP_MOUNTPOINT);
y_log_message(Y_LOG_LEVEL_DEBUG,
"unmounting info partition at %s", INFO_TMP_MOUNTPOINT);
r = umount(INFO_TMP_MOUNTPOINT);
if (r != 0)
{
printf("unmounting failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"unmounting failed: return code %d", r);
return send_simple_response(response, 500, "error",
"unmounting configuration partition failed");
"unmounting configuration partition failed");
}
// Initialise encrypted container on data partition.
printf("creating encrypted container at %s\n", DATA_PARTITION_DEVICE);
y_log_message(Y_LOG_LEVEL_DEBUG,
"creating encrypted container at %s", DATA_PARTITION_DEVICE);
r = create_encrypted_device(DATA_PARTITION_DEVICE, password);
if (r != 0)
{
printf("creating encrypted container failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"creating encrypted container failed: return code %d", r);
return send_simple_response(response, 500, "error",
"creating encryption container failed");
"creating encryption container failed");
}
// Unlock the new container.
printf("unlocking encrypted device\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "unlocking encrypted device");
r = encryption_unlock(DATA_PARTITION_DEVICE, MAPPED_DEVICE_NAME,
password);
if (r != 0)
{
printf("unlocking encrypted container failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"unlocking encrypted container failed: return code %d", r);
return send_simple_response(response, 500, "error",
"unlocking new encryption container failed");
"unlocking new encryption container failed");
}
// Create filesystem in the new container.
printf("creating filesystem in new container\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "creating filesystem in new container");
command = NULL;
asprintf(&command, "mkfs -t %s %s", FILESYSTEM_TYPE, MAPPED_DEVICE_PATH);
r = system(command);
if (r != 0)
{
printf("creating filesystem failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"creating filesystem failed: return code %d", r);
return send_simple_response(response, 500, "error",
"creating filesystem inside encrypted container failed");
"creating filesystem inside encrypted container failed");
}
// Mount the unlocked container.
printf("mounting new filesystem\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "mounting new filesystem");
r = temporary_mount(MAPPED_DEVICE_PATH, DATA_TMP_MOUNTPOINT,
FILESYSTEM_TYPE);
if (r != 0)
{
printf("mounting encrypted device failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"mounting encrypted device failed: return code %d", r);
return send_simple_response(response, 500, "error",
"mounting encrypted root device failed");
"mounting encrypted root device failed");
}
// Copy device contents from temporary filesystem to encrypted container.
printf("copying root device contents from memory\n");
y_log_message(Y_LOG_LEVEL_DEBUG,
"copying root device contents from memory");
command = NULL;
asprintf(&command, "rsync -a %s/ %s", TMP_LOCATION, DATA_TMP_MOUNTPOINT);
r = system(command);
if (r != 0)
{
printf("copying from memory to encrypted device failed:"
" return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"copying from memory to encrypted device failed: return code %d",
r);
return send_simple_response(response, 500, "error",
"copying root device contents from memory failed");
"copying root device contents from memory failed");
}
// Unmount filesystem on encrypted data partition.
printf("unmounting encrypted device at %s\n", DATA_TMP_MOUNTPOINT);
y_log_message(Y_LOG_LEVEL_DEBUG,
"unmounting encrypted device at %s", DATA_TMP_MOUNTPOINT);
r = umount(DATA_TMP_MOUNTPOINT);
if (r != 0)
{
printf("unmounting encrypted device failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"unmounting encrypted device failed: return code %d", r);
return send_simple_response(response, 500, "error",
"unmounting encrypted device failed");
"unmounting encrypted device failed");
}
// Lock the container.
printf("locking encrypted device\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "locking encrypted device");
r = encryption_lock(MAPPED_DEVICE_NAME);
if (r != 0)
{
printf("locking encrypted container failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"locking encrypted container failed: return code %d", r);
return send_simple_response(response, 500, "error",
"locking container failed");
}
......
......@@ -23,7 +23,8 @@ int callback_encryption_keys_get(const struct _u_request * request,
}
if (r != 0)
{
printf("container_initialise failed with status %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"container_initialise failed with status %d", r);
return send_simple_response(response, 500, "error",
"initialising encrypted container failed");
}
......
/**
* Callback function to change a luks encryption password.
* Combined handler for adding and changing luks encryption passwords.
* @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
* @param[in] is_post this is a post request (true) or a put (false)
* @return internal status code
*/
int callback_encryption_keys_put(const struct _u_request * request,
struct _u_response * response, void * user_data)
int encryption_keys_change(const struct _u_request * request,
struct _u_response * response, bool is_post)
{
int r;
......@@ -31,20 +31,30 @@ int callback_encryption_keys_put(const struct _u_request * request,
"missing new password");
}
// Read keyslot from request URI.
const char * keyslot_string = u_map_get(request->map_url, "slot");
if (keyslot_string == NULL)
int keyslot;
// Posting a new password, put it in the first available slot.
if (is_post)
{
return send_simple_response(response, 400, "error",
"missing url parameter `slot`");
keyslot = CRYPT_ANY_SLOT;
}
int keyslot;
r = parse_int(keyslot_string, &keyslot);
if (r != 0)
// Changing an existing password, so read the slot from the url.
else
{
printf("invalid url parameter `slot`: %s\n", keyslot_string);
return send_simple_response(response, 400, "error",
"invalid url parameter `slot`");
// Read keyslot from request URI.
const char * keyslot_string = u_map_get(request->map_url, "slot");
if (keyslot_string == NULL)
{
return send_simple_response(response, 400, "error",
"missing url parameter `slot`");
}
r = parse_int(keyslot_string, &keyslot);
if (r != 0)
{
y_log_message(Y_LOG_LEVEL_WARNING,
"invalid url parameter `slot`: %s", keyslot_string);
return send_simple_response(response, 400, "error",
"invalid url parameter `slot`");
}
}
// Initialise encrypted container.
......@@ -56,14 +66,24 @@ int callback_encryption_keys_put(const struct _u_request * request,
}
if (r != 0)
{
printf("container_initialise failed with status %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"container_initialise failed with status %d", r);
return send_simple_response(response, 500, "error",
"initialising encrypted container failed");
}
// Add encryption password.
r = crypt_keyslot_change_by_passphrase(cd, keyslot, keyslot,
password, strlen(password), new_password, strlen(new_password));
if (is_post)
{
// Add encryption password.
r = crypt_keyslot_add_by_passphrase(cd, keyslot,
password, strlen(password), new_password, strlen(new_password));
}
else
{
// Change encryption password.
r = crypt_keyslot_change_by_passphrase(cd, keyslot, keyslot,
password, strlen(password), new_password, strlen(new_password));
}
if (r == -1)
{
......@@ -75,7 +95,16 @@ int callback_encryption_keys_put(const struct _u_request * request,
if (r < 0)
{
// Something else went wrong.
printf("crypt_keyslot_add_by_passphrase failed with status %d\n", r);
if (is_post)
{
y_log_message(Y_LOG_LEVEL_ERROR,
"crypt_keyslot_add_by_passphrase failed with status %d", r);
}
else
{
y_log_message(Y_LOG_LEVEL_ERROR,
"crypt_keyslot_change_by_passphrase failed with status %d", r);
}
return send_simple_response(response, 500, "error",
"error changing password");
}
......@@ -83,3 +112,28 @@ int callback_encryption_keys_put(const struct _u_request * request,
// If we reach this point, apparently everything went well.
return send_simple_response(response, 200, "status", "ok");
}
/**
* Callback function to add a luks encryption password.
* @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_keys_post(const struct _u_request * request,
struct _u_response * response, void * user_data)
{
return encryption_keys_change(request, response, true);
}
/**
* Callback function to change a luks encryption password.
* @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_keys_put(const struct _u_request * request,
struct _u_response * response, void * user_data)
{
return encryption_keys_change(request, response, false);
}
......@@ -46,7 +46,7 @@ int callback_encryption_remove_post(const struct _u_request * request,
}
// Unlock the container.
printf("unlocking encrypted device\n");
y_log_message(Y_LOG_LEVEL_INFO, "unlocking encrypted device");
r = encryption_unlock(DATA_PARTITION_DEVICE, MAPPED_DEVICE_NAME,
password);
if (r == -1)
......@@ -57,9 +57,10 @@ int callback_encryption_remove_post(const struct _u_request * request,
}
if (r != 0)
{
printf("unlocking encrypted container failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"unlocking encrypted container failed: return code %d", r);
return send_simple_response(response, 500, "error",
"unlocking encrypted container failed");
"unlocking encrypted container failed");
}
// Mount the filesystem on the encrypted data partition.
......@@ -67,9 +68,10 @@ int callback_encryption_remove_post(const struct _u_request * request,
FILESYSTEM_TYPE);
if (r != 0)
{
printf("mounting root device failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"mounting root device failed: return code %d", r);
return send_simple_response(response, 500, "error",
"mounting root device failed");
"mounting root device failed");
}
// Determine the filesystem usage of the encrypted data partition.
......@@ -78,111 +80,127 @@ int callback_encryption_remove_post(const struct _u_request * request,
{
// Projected memory usage is really high, so abort.
return send_simple_response(response, 500, "error",
"device too large");
"device too large");
}
// Copy device contents to temporary filesystem.
printf("copying existing root device contents to memory\n");
y_log_message(Y_LOG_LEVEL_DEBUG,
"copying existing root device contents to memory");
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);
y_log_message(Y_LOG_LEVEL_ERROR,
"copying root device contents into memory failed: return code %d",
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);
y_log_message(Y_LOG_LEVEL_DEBUG,
"unmounting encrypted device at %s", DATA_TMP_MOUNTPOINT);
r = umount(DATA_TMP_MOUNTPOINT);
if (r != 0)
{
printf("unmounting encrypted device failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"unmounting encrypted device failed: return code %d", r);
return send_simple_response(response, 500, "error",
"unmounting encrypted device failed");
"unmounting encrypted device failed");
}
// Lock the container.
printf("locking encrypted device\n");
y_log_message(Y_LOG_LEVEL_DEBUG, "locking encrypted device");
r = encryption_lock(MAPPED_DEVICE_NAME);
if (r != 0)
{
printf("locking encrypted container failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"locking encrypted container failed: return code %d", r);
return send_simple_response(response, 500, "error",
"locking encrypted container failed");
"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);
y_log_message(Y_LOG_LEVEL_DEBUG,
"unmounting info partition at %s", INFO_MOUNTPOINT);
r = umount(INFO_MOUNTPOINT);
if (r != 0)
{
printf("unmounting info partition failed: return code %d\n", r);
y_log_message(Y_LOG_LEVEL_ERROR,
"unmounting info partition failed: return code %d", 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);
y_log_message(Y_LOG_LEVEL_DEBUG,