summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/libcli/auth/spnego.c76
1 files changed, 72 insertions, 4 deletions
diff --git a/source4/libcli/auth/spnego.c b/source4/libcli/auth/spnego.c
index 5ba0e239c5..02bc9043f5 100644
--- a/source4/libcli/auth/spnego.c
+++ b/source4/libcli/auth/spnego.c
@@ -30,7 +30,8 @@
enum spnego_state_position {
SPNEGO_SERVER_START,
SPNEGO_CLIENT_START,
- SPNEGO_TARG,
+ SPNEGO_SERVER_TARG,
+ SPNEGO_CLIENT_TARG,
SPNEGO_FALLBACK,
SPNEGO_DONE
};
@@ -315,11 +316,11 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
/* set next state */
spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG;
- spnego_state->state_position = SPNEGO_TARG;
+ spnego_state->state_position = SPNEGO_CLIENT_TARG;
return nt_status;
}
- case SPNEGO_TARG:
+ case SPNEGO_SERVER_TARG:
{
NTSTATUS nt_status;
if (!in.length) {
@@ -375,7 +376,74 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
DEBUG(1, ("Failed to write SPENGO reply to NEG_TOKEN_TARG\n"));
return NT_STATUS_INVALID_PARAMETER;
}
- spnego_state->state_position = SPNEGO_TARG;
+ spnego_state->state_position = SPNEGO_SERVER_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;
+ }
+ case SPNEGO_CLIENT_TARG:
+ {
+ NTSTATUS nt_status;
+ if (!in.length) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ len = spnego_read_data(in, &spnego);
+
+ if (len == -1) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* OK, so it's real SPNEGO, check the packet's the one we expect */
+ 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.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);
+
+ 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_NONE_RESULT;
+ spnego_out.negTokenTarg.supportedMech = NULL;
+ 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_CLIENT_TARG;
} else if (NT_STATUS_IS_OK(nt_status)) {
spnego_state->state_position = SPNEGO_DONE;
} else {