diff options
author | Dimitri Staessens <dimitri@ouroboros.rocks> | 2025-08-13 09:03:20 +0200 |
---|---|---|
committer | Dimitri Staessens <dimitri@ouroboros.rocks> | 2025-08-18 20:57:23 +0200 |
commit | e35302ca0ab64edd21b9d8e40d3aa74a3a4f4f7e (patch) | |
tree | 348711a66a585f982b19979f083e601fc85ed605 /src/irmd/reg/reg.c | |
parent | f1fcec220c8454cb461bd1ac22621a1b64609051 (diff) | |
download | ouroboros-e35302ca0ab64edd21b9d8e40d3aa74a3a4f4f7e.tar.gz ouroboros-e35302ca0ab64edd21b9d8e40d3aa74a3a4f4f7e.zip |
irmd: Add flow authentication
This adds initial implementation of peer authentication as part of
flow allocation. If credentials are not provided, this will be
accepted and logged as info that the flow is not authenticated.
Certificates and keys are passed as .pem files. The key file should
not be encrypted, else the IRMd will open a prompt for the password.
The default location for these .pem files is in
/etc/ouroboros/security. It is strongly recommended to make this
directory only accessible to root.
├── security
│ ├── cacert
│ │ └── ca.root.o7s.crt.pem
│ ├── client
│ │ ├── <name>
│ │ | ├── crt.pem
│ │ | └── key.pem
│ │ └── <name>
| | ├──...
| |
│ ├── server
│ │ ├── <name>
│ │ | ├── crt.pem
│ │ | └── key.pem
│ │ └── <name>
| | ├── ...
| |
│ └── untrusted
│ └── sign.root.o7s.crt.pem
Trusted root CA certificates go in the /cacert directory, untrusted
certificates for signature verification go in the /untrusted
directory. The IRMd will load these certificates at boot. The IRMd
will look for certificates in the /client and /server directories. For
each name a subdirectory can be added and the credentials in that
directory are used to sign the OAP header for flows at flow_alloc() on
the client side and flow_accept() on the server side.
These defaults can be changed at build time using the following
variables (in alphabetical order):
OUROBOROS_CA_CRT_DIR /etc/ouroboros/security/cacert
OUROBOROS_CLI_CRT_DIR /etc/ouroboros/security/client
OUROBOROS_SECURITY_DIR /etc/ouroboros/security
OUROBOROS_SRV_CRT_DIR /etc/ouroboros/security/server
OUROBOROS_UNTRUSTED_DIR /etc/ouroboros/security/untrusted
The directories for the names can also be configured at IRMd boot
using the configuraton file and at runtime when a name is created
using the "irm name create" CLI tool. The user needs to have
permissions to access the keyfile and certificate when specifying the
paths with the "irm name create" CLI tool.
Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
Diffstat (limited to 'src/irmd/reg/reg.c')
-rw-r--r-- | src/irmd/reg/reg.c | 98 |
1 files changed, 69 insertions, 29 deletions
diff --git a/src/irmd/reg/reg.c b/src/irmd/reg/reg.c index 8d1fa8cf..0d4c6f24 100644 --- a/src/irmd/reg/reg.c +++ b/src/irmd/reg/reg.c @@ -28,6 +28,7 @@ The IPC Resource Manager - Registry #include <ouroboros/errno.h> #include <ouroboros/list.h> #include <ouroboros/logs.h> +#include <ouroboros/protobuf.h> #include <ouroboros/pthread.h> #include "reg.h" @@ -46,6 +47,7 @@ The IPC Resource Manager - Registry struct { struct bmp * flow_ids; /* flow_ids for flows */ + struct list_head flows; /* flow information */ size_t n_flows; /* number of flows */ @@ -196,6 +198,10 @@ static int __reg_get_pending_flow_id(const char * name) struct reg_flow * flow; pid_t pid; + assert(name != NULL); + assert(strlen(name) > 0); + assert(strlen(name) < NAME_SIZE + 1); + entry =__reg_get_name(name); if (entry == NULL) return -ENAME; @@ -205,7 +211,10 @@ static int __reg_get_pending_flow_id(const char * name) return -EAGAIN; flow = __reg_get_accept_flow(pid); - assert(flow != NULL); + if (flow == NULL) /* compiler barks, this can't be NULL */ + return -EAGAIN; + + strcpy(flow->name, name); return flow->info.id; } @@ -580,6 +589,14 @@ void reg_clear(void) reg.n_procs--; } + list_for_each_safe(p, h, ®.flows) { + struct reg_flow * entry; + entry = list_entry(p, struct reg_flow, next); + list_del(&entry->next); + reg_flow_destroy(entry); + reg.n_flows--; + } + list_for_each_safe(p, h, ®.names) { struct reg_name * entry; entry = list_entry(p, struct reg_name, next); @@ -596,14 +613,6 @@ void reg_clear(void) reg.n_ipcps--; } - list_for_each_safe(p, h, ®.flows) { - struct reg_flow * entry; - entry = list_entry(p, struct reg_flow, next); - list_del(&entry->next); - reg_flow_destroy(entry); - reg.n_flows--; - } - pthread_mutex_unlock(®.mtx); } @@ -950,6 +959,34 @@ bool reg_has_name(const char * name) return ret; } +int reg_get_name_info(const char * name, + struct name_info * info) +{ + struct reg_name * n; + + assert(name != NULL); + assert(info != NULL); + + pthread_mutex_lock(®.mtx); + + n = __reg_get_name(name); + if (n == NULL) { + log_err("Name %s does not exist.", name); + goto no_name; + } + + *info = n->info; + + pthread_mutex_unlock(®.mtx); + + return 0; + + no_name: + pthread_mutex_unlock(®.mtx); + return -ENOENT; + +} + int reg_get_name_for_hash(char * buf, enum hash_algo algo, const uint8_t * hash) @@ -986,29 +1023,20 @@ int reg_get_name_for_hash(char * buf, return name == NULL ? -ENOENT : 0; } - -static int __get_name_info(name_info_msg_t ** msg, - struct reg_name * n) +int reg_get_name_for_flow_id(char * buf, + int flow_id) { - *msg = malloc(sizeof(**msg)); - if (*msg == NULL) - goto fail; - - name_info_msg__init(*msg); + struct reg_flow * f; - (*msg)->name = strdup(n->info.name); - if ((*msg)->name == NULL) - goto fail_msg; + pthread_mutex_lock(®.mtx); - (*msg)->pol_lb = n->info.pol_lb; + f = __reg_get_flow(flow_id); + if (f != NULL) + strcpy(buf, f->name); - return 0; + pthread_mutex_unlock(®.mtx); - fail_msg: - name_info_msg__free_unpacked(*msg, NULL); - *msg = NULL; - fail: - return -1; + return f == NULL ? -ENOENT : 0; } int reg_list_names(name_info_msg_t *** names) @@ -1030,10 +1058,20 @@ int reg_list_names(name_info_msg_t *** names) list_for_each(p, ®.names) { struct reg_name * entry; entry = list_entry(p, struct reg_name, next); - if (__get_name_info(&(*names)[i], entry) < 0) { + (*names)[i] = name_info_s_to_msg(&entry->info); + if ((*names)[i] == NULL) { log_err("Failed to create name list info."); goto fail; } + /* wipe security info to avoid huge messages */ + free((*names)[i]->scrt); + (*names)[i]->scrt = NULL; + free((*names)[i]->skey); + (*names)[i]->skey = NULL; + free((*names)[i]->ccrt); + (*names)[i]->ccrt = NULL; + free((*names)[i]->ckey); + (*names)[i]->ckey = NULL; i++; } @@ -1947,12 +1985,14 @@ void reg_dealloc_flow(struct flow_info * info) assert(flow != NULL); assert(flow->data.data == NULL); assert(flow->data.len == 0); - assert(flow->info.state == FLOW_ALLOCATED); + flow->info.state = FLOW_DEALLOC_PENDING; info->state = FLOW_DEALLOC_PENDING; info->n_1_pid = flow->info.n_1_pid; + memset(flow->name, 0, sizeof(flow->name)); + reg_flow_update(flow, info); pthread_mutex_unlock(®.mtx); |