From 09891b98682e5e85b71a821cee1a79dcb9858f83 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 21 Apr 2021 12:57:48 -0700 Subject: [PATCH] ipn/ipnlocal: on fresh lazy-connecting install, start in state NeedsLogin Fixes #1759 Signed-off-by: Brad Fitzpatrick --- control/controlclient/auto.go | 3 +++ ipn/ipnlocal/local.go | 1 + ipn/ipnlocal/local_test.go | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/control/controlclient/auto.go b/control/controlclient/auto.go index cc92e443d..e0f17e172 100644 --- a/control/controlclient/auto.go +++ b/control/controlclient/auto.go @@ -597,6 +597,9 @@ func (c *Client) mapRoutine() { } func (c *Client) AuthCantContinue() bool { + if c == nil { + return true + } c.mu.Lock() defer c.mu.Unlock() diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 154d21d2c..8c9c490ad 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -603,6 +603,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error { return errors.New("no state key or prefs provided") } + defer b.stateMachine() if opts.Prefs != nil { b.logf("Start: %v", opts.Prefs.Pretty()) } else { diff --git a/ipn/ipnlocal/local_test.go b/ipn/ipnlocal/local_test.go index f70ebadf2..fa2f7cef2 100644 --- a/ipn/ipnlocal/local_test.go +++ b/ipn/ipnlocal/local_test.go @@ -5,14 +5,20 @@ package ipnlocal import ( + "bytes" + "fmt" + "net/http" "reflect" + "sync" "testing" "inet.af/netaddr" + "tailscale.com/ipn" "tailscale.com/net/interfaces" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/types/netmap" + "tailscale.com/wgengine" "tailscale.com/wgengine/wgcfg" ) @@ -419,3 +425,48 @@ func TestPeerAPIBase(t *testing.T) { }) } } + +type panicOnUseTransport struct{} + +func (panicOnUseTransport) RoundTrip(*http.Request) (*http.Response, error) { + panic("unexpected HTTP request") +} + +var nl = []byte("\n") + +func TestStartsInNeedsLoginState(t *testing.T) { + var ( + mu sync.Mutex + logBuf bytes.Buffer + ) + logf := func(format string, a ...interface{}) { + mu.Lock() + defer mu.Unlock() + fmt.Fprintf(&logBuf, format, a...) + if !bytes.HasSuffix(logBuf.Bytes(), nl) { + logBuf.Write(nl) + } + } + store := new(ipn.MemoryStore) + eng, err := wgengine.NewFakeUserspaceEngine(logf, 0) + if err != nil { + t.Fatalf("NewFakeUserspaceEngine: %v", err) + } + lb, err := NewLocalBackend(logf, "logid", store, eng) + if err != nil { + t.Fatalf("NewLocalBackend: %v", err) + } + + lb.SetHTTPTestClient(&http.Client{ + Transport: panicOnUseTransport{}, // validate we don't send HTTP requests + }) + + if err := lb.Start(ipn.Options{ + StateKey: ipn.GlobalDaemonStateKey, + }); err != nil { + t.Fatalf("Start: %v", err) + } + if st := lb.State(); st != ipn.NeedsLogin { + t.Errorf("State = %v; want NeedsLogin", st) + } +}