0
votes

I'm working on a project for university where I have to verify credentials as a last step. I should verify if those credentials are valid and I don't have to connect to any service or gain any rights. I'm a bloody beginner in this feeld so please be patient if I fail to provide enough information. If you ask I will do my best to update this post with the requested information.

I'm working on Ubuntu Server 18.04. with Python 3.6. I have the kerberos 5 client software successfully installed on my device and a Realm set up of an existing kdc and krb5 server. Also I have gssapi installed successfully via pip. (I didn't verify but this suggested success Successfully installed gssapi-1.6.5)

I am able to perform a kinit. How can I perform a kinit with gssapi and evaluate if it was successful or not? I just need a True/False value and a kdestroy afterwards.

I'm working with this tutorial but I don't really know what to put there and what I really need. If I got it right, I just need to build a SecurityContext for the credentials and destroy it afterwards like kinit username and kdestroy in my terminal, is this right? In the tutorial it says:

>>> server_hostbased_name = gssapi.Name('HTTP@' + FQDN, name_type=gssapi.NameType.hostbased_service)
>>> server_hostbased_name
Name(b'HTTP@sross', <OID 1.2.840.113554.1.2.1.4>)
>>> server_name = gssapi.Name('HTTP/sross@')
>>> server_name
Name(b'HTTP/sross@', None)

When I perform kinit username enter the correct password and klist afterwards I get:

~$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: [email protected]

Valid starting     Expires            Service principal
05/08/20 14:35:31  05/09/20 14:35:23  krbtgt/[email protected]

Did I get it right that for my case the first two lines from the tutorial won't suit my case and that I can just set server_name = gssapi.Name('krbtgt/DOMAIN.COM@') ? That's just for basic understanding.

In the tutorial I can't find any method to verify credentials username with corresponding password, can anyone tell me how to do it or show me a tutorial which is about verifying those credentials against my kerberos server?

Thanks in advance!

Update: What I found here is the following code (I shortened the _acquire_creds method as it contained more functionality than I needed). Maybe this helps you with explaining it to me?:

def __init__(self, username, password, server):
    log.info("Setting up GSSAPI Security Context for Kerberos auth")
    self.creds = self._acquire_creds(username, password)

    server_spn = "cifs@%s" % server
    log.debug("GSSAPI Server SPN Target: %s" % server_spn)
    server_name = gssapi.Name(base=server_spn,
                              name_type=gssapi.NameType.hostbased_service)
    self.context = gssapi.SecurityContext(name=server_name,
                                          creds=self.creds,
                                          usage='initiate')

def _acquire_creds(self, username, password):
    # 3 use cases with Kerberos Auth
    #   1. Both the user and pass is supplied so we want to create a new
    #      ticket with the pass
    #   2. Only the user is supplied so we will attempt to get the cred
    #      from the existing store
    #   3. The user is not supplied so we will attempt to get the default
    #      cred from the existing store
    log.info("GSSAPI: Acquiring credentials handle")
    if username and password:
        log.debug("GSSAPI: Acquiring credentials handle for user %s with "
                  "password" % username)
        user = gssapi.Name(base=username,
                           name_type=gssapi.NameType.user)
        bpass = password.encode('utf-8')
        try:
            creds = gssapi.raw.acquire_cred_with_password(user, bpass,
                                                          usage='initiate')
        except AttributeError:
            raise SMBAuthenticationError("Cannot get GSSAPI credential "
                                         "with password as the necessary "
                                         "GSSAPI extensions are not "
                                         "available")
        except gssapi.exceptions.GSSError as er:
            raise SMBAuthenticationError("Failed to acquire GSSAPI "
                                         "credential with password: %s"
                                         % str(er))
        # acquire_cred_with_password returns a wrapper, we want the creds
        # object inside this wrapper
        creds = creds.creds

    log.info("GSSAPI: Acquired credentials for user %s" % str(user))
    return creds
1
Just an unrelated note -- I don't know how your project is structured, but if you're doing this password verification in the server then it's not really making good use of Kerberos... it's just using the KDC as a dumb credential database but not actually protecting the credentials.user1686
I use it just to see if the credentials are valid, like checking a database with plaintext credentials. How would I do it in a more secure way, I'm completely new to this feeld and this is just a small component. I have no access to a plaintext database because I have to implement my project into an existing infrastructure...Cal Blau

1 Answers

0
votes

It seems like asking the question with all of its details was enough to get the answer. This code workes for me and lets me verify given username and password. What I am not sure about yet is if I have to perform some kind of kdestroy to "close" the context in the end. I will try to update this answer as soon as I figure it out.

import gssapi

server_name = gssapi.Name('krbtgt/DOMAIN.COM@')

username = "USERNAME"
password = "PASSWORD"

user = gssapi.Name(base=username, name_type=gssapi.NameType.user)
bpass = password.encode('utf-8')
result = False
try:
    creds = gssapi.raw.acquire_cred_with_password(user, bpass, usage='initiate')
    creds = creds.creds
    context = gssapi.SecurityContext(name=server_name, creds=creds, usage='initiate')
    result = True
except AttributeError:
    print("AttributeError")
except gssapi.exceptions.GSSError as er:
    print(er)
# acquire_cred_with_password returns a wrapper, we want the creds
# object inside this wrapper
print(result)