components/desktop/xscreensaver/patches/0009-pam-audit.patch
changeset 5561 0416d82f7f55
parent 5400 1199f8e91f50
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/xscreensaver/patches/0009-pam-audit.patch	Tue Mar 08 09:00:31 2016 -0800
@@ -0,0 +1,284 @@
+From ff65f319d40fdc0d5f9d316b9c5d48d7cdebc6b6 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <[email protected]>
+Date: Sat, 2 Jan 2016 22:38:35 -0800
+Subject: [PATCH] pam audit
+
+Fixes for bugs:
+15201967 SUNBT5015296 xscreensaver doesn't audit
+15326852 SUNBT6417168 xscreensaver loops while trying to unlock a session
+	 	      for a user whose password was expired
+15452882 SUNBT6654320 xscreensaver dies due to memory corruption
+15688159 SUNBT7008058 screensaver continues to accept old password for
+	 	      existing sessions after password changed
+
+Also ensures that Xscreensaver on Solaris only uses PAM, and never attempts
+to fallback to direct use of getpwent(), which isn't audited
+
+Upstream status unknown.
+---
+ driver/Makefile.in  |   2 +-
+ driver/passwd-pam.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++-
+ driver/passwd.c     |   4 ++
+ 3 files changed, 161 insertions(+), 3 deletions(-)
+
+diff --git a/driver/Makefile.in b/driver/Makefile.in
+index a44e312..7aec6d9 100644
+--- a/driver/Makefile.in
++++ b/driver/Makefile.in
+@@ -212,7 +212,7 @@ PDF2JPEG_LIBS	= -framework Cocoa
+ SAVER_LIBS	= $(LIBS) $(X_LIBS) $(XMU_LIBS) @SAVER_LIBS@ \
+ 		  $(XDPMS_LIBS) $(XINERAMA_LIBS) $(GL_LIBS) $(X_PRE_LIBS) \
+ 		  -lXt -lX11 -lXext $(X_EXTRA_LIBS) \
+-		  $(PASSWD_LIBS)
++		  -lbsm $(PASSWD_LIBS)
+ 
+ CMD_LIBS	= $(LIBS) $(X_LIBS) \
+ 		  $(X_PRE_LIBS) -lX11 -lXext $(X_EXTRA_LIBS)
+diff --git a/driver/passwd-pam.c b/driver/passwd-pam.c
+index 93c73f1..4d24ac3 100644
+--- a/driver/passwd-pam.c
++++ b/driver/passwd-pam.c
+@@ -47,6 +47,8 @@
+ 
+ #ifdef __sun
+ # include <deflt.h>
++# include <bsm/adt.h>
++# include <bsm/adt_event.h>
+ #endif
+ 
+ extern char *blurb(void);
+@@ -81,6 +83,9 @@ extern void unblock_sigchld (void);
+ #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!
+  */
+@@ -178,6 +183,124 @@ Bool pam_priv_init (int argc, char **argv, Bool verbose_p);
+  */
+ 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 */
+ 
+ /**
+  * This function is the PAM conversation driver. It conducts a full
+@@ -231,6 +354,12 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
+     fprintf (stderr, "%s: pam_start (\"%s\", \"%s\", ...) ==> %d (%s)\n",
+              blurb(), service, si->user,
+              status, PAM_STRERROR (pamh, status));
++
++#ifdef __sun
++  if (audit_flag_global) /* We want one audit lock log per lock */
++    audit_lock ();
++#endif /**sun*/
++
+   if (status != PAM_SUCCESS) goto DONE;
+ 
+ #ifdef __sun
+@@ -307,6 +436,14 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
+ # endif /* HAVE_SIGTIMEDWAIT */
+   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*/
++
+ #ifdef HAVE_XSCREENSAVER_LOCK
+   /* Send status message to unlock dialog */
+   if (pam_auth_status == PAM_SUCCESS)
+@@ -354,7 +491,14 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
+             write_to_child (si, "ul_acct_ok", PAM_STRERROR(pamh, acct_rc));
+         }
+       else
+-        write_to_child (si, "ul_acct_fail", PAM_STRERROR(pamh, acct_rc));
++        {
++#ifdef __sun
++          /* Only in failure of pam_acct_mgmt case we call audit */
++          audit_unlock (acct_rc);
++#endif /*sun*/
++
++          write_to_child (si, "ul_acct_fail", PAM_STRERROR(pamh, acct_rc));
++        }
+       if (verbose_p)
+         sleep (1);
+ #endif
+@@ -384,6 +528,10 @@ pam_try_unlock(saver_info *si, Bool 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;
+@@ -433,7 +581,13 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
+             write_to_child (si, "ul_setcred_ok", PAM_STRERROR(pamh, setcred_rc));
+         }
+       else
+-        write_to_child (si, "ul_setcred_fail", PAM_STRERROR(pamh, setcred_rc));
++        {
++#ifdef __sun
++          /* Only in failure of pam_setcred() case we call audit. */
++          audit_unlock (setcred_rc);
++#endif /*sun*/
++          write_to_child (si, "ul_setcred_fail", PAM_STRERROR(pamh, setcred_rc));
++        }
+       if (verbose_p)
+         sleep (1);
+ #endif
+diff --git a/driver/passwd.c b/driver/passwd.c
+index 0618642..350dc4d 100644
+--- a/driver/passwd.c
++++ b/driver/passwd.c
+@@ -81,9 +81,11 @@ extern void pam_try_unlock (saver_info *si, Bool verbose_p,
+ extern Bool ext_priv_init (int argc, char **argv, Bool verbose_p);
+ extern Bool ext_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
+ #endif
++#ifndef __sun /* Only use PAM on Solaris, not direct getpwent */
+ extern Bool pwent_lock_init (int argc, char **argv, Bool verbose_p);
+ extern Bool pwent_priv_init (int argc, char **argv, Bool verbose_p);
+ extern Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
++#endif
+ 
+ Bool lock_priv_init (int argc, char **argv, Bool verbose_p);
+ Bool lock_init (int argc, char **argv, Bool verbose_p);
+@@ -107,8 +109,10 @@ struct auth_methods methods[] = {
+   { "external",		0, ext_priv_init, ext_passwd_valid_p, 0,
+   			False, False },
+ # endif
++# ifndef __sun /* Only use PAM on Solaris, not direct getpwent */
+   { "normal",           pwent_lock_init, pwent_priv_init, pwent_passwd_valid_p, 0,
+                         False, False }
++# endif
+ };
+ 
+ 
+-- 
+2.6.1
+