summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2012-08-20 16:38:33 +1200
committerRobert Ancell <robert.ancell@canonical.com>2012-08-20 16:38:33 +1200
commit7e521a6cf33c57e762ee5a04c4a0e6756838f94c (patch)
treea2c092ba7a184d4b1125f5679f3be911337af4c0
parent4fb3abf0fe3c541d9d42183bf62029731bf4b027 (diff)
parent39a1c8cd4a2cd73fbd6fea231ee1efd5b7691b15 (diff)
downloadlightdm-7e521a6cf33c57e762ee5a04c4a0e6756838f94c.tar.gz
Support multiple simultaneous PAM prompts
-rw-r--r--liblightdm-gobject/greeter.c45
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/scripts/login-multi-prompt.conf39
-rw-r--r--tests/src/libsystem.c11
-rw-r--r--tests/src/test-runner.c2
-rwxr-xr-xtests/test-login-gobject-multi-prompt2
6 files changed, 94 insertions, 7 deletions
diff --git a/liblightdm-gobject/greeter.c b/liblightdm-gobject/greeter.c
index 0a603240..2d31b84c 100644
--- a/liblightdm-gobject/greeter.c
+++ b/liblightdm-gobject/greeter.c
@@ -51,6 +51,9 @@ typedef struct
guint8 *read_buffer;
gsize n_read;
+ gsize n_responses_waiting;
+ GList *responses_received;
+
GHashTable *hints;
guint autologin_timeout;
@@ -301,6 +304,10 @@ handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize me
g_free (priv->authentication_user);
priv->authentication_user = username;
+ g_list_free_full (priv->responses_received, g_free);
+ priv->responses_received = NULL;
+ priv->n_responses_waiting = 0;
+
n_messages = read_int (message, message_length, offset);
g_debug ("Prompt user with %d message(s)", n_messages);
@@ -316,9 +323,11 @@ handle_prompt_authentication (LightDMGreeter *greeter, guint8 *message, gsize me
switch (style)
{
case PAM_PROMPT_ECHO_OFF:
+ priv->n_responses_waiting++;
g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_SECRET);
break;
case PAM_PROMPT_ECHO_ON:
+ priv->n_responses_waiting++;
g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, text, LIGHTDM_PROMPT_TYPE_QUESTION);
break;
case PAM_ERROR_MSG:
@@ -827,7 +836,7 @@ lightdm_greeter_authenticate_as_guest (LightDMGreeter *greeter)
* @greeter: A #LightDMGreeter
* @response: Response to a prompt
*
- * Provide response to a prompt.
+ * Provide response to a prompt. May be one in a series.
**/
void
lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response)
@@ -842,13 +851,35 @@ lightdm_greeter_respond (LightDMGreeter *greeter, const gchar *response)
priv = GET_PRIVATE (greeter);
g_return_if_fail (priv->connected);
+ g_return_if_fail (priv->n_responses_waiting > 0);
- g_debug ("Providing response to display manager");
- write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, int_length () + string_length (response), &offset);
- // FIXME: Could be multiple responses required
- write_int (message, MAX_MESSAGE_LENGTH, 1, &offset);
- write_string (message, MAX_MESSAGE_LENGTH, response, &offset);
- write_message (greeter, message, offset);
+ priv->n_responses_waiting--;
+ priv->responses_received = g_list_append (priv->responses_received, g_strdup (response));
+
+ if (priv->n_responses_waiting == 0)
+ {
+ guint32 msg_length;
+ GList *iter;
+
+ g_debug ("Providing response to display manager");
+
+ msg_length = int_length ();
+ for (iter = priv->responses_received; iter; iter = iter->next)
+ {
+ msg_length += string_length ((gchar *)iter->data);
+ }
+
+ write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, msg_length, &offset);
+ write_int (message, MAX_MESSAGE_LENGTH, g_list_length (priv->responses_received), &offset);
+ for (iter = priv->responses_received; iter; iter = iter->next)
+ {
+ write_string (message, MAX_MESSAGE_LENGTH, (gchar *)iter->data, &offset);
+ }
+ write_message (greeter, message, offset);
+
+ g_list_free_full (priv->responses_received, g_free);
+ priv->responses_received = NULL;
+ }
}
/**
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 93b47f33..7d87c3ab 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -58,6 +58,7 @@ TESTS = \
test-login-gobject-new-authtok \
test-login-gobject-info-prompt \
test-login-gobject-multi-info-prompt \
+ test-login-gobject-multi-prompt \
test-login-gobject-pick-session \
test-login-gobject-previous-session \
test-login-gobject-wrong-password \
@@ -207,6 +208,7 @@ EXTRA_DIST = \
scripts/login-manual.conf \
scripts/login-manual-previous-session.conf \
scripts/login-multi-info-prompt.conf \
+ scripts/login-multi-prompt.conf \
scripts/login-new-authtok.conf \
scripts/login-no-password.conf \
scripts/login-pam.conf \
diff --git a/tests/scripts/login-multi-prompt.conf b/tests/scripts/login-multi-prompt.conf
new file mode 100644
index 00000000..ed24986b
--- /dev/null
+++ b/tests/scripts/login-multi-prompt.conf
@@ -0,0 +1,39 @@
+#
+# Check multiple PAM informational messages on login are passed to a greeter
+#
+
+[LightDM]
+minimum-display-number=50
+
+#?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
+
+# Log into account and see an informational prompt
+#?*GREETER :50 AUTHENTICATE USERNAME=multi-prompt
+#?GREETER :50 SHOW-PROMPT TEXT="Favorite Color:"
+#?GREETER :50 SHOW-PROMPT TEXT="Password:"
+
+# Respond with password and check response is correctly handled
+#?*GREETER :50 RESPOND TEXT="blue"
+#?*GREETER :50 RESPOND TEXT="password"
+#?GREETER :50 AUTHENTICATION-COMPLETE USERNAME=multi-prompt AUTHENTICATED=TRUE
+
+# Cleanup
+#?*STOP-DAEMON
+# Don't know what order they will terminate
+#?(GREETER :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15)
+#?(GREETER :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15)
+#?RUNNER DAEMON-EXIT STATUS=0
diff --git a/tests/src/libsystem.c b/tests/src/libsystem.c
index 2b944837..855f668b 100644
--- a/tests/src/libsystem.c
+++ b/tests/src/libsystem.c
@@ -546,6 +546,13 @@ pam_authenticate (pam_handle_t *pamh, int flags)
msg[n_messages]->msg = "You should have seen three messages";
n_messages++;
}
+ if (strcmp (pamh->user, "multi-prompt") == 0)
+ {
+ msg[n_messages] = malloc (sizeof (struct pam_message));
+ msg[n_messages]->msg_style = PAM_PROMPT_ECHO_ON;
+ msg[n_messages]->msg = "Favorite Color:";
+ n_messages++;
+ }
msg[n_messages] = malloc (sizeof (struct pam_message));
msg[n_messages]->msg_style = PAM_PROMPT_ECHO_OFF;
msg[n_messages]->msg = "Password:";
@@ -568,6 +575,10 @@ pam_authenticate (pam_handle_t *pamh, int flags)
if (entry)
password_matches = strcmp (entry->pw_passwd, resp[password_index].resp) == 0;
+
+ if (password_matches && strcmp (pamh->user, "multi-prompt") == 0)
+ password_matches = strcmp ("blue", resp[0].resp) == 0;
+
for (i = 0; i < n_messages; i++)
{
if (resp[i].resp)
diff --git a/tests/src/test-runner.c b/tests/src/test-runner.c
index 491a16c8..516a6788 100644
--- a/tests/src/test-runner.c
+++ b/tests/src/test-runner.c
@@ -1391,6 +1391,8 @@ main (int argc, char **argv)
{"cred-unavail", "password", TRUE, "Cred Unavail", NULL, NULL, NULL, NULL, 1029},
/* This account sends informational messages for each PAM function that is called */
{"log-pam", "password", TRUE, "Log PAM", NULL, NULL, NULL, NULL, 1030},
+ /* This account shows multiple prompts on login */
+ {"multi-prompt", "password", TRUE, "Multi Prompt", NULL, NULL, NULL, NULL, 1031},
{NULL, NULL, FALSE, NULL, NULL, NULL, NULL, NULL, 0}
};
passwd_data = g_string_new ("");
diff --git a/tests/test-login-gobject-multi-prompt b/tests/test-login-gobject-multi-prompt
new file mode 100755
index 00000000..7f4f52e8
--- /dev/null
+++ b/tests/test-login-gobject-multi-prompt
@@ -0,0 +1,2 @@
+#!/bin/sh
+./src/dbus-env ./src/test-runner login-multi-prompt test-gobject-greeter