8

I always boot up my GNU/Linux laptop in console mode. But sometimes I need to bring up the GUI mode. it always requires entering the root password. So I wrote the following script "gogui.sh" and put it in /usr/bin:

#!/bin/bash
echo "mypassword" | sudo service lightdm start

It is a really stupid idea, as if someone read the file, can easily see my password.

Is the an alternative to this?

Dumbo
  • 1,566
  • 2
    you have an aversion to entering your password at a sudo prompt? what are your real goals? – Jeff Schaller Nov 02 '15 at 20:25
  • 1
    I am just usurious to see a proper/alternative way – Dumbo Nov 02 '15 at 20:42
  • 7
    Why not use the NOPASSWD syntax detailed in sudoers(5) for password-free calls to that service command, or a suitable wrapper? – thrig Nov 02 '15 at 20:47
  • 1
    Note that in constructions like these, an unprivileged user doing a process list (with e.g. ps ax) at just the right time might also see your password. It won't happen in this particular case, as echo is a bash builtin command, but the general approach is also dangerous for this reason. – marcelm Nov 03 '15 at 16:15

5 Answers5

35

Passing a password to sudo in a script is utterly pointless. Instead, add a sudo rule adding the particular command you want to run with the NOPASSWD tag. Take care that the command-specific NOPASSWD rule must come after any general rule.

saeid ALL = (ALL:ALL) ALL
saeid ALL = (root) NOPASSWD: service lightdm start

But this is probably not useful anyway. lightdm start starts a login prompt, but you only need that if you want to let other users log in graphically. You don't need it if all you want is to start a GUI session. Instead, call startx to start a GUI session from your text mode session. This does not require any extra privilege.

You may need to explicitly specify your window manager or desktop environment, as startx might not pick up the same default session type that lightdm uses.

startx -- gnome-session
  • Thanks...thats way way way better :P...I use unity, should I still pass to startx the gnome-seesion argument? – Dumbo Nov 02 '15 at 22:40
  • I just checked with startx, while it does bring up my desktop, but many things are missing like the unity launcher and also I got no sound, if I do the lightdm service everything works fine – Dumbo Nov 02 '15 at 22:52
8

There are some options, and one of them is to add the specific command using visudo with the NOPASSWD flag:

%wheel ALL=(ALL) NOPASSWD: /path/to/myscript

cat /path/to/myscript
#!/bin/bash
service lightdm start
Lambert
  • 12,680
3

EDIT
Just noticed in your comments you mentioning Unity, so it appears you're running Ubuntu. My original answer was geared toward SysVinit systems, but commands like telinit still exist for compatibility and will work on distros using Systemd or Upstart.

SysV way

    telinit 5

On modern Systemd systems, telinit is redirected to systemctl.

Systemd way

    systemctl isolate runlevel5.target

or

    systemctl isolate graphical.target

Original answer:
On older non-Systemd distros (RHEL/CentOS 6 and older, for example) the easiest way to switch from console mode to GUI is with the telinit command. On the RHEL/Centos distros, for example, multi-user text-based mode is run level 3 and the multi-user GUI mode is run level 5. Switching from console to GUI mode would be done like this: By default, telinit requires root privileges. To run this as a normal user without a password, you'll need a sudoers entry or set the setuid flag set on the telinit executable. The sudo method is the preferred approach as it can be restricted to just your account.

2

The classical UNIX way is making the script setuid:

$ sudo chown root gogui.sh  #not necessary if root is already the owner of the file
$ sudo chmod u+s gogui.sh

This will set a special permission bit on the file:

$ ls -l gogui.sh
  -rwsr-xr-x 1 root root [omitted] gogui.sh

(Notice the letter s instead of x in the fourth position.)

If you do this, all the times you run the script, it will be run with the privileges of the file's owner, instead of the ones of the user that runs it.

You can now simplify your script gogui.sh to contain only

/usr/sbin/service lightdm start

Notice that I have added an explicit path for the executable (that I have located by typing which service): this is necessary in setuid files, because otherwise the first program called service found in your PATH will be executed. Forgetting the explicit path would be a huge security problem, since it means that any user can tweak the PATH variable and run a program of their choice with root privileges.

If you wish, you can also restrict other users from running the files with chgrp some_group gogui.sh; chmod o-x gogui.sh, which will make the file executable only for members of some_group.

0

Since you're specifically referring to sudo, stick to Gilles' answer. However, since your question title merely was about getting a password to a program's stdin and I had a similar situation recently:

echo $(read -sp "Password: " password; echo $password) | yourcommand

I'll probably earn some bashing for that, but it worked.

Speaking of bash, there you can probably also use

yourcommand <$(read -sp "Password: " password; echo $password)
  • 1
    This will, however briefly, run a process on your system with the password as a command line argument. This makes it discoverable to other processes. Don't do this. – Caleb Nov 04 '15 at 05:13
  • @Caleb oh, that's the very thing I wanted to avoid this way m-/ so bash won't redirect e.g. /dev/fd0 or whatever device <$(...) uses without mentioning the password? Or is it due to read | echo which can hopefully be solved more elegantly anyway? – Tobias Kienzler Nov 04 '15 at 06:34
  • 1
    Any time you pass a variable as an argument to a shell command the shell does the expansion from variable name to value. The command that gets executed has the value as the argument and anything with access to the process list can read those arguments. Try for example var=131 ; sleep $var & ; ps waux | grep 131. You are passing it to the final command through stdin which is okay but that's only after invoking a builtin shell command with the sensitive data as a regular argument in plain sight. – Caleb Nov 04 '15 at 07:40
  • @Caleb So the $password part is the culprit? One could of course write a small Python script, but I wonder if bash can't handle this on its own... – Tobias Kienzler Nov 04 '15 at 18:30