Difference between revisions of "Projects/ConstrainedDelegation"
(24 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | {{project- |
+ | {{project-rel|1.8}} |
==Background== |
==Background== |
||
Line 9: | Line 9: | ||
In constrained delegation, the service passes the KDC a ticket from a user it has authenticated. This "evidence" ticket is placed in the additional tickets field of the TGS-REQ: there is nothing preventing the service from forging this, because it knows its long-term key. To avoid this attack, Windows takes advantage of the fact the PAC is signed with the TGS long-term key: in the constrained delegation case, this is verified before proceeding. |
In constrained delegation, the service passes the KDC a ticket from a user it has authenticated. This "evidence" ticket is placed in the additional tickets field of the TGS-REQ: there is nothing preventing the service from forging this, because it knows its long-term key. To avoid this attack, Windows takes advantage of the fact the PAC is signed with the TGS long-term key: in the constrained delegation case, this is verified before proceeding. |
||
− | Heimdal implements PAC-less constrained delegation by including an authorization data element containing a checksum over the |
+ | Heimdal implements PAC-less constrained delegation by including an authorization data element containing a checksum over the client, authtime, authorization data and delegation path with the TGS key. The ASN.1 encoding of this element is described below: |
<pre> |
<pre> |
||
− | KRB5-AUTHDATA-SIGNTICKET INTEGER ::= |
+ | KRB5-AUTHDATA-SIGNTICKET INTEGER ::= 142 |
KRB5SignedPathPrincipals ::= SEQUENCE OF Principal |
KRB5SignedPathPrincipals ::= SEQUENCE OF Principal |
||
− | -- never encoded on the wire, just used to checksum over |
+ | -- never encoded on the wire, just used to checksum over |
KRB5SignedPathData ::= SEQUENCE { |
KRB5SignedPathData ::= SEQUENCE { |
||
− | + | client[0] Principal OPTIONAL, |
|
− | + | authtime[1] KerberosTime, |
|
− | + | delegated[2] Principals OPTIONAL, |
|
+ | method_data[3] METHOD-DATA OPTIONAL, |
||
+ | authorization_data[4] AuthorizationData OPTIONAL |
||
+ | } |
||
KRB5SignedPath ::= SEQUENCE { |
KRB5SignedPath ::= SEQUENCE { |
||
− | -- DERcoded KRB5SignedPathData |
+ | -- DERcoded KRB5SignedPathData |
− | -- krbtgt key (etype), KeyUsage = XXX |
+ | -- krbtgt key (etype), KeyUsage = XXX |
− | etype[0] ENCTYPE, |
+ | etype[0] ENCTYPE, |
− | cksum[1] Checksum, |
+ | cksum[1] Checksum, |
− | -- srvs delegated though |
+ | -- srvs delegated though |
− | delegated[2] |
+ | delegated[2] Principals OPTIONAL, |
+ | method_data[3] METHOD-DATA OPTIONAL |
||
} |
} |
||
</pre> |
</pre> |
||
− | The checksum is over KRB5SignedPathData |
+ | The checksum is over KRB5SignedPathData. KRB5SignedPath is wrapped in AD-IF-RELEVANT, because it does not need to be understood by application servers. |
==Implementation== |
==Implementation== |
||
Line 38: | Line 38: | ||
===libkrb5=== |
===libkrb5=== |
||
− | New types and encoders are added for the delegation path. |
+ | New types and encoders are added for the delegation path. There is no decoder for the delegation path data, because it is not sent over the wire. |
<pre> |
<pre> |
||
− | typedef struct _krb5_transited_service { |
||
⚫ | |||
− | } krb5_transited_service; |
||
− | |||
typedef struct _krb5_ad_signedpath_data { |
typedef struct _krb5_ad_signedpath_data { |
||
− | krb5_enc_tkt_part enc_tkt_part; |
||
⚫ | |||
⚫ | |||
+ | krb5_timestamp authtime; |
||
⚫ | |||
+ | krb5_pa_data **method_data; |
||
} krb5_ad_signedpath_data; |
} krb5_ad_signedpath_data; |
||
Line 53: | Line 51: | ||
krb5_enctype enctype; |
krb5_enctype enctype; |
||
krb5_checksum checksum; |
krb5_checksum checksum; |
||
− | + | krb5_principal *delegated; |
|
+ | krb5_pa_data **method_data; |
||
} krb5_ad_signedpath; |
} krb5_ad_signedpath; |
||
</pre> |
</pre> |
||
− | Note: krb5_ad_signedpath_data represents data to be checksummed, krb5_ad_signedpath is what is actually encoded and sent on the wire. The enctype field in the latter is a hint to which TGS key to use, but presently this is unused in our implementation. |
+ | Note: krb5_ad_signedpath_data represents data to be checksummed, krb5_ad_signedpath is what is actually encoded and sent on the wire. The enctype field in the latter is a hint to which TGS key to use, but presently this is unused in our implementation: we require it be the same key used to encrypt the ticket. |
Constants are added for the signed path AD type and the checksum key usage: |
Constants are added for the signed path AD type and the checksum key usage: |
||
Line 63: | Line 61: | ||
<pre> |
<pre> |
||
#define KRB5_KEYUSAGE_AD_SIGNEDPATH -21 |
#define KRB5_KEYUSAGE_AD_SIGNEDPATH -21 |
||
− | #define KRB5_AUTHDATA_SIGNTICKET |
+ | #define KRB5_AUTHDATA_SIGNTICKET 142 |
</pre> |
</pre> |
||
I have kept this aligned with Heimdal so that, when using the HDB bridge, a mixed realm of Heimdal and MIT KDCs should interoperate with constrained delegation. |
I have kept this aligned with Heimdal so that, when using the HDB bridge, a mixed realm of Heimdal and MIT KDCs should interoperate with constrained delegation. |
||
⚫ | |||
+ | API changes: |
||
+ | |||
⚫ | |||
+ | * When issuing and verifying KRB5SignedData and AD-KDCIssued, we now ensure the checksum type is keyed |
||
+ | * KDC-issued elements are rejected if present in the AP-REQ authenticator |
||
===KDC=== |
===KDC=== |
||
− | Note: some changes were imported from the HDBBridge branch to speed implementation. |
+ | Note: some changes were imported from the HDBBridge branch to speed implementation. Besides that, the changes are principally confined to kdc_authdata.c. |
− | + | A summary of changes follows: |
|
* We now correctly filter out known KDC issued AD elements when copying authorization data from the TGT. (This uses the krb5int_get_authdata_containee_types() API above.) |
* We now correctly filter out known KDC issued AD elements when copying authorization data from the TGT. (This uses the krb5int_get_authdata_containee_types() API above.) |
||
* Because of the above fix, we can now separate the copying of TGT authdata from the propagation of KDB authdata. We previously relied on the backend to do this. |
* Because of the above fix, we can now separate the copying of TGT authdata from the propagation of KDB authdata. We previously relied on the backend to do this. |
||
− | * A new authdata handler, handle_signedpath_authdata(), is added, which supports the verification and generation of the signed data path. |
+ | * A new authdata handler, handle_signedpath_authdata(), is added, which supports the verification and generation of the signed data path. This element is skipped if the Windows PAC is the only authorization data element, as some versions of Windows have trouble processing additional authorization data. |
− | * The authorization data handlers are now called immediately before the ticket is encrypted, for the purpose of checksumming. |
||
* The merge_authdata() internal API now takes an additional argument denoting whether KDC issued authdata we recognise should be omitted. |
* The merge_authdata() internal API now takes an additional argument denoting whether KDC issued authdata we recognise should be omitted. |
||
− | * |
+ | * Mandatory for KDC authdata is rejected per RFC 4120 |
+ | * When creating a reply ticket, only fields protected by the TGS checksum (client, authtime and authorization data) are copied from the evidence ticket |
||
+ | |||
+ | Finally, the greet_server authdata plugin has been updated for these changes |
||
===KDB=== |
===KDB=== |
||
Line 89: | Line 91: | ||
==Open issues== |
==Open issues== |
||
− | |||
− | * What is the interaction of the ticket checksumming with FAST? |
||
==Status== |
==Status== |
||
Code is in the [http://src.mit.edu/fisheye/browse/krb5/users/lhoward/heimmig users/lhoward/s4u2proxy branch]. |
Code is in the [http://src.mit.edu/fisheye/browse/krb5/users/lhoward/heimmig users/lhoward/s4u2proxy branch]. |
||
+ | |||
+ | To test, use the same t_s4u test added for the Services4User project. |
||
+ | |||
+ | ==Review== |
||
+ | |||
+ | This section documents the review of the project according to [[Project policy]]. |
||
+ | It is divided into multiple sections. First, approvals should be listed. To list an approval type |
||
+ | :<nowiki>#~~~~</nowiki> |
||
+ | (hash mark followed by four tilde characters) on its own line. |
||
+ | The next section is for summarizing discussion, which should take place on krbdev@mit.edu. Provide links to the archive at http://mailman.mit.edu/pipermail/krbdev/ if appropriate. Blocking objections can be noted with <nowiki>{{project-block}}</nowiki>. |
||
+ | |||
+ | ===Approvals=== |
||
+ | |||
+ | #[[User:TomYu|TomYu]] 13:11, 3 November 2009 (UTC) |
||
+ | |||
+ | ===Discussion=== |
Latest revision as of 23:30, 15 February 2010
Contents
Background
Whilst we've had constrained delegation support in the KDC since 1.7, it has required a proprietary backend that supports validating the Windows PAC. This project provides a constrained delegation implementation that works without this requirement.
Architecture
In constrained delegation, the service passes the KDC a ticket from a user it has authenticated. This "evidence" ticket is placed in the additional tickets field of the TGS-REQ: there is nothing preventing the service from forging this, because it knows its long-term key. To avoid this attack, Windows takes advantage of the fact the PAC is signed with the TGS long-term key: in the constrained delegation case, this is verified before proceeding.
Heimdal implements PAC-less constrained delegation by including an authorization data element containing a checksum over the client, authtime, authorization data and delegation path with the TGS key. The ASN.1 encoding of this element is described below:
KRB5-AUTHDATA-SIGNTICKET INTEGER ::= 142 KRB5SignedPathPrincipals ::= SEQUENCE OF Principal -- never encoded on the wire, just used to checksum over KRB5SignedPathData ::= SEQUENCE { client[0] Principal OPTIONAL, authtime[1] KerberosTime, delegated[2] Principals OPTIONAL, method_data[3] METHOD-DATA OPTIONAL, authorization_data[4] AuthorizationData OPTIONAL } KRB5SignedPath ::= SEQUENCE { -- DERcoded KRB5SignedPathData -- krbtgt key (etype), KeyUsage = XXX etype[0] ENCTYPE, cksum[1] Checksum, -- srvs delegated though delegated[2] Principals OPTIONAL, method_data[3] METHOD-DATA OPTIONAL }
The checksum is over KRB5SignedPathData. KRB5SignedPath is wrapped in AD-IF-RELEVANT, because it does not need to be understood by application servers.
Implementation
libkrb5
New types and encoders are added for the delegation path. There is no decoder for the delegation path data, because it is not sent over the wire.
typedef struct _krb5_ad_signedpath_data { krb5_principal client; krb5_timestamp authtime; krb5_principal *delegated; krb5_pa_data **method_data; } krb5_ad_signedpath_data; typedef struct _krb5_ad_signedpath { krb5_enctype enctype; krb5_checksum checksum; krb5_principal *delegated; krb5_pa_data **method_data; } krb5_ad_signedpath;
Note: krb5_ad_signedpath_data represents data to be checksummed, krb5_ad_signedpath is what is actually encoded and sent on the wire. The enctype field in the latter is a hint to which TGS key to use, but presently this is unused in our implementation: we require it be the same key used to encrypt the ticket.
Constants are added for the signed path AD type and the checksum key usage:
#define KRB5_KEYUSAGE_AD_SIGNEDPATH -21 #define KRB5_AUTHDATA_SIGNTICKET 142
I have kept this aligned with Heimdal so that, when using the HDB bridge, a mixed realm of Heimdal and MIT KDCs should interoperate with constrained delegation.
API changes:
- krb5int_get_authdata_containee_types() is added to return the authorization data types within an authdata container without completely decoding it
- When issuing and verifying KRB5SignedData and AD-KDCIssued, we now ensure the checksum type is keyed
- KDC-issued elements are rejected if present in the AP-REQ authenticator
KDC
Note: some changes were imported from the HDBBridge branch to speed implementation. Besides that, the changes are principally confined to kdc_authdata.c.
A summary of changes follows:
- We now correctly filter out known KDC issued AD elements when copying authorization data from the TGT. (This uses the krb5int_get_authdata_containee_types() API above.)
- Because of the above fix, we can now separate the copying of TGT authdata from the propagation of KDB authdata. We previously relied on the backend to do this.
- A new authdata handler, handle_signedpath_authdata(), is added, which supports the verification and generation of the signed data path. This element is skipped if the Windows PAC is the only authorization data element, as some versions of Windows have trouble processing additional authorization data.
- The merge_authdata() internal API now takes an additional argument denoting whether KDC issued authdata we recognise should be omitted.
- Mandatory for KDC authdata is rejected per RFC 4120
- When creating a reply ticket, only fields protected by the TGS checksum (client, authtime and authorization data) are copied from the evidence ticket
Finally, the greet_server authdata plugin has been updated for these changes
KDB
CHECK_ALLOWED_TO_DELEGATE
We provide a CHECK_ALLOWED_TO_DELEGATE db_invoke callback for the LDAP backend that authorizes that target service against the krbAllowedToDelegateTo attribute. There is no support for administrating this attribute via kadmin, or for the DB2 backend.
Open issues
Status
Code is in the users/lhoward/s4u2proxy branch.
To test, use the same t_s4u test added for the Services4User project.
Review
This section documents the review of the project according to Project policy. It is divided into multiple sections. First, approvals should be listed. To list an approval type
- #~~~~
(hash mark followed by four tilde characters) on its own line. The next section is for summarizing discussion, which should take place on krbdev@mit.edu. Provide links to the archive at http://mailman.mit.edu/pipermail/krbdev/ if appropriate. Blocking objections can be noted with {{project-block}}.
Approvals
- TomYu 13:11, 3 November 2009 (UTC)