Explorar el Código

Take a hybrid tunnel on msg3 even over a newer one, the initiator has committed to it

JackDoan hace 6 días
padre
commit
bbade4dc9a
Se han modificado 2 ficheros con 12 adiciones y 2 borrados
  1. 8 1
      handshake_manager.go
  2. 4 1
      handshake_manager_hybrid.go

+ 8 - 1
handshake_manager.go

@@ -495,6 +495,13 @@ var (
 // ErrLocalIndexCollision if we already have an entry in the main or pending
 // hostmap for the hostinfo.localIndexId.
 func (hm *HandshakeManager) CheckAndComplete(hostinfo *HostInfo, handshakePacket uint8, f *Interface) (*HostInfo, error) {
+	return hm.checkAndComplete(hostinfo, handshakePacket, f, false)
+}
+
+// checkAndComplete is CheckAndComplete. committed means the initiator has shown it
+// uses this tunnel, as a hybrid msg3 does, so an existing tunnel is replaced even
+// when its handshake is newer.
+func (hm *HandshakeManager) checkAndComplete(hostinfo *HostInfo, handshakePacket uint8, f *Interface, committed bool) (*HostInfo, error) {
 	hm.mainHostMap.Lock()
 	defer hm.mainHostMap.Unlock()
 	hm.Lock()
@@ -511,7 +518,7 @@ func (hm *HandshakeManager) CheckAndComplete(hostinfo *HostInfo, handshakePacket
 		}
 
 		// Is this a newer handshake?
-		if existingHostInfo.lastHandshakeTime >= hostinfo.lastHandshakeTime && !existingHostInfo.ConnectionState.initiator {
+		if !committed && existingHostInfo.lastHandshakeTime >= hostinfo.lastHandshakeTime && !existingHostInfo.ConnectionState.initiator {
 			return existingHostInfo, ErrExistingHostInfo
 		}
 

+ 4 - 1
handshake_manager_hybrid.go

@@ -214,7 +214,10 @@ func (hm *HandshakeManager) completeHybridResponder(via ViaSender, hh *Handshake
 	remoteCert := result.RemoteCert
 	hostinfo.buildNetworks(f.myVpnNetworksTable, remoteCert.Certificate)
 
-	existing, err := hm.CheckAndComplete(hostinfo, handshakePacketStage0, f)
+	// The initiator only sends msg3 once it settled on this handshake, so this
+	// tunnel wins even over a newer one: a classical attempt that crossed it, say,
+	// which the initiator has already given up on.
+	existing, err := hm.checkAndComplete(hostinfo, handshakePacketStage0, f, true)
 	if err != nil {
 		hm.handleCheckAndCompleteError(err, existing, hostinfo, via, machine.Subtype(), 0)
 		return