📄 spnego.c
字号:
out_mem_ctx, in, out); case SPNEGO_SERVER_START: { NTSTATUS nt_status; if (in.length) { len = spnego_read_data(gensec_security, in, &spnego); if (len == -1) { return gensec_spnego_server_try_fallback(gensec_security, spnego_state, out_mem_ctx, in, out); } /* client sent NegTargetInit, we send NegTokenTarg */ /* OK, so it's real SPNEGO, check the packet's the one we expect */ if (spnego.type != spnego_state->expected_packet) { DEBUG(1, ("Invalid SPNEGO request: %d, expected %d\n", spnego.type, spnego_state->expected_packet)); dump_data(1, in.data, in.length); spnego_free_data(&spnego); return NT_STATUS_INVALID_PARAMETER; } nt_status = gensec_spnego_parse_negTokenInit(gensec_security, spnego_state, out_mem_ctx, spnego.negTokenInit.mechTypes, spnego.negTokenInit.mechToken, &unwrapped_out); nt_status = gensec_spnego_server_negTokenTarg(gensec_security, spnego_state, out_mem_ctx, nt_status, unwrapped_out, out); spnego_free_data(&spnego); return nt_status; } else { nt_status = gensec_spnego_create_negTokenInit(gensec_security, spnego_state, out_mem_ctx, in, out); spnego_state->state_position = SPNEGO_SERVER_START; spnego_state->expected_packet = SPNEGO_NEG_TOKEN_INIT; return nt_status; } } case SPNEGO_CLIENT_START: { /* The server offers a list of mechanisms */ const char *my_mechs[] = {NULL, NULL}; NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; if (!in.length) { /* client to produce negTokenInit */ nt_status = gensec_spnego_create_negTokenInit(gensec_security, spnego_state, out_mem_ctx, in, out); spnego_state->state_position = SPNEGO_CLIENT_TARG; spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG; return nt_status; } len = spnego_read_data(gensec_security, in, &spnego); if (len == -1) { DEBUG(1, ("Invalid SPNEGO request:\n")); dump_data(1, in.data, in.length); 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) { DEBUG(1, ("Invalid SPNEGO request: %d, expected %d\n", spnego.type, spnego_state->expected_packet)); dump_data(1, in.data, in.length); spnego_free_data(&spnego); return NT_STATUS_INVALID_PARAMETER; } if (spnego.negTokenInit.targetPrincipal) { DEBUG(5, ("Server claims it's principal name is %s\n", spnego.negTokenInit.targetPrincipal)); gensec_set_target_principal(gensec_security, spnego.negTokenInit.targetPrincipal); } nt_status = gensec_spnego_parse_negTokenInit(gensec_security, spnego_state, out_mem_ctx, spnego.negTokenInit.mechTypes, spnego.negTokenInit.mechToken, &unwrapped_out); if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(nt_status)) { spnego_free_data(&spnego); return nt_status; } my_mechs[0] = spnego_state->neg_oid; /* compose reply */ 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 SPNEGO 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; if (NT_STATUS_IS_OK(nt_status)) { spnego_state->no_response_expected = true; } spnego_free_data(&spnego); return NT_STATUS_MORE_PROCESSING_REQUIRED; } case SPNEGO_SERVER_TARG: { NTSTATUS nt_status; if (!in.length) { return NT_STATUS_INVALID_PARAMETER; } len = spnego_read_data(gensec_security, in, &spnego); if (len == -1) { DEBUG(1, ("Invalid SPNEGO request:\n")); dump_data(1, in.data, in.length); 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) { DEBUG(1, ("Invalid SPNEGO request: %d, expected %d\n", spnego.type, spnego_state->expected_packet)); dump_data(1, in.data, in.length); spnego_free_data(&spnego); return NT_STATUS_INVALID_PARAMETER; } if (!spnego_state->sub_sec_security) { DEBUG(1, ("SPNEGO: Did not setup a mech in NEG_TOKEN_INIT\n")); spnego_free_data(&spnego); return NT_STATUS_INVALID_PARAMETER; } nt_status = gensec_update(spnego_state->sub_sec_security, out_mem_ctx, spnego.negTokenTarg.responseToken, &unwrapped_out); nt_status = gensec_spnego_server_negTokenTarg(gensec_security, spnego_state, out_mem_ctx, nt_status, unwrapped_out, out); spnego_free_data(&spnego); return nt_status; } case SPNEGO_CLIENT_TARG: { NTSTATUS nt_status; if (!in.length) { return NT_STATUS_INVALID_PARAMETER; } len = spnego_read_data(gensec_security, in, &spnego); if (len == -1) { DEBUG(1, ("Invalid SPNEGO request:\n")); dump_data(1, in.data, in.length); 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) { DEBUG(1, ("Invalid SPNEGO request: %d, expected %d\n", spnego.type, spnego_state->expected_packet)); dump_data(1, in.data, in.length); spnego_free_data(&spnego); return NT_STATUS_INVALID_PARAMETER; } if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) { spnego_free_data(&spnego); return NT_STATUS_ACCESS_DENIED; } /* Server didn't like our choice of mech, and chose something else */ if ((spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_INCOMPLETE) && spnego.negTokenTarg.supportedMech && strcmp(spnego.negTokenTarg.supportedMech, spnego_state->neg_oid) != 0) { DEBUG(3,("GENSEC SPNEGO: client preferred mech (%s) not accepted, server wants: %s\n", gensec_get_name_by_oid(spnego.negTokenTarg.supportedMech), gensec_get_name_by_oid(spnego_state->neg_oid))); talloc_free(spnego_state->sub_sec_security); nt_status = gensec_subcontext_start(spnego_state, gensec_security, &spnego_state->sub_sec_security); if (!NT_STATUS_IS_OK(nt_status)) { spnego_free_data(&spnego); return nt_status; } /* select the sub context */ nt_status = gensec_start_mech_by_oid(spnego_state->sub_sec_security, spnego.negTokenTarg.supportedMech); if (!NT_STATUS_IS_OK(nt_status)) { spnego_free_data(&spnego); return nt_status; } nt_status = gensec_update(spnego_state->sub_sec_security, out_mem_ctx, spnego.negTokenTarg.responseToken, &unwrapped_out); spnego_state->neg_oid = talloc_strdup(spnego_state, spnego.negTokenTarg.supportedMech); } else if (spnego_state->no_response_expected) { if (spnego.negTokenTarg.negResult != SPNEGO_ACCEPT_COMPLETED) { DEBUG(3,("GENSEC SPNEGO: client GENSEC accepted, but server rejected (bad password?)\n")); nt_status = NT_STATUS_INVALID_PARAMETER; } else if (spnego.negTokenTarg.responseToken.length) { DEBUG(2,("GENSEC SPNEGO: client GENSEC accepted, but server continued negotiation!\n")); nt_status = NT_STATUS_INVALID_PARAMETER; } else { nt_status = NT_STATUS_OK; } } else { nt_status = gensec_update(spnego_state->sub_sec_security, out_mem_ctx, spnego.negTokenTarg.responseToken, &unwrapped_out); if (NT_STATUS_IS_OK(nt_status)) { spnego_state->no_response_expected = true; } } spnego_free_data(&spnego); if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("SPNEGO(%s) login failed: %s\n", spnego_state->sub_sec_security->ops->name, nt_errstr(nt_status))); return nt_status; } if (unwrapped_out.length) { /* 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 SPNEGO reply to NEG_TOKEN_TARG\n")); return NT_STATUS_INVALID_PARAMETER; } spnego_state->state_position = SPNEGO_CLIENT_TARG; nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED; } else { /* all done - server has accepted, and we agree */ *out = null_data_blob; if (spnego.negTokenTarg.negResult != SPNEGO_ACCEPT_COMPLETED) { /* unless of course it did not accept */ DEBUG(1,("gensec_update ok but not accepted\n")); nt_status = NT_STATUS_INVALID_PARAMETER; } spnego_state->state_position = SPNEGO_DONE; } return nt_status; } case SPNEGO_DONE: /* We should not be called after we are 'done' */ return NT_STATUS_INVALID_PARAMETER; } return NT_STATUS_INVALID_PARAMETER;}static bool gensec_spnego_have_feature(struct gensec_security *gensec_security, uint32_t feature) { struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (!spnego_state->sub_sec_security) { return false; } return gensec_have_feature(spnego_state->sub_sec_security, feature);}static const char *gensec_spnego_oids[] = { GENSEC_OID_SPNEGO, NULL };static const struct gensec_security_ops gensec_spnego_security_ops = { .name = "spnego", .sasl_name = "GSS-SPNEGO", .auth_type = DCERPC_AUTH_TYPE_SPNEGO, .oid = gensec_spnego_oids, .client_start = gensec_spnego_client_start, .server_start = gensec_spnego_server_start, .update = gensec_spnego_update, .seal_packet = gensec_spnego_seal_packet, .sign_packet = gensec_spnego_sign_packet, .sig_size = gensec_spnego_sig_size, .max_wrapped_size = gensec_spnego_max_wrapped_size, .max_input_size = gensec_spnego_max_input_size, .check_packet = gensec_spnego_check_packet, .unseal_packet = gensec_spnego_unseal_packet, .packet_full_request = gensec_spnego_packet_full_request, .wrap = gensec_spnego_wrap, .unwrap = gensec_spnego_unwrap, .wrap_packets = gensec_spnego_wrap_packets, .unwrap_packets = gensec_spnego_unwrap_packets, .session_key = gensec_spnego_session_key, .session_info = gensec_spnego_session_info, .have_feature = gensec_spnego_have_feature, .enabled = true, .priority = GENSEC_SPNEGO};_PUBLIC_ NTSTATUS gensec_spnego_init(void){ NTSTATUS ret; ret = gensec_register(&gensec_spnego_security_ops); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("Failed to register '%s' gensec backend!\n", gensec_spnego_security_ops.name)); return ret; } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -