summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2004-07-06 18:07:00 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:56:53 -0500
commit4b7cd833a09634d1a94d4b7170286549f883fdfb (patch)
treef366d215db6697f4ea483b4273f7f4cebaaca308
parentc688a1e18ff5e3f50005a8438bdbfb0e4382ca18 (diff)
downloadsamba-4b7cd833a09634d1a94d4b7170286549f883fdfb.tar.gz
samba-4b7cd833a09634d1a94d4b7170286549f883fdfb.tar.bz2
samba-4b7cd833a09634d1a94d4b7170286549f883fdfb.zip
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)
-rw-r--r--source4/libcli/auth/spnego.c89
1 files changed, 88 insertions, 1 deletions
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);