6

I have a python script that is launched as root, I can't change it.

I would like to know if it's possible to exectute certain lines of this script (or all the script) as normal user (I don't need to be root to run this).

The reason is, I use notifications, and python-notify don't work in all machines in root (looks like this bug)

So ,do you know if it's possible to change it, with a subprocess, or other?

Thanks

Guillaume
  • 2,752
  • 5
  • 27
  • 42

3 Answers3

7

I would like to know if it's possible to exectute certain lines of this script (or all the script) as normal user

Yes, it's possible—and a good idea.

Python's os module has a group of functions to set the real, effective, and saved user and group id, starting with setegid. What exactly each of these does is up to your platform, as far as Python is concerned; it's just calling the C functions of the same names.

But POSIX defines what those functions do. See setuid and seteuid for details, but the short version is:

  • If you want to switch to a normal user and then switch back, use either seteuid or setreuid, to set just effective, or real and effective, but not saved UID. Then use the same function again to set them back to root.
  • If you want to run the whole script as a normal user and make sure you can't get root back, use setresuid instead, to set all three.

If you're using Python 3.1 and earlier, you don't have all of these functions. You can still use seteuid to switch effective ID back and forth, but setuid will… well, it depends on your platform, but I think most modern platforms will change saved as well as real, meaning you can't get root back. If you read the linked POSIX doc, there are a bunch of caveats and complexities in the POSIX documentation. If you only care about one platform, you probably want to read your local manpages instead, rather than reading about all of the cases and then trying to figure out which one covers your platform.

So ,do you know if it's possible to change it, with a subprocess, or other?

That isn't necessary (at least on a conforming POSIX system), but it can make things easier or safer. You can use subprocess, multiprocessing, os.fork, or any other mechanism to launch a child process, which immediately uses setuid to drop privileges—or even setresuid to give up the ability to ever restore its privilege. When that child process is done with its task, it just exits.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Using `setuid` does not allow to change back later. – isedev Sep 19 '14 at 07:15
  • Ok, thanks for your response. So, if I add this line at the beginning of my script: `os.setuid(1000)`, it should work ? – Guillaume Sep 19 '14 at 07:22
  • @Guillaume: If you add that at the beginning of your main script, you will change to user 1000 and (on most platforms) not be able to get back to root later. Is that what you want? – abarnert Sep 19 '14 at 07:24
  • @abamert: I think I can use it as well I must try it. But I'm interessed too how to return in root mode. I will read again your response, because my english is not very good. :) – Guillaume Sep 19 '14 at 07:33
  • @Guillaume: I've tried to make that clear with the two separate bullet points. – abarnert Sep 19 '14 at 07:35
2

you need getpwnam from PWD module , for access user-id by pass username and then with os.setuid() you can change the user and Run python script as another user .

import pwd, os
uid = pwd.getpwnam('username')[2] #instead of index 2 you can use pw_uid Attribute
os.setuid(uid)

But Note that using setuid can make a enormous security hole .

Mazdak
  • 105,000
  • 18
  • 159
  • 188
1

If the script is running as root, you can use os.setuid to change the process's current UID to that of another user (irrevocably) or os.seteuid to change the process's current effective UID (and you can use it again afterwards to reset the EUID to root).

Note that os.setuid changes both the real and effective UID - this is the reason it is irrevocable.

os.seteuid changes the effective UID. Since the real UID will still be root, you can still switch back the EUID to root later on in the script.

isedev
  • 18,848
  • 3
  • 60
  • 59
  • `setuid` isn't irrevocable on a system that supports saved user ID, or on a system that follows the older POSIX standard which mandated (or allowed, I forget which) the weird SysV behavior for `setuid` as root, and I don't think there are too many systems that use the newer standard but don't support saved UIDs. – abarnert Sep 19 '14 at 07:15
  • just tried on Linux kernel 3.16 - `setuid` cannot be called a second time to reset back to root. – isedev Sep 19 '14 at 07:17
  • OK, reading more carefully… You're wrong that setting the real and effective makes it irrevocable (except the backwards-compat implementations, which Linux is not). But you're right that `setuid` is irrevocable—because it sets real, effective, _and saved_ when run as root. – abarnert Sep 19 '14 at 07:21
  • Again, from Linux `seteuid` manpage: Unprivileged user processes may only set the effective user ID to the real user ID, the effective UID _or_ saved set-user-ID. So, having the real UID as root is a sufficient condition. Well, that's the way I interpreted it, at least. – isedev Sep 19 '14 at 07:26
  • A sufficient condition for what? Setting the real and effective to non-root without changing the saved means you can set the real or effective back to root, which means it's not irrevocable. – abarnert Sep 19 '14 at 07:30