auth: Test UID not send with external auth
Due to mismatch between UID in a user-namespace
and out-of-band credential acquired by server
on another user-namespace refrain from sending UID
with external authentication by default
to keep compatibility still fallback to sending UID
if it fails
https://github.com/godbus/dbus/issues/345
diff --git a/conn_linux_test.go b/conn_linux_test.go
new file mode 100644
index 0000000..2c13545
--- /dev/null
+++ b/conn_linux_test.go
@@ -0,0 +1,93 @@
+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 := `<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+ <busconfig>
+ <listen>unix:path=/tmp/test.socket</listen>
+ <auth>EXTERNAL</auth>
+ <apparmor mode="disabled"/>
+
+ <policy context='default'>
+ <allow send_destination='*' eavesdrop='true'/>
+ <allow eavesdrop='true'/>
+ <allow user='*'/>
+ </policy>
+ </busconfig>
+ `
+ 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
+}