allow revert to invalid nodeinfo

This commit is contained in:
Christien Rioux
2023-07-14 19:14:12 -04:00
parent 167374969d
commit e61d6be6a9
21 changed files with 207 additions and 220 deletions

View File

@@ -31,9 +31,19 @@ pub enum Destination {
impl Destination {
pub fn target(&self) -> Option<NodeRef> {
match self {
Destination::Direct { target, safety_selection: _ } => Some(target.clone()),
Destination::Relay { relay:_, target, safety_selection: _ } => Some(target.clone()),
Destination::PrivateRoute { private_route:_, safety_selection:_ } => None,
Destination::Direct {
target,
safety_selection: _,
} => Some(target.clone()),
Destination::Relay {
relay: _,
target,
safety_selection: _,
} => Some(target.clone()),
Destination::PrivateRoute {
private_route: _,
safety_selection: _,
} => None,
}
}
pub fn direct(target: NodeRef) -> Self {
@@ -217,7 +227,6 @@ impl RPCProcessor {
private_route,
safety_selection,
} => {
let Some(avoid_node_id) = private_route.first_hop_node_id() else {
return Err(RPCError::internal("destination private route must have first hop"));
};
@@ -227,21 +236,21 @@ impl RPCProcessor {
match safety_selection {
SafetySelection::Unsafe(_) => {
// Sent to a private route with no safety route, use a stub safety route for the response
if !routing_table.has_valid_network_class(RoutingDomain::PublicInternet) {
return Ok(NetworkResult::no_connection_other(
"Own node info must be valid to use private route",
));
}
// Determine if we can use optimized nodeinfo
let route_node = if rss
.has_remote_private_route_seen_our_node_info(&private_route.public_key.value)
{
if !routing_table.has_valid_own_node_info(RoutingDomain::PublicInternet) {
return Ok(NetworkResult::no_connection_other("Own node info must be valid to use private route"));
}
RouteNode::NodeId(routing_table.node_id(crypto_kind).value)
} else {
let Some(own_peer_info) =
routing_table.get_own_peer_info(RoutingDomain::PublicInternet) else {
return Ok(NetworkResult::no_connection_other("Own peer info must be valid to use private route"));
};
RouteNode::PeerInfo(own_peer_info)
let route_node = if rss.has_remote_private_route_seen_our_node_info(
&private_route.public_key.value,
) {
RouteNode::NodeId(routing_table.node_id(crypto_kind).value)
} else {
let own_peer_info =
routing_table.get_own_peer_info(RoutingDomain::PublicInternet);
RouteNode::PeerInfo(own_peer_info)
};
Ok(NetworkResult::value(RespondTo::PrivateRoute(
@@ -250,10 +259,12 @@ impl RPCProcessor {
}
SafetySelection::Safe(safety_spec) => {
// Sent to a private route via a safety route, respond to private route
// Check for loopback test
let opt_private_route_id = rss.get_route_id_for_key(&private_route.public_key.value);
let pr_key = if opt_private_route_id.is_some() && safety_spec.preferred_route == opt_private_route_id
let opt_private_route_id =
rss.get_route_id_for_key(&private_route.public_key.value);
let pr_key = if opt_private_route_id.is_some()
&& safety_spec.preferred_route == opt_private_route_id
{
// Private route is also safety route during loopback test
private_route.public_key.value
@@ -308,7 +319,10 @@ impl RPCProcessor {
};
// Reply directly to the request's source
let sender_node_id = TypedKey::new(detail.envelope.get_crypto_kind(), detail.envelope.get_sender_id());
let sender_node_id = TypedKey::new(
detail.envelope.get_crypto_kind(),
detail.envelope.get_sender_id(),
);
// This may be a different node's reference than the 'sender' in the case of a relay
let peer_noderef = detail.peer_noderef.clone();
@@ -320,18 +334,21 @@ impl RPCProcessor {
} else {
// Look up the sender node, we should have added it via senderNodeInfo before getting here.
let res = match self.routing_table.lookup_node_ref(sender_node_id) {
Ok(v) => v,
Err(e) => return NetworkResult::invalid_message(
format!("failed to look up node info for respond to: {}", e)
)};
Ok(v) => v,
Err(e) => {
return NetworkResult::invalid_message(format!(
"failed to look up node info for respond to: {}",
e
))
}
};
if let Some(sender_noderef) = res {
NetworkResult::value(Destination::relay(peer_noderef, sender_noderef))
NetworkResult::value(Destination::relay(peer_noderef, sender_noderef))
} else {
return NetworkResult::invalid_message(
"not responding to sender that has no node info",
);
}
}
}
RespondTo::PrivateRoute(pr) => {

View File

@@ -888,10 +888,9 @@ impl RPCProcessor {
// Get the target's node info timestamp
let target_node_info_ts = target.node_info_ts(routing_domain);
// Don't return our node info if it's not valid yet
let Some(own_peer_info) = routing_table.get_own_peer_info(routing_domain) else {
return SenderPeerInfo::new_no_peer_info(target_node_info_ts);
};
// Return whatever peer info we have even if the network class is not yet valid
// That away we overwrite any prior existing valid-network-class nodeinfo in the remote routing table
let own_peer_info = routing_table.get_own_peer_info(routing_domain);
// Get our node info timestamp
let our_node_info_ts = own_peer_info.signed_node_info().timestamp();
@@ -1475,6 +1474,12 @@ impl RPCProcessor {
let mut opt_sender_nr: Option<NodeRef> = None;
if let Some(sender_peer_info) = operation.sender_peer_info() {
// Ensure the sender peer info is for the actual sender specified in the envelope
if !sender_peer_info.node_ids().contains(&sender_node_id) {
// Attempted to update peer info for the wrong node id
return Ok(NetworkResult::invalid_message(
"attempt to update peer info for non-sender node id",
));
}
// Sender PeerInfo was specified, update our routing table with it
if !self.verify_node_info(

View File

@@ -55,18 +55,16 @@ impl RPCProcessor {
) -> Result<NetworkResult<()>, RPCError> {
// Ignore if disabled
let routing_table = self.routing_table();
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_APPMESSAGE)
{
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_APPMESSAGE)
{
return Ok(NetworkResult::service_unavailable(
"app call is not available",
));
}
}
return Ok(NetworkResult::service_unavailable(
"app call is not available",
));
}
// Get the question

View File

@@ -26,18 +26,15 @@ impl RPCProcessor {
) -> Result<NetworkResult<()>, RPCError> {
// Ignore if disabled
let routing_table = self.routing_table();
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_APPMESSAGE)
{
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_APPMESSAGE)
{
return Ok(NetworkResult::service_unavailable(
"app message is not available",
));
}
}
return Ok(NetworkResult::service_unavailable(
"app message is not available",
));
}
// Get the statement

View File

@@ -175,15 +175,17 @@ impl RPCProcessor {
}
// Ignore if disabled
let routing_table = self.routing_table();
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_DHT)
{
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
return Ok(NetworkResult::service_unavailable(
"dht is not available",
));
}
}
return Ok(NetworkResult::service_unavailable(
"dht is not available",
));
}
// Get the question
let kind = msg.operation.kind().clone();
let get_value_q = match kind {

View File

@@ -367,14 +367,21 @@ impl RPCProcessor {
) -> Result<NetworkResult<()>, RPCError> {
// Ignore if disabled
let routing_table = self.routing_table();
if !routing_table.has_valid_network_class(msg.header.routing_domain()) {
return Ok(NetworkResult::service_unavailable(
"can't route without valid network class",
));
}
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_ROUTE)
{
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
if !opi.signed_node_info().node_info().has_capability(CAP_ROUTE) {
return Ok(NetworkResult::service_unavailable(
"route is not available",
));
}
}
return Ok(NetworkResult::service_unavailable(
"route is not available",
));
}
// Get header detail, must be direct and not inside a route itself

View File

@@ -177,15 +177,17 @@ impl RPCProcessor {
) -> Result<NetworkResult<()>, RPCError> {
// Ignore if disabled
let routing_table = self.routing_table();
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_DHT)
{
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
return Ok(NetworkResult::service_unavailable(
"dht is not available",
));
}
}
return Ok(NetworkResult::service_unavailable(
"dht is not available",
));
}
// Ensure this never came over a private route, safety route is okay though
match &msg.header.detail {
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}

View File

@@ -39,15 +39,15 @@ impl RPCProcessor {
) -> Result<NetworkResult<()>, RPCError> {
// Ignore if disabled
let routing_table = self.routing_table();
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_SIGNAL)
{
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
let ni = opi.signed_node_info().node_info();
if !ni.has_capability(CAP_SIGNAL) {
return Ok(NetworkResult::service_unavailable(
"signal is not available",
));
}
}
return Ok(NetworkResult::service_unavailable(
"signal is not available",
));
}
// Can't allow anything other than direct packets here, as handling reverse connections

View File

@@ -58,6 +58,14 @@ impl RPCProcessor {
&self,
msg: RPCMessage,
) -> Result<NetworkResult<()>, RPCError> {
let routing_table = self.routing_table();
if !routing_table.has_valid_network_class(msg.header.routing_domain()) {
return Ok(NetworkResult::service_unavailable(
"can't validate dial info without valid network class",
));
}
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
let detail = match msg.header.detail {
RPCMessageHeaderDetail::Direct(detail) => detail,
RPCMessageHeaderDetail::SafetyRouted(_) | RPCMessageHeaderDetail::PrivateRouted(_) => {
@@ -68,16 +76,16 @@ impl RPCProcessor {
};
// Ignore if disabled
let routing_table = self.routing_table();
let ni = opi.signed_node_info().node_info();
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_VALIDATE_DIAL_INFO)
|| !ni.is_fully_direct_inbound()
{
if let Some(opi) = routing_table.get_own_peer_info(detail.routing_domain) {
let ni = opi.signed_node_info().node_info();
if !ni.has_capability(CAP_VALIDATE_DIAL_INFO) || !ni.is_fully_direct_inbound() {
return Ok(NetworkResult::service_unavailable(
"validate dial info is not available",
));
}
}
return Ok(NetworkResult::service_unavailable(
"validate dial info is not available",
));
}
// Get the statement

View File

@@ -8,12 +8,9 @@ impl RPCProcessor {
) -> Result<NetworkResult<()>, RPCError> {
// Ignore if disabled
let routing_table = self.routing_table();
{
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
return Ok(NetworkResult::service_unavailable("dht is not available"));
}
}
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
return Ok(NetworkResult::service_unavailable("dht is not available"));
}
Err(RPCError::unimplemented("process_value_changed"))
}

View File

@@ -8,12 +8,9 @@ impl RPCProcessor {
) -> Result<NetworkResult<()>, RPCError> {
// Ignore if disabled
let routing_table = self.routing_table();
{
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
return Ok(NetworkResult::service_unavailable("dht is not available"));
}
}
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
return Ok(NetworkResult::service_unavailable("dht is not available"));
}
Err(RPCError::unimplemented("process_watch_value_q"))
}