@ -8,8 +8,10 @@ import (
"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 {