"""
Authentication module that uses Spacewalk's auth system.
Any org_admin or kickstart_admin can get in.
"""
from future import standard_library
standard_library.install_aliases()
import xmlrpc.client
[docs]def register():
"""
The mandatory cobbler module registration hook.
"""
return "authn"
def __looks_like_a_token(password):
# what spacewalk sends us could be an internal token or it could be a password
# if it's long and lowercase hex, it's /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.
# we can't use binascii.unhexlify here as it's an "odd length string"
if password.lower() != password:
# tokens are always lowercase, this isn't a token
return False
# 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)
[docs]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.
See also: http://www.redhat.com/spacewalk/documentation/api/0.4/
"""
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":
return False # emergency fail, don't bother RHN!
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")))