TODO downgrade on LOGON_FAILURE??? gensec: move event-using code to gensec_update...
authorAndrew Bartlett <abartlet@samba.org>
Mon, 17 Oct 2011 02:46:57 +0000 (13:46 +1100)
committerStefan Metzmacher <metze@samba.org>
Mon, 17 Oct 2011 08:00:44 +0000 (10:00 +0200)
This ensures that only gensec_update() will require an event context argument
when the API is refactored.

Andrew Bartlett

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

index 55610f57425ee69308e80e493e47f2027b070c7f..564c20cb48223b1c5fcda4a68e21a5fe1693704e 100644 (file)
@@ -267,18 +267,63 @@ static NTSTATUS gensec_gssapi_sasl_server_start(struct gensec_security *gensec_s
        return nt_status;
 }
 
+static NTSTATUS gensec_gssapi_client_creds(struct gensec_security *gensec_security)
+{
+       struct gensec_gssapi_state *gensec_gssapi_state;
+       struct gssapi_creds_container *gcc;
+       struct cli_credentials *creds = gensec_get_credentials(gensec_security);
+       const char *error_string;
+       int ret;
+
+       gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
+
+       /* Only run this the first time the update() call is made */
+       if (gensec_gssapi_state->client_cred) {
+               return NT_STATUS_OK;
+       }
+
+       ret = cli_credentials_get_client_gss_creds(creds,
+                                                      gensec_security->event_ctx,
+                                                      gensec_security->settings->lp_ctx, &gcc, &error_string);
+       switch (ret) {
+       case 0:
+               break;
+       case EINVAL:
+               DEBUG(3, ("Cannot obtain client GSS credentials we need to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
+               return NT_STATUS_INVALID_PARAMETER;
+       case KRB5KDC_ERR_PREAUTH_FAILED:
+       case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
+               DEBUG(1, ("Wrong username or password: %s\n", error_string));
+               return NT_STATUS_LOGON_FAILURE;
+       case KRB5_KDC_UNREACH:
+               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(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;
+       }
+
+       gensec_gssapi_state->client_cred = gcc;
+       if (!talloc_reference(gensec_gssapi_state, gcc)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
 {
        struct gensec_gssapi_state *gensec_gssapi_state;
        struct cli_credentials *creds = gensec_get_credentials(gensec_security);
-       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);
-       struct gssapi_creds_container *gcc;
-       const char *error_string;
 
        if (!hostname) {
                DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
@@ -329,33 +374,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       ret = cli_credentials_get_client_gss_creds(creds, 
-                                                  gensec_security->event_ctx, 
-                                                  gensec_security->settings->lp_ctx, &gcc, &error_string);
-       switch (ret) {
-       case 0:
-               break;
-       case KRB5KDC_ERR_PREAUTH_FAILED:
-       case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
-               DEBUG(1, ("Wrong username or password: %s\n", error_string));
-               return NT_STATUS_LOGON_FAILURE;
-       case KRB5_KDC_UNREACH:
-               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(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;
-       }
-
-       gensec_gssapi_state->client_cred = gcc;
-       if (!talloc_reference(gensec_gssapi_state, gcc)) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       
        return NT_STATUS_OK;
 }
 
@@ -426,6 +444,12 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
                {
                        struct gsskrb5_send_to_kdc send_to_kdc;
                        krb5_error_code ret;
+
+                       nt_status = gensec_gssapi_client_creds(gensec_security);
+                       if (!NT_STATUS_IS_OK(nt_status)) {
+                               return nt_status;
+                       }
+
                        send_to_kdc.func = smb_krb5_send_and_recv_func;
                        send_to_kdc.ptr = gensec_security->event_ctx;
 
index b3a20e4b63d31b4edfda66083b18851b29d40098..f17245ccec0d83b95e094aca3d6989a74d54a652 100644 (file)
@@ -232,16 +232,9 @@ static NTSTATUS gensec_fake_gssapi_krb5_server_start(struct gensec_security *gen
 
 static NTSTATUS gensec_krb5_common_client_start(struct gensec_security *gensec_security, bool gssapi)
 {
+       const char *hostname;
        struct gensec_krb5_state *gensec_krb5_state;
-       krb5_error_code ret;
        NTSTATUS nt_status;
-       struct ccache_container *ccache_container;
-       const char *hostname;
-       const char *error_string;
-       const char *principal;
-       krb5_data in_data;
-       struct tevent_context *previous_ev;
-
        hostname = gensec_get_target_hostname(gensec_security);
        if (!hostname) {
                DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
@@ -276,8 +269,24 @@ static NTSTATUS gensec_krb5_common_client_start(struct gensec_security *gensec_s
                        gensec_krb5_state->ap_req_options |= AP_OPTS_MUTUAL_REQUIRED;
                }
        }
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS gensec_krb5_common_client_creds(struct gensec_security *gensec_security, bool gssapi)
+{
+       struct gensec_krb5_state *gensec_krb5_state;
+       krb5_error_code ret;
+       struct ccache_container *ccache_container;
+       const char *error_string;
+       const char *principal;
+       const char *hostname;
+       krb5_data in_data;
+       struct tevent_context *previous_ev;
+
+       gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;
 
        principal = gensec_get_target_principal(gensec_security);
+       hostname = gensec_get_target_hostname(gensec_security);
 
        ret = cli_credentials_get_ccache(gensec_get_credentials(gensec_security), 
                                         gensec_security->event_ctx, 
@@ -425,6 +434,11 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
        {
                DATA_BLOB unwrapped_out;
                
+               nt_status = gensec_krb5_common_client_creds(gensec_security, gensec_krb5_state->gssapi);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+
                if (gensec_krb5_state->gssapi) {
                        unwrapped_out = data_blob_talloc(out_mem_ctx, gensec_krb5_state->enc_ticket.data, gensec_krb5_state->enc_ticket.length);
                        
index 66204ee26217adfb8c82b149a440539d58cd08b8..71cdaff978303912cca26f11b756aa285e2a3f29 100644 (file)
@@ -515,11 +515,12 @@ static NTSTATUS gensec_spnego_parse_negTokenInit(struct gensec_security *gensec_
                        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_LOGON_FAILURE) ||
                                    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) */
                                        
-                                       DEBUG(1, ("SPNEGO(%s) NEG_TOKEN_INIT failed to parse: %s\n", 
+                                       DEBUG(3, ("SPNEGO(%s) NEG_TOKEN_INIT failed: %s\n", 
                                                  spnego_state->sub_sec_security->ops->name, nt_errstr(nt_status)));
                                        talloc_free(spnego_state->sub_sec_security);
                                        spnego_state->sub_sec_security = NULL;