From 4b7cd833a09634d1a94d4b7170286549f883fdfb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Jul 2004 18:07:00 +0000 Subject: r1366: handle the case where the client need to send the negTokenInit before getting something from the server. (this is needed by SPNEGO in dcerpc) metze (This used to be commit ec978555f0bd612b80dfa49ccc880a3858285879) --- source4/libcli/auth/spnego.c | 89 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/source4/libcli/auth/spnego.c b/source4/libcli/auth/spnego.c index aa0f83700d..b0135dca56 100644 --- a/source4/libcli/auth/spnego.c +++ b/source4/libcli/auth/spnego.c @@ -194,6 +194,93 @@ static NTSTATUS gensec_spengo_server_try_fallback(struct gensec_security *gensec } +/** create a client netTokenInit + * + * This is the case, where the client is the first one who sends data +*/ + +static NTSTATUS gensec_spengo_client_netTokenInit(struct gensec_security *gensec_security, + struct spnego_state *spnego_state, + TALLOC_CTX *out_mem_ctx, + const DATA_BLOB in, DATA_BLOB *out) +{ + NTSTATUS nt_status; + int i; + int num_ops; + char **mechTypes = NULL; + const struct gensec_security_ops **all_ops = gensec_security_all(&num_ops); + DATA_BLOB null_data_blob = data_blob(NULL,0); + DATA_BLOB unwrapped_out = data_blob(NULL,0); + + if (num_ops < 1) { + DEBUG(1, ("no GENSEC backends available\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + /* build a mechTypes list we want to offer */ + for (i=0; i < num_ops; i++) { + if (!all_ops[i]->oid) { + continue; + } + + /* skip SPNEGO itself */ + if (strcmp(OID_SPNEGO,all_ops[i]->oid)==0) { + continue; + } + + mechTypes = talloc_realloc_p(out_mem_ctx, mechTypes, char *, i+2); + if (!mechTypes) { + DEBUG(1, ("talloc_realloc_p(out_mem_ctx, mechTypes, char *, i+1) failed\n")); + return NT_STATUS_NO_MEMORY; + } + + mechTypes[i] = all_ops[i]->oid; + mechTypes[i+1] = NULL; + } + + if (!mechTypes) { + DEBUG(1, ("no GENSEC OID backends available\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + nt_status = gensec_subcontext_start(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)) { + gensec_end(&spnego_state->sub_sec_security); + return nt_status; + } + nt_status = gensec_update(spnego_state->sub_sec_security, + out_mem_ctx, in, &unwrapped_out); + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + struct spnego_data spnego_out; + spnego_out.type = SPNEGO_NEG_TOKEN_INIT; + spnego_out.negTokenInit.mechTypes = mechTypes; + spnego_out.negTokenInit.reqFlags = 0; + spnego_out.negTokenInit.mechListMIC = null_data_blob; + spnego_out.negTokenInit.mechToken = unwrapped_out; + + if (spnego_write_data(out_mem_ctx, out, &spnego_out) == -1) { + DEBUG(1, ("Failed to write SPENGO reply to NEG_TOKEN_INIT\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + /* set next state */ + spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG; + spnego_state->state_position = SPNEGO_CLIENT_TARG; + return nt_status; + } + gensec_end(&spnego_state->sub_sec_security); + + DEBUG(1, ("Failed to setup SPENGO netTokenInit request\n")); + return NT_STATUS_INVALID_PARAMETER; +} + static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out) { @@ -240,7 +327,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA if (!in.length) { /* client to produce negTokenInit */ - return NT_STATUS_INVALID_PARAMETER; + return gensec_spengo_client_netTokenInit(gensec_security, spnego_state, out_mem_ctx, in, out); } len = spnego_read_data(in, &spnego); -- cgit