We have a check for symlinks and hardlinks so that we refuse to open
ccaches through symlinks or which have hardlinks. This check is too
strict, checking for `st_nlink != 1`, which runs into trouble when a
ccache is mounted as a file into a container, in which case `stat(2)`
reports it as having zero links.
The fix is to check for `st_nlink > 1`:
- if (sb2.st_nlink != 1) {
+ if (sb2.st_nlink > 1) {
krb5_set_error_message(context, EPERM, N_("Refuses to open hardlinks for caches FILE:%s", ""), filename);
Though I question the utility of the hardlink check. MIT Kerberos
doesn't have it.
krb5_cc_end_seq_get() is not expected to fail because it is a
cleanup routine. If it fails it indicates something wrong with
the cache or the system. Return the failure if there is one.
Otherwise, the failure from krb5_cc_next_cred() should be
returned UNLESS it is KRB5_CC_END in which case return success.
Change-Id: I80e07103e2fb38aa40418a436fa5351fb89549d3
Although not required to address bad code generation in
some versions of gcc 9 and 10, a coding style that requires
explicit comparison of the result to zero before use is
both clearer and would have avoided the generation of bad
code.
This change converts all use of cmp function usage from
```
if (strcmp(a, b) || !strcmp(c, d)) ...
```
to
```
if (strcmp(a, b) != 0 || strcmp(c, d)) == 0
```
for all C library cmp functions and related:
- strcmp(), strncmp()
- strcasecmp(), strncasecmp()
- stricmp(), strnicmp()
- memcmp()
Change-Id: Ic60c15e1e3a07e4faaf10648eefe3adae2543188
The krb5_cc_ops structure is an extensible structure to which new
functionality has been added over the years.
Version zero was the original. It included all functions up to
and including get_default_name().
Version one added set_default().
Version two added lastchange().
Version three added set_kdc_offset() and get_kdc_offset().
Version four broke compatibility by modifying the signatures
of get_name() and resolve(). This was in change
7bf4d76e75 ("krb5: Improve cccol sub
naming; add gss_store_cred_into2()").
Version five restores the original signatures of get_name()
and resolve() and introduces get_name_2() and resolve_2() that
provide the additional cccol functionality.
This change
* introduces version five
* documents which functions are part of each version
* replaces KRB5_CC_OPS_VERSION with KRB5_CC_OPS_VERSION_0,
KRB5_CC_OPS_VERSION_1, KRB5_CC_OPS_VERSION_2, KRB5_CC_OPS_VERSION_3,
and KRB5_CC_OPS_VERSION_5. KRB5_CC_OPS_VERSION_4 is skipped
because of the aforementioned breakage.
* compatibility logic is added to permit ccache plugins to implement
any of version one, two, three, five or a future version.
* all in-tree krb5_cc_ops implementations are updated to version 5.
Change-Id: Iadfce01d10834bc6151939e4d9d196f03001626e
- Formalize the TYPE:collection_name:subsidiary_name naming scheme for
ccaches in ccache collections
- KEYRING: ccaches are weird because they have one more optional field: the
"anchor", so rather than just assume a naming convention everywhere, we
add new functions as well
- Add krb5_cc_{resolve,default}_sub() that allows one to specify a
"subsidiary" ccache name in a collection separately from the
collection name
- Add krb5_cc_{resolve,default}_for() which take a principal name,
unparse it, and use it as the subsidiary ccache name (with colons
replaced)
- Make kinit use the new interfaces
- Add missing DIR ccache iteration functionality
- Revamps test_cc
- Add krb5_cc_get_collection() and krb5_cc_get_subsidiary()
- Bump the ccops SPI version number
- Add gss_store_cred_into2()
- Make MEMORY:anonymous not linked into the global MEMORY ccache
collection, and uses this for delegated cred handles
TBD:
- Split this up into a krb5 change and gss mech_krb5 change?
- Add krb5_cc_init_and_store() utility, per Greg's suggestion?
Move init/copy/destroy fallback sequence from fcc_move() to
krb5_cc_move().
Make sure all backends's move() method calls krb5_cc_destroy() on the
source on success (and only on success).
In text_cc make sure that we can find in the destination the cred
stored into the source.
Use stdio. Don't lock to read -- we only ever rename new ccaches into
place, or overwrite endtimes to delete entries, or overwrite part of the
realm name of cc config entries.
Dropping locks around ccache iterator stepping strongly implied that we
don't expect truncation, that we only expect appends (and the
overwriting done to delete entries).
Don't unlock -- let close(2) do it, thus making fewer system calls.
Commit ad7e54d698 introduced the use
of _krb5_expand_path_tokens() to expand tokens (and on Windows convert
path delimiters) within credential cache names. This is safe to do
for the path based credential cache types FILE, DIR and SCC but on
Windows is unsafe for the non-path types.
For example on Windows, the API credential cache names are often based
on the principal name and the principal name is parsed from the ccname.
This practice was introduced with the version v2 ccapi when there was
no method of enumerating the caches from the krb5 library.
This change adds a "filepath" boolean parameter to _krb5_expand_path_tokens()
which is set to TRUE (non-zero) when the input is a file path and FALSE
(zero) when the input is not a file path. _krb5_expand_path_tokens() will
only perform directory separator normalization on Windows when the
"filepath" parameter is TRUE.
This change is not the preferred solution because it requires that the
library be aware of all credential cache types that use path based
residuals. The preferred solution would require that the credential cache
implementation indicate whether or not it uses a path based residual.
This change has been implemented using a prefix test and not a change to
struct krb5_cc_ops because existing ccache plugins will not know how to
advertise their use of path based residuals and that path expansion is
safe.
Change-Id: I8135991e8ce69fc5273d381ea9c2078bc2bcd19a
The problem is that fcc_get_cache_next() is called in a context where
context->default_cc_name is not set. We should call
krb5_cc_default_name(), and that fixes the problem. There's a comment
warning that this can result in reentering krb5_cc_cache_match(), but
nothing in libkrb5 calls krb5_cc_cache_match(), so the comment is wrong,
at least in the github tree.
An alternative would be to call krb5_cc_set_default_name(NULL) in
kuser/kinit.c before calling krb5_cc_cache_match(), however, that seems
like an insufficiently general solution. Also, the semantics of
krb5_cc_cache_match() would differ from MIT's -- it seems better to
match MIT's semantics.
Programs like sshd may create or access a ccache with
ruid != user's UID, euid == user's UID.
Set-uid-0 programs (ob reminder: they start life as ruid == user's UID,
euid == 0) shouldn't unintentionally access ccaches. Therefore we
shouldn't check both of ruid and euid, just euid.
We *really* need a ccache instance ID tag. In fact, we should probably
never krb5_cc_initialize() a ccache that doesn't have such a tag. But
for now cred_delete() is now safe enough.
If we're racing enough we could complain about symlinks where there were
none. This was very surprising. Make it surprise less.
We should really #ifndef O_NOFOLLOW that code chunk too, for the obvious
reason that we don't need to worry about symlinks if we have and use
O_NOFOLLOW.
Also, since all uses of fcc_open() use O_NOFOLLOW we should move that
into fcc_open(). Ditto O_BINARY and O_CLOEXEC.
st_dev and st_ino are not set in a consistent fashion by stat()
and fstat() so disable the symlink test.
disable the open group/other readable test because st_mode
cannot be used to perform such a test on Windows.
Change-Id: I1b68c672f882018def7e6d40d4bc7f7add58df36
- use O_NOFOLLOW
- be more strict not to follow symlinks
- require cache files to be owned by the user
- have sane permissions (not group/other readable)