Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37841572
en ru br
ALT Linux repos
S:1.32.0-alt4

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


 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
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin