[gdm-list] a few smart card related patches



(resending because session.c and session.h were too big for the mailing list)

Hi Brian,

So a couple of weeks ago we discussed strategies for implementing
smart card login within GDM, and you pointed out that Sun currently
has an external daemon that listens for smart card insertion and
removal events which reconfigures the gdm daemon to use a different
pam stack and then kills the greeter so the new settings take effect.

Below I've attached a patch (reset-pam.patch) to add a
GDM_SOP_CANCEL_LOGIN_REQUESTS command to reset PAM without having to
restart the greeter.

It uses the same code path as the greeter's cancel button to signal a
cancel request.  This mechanism works by polling at various points in
the PAM conversation function and failing the login attempt if a
cancel request comes in.  On the other side (of pam_authenticate), we
ignore the failure and start over if there is a pending cancel
request.

The reset-pam patch loosely requires another patch,
process-all-ops.patch, which fixes a bug where the greeters get
confused if they get sent too many commands too quickly from the
slave.

What I'd like to do is handle pam authentication more asynchronously.
This would work by forking a helper process to handle the blocking
pam_authenticate call and proxy events back to the parent.  The slave
would then just connect to signals like "user-verified",
"user-verification-error", "session-started", "session-exited", etc to
manage when a user successfully or unsuccessfully logs in.  Some other
important signals would be "info" (to put up a message in the
greeter), "info-query" (to ask the user for a username), and
"secret-info-query" (to ask the user for a password).

By delegating all the work to a separate process we can get rid of
some of the hacks in the code that result from pam modules running in
the same address space as the slave (such as closing and reopening
syslog after every pam call because some modules open syslog
themselves, resetting group lists, resetting process limits, etc).
Part of the handshake toward opening a new session is the pam_setcred
call which can do unforseen things to the process depending on what
pam modules are being used.

I've put the rough ground work for the above up at
http://people.redhat.com/rstrode/session.h and
http://people.redhat.com/rstrode/session.c.  It requires an event loop
to work, which will take some reworking of slave.c, and bits of
session.c should be refactored.  If
the approach sounds reasonable to you, though, I'd like to work on
that in a separate cvs branch and then eventually merge it back in to
HEAD.

I've also attached one last patch (move-default-message.patch) which
moves the "Please enter your username" default message to the greeters
instead of verify-pam.  The pam module I'm using for the smartcard
work sets a non default pam message and the graphical greeter ends up
with something like:

Please enter your username
Please insert smart card or enter your username

which is clearly wrong.  By moving the default message to the greeter
it's easier to only show it when the pam module hasn't set a message.

--Ray
diff -u -p -r1.278 gdmlogin.c
--- gui/gdmlogin.c	31 May 2006 09:24:08 -0000	1.278
+++ gui/gdmlogin.c	7 Jul 2006 19:01:46 -0000
@@ -179,6 +179,8 @@ static void back_prog_launch_after_timeo
 static void back_prog_run (void);
 static void back_prog_stop (void);
 
+static void process_operation (guchar op_code, const gchar *args);
+
 /* 
  * This function is called when the background program exits.
  * It will add a timer to restart the program after the
@@ -1607,13 +1609,8 @@ static gboolean
 gdm_login_ctrl_handler (GIOChannel *source, GIOCondition cond, gint fd)
 {
     gchar buf[PIPE_SIZE];
+    gchar *p;
     gsize len;
-    char *tmp;
-    gint i, x, y;
-    GtkWidget *dlg;
-    static gboolean replace_msg = TRUE;
-    static gboolean messages_to_give = FALSE;
-    gboolean greeter_probably_login_prompt = FALSE;
 
     /* If this is not incoming i/o then return */
     if (cond != G_IO_IN) 
@@ -1627,23 +1624,42 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	    return (TRUE);
     } while (buf[0] && buf[0] != STX);
 
+    memset (buf, '\0', sizeof (buf));
+    if (g_io_channel_read_chars (source, buf, sizeof (buf) - 1, &len, NULL) !=
+	G_IO_STATUS_NORMAL)
+      return TRUE;
+
+    p = memchr (buf, STX, len);
+
+    if (p != NULL) {
+      len = p - buf;
+      g_io_channel_seek_position (source, -(sizeof (buf) - len), G_SEEK_CUR, NULL);
+      memset (buf + len, '\0', sizeof (buf) - len);
+    }
+ 
+    process_operation ((guchar) buf[0], buf + 1);
 
-    /* Read opcode */
-    g_io_channel_read_chars (source, buf, 1, &len, NULL);
+    return TRUE;
+}
 
-    /* If opcode couldn't be read */
-    if (len != 1)
-	return (TRUE);
+static void
+process_operation (guchar       op_code,
+		   const gchar *args)
+{
+    char *tmp;
+    gint i, x, y;
+    GtkWidget *dlg;
+    static gboolean replace_msg = TRUE;
+    static gboolean messages_to_give = FALSE;
+    gboolean greeter_probably_login_prompt = FALSE;
 
     /* Parse opcode */
-    switch (buf[0]) {
+    switch (op_code) {
     case GDM_SETLOGIN:
 	/* somebody is trying to fool us this is the user that
 	 * wants to log in, and well, we are the gullible kind */
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
 	g_free (curuser);
-	curuser = g_strdup (buf);
+	curuser = g_strdup (args);
 	if (browser_ok && gdm_config_get_bool (GDM_KEY_BROWSER))
 		browser_set_user (curuser);
 	printf ("%c\n", STX);
@@ -1651,10 +1667,7 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_PROMPT:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	if (tmp != NULL && strcmp (tmp, _("Username:")) == 0) {
 		gdm_common_login_sound (gdm_config_get_string (GDM_KEY_SOUND_PROGRAM),
 					gdm_config_get_string (GDM_KEY_SOUND_ON_LOGIN_FILE),
@@ -1692,10 +1705,7 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_NOECHO:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	if (tmp != NULL && strcmp (tmp, _("Password:")) == 0) {
 		gtk_label_set_text_with_mnemonic (GTK_LABEL (label), _("_Password:"));
 	} else {
@@ -1725,9 +1735,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_MSG:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-
 	/* the user has not yet seen messages */
 	messages_to_give = TRUE;
 
@@ -1736,23 +1743,23 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	 * whatnot */
 	if ( ! replace_msg &&
 	   /* empty message is for clearing */
-	   ! ve_string_empty (buf)) {
+	   ! ve_string_empty (args)) {
 		const char *oldtext;
 		oldtext = gtk_label_get_text (GTK_LABEL (msg));
 		if ( ! ve_string_empty (oldtext)) {
 			char *newtext;
-			tmp = ve_locale_to_utf8 (buf);
+			tmp = ve_locale_to_utf8 (args);
 			newtext = g_strdup_printf ("%s\n%s", oldtext, tmp);
 			g_free (tmp);
 			gtk_label_set_text (GTK_LABEL (msg), newtext);
 			g_free (newtext);
 		} else {
-			tmp = ve_locale_to_utf8 (buf);
+			tmp = ve_locale_to_utf8 (args);
 			gtk_label_set_text (GTK_LABEL (msg), tmp);
 			g_free (tmp);
 		}
 	} else {
-		tmp = ve_locale_to_utf8 (buf);
+		tmp = ve_locale_to_utf8 (args);
 		gtk_label_set_text (GTK_LABEL (msg), tmp);
 		g_free (tmp);
 	}
@@ -1767,14 +1774,12 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_ERRBOX:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	gtk_label_set_text (GTK_LABEL (err_box), tmp);
 	g_free (tmp);
 	if (err_box_clear_handler > 0)
 		g_source_remove (err_box_clear_handler);
-	if (ve_string_empty (buf))
+	if (ve_string_empty (args))
 		err_box_clear_handler = 0;
 	else
 		err_box_clear_handler = g_timeout_add (30000,
@@ -1787,13 +1792,10 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_ERRDLG:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-
 	/* we should be now fine for focusing new windows */
 	gdm_wm_focus_new_windows (TRUE);
 
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	dlg = ve_hig_dialog_new (NULL /* parent */,
 				 GTK_DIALOG_MODAL /* flags */,
 				 GTK_MESSAGE_ERROR,
@@ -1814,9 +1816,7 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_SESS:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	gdm_login_session_lookup (tmp);
 	g_free (tmp);
 	if (savesess == GTK_RESPONSE_CANCEL) {
@@ -1830,9 +1830,7 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_LANG:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-	gdm_login_language_lookup (buf);
+	gdm_login_language_lookup (args);
 	if (savelang == GTK_RESPONSE_CANCEL)
 	    printf ("%c%s\n", STX, GDM_RESPONSE_CANCEL);
 	else
@@ -1841,8 +1839,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_SSESS:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	if (savesess == GTK_RESPONSE_YES)
 	    printf ("%cY\n", STX);
 	else
@@ -1852,8 +1848,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_SLANG:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	if (savelang == GTK_RESPONSE_YES)
 	    printf ("%cY\n", STX);
 	else
@@ -1885,9 +1879,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	/* fall thru to reset */
 
     case GDM_RESETOK:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-
 	if (curuser != NULL) {
 	    g_free (curuser);
 	    curuser = NULL;
@@ -1900,7 +1891,7 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	if (browser_ok && gdm_config_get_bool (GDM_KEY_BROWSER))
 	    gtk_widget_set_sensitive (GTK_WIDGET (browser), TRUE);
 
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	gtk_label_set_text (GTK_LABEL (msg), tmp);
 	g_free (tmp);
 	gtk_widget_show (GTK_WIDGET (msg));
@@ -1912,8 +1903,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_QUIT:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	if (timed_handler_id != 0) {
 		g_source_remove (timed_handler_id);
 		timed_handler_id = 0;
@@ -1980,8 +1969,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_STARTTIMER:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	/*
 	 * Timed Login: Start Timer Loop
 	 */
@@ -1998,8 +1985,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_STOPTIMER:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	/*
 	 * Timed Login: Stop Timer Loop
 	 */
@@ -2013,7 +1998,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_DISABLE:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
 	if (clock_label != NULL)
 		GTK_WIDGET_SET_FLAGS (clock_label->parent, GTK_SENSITIVE);
 	gtk_widget_set_sensitive (login, FALSE);
@@ -2022,7 +2006,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_ENABLE:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
 	gtk_widget_set_sensitive (login, TRUE);
 	if (clock_label != NULL)
 		GTK_WIDGET_UNSET_FLAGS (clock_label->parent, GTK_SENSITIVE);
@@ -2034,14 +2017,11 @@ gdm_login_ctrl_handler (GIOChannel *sour
      * back a NULL response so that the daemon quits sending them */
     case GDM_NEEDPIC:
     case GDM_READPIC:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
 	printf ("%c\n", STX);
 	fflush (stdout);
 	break;
 
     case GDM_NOFOCUS:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	gdm_wm_no_login_focus_push ();
 	
 	printf ("%c\n", STX);
@@ -2049,8 +2029,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_FOCUS:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	gdm_wm_no_login_focus_pop ();
 	
 	printf ("%c\n", STX);
@@ -2058,8 +2036,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	break;
 
     case GDM_SAVEDIE:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	/* Set busy cursor */
 	gdm_common_setup_cursor (GDK_WATCH);
 
@@ -2071,8 +2047,6 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	_exit (EXIT_SUCCESS);
 
     case GDM_QUERY_CAPSLOCK:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	if (greeter_is_capslock_on ())
 	    printf ("%cY\n", STX);
 	else
@@ -2083,11 +2057,9 @@ gdm_login_ctrl_handler (GIOChannel *sour
 	
     default:
 	gdm_kill_thingies ();
-	gdm_common_fail_greeter ("Unexpected greeter command received: '%c'", buf[0]);
+	gdm_common_fail_greeter ("Unexpected greeter command received: '%c'", op_code);
 	break;
     }
-
-    return (TRUE);
 }
 
 
@@ -3595,7 +3567,10 @@ main (int argc, char *argv[])
     if G_LIKELY ( ! DOING_GDM_DEVELOPMENT) {
 	    ctrlch = g_io_channel_unix_new (STDIN_FILENO);
 	    g_io_channel_set_encoding (ctrlch, NULL, NULL);
-	    g_io_channel_set_buffered (ctrlch, FALSE);
+	    g_io_channel_set_buffered (ctrlch, TRUE);
+	    g_io_channel_set_flags (ctrlch, 
+				    g_io_channel_get_flags (ctrlch) | G_IO_FLAG_NONBLOCK,
+				    NULL);
 	    g_io_add_watch (ctrlch, 
 			    G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 			    (GIOFunc) gdm_login_ctrl_handler,
diff -u -p -r1.125 greeter.c
--- gui/greeter/greeter.c	9 Jun 2006 21:07:42 -0000	1.125
+++ gui/greeter/greeter.c	7 Jul 2006 19:01:47 -0000
@@ -81,6 +81,8 @@ extern gint gdm_timed_delay;
 
 gboolean greeter_probably_login_prompt = FALSE;
 
+static void process_operation (guchar opcode, const gchar *args);
+
 void
 greeter_ignore_buttons (gboolean val)
 {
@@ -124,52 +126,64 @@ greeter_ctrl_handler (GIOChannel *source
 		      gint fd)
 {
     gchar buf[PIPE_SIZE];
+    gchar *p;
     gsize len;
-    GtkWidget *dlg;
-    char *tmp;
-    char *session;
-    GreeterItemInfo *conversation_info;
-    static GnomeCanvasItem *disabled_cover = NULL;
-    gchar *language;
-    gchar *selected_user = NULL;
 
     /* If this is not incoming i/o then return */
     if (cond != G_IO_IN) 
       return TRUE;
 
-    /* Read random garbage from i/o channel until STX is found */
+    /* Read random garbage from i/o channel until first STX is found */
     do {
       g_io_channel_read_chars (source, buf, 1, &len, NULL);
       
       if (len != 1)
 	return TRUE;
-    }  while (buf[0] && buf[0] != STX);
+    } while (buf[0] && buf[0] != STX);
 
-    /* Read opcode */
-    g_io_channel_read_chars (source, buf, 1, &len, NULL);
-
-    /* If opcode couldn't be read */
-    if (len != 1)
+    memset (buf, '\0', sizeof (buf));
+    if (g_io_channel_read_chars (source, buf, sizeof (buf) - 1, &len, NULL) !=
+	G_IO_STATUS_NORMAL)
       return TRUE;
 
+    p = memchr (buf, STX, len);
+
+    if (p != NULL) {
+      len = p - buf;
+      g_io_channel_seek_position (source, -(sizeof (buf) - len), G_SEEK_CUR, NULL);
+      memset (buf + len, '\0', sizeof (buf) - len);
+    }
+      
+    process_operation ((guchar) buf[0], buf + 1);
+    return TRUE;
+}
+
+static void
+process_operation (guchar       op_code,
+		   const gchar *args)
+{
+    GtkWidget *dlg;
+    char *tmp;
+    char *session;
+    GreeterItemInfo *conversation_info;
+    static GnomeCanvasItem *disabled_cover = NULL;
+    gchar *language;
+    gchar *selected_user = NULL;
+
+
     /* Parse opcode */
-    switch (buf[0]) {
+    switch (op_code) {
     case GDM_SETLOGIN:
 	/* somebody is trying to fool us this is the user that
 	 * wants to log in, and well, we are the gullible kind */
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
 	
-	greeter_item_pam_set_user (buf);
+	greeter_item_pam_set_user (args);
 	printf ("%c\n", STX);
 	fflush (stdout);
 	break;
 
     case GDM_PROMPT:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	if (tmp != NULL && strcmp (tmp, _("Username:")) == 0) {
 		gdm_common_login_sound (gdm_config_get_string (GDM_KEY_SOUND_PROGRAM),
 					gdm_config_get_string (GDM_KEY_SOUND_ON_LOGIN_FILE),
@@ -190,9 +204,7 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_NOECHO:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 
 	if (tmp != NULL && strcmp (tmp, _("Password:")) == 0)
 		greeter_probably_login_prompt = FALSE;
@@ -204,9 +216,7 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_MSG:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	greeter_item_pam_message (tmp);
 	g_free (tmp);
 	printf ("%c\n", STX);
@@ -214,10 +224,7 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_ERRBOX:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	greeter_item_pam_error (tmp);
 	g_free (tmp);
 	
@@ -226,13 +233,10 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_ERRDLG:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL);
-	buf[len-1] = '\0';
-
 	/* we should be now fine for focusing new windows */
 	gdm_wm_focus_new_windows (TRUE);
 
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	dlg = ve_hig_dialog_new (NULL /* parent */,
 				 GTK_DIALOG_MODAL /* flags */,
 				 GTK_MESSAGE_ERROR,
@@ -253,10 +257,7 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_SESS:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-	buf[len-1] = '\0';
-
-	tmp = ve_locale_to_utf8 (buf);
+	tmp = ve_locale_to_utf8 (args);
 	session = greeter_session_lookup (tmp);
 	g_free (tmp);
 
@@ -272,9 +273,7 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_LANG:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-	buf[len-1] = '\0';
-	language = greeter_language_get_language (buf);
+	language = greeter_language_get_language (args);
 	if (greeter_language_get_save_language () == GTK_RESPONSE_CANCEL)
 	    printf ("%c%s\n", STX, GDM_RESPONSE_CANCEL);
 	else
@@ -284,8 +283,6 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_SSESS:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	if (greeter_save_session () == GTK_RESPONSE_YES)
 	  printf ("%cY\n", STX);
 	else
@@ -295,8 +292,6 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_SLANG:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	if (greeter_language_get_save_language () == GTK_RESPONSE_YES)
 	    printf ("%cY\n", STX);
 	else
@@ -309,14 +304,12 @@ greeter_ctrl_handler (GIOChannel *source
 	/* fall thru to reset */
 
     case GDM_RESETOK:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-	buf[len-1] = '\0';
 
 	conversation_info = greeter_lookup_id ("pam-conversation");
 	
 	if (conversation_info)
 	  {
-	    tmp = ve_locale_to_utf8 (buf);
+	    tmp = ve_locale_to_utf8 (args);
 	    g_object_set (G_OBJECT (conversation_info->item),
 			  "text", tmp,
 			  NULL);
@@ -331,8 +324,6 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_QUIT:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	greeter_item_timed_stop ();
 
 	if (require_quarter) {
@@ -368,8 +359,6 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_STARTTIMER:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	greeter_item_timed_start ();
 	
 	printf ("%c\n", STX);
@@ -377,8 +366,6 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_STOPTIMER:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	greeter_item_timed_stop ();
 
 	printf ("%c\n", STX);
@@ -386,7 +373,6 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_DISABLE:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
 	gtk_widget_set_sensitive (window, FALSE);
 
 	if (disabled_cover == NULL)
@@ -407,7 +393,6 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_ENABLE:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
 	gtk_widget_set_sensitive (window, TRUE);
 
 	if (disabled_cover != NULL)
@@ -424,14 +409,11 @@ greeter_ctrl_handler (GIOChannel *source
      * back a NULL response so that the daemon quits sending them */
     case GDM_NEEDPIC:
     case GDM_READPIC:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
 	printf ("%c\n", STX);
 	fflush (stdout);
 	break;
 
     case GDM_NOFOCUS:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	gdm_wm_no_login_focus_push ();
 	
 	printf ("%c\n", STX);
@@ -439,8 +421,6 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_FOCUS:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	gdm_wm_no_login_focus_pop ();
 	
 	printf ("%c\n", STX);
@@ -448,8 +428,6 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 
     case GDM_SAVEDIE:
-	g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	/* Set busy cursor */
 	gdm_common_setup_cursor (GDK_WATCH);
 
@@ -460,8 +438,6 @@ greeter_ctrl_handler (GIOChannel *source
 	_exit (EXIT_SUCCESS);
 
     case GDM_QUERY_CAPSLOCK:
-        g_io_channel_read_chars (source, buf, PIPE_SIZE-1, &len, NULL); /* Empty */
-
 	if (greeter_is_capslock_on ())
 	    printf ("%cY\n", STX);
 	else
@@ -471,11 +447,9 @@ greeter_ctrl_handler (GIOChannel *source
 	break;
 	
     default:
-	gdm_common_fail_greeter ("Unexpected greeter command received: '%c'", buf[0]);
+	gdm_common_fail_greeter ("Unexpected greeter command received: '%c'", op_code);
 	break;
     }
-
-    return (TRUE);
 }
 
 static gboolean
@@ -1150,7 +1124,10 @@ main (int argc, char *argv[])
   if G_LIKELY (! DOING_GDM_DEVELOPMENT) {
     ctrlch = g_io_channel_unix_new (STDIN_FILENO);
     g_io_channel_set_encoding (ctrlch, NULL, NULL);
-    g_io_channel_set_buffered (ctrlch, FALSE);
+    g_io_channel_set_buffered (ctrlch, TRUE);
+    g_io_channel_set_flags (ctrlch, 
+			    g_io_channel_get_flags (ctrlch) | G_IO_FLAG_NONBLOCK,
+			    NULL);
     g_io_add_watch (ctrlch, 
 		    G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 		    (GIOFunc) greeter_ctrl_handler,
--- ./daemon/verify-pam.c.move-default-message	2006-07-07 15:20:40.000000000 +0200
+++ ./daemon/verify-pam.c	2006-07-07 15:21:28.000000000 +0200
@@ -517,12 +517,6 @@
 			       then I can afford. */
 			    s = g_strdup (selected_user);
 		    } else {
-			    /* this is an evil hack, but really there is no way we'll
-			    know this is a username prompt.  However we SHOULD NOT
-			    rely on this working.  The pam modules can set their
-			    prompt to whatever they wish to */
-			    gdm_slave_greeter_ctl_no_ret
-				    (GDM_MSG, _("Please enter your username"));
 			    s = gdm_slave_greeter_ctl (GDM_PROMPT, m);
 			    /* this will clear the message */
 			    gdm_slave_greeter_ctl_no_ret (GDM_MSG, "");
--- ./daemon/verify-shadow.c.move-default-message	2006-07-07 15:21:04.000000000 +0200
+++ ./daemon/verify-shadow.c	2006-07-07 15:22:10.000000000 +0200
@@ -114,7 +114,6 @@
 authenticate_again:
 	    /* Ask for the user's login */
 	    gdm_verify_select_user (NULL);
-	    gdm_slave_greeter_ctl_no_ret (GDM_MSG, _("Please enter your username"));
 	    login = gdm_slave_greeter_ctl (GDM_PROMPT, _("Username:"));
 	    if (login == NULL ||
 		gdm_slave_greeter_check_interruption ()) {
--- ./daemon/verify-crypt.c.move-default-message	2006-07-07 15:20:48.000000000 +0200
+++ ./daemon/verify-crypt.c	2006-07-07 15:22:01.000000000 +0200
@@ -115,7 +115,6 @@
 authenticate_again:
 	    /* Ask for the user's login */
 	    gdm_verify_select_user (NULL);
-	    gdm_slave_greeter_ctl_no_ret (GDM_MSG, _("Please enter your username"));
 	    login = gdm_slave_greeter_ctl (GDM_PROMPT, _("Username:"));
 	    if (login == NULL ||
 		gdm_slave_greeter_check_interruption ()) {
--- ./gui/gdmlogin.c.move-default-message	2006-07-07 15:12:01.000000000 +0200
+++ ./gui/gdmlogin.c	2006-07-07 15:28:34.000000000 +0200
@@ -163,6 +163,7 @@
 extern const gchar *current_session;
 extern gboolean session_dir_whacked_out;
 extern gint gdm_timed_delay;
+static gboolean using_fallback_message = FALSE;
 
 static void login_window_resize (gboolean force);
 
@@ -1673,10 +1674,21 @@
 					gdm_config_get_string (GDM_KEY_SOUND_ON_LOGIN_FILE),
 					gdm_config_get_bool   (GDM_KEY_SOUND_ON_LOGIN));
 		gtk_label_set_text_with_mnemonic (GTK_LABEL (label), _("_Username:"));
+
+		if (ve_string_empty (gtk_label_get_text (GTK_LABEL (msg)))) {
+			gtk_label_set_text (GTK_LABEL (msg),
+					    _("Please enter your username"));
+			using_fallback_message = TRUE;
+		}
 		greeter_probably_login_prompt = TRUE;
 	} else {
 		if (tmp != NULL)
 			gtk_label_set_text (GTK_LABEL (label), tmp);
+
+		if (using_fallback_message) {
+			gtk_label_set_text (GTK_LABEL (msg), "");
+			using_fallback_message = FALSE;
+		}
 		greeter_probably_login_prompt = FALSE;
 	}
 	g_free (tmp);
@@ -1764,6 +1776,7 @@
 		g_free (tmp);
 	}
 	replace_msg = FALSE;
+	using_fallback_message = FALSE;
 
 	gtk_widget_show (GTK_WIDGET (msg));
 	printf ("%c\n", STX);
--- ./gui/greeter/greeter_item_pam.c.move-default-message	2006-07-07 15:11:37.000000000 +0200
+++ ./gui/greeter/greeter_item_pam.c	2006-07-07 15:12:16.000000000 +0200
@@ -46,6 +46,7 @@
 gboolean require_quarter = FALSE;
 
 extern gboolean greeter_probably_login_prompt;
+static gboolean using_fallback_message = FALSE;
 
 static gboolean
 greeter_item_pam_error_set (gboolean display)
@@ -230,13 +231,35 @@
 			 int         entry_len,
 			 gboolean    entry_visible)
 {
+  GreeterItemInfo *message_info;
   GreeterItemInfo *conversation_info;
   GreeterItemInfo *entry_info;
   GtkWidget *entry;
 
+  message_info = greeter_lookup_id ("pam-message");
   conversation_info = greeter_lookup_id ("pam-prompt");
   entry_info = greeter_lookup_id ("user-pw-entry");
 
+  if (strcmp (message, _("Username:")) == 0 && message_info)
+    {
+      gchar *text;
+      text = NULL;
+      g_object_get (G_OBJECT (message_info->item),
+                    "text", &text,
+                    NULL);
+      if (ve_string_empty (text))
+        {
+          set_text (message_info, _("Please enter your username"));
+          using_fallback_message = TRUE;
+        }
+      g_free (text);
+    } 
+  else if (using_fallback_message)
+    {
+      set_text (message_info, "");
+      using_fallback_message = FALSE;
+    }
+
   if (conversation_info)
     {
       set_text (conversation_info, message);
@@ -276,6 +299,7 @@
        * we try to collect them until the next prompt or reset or
        * whatnot */
       if ( ! replace_msg &&
+	   ! using_fallback_message &&
 	   /* empty message is for clearing */
 	   ! ve_string_empty (message))
 	{
@@ -295,6 +319,7 @@
         set_text (message_info, message);
     }
   replace_msg = FALSE;
+  using_fallback_message = FALSE;
 }
 
 
--- daemon/gdm.h.reset-pam	2006-07-07 15:11:37.000000000 +0200
+++ daemon/gdm.h	2006-07-07 15:12:37.000000000 +0200
@@ -710,6 +710,9 @@
 /* Start a new standard X flexible server */
 #define GDM_SOP_FLEXI_XSERVER "FLEXI_XSERVER" /* no arguments */
 
+/* Reset any in progress authentication conversations */
+#define GDM_SOP_CANCEL_LOGIN_REQUESTS "CANCEL_LOGIN_REQUESTS" /* no arguments */
+
 /* Notification protocol */
 /* keys */
 #define GDM_NOTIFY_ALLOW_REMOTE_ROOT "AllowRemoteRoot" /* <true/false as int> */
@@ -736,6 +739,7 @@
 #define GDM_NOTIFY_SOFT_RESTART_SERVERS "SOFT_RESTART_SERVERS"
 #define GDM_NOTIFY_GO "GO"
 #define GDM_NOTIFY_TWIDDLE_POINTER "TWIDDLE_POINTER"
+#define GDM_NOTIFY_RESET "RESET"
 
 /* Ack for a slave message */
 /* Note that an extra response can follow an 'ack' */
--- daemon/slave.c.reset-pam	2006-07-07 15:11:37.000000000 +0200
+++ daemon/slave.c	2006-07-07 15:12:37.000000000 +0200
@@ -128,6 +128,12 @@
 static int greeter_fd_out = -1;
 static int greeter_fd_in = -1;
 
+/* a dup of the other side of greeter_fd_in so that
+ * the slave can talk to itself from its sig handler
+ * using the greeter ipc mechanism
+ */
+static int slave_fd_out = -1;
+
 #ifdef HAVE_TSOL
 static gboolean have_suntsol_extension = FALSE;
 #endif
@@ -618,7 +624,7 @@
 }
 
 static void
-whack_greeter_fds (void)
+whack_greeter_and_slave_fds (void)
 {
 	if (greeter_fd_out > 0)
 		VE_IGNORE_EINTR (close (greeter_fd_out));
@@ -626,6 +632,9 @@
 	if (greeter_fd_in > 0)
 		VE_IGNORE_EINTR (close (greeter_fd_in));
 	greeter_fd_in = -1;
+	if (slave_fd_out > 0)
+		VE_IGNORE_EINTR (close (slave_fd_out));
+	slave_fd_out = -1;
 }
 
 static void
@@ -1076,7 +1085,7 @@
 
 	d->greetpid = 0;
 
-	whack_greeter_fds ();
+	whack_greeter_and_slave_fds ();
 
 	gdm_slave_send_num (GDM_SOP_GREETPID, 0);
 
@@ -1842,7 +1851,7 @@
 
 		d->greetpid = 0;
 
-		whack_greeter_fds ();
+		whack_greeter_and_slave_fds ();
 
 		gdm_slave_send_num (GDM_SOP_GREETPID, 0);
 	}
@@ -2075,6 +2084,12 @@
 			break;
 		}
 
+		if (do_cancel) {
+			gdm_debug ("canceling...");
+			gdm_slave_greeter_ctl_no_ret (GDM_RESETOK, "");
+			continue;
+		}
+
 		if (login == NULL) {
 			char *failuresound = gdm_get_value_string (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE);
 
@@ -2673,9 +2688,9 @@
 	
     default:
 	VE_IGNORE_EINTR (close (pipe1[0]));
-	VE_IGNORE_EINTR (close (pipe2[1]));
+	whack_greeter_and_slave_fds ();
 
-	whack_greeter_fds ();
+	slave_fd_out = pipe2[1];
 
 	greeter_fd_out = pipe1[1];
 	greeter_fd_in = pipe2[0];
@@ -4663,7 +4678,7 @@
 
 			greet = FALSE;
 			d->greetpid = 0;
-			whack_greeter_fds ();
+			whack_greeter_and_slave_fds ();
 			gdm_slave_send_num (GDM_SOP_GREETPID, 0);
 
 			do_restart_greeter = TRUE;
@@ -4675,7 +4690,7 @@
 			continue;
 		}
 
-		whack_greeter_fds ();
+		whack_greeter_and_slave_fds ();
 
 		/* if greet is TRUE, then the greeter died outside of our
 		 * control really, so clean up and die, something is wrong
@@ -4818,6 +4833,11 @@
 				gdm_wait_for_go = FALSE;
 			} else if (strcmp (&s[1], GDM_NOTIFY_TWIDDLE_POINTER) == 0) {
 				gdm_twiddle_pointer (d);
+			} else if (strcmp (&s[1], GDM_NOTIFY_RESET) == 0) {
+				if (!d->logged_in) {
+					gdm_fdprintf (slave_fd_out, "%c%c%c\n", 
+						      STX, BEL, GDM_INTERRUPT_CANCEL);
+				}
 			}
 		}
 	}
--- daemon/gdm.c.reset-pam	2006-07-07 15:11:37.000000000 +0200
+++ daemon/gdm.c	2006-07-07 15:12:37.000000000 +0200
@@ -2345,6 +2345,14 @@
 				     TRUE /* handled */,
 				     FALSE /* chooser */,
 				     NULL, 0, NULL, NULL);
+	} else if (strcmp (msg, GDM_SOP_CANCEL_LOGIN_REQUESTS) == 0) {
+		GSList *li;
+		for (li = displays; li != NULL; li = li->next) {
+			GdmDisplay *d = li->data;
+			if (!d->logged_in) {
+				send_slave_command (d, GDM_NOTIFY_RESET);
+			}
+		}
 	}
 }

 
--- gui/greeter/greeter.c.reset-pam	2006-07-07 15:12:01.000000000 +0200
+++ gui/greeter/greeter.c	2006-07-07 15:14:33.000000000 +0200
@@ -165,7 +165,6 @@
     GtkWidget *dlg;
     char *tmp;
     char *session;
-    GreeterItemInfo *conversation_info;
     static GnomeCanvasItem *disabled_cover = NULL;
     gchar *language;
     gchar *selected_user = NULL;
@@ -304,18 +303,11 @@
 	/* fall thru to reset */
 
     case GDM_RESETOK:
-
-	conversation_info = greeter_lookup_id ("pam-conversation");
-	
-	if (conversation_info)
-	  {
-	    tmp = ve_locale_to_utf8 (args);
-	    g_object_set (G_OBJECT (conversation_info->item),
-			  "text", tmp,
-			  NULL);
-	    g_free (tmp);
-	  }
-
+	greeter_item_ulist_unset_selected_user ();
+	greeter_item_pam_prompt ("", PW_ENTRY_SIZE, TRUE);
+	greeter_item_pam_message ("");
+	greeter_item_pam_error ("");
+ 
 	printf ("%c\n", STX);
 	fflush (stdout);
 	greeter_ignore_buttons (FALSE);

--- ./gui/gdmlogin.c.move-default-message	2006-07-07 15:12:01.000000000 +0200
+++ ./gui/gdmlogin.c	2006-07-07 15:28:34.000000000 +0200
@@ -1891,9 +1904,7 @@
 	if (browser_ok && gdm_config_get_bool (GDM_KEY_BROWSER))
 	    gtk_widget_set_sensitive (GTK_WIDGET (browser), TRUE);
 
-	tmp = ve_locale_to_utf8 (args);
-	gtk_label_set_text (GTK_LABEL (msg), tmp);
-	g_free (tmp);
+	gtk_label_set_text (GTK_LABEL (msg), "");
 	gtk_widget_show (GTK_WIDGET (msg));
 
 	printf ("%c\n", STX);




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]