Score:0

Add member to kerberos domain programatically

cn flag

I want to have an embedded device join a Linux based AD/DC domain. I have kerberos libraries (no executables) on the embedded device. I have an application on the embedded device that can successfully authenticate and access services on the domain as a client. What I also want to do is have the embedded device join the domain as a member, to acquire credentials, and to accept authentication requests from domain users.

I've been using the sample program gss-server from the kerberos src/appl/gss-sample directory as a model for integrating the server functionality to my application.

HINT: I posted my solution as an answer to this question.

I am missing an important piece. Before the embedded device can offer kerberos services, it must join the domain, which, as I understand it, involves a) creating a principal for the host, b) adding an entry into the device's keytab, and c) adding a corresponding entry on the domain controllers keytab. If I were running a full samba stack on my device, I would use something like samba-tool domain join or net ads join. I have looked at the code for samba-tool and net and they seem to do a lot more than I need or want. For the most part, I believe all I need to do is add the artifacts that allow the embedded device to authenticate with the DC. I really don't know if I'm going about this right and I don't believe I know all the steps. But here's what I believe I'm trying to do:

  • provision a computer on the DC
  • Export the keytab entry from the DC
  • Import the keytab entry on the emdedded device.

After doing the above three steps, presumably I could run gss-client/gss-server successfully. First question: Is that correct? And is it the way to do this? Second question: How do I import a keytab entry?

Maybe I don't need a keytab but rather instead of using gss_acquire_cred, I somehow export the credential from the DC and securely communicate it to the embedded device and then use gss_import_cred.

Does anyone know if I'm on the right track? Is there any sample code they know about that does this?

As some background, we have a commercial SMB client/server stack that runs on Android. We support both NTLM and Kerberos authentication for the client and just NTLM on the server. We are trying to upgrade the server to support Kerberos authentication as well.

Rowland Penny avatar
ba flag
Not the answer you are looking for, but your device must join AD, also it cannot accept authentication requests, that's the DC's job.
Score:0
fr flag

it must join the domain, which, as I understand it, involves a) creating a principal for the host, b) adding an entry into the device's keytab, and c) adding a corresponding entry on the domain controllers keytab.

Yes, although it's not exactly a single "keytab" on the domain controller's side – it's setting the keys associated with the host principal's entry specifically. In AD, it means setting the (computer or user) account's password and letting it derive keys from that; then you locally use the same procedure to derive keys and store them in a keytab file.

For AD, you only need a true "computer" account if you want to accept Kerberos tickets for the services usually associated with one in AD, e.g host/ (SSH) or cifs/ (SMB). In many other cases, however, it is sufficient to create a "user" account and assign it 'servicePrincipalName' attribute with the particular service principal you want. For example, a web server accepting SPNEGO for HTTP/ can just as easily be tied to a "user" account.

Also note that in the case of Active Directory, it is impossible to actually "export a keytab" from the KDC, as that would be basically equal to retrieving an account's password hash. Instead, the process is reverse: you would set the account's password to a randomly generated value, then locally generate the keytab using the same password as input to the hashing algorithm.

If you want to do everything using Linux tools, the adcli tool (part of realmd) could be used to provision a computer account in Active Directory, as an alternative to samba-tool. It can create a keytab file if necessary, or you could provide it a strong and randomly-generated password for the computer account and use ktutil to manually generate a keytab for it.

However, adcli does not use any unusual RPC interfaces, so you could do the same using a generic LDAP client too – e.g. you could use python-ldap to create a user or computer account and set its password. Finally, could just have the AD admin pre-create an account and generate a keytab for you.

Second question: How do I import a keytab entry?

This depends very much on the Kerberos implementation that you're using, but in most cases there is no "import" procedure – the keytab file stays a keytab file, you just place it at the correct location (/etc/krb5.keytab being the traditional "system-wide" default on Unix-like systems).

Recent versions of MIT Krb5 and Heimdal have the "credential store" extension to the GSS API interface to acquire credentials from a specified path, so the "correct location" can be entirely up to you.

(In older versions, it needed to be done through raw libkrb5 APIs or by setting KRB5_KTNAME in the environment.)

Similarly, other Kerberos or GSSAPI implementations (e.g. the Java one) will generally let you load the server keys from a specified path.

Richard Schmitt avatar
cn flag
Thanks. Some followups: You mention adcli can generate a keytab or use ktutil to manually generate it. I have used `adcli preset-computer --domain=mydomain.com myhost.mydomain.com -V cifs -W`. I also used --one-time-password option. I don't see that it created a keytab nor is there an option to do that.
Richard Schmitt avatar
cn flag
You then say I can use ktutil to create a keytab file. I assume that's by using add_entry followed by write_kt. When I try to create an entry as: `add_entry -password -p cifs/[email protected] -k 1 -f` I get an error `add_entry: Client not found in Kerberos database while adding new entry`. What Client and what Kerberos database? I get what your saying is I would need to do this on both the DC and the computer. That was helpful.
user1686 avatar
fr flag
"cifs/[email protected]" is the 'client' in question, "Kerberos database" is the KDC, as `-f` does an online request to the KDC (to learn what KDF salt it's using for that particular principal). So ideally you would create an account on the KDC first, assign it the SPN, and *then* do the `add_entry -f`.
user1686 avatar
fr flag
It's only `adcli join` that creates a keytab, `adcli preset-computer` doesn't (it just creates a placeholder).
user1686 avatar
fr flag
Also, to make sure, keytabs use raw Kerberos principals, not UPNs/SPNs, and the `@REALM` part of a principal name is **upper-case**, even in AD.
Richard Schmitt avatar
cn flag
Still couldn't get it to work. Guess I am too unfamiliar with kerberos. Here's what I've done: On the DC: ``` # kadmin.local kadmin.local: add_principal cifs/[email protected] kadmin.local: ktadd cifs/[email protected] kadmin.local: quit # ``` Did the same thing on member adding same password. Then ran gss-server with: ``` ./gss-server cifs/ubuntu ``` client with: ``` ./gss-client ubuntu cifs test ``` Get pretty far considering, but end up with: ``` GSS-API error initializing context: The ticket isn't for us ``` More to do. Thanks
user1686 avatar
fr flag
kadmin.local? What kind of software is the DC running? I thought you said it was AD?
Richard Schmitt avatar
cn flag
I was adding more to my comment, sorry. Updated now. Also thought it was markdown so ignore ticks. My DC is samba-ad-dc.
user1686 avatar
fr flag
It is markdown but (deliberately) very minimal markdown, so that people would edit relevant info into their main post instead. If you're using kadmin.local, I suppose that means you're using the mit-kdc version of Samba? What does `KRB5_TRACE=/dev/stderr ./gss-server...` (and the same with ./gss-client) say? Are you sure the client is acquiring a ticket for cifs/ubuntu exactly, and not e.g. for cifs/ubuntu.spiritcloud.app? (Kerberos on Unix does more client-side canonicalization than Windows clients would.)
Score:0
cn flag

SOLUTION: This is what I did to get things to work.

  1. My DC is running samba-ad-dc. This assumes you already have a user configured on your DC. Use samba-tool to add a service principal for the service account and attach it to the user:
# samba-tool spn add cifs/myhost.mydomain.com@MYREALM MyUser

Where cifs is the name of my service, myhost.mydomain.com is the FQDN of my computer, MYREALM is the realm or domain name, and MyUser is the existing user that I want to attach the principal to.

  1. Generate a keytab with an entry for that service principal
# samba-tool domain exportkeytab cifs.keytab --principal cifs/myhost.mydomain.com@MYREALM

Where cifs.keytab is an arbitrary name of an output file that will contain the keytab and cifs/myhost.mydomain.com@MYREALM is the service principal I just added in step 1.

  1. Copy that keytab file to the member computer with the FQDN myhost.mydomain.com. There are three things I could do with this keytab file on the member. a) replace /etc/krb5.keytab with it, b) import the entires from it into /etc/krb5.keytab using the ktutil utilitity, or c) specify it as an argument to gss-server. I am opting for c.

  2. Log in as the user that the service principal we created in step 1 is attached to.

# kinit MyUser@MYREALM
  1. Run gss-server
# gss-server -keytab cifs.keytab cifs/myhost.mydomain.com@MYREALM

where cifs.keytab is the keytab file exported from the DC and copied over to the member computer and cifs/myhost.mydomain.com@MYREALM is the principal we created in step 1.

  1. Run gss-client
# gss-client myhost.mydomain.com cifs message

where myhost.mydomain.com is the FQDN of my member computer, cifs is the service name of the principal I created in step 1 and message is whatever message I want to transfer to my server.

Simple wasn't it? NOT! But with user1686's patient help, I was able to get through this. Thanks.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.