From 65b6bdc8096ef4ac5b3bd41a0f2d38afe12c75ee Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Sat, 2 Jan 2016 22:23:10 -0800
Subject: [PATCH] security-policy

Bug 15284497 SUNBT6317441 Allow admins to remove user-configurability from
                          screensaver

- Upstream rejected as "I will never implement that, because it's stupid and
  unenforcible."  Unfortunately, we're stuck with Common Criteria requirements,
  which do not allow for common sense.

Bug 15779180 SUNBT7154101 Not able to unlock screen after xlock after su to a
                          role

- specific to Solaris RBAC
---
 driver/demo-Gtk.c                  | 79 ++++++++++++++++++++++++++++++++++----
 driver/prefs.c                     | 32 +++++++++++++++
 driver/subprocs.c                  | 24 ++++++++++++
 driver/types.h                     |  3 ++
 driver/xscreensaver-demo.glade2.in |  2 +-
 driver/xscreensaver.c              | 32 +++++++++++++--
 driver/xscreensaver.h              |  2 +
 7 files changed, 163 insertions(+), 11 deletions(-)

diff --git a/driver/demo-Gtk.c b/driver/demo-Gtk.c
index 3d86087..3a4ab09 100644
--- a/driver/demo-Gtk.c
+++ b/driver/demo-Gtk.c
@@ -131,6 +131,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <user_attr.h>
 
 #ifdef HAVE_GTK2
 enum {
@@ -1701,9 +1702,10 @@ flush_dialog_changes_and_save (state *s)
 # undef COPY
 
 # define COPYSTR(FIELD,NAME) \
-  if (!p->FIELD || \
+  if ((p->FIELD != p2->FIELD) && \
+      (!p->FIELD || \
       !p2->FIELD || \
-      strcmp(p->FIELD, p2->FIELD)) \
+      strcmp(p->FIELD, p2->FIELD))) \
     { \
       changed = True; \
       if (s->debug_p) \
@@ -2765,6 +2767,70 @@ update_list_sensitivity (state *s)
 #endif /* !HAVE_GTK2 */
 }
 
+# define SENSITIZE(NAME,SENSITIVEP) \
+    gtk_widget_set_sensitive (name_to_widget (s, (NAME)), (SENSITIVEP))
+
+#define HIDEWIDGET(NAME) \
+    gtk_widget_hide (name_to_widget (s, (NAME)))
+
+static void
+customized_lock(state *s)
+{
+  char *idletime = NULL;
+  int timeout = 0;
+  char *idlecmd = NULL;
+
+  if (((idletime = getuserattruid(getuid(),
+	  USERATTR_IDLETIME_KW, NULL, NULL)) != NULL) &&
+	  ((timeout = atoi(idletime)) != 0) || timeout)
+    {
+
+      GtkWidget *timeout_spinbutton = name_to_widget(s, "timeout_spinbutton");
+      GtkAdjustment *adj = gtk_spin_button_get_adjustment((GtkSpinButton *) timeout_spinbutton);
+      SET_ADJ_UPPER(adj, (gdouble) timeout);
+      if (GET_ADJ_VALUE(adj) > (gdouble) timeout)
+        SET_ADJ_VALUE(adj, (gdouble) timeout);
+      gtk_spin_button_set_adjustment((GtkSpinButton *) timeout_spinbutton, adj);
+
+      /* enforce timeout with idlecmd */
+      if ((idlecmd = getuserattruid(getuid(),
+              USERATTR_IDLECMD_KW, NULL, NULL)) == NULL)
+        idlecmd = strdup(USERATTR_IDLECMD_LOCK_KW);
+
+      if (idlecmd && strcasecmp(idlecmd, USERATTR_IDLECMD_LOGOUT_KW) == 0)
+        {
+          gtk_label_set_text_with_mnemonic(
+              GTK_LABEL (name_to_widget (s, "timeout_label")),
+              "_Logout After");
+
+          HIDEWIDGET("cycle_label");
+          HIDEWIDGET("cycle_spinbutton");
+          HIDEWIDGET("cycle_mlabel");
+
+          HIDEWIDGET("pwd_spinbutton");
+          HIDEWIDGET("pwd_button");
+          HIDEWIDGET("pwd_mlabel");
+          HIDEWIDGET("pwd_button_eventbox");
+
+        }
+      else
+        {
+          gtk_label_set_text_with_mnemonic(
+              GTK_LABEL (name_to_widget(s, "timeout_label")),
+              "_Lock Screen After");
+        }
+      SENSITIZE("lock_spinbutton", 0);
+      SENSITIZE("lock_mlabel", 0);
+      SENSITIZE("lock_button", 0);
+
+      HIDEWIDGET("lock_spinbutton");
+      HIDEWIDGET("lock_mlabel");
+      HIDEWIDGET("lock_button");
+      HIDEWIDGET("lock_button_eventbox");
+    }
+  free(idletime); /* free works on a NULL value */
+  free(idlecmd); /* when you're all with idlecmd */
+}
 
 static void
 populate_prefs_page (state *s)
@@ -2921,10 +2987,6 @@ populate_prefs_page (state *s)
     }
 #endif /* HAVE_DPMS_EXTENSION */
 
-
-# define SENSITIZE(NAME,SENSITIVEP) \
-    gtk_widget_set_sensitive (name_to_widget (s, (NAME)), (SENSITIVEP))
-
     /* Blanking and Locking
      */
     /* bugid 5077081 */
@@ -2964,10 +3026,13 @@ dpms_supported=1;
     SENSITIZE ("fade_spinbutton", (fading_possible &&
                                    (p->fade_p || p->unfade_p)));
 
-# undef SENSITIZE
+    customized_lock(s);
+
   }
 }
 
+# undef SENSITIZE
+# undef HIDEWIDGET
 
 static void
 populate_popup_window (state *s)
diff --git a/driver/prefs.c b/driver/prefs.c
index 52538a8..20f3a4a 100644
--- a/driver/prefs.c
+++ b/driver/prefs.c
@@ -37,6 +37,7 @@
 # include "vms-pwd.h"
 #endif /* VMS */
 
+#include <user_attr.h>
 
 /* This file doesn't need the Xt headers, so stub these types out... */
 #undef XtPointer
@@ -1186,6 +1187,37 @@ load_init_file (Display *dpy, saver_preferences *p)
     if (s) free (s);
   }
 
+  char *idletime = NULL;
+  int timeout = 0;
+  char *idlecmd = NULL;
+
+  if (((idletime = getuserattruid(getuid(),
+          USERATTR_IDLETIME_KW, NULL, NULL)) != NULL) &&
+          ((timeout = atoi(idletime) * 60 * 1000) != 0))
+    {
+
+      p->lock_timeout = 0;
+      if (p->timeout > timeout)
+        p->timeout = timeout;
+
+      /* always lock or logout and do not show blank screen */
+      if (p->mode == DONT_BLANK)
+        p->mode = BLANK_ONLY;
+
+      p->forcedlock_p = p->lock_p = True;
+
+      /* enforce timeout with idlecmd */
+      if ((idlecmd = getuserattruid(getuid(),
+            USERATTR_IDLECMD_KW, NULL, NULL)) == NULL)
+            idlecmd = strdup(USERATTR_IDLECMD_LOCK_KW);
+
+      if (idlecmd && strcasecmp(idlecmd, USERATTR_IDLECMD_LOGOUT_KW) == 0)
+        p->forcedlogout_p = True;
+    }
+
+  free(idletime); /* free works on a NULL value */
+  free(idlecmd); /* when you're all with idlecmd */
+
   if (system_default_screenhack_count)  /* note: first_time is also true */
     {
       merge_system_screenhacks (dpy, p, system_default_screenhacks,
diff --git a/driver/subprocs.c b/driver/subprocs.c
index c975813..ffc435b 100644
--- a/driver/subprocs.c
+++ b/driver/subprocs.c
@@ -940,6 +940,30 @@ check_if_hacks_dir_exists(Bool verbose_p)
     }
 }
 
+/* Added separate function for logout as we need to find better way to log user
+   out. See CR6422890. For s10 we will use /usr/bin/gnome-session-save --kill
+*/
+void
+logout(saver_screen_info *ssi)
+{
+  saver_info *si = ssi->global;
+  saver_preferences *p = &si->prefs;
+  if (!(si->emergency_lock_p || si->locked_p))
+    {
+      struct stat st;
+      if (!stat ("/usr/bin/gnome-session-save", &st))
+        {
+          pid_t forked = fork_and_exec (ssi, "/usr/bin/gnome-session-save\t--force-logout");
+          if (forked < 1)
+            {
+              char buf [255];
+              snprintf (buf, sizeof(buf), "%s: couldn't fork", blurb());
+              perror (buf);
+            }
+        }
+    }
+}
+
 void
 spawn_screenhack (saver_screen_info *ssi)
 {
diff --git a/driver/types.h b/driver/types.h
index b428f73..adee51f 100644
--- a/driver/types.h
+++ b/driver/types.h
@@ -97,6 +97,9 @@ struct saver_preferences {
   Bool xsync_p;			/* whether XSynchronize has been called */
 
   Bool lock_p;			/* whether to lock as well as save */
+  Bool forcedlock_p;		/* whether to forced lock */
+  Bool forcedlogout_p;		/* whether to forced logout */
+
   Bool unlock_timeout_p;	/* whether to timeout unlock dialog */
                                 /* bugid 5077981 */
 
diff --git a/driver/xscreensaver-demo.glade2.in b/driver/xscreensaver-demo.glade2.in
index a7a06a6..85b8069 100644
--- a/driver/xscreensaver-demo.glade2.in
+++ b/driver/xscreensaver-demo.glade2.in
@@ -478,7 +478,7 @@
 			  <property name="update_policy">GTK_UPDATE_ALWAYS</property>
 			  <property name="snap_to_ticks">True</property>
 			  <property name="wrap">False</property>
-			  <property name="adjustment">0 0 720 1 15 15</property>
+			  <property name="adjustment">0 0 720 1 15 0</property>
 			  <accessibility>
 			    <atkrelation target="pwd_button" type="controlled-by"/>
 			    <atkrelation target="pwd_button" type="labelled-by"/>
diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c
index f357281..e502f01 100644
--- a/driver/xscreensaver.c
+++ b/driver/xscreensaver.c
@@ -150,6 +150,7 @@
 
 #include <stdio.h>
 #include <ctype.h>
+#include <user_attr.h>
 #include <X11/Xlib.h>
 
 #ifdef ENABLE_NLS
@@ -1242,6 +1243,9 @@ main_loop (saver_info *si)
 
       maybe_reload_init_file (si);
 
+      if (p->forcedlogout_p)
+        logout(&si->screens[0]);
+
       if (p->mode == DONT_BLANK)
         {
           if (p->verbose_p)
@@ -1532,6 +1536,20 @@ DONE:
 static void analyze_display (saver_info *si);
 static void fix_fds (void);
 
+/*
+ * Is Role attached to userid
+ */
+Bool
+isRoleAttached(uid_t uid)
+{
+  char *type;
+  if (((type = getuserattruid(uid, USERATTR_TYPE_KW, NULL, NULL)) != NULL) &&
+	  (strcmp(type, USERATTR_TYPE_NONADMIN_KW) == 0))
+    return (B_TRUE);
+  else
+    return (B_FALSE);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -1542,6 +1560,14 @@ main (int argc, char **argv)
   struct passwd *spasswd;
   int i;
 
+  uid_t uid = getuid();
+  if (uid == 0 && isRoleAttached(uid))
+    {
+      fprintf(stderr, "Roles Can not login directly.\n");
+      return 1;
+    }
+
+
   /* It turns out that if we do setlocale (LC_ALL, "") here, people
      running in Japanese locales get font craziness on the password
      dialog, presumably because it is displaying Japanese characters
@@ -2054,7 +2080,7 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
   else if (type == XA_EXIT)
     {
       /* Ignore EXIT message if the screen is locked. */
-      if (until_idle_p || !si->locked_p)
+      if (!(p->forcedlogout_p || p->forcedlock_p) && (until_idle_p || !si->locked_p))
 	{
 	  clientmessage_response (si, window, False,
 				  "EXIT ClientMessage received.",
@@ -2071,8 +2097,8 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
 	}
       else
 	clientmessage_response (si, window, True,
-				"EXIT ClientMessage received while locked.",
-				"screen is locked.");
+				"EXIT ClientMessage received.",
+				"screen is locked or does not have privilege to exit.");
     }
   else if (type == XA_RESTART)
     {
diff --git a/driver/xscreensaver.h b/driver/xscreensaver.h
index a52ba63..e688531 100644
--- a/driver/xscreensaver.h
+++ b/driver/xscreensaver.h
@@ -170,6 +170,8 @@ extern struct screenhack_job *make_job (pid_t pid, int screen,
                                         const char *cmd);
 #endif
 
+extern void logout(saver_screen_info *ssi);
+
 /* =======================================================================
    subprocs diagnostics
    ======================================================================= */
-- 
2.6.1

