diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-09-17 09:46:20 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:38:13 -0500 |
commit | f281d7782451efe4211e6e18435ed367c137ea06 (patch) | |
tree | 2a9786a8d3b36046412fe3a6eb5a2a5eacd91fa9 | |
parent | 7f08aa1dd516dfe0e8a79575ed736e1e09a10f9d (diff) | |
download | samba-f281d7782451efe4211e6e18435ed367c137ea06.tar.gz samba-f281d7782451efe4211e6e18435ed367c137ea06.tar.bz2 samba-f281d7782451efe4211e6e18435ed367c137ea06.zip |
r10291: The patch optionally (off by default, not available in all cases) allows
Samba to use the target principal name supplied in the mechTokenMIC of
an SPNEGO negTokenInit.
This isn't a great idea for security reasons, but is how Samba3 behaves,
and allows kerberos to function more often in some environments. It is
only available for CIFS session setups, due to the ordering of the
exchange.
Andrew Bartlett
(This used to be commit f6a645644127ae695a9f7288e0a469f2eb7f3066)
-rw-r--r-- | source4/auth/gensec/gensec.c | 32 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_gssapi.c | 20 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_krb5.c | 48 | ||||
-rw-r--r-- | source4/auth/gensec/spnego.c | 3 | ||||
-rw-r--r-- | source4/param/loadparm.c | 4 |
5 files changed, 85 insertions, 22 deletions
diff --git a/source4/auth/gensec/gensec.c b/source4/auth/gensec/gensec.c index f0256b9668..21e70e1c0e 100644 --- a/source4/auth/gensec/gensec.c +++ b/source4/auth/gensec/gensec.c @@ -707,6 +707,15 @@ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, cons return NT_STATUS_OK; } +const char *gensec_get_target_service(struct gensec_security *gensec_security) +{ + if (gensec_security->target.service) { + return gensec_security->target.service; + } + + return "host"; +} + /** * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed * @@ -731,13 +740,28 @@ const char *gensec_get_target_hostname(struct gensec_security *gensec_security) return NULL; } -const char *gensec_get_target_service(struct gensec_security *gensec_security) +/** + * Set the target principal (assuming it it known, say from the SPNEGO reply) + * - ensures it is talloc()ed + * + */ + +NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal) { - if (gensec_security->target.service) { - return gensec_security->target.service; + gensec_security->target.principal = talloc_strdup(gensec_security, principal); + if (!gensec_security->target.principal) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +const char *gensec_get_target_principal(struct gensec_security *gensec_security) +{ + if (gensec_security->target.principal) { + return gensec_security->target.principal; } - return "host"; + return NULL; } /* diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 69f219fe07..c462cf0ecd 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -229,8 +229,10 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi krb5_error_code ret; NTSTATUS nt_status; gss_buffer_desc name_token; + gss_OID name_type; OM_uint32 maj_stat, min_stat; const char *hostname = gensec_get_target_hostname(gensec_security); + const char *principal; if (!hostname) { DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n")); @@ -248,14 +250,22 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi gensec_gssapi_state = gensec_security->private_data; - name_token.value = talloc_asprintf(gensec_gssapi_state, "%s@%s", - gensec_get_target_service(gensec_security), - hostname); - name_token.length = strlen(name_token.value); + principal = gensec_get_target_principal(gensec_security); + if (principal && lp_client_use_spnego_principal()) { + name_token.value = gensec_get_target_principal(gensec_security); + name_token.length = strlen(name_token.value); + name_type = GSS_C_NULL_OID; + } else { + name_token.value = talloc_asprintf(gensec_gssapi_state, "%s@%s", + gensec_get_target_service(gensec_security), + hostname); + name_token.length = strlen(name_token.value); + name_type = GSS_C_NT_HOSTBASED_SERVICE; + } maj_stat = gss_import_name (&min_stat, &name_token, - GSS_C_NT_HOSTBASED_SERVICE, + name_type, &gensec_gssapi_state->server_name); if (maj_stat) { DEBUG(2, ("GSS Import name of %s failed: %s\n", diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index d4147496fd..3fa2ccd6de 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -50,10 +50,14 @@ struct gensec_krb5_state { krb5_ticket *ticket; }; -static int gensec_krb5_destory(void *ptr) +static int gensec_krb5_destroy(void *ptr) { struct gensec_krb5_state *gensec_krb5_state = ptr; + if (!gensec_krb5_state->smb_krb5_context) { + /* We can't clean anything else up unless we started up this far */ + return 0; + } if (gensec_krb5_state->enc_ticket.length) { kerberos_free_data_contents(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->enc_ticket); @@ -88,6 +92,7 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security) gensec_security->private_data = gensec_krb5_state; + gensec_krb5_state->smb_krb5_context = NULL; gensec_krb5_state->auth_context = NULL; gensec_krb5_state->ticket = NULL; ZERO_STRUCT(gensec_krb5_state->enc_ticket); @@ -95,7 +100,7 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security) gensec_krb5_state->session_key = data_blob(NULL, 0); gensec_krb5_state->pac = data_blob(NULL, 0); - talloc_set_destructor(gensec_krb5_state, gensec_krb5_destory); + talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy); return NT_STATUS_OK; } @@ -141,8 +146,10 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security krb5_error_code ret; NTSTATUS nt_status; struct ccache_container *ccache_container; + const char *hostname; + krb5_flags ap_req_options = AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED; - const char *hostname = gensec_get_target_hostname(gensec_security); + hostname = gensec_get_target_hostname(gensec_security); if (!hostname) { DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n")); return NT_STATUS_INVALID_PARAMETER; @@ -178,18 +185,35 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security return NT_STATUS_INTERNAL_ERROR; } - if (!ret) { + if (ret == 0) { + char *principal; krb5_data in_data; in_data.length = 0; - ret = krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context, - &gensec_krb5_state->auth_context, - AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED, - gensec_get_target_service(gensec_security), - hostname, - &in_data, ccache_container->ccache, - &gensec_krb5_state->enc_ticket); - + principal = gensec_get_target_principal(gensec_security); + if (principal && lp_client_use_spnego_principal()) { + krb5_principal target_principal; + ret = krb5_parse_name(gensec_krb5_state->smb_krb5_context->krb5_context, principal, + &target_principal); + if (ret == 0) { + ret = krb5_mk_req_exact(gensec_krb5_state->smb_krb5_context->krb5_context, + &gensec_krb5_state->auth_context, + ap_req_options, + target_principal, + &in_data, ccache_container->ccache, + &gensec_krb5_state->enc_ticket); + krb5_free_principal(gensec_krb5_state->smb_krb5_context->krb5_context, + target_principal); + } + } else { + ret = krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context, + &gensec_krb5_state->auth_context, + ap_req_options, + gensec_get_target_service(gensec_security), + hostname, + &in_data, ccache_container->ccache, + &gensec_krb5_state->enc_ticket); + } } switch (ret) { case 0: diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c index 133530833b..570ca89f03 100644 --- a/source4/auth/gensec/spnego.c +++ b/source4/auth/gensec/spnego.c @@ -636,7 +636,8 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA } if (spnego.negTokenInit.targetPrincipal) { - DEBUG(5, ("Server claims it's principal name is %s (ignored)\n", spnego.negTokenInit.targetPrincipal)); + DEBUG(5, ("Server claims it's principal name is %s\n", spnego.negTokenInit.targetPrincipal)); + gensec_set_target_principal(gensec_security, spnego.negTokenInit.targetPrincipal); } nt_status = gensec_spnego_parse_negTokenInit(gensec_security, diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index 3f6a22d404..244ce27419 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -184,6 +184,7 @@ typedef struct BOOL bClientPlaintextAuth; BOOL bClientLanManAuth; BOOL bClientNTLMv2Auth; + BOOL client_use_spnego_principal; BOOL bHostMSDfs; BOOL bUnicode; BOOL bUnixExtensions; @@ -422,6 +423,7 @@ static struct parm_struct parm_table[] = { {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE}, @@ -659,6 +661,7 @@ static void init_globals(void) do_parameter("ClientLanManAuth", "True", NULL); do_parameter("LanmanAuth", "True", NULL); do_parameter("NTLMAuth", "True", NULL); + do_parameter("client use spnego principal", "False", NULL); do_parameter("UnixExtensions", "False", NULL); @@ -853,6 +856,7 @@ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth) FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth) FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth) FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth) +FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal) FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs) FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions) FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego) |