"""
Common code to handle privileges
"""
import grp
import logging.handlers
import os
import pwd
logger = logging.getLogger(__name__)
[docs]def drop_privileges(user: pwd.struct_passwd, group: grp.struct_group, permanent: bool = True):
"""
Drop root privileges and change to something more safe.
:param user: The tuple with user info
:param group: The tuple with group info
:param permanent: Whether we want to drop just the euid (temporary), or all uids (permanent)
"""
# Ensure a very conservative umask
os.umask(0o077)
# Don't do anything if we are already the right user
if os.geteuid() == user.pw_uid and os.getegid() == group.gr_gid:
logger.debug("Already {}/{}, not changing privileges".format(user.pw_name, group.gr_name))
return
# Restore euid=0 if we have previously changed it
if os.geteuid() != 0 and os.getuid() == 0:
restore_privileges()
# Remove group privileges
os.setgroups([])
if permanent: # pragma: no cover, we cannot test this
os.setgid(group.gr_gid)
os.setuid(user.pw_uid)
logger.debug("Permanently dropped privileges to {}/{}".format(user.pw_name, group.gr_name))
else:
os.setegid(group.gr_gid)
os.seteuid(user.pw_uid)
logger.debug("Dropped privileges to {}/{}".format(user.pw_name, group.gr_name))
[docs]def restore_privileges():
"""
Restore root privileges
"""
if os.getuid() != 0:
user = pwd.getpwuid(os.getuid())
logger.warning("Root privileges have been permanently dropped, continuing as {}".format(user.pw_name))
return
if os.geteuid() == 0 and os.getegid() == 0:
# Already root, don't need to do anything
return
os.seteuid(0)
os.setegid(0)
logger.debug("Restored root privileges")