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
+}