From ad028d558c2e4390c359eb070cb6bf896c9ed0eb Mon Sep 17 00:00:00 2001
From: Arie Peterson <arie@greenhost.nl>
Date: Wed, 14 Jun 2017 16:24:52 +0200
Subject: [PATCH] Reorganise and split sources

---
 Makefile                    |  34 +++-
 cryptops-api.c              | 336 ------------------------------------
 src/api/default.c           |  13 ++
 src/api/encryption_unlock.c |  47 +++++
 src/auxiliary.c             |  62 +++++++
 src/cryptops-api.c          |  81 +++++++++
 src/encryption_functions.c  |  83 +++++++++
 src/includes.h              |   9 +
 src/settings.h              |   4 +
 9 files changed, 325 insertions(+), 344 deletions(-)
 delete mode 100644 cryptops-api.c
 create mode 100644 src/api/default.c
 create mode 100644 src/api/encryption_unlock.c
 create mode 100644 src/auxiliary.c
 create mode 100644 src/cryptops-api.c
 create mode 100644 src/encryption_functions.c
 create mode 100644 src/includes.h
 create mode 100644 src/settings.h

diff --git a/Makefile b/Makefile
index b1377c9..fa3cc98 100644
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,32 @@
-TARGETS=cryptops-api
-CFLAGS=-O0 -g -Wall -D_GNU_SOURCE -Iincludes
-LDLIBS=-L./libraries -lcryptsetup -lc -lulfius -lyder -lorcania -ljansson
+TARGET=cryptops-api
+
+CFLAGS=-O0 -g -Wall -D_GNU_SOURCE -Iincludes -Isrc
+LFLAGS=-L./libraries -lcryptsetup -lc -lulfius -lyder -lorcania -ljansson
 CC=gcc
+LINKER=gcc
 
-all: $(TARGETS)
+SRCDIR   = src
+OBJDIR   = obj
+BINDIR   = bin
 
-cryptops-api: cryptops-api.o
-	$(CC) -o $@ $^ $(LDLIBS)
+SOURCES  := $(SRCDIR)/$(TARGET).c
+INCLUDES := $(wildcard $(SRCDIR)/*.h)
+OBJECTS  := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
 
-clean:
-	rm -f *.o *~ core $(TARGETS)
+$(BINDIR)/$(TARGET): $(OBJECTS)
+	@$(LINKER) $(OBJECTS) $(LFLAGS) -o $@
+	@echo "Linking complete."
+
+$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
+	@$(CC) $(CFLAGS) -c $< -o $@
+	@echo "Compiled "$<" successfully."
 
 .PHONY: clean
+clean:
+	@rm -f $(OBJECTS)
+	@echo "Cleanup complete."
+
+.PHONY: remove
+remove: clean
+	@rm -f $(BINDIR)/$(TARGET)
+	@echo "Executable removed."
diff --git a/cryptops-api.c b/cryptops-api.c
deleted file mode 100644
index e25c557..0000000
--- a/cryptops-api.c
+++ /dev/null
@@ -1,336 +0,0 @@
-#include <string.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#define U_DISABLE_CURL
-#define U_DISABLE_WEBSOCKET
-#include <ulfius.h>
-#include <jansson.h>
-#include <libcryptsetup.h>
-
-#define PORT 8537
-#define PREFIX "/cryptops/v0"
-#define CONTAINER_DEVICE "/dev/xvda1"
-#define MAPPED_DEVICE_NAME "xvda1_crypt"
-
-#define FIFO_PATH "/tmp/cryptops-api-stop"
-
-/**
- * helper functions declaration
- */
-char * read_file(const char * filename);
-void stop_server();
-int send_simple_response
-(
-    struct _u_response * response,
-    int http_status,
-    const char *field,
-    const char *value
-);
-
-/**
- * callback functions declaration
- */
-int callback_encryption_unlock
-(
-    const struct _u_request * request,
-    struct _u_response * response,
-    void * user_data
-);
-int callback_default
-(
-    const struct _u_request * request,
-    struct _u_response * response,
-    void * user_data
-);
-static int encryption_unlock
-(
-    const char *path,
-    const char *device_name,
-    const char *password
-);
-static int container_initialise
-(
-    struct crypt_device **cd,
-    const char *path
-);
-
-int main(int argc, char **argv)
-{
-    y_init_logs("cryptops-api", Y_LOG_MODE_CONSOLE, Y_LOG_LEVEL_DEBUG,
-        NULL, "Starting cryptops-api");
-
-    struct _u_instance instance;
-    if (ulfius_init_instance(&instance, PORT, NULL, NULL) != U_OK)
-    {
-        y_log_message(Y_LOG_LEVEL_ERROR, "Error ulfius_init_instance, abort");
-        return(1);
-    }
-
-    u_map_put(instance.default_headers, "Access-Control-Allow-Origin", "*");
-
-    // Maximum body size sent by the client is 1 Kb.
-    instance.max_post_body_size = 1024;
-
-    // Add api endpoints.
-    ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/encryption/unlock",
-        0, &callback_encryption_unlock, NULL);
-
-    // Add default endpoint.
-    ulfius_set_default_endpoint(&instance, &callback_default, NULL);
-
-    // Start the framework.
-    int ret;
-    if (argc == 4 && strcmp("-secure", argv[1]) == 0)
-    {
-        // If command-line options are -secure <key_file> <cert_file>,
-        // then listen for https connections.
-        char * key_pem = read_file(argv[2]), * cert_pem = read_file(argv[3]);
-        ret = ulfius_start_secure_framework(&instance, key_pem, cert_pem);
-        o_free(key_pem);
-        o_free(cert_pem);
-    }
-    else
-    {
-        // Listen for http connections.
-        ret = ulfius_start_framework(&instance);
-    }
-
-    if (ret == U_OK)
-    {
-        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");
-        int fifo = 0;
-        char buf[4];
-        char fifo_path[] = FIFO_PATH;
-        mkfifo(fifo_path, 0600);
-        fifo = open(fifo_path, O_RDONLY);
-        // This will block until the fifo is written to.
-        read(fifo, &buf, 4);
-    }
-    else
-    {
-        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);
-    
-    return 0;
-}
-
-/**
- * Callback function that uses the password passed in the request to open the
- * luks volume.
- */
-int callback_encryption_unlock
-(
-    const struct _u_request * request,
-    struct _u_response * response,
-    void * user_data
-)
-{
-    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");
-    }
-  
-    int unlock_status = encryption_unlock
-    (
-        CONTAINER_DEVICE,
-        MAPPED_DEVICE_NAME,
-        password
-    );
-  
-    if (unlock_status == -1)
-    {
-        // Experience learns that -1 is returned when the password is wrong.
-        return send_simple_response(response, 403, "error",
-           "incorrect password");
-    }
-  
-    if (unlock_status != 0)
-    {
-        // Something else went wrong with unlocking.
-        printf("encryption_unlock failed with status %d\n", unlock_status);
-        return send_simple_response(response, 500, "error",
-            "error during unlocking");
-    }
-  
-    // If we reach this point, apparently everything went well.
-    stop_server();
-    return send_simple_response(response, 200, "status", "ok");
-}
-
-/**
- * Default callback function called if no other endpoint matches.
- */
-int callback_default
-(
-    const struct _u_request * request,
-    struct _u_response * response,
-    void * user_data
-)
-{
-    ulfius_set_string_body_response(response, 404, "Unknown endpoint");
-    return U_CALLBACK_CONTINUE;
-}
-
-/**
- * Use a fifo to signal that we want to stop the api server.
- */
-void stop_server()
-{
-    printf("Stopping cryptops-api server...\n");
-    int fifo;
-    char fifo_path[] = FIFO_PATH;
-    fifo = open(fifo_path, O_WRONLY);
-    char * msg = "stop";
-    write(fifo, msg, strlen(msg) + 1);
-}
-
-/**
- * Read a file completely into a string.
- */
-char * read_file(const char * filename)
-{
-    char * buffer = NULL;
-    long length;
-    FILE * f = fopen(filename, "rb");
-    if (filename != NULL)
-    {
-        if (f)
-        {
-            fseek(f, 0, SEEK_END);
-            length = ftell (f);
-            fseek(f, 0, SEEK_SET);
-            buffer = o_malloc(length + 1);
-            if (buffer)
-            {
-                fread(buffer, 1, length, f);
-            }
-            buffer[length] = '\0';
-            fclose (f);
-        }
-        return buffer;
-    }
-    else
-    {
-        return NULL;
-    }
-}
-
-/**
- * Respond to the request with a simple json structure '{$field: $value}'.
- */
-int send_simple_response
-(
-    struct _u_response * response, /* response struct to use */
-    int http_status,               /* HTTP status code to return */
-    const char *field,             /* name of the json field to return */
-    const char *value              /* json value to return */
-)
-{
-    json_t * json_body = NULL;
-    json_body = json_object();
-    json_object_set_new(json_body, field, json_string(value));
-    ulfius_set_json_body_response(response, http_status, json_body);
-    json_decref(json_body);
-    return U_CALLBACK_CONTINUE;
-}
-
-/**
- * Use cryptsetup to unlock the luks container.
- * This will create `/dev/mapper/$device_name`.
- */
-static int encryption_unlock
-(
-    const char *path,        /* path to the encrypted container */
-    const char *device_name, /* name of the mapping */
-    const char *password     /* encryption password of the container */
-)
-{
-    // Let LUKS initialise the encrypted device.
-    struct crypt_device *cd;
-    int r = container_initialise(&cd, path);
-    if (r < 0)
-    {
-        printf("crypt_load() failed on device %s.\n",
-            crypt_get_device_name(cd));
-        crypt_free(cd);
-        return r;
-    }
-
-    // Device activation creates device-mapper devie mapping with namei
-    // device_name.
-    r = crypt_activate_by_passphrase
-    (
-        cd,                          /* crypt context */
-        device_name,                 /* device name to activate */
-        CRYPT_ANY_SLOT,              /* which slot use (ANY - try all) */
-        password, strlen(password),  /* passphrase */
-        CRYPT_ACTIVATE_READONLY      /* flags */
-    );
-    if (r < 0)
-    {
-        printf("Device %s activation failed.\n", device_name);
-        crypt_free(cd);
-        return r;
-    }
-
-    printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name);
-    printf("\tcipher used: %s\n", crypt_get_cipher(cd));
-    printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
-    printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));
-
-    crypt_free(cd);
-    return 0;
-}
-
-/**
- * Use cryptsetup to initialise the luks container.
- * It will not be opened (decrypted) yet, but it does check if the container
- * seems usable.
- */
-static int container_initialise
-(
-    struct crypt_device **cd, /* struct to store crypt device context */
-    const char *path          /* path to the encrypted container */
-)
-{
-    // Let LUKS initialise the encrypted device.
-    int r = crypt_init(cd, path);
-    if (r < 0)
-    {
-        printf("crypt_init() failed for %s.\n", path);
-        printf("status: %d.\n", r);
-        return r;
-    }
-
-    // Load the LUKS header from the block device into the crypt device context.
-    r = crypt_load
-    (
-        *cd,         /* crypt device context */
-        CRYPT_LUKS1, /* requested encryption type */
-        NULL         /* additional parameters (not used) */
-    );
-    if (r < 0)
-    {
-        printf("crypt_load() failed on device %s.\n",
-            crypt_get_device_name(*cd));
-    }
-
-    return r;
-}
diff --git a/src/api/default.c b/src/api/default.c
new file mode 100644
index 0000000..b581ffb
--- /dev/null
+++ b/src/api/default.c
@@ -0,0 +1,13 @@
+/**
+ * Default callback function called if no other endpoint matches.
+ */
+int callback_default
+(
+    const struct _u_request * request,
+    struct _u_response * response,
+    void * user_data
+)
+{
+    ulfius_set_string_body_response(response, 404, "Unknown endpoint");
+    return U_CALLBACK_CONTINUE;
+}
diff --git a/src/api/encryption_unlock.c b/src/api/encryption_unlock.c
new file mode 100644
index 0000000..1a57ef4
--- /dev/null
+++ b/src/api/encryption_unlock.c
@@ -0,0 +1,47 @@
+/**
+ * Callback function that uses the password passed in the request to open the
+ * luks volume.
+ */
+int callback_encryption_unlock
+(
+    const struct _u_request * request,
+    struct _u_response * response,
+    void * user_data
+)
+{
+    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");
+    }
+  
+    int unlock_status = encryption_unlock
+    (
+        CONTAINER_DEVICE,
+        MAPPED_DEVICE_NAME,
+        password
+    );
+  
+    if (unlock_status == -1)
+    {
+        // Experience learns that -1 is returned when the password is wrong.
+        return send_simple_response(response, 403, "error",
+           "incorrect password");
+    }
+  
+    if (unlock_status != 0)
+    {
+        // Something else went wrong with unlocking.
+        printf("encryption_unlock failed with status %d\n", unlock_status);
+        return send_simple_response(response, 500, "error",
+            "error during unlocking");
+    }
+  
+    // If we reach this point, apparently everything went well.
+    int r = send_simple_response(response, 200, "status", "ok");
+    stop_server();
+    return r;
+}
diff --git a/src/auxiliary.c b/src/auxiliary.c
new file mode 100644
index 0000000..613d070
--- /dev/null
+++ b/src/auxiliary.c
@@ -0,0 +1,62 @@
+/**
+ * Use a fifo to signal that we want to stop the api server.
+ */
+void stop_server()
+{
+    printf("Stopping cryptops-api server...\n");
+    int fifo;
+    char fifo_path[] = FIFO_PATH;
+    fifo = open(fifo_path, O_WRONLY);
+    char * msg = "stop";
+    write(fifo, msg, strlen(msg) + 1);
+}
+
+/**
+ * Read a file completely into a string.
+ */
+char * read_file(const char * filename)
+{
+    char * buffer = NULL;
+    long length;
+    FILE * f = fopen(filename, "rb");
+    if (filename != NULL)
+    {
+        if (f)
+        {
+            fseek(f, 0, SEEK_END);
+            length = ftell (f);
+            fseek(f, 0, SEEK_SET);
+            buffer = o_malloc(length + 1);
+            if (buffer)
+            {
+                fread(buffer, 1, length, f);
+            }
+            buffer[length] = '\0';
+            fclose (f);
+        }
+        return buffer;
+    }
+    else
+    {
+        return NULL;
+    }
+}
+
+/**
+ * Respond to the request with a simple json structure '{$field: $value}'.
+ */
+int send_simple_response
+(
+    struct _u_response * response, /* response struct to use */
+    int http_status,               /* HTTP status code to return */
+    const char *field,             /* name of the json field to return */
+    const char *value              /* json value to return */
+)
+{
+    json_t * json_body = NULL;
+    json_body = json_object();
+    json_object_set_new(json_body, field, json_string(value));
+    ulfius_set_json_body_response(response, http_status, json_body);
+    json_decref(json_body);
+    return U_CALLBACK_CONTINUE;
+}
diff --git a/src/cryptops-api.c b/src/cryptops-api.c
new file mode 100644
index 0000000..88e576c
--- /dev/null
+++ b/src/cryptops-api.c
@@ -0,0 +1,81 @@
+#include <includes.h>
+#include <settings.h>
+
+#define FIFO_PATH "/tmp/cryptops-api-stop"
+
+#include <auxiliary.c>
+#include <encryption_functions.c>
+#include <api/default.c>
+#include <api/encryption_unlock.c>
+
+int main(int argc, char **argv)
+{
+    y_init_logs("cryptops-api", Y_LOG_MODE_CONSOLE, Y_LOG_LEVEL_DEBUG,
+        NULL, "Starting cryptops-api");
+
+    struct _u_instance instance;
+    if (ulfius_init_instance(&instance, PORT, NULL, NULL) != U_OK)
+    {
+        y_log_message(Y_LOG_LEVEL_ERROR, "Error ulfius_init_instance, abort");
+        return(1);
+    }
+
+    u_map_put(instance.default_headers, "Access-Control-Allow-Origin", "*");
+
+    // Maximum body size sent by the client is 1 Kb.
+    instance.max_post_body_size = 1024;
+
+    // Add api endpoints.
+    ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/encryption/unlock",
+        0, &callback_encryption_unlock, NULL);
+
+    // Add default endpoint.
+    ulfius_set_default_endpoint(&instance, &callback_default, NULL);
+
+    // Start the framework.
+    int ret;
+    if (argc == 4 && strcmp("-secure", argv[1]) == 0)
+    {
+        // If command-line options are -secure <key_file> <cert_file>,
+        // then listen for https connections.
+        char * key_pem = read_file(argv[2]), * cert_pem = read_file(argv[3]);
+        ret = ulfius_start_secure_framework(&instance, key_pem, cert_pem);
+        o_free(key_pem);
+        o_free(cert_pem);
+    }
+    else
+    {
+        // Listen for http connections.
+        ret = ulfius_start_framework(&instance);
+    }
+
+    if (ret == U_OK)
+    {
+        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");
+        int fifo = 0;
+        char buf[4];
+        char fifo_path[] = FIFO_PATH;
+        mkfifo(fifo_path, 0600);
+        fifo = open(fifo_path, O_RDONLY);
+        // This will block until the fifo is written to.
+        read(fifo, &buf, 4);
+    }
+    else
+    {
+        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);
+    
+    return 0;
+}
diff --git a/src/encryption_functions.c b/src/encryption_functions.c
new file mode 100644
index 0000000..6b7dc4d
--- /dev/null
+++ b/src/encryption_functions.c
@@ -0,0 +1,83 @@
+/**
+ * Use cryptsetup to initialise the luks container.
+ * It will not be opened (decrypted) yet, but it does check if the container
+ * seems usable.
+ */
+static int container_initialise
+(
+    struct crypt_device **cd, /* struct to store crypt device context */
+    const char *path          /* path to the encrypted container */
+)
+{
+    // Let LUKS initialise the encrypted device.
+    int r = crypt_init(cd, path);
+    if (r < 0)
+    {
+        printf("crypt_init() failed for %s.\n", path);
+        printf("status: %d.\n", r);
+        return r;
+    }
+
+    // Load the LUKS header from the block device into the crypt device context.
+    r = crypt_load
+    (
+        *cd,         /* crypt device context */
+        CRYPT_LUKS1, /* requested encryption type */
+        NULL         /* additional parameters (not used) */
+    );
+    if (r < 0)
+    {
+        printf("crypt_load() failed on device %s.\n",
+            crypt_get_device_name(*cd));
+    }
+
+    return r;
+}
+
+/**
+ * Use cryptsetup to unlock the luks container.
+ * This will create `/dev/mapper/$device_name`.
+ */
+static int encryption_unlock
+(
+    const char *path,        /* path to the encrypted container */
+    const char *device_name, /* name of the mapping */
+    const char *password     /* encryption password of the container */
+)
+{
+    // Let LUKS initialise the encrypted device.
+    struct crypt_device *cd;
+    int r = container_initialise(&cd, path);
+    if (r < 0)
+    {
+        printf("crypt_load() failed on device %s.\n",
+            crypt_get_device_name(cd));
+        crypt_free(cd);
+        return r;
+    }
+
+    // Device activation creates device-mapper devie mapping with namei
+    // device_name.
+    r = crypt_activate_by_passphrase
+    (
+        cd,                          /* crypt context */
+        device_name,                 /* device name to activate */
+        CRYPT_ANY_SLOT,              /* which slot use (ANY - try all) */
+        password, strlen(password),  /* passphrase */
+        CRYPT_ACTIVATE_READONLY      /* flags */
+    );
+    if (r < 0)
+    {
+        printf("Device %s activation failed.\n", device_name);
+        crypt_free(cd);
+        return r;
+    }
+
+    printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name);
+    printf("\tcipher used: %s\n", crypt_get_cipher(cd));
+    printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
+    printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));
+
+    crypt_free(cd);
+    return 0;
+}
diff --git a/src/includes.h b/src/includes.h
new file mode 100644
index 0000000..910cd61
--- /dev/null
+++ b/src/includes.h
@@ -0,0 +1,9 @@
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define U_DISABLE_CURL
+#define U_DISABLE_WEBSOCKET
+#include <ulfius.h>
+#include <jansson.h>
+#include <libcryptsetup.h>
diff --git a/src/settings.h b/src/settings.h
new file mode 100644
index 0000000..10122d0
--- /dev/null
+++ b/src/settings.h
@@ -0,0 +1,4 @@
+#define PREFIX "/cryptops/v0"
+#define PORT 8000
+#define CONTAINER_DEVICE "/dev/xvda1"
+#define MAPPED_DEVICE_NAME "xvda1_crypt"
-- 
GitLab