📄 spnego.c
字号:
/* Unix SMB/CIFS implementation. RFC2478 Compliant SPNEGO implementation Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "auth/gensec/spnego.h"#include "librpc/gen_ndr/ndr_dcerpc.h"#include "auth/credentials/credentials.h"#include "auth/gensec/gensec.h"#include "auth/gensec/gensec_proto.h"enum spnego_state_position { SPNEGO_SERVER_START, SPNEGO_CLIENT_START, SPNEGO_SERVER_TARG, SPNEGO_CLIENT_TARG, SPNEGO_FALLBACK, SPNEGO_DONE};struct spnego_state { enum spnego_message_type expected_packet; enum spnego_state_position state_position; struct gensec_security *sub_sec_security; bool no_response_expected; const char *neg_oid;};static NTSTATUS gensec_spnego_client_start(struct gensec_security *gensec_security){ struct spnego_state *spnego_state; spnego_state = talloc(gensec_security, struct spnego_state); if (!spnego_state) { return NT_STATUS_NO_MEMORY; } spnego_state->expected_packet = SPNEGO_NEG_TOKEN_INIT; spnego_state->state_position = SPNEGO_CLIENT_START; spnego_state->sub_sec_security = NULL; spnego_state->no_response_expected = false; gensec_security->private_data = spnego_state; return NT_STATUS_OK;}static NTSTATUS gensec_spnego_server_start(struct gensec_security *gensec_security){ struct spnego_state *spnego_state; spnego_state = talloc(gensec_security, struct spnego_state); if (!spnego_state) { return NT_STATUS_NO_MEMORY; } spnego_state->expected_packet = SPNEGO_NEG_TOKEN_INIT; spnego_state->state_position = SPNEGO_SERVER_START; spnego_state->sub_sec_security = NULL; spnego_state->no_response_expected = false; gensec_security->private_data = spnego_state; return NT_STATUS_OK;}/* wrappers for the spnego_*() functions*/static NTSTATUS gensec_spnego_unseal_packet(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, const DATA_BLOB *sig){ struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { return NT_STATUS_INVALID_PARAMETER; } return gensec_unseal_packet(spnego_state->sub_sec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig); }static NTSTATUS gensec_spnego_check_packet(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, const DATA_BLOB *sig){ struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { return NT_STATUS_INVALID_PARAMETER; } return gensec_check_packet(spnego_state->sub_sec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);}static NTSTATUS gensec_spnego_seal_packet(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, DATA_BLOB *sig){ struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { return NT_STATUS_INVALID_PARAMETER; } return gensec_seal_packet(spnego_state->sub_sec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);}static NTSTATUS gensec_spnego_sign_packet(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, DATA_BLOB *sig){ struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { return NT_STATUS_INVALID_PARAMETER; } return gensec_sign_packet(spnego_state->sub_sec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);}static NTSTATUS gensec_spnego_wrap(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const DATA_BLOB *in, DATA_BLOB *out){ struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { DEBUG(1, ("gensec_spnego_wrap: wrong state for wrap\n")); return NT_STATUS_INVALID_PARAMETER; } return gensec_wrap(spnego_state->sub_sec_security, mem_ctx, in, out);}static NTSTATUS gensec_spnego_unwrap(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const DATA_BLOB *in, DATA_BLOB *out){ struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { DEBUG(1, ("gensec_spnego_unwrap: wrong state for unwrap\n")); return NT_STATUS_INVALID_PARAMETER; } return gensec_unwrap(spnego_state->sub_sec_security, mem_ctx, in, out);}static NTSTATUS gensec_spnego_wrap_packets(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const DATA_BLOB *in, DATA_BLOB *out, size_t *len_processed) { struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { DEBUG(1, ("gensec_spnego_wrap: wrong state for wrap\n")); return NT_STATUS_INVALID_PARAMETER; } return gensec_wrap_packets(spnego_state->sub_sec_security, mem_ctx, in, out, len_processed);}static NTSTATUS gensec_spnego_packet_full_request(struct gensec_security *gensec_security, DATA_BLOB blob, size_t *size){ struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { DEBUG(1, ("gensec_spnego_unwrap: wrong state for unwrap\n")); return NT_STATUS_INVALID_PARAMETER; } return gensec_packet_full_request(spnego_state->sub_sec_security, blob, size);}static NTSTATUS gensec_spnego_unwrap_packets(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const DATA_BLOB *in, DATA_BLOB *out, size_t *len_processed) { struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { DEBUG(1, ("gensec_spnego_unwrap: wrong state for unwrap\n")); return NT_STATUS_INVALID_PARAMETER; } return gensec_unwrap_packets(spnego_state->sub_sec_security, mem_ctx, in, out, len_processed);}static size_t gensec_spnego_sig_size(struct gensec_security *gensec_security, size_t data_size) { struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { return 0; } return gensec_sig_size(spnego_state->sub_sec_security, data_size);}static size_t gensec_spnego_max_input_size(struct gensec_security *gensec_security) { struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { return 0; } return gensec_max_input_size(spnego_state->sub_sec_security);}static size_t gensec_spnego_max_wrapped_size(struct gensec_security *gensec_security) { struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (spnego_state->state_position != SPNEGO_DONE && spnego_state->state_position != SPNEGO_FALLBACK) { return 0; } return gensec_max_wrapped_size(spnego_state->sub_sec_security);}static NTSTATUS gensec_spnego_session_key(struct gensec_security *gensec_security, DATA_BLOB *session_key){ struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (!spnego_state->sub_sec_security) { return NT_STATUS_INVALID_PARAMETER; } return gensec_session_key(spnego_state->sub_sec_security, session_key);}static NTSTATUS gensec_spnego_session_info(struct gensec_security *gensec_security, struct auth_session_info **session_info) { struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; if (!spnego_state->sub_sec_security) { return NT_STATUS_INVALID_PARAMETER; } return gensec_session_info(spnego_state->sub_sec_security, session_info);}/** Fallback to another GENSEC mechanism, based on magic strings * * This is the 'fallback' case, where we don't get SPNEGO, and have to * try all the other options (and hope they all have a magic string * they check)*/static NTSTATUS gensec_spnego_server_try_fallback(struct gensec_security *gensec_security, struct spnego_state *spnego_state, TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out) { int i,j; struct gensec_security_ops **all_ops = gensec_security_mechs(gensec_security, out_mem_ctx); for (i=0; all_ops[i]; i++) { bool is_spnego; NTSTATUS nt_status; if (!all_ops[i]->oid) { continue; } is_spnego = false; for (j=0; all_ops[i]->oid[j]; j++) { if (strcasecmp(GENSEC_OID_SPNEGO,all_ops[i]->oid[j]) == 0) { is_spnego = true; } } if (is_spnego) { continue; } if (!all_ops[i]->magic) { continue; } nt_status = all_ops[i]->magic(gensec_security, &in); if (!NT_STATUS_IS_OK(nt_status)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -