+Overview of changes in lightdm 1.3.5
+
+ * Correctly implement and test autologin timeouts
+
Overview of changes in lightdm 1.3.4
* Correctly annotate enums in vapi file
write_message (greeter, message, offset);
}
+/**
+ * lightdm_greeter_authenticate_autologin:
+ * @greeter: A #LightDMGreeter
+ *
+ * Starts the authentication procedure for the automatic login user.
+ **/
+void
+lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter)
+{
+ const gchar *user;
+
+ user = lightdm_greeter_get_autologin_user_hint (greeter);
+ if (lightdm_greeter_get_autologin_guest_hint (greeter))
+ lightdm_greeter_authenticate_as_guest (greeter);
+ else if (user)
+ lightdm_greeter_authenticate (greeter, user);
+}
+
/**
* lightdm_greeter_authenticate_remote:
* @greeter: A #LightDMGreeter
void lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter);
+void lightdm_greeter_authenticate_autologin (LightDMGreeter *greeter);
+
void lightdm_greeter_authenticate_remote (LightDMGreeter *greeter, const gchar *session, const gchar *username);
void lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response);
bool connectSync();
void authenticate(const QString &username=QString());
void authenticateAsGuest();
+ void authenticateAutologin();
void authenticateRemote(const QString &session=QString(), const QString &username=QString());
void respond(const QString &response);
void cancelAuthentication();
lightdm_greeter_authenticate_as_guest(d->ldmGreeter);
}
+void Greeter::authenticateAutologin()
+{
+ Q_D(Greeter);
+ lightdm_greeter_authenticate_autologin(d->ldmGreeter);
+}
+
void Greeter::authenticateRemote(const QString &session, const QString &username)
{
Q_D(Greeter);
g_signal_connect (display->priv->session, "authentication-complete", G_CALLBACK (greeter_authentication_complete_cb), display);
/* Make communication link to greeter that will run on this session */
- display->priv->greeter = greeter_new (display->priv->session, USER_SERVICE);
+ display->priv->greeter = greeter_new (display->priv->session, USER_SERVICE, AUTOLOGIN_SERVICE);
g_signal_connect (G_OBJECT (display->priv->greeter), "connected", G_CALLBACK (greeter_connected_cb), display);
g_signal_connect (G_OBJECT (display->priv->greeter), "start-authentication", G_CALLBACK (greeter_start_authentication_cb), display);
g_signal_connect (G_OBJECT (display->priv->greeter), "start-session", G_CALLBACK (greeter_start_session_cb), display);
/* Automatically start requested user session */
result = FALSE;
- if (display->priv->autologin_guest)
+ if (display->priv->autologin_timeout == 0 && display->priv->autologin_guest)
{
g_debug ("Automatically logging in as guest");
result = autologin_guest (display, AUTOLOGIN_SERVICE, TRUE);
}
- else if (display->priv->autologin_user)
+ else if (display->priv->autologin_timeout == 0 && display->priv->autologin_user)
{
g_debug ("Automatically logging in user %s", display->priv->autologin_user);
result = autologin (display, display->priv->autologin_user, AUTOLOGIN_SERVICE, TRUE, FALSE);
/* PAM service to authenticate with */
gchar *pam_service;
+ gchar *autologin_pam_service;
/* Buffer for data read from greeter */
guint8 *read_buffer;
static gboolean read_cb (GIOChannel *source, GIOCondition condition, gpointer data);
Greeter *
-greeter_new (Session *session, const gchar *pam_service)
+greeter_new (Session *session, const gchar *pam_service, const gchar *autologin_pam_service)
{
Greeter *greeter;
greeter = g_object_new (GREETER_TYPE, NULL);
greeter->priv->session = g_object_ref (session);
greeter->priv->pam_service = g_strdup (pam_service);
+ greeter->priv->autologin_pam_service = g_strdup (autologin_pam_service);
return greeter;
}
static void
handle_login (Greeter *greeter, guint32 sequence_number, const gchar *username)
{
+ const gchar *autologin_username, *service;
+ gboolean is_interactive;
+
if (username[0] == '\0')
{
g_debug ("Greeter start authentication");
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);
+ /* Use non-interactive service for autologin user */
+ autologin_username = g_hash_table_lookup (greeter->priv->hints, "autologin-user");
+ if (autologin_username != NULL && g_strcmp0 (username, autologin_username) == 0)
+ {
+ service = greeter->priv->autologin_pam_service;
+ is_interactive = FALSE;
+ }
+ else
+ {
+ service = greeter->priv->pam_service;
+ is_interactive = TRUE;
+ }
+
/* Run the session process */
- session_start (greeter->priv->authentication_session, greeter->priv->pam_service, username, TRUE, TRUE, FALSE);
+ session_start (greeter->priv->authentication_session, service, username, TRUE, is_interactive, FALSE);
}
static void
g_signal_handlers_disconnect_matched (self->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
g_object_unref (self->priv->session);
g_free (self->priv->pam_service);
+ g_free (self->priv->autologin_pam_service);
g_free (self->priv->read_buffer);
g_hash_table_unref (self->priv->hints);
g_free (self->priv->remote_session);
GType greeter_get_type (void);
-Greeter *greeter_new (Session *session, const gchar *pam_service);
+Greeter *greeter_new (Session *session, const gchar *pam_service, const gchar *autologin_pam_service);
void greeter_set_allow_guest (Greeter *greeter, gboolean allow_guest);
}
static gboolean
-switch_to_user_or_start_greeter (Seat *seat, const gchar *username, gboolean use_existing, gboolean is_guest, const gchar *session_name, gboolean is_lock, gboolean autologin)
+switch_to_user_or_start_greeter (Seat *seat, const gchar *username, gboolean use_existing, gboolean is_guest, const gchar *session_name, gboolean is_lock, gboolean autologin, int autologin_timeout)
{
Display *display;
DisplayServer *display_server;
display_set_allow_guest (display, seat_get_allow_guest (seat));
display_set_greeter_allow_guest (display, seat_get_greeter_allow_guest (seat));
if (autologin)
- display_set_autologin_user (display, username, is_guest, 0);
+ display_set_autologin_user (display, username, is_guest, autologin_timeout);
else
display_set_select_user_hint (display, username, is_guest);
if (!session_name)
return FALSE;
g_debug ("Switching to greeter");
- return switch_to_user_or_start_greeter (seat, NULL, TRUE, FALSE, NULL, FALSE, FALSE);
+ return switch_to_user_or_start_greeter (seat, NULL, TRUE, FALSE, NULL, FALSE, FALSE, 0);
}
gboolean
return FALSE;
g_debug ("Switching to user %s", username);
- return switch_to_user_or_start_greeter (seat, username, TRUE, FALSE, session_name, FALSE, FALSE);
+ return switch_to_user_or_start_greeter (seat, username, TRUE, FALSE, session_name, FALSE, FALSE, 0);
}
gboolean
g_debug ("Switching to existing guest account %s", seat->priv->guest_username);
else
g_debug ("Switching to new guest account");
- return switch_to_user_or_start_greeter (seat, seat->priv->guest_username, TRUE, TRUE, session_name, FALSE, TRUE);
+ return switch_to_user_or_start_greeter (seat, seat->priv->guest_username, TRUE, TRUE, session_name, FALSE, TRUE, 0);
}
gboolean
return FALSE;
g_debug ("Locking seat");
- return switch_to_user_or_start_greeter (seat, username, FALSE, FALSE, NULL, TRUE, FALSE);
+ return switch_to_user_or_start_greeter (seat, username, FALSE, FALSE, NULL, TRUE, FALSE, 0);
}
void
seat_real_start (Seat *seat)
{
const gchar *autologin_username;
+ int autologin_timeout;
g_debug ("Starting seat");
autologin_username = seat_get_string_property (seat, "autologin-user");
if (g_strcmp0 (autologin_username, "") == 0)
autologin_username = NULL;
+ autologin_timeout = seat_get_integer_property (seat, "autologin-user-timeout");
if (autologin_username)
- return switch_to_user_or_start_greeter (seat, autologin_username, TRUE, FALSE, NULL, FALSE, TRUE);
+ return switch_to_user_or_start_greeter (seat, autologin_username, TRUE, FALSE, NULL, FALSE, TRUE, autologin_timeout);
else if (seat_get_boolean_property (seat, "autologin-guest"))
- return switch_to_user_or_start_greeter (seat, NULL, TRUE, TRUE, NULL, FALSE, TRUE);
+ return switch_to_user_or_start_greeter (seat, NULL, TRUE, TRUE, NULL, FALSE, TRUE, autologin_timeout);
else
- return switch_to_user_or_start_greeter (seat, NULL, TRUE, FALSE, NULL, FALSE, FALSE);
+ return switch_to_user_or_start_greeter (seat, NULL, TRUE, FALSE, NULL, FALSE, FALSE, 0);
}
static void
test-autologin-session-crash \
test-autologin-password \
test-autologin-new-authtok \
+ test-autologin-gobject-timeout \
+ test-autologin-gobject-guest-timeout \
+ test-autologin-python-timeout \
+ test-autologin-python-guest-timeout \
test-change-authentication \
test-restart-authentication \
test-pam \
if COMPILE_LIBLIGHTDM_QT
TESTS += \
+ test-autologin-qt-timeout \
+ test-autologin-qt-guest-timeout \
test-login-qt \
test-login-qt-manual \
test-login-qt-manual-previous-session \
--- /dev/null
+#
+# Check automatically logs in default user
+#
+
+[LightDM]
+minimum-display-number=50
+
+[SeatDefaults]
+autologin-guest=true
+autologin-user-timeout=1
+
+#?RUNNER DAEMON-START
+
+# X server starts
+#?XSERVER :50 START
+#?XSERVER :50 INDICATE-READY
+
+# LightDM connects to X server
+#?XSERVER :50 ACCEPT-CONNECT
+
+# Greeter starts
+#?GREETER :50 START
+#?XSERVER :50 ACCEPT-CONNECT
+#?GREETER :50 CONNECT-XSERVER
+#?GREETER :50 CONNECT-TO-DAEMON
+#?GREETER :50 CONNECTED-TO-DAEMON
+
+# Autologin timer expires
+#?GREETER :50 AUTOLOGIN-TIMER-EXPIRED
+
+# Trigger autologin
+#?*GREETER :50 AUTHENTICATE-AUTOLOGIN
+#?GREETER :50 AUTHENTICATION-COMPLETE AUTHENTICATED=TRUE
+#?*GREETER :50 START-SESSION
+#?GREETER :50 TERMINATE SIGNAL=15
+
+# Guest account created
+#?GUEST-ACCOUNT ADD USERNAME=guest-.*
+
+# Guest session starts
+#?SESSION :50 START USER=guest-.*
+#?XSERVER :50 ACCEPT-CONNECT
+#?SESSION :50 CONNECT-XSERVER
+
+# Cleanup
+#?*STOP-DAEMON
+# Don't know what order they will terminate
+#?(SESSION :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15|GUEST-ACCOUNT REMOVE USERNAME=guest-.*)
+#?(SESSION :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15|GUEST-ACCOUNT REMOVE USERNAME=guest-.*)
+#?(SESSION :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15|GUEST-ACCOUNT REMOVE USERNAME=guest-.*)
+#?RUNNER DAEMON-EXIT STATUS=0
--- /dev/null
+#
+# Check automatically logs in default user
+#
+
+[LightDM]
+minimum-display-number=50
+
+[SeatDefaults]
+autologin-user=have-password1
+autologin-user-timeout=1
+
+#?RUNNER DAEMON-START
+
+# X server starts
+#?XSERVER :50 START
+#?XSERVER :50 INDICATE-READY
+
+# LightDM connects to X server
+#?XSERVER :50 ACCEPT-CONNECT
+
+# Greeter starts
+#?GREETER :50 START
+#?XSERVER :50 ACCEPT-CONNECT
+#?GREETER :50 CONNECT-XSERVER
+#?GREETER :50 CONNECT-TO-DAEMON
+#?GREETER :50 CONNECTED-TO-DAEMON
+
+# Autologin timer expires
+#?GREETER :50 AUTOLOGIN-TIMER-EXPIRED
+
+# Trigger autologin
+#?*GREETER :50 AUTHENTICATE-AUTOLOGIN
+#?GREETER :50 AUTHENTICATION-COMPLETE USERNAME=have-password1 AUTHENTICATED=TRUE
+#?*GREETER :50 START-SESSION
+#?GREETER :50 TERMINATE SIGNAL=15
+
+# Session starts
+#?SESSION :50 START USER=have-password1
+#?XSERVER :50 ACCEPT-CONNECT
+#?SESSION :50 CONNECT-XSERVER
+
+# Cleanup
+#?*STOP-DAEMON
+# Don't know what order they will terminate
+#?(SESSION :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15)
+#?(SESSION :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15)
+#?RUNNER DAEMON-EXIT STATUS=0
lightdm_greeter_get_is_authenticated (greeter) ? "TRUE" : "FALSE");
}
+static void
+autologin_timer_expired_cb (LightDMGreeter *greeter)
+{
+ status_notify ("GREETER %s AUTOLOGIN-TIMER-EXPIRED", getenv ("DISPLAY"));
+}
+
static void
signal_cb (int signum)
{
lightdm_greeter_authenticate_as_guest (greeter);
g_free (r);
+ r = g_strdup_printf ("GREETER %s AUTHENTICATE-AUTOLOGIN", getenv ("DISPLAY"));
+ if (strcmp (request, r) == 0)
+ lightdm_greeter_authenticate_autologin (greeter);
+ g_free (r);
+
r = g_strdup_printf ("GREETER %s AUTHENTICATE-REMOTE SESSION=", getenv ("DISPLAY"));
if (g_str_has_prefix (request, r))
lightdm_greeter_authenticate_remote (greeter, request + strlen (r), NULL);
g_signal_connect (greeter, "show-message", G_CALLBACK (show_message_cb), NULL);
g_signal_connect (greeter, "show-prompt", G_CALLBACK (show_prompt_cb), NULL);
g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
+ g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (autologin_timer_expired_cb), NULL);
status_notify ("GREETER %s CONNECT-TO-DAEMON", getenv ("DISPLAY"));
if (!lightdm_greeter_connect_sync (greeter, NULL))
if request.startswith (r):
greeter.authenticate (request[len(r):])
- r = 'GREETER %s AUTHENTICATE-REMOTE SESSION=' % os.getenv ('DISPLAY')
- if request.startswith (r):
- greeter.authenticate_remote (request[len(r):], None)
-
r = 'GREETER %s AUTHENTICATE-GUEST' % os.getenv ('DISPLAY')
if request == r:
greeter.authenticate_as_guest ()
+ r = 'GREETER %s AUTHENTICATE-AUTOLOGIN' % os.getenv ('DISPLAY')
+ if request == r:
+ greeter.authenticate_autologin ()
+
+ r = 'GREETER %s AUTHENTICATE-REMOTE SESSION=' % os.getenv ('DISPLAY')
+ if request.startswith (r):
+ greeter.authenticate_remote (request[len(r):], None)
+
r = 'GREETER %s RESPOND TEXT=\"' % os.getenv ('DISPLAY')
if request.startswith (r):
greeter.respond (request[len (r):-1])
else:
status_notify ('GREETER %s AUTHENTICATION-COMPLETE AUTHENTICATED=%s' % (os.getenv ('DISPLAY'), is_authenticated))
+def autologin_timer_expired_cb (greeter):
+ status_notify ('GREETER %s AUTOLOGIN-TIMER-EXPIRED' % os.getenv ('DISPLAY'))
+
greeter = LightDM.Greeter ()
greeter.connect ('show-message', show_message_cb)
greeter.connect ('show-prompt', show_prompt_cb)
greeter.connect ('authentication-complete', authentication_complete_cb)
+greeter.connect ('autologin-timer-expired', autologin_timer_expired_cb)
status_notify ('GREETER %s CONNECT-TO-DAEMON' % os.getenv ('DISPLAY'))
if not greeter.connect_sync ():
if greeter.get_select_user_hint () is not None:
status_notify ('GREETER %s SELECT-USER-HINT USERNAME=%s' % (os.getenv ('DISPLAY'), greeter.get_select_user_hint ()))
if greeter.get_lock_hint ():
- status_notify ('GREETER %s LOCK-HINT' % os.getenv ('DISPLAY'));
+ status_notify ('GREETER %s LOCK-HINT' % os.getenv ('DISPLAY'));
loop.run ()
connect (this, SIGNAL(showMessage(QString, QLightDM::Greeter::MessageType)), SLOT(showMessage(QString, QLightDM::Greeter::MessageType)));
connect (this, SIGNAL(showPrompt(QString, QLightDM::Greeter::PromptType)), SLOT(showPrompt(QString, QLightDM::Greeter::PromptType)));
connect (this, SIGNAL(authenticationComplete()), SLOT(authenticationComplete()));
+ connect (this, SIGNAL(autologinTimerExpired()), SLOT(autologinTimerExpired()));
}
void TestGreeter::showMessage (QString text, QLightDM::Greeter::MessageType type)
status_notify ("GREETER %s AUTHENTICATION-COMPLETE AUTHENTICATED=%s", getenv ("DISPLAY"), isAuthenticated () ? "TRUE" : "FALSE");
}
+void TestGreeter::autologinTimerExpired ()
+{
+ status_notify ("GREETER %s AUTOLOGIN-TIMER-EXPIRED", getenv ("DISPLAY"));
+}
+
static void
signal_cb (int signum)
{
greeter->authenticateAsGuest ();
g_free (r);
+ r = g_strdup_printf ("GREETER %s AUTHENTICATE-AUTOLOGIN", getenv ("DISPLAY"));
+ if (strcmp (request, r) == 0)
+ greeter->authenticateAutologin ();
+ g_free (r);
+
r = g_strdup_printf ("GREETER %s AUTHENTICATE-REMOTE SESSION=", getenv ("DISPLAY"));
if (g_str_has_prefix (request, r))
greeter->authenticateRemote (request + strlen (r), NULL);
void showMessage(QString text, QLightDM::Greeter::MessageType type);
void showPrompt(QString text, QLightDM::Greeter::PromptType type);
void authenticationComplete();
+ void autologinTimerExpired();
};
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner autologin-guest-timeout test-gobject-greeter
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner autologin-timeout test-gobject-greeter
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner autologin-guest-timeout test-python-greeter
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner autologin-timeout test-python-greeter
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner autologin-guest-timeout test-qt-greeter
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner autologin-timeout test-qt-greeter