diff --git a/conn_unix_test.go b/conn_unix_test.go new file mode 100644 index 0000000..b2a678f --- /dev/null +++ b/conn_unix_test.go @@ -0,0 +1,94 @@ +package dbus + +import ( + "bufio" + "io/ioutil" + "os" + "os/exec" + "syscall" + "testing" +) + +// tests whether AUTH EXTERNAL is successful connecting to +// a server in a different user-namespace +// if AUTH EXTERNAL sends the UID of the client +// it will clash with out-of-band credentials derived by server +// from underlying UDS and authentication will be rejected +func TestConnectToDifferentUserNamespace(t *testing.T) { + addr, process := startDaemonInDifferentUserNamespace(t) + defer func() { _ = process.Kill() }() + conn, err := Connect(addr) + if err != nil { + t.Fatal(err) + } + if err = conn.Close(); err != nil { + t.Fatal(err) + } + if conn.Connected() { + t.Fatal("Should be closed") + } +} + + +// starts a dbus-daemon instance in a new user-namespace +// and returns its address string and underlying process. +func startDaemonInDifferentUserNamespace(t *testing.T) (string, *os.Process) { + config := ` + + unix:path=/tmp/test.socket + EXTERNAL + + + + + + + + + ` + cfg, err := ioutil.TempFile("", "") + if err != nil { + t.Fatal(err) + } + defer os.Remove(cfg.Name()) + if _, err = cfg.Write([]byte(config)); err != nil { + t.Fatal(err) + } + + cmd := exec.Command("dbus-daemon", "--nofork", "--print-address", "--config-file", cfg.Name()) + + cmd.SysProcAttr = &syscall.SysProcAttr{ + Cloneflags: syscall.CLONE_NEWPID | syscall.CLONE_NEWUSER, + UidMappings: []syscall.SysProcIDMap{ + { + ContainerID: 0, + HostID: os.Getuid(), + Size: 1, + }, + }, + GidMappings: []syscall.SysProcIDMap{ + { + ContainerID: 0, + HostID: os.Getgid(), + Size: 1, + }, + }, + } + + cmd.Stderr = os.Stderr + out, err := cmd.StdoutPipe() + if err != nil { + t.Fatal(err) + } + if err := cmd.Start(); err != nil { + t.Fatal(err) + } + r := bufio.NewReader(out) + l, _, err := r.ReadLine() + if err != nil { + _ = cmd.Process.Kill() + t.Fatal(err) + } + return string(l), cmd.Process +}