Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions nvflare/fuel/f3/cellnet/core_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
from nvflare.fuel.f3.cellnet.defs import (
AbortRun,
AuthenticationError,
CellChannel,
CellChannelTopic,
CellPropertyKey,
InvalidRequest,
InvalidSession,
Expand Down Expand Up @@ -60,9 +62,7 @@
from nvflare.fuel.utils.log_utils import get_obj_logger
from nvflare.security.logging import secure_format_exception, secure_format_traceback

_CHANNEL = "cellnet.channel"
_TOPIC_BULK = "bulk"
_TOPIC_BYE = "bye"
_SM_CHANNEL = "credential_manager"
_SM_TOPIC = "key_exchange"

Expand Down Expand Up @@ -197,7 +197,7 @@ def send(self):
tms = [m.to_dict() for m in messages_to_send]
bulk_msg = Message(None, tms)
send_errs = self.cell.fire_and_forget(
channel=_CHANNEL, topic=_TOPIC_BULK, targets=[self.target], message=bulk_msg
channel=CellChannel.CELLNET, topic=_TOPIC_BULK, targets=[self.target], message=bulk_msg
)
if send_errs[self.target]:
log_messaging_error(
Expand Down Expand Up @@ -497,8 +497,8 @@ def __init__(
self.adhoc_connector_lock = threading.Lock()
self.root_change_lock = threading.Lock()

self.register_request_cb(channel=_CHANNEL, topic=_TOPIC_BULK, cb=self._receive_bulk_message)
self.register_request_cb(channel=_CHANNEL, topic=_TOPIC_BYE, cb=self._peer_goodbye)
self.register_request_cb(channel=CellChannel.CELLNET, topic=_TOPIC_BULK, cb=self._receive_bulk_message)
self.register_request_cb(channel=CellChannel.CELLNET, topic=CellChannelTopic.Bye, cb=self._peer_goodbye)

self.cleanup_waiter = None
self.msg_stats_pool = StatsPoolManager.add_time_hist_pool(
Expand Down Expand Up @@ -974,8 +974,8 @@ def stop(self):
targets = [peer_name for peer_name in self.agents.keys()]
self.logger.debug(f"broadcasting goodbye to {targets}")
self.broadcast_request(
channel=_CHANNEL,
topic=_TOPIC_BYE,
channel=CellChannel.CELLNET,
topic=CellChannelTopic.Bye,
targets=targets,
request=Message(),
timeout=0.5,
Expand Down
2 changes: 2 additions & 0 deletions nvflare/fuel/f3/cellnet/defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,14 @@ class CellChannel:
RETURN_ONLY = "return_only"
EDGE_REQUEST = "edge_request"
HCI = "hci_channel"
CELLNET = "cellnet.channel"


class CellChannelTopic:

Challenge = "challenge"
Register = "register"
Bye = "bye"
Quit = "quit"
GET_TASK = "get_task"
SUBMIT_RESULT = "submit_result"
Expand Down
21 changes: 21 additions & 0 deletions nvflare/private/fed/authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,27 @@ def validate_auth_headers(
logger.debug(f"skip special message {topic=} {channel=}")
return None

# Cellnet protocol-level goodbye is broadcast by Cell.stop() with an empty
# Message() that carries no FL-level auth headers. Only bypass auth when the
# message is for the immediate (direct-neighbor) recipient, i.e. TO_CELL ==
# DESTINATION. If it would be forwarded onward (TO_CELL != DESTINATION), a
# remote unauthenticated peer could craft a bye with DESTINATION pointing
# at a downstream cell whose _peer_goodbye would then drop the immediate
# endpoint (the server/relay) from its agents dict — fall through to the
# normal auth check in that case. The explicit ``to_cell is not None``
# check rejects crafted messages that omit both headers (None == None
# would otherwise pass).
to_cell = message.get_header(MessageHeaderKey.TO_CELL)
destination = message.get_header(MessageHeaderKey.DESTINATION)
if (
topic == CellChannelTopic.Bye
and channel == CellChannel.CELLNET
and to_cell is not None
and to_cell == destination
Comment thread
YuanTingHsieh marked this conversation as resolved.
Outdated
):
logger.debug(f"skip direct-neighbor cellnet bye {topic=} {channel=}")
return None

client_name = message.get_header(CellMessageHeaderKeys.CLIENT_NAME)
err_text = f"unauthenticated msg ({channel=} {topic=}) received from {origin}"
if not client_name:
Expand Down
Loading