diff options
-rw-r--r-- | source4/libcli/auth/gensec.c | 11 | ||||
-rw-r--r-- | source4/libcli/auth/spnego.c | 238 | ||||
-rw-r--r-- | source4/libcli/auth/spnego.h | 4 |
3 files changed, 137 insertions, 116 deletions
diff --git a/source4/libcli/auth/gensec.c b/source4/libcli/auth/gensec.c index f6d6db9e62..8ece7c76dc 100644 --- a/source4/libcli/auth/gensec.c +++ b/source4/libcli/auth/gensec.c @@ -162,6 +162,17 @@ static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security) return NT_STATUS_INVALID_PARAMETER; } +NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security, + const char *name) +{ + gensec_security->ops = gensec_security_by_name(name); + if (!gensec_security->ops) { + DEBUG(1, ("Could not find GENSEC backend for name=%s\n", name)); + return NT_STATUS_INVALID_PARAMETER; + } + return gensec_start_mech(gensec_security); +} + NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security, uint8_t authtype) { diff --git a/source4/libcli/auth/spnego.c b/source4/libcli/auth/spnego.c index bb9d2504ac..eb1ed15368 100644 --- a/source4/libcli/auth/spnego.c +++ b/source4/libcli/auth/spnego.c @@ -41,7 +41,7 @@ struct spnego_state { uint_t ref_count; enum spnego_message_type expected_packet; enum spnego_message_type state_position; - negResult_t result; + enum spnego_negResult result; struct gensec_security *sub_sec_security; }; @@ -169,9 +169,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA out_mem_ctx, in, out); } - len = spnego_read_data(in, &spnego); - - if (len == -1 && spnego_state->state_position == SPNEGO_SERVER_START) { + if (spnego_state->state_position == SPNEGO_SERVER_START) { int i; int num_ops; const struct gensec_security_ops **all_ops = gensec_security_all(&num_ops); @@ -198,140 +196,152 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA } gensec_end(&spnego_state->sub_sec_security); } + DEBUG(1, ("Failed to start SPENGO SERVER\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + len = spnego_read_data(in, &spnego); + if (len == -1) { DEBUG(1, ("Failed to parse SPENGO request\n")); return NT_STATUS_INVALID_PARAMETER; - } else { + } - if (spnego.type != spnego_state->expected_packet) { - spnego_free_data(&spnego); - DEBUG(1, ("Invalid SPENGO request: %d, expected %d\n", spnego.type, - spnego_state->expected_packet)); - return NT_STATUS_INVALID_PARAMETER; - } + if (spnego.type != spnego_state->expected_packet) { + spnego_free_data(&spnego); + DEBUG(1, ("Invalid SPENGO request: %d, expected %d\n", spnego.type, + spnego_state->expected_packet)); + return NT_STATUS_INVALID_PARAMETER; + } - if (spnego_state->state_position == SPNEGO_CLIENT_GET_MECHS) { + if (spnego_state->state_position == SPNEGO_CLIENT_GET_MECHS) { - /* The server offers a list of mechanisms */ - - char **mechType = spnego.negTokenInit.mechTypes; - char *my_mechs[] = {NULL, NULL}; - int i; - NTSTATUS nt_status; - - for (i=0; mechType[i]; i++) { - nt_status = gensec_client_start(&spnego_state->sub_sec_security); - if (!NT_STATUS_IS_OK(nt_status)) { - break; - } - nt_status = gensec_start_mech_by_oid(spnego_state->sub_sec_security, - mechType[i]); - if (!NT_STATUS_IS_OK(nt_status)) { - gensec_end(&spnego_state->sub_sec_security); - continue; - } - - if (i == 0) { - nt_status = gensec_update(spnego_state->sub_sec_security, - out_mem_ctx, - spnego.negTokenInit.mechToken, - &unwrapped_out); - } else { - /* only get the helping start blob for the first OID */ - nt_status = gensec_update(spnego_state->sub_sec_security, - out_mem_ctx, - null_data_blob, - &unwrapped_out); - } - if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - DEBUG(1, ("SPENGO(%s) NEG_TOKEN_INIT failed: %s\n", - spnego_state->sub_sec_security->ops->name, nt_errstr(nt_status))); - gensec_end(&spnego_state->sub_sec_security); - } else { - break; - } - } - if (!mechType[i]) { - DEBUG(1, ("SPENGO: Could not find a suitable mechtype in NEG_TOKEN_INIT\n")); - } + /* The server offers a list of mechanisms */ + + char **mechType = spnego.negTokenInit.mechTypes; + char *my_mechs[] = {NULL, NULL}; + int i; + NTSTATUS nt_status; - spnego_free_data(&spnego); - if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - return nt_status; - } - - /* compose reply */ - my_mechs[0] = spnego_state->sub_sec_security->ops->oid; + spnego_state->sub_sec_security = NULL; - spnego_out.type = SPNEGO_NEG_TOKEN_INIT; - spnego_out.negTokenInit.mechTypes = my_mechs; - 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; + for (i=0; mechType && mechType[i]; i++) { + nt_status = gensec_client_start(&spnego_state->sub_sec_security); + if (!NT_STATUS_IS_OK(nt_status)) { + break; } - - /* set next state */ - spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG; - spnego_state->state_position = SPNEGO_TARG; - - return nt_status; - } else if (spnego_state->state_position == SPNEGO_TARG) { - NTSTATUS nt_status; - if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) { - return NT_STATUS_ACCESS_DENIED; + /* forward the user info to the sub context */ + spnego_state->sub_sec_security->user = gensec_security->user; + spnego_state->sub_sec_security->password_callback = gensec_security->password_callback; + spnego_state->sub_sec_security->password_callback_private = gensec_security->password_callback_private; + /* select the sub context */ + nt_status = gensec_start_mech_by_oid(spnego_state->sub_sec_security, + mechType[i]); + if (!NT_STATUS_IS_OK(nt_status)) { + gensec_end(&spnego_state->sub_sec_security); + continue; } - if (spnego.negTokenTarg.responseToken.length) { + if (i == 0) { nt_status = gensec_update(spnego_state->sub_sec_security, out_mem_ctx, - spnego.negTokenTarg.responseToken, + spnego.negTokenInit.mechToken, &unwrapped_out); } else { - unwrapped_out = data_blob(NULL, 0); - nt_status = NT_STATUS_OK; + /* only get the helping start blob for the first OID */ + nt_status = gensec_update(spnego_state->sub_sec_security, + out_mem_ctx, + null_data_blob, + &unwrapped_out); } - - if (NT_STATUS_IS_OK(nt_status) - && (spnego.negTokenTarg.negResult != SPNEGO_ACCEPT_COMPLETED)) { - nt_status = NT_STATUS_INVALID_PARAMETER; + if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + DEBUG(1, ("SPENGO(%s) NEG_TOKEN_INIT failed: %s\n", + spnego_state->sub_sec_security->ops->name, nt_errstr(nt_status))); + gensec_end(&spnego_state->sub_sec_security); + } else { + break; } + } + if (!spnego_state->sub_sec_security) { + DEBUG(1, ("SPENGO: Could not find a suitable mechtype in NEG_TOKEN_INIT\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + spnego_free_data(&spnego); + if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + return nt_status; + } + + /* compose reply */ + my_mechs[0] = spnego_state->sub_sec_security->ops->oid; + + spnego_out.type = SPNEGO_NEG_TOKEN_INIT; + spnego_out.negTokenInit.mechTypes = my_mechs; + 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_TARG; + + return nt_status; + } else if (spnego_state->state_position == SPNEGO_TARG) { + NTSTATUS nt_status; + if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) { + return NT_STATUS_ACCESS_DENIED; + } + + if (spnego.negTokenTarg.responseToken.length) { + nt_status = gensec_update(spnego_state->sub_sec_security, + out_mem_ctx, + spnego.negTokenTarg.responseToken, + &unwrapped_out); + } else { + unwrapped_out = data_blob(NULL, 0); + nt_status = NT_STATUS_OK; + } + + if (NT_STATUS_IS_OK(nt_status) + && (spnego.negTokenTarg.negResult != SPNEGO_ACCEPT_COMPLETED)) { + nt_status = NT_STATUS_INVALID_PARAMETER; + } - spnego_state->result = spnego.negTokenTarg.negResult; - spnego_free_data(&spnego); + spnego_state->result = spnego.negTokenTarg.negResult; + spnego_free_data(&spnego); + + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + /* compose reply */ + spnego_out.type = SPNEGO_NEG_TOKEN_TARG; + spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; + spnego_out.negTokenTarg.supportedMech + = spnego_state->sub_sec_security->ops->oid; + spnego_out.negTokenTarg.responseToken = unwrapped_out; + spnego_out.negTokenTarg.mechListMIC = null_data_blob; - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - /* compose reply */ - spnego_out.type = SPNEGO_NEG_TOKEN_TARG; - spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; - spnego_out.negTokenTarg.supportedMech - = spnego_state->sub_sec_security->ops->oid; -; - spnego_out.negTokenTarg.responseToken = unwrapped_out; - spnego_out.negTokenTarg.mechListMIC = null_data_blob; - if (spnego_write_data(out_mem_ctx, out, &spnego_out) == -1) { DEBUG(1, ("Failed to write SPENGO reply to NEG_TOKEN_TARG\n")); return NT_STATUS_INVALID_PARAMETER; } - spnego_state->state_position = SPNEGO_TARG; - } else if (NT_STATUS_IS_OK(nt_status)) { - spnego_state->state_position = SPNEGO_DONE; - } else { - DEBUG(1, ("SPENGO(%s) login failed: %s\n", - spnego_state->sub_sec_security->ops->name, - nt_errstr(nt_status))); - return nt_status; - } - - return nt_status; + spnego_state->state_position = SPNEGO_TARG; + } else if (NT_STATUS_IS_OK(nt_status)) { + spnego_state->state_position = SPNEGO_DONE; } else { - spnego_free_data(&spnego); - DEBUG(1, ("Invalid SPENGO request: %d\n", spnego.type)); - return NT_STATUS_INVALID_PARAMETER; + DEBUG(1, ("SPENGO(%s) login failed: %s\n", + spnego_state->sub_sec_security->ops->name, + nt_errstr(nt_status))); + return nt_status; } + + return nt_status; + } else { + spnego_free_data(&spnego); + DEBUG(1, ("Invalid SPENGO request: %d\n", spnego.type)); + return NT_STATUS_INVALID_PARAMETER; } } diff --git a/source4/libcli/auth/spnego.h b/source4/libcli/auth/spnego.h index 60ef4c1d36..eba98c5218 100644 --- a/source4/libcli/auth/spnego.h +++ b/source4/libcli/auth/spnego.h @@ -33,11 +33,11 @@ #define SPNEGO_INTEG_FLAG 0x40 #define SPNEGO_REQ_FLAG 0x80 -typedef enum _spnego_negResult { +enum spnego_negResult { SPNEGO_ACCEPT_COMPLETED = 0, SPNEGO_ACCEPT_INCOMPLETE = 1, SPNEGO_REJECT = 2 -} negResult_t; +}; struct spnego_negTokenInit { char **mechTypes; |