Commit 1dbcc78d authored by Brian Cameron's avatar Brian Cameron Committed by Brian Cameron

Add RBAC support and allow more configuration on how the System Commands

2007-04-19  Brian Cameron  <brian.cameron@sun.com>

        * configure.ac, acconfig.h, daemon/gdm.c,
          daemon/gdm-daemon-config-entries.h, daemon/gdm-daemon-config-keys.h,
          gui/Makefile.am, gui/gdmlogin.c, gui/greeter/Makefile.am,
          gui/greeter/greeter.c, gui/greeter/greeter_system.c,
          config/Makefile.am, config/gdm.conf.in, docs/C/gdm.xml:  Add
          RBAC support and allow more configuration on how the System
          Commands are handled.  This includes adding the SystemCommandsInMenu
          option to specify which commands show up in the greeter menu and
          the AllowLogoutActions to specify which system commands are supported
          via the QUERY_LOGOUT_ACTION, SET_LOGOUT_ACTION, and
          SET_SAFE_LOGOUT_ACTION gdmflexiserver commands.  Also add the
          RBACSystemCommandKeys option so that RBAC can be configured in a
          generic way for each system command.  The configure.ac script sets
          up this key properly for Solaris.  Add RBAC section to the Security
          section of the docs and info about the three new configuration
          options.  This fixes bug #372738.  Note that the gdmflexiserver
          QUERY_LOGOUT_ACTION, SET_LOGOUT_ACTION, and SET_SAFE_LOGOUT_ACTION
          were broken after William Jon McCann's config cleanup, so I fixed
          this.
        * daemon/gdm-net.c: Fix includes so glib includes are after system
          includes.

svn path=/trunk/; revision=4843
parent 771eacb0
2007-04-19 Brian Cameron <brian.cameron@sun.com>
* configure.ac, acconfig.h, daemon/gdm.c,
daemon/gdm-daemon-config-entries.h, daemon/gdm-daemon-config-keys.h,
gui/Makefile.am, gui/gdmlogin.c, gui/greeter/Makefile.am,
gui/greeter/greeter.c, gui/greeter/greeter_system.c,
config/Makefile.am, config/gdm.conf.in, docs/C/gdm.xml: Add
RBAC support and allow more configuration on how the System
Commands are handled. This includes adding the SystemCommandsInMenu
option to specify which commands show up in the greeter menu and
the AllowLogoutActions to specify which system commands are supported
via the QUERY_LOGOUT_ACTION, SET_LOGOUT_ACTION, and
SET_SAFE_LOGOUT_ACTION gdmflexiserver commands. Also add the
RBACSystemCommandKeys option so that RBAC can be configured in a
generic way for each system command. The configure.ac script sets
up this key properly for Solaris. Add RBAC section to the Security
section of the docs and info about the three new configuration
options. This fixes bug #372738. Note that the gdmflexiserver
QUERY_LOGOUT_ACTION, SET_LOGOUT_ACTION, and SET_SAFE_LOGOUT_ACTION
were broken after William Jon McCann's config cleanup, so I fixed
this.
* daemon/gdm-net.c: Fix includes so glib includes are after system
includes.
2007-04-17 William Jon McCann <mccann@jhu.edu>
* daemon/gdm-xdmcp-manager.c:
......
......@@ -9,8 +9,10 @@
#undef ENABLE_NLS
#undef ALWAYS_RESTART_SERVER
#undef GDM_USER_PATH
#undef GDM_RBAC_SYSCMD_KEYS
#undef HAVE_ADT
#undef HAVE_CATGETS
#undef HAVE_CHKAUTHATTR
#undef HAVE_CHPASS
#undef HAVE_CLEARENV
#undef HAVE_CRYPT
......
......@@ -58,6 +58,7 @@ gdm.conf: $(srcdir)/gdm.conf.in
-e 's,[@]X_XNEST_CMD[@],$(X_XNEST_CMD),g' \
-e 's,[@]X_XNEST_CONFIG_OPTIONS[@],$(X_XNEST_CONFIG_OPTIONS),g' \
-e 's,[@]X_XNEST_UNSCALED_FONTPATH[@],$(X_XNEST_UNSCALED_FONTPATH),g' \
-e 's,[@]GDM_RBAC_SYSCMD_KEYS[@],$(GDM_RBAC_SYSCMD_KEYS),g' \
-e 's,[@]authdir[@],$(authdir),g' \
-e 's,[@]datadir[@],$(datadir),g' \
-e 's,[@]dmconfdir[@],$(dmconfdir),g' \
......
......@@ -121,11 +121,38 @@ DisplayInitDir=@gdmconfdir@/Init
# of cool stuff to figure out what to tell the user and such and can run an X
# configuration program.
XKeepsCrashing=@gdmconfdir@/XKeepsCrashing
# System command support.
#
# Reboot, Halt and suspend commands, you can add different commands separated
# by a semicolon. GDM will use the first one it can find.
#RebootCommand=@REBOOT_COMMAND@
#HaltCommand=@HALT_COMMAND@
#SuspendCommand=@SUSPEND_COMMAND@
RebootCommand=@REBOOT_COMMAND@
HaltCommand=@HALT_COMMAND@
SuspendCommand=@SUSPEND_COMMAND@
# The following options specify how GDM system commands are supported.
#
# Specify which actions are displayed in the greeter. Valid values are HALT,
# REBOOT, SUSPEND, and CUSTOM_CMD separated by semicolons.
SystemCommandsInMenu=HALT;REBOOT;SUSPEND;CUSTOM_CMD
# Specify which actions are supported by QUERY_LOGOUT_ACTION, SET_LOGOUT_ACTION
# and SET_SAFE_LOGOUT_ACTION. Valid values are HALT, REBOOT, SUSPEND, and
# CUSTOM_CMD separated by semicolons.
AllowLogoutActions=HALT;REBOOT;SUSPEND;CUSTOM_CMD
# This feature is only functional if GDM is compiled with RBAC (Role Based
# Access Control) support.
# Specify the RBAC key used to determine if the user has permission to use
# the action via QUERY_LOGOUT_ACTION, SET_LOGOUT_ACTION and
# SET_SAFE_LOGOUT_ACTION. The GDM GUI will only display the action if the
# "gdm" user has RBAC permissions to use the action. RBAC keys for multiple
# actions can be specified by separating them by semicolons. The format for
# each is "Action:RBAC key". If an action is not specified, it is assumed
# all users have permission for this action. For example:
# HALT:key.for.halt,REBOOT:key.for.reboot,[...]
RBACSystemCommandKeys=@GDM_RBAC_SYSCMD_KEYS@
# Probably should not touch the below this is the standard setup.
ServAuthDir=@authdir@
# This is our standard startup script. A bit different from a normal X
......
......@@ -245,6 +245,7 @@ EXTRA_XNEST_LIBS=""
EXTRA_FLEXI_LIBS=""
EXTRA_DYNAMIC_LIBS=""
EXTRA_SETUP_LIBS=""
EXTRA_GREETER_LIBS=""
AC_CHECK_FUNC(socket,,[
AC_CHECK_LIB(socket,socket, [
......@@ -820,16 +821,6 @@ AC_SUBST(WITH_CONSOLE_KIT)
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
#
# Subst the extra libs
#
AC_SUBST(EXTRA_DAEMON_LIBS)
AC_SUBST(EXTRA_CHOOSER_LIBS)
AC_SUBST(EXTRA_XNEST_LIBS)
AC_SUBST(EXTRA_FLEXI_LIBS)
AC_SUBST(EXTRA_DYNAMIC_LIBS)
AC_SUBST(EXTRA_SETUP_LIBS)
#
# Define some variables to represent the directories we use.
#
......@@ -985,12 +976,32 @@ AC_CHECK_LIB(devinfo, di_devperm_login, [
AC_DEFINE(HAVE_LOGINDEVPERM)
EXTRA_DAEMON_LIBS="$EXTRA_DAEMON_LIBS -ldevinfo" ])
# Check for RBAC support (chkauthattr
#
AC_MSG_CHECKING(for RBAC support - chkauthattr)
AC_CHECK_LIB(secdb, chkauthattr, [
AC_DEFINE(HAVE_CHKAUTHATTR)
EXTRA_DAEMON_LIBS="$EXTRA_DAEMON_LIBS -lsecdb"
EXTRA_GREETER_LIBS="$EXTRA_GREETER_LIBS -lsecdb"])
#
# Subst the extra libs
#
AC_SUBST(EXTRA_DAEMON_LIBS)
AC_SUBST(EXTRA_CHOOSER_LIBS)
AC_SUBST(EXTRA_XNEST_LIBS)
AC_SUBST(EXTRA_FLEXI_LIBS)
AC_SUBST(EXTRA_DYNAMIC_LIBS)
AC_SUBST(EXTRA_SETUP_LIBS)
AC_SUBST(EXTRA_GREETER_LIBS)
# Define different Halt, and Reboot commands differently for Solaris.
#
# On Solaris/bin is a symlink to /usr/bin, so don't include it in
# GDM_USER_PATH.
#
GDM_USER_PATH=""
GDM_RBAC_SYSCMD_KEYS=""
case "$host" in
*solaris*)
......@@ -1001,6 +1012,7 @@ case "$host" in
XSESSION_SHELL=/bin/ksh
SOUND_PROGRAM=/usr/bin/audioplay
GDMGNOMESESSIONCMD=/usr/dt/config/Xsession.jds
GDM_RBAC_SYSCMD_KEYS="HALT:solaris.system.shutdown;REBOOT:solaris.system.shutdown"
;;
*freebsd*)
GDM_USER_PATH="/bin:/usr/bin"
......@@ -1191,6 +1203,14 @@ else
AC_MSG_RESULT(no)
fi
# Allow configure to specify RBAC keys.
#
AC_ARG_WITH(rbac-system-command-keys, [ --with-rbac-system-command-keys=<keys> RBAC system command keys])
if ! test -z "$with_system_command_keys"; then
GDM_RBAC_SYSCMD_KEYS=$with_system_command_keys
fi
# Set configuration choices.
#
AC_SUBST(HALT_COMMAND)
......@@ -1206,6 +1226,8 @@ AC_DEFINE_UNQUOTED(GDM_USER_PATH,"$GDM_USER_PATH")
AC_SUBST(SOUND_PROGRAM)
AC_DEFINE_UNQUOTED(SOUND_PROGRAM,"$SOUND_PROGRAM")
AC_SUBST(GDMGNOMESESSIONCMD)
AC_SUBST(GDM_RBAC_SYSCMD_KEYS)
AC_DEFINE_UNQUOTED(GDM_RBAC_SYSCMD_KEYS,"$GDM_RBAC_SYSCMD_KEYS")
AC_SUBST(X_PATH)
AC_SUBST(X_SERVER)
......
......@@ -205,6 +205,9 @@ typedef enum {
GDM_ID_SHOW_GNOME_FAILSAFE,
GDM_ID_SHOW_XTERM_FAILSAFE,
GDM_ID_SHOW_LAST_SESSION,
GDM_ID_SYSTEM_COMMANDS_IN_MENU,
GDM_ID_ALLOW_LOGOUT_ACTIONS,
GDM_ID_RBAC_SYSTEM_COMMAND_KEYS,
GDK_ID_LAST
} GdmConfigKey;
......@@ -218,31 +221,28 @@ typedef enum {
* Developers who add new configuration options should ensure that they do the
* following:
*
* + Edit the config/gdm.conf file to include the default setting.
* + Add the key to config/gdm.conf.in file and specify the default value.
* Include comments explaining what the key does.
*
* + Specify the same default in this file as in the config/gdm.conf.in file.
* + Add the key as a #define to daemon/gdm-daemon-config-keys.h with
* the same default value.
*
* + Update the gdm_daemon_config_entries[] to add the
* new key. Include some documentation about the new key, following the
* style of existing comments.
* + Update the GdmConfigKey enumeration and gdm_daemon_config_entries[] to
* add the new key. Include some documentation about the new key,
* following the style of existing comments.
*
* + Add any validation to the validate_cb function in
* gdm-daemon-config.c, if validation is needed.
*
* + If GDM_UPDATE_CONFIG should not respond to this configuration setting,
* update the update_config function in gdmconfig.c to return FALSE for
* this key. Examples include changing the PidFile, ServAuthDir, or
* other values that GDM should not change until it is restarted. If
* update the gdm_daemon_config_update_key function in gdmconfig.c to
* return FALSE for this key. Examples include changing the ServAuthDir
* or other values that GDM should not change until it is restarted. If
* this is true, the next bullet can be ignored.
*
* + If the option should cause the greeter (gdmlogin/gdmgreeter) program to
* be updated immediately, make sure to update the appropriate
* _gdm_set_value_* function in gdmconfig.c. This function calls the
* notify_displays_* function to call when this value is changed, so you
* will need to add your new config value to the list of values sending
* such notification. Supporting logic will need to be added to
* gdm_slave_handle_notify function in slave.c to process the notify.
* It should be clear to see how to do this from the existing code.
* be updated immediately, update the notify_cb and lookup_notify_key
* functions to handle this key.
*
* + Add the key to the gdm_read_config and gdm_reread_config functions in
* gui/gdmlogin.c, gui/gdmchooser.c, and gui/greeter/greeter.c
......@@ -349,6 +349,10 @@ static const GdmConfigEntry gdm_daemon_config_entries [] = {
/* How long to wait before assuming an Xserver has timed out */
{ GDM_CONFIG_GROUP_DAEMON, "GdmXserverTimeout", GDM_CONFIG_VALUE_INT, "10", GDM_ID_XSERVER_TIMEOUT },
{ GDM_CONFIG_GROUP_DAEMON, "SystemCommandsInMenu", GDM_CONFIG_VALUE_STRING_ARRAY, "HALT;REBOOT;SUSPEND;CUSTOM_CMD", GDM_ID_SYSTEM_COMMANDS_IN_MENU },
{ GDM_CONFIG_GROUP_DAEMON, "AllowLogoutActions", GDM_CONFIG_VALUE_STRING_ARRAY, "HALT;REBOOT;SUSPEND;CUSTOM_CMD", GDM_ID_ALLOW_LOGOUT_ACTIONS },
{ GDM_CONFIG_GROUP_DAEMON, "RBACSystemCommandKeys", GDM_CONFIG_VALUE_STRING_ARRAY, GDM_RBAC_SYSCMD_KEYS, GDM_ID_RBAC_SYSTEM_COMMAND_KEYS },
{ GDM_CONFIG_GROUP_SECURITY, "AllowRoot", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALLOW_ROOT },
{ GDM_CONFIG_GROUP_SECURITY, "AllowRemoteRoot", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ALLOW_REMOTE_ROOT },
{ GDM_CONFIG_GROUP_SECURITY, "AllowRemoteAutoLogin", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ALLOW_REMOTE_AUTOLOGIN },
......
......@@ -82,6 +82,9 @@ G_BEGIN_DECLS
#define GDM_KEY_VT_ALLOCATION "daemon/VTAllocation=true"
#define GDM_KEY_CONSOLE_CANNOT_HANDLE "daemon/ConsoleCannotHandle=am,ar,az,bn,el,fa,gu,hi,ja,ko,ml,mr,pa,ta,zh"
#define GDM_KEY_XSERVER_TIMEOUT "daemon/GdmXserverTimeout=10"
#define GDM_KEY_SYSTEM_COMMANDS_IN_MENU "daemon/SystemCommandsInMenu=HALT;REBOOT;SUSPEND;CUSTOM_CMD"
#define GDM_KEY_ALLOW_LOGOUT_ACTIONS "daemon/AllowLogoutActions=HALT;REBOOT;SUSPEND;CUSTOM_CMD"
#define GDM_KEY_RBAC_SYSTEM_COMMAND_KEYS "daemon/RBACSystemCommandKeys=" GDM_RBAC_SYSCMD_KEYS
#define GDM_KEY_SERVER_PREFIX "server-"
#define GDM_KEY_SERVER_NAME "name=Standard server"
......
......@@ -17,7 +17,8 @@
*/
#include "config.h"
#include <glib/gi18n.h>
#include <strings.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
......@@ -31,6 +32,8 @@
#include <fcntl.h>
#include <errno.h>
#include <glib/gi18n.h>
#include "gdm.h"
#include "misc.h"
#include "gdm-net.h"
......
......@@ -42,7 +42,11 @@
#include <errno.h>
#include <locale.h>
#include <dirent.h>
#include <gtk/gtk.h>
#ifdef HAVE_CHKAUTHATTR
#include <auth_attr.h>
#include <secdb.h>
#endif
/* This should be moved to auth.c I suppose */
......@@ -50,6 +54,8 @@
#include <glib/gi18n.h>
#include <glib-object.h>
#include <gtk/gtk.h>
/* Needed for signal handling */
#include "gdm-common.h"
......@@ -3613,6 +3619,54 @@ sup_handle_get_config (GdmConnection *conn,
g_strfreev (splitstr);
}
static gboolean
is_action_available (GdmDisplay *disp, gchar *action)
{
const gchar **allowsyscmd;
const gchar **rbackeys;
gboolean sysmenu;
gboolean ret = FALSE;
int i;
allowsyscmd = gdm_daemon_config_get_value_string_array (GDM_KEY_ALLOW_LOGOUT_ACTIONS);
rbackeys = gdm_daemon_config_get_value_string_array (GDM_KEY_RBAC_SYSTEM_COMMAND_KEYS);
sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name);
if (!disp->attached || !sysmenu) {
return FALSE;
}
for (i = 0; allowsyscmd[i] != NULL; i++) {
if (strcmp (allowsyscmd[i], action) == 0) {
ret = TRUE;
break;
}
}
#ifdef HAVE_CHKAUTHATTR
if (ret == TRUE && rbackeys) {
for (i = 0; rbackeys[i] != NULL; i++) {
gchar **rbackey = g_strsplit (rbackeys[i], ":", 2);
if (! ve_string_empty (rbackey[0]) &&
! ve_string_empty (rbackey[1]) &&
strcmp (rbackey[0], action) == 0) {
if (!chkauthattr (rbackey[1], disp->login)) {
g_strfreev (rbackey);
ret = FALSE;
break;
}
}
g_strfreev (rbackey);
}
}
#endif
return ret;
}
static void
sup_handle_query_logout_action (GdmConnection *conn,
const char *msg,
......@@ -3622,14 +3676,14 @@ sup_handle_query_logout_action (GdmConnection *conn,
GdmDisplay *disp;
GString *reply;
const gchar *sep = " ";
gboolean sysmenu;
gboolean has_authority = TRUE;
gboolean allow_custom = FALSE;
int i;
disp = gdm_connection_get_display (conn);
/* Only allow locally authenticated connections */
if ( ! GDM_CONN_AUTHENTICATED (conn) ||
disp == NULL) {
if (! GDM_CONN_AUTHENTICATED (conn) || disp == NULL) {
gdm_info (_("%s request denied: "
"Not authenticated"), "QUERY_LOGOUT_ACTION");
gdm_connection_write (conn,
......@@ -3637,50 +3691,58 @@ sup_handle_query_logout_action (GdmConnection *conn,
return;
}
sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name);
reply = g_string_new ("OK");
reply = g_string_new ("OK");
logout_action = disp->logout_action;
if (logout_action == GDM_LOGOUT_ACTION_NONE)
logout_action = safe_logout_action;
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_HALT))) {
g_string_append_printf (reply, "%s%s", sep, GDM_SUP_LOGOUT_ACTION_HALT);
if (! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_HALT)) &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HALT)) {
g_string_append_printf (reply, "%s%s", sep,
GDM_SUP_LOGOUT_ACTION_HALT);
if (logout_action == GDM_LOGOUT_ACTION_HALT)
g_string_append (reply, "!");
sep = ";";
}
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_REBOOT))) {
g_string_append_printf (reply, "%s%s", sep, GDM_SUP_LOGOUT_ACTION_REBOOT);
if (! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT)) &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_REBOOT)) {
g_string_append_printf (reply, "%s%s", sep,
GDM_SUP_LOGOUT_ACTION_REBOOT);
if (logout_action == GDM_LOGOUT_ACTION_REBOOT)
g_string_append (reply, "!");
sep = ";";
}
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND))) {
g_string_append_printf (reply, "%s%s", sep, GDM_SUP_LOGOUT_ACTION_SUSPEND);
if (! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND)) &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) {
g_string_append_printf (reply, "%s%s", sep,
GDM_SUP_LOGOUT_ACTION_SUSPEND);
if (logout_action == GDM_LOGOUT_ACTION_SUSPEND)
g_string_append (reply, "!");
sep = ";";
}
for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
gchar *key_string = NULL;
key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
g_free (key_string);
key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i);
if (gdm_daemon_config_get_value_bool (key_string)) {
g_string_append_printf (reply, "%s%s%d", sep, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE, i);
if (logout_action == (GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + i))
g_string_append (reply, "!");
if (is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) {
for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
gchar *key_string = NULL;
key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
if (! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
g_free (key_string);
key_string = g_strdup_printf("%s%d=",
GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i);
if (gdm_daemon_config_get_value_bool (key_string)) {
g_string_append_printf (reply, "%s%s%d", sep,
GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE, i);
if (logout_action == (GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + i))
g_string_append (reply, "!");
sep = ";";
}
}
g_free(key_string);
}
g_free(key_string);
}
g_string_append (reply, "\n");
......@@ -3707,7 +3769,7 @@ sup_handle_query_custom_cmd_labels (GdmConnection *conn,
if ( ! GDM_CONN_AUTHENTICATED (conn) ||
disp == NULL) {
gdm_info (_("%s request denied: "
"Not authenticated"), "QUERY_LOGOUT_ACTION");
"Not authenticated"), "QUERY_CUSTOM_CMD_LABELS");
gdm_connection_write (conn,
"ERROR 100 Not authenticated\n");
return;
......@@ -3837,7 +3899,7 @@ sup_handle_query_custom_cmd_no_restart_status (GdmConnection *conn,
if ( ! GDM_CONN_AUTHENTICATED (conn) ||
disp == NULL) {
gdm_info (_("%s request denied: "
"Not authenticated"), "QUERY_LOGOUT_ACTION");
"Not authenticated"), "QUERY_CUSTOM_CMD_NO_RESTART_STATUS");
gdm_connection_write (conn,
"ERROR 100 Not authenticated\n");
return;
......@@ -3873,13 +3935,12 @@ sup_handle_set_logout_action (GdmConnection *conn,
gpointer data)
{
const gchar *action;
GdmDisplay *disp;
const gchar *action;
gboolean was_ok = FALSE;
gboolean sysmenu;
action = &msg[strlen (GDM_SUP_SET_LOGOUT_ACTION " ")];
disp = gdm_connection_get_display (conn);
disp = gdm_connection_get_display (conn);
/* Only allow locally authenticated connections */
if ( ! GDM_CONN_AUTHENTICATED(conn) ||
......@@ -3892,40 +3953,34 @@ sup_handle_set_logout_action (GdmConnection *conn,
return;
}
sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name);
if (strcmp (action, GDM_SUP_LOGOUT_ACTION_NONE) == 0) {
disp->logout_action = GDM_LOGOUT_ACTION_NONE;
was_ok = TRUE;
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0) {
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_HALT))) {
disp->logout_action =
GDM_LOGOUT_ACTION_HALT;
was_ok = TRUE;
}
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0) {
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_REBOOT))) {
disp->logout_action =
GDM_LOGOUT_ACTION_REBOOT;
was_ok = TRUE;
}
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0) {
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND))) {
disp->logout_action =
GDM_LOGOUT_ACTION_SUSPEND;
was_ok = TRUE;
}
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0 &&
! gdm_daemon_config_get_value_string_array (GDM_KEY_HALT) &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HALT)) {
disp->logout_action = GDM_LOGOUT_ACTION_HALT;
was_ok = TRUE;
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0 &&
! gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT) &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_REBOOT)) {
disp->logout_action = GDM_LOGOUT_ACTION_REBOOT;
was_ok = TRUE;
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0 &&
! gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) {
disp->logout_action = GDM_LOGOUT_ACTION_SUSPEND;
was_ok = TRUE;
}
else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE,
strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0) {
strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0 &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) {
int cmd_index;
if (sscanf (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "%d", &cmd_index) == 1) {
gchar *key_string = NULL;
key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index);
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
if (! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
disp->logout_action =
GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index;
was_ok = TRUE;
......@@ -3933,6 +3988,7 @@ sup_handle_set_logout_action (GdmConnection *conn,
g_free(key_string);
}
}
if (was_ok) {
gdm_connection_write (conn, "OK\n");
gdm_try_logout_action (disp);
......@@ -3947,14 +4003,12 @@ sup_handle_set_safe_logout_action (GdmConnection *conn,
gpointer data)
{
const gchar *action;
GdmDisplay *disp;
const gchar *action;
gboolean was_ok = FALSE;
gboolean sysmenu;
action = &msg[strlen (GDM_SUP_SET_SAFE_LOGOUT_ACTION " ")];
disp = gdm_connection_get_display (conn);
disp = gdm_connection_get_display (conn);
/* Only allow locally authenticated connections */
if ( ! GDM_CONN_AUTHENTICATED(conn) ||
......@@ -3967,40 +4021,36 @@ sup_handle_set_safe_logout_action (GdmConnection *conn,
return;
}
sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name);
if (strcmp (action, GDM_SUP_LOGOUT_ACTION_NONE) == 0) {
safe_logout_action = GDM_LOGOUT_ACTION_NONE;
was_ok = TRUE;
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0) {
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_HALT))) {
safe_logout_action =
GDM_LOGOUT_ACTION_HALT;
was_ok = TRUE;
}
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0) {
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_REBOOT))) {
safe_logout_action =
GDM_LOGOUT_ACTION_REBOOT;
was_ok = TRUE;
}
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0) {
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND))) {
safe_logout_action =
GDM_LOGOUT_ACTION_SUSPEND;
was_ok = TRUE;
}
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0 &&
! gdm_daemon_config_get_value_string_array (GDM_KEY_HALT) &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HALT)) {
safe_logout_action = GDM_LOGOUT_ACTION_HALT;
was_ok = TRUE;
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0 &&
! gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT) &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_REBOOT)) {
safe_logout_action = GDM_LOGOUT_ACTION_REBOOT;
was_ok = TRUE;
} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0 &&
! gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) {
safe_logout_action = GDM_LOGOUT_ACTION_SUSPEND;
was_ok = TRUE;
}
else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE,
strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0) {
strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0 &&
is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) {
int cmd_index;
if (sscanf (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "%d", &cmd_index) == 1) {
gchar *key_string = NULL;
key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index);
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
if (! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
safe_logout_action =
GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index;
was_ok = TRUE;
......@@ -4008,6 +4058,7 @@ sup_handle_set_safe_logout_action (GdmConnection *conn,
g_free(key_string);
}
}
if (was_ok) {
gdm_connection_write (conn, "OK\n");
gdm_try_logout_action (disp);
......
......@@ -1085,6 +1085,25 @@ gdm: .your.domain
page for details.
</para>
</sect2>
<sect2 id="rbac">
<title>RBAC (Role Based Access Control)</title>
<para>
If GDM is compiled with RBAC support, then the
<filename>RBACSystemCommandKeys</filename> configuration option can be
used to specify the RBAC key to be used to determine if the user has
authority to use commands. This is supported for the Shutdown,
Reboot, Suspend, and Custom Commands that appear in the GDM greeter
and via the <command>gdmflexiserver</command> QUERY_LOGOUT_ACTION,
SET_LOGOUT_ACTION, and SET_SAFE_LOGOUT_ACTION commands. The greeter
will only display the option if the gdm user (specified by the
<filename>User</filename> configuration option) has permission
via RBAC. Users will only be able to use the
<command>gdmflexiserver</command> commands if the user has
permission via RBAC.
</para>
</sect2>
</sect1>
<sect1 id="consolekit">
......@@ -1791,6 +1810,23 @@ Greeter=/usr/lib/gdmgreeter
</listitem>
</varlistentry>
<varlistentry>
<term>AllowLogoutActions</term>
<listitem>
<synopsis>AllowLogoutActions=HALT;REBOOT;SHUTDOWN;SUSPEND;CUSTOM_CMD</synopsis>
<para>
Specify which actions are supported by the QUERY_LOGOUT_ACTION,
SET_LOGOUT_ACTION, and SET_SAFE_LOGOUT_ACTION
<command>gdmflexiserver</command> commands. Valid values are
HALT, REBOOT, SHUTDOWN, SUSPEND, and CUSTOM_CMD and these should be
separated by semicolons. This allows certain options to be disabled
if desired. Refer to the related
<filename>SystemCommandsInMenu</filename> and
<filename>RBACSystemCommandKeys</filename> configuration options.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>AlwaysLoginCurrentSession</term>
<listitem>
......@@ -2240,6 +2276,31 @@ Greeter=/usr/lib/gdmgreeter
</listitem>
</varlistentry>
<varlistentry>
<term>RBACSystemCommandKeys</term>
<listitem>
<synopsis>RBACSystemCommandKeys</synopsis>
<para>
Support RBAC (Role Based Access Control) for system commands
(Shutdown, Reboot, Suspend, etc.). This feature is only functional
if GDM is compiled with RBAC support. Specify the RBAC key used
to determine if the user has permission to use the action via the
QUERY_LOGOUT_ACTION, SET_LOGOUT_ACTION, and SET_SAFE_LOGOUT_ACTION
<command>gdmflexiserver</command> commands. Valid actions are
HALT, REBOOT, SUSPEND, and CUSTOM_CMD. The greeter will only
display the command if the gdm user (<filename>User</filename>
configuration key) has RBAC permissions to use the action. RBAC
keys for multiple actions can be specified by separating them with
semicolons. The format for each is "Action:RBAC key". If an
action is not specified, it is assumed that all users have
permission to use this action. For example, a valid value for
this configuration option would be
&quot;HALT:key.for.halt;REBOOT:key.for.reboot&quot;. Refer to the
related <filename>AllowLogoutActions</filename> and
<filename>SystemCommandsInMenu</filename> configuration options.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>RebootCommand</term>
<listitem>
......@@ -2365,6 +2426,27 @@ Greeter=/usr/lib/gdmgreeter
</listitem>
</varlistentry>
<varlistentry>
<term>SystemCommandsInMenu</term>
<listitem>
<synopsis>SuspendCommand=HALT;REBOOT;SHUTDOWN;SUSPEND;CUSTOM_CMD</synopsis>
<para>
Specify which system commands are available in the greeter
menu. Valid values are HALT, REBOOT, SHUTDOWN, SUSPEND, and CUSTOM_CMD
and these should be separated by semicolons. This can be useful if you
want to disable some options in the menu, but still have them available
to authenticated users via the SET_LOGOUT_ACTION or
SET_SAFE_LOGOUT_ACTION <command>gdmflexiserver</command> commands. For
example, the GNOME panel uses these commands to provide Shutdown,
Reboot, and Suspend in the application menu. Therefore if you turn off
these options in the greeter, these options can still be available to
users who have authenticated via the GNOME panel. Refer to the related
<filename>AllowLogoutActions</filename> and
<filename>RBACSystemCommandKeys</filename> configuration options.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>TimedLoginEnable</term>
<listitem>
......@@ -7287,6 +7369,90 @@ svcadm enable servicename
</screen>
</sect2>
<sect2 id="solarisrbac">
<title>Solaris RBAC support for Shutdown, Reboot, and Suspend</title>
<para>
Starting with GDM 2.19, GDM supports RBAC (Role Based
Access Control) for enabling the system commands (Shutdown,
Reboot, Suspend, etc.) that appear in the greeter system
menu and via the <command>gdmflexiserver</command>