diff --git a/VERSION.txt b/VERSION.txt index a95a46d9fa9c7..00e952d041c97 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.34.1 +1.34.2 diff --git a/cmd/tailscale/cli/web.go b/cmd/tailscale/cli/web.go index ea55d1b0b2c9b..1bf319dc74a59 100644 --- a/cmd/tailscale/cli/web.go +++ b/cmd/tailscale/cli/web.go @@ -223,8 +223,8 @@ func qnapAuthnQtoken(r *http.Request, user, token string) (string, *qnapAuthResp "user": []string{user}, } u := url.URL{ - Scheme: r.URL.Scheme, - Host: r.URL.Host, + Scheme: "http", + Host: "127.0.0.1:8080", Path: "/cgi-bin/authLogin.cgi", RawQuery: query.Encode(), } @@ -237,8 +237,8 @@ func qnapAuthnSid(r *http.Request, user, sid string) (string, *qnapAuthResponse, "sid": []string{sid}, } u := url.URL{ - Scheme: r.URL.Scheme, - Host: r.URL.Host, + Scheme: "http", + Host: "127.0.0.1:8080", Path: "/cgi-bin/authLogin.cgi", RawQuery: query.Encode(), } diff --git a/go.mod b/go.mod index 68732f99de27b..ac80176e9755b 100644 --- a/go.mod +++ b/go.mod @@ -68,7 +68,7 @@ require ( golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e golang.org/x/net v0.1.0 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 - golang.org/x/sys v0.1.0 + golang.org/x/sys v0.3.1-0.20221220025402-2204b6615fb8 golang.org/x/term v0.1.0 golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 golang.org/x/tools v0.1.12 diff --git a/go.sum b/go.sum index 4f4e53e16684b..88054ee5fa6d3 100644 --- a/go.sum +++ b/go.sum @@ -1516,6 +1516,8 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.1-0.20221220025402-2204b6615fb8 h1:/VqMvhQCyzfuc826eNrpWmMb3AwD2Sxz/HMsYIhwcIs= +golang.org/x/sys v0.3.1-0.20221220025402-2204b6615fb8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/go.toolchain.rev b/go.toolchain.rev index d2ac200d2fbd9..822a5d34a5880 100644 --- a/go.toolchain.rev +++ b/go.toolchain.rev @@ -1 +1 @@ -3fd24dee31726924c1b61c8037a889b30b8aa0f6 +e6ce5b50036022c91783161890eabecfddc5ae79 diff --git a/ipn/ipnlocal/profiles.go b/ipn/ipnlocal/profiles.go index ee4bf5945a632..e807cf7392e0c 100644 --- a/ipn/ipnlocal/profiles.go +++ b/ipn/ipnlocal/profiles.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "math/rand" + "net/netip" "runtime" "time" @@ -19,6 +20,7 @@ import ( "tailscale.com/types/logger" "tailscale.com/util/clientmetric" "tailscale.com/util/strs" + "tailscale.com/util/winutil" "tailscale.com/version" ) @@ -322,7 +324,7 @@ func (pm *profileManager) setAsUserSelectedProfileLocked() error { func (pm *profileManager) loadSavedPrefs(key ipn.StateKey) (ipn.PrefsView, error) { bs, err := pm.store.ReadState(key) if err == ipn.ErrStateNotExist || len(bs) == 0 { - return emptyPrefs, nil + return defaultPrefs, nil } if err != nil { return ipn.PrefsView{}, err @@ -394,15 +396,29 @@ func (pm *profileManager) writeKnownProfiles() error { func (pm *profileManager) NewProfile() { metricNewProfile.Add(1) - pm.prefs = emptyPrefs + pm.prefs = defaultPrefs pm.isNewProfile = true pm.currentProfile = &ipn.LoginProfile{} } -// emptyPrefs is the default prefs for a new profile. -var emptyPrefs = func() ipn.PrefsView { +// defaultPrefs is the default prefs for a new profile. +var defaultPrefs = func() ipn.PrefsView { prefs := ipn.NewPrefs() prefs.WantRunning = false + + prefs.ControlURL = winutil.GetPolicyString("LoginURL", "") + + if exitNode := winutil.GetPolicyString("ExitNodeIP", ""); exitNode != "" { + if ip, err := netip.ParseAddr(exitNode); err == nil { + prefs.ExitNodeIP = ip + } + } + + // Allow Incoming (used by the UI) is the negation of ShieldsUp (used by the + // backend), so this has to convert between the two conventions. + prefs.ShieldsUp = winutil.GetPolicyString("AllowIncomingConnections", "") == "never" + prefs.ForceDaemon = winutil.GetPolicyString("UnattendedMode", "") == "always" + return prefs.View() }() diff --git a/ipn/ipnlocal/profiles_test.go b/ipn/ipnlocal/profiles_test.go index 4bc64695749af..c977676ba5eb5 100644 --- a/ipn/ipnlocal/profiles_test.go +++ b/ipn/ipnlocal/profiles_test.go @@ -53,7 +53,7 @@ func TestProfileCurrentUserSwitch(t *testing.T) { } else if pm.currentProfile.ID != "" { t.Fatalf("currentProfile.ID = %q, want empty", pm.currentProfile.ID) } - if !pm.CurrentPrefs().Equals(emptyPrefs) { + if !pm.CurrentPrefs().Equals(defaultPrefs) { t.Fatalf("CurrentPrefs() = %v, want emptyPrefs", pm.CurrentPrefs().Pretty()) } @@ -67,7 +67,7 @@ func TestProfileCurrentUserSwitch(t *testing.T) { } else if pm.currentProfile.ID != "" { t.Fatalf("currentProfile.ID = %q, want empty", pm.currentProfile.ID) } - if !pm.CurrentPrefs().Equals(emptyPrefs) { + if !pm.CurrentPrefs().Equals(defaultPrefs) { t.Fatalf("CurrentPrefs() = %v, want emptyPrefs", pm.CurrentPrefs().Pretty()) } } @@ -159,7 +159,7 @@ func TestProfileManagement(t *testing.T) { } wantCurProfile := "" wantProfiles := map[string]ipn.PrefsView{ - "": emptyPrefs, + "": defaultPrefs, } checkProfiles := func(t *testing.T) { t.Helper() @@ -237,7 +237,7 @@ func TestProfileManagement(t *testing.T) { t.Logf("Create new profile") pm.NewProfile() wantCurProfile = "" - wantProfiles[""] = emptyPrefs + wantProfiles[""] = defaultPrefs checkProfiles(t) { @@ -276,7 +276,7 @@ func TestProfileManagement(t *testing.T) { t.Logf("Create new profile - 2") pm.NewProfile() wantCurProfile = "" - wantProfiles[""] = emptyPrefs + wantProfiles[""] = defaultPrefs checkProfiles(t) t.Logf("Login with the existing profile") @@ -310,7 +310,7 @@ func TestProfileManagementWindows(t *testing.T) { } wantCurProfile := "" wantProfiles := map[string]ipn.PrefsView{ - "": emptyPrefs, + "": defaultPrefs, } checkProfiles := func(t *testing.T) { t.Helper() @@ -363,7 +363,7 @@ func TestProfileManagementWindows(t *testing.T) { t.Logf("Create new profile") pm.NewProfile() wantCurProfile = "" - wantProfiles[""] = emptyPrefs + wantProfiles[""] = defaultPrefs checkProfiles(t) t.Logf("Save as test profile") @@ -380,7 +380,7 @@ func TestProfileManagementWindows(t *testing.T) { t.Fatal(err) } wantCurProfile = "" - wantProfiles[""] = emptyPrefs + wantProfiles[""] = defaultPrefs checkProfiles(t) { diff --git a/net/dns/resolvconffile/resolvconffile.go b/net/dns/resolvconffile/resolvconffile.go index a1b334aa3601a..6b9cf04522ef8 100644 --- a/net/dns/resolvconffile/resolvconffile.go +++ b/net/dns/resolvconffile/resolvconffile.go @@ -83,17 +83,26 @@ func Parse(r io.Reader) (*Config, error) { } if s, ok := strs.CutPrefix(line, "search"); ok { - domain := strings.TrimSpace(s) - if len(domain) == len(s) { + domains := strings.TrimSpace(s) + if len(domains) == len(s) { // No leading space?! - return nil, fmt.Errorf("missing space after \"domain\" in %q", line) + return nil, fmt.Errorf("missing space after \"search\" in %q", line) } - fqdn, err := dnsname.ToFQDN(domain) - if err != nil { - return nil, fmt.Errorf("parsing search domains %q: %w", line, err) + for len(domains) > 0 { + domain := domains + i := strings.IndexAny(domain, " \t") + if i != -1 { + domain = domain[:i] + domains = strings.TrimSpace(domains[i+1:]) + } else { + domains = "" + } + fqdn, err := dnsname.ToFQDN(domain) + if err != nil { + return nil, fmt.Errorf("parsing search domain %q in %q: %w", domain, line, err) + } + config.SearchDomains = append(config.SearchDomains, fqdn) } - config.SearchDomains = append(config.SearchDomains, fqdn) - continue } } return config, nil diff --git a/net/dns/resolvconffile/resolvconffile_test.go b/net/dns/resolvconffile/resolvconffile_test.go index ed9583a0930b6..e5b5cc671084c 100644 --- a/net/dns/resolvconffile/resolvconffile_test.go +++ b/net/dns/resolvconffile/resolvconffile_test.go @@ -57,6 +57,31 @@ func TestParse(t *testing.T) { }, {in: `searchtailsacle.com`, wantErr: true}, {in: `search`, wantErr: true}, + + // Issue 6875: there can be multiple search domains, and even if they're + // over 253 bytes long total. + { + in: "search search-01.example search-02.example search-03.example search-04.example search-05.example search-06.example search-07.example search-08.example search-09.example search-10.example search-11.example search-12.example search-13.example search-14.example search-15.example\n", + want: &Config{ + SearchDomains: []dnsname.FQDN{ + "search-01.example.", + "search-02.example.", + "search-03.example.", + "search-04.example.", + "search-05.example.", + "search-06.example.", + "search-07.example.", + "search-08.example.", + "search-09.example.", + "search-10.example.", + "search-11.example.", + "search-12.example.", + "search-13.example.", + "search-14.example.", + "search-15.example.", + }, + }, + }, } for _, tt := range tests {