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.
"bufio"
"bytes"
"fmt"
+ "io/ioutil"
"os"
"os/exec"
+ "path/filepath"
"strconv"
"strings"
)
@@ -19,6 +21,38 @@ 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
