From 40e9874b5ce72d9de46f5a18251bfe283a76df13 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Mon, 20 Aug 2012 17:34:12 +1200 Subject: Start work on supporting remote session types --- liblightdm-gobject/greeter.c | 44 +++++++++++++++++++- liblightdm-gobject/lightdm/greeter.h | 4 +- liblightdm-gobject/lightdm/session.h | 2 + liblightdm-gobject/session.c | 15 +++++++ liblightdm-qt/QLightDM/greeter.h | 1 + liblightdm-qt/greeter.cpp | 7 +++- src/greeter.c | 80 +++++++++++++++++++++++++++++++++++- 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]; @@ -831,6 +832,45 @@ lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter) write_message (greeter, message, offset); } +/** + * 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 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) @@ -208,6 +209,20 @@ lightdm_get_sessions (void) return sessions; } +/** + * 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)); -- cgit v1.2.1