s4-auth Supply more useful error messages on Kerberos failure
authorAndrew Bartlett <abartlet@samba.org>
Mon, 8 Nov 2010 05:55:17 +0000 (16:55 +1100)
committerAndrew Tridgell <tridge@samba.org>
Mon, 8 Nov 2010 07:15:23 +0000 (18:15 +1100)
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

source4/auth/gensec/gensec_gssapi.c
source4/auth/gensec/gensec_gssapi.h
source4/auth/gensec/spnego.c

index 3c579fee50989397f214f31f0a3118623a1bca3f..a03cf9edd7b11bc9988399145529c162b68013a0 100644 (file)
@@ -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@%s",
+               gensec_gssapi_state->target_principal = talloc_asprintf(gensec_gssapi_state, "%s/%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;
@@ -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:
index b55b4391e0cd001094c1576604b65e760c85554c..1b826b963d797bebe8d15d0bf0e0dfac29e489ea 100644 (file)
@@ -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;
 };
 
index 4902cd8ee120bb44f6b23b63359c48e42db61075..813bf0a730e3e071655509e4fd4ec437e53e9c3b 100644 (file)
@@ -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) */