The branch, master has been updated via cb3d6c4 heimdal Add clock-skew handling to DCE-style GSSAPI via 10c82d0 s4-auth Supply more useful error messages on Kerberos failure via cd4c3d6 s4-auth Fix typos in samba4 auth code via 3c4376c s4-dsdb Explain why we may not use the GC name in some situations. via e77e162 s4-selftest fix indentation from 11b4202 s4-repl: fixed replication notifications to RODCs
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit cb3d6c407e9ab3e5e8dffeae5e2e77769056d75a Author: Andrew Bartlett <abart...@samba.org> Date: Mon Nov 8 17:38:38 2010 +1100 heimdal Add clock-skew handling to DCE-style GSSAPI The clock skew handling was previously only on properly wrapped GSSAPI, and was skipped for DCE-style. This allows the ASN.1 errors from the krb5_rd_req to suggest parsing as a kerberos error packet. Andrew Bartlett Autobuild-User: Andrew Tridgell <tri...@samba.org> Autobuild-Date: Mon Nov 8 07:58:09 UTC 2010 on sn-devel-104 commit 10c82d0619f71e8c6dac5755d2b327c2a543cca4 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Nov 8 16:55:17 2010 +1100 s4-auth Supply more useful error messages on Kerberos failure The practice of returning only NT_STATUS_INVALID_PARAMETER hasn't helped our users to debug problems effectivly, and so we now return more errors and try and give a more useful debug message when then happen. Andrew Bartlett commit cd4c3d6d7ba987abf7b2ae7b826b9ef0c8cb0f2f Author: Brad Hards <br...@frogmouth.net> Date: Mon Nov 8 12:15:50 2010 +1100 s4-auth Fix typos in samba4 auth code commit 3c4376c4d8dbd7c5db52df7442ec410dbfb06e62 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Nov 8 12:13:32 2010 +1100 s4-dsdb Explain why we may not use the GC name in some situations. This delicate balance caused us a bit of a puzzle when we could not work out why an DC join failed with the new python scripts. Andrew Bartlett commit e77e162b973632b9717b48548b3b88e2ef2fd896 Author: Andrew Bartlett <abart...@samba.org> Date: Sat Nov 6 13:48:31 2010 +1100 s4-selftest fix indentation ----------------------------------------------------------------------- Summary of changes: selftest/target/Samba4.pm | 6 +- source4/auth/gensec/gensec_gssapi.c | 51 ++++++---- source4/auth/gensec/gensec_gssapi.h | 2 + source4/auth/gensec/spnego.c | 2 + source4/dsdb/repl/drepl_partitions.c | 8 ++ source4/heimdal/lib/gssapi/krb5/init_sec_context.c | 104 ++++++++++++-------- 6 files changed, 111 insertions(+), 62 deletions(-) Changeset truncated at 500 lines: diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 56b6186..4242b86 100644 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1377,11 +1377,11 @@ sub setup_rpc_proxy($$$) my $env = $self->provision_rpc_proxy($path, $dc_vars); if (defined $env) { - $self->check_or_start($env, ($ENV{SMBD_MAXTIME} or 7500)); + $self->check_or_start($env, ($ENV{SMBD_MAXTIME} or 7500)); - $self->wait_for_start($env); + $self->wait_for_start($env); - $self->{vars}->{rpc_proxy} = $env; + $self->{vars}->{rpc_proxy} = $env; } return $env; } diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 4729ed6..a03cf9e 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -315,7 +315,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi gss_OID name_type; OM_uint32 maj_stat, min_stat; const char *hostname = gensec_get_target_hostname(gensec_security); - const char *principal; struct gssapi_creds_container *gcc; const char *error_string; @@ -339,18 +338,18 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state); - principal = gensec_get_target_principal(gensec_security); - if (principal) { + gensec_gssapi_state->target_principal = gensec_get_target_principal(gensec_security); + if (gensec_gssapi_state->target_principal) { name_type = GSS_C_NULL_OID; } else { - principal = talloc_asprintf(gensec_gssapi_state, "%s/%...@%s", + gensec_gssapi_state->target_principal = talloc_asprintf(gensec_gssapi_state, "%s/%...@%s", gensec_get_target_service(gensec_security), hostname, lpcfg_realm(gensec_security->settings->lp_ctx)); name_type = GSS_C_NT_USER_NAME; } - name_token.value = discard_const_p(uint8_t, principal); - name_token.length = strlen(principal); + name_token.value = discard_const_p(uint8_t, gensec_gssapi_state->target_principal); + name_token.length = strlen(gensec_gssapi_state->target_principal); maj_stat = gss_import_name (&min_stat, @@ -373,12 +372,12 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi case KRB5KDC_ERR_PREAUTH_FAILED: return NT_STATUS_LOGON_FAILURE; case KRB5_KDC_UNREACH: - DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", principal, error_string)); - return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ + DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string)); + return NT_STATUS_NO_LOGON_SERVERS; case KRB5_CC_NOTFOUND: case KRB5_CC_END: - DEBUG(3, ("Error preparing credentials we require to contact %s : %s\n", principal, error_string)); - return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ + DEBUG(2, ("Error obtaining ticket we require to contact %s: (possibly due to clock skew between us and the KDC) %s\n", gensec_gssapi_state->target_principal, error_string)); + return NT_STATUS_TIME_DIFFERENCE_AT_DC; default: DEBUG(1, ("Aquiring initiator credentials failed: %s\n", error_string)); return NT_STATUS_UNSUCCESSFUL; @@ -553,9 +552,9 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, gensec_gssapi_state->sasl_state = STAGE_DONE; if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) { - DEBUG(5, ("GSSAPI Connection will be cryptographicly sealed\n")); + DEBUG(5, ("GSSAPI Connection will be cryptographically sealed\n")); } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { - DEBUG(5, ("GSSAPI Connection will be cryptographicly signed\n")); + DEBUG(5, ("GSSAPI Connection will be cryptographically signed\n")); } else { DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n")); } @@ -569,12 +568,24 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, return NT_STATUS_MORE_PROCESSING_REQUIRED; } else if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) { switch (min_stat) { + case KRB5KRB_AP_ERR_TKT_NYV: + DEBUG(1, ("Error with ticket to contact %s: possible clock skew between us and the KDC or target server: %s\n", + gensec_gssapi_state->target_principal, + gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + return NT_STATUS_TIME_DIFFERENCE_AT_DC; /* Make SPNEGO ignore us, we can't go any further here */ + case KRB5KRB_AP_ERR_TKT_EXPIRED: + DEBUG(1, ("Error with ticket to contact %s: ticket is expired, possible clock skew between us and the KDC or target server: %s\n", + gensec_gssapi_state->target_principal, + gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ case KRB5_KDC_UNREACH: - DEBUG(3, ("Cannot reach a KDC we require: %s\n", + DEBUG(3, ("Cannot reach a KDC we require in order to obtain a ticetk to %s: %s\n", + gensec_gssapi_state->target_principal, gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); - return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ + return NT_STATUS_NO_LOGON_SERVERS; /* Make SPNEGO ignore us, we can't go any further here */ case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: - DEBUG(3, ("Server is not registered with our KDC: %s\n", + DEBUG(3, ("Server %s is not registered with our KDC: %s\n", + gensec_gssapi_state->target_principal, gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ case KRB5KRB_AP_ERR_MSG_TYPE: @@ -688,11 +699,11 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, gensec_gssapi_state->sasl_state = STAGE_DONE; if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) { - DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly sealed\n")); + DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically sealed\n")); } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { - DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly signed\n")); + DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically signed\n")); } else { - DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographicly protection\n")); + DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographically protection\n")); } return NT_STATUS_OK; @@ -816,9 +827,9 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */ gensec_gssapi_state->sasl_state = STAGE_DONE; if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) { - DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly sealed\n")); + DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically sealed\n")); } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { - DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly signed\n")); + DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically signed\n")); } else { DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n")); } diff --git a/source4/auth/gensec/gensec_gssapi.h b/source4/auth/gensec/gensec_gssapi.h index b55b439..1b826b9 100644 --- a/source4/auth/gensec/gensec_gssapi.h +++ b/source4/auth/gensec/gensec_gssapi.h @@ -64,5 +64,7 @@ struct gensec_gssapi_state { size_t max_wrap_buf_size; int gss_exchange_count; size_t sig_size; + + const char *target_principal; }; diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c index 4902cd8..813bf0a 100644 --- a/source4/auth/gensec/spnego.c +++ b/source4/auth/gensec/spnego.c @@ -495,6 +495,8 @@ static NTSTATUS gensec_spnego_parse_negTokenInit(struct gensec_security *gensec_ * of this mech */ if (spnego_state->state_position != SPNEGO_SERVER_START) { if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER) || + NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_LOGON_SERVERS) || + NT_STATUS_EQUAL(nt_status, NT_STATUS_TIME_DIFFERENCE_AT_DC) || NT_STATUS_EQUAL(nt_status, NT_STATUS_CANT_ACCESS_DOMAIN_INFO)) { /* Pretend we never started it (lets the first run find some incompatible demand) */ diff --git a/source4/dsdb/repl/drepl_partitions.c b/source4/dsdb/repl/drepl_partitions.c index 70173fe..d4511f6 100644 --- a/source4/dsdb/repl/drepl_partitions.c +++ b/source4/dsdb/repl/drepl_partitions.c @@ -141,6 +141,14 @@ NTSTATUS dreplsrv_get_target_principal(struct dreplsrv_service *s, return NT_STATUS_OK; } + /* All DCs have the GC/hostname/realm name, but if some of the + * preconditions are not satisfied, then we will fall back to + * the + * E3514235-4B06-11D1-AB04-00C04FC2DCD2/${NTDSGUID}/${DNSDOMAIN} + * name. This means that if a AD server has a dnsHostName set + * on it's record, it must also have GC/hostname/realm + * servicePrincipalName */ + *target_principal = talloc_asprintf(mem_ctx, "GC/%s/%s", hostname, lpcfg_dnsdomain(s->task->lp_ctx)); diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c index f4e103a..4538a53 100644 --- a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -698,6 +698,44 @@ failure: return ret; } +static krb5_error_code +handle_error_packet(krb5_context context, + gsskrb5_ctx ctx, + krb5_data indata) +{ + krb5_error_code kret; + KRB_ERROR error; + + kret = krb5_rd_error(context, &indata, &error); + if (kret == 0) { + kret = krb5_error_from_rd_error(context, &error, NULL); + + /* save the time skrew for this host */ + if (kret == KRB5KRB_AP_ERR_SKEW) { + krb5_data timedata; + unsigned char p[4]; + int32_t t = error.stime - time(NULL); + + p[0] = (t >> 24) & 0xFF; + p[1] = (t >> 16) & 0xFF; + p[2] = (t >> 8) & 0xFF; + p[3] = (t >> 0) & 0xFF; + + timedata.data = p; + timedata.length = sizeof(p); + + krb5_cc_set_config(context, ctx->ccache, ctx->target, + "time-offset", &timedata); + + if ((ctx->more_flags & RETRIED) == 0) + ctx->state = INITIATOR_RESTART; + ctx->more_flags |= RETRIED; + } + free_KRB_ERROR (&error); + } + return kret; +} + static OM_uint32 repl_mutual @@ -730,6 +768,24 @@ repl_mutual /* There is no OID wrapping. */ indata.length = input_token->length; indata.data = input_token->value; + kret = krb5_rd_rep (context, + ctx->auth_context, + &indata, + &repl); + if (kret >= ASN1_BAD_TIMEFORMAT && kret <= ASN1_INDEF_EXTRA_DATA) { + ret = _gsskrb5_decapsulate (minor_status, + input_token, + &indata, + "\x03\x00", + GSS_KRB5_MECHANISM); + if (ret == GSS_S_COMPLETE) { + *minor_status = handle_error_packet(context, ctx, indata); + return GSS_S_FAILURE; + } + } else if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } } else { ret = _gsskrb5_decapsulate (minor_status, input_token, @@ -744,50 +800,20 @@ repl_mutual "\x03\x00", GSS_KRB5_MECHANISM); if (ret == GSS_S_COMPLETE) { - KRB_ERROR error; - - kret = krb5_rd_error(context, &indata, &error); - if (kret == 0) { - kret = krb5_error_from_rd_error(context, &error, NULL); - - /* save the time skrew for this host */ - if (kret == KRB5KRB_AP_ERR_SKEW) { - krb5_data timedata; - unsigned char p[4]; - int32_t t = error.stime - time(NULL); - - p[0] = (t >> 24) & 0xFF; - p[1] = (t >> 16) & 0xFF; - p[2] = (t >> 8) & 0xFF; - p[3] = (t >> 0) & 0xFF; - - timedata.data = p; - timedata.length = sizeof(p); - - krb5_cc_set_config(context, ctx->ccache, ctx->target, - "time-offset", &timedata); - - if ((ctx->more_flags & RETRIED) == 0) - ctx->state = INITIATOR_RESTART; - ctx->more_flags |= RETRIED; - } - free_KRB_ERROR (&error); - } - *minor_status = kret; + *minor_status = handle_error_packet(context, ctx, indata); return GSS_S_FAILURE; } - return ret; + } + kret = krb5_rd_rep (context, + ctx->auth_context, + &indata, + &repl); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; } } - kret = krb5_rd_rep (context, - ctx->auth_context, - &indata, - &repl); - if (kret) { - *minor_status = kret; - return GSS_S_FAILURE; - } krb5_free_ap_rep_enc_part (context, repl); -- Samba Shared Repository