* [PATCH BlueZ v6 0/2] mesh: node dir Restructure, and keyring @ 2019-05-09 21:33 Brian Gix 2019-05-09 21:33 ` [PATCH BlueZ v6 1/2] mesh: Reconfigure node storage tree Brian Gix 2019-05-09 21:33 ` [PATCH BlueZ v6 2/2] mesh: Add key storage Brian Gix 0 siblings, 2 replies; 4+ messages in thread From: Brian Gix @ 2019-05-09 21:33 UTC (permalink / raw) To: linux-bluetooth; +Cc: inga.stotland, brian.gix, michal.lowas-rzechonek This version 6 allows the legal file descriptor == 0, and uses lseek() to streamline checking network bindings when updating application keys. Brian Gix (2): mesh: Reconfigure node storage tree mesh: Add key storage Makefile.mesh | 1 + mesh/README | 34 ++++++- mesh/keyring.c | 298 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mesh/keyring.h | 49 ++++++++++ mesh/node.c | 16 ++-- mesh/node.h | 4 +- mesh/storage.c | 144 +++++++++++++++++----------- 7 files changed, 479 insertions(+), 67 deletions(-) create mode 100644 mesh/keyring.c create mode 100644 mesh/keyring.h -- 2.14.5 ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH BlueZ v6 1/2] mesh: Reconfigure node storage tree 2019-05-09 21:33 [PATCH BlueZ v6 0/2] mesh: node dir Restructure, and keyring Brian Gix @ 2019-05-09 21:33 ` Brian Gix 2019-05-13 19:32 ` Gix, Brian 2019-05-09 21:33 ` [PATCH BlueZ v6 2/2] mesh: Add key storage Brian Gix 1 sibling, 1 reply; 4+ messages in thread From: Brian Gix @ 2019-05-09 21:33 UTC (permalink / raw) To: linux-bluetooth; +Cc: inga.stotland, brian.gix, michal.lowas-rzechonek Add a tree structure to a nodes data storage, in order to safely handle Replay Protection list, Refactor local Sequence Numbers, and add Key storage for Config Client nodes. --- mesh/README | 34 +++++++++++++- mesh/node.c | 16 ++++--- mesh/node.h | 4 +- mesh/storage.c | 144 ++++++++++++++++++++++++++++++++++----------------------- 4 files changed, 131 insertions(+), 67 deletions(-) diff --git a/mesh/README b/mesh/README index ca223a6d8..82fd5a017 100644 --- a/mesh/README +++ b/mesh/README @@ -36,8 +36,40 @@ Each subdirectory contains the following files: provisioner/configuration client - node.json.bak: a backup that the last known good node configuration. + - seq_num: + File containing next sequence number to use + - seq_num.bak: + Backup of the sequence number. This may be larger than the + actual sequence number being used at runtime, to prevent re-use + of sequence numbers in the event of an unexpected restart. + - ./rpl/: + Directory to store the sequence numbers of remote nodes, as + required by Replay Protection List (RPL) parameters. + - xxxx: + Files named for remote Unicast addresses, and contain + last received iv_index + seq_num from each SRC address. + - ./dev_keys/: + Directory to store remote Device keys. This is only created/used + by Configuration Client (Network administration) nodes. + - xxxx: + Files named for remote Unicast addresses, and contains + 16 octet key. + - ./net_keys/: + Directory to store network subnet keys. This is only + created/used by Configuration Client (Network administration) + nodes. + - xxx: + Files named for subnet index, and contains key refresh + phase, and old/new versions of the key. + - ./app_keys/: + Directory to store application keys. This is only created/used + by Configuration Client (Network administration) nodes. + - xxx: + Files named for application index, and contains bound + subnet index, and old/new versions of the key. -The files are in JSON format. +The node.json and node.json.bak are in JSON format. All other files are stored +in little endian binary format. Information =========== diff --git a/mesh/node.c b/mesh/node.c index 5904b116c..6f95c8d1c 100644 --- a/mesh/node.c +++ b/mesh/node.c @@ -79,7 +79,7 @@ struct mesh_node { char *owner; char *path; void *jconfig; - char *cfg_file; + char *node_path; uint32_t disc_watch; time_t upd_sec; uint32_t seq_number; @@ -236,6 +236,7 @@ static void free_node_resources(void *data) l_free(node->comp); l_free(node->app_path); l_free(node->owner); + l_free(node->node_path); if (node->disc_watch) l_dbus_remove_watch(dbus_get_bus(), node->disc_watch); @@ -259,7 +260,7 @@ void node_remove(struct mesh_node *node) l_queue_remove(nodes, node); - if (node->cfg_file) + if (node->node_path) storage_remove_node_config(node); free_node_resources(node); @@ -395,7 +396,7 @@ static void cleanup_node(void *data) struct mesh_net *net = node->net; /* Save local node configuration */ - if (node->cfg_file) { + if (node->node_path) { /* Preserve the last sequence number */ storage_write_sequence_number(net, mesh_net_get_seq_num(net)); @@ -1859,14 +1860,15 @@ void *node_jconfig_get(struct mesh_node *node) return node->jconfig; } -void node_cfg_file_set(struct mesh_node *node, char *cfg) +void node_path_set(struct mesh_node *node, char *path) { - node->cfg_file = cfg; + l_free(node->node_path); + node->node_path = l_strdup(path); } -char *node_cfg_file_get(struct mesh_node *node) +char *node_path_get(struct mesh_node *node) { - return node->cfg_file; + return node->node_path; } struct mesh_net *node_get_net(struct mesh_node *node) diff --git a/mesh/node.h b/mesh/node.h index 1be4de1da..1194ff837 100644 --- a/mesh/node.h +++ b/mesh/node.h @@ -95,5 +95,5 @@ bool node_dbus_init(struct l_dbus *bus); void node_cleanup_all(void); void node_jconfig_set(struct mesh_node *node, void *jconfig); void *node_jconfig_get(struct mesh_node *node); -void node_cfg_file_set(struct mesh_node *node, char *cfg); -char *node_cfg_file_get(struct mesh_node *node); +void node_path_set(struct mesh_node *node, char *path); +char *node_path_get(struct mesh_node *node); diff --git a/mesh/storage.c b/mesh/storage.c index 2580cbe7f..f4e23bf49 100644 --- a/mesh/storage.c +++ b/mesh/storage.c @@ -28,6 +28,7 @@ #include <unistd.h> #include <dirent.h> #include <libgen.h> +#include <ftw.h> #include <sys/types.h> #include <sys/stat.h> @@ -49,13 +50,30 @@ struct write_info { json_object *jnode; - const char *config_name; + const char *node_path; void *user_data; mesh_status_func_t cb; }; +static const char *cfg_name = "/node.json"; +static const char *bak_ext = ".bak"; +static const char *tmp_ext = ".tmp"; static const char *storage_dir; +/* This is a thread-safe always malloced version of dirname which will work + * regardless of which underlying dirname() implementation is used. + */ +static char *alloc_dirname(const char *path) +{ + char *tmp = l_strdup(path); + char *dir; + + dir = dirname(tmp); + strncpy(tmp, dir, strlen(path) + 1); + + return tmp; +} + static bool read_node_cb(struct mesh_db_node *db_node, void *user_data) { struct mesh_node *node = user_data; @@ -166,7 +184,7 @@ static bool parse_node(struct mesh_node *node, json_object *jnode) return true; } -static bool parse_config(char *in_file, char *out_file, const uint8_t uuid[16]) +static bool parse_config(char *in_file, char *out_dir, const uint8_t uuid[16]) { int fd; char *str; @@ -213,7 +231,7 @@ static bool parse_config(char *in_file, char *out_file, const uint8_t uuid[16]) } node_jconfig_set(node, jnode); - node_cfg_file_set(node, out_file); + node_path_set(node, out_dir); done: close(fd); @@ -430,15 +448,12 @@ static bool save_config(json_object *jnode, const char *config_name) static void idle_save_config(void *user_data) { struct write_info *info = user_data; - size_t len = strlen(info->config_name) + 5; - char *tmp = l_malloc(len); - char *bak = l_malloc(len); + char *tmp, *bak, *cfg; bool result = false; - strncpy(tmp, info->config_name, len); - strncpy(bak, info->config_name, len); - tmp = strncat(tmp, ".tmp", 5); - bak = strncat(bak, ".bak", 5); + cfg = l_strdup_printf("%s%s", info->node_path, cfg_name); + tmp = l_strdup_printf("%s%s", cfg, tmp_ext); + bak = l_strdup_printf("%s%s", cfg, bak_ext); remove(tmp); l_debug("Storage-Wrote"); @@ -446,13 +461,14 @@ static void idle_save_config(void *user_data) if (result) { remove(bak); - rename(info->config_name, bak); - rename(tmp, info->config_name); + rename(cfg, bak); + rename(tmp, cfg); } remove(tmp); l_free(tmp); l_free(bak); + l_free(cfg); if (info->cb) info->cb(info->user_data, result); @@ -467,7 +483,7 @@ void storage_save_config(struct mesh_node *node, bool no_wait, info = l_new(struct write_info, 1); info->jnode = node_jconfig_get(node); - info->config_name = node_cfg_file_get(node); + info->node_path = node_path_get(node); info->cb = cb; info->user_data = user_data; @@ -517,6 +533,7 @@ bool storage_load_nodes(const char *dir_name) { DIR *dir; struct dirent *entry; + size_t path_len = strlen(dir_name) + strlen(cfg_name) + strlen(bak_ext); create_dir(dir_name); dir = opendir(dir_name); @@ -529,33 +546,37 @@ bool storage_load_nodes(const char *dir_name) storage_dir = dir_name; while ((entry = readdir(dir)) != NULL) { - char *cfg; - char *bak; + char *dir, *cfg, *bak; uint8_t uuid[16]; + size_t node_len; if (entry->d_type != DT_DIR) continue; - if (!str2hex(entry->d_name, strlen(entry->d_name), uuid, sizeof(uuid))) + /* Check path length */ + node_len = strlen(entry->d_name); + if (path_len + node_len + 1 >= PATH_MAX) continue; - cfg = l_strdup_printf("%s/%s/node.json", dir_name, entry->d_name); - - if (parse_config(cfg, cfg, uuid)) + if (!str2hex(entry->d_name, node_len, uuid, sizeof(uuid))) continue; - /* Fall-back to Backup version */ - bak = l_strdup_printf("%s/%s/node.json.bak", dir_name, entry->d_name); + dir = l_strdup_printf("%s/%s", dir_name, entry->d_name); + cfg = l_strdup_printf("%s%s", dir, cfg_name); - if (parse_config(bak, cfg, uuid)) { - remove(cfg); - rename(bak, cfg); - l_free(cfg); - continue; - } + if (!parse_config(cfg, dir, uuid)) { + /* Fall-back to Backup version */ + bak = l_strdup_printf("%s%s", cfg, bak_ext); + + if (parse_config(bak, dir, uuid)) { + remove(cfg); + rename(bak, cfg); + } + l_free(bak); + } l_free(cfg); - l_free(bak); + l_free(dir); } return true; @@ -566,8 +587,8 @@ bool storage_create_node_config(struct mesh_node *node, void *data) struct mesh_db_node *db_node = data; char uuid[33]; char name_buf[PATH_MAX]; - char *filename; json_object *jnode; + size_t max_len = strlen(cfg_name) + strlen(bak_ext); if (!storage_dir) return false; @@ -578,25 +599,26 @@ bool storage_create_node_config(struct mesh_node *node, void *data) return false; if (!hex2str(node_uuid_get(node), 16, uuid, sizeof(uuid))) - return false; + goto fail; snprintf(name_buf, PATH_MAX, "%s/%s", storage_dir, uuid); + if (strlen(name_buf) + max_len >= PATH_MAX) + goto fail; + /* Create a new directory and node.json file */ if (mkdir(name_buf, 0755) != 0) goto fail; - filename = l_strdup_printf("%s/node.json", name_buf); + node_path_set(node, name_buf); - l_debug("New node config %s", filename); + snprintf(name_buf, PATH_MAX, "%s/%s%s", storage_dir, uuid, cfg_name); + l_debug("New node config %s", name_buf); - if (!save_config(jnode, filename)) { - l_free(filename); + if (!save_config(jnode, name_buf)) goto fail; - } node_jconfig_set(node, jnode); - node_cfg_file_set(node, filename); return true; fail: @@ -604,13 +626,29 @@ fail: return false; } +static int del_fobject(const char *fpath, const struct stat *sb, int typeflag, + struct FTW *ftwbuf) +{ + switch (typeflag) { + case FTW_DP: + rmdir(fpath); + l_debug("RMDIR %s", fpath); + break; + + case FTW_SL: + default: + remove(fpath); + l_debug("RM %s", fpath); + break; + } + return 0; +} + /* Permanently remove node configuration */ void storage_remove_node_config(struct mesh_node *node) { - char *cfg; + char *node_path, *mesh_path, *mesh_name; struct json_object *jnode; - const char *dir_name; - char *bak; if (!node) return; @@ -621,25 +659,17 @@ void storage_remove_node_config(struct mesh_node *node) json_object_put(jnode); node_jconfig_set(node, NULL); - /* Delete node configuration file */ - cfg = node_cfg_file_get(node); - if (!cfg) - return; - - l_debug("Delete node config file %s", cfg); - remove(cfg); - - /* Delete the backup file */ - bak = l_strdup_printf("%s.bak", cfg); - remove(bak); - l_free(bak); + node_path = node_path_get(node); + l_debug("Delete node config %s", node_path); - /* Delete the node directory */ - dir_name = dirname(cfg); + /* Make sure path name of node follows expected guidelines */ + mesh_path = alloc_dirname(node_path); + mesh_name = basename(mesh_path); + if (strcmp(mesh_name, "mesh")) + goto done; - l_debug("Delete directory %s", dir_name); - rmdir(dir_name); + nftw(node_path, del_fobject, 5, FTW_DEPTH | FTW_PHYS); - l_free(cfg); - node_cfg_file_set(node, NULL); +done: + l_free(mesh_path); } -- 2.14.5 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH BlueZ v6 1/2] mesh: Reconfigure node storage tree 2019-05-09 21:33 ` [PATCH BlueZ v6 1/2] mesh: Reconfigure node storage tree Brian Gix @ 2019-05-13 19:32 ` Gix, Brian 0 siblings, 0 replies; 4+ messages in thread From: Gix, Brian @ 2019-05-13 19:32 UTC (permalink / raw) To: linux-bluetooth@vger.kernel.org Cc: michal.lowas-rzechonek@silvair.com, Stotland, Inga Patch-set applied On Thu, 2019-05-09 at 14:33 -0700, Brian Gix wrote: > Add a tree structure to a nodes data storage, in order to safely handle > Replay Protection list, Refactor local Sequence Numbers, and add Key > storage for Config Client nodes. > --- > mesh/README | 34 +++++++++++++- > mesh/node.c | 16 ++++--- > mesh/node.h | 4 +- > mesh/storage.c | 144 ++++++++++++++++++++++++++++++++++----------------------- > 4 files changed, 131 insertions(+), 67 deletions(-) > > diff --git a/mesh/README b/mesh/README > index ca223a6d8..82fd5a017 100644 > --- a/mesh/README > +++ b/mesh/README > @@ -36,8 +36,40 @@ Each subdirectory contains the following files: > provisioner/configuration client > - node.json.bak: > a backup that the last known good node configuration. > + - seq_num: > + File containing next sequence number to use > + - seq_num.bak: > + Backup of the sequence number. This may be larger than the > + actual sequence number being used at runtime, to prevent re-use > + of sequence numbers in the event of an unexpected restart. > + - ./rpl/: > + Directory to store the sequence numbers of remote nodes, as > + required by Replay Protection List (RPL) parameters. > + - xxxx: > + Files named for remote Unicast addresses, and contain > + last received iv_index + seq_num from each SRC address. > + - ./dev_keys/: > + Directory to store remote Device keys. This is only created/used > + by Configuration Client (Network administration) nodes. > + - xxxx: > + Files named for remote Unicast addresses, and contains > + 16 octet key. > + - ./net_keys/: > + Directory to store network subnet keys. This is only > + created/used by Configuration Client (Network administration) > + nodes. > + - xxx: > + Files named for subnet index, and contains key refresh > + phase, and old/new versions of the key. > + - ./app_keys/: > + Directory to store application keys. This is only created/used > + by Configuration Client (Network administration) nodes. > + - xxx: > + Files named for application index, and contains bound > + subnet index, and old/new versions of the key. > > -The files are in JSON format. > +The node.json and node.json.bak are in JSON format. All other files are stored > +in little endian binary format. > > Information > =========== > diff --git a/mesh/node.c b/mesh/node.c > index 5904b116c..6f95c8d1c 100644 > --- a/mesh/node.c > +++ b/mesh/node.c > @@ -79,7 +79,7 @@ struct mesh_node { > char *owner; > char *path; > void *jconfig; > - char *cfg_file; > + char *node_path; > uint32_t disc_watch; > time_t upd_sec; > uint32_t seq_number; > @@ -236,6 +236,7 @@ static void free_node_resources(void *data) > l_free(node->comp); > l_free(node->app_path); > l_free(node->owner); > + l_free(node->node_path); > > if (node->disc_watch) > l_dbus_remove_watch(dbus_get_bus(), node->disc_watch); > @@ -259,7 +260,7 @@ void node_remove(struct mesh_node *node) > > l_queue_remove(nodes, node); > > - if (node->cfg_file) > + if (node->node_path) > storage_remove_node_config(node); > > free_node_resources(node); > @@ -395,7 +396,7 @@ static void cleanup_node(void *data) > struct mesh_net *net = node->net; > > /* Save local node configuration */ > - if (node->cfg_file) { > + if (node->node_path) { > > /* Preserve the last sequence number */ > storage_write_sequence_number(net, mesh_net_get_seq_num(net)); > @@ -1859,14 +1860,15 @@ void *node_jconfig_get(struct mesh_node *node) > return node->jconfig; > } > > -void node_cfg_file_set(struct mesh_node *node, char *cfg) > +void node_path_set(struct mesh_node *node, char *path) > { > - node->cfg_file = cfg; > + l_free(node->node_path); > + node->node_path = l_strdup(path); > } > > -char *node_cfg_file_get(struct mesh_node *node) > +char *node_path_get(struct mesh_node *node) > { > - return node->cfg_file; > + return node->node_path; > } > > struct mesh_net *node_get_net(struct mesh_node *node) > diff --git a/mesh/node.h b/mesh/node.h > index 1be4de1da..1194ff837 100644 > --- a/mesh/node.h > +++ b/mesh/node.h > @@ -95,5 +95,5 @@ bool node_dbus_init(struct l_dbus *bus); > void node_cleanup_all(void); > void node_jconfig_set(struct mesh_node *node, void *jconfig); > void *node_jconfig_get(struct mesh_node *node); > -void node_cfg_file_set(struct mesh_node *node, char *cfg); > -char *node_cfg_file_get(struct mesh_node *node); > +void node_path_set(struct mesh_node *node, char *path); > +char *node_path_get(struct mesh_node *node); > diff --git a/mesh/storage.c b/mesh/storage.c > index 2580cbe7f..f4e23bf49 100644 > --- a/mesh/storage.c > +++ b/mesh/storage.c > @@ -28,6 +28,7 @@ > #include <unistd.h> > #include <dirent.h> > #include <libgen.h> > +#include <ftw.h> > > #include <sys/types.h> > #include <sys/stat.h> > @@ -49,13 +50,30 @@ > > struct write_info { > json_object *jnode; > - const char *config_name; > + const char *node_path; > void *user_data; > mesh_status_func_t cb; > }; > > +static const char *cfg_name = "/node.json"; > +static const char *bak_ext = ".bak"; > +static const char *tmp_ext = ".tmp"; > static const char *storage_dir; > > +/* This is a thread-safe always malloced version of dirname which will work > + * regardless of which underlying dirname() implementation is used. > + */ > +static char *alloc_dirname(const char *path) > +{ > + char *tmp = l_strdup(path); > + char *dir; > + > + dir = dirname(tmp); > + strncpy(tmp, dir, strlen(path) + 1); > + > + return tmp; > +} > + > static bool read_node_cb(struct mesh_db_node *db_node, void *user_data) > { > struct mesh_node *node = user_data; > @@ -166,7 +184,7 @@ static bool parse_node(struct mesh_node *node, json_object *jnode) > return true; > } > > -static bool parse_config(char *in_file, char *out_file, const uint8_t uuid[16]) > +static bool parse_config(char *in_file, char *out_dir, const uint8_t uuid[16]) > { > int fd; > char *str; > @@ -213,7 +231,7 @@ static bool parse_config(char *in_file, char *out_file, const uint8_t uuid[16]) > } > > node_jconfig_set(node, jnode); > - node_cfg_file_set(node, out_file); > + node_path_set(node, out_dir); > > done: > close(fd); > @@ -430,15 +448,12 @@ static bool save_config(json_object *jnode, const char *config_name) > static void idle_save_config(void *user_data) > { > struct write_info *info = user_data; > - size_t len = strlen(info->config_name) + 5; > - char *tmp = l_malloc(len); > - char *bak = l_malloc(len); > + char *tmp, *bak, *cfg; > bool result = false; > > - strncpy(tmp, info->config_name, len); > - strncpy(bak, info->config_name, len); > - tmp = strncat(tmp, ".tmp", 5); > - bak = strncat(bak, ".bak", 5); > + cfg = l_strdup_printf("%s%s", info->node_path, cfg_name); > + tmp = l_strdup_printf("%s%s", cfg, tmp_ext); > + bak = l_strdup_printf("%s%s", cfg, bak_ext); > remove(tmp); > > l_debug("Storage-Wrote"); > @@ -446,13 +461,14 @@ static void idle_save_config(void *user_data) > > if (result) { > remove(bak); > - rename(info->config_name, bak); > - rename(tmp, info->config_name); > + rename(cfg, bak); > + rename(tmp, cfg); > } > > remove(tmp); > l_free(tmp); > l_free(bak); > + l_free(cfg); > > if (info->cb) > info->cb(info->user_data, result); > @@ -467,7 +483,7 @@ void storage_save_config(struct mesh_node *node, bool no_wait, > > info = l_new(struct write_info, 1); > info->jnode = node_jconfig_get(node); > - info->config_name = node_cfg_file_get(node); > + info->node_path = node_path_get(node); > info->cb = cb; > info->user_data = user_data; > > @@ -517,6 +533,7 @@ bool storage_load_nodes(const char *dir_name) > { > DIR *dir; > struct dirent *entry; > + size_t path_len = strlen(dir_name) + strlen(cfg_name) + strlen(bak_ext); > > create_dir(dir_name); > dir = opendir(dir_name); > @@ -529,33 +546,37 @@ bool storage_load_nodes(const char *dir_name) > storage_dir = dir_name; > > while ((entry = readdir(dir)) != NULL) { > - char *cfg; > - char *bak; > + char *dir, *cfg, *bak; > uint8_t uuid[16]; > + size_t node_len; > > if (entry->d_type != DT_DIR) > continue; > > - if (!str2hex(entry->d_name, strlen(entry->d_name), uuid, sizeof(uuid))) > + /* Check path length */ > + node_len = strlen(entry->d_name); > + if (path_len + node_len + 1 >= PATH_MAX) > continue; > > - cfg = l_strdup_printf("%s/%s/node.json", dir_name, entry->d_name); > - > - if (parse_config(cfg, cfg, uuid)) > + if (!str2hex(entry->d_name, node_len, uuid, sizeof(uuid))) > continue; > > - /* Fall-back to Backup version */ > - bak = l_strdup_printf("%s/%s/node.json.bak", dir_name, entry->d_name); > + dir = l_strdup_printf("%s/%s", dir_name, entry->d_name); > + cfg = l_strdup_printf("%s%s", dir, cfg_name); > > - if (parse_config(bak, cfg, uuid)) { > - remove(cfg); > - rename(bak, cfg); > - l_free(cfg); > - continue; > - } > + if (!parse_config(cfg, dir, uuid)) { > > + /* Fall-back to Backup version */ > + bak = l_strdup_printf("%s%s", cfg, bak_ext); > + > + if (parse_config(bak, dir, uuid)) { > + remove(cfg); > + rename(bak, cfg); > + } > + l_free(bak); > + } > l_free(cfg); > - l_free(bak); > + l_free(dir); > } > > return true; > @@ -566,8 +587,8 @@ bool storage_create_node_config(struct mesh_node *node, void *data) > struct mesh_db_node *db_node = data; > char uuid[33]; > char name_buf[PATH_MAX]; > - char *filename; > json_object *jnode; > + size_t max_len = strlen(cfg_name) + strlen(bak_ext); > > if (!storage_dir) > return false; > @@ -578,25 +599,26 @@ bool storage_create_node_config(struct mesh_node *node, void *data) > return false; > > if (!hex2str(node_uuid_get(node), 16, uuid, sizeof(uuid))) > - return false; > + goto fail; > > snprintf(name_buf, PATH_MAX, "%s/%s", storage_dir, uuid); > > + if (strlen(name_buf) + max_len >= PATH_MAX) > + goto fail; > + > /* Create a new directory and node.json file */ > if (mkdir(name_buf, 0755) != 0) > goto fail; > > - filename = l_strdup_printf("%s/node.json", name_buf); > + node_path_set(node, name_buf); > > - l_debug("New node config %s", filename); > + snprintf(name_buf, PATH_MAX, "%s/%s%s", storage_dir, uuid, cfg_name); > + l_debug("New node config %s", name_buf); > > - if (!save_config(jnode, filename)) { > - l_free(filename); > + if (!save_config(jnode, name_buf)) > goto fail; > - } > > node_jconfig_set(node, jnode); > - node_cfg_file_set(node, filename); > > return true; > fail: > @@ -604,13 +626,29 @@ fail: > return false; > } > > +static int del_fobject(const char *fpath, const struct stat *sb, int typeflag, > + struct FTW *ftwbuf) > +{ > + switch (typeflag) { > + case FTW_DP: > + rmdir(fpath); > + l_debug("RMDIR %s", fpath); > + break; > + > + case FTW_SL: > + default: > + remove(fpath); > + l_debug("RM %s", fpath); > + break; > + } > + return 0; > +} > + > /* Permanently remove node configuration */ > void storage_remove_node_config(struct mesh_node *node) > { > - char *cfg; > + char *node_path, *mesh_path, *mesh_name; > struct json_object *jnode; > - const char *dir_name; > - char *bak; > > if (!node) > return; > @@ -621,25 +659,17 @@ void storage_remove_node_config(struct mesh_node *node) > json_object_put(jnode); > node_jconfig_set(node, NULL); > > - /* Delete node configuration file */ > - cfg = node_cfg_file_get(node); > - if (!cfg) > - return; > - > - l_debug("Delete node config file %s", cfg); > - remove(cfg); > - > - /* Delete the backup file */ > - bak = l_strdup_printf("%s.bak", cfg); > - remove(bak); > - l_free(bak); > + node_path = node_path_get(node); > + l_debug("Delete node config %s", node_path); > > - /* Delete the node directory */ > - dir_name = dirname(cfg); > + /* Make sure path name of node follows expected guidelines */ > + mesh_path = alloc_dirname(node_path); > + mesh_name = basename(mesh_path); > + if (strcmp(mesh_name, "mesh")) > + goto done; > > - l_debug("Delete directory %s", dir_name); > - rmdir(dir_name); > + nftw(node_path, del_fobject, 5, FTW_DEPTH | FTW_PHYS); > > - l_free(cfg); > - node_cfg_file_set(node, NULL); > +done: > + l_free(mesh_path); > } ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH BlueZ v6 2/2] mesh: Add key storage 2019-05-09 21:33 [PATCH BlueZ v6 0/2] mesh: node dir Restructure, and keyring Brian Gix 2019-05-09 21:33 ` [PATCH BlueZ v6 1/2] mesh: Reconfigure node storage tree Brian Gix @ 2019-05-09 21:33 ` Brian Gix 1 sibling, 0 replies; 4+ messages in thread From: Brian Gix @ 2019-05-09 21:33 UTC (permalink / raw) To: linux-bluetooth; +Cc: inga.stotland, brian.gix, michal.lowas-rzechonek This implements internal key storage add/delete/fetch for the three basic key types managed in Mesh: Network, Application and Device. This key storage is separate from keys assigned to nodes within the mesh, and are used to support Configuration Client functionality. --- Makefile.mesh | 1 + mesh/keyring.c | 298 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mesh/keyring.h | 49 ++++++++++ 3 files changed, 348 insertions(+) create mode 100644 mesh/keyring.c create mode 100644 mesh/keyring.h diff --git a/Makefile.mesh b/Makefile.mesh index 76e424b92..bccd4d946 100644 --- a/Makefile.mesh +++ b/Makefile.mesh @@ -25,6 +25,7 @@ mesh_sources = mesh/mesh.h mesh/mesh.c \ mesh/agent.h mesh/agent.c \ mesh/prov-acceptor.c mesh/prov-initiator.c \ mesh/pb-adv.h mesh/pb-adv.c \ + mesh/keyring.h mesh/keyring.c \ mesh/mesh-defs.h libexec_PROGRAMS += mesh/bluetooth-meshd diff --git a/mesh/keyring.c b/mesh/keyring.c new file mode 100644 index 000000000..59aa1eaf4 --- /dev/null +++ b/mesh/keyring.c @@ -0,0 +1,298 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#define _GNU_SOURCE +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include <dirent.h> +#include <libgen.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#include <ell/ell.h> + +#include "mesh/mesh-defs.h" + +#include "mesh/net.h" +#include "mesh/keyring.h" +#include "mesh/mesh.h" +#include "mesh/node.h" + +const char *dev_key_dir = "/dev_keys"; +const char *app_key_dir = "/app_keys"; +const char *net_key_dir = "/net_keys"; + +bool keyring_put_net_key(struct mesh_node *node, uint16_t net_idx, + struct keyring_net_key *key) +{ + char *node_path; + char key_file[PATH_MAX]; + bool result = false; + int fd; + + if (!node || !key) + return false; + + node_path = node_path_get(node); + + if (strlen(node_path) + strlen(net_key_dir) + 1 + 3 >= PATH_MAX) + return false; + + snprintf(key_file, PATH_MAX, "%s%s", node_path, net_key_dir); + mkdir(key_file, 0755); + snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, net_key_dir, + net_idx); + l_debug("Put Net Key %s", key_file); + + fd = open(key_file, O_WRONLY | O_CREAT | O_TRUNC); + if (fd >= 0) { + if (write(fd, key, sizeof(*key)) == sizeof(*key)) + result = true; + + close(fd); + } + + return result; +} + +bool keyring_put_app_key(struct mesh_node *node, uint16_t app_idx, + uint16_t net_idx, struct keyring_app_key *key) +{ + char *node_path; + char key_file[PATH_MAX]; + bool result = false; + int fd; + + if (!node || !key) + return false; + + node_path = node_path_get(node); + + if (strlen(node_path) + strlen(app_key_dir) + 1 + 3 >= PATH_MAX) + return false; + + snprintf(key_file, PATH_MAX, "%s%s", node_path, app_key_dir); + mkdir(key_file, 0755); + snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, app_key_dir, + app_idx); + l_debug("Put App Key %s", key_file); + + fd = open(key_file, O_RDWR); + if (fd >= 0) { + struct keyring_app_key old_key; + + if (read(fd, &old_key, sizeof(old_key)) == sizeof(old_key)) { + if (old_key.net_idx != net_idx) { + close(fd); + return false; + } + } + lseek(fd, 0, SEEK_SET); + } else + fd = open(key_file, O_WRONLY | O_CREAT | O_TRUNC); + + if (fd >= 0) { + if (write(fd, key, sizeof(*key)) == sizeof(*key)) + result = true; + + close(fd); + } + + return result; +} + +bool keyring_put_remote_dev_key(struct mesh_node *node, uint16_t unicast, + uint8_t count, uint8_t dev_key[16]) +{ + char *node_path; + char key_file[PATH_MAX]; + bool result = true; + int fd, i; + + if (!node) + return false; + + node_path = node_path_get(node); + + if (strlen(node_path) + strlen(dev_key_dir) + 1 + 4 >= PATH_MAX) + return false; + + snprintf(key_file, PATH_MAX, "%s%s", node_path, dev_key_dir); + mkdir(key_file, 0755); + + for (i = 0; i < count; i++) { + snprintf(key_file, PATH_MAX, "%s%s/%4.4x", node_path, + dev_key_dir, unicast + i); + l_debug("Put Dev Key %s", key_file); + + fd = open(key_file, O_WRONLY | O_CREAT | O_TRUNC); + if (fd >= 0) { + if (write(fd, dev_key, 16) != 16) + result = false; + + close(fd); + } else + result = false; + } + + return result; +} + +bool keyring_get_net_key(struct mesh_node *node, uint16_t net_idx, + struct keyring_net_key *key) +{ + char *node_path; + char key_file[PATH_MAX]; + bool result = false; + int fd; + + if (!node || !key) + return false; + + node_path = node_path_get(node); + snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, net_key_dir, + net_idx); + + fd = open(key_file, O_RDONLY); + if (fd >= 0) { + if (read(fd, key, sizeof(*key)) == sizeof(*key)) + result = true; + + close(fd); + } + + return result; +} + +bool keyring_get_app_key(struct mesh_node *node, uint16_t app_idx, + struct keyring_app_key *key) +{ + char *node_path; + char key_file[PATH_MAX]; + bool result = false; + int fd; + + if (!node || !key) + return false; + + node_path = node_path_get(node); + snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, app_key_dir, + app_idx); + + fd = open(key_file, O_RDONLY); + if (fd >= 0) { + if (read(fd, key, sizeof(*key)) == sizeof(*key)) + result = true; + + close(fd); + } + + return result; +} + +bool keyring_get_remote_dev_key(struct mesh_node *node, uint16_t unicast, + uint8_t dev_key[16]) +{ + char *node_path; + char key_file[PATH_MAX]; + bool result = false; + int fd; + + if (!node) + return false; + + node_path = node_path_get(node); + snprintf(key_file, PATH_MAX, "%s%s/%4.4x", node_path, dev_key_dir, + unicast); + + fd = open(key_file, O_RDONLY); + if (fd >= 0) { + if (read(fd, dev_key, 16) == 16) + result = true; + + close(fd); + } + + return result; +} + +bool keyring_del_net_key(struct mesh_node *node, uint16_t net_idx) +{ + char *node_path; + char key_file[PATH_MAX]; + + if (!node) + return false; + + node_path = node_path_get(node); + snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, net_key_dir, + net_idx); + l_debug("RM Net Key %s", key_file); + remove(key_file); + + /* TODO: See if it is easiest to delete all bound App keys here */ + /* TODO: see nftw() */ + + return true; +} + +bool keyring_del_app_key(struct mesh_node *node, uint16_t app_idx) +{ + char *node_path; + char key_file[PATH_MAX]; + + if (!node) + return false; + + node_path = node_path_get(node); + snprintf(key_file, PATH_MAX, "%s%s/%3.3x", node_path, app_key_dir, + app_idx); + l_debug("RM App Key %s", key_file); + remove(key_file); + + return true; +} + +bool keyring_del_remote_dev_key(struct mesh_node *node, uint16_t unicast, + uint8_t count) +{ + char *node_path; + char key_file[PATH_MAX]; + int i; + + if (!node) + return false; + + node_path = node_path_get(node); + for (i = 0; i < count; i++) { + snprintf(key_file, PATH_MAX, "%s%s/%4.4x", node_path, + dev_key_dir, unicast + i); + l_debug("RM Dev Key %s", key_file); + remove(key_file); + } + + return true; +} diff --git a/mesh/keyring.h b/mesh/keyring.h new file mode 100644 index 000000000..167191013 --- /dev/null +++ b/mesh/keyring.h @@ -0,0 +1,49 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +struct keyring_net_key { + uint16_t net_idx; + uint8_t phase; + uint8_t old_key[16]; + uint8_t new_key[16]; +}; + +struct keyring_app_key { + uint16_t app_idx; + uint16_t net_idx; + uint8_t old_key[16]; + uint8_t new_key[16]; +}; + +bool keyring_put_net_key(struct mesh_node *node, uint16_t net_idx, + struct keyring_net_key *key); +bool keyring_get_net_key(struct mesh_node *node, uint16_t net_idx, + struct keyring_net_key *key); +bool keyring_del_net_key(struct mesh_node *node, uint16_t net_idx); +bool keyring_put_app_key(struct mesh_node *node, uint16_t app_idx, + uint16_t net_idx, struct keyring_app_key *key); +bool keyring_get_app_key(struct mesh_node *node, uint16_t app_idx, + struct keyring_app_key *key); +bool keyring_del_app_key(struct mesh_node *node, uint16_t app_idx); +bool keyring_get_remote_dev_key(struct mesh_node *node, uint16_t unicast, + uint8_t dev_key[16]); +bool keyring_put_remote_dev_key(struct mesh_node *node, uint16_t unicast, + uint8_t count, uint8_t dev_key[16]); +bool keyring_del_remote_dev_key(struct mesh_node *node, uint16_t unicast, + uint8_t count); -- 2.14.5 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2019-05-13 19:32 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2019-05-09 21:33 [PATCH BlueZ v6 0/2] mesh: node dir Restructure, and keyring Brian Gix 2019-05-09 21:33 ` [PATCH BlueZ v6 1/2] mesh: Reconfigure node storage tree Brian Gix 2019-05-13 19:32 ` Gix, Brian 2019-05-09 21:33 ` [PATCH BlueZ v6 2/2] mesh: Add key storage Brian Gix
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).