From f1aaef3015864f9323711127a4964a8eceff6a52 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 21 Jan 2005 11:10:03 +0000 Subject: r4890: Try to cope with mechanism mismatch in the client speaks first version of the SPNEGO state-machine. (Such as on LDAP and HTTP) Andrew Bartlett (This used to be commit c1cae6b3b1efe109a09e449ed2e09983431eac7e) --- source4/libcli/auth/spnego.c | 105 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 7 deletions(-) diff --git a/source4/libcli/auth/spnego.c b/source4/libcli/auth/spnego.c index f7221b7458..1e92a7d16e 100644 --- a/source4/libcli/auth/spnego.c +++ b/source4/libcli/auth/spnego.c @@ -287,11 +287,63 @@ static NTSTATUS gensec_spnego_server_try_fallback(struct gensec_security *gensec } -static NTSTATUS gensec_spnego_parse_negTokenInit(struct gensec_security *gensec_security, - struct spnego_state *spnego_state, - TALLOC_CTX *out_mem_ctx, - const char **mechType, - const DATA_BLOB unwrapped_in, DATA_BLOB *unwrapped_out) +/* + Parse the netTokenInit from the client, to the server. + + +*/ + +static NTSTATUS gensec_spnego_server_parse_negTokenInit(struct gensec_security *gensec_security, + struct spnego_state *spnego_state, + TALLOC_CTX *out_mem_ctx, + const char **mechType, + const DATA_BLOB unwrapped_in, DATA_BLOB *unwrapped_out) +{ + NTSTATUS nt_status; + + if (!mechType || !mechType[0]) { + DEBUG(1, ("SPNEGO: Could not find a suitable mechtype in NEG_TOKEN_INIT\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + nt_status = gensec_subcontext_start(spnego_state, + gensec_security, + &spnego_state->sub_sec_security); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + /* select the sub context */ + nt_status = gensec_start_mech_by_oid(spnego_state->sub_sec_security, + mechType[0]); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(spnego_state->sub_sec_security); + spnego_state->sub_sec_security = NULL; + return nt_status; + } + + if (!unwrapped_in.length) { + return NT_STATUS_INVALID_PARAMETER; + } + + nt_status = gensec_update(spnego_state->sub_sec_security, + out_mem_ctx, + unwrapped_in, + unwrapped_out); + + if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(nt_status)) { + DEBUG(1, ("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; + } + return nt_status; +} + +static NTSTATUS gensec_spnego_client_parse_negTokenInit(struct gensec_security *gensec_security, + struct spnego_state *spnego_state, + TALLOC_CTX *out_mem_ctx, + const char **mechType, + const DATA_BLOB unwrapped_in, DATA_BLOB *unwrapped_out) { int i; NTSTATUS nt_status; @@ -440,6 +492,40 @@ static NTSTATUS gensec_spnego_server_negTokenTarg(struct gensec_security *gensec } spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED; spnego_state->state_position = SPNEGO_DONE; + } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) { + if (spnego_state->sub_sec_security) { + /* we have a mech, but we just didn't get the input parameter */ + spnego_out.negTokenTarg.supportedMech + = spnego_state->sub_sec_security->ops->oid; + } else { + const char **mechTypes = gensec_security_oids(out_mem_ctx, GENSEC_OID_SPNEGO); + if (!mechTypes) { + DEBUG(1, ("no GENSEC OID backends available\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + nt_status = gensec_subcontext_start(spnego_state, + gensec_security, + &spnego_state->sub_sec_security); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + /* select our preferred mech */ + nt_status = gensec_start_mech_by_oid(spnego_state->sub_sec_security, + mechTypes[0]); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(spnego_state->sub_sec_security); + spnego_state->sub_sec_security = NULL; + return nt_status; + } + + /* we should be sending the whole list here */ + spnego_out.negTokenTarg.supportedMech = mechTypes[0]; + } + + spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; + spnego_state->state_position = SPNEGO_SERVER_TARG; + nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED; } else { spnego_out.negTokenTarg.negResult = SPNEGO_REJECT; DEBUG(2, ("SPNEGO login failed: %s\n", nt_errstr(nt_status))); @@ -500,7 +586,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA return NT_STATUS_INVALID_PARAMETER; } - nt_status = gensec_spnego_parse_negTokenInit(gensec_security, + nt_status = gensec_spnego_server_parse_negTokenInit(gensec_security, spnego_state, out_mem_ctx, spnego.negTokenInit.mechTypes, @@ -580,7 +666,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA } } - nt_status = gensec_spnego_parse_negTokenInit(gensec_security, + nt_status = gensec_spnego_client_parse_negTokenInit(gensec_security, spnego_state, out_mem_ctx, spnego.negTokenInit.mechTypes, @@ -640,6 +726,11 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA return NT_STATUS_INVALID_PARAMETER; } + if (!spnego_state->sub_sec_security) { + DEBUG(1, ("SPNEGO: Did not setup a mech in NEG_TOKEN_INIT\n")); + return NT_STATUS_INVALID_PARAMETER; + } + nt_status = gensec_update(spnego_state->sub_sec_security, out_mem_ctx, spnego.negTokenTarg.responseToken, -- cgit