Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework _kdc_find_etype() #947

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Conversation

nicowilliams
Copy link
Contributor

_kdc_find_etype() has become a monster. It's time to rewrite it.

I'm splitting it into two parts:

  • _kdc_find_etype(), meant for selecting a ticket's session key enctype (though it's also used in GSS pre-auth to pick the enctype for which to derive a reply key, but the considerations are the same in that case)

  • _kdc_find_key_and_salt(), which is used to pick a key and salt for use in PA-ETYPE-INFO and PA-ETYPE-INFO2

The latter is similar in function to _kdc_get_preferred_key(), but whereas the KDC-REQ-BODY's etype list does not affect service key selection, it does affect client key selection (I think so anyways), so _kdc_find_key_and_salt() does call _kdc_find_etype().

kdc/kerberos5.c Outdated Show resolved Hide resolved
kdc/kerberos5.c Outdated Show resolved Hide resolved
weak_offered = 1;

for (i = 0; i < ninner; i++) {
if (--limit == 0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit ugly.

@nicowilliams
Copy link
Contributor Author

nicowilliams commented Jan 21, 2022

check-des is broken.

default:
for (i = 0; i < _krb5_num_etypes; i++)
if (_krb5_etypes[i]->type == type)
return _krb5_etypes[i];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, isn't the compiler going to optimise to this anyway? Is _krb5_etypes local to crypto.c? Seems a bit premature optimisation-ish...

Copy link
Contributor Author

@nicowilliams nicowilliams Jan 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would it optimize this?

The problem is this is an O(N) algorithm invoked from loops elsewhere.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can’t it unroll the etype list?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess a compiler could turn the loop into a switch, yeah. I will examine the dissassembly, though I'm not sure I want to assume a compiler this smart.

* NOTE: This is either all strong enctypes only, or all enctypes,
* including weak ones, depending on configuration.
*/
cached_kerberos_enctypes = krb5_kerberos_enctypes(r->context);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, introduced global shared state when we've been trying to refactor everything to use r. Can you cache these in the context instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a global in krb5_kerberos_enctypes()...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then why do we need to cache it? And why does it take a context argument? (Not in front of computer :))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it's a pair of static variables inside that function, krb5_kerberos_enctypes()...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, OK, so relying on krb5_enctype_valid() being invariant across contexts, which I guess is safe. But, why can't we just call krb5_enctype_valid() each time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that: because it does a lot of work on error that we don't need to do in this context. I'm manually inlining just the piece we need.

kdc/kerberos5.c Outdated Show resolved Hide resolved
@nicowilliams nicowilliams force-pushed the rework-_kdc_find_etype branch 5 times, most recently from 3a28906 to c9a4abf Compare January 23, 2022 05:35
This is a bug that was introduced by 5447b81
(which made it so that on-store we derive an `etypes` for every HDB entry that
had that field absent), but masked by a bug in `_kdc_find_etype()`.

The fix is to not just rely on `kadmin del_enctype` for affecting ticket
session key negotiation, but to also or instead use `kadmin mod -e`.
_krb5_find_enctype() gets called from loops implementing linear
searches, yielding accidentally O(N^2) or worse algorithms.

But _krb5_find_enctype() can be O(1) for all numerically-small enctypes.
This commit makes it so.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants