summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2012-08-20 17:34:12 +1200
committerRobert Ancell <robert.ancell@canonical.com>2012-08-20 17:34:12 +1200
commit40e9874b5ce72d9de46f5a18251bfe283a76df13 (patch)
treeed7d17beae60d20e9a838418706da788fab83c8f
parent7e521a6cf33c57e762ee5a04c4a0e6756838f94c (diff)
downloadlightdm-40e9874b5ce72d9de46f5a18251bfe283a76df13.tar.gz
Start work on supporting remote session types
-rw-r--r--liblightdm-gobject/greeter.c44
-rw-r--r--liblightdm-gobject/lightdm/greeter.h4
-rw-r--r--liblightdm-gobject/lightdm/session.h2
-rw-r--r--liblightdm-gobject/session.c15
-rw-r--r--liblightdm-qt/QLightDM/greeter.h1
-rw-r--r--liblightdm-qt/greeter.cpp7
-rw-r--r--src/greeter.c80
7 files changed, 148 insertions, 5 deletions
diff --git a/liblightdm-gobject/greeter.c b/liblightdm-gobject/greeter.c
index 2d31b84c..b6d1ba77 100644
--- a/liblightdm-gobject/greeter.c
+++ b/liblightdm-gobject/greeter.c
@@ -80,7 +80,8 @@ typedef enum
GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
GREETER_MESSAGE_START_SESSION,
GREETER_MESSAGE_CANCEL_AUTHENTICATION,
- GREETER_MESSAGE_SET_LANGUAGE
+ GREETER_MESSAGE_SET_LANGUAGE,
+ GREETER_MESSAGE_AUTHENTICATE_REMOTE
} GreeterMessage;
/* Messages from the server to the greeter */
@@ -770,7 +771,7 @@ lightdm_greeter_cancel_autologin (LightDMGreeter *greeter)
* Starts the authentication procedure for a user.
**/
void
-lightdm_greeter_authenticate (LightDMGreeter *greeter, const char *username)
+lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username)
{
LightDMGreeterPrivate *priv;
guint8 message[MAX_MESSAGE_LENGTH];
@@ -832,6 +833,45 @@ lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter)
}
/**
+ * lightdm_greeter_authenticate_remote:
+ * @greeter: A #LightDMGreeter
+ * @session: The name of a remote session
+ * @username: (allow-none): A username of #NULL to prompt for a username.
+ *
+ * Start authentication for a remote session type.
+ **/
+void
+lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username)
+{
+ LightDMGreeterPrivate *priv;
+ guint8 message[MAX_MESSAGE_LENGTH];
+ gsize offset = 0;
+
+ g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
+
+ priv = GET_PRIVATE (greeter);
+
+ g_return_if_fail (priv->connected);
+
+ priv->cancelling_authentication = FALSE;
+ priv->authenticate_sequence_number++;
+ priv->in_authentication = TRUE;
+ priv->is_authenticated = FALSE;
+ g_free (priv->authentication_user);
+ priv->authentication_user = NULL;
+
+ if (username)
+ g_debug ("Starting authentication for remote session %s as user %s...", session, username);
+ else
+ g_debug ("Starting authentication for remote session %s...", session);
+ write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_AUTHENTICATE_REMOTE, int_length () + string_length (session) + string_length (username), &offset);
+ write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
+ write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
+ write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
+ write_message (greeter, message, offset);
+}
+
+/**
* lightdm_greeter_respond:
* @greeter: A #LightDMGreeter
* @response: Response to a prompt
diff --git a/liblightdm-gobject/lightdm/greeter.h b/liblightdm-gobject/lightdm/greeter.h
index dc051b3e..cd26f772 100644
--- a/liblightdm-gobject/lightdm/greeter.h
+++ b/liblightdm-gobject/lightdm/greeter.h
@@ -98,10 +98,12 @@ gint lightdm_greeter_get_autologin_timeout_hint (LightDMGreeter *greeter);
void lightdm_greeter_cancel_autologin (LightDMGreeter *greeter);
-void lightdm_greeter_authenticate (LightDMGreeter *greeter, const char *username);
+void lightdm_greeter_authenticate (LightDMGreeter *greeter, const gchar *username);
void lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter);
+void lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username);
+
void lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response);
void lightdm_greeter_cancel_authentication (LightDMGreeter *greeter);
diff --git a/liblightdm-gobject/lightdm/session.h b/liblightdm-gobject/lightdm/session.h
index 3b07bdcd..910205e0 100644
--- a/liblightdm-gobject/lightdm/session.h
+++ b/liblightdm-gobject/lightdm/session.h
@@ -45,6 +45,8 @@ GType lightdm_session_get_type (void);
GList *lightdm_get_sessions (void);
+GList *lightdm_get_remote_sessions (void);
+
const gchar *lightdm_session_get_key (LightDMSession *session);
const gchar *lightdm_session_get_name (LightDMSession *session);
diff --git a/liblightdm-gobject/session.c b/liblightdm-gobject/session.c
index 603ddb7f..577e3274 100644
--- a/liblightdm-gobject/session.c
+++ b/liblightdm-gobject/session.c
@@ -34,6 +34,7 @@ G_DEFINE_TYPE (LightDMSession, lightdm_session, G_TYPE_OBJECT);
static gboolean have_sessions = FALSE;
static GList *sessions = NULL;
+static GList *remote_sessions = NULL;
static gint
compare_session (gconstpointer a, gconstpointer b)
@@ -209,6 +210,20 @@ lightdm_get_sessions (void)
}
/**
+ * lightdm_get_remote_sessions:
+ *
+ * Get the available remote sessions.
+ *
+ * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession
+ **/
+GList *
+lightdm_get_remote_sessions (void)
+{
+ update_sessions ();
+ return remote_sessions;
+}
+
+/**
* lightdm_session_get_key:
* @session: A #LightDMSession
*
diff --git a/liblightdm-qt/QLightDM/greeter.h b/liblightdm-qt/QLightDM/greeter.h
index ab296b5e..4c6799e0 100644
--- a/liblightdm-qt/QLightDM/greeter.h
+++ b/liblightdm-qt/QLightDM/greeter.h
@@ -72,6 +72,7 @@ public slots:
bool connectSync();
void authenticate(const QString &username=QString());
void authenticateAsGuest();
+ void authenticateRemote(const QString &session=QString(), const QString &username=QString());
void respond(const QString &response);
void cancelAuthentication();
void setLanguage (const QString &language);
diff --git a/liblightdm-qt/greeter.cpp b/liblightdm-qt/greeter.cpp
index 02e8cd8c..2df535b5 100644
--- a/liblightdm-qt/greeter.cpp
+++ b/liblightdm-qt/greeter.cpp
@@ -117,7 +117,12 @@ void Greeter::authenticateAsGuest()
{
Q_D(Greeter);
lightdm_greeter_authenticate_as_guest(d->ldmGreeter);
-
+}
+
+void Greeter::authenticateRemote(const QString &session, const QString &username)
+{
+ Q_D(Greeter);
+ lightdm_greeter_authenticate_remote(d->ldmGreeter, session.toLocal8Bit().data(), username.toLocal8Bit().data());
}
void Greeter::respond(const QString &response)
diff --git a/src/greeter.c b/src/greeter.c
index bcdc2ae3..ad0cf557 100644
--- a/src/greeter.c
+++ b/src/greeter.c
@@ -76,7 +76,8 @@ typedef enum
GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
GREETER_MESSAGE_START_SESSION,
GREETER_MESSAGE_CANCEL_AUTHENTICATION,
- GREETER_MESSAGE_SET_LANGUAGE
+ GREETER_MESSAGE_SET_LANGUAGE,
+ GREETER_MESSAGE_AUTHENTICATE_REMOTE
} GreeterMessage;
/* Messages from the server to the greeter */
@@ -350,6 +351,77 @@ handle_login_as_guest (Greeter *greeter, guint32 sequence_number)
send_end_authentication (greeter, sequence_number, "", PAM_SUCCESS);
}
+static gchar *
+get_remote_session_service (const gchar *session_name)
+{
+ GKeyFile *session_desktop_file;
+ gboolean result;
+ const gchar *c;
+ gchar *filename, *path, *service = NULL;
+ GError *error = NULL;
+
+ /* Validate session name doesn't contain directory separators */
+ for (c = session_name; *c; c++)
+ {
+ if (*c == '/')
+ return NULL;
+ }
+
+ /* Load the session file */
+ session_desktop_file = g_key_file_new ();
+ filename = g_strdup_printf ("%s.desktop", session_name);
+ path = g_build_filename (REMOTE_SESSION_DIR, filename);
+ g_free (filename);
+ result = g_key_file_load_from_file (session_desktop_file, path, G_KEY_FILE_NONE, &error);
+ g_free (path);
+ if (error)
+ g_debug ("Failed to load session file %s: %s", filename, error->message);
+ g_clear_error (&error);
+ if (result)
+ service = g_key_file_get_string (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, "X-LightDM-PAM-Service", NULL);
+ g_key_file_free (session_desktop_file);
+
+ return service;
+}
+
+static void
+handle_login_remote (Greeter *greeter, const gchar *session_name, const gchar *username, guint32 sequence_number)
+{
+ gchar *service;
+
+ if (username)
+ g_debug ("Greeter start authentication for remote session %s as user %s", session_name, username);
+ else
+ g_debug ("Greeter start authentication for remote session %s", session_name);
+
+ reset_session (greeter);
+
+ service = get_remote_session_service (session_name);
+ if (!service)
+ {
+ send_end_authentication (greeter, sequence_number, "", PAM_SYSTEM_ERR);
+ return;
+ }
+
+ g_signal_emit (greeter, signals[START_AUTHENTICATION], 0, username, &greeter->priv->authentication_session);
+ if (greeter->priv->authentication_session)
+ {
+ g_signal_connect (G_OBJECT (greeter->priv->authentication_session), "got-messages", G_CALLBACK (pam_messages_cb), greeter);
+ g_signal_connect (G_OBJECT (greeter->priv->authentication_session), "authentication-complete", G_CALLBACK (authentication_complete_cb), greeter);
+
+ /* Run the session process */
+ session_start (greeter->priv->authentication_session, service, username, TRUE, TRUE);
+ }
+
+ g_free (service);
+
+ if (!greeter->priv->authentication_session)
+ {
+ send_end_authentication (greeter, sequence_number, "", PAM_USER_UNKNOWN);
+ return;
+ }
+}
+
static void
handle_continue_authentication (Greeter *greeter, gchar **secrets)
{
@@ -569,6 +641,12 @@ read_cb (GIOChannel *source, GIOCondition condition, gpointer data)
sequence_number = read_int (greeter, &offset);
handle_login_as_guest (greeter, sequence_number);
break;
+ case GREETER_MESSAGE_AUTHENTICATE_REMOTE:
+ sequence_number = read_int (greeter, &offset);
+ session_name = read_string (greeter, &offset);
+ username = read_string (greeter, &offset);
+ handle_login_remote (greeter, session_name, username, sequence_number);
+ break;
case GREETER_MESSAGE_CONTINUE_AUTHENTICATION:
n_secrets = read_int (greeter, &offset);
secrets = g_malloc (sizeof (gchar *) * (n_secrets + 1));