This is the second of two commits in a series that must be picked together.
This series of two commits moves parts of lib/krb5/ infrastructure
functionality to lib/base/, leaving behind wrappers.
Some parts of libkrb5 are entirely generic or easily made so, and could
be useful in various parts of Heimdal that are not specific to the krb5
API, such as:
- lib/gssapi/ (especially since the integration of NegoEx)
- lib/hx509/
- bx509d (which should really move out of kdc/)
For the above we need to move these bits of lib/krb5/:
- lib/krb5/config_file.c (all of it, leaving forwardings behind)
- lib/krb5/config_reg.c (all of it)
- lib/krb5/plugin.c (all of it, leaving forwardings behind)
- lib/krb5/log.c (all of it, ditto)
- lib/krb5/heim_err.et (all of it)
And because of those two, these too must also move:
- lib/krb5/expand_path.c (all of it, leaving forwardings behind)
- lib/krb5/warn.c (just the warning functions, ditto)
The changes to the moved files are mostly quite straightforward and are
best reviewed with --word-diff=color.
We're also creating a heim_context and a heim API to go with it. But
it's as thin as possible, with as little state as necessary to enable
this move. Functions for dealing with error messages use callbacks.
Moving plugin.c does have one knock-on effect on all users of the old
krb5 plugin API (which remains), which is that a global search and
replace of struct krb5_plugin_data to struct heim_plugin_data was
needed, though the layout and size of that structure doesn't change, so
the ABI doesn't either.
As well, we now build lib/vers/ and lib/com_err/ before lib/base/ so as
to be able to move lib/krb5/heim_err.et to lib/base/ so that we can make
use of HEIM_ERR_* in lib/base/, specifically in the files that moved.
Once this is all done we'll be able to use config files and plugins in
lib/hx509/, we'll be able to move bx509d out of kdc/, and so on.
Most if not all of the new functions in lib/base/ are Heimdal-private,
thus calling conventions for them are not declared.
Status:
- builds and passes CIs (Travis, Appveyor)
- ran make check-valgrind and no new leaks or other memory errors
- ready for review
HOW TO REVIEW:
$ # Review file moves:
$ git log --stat -n1 HEAD^
$
$ # Review changes to moved files using --word-diff=color
$ git log -p -b -w --word-diff=color HEAD^..HEAD \
lib/base/config_file.c \
lib/base/config_reg.c \
lib/base/expand_path.c \
lib/base/warn.c \
lib/krb5/config_file.c \
lib/krb5/config_reg.c \
lib/krb5/expand_path.c \
lib/krb5/warn.c
$
$ # Review the whole thing, possibly adding -b and/or -w, and
$ # maybe --word-diff=color:
$ git log -p origin/master..HEAD
$ git log -p -b -w origin/master..HEAD
$ git log -p -b -w --word-diff=color origin/master..HEAD
TBD (future commits):
- make lib/gssapi use the new heimbase functions
- move kx509/bx509d common code to lib/hx509/ or other approp. location
- move bx509d out of kdc/
This is the first of two commits in a series that must be picked
together.
This series of two commits moves parts of lib/krb5/ infrastructure
functionality to lib/base/, leaving behind wrappers.
This commit only renames files to enable git log/diff/blame to follow
the renames: to help future code archeology, and to make reviewing these
two commits easier.
The next commit in this series ensures that the moved files have the
correct content (i.e., defining heim APIs instead of krb5 APIs), and
will create files in lib/krb5 with the same names and krb5 API wrappers
around the new heim API functions.
The next commit also explains the motivation, which, briefly, is to:
- remove krb5 API usage from lib/gssapi/,
- enable the use of configuration and plugins in lib/hx509/
(as well as lib/gssapi/ and future projects),
and
- enable the further disentanglement of bx509d from kdc/.
Initialize mechanism output parameters before calling mechanism
GSS_Accept_sec_context(), to behave robustly with poorly implemented mechanisms
that may return before initializing them.
test_negoex_mech, being a simple test mechanism ported from MIT that was not
designed to be particularly robust, failed to initialize various output
parameters such as the source name. On Heimdal this triggered an invalid read
because the mechglue did not initialize those variables before calling the
mechanism. This commit fixes this.
NTLM erroneously requires a mechListMIC at the SPNEGO layer if an internal MIC
in the NTLM protocol was used. Add a private interface between SPNEGO and the
Samba NTLM mechanism to allow the mechanism to signal that a mechListMIC is
required even if it otherwise would not be.
This interface is the same as that supported by MIT.
Note that only the Samba NTLM mechanism currently implements this feature, it
is not implemented by the Heimdal NTLM mechanism (which does not support NTLM
authenticate message MICs).
Previously krb5 was tried explicitly, but now the internal mech list is
reordered so that krb5 is first, this should no longer be required. This
permits an application to specify another mechanism as preferred over krb5
using gss_set_neg_mechs().
RFC 4178 4.2.2 uses the field name negState rather than negResult in
NegTokenResp, to denote the negotiation state. Harmonize with this, also
replacing the underscores in accept-completed and accepet-incomplete to match
the RFC.
An implementation of draft-zhu-negoex-04 for MIT Kerberos was developed in
2011. This has been recently integrated, with many fixes from Greg Hudson. This
commit ports it to Heimdal. The implementation has been interoperability tested
with MIT Kerberos and Windows, using the GSS EAP mechanism developed as part of
the Moonshot project.
The SPNEGO code was also updated to import the state machine from Apple which
improves mechListMIC processing and avoids discarding initial context tokens
generated during mechanism probing, that can be used for optimistic tokens.
Finally, to aid in testing, the GSS-API mechanism glue configuration file can
be changed using the environment variable GSS_MECH_CONFIG. This environment
variable name, along with the format of the configuration file, is compatible
with MIT (although it would be difficult for a single mechanism binary to
support both implementations).
Wrapping GSS names at the SPNEGO level serves no purpose; remove it and return
mechglue names directly. This required a small change to the NTLM mechanism to
allow NULL names to be passed to its release name function.
GM_USE_MG_CRED allows a mechanism glue credential to be used by a mechanism
without additional wrapping. Although no extant mechanisms use this flag, the
flag had sporadic support in the mechanism glue already. In the interest of
consistency, add missing GM_USE_MG_CRED checks. If this functionality is not
desired, then all checks should be removed.
Add helper APIs to the mechanism glue from the Apple implementation.
gss_mg_export_name() can be used by a mechanism to create an exported name
(this is used by the future SAnon implementation). _gss_mech_import_name()
allows the mechanism to pass in a list of parsing functions for specific name
tiypes. This commit only adds support to the mechanism glue itself.
The GSS mechglue uses singly linked lists for mechanisms and mechanism objects,
to which new entries are inserted at the head. This breaks ordering of
mechanisms specified in OID sets and in /etc/gss/mech, as they will be back to
front. Use a tail queue instead so that new entries are inserted at the end.
Make mechanism interfaces that are optional in usage, optional in
implementation, i.e. do not require them to be present when dynamically loading
a mechanism. In order to aid minimal mechanism implementation, more of these
should likely be made optional (this will require an additional check in the
mechglue to return GSS_S_UNAVAILABLE if the function pointer is NULL). This is
left as a future exercise.
_gss_ntlm_accept_sec_context() does not provide the acceptor domain to
nsi_probe(); for consistency, _gss_ntlm_acquire_cred_from() should do that
same. Providing the acceptor domain was breaking tests.
Note that the Heimdal NTLM implementation is old and has few consumers (Apple
and Samba use their own implementations). Arguably we should merge the Apple
implementation or remove it.
The Kerberos GSS mechanism specific error table in gkrb5_err.et was never
registered with libkrb5, so the messages corresponding to those errors would
never be available. Register them with the thread local context used by the
krb5 mechanism.
Since at least SDK V6.1 HCRYPTPROV has been specified as ULONG_PTR
this means that comparing or setting one with NULL causes a cast
warning.
Use an explicit cast from zero to that type.
Add two ways to exclude private keys when dealing with an hx509
certificate store. One as a load option (load no private keys, never
add private keys), one as a store option (store no private keys).
This is useful for CA code so it can have a single store with the
issuer's credentials _and_ the chain for it, and copy those to a store
with the issued certificate and _not_ accidentally include the issuer's
private key.
It would be much safer still to flip the default for this flag, but that
could break out-of-tree libhx509 dependents.
Our logging framework used to strnvisx(3) each and every line
iff it is written to a FILE. This is often unhelpful because
the line usually contains a number of elements that have already
been quoted and it makes the logs much more difficult to read in
this case. An example if krb5_unparse_name() which will already
quote most characters that one cares about.
We change the behaviour to simply drop unprintable characters
rather than encoding them. We thus rely on the rest of the
code to properly encode data elements written into the logs.
This commit adds a few functions for marking KU, EKUs, and SANs as
authorized, and for getting a count of unsupported certificate
extensions requested, and a count of authorized KU/EKUs/SANs.
The intent is to make it easier to build CSR authorization and CA code
that is robust in the face of future support for certificate extensions
and SAN types not currently supported. An application could parse a
CSR, iterate all KU/EKUs/SANs, check a subject's authorization to them,
mark them authorized where authorized, then check if there are any
remaining unauthorized extensions or unsupported extensions requested.
Ultimately, if a CSR's KU/EKUs/SANs are all authorized, then they can
all be copied to a TBS, and a certificate can be issued.