summaryrefslogtreecommitdiff
path: root/src/irmd/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/irmd/main.c')
-rw-r--r--src/irmd/main.c746
1 files changed, 175 insertions, 571 deletions
diff --git a/src/irmd/main.c b/src/irmd/main.c
index daaf4129..57703254 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -85,13 +85,6 @@ 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;
@@ -105,12 +98,6 @@ 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 */
@@ -456,7 +443,7 @@ 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);
+ sprintf(info->s.enc, "%s/%s/enc.conf", srv_dir, info->name);
if (strlen(info->s.crt) == 0)
sprintf(info->s.crt, "%s/%s/crt.pem", srv_dir, info->name);
@@ -465,7 +452,7 @@ static void name_update_sec_paths(struct name_info * info)
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);
+ sprintf(info->c.enc, "%s/%s/enc.conf", cli_dir, info->name);
if (strlen(info->c.crt) == 0)
sprintf(info->c.crt, "%s/%s/crt.pem", cli_dir, info->name);
@@ -613,18 +600,21 @@ static int unbind_program(const char * prog,
if (name == NULL) {
if (reg_destroy_prog(prog) < 0) {
log_err("Failed to unbind %s.", prog);
- return -1;
+ goto fail;
}
log_info("Program %s unbound.", prog);
} else {
if (reg_unbind_prog(name, prog) < 0) {
log_err("Failed to unbind %s from %s", prog, name);
- return -1;
+ goto fail;
}
log_info("Name %s unbound for %s.", name, prog);
}
return 0;
+
+ fail:
+ return -1;
}
static int unbind_process(pid_t pid,
@@ -633,18 +623,21 @@ static int unbind_process(pid_t pid,
if (name == NULL) {
if (reg_destroy_proc(pid) < 0) {
log_err("Failed to unbind %d.", pid);
- return -1;
+ goto fail;
}
log_info("Process %d unbound.", pid);
} else {
if (reg_unbind_proc(name, pid) < 0) {
log_err("Failed to unbind %d from %s", pid, name);
- return -1;
+ goto fail;
}
log_info("Name %s unbound for process %d.", name, pid);
}
return 0;
+
+ fail:
+ return -1;
}
static int list_ipcps(ipcp_list_msg_t *** ipcps,
@@ -716,8 +709,7 @@ int name_reg(const char * name,
if (ipcp_reg(pid, hash)) {
log_err("Could not register " HASH_FMT32 " with IPCP %d.",
HASH_VAL32(hash.data), pid);
- freebuf(hash);
- return -1;
+ goto fail_hash;
}
log_info("Registered %s with IPCP %d as " HASH_FMT32 ".",
@@ -726,6 +718,10 @@ int name_reg(const char * name,
freebuf(hash);
return 0;
+
+ fail_hash:
+ freebuf(hash);
+ return -1;
}
static int name_unreg(const char * name,
@@ -760,8 +756,7 @@ static int name_unreg(const char * name,
if (ipcp_unreg(pid, hash)) {
log_err("Could not unregister %s with IPCP %d.", name, pid);
- freebuf(hash);
- return -1;
+ goto fail_hash;
}
log_info("Unregistered %s from %d.", name, pid);
@@ -769,6 +764,10 @@ static int name_unreg(const char * name,
freebuf(hash);
return 0;
+
+ fail_hash:
+ freebuf(hash);
+ return -1;
}
static int proc_announce(const struct proc_info * info)
@@ -796,266 +795,26 @@ static int proc_exit(pid_t pid)
return 0;
}
-static void __cleanup_pkp(void * pkp)
-{
- if (pkp != NULL)
- crypt_dh_pkp_destroy(pkp);
-}
-
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,
- bool * crypt)
-{
- assert(paths != NULL);
- assert(pkp != NULL);
- assert(crt != NULL);
-
- *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;
- }
-
- 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,
- bool * crypt)
-{
- 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, crypt);
-}
-
-static int load_cli_credentials(const char * name,
- void ** pkp,
- void ** crt,
- bool * crypt)
-{
- 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, crypt);
-}
-
-#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;
- const char * n = name == NULL ? "<client>" : name;
-
- 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 %s.", n);
- return 0;
- }
-
- if (crypt_load_crt_der(r_oap_hdr->crt, &crt) < 0) {
- log_err("Failed to load certificate from %s.", n);
- goto fail_check;
- }
-
- log_dbg("Loaded peer certificate for %s.", n);
-
- if (name != NULL) {
- if (crypt_check_crt_name(crt, n) < 0) {
- log_err("Certificate does not match %s.", n);
- goto fail_crt;
- }
- log_dbg("Certificate matches name %s.", n);
- }
-
- if (crypt_get_pubkey_crt(crt, &pk) < 0) {
- log_err("Failed to get pubkey from certificate for %s.", n);
- goto fail_crt;
- }
-
- log_dbg("Got public key from certificate for %s.", n);
-
- if (auth_verify_crt(irmd.auth.ctx, crt) < 0) {
- log_err("Failed to verify peer %s with CA store.", n);
- goto fail_crt;
- }
-
- log_info("Successfully verified peer certificate for %s.", n);
-
- 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.", n);
- goto fail_check_sig;
- }
-
- crypt_free_key(pk);
- crypt_free_crt(crt);
-
- log_info("Successfully authenticated %s.", n);
-
- 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 timespec * abstime,
+ struct crypt_sk * sk)
{
- 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;
+ buffer_t req_hdr;
+ buffer_t resp_hdr;
+ char name[NAME_SIZE + 1];
+ struct name_info info;
+ int err;
- /* piggyback of user data not yet implemented */
assert(data != NULL && BUF_IS_EMPTY(data));
- assert(symmkey != NULL && BUF_IS_EMPTY(symmkey));
+
+ clrbuf(req_hdr);
+ clrbuf(resp_hdr);
if (!reg_has_proc(flow->n_pid)) {
log_err("Unknown process %d calling accept.", flow->n_pid);
@@ -1077,7 +836,7 @@ static int flow_accept(struct flow_info * flow,
pthread_cleanup_push(__cleanup_flow, flow);
- err = reg_wait_flow_accepted(flow, &oap_hdr.hdr, abstime);
+ err = reg_wait_flow_accepted(flow, &req_hdr, abstime);
pthread_cleanup_pop(false);
@@ -1097,119 +856,38 @@ 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_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;
- 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 (crypt && oap_hdr.eph.len == 0) {
- log_warn("Encryption required but no key provided.");
- err = -ECRYPT;
- goto fail_oap_hdr;
+ goto fail_oap;
}
- 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) {
- log_err("Failed to malloc symmkey.");
- err = -ENOMEM;
- goto fail_keys;
- }
-
- key_len = crypt_dh_pkp_create(&pkp, buf);
- if (key_len < 0) {
- free(s);
- log_err("Failed to generate key pair.");
- err = -ECRYPT;
- goto fail_keys;
- }
-
- lpk.data = buf;
- lpk.len = (size_t) key_len;
-
- log_dbg("Generated ephemeral keys for %d.", flow->n_pid);
-
- if (crypt_dh_derive(pkp, oap_hdr.eph, s) < 0) {
- log_err("Failed to derive secret for %d.", flow->id);
- crypt_dh_pkp_destroy(pkp);
- free(s);
- err = -ECRYPT;
- goto fail_derive;
- }
-
- symmkey->data = s;
- symmkey->len = SYMMKEYSZ;
-
- crypt_dh_pkp_destroy(pkp);
+ if (reg_get_name_info(name, &info) < 0) {
+ log_err("Failed to get name info for %s.", name);
+ err = -ENAME;
+ goto fail_oap;
}
- 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;
- }
+ log_dbg("IPCP %d accepting flow %d for %s.",
+ flow->n_pid, flow->id, name);
- if (irm_auth_peer(NULL, &r_oap_hdr, &oap_hdr) < 0) {
- log_err("Failed to auth %s client, flow %d.", name, flow->id);
- err = -EAUTH;
- goto fail_r_oap_hdr;
+ err = oap_srv_process(&info, req_hdr, &resp_hdr, data, sk);
+ if (err < 0) {
+ log_err("OAP processing failed for %s.", name);
+ goto fail_oap;
}
- crypt_free_crt(crt);
- crypt_free_key(pkp);
-
-#ifdef DEBUG_PROTO_OAP
- debug_oap_hdr_snd(&r_oap_hdr);
-#endif
- if (ipcp_flow_alloc_resp(flow, 0, r_oap_hdr.hdr) < 0) {
+ if (ipcp_flow_alloc_resp(flow, 0, resp_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);
+ 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);
+ freebuf(req_hdr);
+ freebuf(resp_hdr);
return 0;
- fail_r_oap_hdr:
- 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_oap:
+ ipcp_flow_alloc_resp(flow, err, resp_hdr);
fail_wait:
reg_destroy_flow(flow->id);
fail_flow:
@@ -1217,10 +895,8 @@ static int flow_accept(struct flow_info * flow,
fail_resp:
flow->state = FLOW_NULL;
- oap_hdr_fini(&r_oap_hdr);
- freebuf(*symmkey);
- clrbuf(lpk);
- oap_hdr_fini(&oap_hdr);
+ freebuf(req_hdr);
+ freebuf(resp_hdr);
reg_destroy_flow(flow->id);
return -EIPCP;
}
@@ -1361,78 +1037,31 @@ static int get_ipcp_by_dst(const char * dst,
return err;
}
-static int flow_alloc(struct flow_info * flow,
- const char * dst,
- buffer_t * symmkey,
+static int flow_alloc(const char * dst,
+ struct flow_info * flow,
buffer_t * data,
- struct timespec * abstime)
+ struct timespec * abstime,
+ struct crypt_sk * sk)
{
- struct oap_hdr oap_hdr; /* outgoing request */
- struct oap_hdr r_oap_hdr; /* incoming response */
- uint8_t buf[MSGBUFSZ]; /* buffer for local ephkey */
- 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;
- bool crypt;
+ buffer_t req_hdr = BUF_INIT;
+ buffer_t resp_hdr = BUF_INIT;
+ buffer_t hash = BUF_INIT;
+ struct name_info info;
+ void * ctx;
+ int err;
/* 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;
- goto fail_id;
- }
-
- id.data = idbuf;
- id.len = OAP_ID_SIZE;
-
- 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);
- if (s == NULL) {
- log_err("Failed to malloc symmetric key");
- err = -ENOMEM;
- goto fail_malloc;
- }
-
- key_len = crypt_dh_pkp_create(&pkp, buf);
- if (key_len < 0) {
- log_err("Failed to generate key pair.");
- err = -ECRYPT;
- goto fail_pkp;
- }
-
- lpk.data = buf;
- lpk.len = (size_t) key_len;
-
- log_dbg("Generated ephemeral keys for %d.", flow->n_pid);
+ /* Look up name_info for dst */
+ if (reg_get_name_info(dst, &info) < 0) {
+ log_err("Failed to get name info for %s.", dst);
+ err = -ENAME;
+ goto fail_flow;
}
- 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;
- }
-#ifdef DEBUG_PROTO_OAP
- debug_oap_hdr_snd(&oap_hdr);
-#endif
if (reg_create_flow(flow) < 0) {
log_err("Failed to create flow.");
err = -EBADF;
@@ -1445,109 +1074,70 @@ static int flow_alloc(struct flow_info * flow,
goto fail_ipcp;
}
- reg_prepare_flow_alloc(flow);
+ if (reg_prepare_flow_alloc(flow) < 0) {
+ log_err("Failed to prepare flow allocation.");
+ err = -EBADF;
+ goto fail_prepare;
+ }
- if (ipcp_flow_alloc(flow, hash, oap_hdr.hdr)) {
+ if (oap_cli_prepare(&ctx, &info, &req_hdr, *data) < 0) {
+ log_err("Failed to prepare OAP request for %s.", dst);
+ err = -EBADF;
+ goto fail_prepare;
+ }
+
+ if (ipcp_flow_alloc(flow, hash, req_hdr)) {
log_err("Flow allocation %d failed.", flow->id);
- err = -ENOTALLOC;
+ err = -EIPCP;
goto fail_alloc;
}
pthread_cleanup_push(__cleanup_flow, flow);
- pthread_cleanup_push(__cleanup_pkp, pkp);
pthread_cleanup_push(free, hash.data);
- pthread_cleanup_push(free, s);
- err = reg_wait_flow_allocated(flow, &r_oap_hdr.hdr, abstime);
+ err = reg_wait_flow_allocated(flow, &resp_hdr, abstime);
pthread_cleanup_pop(false);
pthread_cleanup_pop(false);
- pthread_cleanup_pop(false);
- pthread_cleanup_pop(false);
if (err == -ETIMEDOUT) {
log_err("Flow allocation timed out.");
- goto fail_alloc;
- }
-
- if (err == -1) {
- log_dbg("Flow allocation terminated.");
- err = -EIPCP;
- goto fail_alloc;
+ goto fail_wait;
}
- log_dbg("Response received for flow %d to %s.", flow->id, dst);
+ log_dbg("Response for flow %d to %s.", flow->id, dst);
if (err < 0) {
- log_warn("Flow allocation rejected for %s: %d.", dst, err);
- goto fail_alloc;
+ log_warn("Allocation rejected: %s (%d).", dst, err);
+ goto fail_peer;
}
- if (oap_hdr_decode(r_oap_hdr.hdr, &r_oap_hdr) < 0) {
- log_err("Failed to decode OAP header.");
- err = -EIPCP;
- goto fail_r_oap_hdr;
- }
-#ifdef DEBUG_PROTO_OAP
- debug_oap_hdr_rcv(&r_oap_hdr);
-#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;
- }
-
- 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;
- }
-
- 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;
- goto fail_r_oap_hdr;
- }
- crypt_dh_pkp_destroy(pkp);
-
- symmkey->data = s;
- symmkey->len = SYMMKEYSZ;
- s = NULL;
+ err = oap_cli_complete(ctx, &info, resp_hdr, data, sk);
+ if (err < 0) {
+ log_err("OAP completion failed for %s.", dst);
+ goto fail_complete;
}
- 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(req_hdr);
+ freebuf(resp_hdr);
freebuf(hash);
- free(s);
return 0;
- fail_r_oap_hdr:
+ fail_complete:
+ ctx = NULL; /* freee'd on complete */
+ fail_peer:
flow->state = FLOW_DEALLOCATED;
- oap_hdr_fini(&r_oap_hdr);
+ fail_wait:
+ freebuf(resp_hdr);
fail_alloc:
+ freebuf(req_hdr);
+ oap_ctx_free(ctx);
+ fail_prepare:
freebuf(hash);
fail_ipcp:
reg_destroy_flow(flow->id);
fail_flow:
- oap_hdr_fini(&oap_hdr);
- fail_oap_hdr:
- 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;
}
@@ -1744,19 +1334,21 @@ static void __cleanup_irm_msg(void * o)
static irm_msg_t * do_command_msg(irm_msg_t * msg)
{
- struct ipcp_config conf;
- struct ipcp_info ipcp;
- struct flow_info flow;
- struct proc_info proc;
- struct name_info name;
- struct timespec * abstime;
- struct timespec max = TIMESPEC_INIT_MS(FLOW_ALLOC_TIMEOUT);
- struct timespec now;
- struct timespec ts = TIMESPEC_INIT_S(0); /* static analysis */
- int res;
- irm_msg_t * ret_msg;
- buffer_t data;
- buffer_t symmkey = BUF_INIT;;
+ struct ipcp_config conf;
+ struct ipcp_info ipcp;
+ struct flow_info flow;
+ struct proc_info proc;
+ struct name_info name;
+ struct crypt_sk sk;
+ uint8_t kbuf[SYMMKEYSZ]; /* stack buffer for OAP */
+ uint8_t * hbuf = NULL; /* heap copy for response */
+ struct timespec * abstime;
+ struct timespec max = TIMESPEC_INIT_MS(FLOW_ALLOC_TIMEOUT);
+ struct timespec now;
+ struct timespec ts = TIMESPEC_INIT_S(0); /* static analysis */
+ int res;
+ irm_msg_t * ret_msg;
+ buffer_t data;
memset(&flow, 0, sizeof(flow));
@@ -1858,15 +1450,27 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg)
msg->has_pk = false;
assert(data.len > 0 ? data.data != NULL : data.data == NULL);
flow = flow_info_msg_to_s(msg->flow_info);
- res = flow_accept(&flow, &symmkey, &data, abstime);
+ sk.key = kbuf;
+ res = flow_accept(&flow, &data, abstime, &sk);
if (res == 0) {
- ret_msg->flow_info = flow_info_s_to_msg(&flow);
- ret_msg->has_symmkey = symmkey.len != 0;
- ret_msg->symmkey.data = symmkey.data;
- ret_msg->symmkey.len = symmkey.len;
- ret_msg->has_pk = data.len != 0;
- ret_msg->pk.data = data.data;
- ret_msg->pk.len = data.len;
+ ret_msg->flow_info = flow_info_s_to_msg(&flow);
+ ret_msg->has_pk = data.len != 0;
+ ret_msg->pk.data = data.data;
+ ret_msg->pk.len = data.len;
+ ret_msg->has_cipher_nid = true;
+ ret_msg->cipher_nid = sk.nid;
+ if (sk.nid != NID_undef) {
+ hbuf = malloc(SYMMKEYSZ);
+ if (hbuf == NULL) {
+ log_err("Failed to malloc key buf");
+ return NULL;
+ }
+
+ memcpy(hbuf, kbuf, SYMMKEYSZ);
+ ret_msg->sym_key.data = hbuf;
+ ret_msg->sym_key.len = SYMMKEYSZ;
+ ret_msg->has_sym_key = true;
+ }
}
break;
case IRM_MSG_CODE__IRM_FLOW_ALLOC:
@@ -1876,15 +1480,26 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg)
assert(data.len > 0 ? data.data != NULL : data.data == NULL);
flow = flow_info_msg_to_s(msg->flow_info);
abstime = abstime == NULL ? &max : abstime;
- res = flow_alloc(&flow, msg->dst, &symmkey, &data, abstime);
+ sk.key = kbuf;
+ res = flow_alloc(msg->dst, &flow, &data, abstime, &sk);
if (res == 0) {
- ret_msg->flow_info = flow_info_s_to_msg(&flow);
- ret_msg->has_symmkey = symmkey.len != 0;
- ret_msg->symmkey.data = symmkey.data;
- ret_msg->symmkey.len = symmkey.len;
- ret_msg->has_pk = data.len != 0;
- ret_msg->pk.data = data.data;
- ret_msg->pk.len = data.len;
+ ret_msg->flow_info = flow_info_s_to_msg(&flow);
+ ret_msg->has_pk = data.len != 0;
+ ret_msg->pk.data = data.data;
+ ret_msg->pk.len = data.len;
+ ret_msg->has_cipher_nid = true;
+ ret_msg->cipher_nid = sk.nid;
+ if (sk.nid != NID_undef) {
+ hbuf = malloc(SYMMKEYSZ);
+ if (hbuf == NULL) {
+ log_err("Failed to malloc key buf");
+ return NULL;
+ }
+ memcpy(hbuf, kbuf, SYMMKEYSZ);
+ ret_msg->sym_key.data = hbuf;
+ ret_msg->sym_key.len = SYMMKEYSZ;
+ ret_msg->has_sym_key = true;
+ }
}
break;
case IRM_MSG_CODE__IRM_FLOW_JOIN:
@@ -1938,14 +1553,16 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg)
else
ret_msg->result = res;
+ explicit_bzero(kbuf, SYMMKEYSZ);
+
return ret_msg;
}
static void * mainloop(void * o)
{
- int sfd;
- irm_msg_t * msg;
- buffer_t buffer;
+ int sfd;
+ irm_msg_t * msg;
+ buffer_t buffer;
(void) o;
@@ -2170,7 +1787,7 @@ static int irm_load_store(char * dpath)
goto fail_file;
}
- if (auth_add_crt_to_store(irmd.auth.ctx, crt) < 0) {
+ if (oap_auth_add_ca_crt(crt) < 0) {
log_err("Failed to add certificate from %s to store.",
path);
goto fail_crt_add;
@@ -2295,27 +1912,19 @@ static int irm_init(void)
goto fail_tpm_create;
}
- if (pthread_mutex_init(&irmd.auth.mtx, NULL) < 0) {
- log_err("Failed to initialize auth mutex.");
- goto fail_auth_mtx;
+ if (oap_auth_init() < 0) {
+ log_err("Failed to initialize OAP module.");
+ goto fail_oap;
}
- 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;
+ goto fail_load_store;
}
if (irm_load_store(OUROBOROS_CHAIN_DIR) < 0) {
log_err("Failed to load intermediate certificates.");
- goto fail_auth_ctx;
+ goto fail_load_store;
}
#ifdef HAVE_FUSE
@@ -2352,11 +1961,10 @@ static int irm_init(void)
#ifdef HAVE_FUSE
rmdir(FUSE_PREFIX);
#endif
- auth_destroy_ctx(irmd.auth.ctx);
#endif
- fail_auth_ctx:
- pthread_mutex_destroy(&irmd.auth.mtx);
- fail_auth_mtx:
+ fail_load_store:
+ oap_auth_fini();
+ fail_oap:
tpm_destroy(irmd.tpm);
fail_tpm_create:
shm_rdrbuff_destroy(irmd.rdrb);
@@ -2388,18 +1996,7 @@ static void irm_fini(void)
if (irmd_get_state() != IRMD_INIT)
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);
+ oap_auth_fini();
tpm_destroy(irmd.tpm);
@@ -2637,6 +2234,11 @@ int main(int argc,
goto fail_reg;
}
+ if (crypt_secure_malloc_init(IRMD_SECMEM_MAX) < 0) {
+ log_err("Failed to initialize secure memory allocation.");
+ goto fail_reg;
+ }
+
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
if (irm_start() < 0)
@@ -2656,6 +2258,8 @@ int main(int argc,
pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
+ crypt_secure_malloc_fini();
+
reg_clear();
reg_fini();