A HEAD or GET of / or /health will now produce a 200 instead of a 404.
Ideally we should add configuration arguments that would allow /health
to get a token, make a CSR, and test the /bx509 (and/or /bnegotiate)
functionality, that way we'd have a real health check. For now we defer
that work, as external health monitoring can be done using a simple
script anyways.
The Negotiate token validation plugin links against libgssapi, but on macOS the
dynamic linker cannot find it before Heimdal is installed. This causes tests to
fail. Although test_token_validator itself does not require libgsaspi, link
against it so that the test can proceed.
Now we'll put the "reason=..." last in the log lines and we won't escape
spaces -- just newlines and other control characters. This makes
reading log lines much easier without complicating parsing of log lines
because interior key=value pairs do get whitespace escaped or removed.
krb5_kdc_process_request() must return 0 when it produces a reply, and only
return non-zero when it could not construct any kind of reply (e.g., ENOMEM, or
-1 if no handler claimed responsibility for the request).
We take all of the kdc_log() and _kdc_r_log() calls in AS and TGS
and move their log levels down to debugging on the assumption that
our new log line subsumes the "informational" requirements. We
collect some additional information in the kv-pair "pe-text" which
is like e-text except it is not returned to the client.
We refactor the code a bit to extend kdc_request_t which until now
was only used for the AS. We make the structure extensible and
start using it for the TGS as well. We leave digest and kx509
alone for the time being.
We also define the concept of kv-pairs in our audit trail which
allows us to define a rigorous but extensible format:
type error from-addr client server key1=val1 key2=val2 ...
We define the meaning of the various log levels in the man page
for krb5_openlog(3). If logging configured and levels are not
specified, we change the default levels to 0-3 which should exclude
debugging messages which are generally only desired in exceptional
circumstances.
We also go through the KDC and adjust the levels to be appropriate.
This commit adds support for proof of posession to the kx509 protocol by
using PKCS#10 CSRs.
This allows conveyance of extReq CSR attributes requesting desired
Certificate Extensions.
This commit adds support for kx509 in libkrb5, and revamps the KDC's
kx509 service (fixing bugs, adding features).
Of note is that kx509 is attempted optimistically by the client, with
the certificate and private key stored in the ccache, and optionally in
an external PEM or DER file.
NOTE: We do not optimistically use kx509 in krb5_cc_store_cred() if the
ccache is a MEMORY ccache so we don't generate a key when
accepting a GSS context with a delegated credential.
kx509 protocol issues to be fixed in an upcoming commit:
- no proof of possession (this is mostly not too bad, but we'll want to
fix it by using CSRs)
- no algorithm agility (only plain RSA is supported)
- very limited (no way to request any options in regards to the
requested cert)
- error codes are not very useful
Things we're adding in this commit:
- libkrb5 kx509 client
- automatic kx509 usage hooked in via krb5_cc_store_cred() of start TGT
- per-realm templates on the KDC side
- per-realm issuer certificates
- send error messages on the KDC side
(this is essential to avoid client-side timeouts on error)
- authenticate as many error messages
- add a protocol probe feature so we can avoid generating a
keypair if the service is not enabled
(once we add support for ECC algorithms we won't need this
anymore; the issue is that RSA keygen is slow)
- support for different types of client principals, not just username:
- host-based service and domain-based service, each with its own
template set per-{realm, service} or per-service
(the idea is to support issuance of server certificates too, not
just client/user certs)
- more complete support for SAN types
- tests (including that PKINIT->kx509->PKINIT works, which makes it
possible to have "delegation" of PKIX credentials by just delegating
Kerberos credentials)
- document the protocol in lib/krb5/kx509.c
Future work:
- add option for longer-ticket-lifetime service certs
- add support for ECDSA, and some day for ed25519 and ed448
- reuse private key when running kinit
(this will require rethinking how we trigger optimistic kx509
usage)
- HDB lookup for:
- optional revocation check (not strictly necessary)
- adding to certificates those SANs listed in HDB
- hostname aliases (dNSName SANs)
- rfc822Name (email)
- XMPP SANs
- id-pkinit-san (a user could have aliases too)
- support username wild-card A RRs, ala OSKT/krb5_admin
i.e., if a host/f.q.d.n principal asks for a certificate for
some service at some-label.f.q.d.n, then issue it
(this is not needed at OSKT sites because OSKT already
supports keying such service principals, which means kx509
will issue certificates for them, however, it would be nice
to be able to have this independent of OSKT)
(a better way to do this would be to integrate more of OSKT
into Heimdal proper)
- a kx509 command, or heimtools kx509 subcommand for explicitly
attempting use of the kx509 protocol (as opposed to implicit, as is
done in kinit via krb5_cc_store_cred() magic right now)
Issues:
- optimistically trying kx509 on start realm TGT store -> timeout issues!
- newer KDCs will return errors because of this commit; older ones
will not, which causes timouts
- need a separate timeout setting for kx509 for optimistic case
- need a [realm] config item and DNS SRV RR lookup for whether a
realm is expected to support kx509 service
In order to support certain use cases, we implement a mechanism to
allow wildcard principals to be defined and for the KDC to issue
tickets for said principals by deriving a key for them from a
cluster master entry in the HDB.
The way that this works is we defined an entry of the form:
WELLKNOWN/DERIVED-KEY/KRB5-CRYPTO-PRFPLUS/<hostname>@REALM
When reading from the Kerberos DB, if we can't find an entry for
what looks like a hostbased principal, then we will attempt to
search for a principal of the above form chopping name components
off the front as we search.
If we find an entry, then we derive keys for it by using
krb5_crypto_prfplus() with the entry's key and the principal name
of the request.
* Anonymous pkinit responses from the KDC where the name
type is not well-known (as issued by 7.5 KDCs and earlier)
are accepted by the client. There is no need for the client
to strictly enforce the name type.
* With historical_anon_pkinit = true, the kinit(1) client's
"--anonymous" option only performs anon pkinit, and does
not require an '@' prefix for the realm argument.
* With historical_anon_realm = true, the KDC issues anon
pkinit tickets with the legacy pre-7.0 "real" realm.
Drafts 0 through 10 of the Kerberos anonymity internet draft,
https://tools.ietf.org/html/draft-ietf-krb-wg-anon, specified the
TicketFlags.anonymous flag as bit 14 and the KDCOptions.anonymous
flag as bit 14. These were changed to bit 16 by MIT after it was
discovered that Microsoft used KDCOptions bit 14 for S4U2Proxy
cname-in-addl-tkt.
(Feb 2007) Heimdal added constrained delegation support prior to
1.0 but named the KDCOptions flag constrained_delegation instead of
cname-in-addl-tkt as per MS-SFU. It also assigned bit 16 instead
of bit 14. Perhaps this was done in the hope that the conflict
with Microsoft would be resolved in favor of the IETF internet
draft instead of the proprietary protocol extension.
adf9121822 ("Add PA-ClientCanonicalized
and friends.") introduced the KDCOptions.constrained_delegation flag
as bit 16.
(June 2007) In order to make Heimdal's constrained delegation work
with Microsoft's implementation Heimdal began to set both KDCOptions
bits 14 and 16 when requesting constrained delegation.
d5bb7a7c56 ("(krb5_get_creds): if
KRB5_GC_CONSTRAINED_DELEGATION is set, set both") set both the
anonymous and constrained_delegation TicketFlags when issuing a
S4U2Proxy request.
(June 2010) MIT reassigned the KDCOption.anonymous and
TicketFlags.anonymous flags to bit 16. draft-ietf-krb-anon-11
was published with this change.
(July 2014) After the release of Heimdal 1.5.0 and prior to 1.5.1
it was noticed that Heimdal's anonymous TGT support did not
interoperate with MIT.
86554f5a7f ("Use correct value for
anonymous flags") swapped the bit assignments for request_anonymous
and constrained_delegation but failed to remove the setting of
KDCOptions bit 16 ("anonymous") when requesting constrained
delegation.
(May 2019) Prior to the 7.6 release many corrections to Heimdal's
anonymity support were introduced to bring it into compliance
with RFC8062. This included support for requesting anonymous
tickets via the TGS service. Because not all KDC can satisfy
anonymous requests the client must verify if the response was
anonymized. This check wasn't added until after 7.6 was
released.
014e318d6b ("krb5: check KDC
supports anonymous if requested").
The combination of setting KDCOption.anonymous when requesting
constrained delegation and the anonymized ticket validation
broke S4U2Proxy requests to Windows KDCs. Windows KDCs ignore
the KDCOption.anonymous flag when processing a TGS request
with KDCOption.cname-in-addl-tkt set.
ea7615ade3 ("Do not set
anonymous flag in S4U2Proxy request") removed the behavior
of setting the KDCOption.anonymous flag that should have
been removed in July 2014.
(June 2019) The Heimdal KDC includes fallback logic to handle
Heimdal clients from 1.0 to 1.5.0, inclusive, that set the
KDCOptions.anonymous flag as bit 14. Prior to the 7.7 release
this logic only handled AS request but failed to handle the
constrained delegation request case where both bits 14 and 16
were set in the TGS request.
cdd0b70d37 ("kdc: don't misidentify
constrained delegation requests as anonymous") added the TGS
request validation to distinguish anonymous requests from
constrained delegation requests.
This change documents the history in the commit message and
updates some in-tree comments.
Change-Id: I625cd012e2e6c263c71948c6021cc2fad4d2e53a
Earlier (pre-7.6) Heimdal clients would send both the request-anonymous and
cname-in-addl-tkt flags for constrained delegation requests. A true anonymous
TGS request will only have the former flag set. Do not treat TGS requests with
both flags set as anonymous requests.
_kdc_is_anon_request() is only used by the AS, so make it static.
Centralize anonymous poilcy checks shared between AS and TGS into a shared
function, _kdc_check_anon_policy().
When issuing an anonymous ticket, set the ticket flag early and test that
rather than re-testing the request.