diff options
Diffstat (limited to 'src/irmd/main.c')
-rw-r--r-- | src/irmd/main.c | 117 |
1 files changed, 72 insertions, 45 deletions
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; |