krb5: fcc_next_cred do not return removed creds

commit a9bd3c6e50 ("Fix racy file ccache
corruption in cred_delete()") implemented krb5_cc_remove_cred() for
"FILE" ccaches by overwriting the removed credential endtime value
with zero (Unix Epoch).  However, it did not modify fcc_get_next()
to filter out these deleted entries.  As a result, invalid credentials
can be returned from the FILE ccache where endtime < starttime.
RFC4120 requires endtime >= starttime for all tickets.

MIT Kerberos since d3b39a8bac6206b5ea78b0bf6a2958c1df0b0dd5
("Implement krb5_cc_remove_cred for remaining types") modifies a
removed cred by setting

  endtime = 0
  authtime = -1

and then filters out removed creds from the fcc_next_cred() results.

In 2013 Heimdal broke interop with MIT processes that share the
FILE ccache by implementing remove by setting "endtime = 0" and
now MIT has broken interop with the Heimdal implementation of
fcc_remove_cred() by checking for both "endtime = 0" and "authtime = -1".

This change filters results from fcc_get_next() when the "endtime == 0"
which is acceptable because a KDC is not permitted to return a
ticket with an endtime == 0.
This commit is contained in:
Jeffrey Altman
2024-06-17 11:16:28 -04:00
parent ec37879038
commit 68dbf1ba10

View File

@@ -997,15 +997,25 @@ fcc_get_next (krb5_context context,
if (FCC_CURSOR(*cursor) == NULL)
return krb5_einval(context, 3);
FCC_CURSOR(*cursor)->cred_start =
krb5_storage_seek(FCC_CURSOR(*cursor)->sp, 0, SEEK_CUR);
while (1) {
FCC_CURSOR(*cursor)->cred_start =
krb5_storage_seek(FCC_CURSOR(*cursor)->sp, 0, SEEK_CUR);
ret = krb5_ret_creds(FCC_CURSOR(*cursor)->sp, creds);
if (ret)
krb5_clear_error_message(context);
ret = krb5_ret_creds(FCC_CURSOR(*cursor)->sp, creds);
FCC_CURSOR(*cursor)->cred_end =
krb5_storage_seek(FCC_CURSOR(*cursor)->sp, 0, SEEK_CUR);
FCC_CURSOR(*cursor)->cred_end =
krb5_storage_seek(FCC_CURSOR(*cursor)->sp, 0, SEEK_CUR);
if (ret) {
krb5_clear_error_message(context);
break;
}
if (creds->times.endtime != 0)
break;
krb5_free_cred_contents(context, creds);
}
return ret;
}