Microsoft's S4U2Self extension allows a service to obtain a ticket to itself from an arbitrary user. The user can be identified by regular krb5 principal, by enterprise principal, or by X.509 certificate. In the latter two cases, AS requests are used to identify the client's realm. After the realm is identified, a TGS-REQ with S4U2Self pa- data is used to obtain the ticket. (In the cross-realm case, multiple TGS-REQs are required.) Commit 0e39f8a3ad915eeb0131fb4a87b0fef304101cfd added the client code for S4U2Self to the MIT krb5 tree. It contained support for using an X.509 certificate to identify the user, but that functionality was not reachable by any public path. Isaac Boukris has identified and corrected the following issues with the client code for using X.509 certificates: * During realm identification, the code attempted to present the X.509 certificate using an optimistic preauth list and special handling in preauth2.c. Changes to the preauth framework caused this attempt to fail (because it did not produce authenticating padata from a clpreauth module) and fall back to sending an AS request without the cert. * When performing realm identification with a cert, the existing code uses a client principal with NT-ENTERPRISE type and no data components. Windows clients provide a principal of type NT-X500- PRINCIPAL and the certificate subject as a single data component. Doing that would require partially decoding the certificate. Experimentally, using a single empty data component actually works better with Windows KDCs than including the certificate subject (it works with cross-realm), so we should do that instead. * If an enterprise principal and cert are both presented to the API, to be consistent with Windows clients we should do realm identification with just the enterprise principal, and then prsent the cert in the TGS request. The current code presents (well, tries to present) the certificate during realm identification in this case. * In krb5_get_self_cred_from_kdc(), if no client principal is provided, the code to build s4u_user.user_id.user did not terminate the krb5_build_principal_ext() variable argument list and could therefore crash. * In the same function, the PA-FOR_USER padata input is supplied to krb5_get_cred_via_tkt_ext() via an in_padata list, while the PA-FOR- X509-USER padata is constructed via a callback because so that the TGS subkey can be used to build it. When the TGS reply is received, krb5int_process_tgs_reply() looks for PA-FOR_USER or PA-FOR-X509-USER padata in the in_padata list to decide whether to use S4U2Self logic to validate the client. Because the PA-FOR-X509-USER padata is not supplied via the in_padata list, the code will never find that type. In the usual case, we will find the PA-FOR_USER type and do the right thing, but in the cert-only case there is no PA-FOR_USER padata value, so the S4U2Self logic is not applied.