6417168 xscreensaver loops while trying to unlock a session for a user whose password was expired nv_43
authorMahmood Ali <Mahmood.Ali@Sun.COM>
Fri, 09 Jun 2006 18:09:17 -0700
changeset 34 e0b6b789b46a
parent 33 36c599198505
child 35 b52017b8441e
6417168 xscreensaver loops while trying to unlock a session for a user whose password was expired 5015296 xscreensaver doesn't audit
open-src/app/xscreensaver/Makefile
open-src/app/xscreensaver/pam_audit.patch
open-src/app/xscreensaver/sun-src/driver/lock-Gtk.c
--- a/open-src/app/xscreensaver/Makefile	Mon Jun 12 18:04:06 2006 -0700
+++ b/open-src/app/xscreensaver/Makefile	Fri Jun 09 18:09:17 2006 -0700
@@ -30,7 +30,7 @@
 # or other dealings in this Software without prior written authorization
 # of the copyright holder.
 #
-# @(#)Makefile	1.62	06/06/09
+# @(#)Makefile	1.63	06/06/12
 #
 
 PWD:sh=pwd
@@ -71,7 +71,8 @@
 	blurb.patch \
 	accessibility.patch \
 	misc.patch \
-	trusted.patch
+	trusted.patch \
+        pam_audit.patch
 
 # Directory created by unpacking source
 SOURCE_DIR=$(BUILD_DIR)/xscreensaver-$(XSCREENSAVER_VERS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/app/xscreensaver/pam_audit.patch	Fri Jun 09 18:09:17 2006 -0700
@@ -0,0 +1,670 @@
+
+Fixes for bugs:
+5015296, P1, gnome/screensaver - xscreensaver doesn't audit
+6417168, P3, gnome/screensaver - xcreensaver loops while trying to unlock a session for a user whose password was expired
+
+diff -ur driver/Makefile.in driver/Makefile.in
+--- driver/Makefile.in	Wed Jun  7 18:28:35 2006
++++ driver/Makefile.in	Wed Jun  7 19:19:46 2006
+@@ -202,7 +202,7 @@
+ SAVER_LIBS	= $(LIBS) $(X_LIBS) $(XMU_LIBS) @SAVER_LIBS@ \
+ 		  $(XDPMS_LIBS) $(GL_LIBS) $(X_PRE_LIBS) \
+ 		  -lXt -lX11 -lXext -lXi $(X_EXTRA_LIBS) \
+-		  $(PASSWD_LIBS)
++		  -lbsm $(PASSWD_LIBS)
+ 
+ CMD_LIBS	= $(LIBS) $(X_LIBS) \
+ 		  $(X_PRE_LIBS) -lX11 -lXext $(X_EXTRA_LIBS)
+diff -ur driver/demo-Gtk.c driver/demo-Gtk.c
+--- driver/demo-Gtk.c	Wed Jun  7 18:28:35 2006
++++ driver/demo-Gtk.c	Wed Jun  7 19:19:46 2006
+@@ -541,7 +541,7 @@
+   if (getuid() == 0) 
+    {
+       char buf [255];
+-      strcpy (buf, _("Cant run hacks if logged in as root!"));
++      strcpy (buf, _("Can not run hacks if logged in as root!"));
+       warning_dialog (s->toplevel_widget, buf, False, 100);
+      return; 
+    }
+@@ -569,7 +569,7 @@
+   if (getuid() == 0) 
+    {
+       char buf [255];
+-      strcpy (buf, _("Cant run hacks if logged in as root!"));
++      strcpy (buf, _("Can not run hacks if logged in as root!"));
+       warning_dialog (s->toplevel_widget, buf, False, 100);
+      return; 
+    }
+diff -ur driver/passwd-pam.c driver/passwd-pam.c
+--- driver/passwd-pam.c	Wed Jun  7 18:28:35 2006
++++ driver/passwd-pam.c	Wed Jun  7 19:19:46 2006
+@@ -44,12 +44,14 @@
+ #ifdef HAVE_UNISTD_H
+ # include <unistd.h>
+ #endif
++ 
++#ifdef sun
++#include <deflt.h>
++#include <bsm/adt.h>
++#include <bsm/adt_event.h>
++#endif
+ 
+-# ifdef sun
+-#  include <deflt.h>
+-# endif
+ 
+-
+ /*extern char *blurb(void);*/
+ 
+ 
+@@ -97,12 +99,14 @@
+ #define True  1
+ #define False 0
+ 
+-
+ Bool we_have_pam;
+ 
+ #undef countof
+ #define countof(x) (sizeof((x))/sizeof(*(x)))
+ 
++static struct pam_response *reply = 0; /*making it global so we can free it */
++static int replies = 0;
++
+ /* Some time between Red Hat 4.2 and 7.0, the words were transposed 
+    in the various PAM_x_CRED macro names.  Yay!
+  */
+@@ -112,8 +116,8 @@
+ 
+ int pam_conversation (int nmsgs,
+                       struct pam_message **msg,
+-                             struct pam_response **resp,
+-                             void *closure);
++                      struct pam_response **resp,
++                      void *closure);
+ 
+ struct pam_closure {
+   const char *user;
+@@ -199,13 +203,154 @@
+  */
+ static void *suns_pam_implementation_blows = 0;
+ 
++#ifdef  sun
++#include <syslog.h>
++#include <bsm/adt.h>
++#include <bsm/adt_event.h>
+ 
++static Bool audit_flag_global = True;
++
++/*
++ * audit_lock - audit entry to screenlock
++ *
++ *      Entry   Process running with appropriate privilege to generate
++ *                      audit records and real uid of the user.
++ *
++ *      Exit    ADT_screenlock audit record written.
++ */
++void
++audit_lock(void)
++{
++        adt_session_data_t      *ah;  	/* audit session handle */
++        adt_event_data_t        *event;	/* audit event handle */
++
++      	/* Audit start of screen lock -- equivalent to logout ;-) */
++        if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
++
++                syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
++                return;
++        }
++        if ((event = adt_alloc_event(ah, ADT_screenlock)) == NULL) {
++
++                syslog(LOG_AUTH | LOG_ALERT,
++                    "adt_alloc_event(ADT_screenlock): %m");
++        } else {
++                if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
++
++                        syslog(LOG_AUTH | LOG_ALERT,
++                            "adt_put_event(ADT_screenlock): %m");
++                }
++                adt_free_event(event);
++        }
++        (void) adt_end_session(ah);
++}
++
++/*
++ * audit_unlock - audit screen unlock
++ *
++ *      Entry   Process running with appropriate privilege to generate
++ *                      audit records and real uid of the user.
++ *              pam_status = PAM error code; reason for failure.
++ *
++ *      Exit    ADT_screenunlock audit record written.
++ */
++static void
++audit_unlock(int pam_status)
++{
++        adt_session_data_t      *ah;  	/* audit session handle */
++        adt_event_data_t        *event;/* audit event handle */
++
++        if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
++
++                syslog(LOG_AUTH | LOG_ALERT,
++                    "adt_start_session(ADT_screenunlock): %m");
++                return;
++        }
++        if ((event = adt_alloc_event(ah, ADT_screenunlock)) == NULL) {
++
++                syslog(LOG_AUTH | LOG_ALERT,
++                    "adt_alloc_event(ADT_screenunlock): %m");
++        } else {
++                if (adt_put_event(event,
++                    pam_status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAILURE,
++                    pam_status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAIL_PAM +
++                    pam_status) != 0) {
++
++                        syslog(LOG_AUTH | LOG_ALERT,
++                            "adt_put_event(ADT_screenunlock(%s): %m",
++                            pam_strerror(NULL, pam_status));
++                }
++                adt_free_event(event);
++        }
++        (void) adt_end_session(ah);
++}
++
++/*
++ * audit_passwd - audit password change
++ *      Entry   Process running with appropriate privilege to generate
++ *                      audit records and real uid of the user.
++ *              pam_status = PAM error code; reason for failure.
++ *
++ *      Exit    ADT_passwd audit record written.
++ */
++static void
++audit_passwd(int pam_status)
++{
++        adt_session_data_t      *ah;		/* audit session handle */
++        adt_event_data_t        *event;	/* audit event handle */
++
++        if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
++
++                syslog(LOG_AUTH | LOG_ALERT,
++                    "adt_start_session(ADT_passwd): %m");
++                return;
++        }
++        if ((event = adt_alloc_event(ah, ADT_passwd)) == NULL) {
++
++                syslog(LOG_AUTH | LOG_ALERT,
++                    "adt_alloc_event(ADT_passwd): %m");
++        } else {
++                if (adt_put_event(event,
++                    pam_status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAILURE,
++                    pam_status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAIL_PAM +
++                    pam_status) != 0) {
++
++                        syslog(LOG_AUTH | LOG_ALERT,
++                            "adt_put_event(ADT_passwd(%s): %m",
++                            pam_strerror(NULL, pam_status));
++                }
++                adt_free_event(event);
++        }
++        (void) adt_end_session(ah);
++}
++#endif /* sun */
++
++void free_pam_response_struct ()
++{
++ int i;
++ struct pam_response *pam_resp = reply;
++
++  if (!replies) 
++    return;
++
++   for (i = 0; i < replies; i++,pam_resp++)
++     if (pam_resp->resp)
++      {
++       free (pam_resp->resp);
++       pam_resp->resp = NULL;
++     } 
++  if (pam_resp)
++    free (pam_resp);
++  pam_resp = NULL;
++  replies = 0;
++}
++
+ /* This can be called at any time, and says whether the typed password
+    belongs to either the logged in user (real uid, not effective); or
+    to root.
+  */
+ Bool
+-pam_passwd_valid_p ()
++pam_passwd_valid_p (void)
+ {
+   const char *service;
+   uid_t euid;
+@@ -266,6 +411,15 @@
+     fprintf (stderr, "%s: pam_start (\"%s\", \"%s\", ...) ==> %d (%s)\n",
+              blurb(), service, c.user,
+              status, PAM_STRERROR (pamh, status));
++
++/* We call pam_passwd_valid_p() everytime we lock screen, 
++ * so calling audit here is fine.
++ */
++#ifdef sun
++ if (audit_flag_global) /* We want one audit lock log per lock */
++  audit_lock();
++#endif /**sun*/
++
+   if (status != PAM_SUCCESS) 
+    {
+     we_have_pam = False;
+@@ -296,32 +450,6 @@
+         }
+ #endif
+ 
+-  /* #### We should set PAM_TTY to the display we're using, but we
+-     don't have that handy from here.  So set it to :0.0, which is a
+-     good guess (and has the bonus of counting as a "secure tty" as
+-     far as PAM is concerned...)
+-   */
+-
+-/* From the pam trace and log file, it is found out that the 
+-   Sun pam modules can drive itself.
+-*/
+-
+-#if 0
+-
+-  {
+-    char *tty,*displayname;
+-    if ((displayname = getenv ("DISPLAY")) != NULL)
+-        tty = strdup(displayname);
+-    else
+-   	tty = strdup (":0.0");
+-    status = pam_set_item (pamh, PAM_TTY, tty);
+-    if (verbose_p)
+-      fprintf (stderr, "%s:   pam_set_item (p, PAM_TTY, \"%s\") ==> %d (%s)\n",
+-               blurb(), tty, status, PAM_STRERROR(pamh, status));
+-    free (tty);
+-  }
+-#endif
+-
+   /* Try to authenticate as the current user.
+      We must turn off our SIGCHLD handler for the duration of the call to
+      pam_authenticate(), because in some cases, the underlying PAM code
+@@ -344,15 +472,18 @@
+ 
+   PAM_NO_DELAY(pamh);
+ 
+-/************* no need
+-  fprintf(stderr,"before calling pam_authenticate passwd_string: %s\n",si->pw_data->passwd_string);
+-  if (si->pw_data->passwd_string)
+-****************************/
+    {
+ 
+-  block_sigchld();
++     block_sigchld();
+      pam_auth_status = pam_authenticate (pamh, pam_flags);
+-  unblock_sigchld();
++     unblock_sigchld();
++
++#ifdef sun
++        audit_unlock(pam_auth_status);
++        if (pam_auth_status == PAM_SUCCESS) audit_flag_global = True;
++        else audit_flag_global = False;
++#endif /*sun*/
++
+      /* Send status message to unlock dialog ***/
+      if (pam_auth_status == PAM_SUCCESS)
+       {
+@@ -375,7 +506,7 @@
+ 
+      /* PAM_SUCCESS defined to be 0 in /usr/include/security/pam_appl.h */
+      si->pw_data->state = (pam_auth_status == PAM_SUCCESS ? pw_ok : pw_fail);
+-  if (verbose_p)
++     if (verbose_p)
+         fprintf(stderr,"after calling pam_authenticate status is:%d state is:%d\n",
+ 			pam_auth_status,si->pw_data->state);
+ 
+@@ -390,23 +521,8 @@
+     {
+         /* perform PAM account validation procedures for login user only */
+ 	acct_rc   = pam_acct_mgmt(pamh, pam_flags);
++      /*free_pam_response_struct ();**/
+ 
+-        /******************************************************************
+-           ignore other cases for the time being 
+-           PAM_USER_UNKNOWN, PAM_AUTH_ERR, PAM_ACCT_EXPIRED
+-           (password mgn service module)
+-           same as pam_setcred(), focus on auth. service module only
+-         *****************************************************************/
+-
+-	if (acct_rc   == PAM_NEW_AUTHTOK_REQD) {
+-		do {
+-			chauth_rc  = pam_chauthtok(pamh, 0);
+-                    } while (chauth_rc == PAM_AUTHTOK_ERR ||
+-                      chauth_rc  == PAM_TRY_AGAIN);
+-      		if (verbose_p)
+-        	  fprintf (stderr, "%s:   pam_chauthtok (...) ==> %d (%s)\n",
+-                 blurb(), chauth_rc, PAM_STRERROR(pamh, chauth_rc));
+-	}
+         if (verbose_p)
+         fprintf (stderr, "%s:   pam_acct_mgmt (...) ==> %d (%s)\n",
+                  blurb(), acct_rc, PAM_STRERROR(pamh, acct_rc));
+@@ -427,13 +543,49 @@
+         write_to_child (si, tmp_buf);
+         if (verbose_p)
+           sleep (1);
+-      }
+ 
++   /* Only in failure of pam_acct_mgmt case we call audit */
++#ifdef sun
++        audit_unlock(acct_rc);
++#endif /*sun*/
++
++     }/* end of else */
++
++     if (acct_rc   == PAM_NEW_AUTHTOK_REQD) 
++      {
++        for (int i=0; i<3; i++) 
++         {
++          chauth_rc  = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
++          if (chauth_rc == PAM_AUTHTOK_ERR ||
++              chauth_rc  == PAM_TRY_AGAIN ) 
++           {
++             i = 0; /* Reset num tries we need to do to change expired passwd */
++             si->pw_data->state = pw_read; 
++           }
++          else break; /* get out of the loop */
++         }/*for*/ 
++ 
++       if (verbose_p)
++            fprintf (stderr, "%s:   pam_chauthtok (...) ==> %d (%s)\n",
++                 blurb(), chauth_rc, PAM_STRERROR(pamh, chauth_rc));
++
++#ifdef  sun
++          audit_passwd(chauth_rc);
++#endif /* sun */
++
++        if (chauth_rc != PAM_SUCCESS) 
++         {
++          pam_auth_status = chauth_rc;
++          goto DONE;
++         }
++	}
++
+       /* Each time we successfully authenticate, refresh credentials,
+          for Kerberos/AFS/DCE/etc.  If this fails, just ignore that
+          failure and blunder along; it shouldn't matter.
+        */
+       setcred_rc = pam_setcred (pamh, PAM_REFRESH_CRED);
++
+       if (verbose_p)
+         fprintf (stderr, "%s:   pam_setcred (...) ==> %d (%s)\n",
+                  blurb(), setcred_rc , PAM_STRERROR(pamh, setcred_rc));
+@@ -454,6 +606,11 @@
+         write_to_child (si, tmp_buf);
+         if (verbose_p)
+           sleep (1);
++
++/* Only in failure of pam_setcred() case we call audit. */
++#ifdef sun
++        audit_unlock(setcred_rc);
++#endif /*sun*/
+       }
+ 
+       goto DONE;
+@@ -490,7 +647,7 @@
+         tmp_buf = strdup (_("Letting you in as ROOT!!"));
+         write_to_child (si, tmp_buf);
+         free (tmp_buf);
+-  if (verbose_p)
++        if (verbose_p)
+          sleep (1);
+       }
+ 
+@@ -506,10 +663,11 @@
+  DONE:
+   if (service) free((void *)service);
+   if (user) free (user);
++  if (reply) free (reply);
+   if (pamh)
+     {
+       int status2 = pam_end (pamh, pam_auth_status);
+-      pamh = 0;
++      pamh = NULL;
+       if (verbose_p)
+         fprintf (stderr, "%s: pam_end (...) ==> %d (%s)\n",
+                  blurb(), status2,
+@@ -520,7 +678,7 @@
+    {
+     if (verbose_p)
+       perror("Error pam could not revert euid to user running as euid root, locking may not work now\n");
+-}
++   }
+ 
+   if (verbose_p)
+      fprintf (stderr, "<--end of pam_authenticate() returning ok_to_unblank = %d\n",
+@@ -536,8 +694,8 @@
+ 
+   if (si->pw_data->passwd_string)
+    {
++    memset(si->pw_data->passwd_string, 0, strlen(si->pw_data->passwd_string));
+     free (si->pw_data->passwd_string); 
+-    si->pw_data->passwd_string = 0;
+    }
+ 
+   if(pam_auth_status == PAM_SUCCESS) 
+@@ -572,7 +730,7 @@
+ #ifndef S_ISDIR
+ # define S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
+ #endif
+-  
++
+   if (stat (dir, &st) == 0 && S_ISDIR(st.st_mode))
+     {
+       if (stat (file, &st) != 0)
+@@ -645,10 +803,10 @@
+                   struct pam_response **resp,
+                   void *closure)
+ {
+-  int replies = 0;
+-  struct pam_response *reply = 0;
++/*mali fix  struct pam_response *reply = 0; */
+   struct pam_closure *c = (struct pam_closure *) closure;
+   saver_info *si = global_si_kludge;
++  int conv_status = PAM_SUCCESS;
+ 
+   /* On SunOS 5.6, the `closure' argument always comes in as random garbage. */
+   c = (struct pam_closure *) suns_pam_implementation_blows;
+@@ -657,6 +815,7 @@
+      fprintf(stderr, "-->pam_conv() \n");
+ 
+   reply = (struct pam_response *) calloc (nmsgs, sizeof (*reply));
++
+   if (!reply) return PAM_CONV_ERR;
+ 	
+   for (replies = 0; replies < nmsgs; replies++)
+@@ -671,7 +830,6 @@
+            make_passwd_window (si);
+          }
+ 
+-/**fprintf(stderr, "top of switch %d\n", replies);**/
+       switch (msg[replies]->msg_style)
+         {
+         case PAM_PROMPT_ECHO_ON:
+@@ -681,8 +839,6 @@
+             fprintf (stderr, "%s:     PAM ECHO_OFF(\"%s\") ==> password\n",
+                      blurb(), msg[replies]->msg);
+ 
+-          /**fprintf(stderr, "PAM_ECHO_OFF/ECHO_ON nmsgs=%d\n",nmsgs);**/
+-
+              write_to_child (si, msg[replies]->msg);
+              if (c->verbose_p)
+               sleep (1); /* let user see these */
+@@ -691,9 +847,37 @@
+                 fprintf(stderr, "PAM_ECHO_OFF/ECHO_ON msg[replies]-> %s\n",
+ 					msg[replies]->msg);
+ 
++             /* For our hack to see if the user typed in root passwd to unlock. */
++             if (strcmp (c->user, "root") == 0)
++              {
++               if (c->verbose_p)
++                {
++                 write_to_child (si, "Checking if you typed root password");
++                 sleep (1);
++                }
++
++               if (si->pw_data->passwd_string) /* if passwd is still stored */
++                 reply[replies].resp = strdup (si->pw_data->passwd_string); /*freed by PAM*/
++               else
++                 reply[replies].resp = NULL; /* freed by PAM */
++   
++               break; /* To check if user has entered a root passwd, we dont want to prompt
++                       * user to enter the root passwd, we already have it so try that. */
++              }
++
+              si->pw_data->state = pw_read;
+-             while (!si->pw_data->got_windowid && si->pw_data->state == pw_read)
++
++             /* Wipe the old password, so we get prompted to enter new password. */
++             if (si->pw_data->passwd_string) 
+               {
++               memset(si->pw_data->passwd_string, 0, strlen(si->pw_data->passwd_string));
++               free (si->pw_data->passwd_string);
++               si->pw_data->passwd_string = NULL;
++              }
++
++             /***while (!si->pw_data->got_windowid && si->pw_data->state == pw_read)**/
++             while (si->pw_data->state == pw_read)
++              {
+                if (c->verbose_p)
+                  fprintf(stderr,"WAiting for window id from lock dialog\n");
+                handle_typeahead (si);
+@@ -702,13 +886,13 @@
+                  fprintf(stderr,"<---passwd_event_loop() state =%d\n",si->pw_data->state);
+               }
+ 
+-          reply[replies].resp_retcode = PAM_SUCCESS;
++             reply[replies].resp = NULL;  /* freed by PAM */
+ 
+-             /*Make sure user inputs a response..and dialog is not timiing out **/
++             /*Make sure user inputs a response..and dialog is not timing out **/
+              if (si->pw_data->state != pw_time && si->pw_data->passwd_string != NULL)
+               {
+                reply[replies].resp = strdup (si->pw_data->passwd_string);/*freed by PAM*/
+-          if (c->verbose_p)
++               if (c->verbose_p)
+                  fprintf(stderr, "in ECHO OFF and got a passwd..:%s\n",
+                                        si->pw_data->passwd_string);
+               }
+@@ -716,37 +900,37 @@
+               {
+                /* this shouldnt happen...perhaps sending null passwd to pam is 
+ 	        * best for now**/
+-               /* reply[replies].resp = 0;Dont send any resp*/ /* freed by PAM */
++               reply[replies].resp = NULL; /*Dont send any resp*/ /* freed by PAM */
+                /* Reset state to fail */
+                si->pw_data->state = pw_fail;
+ 
+                if (c->verbose_p)
+                 {
+-                  fprintf(stderr, "Dude sending null password to pam..\n");
+                   fprintf(stderr,"We didnt receive any input from user!!!\n");
+                 }
+               }
+           break;
+          }
++
+         case PAM_TEXT_INFO:
+         case PAM_ERROR_MSG:
+ 	{
+-	 char* tmp_msg;
+ 
+           /* display messages coming from pam... */
+           /* we should have dialog up still to show this */
+           if (c->verbose_p)
+             fprintf(stderr, "PAM_ERROR/PAM_TEXT_INFO nmsgs=%d\n",nmsgs);
++
+           if (!g_passwd_dialog_created)
+            {
+             make_passwd_window (si);
+-            /*sleep (1);*/ /*make sure window is created by now **/
++            usleep (500000); /*make sure window is created by now **/
+            }
+-          tmp_msg = strdup (msg[replies]->msg);
+-          write_to_child (si, tmp_msg);
+-          sleep(1);
++          write_to_child (si, msg[replies]->msg);
++          sleep(2);
+ 
+-          fprintf (stderr,"scf_scdata_state = %d\n",
++          if (c->verbose_p)
++            fprintf (stderr,"scf_scdata_state = %d\n",
+                               si->scf_si->scdata->state);
+           /* The following need to change to some other variable which gets set 
+            * when the user hits OK button in the dialog displaying the TEXT_INFO or
+@@ -758,13 +942,6 @@
+             XEvent event;
+             XtAppNextEvent (si->app, &event);
+             XtDispatchEvent (&event);
+-#if 0
+-             /* handle_typeahead (si);**/
+-              passwd_event_loop (si);
+-          if (c->verbose_p)
+-                fprintf (stderr,"scf_scdata_state = %d\n",
+-                              si->scf_si->scdata->state);
+-#endif /*0*/
+            }
+ 
+           if (c->verbose_p)
+@@ -771,12 +948,10 @@
+             fprintf(stderr, "PAM_ERROR/PAM_TEXT_INFO msg[%d]-> %s\n",
+ 					replies,msg[replies]->msg);
+ 
+-          reply[replies].resp_retcode = PAM_CONV_ERR;
+-          /*reply[replies].resp = 0;*/
++          reply[replies].resp = NULL;
+           /* Reset state to read */
+           si->pw_data->state = pw_read;
+ 
+-          free(tmp_msg);
+           break;
+ 	}
+ 
+@@ -784,17 +959,14 @@
+ 
+          {
+            int i;
+-          if (c->verbose_p)
+-            fprintf (stderr, "%s:     PAM unknown %d(\"%s\") ==> ERROR..default case:\n",
+-                     blurb(), msg[replies]->msg_style, msg[replies]->msg);
+-          /* Must be an error of some sort... */
+-            for (i = 0; i < replies; i++)
+-                    if (reply[replies].resp != NULL)
+-                            free (reply[replies].resp);
+-            free (reply);
+-            reply = NULL;
+-          return PAM_CONV_ERR;
++            if (c->verbose_p)
++            fprintf (stderr, "%s: PAM unknown  ==> ..default case:\n", blurb());
++#ifdef  sun
++            audit_unlock("PAM_CONV_ERR");
++#endif  /* sun */
+ 
++            return PAM_CONV_ERR;
++
+           } /* end default */
+         } /* end switch */
+     } /* end for loop */
+diff -ur driver/xscreensaver.c driver/xscreensaver.c
+--- driver/xscreensaver.c	Wed Jun  7 18:28:36 2006
++++ driver/xscreensaver.c	Wed Jun  7 19:19:46 2006
+@@ -1221,6 +1221,9 @@
+               if (ok_to_unblank == True)
+                {
+                 set_locked_p (si, False);
++                XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor);
++                /* If hack is not resumed it doesnt get killed and leaves zombie processes. */
++	        suspend_screenhack (si, False);  /* resume */
+                 goto DONE;
+                }
+               }
--- a/open-src/app/xscreensaver/sun-src/driver/lock-Gtk.c	Mon Jun 12 18:04:06 2006 -0700
+++ b/open-src/app/xscreensaver/sun-src/driver/lock-Gtk.c	Fri Jun 09 18:09:17 2006 -0700
@@ -790,6 +790,11 @@
   s = g_strdup_printf ("%s\n", gtk_entry_get_text (GTK_ENTRY (pwd->passwd_entry)));
      
   write_string (s);
+
+/* Reset password field to blank, else passwd field shows old passwd *'s, visible when
+   passwd is expired, and pam is walking the user to change old passwd.
+ */
+  gtk_editable_delete_text (pwd->passwd_entry, 0, strlen(s));
   g_free (s);
 
 /* #6178584 P1 "Xscreensaver needs to use ROLE_PASSWORD_TEXT 
@@ -915,7 +920,7 @@
         }
        else if ((strncmp(str,"pw_acct_fail",12)) == 0 ) 
         {
-          hmsg = strdup (_("Just a Warning PAM Account Management Unsuccessful"));
+          hmsg = strdup (_("Your Password has expired."));
         }
        else if ((strncmp(str,"pw_fail",7)) == 0 ) 
         {