def test_authenticate_ascii(fake_socket, packets): """ client -> AUTHSTART (username) STATUS_GETPASS <- server client -> AUTHCONTINUE (password) STATUS_PASS <- server """ client = TACACSClient('127.0.0.1', 49, None, session_id=12345) client._sock = fake_socket reply = client.authenticate('username', 'pass') assert reply.valid fake_socket.buff.seek(0) first_header = TACACSHeader.unpacked(fake_socket.buff.read(12)) assert (first_header.version_max, first_header.version_min) == (12, 0) first_body = fake_socket.buff.read(first_header.length) assert TACACSAuthenticationStart( 'username', TAC_PLUS_AUTHEN_TYPE_ASCII).packed == first_body second_header = TACACSHeader.unpacked(fake_socket.buff.read(12)) assert (first_header.version_max, first_header.version_min) == (12, 0) assert second_header.seq_no > first_header.seq_no second_body = fake_socket.buff.read() assert TACACSAuthenticationContinue('pass').packed == second_body
def login(): if request.method == 'POST': name = str(request.form['name']) password = str(request.form['password']) user = db.session.query(User).filter_by(name=name).first() if user and cisco_type7.verify(password, user.password): flask_login.login_user(user) return redirect(url_for('base_blueprint.dashboard')) else: try: # tacacs_plus does not support py2 unicode, hence the # conversion to string. # TACACSClient cannot be saved directly to session # as it is not serializable: this temporary fixes will create # a new instance of TACACSClient at each TACACS connection # attemp: clearly suboptimal, to be improved later. encrypted_password = cisco_type7.hash(password) tacacs_server = db.session.query(TacacsServer).one() tacacs_client = TACACSClient( str(tacacs_server.ip_address), int(tacacs_server.port), str(cisco_type7.decode(str(tacacs_server.password)))) if tacacs_client.authenticate( name, password, TAC_PLUS_AUTHEN_TYPE_ASCII).valid: user = User(name=name, password=encrypted_password) db.session.add(user) db.session.commit() flask_login.login_user(user) return redirect(url_for('base_blueprint.dashboard')) except NoResultFound: pass return render_template('errors/page_403.html') if not flask_login.current_user.is_authenticated: form = LoginForm(request.form) return render_template('login/login.html', form=form) return redirect(url_for('base_blueprint.dashboard'))
def test_authenticate_chap_challenge_required(): client = TACACSClient('127.0.0.1', 49, None, session_id=12345) with pytest.raises(ValueError): client.authenticate('username', 'pass', authen_type=TAC_PLUS_AUTHEN_TYPE_CHAP, chap_ppp_id='X')
def tacacs_authentication(self, user, name, password): if not hasattr(self, "tacacs_client"): self.tacacs_client = TACACSClient( environ.get("TACACS_ADDR"), 49, environ.get("TACACS_PASSWORD") ) success = self.tacacs_client.authenticate(name, password).valid return {"group": "Admin", "name": name} if success else False
def authenticate(self) -> None: try: client = TACACSClient(host=settings.TACACS_SVR, port=49, secret=settings.TACACS_KEY) if not client.authenticate(self.username, self.password).valid: raise errors.unauth_error("Incorrect username or password", "Basic") except ConnectionRefusedError: raise errors.server_error("Unable to connect to TACACS")
def test_authenticate_chap_challenge_length(): client = TACACSClient('127.0.0.1', 49, None, session_id=12345) with pytest.raises(ValueError) as e: client.authenticate('username', 'pass', authen_type=TAC_PLUS_AUTHEN_TYPE_CHAP, chap_ppp_id='A', chap_challenge='X' * 256) assert 'chap_challenge may not be more 255 bytes' in str(e)
def test_authorize_lesser_priv_lvl(fake_socket, packets): client = TACACSClient('127.0.0.1', 49, None, session_id=12345) client._sock = fake_socket reply = client.authorize( 'username', arguments=[b"service=shell", b"cmd=show", b"cmdargs=version"], authen_type=TAC_PLUS_AUTHEN_TYPE_PAP, priv_lvl=TAC_PLUS_PRIV_LVL_MAX) assert not reply.valid, "the privilege level sent by the server is less than the requested one (1 < 15)"
def test_authenticate_chap_ppp_id_length(): client = TACACSClient('127.0.0.1', 49, None, session_id=12345) with pytest.raises(ValueError) as e: client.authenticate('username', 'pass', authen_type=TAC_PLUS_AUTHEN_TYPE_CHAP, chap_ppp_id='AA', chap_challenge='challenge') assert 'chap_ppp_id must be a 1-byte string' in str(e)
def test_v4_sock(family): try: client = TACACSClient('127.0.0.1', 49, None, family=family) client.sock except socket.error: pass assert client._sock.family == family
class CustomController: def pre_init(self): pass def post_init(self): pass def ldap_authentication(self, user, name, password): if not hasattr(self, "ldap_server"): self.ldap_server = Server(getenv("LDAP_ADDR")) user = f"uid={name},dc=example,dc=com" success = Connection(self.ldap_server, user=user, password=password).bind() return {"name": name, "is_admin": True} if success else False def tacacs_authentication(self, user, name, password): if not hasattr(self, "tacacs_client"): self.tacacs_client = TACACSClient(getenv("TACACS_ADDR"), 49, getenv("TACACS_PASSWORD")) success = self.tacacs_client.authenticate(name, password).valid return {"name": name, "is_admin": True} if success else False def parse_configuration_property(self, device, property, value=None): if not value: value = getattr(device, property) if device.operating_system == "eos" and property == "configuration": value = sub(r"(username.*secret) (.*)", "\g<1> ********", value) return value
def login(): if request.method == 'POST': name = str(request.form['name']) user_password = str(request.form['password']) user = fetch(User, name=name) if user: if app.config['USE_VAULT']: pwd = vault_helper(app, f'user/{user.name}')['password'] else: pwd = user.password if user_password == pwd: login_user(user) return redirect(url_for('base_blueprint.dashboard')) else: try: # tacacs_plus does not support py2 unicode, hence the # conversion to string. # TACACSClient cannot be saved directly to session # as it is not serializable: this temporary fixes will create # a new instance of TACACSClient at each TACACS connection # attemp: clearly suboptimal, to be improved later. tacacs_server = db.session.query(TacacsServer).one() tacacs_client = TACACSClient( str(tacacs_server.ip_address), int(tacacs_server.port), str(tacacs_server.password) ) if tacacs_client.authenticate( name, user_password, TAC_PLUS_AUTHEN_TYPE_ASCII ).valid: user = User(name=name, password=user_password) db.session.add(user) db.session.commit() login_user(user) return redirect(url_for('base_blueprint.dashboard')) except NoResultFound: pass return render_template('errors/page_403.html') if not current_user.is_authenticated: return render_template( 'login.html', login_form=LoginForm(request.form), create_account_form=CreateAccountForm(request.form) ) return redirect(url_for('base_blueprint.dashboard'))
def tacacs_server(): if request.method == 'POST': tacacs_client = TACACSClient(request.form['ip_address'], request.form['port'], request.form['password'], request.form['timeout']) return _render_template('tacacs_server.html', form=TacacsServer(request.form))
def test_client_socket_send(fake_socket, packets, state): body = TACACSAuthenticationStart('user123', TAC_PLUS_AUTHEN_TYPE_ASCII) client = TACACSClient('127.0.0.1', 49, None, session_id=12345) client._sock = fake_socket packet = client.send(body, TAC_PLUS_AUTHEN) assert isinstance(packet, TACACSPacket) reply = TACACSAuthenticationReply.unpacked(packet.body) assert getattr(reply, state) is True # the first 12 bytes of the packet represent the header fake_socket.buff.seek(0) sent_header, sent_body = (fake_socket.buff.read(12), fake_socket.buff.read()) body_length = TACACSHeader.unpacked(sent_header).length assert len(sent_body) == body_length assert body.packed == sent_body
def test_authorize_ascii(fake_socket, packets): client = TACACSClient('127.0.0.1', 49, None, session_id=12345) client._sock = fake_socket reply = client.authorize( 'username', arguments=[b"service=shell", b"cmd=show", b"cmdargs=version"]) assert reply.valid fake_socket.buff.seek(0) first_header = TACACSHeader.unpacked(fake_socket.buff.read(12)) assert (first_header.version_max, first_header.version_min) == (12, 0) first_body = fake_socket.buff.read(first_header.length) assert TACACSAuthorizationStart( 'username', TAC_PLUS_AUTHEN_METH_TACACSPLUS, TAC_PLUS_PRIV_LVL_MIN, TAC_PLUS_AUTHEN_TYPE_ASCII, [b"service=shell", b"cmd=show", b"cmdargs=version"], ).packed == first_body
def test_authenticate_pap(fake_socket, packets): """ client -> AUTHSTART (user+pass) STATUS_PASS <- server """ client = TACACSClient('127.0.0.1', 49, None, session_id=12345) client._sock = fake_socket reply = client.authenticate('username', 'pass', authen_type=TAC_PLUS_AUTHEN_TYPE_PAP) assert reply.valid fake_socket.buff.seek(0) first_header = TACACSHeader.unpacked(fake_socket.buff.read(12)) assert (first_header.version_max, first_header.version_min) == (12, 1) first_body = fake_socket.buff.read(first_header.length) assert TACACSAuthenticationStart('username', TAC_PLUS_AUTHEN_TYPE_PAP, data=six.b('pass')).packed == first_body
def init_authentication(self): ldap_address, tacacs_address = getenv("LDAP_ADDR"), getenv("TACACS_ADDR") try: if ldap_address: self.ldap_server = Server(getenv("LDAP_ADDR")) if tacacs_address: self.tacacs_client = TACACSClient( getenv("TACACS_ADDR"), 49, getenv("TACACS_PASSWORD") ) except NameError as exc: warn(f"Module missing ({exc})")
def login(): if request.method == 'POST': username = str(request.form['username']) password = str(request.form['password']) user = db.session.query(User).filter_by(username=username).first() if user and password == user.password: flask_login.login_user(user) return redirect(url_for('base_blueprint.dashboard')) else: try: # tacacs_plus does not support py2 unicode, hence the # conversion to string. # TACACSClient cannot be saved directly to session # as it is not serializable: this temporary fixes will create # a new instance of TACACSClient at each TACACS connection # attemp: clearly suboptimal, to be improved later. tacacs_client = TACACSClient( str(session['ip_address']), int(session['port']), str(session['password']) ) if tacacs_client.authenticate( username, password, TAC_PLUS_AUTHEN_TYPE_ASCII ).valid: user = User(username=username, password=password) db.session.add(user) db.session.commit() flask_login.login_user(user) return redirect(url_for('base_blueprint.dashboard')) except KeyError: pass return render_template('errors/page_403.html') if not flask_login.current_user.is_authenticated: form = LoginForm(request.form) return render_template('login/login.html', form=form) return redirect(url_for('base_blueprint.dashboard'))
def test_authenticate_chap(fake_socket, packets): """ client -> AUTHSTART user+md5challenge(pass) STATUS_PASS <- server """ client = TACACSClient('127.0.0.1', 49, None, session_id=12345) client._sock = fake_socket reply = client.authenticate('username', 'pass', authen_type=TAC_PLUS_AUTHEN_TYPE_CHAP, chap_ppp_id='A', chap_challenge='challenge') assert reply.valid fake_socket.buff.seek(0) first_header = TACACSHeader.unpacked(fake_socket.buff.read(12)) assert (first_header.version_max, first_header.version_min) == (12, 1) first_body = fake_socket.buff.read(first_header.length) assert TACACSAuthenticationStart( 'username', TAC_PLUS_AUTHEN_TYPE_CHAP, data=(six.b('A') + six.b('challenge') + md5(six.b('Apasschallenge')).digest())).packed == first_body
class CustomController: def ldap_authentication(self, user, name, password): if not hasattr(self, "ldap_server"): self.ldap_server = Server(environ.get("LDAP_ADDR")) user = f"uid={name},dc=example,dc=com" success = Connection(self.ldap_server, user=user, password=password).bind() return {"name": name, "is_admin": True} if success else False def tacacs_authentication(self, user, name, password): if not hasattr(self, "tacacs_client"): self.tacacs_client = TACACSClient(environ.get("TACACS_ADDR"), 49, environ.get("TACACS_PASSWORD")) success = self.tacacs_client.authenticate(name, password).valid return {"name": name, "is_admin": True} if success else False
def authenticate(self, username, password): if not settings.TACACSPLUS_HOST: return None try: auth = TACACSClient( settings.TACACSPLUS_HOST.encode('utf-8'), settings.TACACSPLUS_PORT, settings.TACACSPLUS_SECRET.encode('utf-8'), timeout=settings.TACACSPLUS_SESSION_TIMEOUT, ).authenticate( username.encode('utf-8'), password.encode('utf-8'), TAC_PLUS_AUTHEN_TYPES[settings.TACACSPLUS_AUTH_PROTOCOL], ) except Exception as e: logger.exception("TACACS+ Authentication Error: %s" % (e.message, )) return None if auth.valid: return self._get_or_set_user(username, password) else: return None return None
}) ldap_client = Server(environ.get("LDAP_SERVER"), get_info=ALL) if USE_LDAP else None login_manager = LoginManager() login_manager.session_protection = "strong" mail_client = Mail() scheduler = BackgroundScheduler({ "apscheduler.jobstores.default": { "type": "sqlalchemy", "url": "sqlite:///jobs.sqlite", }, "apscheduler.executors.default": { "class": "apscheduler.executors.pool:ThreadPoolExecutor", "max_workers": "50", }, "apscheduler.job_defaults.misfire_grace_time": "5", "apscheduler.job_defaults.coalesce": "true", "apscheduler.job_defaults.max_instances": "3", }) scheduler.start() tacacs_client = (TACACSClient(environ.get("TACACS_ADDR"), 49, environ.get("TACACS_PASSWORD")) if USE_TACACS else None) vault_client = VaultClient()
def init_tacacs_client(self): self.tacacs_client = TACACSClient(self.settings["tacacs"]["address"], 49, environ.get("TACACS_PASSWORD"))
def test_client_socket_send_wrong_headers(fake_socket, packets): body = TACACSAuthenticationStart('user123', TAC_PLUS_AUTHEN_TYPE_ASCII) client = TACACSClient('127.0.0.1', 49, None, session_id=12345) client._sock = fake_socket with pytest.raises(socket.error): client.send(body, TAC_PLUS_AUTHEN)
def tacacs_authentication(self, user, name, password): if not hasattr(self, "tacacs_client"): self.tacacs_client = TACACSClient(getenv("TACACS_ADDR"), 49, getenv("TACACS_PASSWORD")) success = self.tacacs_client.authenticate(name, password).valid return {"name": name, "is_admin": True} if success else False
'max_workers': '50' }, 'apscheduler.job_defaults.misfire_grace_time': '5', 'apscheduler.job_defaults.coalesce': 'true', 'apscheduler.job_defaults.max_instances': '3' }) # Vault use_vault = int(environ.get('USE_VAULT', False)) vault_client = VaultClient() # Tacacs+ use_tacacs = int(environ.get('USE_TACACS', False)) tacacs_client = TACACSClient( environ.get('TACACS_ADDR'), 49, environ.get('TACACS_PASSWORD'), ) if use_tacacs else None # Syslog use_syslog = int(environ.get('USE_SYSLOG', False)) from eNMS.base.default import (create_default_services, create_default_parameters, create_default_pools, create_default_users, create_default_examples) from eNMS.base.helpers import fetch from eNMS.base.rest import configure_rest_api from eNMS.logs.models import SyslogServer def register_extensions(app):
token = line.split(";") # token[0] username, token[1] password def get_av_pair(arguments, key, default=None): ret = default for av in arguments: avf = av.split("=") if avf[0] == key: ret = avf[1] break return ret cli = TACACSClient('localhost', 49, 'testing123', timeout=10, family=socket.AF_INET) authen = cli.authenticate(token[0], token[1]) if authen.valid == True: auth = cli.authorize(token[0], arguments=["service=tailf"]) groups = get_av_pair(auth.arguments, key="groups") if groups != None: uid = get_av_pair(auth.arguments, key="uid", default=9000) gid = get_av_pair(auth.arguments, key="gid", default=100) home = "/var/confd/homes/{}".format(token[0]) print("accept {} {} {} {}".format(groups, uid, gid, home)) else: print( "reject Cannot retrieve groups AV pair (tailf service) for user {}" .format(token[0]))
from .forms import * from .properties import user_search_properties from tacacs_plus.client import TACACSClient from tacacs_plus.flags import * import flask_login blueprint = Blueprint('users_blueprint', __name__, url_prefix='/users', template_folder='templates') from main import app, db from base.routes import _render_template from .models import User tacacs_client = TACACSClient('10.253.60.125', 49, 'bts2007', timeout=10) @app.login_manager.request_loader def request_loader(request): username = request.form.get('username') user = db.session.query(User).filter_by(username=username).first() return user if user else None @blueprint.route('/overview') @login_required def users(): return _render_template('users_overview.html', fields=user_search_properties, users=User.query.all())
def init_tacacs_client(self) -> None: self.tacacs_client = TACACSClient(self.tacacs_addr, 49, self.tacacs_password)
username = arg elif opt in ("-p", "--password"): password = arg elif opt in ("-s", "--secret"): secret = arg # Check if necessary options are set if(host == "" or username == "" or password == "" or secret == ""): print("Missing mandatory parameters!") print("check_tacacs.py -h <host> -u <username> -p <password> -s <secret>") sys.exit(3) # initialize TACACS try: cli = TACACSClient(host, 49, secret, timeout=10, family=socket.AF_INET) except: print("Error connecting to TACACS server") exit(3) # authenticate user and pass try: authen = cli.authenticate(username, password) except: print("Error trying authentication") exit(3) if(authen.valid): print("OK") exit(0)