summaryrefslogtreecommitdiff
path: root/src/irmd/oap
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2026-05-01 23:41:49 +0200
committerSander Vrijders <sander@ouroboros.rocks>2026-05-20 08:17:05 +0200
commit2ddcad3989cd8d2314453ed31ff43e122118663f (patch)
tree201cbde8ccb850021ab54d1331a7c8ec3558793c /src/irmd/oap
parent44ca111c2b9cf45491edc99062f89c89060525ae (diff)
downloadouroboros-2ddcad3989cd8d2314453ed31ff43e122118663f.tar.gz
ouroboros-2ddcad3989cd8d2314453ed31ff43e122118663f.zip
irmd: Drop replayed flow alloc requests
A duplicating link could deliver the same alloc request twice. OAP detected the replay but still replied over the wire, so the requester saw a second flow_alloc_reply on an already-allocated flow and reg_respond_alloc tripped its PENDING-state assertion. Add EREPLAY so the OAP server can signal replays distinctly; flow_accept drops them silently. As a safety net, reg_respond_alloc warn-drops late replies instead of asserting. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/irmd/oap')
-rw-r--r--src/irmd/oap/auth.c1
-rw-r--r--src/irmd/oap/srv.c15
-rw-r--r--src/irmd/oap/tests/oap_test.c7
3 files changed, 18 insertions, 5 deletions
diff --git a/src/irmd/oap/auth.c b/src/irmd/oap/auth.c
index 4b86f055..d165de73 100644
--- a/src/irmd/oap/auth.c
+++ b/src/irmd/oap/auth.c
@@ -174,6 +174,7 @@ int oap_check_hdr(const struct oap_hdr * hdr)
fail_replay:
pthread_mutex_unlock(&oap_auth.replay.mtx);
free(new);
+ return -EREPLAY;
fail_stamp:
return -EAUTH;
}
diff --git a/src/irmd/oap/srv.c b/src/irmd/oap/srv.c
index afc54acc..ce97654f 100644
--- a/src/irmd/oap/srv.c
+++ b/src/irmd/oap/srv.c
@@ -393,6 +393,7 @@ int oap_srv_process(const struct name_info * info,
void * pkp = NULL;
void * crt = NULL;
int req_md_nid;
+ int ret;
assert(info != NULL);
assert(rsp_buf != NULL);
@@ -427,8 +428,13 @@ int oap_srv_process(const struct name_info * info,
id = peer_hdr.id.data; /* Logging */
- if (oap_check_hdr(&peer_hdr) < 0) {
- log_err_id(id, "OAP header failed replay check.");
+ ret = oap_check_hdr(&peer_hdr);
+ if (ret == -EREPLAY) {
+ log_warn_id(id, "OAP header failed replay check.");
+ goto fail_replay;
+ }
+ if (ret < 0) {
+ log_err_id(id, "OAP header check failed.");
goto fail_auth;
}
@@ -491,6 +497,11 @@ int oap_srv_process(const struct name_info * info,
fail_cred:
return -EAUTH;
+ fail_replay:
+ crypt_free_crt(crt);
+ crypt_free_key(pkp);
+ return -EREPLAY;
+
fail_kex:
crypt_free_crt(crt);
crypt_free_key(pkp);
diff --git a/src/irmd/oap/tests/oap_test.c b/src/irmd/oap/tests/oap_test.c
index a324b586..a525d988 100644
--- a/src/irmd/oap/tests/oap_test.c
+++ b/src/irmd/oap/tests/oap_test.c
@@ -32,6 +32,7 @@
#include <ouroboros/crypt.h>
#include <ouroboros/endian.h>
+#include <ouroboros/errno.h>
#include <ouroboros/flow.h>
#include <ouroboros/name.h>
#include <ouroboros/random.h>
@@ -1053,9 +1054,9 @@ static int test_oap_replay_packet(void)
freebuf(ctx.req_hdr);
ctx.req_hdr = saved_req;
- /* Replayed request should fail */
- if (oap_srv_process_ctx(&ctx) == 0) {
- printf("Server should reject replayed packet.\n");
+ /* Replay must return -EREPLAY so callers can drop silently. */
+ if (oap_srv_process_ctx(&ctx) != -EREPLAY) {
+ printf("Replayed packet rejection != -EREPLAY.\n");
goto fail_cleanup;
}