File refactored_auth_module.diff of Package cobbler

diff --git a/cobbler/modules/authentication/spacewalk.py b/cobbler/modules/authentication/spacewalk.py
index c553c8e6f..2bd1c918b 100644
--- a/cobbler/modules/authentication/spacewalk.py
+++ b/cobbler/modules/authentication/spacewalk.py
@@ -21,10 +21,14 @@
 02110-1301  USA
 """
 
-
 from future import standard_library
+
 standard_library.install_aliases()
-import xmlrpc.client
+
+from cobbler.cexceptions import CX
+from cobbler.utils import log_exc
+from cobbler import clogger
+from xmlrpc.client import ServerProxy, Error
 
 
 def register():
@@ -40,32 +44,66 @@ def __looks_like_a_token(password):
     /likely/ a token, and we should try to treat it as a token first, if not, we should treat it as a password.  All of
     this code is there to avoid extra XMLRPC calls, which are slow.
 
+    A password gets detected as a token if it is lowercase and under 45 characters.
+
     :param password: The password which is possibly a token.
     :return: True if it is possibly a token or False otherwise.
     :rtype: bool
     """
 
-    if password.lower() != password:
-        # Tokens are always lowercase, this isn't a token.
+    return password.lower() == password and len(password) > 45
+
+
+def __check_auth_token(xmlrpc_client, api_handle, username, password):
+    """
+    This checks if the auth token is valid.
+    :param xmlrpc_client: The xmlrpc client to check access for.
+    :param api_handle: The api instance to retrieve settings of.
+    :param username: The username to try.
+    :param password: The password to try.
+    :return: In any error case this will return 0. Otherwise the return value of the API which should be 1.
+    """
+    # If the token is not a token this will raise an exception rather than return an integer.
+    try:
+        return xmlrpc_client.auth.checkAuthToken(username, password)
+    except Error:
+        logger = api_handle.logger
+        logger.error("Error while checking authentication token.")
+        log_exc(logger)
         return False
 
-    # We can't use binascii.unhexlify here as it's an "odd length string".
-    # try:
-    #    #data = binascii.unhexlify(password)
-    #    return True # looks like a token, but we can't be sure
-    # except:
-    #    return False # definitely not a token
 
-    return (len(password) > 45)
+def __check_user_login(xmlrpc_client, api_handle, user_enabled, username, password):
+    """
+    This actually performs the login to spacewalk.
+
+    :param xmlrpc_client: The xmlrpc client bound to the target spacewalk instance.
+    :param api_handle: The api instance to retrieve settings of.
+    :param user_enabled: Weather we allow Spacewalk users to log in or not.
+    :type user_enabled: bool
+    :param username: The username to log in.
+    :param password: The password to log in.
+    :return: True if users are allowed to log in and he is of the role ``config_admin`` or ``org_admin``.
+    """
+    try:
+        session = xmlrpc_client.auth.login(username, password)
+        # login success by username, role must also match and user_enabled needs to be true.
+        roles = xmlrpc_client.user.listRoles(session, username)
+        if user_enabled and ("config_admin" in roles or "org_admin" in roles):
+            return True
+    except Error:
+        logger = api_handle.logger
+        logger.error("Error while checking user authentication data.")
+        log_exc(logger)
+    return False
 
 
 def authenticate(api_handle, username, password):
     """
-    Validate a username/password combo, returning True/False
-
-    This will pass the username and password back to Spacewalk to see if this authentication request is valid.
+    Validate a username/password combo. This will pass the username and password back to Spacewalk to see if this
+    authentication request is valid.
 
-    See also: https://github.com/uyuni-project/uyuni/blob/bbbbbf537a1928c1922015c70322034a89b1cb9a/java/code/src/com/redhat/rhn/frontend/xmlrpc/auth/AuthHandler.java#L133
+    See also: https://github.com/uyuni-project/uyuni/blob/master/java/code/src/com/redhat/rhn/frontend/xmlrpc/auth/AuthHandler.java#L133
 
     :param api_handle: The api instance to retrieve settings of.
     :param username: The username to authenticate agains spacewalk/uyuni/SUSE Manager
@@ -74,78 +112,25 @@ def authenticate(api_handle, username, password):
     :rtype: bool
     """
 
-    if api_handle is not None:
-        server = api_handle.settings().redhat_management_server
-        user_enabled = api_handle.settings().redhat_management_permissive
-    else:
-        server = "columbia.devel.redhat.com"
-        user_enabled = True
-
-    if server == "xmlrpc.rhn.redhat.com":
-        # Emergency fail, don't bother RHN!
-        return False
+    if api_handle is None:
+        raise CX("api_handle required. Please don't call this without it.")
+    server = api_handle.settings().redhat_management_server
+    user_enabled = api_handle.settings().redhat_management_permissive
 
     spacewalk_url = "https://%s/rpc/api" % server
-    client = xmlrpc.client.Server(spacewalk_url, verbose=0)
-
-    if __looks_like_a_token(password) or username == 'taskomatic_user':
-        # The tokens are lowercase hex, but a password can also be lowercase hex, so we have to try it as both a token
-        # and then a password if we are unsure. We do it this way to be faster but also to avoid any login failed stuff
-        # in the logs that we don't need to send.
-
-        try:
-            valid = client.auth.checkAuthToken(username, password)
-        except:
-            # If the token is not a token this will raise an exception rather than return an integer.
-            valid = 0
-
-        # Problem at this point, 0xdeadbeef is valid as a token but if that fails, it's also a valid password, so we
-        # must try auth system #2
-
-        if valid != 1:
-            # First API code returns 1 on success the second uses exceptions for login failed.
-            # So... token check failed, but maybe the username/password is just a simple username/pass!
-
-            if user_enabled == 0:
-                # this feature must be explicitly enabled.
-                return False
-
-            session = ""
-            try:
-                session = client.auth.login(username, password)
-            except:
-                # FIXME: Should log exceptions that are not excepted as we could detect spacewalk java errors here that
-                #        are not login related.
-                return False
-
-            # login success by username, role must also match
-            roles = client.user.listRoles(session, username)
-            if not ("config_admin" in roles or "org_admin" in roles):
-                return False
-
-        return True
-
-    else:
-        # It's an older version of spacewalk, so just try the username/pass.
-        # OR: We know for sure it's not a token because it's not lowercase hex.
-
-        if user_enabled == 0:
-            # this feature must be explicitly enabled.
-            return False
-
-        session = ""
-        try:
-            session = client.auth.login(username, password)
-        except:
-            return False
-
-        # login success by username, role must also match
-        roles = client.user.listRoles(session, username)
-        if not ("config_admin" in roles or "org_admin" in roles):
-            return False
-
-        return True
-
-
-if __name__ == "__main__":
-    print((authenticate(None, "admin", "redhat")))
+    with ServerProxy(spacewalk_url, verbose=True) as client:
+        if username == 'taskomatic_user' or __looks_like_a_token(password):
+            # The tokens are lowercase hex, but a password can also be lowercase hex, so we have to try it as both a
+            # token and then a password if we are unsure. We do it this way to be faster but also to avoid any login
+            # failed stuff in the logs that we don't need to send.
+
+            # Problem at this point, 0xdeadbeef is valid as a token but if that fails, it's also a valid password, so we
+            # must try auth system #2
+
+            if __check_auth_token(client, api_handle, username, password) != 1:
+                return __check_user_login(client, api_handle, user_enabled, username, password)
+            return True
+        else:
+            # It's an older version of spacewalk, so just try the username/pass.
+            # OR: We know for sure it's not a token because it's not lowercase hex.
+            return __check_user_login(client, api_handle, user_enabled, username, password)
openSUSE Build Service is sponsored by