From 8a68f96f8cea2c53c8babf2ec826dfc6ef1cc199 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Jun 2005 02:12:26 +0000 Subject: r7827: Add in-memory keytab to Samba4, using the new MEMORY_WILDCARD keytab support in Heimdal. This removes the 'ext_keytab' step from my Samba4/WinXP client howto. In doing this work, I realised that the replay cache in Heimdal is currently a no-op, so I have removed the calls to it, and therefore the mutex calls from passdb/secrets.c. This patch also includes a replacement 'magic' mechanism detection, that does not issue extra error messages from deep inside the GSSAPI code. Andrew Bartlett (This used to be commit c19d5706f4fa760415b727b970bc99e7f1abd064) --- source4/auth/gensec/gensec.h | 5 ++++ source4/auth/gensec/gensec_gssapi.c | 59 +++++++++++++++++++++++++++++++++++-- source4/auth/gensec/gensec_krb5.c | 25 ++++++++++++++-- source4/auth/gensec/spnego.c | 23 +++++++++------ 4 files changed, 98 insertions(+), 14 deletions(-) (limited to 'source4/auth/gensec') diff --git a/source4/auth/gensec/gensec.h b/source4/auth/gensec/gensec.h index 2951e13dd9..20f0b1c642 100644 --- a/source4/auth/gensec/gensec.h +++ b/source4/auth/gensec/gensec.h @@ -57,6 +57,11 @@ struct gensec_security_ops { const char **oid; /* NULL if not offered by SPNEGO */ NTSTATUS (*client_start)(struct gensec_security *gensec_security); NTSTATUS (*server_start)(struct gensec_security *gensec_security); + /** + Determine if a packet has the right 'magic' for this mechanism + */ + NTSTATUS (*magic)(struct gensec_security *gensec_security, + const DATA_BLOB *first_packet); NTSTATUS (*update)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out); NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index c6a16cdf33..1542441e27 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -46,6 +46,7 @@ struct gensec_gssapi_state { struct smb_krb5_context *smb_krb5_context; krb5_ccache ccache; const char *ccache_name; + krb5_keytab keytab; gss_cred_id_t cred; }; @@ -170,6 +171,7 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi { NTSTATUS nt_status; struct gensec_gssapi_state *gensec_gssapi_state; + struct cli_credentials *machine_account; nt_status = gensec_gssapi_start(gensec_security); if (!NT_STATUS_IS_OK(nt_status)) { @@ -178,7 +180,30 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi gensec_gssapi_state = gensec_security->private_data; + machine_account = cli_credentials_init(gensec_gssapi_state); + cli_credentials_set_conf(machine_account); + nt_status = cli_credentials_set_machine_account(machine_account); + + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(3, ("Could not obtain machine account credentials from the local database\n")); + talloc_free(machine_account); + return nt_status; + } else { + nt_status = create_memory_keytab(gensec_gssapi_state, + machine_account, + gensec_gssapi_state->smb_krb5_context, + &gensec_gssapi_state->keytab); + talloc_free(machine_account); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(3, ("Could not create memory keytab!\n")); + talloc_free(machine_account); + return nt_status; + } + } + + gsskrb5_register_acceptor_keytab(gensec_gssapi_state->keytab); return NT_STATUS_OK; + } static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security) @@ -236,7 +261,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi return nt_status; } -#ifdef HAVE_GSS_KRB5_CCACHE_NAME /* FIXME, we need an alternate function */ maj_stat = gss_krb5_ccache_name(&min_stat, gensec_gssapi_state->ccache_name, NULL); @@ -246,7 +270,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat))); return NT_STATUS_UNSUCCESSFUL; } -#endif maj_stat = gss_acquire_cred(&min_stat, gensec_gssapi_state->client_name, @@ -266,6 +289,25 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi } +/** + * Check if the packet is one for this mechansim + * + * @param gensec_security GENSEC state + * @param in The request, as a DATA_BLOB + * @return Error, INVALID_PARAMETER if it's not a packet for us + * or NT_STATUS_OK if the packet is ok. + */ + +static NTSTATUS gensec_gssapi_magic(struct gensec_security *gensec_security, + const DATA_BLOB *in) +{ + if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) { + return NT_STATUS_OK; + } else { + return NT_STATUS_INVALID_PARAMETER; + } +} + /** * Next state function for the GSSAPI GENSEC mechanism @@ -294,8 +336,18 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, switch (gensec_security->gensec_role) { case GENSEC_CLIENT: { + maj_stat = gss_krb5_ccache_name(&min_stat, + gensec_gssapi_state->ccache_name, + NULL); + if (maj_stat) { + DEBUG(1, ("GSS krb5 ccache set %s failed: %s\n", + gensec_gssapi_state->ccache_name, + gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat))); + return NT_STATUS_UNSUCCESSFUL; + } + maj_stat = gss_init_sec_context(&min_stat, - GSS_C_NO_CREDENTIAL, + gensec_gssapi_state->cred, &gensec_gssapi_state->gssapi_context, gensec_gssapi_state->server_name, discard_const_p(gss_OID_desc, gensec_gssapi_state->gss_oid), @@ -756,6 +808,7 @@ static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = { .oid = gensec_krb5_oids, .client_start = gensec_gssapi_client_start, .server_start = gensec_gssapi_server_start, + .magic = gensec_gssapi_magic, .update = gensec_gssapi_update, .session_key = gensec_gssapi_session_key, .session_info = gensec_gssapi_session_info, diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index d633794e1c..348a75b535 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -399,6 +399,26 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security } +/** + * Check if the packet is one for this mechansim + * + * @param gensec_security GENSEC state + * @param in The request, as a DATA_BLOB + * @return Error, INVALID_PARAMETER if it's not a packet for us + * or NT_STATUS_OK if the packet is ok. + */ + +static NTSTATUS gensec_krb5_magic(struct gensec_security *gensec_security, + const DATA_BLOB *in) +{ + if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) { + return NT_STATUS_OK; + } else { + return NT_STATUS_INVALID_PARAMETER; + } +} + + /** * Next state function for the Krb5 GENSEC mechanism * @@ -494,7 +514,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security, /* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */ if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) { nt_status = ads_verify_ticket(out_mem_ctx, - gensec_krb5_state->smb_krb5_context->krb5_context, + gensec_krb5_state->smb_krb5_context, gensec_krb5_state->auth_context, lp_realm(), gensec_get_target_service(gensec_security), &in, @@ -503,7 +523,7 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security, } else { /* TODO: check the tok_id */ nt_status = ads_verify_ticket(out_mem_ctx, - gensec_krb5_state->smb_krb5_context->krb5_context, + gensec_krb5_state->smb_krb5_context, gensec_krb5_state->auth_context, lp_realm(), gensec_get_target_service(gensec_security), @@ -669,6 +689,7 @@ static const struct gensec_security_ops gensec_krb5_security_ops = { .oid = gensec_krb5_oids, .client_start = gensec_krb5_client_start, .server_start = gensec_krb5_server_start, + .magic = gensec_krb5_magic, .update = gensec_krb5_update, .session_key = gensec_krb5_session_key, .session_info = gensec_krb5_session_info, diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c index f5d1dd2238..e3d335b71b 100644 --- a/source4/auth/gensec/spnego.c +++ b/source4/auth/gensec/spnego.c @@ -269,9 +269,21 @@ static NTSTATUS gensec_spnego_server_try_fallback(struct gensec_security *gensec continue; } + if (!all_ops[i]->magic) { + continue; + } + + nt_status = all_ops[i]->magic(gensec_security, &in); + if (!NT_STATUS_IS_OK(nt_status)) { + continue; + } + + spnego_state->state_position = SPNEGO_FALLBACK; + nt_status = gensec_subcontext_start(spnego_state, gensec_security, &spnego_state->sub_sec_security); + if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } @@ -279,18 +291,11 @@ static NTSTATUS gensec_spnego_server_try_fallback(struct gensec_security *gensec nt_status = gensec_start_mech_by_ops(spnego_state->sub_sec_security, all_ops[i]); if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(spnego_state->sub_sec_security); - spnego_state->sub_sec_security = NULL; - continue; + return nt_status; } nt_status = gensec_update(spnego_state->sub_sec_security, out_mem_ctx, in, out); - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - spnego_state->state_position = SPNEGO_FALLBACK; - return nt_status; - } - talloc_free(spnego_state->sub_sec_security); - spnego_state->sub_sec_security = NULL; + return nt_status; } DEBUG(1, ("Failed to parse SPNEGO request\n")); return NT_STATUS_INVALID_PARAMETER; -- cgit