Mini Shell
import os
import pwd
import grp
import re
import subprocess
import tempfile
from stat import S_IRUSR, S_IRGRP
class NoSuchUser(Exception):
def __init__(self, user):
message = 'No such user (%s)' % user
Exception.__init__(self, 'No such user (%s)' % (user,))
class NoSuchGroup(Exception):
def __init__(self, group):
message = 'No such group (%s)' % group
Exception.__init__(self, message)
class UnableToReadFile(Exception):
def __init__(self):
Exception.__init__(self, 'Cannot read sudoers file')
class UnableToWriteFile(Exception):
def __init__(self):
Exception.__init__(self, 'Cannot modify sudoers file')
ALIAS_LVECTL_CMDS = [ "/bin/ps", "/bin/grep", "/sbin/service", "/usr/bin/getcontrolpaneluserspackages",
"/usr/sbin/lvectl", "/usr/local/directadmin/plugins/new_lvemanager/admin/GetDomains" ]
ALIAS_SELECTOR_CMDS = [ "/usr/bin/cl-selector", "/usr/bin/piniset", "/usr/sbin/lveps", "/usr/bin/selectorctl" ]
DEFAULTS_REQUIRETTY = 'Defaults:%s !requiretty'
# Patterns for group
GROUP_LVECTL_SELECTOR = '%%%s ALL=NOPASSWD: LVECTL_CMDS, SELECTOR_CMDS'
GROUP_DEFAULTS_REQUIRETTY = 'Defaults:%%%s !requiretty'
class Clsudo(object):
"""
Adds CloudLinux users to sudoers file
"""
filepath = '/etc/sudoers'
temp_dir = '/etc'
temp_prefix = 'lve_sudoers_'
def add_user(user):
"""
Adds username to sudoers file
"""
Clsudo._check_user(user)
Clsudo._get_contents(user)
if not Clsudo.has_alias:
Clsudo.sudoers_list.append ( 'Cmnd_Alias LVECTL_CMDS = ' + ", ".join( ALIAS_LVECTL_CMDS ) )
if not Clsudo.has_selector_alias:
Clsudo.sudoers_list.append('Cmnd_Alias SELECTOR_CMDS = ' + ", ".join( ALIAS_SELECTOR_CMDS ))
if not Clsudo.has_rights:
Clsudo.sudoers_list.append('%s ALL=NOPASSWD: LVECTL_CMDS' % (user,))
if not Clsudo.has_selector_rights:
Clsudo.sudoers_list.append('%s ALL=NOPASSWD: SELECTOR_CMDS' % (user,))
if not Clsudo.has_action:
Clsudo.sudoers_list.append(DEFAULTS_REQUIRETTY % (user,))
Clsudo._write_contents()
add_user = staticmethod(add_user)
def add_cagefs_user(user):
"""
Adds username to sudoers file
"""
Clsudo._check_user(user)
Clsudo._get_contents(user)
if not Clsudo.has_cagefs_alias:
Clsudo.sudoers_list.append('Cmnd_Alias CAGEFS_CMDS = /usr/sbin/cagefsctl, '
'/bin/ps, /bin/grep, /sbin/service')
if not Clsudo.has_cagefs_rights:
Clsudo.sudoers_list.append('%s ALL=NOPASSWD: CAGEFS_CMDS' % (user,))
if not Clsudo.has_action:
Clsudo.sudoers_list.append(DEFAULTS_REQUIRETTY % (user,))
Clsudo._write_contents()
add_cagefs_user = staticmethod(add_cagefs_user)
def add_lvemanager_group(group_name):
"""
Adds group to sudoers file, grants access to LVE Manager
"""
Clsudo._check_group(group_name)
Clsudo._get_contents_group(group_name)
if not Clsudo.has_alias:
Clsudo.sudoers_list.append ( 'Cmnd_Alias LVECTL_CMDS = ' + ", ".join( ALIAS_LVECTL_CMDS ) )
if not Clsudo.has_selector_alias:
Clsudo.sudoers_list.append('Cmnd_Alias SELECTOR_CMDS = ' + ", ".join( ALIAS_SELECTOR_CMDS ))
if not Clsudo.has_action:
Clsudo.sudoers_list.append(GROUP_LVECTL_SELECTOR % (group_name,))
if not Clsudo.has_group_action:
Clsudo.sudoers_list.append(GROUP_DEFAULTS_REQUIRETTY % (group_name,))
# writes file
Clsudo._write_contents()
add_lvemanager_group = staticmethod(add_lvemanager_group)
def remove_user(user):
"""
Removes username from sudoers file
"""
try:
f = open(Clsudo.filepath)
Clsudo.sudoers_list = f.read().splitlines()
f.close()
idx = 0
removed = False
while idx < len(Clsudo.sudoers_list):
line = Clsudo.sudoers_list[idx]
if (('%s ALL=NOPASSWD:' % (user,)) in line) or ((DEFAULTS_REQUIRETTY % (user,))in line):
Clsudo.sudoers_list.remove(line)
removed = True
continue
idx += 1
if removed:
Clsudo._write_contents()
except (IOError, OSError):
raise UnableToReadFile()
remove_user = staticmethod(remove_user)
def update_user(user):
"""
updates username in sudoers file
"""
# Check user presence in system
Clsudo._check_user(user)
Clsudo._get_contents(user)
cmnd_dict = {"Cmnd_Alias LVECTL_CMDS":ALIAS_LVECTL_CMDS, "Cmnd_Alias SELECTOR_CMDS": ALIAS_SELECTOR_CMDS}
is_sudoer_change = 0
for idx in range(len(Clsudo.sudoers_list)):
comand_string = Clsudo.sudoers_list[idx]
for aliase_key, aliase_list in cmnd_dict.iteritems():
if aliase_key in comand_string:
comand_string = comand_string.replace(aliase_key,"").strip()
cmnd_list = comand_string.split(",")
for aliase_cmnd_item in aliase_list:
if aliase_cmnd_item not in cmnd_list:
is_sudoer_change = 1
Clsudo.sudoers_list[idx] = "%s = %s" % (aliase_key, ", ".join(aliase_list))
break
if(is_sudoer_change == 1):
Clsudo._write_contents()
update_user = staticmethod(update_user)
def _check_user(user):
"""
Checks passwd database for username presence
@param user: string
"""
try:
pwd.getpwnam(user)
except KeyError:
raise NoSuchUser(user)
_check_user = staticmethod(_check_user)
def _check_group(group_name):
"""
Checks grp database for group_name presence
@param group_name: string
"""
try:
grp.getgrnam(group_name)
except KeyError:
raise NoSuchGroup(group_name)
_check_group = staticmethod(_check_group)
def _get_contents(user):
"""
Reads file into list of strings
@param filename: string
"""
# Clear all status flags
Clsudo.has_action = False
Clsudo.has_group_action = False
Clsudo.has_alias = False
Clsudo.has_rights = False
Clsudo.has_selector_alias = False
Clsudo.has_selector_rights = False
Clsudo.has_cagefs_alias = False
Clsudo.has_cagefs_rights = False
require_tty_pattern = re.compile(r'Defaults:\s*%s\s*!requiretty' % user)
try:
i = open(Clsudo.filepath)
Clsudo.sudoers_list = i.read().splitlines()
i.close()
for idx in range(len(Clsudo.sudoers_list)):
if "Cmnd_Alias LVECTL_CMDS" in Clsudo.sudoers_list[idx]:
Clsudo.has_alias = True
continue
if "Cmnd_Alias CAGEFS_CMDS" in Clsudo.sudoers_list[idx]:
Clsudo.has_cagefs_alias = True
continue
if ("%s ALL=NOPASSWD: LVECTL_CMDS" % (user,)
in Clsudo.sudoers_list[idx]):
Clsudo.has_rights = True
continue
if "%s ALL=NOPASSWD: CAGEFS_CMDS" % (user,) in Clsudo.sudoers_list[idx]:
Clsudo.has_cagefs_rights = True
continue
if "requiretty" in Clsudo.sudoers_list[idx]:
pattern_match = require_tty_pattern.search(
Clsudo.sudoers_list[idx])
if pattern_match:
Clsudo.has_action = True
continue
if "Cmnd_Alias SELECTOR_CMDS" in Clsudo.sudoers_list[idx]:
if 'piniset' not in Clsudo.sudoers_list[idx]:
Clsudo.sudoers_list[idx] = Clsudo.sudoers_list[idx].replace(
'/usr/bin/cl-selector',
'/usr/bin/cl-selector, /usr/bin/piniset')
if 'lveps' not in Clsudo.sudoers_list[idx]:
Clsudo.sudoers_list[idx] = Clsudo.sudoers_list[idx].replace(
'/usr/bin/cl-selector, /usr/bin/piniset',
'/usr/bin/cl-selector, /usr/bin/piniset, /usr/sbin/lveps')
Clsudo.has_selector_alias = True
continue
if ("%s ALL=NOPASSWD: SELECTOR_CMDS" % (user,)
in Clsudo.sudoers_list[idx]):
Clsudo.has_selector_rights = True
continue
except (IOError, OSError):
raise UnableToReadFile()
_get_contents = staticmethod(_get_contents)
def _get_contents_group(group_name):
"""
Reads file into list of strings
@param group_name: string
"""
# Clear all status flags
Clsudo.has_action = False
Clsudo.has_group_action = False
Clsudo.has_alias = False
Clsudo.has_rights = False
Clsudo.has_selector_alias = False
Clsudo.has_selector_rights = False
Clsudo.has_cagefs_alias = False
Clsudo.has_cagefs_rights = False
group_prefix = "%%%s" % group_name
group_action = "Defaults:%%%s" % group_name
group_pattern = re.compile(r'%s\s*ALL=NOPASSWD:\s*LVECTL_CMDS,\s*SELECTOR_CMDS' % (group_name,))
try:
i = open(Clsudo.filepath)
Clsudo.sudoers_list = i.read().splitlines()
i.close()
for idx in range(len(Clsudo.sudoers_list)):
if "Cmnd_Alias SELECTOR_CMDS" in Clsudo.sudoers_list[idx]:
if 'piniset' not in Clsudo.sudoers_list[idx]:
Clsudo.sudoers_list[idx] = Clsudo.sudoers_list[idx].replace(
'/usr/bin/cl-selector',
'/usr/bin/cl-selector, /usr/bin/piniset')
if 'lveps' not in Clsudo.sudoers_list[idx]:
Clsudo.sudoers_list[idx] = Clsudo.sudoers_list[idx].replace(
'/usr/bin/cl-selector, /usr/bin/piniset',
'/usr/bin/cl-selector, /usr/bin/piniset, /usr/sbin/lveps')
Clsudo.has_selector_alias = True
continue
if "Cmnd_Alias LVECTL_CMDS" in Clsudo.sudoers_list[idx]:
Clsudo.has_alias = True
continue
if "Cmnd_Alias CAGEFS_CMDS" in Clsudo.sudoers_list[idx]:
Clsudo.has_cagefs_alias = True
continue
if Clsudo.sudoers_list[idx].startswith(group_prefix):
pattern_match = group_pattern.search(Clsudo.sudoers_list[idx])
if pattern_match:
Clsudo.has_action = True
if Clsudo.sudoers_list[idx].startswith(group_action):
Clsudo.has_group_action = True
if Clsudo.sudoers_list[idx].startswith(group_action):
Clsudo.has_group_action = True
except (IOError, OSError):
raise UnableToReadFile()
_get_contents_group = staticmethod(_get_contents_group)
def _write_contents():
"""
Writes data to temporary file then checks it and rewrites sudoers file
"""
try:
fd, temp_path = tempfile.mkstemp(
prefix=Clsudo.temp_prefix, dir=Clsudo.temp_dir)
fo = os.fdopen(fd, 'w')
fo.write('\n'.join(Clsudo.sudoers_list) + '\n')
fo.close()
mask = S_IRUSR | S_IRGRP
os.chmod(temp_path, mask)
if not Clsudo._is_file_valid(temp_path):
raise IOError
except (IOError, OSError):
try:
if os.path.exists(temp_path):
os.unlink(temp_path)
except:
pass
raise UnableToWriteFile()
try:
os.rename(temp_path, Clsudo.filepath)
except OSError:
raise UnableToWriteFile()
_write_contents = staticmethod(_write_contents)
def _is_file_valid(filename):
cmd = [
'/usr/sbin/visudo',
'-c',
'-f', filename
]
rv = subprocess.Popen(
cmd,
stdin=open('/dev/null'),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
close_fds=True)
rt = rv.communicate()
if rv.returncode != 0:
return False
return True
_is_file_valid = staticmethod(_is_file_valid)
Zerion Mini Shell 1.0