1

I would like to know any solutions people came up with restricting a user from changing a system wide configuration of xscreensaver. Part of my job is managing systems which have a requirement that the desktop locks in about 10 minutes and can only be unlocked with a password. I want to use one screensaver and considering xscreensaver is very secure with a mature code base it is a logical choice.

I created appropriate settings in /etc/X11/app-defaults/XScreenSaver*, however the problem is a user can still change their personal preferences by running xscreensaver-demo or editing ~/.xscreensaver.

I understand there is a bit of a hackish way to do this, removing the executable permissions from /usr/bin/xscreensaver-demo and changing the ownership of ~/.xscreensaver to root.

If that is the only practical way of doing this, how would I go about creating ~/.xscreensaver with root ownership upon initial login of the user (in redhat and debian/ubuntu)?

aseq
  • 4,610
  • 1
  • 24
  • 48

2 Answers2

1

If your users' home directories are on a local disk, or they are hosted on a Linux NFS server which you have sudo/root privileges on, then you can set each ~/.xscreensaver file as "immutable".

sudo chattr +i /home/username/.xscreensaver

This will prevent users from modifying it, and from deleting/moving/renaming it.

Reference: http://sattia.blogspot.com/2015/01/how-to-make-file-immutable-on-linux.html

mikedep333
  • 86
  • 1
  • 6
  • Thank you, I did toy with the idea of using chattr. However the problem is that the profile.d script is run as the user who logs in, which means chattr is run as that user as well and thus is easy to circumvent. I was unable to find a way to run a script upon (first) user login as the root user. Also things like /etc/skel get created with the user's ownership. It needs to be automated because we use LDAP with 1000s of potential users who can login. Similarly using (sym)links in various forms could be circumvented. – aseq Mar 11 '15 at 00:55
  • 1
    @aseq here's a solution. Create the script /etc/profile.d/set-xscreensaver.sh and have it call "sudo /usr/local/bin/set-xscreensaver.sh". In that /usr/local/bin/ script, put the logic to set the contents, ownership, and immutable flag on the user's ~/.xscreensaver file unless it already has immutable set. Run "visudo" to edit the /etc/sudoers file so that any user can run /usr/local/bin/set-xscreensaver.sh with sudo. Remember to sanitize the environment variables in that script. Note that I would suggest a setuid script, but most Linux distros disable setuid from working on scripts. – mikedep333 Mar 11 '15 at 13:46
  • Thanks, that could work. However in our environment blanket sudo rights for anything are not allowed, they're at best granted on a case by case basis with appropriate justification (I actually like that security model, less stuff users can break). – aseq Mar 11 '15 at 21:53
  • 1
    This isn't blanket sudo rights. With /etc/sudoers or an nsswitch provider for sudoers, you can set only specific commands that users can run with sudo. You can also set certain commands (or all commands) to require no password, which you would have to do for a login script like this. – mikedep333 Mar 12 '15 at 01:51
  • I understand what you're saying, however I meant it's not allowed to grant any sudo right just like that without any justification. In this case each user account would get a default predetermined sudo right. – aseq Mar 18 '15 at 01:43
0

It looks like this is not really possible. I did end up slightly modifying the source of xscreensaver in order to force certain settings. I tried to use the least invasive way of accomplishing this with minimal modification of the source. This will still allow the user to configure many parts of the screensaver, just not the ones regarding screenlocking and the timeout.

In the source tree find the file driver/prefs.c and in there look for the function write_init_file. In that function find these lines:

if (!pr || !*pr)          ;
CHECK("timeout")          type = pref_time, t = p->timeout;
CHECK("cycle")            type = pref_time, t = p->cycle;
CHECK("lock")             type = pref_bool, b = p->lock_p;
CHECK("lockTimeout")      type = pref_time, t = p->lock_timeout;
(..)
CHECK("mode")             type = pref_str,
                          s = (p->mode == ONE_HACK ? "one" :
                               p->mode == BLANK_ONLY ? "blank" :
                               p->mode == DONT_BLANK ? "off" :
                               p->mode == RANDOM_HACKS_SAME
                               ? "random-same"
                               : "random");

And change to something like the below source sample. What this will do is prevent these settings from being saved to the .xscreensaver file in the user's home directory. And then as long as the system wide default is set to whatever you prefer xscreensaver will keep using these settings in lieu of what would be configured in the .xscreensaver file.

if (!pr || !*pr)          ;
CHECK("timeout")          continue; /* don't save */
CHECK("cycle")            continue; /* don't save */
CHECK("lock")             continue; /* don't save */
CHECK("lockTimeout")      continue; /* don't save */
(..)
CHECK("mode")             type = pref_str,
                          s = (p->mode == ONE_HACK ? "one" :
                               p->mode == BLANK_ONLY ? "blank" :
                               p->mode == DONT_BLANK ? "blank" : /* prevents xscreensaver from being disabled, will force to blank */
                               p->mode == RANDOM_HACKS_SAME
                               ? "random-same"
                               : "random");

The find the function called load_init_file and change the line:

else if (s && !strcasecmp (s, "off"))         p->mode = DONT_BLANK;

to:

else if (s && !strcasecmp (s, "off"))         p->mode = BLANK_ONLY;

Now find the aptly named function stop_the_insanity which sets some values of preferences back to sane values, such as a timeout > 15 seconds will be forced to 15 seconds. This is a good spot to make sure that when a user hand edits the .xscreensaver file instead of using xscreensaver-demo the values will not be used by xscreensaver, but our "sane" values will be used instead.

In function stop_the_insanity add something like this, using your own values if you want. Note that values for time are seconds*1000. In the case user sets mode to "off" we already force it back to blank above.

if (p->timeout > 600000) p->timeout = 600000;
if (p->lock_timeout > 0) p->lock_timeout = 0;
if (! p->lock_p) p->lock_p = True;

With regards to creating .xscreensaver with root ownership upon initial login, I think that is not really possible or advisable. You can create a script in /etc/profile.d which will create an empty .xscreensaver upon user login. But the above mentioned change makes that unnecessary.

aseq
  • 4,610
  • 1
  • 24
  • 48