forked from pool/xorg-x11-server
bc8b5dc1a8
- U_os-support-new-implicit-local-user-access-mode.patch, U_xwayland-default-to-local-user-if-no-xauth-file-given.patch, U_xwayland-enable-access-control-on-open-socket.patch * Prevent unauthorized local access. (bnc#934102, CVE-2015-3164) OBS-URL: https://build.opensuse.org/request/show/311799 OBS-URL: https://build.opensuse.org/package/show/X11:XOrg/xorg-x11-server?expand=0&rev=575
246 lines
5.9 KiB
Diff
246 lines
5.9 KiB
Diff
Subject: os: support new implicit local user access mode
|
|
Author: Ray Strode <rstrode@redhat.com>
|
|
Path-mainline: Upstream
|
|
Git-commit: 4b4b9086d02b80549981d205fb1f495edc373538
|
|
References: bnc#934102 CVE-2015-3164
|
|
Signed-off-by: Michal Srb <msrb@suse.com>
|
|
|
|
If the X server is started without a '-auth' argument, then
|
|
it gets started wide open to all local users on the system.
|
|
|
|
This isn't a great default access model, but changing it in
|
|
Xorg at this point would break backward compatibility.
|
|
|
|
Xwayland, on the other hand is new, and much more targeted
|
|
in scope. It could, in theory, be changed to allow the much
|
|
more secure default of a "user who started X server can connect
|
|
clients to that server."
|
|
|
|
This commit paves the way for that change, by adding a mechanism
|
|
for DDXs to opt-in to that behavior. They merely need to call
|
|
|
|
LocalAccessScopeUser()
|
|
|
|
in their init functions.
|
|
|
|
A subsequent commit will add that call for Xwayland.
|
|
|
|
Signed-off-by: Ray Strode <rstrode@redhat.com>
|
|
Reviewed-by: Daniel Stone <daniels@collabora.com>
|
|
Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com>
|
|
Signed-off-by: Keith Packard <keithp@keithp.com>
|
|
|
|
diff --git a/include/os.h b/include/os.h
|
|
index 6638c84..b2b96c8 100644
|
|
--- a/include/os.h
|
|
+++ b/include/os.h
|
|
@@ -431,11 +431,28 @@ extern _X_EXPORT void
|
|
ResetHosts(const char *display);
|
|
|
|
extern _X_EXPORT void
|
|
+EnableLocalAccess(void);
|
|
+
|
|
+extern _X_EXPORT void
|
|
+DisableLocalAccess(void);
|
|
+
|
|
+extern _X_EXPORT void
|
|
EnableLocalHost(void);
|
|
|
|
extern _X_EXPORT void
|
|
DisableLocalHost(void);
|
|
|
|
+#ifndef NO_LOCAL_CLIENT_CRED
|
|
+extern _X_EXPORT void
|
|
+EnableLocalUser(void);
|
|
+
|
|
+extern _X_EXPORT void
|
|
+DisableLocalUser(void);
|
|
+
|
|
+extern _X_EXPORT void
|
|
+LocalAccessScopeUser(void);
|
|
+#endif
|
|
+
|
|
extern _X_EXPORT void
|
|
AccessUsingXdmcp(void);
|
|
|
|
diff --git a/os/access.c b/os/access.c
|
|
index 8fa028e..75e7a69 100644
|
|
--- a/os/access.c
|
|
+++ b/os/access.c
|
|
@@ -102,6 +102,10 @@ SOFTWARE.
|
|
#include <sys/ioctl.h>
|
|
#include <ctype.h>
|
|
|
|
+#ifndef NO_LOCAL_CLIENT_CRED
|
|
+#include <pwd.h>
|
|
+#endif
|
|
+
|
|
#if defined(TCPCONN) || defined(STREAMSCONN)
|
|
#include <netinet/in.h>
|
|
#endif /* TCPCONN || STREAMSCONN */
|
|
@@ -225,6 +229,13 @@ static int LocalHostEnabled = FALSE;
|
|
static int LocalHostRequested = FALSE;
|
|
static int UsingXdmcp = FALSE;
|
|
|
|
+static enum {
|
|
+ LOCAL_ACCESS_SCOPE_HOST = 0,
|
|
+#ifndef NO_LOCAL_CLIENT_CRED
|
|
+ LOCAL_ACCESS_SCOPE_USER,
|
|
+#endif
|
|
+} LocalAccessScope;
|
|
+
|
|
/* FamilyServerInterpreted implementation */
|
|
static Bool siAddrMatch(int family, void *addr, int len, HOST * host,
|
|
ClientPtr client);
|
|
@@ -237,6 +248,21 @@ static void siTypesInitialize(void);
|
|
*/
|
|
|
|
void
|
|
+EnableLocalAccess(void)
|
|
+{
|
|
+ switch (LocalAccessScope) {
|
|
+ case LOCAL_ACCESS_SCOPE_HOST:
|
|
+ EnableLocalHost();
|
|
+ break;
|
|
+#ifndef NO_LOCAL_CLIENT_CRED
|
|
+ case LOCAL_ACCESS_SCOPE_USER:
|
|
+ EnableLocalUser();
|
|
+ break;
|
|
+#endif
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
EnableLocalHost(void)
|
|
{
|
|
if (!UsingXdmcp) {
|
|
@@ -249,6 +275,21 @@ EnableLocalHost(void)
|
|
* called when authorization is enabled to keep us secure
|
|
*/
|
|
void
|
|
+DisableLocalAccess(void)
|
|
+{
|
|
+ switch (LocalAccessScope) {
|
|
+ case LOCAL_ACCESS_SCOPE_HOST:
|
|
+ DisableLocalHost();
|
|
+ break;
|
|
+#ifndef NO_LOCAL_CLIENT_CRED
|
|
+ case LOCAL_ACCESS_SCOPE_USER:
|
|
+ DisableLocalUser();
|
|
+ break;
|
|
+#endif
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
DisableLocalHost(void)
|
|
{
|
|
HOST *self;
|
|
@@ -262,6 +303,74 @@ DisableLocalHost(void)
|
|
}
|
|
}
|
|
|
|
+#ifndef NO_LOCAL_CLIENT_CRED
|
|
+static int GetLocalUserAddr(char **addr)
|
|
+{
|
|
+ static const char *type = "localuser";
|
|
+ static const char delimiter = '\0';
|
|
+ static const char *value;
|
|
+ struct passwd *pw;
|
|
+ int length = -1;
|
|
+
|
|
+ pw = getpwuid(getuid());
|
|
+
|
|
+ if (pw == NULL || pw->pw_name == NULL)
|
|
+ goto out;
|
|
+
|
|
+ value = pw->pw_name;
|
|
+
|
|
+ length = asprintf(addr, "%s%c%s", type, delimiter, value);
|
|
+
|
|
+ if (length == -1) {
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* Trailing NUL */
|
|
+ length++;
|
|
+
|
|
+out:
|
|
+ return length;
|
|
+}
|
|
+
|
|
+void
|
|
+EnableLocalUser(void)
|
|
+{
|
|
+ char *addr = NULL;
|
|
+ int length = -1;
|
|
+
|
|
+ length = GetLocalUserAddr(&addr);
|
|
+
|
|
+ if (length == -1)
|
|
+ return;
|
|
+
|
|
+ NewHost(FamilyServerInterpreted, addr, length, TRUE);
|
|
+
|
|
+ free(addr);
|
|
+}
|
|
+
|
|
+void
|
|
+DisableLocalUser(void)
|
|
+{
|
|
+ char *addr = NULL;
|
|
+ int length = -1;
|
|
+
|
|
+ length = GetLocalUserAddr(&addr);
|
|
+
|
|
+ if (length == -1)
|
|
+ return;
|
|
+
|
|
+ RemoveHost(NULL, FamilyServerInterpreted, length, addr);
|
|
+
|
|
+ free(addr);
|
|
+}
|
|
+
|
|
+void
|
|
+LocalAccessScopeUser(void)
|
|
+{
|
|
+ LocalAccessScope = LOCAL_ACCESS_SCOPE_USER;
|
|
+}
|
|
+#endif
|
|
+
|
|
/*
|
|
* called at init time when XDMCP will be used; xdmcp always
|
|
* adds local hosts manually when needed
|
|
diff --git a/os/auth.c b/os/auth.c
|
|
index 5fcb538..7da6fc6 100644
|
|
--- a/os/auth.c
|
|
+++ b/os/auth.c
|
|
@@ -181,11 +181,11 @@ CheckAuthorization(unsigned int name_length,
|
|
|
|
/*
|
|
* If the authorization file has at least one entry for this server,
|
|
- * disable local host access. (loadauth > 0)
|
|
+ * disable local access. (loadauth > 0)
|
|
*
|
|
* If there are zero entries (either initially or when the
|
|
* authorization file is later reloaded), or if a valid
|
|
- * authorization file was never loaded, enable local host access.
|
|
+ * authorization file was never loaded, enable local access.
|
|
* (loadauth == 0 || !loaded)
|
|
*
|
|
* If the authorization file was loaded initially (with valid
|
|
@@ -194,11 +194,11 @@ CheckAuthorization(unsigned int name_length,
|
|
*/
|
|
|
|
if (loadauth > 0) {
|
|
- DisableLocalHost(); /* got at least one */
|
|
+ DisableLocalAccess(); /* got at least one */
|
|
loaded = TRUE;
|
|
}
|
|
else if (loadauth == 0 || !loaded)
|
|
- EnableLocalHost();
|
|
+ EnableLocalAccess();
|
|
}
|
|
if (name_length) {
|
|
for (i = 0; i < NUM_AUTHORIZATION; i++) {
|