diff options
Diffstat (limited to 'src/irmd')
-rw-r--r-- | src/irmd/configfile.c | 9 | ||||
-rw-r--r-- | src/irmd/ipcp.c | 2 | ||||
-rw-r--r-- | src/irmd/main.c | 117 | ||||
-rw-r--r-- | src/irmd/reg/flow.h | 1 | ||||
-rw-r--r-- | src/irmd/reg/reg.c | 9 | ||||
-rw-r--r-- | src/irmd/reg/reg.h | 3 | ||||
-rw-r--r-- | src/irmd/reg/tests/reg_test.c | 7 |
7 files changed, 96 insertions, 52 deletions
diff --git a/src/irmd/configfile.c b/src/irmd/configfile.c index 2dfb41a8..ce9fc8fc 100644 --- a/src/irmd/configfile.c +++ b/src/irmd/configfile.c @@ -922,8 +922,10 @@ static int toml_name(toml_table_t * table, toml_array_t * progs; toml_array_t * args; toml_datum_t lb; + toml_datum_t senc; toml_datum_t scrt; toml_datum_t skey; + toml_datum_t cenc; toml_datum_t ccrt; toml_datum_t ckey; @@ -955,6 +957,9 @@ static int toml_name(toml_table_t * table, log_err("Invalid load-balancing policy for %s.", name); return -1; } + senc = toml_string_in(table, "server_enc_file"); + if (senc.ok && cp_chk_path(info.s.enc, senc.u.s) < 0) + return -1; scrt = toml_string_in(table, "server_crt_file"); if (scrt.ok && cp_chk_path(info.s.crt, scrt.u.s) < 0) @@ -964,6 +969,10 @@ static int toml_name(toml_table_t * table, if (skey.ok && cp_chk_path(info.s.key, skey.u.s) < 0) return -1; + cenc = toml_string_in(table, "client_enc_file"); + if (cenc.ok && cp_chk_path(info.c.enc, cenc.u.s) < 0) + return -1; + ccrt = toml_string_in(table, "client_crt_file"); if (ccrt.ok && cp_chk_path(info.c.crt, ccrt.u.s) < 0) return -1; diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c index fdee6a75..6226aeda 100644 --- a/src/irmd/ipcp.c +++ b/src/irmd/ipcp.c @@ -497,7 +497,7 @@ int ipcp_flow_alloc_resp(const struct flow_info * flow, msg.pid = flow->n_pid; msg.has_response = true; msg.response = response; - msg.has_pk = true; + msg.has_pk = response == 0; msg.pk.data = data.data; msg.pk.len = data.len; diff --git a/src/irmd/main.c b/src/irmd/main.c index 05f9236f..834a7a8c 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -455,12 +455,18 @@ static void name_update_sec_paths(struct name_info * info) assert(info != NULL); + if (strlen(info->s.enc) == 0) + sprintf(info->s.enc, "%s/%s/enc.cfg", srv_dir, info->name); + 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.enc) == 0) + sprintf(info->c.enc, "%s/%s/enc.cfg", cli_dir, info->name); + if (strlen(info->c.crt) == 0) sprintf(info->c.crt, "%s/%s/crt.pem", cli_dir, info->name); @@ -816,7 +822,8 @@ static bool file_exists(const char * path) static int load_credentials(const char * name, const struct name_sec_paths * paths, void ** pkp, - void ** crt) + void ** crt, + bool * crypt) { assert(paths != NULL); assert(pkp != NULL); @@ -825,6 +832,11 @@ static int load_credentials(const char * name, *pkp = NULL; *crt = NULL; + /* TODO: Allow configuration. For now, encrypt if path exists */ + *crypt = file_exists(paths->enc); + if (*crypt) + log_info("Encryption enabled for %s.", name); + if (!file_exists(paths->crt) || !file_exists(paths->key)) { log_info("No security info for %s.", name); return 0; @@ -853,7 +865,8 @@ static int load_credentials(const char * name, static int load_srv_credentials(const char * name, void ** pkp, - void ** crt) + void ** crt, + bool * crypt) { struct name_info info; @@ -866,12 +879,13 @@ static int load_srv_credentials(const char * name, return -ENAME; } - return load_credentials(name, &info.s, pkp, crt); + return load_credentials(name, &info.s, pkp, crt, crypt); } static int load_cli_credentials(const char * name, void ** pkp, - void ** crt) + void ** crt, + bool * crypt) { struct name_info info; @@ -884,7 +898,7 @@ static int load_cli_credentials(const char * name, return -ENAME; } - return load_credentials(name, &info.c, pkp, crt); + return load_credentials(name, &info.c, pkp, crt, crypt); } #define ID_IS_EQUAL(id1, id2) (memcmp(id1, id2, OAP_ID_SIZE) == 0) @@ -1029,14 +1043,15 @@ static int flow_accept(struct flow_info * flow, 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 */ - char name[NAME_SIZE + 1]; /* name for flow */ - void * pkp = NULL; /* signing private key */ - void * crt = NULL; /* signing certificate */ - int err; + 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; + bool crypt; /* piggyback of user data not yet implemented */ assert(data != NULL && BUF_IS_EMPTY(data)); @@ -1082,12 +1097,18 @@ static int flow_accept(struct flow_info * flow, 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; + goto fail_cred; } log_dbg("IPCP %d accepting flow %d for %s.", flow->n_pid, flow->id, name); + if (load_srv_credentials(name, &pkp, &crt, &crypt) < 0) { + log_err("Failed to load security keys for %s.", name); + err = -EAUTH; + goto fail_cred; + } + if (oap_hdr_decode(oap_hdr.hdr, &oap_hdr) < 0) { log_err("Failed to decode OAP header from %s.", name); err = -EIPCP; @@ -1101,10 +1122,16 @@ static int flow_accept(struct flow_info * flow, 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 */ - void * pkp = NULL; /* ephemeral private key pair */ + if (crypt && oap_hdr.eph.len == 0) { + log_warn("Encryption required but no key provided."); + err = -ECRYPT; + goto fail_oap_hdr; + } + + if (oap_hdr.eph.len > 0) { /* crypto requested */ + uint8_t * s; /* symmetric encryption key */ + ssize_t key_len; /* length of local pubkey */ + void * pkp = NULL; /* ephemeral private key pair */ s = malloc(SYMMKEYSZ); if (s == NULL) { @@ -1140,12 +1167,6 @@ static int flow_accept(struct flow_info * flow, crypt_dh_pkp_destroy(pkp); } - 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; @@ -1178,15 +1199,15 @@ static int flow_accept(struct flow_info * flow, return 0; fail_r_oap_hdr: - crypt_free_crt(crt); - crypt_free_key(pkp); - fail_cred: freebuf(*symmkey); fail_derive: clrbuf(lpk); fail_keys: oap_hdr_fini(&oap_hdr); fail_oap_hdr: + crypt_free_crt(crt); + crypt_free_key(pkp); + fail_cred: assert(lpk.data == NULL && lpk.len == 0); ipcp_flow_alloc_resp(flow, err, lpk); fail_wait: @@ -1354,11 +1375,14 @@ static int flow_alloc(struct flow_info * flow, uint8_t idbuf[OAP_ID_SIZE]; buffer_t id; int err; + bool crypt; /* piggyback of user data not yet implemented */ assert(data != NULL && BUF_IS_EMPTY(data)); assert(symmkey != NULL && BUF_IS_EMPTY(symmkey)); + log_info("Allocating flow for %d to %s.", flow->n_pid, dst); + if (random_buffer(idbuf, OAP_ID_SIZE) < 0) { log_err("Failed to generate ID."); err = -EIRMD; @@ -1368,7 +1392,13 @@ static int flow_alloc(struct flow_info * flow, id.data = idbuf; id.len = OAP_ID_SIZE; - if (flow->qs.cypher_s > 0) { + if (load_cli_credentials(dst, &cpkp, &ccrt, &crypt) < 0) { + log_err("Failed to load security keys for %s.", dst); + err = -EAUTH; + goto fail_cred; + } + + if (crypt > 0) { ssize_t key_len; s = malloc(SYMMKEYSZ); @@ -1391,12 +1421,6 @@ static int flow_alloc(struct flow_info * flow, log_dbg("Generated ephemeral keys for %d.", flow->n_pid); } - 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; @@ -1405,9 +1429,6 @@ static int flow_alloc(struct flow_info * flow, #ifdef DEBUG_PROTO_OAP debug_oap_hdr_snd(&oap_hdr); #endif - - log_info("Allocating flow for %d to %s.", flow->n_pid, dst); - if (reg_create_flow(flow) < 0) { log_err("Failed to create flow."); err = -EBADF; @@ -1447,11 +1468,16 @@ static int flow_alloc(struct flow_info * flow, if (err == -1) { log_dbg("Flow allocation terminated."); - err = -EPIPE; + err = -EIPCP; goto fail_alloc; } - assert(err == 0); + log_dbg("Response received for flow %d to %s.", flow->id, dst); + + if (err < 0) { + log_warn("Flow allocation rejected for %s: %d.", dst, err); + goto fail_alloc; + } if (oap_hdr_decode(r_oap_hdr.hdr, &r_oap_hdr) < 0) { log_err("Failed to decode OAP header."); @@ -1463,6 +1489,7 @@ static int flow_alloc(struct flow_info * flow, #endif if (irm_check_oap_hdr(&r_oap_hdr, flow->mpl) < 0) { log_err("OAP header failed replay check."); + err = -EAUTH; goto fail_r_oap_hdr; } @@ -1472,7 +1499,7 @@ static int flow_alloc(struct flow_info * flow, goto fail_r_oap_hdr; } - if (flow->qs.cypher_s != 0) { /* crypto requested */ + if (lpk.len > 0) { /* crypto requested */ if (crypt_dh_derive(pkp, r_oap_hdr.eph, s) < 0) { log_err("Failed to derive secret for %d.", flow->id); err = -ECRYPT; @@ -1508,13 +1535,13 @@ 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); fail_malloc: + crypt_free_crt(ccrt); + crypt_free_key(cpkp); + fail_cred: clrbuf(id); fail_id: return err; @@ -1616,9 +1643,9 @@ static int flow_alloc_reply(struct flow_info * flow, int response, buffer_t * data) { - flow->state = response ? FLOW_DEALLOCATED : FLOW_ALLOCATED; + flow->state = response != 0 ? FLOW_DEALLOCATED : FLOW_ALLOCATED; - if (reg_respond_alloc(flow, data) < 0) { + if (reg_respond_alloc(flow, data, response) < 0) { log_err("Failed to reply to flow %d.", flow->id); flow->state = FLOW_DEALLOCATED; return -EBADF; diff --git a/src/irmd/reg/flow.h b/src/irmd/reg/flow.h index aba0d7a4..d1e4811c 100644 --- a/src/irmd/reg/flow.h +++ b/src/irmd/reg/flow.h @@ -38,6 +38,7 @@ struct reg_flow { struct list_head next; struct flow_info info; + int response; buffer_t data; struct timespec t0; diff --git a/src/irmd/reg/reg.c b/src/irmd/reg/reg.c index 91385260..a24a9d1d 100644 --- a/src/irmd/reg/reg.c +++ b/src/irmd/reg/reg.c @@ -1714,7 +1714,7 @@ int reg_wait_flow_allocated(struct flow_info * info, stop = true; break; case FLOW_DEALLOCATED: - ret = -1; + ret = flow->response; stop = true; break; default: @@ -1746,7 +1746,8 @@ int reg_wait_flow_allocated(struct flow_info * info, } int reg_respond_alloc(struct flow_info * info, - buffer_t * pbuf) + buffer_t * pbuf, + int response) { struct reg_flow * flow; @@ -1779,7 +1780,9 @@ int reg_respond_alloc(struct flow_info * info, if (reg_flow_update(flow, info) < 0) { log_err("Failed to create flow structs."); goto fail_flow; - }; + } + + flow->response = response; if (info->state == FLOW_ALLOCATED) reg_flow_set_data(flow, pbuf); diff --git a/src/irmd/reg/reg.h b/src/irmd/reg/reg.h index 57257dd5..7728c80f 100644 --- a/src/irmd/reg/reg.h +++ b/src/irmd/reg/reg.h @@ -126,7 +126,8 @@ int reg_wait_flow_allocated(struct flow_info * info, const struct timespec * abstime); int reg_respond_alloc(struct flow_info * info, - buffer_t * pbuf); + buffer_t * pbuf, + int response); int reg_prepare_flow_accept(struct flow_info * info); diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c index d18f5733..4699beab 100644 --- a/src/irmd/reg/tests/reg_test.c +++ b/src/irmd/reg/tests/reg_test.c @@ -174,6 +174,9 @@ static void * test_flow_respond_alloc(void * o) { struct flow_info * info = (struct flow_info *) o; buffer_t pbuf = BUF_INIT; + int response; + + response = (info->state == FLOW_ALLOCATED) ? 0 : -1; if (info->state == FLOW_ALLOCATED) { pbuf.data = (uint8_t *) strdup(TEST_DATA2); @@ -184,7 +187,7 @@ static void * test_flow_respond_alloc(void * o) pbuf.len = strlen((char *) pbuf.data) + 1; } - reg_respond_alloc(info, &pbuf); + reg_respond_alloc(info, &pbuf, response); return (void *) 0; fail: @@ -224,7 +227,7 @@ static int test_reg_accept_flow_success(void) struct flow_info n_1_info = { .n_1_pid = TEST_N_1_PID, - .qs = qos_data_crypt, + .qs = qos_data, .state = FLOW_ALLOCATED /* RESPONSE SUCCESS */ }; |