From 130432987826662c2187e7a88ad9a2d9dda0cd1e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 17 Oct 2011 13:46:57 +1100 Subject: [PATCH] TODO downgrade on LOGON_FAILURE??? gensec: move event-using code to gensec_update() hooks out of gensec_start*() 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 | 84 ++++++++++++++++++----------- source4/auth/gensec/gensec_krb5.c | 30 ++++++++--- source4/auth/gensec/spnego.c | 3 +- 3 files changed, 78 insertions(+), 39 deletions(-) diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 55610f57425e..564c20cb4822 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -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; diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index b3a20e4b63d3..f17245ccec0d 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -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); diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c index 66204ee26217..71cdaff97830 100644 --- a/source4/auth/gensec/spnego.c +++ b/source4/auth/gensec/spnego.c @@ -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; -- 2.34.1