diff --git a/src/sambal/client.py b/src/sambal/client.py index 63e763f..273c111 100644 --- a/src/sambal/client.py +++ b/src/sambal/client.py @@ -1,52 +1,62 @@ from typing import Optional -from ldb import LdbError from samba.auth import system_session from samba.credentials import Credentials from samba.param import LoadParm from samba.samdb import SamDB -def connect_samdb(username, password, host, realm=None) -> Optional[SamDB]: - """Connect to Samba or Windows host and return SamDB on success.""" - if host and username and password: - if host.startswith(("ldap://", "ldaps://")): - url = host - else: - url = f"ldap://{host}" +def connect_samdb(host, username, password, realm=None) -> SamDB: + """Connect to Samba or Windows host and return SamDB on success. - lp = LoadParm() - lp.load_default() + :param host: Host name or URL + :param username: Account name + :param password: Account password + :param realm: Optional realm + :raises LdbError: on failure, caller should handle error. + """ + if host.startswith(("ldap://", "ldaps://")): + url = host + else: + url = f"ldap://{host}" + + lp = LoadParm() + lp.load_default() - creds = Credentials() - creds.set_username(username) - creds.set_password(password) + creds = Credentials() + creds.set_username(username) + creds.set_password(password) - if realm: - creds.set_realm(realm) + if realm: + creds.set_realm(realm) - try: - return SamDB( - url=url, - session_info=system_session(), - credentials=creds, - lp=lp, - ) - except LdbError: - return None + return SamDB( + url=url, + session_info=system_session(), + credentials=creds, + lp=lp, + ) def get_samdb(request) -> Optional[SamDB]: """Returns a SamDB connection to be used via the request.samdb property. + Fetch credentials out of the session after user has logged in. + All keys except for realm must be present. + + For this to be secure the session MUST be a backend session only, + with a password on Redis and a unique session secret different to the + authtkt cookie secret. + :param request: Pyramid request object :return: SamDB or None if no credentials in session + :raises LdbError: On connection error or if the credentials no longer work """ - # Fetch credentials out of the session after user logs in. - # For this to be secure the session MUST be a backend session only. - username = request.session.get("samba.username") - password = request.session.get("samba.password") - host = request.session.get("samba.host") - realm = request.session.get("samba.realm") - - return connect_samdb(username, password, host, realm) + try: + host = request.session["samba.host"] + username = request.session["samba.username"] + password = request.session["samba.password"] + realm = request.session.get("samba.realm") + return connect_samdb(host, username, password, realm) + except KeyError: + return None diff --git a/src/sambal/security.py b/src/sambal/security.py index 24a9ed9..2cdb474 100644 --- a/src/sambal/security.py +++ b/src/sambal/security.py @@ -1,5 +1,6 @@ from typing import Optional +from ldb import LdbError from pyramid.authentication import AuthTktCookieHelper from pyramid.interfaces import ISecurityPolicy from pyramid.security import forget, remember @@ -41,13 +42,16 @@ def forget(self, request, **kwargs): def login(request, username, password, host, realm): """Log into server and put credentials in session on success only.""" - samdb = connect_samdb(username, password, host, realm) - if samdb and (user_sid := samdb.connecting_user_sid): - request.session["samba.username"] = username - request.session["samba.password"] = password - request.session["samba.host"] = host - request.session["samba.realm"] = realm - return remember(request, user_sid) + try: + samdb = connect_samdb(host, username, password, realm) + if user_sid := samdb.connecting_user_sid: + request.session["samba.username"] = username + request.session["samba.password"] = password + request.session["samba.host"] = host + request.session["samba.realm"] = realm + return remember(request, user_sid) + except LdbError: + pass def logout(request):