diff options
Diffstat (limited to 'source4')
-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) |