diff options
Diffstat (limited to 'src/conf_mode/system-login.py')
-rwxr-xr-x | src/conf_mode/system-login.py | 102 |
1 files changed, 51 insertions, 51 deletions
diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py index 23152fee0..43732cfae 100755 --- a/src/conf_mode/system-login.py +++ b/src/conf_mode/system-login.py @@ -14,36 +14,22 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import sys import os -import jinja2 +from jinja2 import FileSystemLoader, Environment +from psutil import users from pwd import getpwall, getpwnam from stat import S_IRUSR, S_IWUSR, S_IRWXU, S_IRGRP, S_IXGRP -from subprocess import Popen, PIPE, STDOUT -from psutil import users +from sys import exit from vyos.config import Config from vyos.configdict import list_diff +from vyos.defaults import directories as vyos_data_dir from vyos import ConfigError +from vyos.util import cmd +from vyos.util import call radius_config_file = "/etc/pam_radius_auth.conf" -radius_config_tmpl = """ -# Automatically generated by VyOS -# RADIUS configuration file -{%- if radius_server %} -# server[:port] shared_secret timeout (s) source_ip -{% for s in radius_server %} -{%- if not s.disabled -%} -{{ s.address }}:{{ s.port }} {{ s.key }} {{ s.timeout }} {% if radius_source_address -%}{{ radius_source_address }}{% endif %} -{% endif %} -{%- endfor %} - -priv-lvl 15 -mapped_priv_user radius_priv_user -{% endif %} - -""" default_config_data = { 'deleted': False, @@ -67,10 +53,7 @@ def get_local_users(): def get_crypt_pw(password): - command = '/usr/bin/mkpasswd --method=sha-512 {}'.format(password) - p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True) - tmp = p.communicate()[0].strip() - return tmp.decode() + return cmd(f'/usr/bin/mkpasswd --method=sha-512 {password}') def get_config(): @@ -196,6 +179,14 @@ def verify(login): if cur_user in login['del_users']: raise ConfigError('Attempting to delete current user: {}'.format(cur_user)) + for user in login['add_users']: + for key in user['public_keys']: + if not key['type']: + raise ConfigError('SSH public key type missing for "{}"!'.format(key['name'])) + + if not key['key']: + raise ConfigError('SSH public key for id "{}" missing!'.format(key['name'])) + # At lease one RADIUS server must not be disabled if len(login['radius_server']) > 0: fail = True @@ -221,7 +212,12 @@ def generate(login): os.system("vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set system login user '{}' authentication encrypted-password '{}' >/dev/null".format(user['name'], user['password_encrypted'])) if len(login['radius_server']) > 0: - tmpl = jinja2.Template(radius_config_tmpl) + # Prepare Jinja2 template loader from files + tmpl_path = os.path.join(vyos_data_dir['data'], 'templates', 'system-login') + fs_loader = FileSystemLoader(tmpl_path) + env = Environment(loader=fs_loader) + + tmpl = env.get_template('pam_radius_auth.conf.tmpl') config_text = tmpl.render(login) with open(radius_config_file, 'w') as f: f.write(config_text) @@ -240,40 +236,44 @@ def apply(login): for user in login['add_users']: # make new user using vyatta shell and make home directory (-m), # default group of 100 (users) - cmd = "useradd -m -N" + command = "useradd -m -N" # check if user already exists: if user['name'] in get_local_users(): # update existing account - cmd = "usermod" + command = "usermod" # we need to use '' quotes when passing formatted data to the shell # else it will not work as some data parts are lost in translation - cmd += " -p '{}'".format(user['password_encrypted']) - cmd += " -s /bin/vbash" + command += " -p '{}'".format(user['password_encrypted']) + command += " -s /bin/vbash" if user['full_name']: - cmd += " -c '{}'".format(user['full_name']) + command += " -c '{}'".format(user['full_name']) if user['home_dir']: - cmd += " -d '{}'".format(user['home_dir']) + command += " -d '{}'".format(user['home_dir']) - cmd += " -G frrvty,vyattacfg,sudo,adm,dip,disk" - cmd += " {}".format(user['name']) + command += " -G frrvty,vyattacfg,sudo,adm,dip,disk" + command += " {}".format(user['name']) try: - os.system(cmd) + call(command) uid = getpwnam(user['name']).pw_uid gid = getpwnam(user['name']).pw_gid + # we should not rely on the home dir value stored in user['home_dir'] + # as if a crazy user will choose username root or any other system + # user this will fail. should be deny using root at all? + home_dir = getpwnam(user['name']).pw_dir # install ssh keys - key_dir = '{}/.ssh'.format(user['home_dir']) - if not os.path.isdir(key_dir): - os.mkdir(key_dir) - os.chown(key_dir, uid, gid) - os.chmod(key_dir, S_IRWXU | S_IRGRP | S_IXGRP) - - key_file = key_dir + '/authorized_keys'; - with open(key_file, 'w') as f: + ssh_key_dir = home_dir + '/.ssh' + if not os.path.isdir(ssh_key_dir): + os.mkdir(ssh_key_dir) + os.chown(ssh_key_dir, uid, gid) + os.chmod(ssh_key_dir, S_IRWXU | S_IRGRP | S_IXGRP) + + ssh_key_file = ssh_key_dir + '/authorized_keys'; + with open(ssh_key_file, 'w') as f: f.write("# Automatically generated by VyOS\n") f.write("# Do not edit, all changes will be lost\n") @@ -285,8 +285,8 @@ def apply(login): line += '{} {} {}\n'.format(id['type'], id['key'], id['name']) f.write(line) - os.chown(key_file, uid, gid) - os.chmod(key_file, S_IRUSR | S_IWUSR) + os.chown(ssh_key_file, uid, gid) + os.chmod(ssh_key_file, S_IRUSR | S_IWUSR) except Exception as e: raise ConfigError('Adding user "{}" raised an exception: {}'.format(user['name'], e)) @@ -296,10 +296,10 @@ def apply(login): # Logout user if he is logged in if user in list(set([tmp[0] for tmp in users()])): print('{} is logged in, forcing logout'.format(user)) - os.system('pkill -HUP -u {}'.format(user)) + call('pkill -HUP -u {}'.format(user)) # Remove user account but leave home directory to be safe - os.system('userdel -r {} 2>/dev/null'.format(user)) + call('userdel -r {} 2>/dev/null'.format(user)) except Exception as e: raise ConfigError('Deleting user "{}" raised an exception: {}'.format(user, e)) @@ -313,7 +313,7 @@ def apply(login): os.system("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --enable radius") # Make NSS system aware of RADIUS, too - cmd = "sed -i -e \'/\smapname/b\' \ + command = "sed -i -e \'/\smapname/b\' \ -e \'/^passwd:/s/\s\s*/&mapuid /\' \ -e \'/^passwd:.*#/s/#.*/mapname &/\' \ -e \'/^passwd:[^#]*$/s/$/ mapname &/\' \ @@ -321,7 +321,7 @@ def apply(login): -e \'/^group:[^#]*$/s/: */&mapname /\' \ /etc/nsswitch.conf" - os.system(cmd) + call(command) except Exception as e: raise ConfigError('RADIUS configuration failed: {}'.format(e)) @@ -331,13 +331,13 @@ def apply(login): # Disable RADIUS in PAM os.system("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --remove radius") - cmd = "sed -i -e \'/^passwd:.*mapuid[ \t]/s/mapuid[ \t]//\' \ + command = "sed -i -e \'/^passwd:.*mapuid[ \t]/s/mapuid[ \t]//\' \ -e \'/^passwd:.*[ \t]mapname/s/[ \t]mapname//\' \ -e \'/^group:.*[ \t]mapname/s/[ \t]mapname//\' \ -e \'s/[ \t]*$//\' \ /etc/nsswitch.conf" - os.system(cmd) + call(command) except Exception as e: raise ConfigError('Removing RADIUS configuration failed'.format(e)) @@ -352,4 +352,4 @@ if __name__ == '__main__': apply(c) except ConfigError as e: print(e) - sys.exit(1) + exit(1) |