Page 1 of 1

[Solved]How to reboot/poweroff as normal User

Posted: 14 May 2014, 20:40
by sabir
Hi all!
How to restart Linux from inside a C program without qt/gtk/sudo/python/java script/bash script/pressing poweroff button manually/etc?
I mean using only real system/kernel calls and pure C libs, for example:

#include <unistd.h>
#include <sys/reboot.h>
#define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc
sync();
reboot(RB_POWER_OFF); / reboot(LINUX_REBOOT_CMD_POWER_OFF);

or

#include <stdio.h>
int main()
{
setuid (0);
system("shutdown -P now");
return 0;
}

It works under root user only, but it is wrong way (security). User is in power group (/etc/group/power:x:84:guest).
Please don't tell me about:
just press lxde panel->menu->Logout
cairo-dock->Logout->Shutdown/Restart
su->root password->reboot/poweroff
execl("/usr/bin/sudo", "/sbin/shutdown", "-h", "1:30", (char*)NULL);

Thanks :)

Re: How to reboot/poweroff as normal User

Posted: 15 May 2014, 04:02
by tome

Re: How to reboot/poweroff as normal User

Posted: 15 May 2014, 17:53
by sabir
Thanks, man :)
As I understood there is no way to do it as normal user, unless run any prog with root privileges.

Re: How to reboot/poweroff as normal User

Posted: 15 May 2014, 18:49
by tome
root privileges are unneeded

Re: How to reboot/poweroff as normal User

Posted: 17 May 2014, 05:42
by sabir
tome wrote:root privileges are unneeded
To run "/usr/bin/dbus-send" the root privileges are unneeded, but "dbus" itself has root privileges (/usr/bin/dbus-send owner:root, group:root). A normal user just asks dbus-send to send his message to the ConsoleKit/UPower. The /usr/bin/upower and the /usr/bin/ck-* have root privileges too. Am I wrong?

Re: How to reboot/poweroff as normal User

Posted: 17 May 2014, 10:14
by tome
I don't know but you don't need root password.

Re: How to reboot/poweroff as normal User

Posted: 18 May 2014, 01:26
by brokenman
No you are not wrong. This is the process when guest hits the shutdown button. You should be able to accomplish this from within a script like so:

Code: Select all

/usr/bin/dbus-send --system --print-reply \
--dest="org.freedesktop.ConsoleKit" \
/org/freedesktop/ConsoleKit/Manager \
org.freedesktop.ConsoleKit.Manager.Stop
This is what tome says in his thread.

Re: How to reboot/poweroff as normal User

Posted: 19 May 2014, 07:33
by sabir
brokenman wrote:This is what tome says in his thread.
Yeah, I understood. But I'd like to reboot my own computer directly as a normal user, without any root privileged progs. I mean, I'd like to call reboot(RB_POWER_OFF) directly as a non-privileged user :)

Re: How to reboot/poweroff as normal User

Posted: 19 May 2014, 19:28
by fanthom
linux is designed to prevent this

Code: Select all

guest@porteus:~$ /sbin/reboot
reboot: must be superuser.

Re: [Solved]How to reboot/poweroff as normal User

Posted: 21 May 2014, 01:50
by brokenman
OK i understood you were writing a script that would run on other systems too. If this is just for your box then perhaps change ownership/access rights of the binaries and put them in /usr/bin. Havn't tried it since the shutdown button works as guest fo rme. If you're in terminal then just su to root and shutdown.

Another option is to create a script as suggested above, put it in /usr/bin and call it as guest. I tested this and it works fine.

Re: [Solved]How to reboot/poweroff as normal User

Posted: 30 May 2014, 03:41
by sabir
brokenman wrote:If this is just for your box then perhaps change ownership/access rights of the binaries and put them in /usr/bin.
Make our reboot binary file:

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <linux/reboot.h>
#include <sys/reboot.h>

#include <grp.h>
#include <pwd.h>

#include <error.h>
#include <errno.h>

static gid_t * read_groups(void)
{
	int n;
	gid_t *groups;
	
	n = getgroups(0, NULL);

	if(n < 0)
	{
		fprintf(stderr, "Unable to retrieve groups: %m\n");
		return NULL;
	}

	groups = malloc(n * sizeof(gid_t));
	if(!groups) return NULL;

	if(getgroups(n, groups) < 0)
	{
		fprintf(stderr, "Unable to retrieve groups: %m\n");
		free(groups);
		return NULL;
	}
	return groups;
}

static int reboot_allowed()
{
	struct group *gr;
	gid_t *groups;
	int i;
	
	gr = getgrnam("power");
	if(gr)
	{
		groups = read_groups();
		if (groups)
		{
			for (i = 0; groups[i]; ++i)
			{
				if (groups[i] == gr->gr_gid)
				{
					free(groups);
					return 1;
				}
			}
			free(groups);
		}
	}
	return 0;
}

int main()
{
	struct passwd *pw;
	
	pw = getpwuid(getuid());
	if(pw == NULL) error(1, errno, "failed to get username\n");
	
	if(!reboot_allowed()) error(1, 0, "Permission denied\n");
	
	sync();
	reboot(LINUX_REBOOT_CMD_RESTART);
	return 0;
}
Then change ownership/access rights of the binary and put it in /usr/bin:
Run it as root of course :)

Code: Select all

cp re-boot /usr/bin/
chown root /usr/bin/re-boot
chmod +s /usr/bin/re-boot
And now you can reboot you're computer as normal user. Just run re-boot (where re-boot is the binary name), but be carefull it's unsecure way to do it :)