diff options
author | Andreas Schneider <asn@samba.org> | 2017-03-09 08:05:26 +0100 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2017-03-10 11:37:22 +0100 |
commit | 3ba1ad1f8c7871070d0ecbe5d49c5c44afe98bbf (patch) | |
tree | f75b7797c698c0bb96708f94ac324e6dcc0ed9c4 /source3/librpc | |
parent | e6b1e58874de30d094f9bce474479cfddb39d3fc (diff) | |
download | samba-3ba1ad1f8c7871070d0ecbe5d49c5c44afe98bbf.tar.gz |
s3:gse: Move setup of service_principal to update function
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Andreas Schneider <asn@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source3/librpc')
-rw-r--r-- | source3/librpc/crypto/gse.c | 97 |
1 files changed, 71 insertions, 26 deletions
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c index 8fee44424c7..9d433439395 100644 --- a/source3/librpc/crypto/gse.c +++ b/source3/librpc/crypto/gse.c @@ -255,8 +255,6 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER; gss_OID oid = discard_const(GSS_KRB5_CRED_NO_CI_FLAGS_X); #endif - char *server_principal = NULL; - char *server_realm = NULL; NTSTATUS status; if (!server || !service) { @@ -270,28 +268,6 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - /* Guess the realm based on the supplied service, and avoid the GSS libs - doing DNS lookups which may fail. - */ - server_realm = smb_krb5_get_realm_from_hostname(mem_ctx, - server, - realm); - if (server_realm == NULL) { - return NT_STATUS_NO_MEMORY; - } - - status = gse_setup_server_principal(mem_ctx, - NULL, - service, - server, - server_realm, - &server_principal, - &gse_ctx->server_name); - TALLOC_FREE(server_realm); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* TODO: get krb5 ticket using username/password, if no valid * one already available in ccache */ @@ -343,11 +319,9 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, #endif *_gse_ctx = gse_ctx; - TALLOC_FREE(server_principal); return NT_STATUS_OK; err_out: - TALLOC_FREE(server_principal); TALLOC_FREE(gse_ctx); return status; } @@ -367,10 +341,81 @@ static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, NTSTATUS status; OM_uint32 time_rec = 0; struct timeval tv; + struct cli_credentials *cli_creds = gensec_get_credentials(gensec_security); + const char *hostname = gensec_get_target_hostname(gensec_security); + const char *service = gensec_get_target_service(gensec_security); + const char *client_realm = cli_credentials_get_realm(cli_creds); + char *server_principal = NULL; + char *server_realm = NULL; in_data.value = token_in->data; in_data.length = token_in->length; + /* + * 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. + */ + if (gse_ctx->server_name == NULL) { + server_realm = smb_krb5_get_realm_from_hostname(mem_ctx, + hostname, + client_realm); + if (server_realm == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = gse_setup_server_principal(mem_ctx, + NULL, + service, + hostname, + server_realm, + &server_principal, + &gse_ctx->server_name); + TALLOC_FREE(server_realm); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + TALLOC_FREE(server_principal); + } + gss_maj = gss_init_sec_context(&gss_min, gse_ctx->creds, &gse_ctx->gssapi_context, |