jcmturner / gokrb5

Pure Go Kerberos library for clients and services
Apache License 2.0
729 stars 249 forks source link

Strict validation of KVNO in Keytab for SPNEGO #421

Closed jfixemer closed 3 years ago

jfixemer commented 3 years ago

I have been trying to convert both an Apache mod_auth_krb and Tomcat (java.sun.security kerberos stuff) to GO.

In both of these cases it seems the implementations are not strict about the KVNO value in the keytab matching the ticket (sorry if this is wrong terminology, kind of hacking my way through, learning as I go).

I got it to work 2 ways: First I copied keys in the keytab and 'updated' KVNO. (worked) Second I tried a small change in gokrb5 (also worked)

v8/keytab/keytab.go
line 78: 
-           (k.KVNO == uint32(kvno) || kvno == 0 ) &&
+           (k.KVNO == uint32(kvno) || kvno == 0 || k.KVNO == 0) &&

As I am hacking rather than an expert in kerberos so I am not making a fork, pull request and all that jazz. I guess it is just an idea with unknown implications (I haven't read the RFCs or anything)

The downside of strict matching of KVNO is that I don't think the DC will tell my server when it updates, so even if I put together a sync (chron) job it runs frequently there are still windows or I 'anticipate' the next KVNO and pre populate. If I'm pre-populating future KVNOs to the same key is there really any difference to having a 'wildcard' value in the keytab?

Finding the entry with kvno=0 doesn't guarantee the timewindow or the validity of the key so it can/will fail later, but I think that is reasonable.

Thoughts?

Regards, Jeremy

jfixemer commented 3 years ago

I am also pondering the following alternative:

            (k.KVNO <= uint32(kvno) || kvno == 0) && (k.KVNO > uint32(kv)) &&

Which is basically to find the keytab entry with greatest KVNO not exceeding the kvno passed in.

Given a keytab with keyA at 0, keyB at 52 (rotate once per year and AD updates KVNO weekly but doesn't change the key)

Then a clientA could still be using keyA(kvno=51) [because they didn't logout and login yet, trigger credential refresh from AD] ClientB [just logged in] could use latest ticket with kvno=52 and keyB.

Hopefully KeyA will be nearing a max age (with some reasonable overlap) where AD itself will stop allowing the authentication.

Sorry if this is foobar vs RFCs, just looking at the algorithm and minor tweaks that could handle various scenarios for keytabs and clients...

Regards,

Jeremy

jfixemer commented 3 years ago

I see in rfc1510 that it pretty explicitly would like KRB_AP_ERR_BADKEYVER to be used when KVNO does not match, so this is moot.