{
struct gensec_gssapi_state *gensec_gssapi_state
= talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
- NTSTATUS nt_status;
OM_uint32 maj_stat, min_stat;
OM_uint32 min_stat2;
gss_buffer_desc input_token = { 0, NULL };
gss_buffer_desc output_token = { 0, NULL };
- struct cli_credentials *cli_creds = gensec_get_credentials(gensec_security);
- const char *target_principal = gensec_get_target_principal(gensec_security);
- const char *hostname = gensec_get_target_hostname(gensec_security);
- const char *service = gensec_get_target_service(gensec_security);
gss_OID gss_oid_p = NULL;
OM_uint32 time_req = 0;
OM_uint32 time_rec = 0;
switch (gensec_security->gensec_role) {
case GENSEC_CLIENT:
{
- const char *client_realm = NULL;
-#ifdef SAMBA4_USES_HEIMDAL
-#else
- bool fallback = false;
-#endif
-
- /*
- * With credentials for
- * administrator@FOREST1.EXAMPLE.COM this patch changes
- * the target_principal for the ldap service of host
- * dc2.forest2.example.com from
- *
- * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
- *
- * to
- *
- * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM
- *
- * Typically
- * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
- * should be used in order to allow the KDC of
- * FOREST1.EXAMPLE.COM to generate a referral ticket
- * for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM.
- *
- * The problem is that KDCs only return such referral
- * tickets if there's a forest trust between
- * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM. If
- * there's only an external domain trust between
- * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM the KDC
- * of FOREST1.EXAMPLE.COM will respond with
- * S_PRINCIPAL_UNKNOWN when being asked for
- * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM.
- *
- * In the case of an external trust the client can
- * still ask explicitly for
- * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM and
- * the KDC of FOREST1.EXAMPLE.COM will generate it.
- *
- * From there the client can use the
- * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM
- * ticket and ask a KDC of FOREST2.EXAMPLE.COM for a
- * service ticket for
- * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM.
- *
- * With Heimdal we'll get the fallback on
- * S_PRINCIPAL_UNKNOWN behavior when we pass
- * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM as
- * target principal. As _krb5_get_cred_kdc_any() first
- * calls get_cred_kdc_referral() (which always starts
- * with the client realm) and falls back to
- * get_cred_kdc_capath() (which starts with the given
- * realm).
- *
- * MIT krb5 only tries the given realm of the target
- * principal, if we want to autodetect support for
- * transitive forest trusts, would have to do the
- * fallback ourself.
- */
- client_realm = cli_credentials_get_realm(cli_creds);
-#ifndef SAMBA4_USES_HEIMDAL
- if (gensec_gssapi_state->server_name == NULL) {
- nt_status = gssapi_setup_server_principal(gensec_gssapi_state,
- target_principal,
- service,
- hostname,
- client_realm,
- gensec_gssapi_state->gss_oid,
- &gensec_gssapi_state->target_principal,
- &gensec_gssapi_state->server_name);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
-
- maj_stat = gss_init_sec_context(&min_stat,
- gensec_gssapi_state->client_creds,
- &gensec_gssapi_state->gssapi_context,
- gensec_gssapi_state->server_name,
- gensec_gssapi_state->gss_oid,
- gensec_gssapi_state->gss_want_flags,
- time_req,
- gensec_gssapi_state->input_chan_bindings,
- &input_token,
- &gss_oid_p,
- &output_token,
- &gensec_gssapi_state->gss_got_flags, /* ret flags */
- &time_rec);
- if (maj_stat != GSS_S_FAILURE) {
- goto init_sec_context_done;
- }
- if (min_stat != (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
- goto init_sec_context_done;
- }
- if (target_principal != NULL) {
- goto init_sec_context_done;
- }
-
- fallback = true;
- TALLOC_FREE(gensec_gssapi_state->target_principal);
- gss_release_name(&min_stat2, &gensec_gssapi_state->server_name);
- }
-#endif /* !SAMBA4_USES_HEIMDAL */
- if (gensec_gssapi_state->server_name == NULL) {
- const char *server_realm = NULL;
-
- server_realm = smb_krb5_get_realm_from_hostname(gensec_gssapi_state,
- hostname,
- client_realm);
- if (server_realm == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
-#ifndef SAMBA4_USES_HEIMDAL
- if (fallback &&
- strequal(client_realm, server_realm)) {
- goto init_sec_context_done;
- }
-#endif /* !SAMBA4_USES_HEIMDAL */
-
- nt_status = gssapi_setup_server_principal(gensec_gssapi_state,
- target_principal,
- service,
- hostname,
- server_realm,
- gensec_gssapi_state->gss_oid,
- &gensec_gssapi_state->target_principal,
- &gensec_gssapi_state->server_name);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
- }
-
maj_stat = gss_init_sec_context(&min_stat,
gensec_gssapi_state->client_creds,
&gensec_gssapi_state->gssapi_context,
&output_token,
&gensec_gssapi_state->gss_got_flags, /* ret flags */
&time_rec);
- goto init_sec_context_done;
- /* JUMP! */
-init_sec_context_done:
if (gss_oid_p) {
gensec_gssapi_state->gss_oid = gss_oid_p;
}