It's time to start caring about the cipher selection parameters.
(Apologies for the memory leaks, but it is just a mount helper, after
all...)
Signed-off-by: Mike Halcrow <[EMAIL PROTECTED]>
---
diff --git a/src/include/decision_graph.h b/src/include/decision_graph.h
index 6385d07..d3bd29d 100644
--- a/src/include/decision_graph.h
+++ b/src/include/decision_graph.h
@@ -99,12 +99,20 @@ struct param_node {
#define PARAMETER_SET 0x00000080
#define ECRYPTFS_PARAM_FLAG_LOCK_MEM 0x00000100
#define ECRYPTFS_PARAM_FORCE_DISPLAY_NODES 0x00000200
+#define ECRYPTFS_DISPLAY_PRETTY_VALS 0x00000400
uint32_t flags;
int num_transitions;
-#define MAX_NUM_TRANSITIONS 8
+#define MAX_NUM_TRANSITIONS 64
struct transition_node tl[MAX_NUM_TRANSITIONS];
};
+struct prompt_elem;
+
+struct prompt_elem {
+ char *str;
+ struct prompt_elem *next;
+};
+
int add_transition_node_to_param_node(struct param_node *param_node,
struct transition_node *trans_node);
void ecryptfs_dump_param_node(FILE *file_stream,
diff --git a/src/include/ecryptfs.h b/src/include/ecryptfs.h
index b2a7de3..d0648d4 100644
--- a/src/include/ecryptfs.h
+++ b/src/include/ecryptfs.h
@@ -218,14 +218,6 @@ struct ecryptfs_daemon_info {
char socket_file_full_path[PATH_MAX];
};
-struct ecryptfs_cipher_elem {
- uint8_t loaded_cipher;
- char *kernel_name;
- char *user_name;
- uint32_t bytes;
- struct ecryptfs_cipher_elem *next;
-};
-
struct ecryptfs_netlink_message {
uint32_t index;
uint32_t data_len;
@@ -365,12 +357,6 @@ struct ecryptfs_ctx {
struct ecryptfs_name_val_pair *nvp_head;
};
-struct cipher_str_name_map_elem {
- char *kernel_name;
- char *user_name;
- int keysize_bytes;
-};
-
enum main_menu_enum {
MME_NULL,
MME_MOUNT_PASSPHRASE,
@@ -382,6 +368,39 @@ enum main_menu_enum {
struct val_node;
struct param_node;
+struct cipher_str_name_map_elem {
+ char *kernel_name;
+ char *user_name;
+ int keysize_bytes;
+};
+
+struct ecryptfs_cipher_elem;
+
+struct ecryptfs_cipher_elem {
+ uint8_t loaded_cipher;
+ char *kernel_name;
+ char *user_name;
+ uint32_t bytes;
+ struct ecryptfs_cipher_elem *next;
+};
+
+struct cipher_descriptor;
+
+struct cipher_descriptor {
+#define CIPHER_DESCRIPTOR_FLAG_LOADED 0x00000001
+ uint32_t flags;
+ char *crypto_api_name;
+ char *descriptive_name;
+ char *driver_name;
+ char *module_name;
+ uint32_t blocksize;
+ uint32_t min_keysize;
+ uint32_t max_keysize;
+ struct cipher_descriptor *next;
+};
+
+int ecryptfs_get_kernel_ciphers(struct cipher_descriptor *cd_head);
+int ecryptfs_get_module_ciphers(struct cipher_descriptor *cd_head);
int ecryptfs_get_version(uint32_t *version);
int ecryptfs_supports_passphrase(uint32_t version);
int ecryptfs_supports_pubkey(uint32_t version);
diff --git a/src/libecryptfs/cipher_list.c b/src/libecryptfs/cipher_list.c
index e142de2..83907ca 100644
--- a/src/libecryptfs/cipher_list.c
+++ b/src/libecryptfs/cipher_list.c
@@ -39,14 +39,18 @@
#include "../include/ecryptfs.h"
#define MAX_BUF_LEN 128
+#define MTAB_FULLPATH "/etc/mtab"
+/**
+ * Pulling ourselves up by the bootstraps...
+ */
static int get_proc_mount_point(char **proc_mount_point)
{
FILE *fp;
struct mntent *mntent;
int rc = 0;
- fp = fopen("/etc/mtab", "r");
+ fp = fopen(MTAB_FULLPATH, "r");
if (!fp) {
rc = -errno;
goto out;
@@ -308,3 +312,296 @@ int ecryptfs_free_cipher_list(struct ecryptfs_cipher_elem
cipher_list_head)
}
return 0;
}
+
+int ecryptfs_get_kernel_ciphers(struct cipher_descriptor *cd_head)
+{
+ struct cipher_descriptor *cd_cursor = cd_head;
+ char *proc_mount_point = NULL;
+ char *crypto_full_path = NULL;
+ FILE *crypto_file = NULL;
+ char buf[MAX_BUF_LEN];
+ char *tmp = NULL;
+ int rc;
+
+ rc = get_proc_mount_point(&proc_mount_point);
+ if (rc) {
+ syslog(LOG_WARNING, "Error attempting to find proc mount "
+ "point in [/etc/mtab]. Defaulting to [/proc].\n");
+ rc = 0;
+ if (asprintf(&proc_mount_point, "/proc") == -1) {
+ proc_mount_point = NULL;
+ rc = -ENOMEM;
+ goto out;
+ }
+ }
+ if (asprintf(&crypto_full_path, "%s/crypto", proc_mount_point) == -1) {
+ crypto_full_path = NULL;
+ rc = -ENOMEM;
+ goto out;
+ }
+ if (!(crypto_file = fopen(crypto_full_path, "r"))) {
+ rc = -EIO;
+ goto out;
+ }
+ while (fgets(buf, MAX_BUF_LEN, crypto_file)) {
+ if (!strncmp(buf, "name", 4)) {
+ struct cipher_descriptor *cd_tmp;
+ int found_duplicate = 0;
+
+ strtok(buf, ": ");
+ tmp = strtok(NULL, ": ");
+ cd_tmp = cd_head->next;
+ while (cd_tmp) {
+ if (!strcmp(cd_tmp->crypto_api_name, tmp)) {
+ found_duplicate = 1;
+ break;
+ }
+ cd_tmp = cd_tmp->next;
+ }
+ if (found_duplicate)
+ continue;
+ cd_cursor->next = malloc(sizeof(*cd_cursor));
+ if (!cd_cursor->next) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ memset(cd_cursor->next, 0, sizeof(*cd_cursor));
+ cd_cursor->next->flags |= CIPHER_DESCRIPTOR_FLAG_LOADED;
+ if (strlen(tmp) <= 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+ tmp[strlen(tmp) - 1] = '\0';
+ rc = asprintf(&cd_cursor->next->crypto_api_name,
+ "%s", tmp);
+ if (rc == -1) {
+ cd_cursor->next->crypto_api_name = NULL;
+ free(cd_cursor->next);
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ } else if (!strncmp(buf, "module", 6)) {
+ if (!cd_cursor->next)
+ continue;
+ strtok(buf, ": ");
+ tmp = strtok(NULL, ": ");
+ if (strlen(tmp) <= 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+ tmp[strlen(tmp) - 1] = '\0';
+ rc = asprintf(&cd_cursor->next->module_name, "%s.ko",
+ tmp);
+ if (rc == -1) {
+ cd_cursor->next->module_name = NULL;
+ free(cd_cursor->next->crypto_api_name);
+ free(cd_cursor->next);
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ } else if (!strncmp(buf, "driver", 6)) {
+ if (!cd_cursor->next)
+ continue;
+ strtok(buf, ": ");
+ tmp = strtok(NULL, ": ");
+ if (strlen(tmp) <= 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+ tmp[strlen(tmp) - 1] = '\0';
+ rc = asprintf(&cd_cursor->next->driver_name, "%s", tmp);
+ if (rc == -1) {
+ cd_cursor->next->module_name = NULL;
+ free(cd_cursor->next->module_name);
+ free(cd_cursor->next->crypto_api_name);
+ free(cd_cursor->next);
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ } else if (!strncmp(buf, "type", 4)) {
+ if (!cd_cursor->next)
+ continue;
+ strtok(buf, ": ");
+ tmp = strtok(NULL, ": ");
+ if (strlen(tmp) <= 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+ tmp[strlen(tmp) - 1] = '\0';
+ /* We only care about ciphers, not hashes, etc. */
+ if (strncmp(tmp, "cipher", 6)) {
+ free(cd_cursor->next->module_name);
+ free(cd_cursor->next->crypto_api_name);
+ free(cd_cursor->next->driver_name);
+ free(cd_cursor->next);
+ cd_cursor->next = NULL;
+ continue;
+ }
+ } else if (!strncmp(buf, "blocksize", 9)) {
+ if (!cd_cursor->next)
+ continue;
+ strtok(buf, ": ");
+ tmp = strtok(NULL, ": ");
+ if (strlen(tmp) <= 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+ tmp[strlen(tmp) - 1] = '\0';
+ cd_cursor->next->blocksize = atoi(tmp);
+ } else if (!strncmp(buf, "min keysize", 11)) {
+ if (!cd_cursor->next)
+ continue;
+ strtok(buf, ": ");
+ tmp = strtok(NULL, ": ");
+ if (strlen(tmp) <= 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+ tmp[strlen(tmp) - 1] = '\0';
+ cd_cursor->next->min_keysize = atoi(tmp);
+ } else if (!strncmp(buf, "max keysize", 11)) {
+ if (!cd_cursor->next)
+ continue;
+ strtok(buf, ": ");
+ tmp = strtok(NULL, ": ");
+ if (strlen(tmp) <= 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+ tmp[strlen(tmp) - 1] = '\0';
+ cd_cursor->next->max_keysize = atoi(tmp);
+ cd_cursor = cd_cursor->next;
+ }
+ }
+out:
+ if (crypto_file)
+ fclose(crypto_file);
+ free(proc_mount_point);
+ free(crypto_full_path);
+ return rc;
+}
+
+static struct cipher_name_module_map {
+ char *name;
+ char *module;
+ uint32_t blocksize;
+ uint32_t min_keysize;
+ uint32_t max_keysize;
+} cipher_name_module_map[] = {
+ {"aes", "aes.ko", 16, 16, 32},
+ {"aes", "aes_generic.ko", 16, 16, 32},
+ {"serpent", "serpent.ko", 16, 0, 32},
+ {"tnepres", "serpent.ko", 16, 0, 32},
+ {"arc4", "arc4.ko", 1, 1, 256},
+ {"tea", "tea.ko", 8, 16, 16},
+ {"xeta", "tea.ko", 8, 16, 16},
+ {"xtea", "tea.ko", 8, 16, 16},
+ {"blowfish", "blowfish.ko", 16, 16, 32},
+ {"twofish", "twofish.ko", 16, 16, 32},
+ {"khazad", "khazad.ko", 8, 16, 16},
+ {"cast5", "cast5.ko", 8, 5, 16},
+ {"cast6", "cast6.ko", 16, 16, 32},
+ {"des3_ede", "des.ko", 8, 24, 24},
+ {"des3_ede", "des_generic.ko", 8, 24, 24},
+ {"anubis", "anubis.ko", 16, 16, 40},
+ {"cipher_null", "cipher_null.ko", 1, 0, 0},
+ {NULL, NULL}
+};
+
+int ecryptfs_get_module_ciphers(struct cipher_descriptor *cd_head)
+{
+ struct cipher_descriptor *cd_cursor = cd_head;
+ char *kernel_crypto_dir = NULL;
+ struct utsname kern_info;
+ DIR *dir = NULL;
+ struct dirent *dir_entry;
+ int rc;
+
+ while (cd_cursor->next)
+ cd_cursor = cd_cursor->next;
+ rc = uname(&kern_info);
+ if (rc) {
+ syslog(LOG_ERR, "%s: uname returned [%d]\n", __FUNCTION__, rc);
+ goto out;
+ }
+ rc = asprintf(&kernel_crypto_dir, "/lib/modules/%s/kernel/crypto",
+ kern_info.release);
+ if (rc == -1) {
+ syslog(LOG_ERR, "%s: Error building kernel location string\n",
+ __FUNCTION__);
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ dir = opendir(kernel_crypto_dir);
+ if (!dir) {
+ syslog(LOG_ERR, "%s: opendir error on [%s]\n", __FUNCTION__,
+ kernel_crypto_dir);
+ rc = -EINVAL;
+ goto out;
+ }
+ while ((dir_entry = readdir(dir))) {
+ struct cipher_descriptor *cd_tmp;
+ int found_match;
+ int i;
+
+ if (!strstr(dir_entry->d_name, ".ko"))
+ continue;
+ found_match = 0;
+ cd_tmp = cd_head->next;
+ while (cd_tmp) {
+ if (!strcmp(cd_tmp->module_name, dir_entry->d_name)) {
+ found_match = 1;
+ break;
+ }
+ cd_tmp = cd_tmp->next;
+ }
+ if (found_match)
+ continue;
+ i = 0;
+ while (cipher_name_module_map[i].name) {
+ if (!strcmp(cipher_name_module_map[i].module,
+ dir_entry->d_name)) {
+ cd_cursor->next = malloc(sizeof(*cd_cursor));
+ if (!cd_cursor->next) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ memset(cd_cursor->next, 0, sizeof(*cd_cursor));
+ rc = asprintf(&cd_cursor->next->crypto_api_name,
+ "%s",
+ cipher_name_module_map[i].name);
+ if (rc == -1) {
+ free(cd_cursor->next);
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = asprintf(&cd_cursor->next->module_name,
+ "%s", dir_entry->d_name);
+ if (rc == -1) {
+ free(cd_cursor->next->crypto_api_name);
+ free(cd_cursor->next);
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ cd_cursor->next->blocksize =
+ cipher_name_module_map[i].blocksize;
+ cd_cursor->next->min_keysize =
+ cipher_name_module_map[i].min_keysize;
+ cd_cursor->next->max_keysize =
+ cipher_name_module_map[i].max_keysize;
+ cd_cursor = cd_cursor->next;
+ }
+ i++;
+ }
+ }
+out:
+ free(kernel_crypto_dir);
+ if (dir)
+ closedir(dir);
+ return rc;
+}
diff --git a/src/libecryptfs/decision_graph.c b/src/libecryptfs/decision_graph.c
index 315b434..e46f5d2 100644
--- a/src/libecryptfs/decision_graph.c
+++ b/src/libecryptfs/decision_graph.c
@@ -269,15 +269,20 @@ int do_transition(struct ecryptfs_ctx *ctx, struct
param_node **next,
* Try to find one of the aliases for this node in the list of
* name-value pairs. If found, set the value from that element in the
* list.
+ *
+ * Returns non-zero on error condition
*/
-static int retrieve_val(struct ecryptfs_name_val_pair *nvp_head,
+static int retrieve_val(int *value_retrieved,
+ struct ecryptfs_name_val_pair *nvp_head,
struct param_node *node)
{
int i = node->num_mnt_opt_names;
+ int rc = 0;
if (ecryptfs_verbosity)
syslog(LOG_INFO, "%s: Called on node [%s]\n", __FUNCTION__,
node->mnt_opt_names[0]);
+ (*value_retrieved) = 0;
while (i > 0) {
struct ecryptfs_name_val_pair *temp = nvp_head->next;
@@ -299,23 +304,32 @@ static int retrieve_val(struct ecryptfs_name_val_pair
*nvp_head,
if (temp->value
&& (strcmp(temp->value, "(null)") != 0)) {
if (asprintf(&node->val, "%s",
- temp->value) == -1)
- return -ENOMEM;
- } else {
+ temp->value) == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ } else
node->flags |= PARAMETER_SET;
- return -1;
- }
- return 0;
+ (*value_retrieved) = 1;
+ goto out;
}
temp = temp->next;
}
}
if (node->default_val) {
- if (asprintf(&node->val, "%s", node->default_val) == -1)
- return -ENOMEM;
- return 0;
+ if (asprintf(&node->val, "%s", node->default_val) == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO, "%s: Value retrieved from "
+ "node->default_val = [%s]\n", __FUNCTION__,
+ node->default_val);
+ (*value_retrieved) = 1;
+ goto out;
}
- return -1;
+out:
+ return rc;
}
/**
@@ -328,75 +342,154 @@ static int alloc_and_get_val(struct ecryptfs_ctx *ctx,
struct param_node *node,
{
char *verify_prompt;
char *verify;
- int rc = 0;
int val;
+ int value_retrieved;
+ int rc;
- if (!retrieve_val(nvp_head, node))
+ rc = retrieve_val(&value_retrieved, nvp_head, node);
+ if (rc) {
+ syslog(LOG_ERR, "%s: Error attempting to retrieve value; "
+ "rc = [%d]\n", __FUNCTION__, rc);
goto out;
- if (node->flags & ECRYPTFS_PARAM_FLAG_NO_VALUE)
+ }
+ if (value_retrieved) {
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO,
+ "%s: Value retrieved from default_val or from "
+ "parameter list; returning\n",
+ __FUNCTION__);
goto out;
- if (ctx->verbosity == 0 && !(node->flags & STDIN_REQUIRED))
- return 0;
- if ((node->flags & PARAMETER_SET) && !(node->flags & STDIN_REQUIRED))
- return 0;
+ }
+ if (node->flags & ECRYPTFS_PARAM_FLAG_NO_VALUE) {
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO,
+ "%s: ECRYPTFS_PARAM_FLAG_NO_VALUE set\n",
+ __FUNCTION__);
+ goto out;
+ }
+ if (ctx->verbosity == 0 && !(node->flags & STDIN_REQUIRED)) {
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO, "%s: ctx->verbosity == 0 and "
+ "STDIN_REQUIRED not set\n", __FUNCTION__);
+ goto out;
+ }
+ if ((node->flags & PARAMETER_SET) && !(node->flags & STDIN_REQUIRED)) {
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO, "%s: PARAMETER_SET and "
+ "STDIN_REQUIRED not set\n", __FUNCTION__);
+ goto out;
+ }
if (ctx->get_string) {
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO, "%s: ctx->get_string defined\n",
+ __FUNCTION__);
if (node->flags & DISPLAY_TRANSITION_NODE_VALS) {
- int i, strpos = 0;
- int node_prompt_len = strlen(node->prompt);
- int default_val_len = 0;
- int len;
+ struct prompt_elem pe_head;
+ struct prompt_elem *pe;
char *prompt;
+ uint32_t prompt_len;
+ int i;
- if (node->default_val)
- default_val_len = strlen(node->default_val);
- len = node_prompt_len + default_val_len + 32;
- if (node->num_transitions == 1
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO, "%s: DISPLAY_TRANSITION_NODE_"
+ "VALS set\n", __FUNCTION__);
+ memset(&pe_head, 0, sizeof(pe_head));
+ pe = &pe_head;
+ if ((node->num_transitions == 1)
&& !(node->flags
& ECRYPTFS_PARAM_FORCE_DISPLAY_NODES)) {
if (asprintf(&(node->val), "%s",
- node->tl[0].val) == -1)
- return MOUNT_ERROR;
- return 0;
+ node->tl[0].val) == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ goto out;
+ }
+ /* === Begin add component to prompt === */
+ pe->next = malloc(sizeof(*pe));
+ if (!pe->next) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ pe = pe->next;
+ memset(pe, 0, sizeof(*pe));
+ rc = asprintf(&pe->str, "%s: \n", node->prompt);
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
}
- for (i = 0; i < node->num_transitions; i++)
- len += (strlen(node->tl[i].val) + 5);
- prompt = malloc(len);
- if (!prompt)
- return -ENOMEM;
- memcpy(prompt, node->prompt, node_prompt_len);
- prompt[node_prompt_len] = ':';
- strpos = node_prompt_len + 1;
- prompt[strpos++] = '\n';
+ rc = 0;
+ /* === End add component to prompt === */
for (i = 0; i < node->num_transitions; i++) {
- prompt[strpos++] = ' ';
- prompt[strpos++] = '0' + (char)(i + 1);
- prompt[strpos++] = ')';
- prompt[strpos++] = ' ';
- memcpy(&prompt[strpos], node->tl[i].val,
- strlen(node->tl[i].val));
- strpos += strlen(node->tl[i].val);
- prompt[strpos++] = '\n';
+ pe->next = malloc(sizeof(*pe));
+ if (!pe->next) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ pe = pe->next;
+ memset(pe, 0, sizeof(*pe));
+ if (node->flags & ECRYPTFS_DISPLAY_PRETTY_VALS)
+ rc = asprintf(&pe->str, " %d) %s\n",
+ (i + 1),
+ node->tl[i].pretty_val);
+ else
+ rc = asprintf(&pe->str, " %d) %s\n",
+ (i + 1),
+ node->tl[i].val);
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ }
+ pe->next = malloc(sizeof(*pe));
+ if (!pe->next) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ pe = pe->next;
+ memset(pe, 0, sizeof(*pe));
+ if (node->suggested_val)
+ rc = asprintf(&pe->str, "Selection [%s]",
+ node->suggested_val);
+ else if (node->default_val)
+ rc = asprintf(&pe->str, "Selection [%s]",
+ node->default_val);
+ else
+ rc = asprintf(&pe->str, "Selection");
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ /* Convert prompt_elem linked list into
+ * single prompt string */
+ prompt_len = 0;
+ pe = pe_head.next;
+ while (pe) {
+ prompt_len += strlen(pe->str);
+ pe = pe->next;
}
- memcpy(&prompt[strpos], "Selection", 9);
- strpos += 9;
- if (node->suggested_val) {
- memcpy(&prompt[strpos], " [", 2);
- strpos += 2;
- memcpy(&prompt[strpos], node->default_val,
- default_val_len);
- strpos += default_val_len;
- memcpy(&prompt[strpos], "]", 1);
- strpos += 1;
- } else if (node->default_val) {
- memcpy(&prompt[strpos], " [", 2);
- strpos += 2;
- memcpy(&prompt[strpos], node->default_val,
- default_val_len);
- strpos += default_val_len;
- memcpy(&prompt[strpos], "]", 1);
- strpos += 1;
+ prompt_len++;
+ i = 0;
+ prompt = malloc(prompt_len);
+ if (!prompt) {
+ rc = -ENOMEM;
+ goto out;
}
- prompt[strpos] = '\0';
+ pe = pe_head.next;
+ while (pe) {
+ struct prompt_elem *pe_tmp;
+
+ memcpy(&prompt[i], pe->str, strlen(pe->str));
+ i += strlen(pe->str);
+ pe_tmp = pe;
+ pe = pe->next;
+ free(pe_tmp->str);
+ free(pe_tmp);
+ }
+ prompt[i] = '\0';
get_value:
rc = (ctx->get_string)
(&(node->val), prompt,
@@ -408,13 +501,38 @@ get_value:
asprintf(&(node->val), "%s",
node->tl[val - 1].val);
} else {
- goto get_value;
+ int valid_val;
+
+ if (node->val[0] == '\0') {
+ if (!node->suggested_val)
+ goto get_value;
+ rc = asprintf(&node->val, "%s",
+ node->suggested_val);
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ }
+ valid_val = 0;
+ for (i = 0; i < node->num_transitions; i++) {
+ if (strcmp(node->val, node->tl[i].val)
+ == 0) {
+ valid_val = 1;
+ break;
+ }
+ }
+ if (!valid_val)
+ goto get_value;
}
free(prompt);
return rc;
} else {
char *prompt;
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO, "%s: DISPLAY_TRANSITION_NODE_"
+ "VALS not set\n", __FUNCTION__);
obtain_value:
if (node->suggested_val)
asprintf(&prompt, "%s [%s]", node->prompt,
@@ -451,8 +569,12 @@ obtain_value:
}
return rc;
}
+ } else {
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO, "%s: ctx->get_string not defined",
+ __FUNCTION__);
}
- return MOUNT_ERROR;
+ rc = MOUNT_ERROR;
out:
return rc;
}
diff --git a/src/libecryptfs/module_mgr.c b/src/libecryptfs/module_mgr.c
index 39b8aa2..820fc00 100644
--- a/src/libecryptfs/module_mgr.c
+++ b/src/libecryptfs/module_mgr.c
@@ -78,7 +78,7 @@ out:
return rc;
}
-static struct param_node cipher_param_node;
+static struct param_node ecryptfs_cipher_param_node;
static struct param_node root_param_node = {
.num_mnt_opt_names = 1,
@@ -92,7 +92,7 @@ static struct param_node root_param_node = {
.num_transitions = 1,
.tl = {{.val = "default",
.pretty_val = "default",
- .next_token = &cipher_param_node,
+ .next_token = &ecryptfs_cipher_param_node,
.trans_func = sig_param_node_callback}}
};
@@ -222,8 +222,8 @@ static int get_encrypted_passthrough(struct ecryptfs_ctx
*ctx,
static struct param_node end_param_node = {
.num_mnt_opt_names = 1,
- .mnt_opt_names = {"cipher"},
- .prompt = "Select cipher",
+ .mnt_opt_names = {"end"},
+ .prompt = "end",
.val_type = VAL_STR,
.val = NULL,
.display_opts = NULL,
@@ -233,7 +233,7 @@ static struct param_node end_param_node = {
.tl = {{.val = "default",
.pretty_val = "default",
.next_token = NULL,
- .trans_func = get_cipher}}
+ .trans_func = NULL}}
};
static struct param_node encrypted_passthrough_param_node = {
@@ -284,22 +284,233 @@ static struct param_node passthrough_param_node = {
.trans_func = get_passthrough}}
};
-static struct param_node cipher_param_node = {
+static struct param_node ecryptfs_key_bytes_param_node = {
+ .num_mnt_opt_names = 1,
+ .mnt_opt_names = {"ecryptfs_key_bytes"},
+ .prompt = "Select key bytes",
+ .val_type = VAL_STR,
+ .val = NULL,
+ .display_opts = NULL,
+ .default_val = NULL,
+ .flags = (DISPLAY_TRANSITION_NODE_VALS
+ | ECRYPTFS_PARAM_FORCE_DISPLAY_NODES
+ | ECRYPTFS_PARAM_FLAG_ECHO_INPUT),
+ .num_transitions = 0,
+ .tl = {{0}}
+};
+
+static struct supported_key_bytes {
+ char *cipher_name;
+ uint32_t key_bytes;
+} supported_key_bytes[] = {
+ {"aes", 16},
+ {"aes", 24},
+ {"aes", 32},
+ {"anubis", 16},
+ {"anubis", 32},
+ {"des3_ede", 24},
+ {"serpent", 16},
+ {"serpent", 32},
+ {"tnepres", 16},
+ {"tnepres", 32},
+ {"tea", 16},
+ {"xeta", 16},
+ {"xtea", 16},
+ {"cast5", 16},
+ {"cast6", 16},
+ {"cast6", 32},
+ {"twofish", 16},
+ {"twofish", 32},
+ {"blowfish", 16},
+ {"blowfish", 32},
+ {"khazad", 16},
+ {"arc4", 16},
+ {"arc4", 32},
+ {NULL, 0}
+};
+
+static int tf_ecryptfs_key_bytes(struct ecryptfs_ctx *ctx,
+ struct param_node *node,
+ struct val_node **head, void **foo)
+{
+ char *opt;
+ int rc = 0;
+
+ rc = asprintf(&opt, "ecryptfs_key_bytes=%s", node->val);
+ free(node->val);
+ node->val = NULL;
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ stack_push(head, opt);
+out:
+ return rc;
+}
+
+static int init_ecryptfs_key_bytes_param_node(char *cipher_name)
+{
+ int i;
+ int rc = 0;
+
+ i = 0;
+ while (supported_key_bytes[i].cipher_name) {
+ if (strcmp(cipher_name, supported_key_bytes[i].cipher_name)
+ == 0) {
+ struct transition_node *tn;
+
+ tn = &ecryptfs_key_bytes_param_node.tl[
+ ecryptfs_key_bytes_param_node.num_transitions];
+ rc = asprintf(&tn->val, "%d",
+ supported_key_bytes[i].key_bytes);
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ if (!ecryptfs_key_bytes_param_node.suggested_val) {
+ rc =
asprintf(&ecryptfs_key_bytes_param_node.suggested_val,
+ "%d",
+ supported_key_bytes[i].key_bytes);
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ }
+ tn->next_token = &end_param_node;
+ tn->trans_func = tf_ecryptfs_key_bytes;
+ ecryptfs_key_bytes_param_node.num_transitions++;
+ }
+ i++;
+ }
+out:
+ return rc;
+}
+
+static int tf_ecryptfs_cipher(struct ecryptfs_ctx *ctx, struct param_node
*node,
+ struct val_node **head, void **foo)
+{
+ char *opt;
+ int rc;
+
+ rc = init_ecryptfs_key_bytes_param_node(node->val);
+ if (rc) {
+ syslog(LOG_ERR, "%s: Error initializing key_bytes param node; "
+ "rc = [%d]\n", __FUNCTION__, rc);
+ goto out;
+ }
+ rc = asprintf(&opt, "ecryptfs_cipher=%s", node->val);
+ free(node->val);
+ node->val = NULL;
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ if (ecryptfs_verbosity)
+ syslog(LOG_INFO, "%s: Pushing onto stack; opt = [%s]\n",
+ __FUNCTION__, opt);
+ stack_push(head, opt);
+out:
+ return rc;
+}
+
+static struct param_node ecryptfs_cipher_param_node = {
.num_mnt_opt_names = 1,
- .mnt_opt_names = {"cipher"},
+ .mnt_opt_names = {"ecryptfs_cipher"},
.prompt = "Select cipher",
.val_type = VAL_STR,
.val = NULL,
.display_opts = NULL,
.default_val = NULL,
- .flags = ECRYPTFS_PARAM_FLAG_NO_VALUE,
- .num_transitions = 1,
- .tl = {{.val = "default",
- .pretty_val = "default",
- .next_token = &end_param_node,
- .trans_func = get_cipher}}
+ .flags = (DISPLAY_TRANSITION_NODE_VALS | ECRYPTFS_DISPLAY_PRETTY_VALS
+ | ECRYPTFS_PARAM_FLAG_ECHO_INPUT),
+ .num_transitions = 0,
+ .tl = {{0}}
};
+static int init_ecryptfs_cipher_param_node(uint32_t version)
+{
+ struct cipher_descriptor cd_head;
+ struct cipher_descriptor *cd_cursor;
+ int rc;
+
+ memset(&cd_head, 0, sizeof(cd_head));
+ rc = ecryptfs_get_kernel_ciphers(&cd_head);
+ if (rc) {
+ syslog(LOG_ERR, "%s: Error getting kernel ciphers; rc = [%d]\n",
+ __FUNCTION__, rc);
+ goto out;
+ }
+ rc = ecryptfs_get_module_ciphers(&cd_head);
+ if (rc) {
+ syslog(LOG_ERR, "%s: Error getting module ciphers; rc = [%d]\n",
+ __FUNCTION__, rc);
+ goto out;
+ }
+ cd_cursor = cd_head.next;
+ while (cd_cursor) {
+ struct transition_node *tn;
+ struct cipher_descriptor *cd_tmp;
+
+ if (ecryptfs_cipher_param_node.num_transitions
+ >= MAX_NUM_TRANSITIONS) {
+ syslog(LOG_WARNING, "%s: Exceeded maximum number of "
+ "transition nodes [%d] whilst constructing "
+ "cipher list\n", __FUNCTION__,
+ MAX_NUM_TRANSITIONS);
+ goto out;
+ }
+ tn = &ecryptfs_cipher_param_node.tl[
+ ecryptfs_cipher_param_node.num_transitions];
+ rc = asprintf(&tn->val, "%s", cd_cursor->crypto_api_name);
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ if (!ecryptfs_cipher_param_node.suggested_val) {
+ rc = asprintf(&ecryptfs_cipher_param_node.suggested_val,
+ "%s", cd_cursor->crypto_api_name);
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ }
+ rc = asprintf(&tn->pretty_val,
+ "%s: blocksize = %d; "
+ "min keysize = %d; max keysize = %d (%s)",
+ cd_cursor->crypto_api_name,
+ cd_cursor->blocksize,
+ cd_cursor->min_keysize,
+ cd_cursor->max_keysize,
+ ((cd_cursor->flags
+ & CIPHER_DESCRIPTOR_FLAG_LOADED) ? "loaded"
+ : "not loaded"));
+ if (rc == -1) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = 0;
+ tn->next_token = &ecryptfs_key_bytes_param_node;
+ tn->trans_func = tf_ecryptfs_cipher;
+ ecryptfs_cipher_param_node.num_transitions++;
+ free(cd_cursor->crypto_api_name);
+ free(cd_cursor->descriptive_name);
+ free(cd_cursor->driver_name);
+ free(cd_cursor->module_name);
+ cd_tmp = cd_cursor;
+ cd_cursor = cd_cursor->next;
+ cd_tmp->next = NULL;
+ free(cd_tmp);
+ }
+out:
+ return rc;
+}
+
static int
another_key_param_node_callback(struct ecryptfs_ctx *ctx,
struct param_node *node,
@@ -337,7 +548,7 @@ another_key_param_node_callback(struct ecryptfs_ctx *ctx,
}
nvp = nvp->next;
}
- node->tl[0].next_token = &cipher_param_node;
+ node->tl[0].next_token = &ecryptfs_cipher_param_node;
out:
return rc;
}
@@ -358,28 +569,46 @@ static struct param_node another_key_param_node = {
.num_transitions = 1,
.tl = {{.val = "default",
.pretty_val = "default",
- .next_token = &cipher_param_node,
+ .next_token = &ecryptfs_cipher_param_node,
.trans_func = another_key_param_node_callback}}
};
-static void
+static int
fill_in_decision_graph_based_on_version_support(struct param_node *root,
uint32_t version)
{
- struct param_node *last_param_node = &cipher_param_node;
+ struct param_node *last_param_node = &ecryptfs_key_bytes_param_node;
+ int rc;
ecryptfs_set_exit_param_on_graph(root, &another_key_param_node);
+ rc = init_ecryptfs_cipher_param_node(version);
+ if (rc) {
+ syslog(LOG_ERR,
+ "%s: Error initializing cipher list; rc = [%d]\n",
+ __FUNCTION__, rc);
+ goto out;
+ }
if (ecryptfs_supports_plaintext_passthrough(version)) {
- last_param_node->tl[0].next_token = &passthrough_param_node;
+ int i;
+
+ for (i = 0; i < last_param_node->num_transitions; i++)
+ last_param_node->tl[i].next_token =
+ &passthrough_param_node;
last_param_node = &passthrough_param_node;
}
if (ecryptfs_supports_xattr(version)) {
- last_param_node->tl[0].next_token = &xattr_param_node;
+ int i;
+
+ for (i = 0; i < last_param_node->num_transitions; i++)
+ last_param_node->tl[i].next_token = &xattr_param_node;
last_param_node = &xattr_param_node;
- last_param_node->tl[0].next_token =
- &encrypted_passthrough_param_node;
+ for (i = 0; i < last_param_node->num_transitions; i++)
+ last_param_node->tl[i].next_token =
+ &encrypted_passthrough_param_node;
last_param_node = &encrypted_passthrough_param_node;
}
+out:
+ return rc;
}
static struct param_node dummy_param_node = {
@@ -498,10 +727,15 @@ int ecryptfs_process_decision_graph(struct ecryptfs_ctx
*ctx,
}
key_mod = key_mod->next;
}
- if (key_module_only == ECRYPTFS_ASK_FOR_ALL_MOUNT_OPTIONS)
-
fill_in_decision_graph_based_on_version_support(&key_module_select_node,
- version);
- else
+ if (key_module_only == ECRYPTFS_ASK_FOR_ALL_MOUNT_OPTIONS) {
+ rc = fill_in_decision_graph_based_on_version_support(
+ &key_module_select_node, version);
+ if (rc) {
+ syslog(LOG_ERR, "%s: Error attempting to fill in "
+ "decision graph; rc = [%d]\n", __FUNCTION__, rc);
+ goto out;
+ }
+ } else
ecryptfs_set_exit_param_on_graph(&key_module_select_node,
&dummy_param_node);
memset(&nvp_head, 0, sizeof(struct ecryptfs_name_val_pair));
@@ -521,6 +755,20 @@ int ecryptfs_process_decision_graph(struct ecryptfs_ctx
*ctx,
}
}
ctx->nvp_head = &rc_file_nvp_head;
+#if 1
+ {
+ struct ecryptfs_name_val_pair *nv_tmp = rc_file_nvp_head.next;
+
+ while (nv_tmp) {
+ syslog(LOG_INFO, "%s: name = [%s]; value = [%s]\n",
+ __FUNCTION__, nv_tmp->name, nv_tmp->value);
+ nv_tmp = nv_tmp->next;
+ }
+/* ecryptfs_dump_param_node(stdout,
+ &key_module_select_node, 0,
+ 1); */
+ }
+#endif
ecryptfs_eval_decision_graph(ctx, mnt_params, &root_param_node,
&rc_file_nvp_head);
out_free_allowed_duplicates:
diff --git a/src/testcases/test-cipher-list.c b/src/testcases/test-cipher-list.c
new file mode 100644
index 0000000..75ac3b9
--- /dev/null
+++ b/src/testcases/test-cipher-list.c
@@ -0,0 +1,37 @@
+#include "../include/ecryptfs.h"
+
+int main()
+{
+ struct cipher_descriptor cd_head;
+ struct cipher_descriptor *cd_cursor;
+ int rc;
+
+ memset(&cd_head, 0, sizeof(cd_head));
+ rc = ecryptfs_get_kernel_ciphers(&cd_head);
+ if (rc) {
+ printf("rc = [%d]\n", rc);
+ goto out;
+ }
+ rc = ecryptfs_get_module_ciphers(&cd_head);
+ if (rc) {
+ printf("rc = [%d]\n", rc);
+ goto out;
+ }
+ cd_cursor = cd_head.next;
+ while (cd_cursor) {
+ struct cipher_descriptor *cd_tmp;
+
+ printf("[%s]: [%s] (%s)\n", cd_cursor->crypto_api_name,
+ cd_cursor->module_name, (cd_cursor->flags &
CIPHER_DESCRIPTOR_FLAG_LOADED ? "loaded" : "not loaded"));
+ free(cd_cursor->crypto_api_name);
+ free(cd_cursor->descriptive_name);
+ free(cd_cursor->driver_name);
+ free(cd_cursor->module_name);
+ cd_tmp = cd_cursor;
+ cd_cursor = cd_cursor->next;
+ cd_tmp->next = NULL;
+ free(cd_tmp);
+ }
+out:
+ return rc;
+}
-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
eCryptfs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ecryptfs-devel