On Mon, 1 Nov 2021 17:24:48 GMT, Weijun Wang <wei...@openjdk.org> wrote:

>> The S4U2proxy extension requires that the service ticket to the first 
>> service has the forwardable flag set, but some versions of Windows Server do 
>> not set the forwardable flag in a S4U2self response and accept it in a 
>> S4U2proxy request.
>> 
>> There are 2 commits now. The 1st is a refactoring that sends more info into 
>> the methods (Ex: `KdcComm::send(byte[])` -> `KdcComm::send(KrbKdcReq)`, and 
>> `Ticket` -> `Credentials` in multiple places) so that inside `KdcComm::send` 
>> there is enough info to decide how to deal with various errors. The 2nd is 
>> the actual fix to this issue, i.e. ignore the flag and retry another KDC.
>
> Oops, I introduced a bug. At the end of the constructor of `KrbTgsReq`, 
> `options` could be changed. Since I'm now calculating the encoding on-demand, 
> the encoding will also change. I'll fix this in another commit.

Hi @wangweij ,

Yes, I see the concern about the 50 KDCs scenario. But one nuance here: having 
different AD behaviors with issued tickets that won't be accepted in other 
services afterwards looks to me like a configuration problem that goes beyond 
OpenJDK. Now, if we cannot distinguish between S4U2Self and non-S4U2Self second 
tickets based on their actual data, it's likely that the KDC behaves in the 
same way when it comes to the forwardable flag -both in 2012 DC and after-. 
That would be a reason not to establish any difference in OpenJDK and behave in 
the same way. This official documentation here [1] makes no distinction between 
the two types:

"The S4U2proxy extension requires that the service ticket to the first service 
has the forwardable flag set (see Service 1 in the figure specifying Kerberos 
delegation with forwarded TGT, section 1.3.3). This ticket can be obtained 
through an S4U2self protocol exchange."

If we are concerned about this, why don't we let the user decide the behavior 
by means of a security/system property? That would also mitigate the risk of 
assuming that a KDC_ERR_BADOPTION error is always because of a non-forwardable 
ticket on a 2012 DC -which looks quite an assumption to me-.

Thanks,
Martin.-

--
[1] - 
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/bde93b0e-f3c9-4ddf-9f44-e1453be7af5a

> First, my latest commit contains a mechanism to tell if a ticket is from 
> S4U2self. Is it significant enough to change your mind?
> 
> Even if there is a system property for this purpose (suppose it's named 
> `jdk.security.krb5.accept.non.forwardble.s4u2self.response.and.retry`), I 
> wonder if it's worth turning it off. As you said, a  legitimate S4U2self 
> should always be FORWARDABLE, and in this case the system property is 
> useless. But, if a service really receives such a ticket, I assume it would 
> prefer to try it in a S4U2proxy request instead of just failing early. After 
> all, when it impersonates someone, its purpose should be accessing a backend 
> service.
> 
> We usually introduce a system property for a compatibility reason so that 
> existing normal cases will not behave differently, but here, we are simply 
> trying to resurrect a former failure.
> 
> The main problem I see with the current approach is still about whether a 
> "tolerant" KDC can be accessed in time. If this can be optimized by adjusting 
> the orders of KDC either in krb5.conf or in the DNS response, then I would be 
> greatly relieved.

Hi @wangweij ,

I liked the renaming that you proposed, including the 'ccreds -> middleTGT' 
change. I find it easier to reason about now. There is still a 'ccreds' in 
CredentialsUtil::acquireS4U2proxyCreds that you might want to check.

In regards to 'type' -and assuming that we want to keep that check-, can we 
re-use the CredentialsUtil::S4U2Type enum type? I'm fine if you want to move 
the enum location to Credentials.java.

I'm not sure that we are resurrecting an old failure. My understanding is that 
the new KrbException exception (in KdcComm::sendIfPossible) is causing a 
behavioral change in the sense that it's now allowing KDC iteration, and there 
is no way to go back to the old fail-immediately behavior. The property would 
be to avoid iterating over the 50 KDCs after the first failure; or it could be 
to not even try if the ticket is non-forwardable. In that sense, the property's 
name would be something like 
'jdk.security.krb5.s4u2proxy.acceptNonForwardableServiceTicket'. My second 
concern is that the condition that we use to iterate might be beyond the 
forwardable flag scope, because we are now based on a KDC_ERR_BADOPTION error.

I personally wouldn't make any distinction between S4U2Self and non-S4U2Self 
second tickets when it comes to the second ticket forwardable flag.

> That `ccreds` in `acquireS4U2selfCreds`? I'll fix it.
> 
> Other comments accepted. I'll add a system property.

Hi @wangweij ,

Thanks for taking the backward-compatibility property suggestion.

I went through all the changes again and have some comments / questions:

 * I realized that the field 'Krb5Context::serviceCreds' in Krb5Context.java is 
now overloaded and might have two different value depending on whether it's an 
Initiator or an Acceptor context. A comment next to the field declaration might 
be helpful if you want to consider: "// On the Initiator side, contains the 
final TGS to a service on both delegation and no-delegation scenarios. On the 
Acceptor side, contains a user TGS usable for delegation.". Note that previous 
to this change, the field was meaningful for the Initiator side only, as the 
Acceptor side was using 'Krb5Context::serviceTicket'.

 * In Credentials.java, can we replace 'ccreds' with 'middleTGT' in 
acquireS4U2proxyCreds? This would align the names with 
CredentialsUtil::acquireS4U2proxyCreds and, in my opinion, would be more clear. 
Additionally, you might want to consider replacing 'ccreds' with 'initCreds' in 
acquireServiceCreds, so it's aligned with CredentialsUtil::acquireServiceCreds.

 * In KrbTgsReq.java, you said 'At the end of the constructor of KrbTgsReq, 
options could be changed. Since I'm now calculating the encoding on-demand, the 
encoding will also change. I'll fix this in another commit.'. Have you made 
that change? I still see 'obuf = ...' before 'options.set(KDCOptions.FORWARDED, 
true);'.

 * I'm not entirely sure of the reason why 'KrbKdcReq::getMessage' was reverted 
to 'KrbKdcReq::encoding'. It does not look wrong but wish I could understand 
the reason.

 * In CredentialsUtil.java, new line missing in 'return creds;' 
(CredentialsUtil::acquireS4U2selfCreds)

 * In java.security, I'd reword the text a bit (and fix a typo). One suggestion 
for you to consider:

"The S4U2proxy Kerberos extension enables a middle service to obtain a service 
ticket to another service on behalf of a user. It requires that the user 
service ticket to the middle service has the forwardable flag set [1]. However, 
some implementations ignore this requirement and accept service tickets with 
the flag unset.

If this security property is set to "true", then

1) The user service ticket, when obtained by the middle service after a 
S4U2self impersonation, is not required to have the forwardable flag set; and,

2) If a S4U2proxy request receives a KRB_ERROR of the KDC_ERR_BADOPTION error 
code and the ticket to the middle service is not forwardable, OpenJDK will try 
the same request in another KDC instead of treating it as a fatal failure.

The default value is "false".

If a system property of the same name is also specified, it supersedes the 
security property value defined here.

[1] 
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/bde93b0e-f3c9-4ddf-9f44-e1453be7af5a
jdk.security.krb5.s4u2proxy.acceptNonForwardableServiceTicket=false
"

Thanks,
Martin.-

> All suggestions accepted, except that I still write out the full name for 
> S4U2proxy in `java.security`.
> 
> For the `KrbKdcReq` method name. It's now `encoding` because it's returning a 
> byte array. `getMessage` was used to return a message type.

Hi @wangweij 

Thanks for considering my suggestions.

I agree with removing the 'forwardable middle service TGT' requirement from 
S4U2Self.

This looks good to me.

Note: I'm not an official JDK Reviewer so you'll need someone else to have a 
look.

Martin.-

-------------

PR: https://git.openjdk.java.net/jdk/pull/6082

Reply via email to