diff --git a/share/restrict_command.sed b/share/restrict_command.sed new file mode 100644 index 0000000000000000000000000000000000000000..9b8500c3d10f8bbbdc8aeb9585276bcb3f88b5fb --- /dev/null +++ b/share/restrict_command.sed @@ -0,0 +1,3 @@ +# Usage: echo "blablabla bia" | sed -rf etc/restrictCommand.sed +/^#/d +s@^(agent-forwarding|cert-authority|command="[^"]*"|environment="[^"]*"|from="[^"]*"|no-agent-forwarding|no-port-forwarding|no-pty|no-user-rc|no-X11-forwarding|permitopen="[^"]*"|port-forwarding|principals="[^"]*"|pty|restrict|tunnel="[^"]*"|user-rc|X11-forwarding|,)* *@command="cd / \&\& /usr/bin/cryptops-client" @ diff --git a/src/api/ssh_keys_post.c b/src/api/ssh_keys_post.c new file mode 100644 index 0000000000000000000000000000000000000000..f579496f900e716989d64c6b534d8c5cf02b016e --- /dev/null +++ b/src/api/ssh_keys_post.c @@ -0,0 +1,68 @@ +/** + * Callback function that appends an SSH key tot the list of keys authorised for + * access to the initrd. + * + * Example output: + * {"ssh-keys":{"1":"ssh-rsa AAAAB3... example@example.com", + * "2":"ssh-rsa AAAAB3...","5":"command=\"/usr/bin/cryptops-client\" ssh-rsa + * AAAAB3... cryptops-test@greenhost"}} + * + * The indices correspond to line numbers of the authorized_keys file. + * Missing indices (like 3 and 4 in the example) arise from empty lines in the + * file; those are creted when keys are deleted. + * + * @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_ssh_keys_post(const struct _u_request * request, + struct _u_response * response, void * user_data) +{ + // Open file with append mode + FILE * authorized_keys = fopen(AUTHORIZED_KEYS_PATH, "a"); + + // Check if that succeeded. + if (authorized_keys == NULL) + { + printf("Could not open authorized_keys file for writing\n"); + return send_simple_response(response, 500, "error", + "error reading authorized_keys"); + } + + // Read in json request body. + json_t * json_input = ulfius_get_json_body_request(request, NULL); + + // Read SSH key from request. + const char * ssh_key; + ssh_key = json_string_value(json_object_get(json_input, "ssh-key")); + if (ssh_key == NULL) + { + return send_simple_response(response, 400, "error", "missing ssh-key"); + } + + // Call cat to append the command correctly: + char * command = NULL; + asprintf(&command, "echo %s | sed -rf %s", ssh_key, RESTRICT_COMMAND_PATH); + FILE *sed_output = popen(command, "r"); + + if (!sed_output) + { + return send_simple_response(response, 500, "error", "Internal error while handling ssh-key"); + } + + // Get the output from sed + ssh_key = read_from_file(sed_output); + + if(!ssh_key) + { + return send_simple_response(response, 500, "error", "Internal error while converting ssh-key"); + } + + // Write SSH key to file + fprintf(authorized_keys, ssh_key); + fclose(authorized_keys); + + return send_simple_response(response, 200, "status", "ok"); +} + diff --git a/src/auxiliary.c b/src/auxiliary.c index 797839db2a39488633f758a290907354d1e09241..1a0b9b6495226ce7c4062ad18cbf96cd551aa02f 100644 --- a/src/auxiliary.c +++ b/src/auxiliary.c @@ -18,30 +18,37 @@ void stop_server() */ char * read_file(const char * filename) { - char * buffer = NULL; - long length; - FILE * file = fopen(filename, "rb"); if (filename != NULL) { - if (file) - { - fseek(file, 0, SEEK_END); - length = ftell(file); - fseek(file, 0, SEEK_SET); - buffer = o_malloc(length + 1); - if (buffer) - { - fread(buffer, 1, length, file); - } - buffer[length] = '\0'; - fclose (file); - } - return buffer; + FILE * file = fopen(filename, "rb"); + return read_from_file(file); } - else + return NULL; +} + +/** + * Read the contents of an already opened file into a string + * @param file The file as opened by fopen with "rb" + * @return Contents of the file + */ +char * read_from_file(const FILE file) +{ + long length; + char * buffer = NULL; + if (file) { - return NULL; + fseek(file, 0, SEEK_END); + length = ftell(file); + fseek(file, 0, SEEK_SET); + buffer = o_malloc(length + 1); + if (buffer) + { + fread(buffer, 1, length, file); + } + buffer[length] = '\0'; + fclose (file); } + return buffer; } /** diff --git a/src/cryptops-api.c b/src/cryptops-api.c index 5b1e1024755a607e5f0002c7ee9a78c5672fd38d..faaf253e4f8d3df0db6f20b0a6eaba4e17726663 100644 --- a/src/cryptops-api.c +++ b/src/cryptops-api.c @@ -10,6 +10,7 @@ #include <api/encryption_unlock.c> #include <api/encryption_keys_put.c> #include <api/ssh_keys_get.c> +#include <api/ssh_keys_post.c> int main(int argc, char ** argv) { @@ -49,6 +50,9 @@ int main(int argc, char ** argv) ulfius_add_endpoint_by_val(&instance, "GET" , PREFIX, "/ssh/keys", 0, &callback_ssh_keys_get, NULL); + ulfius_add_endpoint_by_val(&instance, "POST" , PREFIX, + "/ssh/keys", + 0, &callback_ssh_keys_post, NULL); // Add default endpoint. ulfius_set_default_endpoint(&instance, &callback_default, NULL); @@ -76,7 +80,7 @@ int main(int argc, char ** argv) y_log_message(Y_LOG_LEVEL_DEBUG, "Start %sframework on port %d", ((argc == 4 && strcmp("-secure", argv[1]) == 0) ? "secure " : ""), instance.port); - + // Wait for signal from fifo to quit. y_init_logs("cryptops-api", Y_LOG_MODE_CONSOLE, Y_LOG_LEVEL_DEBUG, NULL, "Waiting for fifo signal to quit"); @@ -93,9 +97,9 @@ 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"); - + y_close_logs(); - + ulfius_stop_framework(&instance); ulfius_clean_instance(&instance); diff --git a/src/includes/settings.h b/src/includes/settings.h index 8352c51513477907acf8d2148e30fb6807203cbf..d9e98d50da311245f853a5b329ccc342c1fa9c34 100644 --- a/src/includes/settings.h +++ b/src/includes/settings.h @@ -14,4 +14,7 @@ #define TMP_LOCATION "/tmp/" MAPPED_DEVICE_NAME #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" +// FIXME: This means that we need to add copying this script to the initrd to +// the deploy script +#define RESTRICT_COMMAND_PATH "/etc/cryptops-api/restrict_command.sed"