ipn/ipnlocal: account for ControlURL when merging profiles

We merge/dedupe profiles based on UserID and NodeID, however we were not accounting for ControlURLs.

Updates #713

Signed-off-by: Maisem Ali <maisem@tailscale.com>
pull/6564/head
Maisem Ali 2 years ago committed by Maisem Ali
parent adc302f428
commit 82ad585b5b

@ -98,21 +98,25 @@ func (pm *profileManager) matchingProfiles(f func(*ipn.LoginProfile) bool) (out
return 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() { if nodeID.IsZero() {
return nil return nil
} }
return pm.matchingProfiles(func(p *ipn.LoginProfile) bool { 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() { if userID.IsZero() {
return nil return nil
} }
return pm.matchingProfiles(func(p *ipn.LoginProfile) bool { 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 { if pm.isNewProfile {
pm.isNewProfile = false pm.isNewProfile = false
// Check if we already have a profile for this user. // 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. // 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 { if len(existing) == 0 {
cp.ID, cp.Key = newUnusedID(pm.knownProfiles) cp.ID, cp.Key = newUnusedID(pm.knownProfiles)
} else { } else {
@ -217,6 +221,7 @@ func (pm *profileManager) SetPrefs(prefsIn ipn.PrefsView) error {
} else { } else {
cp.Name = up.LoginName cp.Name = up.LoginName
} }
cp.ControlURL = prefs.ControlURL()
cp.UserProfile = newPersist.UserProfile cp.UserProfile = newPersist.UserProfile
cp.NodeID = newPersist.NodeID cp.NodeID = newPersist.NodeID
pm.knownProfiles[cp.ID] = cp pm.knownProfiles[cp.ID] = cp

@ -131,15 +131,22 @@ func TestProfileList(t *testing.T) {
if lp := pm.findProfileByName(carol.Name); lp != nil { if lp := pm.findProfileByName(carol.Name); lp != nil {
t.Fatalf("found profile for user2 in user1's profile list") 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") 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") t.Fatalf("found profile for user2 in user1's profile list")
} }
pm.SetCurrentUserID("user2") pm.SetCurrentUserID("user2")
checkProfiles(t, "carol") 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. // TestProfileManagement tests creating, loading, and switching profiles.

@ -741,4 +741,8 @@ type LoginProfile struct {
// It is only relevant on Windows where we have a multi-user system. // It is only relevant on Windows where we have a multi-user system.
// It is assigned once at profile creation time and never changes. // It is assigned once at profile creation time and never changes.
LocalUserID WindowsUserID LocalUserID WindowsUserID
// ControlURL is the URL of the control server that this profile is logged
// into.
ControlURL string
} }

Loading…
Cancel
Save