X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source4%2Fauth%2Fgensec%2Fgensec_gssapi.c;h=564c20cb48223b1c5fcda4a68e21a5fe1693704e;hb=130432987826662c2187e7a88ad9a2d9dda0cd1e;hp=6ecd29bf340ce09ba8ecc6a8ac764f4963a3d9ef;hpb=16b2118b4369f8204d86d5ad2eb117837da26789;p=metze%2Fsamba%2Fwip.git diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 6ecd29bf340c..564c20cb4822 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -169,9 +169,6 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security) break; } - gensec_gssapi_state->session_key = data_blob(NULL, 0); - gensec_gssapi_state->pac = data_blob(NULL, 0); - ret = smb_krb5_init_context(gensec_gssapi_state, NULL, gensec_security->settings->lp_ctx, @@ -270,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")); @@ -332,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; } @@ -429,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; @@ -1038,7 +1059,6 @@ static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_securit } static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, const DATA_BLOB *sig) @@ -1053,7 +1073,7 @@ static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_secur dump_data_pw("gensec_gssapi_unseal_packet: sig\n", sig->data, sig->length); - in = data_blob_talloc(mem_ctx, NULL, sig->length + length); + in = data_blob_talloc(gensec_security, NULL, sig->length + length); memcpy(in.data, sig->data, sig->length); memcpy(in.data + sig->length, data, length); @@ -1067,9 +1087,12 @@ static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_secur &output_token, &conf_state, &qop_state); + talloc_free(in.data); if (GSS_ERROR(maj_stat)) { + char *error_string = gssapi_error_string(NULL, maj_stat, min_stat, gensec_gssapi_state->gss_oid); DEBUG(1, ("gensec_gssapi_unseal_packet: GSS UnWrap failed: %s\n", - gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + error_string)); + talloc_free(error_string); return NT_STATUS_ACCESS_DENIED; } @@ -1128,7 +1151,6 @@ static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_securit } static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, const uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, const DATA_BLOB *sig) @@ -1159,8 +1181,10 @@ static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_securi &input_token, &qop_state); if (GSS_ERROR(maj_stat)) { - DEBUG(1, ("GSS VerifyMic failed: %s\n", - gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + char *error_string = gssapi_error_string(NULL, maj_stat, min_stat, gensec_gssapi_state->gss_oid); + DEBUG(1, ("GSS VerifyMic failed: %s\n", error_string)); + talloc_free(error_string); + return NT_STATUS_ACCESS_DENIED; } @@ -1239,6 +1263,7 @@ static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security, * This breaks all the abstractions, but what do you expect... */ static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, DATA_BLOB *session_key) { struct gensec_gssapi_state *gensec_gssapi_state @@ -1250,11 +1275,6 @@ static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_securit return NT_STATUS_NO_USER_SESSION_KEY; } - if (gensec_gssapi_state->session_key.data) { - *session_key = gensec_gssapi_state->session_key; - return NT_STATUS_OK; - } - maj_stat = gsskrb5_get_subkey(&min_stat, gensec_gssapi_state->gssapi_context, &subkey); @@ -1266,10 +1286,9 @@ static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_securit DEBUG(10, ("Got KRB5 session key of length %d%s\n", (int)KRB5_KEY_LENGTH(subkey), (gensec_gssapi_state->sasl_state == STAGE_DONE)?" (done)":"")); - *session_key = data_blob_talloc(gensec_gssapi_state, + *session_key = data_blob_talloc(mem_ctx, KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey)); krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, subkey); - gensec_gssapi_state->session_key = *session_key; dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length); return NT_STATUS_OK; @@ -1279,6 +1298,7 @@ static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_securit * this session. This uses either the PAC (if present) or a local * database lookup */ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx_out, struct auth_session_info **_session_info) { NTSTATUS nt_status; @@ -1299,7 +1319,7 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi return NT_STATUS_INVALID_PARAMETER; } - mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context"); + mem_ctx = talloc_named(mem_ctx_out, 0, "gensec_gssapi_session_info context"); NT_STATUS_HAVE_NO_MEMORY(mem_ctx); nt_status = gssapi_obtain_pac_blob(mem_ctx, gensec_gssapi_state->gssapi_context, @@ -1388,7 +1408,7 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi return nt_status; } - nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key); + nt_status = gensec_gssapi_session_key(gensec_security, session_info, &session_info->session_key); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return nt_status; @@ -1433,9 +1453,8 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi /* It has been taken from this place... */ gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL; } - talloc_steal(gensec_gssapi_state, session_info); + *_session_info = talloc_steal(mem_ctx_out, session_info); talloc_free(mem_ctx); - *_session_info = session_info; return NT_STATUS_OK; }