From f11cb811cc9229f86c7f0ec18f1a2cf08f0dfa87 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 5 Mar 2021 13:29:03 -0800 Subject: [PATCH] safesocket: support finding tailscale port/auth token from sandboxed CLI Previously the CLI could only find the HTTP auth token when running the CLI outside the sandbox, not like /Applications/Tailscale.app/Contents/MacOS/Tailscale when that was from the App Store. Signed-off-by: Brad Fitzpatrick --- safesocket/safesocket_darwin.go | 40 ++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/safesocket/safesocket_darwin.go b/safesocket/safesocket_darwin.go index c0d43c41a..f53113f38 100644 --- a/safesocket/safesocket_darwin.go +++ b/safesocket/safesocket_darwin.go @@ -8,8 +8,10 @@ "bufio" "bytes" "fmt" + "io/ioutil" "os" "os/exec" + "path/filepath" "strconv" "strings" ) @@ -19,11 +21,43 @@ func init() { } func localTCPPortAndTokenDarwin() (port int, token string, err error) { + // There are two ways this binary can be run: as the Mac App Store sandboxed binary, + // or a normal binary that somebody built or download and are being run from outside + // the sandbox. Detect which way we're running and then figure out how to connect + // to the local daemon. + + if dir := os.Getenv("TS_MACOS_CLI_SHARED_DIR"); dir != "" { + // The current binary (this process) is sandboxed. The user is + // running the CLI via /Applications/Tailscale.app/Contents/MacOS/Tailscale + // which sets the TS_MACOS_CLI_SHARED_DIR environment variable. + fis, err := ioutil.ReadDir(dir) + if err != nil { + return 0, "", err + } + for _, fi := range fis { + name := filepath.Base(fi.Name()) + // Look for name like "sameuserproof-61577-2ae2ec9e0aa2005784f1" + // to extract out the port number and token. + if strings.HasPrefix(name, "sameuserproof-") { + f := strings.SplitN(name, "-", 3) + if len(f) == 3 { + if port, err := strconv.Atoi(f[1]); err == nil { + return port, f[2], nil + } + } + } + } + return 0, "", fmt.Errorf("failed to find sandboxed sameuserproof-* file in TS_MACOS_CLI_SHARED_DIR %q", dir) + } + + // The current process is running outside the sandbox, so use + // lsof to find the IPNExtension: + out, err := exec.Command("lsof", - "-n", // numeric sockets; don't do DNS lookups, etc - "-a", // logical AND remaining options + "-n", // numeric sockets; don't do DNS lookups, etc + "-a", // logical AND remaining options fmt.Sprintf("-u%d", os.Getuid()), // process of same user only - "-c", "IPNExtension", // starting with IPNExtension + "-c", "IPNExtension", // starting with IPNExtension "-F", // machine-readable output ).Output() if err != nil {