summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2025-08-13 09:03:20 +0200
committerDimitri Staessens <dimitri@ouroboros.rocks>2025-08-18 20:57:23 +0200
commite35302ca0ab64edd21b9d8e40d3aa74a3a4f4f7e (patch)
tree348711a66a585f982b19979f083e601fc85ed605 /src/tools
parentf1fcec220c8454cb461bd1ac22621a1b64609051 (diff)
downloadouroboros-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/tools')
-rw-r--r--src/tools/irm/irm_name_create.c124
-rw-r--r--src/tools/irm/irm_name_reg.c37
2 files changed, 141 insertions, 20 deletions
diff --git a/src/tools/irm/irm_name_create.c b/src/tools/irm/irm_name_create.c
index a0079cad..04d7f95f 100644
--- a/src/tools/irm/irm_name_create.c
+++ b/src/tools/irm/irm_name_create.c
@@ -36,31 +36,50 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define _POSIX_C_SOURCE 200809L
+#define _XOPEN_SOURCE 500
+
+#include <ouroboros/errno.h>
#include <ouroboros/irm.h>
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "irm_ops.h"
#include "irm_utils.h"
#define RR "round-robin"
#define SPILL "spillover"
+#define SCRT "<security_dir>/server/<name>/crt.pem"
+#define SKEY "<security_dir>/server/<name>/key.pem"
+#define CCRT "<security_dir>/client/<name>/crt.pem"
+#define CKEY "<security_dir>/client/<name>/key.pem"
static void usage(void)
{
printf("Usage: irm name create\n"
- " <name>\n"
- " lb [LB_POLICY], default: %s\n\n"
- "where LB_POLICY in {" RR " " SPILL "}\n", RR);
+ " <name>. max %d chars.\n"
+ " [lb LB_POLICY], default: %s\n"
+ " [scrtpath <path>, default: " SCRT "]\n"
+ " [skeypath <path>, default: " SKEY "]\n"
+ " [ccrtpath <path>, default: " CCRT "]\n"
+ " [ckeypath <path>, default: " CKEY "]\n"
+ "\n"
+ "where LB_POLICY in {" RR " " SPILL "}\n",
+ NAME_SIZE, RR);
}
int do_create_name(int argc,
char ** argv)
{
- char * name = NULL;
- char * lb_pol = RR;
- enum pol_balance pol_lb = LB_RR;
+ struct name_info info = {};
+ char * name = NULL;
+ char * scrtpath = NULL;
+ char * skeypath = NULL;
+ char * ccrtpath = NULL;
+ char * ckeypath = NULL;
+ char * lb_pol = RR;
name = *(argv++);
--argc;
@@ -68,6 +87,14 @@ int do_create_name(int argc,
while (argc > 0) {
if (matches(*argv, "lb") == 0) {
lb_pol = *(argv + 1);
+ } else if (matches(*argv, "scrtpath") == 0) {
+ scrtpath = *(argv + 1);
+ } else if (matches(*argv, "skeypath") == 0) {
+ skeypath = *(argv + 1);
+ } else if (matches(*argv, "ccrtpath") == 0) {
+ ccrtpath = *(argv + 1);
+ } else if (matches(*argv, "ckeypath") == 0) {
+ ckeypath = *(argv + 1);
} else {
printf("\"%s\" is unknown, try \"irm "
"name create\".\n", *argv);
@@ -78,19 +105,92 @@ int do_create_name(int argc,
argv += 2;
}
- if (name == NULL) {
- usage();
- return -1;
+ if (name == NULL)
+ goto fail;
+
+ if (strlen(name) > NAME_SIZE) {
+ printf("Name too long.\n");
+ goto fail;
+ }
+
+ strcpy(info.name, name);
+
+ if (scrtpath != NULL) {
+ scrtpath = realpath(scrtpath, NULL);
+ if (scrtpath == NULL) {
+ printf("Failed to resolve server crt path: %s.\n",
+ strerror(errno));
+ goto fail;
+ }
+ if (strlen(scrtpath) > NAME_PATH_SIZE) {
+ printf("Server crt path > %d chars.", NAME_PATH_SIZE);
+ free(scrtpath);
+ goto fail;
+ }
+ strcpy(info.s.crt, scrtpath);
+ free(scrtpath);
+ }
+
+ if (skeypath != NULL) {
+ skeypath = realpath(skeypath, NULL);
+ if (skeypath == NULL) {
+ printf("Failed to resolve server key path: %s.\n",
+ strerror(errno));
+ goto fail;
+ }
+ if (strlen(skeypath) > NAME_PATH_SIZE) {
+ printf("Server key path > %d chars.", NAME_PATH_SIZE);
+ free(skeypath);
+ goto fail;
+ }
+ strcpy(info.s.key, skeypath);
+ free(skeypath);
+ }
+
+ if (ccrtpath != NULL) {
+ ccrtpath = realpath(ccrtpath, NULL);
+ if (ccrtpath == NULL) {
+ printf("Failed to resolve client crt path: %s.\n",
+ strerror(errno));
+ goto fail;
+ }
+ if (strlen(ccrtpath) > NAME_PATH_SIZE) {
+ printf("Client crt path > %d chars.", NAME_PATH_SIZE);
+ free(ccrtpath);
+ goto fail;
+ }
+ strcpy(info.c.crt, ccrtpath);
+ free(ccrtpath);
+ }
+
+ if (ckeypath != NULL) {
+ ckeypath = realpath(ckeypath, NULL);
+ if (ckeypath == NULL) {
+ printf("Failed to resolve client key path: %s.\n",
+ strerror(errno));
+ goto fail;
+ }
+
+ if (strlen(ckeypath) > NAME_PATH_SIZE) {
+ printf("Client key path > %d chars.", NAME_PATH_SIZE);
+ free(ckeypath);
+ goto fail;
+ }
+ strcpy(info.c.key, ckeypath);
+ free(ckeypath);
}
if (strcmp(lb_pol, RR) == 0)
- pol_lb = LB_RR;
+ info.pol_lb = LB_RR;
else if (strcmp(lb_pol, SPILL) == 0)
- pol_lb = LB_SPILL;
+ info.pol_lb = LB_SPILL;
else {
usage();
return -1;
}
- return irm_create_name(name, pol_lb);
+ return irm_create_name(&info);
+ fail:
+ usage();
+ return -1;
}
diff --git a/src/tools/irm/irm_name_reg.c b/src/tools/irm/irm_name_reg.c
index 061ed8be..7689119a 100644
--- a/src/tools/irm/irm_name_reg.c
+++ b/src/tools/irm/irm_name_reg.c
@@ -107,14 +107,23 @@ int do_reg_name(int argc,
return -1;
}
+ if (strlen(name) > NAME_SIZE) {
+ printf("Name too long.\n");
+ usage();
+ return -1;
+ }
+
ipcps_len = irm_list_ipcps(&ipcps);
- if (ipcps_len < 0)
- return ipcps_len;
+ if (ipcps_len <= 0) {
+ printf("Failed to list IPCPs.\n");
+ return -1;
+ }
names_len = irm_list_names(&names);
if (names_len < 0) {
+ printf("Failed to list names.\n");
free(ipcps);
- return names_len;
+ return -1;
}
for (i = 0; i < names_len; ++i) {
@@ -124,11 +133,19 @@ int do_reg_name(int argc,
}
}
- if (name_create && irm_create_name(name, LB_SPILL)) {
- printf("Error creating name.");
- free(ipcps);
- free(name);
- return -1;
+ if (name_create) {
+ struct name_info info = {
+ .pol_lb = LB_SPILL
+ };
+
+ strcpy(info.name, name);
+
+ if (irm_create_name(&info) < 0) {
+ printf("Error creating name.");
+ free(ipcps);
+ free(names);
+ return -1;
+ }
}
for (i = 0; i < ipcps_len; ++i) {
@@ -136,6 +153,8 @@ int do_reg_name(int argc,
for (j = 0; j < layers_len; j++) {
if (wildcard_match(layers[j], ipcps[i].layer) == 0) {
if (irm_reg_name(name, ipcps[i].pid)) {
+ printf("Failed to register with %s",
+ ipcps[i].layer);
free(ipcps);
free(names);
return -1;
@@ -145,6 +164,8 @@ int do_reg_name(int argc,
for (j = 0; j < ipcp_len; j++) {
if (wildcard_match(ipcp[j], ipcps[i].name) == 0) {
if (irm_reg_name(name, ipcps[i].pid)) {
+ printf("Failed to register with %s",
+ ipcps[i].name);
free(ipcps);
free(names);
return -1;