[gdm-list] [RFC PATCH] Support for PAM_XDISPLAY and PAM_XAUTH_DATA



This patch implements support for two new pam items that are in the Linux-PAM repo. The first item is PAM_XDISPLAY which contains the name of the X display, and the second item is PAM_XAUTH_DATA which contains an Xauth structure. These are intended to allow PAM session modules to connect to the X server to set up the user's session, if the X server supports security extensions (such as SELinux, which is my reason for working on this).

The display name was easy, but to get the Xauth structure the name of the display authority file must be sent through the SessionDirect object to the SessionWorker object. The SessionWorker object looks up the display in the authority file before calling pam_open_session(). This last step is a little dodgy and I am considering going back to the Linux-PAM list and asking to change PAM_XAUTH_DATA (if it's not too late) to just take the name of an authority file instead of a raw Xauth structure. Alternately, the lookup could be added to the DisplayAccessFile class which already has authfile parsing code.

Comments and review are appreciated. Makefile.am | 1 gdm-product-slave.c | 3 +
gdm-session-direct.c |   46 +++++++++++++++++++++++++++-
gdm-session-direct.h | 1 gdm-session-worker.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++--
gdm-simple-slave.c   |    3 +
test-session.c | 1 7 files changed, 131 insertions(+), 5 deletions(-)


Index: daemon/gdm-product-slave.c
===================================================================
--- daemon/gdm-product-slave.c	(revision 5615)
+++ daemon/gdm-product-slave.c	(working copy)
@@ -671,6 +671,7 @@
        char          *display_name;
        char          *display_hostname;
        char          *display_device;
+        char          *display_x11_authority_file;

        g_debug ("GdmProductSlave: Creating new session");

@@ -678,6 +679,7 @@
                      "display-name", &display_name,
                      "display-hostname", &display_hostname,
                      "display-is-local", &display_is_local,
+                      "display-x11-authority-file", &display_x11_authority_file,
                      NULL);

        /* FIXME: we don't yet have a display device! */
@@ -686,6 +688,7 @@
        slave->priv->session = gdm_session_direct_new (display_name,
                                                       display_hostname,
                                                       display_device,
+                                                       display_x11_authority_file,
                                                       display_is_local);
        g_free (display_name);
        g_free (display_hostname);
Index: daemon/test-session.c
===================================================================
--- daemon/test-session.c	(revision 5615)
+++ daemon/test-session.c	(working copy)
@@ -248,6 +248,7 @@
                session = gdm_session_direct_new (":0",
                                                  g_get_host_name (),
                                                  ttyname (STDIN_FILENO),
+                                                  getenv("XAUTHORITY"),
                                                  TRUE);
                g_debug ("GdmSessionDirect object created successfully");

Index: daemon/gdm-session-worker.c
===================================================================
--- daemon/gdm-session-worker.c	(revision 5615)
+++ daemon/gdm-session-worker.c	(working copy)
@@ -34,6 +34,9 @@

#include <security/pam_appl.h>

+#include <X11/Xauth.h>
+#include <xcb/xcb.h>
+
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
@@ -94,6 +97,7 @@
        /* from Setup */
        char             *service;
        char             *x11_display_name;
+        char             *x11_authority_file;
        char             *display_device;
        char             *hostname;
        char             *username;
@@ -801,18 +805,54 @@
        return g_strdup (x11_display_name);
}

+static struct pam_xauth_data *
+_get_xauth_for_pam (const char *x11_display_name,
+                    const char *x11_authority_file)
+{
+        struct pam_xauth_data *retval;
+        char *hostname, displayname[16];
+        int display;
+        Xauth *auth;
+
+        if (x11_authority_file == NULL || x11_authority_file[0] == '\0')
+                return NULL;
+        if (! xcb_parse_display (x11_display_name, &hostname, &display, NULL))
+                return NULL;
+ + snprintf (displayname, sizeof (displayname), "%d", display);
+        g_setenv ("XAUTHORITY", x11_authority_file, TRUE);
+
+        auth = XauGetAuthByAddr(FamilyWild,
+                                strlen (hostname), hostname,
+                                strlen (displayname), displayname,
+                                0, NULL);
+        retval = g_malloc0 (sizeof (struct pam_xauth_data));
+
+        if (auth && retval) {
+                retval->namelen = auth->name_length;
+                retval->name = g_strndup (auth->name, auth->name_length);
+                retval->datalen = auth->data_length;
+                retval->data = g_memdup (auth->data, auth->data_length);
+        }
+        XauDisposeAuth(auth);
+        g_debug("GdmSessionWorker: finished _get_xauth_for_pam");
+        return retval;
+}
+
static gboolean
gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
                                   const char       *service,
                                   const char       *username,
                                   const char       *hostname,
                                   const char       *x11_display_name,
+                                   const char       *x11_authority_file,
                                   const char       *display_device,
                                   GError          **error)
{
-        struct pam_conv  pam_conversation;
-        int              error_code;
-        char            *pam_tty;
+        struct pam_conv        pam_conversation;
+        struct pam_xauth_data *pam_xauth;
+        int                    error_code;
+        char                  *pam_tty;

        g_assert (worker->priv->pam_handle == NULL);

@@ -885,6 +925,34 @@
                goto out;
        }

+        /* set XDISPLAY */
+        error_code = pam_set_item (worker->priv->pam_handle, PAM_XDISPLAY, x11_display_name);
+
+        if (error_code != PAM_SUCCESS) {
+                g_set_error (error,
+                             GDM_SESSION_WORKER_ERROR,
+                             GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
+                             _("error informing authentication system of display string - %s"),
+                             pam_strerror (worker->priv->pam_handle, error_code));
+                goto out;
+        }
+
+        /* set XAUTHDATA */
+        pam_xauth = _get_xauth_for_pam (x11_display_name, x11_authority_file);
+        error_code = pam_set_item (worker->priv->pam_handle, PAM_XAUTHDATA, pam_xauth);
+        g_free (pam_xauth->name);
+        g_free (pam_xauth->data);
+        g_free (pam_xauth);
+
+        if (error_code != PAM_SUCCESS) {
+                g_set_error (error,
+                             GDM_SESSION_WORKER_ERROR,
+                             GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
+                             _("error informing authentication system of display xauth credentials - %s"),
+                             pam_strerror (worker->priv->pam_handle, error_code));
+                goto out;
+        }
+
        g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
        worker->priv->state = GDM_SESSION_WORKER_STATE_SETUP_COMPLETE;

@@ -1527,6 +1595,7 @@
                                                 worker->priv->username,
                                                 worker->priv->hostname,
                                                 worker->priv->x11_display_name,
+                                                 worker->priv->x11_authority_file,
                                                 worker->priv->display_device,
                                                 &error);
        if (! res) {
@@ -1784,6 +1853,7 @@
        DBusError   error;
        const char *service;
        const char *x11_display_name;
+        const char *x11_authority_file;
        const char *console;
        const char *hostname;
        dbus_bool_t res;
@@ -1797,10 +1867,12 @@
                                     DBUS_TYPE_STRING, &x11_display_name,
                                     DBUS_TYPE_STRING, &console,
                                     DBUS_TYPE_STRING, &hostname,
+                                     DBUS_TYPE_STRING, &x11_authority_file,
                                     DBUS_TYPE_INVALID);
        if (res) {
                worker->priv->service = g_strdup (service);
                worker->priv->x11_display_name = g_strdup (x11_display_name);
+                worker->priv->x11_authority_file = g_strdup (x11_authority_file);
                worker->priv->display_device = g_strdup (console);
                worker->priv->hostname = g_strdup (hostname);
                worker->priv->username = NULL;
@@ -1820,6 +1892,7 @@
        DBusError   error;
        const char *service;
        const char *x11_display_name;
+        const char *x11_authority_file;
        const char *console;
        const char *hostname;
        const char *username;
@@ -1834,11 +1907,13 @@
                                     DBUS_TYPE_STRING, &x11_display_name,
                                     DBUS_TYPE_STRING, &console,
                                     DBUS_TYPE_STRING, &hostname,
+                                     DBUS_TYPE_STRING, &x11_authority_file,
                                     DBUS_TYPE_STRING, &username,
                                     DBUS_TYPE_INVALID);
        if (res) {
                worker->priv->service = g_strdup (service);
                worker->priv->x11_display_name = g_strdup (x11_display_name);
+                worker->priv->x11_authority_file = g_strdup (x11_authority_file);
                worker->priv->display_device = g_strdup (console);
                worker->priv->hostname = g_strdup (hostname);
                worker->priv->username = g_strdup (username);
Index: daemon/gdm-session-direct.c
===================================================================
--- daemon/gdm-session-direct.c	(revision 5615)
+++ daemon/gdm-session-direct.c	(working copy)
@@ -82,6 +82,7 @@
        char                *display_name;
        char                *display_hostname;
        char                *display_device;
+        char                *display_x11_authority_file;
        gboolean             display_is_local;

        DBusServer          *server;
@@ -95,6 +96,7 @@
        PROP_DISPLAY_HOSTNAME,
        PROP_DISPLAY_IS_LOCAL,
        PROP_DISPLAY_DEVICE,
+        PROP_DISPLAY_X11_AUTHORITY_FILE,
        PROP_USER_X11_AUTHORITY_FILE,
};

@@ -898,12 +900,14 @@
                               "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
                               "      <arg name=\"display_device\" type=\"s\"/>\n"
                               "      <arg name=\"hostname\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
                               "    </signal>\n"
                               "    <signal name=\"SetupForUser\">\n"
                               "      <arg name=\"service_name\" type=\"s\"/>\n"
                               "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
                               "      <arg name=\"display_device\" type=\"s\"/>\n"
                               "      <arg name=\"hostname\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
                               "      <arg name=\"username\" type=\"s\"/>\n"
                               "    </signal>\n"
                               "    <signal name=\"Authenticate\">\n"
@@ -1281,6 +1285,7 @@
        const char     *display_name;
        const char     *display_device;
        const char     *display_hostname;
+        const char     *display_x11_authority_file;

        if (session->priv->display_name != NULL) {
                display_name = session->priv->display_name;
@@ -1297,6 +1302,11 @@
        } else {
                display_device = "";
        }
+        if (session->priv->display_x11_authority_file != NULL) {
+                display_x11_authority_file = session->priv->display_x11_authority_file;
+        } else {
+                display_x11_authority_file = "";
+        }

        g_debug ("GdmSessionDirect: Beginning setup");

@@ -1309,6 +1319,7 @@
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);

        if (! send_dbus_message (session->priv->worker_connection, message)) {
                g_debug ("GdmSessionDirect: Could not send %s signal", "Setup");
@@ -1325,6 +1336,7 @@
        const char     *display_name;
        const char     *display_device;
        const char     *display_hostname;
+        const char     *display_x11_authority_file;
        const char     *selected_user;

        if (session->priv->display_name != NULL) {
@@ -1342,6 +1354,11 @@
        } else {
                display_device = "";
        }
+        if (session->priv->display_x11_authority_file != NULL) {
+                display_x11_authority_file = session->priv->display_x11_authority_file;
+        } else {
+                display_x11_authority_file = "";
+        }
        if (session->priv->selected_user != NULL) {
                selected_user = session->priv->selected_user;
        } else {
@@ -1359,6 +1376,7 @@
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &selected_user);

        if (! send_dbus_message (session->priv->worker_connection, message)) {
@@ -1882,6 +1900,14 @@
}

static void
+_gdm_session_direct_set_display_x11_authority_file (GdmSessionDirect *session,
+                                                    const char       *name)
+{
+        g_free (session->priv->display_x11_authority_file);
+        session->priv->display_x11_authority_file = g_strdup (name);
+}
+
+static void
_gdm_session_direct_set_display_is_local (GdmSessionDirect *session,
                                          gboolean          is)
{
@@ -1911,6 +1937,9 @@
        case PROP_USER_X11_AUTHORITY_FILE:
                _gdm_session_direct_set_user_x11_authority_file (self, g_value_get_string (value));
                break;
+        case PROP_DISPLAY_X11_AUTHORITY_FILE:
+                _gdm_session_direct_set_display_x11_authority_file (self, g_value_get_string (value));
+                break;
        case PROP_DISPLAY_IS_LOCAL:
                _gdm_session_direct_set_display_is_local (self, g_value_get_boolean (value));
                break;
@@ -1943,6 +1972,9 @@
        case PROP_USER_X11_AUTHORITY_FILE:
                g_value_set_string (value, self->priv->user_x11_authority_file);
                break;
+        case PROP_DISPLAY_X11_AUTHORITY_FILE:
+                g_value_set_string (value, self->priv->display_x11_authority_file);
+                break;
        case PROP_DISPLAY_IS_LOCAL:
                g_value_set_boolean (value, self->priv->display_is_local);
                break;
@@ -1975,6 +2007,9 @@
        g_free (session->priv->display_device);
        session->priv->display_device = NULL;

+        g_free (session->priv->display_x11_authority_file);
+        session->priv->display_x11_authority_file = NULL;
+
        g_free (session->priv->server_address);
        session->priv->server_address = NULL;

@@ -2062,6 +2097,13 @@
                                                               "display is local",
                                                               TRUE,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (object_class,
+                                         PROP_DISPLAY_X11_AUTHORITY_FILE,
+                                         g_param_spec_string ("display-x11-authority-file",
+                                                              "display x11 authority file",
+                                                              "display x11 authority file",
+                                                              NULL,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
        /* not construct only */
        g_object_class_install_property (object_class,
                                         PROP_USER_X11_AUTHORITY_FILE,
@@ -2077,14 +2119,13 @@
                                                              "display device",
                                                              NULL,
                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
-
}

GdmSessionDirect *
gdm_session_direct_new (const char *display_name,
                        const char *display_hostname,
                        const char *display_device,
+                        const char *display_x11_authority_file,
                        gboolean    display_is_local)
{
        GdmSessionDirect *session;
@@ -2093,6 +2134,7 @@
                                "display-name", display_name,
                                "display-hostname", display_hostname,
                                "display-device", display_device,
+                                "display-x11-authority-file", display_x11_authority_file,
                                "display-is-local", display_is_local,
                                NULL);

Index: daemon/gdm-session-direct.h
===================================================================
--- daemon/gdm-session-direct.h	(revision 5615)
+++ daemon/gdm-session-direct.h	(working copy)
@@ -51,6 +51,7 @@
GdmSessionDirect * gdm_session_direct_new                      (const char *display_name,
                                                                const char *display_hostname,
                                                                const char *display_device,
+                                                                const char *display_x11_authority_file,
                                                                gboolean    display_is_local) G_GNUC_MALLOC;

char             * gdm_session_direct_get_username             (GdmSessionDirect     *session_direct);
Index: daemon/gdm-simple-slave.c
===================================================================
--- daemon/gdm-simple-slave.c	(revision 5615)
+++ daemon/gdm-simple-slave.c	(working copy)
@@ -324,6 +324,7 @@
        char          *display_name;
        char          *display_hostname;
        char          *display_device;
+        char          *display_x11_authority_file;

        g_debug ("GdmSimpleSlave: Creating new session");

@@ -331,6 +332,7 @@
                      "display-name", &display_name,
                      "display-hostname", &display_hostname,
                      "display-is-local", &display_is_local,
+                      "display-x11-authority-file", &display_x11_authority_file,
                      NULL);

        display_device = NULL;
@@ -341,6 +343,7 @@
        slave->priv->session = gdm_session_direct_new (display_name,
                                                       display_hostname,
                                                       display_device,
+                                                       display_x11_authority_file,
                                                       display_is_local);
        g_free (display_name);
        g_free (display_device);
Index: daemon/Makefile.am
===================================================================
--- daemon/Makefile.am	(revision 5615)
+++ daemon/Makefile.am	(working copy)
@@ -209,6 +209,7 @@
	$(NULL)

gdm_session_worker_LDFLAGS =			\
+	$(XLIB_LIBS)				\
	$(PAM_LIBS)				\
	$(NULL)




--
Eamon Walsh <ewalsh tycho nsa gov>
National Security Agency



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]