internal void ProcessNewSessionKeyMessage(Node messageFrom, byte[] key) { string keyHash = FileFind.Common.SHA512Str(key); // This lets us create a brand new session key // if someone wants that for whatever reason. if (messageFrom.SessionKeyDataHash != String.Empty && keyHash != messageFrom.SessionKeyDataHash) { Core.LoggingService.LogInfo("MessageProcessor: Re-keying with: {0}.", messageFrom.ToString()); messageFrom.ClearSessionKey(); } if (messageFrom.FinishedKeyExchange == false) { Core.LoggingService.LogInfo("Received secure channel key from: {0}.", messageFrom.ToString()); messageFrom.SessionKeyDataHash = keyHash; messageFrom.DecryptKeyExchange(key); if (messageFrom.RemoteHasKey == true) { Core.LoggingService.LogInfo("Secure communication channel to {0} now avaliable.", messageFrom.ToString()); network.SendInfoToTrustedNode(messageFrom); } else { messageFrom.CreateNewSessionKey(); } } else { Core.LoggingService.LogWarning("Received secure communication key from: {0}, but key exchange was already finished!", messageFrom.ToString()); } }
internal void ProcessReadyMessage(LocalNodeConnection connection, Node messageFrom) { if (connection.ConnectionState != ConnectionState.Ready) { connection.NodeRemote.RemotelyUntrusted = false; connection.ConnectionState = ConnectionState.Ready; connection.RaiseConnectionReady(); connection.RemoteNodeInfo.LastConnected = DateTime.Now; Core.Settings.SyncNetworkInfoAndSave(); if (connection.ReadySent == false) { connection.SendReady(); } if (messageFrom.FinishedKeyExchange == false && messageFrom.SentKeyExchange == false) { messageFrom.CreateNewSessionKey(); } // The network needs to know about me this new connection, // any nodes I know about, memos, etc... so say hi to // everyone and let them know everything that I know. Message message = network.MessageBuilder.CreateHelloMessage(); message.To = Network.BroadcastNodeID; network.SendBroadcast(message); } else { // XXX: Do we need this? if (connection.ReadySent == false) { connection.SendReady(); } } }
private void ProcessNewConnection(ConnectionInfo connection) { lock (nodes) { Node DestNode = GetNode(connection.DestNodeID); Node SourceNode = GetNode(connection.SourceNodeID); if (DestNode != this.LocalNode & SourceNode != this.LocalNode) { if (DestNode != SourceNode) { if (this.FindConnection(connection.SourceNodeID, connection.DestNodeID) == null) { if (SourceNode == null) { SourceNode = new Node(this, connection.SourceNodeID); SourceNode.NickName = connection.SourceNodeNickname; AddNode(SourceNode); if (this.TrustedNodes.ContainsKey(SourceNode.NodeID)) { SourceNode.CreateNewSessionKey(); } } else { SourceNode.NickName = connection.SourceNodeNickname; } if (DestNode == null) { DestNode = new Node(this, connection.DestNodeID); DestNode.NickName = connection.DestNodeNickname; AddNode(DestNode); if (this.TrustedNodes.ContainsKey(DestNode.NodeID)) { DestNode.CreateNewSessionKey(); } } else { DestNode.NickName = connection.DestNodeNickname; } RemoteNodeConnection c = new RemoteNodeConnection(this); c.NodeLocal = SourceNode; c.NodeRemote = DestNode; c.ConnectionState = ConnectionState.Remote; AddConnection(c); } else { // I am not really sure if this is actually useful... SourceNode.NickName = connection.SourceNodeNickname; DestNode.NickName = connection.DestNodeNickname; } } else { LoggingService.LogWarning("Someone told me about an invalid connection - both sides are the same?! Thats no good!! " + connection.SourceNodeNickname + " <-> " + connection.DestNodeNickname); } } else { if (this.FindConnection(connection.SourceNodeID, connection.DestNodeID) == null) { LoggingService.LogWarning("THAT CONNECTION DOESNT EXIST!!!" + connection.SourceNodeNickname + " <-> " + connection.DestNodeNickname); this.SendBroadcast(this.MessageBuilder.CreateConnectionDownMessage(connection.SourceNodeID, connection.DestNodeID), this.LocalNode); } } } }
// XXX: Refactor this entire method! internal void ProcessMessage(object state) { Message message = null; LocalNodeConnection connection; try { MessageInfo info = (MessageInfo)state; connection = info.Connection; message = info.Message; if (Connections.Contains(connection) == false || connection.ConnectionState == ConnectionState.Disconnected) { LoggingService.LogWarning("Network.ProcessMessage: Ignored message from disconnected connection."); return; } if (this.processedMessages.ContainsKey(message.MessageID)) { return; } this.processedMessages.Add(message.MessageID); if (message.To == Network.BroadcastNodeID || message.To != this.LocalNode.NodeID) { this.SendBroadcast(message, connection.NodeRemote); if (message.To != Network.BroadcastNodeID) return; } TrustedNodeInfo trustedNode = null; if (trustedNodes.ContainsKey(message.From)) { trustedNode = trustedNodes[message.From]; } object content = message.Content; if (message.From == this.LocalNode.NodeID) { if (message.To != Network.BroadcastNodeID) { // This shouldnt have happened, ever. throw new Exception ("Attempt to process our own message. Type: " + message.Type.ToString()); } else { // It's normal to receive our own messages again. Routing ain't so smart. return; } } Node messageFrom = null; lock (nodes) { messageFrom = GetNode(message.From); if (messageFrom == null) { // We don't know about this node! Lets add it.. oh, let's do. if (trustedNode != null) { // If its a trusted node that means we verified the message's signature, // so we know its valid (and thus know this node actually exists). Node node = new Node (this, message.From); node.NickName = trustedNode.Identifier; node.Verified = true; AddNode(node); messageFrom = node; node.CreateNewSessionKey(); } else { // Even if we can't verify that this node exists, we add it anyway. // This has certain potential security issues, such as a flood of messages from random IDs, // but there is really no way around that. // The node will be marked Verified = false by default, so the GUI can ignore it. // (This is added so things like ChatMessages work properly) Node node = new Node (this, message.From); node.NickName = "[" + message.From + "]"; AddNode(node); messageFrom = node; } } } if (trustedNode == null) { if (InsecureMessageTypes.IndexOf(message.Type) == -1) { this.SendNonCriticalError (messageFrom, new NotTrustedError()); return; } } // Make sure nobody is trying to screw with us if (LocalOnlyMessageTypes.IndexOf (message.Type) > -1) { if (messageFrom != connection.NodeRemote) { this.SendCriticalError (messageFrom, new MeshworkError ("That message type is only valid for local connections.")); } } // Well, if they sent us something we can assume they trust us if (message.To != Network.BroadcastNodeID) { messageFrom.RemotelyUntrusted = false; } if (connection != null && (message.From == connection.RemoteNodeInfo.NodeID & message.To == this.LocalNode.NodeID & message.Type == MessageType.CriticalError)) { MeshworkError error = ((MeshworkError)(content)); LoggingService.LogError("RECIEVED CRITICAL ERROR", error.Message); if (ReceivedCriticalError != null) { ReceivedCriticalError((INodeConnection)connection, error); } connection.Disconnect (error.ToException ()); return; } switch (message.Type) { case MessageType.Ping: processor.ProcessPingMessage(messageFrom, (ulong)content); break; case MessageType.Pong: connection.ReceivedPong ((ulong)content); //processor.ProcessPongMessage(messageFrom, (ulong)content); break; case MessageType.Auth: processor.ProcessAuthMessage(connection, messageFrom, (AuthInfo)content, false); break; case MessageType.AuthReply: processor.ProcessAuthMessage(connection, messageFrom, (AuthInfo)content, true); break; case MessageType.RequestKey: processor.ProcessRequestKeyMessage(messageFrom); break; case MessageType.MyKey: processor.ProcessMyKeyMessage(messageFrom, (KeyInfo)content); break; case MessageType.RequestInfo: processor.ProcessRequestInfoMessage(messageFrom); break; case MessageType.NewSessionKey: processor.ProcessNewSessionKeyMessage(messageFrom, (byte[])content); break; case MessageType.MyInfo: processor.ProcessMyInfoMessage(messageFrom, (NodeInfo)content); break; case MessageType.NonCriticalError: processor.ProcessNonCriticalErrorMessage(messageFrom, (MeshworkError)content); break; case MessageType.SearchRequest: processor.ProcessSearchRequestMessage (messageFrom, (SearchRequestInfo)content); break; case MessageType.SearchResult: processor.ProcessSearchResultMessage (messageFrom, (SearchResultInfo)content); break; /* case MessageType.SendFile: processor.ProcessSendFileMessage (messageFrom, (SharedFileInfo)content); break; */ case MessageType.RequestFile: processor.ProcessRequestFileMessage(messageFrom, (RequestFileInfo)content); break; case MessageType.ConnectionDown: processor.ProcessConnectionDownMessage (messageFrom, (ConnectionInfo)content); break; case MessageType.JoinChat: processor.ProcessJoinChatMessage (messageFrom, (ChatAction)content); break; case MessageType.LeaveChat: processor.ProcessLeaveChatMessage (messageFrom, (ChatAction)content); break; case MessageType.ChatInvite: processor.ProcessChatInviteMessage (messageFrom, (ChatInviteInfo)content); break; case MessageType.ChatroomMessage: processor.ProcessChatMessage (messageFrom, (ChatMessage)content); break; case MessageType.PrivateMessage: processor.ProcessPrivateMessage (messageFrom, content.ToString()); break; case MessageType.Ready: processor.ProcessReadyMessage (connection, messageFrom); //, (NetworkState)content); break; case MessageType.AddMemo: processor.ProcessAddMemoMessage (messageFrom, (MemoInfo)content); break; case MessageType.DeleteMemo: processor.ProcessDeleteMemoMessage (messageFrom, content.ToString ()); break; case MessageType.RequestDirListing: processor.ProcessRequestDirListingMessage (messageFrom, content.ToString()); break; case MessageType.RespondDirListing: Core.FileSystem.ProcessRespondDirListingMessage (this, messageFrom, (SharedDirectoryInfo)content); break; case MessageType.Ack: processor.ProcessAckMessage(messageFrom, content.ToString()); break; case MessageType.Hello: processor.ProcessHelloMessage (messageFrom, (HelloInfo)content); break; // case MessageType.NetworkState: // AppendNetworkState ( content as NetworkState ); // //processor.ProcessNetworkStateMessage ( // break; case MessageType.RequestFileDetails: processor.ProcessRequestFileDetails(messageFrom, (string)content); break; case MessageType.FileDetails: Core.FileSystem.ProcessFileDetailsMessage(this, messageFrom, (SharedFileListing)content); break; case MessageType.RequestAvatar: processor.ProcessRequestAvatarMessage(messageFrom); break; case MessageType.Avatar: processor.ProcessAvatarMessage(messageFrom, (byte[])content); break; case MessageType.Test: // Do nothing here. break; default: LoggingService.LogWarning("Received unhandled Message type: {0}, content: {1}", message.Type, content); break; } // else if (Message.Type == MessageTypes.networkState) // AppendNetworkState(((NetworkState)(content))); // //TODO: Why are we checking mesage types // if (message.Type != MessageType.Ack & message.Type != MessageType.Ping & message.Type != MessageType.Pong & message.Type != MessageType.Auth & message.Type != MessageType.AuthReply) { if (nodes.ContainsKey(message.From)) { if (this.TrustedNodes.ContainsKey(message.From) && MessageTypesToAck.IndexOf(message.Type) > -1) { this.SendRoutedMessage((this.MessageBuilder.CreateAckMessage(message.MessageID, messageFrom))); } } // } } catch (Exception ex) { // XXX: Better error handling! string messageType = (message != null) ? message.Type.ToString() : "(Unknown)"; string messageFrom = (message != null) ? message.From : "(Unknown)"; LoggingService.LogError("Network.ProcessMessage: Error processing message of type {0} from {1}: {2}", messageType, messageFrom, ex.ToString()); } }
internal void ProcessReadyMessage(LocalNodeConnection connection, Node messageFrom) { if (connection.ConnectionState != ConnectionState.Ready) { connection.NodeRemote.RemotelyUntrusted = false; connection.ConnectionState = ConnectionState.Ready; connection.RaiseConnectionReady(); connection.RemoteNodeInfo.LastConnected = DateTime.Now; Core.Settings.SyncNetworkInfoAndSave(); if (connection.ReadySent == false) { connection.SendReady(); } if (messageFrom.FinishedKeyExchange == false && messageFrom.SentKeyExchange == false) { messageFrom.CreateNewSessionKey(); } // The network needs to know about me this new connection, // any nodes I know about, memos, etc... so say hi to // everyone and let them know everything that I know. Message message = network.MessageBuilder.CreateHelloMessage (); message.To = Network.BroadcastNodeID; network.SendBroadcast (message); } else { // XXX: Do we need this? if (connection.ReadySent == false) { connection.SendReady(); } } }
internal void ProcessNewSessionKeyMessage(Node messageFrom, byte[] key) { string keyHash = FileFind.Common.SHA512Str(key); // This lets us create a brand new session key // if someone wants that for whatever reason. if (messageFrom.SessionKeyDataHash != String.Empty && keyHash != messageFrom.SessionKeyDataHash) { LoggingService.LogInfo("MessageProcessor: Re-keying with: {0}.", messageFrom.ToString()); messageFrom.ClearSessionKey(); } if (messageFrom.FinishedKeyExchange == false) { LoggingService.LogInfo("Received secure channel key from: {0}.", messageFrom.ToString()); messageFrom.SessionKeyDataHash = keyHash; messageFrom.DecryptKeyExchange(key); if (messageFrom.RemoteHasKey == true) { LoggingService.LogInfo("Secure communication channel to {0} now avaliable.", messageFrom.ToString()); network.SendInfoToTrustedNode(messageFrom); } else { messageFrom.CreateNewSessionKey(); } } else { LoggingService.LogWarning("Received secure communication key from: {0}, but key exchange was already finished!", messageFrom.ToString()); } }