From 53079da638e6e45e9e0a352f532e05073e60d3fb Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 25 Apr 2005 03:37:37 +0000 Subject: r6454: Start to migrate NTLMSSP away from it's own API to just use GENSEC. The aim here is to remove the extra layer of abstraction, and to then use the credentials code directly in the NTLMSSP layer. Andrew Bartlett (This used to be commit b14c530dfd3e56975dea7e30aa8d62d4f2827700) --- source4/auth/gensec/gensec.c | 9 +- source4/auth/gensec/gensec.h | 2 +- source4/auth/gensec/gensec.mk | 3 +- source4/auth/gensec/gensec_gsskrb5.c | 2 +- source4/auth/gensec/gensec_ntlmssp.c | 514 ----------------------------------- source4/auth/gensec/ntlmssp.c | 349 +++++++++++++++++++++++- source4/auth/gensec/ntlmssp.h | 8 + source4/auth/gensec/ntlmssp_sign.c | 172 +++++++++--- source4/auth/gensec/schannel_sign.c | 2 +- 9 files changed, 492 insertions(+), 569 deletions(-) delete mode 100644 source4/auth/gensec/gensec_ntlmssp.c (limited to 'source4/auth/gensec') diff --git a/source4/auth/gensec/gensec.c b/source4/auth/gensec/gensec.c index cc7327187c..43ace2c36d 100644 --- a/source4/auth/gensec/gensec.c +++ b/source4/auth/gensec/gensec.c @@ -247,10 +247,15 @@ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security, gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE); if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN); - } - if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { + } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN); gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL); + } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) { + /* Default features */ + } else { + DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n", + auth_level)); + return NT_STATUS_INVALID_PARAMETER; } return gensec_start_mech(gensec_security); diff --git a/source4/auth/gensec/gensec.h b/source4/auth/gensec/gensec.h index 91c817d48a..71c00c5157 100644 --- a/source4/auth/gensec/gensec.h +++ b/source4/auth/gensec/gensec.h @@ -74,7 +74,7 @@ struct gensec_security_ops { NTSTATUS (*unseal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig); + const DATA_BLOB *sig); NTSTATUS (*wrap)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const DATA_BLOB *in, diff --git a/source4/auth/gensec/gensec.mk b/source4/auth/gensec/gensec.mk index 8ed6f7c840..7b5fa7ae36 100644 --- a/source4/auth/gensec/gensec.mk +++ b/source4/auth/gensec/gensec.mk @@ -54,9 +54,8 @@ ADD_OBJ_FILES = \ [MODULE::gensec_ntlmssp] SUBSYSTEM = GENSEC INIT_FUNCTION = gensec_ntlmssp_init -INIT_OBJ_FILES = auth/gensec/gensec_ntlmssp.o +INIT_OBJ_FILES = auth/gensec/ntlmssp.o ADD_OBJ_FILES = \ - auth/gensec/ntlmssp.o \ auth/gensec/ntlmssp_parse.o \ auth/gensec/ntlmssp_sign.o REQUIRED_SUBSYSTEMS = AUTH diff --git a/source4/auth/gensec/gensec_gsskrb5.c b/source4/auth/gensec/gensec_gsskrb5.c index 4aa7d32f58..8fe1e0d224 100644 --- a/source4/auth/gensec/gensec_gsskrb5.c +++ b/source4/auth/gensec/gensec_gsskrb5.c @@ -406,7 +406,7 @@ static NTSTATUS gensec_gsskrb5_unseal_packet(struct gensec_security *gensec_secu TALLOC_CTX *mem_ctx, uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig) + const DATA_BLOB *sig) { struct gensec_gsskrb5_state *gensec_gsskrb5_state = gensec_security->private_data; OM_uint32 maj_stat, min_stat; diff --git a/source4/auth/gensec/gensec_ntlmssp.c b/source4/auth/gensec/gensec_ntlmssp.c deleted file mode 100644 index 5955904886..0000000000 --- a/source4/auth/gensec/gensec_ntlmssp.c +++ /dev/null @@ -1,514 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - dcerpc authentication operations - - Copyright (C) Andrew Tridgell 2003 - Copyright (C) Andrew Bartlett 2004 - Copyright (C) Stefan Metzmacher 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "auth/auth.h" - -struct gensec_ntlmssp_state { - struct auth_context *auth_context; - struct auth_serversupplied_info *server_info; - struct ntlmssp_state *ntlmssp_state; - uint32_t have_features; -}; - - -/** - * Return the challenge as determined by the authentication subsystem - * @return an 8 byte random challenge - */ - -static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; - NTSTATUS status; - const uint8_t *chal; - - status = auth_get_challenge(gensec_ntlmssp_state->auth_context, &chal); - if (!NT_STATUS_IS_OK(status)) { - return NULL; - } - - return chal; -} - -/** - * Some authentication methods 'fix' the challenge, so we may not be able to set it - * - * @return If the effective challenge used by the auth subsystem may be modified - */ -static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; - - return auth_challenge_may_be_modified(gensec_ntlmssp_state->auth_context); -} - -/** - * NTLM2 authentication modifies the effective challenge, - * @param challenge The new challenge value - */ -static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge) -{ - NTSTATUS nt_status; - struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; - struct auth_context *auth_context = gensec_ntlmssp_state->auth_context; - const uint8_t *chal; - - if (challenge->length != 8) { - return NT_STATUS_INVALID_PARAMETER; - } - - chal = challenge->data; - - nt_status = auth_context_set_challenge(auth_context, chal, "NTLMSSP callback (NTLM2)"); - - return nt_status; -} - -/** - * Check the password on an NTLMSSP login. - * - * Return the session keys used on the connection. - */ - -static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; - struct auth_usersupplied_info *user_info = NULL; - NTSTATUS nt_status; - - nt_status = make_user_info_map(ntlmssp_state, - gensec_ntlmssp_state->ntlmssp_state->user, - gensec_ntlmssp_state->ntlmssp_state->domain, - gensec_ntlmssp_state->ntlmssp_state->workstation, - gensec_ntlmssp_state->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->lm_resp : NULL, - gensec_ntlmssp_state->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->nt_resp : NULL, - NULL, NULL, NULL, True, - &user_info); - NT_STATUS_NOT_OK_RETURN(nt_status); - - nt_status = auth_check_password(gensec_ntlmssp_state->auth_context, gensec_ntlmssp_state, - user_info, &gensec_ntlmssp_state->server_info); - talloc_free(user_info); - NT_STATUS_NOT_OK_RETURN(nt_status); - - if (gensec_ntlmssp_state->server_info->user_session_key.length) { - DEBUG(10, ("Got NT session key of length %u\n", gensec_ntlmssp_state->server_info->user_session_key.length)); - *user_session_key = data_blob_talloc(ntlmssp_state, - gensec_ntlmssp_state->server_info->user_session_key.data, - gensec_ntlmssp_state->server_info->user_session_key.length); - } - if (gensec_ntlmssp_state->server_info->lm_session_key.length) { - DEBUG(10, ("Got LM session key of length %u\n", gensec_ntlmssp_state->server_info->lm_session_key.length)); - *lm_session_key = data_blob_talloc(ntlmssp_state, - gensec_ntlmssp_state->server_info->lm_session_key.data, - gensec_ntlmssp_state->server_info->lm_session_key.length); - } - return nt_status; -} - -static int gensec_ntlmssp_destroy(void *ptr) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = ptr; - - if (gensec_ntlmssp_state->ntlmssp_state) { - ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state); - } - - return 0; -} - -static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state; - - gensec_ntlmssp_state = talloc(gensec_security, struct gensec_ntlmssp_state); - if (!gensec_ntlmssp_state) { - return NT_STATUS_NO_MEMORY; - } - - gensec_ntlmssp_state->ntlmssp_state = NULL; - gensec_ntlmssp_state->auth_context = NULL; - gensec_ntlmssp_state->server_info = NULL; - gensec_ntlmssp_state->have_features = 0; - - talloc_set_destructor(gensec_ntlmssp_state, gensec_ntlmssp_destroy); - - gensec_security->private_data = gensec_ntlmssp_state; - return NT_STATUS_OK; -} - -static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security) -{ - NTSTATUS nt_status; - struct ntlmssp_state *ntlmssp_state; - struct gensec_ntlmssp_state *gensec_ntlmssp_state; - - nt_status = gensec_ntlmssp_start(gensec_security); - NT_STATUS_NOT_OK_RETURN(nt_status); - - gensec_ntlmssp_state = gensec_security->private_data; - - nt_status = ntlmssp_server_start(gensec_ntlmssp_state, &gensec_ntlmssp_state->ntlmssp_state); - NT_STATUS_NOT_OK_RETURN(nt_status); - - if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { - gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; - } - if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { - gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; - } - - nt_status = auth_context_create(gensec_ntlmssp_state, lp_auth_methods(), &gensec_ntlmssp_state->auth_context); - NT_STATUS_NOT_OK_RETURN(nt_status); - - ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; - ntlmssp_state->auth_context = gensec_ntlmssp_state; - ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge; - ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge; - ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge; - ntlmssp_state->check_password = auth_ntlmssp_check_password; - ntlmssp_state->server_role = lp_server_role(); - - return NT_STATUS_OK; -} - -static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state; - const char *password = NULL; - NTSTATUS nt_status; - - nt_status = gensec_ntlmssp_start(gensec_security); - NT_STATUS_NOT_OK_RETURN(nt_status); - - gensec_ntlmssp_state = gensec_security->private_data; - nt_status = ntlmssp_client_start(gensec_ntlmssp_state, - &gensec_ntlmssp_state->ntlmssp_state); - NT_STATUS_NOT_OK_RETURN(nt_status); - - if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) { - /* - * We need to set this to allow a later SetPassword - * via the SAMR pipe to succeed. Strange.... We could - * also add NTLMSSP_NEGOTIATE_SEAL here. JRA. - * - * Without this, Windows will not create the master key - * that it thinks is only used for NTLMSSP signing and - * sealing. (It is actually pulled out and used directly) - */ - gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; - } - if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { - gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; - } - if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { - gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; - } - - nt_status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, - cli_credentials_get_domain(gensec_security->credentials)); - NT_STATUS_NOT_OK_RETURN(nt_status); - - nt_status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, - cli_credentials_get_username(gensec_security->credentials)); - NT_STATUS_NOT_OK_RETURN(nt_status); - - password = cli_credentials_get_password(gensec_security->credentials); - - nt_status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, password); - NT_STATUS_NOT_OK_RETURN(nt_status); - - nt_status = ntlmssp_set_workstation(gensec_ntlmssp_state->ntlmssp_state, - cli_credentials_get_workstation(gensec_security->credentials)); - - gensec_security->private_data = gensec_ntlmssp_state; - - return NT_STATUS_OK; -} - -/* - wrappers for the ntlmssp_*() functions -*/ -static NTSTATUS gensec_ntlmssp_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, - DATA_BLOB *sig) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - - return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig); -} - -static NTSTATUS gensec_ntlmssp_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 gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - - return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig); -} - -static NTSTATUS gensec_ntlmssp_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 gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - - return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig); -} - -static NTSTATUS gensec_ntlmssp_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 gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - - return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig); -} - -static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) -{ - return NTLMSSP_SIG_SIZE; -} - -static NTSTATUS gensec_ntlmssp_wrap(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - const DATA_BLOB *in, - DATA_BLOB *out) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - DATA_BLOB sig; - NTSTATUS nt_status; - - if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { - - *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); - memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); - - nt_status = ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, - out->data + NTLMSSP_SIG_SIZE, - out->length - NTLMSSP_SIG_SIZE, - out->data + NTLMSSP_SIG_SIZE, - out->length - NTLMSSP_SIG_SIZE, - &sig); - - if (NT_STATUS_IS_OK(nt_status)) { - memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); - } - return nt_status; - - } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) - || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) { - - *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); - memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); - - nt_status = ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, - out->data + NTLMSSP_SIG_SIZE, - out->length - NTLMSSP_SIG_SIZE, - out->data + NTLMSSP_SIG_SIZE, - out->length - NTLMSSP_SIG_SIZE, - &sig); - - if (NT_STATUS_IS_OK(nt_status)) { - memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); - } - return nt_status; - - } else { - *out = *in; - return NT_STATUS_OK; - } -} - - -static NTSTATUS gensec_ntlmssp_unwrap(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - const DATA_BLOB *in, - DATA_BLOB *out) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - DATA_BLOB sig; - - if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { - if (in->length < NTLMSSP_SIG_SIZE) { - return NT_STATUS_INVALID_PARAMETER; - } - sig.data = in->data; - sig.length = NTLMSSP_SIG_SIZE; - - *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); - - return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, - out->data, out->length, - out->data, out->length, - &sig); - - } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) - || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) { - if (in->length < NTLMSSP_SIG_SIZE) { - return NT_STATUS_INVALID_PARAMETER; - } - sig.data = in->data; - sig.length = NTLMSSP_SIG_SIZE; - - *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); - - return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, - out->data, out->length, - out->data, out->length, - &sig); - } else { - *out = *in; - return NT_STATUS_OK; - } -} - -static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, - DATA_BLOB *session_key) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - - return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key); -} - -/** - * Next state function for the wrapped NTLMSSP state machine - * - * @param gensec_security GENSEC state, initialised to NTLMSSP - * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on - * @param in The request, as a DATA_BLOB - * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx - * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, - * or NT_STATUS_OK if the user is authenticated. - */ - -static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, - const DATA_BLOB in, DATA_BLOB *out) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - NTSTATUS status; - - status = ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out); - - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { - return status; - } - - gensec_ntlmssp_state->have_features = 0; - - if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { - gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SIGN; - } - - if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { - gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SEAL; - } - - if (gensec_ntlmssp_state->ntlmssp_state->session_key.data) { - gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SESSION_KEY; - } - - return status; -} - -/** - * Return the credentials of a logged on user, including session keys - * etc. - * - * Only valid after a successful authentication - * - * May only be called once per authentication. - * - */ - -static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security, - struct auth_session_info **session_info) -{ - NTSTATUS nt_status; - struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - - nt_status = auth_generate_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info); - NT_STATUS_NOT_OK_RETURN(nt_status); - - (*session_info)->session_key = data_blob_talloc(*session_info, - gensec_ntlmssp_state->ntlmssp_state->session_key.data, - gensec_ntlmssp_state->ntlmssp_state->session_key.length); - - return NT_STATUS_OK; -} - -static BOOL gensec_ntlmssp_have_feature(struct gensec_security *gensec_security, - uint32_t feature) -{ - struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - if (gensec_ntlmssp_state->have_features & feature) { - return True; - } - - return False; -} - -static const struct gensec_security_ops gensec_ntlmssp_security_ops = { - .name = "ntlmssp", - .sasl_name = "NTLM", - .auth_type = DCERPC_AUTH_TYPE_NTLMSSP, - .oid = GENSEC_OID_NTLMSSP, - .client_start = gensec_ntlmssp_client_start, - .server_start = gensec_ntlmssp_server_start, - .update = gensec_ntlmssp_update, - .sig_size = gensec_ntlmssp_sig_size, - .sign_packet = gensec_ntlmssp_sign_packet, - .check_packet = gensec_ntlmssp_check_packet, - .seal_packet = gensec_ntlmssp_seal_packet, - .unseal_packet = gensec_ntlmssp_unseal_packet, - .wrap = gensec_ntlmssp_wrap, - .unwrap = gensec_ntlmssp_unwrap, - .session_key = gensec_ntlmssp_session_key, - .session_info = gensec_ntlmssp_session_info, - .have_feature = gensec_ntlmssp_have_feature, - .enabled = True -}; - - -NTSTATUS gensec_ntlmssp_init(void) -{ - NTSTATUS ret; - ret = gensec_register(&gensec_ntlmssp_security_ops); - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register '%s' gensec backend!\n", - gensec_ntlmssp_security_ops.name)); - return ret; - } - - return ret; -} diff --git a/source4/auth/gensec/ntlmssp.c b/source4/auth/gensec/ntlmssp.c index 37374d9d39..c17352a469 100644 --- a/source4/auth/gensec/ntlmssp.c +++ b/source4/auth/gensec/ntlmssp.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 2001 Copyright (C) Andrew Bartlett 2001-2005 + Copyright (C) Stefan Metzmacher 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 @@ -55,8 +56,6 @@ static const struct ntlmssp_callbacks { {NTLMSSP_SERVER, NTLMSSP_NEGOTIATE, ntlmssp_server_negotiate}, {NTLMSSP_CLIENT, NTLMSSP_CHALLENGE, ntlmssp_client_challenge}, {NTLMSSP_SERVER, NTLMSSP_AUTH, ntlmssp_server_auth}, - {NTLMSSP_CLIENT, NTLMSSP_UNKNOWN, NULL}, - {NTLMSSP_SERVER, NTLMSSP_UNKNOWN, NULL} }; @@ -215,9 +214,9 @@ NTSTATUS ntlmssp_store_response(struct ntlmssp_state *ntlmssp_state, } /** - * Next state function for the NTLMSSP state machine + * Next state function for the wrapped NTLMSSP state machine * - * @param ntlmssp_state NTLMSSP State + * @param gensec_security GENSEC state, initialised to NTLMSSP * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on * @param in The request, as a DATA_BLOB * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx @@ -225,10 +224,13 @@ NTSTATUS ntlmssp_store_response(struct ntlmssp_state *ntlmssp_state, * or NT_STATUS_OK if the user is authenticated. */ -NTSTATUS ntlmssp_update(struct ntlmssp_state *ntlmssp_state, - TALLOC_CTX *out_mem_ctx, - const DATA_BLOB in, DATA_BLOB *out) +static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, + const DATA_BLOB in, DATA_BLOB *out) { + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; + NTSTATUS status; + DATA_BLOB input; uint32_t ntlmssp_command; int i; @@ -280,18 +282,41 @@ NTSTATUS ntlmssp_update(struct ntlmssp_state *ntlmssp_state, return NT_STATUS_INVALID_PARAMETER; } - for (i=0; ntlmssp_callbacks[i].fn; i++) { + for (i=0; i < ARRAY_SIZE(ntlmssp_callbacks); i++) { if (ntlmssp_callbacks[i].role == ntlmssp_state->role - && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command - && ntlmssp_callbacks[i].fn) { - return ntlmssp_callbacks[i].fn(ntlmssp_state, out_mem_ctx, input, out); + && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) { + status = ntlmssp_callbacks[i].fn(ntlmssp_state, out_mem_ctx, input, out); + break; } } - DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n", - ntlmssp_state->role, ntlmssp_command)); + if (i == ARRAY_SIZE(ntlmssp_callbacks)) { + + DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n", + ntlmssp_state->role, ntlmssp_command)); + + return NT_STATUS_INVALID_PARAMETER; + } - return NT_STATUS_INVALID_PARAMETER; + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { + return status; + } + + gensec_ntlmssp_state->have_features = 0; + + if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { + gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SIGN; + } + + if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { + gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SEAL; + } + + if (gensec_ntlmssp_state->ntlmssp_state->session_key.data) { + gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SESSION_KEY; + } + + return status; } /** @@ -1271,7 +1296,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, return nt_status; } -NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx, struct ntlmssp_state **ntlmssp_state) +static NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx, struct ntlmssp_state **ntlmssp_state) { *ntlmssp_state = talloc(mem_ctx, struct ntlmssp_state); if (!*ntlmssp_state) { @@ -1320,3 +1345,297 @@ NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx, struct ntlmssp_state **ntlmss return NT_STATUS_OK; } +/** + * Return the challenge as determined by the authentication subsystem + * @return an 8 byte random challenge + */ + +static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; + NTSTATUS status; + const uint8_t *chal; + + status = auth_get_challenge(gensec_ntlmssp_state->auth_context, &chal); + if (!NT_STATUS_IS_OK(status)) { + return NULL; + } + + return chal; +} + +/** + * Some authentication methods 'fix' the challenge, so we may not be able to set it + * + * @return If the effective challenge used by the auth subsystem may be modified + */ +static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; + + return auth_challenge_may_be_modified(gensec_ntlmssp_state->auth_context); +} + +/** + * NTLM2 authentication modifies the effective challenge, + * @param challenge The new challenge value + */ +static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge) +{ + NTSTATUS nt_status; + struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; + struct auth_context *auth_context = gensec_ntlmssp_state->auth_context; + const uint8_t *chal; + + if (challenge->length != 8) { + return NT_STATUS_INVALID_PARAMETER; + } + + chal = challenge->data; + + nt_status = auth_context_set_challenge(auth_context, chal, "NTLMSSP callback (NTLM2)"); + + return nt_status; +} + +/** + * Check the password on an NTLMSSP login. + * + * Return the session keys used on the connection. + */ + +static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; + struct auth_usersupplied_info *user_info = NULL; + NTSTATUS nt_status; + + nt_status = make_user_info_map(ntlmssp_state, + gensec_ntlmssp_state->ntlmssp_state->user, + gensec_ntlmssp_state->ntlmssp_state->domain, + gensec_ntlmssp_state->ntlmssp_state->workstation, + gensec_ntlmssp_state->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->lm_resp : NULL, + gensec_ntlmssp_state->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->nt_resp : NULL, + NULL, NULL, NULL, True, + &user_info); + NT_STATUS_NOT_OK_RETURN(nt_status); + + nt_status = auth_check_password(gensec_ntlmssp_state->auth_context, gensec_ntlmssp_state, + user_info, &gensec_ntlmssp_state->server_info); + talloc_free(user_info); + NT_STATUS_NOT_OK_RETURN(nt_status); + + if (gensec_ntlmssp_state->server_info->user_session_key.length) { + DEBUG(10, ("Got NT session key of length %u\n", gensec_ntlmssp_state->server_info->user_session_key.length)); + *user_session_key = data_blob_talloc(ntlmssp_state, + gensec_ntlmssp_state->server_info->user_session_key.data, + gensec_ntlmssp_state->server_info->user_session_key.length); + } + if (gensec_ntlmssp_state->server_info->lm_session_key.length) { + DEBUG(10, ("Got LM session key of length %u\n", gensec_ntlmssp_state->server_info->lm_session_key.length)); + *lm_session_key = data_blob_talloc(ntlmssp_state, + gensec_ntlmssp_state->server_info->lm_session_key.data, + gensec_ntlmssp_state->server_info->lm_session_key.length); + } + return nt_status; +} + +static int gensec_ntlmssp_destroy(void *ptr) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = ptr; + + if (gensec_ntlmssp_state->ntlmssp_state) { + ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state); + } + + return 0; +} + +static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state; + + gensec_ntlmssp_state = talloc(gensec_security, struct gensec_ntlmssp_state); + if (!gensec_ntlmssp_state) { + return NT_STATUS_NO_MEMORY; + } + + gensec_ntlmssp_state->ntlmssp_state = NULL; + gensec_ntlmssp_state->auth_context = NULL; + gensec_ntlmssp_state->server_info = NULL; + gensec_ntlmssp_state->have_features = 0; + + talloc_set_destructor(gensec_ntlmssp_state, gensec_ntlmssp_destroy); + + gensec_security->private_data = gensec_ntlmssp_state; + return NT_STATUS_OK; +} + +static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security) +{ + NTSTATUS nt_status; + struct ntlmssp_state *ntlmssp_state; + struct gensec_ntlmssp_state *gensec_ntlmssp_state; + + nt_status = gensec_ntlmssp_start(gensec_security); + NT_STATUS_NOT_OK_RETURN(nt_status); + + gensec_ntlmssp_state = gensec_security->private_data; + + nt_status = ntlmssp_server_start(gensec_ntlmssp_state, &gensec_ntlmssp_state->ntlmssp_state); + NT_STATUS_NOT_OK_RETURN(nt_status); + + if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { + gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { + gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; + } + + nt_status = auth_context_create(gensec_ntlmssp_state, lp_auth_methods(), &gensec_ntlmssp_state->auth_context); + NT_STATUS_NOT_OK_RETURN(nt_status); + + ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; + ntlmssp_state->auth_context = gensec_ntlmssp_state; + ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge; + ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge; + ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge; + ntlmssp_state->check_password = auth_ntlmssp_check_password; + ntlmssp_state->server_role = lp_server_role(); + + return NT_STATUS_OK; +} + +static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state; + const char *password = NULL; + NTSTATUS nt_status; + + nt_status = gensec_ntlmssp_start(gensec_security); + NT_STATUS_NOT_OK_RETURN(nt_status); + + gensec_ntlmssp_state = gensec_security->private_data; + nt_status = ntlmssp_client_start(gensec_ntlmssp_state, + &gensec_ntlmssp_state->ntlmssp_state); + NT_STATUS_NOT_OK_RETURN(nt_status); + + if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) { + /* + * We need to set this to allow a later SetPassword + * via the SAMR pipe to succeed. Strange.... We could + * also add NTLMSSP_NEGOTIATE_SEAL here. JRA. + * + * Without this, Windows will not create the master key + * that it thinks is only used for NTLMSSP signing and + * sealing. (It is actually pulled out and used directly) + */ + gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { + gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { + gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; + } + + nt_status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, + cli_credentials_get_domain(gensec_security->credentials)); + NT_STATUS_NOT_OK_RETURN(nt_status); + + nt_status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, + cli_credentials_get_username(gensec_security->credentials)); + NT_STATUS_NOT_OK_RETURN(nt_status); + + password = cli_credentials_get_password(gensec_security->credentials); + + nt_status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, password); + NT_STATUS_NOT_OK_RETURN(nt_status); + + nt_status = ntlmssp_set_workstation(gensec_ntlmssp_state->ntlmssp_state, + cli_credentials_get_workstation(gensec_security->credentials)); + + gensec_security->private_data = gensec_ntlmssp_state; + + return NT_STATUS_OK; +} + +static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, + DATA_BLOB *session_key) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + + return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key); +} + +/** + * Return the credentials of a logged on user, including session keys + * etc. + * + * Only valid after a successful authentication + * + * May only be called once per authentication. + * + */ + +static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security, + struct auth_session_info **session_info) +{ + NTSTATUS nt_status; + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + + nt_status = auth_generate_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info); + NT_STATUS_NOT_OK_RETURN(nt_status); + + (*session_info)->session_key = data_blob_talloc(*session_info, + gensec_ntlmssp_state->ntlmssp_state->session_key.data, + gensec_ntlmssp_state->ntlmssp_state->session_key.length); + + return NT_STATUS_OK; +} + +static BOOL gensec_ntlmssp_have_feature(struct gensec_security *gensec_security, + uint32_t feature) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + if (gensec_ntlmssp_state->have_features & feature) { + return True; + } + + return False; +} + +static const struct gensec_security_ops gensec_ntlmssp_security_ops = { + .name = "ntlmssp", + .sasl_name = "NTLM", + .auth_type = DCERPC_AUTH_TYPE_NTLMSSP, + .oid = GENSEC_OID_NTLMSSP, + .client_start = gensec_ntlmssp_client_start, + .server_start = gensec_ntlmssp_server_start, + .update = gensec_ntlmssp_update, + .sig_size = gensec_ntlmssp_sig_size, + .sign_packet = gensec_ntlmssp_sign_packet, + .check_packet = gensec_ntlmssp_check_packet, + .seal_packet = gensec_ntlmssp_seal_packet, + .unseal_packet = gensec_ntlmssp_unseal_packet, + .wrap = gensec_ntlmssp_wrap, + .unwrap = gensec_ntlmssp_unwrap, + .session_key = gensec_ntlmssp_session_key, + .session_info = gensec_ntlmssp_session_info, + .have_feature = gensec_ntlmssp_have_feature, + .enabled = True +}; + + +NTSTATUS gensec_ntlmssp_init(void) +{ + NTSTATUS ret; + ret = gensec_register(&gensec_ntlmssp_security_ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' gensec backend!\n", + gensec_ntlmssp_security_ops.name)); + return ret; + } + + return ret; +} diff --git a/source4/auth/gensec/ntlmssp.h b/source4/auth/gensec/ntlmssp.h index e17c133c8b..0fe04a7c0f 100644 --- a/source4/auth/gensec/ntlmssp.h +++ b/source4/auth/gensec/ntlmssp.h @@ -188,3 +188,11 @@ struct ntlmssp_state }; +struct gensec_ntlmssp_state { + struct auth_context *auth_context; + struct auth_serversupplied_info *server_info; + struct ntlmssp_state *ntlmssp_state; + uint32_t have_features; +}; + + diff --git a/source4/auth/gensec/ntlmssp_sign.c b/source4/auth/gensec/ntlmssp_sign.c index 347a85da77..dba3dbee29 100644 --- a/source4/auth/gensec/ntlmssp_sign.c +++ b/source4/auth/gensec/ntlmssp_sign.c @@ -3,7 +3,7 @@ * Version 3.0 * NTLMSSP Signing routines * Copyright (C) Luke Kenneth Casson Leighton 1996-2001 - * Copyright (C) Andrew Bartlett 2003-2004 + * Copyright (C) Andrew Bartlett 2003-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 @@ -32,16 +32,10 @@ /** * Some notes on then NTLM2 code: * - * This code works correctly for the sealing part of the problem. If - * we disable the check for valid client signatures, then we see that - * the output of a rpcecho 'sinkdata' at smbd is correct. We get the - * valid data, and it is validly decrypted. - * - * This means that the quantity of data passing though the RC4 sealing - * pad is correct. - * - * This code also correctly matches test values that I have obtained, - * claiming to be the correct output of NTLM2 signature generation. + * NTLM2 is a AEAD system. This means that the data encrypted is not + * all the data that is signed. In DCE-RPC case, the headers of the + * DCE-RPC packets are also signed. This prevents some of the + * fun-and-games one might have by changing them. * */ @@ -128,12 +122,15 @@ static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_stat return NT_STATUS_OK; } -NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state, - TALLOC_CTX *sig_mem_ctx, - const uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig) +NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, + TALLOC_CTX *sig_mem_ctx, + const uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + DATA_BLOB *sig) { + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; + if (!ntlmssp_state->session_key.length) { DEBUG(3, ("NO session key, cannot check sign packet\n")); return NT_STATUS_NO_USER_SESSION_KEY; @@ -155,12 +152,15 @@ NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state, * */ -NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state, - TALLOC_CTX *sig_mem_ctx, - const uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - const DATA_BLOB *sig) +NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, + TALLOC_CTX *sig_mem_ctx, + const uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + const DATA_BLOB *sig) { + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; + DATA_BLOB local_sig; NTSTATUS nt_status; @@ -222,12 +222,14 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state, * */ -NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state, - TALLOC_CTX *sig_mem_ctx, - uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig) -{ +NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, + TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + DATA_BLOB *sig) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; NTSTATUS nt_status; if (!ntlmssp_state->session_key.length) { DEBUG(3, ("NO session key, cannot seal packet\n")); @@ -284,12 +286,17 @@ NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state, * */ -NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state, - TALLOC_CTX *sig_mem_ctx, - uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig) +/* + wrappers for the ntlmssp_*() functions +*/ +NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, + TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + const DATA_BLOB *sig) { + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; DATA_BLOB local_sig; NTSTATUS nt_status; if (!ntlmssp_state->session_key.length) { @@ -327,7 +334,7 @@ NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state, } else { arcfour_crypt_sbox(ntlmssp_state->ntlmssp_hash, data, length); dump_data_pw("ntlmssp clear data\n", data, length); - return ntlmssp_check_packet(ntlmssp_state, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig); + return gensec_ntlmssp_check_packet(gensec_security, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig); } } @@ -447,3 +454,102 @@ NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state) return NT_STATUS_OK; } + +size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) +{ + return NTLMSSP_SIG_SIZE; +} + +NTSTATUS gensec_ntlmssp_wrap(struct gensec_security *gensec_security, + TALLOC_CTX *sig_mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + DATA_BLOB sig; + NTSTATUS nt_status; + + if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { + + *out = data_blob_talloc(sig_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); + memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); + + nt_status = gensec_ntlmssp_seal_packet(gensec_security, sig_mem_ctx, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + &sig); + + if (NT_STATUS_IS_OK(nt_status)) { + memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); + } + return nt_status; + + } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) + || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) { + + *out = data_blob_talloc(sig_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); + memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); + + nt_status = gensec_ntlmssp_sign_packet(gensec_security, sig_mem_ctx, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + out->data + NTLMSSP_SIG_SIZE, + out->length - NTLMSSP_SIG_SIZE, + &sig); + + if (NT_STATUS_IS_OK(nt_status)) { + memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); + } + return nt_status; + + } else { + *out = *in; + return NT_STATUS_OK; + } +} + + +NTSTATUS gensec_ntlmssp_unwrap(struct gensec_security *gensec_security, + TALLOC_CTX *sig_mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out) +{ + struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; + DATA_BLOB sig; + + if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { + if (in->length < NTLMSSP_SIG_SIZE) { + return NT_STATUS_INVALID_PARAMETER; + } + sig.data = in->data; + sig.length = NTLMSSP_SIG_SIZE; + + *out = data_blob_talloc(sig_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); + + return gensec_ntlmssp_unseal_packet(gensec_security, sig_mem_ctx, + out->data, out->length, + out->data, out->length, + &sig); + + } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) + || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) { + if (in->length < NTLMSSP_SIG_SIZE) { + return NT_STATUS_INVALID_PARAMETER; + } + sig.data = in->data; + sig.length = NTLMSSP_SIG_SIZE; + + *out = data_blob_talloc(sig_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); + + return gensec_ntlmssp_check_packet(gensec_security, sig_mem_ctx, + out->data, out->length, + out->data, out->length, + &sig); + } else { + *out = *in; + return NT_STATUS_OK; + } +} + diff --git a/source4/auth/gensec/schannel_sign.c b/source4/auth/gensec/schannel_sign.c index 493b26f6c0..f143ccd4c7 100644 --- a/source4/auth/gensec/schannel_sign.c +++ b/source4/auth/gensec/schannel_sign.c @@ -103,7 +103,7 @@ NTSTATUS schannel_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, - DATA_BLOB *sig) + const DATA_BLOB *sig) { struct schannel_state *state = gensec_security->private_data; -- cgit