diff --git a/app/app.go b/app/app.go index cc8aea9..62da8bd 100644 --- a/app/app.go +++ b/app/app.go @@ -113,7 +113,7 @@ func (app *application) CreatePeer(name string, password string) { blockedPeers := profile.BlockedPeers() // TODO: Would be nice if ProtocolEngine did not need to explicitly be given the Private Key. identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey) - engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, app.acn, app.eventBuses[profile.Onion], blockedPeers) + engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, app.acn, app.eventBuses[profile.Onion], profile.GetContacts(), blockedPeers) app.peers[profile.Onion] = peer app.engines[profile.Onion] = engine @@ -168,7 +168,7 @@ func (app *application) LoadProfiles(password string) { blockedPeers := profile.BlockedPeers() identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey) - engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, app.acn, app.eventBuses[profile.Onion], blockedPeers) + engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, app.acn, app.eventBuses[profile.Onion], profile.GetContacts(), blockedPeers) app.mutex.Lock() app.peers[profile.Onion] = peer app.storage[profile.Onion] = profileStore diff --git a/app/appService.go b/app/appService.go index 4041527..6e7d719 100644 --- a/app/appService.go +++ b/app/appService.go @@ -96,7 +96,7 @@ func (as *applicationService) createPeer(name, password string) { blockedPeers := profile.BlockedPeers() // TODO: Would be nice if ProtocolEngine did not need to explicitly be given the Private Key. identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey) - engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], blockedPeers) + engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], profile.GetContacts(), blockedPeers) as.storage[profile.Onion] = profileStore as.engines[profile.Onion] = engine @@ -112,7 +112,7 @@ func (as *applicationService) loadProfiles(password string) { blockedPeers := profile.BlockedPeers() identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey) - engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], blockedPeers) + engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], profile.GetContacts(), blockedPeers) as.mutex.Lock() as.storage[profile.Onion] = profileStore as.engines[profile.Onion] = engine diff --git a/event/common.go b/event/common.go index 188f25b..54cab70 100644 --- a/event/common.go +++ b/event/common.go @@ -16,6 +16,10 @@ const ( BlockPeer = Type("BlockPeer") UnblockPeer = Type("UnblockPeer") + // Turn on/off blocking of unknown peers (if peers aren't in the contact list then they will be autoblocked + BlockUnknownPeers = Type("BlockUnknownPeers") + AllowUnknownPeers = Type("AllowUnknownPeers") + JoinServer = Type("JoinServer") ProtocolEngineStartListen = Type("ProtocolEngineStartListen") diff --git a/protocol/connections/engine.go b/protocol/connections/engine.go index 524e770..3c87ca1 100644 --- a/protocol/connections/engine.go +++ b/protocol/connections/engine.go @@ -30,6 +30,9 @@ type engine struct { // Blocklist blocked sync.Map + // Block Unknown Contacts + blockUnknownContacts bool + // Pointer to the Global Event Manager eventManager event.Manager @@ -51,7 +54,7 @@ type Engine interface { } // NewProtocolEngine initializes a new engine that runs Cwtch using the given parameters -func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateKey, acn connectivity.ACN, eventManager event.Manager, blockedPeers []string) Engine { +func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateKey, acn connectivity.ACN, eventManager event.Manager, knownPeers []string, blockedPeers []string) Engine { engine := new(engine) engine.identity = identity engine.privateKey = privateKey @@ -79,6 +82,13 @@ func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateK engine.eventManager.Subscribe(event.BlockPeer, engine.queue) engine.eventManager.Subscribe(event.UnblockPeer, engine.queue) + engine.eventManager.Subscribe(event.BlockUnknownPeers, engine.queue) + engine.eventManager.Subscribe(event.AllowUnknownPeers, engine.queue) + + for _, peer := range knownPeers { + engine.blocked.Store(peer, false) + } + for _, peer := range blockedPeers { engine.blocked.Store(peer, true) } @@ -101,6 +111,7 @@ func (e *engine) eventHandler() { case event.StatusRequest: e.eventManager.Publish(event.Event{EventType: event.ProtocolEngineStatus, EventID: ev.EventID}) case event.PeerRequest: + e.blocked.Store(ev.Data[event.RemotePeer], false) go e.peerWithOnion(ev.Data[event.RemotePeer]) case event.InvitePeerToGroup: e.sendMessageToPeer(ev.EventID, ev.Data[event.RemotePeer], event.ContextInvite, []byte(ev.Data[event.GroupInvite])) @@ -108,6 +119,8 @@ func (e *engine) eventHandler() { e.joinServer(ev.Data[event.GroupServer]) case event.DeleteContact: onion := ev.Data[event.RemotePeer] + // We remove this peer from out blocklist which will prevent them from contacting us if we have "block unknown peers" turned on. + e.blocked.Delete(ev.Data[event.RemotePeer]) e.deleteConnection(onion) case event.DeleteGroup: // TODO: There isn't a way here to determine if other Groups are using a server connection... @@ -127,7 +140,7 @@ func (e *engine) eventHandler() { // We simply remove the peer from our blocklist // The UI has the responsibility to reinitiate contact with the peer. // (this should happen periodically in any case) - e.blocked.Delete(ev.Data[event.RemotePeer]) + e.blocked.Store(ev.Data[event.RemotePeer], false) case event.BlockPeer: e.blocked.Store(ev.Data[event.RemotePeer], true) connection, err := e.service.GetConnection(ev.Data[event.RemotePeer]) @@ -138,6 +151,10 @@ func (e *engine) eventHandler() { // an ongoing Open() connection fails and so the user will see a blocked peer as still connecting (because // there isn't an active connection and we are stuck waiting for tor to time out) e.peerDisconnected(ev.Data[event.RemotePeer]) + case event.AllowUnknownPeers: + e.blockUnknownContacts = false + case event.BlockUnknownPeers: + e.blockUnknownContacts = true case event.ProtocolEngineStartListen: go e.listenFn() default: @@ -149,8 +166,12 @@ func (e *engine) eventHandler() { func (e *engine) createPeerTemplate() *PeerApp { peerAppTemplate := new(PeerApp) peerAppTemplate.IsBlocked = func(onion string) bool { - _, blocked := e.blocked.Load(onion) - return blocked + blocked, known := e.blocked.Load(onion) + if !known { + // if we block unknown peers we will block this contact + return e.blockUnknownContacts + } + return blocked.(bool) } peerAppTemplate.MessageHandler = e.handlePeerMessage peerAppTemplate.OnAcknowledgement = e.ignoreOnShutdown2(e.peerAck) @@ -180,8 +201,8 @@ func (e *engine) Shutdown() { // peerWithOnion is the entry point for cwtchPeer relationships // needs to be run in a goroutine as will block on Open. func (e *engine) peerWithOnion(onion string) { - _, blocked := e.blocked.Load(onion) - if !blocked { + blocked, known := e.blocked.Load(onion) + if known && !(blocked.(bool)) { e.ignoreOnShutdown(e.peerConnecting)(onion) connected, err := e.service.Connect(onion, e.createPeerTemplate()) diff --git a/protocol/connections/peerserverconnection_test.go b/protocol/connections/peerserverconnection_test.go index ce89efc..c7b28d6 100644 --- a/protocol/connections/peerserverconnection_test.go +++ b/protocol/connections/peerserverconnection_test.go @@ -78,7 +78,7 @@ func TestPeerServerConnection(t *testing.T) { onionAddr := identity.Hostname() manager := event.NewEventManager() - engine := NewProtocolEngine(identity, priv, connectivity.LocalProvider(), manager, nil) + engine := NewProtocolEngine(identity, priv, connectivity.LocalProvider(), manager, nil, nil) psc := NewPeerServerConnection(engine, "127.0.0.1:5451|"+onionAddr) numcalls := 0