diff options
Diffstat (limited to 'src/irmd')
-rw-r--r-- | src/irmd/CMakeLists.txt | 18 | ||||
-rw-r--r-- | src/irmd/config.h.in | 7 | ||||
-rw-r--r-- | src/irmd/configfile.c | 115 | ||||
-rw-r--r-- | src/irmd/irmd.h | 2 | ||||
-rw-r--r-- | src/irmd/main.c | 648 | ||||
-rw-r--r-- | src/irmd/reg/flow.h | 3 | ||||
-rw-r--r-- | src/irmd/reg/name.c | 74 | ||||
-rw-r--r-- | src/irmd/reg/name.h | 28 | ||||
-rw-r--r-- | src/irmd/reg/reg.c | 98 | ||||
-rw-r--r-- | src/irmd/reg/reg.h | 6 | ||||
-rw-r--r-- | src/irmd/reg/tests/name_test.c | 51 | ||||
-rw-r--r-- | src/irmd/reg/tests/reg_test.c | 7 | ||||
-rw-r--r-- | src/irmd/tests/oap_test.c | 10 |
13 files changed, 836 insertions, 231 deletions
diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt index 965c4b3d..46d49391 100644 --- a/src/irmd/CMakeLists.txt +++ b/src/irmd/CMakeLists.txt @@ -4,13 +4,14 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${CMAKE_BINARY_DIR}/include) +set(OUROBOROS_CONFIG_DIR /etc/ouroboros CACHE STRING + "Configuration directory") + find_library(LIBTOML_LIBRARIES toml QUIET) if (LIBTOML_LIBRARIES) set(DISABLE_CONFIGFILE FALSE CACHE BOOL "Disable configuration file support") if (NOT DISABLE_CONFIGFILE) - set(OUROBOROS_CONFIG_DIR /etc/ouroboros/ CACHE STRING - "Configuration directory") set(OUROBOROS_CONFIG_FILE irmd.conf CACHE STRING "Name of the IRMd configuration file") set(HAVE_TOML TRUE) @@ -28,7 +29,6 @@ if (LIBTOML_LIBRARIES) else () message(STATUS "Configuration file support disabled by user") unset(OUROBOROS_CONFIG_FILE CACHE) - unset(OUROBOROS_CONFIG_DIR CACHE) set(HAVE_TOML FALSE) endif () else () @@ -39,9 +39,19 @@ else () unset(HAVE_TOML) endif () +set(OUROBOROS_SECURITY_DIR "${OUROBOROS_CONFIG_DIR}/security" CACHE STRING + "Security directory holding authentication information") +set(OUROBOROS_CA_CRT_DIR "${OUROBOROS_SECURITY_DIR}/cacert" CACHE STRING + "Directory holding trusted CA certificates") +set(OUROBOROS_SRV_CRT_DIR "${OUROBOROS_SECURITY_DIR}/server" CACHE STRING + "Directory holding trusted CA certificates") +set(OUROBOROS_CLI_CRT_DIR "${OUROBOROS_SECURITY_DIR}/client" CACHE STRING + "Directory holding trusted CA certificates") +set(OUROBOROS_UNTRUSTED_DIR "${OUROBOROS_SECURITY_DIR}/untrusted" CACHE STRING + "Directory holding untrusted intermediate certificates") + set(IRMD_REQ_ARR_TIMEOUT 1000 CACHE STRING "Timeout for an application to respond to a new flow (ms)") - set(BOOTSTRAP_TIMEOUT 5000 CACHE STRING "Timeout for an IPCP to bootstrap (ms)") set(ENROLL_TIMEOUT 20000 CACHE STRING diff --git a/src/irmd/config.h.in b/src/irmd/config.h.in index 6bf3817b..c829cfb7 100644 --- a/src/irmd/config.h.in +++ b/src/irmd/config.h.in @@ -50,7 +50,6 @@ #define IRMD_MIN_THREADS @IRMD_MIN_THREADS@ #define IRMD_ADD_THREADS @IRMD_ADD_THREADS@ - #cmakedefine HAVE_FUSE #ifdef HAVE_FUSE #define FUSE_PREFIX "@FUSE_PREFIX@" @@ -62,6 +61,12 @@ #define OUROBOROS_CONFIG_FILE "@OUROBOROS_CONFIG_FILE@" #endif +#define OUROBOROS_SECURITY_DIR "@OUROBOROS_SECURITY_DIR@" +#define OUROBOROS_CA_CRT_DIR "@OUROBOROS_CA_CRT_DIR@" +#define OUROBOROS_SRV_CRT_DIR "@OUROBOROS_SRV_CRT_DIR@" +#define OUROBOROS_CLI_CRT_DIR "@OUROBOROS_CLI_CRT_DIR@" +#define OUROBOROS_CHAIN_DIR "@OUROBOROS_UNTRUSTED_DIR@" + #define IRMD_PKILL_TIMEOUT @IRMD_PKILL_TIMEOUT@ #cmakedefine IRMD_KILL_ALL_PROCESSES diff --git a/src/irmd/configfile.c b/src/irmd/configfile.c index 14b03d53..229a3fd3 100644 --- a/src/irmd/configfile.c +++ b/src/irmd/configfile.c @@ -258,7 +258,7 @@ static int toml_dir(toml_table_t * table, if (!BETWEEN(alpha.u.i, DHT_ALPHA_MIN, DHT_ALPHA_MAX)) { log_err("Invalid alpha value: %ld", - alpha.u.i); + (long) alpha.u.i); return -EINVAL; } DHT(conf, alpha) = alpha.u.i; @@ -268,7 +268,7 @@ static int toml_dir(toml_table_t * table, if (!BETWEEN(t_expire.u.i, DHT_T_EXPIRE_MIN, DHT_T_EXPIRE_MAX)) { log_err("Invalid expire time: %ld", - t_expire.u.i); + (long) t_expire.u.i); return -EINVAL; } DHT(conf, t_expire) = t_expire.u.i; @@ -278,7 +278,7 @@ static int toml_dir(toml_table_t * table, if (!BETWEEN(t_refresh.u.i, DHT_T_REFRESH_MIN, DHT_T_REFRESH_MAX)) { log_err("Invalid refresh time: %ld", - t_refresh.u.i); + (long) t_refresh.u.i); return -EINVAL; } DHT(conf, t_refresh) = t_refresh.u.i; @@ -288,7 +288,7 @@ static int toml_dir(toml_table_t * table, if (!BETWEEN(t_replicate.u.i, DHT_T_REPLICATE_MIN, DHT_T_REPLICATE_MAX)) { log_err("Invalid replication time: %ld", - t_replicate.u.i); + (long) t_replicate.u.i); return -EINVAL; } DHT(conf, t_replicate) = t_replicate.u.i; @@ -297,7 +297,7 @@ static int toml_dir(toml_table_t * table, if (k.ok) { if (!BETWEEN(k.u.i, DHT_K_MIN, DHT_K_MAX)) { log_err("Invalid replication factor: %ld", - k.u.i); + (long) k.u.i); return -EINVAL; } DHT(conf, k) = k.u.i; @@ -344,7 +344,7 @@ static int toml_routing(toml_table_t * table, if (t_recalc.ok) { if (t_recalc.u.i < 1) { log_err("Invalid ls_t_recalc value: %ld", - t_recalc.u.i); + (long) t_recalc.u.i); return -EINVAL; } conf->routing.ls.t_recalc = t_recalc.u.i; @@ -353,7 +353,7 @@ static int toml_routing(toml_table_t * table, if (t_update.ok) { if (t_update.u.i < 1) { log_err("Invalid ls_t_update value: %ld", - t_update.u.i); + (long) t_update.u.i); return -EINVAL; } conf->routing.ls.t_update = t_update.u.i; @@ -362,7 +362,7 @@ static int toml_routing(toml_table_t * table, if (t_timeo.ok) { if (t_timeo.u.i < 1) { log_err("Invalid ls_t_timeo value: %ld", - t_timeo.u.i); + (long) t_timeo.u.i); return -EINVAL; } conf->routing.ls.t_timeo = t_timeo.u.i; @@ -833,15 +833,27 @@ static int toml_prog_list(toml_array_t * progs, static int toml_name(toml_table_t * table, const char * name) { - toml_array_t * progs; - toml_array_t * args; - toml_datum_t lb; + toml_array_t * progs; + toml_array_t * args; + toml_datum_t lb; + toml_datum_t scrt; + toml_datum_t skey; + toml_datum_t ccrt; + toml_datum_t ckey; + struct name_info info = { .pol_lb = LB_SPILL }; log_dbg("Found service name %s in configuration file.", name); + if (strlen(name) > NAME_SIZE) { + log_err("Name too long: %s", name); + return -1; + } + + strcpy(info.name, name); + lb = toml_string_in(table, "lb"); if (lb.ok) { if (strcmp(lb.u.s, "spill") == 0) @@ -858,7 +870,83 @@ static int toml_name(toml_table_t * table, return -1; } - strcpy(info.name, name); + scrt = toml_string_in(table, "server_crt_file"); + if (scrt.ok) { + char * scrt_path = realpath(scrt.u.s, NULL); + if (scrt_path == NULL) { + log_err("Failed to check path for %s: %s.", + scrt.u.s, strerror(errno)); + free(scrt.u.s); + return -1; + } + if (strlen(scrt.u.s) > NAME_PATH_SIZE) { + log_err("Server certificate file path too long: %s", + scrt_path); + free(scrt.u.s); + return -1; + } + strcpy(info.s.crt, scrt_path); + free(scrt_path); + free(scrt.u.s); + } + + skey = toml_string_in(table, "server_key_file"); + if (skey.ok) { + char * skey_path = realpath(skey.u.s, NULL); + if (skey_path == NULL) { + log_err("Failed to check path for %s: %s.", + skey.u.s, strerror(errno)); + free(skey.u.s); + return -1; + } + if (strlen(skey.u.s) > NAME_PATH_SIZE) { + log_err("Server key file path too long: %s", skey_path); + free(skey.u.s); + return -1; + } + strcpy(info.s.key, skey_path); + free(skey_path); + free(skey.u.s); + } + + ccrt = toml_string_in(table, "client_crt_file"); + if (ccrt.ok) { + char * ccrt_path = realpath(ccrt.u.s, NULL); + if (ccrt_path == NULL) { + log_err("Failed to check path for %s: %s.", + ccrt.u.s, strerror(errno)); + free(ccrt.u.s); + return -1; + } + if (strlen(ccrt.u.s) > NAME_PATH_SIZE) { + log_err("Client certificate file path too long: %s", + ccrt_path); + free(ccrt.u.s); + return -1; + } + strcpy(info.c.crt, ccrt_path); + free(ccrt_path); + free(ccrt.u.s); + } + + ckey = toml_string_in(table, "client_key_file"); + if (ckey.ok) { + char * ckey_path = realpath(ckey.u.s, NULL); + if (ckey_path == NULL) { + log_err("Failed to check path for %s: %s.", + ckey.u.s, strerror(errno)); + free(ckey.u.s); + return -1; + } + if (strlen(ckey.u.s) > NAME_PATH_SIZE) { + log_err("Client key file path too long: %s", ckey_path); + free(ckey.u.s); + return -1; + } + strcpy(info.c.key, ckey_path); + free(ckey_path); + free(ckey.u.s); + } if (name_create(&info) < 0) { log_err("Failed to create name %s.", name); @@ -976,7 +1064,8 @@ int irm_configure(const char * path) rp = realpath(path, NULL); if (rp == NULL) { - log_err("Failed to resolve path for %s", path); + log_err("Failed to check path for %s: %s.", + path, strerror(errno)); goto fail_resolve; } diff --git a/src/irmd/irmd.h b/src/irmd/irmd.h index cf8f6953..3e54904a 100644 --- a/src/irmd/irmd.h +++ b/src/irmd/irmd.h @@ -39,7 +39,7 @@ int connect_ipcp(pid_t pid, const char * component, qosspec_t qs); -int name_create(const struct name_info * info); +int name_create(struct name_info * info); int name_reg(const char * name, pid_t pid); diff --git a/src/irmd/main.c b/src/irmd/main.c index 4acd0ef3..e799666f 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -55,6 +55,7 @@ #include "reg/reg.h" #include "configfile.h" +#include <dirent.h> #include <sys/socket.h> #include <sys/un.h> #include <signal.h> @@ -74,6 +75,7 @@ #define IPCP_HASH_LEN(p) hash_len((p)->dir_hash_algo) #define BIND_TIMEOUT 10 /* ms */ #define TIMESYNC_SLACK 100 /* ms */ +#define OAP_SEEN_TIMER 20 /* s */ #define DEALLOC_TIME 300 /* s */ enum irm_state { @@ -82,6 +84,13 @@ enum irm_state { IRMD_SHUTDOWN }; +struct oaph { + struct list_head next; + + uint64_t stamp; + uint8_t id[OAP_ID_SIZE]; +}; + struct cmd { struct list_head next; @@ -95,6 +104,12 @@ struct { #ifdef HAVE_TOML char * cfg_file; /* configuration file path */ #endif + struct { + struct auth_ctx * ctx; /* default authentication ctx */ + struct list_head list; /* OAP headers seen before */ + pthread_mutex_t mtx; /* mutex for OAP headers */ + } auth; + struct lockfile * lf; /* single irmd per system */ struct shm_rdrbuff * rdrb; /* rdrbuff for packets */ @@ -427,6 +442,65 @@ static int disconnect_ipcp(pid_t pid, return 0; } +static void name_update_sec_paths(struct name_info * info) +{ + char * srv_dir = OUROBOROS_SRV_CRT_DIR; + char * cli_dir = OUROBOROS_CLI_CRT_DIR; + + assert(info != NULL); + + if (strlen(info->s.crt) == 0) + sprintf(info->s.crt, "%s/%s/crt.pem", srv_dir, info->name); + + if (strlen(info->s.key) == 0) + sprintf(info->s.key, "%s/%s/key.pem", srv_dir, info->name); + + if (strlen(info->c.crt) == 0) + sprintf(info->c.crt, "%s/%s/crt.pem", cli_dir, info->name); + + if (strlen(info->c.key) == 0) + sprintf(info->c.key, "%s/%s/key.pem", cli_dir, info->name); +} + +int name_create(struct name_info * info) +{ + int ret; + + assert(info != NULL); + + name_update_sec_paths(info); + + ret = reg_create_name(info); + if (ret == -EEXIST) { + log_info("Name %s already exists.", info->name); + return 0; + } + + if (ret < 0) { + log_err("Failed to create name %s.", info->name); + return -1; + } + + log_info("Created new name: %s.", info->name); + + return 0; +} + +static int name_destroy(const char * name) +{ + + assert(name != NULL); + + if (reg_destroy_name(name) < 0) { + log_err("Failed to destroy name %s.", name); + return -1; + } + + log_info("Destroyed name: %s.", name); + + return 0; +} + int bind_program(char ** exec, const char * name, uint8_t flags) @@ -450,10 +524,8 @@ int bind_program(char ** exec, if (!reg_has_name(name)) { ni.pol_lb = LB_SPILL; strcpy(ni.name, name); - if (reg_create_name(&ni) < 0) { - log_err("Failed to create name %s.", name); + if (name_create(&ni) < 0) goto fail_name; - } } if (reg_bind_prog(name, exec, flags) < 0) { @@ -499,10 +571,8 @@ int bind_process(pid_t pid, if (!reg_has_name(name)) { ni.pol_lb = LB_SPILL; strcpy(ni.name, name); - if (reg_create_name(&ni) < 0) { - log_err("Failed to create name %s.", name); + if (name_create(&ni) < 0) goto fail; - } } if (reg_bind_proc(name, pid) < 0) { @@ -583,43 +653,6 @@ static int list_ipcps(ipcp_list_msg_t *** ipcps, return -1; } -int name_create(const struct name_info * info) -{ - int ret; - - assert(info != NULL); - - ret = reg_create_name(info); - if (ret == -EEXIST) { - log_info("Name %s already exists.", info->name); - return 0; - } - - if (ret < 0) { - log_err("Failed to create name %s.", info->name); - return -1; - } - - log_info("Created new name: %s.", info->name); - - return 0; -} - -static int name_destroy(const char * name) -{ - - assert(name != NULL); - - if (reg_destroy_name(name) < 0) { - log_err("Failed to destroy name %s.", name); - return -1; - } - - log_info("Destroyed name: %s.", name); - - return 0; -} - static int list_names(name_info_msg_t *** names, size_t * n_names) { @@ -762,22 +795,244 @@ static void __cleanup_flow(void * flow) reg_destroy_flow(((struct flow_info *) flow)->id); } +static bool file_exists(const char * path) +{ + struct stat s; + + if (stat(path, &s) < 0 && errno == ENOENT) { + log_dbg("File %s does not exist.", path); + return false; + } + + return true; +} + +static int load_credentials(const char * name, + const struct name_sec_paths * paths, + void ** pkp, + void ** crt) +{ + assert(paths != NULL); + assert(pkp != NULL); + assert(crt != NULL); + + *pkp = NULL; + *crt = NULL; + + if (!file_exists(paths->crt) || !file_exists(paths->key)) { + log_info("No security info for %s.", name); + return 0; + } + + if (crypt_load_crt_file(paths->crt, crt) < 0) { + log_err("Failed to load %s for %s.", paths->crt, name); + goto fail_crt; + } + + if (crypt_load_privkey_file(paths->key, pkp) < 0) { + log_err("Failed to load %s for %s.", paths->key, name); + goto fail_key; + } + + log_info("Loaded security keys for %s.", name); + + return 0; + + fail_key: + crypt_free_crt(*crt); + *crt = NULL; + fail_crt: + return -EAUTH; +} + +static int load_srv_credentials(const char * name, + void ** pkp, + void ** crt) +{ + struct name_info info; + + assert(name != NULL); + assert(pkp != NULL); + assert(crt != NULL); + + if (reg_get_name_info(name, &info) < 0) { + log_err("Failed to get name info for %s.", name); + return -ENAME; + } + + return load_credentials(name, &info.s, pkp, crt); +} + +static int load_cli_credentials(const char * name, + void ** pkp, + void ** crt) +{ + struct name_info info; + + assert(name != NULL); + assert(pkp != NULL); + assert(crt != NULL); + + if (reg_get_name_info(name, &info) < 0) { + log_err("Failed to get name info for %s.", name); + return -ENAME; + } + + return load_credentials(name, &info.c, pkp, crt); +} + +#define ID_IS_EQUAL(id1, id2) (memcmp(id1, id2, OAP_ID_SIZE) == 0) +static int irm_check_oap_hdr(const struct oap_hdr * oap_hdr, + time_t mpl) +{ + struct list_head * p; + struct list_head * h; + struct timespec now; + struct oaph * new; + uint64_t stamp; + uint64_t cur; + uint8_t * id; + ssize_t delta; + + assert(oap_hdr != NULL); + + stamp = oap_hdr->timestamp; + id = oap_hdr->id.data; + + clock_gettime(CLOCK_REALTIME, &now); + + cur = TS_TO_UINT64(now); + + delta = (ssize_t)(cur - stamp) / MILLION; + if (delta > mpl) + log_warn("Transit time exceeds MPL by %zd ms.", delta); + if (delta < -TIMESYNC_SLACK) + log_warn("OAP header sent %zd ms from the future.", -delta); + + new = malloc(sizeof(*new)); + if (new == NULL) { + log_err("Failed to allocate memory for OAP element."); + return -ENOMEM; + } + + pthread_mutex_lock(&irmd.auth.mtx); + + list_for_each_safe(p, h, &irmd.auth.list) { + struct oaph * oaph = list_entry(p, struct oaph, next); + if (cur > oaph->stamp + OAP_SEEN_TIMER * BILLION) { + list_del(&oaph->next); + free(oaph); + continue; + } + + if (oaph->stamp == stamp && ID_IS_EQUAL(oaph->id, id)) { + log_warn("OAP header already known: " HASH_FMT64 ".", + HASH_VAL64(id)); + goto fail_replay; + } + } + + memcpy(new->id, id, OAP_ID_SIZE); + new->stamp = stamp; + + list_add_tail(&new->next, &irmd.auth.list); + + pthread_mutex_unlock(&irmd.auth.mtx); + + return 0; + + fail_replay: + pthread_mutex_unlock(&irmd.auth.mtx); + free(new); + return -EAUTH; +} + +static int irm_auth_peer(const char * name, + const struct oap_hdr * oap_hdr, + const struct oap_hdr * r_oap_hdr) +{ + void * crt; + void * pk; + buffer_t sign; + + if (memcmp(r_oap_hdr->id.data, oap_hdr->id.data, OAP_ID_SIZE) != 0) { + log_err("OAP ID mismatch in flow allocation."); + goto fail_check; + } + + if (r_oap_hdr->crt.len == 0) { + log_info("No certificate provided by peer %s.", name); + return 0; + } + + if (crypt_load_crt_der(r_oap_hdr->crt, &crt) < 0) { + log_err("Failed to load certificate from peer %s.", name); + goto fail_check; + } + + log_dbg("Loaded peer certificate for %s.", name); + + if (crypt_check_crt_name(crt, name) < 0) { + log_err("Certificate does not match name %s.", name); + goto fail_crt; + } + + log_dbg("Certificate matches name %s.", name); + + if (crypt_get_pubkey_crt(crt, &pk) < 0) { + log_err("Failed to get pubkey from certificate for %s.", name); + goto fail_crt; + } + + log_dbg("Got public key from certificate for %s.", name); + + if (auth_verify_crt(irmd.auth.ctx, crt) < 0) { + log_err("Failed to verify peer %s with CA store.", name); + goto fail_crt; + } + + log_info("Successfully verified peer certificate for %s.", name); + + sign = r_oap_hdr->hdr; + sign.len -= (r_oap_hdr->sig.len + sizeof(uint16_t)); + + if (auth_verify_sig(pk, sign, r_oap_hdr->sig) < 0) { + log_err("Failed to verify signature for peer %s.", name); + goto fail_check_sig; + } + + crypt_free_key(pk); + crypt_free_crt(crt); + + log_info("Successfully authenticated %s.", name); + + return 0; + + fail_check_sig: + crypt_free_key(pk); + fail_crt: + crypt_free_crt(crt); + fail_check: + return -1; +} + static int flow_accept(struct flow_info * flow, buffer_t * symmkey, buffer_t * data, struct timespec * abstime) { - struct oap_hdr oap_hdr; /* incoming request */ - struct oap_hdr r_oap_hdr; /* outgoing response */ - uint8_t buf[MSGBUFSZ]; /* buffer for local ephkey */ - buffer_t lpk = BUF_INIT; /* local ephemeral pubkey */ - ssize_t delta; /* allocation time difference */ - int err; - struct timespec now; + struct oap_hdr oap_hdr; /* incoming request */ + struct oap_hdr r_oap_hdr; /* outgoing response */ + uint8_t buf[MSGBUFSZ]; /* buffer for local ephkey */ + buffer_t lpk = BUF_INIT; /* local ephemeral pubkey */ + char name[NAME_SIZE + 1]; /* name for flow */ + void * pkp = NULL; /* signing private key */ + void * crt = NULL; /* signing certificate */ + int err; /* piggyback of user data not yet implemented */ - assert(data != NULL && data->len == 0 && data->data == NULL); - assert(symmkey != NULL && symmkey->len == 0 && symmkey->data == NULL); + assert(data != NULL && BUF_IS_EMPTY(data)); + assert(symmkey != NULL && BUF_IS_EMPTY(symmkey)); if (!reg_has_proc(flow->n_pid)) { log_err("Unknown process %d calling accept.", flow->n_pid); @@ -816,23 +1071,28 @@ static int flow_accept(struct flow_info * flow, assert(err == 0); - if (oap_hdr_decode(oap_hdr.hdr, &oap_hdr) < 0) { - log_err("Failed to decode OAP header."); + if (reg_get_name_for_flow_id(name, flow->id) < 0) { + log_err("Failed to get name for flow %d.", flow->id); err = -EIPCP; goto fail_oap_hdr; } - clock_gettime(CLOCK_REALTIME, &now); - - delta = (ssize_t)(TS_TO_UINT64(now) - oap_hdr.timestamp) / MILLION; - if (delta > flow->mpl) - log_warn("Flow alloc time exceeds MPL (%zd ms).", delta); + log_dbg("IPCP %d accepting flow %d for %s.", + flow->n_pid, flow->id, name); - if (delta < -TIMESYNC_SLACK) - log_warn("Flow alloc sent from the future (%zd ms).", -delta); + if (oap_hdr_decode(oap_hdr.hdr, &oap_hdr) < 0) { + log_err("Failed to decode OAP header from %s.", name); + err = -EIPCP; + goto fail_oap_hdr; + } #ifdef DEBUG_PROTO_OAP debug_oap_hdr_rcv(&oap_hdr); #endif + if (irm_check_oap_hdr(&oap_hdr, flow->mpl) < 0) { + log_err("OAP header failed replay check."); + goto fail_oap_hdr; + } + if (flow->qs.cypher_s != 0) { /* crypto requested */ uint8_t * s; /* symmetric encryption key */ ssize_t key_len; /* length of local pubkey */ @@ -872,25 +1132,47 @@ static int flow_accept(struct flow_info * flow, crypt_dh_pkp_destroy(pkp); } - if (oap_hdr_init(oap_hdr.id, NULL, NULL, lpk, *data, &r_oap_hdr) < 0) { + if (load_srv_credentials(name, &pkp, &crt) < 0) { + log_err("Failed to load security keys for %s.", name); + err = -EAUTH; + goto fail_cred; + } + + if (oap_hdr_init(oap_hdr.id, pkp, crt, lpk, *data, &r_oap_hdr) < 0) { log_err("Failed to create OAP header."); err = -ENOMEM; goto fail_r_oap_hdr; } + + if (irm_auth_peer(name, &oap_hdr, &r_oap_hdr) < 0) { + log_err("Failed to authenticate %s flow %d.", name, flow->id); + err = -EAUTH; + goto fail_r_oap_hdr; + } + + crypt_free_crt(crt); + crypt_free_key(pkp); + #ifdef DEBUG_PROTO_OAP - debug_oap_hdr_snd(&oap_hdr); + debug_oap_hdr_snd(&r_oap_hdr); #endif if (ipcp_flow_alloc_resp(flow, 0, r_oap_hdr.hdr) < 0) { log_err("Failed to respond to flow allocation."); goto fail_resp; } + log_info("Flow %d accepted by %d for %s.", + flow->id, flow->n_pid, name); + oap_hdr_fini(&oap_hdr); oap_hdr_fini(&r_oap_hdr); return 0; fail_r_oap_hdr: + crypt_free_crt(crt); + crypt_free_key(pkp); + fail_cred: freebuf(*symmkey); fail_derive: clrbuf(lpk); @@ -949,7 +1231,6 @@ static int flow_join(struct flow_info * flow, reg_prepare_flow_alloc(flow); - if (ipcp_flow_join(flow, hash)) { log_err("Flow join with layer %s failed.", dst); err = -ENOTALLOC; @@ -1059,14 +1340,16 @@ static int flow_alloc(struct flow_info * flow, buffer_t lpk = BUF_INIT; /* local ephemeral pubkey */ void * pkp = NULL; /* ephemeral private key pair */ uint8_t * s = NULL; /* symmetric key */ + void * cpkp = NULL; /* signing private key */ + void * ccrt = NULL; /* signing certificate */ buffer_t hash; uint8_t idbuf[OAP_ID_SIZE]; buffer_t id; int err; /* piggyback of user data not yet implemented */ - assert(data != NULL && data->len == 0 && data->data == NULL); - assert(symmkey != NULL && symmkey->len == 0 && symmkey->data == NULL); + assert(data != NULL && BUF_IS_EMPTY(data)); + assert(symmkey != NULL && BUF_IS_EMPTY(symmkey)); if (random_buffer(idbuf, OAP_ID_SIZE) < 0) { log_err("Failed to generate ID."); @@ -1100,7 +1383,13 @@ static int flow_alloc(struct flow_info * flow, log_dbg("Generated ephemeral keys for %d.", flow->n_pid); } - if (oap_hdr_init(id, NULL, NULL, lpk, *data, &oap_hdr) < 0) { + if (load_cli_credentials(dst, &cpkp, &ccrt) < 0) { + log_err("Failed to load security keys for %s.", dst); + err = -EAUTH; + goto fail_cred; + } + + if (oap_hdr_init(id, cpkp, ccrt, lpk, *data, &oap_hdr) < 0) { log_err("Failed to create OAP header."); err = -ENOMEM; goto fail_oap_hdr; @@ -1164,9 +1453,14 @@ static int flow_alloc(struct flow_info * flow, #ifdef DEBUG_PROTO_OAP debug_oap_hdr_rcv(&r_oap_hdr); #endif - if (memcmp(r_oap_hdr.id.data, oap_hdr.id.data, r_oap_hdr.id.len) != 0) { - log_err("OAP ID mismatch in flow allocation."); - err = -EIPCP; + if (irm_check_oap_hdr(&r_oap_hdr, flow->mpl) < 0) { + log_err("OAP header failed replay check."); + goto fail_r_oap_hdr; + } + + if (irm_auth_peer(dst, &oap_hdr, &r_oap_hdr) < 0) { + log_err("Failed to authenticate %s (flow %d).", dst, flow->id); + err = -EAUTH; goto fail_r_oap_hdr; } @@ -1186,6 +1480,9 @@ static int flow_alloc(struct flow_info * flow, oap_hdr_fini(&r_oap_hdr); oap_hdr_fini(&oap_hdr); + crypt_free_crt(ccrt); + crypt_free_key(cpkp); + /* TODO: piggyback user data if needed */ freebuf(hash); @@ -1203,6 +1500,9 @@ static int flow_alloc(struct flow_info * flow, fail_flow: oap_hdr_fini(&oap_hdr); fail_oap_hdr: + crypt_free_crt(ccrt); + crypt_free_key(cpkp); + fail_cred: crypt_dh_pkp_destroy(pkp); fail_pkp: free(s); @@ -1497,8 +1797,7 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg) res = list_ipcps(&ret_msg->ipcps, &ret_msg->n_ipcps); break; case IRM_MSG_CODE__IRM_CREATE_NAME: - strcpy(name.name, msg->names[0]->name); - name.pol_lb = msg->names[0]->pol_lb; + name = name_info_msg_to_s(msg->name_info); res = name_create(&name); break; case IRM_MSG_CODE__IRM_DESTROY_NAME: @@ -1708,40 +2007,6 @@ static void * mainloop(void * o) return (void *) 0; } -static void irm_fini(void) -{ -#ifdef HAVE_FUSE - struct timespec wait = TIMESPEC_INIT_MS(1); - int retries = 5; -#endif - if (irmd_get_state() != IRMD_NULL) - log_warn("Unsafe destroy."); - - tpm_destroy(irmd.tpm); - - close(irmd.sockfd); - - if (unlink(IRM_SOCK_PATH)) - log_dbg("Failed to unlink %s.", IRM_SOCK_PATH); - - if (irmd.rdrb != NULL) - shm_rdrbuff_destroy(irmd.rdrb); - - if (irmd.lf != NULL) - lockfile_destroy(irmd.lf); - - pthread_mutex_destroy(&irmd.cmd_lock); - pthread_cond_destroy(&irmd.cmd_cond); - pthread_rwlock_destroy(&irmd.state_lock); - -#ifdef HAVE_FUSE - while (rmdir(FUSE_PREFIX) < 0 && retries-- > 0) - nanosleep(&wait, NULL); - if (retries < 0) - log_err("Failed to remove " FUSE_PREFIX); -#endif -} - #ifdef HAVE_FUSE static void destroy_mount(char * mnt) { @@ -1817,6 +2082,79 @@ void * irm_sanitize(void * o) return (void *) 0; } +static int irm_load_store(char * dpath) +{ + struct stat st; + struct dirent * dent; + DIR * dir; + void * crt; + + if (stat(dpath, &st) == -1) { + log_dbg("Store directory %s not found.", dpath); + return 0; + } + + if (!S_ISDIR(st.st_mode)) { + log_err("%s is not a directory.", dpath); + goto fail_dir; + } + + /* loop through files in directory and load certificates */ + dir = opendir(dpath); + if (dir == NULL) { + log_err("Failed to open %s.", dpath); + goto fail_dir; + } + + while ((dent = readdir(dir)) != NULL) { + char path[NAME_PATH_SIZE + 1]; + + if (strcmp(dent->d_name, ".") == 0 || + strcmp(dent->d_name, "..") == 0) + continue; + + snprintf(path, sizeof(path), "%s/%s", dpath, + dent->d_name); + + if (stat(path, &st) == -1) { + log_dbg("Failed to stat %s.", path); + continue; + } + + if (!S_ISREG(st.st_mode)) { + log_dbg("%s is not a regular file.", path); + goto fail_file; + } + + if (crypt_load_crt_file(path, &crt) < 0) { + log_err("Failed to load certificate from %s.", path); + goto fail_file; + } + + if (auth_add_crt_to_store(irmd.auth.ctx, crt) < 0) { + log_err("Failed to add certificate from %s to store.", + path); + goto fail_crt_add; + } + + log_dbg("Loaded certificate: %s.", path); + + crypt_free_crt(crt); + } + + closedir(dir); + + log_info("Loaded certificates from %s.", dpath); + + return 0; + + fail_crt_add: + crypt_free_crt(crt); + fail_file: + closedir(dir); + fail_dir: + return -1; +} static int irm_init(void) { @@ -1917,6 +2255,30 @@ static int irm_init(void) log_err("Failed to greate thread pool."); goto fail_tpm_create; } + + if (pthread_mutex_init(&irmd.auth.mtx, NULL) < 0) { + log_err("Failed to initialize auth mutex."); + goto fail_auth_mtx; + } + + irmd.auth.ctx = auth_create_ctx(); + if (irmd.auth.ctx == NULL) { + log_err("Failed to create auth store context."); + goto fail_auth_ctx; + } + + list_head_init(&irmd.auth.list); + + if (irm_load_store(OUROBOROS_CA_CRT_DIR) < 0) { + log_err("Failed to load CA certificates."); + goto fail_auth_ctx; + } + + if (irm_load_store(OUROBOROS_CHAIN_DIR) < 0) { + log_err("Failed to load intermediate certificates."); + goto fail_auth_ctx; + } + #ifdef HAVE_FUSE mask = umask(0); @@ -1941,7 +2303,6 @@ static int irm_init(void) gcry_control(GCRYCTL_INITIALIZATION_FINISHED); #endif - return 0; #ifdef HAVE_LIBGCRYPT @@ -1949,8 +2310,12 @@ static int irm_init(void) #ifdef HAVE_FUSE rmdir(FUSE_PREFIX); #endif - tpm_destroy(irmd.tpm); + auth_destroy_ctx(irmd.auth.ctx); #endif + fail_auth_ctx: + pthread_mutex_destroy(&irmd.auth.mtx); + fail_auth_mtx: + tpm_destroy(irmd.tpm); fail_tpm_create: shm_rdrbuff_destroy(irmd.rdrb); fail_rdrbuff: @@ -1970,6 +2335,67 @@ static int irm_init(void) return -1; } +static void irm_fini(void) +{ + struct list_head * p; + struct list_head * h; +#ifdef HAVE_FUSE + struct timespec wait = TIMESPEC_INIT_MS(1); + int retries = 5; +#endif + if (irmd_get_state() != IRMD_NULL) + log_warn("Unsafe destroy."); + + pthread_mutex_lock(&irmd.auth.mtx); + + list_for_each_safe(p, h, &irmd.auth.list) { + struct oaph * oaph = list_entry(p, struct oaph, next); + list_del(&oaph->next); + free(oaph); + } + + pthread_mutex_unlock(&irmd.auth.mtx); + pthread_mutex_destroy(&irmd.auth.mtx); + + auth_destroy_ctx(irmd.auth.ctx); + + tpm_destroy(irmd.tpm); + + close(irmd.sockfd); + + if (unlink(IRM_SOCK_PATH)) + log_dbg("Failed to unlink %s.", IRM_SOCK_PATH); + + if (irmd.rdrb != NULL) + shm_rdrbuff_destroy(irmd.rdrb); + + if (irmd.lf != NULL) + lockfile_destroy(irmd.lf); + + pthread_mutex_lock(&irmd.cmd_lock); + + list_for_each_safe(p, h, &irmd.cmds) { + struct cmd * cmd = list_entry(p, struct cmd, next); + list_del(&cmd->next); + close(cmd->fd); + free(cmd); + } + + pthread_mutex_unlock(&irmd.cmd_lock); + + pthread_mutex_destroy(&irmd.cmd_lock); + pthread_cond_destroy(&irmd.cmd_cond); + pthread_rwlock_destroy(&irmd.state_lock); + +#ifdef HAVE_FUSE + while (rmdir(FUSE_PREFIX) < 0 && retries-- > 0) + nanosleep(&wait, NULL); + if (retries < 0) + log_err("Failed to remove " FUSE_PREFIX); +#endif + assert(list_is_empty(&irmd.cmds)); +} + static void usage(void) { printf("Usage: irmd \n" @@ -2096,8 +2522,8 @@ static void * kill_dash_nine(void * o) slept += intv; } - log_dbg("I am become Death, destroyer of hung processes."); - + log_dbg("I guess I’ll have to shut you down for good this time,"); + log_dbg("already tried a SIGQUIT, so now it’s KILL DASH 9."); #ifdef IRMD_KILL_ALL_PROCESSES reg_kill_all_proc(SIGKILL); nanosleep(&ts, NULL); @@ -2156,7 +2582,7 @@ int main(int argc, if (geteuid() != 0) { printf("IPC Resource Manager must be run as root.\n"); - exit(EXIT_FAILURE); + goto fail_irm_init; } if (irm_init() < 0) diff --git a/src/irmd/reg/flow.h b/src/irmd/reg/flow.h index b0f0c51c..aba0d7a4 100644 --- a/src/irmd/reg/flow.h +++ b/src/irmd/reg/flow.h @@ -25,6 +25,7 @@ #include <ouroboros/list.h> #include <ouroboros/flow.h> +#include <ouroboros/name.h> #include <ouroboros/pthread.h> #include <ouroboros/qos.h> #include <ouroboros/shm_rbuff.h> @@ -41,6 +42,8 @@ struct reg_flow { buffer_t data; struct timespec t0; + char name[NAME_SIZE + 1]; + struct shm_rbuff * n_rb; struct shm_rbuff * n_1_rb; }; diff --git a/src/irmd/reg/name.c b/src/irmd/reg/name.c index 1ac939a5..4e609711 100644 --- a/src/irmd/reg/name.c +++ b/src/irmd/reg/name.c @@ -66,15 +66,14 @@ struct reg_name * reg_name_create(const struct name_info * info) goto fail_malloc; } + memset(name, 0, sizeof(*name)); + list_head_init(&name->next); - list_head_init(&name->progs); - list_head_init(&name->procs); - list_head_init(&name->active); + list_head_init(&name->progs.list); + list_head_init(&name->procs.list); + list_head_init(&name->active.list); - name->info = *info; - name->n_progs = 0; - name->n_procs = 0; - name->n_active = 0; + name->info = *info; return name; @@ -88,13 +87,13 @@ void reg_name_destroy(struct reg_name * name) assert(list_is_empty(&name->next)); - assert(name->n_progs == 0); - assert(name->n_procs == 0); - assert(name->n_active == 0); + assert(name->progs.len == 0); + assert(name->procs.len == 0); + assert(name->active.len == 0); - assert(list_is_empty(&name->progs)); - assert(list_is_empty(&name->procs)); - assert(list_is_empty(&name->active)); + assert(list_is_empty(&name->progs.list)); + assert(list_is_empty(&name->procs.list)); + assert(list_is_empty(&name->active.list)); free(name); } @@ -107,7 +106,7 @@ static struct proc_entry * __reg_name_get_active(const struct reg_name * name, assert(name != NULL); assert(pid > 0); - list_for_each(p, &name->active) { + list_for_each(p, &name->active.list) { struct proc_entry * entry; entry = list_entry(p, struct proc_entry, next); if (entry->pid == pid) @@ -123,13 +122,13 @@ static void __reg_name_del_all_active(struct reg_name * name, struct list_head * p; struct list_head * h; - list_for_each_safe(p, h, &name->active) { + list_for_each_safe(p, h, &name->active.list) { struct proc_entry * entry; entry = list_entry(p, struct proc_entry, next); if (entry->pid == pid) { list_del(&entry->next); free(entry); - name->n_active--; + --name->active.len; } } } @@ -142,7 +141,7 @@ static struct proc_entry * __reg_name_get_proc(const struct reg_name * name, assert(name != NULL); assert(pid > 0); - list_for_each(p, &name->procs) { + list_for_each(p, &name->procs.list) { struct proc_entry * entry; entry = list_entry(p, struct proc_entry, next); if (entry->pid == pid) @@ -160,7 +159,7 @@ static struct prog_entry * __reg_name_get_prog(const struct reg_name * name, assert(name != NULL); assert(prog != NULL); - list_for_each(p, &name->progs) { + list_for_each(p, &name->progs.list) { struct prog_entry * entry; entry = list_entry(p, struct prog_entry, next); if (strcmp(entry->exec[0], prog) == 0) @@ -195,16 +194,16 @@ int reg_name_add_active(struct reg_name * name, switch (name->info.pol_lb) { case LB_RR: /* Round robin policy. */ - list_add_tail(&entry->next, &name->active); + list_add_tail(&entry->next, &name->active.list); break; case LB_SPILL: /* Keep accepting flows on the current process */ - list_add(&entry->next, &name->active); + list_add(&entry->next, &name->active.list); break; default: goto fail_unreachable; } - name->n_active++; + ++name->active.len; return 0; @@ -226,19 +225,23 @@ void reg_name_del_active(struct reg_name * name, list_del(&entry->next); - name->n_active--; + --name->active.len; free(entry); } pid_t reg_name_get_active(struct reg_name * name) { + struct proc_entry * e; + assert(name != NULL); - if (list_is_empty(&name->active)) + if (list_is_empty(&name->active.list)) return -1; - return list_first_entry(&name->active, struct proc_entry, next)->pid; + e = list_first_entry(&name->active.list, struct proc_entry, next); + + return e->pid; } int reg_name_add_proc(struct reg_name * name, @@ -259,9 +262,9 @@ int reg_name_add_proc(struct reg_name * name, entry->pid = pid; - list_add(&entry->next, &name->procs); + list_add(&entry->next, &name->procs.list); - name->n_procs++; + ++name->procs.len; return 0; @@ -287,7 +290,7 @@ void reg_name_del_proc(struct reg_name * name, free(entry); - name->n_procs--; + --name->procs.len; assert(__reg_name_get_proc(name, pid) == NULL); } @@ -296,8 +299,7 @@ bool reg_name_has_proc(const struct reg_name * name, pid_t pid) { return __reg_name_get_proc(name, pid) != NULL; -} char ** exec; - +} int reg_name_add_prog(struct reg_name * name, char ** exec) @@ -322,11 +324,11 @@ int reg_name_add_prog(struct reg_name * name, goto fail_exec; } - list_add(&entry->next, &name->progs); + list_add(&entry->next, &name->progs.list); log_dbg("Add prog %s to name %s.", exec[0], name->info.name); - name->n_progs++; + ++name->progs.len; return 0; @@ -352,7 +354,7 @@ void reg_name_del_prog(struct reg_name * name, __free_prog_entry(entry); - name->n_progs--; + --name->progs.len; assert(__reg_name_get_prog(name, prog) == NULL); } @@ -368,8 +370,12 @@ bool reg_name_has_prog(const struct reg_name * name, char ** reg_name_get_exec(const struct reg_name * name) { - if (list_is_empty(&name->progs)) + struct prog_entry * e; + + if (list_is_empty(&name->progs.list)) return NULL; - return list_first_entry(&name->progs, struct prog_entry, next)->exec; + e = list_first_entry(&name->progs.list, struct prog_entry, next); + + return e->exec; } diff --git a/src/irmd/reg/name.h b/src/irmd/reg/name.h index 97ca7f04..30a64e1c 100644 --- a/src/irmd/reg/name.h +++ b/src/irmd/reg/name.h @@ -33,14 +33,25 @@ struct reg_name { struct name_info info; - struct list_head progs; /* autostart programs for this name */ - size_t n_progs; /* number of programs */ - - struct list_head procs; /* processes bound to this name */ - size_t n_procs; /* number of processes */ - - struct list_head active; /* processes actively calling accept */ - size_t n_active; /* number of processes accepting */ + struct { + void * key; + void * crt; + } cache; + + struct { + struct list_head list; + size_t len; + } progs; /* autostart programs for this name */ + + struct { + struct list_head list; + size_t len; + } procs; /* processes bound to this name */ + + struct { + struct list_head list; + size_t len; + } active; /* processes actively calling accept */ }; struct reg_name * reg_name_create(const struct name_info * info); @@ -74,5 +85,4 @@ pid_t reg_name_get_active(struct reg_name * name); void reg_name_del_active(struct reg_name * name, pid_t proc); - #endif /* OUROBOROS_IRMD_REG_NAME_H */ 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); diff --git a/src/irmd/reg/reg.h b/src/irmd/reg/reg.h index 00db8f0b..57257dd5 100644 --- a/src/irmd/reg/reg.h +++ b/src/irmd/reg/reg.h @@ -90,10 +90,16 @@ int reg_destroy_name(const char * name); bool reg_has_name(const char * name); +int reg_get_name_info(const char * name, + struct name_info * info); + int reg_get_name_for_hash(char * buf, enum hash_algo algo, const uint8_t * hash); +int reg_get_name_for_flow_id(char * buf, + int flow_id); + /* TODO don't rely on protobuf here */ int reg_list_names(name_info_msg_t *** names); diff --git a/src/irmd/reg/tests/name_test.c b/src/irmd/reg/tests/name_test.c index 64635eec..9071364b 100644 --- a/src/irmd/reg/tests/name_test.c +++ b/src/irmd/reg/tests/name_test.c @@ -76,8 +76,8 @@ static int test_reg_name_add_proc(void) goto fail; } - if (n->n_procs != 1) { - printf("n_procs not updated.\n"); + if (n->procs.len != 1) { + printf("Proc not added to list.\n"); goto fail; } @@ -88,8 +88,8 @@ static int test_reg_name_add_proc(void) reg_name_del_proc(n, TEST_PID); - if (n->n_procs != 0) { - printf("n_procs not updated.\n"); + if (n->procs.len != 0) { + printf("Proc not removed from list.\n"); goto fail; } @@ -126,8 +126,8 @@ static int test_reg_name_add_prog(void) goto fail; } - if (n->n_progs != 1) { - printf("n_progs not updated.\n"); + if (n->progs.len != 1) { + printf("Prog not added to list.\n"); goto fail; } @@ -138,8 +138,8 @@ static int test_reg_name_add_prog(void) reg_name_del_prog(n, TEST_PROG); - if (n->n_progs != 0) { - printf("n_progs not updated.\n"); + if (n->progs.len != 0) { + printf("Prog not removed from list.\n"); goto fail; } @@ -195,8 +195,8 @@ static int test_reg_name_add_active(enum pol_balance lb) goto fail; } - if (n->n_active != 1) { - printf("n_active not updated.\n"); + if (n->active.len != 1) { + printf("Active list not updated.\n"); goto fail; } @@ -226,13 +226,13 @@ static int test_reg_name_add_active(enum pol_balance lb) goto fail; } - if (n->n_procs != 3) { - printf("n_procs not updated.\n"); + if (n->procs.len != 3) { + printf("Procs list not updated.\n"); goto fail; } - if (n->n_active != 4) { - printf("n_active not updated.\n"); + if (n->active.len != 4) { + printf("Active list not updated.\n"); goto fail; } @@ -263,13 +263,13 @@ static int test_reg_name_add_active(enum pol_balance lb) reg_name_del_proc(n, TEST_PID); - if (n->n_procs != 0) { - printf("n_procs not updated.\n"); + if (n->procs.len != 0) { + printf("Procs list not cleared.\n"); goto fail; } - if (n->n_active != 0) { - printf("n_active not updated.\n"); + if (n->active.len != 0) { + printf("Active list not cleared.\n"); goto fail; } @@ -283,20 +283,19 @@ static int test_reg_name_add_active(enum pol_balance lb) return TEST_RC_FAIL; } - int name_test(int argc, char ** argv) { - int res = 0; + int rc = 0; (void) argc; (void) argv; - res |= test_reg_name_create(); - res |= test_reg_name_add_proc(); - res |= test_reg_name_add_prog(); - res |= test_reg_name_add_active(LB_RR); - res |= test_reg_name_add_active(LB_SPILL); + rc |= test_reg_name_create(); + rc |= test_reg_name_add_proc(); + rc |= test_reg_name_add_prog(); + rc |= test_reg_name_add_active(LB_RR); + rc |= test_reg_name_add_active(LB_SPILL); - return res; + return rc; } diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c index fb99e6d3..280ea9a8 100644 --- a/src/irmd/reg/tests/reg_test.c +++ b/src/irmd/reg/tests/reg_test.c @@ -36,7 +36,7 @@ #define TEST_DATA2 "testpbufdata2" #define TEST_LAYER "testlayer" #define REG_TEST_FAIL() \ - do { TEST_FAIL(); memset(®, 0, sizeof(reg)); } while(0) + do { TEST_FAIL(); memset(®, 0, sizeof(reg)); abort();} while(0) static int test_reg_init(void) { @@ -254,7 +254,7 @@ static int test_reg_accept_flow_success(void) pthread_create(&thr, NULL, test_flow_respond_accept, &n_1_info); - if (reg_wait_flow_accepted(&info, &rbuf, &abstime) < 0 ) { + if (reg_wait_flow_accepted(&info, &rbuf, &abstime) < 0) { printf("Flow allocation failed.\n"); goto fail; } @@ -1344,13 +1344,14 @@ static int test_wait_accepting_success(void) { struct timespec abstime; struct timespec timeo = TIMESPEC_INIT_S(1); - int flow_id; pthread_t thr; + int flow_id; struct name_info ninfo = { .name = TEST_NAME, .pol_lb = LB_RR }; + TEST_START(); if (reg_init()) { diff --git a/src/irmd/tests/oap_test.c b/src/irmd/tests/oap_test.c index 2e27762d..4e7fb2d1 100644 --- a/src/irmd/tests/oap_test.c +++ b/src/irmd/tests/oap_test.c @@ -210,6 +210,16 @@ static int test_oap_hdr_init_fini_signed(void) goto fail_req_hdr; } + if (oap_hdr.crt.len == 0) { + printf("OAP request header has no public certificate.\n"); + goto fail_req_hdr; + } + + if (oap_hdr.sig.len == 0) { + printf("OAP request header no signature.\n"); + goto fail_req_hdr; + } + if (crypt_load_crt_der(oap_hdr.crt, &pubcrt2) < 0) { printf("Failed to load public certificate from DER.\n"); goto fail_crt_der; |