Group :: Graphical desktop/Other
RPM: lightdm
Main Changelog Spec Patches Sources Download Gear Bugs and FR Repocop
Patch: lightdm-1.32.0-pam-locale.patch
Download
Download
src/greeter.c | 13 +++++++
src/session-child.c | 86 +++++++++++++++++++++++++++--------------
src/session.c | 14 +++++++
src/session.h | 2 +
tests/Makefile.am | 2 +
tests/scripts/language-pam.conf | 46 ++++++++++++++++++++++
tests/src/libsystem.c | 7 ++++
tests/src/test-runner.c | 2 +
tests/test-language-pam | 2 +
9 files changed, 146 insertions(+), 28 deletions(-)
diff --git a/src/greeter.c b/src/greeter.c
index 75fe9ff6..e8083616 100644
--- a/src/greeter.c
+++ b/src/greeter.c
@@ -57,6 +57,9 @@ typedef struct
/* Currently selected user */
gchar *active_username;
+ /* Currently selected language */
+ gchar *language;
+
/* PAM session being constructed by the greeter */
Session *authentication_session;
@@ -548,6 +551,10 @@ handle_authenticate (Greeter *greeter, guint32 sequence_number, const gchar *use
is_interactive = TRUE;
}
+ // Set the language here in order to run the PAM session
+ // with the selected locale:
+ session_set_language (priv->authentication_session, priv->language);
+
/* Run the session process */
session_set_pam_service (priv->authentication_session, service);
session_set_username (priv->authentication_session, username);
@@ -759,6 +766,11 @@ handle_set_language (Greeter *greeter, const gchar *language)
{
GreeterPrivate *priv = greeter_get_instance_private (greeter);
+ // Save the selected language string in order to pass it to the
+ // next authentication session:
+ g_free (priv->language);
+ priv->language = g_strdup (language);
+
if (!priv->guest_account_authenticated && !session_get_is_authenticated (priv->authentication_session))
{
g_debug ("Ignoring set language request, user is not authorized");
@@ -1092,6 +1104,7 @@ greeter_finalize (GObject *object)
g_hash_table_unref (priv->hints);
g_clear_pointer (&priv->remote_session, g_free);
g_clear_pointer (&priv->active_username, g_free);
+ g_clear_pointer (&priv->language, g_free);
if (priv->authentication_session)
{
g_signal_handlers_disconnect_matched (priv->authentication_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
diff --git a/src/session-child.c b/src/session-child.c
index 112daabe..b6752f21 100644
--- a/src/session-child.c
+++ b/src/session-child.c
@@ -16,6 +16,7 @@
#include <utmp.h>
#include <utmpx.h>
#include <sys/mman.h>
+#include <locale.h>
#if HAVE_LIBAUDIT
#include <libaudit.h>
@@ -239,6 +240,48 @@ audit_event (int type, const gchar *username, uid_t uid, const gchar *remote_hos
}
#endif
+static void
+apply_locale (const gchar *locale, GError **error)
+{
+ if (setlocale (LC_ALL, locale))
+ {
+ static const gchar * const locale_var_names[] = {
+ "LC_PAPER",
+ "LC_NAME",
+ "LC_ADDRESS",
+ "LC_TELEPHONE",
+ "LC_MEASUREMENT",
+ "LC_IDENTIFICATION",
+ "LC_COLLATE",
+ "LC_CTYPE",
+ "LC_MONETARY",
+ "LC_NUMERIC",
+ "LC_TIME",
+ "LC_MESSAGES",
+ "LC_ALL",
+ "LANG",
+ NULL
+ };
+ for (int i = 0; locale_var_names[i] != NULL; i++)
+ {
+ setenv (locale_var_names[i], locale, 1);
+ }
+ }
+ else
+ {
+ g_set_error_literal (error, 1, errno, strerror (errno));
+ }
+}
+
+static void
+set_locale (const gchar *language, GError **error)
+{
+ if (language && strlen (language) > 0)
+ {
+ apply_locale (language, error);
+ }
+}
+
int
session_child_run (int argc, char **argv)
{
@@ -293,6 +336,15 @@ session_child_run (int argc, char **argv)
g_autofree gchar *remote_host_name = read_string ();
g_autofree gchar *xdisplay = read_string ();
g_autoptr(XAuthority) x_authority = read_xauth ();
+ g_autofree gchar *language = read_string ();
+
+ g_autoptr(GError) locale_err = NULL;
+ set_locale (language, &locale_err);
+ if (locale_err)
+ {
+ g_printerr ("Unable to read and set locale: %s", locale_err->message);
+ return EXIT_FAILURE;
+ }
/* Setup PAM */
struct pam_conv conversation = { pam_conv_cb, NULL };
@@ -399,34 +451,12 @@ session_child_run (int argc, char **argv)
pam_putenv (pam_handle, g_strdup_printf ("LOGNAME=%s", username));
pam_putenv (pam_handle, g_strdup_printf ("HOME=%s", user_get_home_directory (user)));
pam_putenv (pam_handle, g_strdup_printf ("SHELL=%s", user_get_shell (user)));
-
- /* Let the greeter and user session inherit the system default locale */
- static const gchar * const locale_var_names[] = {
- "LC_PAPER",
- "LC_NAME",
- "LC_ADDRESS",
- "LC_TELEPHONE",
- "LC_MEASUREMENT",
- "LC_IDENTIFICATION",
- "LC_COLLATE",
- "LC_CTYPE",
- "LC_MONETARY",
- "LC_NUMERIC",
- "LC_TIME",
- "LC_MESSAGES",
- "LC_ALL",
- "LANG",
- NULL
- };
- for (int i = 0; locale_var_names[i] != NULL; i++)
- {
- const gchar *locale_value;
- if ((locale_value = g_getenv (locale_var_names[i])) != NULL)
- {
- g_autofree gchar *locale_var = g_strdup_printf ("%s=%s", locale_var_names[i], locale_value);
- pam_putenv (pam_handle, locale_var);
- }
- }
+ /* Let the greeter and user session inherit the selected
+ or the system default locale. However, don't set
+ anything except the LANG var --- let's leave the other
+ on behalf of the environment, that is copyed from the
+ session configuration below. */
+ pam_putenv (pam_handle, g_strdup_printf ("LANG=%s", g_getenv ("LANG")));
}
}
diff --git a/src/session.c b/src/session.c
index fce12a0b..486a16a4 100644
--- a/src/session.c
+++ b/src/session.c
@@ -96,6 +96,9 @@ typedef struct
XAuthority *x_authority;
gboolean x_authority_use_system_location;
+ /* The language currently selected in the greeter */
+ gchar *language;
+
/* Socket to allow greeters to connect to (if allowed) */
GreeterSocket *greeter_socket;
@@ -278,6 +281,15 @@ session_set_x_authority (Session *session, XAuthority *authority, gboolean use_s
priv->x_authority_use_system_location = use_system_location;
}
+void
+session_set_language (Session *session, const gchar *language)
+{
+ SessionPrivate *priv = session_get_instance_private (session);
+ g_return_if_fail (session != NULL);
+ g_free (priv->language);
+ priv->language = g_strdup (language);
+}
+
void
session_set_remote_host_name (Session *session, const gchar *remote_host_name)
{
@@ -657,6 +669,7 @@ session_real_start (Session *session)
write_string (session, priv->remote_host_name);
write_string (session, priv->xdisplay);
write_xauth (session, priv->x_authority);
+ write_string (session, priv->language);
l_debug (session, "Started with service '%s', username '%s'", priv->pam_service, priv->username);
@@ -1015,6 +1028,7 @@ session_finalize (GObject *object)
g_clear_pointer (&priv->tty, g_free);
g_clear_pointer (&priv->xdisplay, g_free);
g_clear_object (&priv->x_authority);
+ g_clear_pointer (&priv->language, g_free);
g_clear_pointer (&priv->remote_host_name, g_free);
g_clear_pointer (&priv->login1_session_id, g_free);
g_clear_pointer (&priv->console_kit_cookie, g_free);
diff --git a/src/session.h b/src/session.h
index e1130e83..2ad6aee3 100644
--- a/src/session.h
+++ b/src/session.h
@@ -99,6 +99,8 @@ void session_set_xdisplay (Session *session, const gchar *xdisplay);
void session_set_x_authority (Session *session, XAuthority *authority, gboolean use_system_location);
+void session_set_language (Session *session, const gchar *language);
+
void session_set_remote_host_name (Session *session, const gchar *remote_host_name);
void session_set_env (Session *session, const gchar *name, const gchar *value);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index da6305f0..9649cf2b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -88,6 +88,7 @@ TESTS = \
test-language \
test-language-no-accounts-service \
test-language-greeter \
+ test-language-pam \
test-login-crash-authenticate \
test-login-invalid-greeter \
test-login-gobject \
@@ -420,6 +421,7 @@ EXTRA_DIST = \
scripts/language-env.conf \
scripts/language-no-accounts-service.conf \
scripts/language-greeter.conf \
+ scripts/language-pam.conf \
scripts/lock-seat.conf \
scripts/lock-seat-after-vt-switch.conf \
scripts/lock-seat-console-kit.conf \
diff --git a/tests/scripts/language-pam.conf b/tests/scripts/language-pam.conf
new file mode 100644
index 00000000..6fc79e1c
--- /dev/null
+++ b/tests/scripts/language-pam.conf
@@ -0,0 +1,46 @@
+#
+# Checks the language is changed in PAM
+#
+
+#?*START-DAEMON
+#?RUNNER DAEMON-START
+
+# X server starts
+#?XSERVER-0 START VT=7 SEAT=seat0
+
+# Daemon connects when X server is ready
+#?*XSERVER-0 INDICATE-READY
+#?XSERVER-0 INDICATE-READY
+#?XSERVER-0 ACCEPT-CONNECT
+
+# Greeter starts
+#?GREETER-X-0 START XDG_SEAT=seat0 XDG_VTNR=7 XDG_SESSION_CLASS=greeter
+#?LOGIN1 ACTIVATE-SESSION SESSION=c0
+#?XSERVER-0 ACCEPT-CONNECT
+#?GREETER-X-0 CONNECT-XSERVER
+#?GREETER-X-0 CONNECT-TO-DAEMON
+#?GREETER-X-0 CONNECTED-TO-DAEMON
+
+# Start authentication
+#?*GREETER-X-0 AUTHENTICATE USERNAME=show-locale
+#?GREETER-X-0 SHOW-MESSAGE TEXT=""
+#?GREETER-X-0 SHOW-PROMPT TEXT="Password:"
+
+# Cancel authentication
+#?*GREETER-X-0 CANCEL-AUTHENTICATION
+#?GREETER-X-0 AUTHENTICATION-COMPLETE USERNAME=show-locale AUTHENTICATED=FALSE
+
+# Select language
+#?*GREETER-X-0 SET-LANGUAGE VALUE=ru_RU.UTF-8
+#?GREETER-X-0 SET-LANGUAGE OK
+
+# Start new authentication
+#?*GREETER-X-0 AUTHENTICATE USERNAME=show-locale
+#?GREETER-X-0 SHOW-MESSAGE TEXT="ru_RU.UTF-8"
+#?GREETER-X-0 SHOW-PROMPT TEXT="Password:"
+
+# Cleanup
+#?*STOP-DAEMON
+#?GREETER-X-0 TERMINATE SIGNAL=15
+#?XSERVER-0 TERMINATE SIGNAL=15
+#?RUNNER DAEMON-EXIT STATUS=0
diff --git a/tests/src/libsystem.c b/tests/src/libsystem.c
index 1c68dc10..564b07c1 100644
--- a/tests/src/libsystem.c
+++ b/tests/src/libsystem.c
@@ -1034,6 +1034,13 @@ pam_authenticate (pam_handle_t *pamh, int flags)
msg[n_messages]->msg = "Favorite Color:";
n_messages++;
}
+ if (strcmp (pamh->user, "show-locale") == 0)
+ {
+ msg[n_messages] = malloc (sizeof (struct pam_message));
+ msg[n_messages]->msg_style = PAM_TEXT_INFO;
+ msg[n_messages]->msg = getenv ("LANG");
+ n_messages++;
+ }
msg[n_messages] = malloc (sizeof (struct pam_message));
msg[n_messages]->msg_style = PAM_PROMPT_ECHO_OFF;
msg[n_messages]->msg = "Password:";
diff --git a/tests/src/test-runner.c b/tests/src/test-runner.c
index 1b961961..2eaa172e 100644
--- a/tests/src/test-runner.c
+++ b/tests/src/test-runner.c
@@ -2644,6 +2644,8 @@ main (int argc, char **argv)
{"corrupt-xauth", "password", "Corrupt Xauthority", 1032},
/* User to test properties */
{"prop-user", "", "TEST", 1033},
+ /* This account shows current locale */
+ {"show-locale", "password", "Show Locale", 1034},
{NULL, NULL, NULL, 0}
};
g_autoptr(GString) passwd_data = g_string_new ("");
diff --git a/tests/test-language-pam b/tests/test-language-pam
new file mode 100755
index 00000000..024e5df5
--- /dev/null
+++ b/tests/test-language-pam
@@ -0,0 +1,2 @@
+#!/bin/sh
+./src/dbus-env ./src/test-runner language-pam test-gobject-greeter