I have a python script on raspberryi pi 3. I want to make it only executable for x user without having root permission. It can not be readable and writable. How can I do that? I gave only x(execute) permission to the file for x user. But when I execute the script, it wants root password.
If the user has access to the script, he can modify the content himself. However, just for the sake of the answer or method, we can do something like this:
You can restrict the access to the script by getting the username of the person on the operating the system:
import getpass
if getpass.getuser() in ['user1','user2'] # allowed user list:
main() # main function
else:
print("You are not authorised to run this script")
Related
How can I launch a child process that has root privileges?
I have a python program in MacOS that can do most of its operations as a normal user. But occasionally, triggered by some user interaction, it will need root permissions to preform a task.
For security reasons, I don't want the entire GUI app to be started and left running as root. I want only a child process with a very minimal subset of functions to run as root.
For UX reasons, I don't want to have to tell the user "Sorry, please restart this app as Administrator". I want to be able to have them stay in the GUI, get presented with a pop-up that says "Uh, you need root to do that. Please enter your password."
Of course, if my unprivileged python process attempts to become root with
setuid(0)
...then I just get a permissions error
PermissionError: [Errno 1] Operation not permitted
What can I use as an alternate to setuid() so that I can launch a new child process on a MacOS system, after escalating privilege by getting authentication from the user in the GUI?
I want to be able to have them stay in the GUI, get presented with a pop-up that says "Uh, you need root to do that. Please enter your password."
This is exactly what the MacOS Security API's AuthorizationExecuteWithPrivileges() function was created for.
You can call AuthorizationExecuteWithPrivileges() directly with python's ctypes.
For example, consider your parent script running as your normal, non-root user. If you try to just run setuid(0), then it will fail with
PermissionError: [Errno 1] Operation not permitted
Instead, let's create another script named root_child.py, which we'll execute as root with AuthorizationExecuteWithPrivileges()
Child (root_child.py)
#!/usr/bin/env python3
import os
if __name__ == "__main__":
try:
os.setuid(9)
print( "I am root!" )
except Exception as e:
print( "I am not root :'(" )
Parent (spawn_root.py)
We can execute the above root_child.py script as root from our non-root script spawn_root.py:
import sys, ctypes, struct
import ctypes.util
from ctypes import byref
# import some C libraries for interacting via ctypes with the MacOS API
libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))
# https://developer.apple.com/documentation/security
sec = ctypes.cdll.LoadLibrary(ctypes.util.find_library("Security"))
kAuthorizationFlagDefaults = 0
auth = ctypes.c_void_p()
r_auth = byref(auth)
sec.AuthorizationCreate(None,None,kAuthorizationFlagDefaults,r_auth)
exe = [sys.executable,"root_child.py"]
args = (ctypes.c_char_p * len(exe))()
for i,arg in enumerate(exe[1:]):
args[i] = arg.encode('utf8')
io = ctypes.c_void_p()
print( "running root_child.py")
err = sec.AuthorizationExecuteWithPrivileges(auth,exe[0].encode('utf8'),0,args,byref(io))
print( "err:|" +str(err)+ "|" )
print( "root_child.py executed!")
Example Execution
Note that, because the credential challenge for AuthorizationExecuteWithPrivileges() comes via the GUI, you must execute this from within the GUI. If you attempt to execute the above scripts, for example, over a SSH in a tty, you'll get an error -60007, which is errAuthorizationInteractionNotAllowed and means:
The Security Server denied authorization because no user interaction is allowed.
user#host ~ % ./spawn_root.py
running root_child.py
err:|-60007|
root_child.py executed!
user#host ~ %
However, if executed from the Terminal app in the GUI, then it prompts the user for their password.
If the user successfully enters their credentials correctly, then the root_child.py script is executed with root privileges.
user#host ~ % ./spawn_root.py
running root_child.py
err:|0|
root_child.py executed!
Additional Information
Security
Note that AuthorizationExecuteWithPrivileges() has been deprecated by apple in-favor of an alternatve that requires you to pay them money. Unfortunately, there's some misinformation out there that AuthorizationExecuteWithPrivileges() is a huge security hole. While it's true that using AuthorizationExecuteWithPrivileges() incorrectly can cause security issues, it is not inherently insecure to use it.
Obviously, any time you run something as root, you need to be very careful!
AuthorizationExecuteWithPrivileges() is deprecated, but it can be used safely. But it can also be used unsafely!
It basically boils down to: do you actually know what you're running as root? If the script you're running as root is located in a Temp dir that has world-writeable permissions (as a lot of MacOS App installers have done historically), then any malicious process could gain root access.
To execute a process as root safely:
Make sure that the permissions on the process-to-be-launched are root:root 0400 (or writeable only by root)
Specify the absolute path to the process-to-be-launched, and don't allow any malicious modification of that path
Further Reading
AuthorizationExecuteWithPrivileges() Reference Documentation
https://github.com/cloudmatrix/esky/blob/master/esky/sudo/sudo_osx.py
https://github.com/BusKill/buskill-app/issues/14
https://www.jamf.com/blog/detecting-insecure-application-updates-on-macos/
How can i change to root user providing my password in the script?
I have this code
import os
# change to root user
# changing to root call this function
# example
os.sytem('reboot')
PS. not only this function but iptables too, so i need to change to root with out typing the password because i want to be automated.
If you don't want to do anything after the call to reboot, you can use os.exec*() to replace the current Python process with sudo, which will switch to the root user. Then, have sudo execute reboot as below.
import os
import shutil
SUDO_PATH = shutil.which('sudo')
if SUDO_PATH is None:
raise OSError('cannot find sudo executable')
os.execl(SUDO_PATH, SUDO_PATH, 'reboot')
For the cases where you wish do something after executing an external process, use subprocess.run().
I'm running the same Python script for different users on my PC (Windows 10). This script has to get the user who is actually logged in. For example getpass.getuser() isn't working because it just returns the user for which the Python script is running. How can I get this? Thanks for help!
The whole point of Run as... is to mimic the environment of another user so, naturally, when you query for the username (which essentially gets you the value of %USERNAME% env. variable) you'll get the one under which you're running the script.
To get the currently logged in user, you'll have prod the current session, and to do that, at the very least, you'll have to query WMIC (or access the Win32 API directly). Something like:
import subprocess
def get_session_user():
res = subprocess.check_output(["WMIC", "ComputerSystem", "GET", "UserName"],
universal_newlines=True)
_, username = res.strip().rsplit("\n", 1)
return username.rsplit("\\", 1)
Beware that this will return a tuple containing both the system/domain of the currently logged-in user and the username itself, so call it as:
system, username = get_session_user()
To get both.
RELATED: Python multiprocessing: Permission denied
I want to use Python's multiprocessing.Pool
import multiprocessing as mp
pool = mp.Pool(3)
for i in range(num_to_run):
pool.apply_async(popen_wrapper, args=(i,), callback=log_result)
I get OSError
File "/usr/local/lib/python2.6/multiprocessing/__init__.py", line 178, in RLock
return RLock()
File "/usr/local/lib/python2.6/multiprocessing/synchronize.py", line 142, in __init__
SemLock.__init__(self, RECURSIVE_MUTEX, 1, 1)
File "/usr/local/lib/python2.6/multiprocessing/synchronize.py", line 49, in __init__
sl = self._semlock = _multiprocessing.SemLock(kind, value, maxvalue)
OSError: [Errno 13] Permission denied
I read in the related question that it's due to not having r/w to /dev/shm
Besides changing the permission in /dev/shm, is there a way to run as root in the code?
I initially thought you could do something like os.umask() but it didnt work
EDIT (rephrasing the question):
let's say a username A has r/w access to directory A
You are user B and your program needs access to directory A. how do you run a program as user A?
In order from the least dangerous to the most dangerous.
You can try dropping permissions as John Zwinck suggested.
Basically you would start the program with root level permissions,
immediately do what you need to do, and then switch to a non-root
user.
From this StackOverflow.
import os, pwd, grp
def drop_privileges(uid_name='nobody', gid_name='nogroup'):
if os.getuid() != 0:
# We're not root so, like, whatever dude
return
# Get the uid/gid from the name
running_uid = pwd.getpwnam(uid_name).pw_uid
running_gid = grp.getgrnam(gid_name).gr_gid
# Remove group privileges
os.setgroups([])
# Try setting the new uid/gid
os.setgid(running_gid)
os.setuid(running_uid)
# Ensure a very conservative umask
old_umask = os.umask(077)
You could also require the credentials for the root user to be
inputed into the script, and then only use them when they are
required.
subprocess.call("sudo python RunStuffWithElevatedPrivelages.py")
#From here, the main script will continue to run without root permissions
Or if you don't want the script to prompt the user for the password you can do
subprocess.call("echo getRootCredentials() | sudo -S python RunStuffWithElevatedPrivelages.py")
Or you could just run the entire program as a root user -- sudo python myScript.py.
As far as temporarily giving users root permission to /dev/shm only when they run your script, the only thing I could think of was having some script that runs in the background under the root user that can temporarily grant anyone who uses your script root privileges to /dev/shm. This could be done through using setuid to grant such permissions and then after a certain amount of time or if the script ends the privilege is taken away. My only concern would be if there is a way a user who has temporarily been given such permissions might be able to secure more permanent privileges.
I have a script that needs to be run as a super user:
$ sudo ./python-script.py
Within this script, I do some other things that do not require super user privileges.
$ os.mkdir('somefolder')
What is the best/most efficient way of creating the directory as non-root user? Should I let the script make the directory as root user, and then change permissions on it?
os.mkdir does allow you to specify the permissions explicitly:
os.mkdir(path [, mode=0777])
And you also have the option of running os.chown to set the user and group
os.chown(path, uid, gid)
You can probably get the original user like this (but it might be platform specific?)
import os
original_user = os.environ.get('SUDO_USER')
original_uid = os.environ.get('SUDO_UID')
original_gid = os.environ.get('SUDO_GID')