summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2015-05-05 16:43:43 -0400
committerAdam Jackson <ajax@redhat.com>2015-06-03 09:05:39 -0400
commit01b4f5bc89820cf8cbe01777871834411074d683 (patch)
tree5c799da95f96dc18b3064b24b61b4187ef682913
parentbebaaa2216026bd6b649a8123e67a7f5172b120f (diff)
os: support new implicit local user access mode [CVE-2015-3164 2/3]
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> (cherry picked from commit 4b4b9086d02b80549981d205fb1f495edc373538)
-rw-r--r--include/os.h17
-rw-r--r--os/access.c109
-rw-r--r--os/auth.c8
3 files changed, 130 insertions, 4 deletions
diff --git a/include/os.h b/include/os.h
index 3e68c4933..3c3954f8d 100644
--- a/include/os.h
+++ b/include/os.h
@@ -413,11 +413,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 8fa028eb4..75e7a6983 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 5fcb538c4..7da6fc6ed 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++) {