I have to open a system file and read from it. This file is usually only readable by root (the super user). I have a way to ask the user for the superuser password. I would like to use this credentials to open the file and read from it without having my entire program running as a superuser process. Is there a way to achieve this in a multiplatform way?
Use one of the exec(3) functions to execute the unprivileged executable. If you want to make it so that you can run this program without using sudo , then make it owned by root and make it a set-user-ID executable with chown root the-program; chmod +s the-program .
Root is the superuser account in Unix and Linux. It is a user account for administrative purposes, and typically has the highest access rights on the system. Usually, the root user account is called root .
Since privileges work completely differently on Unix-like systems and Windows, you're going to need to have platform-specific code. In any case, you'll need to break up your program into two separate programs, one of which runs with elevated permissions and the other of which runs with standard/reduced permissions.
In Unix-like systems (including Linux and Mac OS X), the executable that runs with elevated permissions should do this:
setreuid(2)
and setregid(2)
to set your user ID and group ID back to an unprivileged user.exec(3)
functions to execute the unprivileged executable.sudo
, then make it owned by root and make it a set-user-ID executable with chown root the-program; chmod +s the-program
.The unprivileged program will now be run with normal permissions, but when it starts up, it will have an open file descriptor (file descriptor #3) that can be used to read from your special file.
For Windows, it's similar but slightly different:
CreateFile
. Do not use default security attributes -- create a SECURITY_ATTRIBUTES
structure with bInheritHandle
set to TRUE
so that the handle will be inherited by child processes. If opening the file failed, print an error message and exit.CreateProcess
to launch your child process. Pass in the handle above on the command line (e.g. printed as a numerical value); you could also use a shared memory region, but that's more trouble than it's worth for this problem.requireAdministrator
set to true
. After you do this, when you run the program, you'll get a UAC prompt asking you if you want to allow the program to makes changes.The child process then does grabs the inherited handle by parsing the command line, and it can then read in the data as it pleases.
One problem with this approach is that when you inherit a handle, you have to use the low-level system calls (read(2)
on Unix, ReadFile
on Windows) to read from it -- you can't use higher-level functions like C's fread(3)
or C++'s iostream
s (ok, Unix has fdopen(3)
, but there's no equivalent on Windows as far as I'm aware).
As I'm sure you've noticed by now, everything above has been in C. In Unix, this translates pretty straightforwardly into Python, since the os
module has lots of goodies like setreuid
, exec*
, and fdopen
. On Windows, you might be able to do some of this stuff with the ctypes
module and/or Pywin32, but it's probably easier to stick with C.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With