diff --git a/ipn/ipnlocal/profiles.go b/ipn/ipnlocal/profiles.go index 917ebf027..ee4bf5945 100644 --- a/ipn/ipnlocal/profiles.go +++ b/ipn/ipnlocal/profiles.go @@ -98,21 +98,25 @@ func (pm *profileManager) matchingProfiles(f func(*ipn.LoginProfile) bool) (out return out } -func (pm *profileManager) findProfilesByNodeID(nodeID tailcfg.StableNodeID) []*ipn.LoginProfile { +// findProfilesByNodeID returns all profiles that have the provided nodeID and +// belong to the same control server. +func (pm *profileManager) findProfilesByNodeID(controlURL string, nodeID tailcfg.StableNodeID) []*ipn.LoginProfile { if nodeID.IsZero() { return nil } return pm.matchingProfiles(func(p *ipn.LoginProfile) bool { - return p.NodeID == nodeID + return p.NodeID == nodeID && p.ControlURL == controlURL }) } -func (pm *profileManager) findProfilesByUserID(userID tailcfg.UserID) []*ipn.LoginProfile { +// findProfilesByUserID returns all profiles that have the provided userID and +// belong to the same control server. +func (pm *profileManager) findProfilesByUserID(controlURL string, userID tailcfg.UserID) []*ipn.LoginProfile { if userID.IsZero() { return nil } return pm.matchingProfiles(func(p *ipn.LoginProfile) bool { - return p.UserProfile.ID == userID + return p.UserProfile.ID == userID && p.ControlURL == controlURL }) } @@ -197,9 +201,9 @@ func (pm *profileManager) SetPrefs(prefsIn ipn.PrefsView) error { if pm.isNewProfile { pm.isNewProfile = false // Check if we already have a profile for this user. - existing := pm.findProfilesByUserID(newPersist.UserProfile.ID) + existing := pm.findProfilesByUserID(prefs.ControlURL(), newPersist.UserProfile.ID) // Also check if we have a profile with the same NodeID. - existing = append(existing, pm.findProfilesByNodeID(newPersist.NodeID)...) + existing = append(existing, pm.findProfilesByNodeID(prefs.ControlURL(), newPersist.NodeID)...) if len(existing) == 0 { cp.ID, cp.Key = newUnusedID(pm.knownProfiles) } else { @@ -217,6 +221,7 @@ func (pm *profileManager) SetPrefs(prefsIn ipn.PrefsView) error { } else { cp.Name = up.LoginName } + cp.ControlURL = prefs.ControlURL() cp.UserProfile = newPersist.UserProfile cp.NodeID = newPersist.NodeID pm.knownProfiles[cp.ID] = cp diff --git a/ipn/ipnlocal/profiles_test.go b/ipn/ipnlocal/profiles_test.go index 9543b2421..4bc646957 100644 --- a/ipn/ipnlocal/profiles_test.go +++ b/ipn/ipnlocal/profiles_test.go @@ -131,15 +131,22 @@ func TestProfileList(t *testing.T) { if lp := pm.findProfileByName(carol.Name); lp != nil { t.Fatalf("found profile for user2 in user1's profile list") } - if lp := pm.findProfilesByNodeID(carol.NodeID); lp != nil { + if lp := pm.findProfilesByNodeID(carol.ControlURL, carol.NodeID); lp != nil { t.Fatalf("found profile for user2 in user1's profile list") } - if lp := pm.findProfilesByUserID(carol.UserProfile.ID); lp != nil { + if lp := pm.findProfilesByUserID(carol.ControlURL, carol.UserProfile.ID); lp != nil { t.Fatalf("found profile for user2 in user1's profile list") } pm.SetCurrentUserID("user2") checkProfiles(t, "carol") + if lp := pm.findProfilesByNodeID(carol.ControlURL, carol.NodeID); lp == nil { + t.Fatalf("did not find profile for user2 in user2's profile list") + } + if lp := pm.findProfilesByUserID(carol.ControlURL, carol.UserProfile.ID); lp == nil { + t.Fatalf("did not find profile for user2 in user2's profile list") + } + } // TestProfileManagement tests creating, loading, and switching profiles. diff --git a/ipn/prefs.go b/ipn/prefs.go index 466f20b15..a94c46887 100644 --- a/ipn/prefs.go +++ b/ipn/prefs.go @@ -741,4 +741,8 @@ type LoginProfile struct { // It is only relevant on Windows where we have a multi-user system. // It is assigned once at profile creation time and never changes. LocalUserID WindowsUserID + + // ControlURL is the URL of the control server that this profile is logged + // into. + ControlURL string }