From 296dcbac5897ad208c890720d3356a3ddc5f7794 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Mar 2007 01:17:47 +0000 Subject: r21882: The server part of the code has to use an AUTH_NTLMSSP struct, not just an NTLMSSP - grr. This complicates the re-use of common client and server code but I think I've got it right. Not turned on of valgrinded yet, but you can see it start to take shape ! Jeremy. (This used to be commit 60fc9c0aedf42dcd9df2ef9f1df07eaf3bca9bce) --- source3/smbd/seal.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 source3/smbd/seal.c (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c new file mode 100644 index 0000000000..2dd4fc8b62 --- /dev/null +++ b/source3/smbd/seal.c @@ -0,0 +1,257 @@ +/* + Unix SMB/CIFS implementation. + SMB Transport encryption (sealing) code - server code. + Copyright (C) Jeremy Allison 2007. + + 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" + +/****************************************************************************** + Server side encryption. +******************************************************************************/ + +/****************************************************************************** + Global server state. +******************************************************************************/ + +struct smb_srv_trans_enc_ctx { + struct smb_trans_enc_state *es; + AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */ +}; + +static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx; +static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx; + +/****************************************************************************** + Is server encryption on ? +******************************************************************************/ + +BOOL srv_encryption_on(void) +{ + if (srv_trans_enc_ctx) { + return common_encryption_on(srv_trans_enc_ctx->es); + } + return False; +} + +/****************************************************************************** + Shutdown a server encryption state. +******************************************************************************/ + +static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) +{ + struct smb_srv_trans_enc_ctx *ec = *pp_ec; + + if (!ec) { + return; + } + + if (ec->es) { + struct smb_trans_enc_state *es = ec->es; + if (es->smb_enc_type == SMB_TRANS_ENC_NTLM && + ec->auth_ntlmssp_state) { + auth_ntlmssp_end(&ec->auth_ntlmssp_state); + /* The auth_ntlmssp_end killed this already. */ + es->ntlmssp_state = NULL; + } + common_free_encryption_state(&ec->es); + } + + SAFE_FREE(ec); + *pp_ec = NULL; +} + +/****************************************************************************** + Free an encryption-allocated buffer. +******************************************************************************/ + +void srv_free_enc_buffer(char *buf) +{ + if (srv_trans_enc_ctx) { + return common_free_enc_buffer(srv_trans_enc_ctx->es, buf); + } +} + +/****************************************************************************** + Decrypt an incoming buffer. +******************************************************************************/ + +NTSTATUS srv_decrypt_buffer(char *buf) +{ + if (srv_trans_enc_ctx) { + return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); + } + return NT_STATUS_OK; +} + +/****************************************************************************** + Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. +******************************************************************************/ + +NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) +{ + if (srv_trans_enc_ctx) { + return common_encrypt_buffer(srv_trans_enc_ctx->es, buffer, buf_out); + } + /* Not encrypting. */ + *buf_out = buffer; + return NT_STATUS_OK; +} + +/****************************************************************************** + Do the gss encryption negotiation. Parameters are in/out. + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) +static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB *psecblob) +{ + return NT_STATUS_NOT_SUPPORTED; +} +#endif + +/****************************************************************************** + Do the SPNEGO encryption negotiation. Parameters are in/out. + Covers the NTLM case. Based off code in smbd/sesssionsetup.c + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob(NULL,0); + DATA_BLOB secblob = data_blob(NULL, 0); + DATA_BLOB chal = data_blob(NULL, 0); + DATA_BLOB response = data_blob(NULL, 0); + BOOL got_kerberos_mechanism = False; + struct smb_srv_trans_enc_ctx *ec = NULL; + + blob = data_blob_const(*ppdata, *p_data_size); + + status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + /* We should have no partial context at this point. */ + + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + + partial_srv_trans_enc_ctx = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); + if (!partial_srv_trans_enc_ctx) { + data_blob_free(&secblob); + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(partial_srv_trans_enc_ctx); + +#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) + if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) { + status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, &secblob); + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&secblob); + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + } + return status; + } +#endif + + /* Deal with an NTLM enc. setup. */ + ec = partial_srv_trans_enc_ctx; + + status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + + status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal); + data_blob_free(&secblob); + + /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED + * for success ... */ + + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + data_blob_free(&chal); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + + return status; +} + +/****************************************************************************** + Complete a SPNEGO encryption negotiation. Parameters are in/out. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_auth(unsigned char **ppdata, size_t *p_data_size) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +/****************************************************************************** + Do the SPNEGO encryption negotiation. Parameters are in/out. +******************************************************************************/ + +NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_size) +{ + unsigned char *pdata = *ppdata; + + if (*p_data_size < 1) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (pdata[0] == ASN1_APPLICATION(0)) { + /* + * Until success we do everything on the partial + * enc state. + */ + /* its a negTokenTarg packet */ + return srv_enc_spnego_negotiate(ppdata, p_data_size); + } + + if (pdata[0] == ASN1_CONTEXT(1)) { + /* Its a auth packet */ + return srv_enc_spnego_auth(ppdata, p_data_size); + } + + return NT_STATUS_INVALID_PARAMETER; +} + +/****************************************************************************** + Negotiation was successful - turn on server-side encryption. +******************************************************************************/ + +void srv_encryption_start(void) +{ + srv_free_encryption_context(&srv_trans_enc_ctx); + /* Steal the partial pointer. Deliberate shallow copy. */ + srv_trans_enc_ctx = partial_srv_trans_enc_ctx; + srv_trans_enc_ctx->es->enc_on = True; + + partial_srv_trans_enc_ctx = NULL; +} + +/****************************************************************************** + Shutdown all server contexts. +******************************************************************************/ + +void server_encryption_shutdown(void) +{ + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + srv_free_encryption_context(&srv_trans_enc_ctx); +} -- cgit From 492ad718552b77d6de7233b126e834cf11f9316c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Mar 2007 18:11:48 +0000 Subject: r21891: Finish server-side NTLM-SPNEGO negotiation support. Now for the client part, and testing. Jeremy. (This used to be commit 487706701f5f4a92c8fd1da1f29fb44491bac064) --- source3/smbd/seal.c | 108 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 75 insertions(+), 33 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 2dd4fc8b62..0a530526a2 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -118,15 +118,46 @@ NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) ******************************************************************************/ #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) -static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB *psecblob) +static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB secblob) { return NT_STATUS_NOT_SUPPORTED; } #endif +/****************************************************************************** + Do the NTLM SPNEGO encryption negotiation. Parameters are in/out. + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) +{ + NTSTATUS status; + DATA_BLOB chal = data_blob(NULL, 0); + DATA_BLOB response = data_blob(NULL, 0); + struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; + + status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal); + + /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED + * for success ... */ + + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + data_blob_free(&chal); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + /****************************************************************************** Do the SPNEGO encryption negotiation. Parameters are in/out. - Covers the NTLM case. Based off code in smbd/sesssionsetup.c + Based off code in smbd/sesssionsetup.c Until success we do everything on the partial enc ctx. ******************************************************************************/ @@ -135,10 +166,7 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ NTSTATUS status; DATA_BLOB blob = data_blob(NULL,0); DATA_BLOB secblob = data_blob(NULL, 0); - DATA_BLOB chal = data_blob(NULL, 0); - DATA_BLOB response = data_blob(NULL, 0); BOOL got_kerberos_mechanism = False; - struct smb_srv_trans_enc_ctx *ec = NULL; blob = data_blob_const(*ppdata, *p_data_size); @@ -160,47 +188,59 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) { - status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, &secblob); - if (!NT_STATUS_IS_OK(status)) { - data_blob_free(&secblob); - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - } - return status; - } + status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); + } else #endif - - /* Deal with an NTLM enc. setup. */ - ec = partial_srv_trans_enc_ctx; - - status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return nt_status_squash(status); + { + status = srv_enc_spnego_ntlm_negotiate(ppdata, p_data_size, secblob); } - status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal); data_blob_free(&secblob); - /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED - * for success ... */ - - response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); - data_blob_free(&chal); - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; + if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + } return status; } /****************************************************************************** Complete a SPNEGO encryption negotiation. Parameters are in/out. + We only get this for a NTLM auth second stage. ******************************************************************************/ -static NTSTATUS srv_enc_spnego_auth(unsigned char **ppdata, size_t *p_data_size) +static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_size) { - return NT_STATUS_NOT_SUPPORTED; + NTSTATUS status; + DATA_BLOB blob = data_blob(NULL,0); + DATA_BLOB auth = data_blob(NULL,0); + DATA_BLOB auth_reply = data_blob(NULL,0); + DATA_BLOB response = data_blob(NULL,0); + struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; + + /* We must have a partial context here. */ + + if (!ec || ec->auth_ntlmssp_state == NULL) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + blob = data_blob_const(*ppdata, *p_data_size); + if (!spnego_parse_auth(blob, &auth)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); + data_blob_free(&auth); + + response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); + data_blob_free(&auth_reply); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; } /****************************************************************************** @@ -226,7 +266,7 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz if (pdata[0] == ASN1_CONTEXT(1)) { /* Its a auth packet */ - return srv_enc_spnego_auth(ppdata, p_data_size); + return srv_enc_spnego_ntlm_auth(ppdata, p_data_size); } return NT_STATUS_INVALID_PARAMETER; @@ -238,7 +278,9 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz void srv_encryption_start(void) { + /* Throw away the context we're using currently (if any). */ srv_free_encryption_context(&srv_trans_enc_ctx); + /* Steal the partial pointer. Deliberate shallow copy. */ srv_trans_enc_ctx = partial_srv_trans_enc_ctx; srv_trans_enc_ctx->es->enc_on = True; -- cgit From 6b0dcfa62d23980351e852eec05123c0a9823f1d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 20 Mar 2007 22:01:02 +0000 Subject: r21894: Some refactoring of server side encryption context. Support "raw" NTLM auth (no spnego). Jeremy. (This used to be commit 6b5ff7bd591b4f65e2eb767928db50ddf445f09a) --- source3/smbd/seal.c | 163 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 136 insertions(+), 27 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 0a530526a2..9910a84f4c 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -49,7 +49,44 @@ BOOL srv_encryption_on(void) } /****************************************************************************** - Shutdown a server encryption state. + Create an auth_ntlmssp_state and ensure pointer copy is correct. +******************************************************************************/ + +static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) +{ + NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + /* + * We must remember to update the pointer copy for the common + * functions after any auth_ntlmssp_start/auth_ntlmssp_end. + */ + ec->es->ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; + return status; +} + +/****************************************************************************** + Destroy an auth_ntlmssp_state and ensure pointer copy is correct. +******************************************************************************/ + +static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) +{ + /* + * We must remember to update the pointer copy for the common + * functions after any auth_ntlmssp_start/auth_ntlmssp_end. + */ + + if (ec->auth_ntlmssp_state) { + auth_ntlmssp_end(&ec->auth_ntlmssp_state); + /* The auth_ntlmssp_end killed this already. */ + ec->es->ntlmssp_state = NULL; + } +} + +/****************************************************************************** + Shutdown a server encryption context. ******************************************************************************/ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) @@ -61,12 +98,8 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) } if (ec->es) { - struct smb_trans_enc_state *es = ec->es; - if (es->smb_enc_type == SMB_TRANS_ENC_NTLM && - ec->auth_ntlmssp_state) { - auth_ntlmssp_end(&ec->auth_ntlmssp_state); - /* The auth_ntlmssp_end killed this already. */ - es->ntlmssp_state = NULL; + if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { + destroy_auth_ntlmssp(ec); } common_free_encryption_state(&ec->es); } @@ -75,6 +108,36 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) *pp_ec = NULL; } +/****************************************************************************** + Create a server encryption context. +******************************************************************************/ + +static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type) +{ + struct smb_srv_trans_enc_ctx *ec; + + ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); + if (!ec) { + return NULL; + } + ZERO_STRUCTP(partial_srv_trans_enc_ctx); + ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); + if (!ec->es) { + SAFE_FREE(ec); + return NULL; + } + ZERO_STRUCTP(ec->es); + ec->es->smb_enc_type = smb_enc_type; + if (smb_enc_type == SMB_TRANS_ENC_NTLM) { + NTSTATUS status = make_auth_ntlmssp(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return NULL; + } + } + return ec; +} + /****************************************************************************** Free an encryption-allocated buffer. ******************************************************************************/ @@ -125,29 +188,33 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, #endif /****************************************************************************** - Do the NTLM SPNEGO encryption negotiation. Parameters are in/out. + Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out. Until success we do everything on the partial enc ctx. ******************************************************************************/ -static NTSTATUS srv_enc_spnego_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) +static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, BOOL spnego_wrap) { NTSTATUS status; DATA_BLOB chal = data_blob(NULL, 0); DATA_BLOB response = data_blob(NULL, 0); - struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; - status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); + partial_srv_trans_enc_ctx = make_srv_encryption_context(SMB_TRANS_ENC_NTLM); + if (!partial_srv_trans_enc_ctx) { + return NT_STATUS_NO_MEMORY; } - status = auth_ntlmssp_update(ec->auth_ntlmssp_state, secblob, &chal); + status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED * for success ... */ - response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); - data_blob_free(&chal); + if (spnego_wrap) { + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + data_blob_free(&chal); + } else { + /* Return the raw blob. */ + response = chal; + } SAFE_FREE(*ppdata); *ppdata = response.data; @@ -179,20 +246,13 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ srv_free_encryption_context(&partial_srv_trans_enc_ctx); - partial_srv_trans_enc_ctx = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); - if (!partial_srv_trans_enc_ctx) { - data_blob_free(&secblob); - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(partial_srv_trans_enc_ctx); - #if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) { status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); } else #endif { - status = srv_enc_spnego_ntlm_negotiate(ppdata, p_data_size, secblob); + status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, True); } data_blob_free(&secblob); @@ -220,7 +280,7 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_ /* We must have a partial context here. */ - if (!ec || ec->auth_ntlmssp_state == NULL) { + if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { srv_free_encryption_context(&partial_srv_trans_enc_ctx); return NT_STATUS_INVALID_PARAMETER; } @@ -243,6 +303,44 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_ return status; } +/****************************************************************************** + Raw NTLM encryption negotiation. Parameters are in/out. + This function does both steps. +******************************************************************************/ + +static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); + DATA_BLOB response = data_blob(NULL,0); + struct smb_srv_trans_enc_ctx *ec; + + if (!partial_srv_trans_enc_ctx) { + /* This is the initial step. */ + status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, False); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + return status; + } + + ec = partial_srv_trans_enc_ctx; + if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + /* Second step. */ + status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); + + /* Return the raw blob. */ + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + /****************************************************************************** Do the SPNEGO encryption negotiation. Parameters are in/out. ******************************************************************************/ @@ -265,11 +363,22 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz } if (pdata[0] == ASN1_CONTEXT(1)) { - /* Its a auth packet */ + /* It's an auth packet */ return srv_enc_spnego_ntlm_auth(ppdata, p_data_size); } - return NT_STATUS_INVALID_PARAMETER; + /* Maybe it's a raw unwrapped auth ? */ + if (*p_data_size < 7) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { + return srv_enc_raw_ntlm_auth(ppdata, p_data_size); + } + + DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); + + return NT_STATUS_LOGON_FAILURE; } /****************************************************************************** -- cgit From 071db6fdbff694681fa1793ee678a9a0af3e266a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Mar 2007 00:25:08 +0000 Subject: r21897: Add in a basic raw NTLM encrypt request. Now for testing. Jeremy. (This used to be commit 783a7b3085a155d9652cd725bf2960cd272cb554) --- source3/smbd/seal.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 9910a84f4c..8283346c28 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -385,8 +385,36 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz Negotiation was successful - turn on server-side encryption. ******************************************************************************/ -void srv_encryption_start(void) +static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) { + if (!ec || !ec->es) { + return NT_STATUS_LOGON_FAILURE; + } + + if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { + if ((ec->es->ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != + (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { + return NT_STATUS_INVALID_PARAMETER; + } + } + /* Todo - check gssapi case. */ + + return NT_STATUS_OK; +} + +/****************************************************************************** + Negotiation was successful - turn on server-side encryption. +******************************************************************************/ + +NTSTATUS srv_encryption_start(void) +{ + NTSTATUS status; + + /* Check that we are really doing sign+seal. */ + status = check_enc_good(partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } /* Throw away the context we're using currently (if any). */ srv_free_encryption_context(&srv_trans_enc_ctx); @@ -395,6 +423,7 @@ void srv_encryption_start(void) srv_trans_enc_ctx->es->enc_on = True; partial_srv_trans_enc_ctx = NULL; + return NT_STATUS_OK; } /****************************************************************************** -- cgit From ea4dada48f404b1ee0caa7b128ddac9c224fc1f4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Mar 2007 01:04:56 +0000 Subject: r21900: Token exchange now seems to work, now why does the client encrypt fail ? Jeremy. (This used to be commit 6bd7c05290909ef9f5f377dd141a64ed0d654134) --- source3/smbd/seal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 8283346c28..fa47786d51 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -318,7 +318,7 @@ static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_siz if (!partial_srv_trans_enc_ctx) { /* This is the initial step. */ status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, False); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { srv_free_encryption_context(&partial_srv_trans_enc_ctx); return nt_status_squash(status); } -- cgit From 4a965110e5cebcb7395bc71de2ee5d222000c524 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 21 Mar 2007 14:13:42 +0000 Subject: r21904: Fix HP build -- thanks, Don (This used to be commit 57efba97b634728ae75901cb76b904a5d82986a4) --- source3/smbd/seal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index fa47786d51..64965d4272 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -145,7 +145,7 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ void srv_free_enc_buffer(char *buf) { if (srv_trans_enc_ctx) { - return common_free_enc_buffer(srv_trans_enc_ctx->es, buf); + common_free_enc_buffer(srv_trans_enc_ctx->es, buf); } } -- cgit From 42238c78bb8820a21cfb08fc29a5109ee1a62bab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 21 Mar 2007 19:15:14 +0000 Subject: r21917: Start to do the gss versions of sign+seal. Jeremy. (This used to be commit a226645353a40047b72de1b96c3a7676a2bf1034) --- source3/smbd/seal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 64965d4272..9fa35601f8 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -180,8 +180,8 @@ NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) Until success we do everything on the partial enc ctx. ******************************************************************************/ -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) -static NTSTATUS srv_enc_spnego_gss_negotiate(char **ppdata, size_t *p_data_size, DATA_BLOB secblob) +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) +static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) { return NT_STATUS_NOT_SUPPORTED; } @@ -246,8 +246,8 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ srv_free_encryption_context(&partial_srv_trans_enc_ctx); -#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) - if (got_kerberos_mechanism && lp_use_kerberos_keytab()) ) { +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); } else #endif -- cgit From 23149b3bb8257eeb1aeb15f165099bf3447ee05b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Mar 2007 01:14:55 +0000 Subject: r21925: Start to code up the gss acquire creds calls. Jeremy. (This used to be commit 4a7fbc88520e8f5dfe53a7c5da68040271149da3) --- source3/smbd/seal.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 9fa35601f8..e3c8b4f029 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -98,8 +98,14 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) } if (ec->es) { - if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { - destroy_auth_ntlmssp(ec); + switch (ec->es->smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + destroy_auth_ntlmssp(ec); + break; +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + break; +#endif } common_free_encryption_state(&ec->es); } @@ -128,12 +134,25 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ } ZERO_STRUCTP(ec->es); ec->es->smb_enc_type = smb_enc_type; - if (smb_enc_type == SMB_TRANS_ENC_NTLM) { - NTSTATUS status = make_auth_ntlmssp(ec); - if (!NT_STATUS_IS_OK(status)) { + switch (smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + { + NTSTATUS status = make_auth_ntlmssp(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return NULL; + } + } + break; + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + /* Acquire our credentials by calling gss_acquire_cred here. */ + break; +#endif + default: srv_free_encryption_context(&ec); return NULL; - } } return ec; } @@ -183,6 +202,13 @@ NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) { + if (!partial_srv_trans_enc_ctx) { + partial_srv_trans_enc_ctx = make_srv_encryption_context(SMB_TRANS_ENC_GSS); + if (!partial_srv_trans_enc_ctx) { + return NT_STATUS_NO_MEMORY; + } + } + return NT_STATUS_NOT_SUPPORTED; } #endif -- cgit From f93d75c932e7a48da8bcd589d7505bf5445b89df Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Mar 2007 02:24:12 +0000 Subject: r21926: Fix missing enum specifier pointed out by Don McCall @ HP. Thanks Don ! Jeremy. (This used to be commit 662344d1ec3593689de7602afa518ed98e10dc37) --- source3/smbd/seal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index e3c8b4f029..f95a982f60 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -63,7 +63,7 @@ static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) * We must remember to update the pointer copy for the common * functions after any auth_ntlmssp_start/auth_ntlmssp_end. */ - ec->es->ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; + ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; return status; } @@ -81,7 +81,7 @@ static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) if (ec->auth_ntlmssp_state) { auth_ntlmssp_end(&ec->auth_ntlmssp_state); /* The auth_ntlmssp_end killed this already. */ - ec->es->ntlmssp_state = NULL; + ec->es->s.ntlmssp_state = NULL; } } @@ -418,7 +418,7 @@ static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) } if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { - if ((ec->es->ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != + if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { return NT_STATUS_INVALID_PARAMETER; } -- cgit From 8b63654c2e63448cc21505d7996e1a4805e391df Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Mar 2007 00:50:53 +0000 Subject: r21969: Start working on the gss-side of the server negotiation. Jeremy. (This used to be commit fbc569b530104679e47fe743963eb0c4384de6ae) --- source3/smbd/seal.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index f95a982f60..fbb0eade52 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -85,6 +85,85 @@ static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) } } +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + +/****************************************************************************** + Import a name. +******************************************************************************/ + +static NTSTATUS get_gss_creds(const char *service, + const char *name, + gss_cred_usage_t cred_type, + gss_cred_id_t *p_srv_cred) +{ + OM_uint32 ret; + OM_uint32 min; + gss_name_t srv_name; + gss_buffer_desc input_name; + char *host_princ_s = NULL; + NTSTATUS status = NT_STATUS_OK; + + asprintf(&host_princ_s, "%s@%s", service, name); + if (host_princ_s == NULL) { + return NT_STATUS_NO_MEMORY; + } + + input_name.value = host_princ_s; + input_name.length = strlen(host_princ_s) + 1; + + ret = gss_import_name(&min, + &input_name, + GSS_C_NT_HOSTBASED_SERVICE, + &srv_name); + + if (ret != GSS_S_COMPLETE) { + SAFE_FREE(host_princ_s); + return map_nt_error_from_gss(ret, min); + } + + ret = gss_acquire_cred(&min, + &srv_name, + GSS_C_INDEFINITE, + GSS_C_NULL_OID_SET, + cred_type, + p_srv_cred, + NULL, + NULL); + + if (ret != GSS_S_COMPLETE) { + status = map_nt_error_from_gss(ret, min); + } + + SAFE_FREE(host_princ_s); + gss_release_name(&min, &srv_name); + return status; +} + +/****************************************************************************** + Create a gss state. +******************************************************************************/ + +static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) +{ + NTSTATUS status; + gss_cred_id_t srv_cred; + fstring fqdn; + + name_to_fqdn(fqdn, global_myname()); + strlower_m(fqdn); + + status = get_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); + if (!NT_STATUS_IS_OK(status)) { + status = get_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + } + + return NT_STATUS_OK; +} +#endif + /****************************************************************************** Shutdown a server encryption context. ******************************************************************************/ @@ -148,6 +227,13 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) case SMB_TRANS_ENC_GSS: /* Acquire our credentials by calling gss_acquire_cred here. */ + { + NTSTATUS status = make_auth_gss(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return NULL; + } + } break; #endif default: -- cgit From 4a66d0e232271968ba96da50274428916a393975 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Mar 2007 21:13:31 +0000 Subject: r21991: I hate Steve French :-). Add support for encryption contexts.... Jeremy. (This used to be commit ae8f3649f773b8a8dcb55921536d038d3475322e) --- source3/smbd/seal.c | 96 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 15 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index fbb0eade52..d5b956c53d 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -249,6 +249,14 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ void srv_free_enc_buffer(char *buf) { + /* We know this is an smb buffer, and we + * didn't malloc, only copy, for a keepalive, + * so ignore session keepalives. */ + + if(CVAL(buf,0) == SMBkeepalive) { + return; + } + if (srv_trans_enc_ctx) { common_free_enc_buffer(srv_trans_enc_ctx->es, buf); } @@ -260,9 +268,15 @@ void srv_free_enc_buffer(char *buf) NTSTATUS srv_decrypt_buffer(char *buf) { + /* Ignore session keepalives. */ + if(CVAL(buf,0) == SMBkeepalive) { + return NT_STATUS_OK; + } + if (srv_trans_enc_ctx) { return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); } + return NT_STATUS_OK; } @@ -270,13 +284,19 @@ NTSTATUS srv_decrypt_buffer(char *buf) Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. ******************************************************************************/ -NTSTATUS srv_encrypt_buffer(char *buffer, char **buf_out) +NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) { + *buf_out = buf; + + /* Ignore session keepalives. */ + if(CVAL(buf,0) == SMBkeepalive) { + return NT_STATUS_OK; + } + if (srv_trans_enc_ctx) { - return common_encrypt_buffer(srv_trans_enc_ctx->es, buffer, buf_out); + return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out); } /* Not encrypting. */ - *buf_out = buffer; return NT_STATUS_OK; } @@ -340,7 +360,11 @@ static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_si Until success we do everything on the partial enc ctx. ******************************************************************************/ -static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_size) +static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) { NTSTATUS status; DATA_BLOB blob = data_blob(NULL,0); @@ -371,6 +395,17 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + *pparam = SMB_MALLOC(2); + if (!*pparam) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); + *p_param_size = 2; } return status; @@ -381,7 +416,11 @@ static NTSTATUS srv_enc_spnego_negotiate(unsigned char **ppdata, size_t *p_data_ We only get this for a NTLM auth second stage. ******************************************************************************/ -static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_size) +static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) { NTSTATUS status; DATA_BLOB blob = data_blob(NULL,0); @@ -409,6 +448,16 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_ response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); data_blob_free(&auth_reply); + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + *pparam = SMB_MALLOC(2); + if (!*pparam) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,ec->es->enc_ctx_num); + *p_param_size = 2; + } + SAFE_FREE(*ppdata); *ppdata = response.data; *p_data_size = response.length; @@ -420,7 +469,11 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(unsigned char **ppdata, size_t *p_data_ This function does both steps. ******************************************************************************/ -static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_size) +static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) { NTSTATUS status; DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); @@ -446,6 +499,16 @@ static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_siz /* Second step. */ status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + *pparam = SMB_MALLOC(2); + if (!*pparam) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,ec->es->enc_ctx_num); + *p_param_size = 2; + } + /* Return the raw blob. */ SAFE_FREE(*ppdata); *ppdata = response.data; @@ -457,26 +520,29 @@ static NTSTATUS srv_enc_raw_ntlm_auth(unsigned char **ppdata, size_t *p_data_siz Do the SPNEGO encryption negotiation. Parameters are in/out. ******************************************************************************/ -NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_size) +NTSTATUS srv_request_encryption_setup(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) { unsigned char *pdata = *ppdata; + SAFE_FREE(*pparam); + *p_param_size = 0; + if (*p_data_size < 1) { return NT_STATUS_INVALID_PARAMETER; } if (pdata[0] == ASN1_APPLICATION(0)) { - /* - * Until success we do everything on the partial - * enc state. - */ /* its a negTokenTarg packet */ - return srv_enc_spnego_negotiate(ppdata, p_data_size); + return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size); } if (pdata[0] == ASN1_CONTEXT(1)) { /* It's an auth packet */ - return srv_enc_spnego_ntlm_auth(ppdata, p_data_size); + return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); } /* Maybe it's a raw unwrapped auth ? */ @@ -485,7 +551,7 @@ NTSTATUS srv_request_encryption_setup(unsigned char **ppdata, size_t *p_data_siz } if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { - return srv_enc_raw_ntlm_auth(ppdata, p_data_size); + return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); } DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); @@ -518,7 +584,7 @@ static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) Negotiation was successful - turn on server-side encryption. ******************************************************************************/ -NTSTATUS srv_encryption_start(void) +NTSTATUS srv_encryption_start(connection_struct *conn) { NTSTATUS status; -- cgit From e9157961d6c89318de4c7ff5a700aed640d91d92 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Mar 2007 01:11:27 +0000 Subject: r21997: Implement the server side of gss seal negotiate. Jeremy. (This used to be commit 6b923acfee59e39eea69e9e9a00f1f6118ed4270) --- source3/smbd/seal.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 15 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index d5b956c53d..0a093d21ab 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -97,7 +97,7 @@ static NTSTATUS get_gss_creds(const char *service, gss_cred_id_t *p_srv_cred) { OM_uint32 ret; - OM_uint32 min; + OM_uint32 min; gss_name_t srv_name; gss_buffer_desc input_name; char *host_princ_s = NULL; @@ -141,6 +141,8 @@ static NTSTATUS get_gss_creds(const char *service, /****************************************************************************** Create a gss state. + Try and get the cifs/server@realm principal first, then fall back to + host/server@realm. ******************************************************************************/ static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) @@ -160,6 +162,18 @@ static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) } } + ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss); + if (!ec->es->s.gss_state) { + OM_uint32 min; + gss_release_cred(&min, &srv_cred); + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(ec->es->s.gss_state); + ec->es->s.gss_state->creds = srv_cred; + + /* No context yet. */ + ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT; + return NT_STATUS_OK; } #endif @@ -197,19 +211,21 @@ static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) Create a server encryption context. ******************************************************************************/ -static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type) +static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec) { struct smb_srv_trans_enc_ctx *ec; + *pp_ec = NULL; + ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); if (!ec) { - return NULL; + return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(partial_srv_trans_enc_ctx); ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); if (!ec->es) { SAFE_FREE(ec); - return NULL; + return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(ec->es); ec->es->smb_enc_type = smb_enc_type; @@ -219,7 +235,7 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ NTSTATUS status = make_auth_ntlmssp(ec); if (!NT_STATUS_IS_OK(status)) { srv_free_encryption_context(&ec); - return NULL; + return status; } } break; @@ -231,16 +247,17 @@ static struct smb_srv_trans_enc_ctx *make_srv_encryption_context(enum smb_trans_ NTSTATUS status = make_auth_gss(ec); if (!NT_STATUS_IS_OK(status)) { srv_free_encryption_context(&ec); - return NULL; + return status; } } break; #endif default: srv_free_encryption_context(&ec); - return NULL; + return NT_STATUS_INVALID_PARAMETER; } - return ec; + *pp_ec = ec; + return NT_STATUS_OK; } /****************************************************************************** @@ -308,14 +325,68 @@ NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) { + OM_uint32 ret; + OM_uint32 min; + OM_uint32 flags = 0; + gss_buffer_desc in_buf, out_buf; + struct smb_tran_enc_state_gss *gss_state; + if (!partial_srv_trans_enc_ctx) { - partial_srv_trans_enc_ctx = make_srv_encryption_context(SMB_TRANS_ENC_GSS); - if (!partial_srv_trans_enc_ctx) { - return NT_STATUS_NO_MEMORY; + NTSTATUS status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + gss_state = partial_srv_trans_enc_ctx->es->s.gss_state; + + in_buf.value = secblob.data; + in_buf.length = secblob.length; + + out_buf.value = NULL; + out_buf.length = 0; + + ret = gss_accept_sec_context(&min, + &gss_state->gss_ctx, + gss_state->creds, + &in_buf, + GSS_C_NO_CHANNEL_BINDINGS, + NULL, + NULL, /* Ignore oids. */ + &out_buf, /* To return. */ + &flags, + NULL, /* Ingore time. */ + NULL); /* Ignore delegated creds. */ + + if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { + return gss_err_to_ntstatus(ret, min); + } + + /* Ensure we've got sign+seal available. */ + if (ret == GSS_S_COMPLETE) { + if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) != + (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) { + DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough " + "for SMB sealing.\n")); + gss_release_buffer(&min, &out_buf); + return NT_STATUS_ACCESS_DENIED; } } - return NT_STATUS_NOT_SUPPORTED; + SAFE_FREE(*ppdata); + *ppdata = memdup(out_buf.value, out_buf.length); + if (!*ppdata) { + gss_release_buffer(&min, &out_buf); + return NT_STATUS_NO_MEMORY; + } + *p_data_size = out_buf.length; + gss_release_buffer(&min, &out_buf); + + if (ret != GSS_S_CONTINUE_NEEDED) { + return NT_STATUS_MORE_PROCESSING_REQUIRED; + } else { + return NT_STATUS_OK; + } } #endif @@ -330,9 +401,9 @@ static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_si DATA_BLOB chal = data_blob(NULL, 0); DATA_BLOB response = data_blob(NULL, 0); - partial_srv_trans_enc_ctx = make_srv_encryption_context(SMB_TRANS_ENC_NTLM); - if (!partial_srv_trans_enc_ctx) { - return NT_STATUS_NO_MEMORY; + status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; } status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); -- cgit From b0bcb483697249123f92f5ac477c98b579135887 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Mar 2007 22:19:51 +0000 Subject: r22013: Move to SSPI framing (sig first in NTLM). Jeremy (This used to be commit 22eaed76f01ea9d0184dcaf57adca23abc6330b9) --- source3/smbd/seal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 0a093d21ab..66ae8419d4 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -91,7 +91,7 @@ static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) Import a name. ******************************************************************************/ -static NTSTATUS get_gss_creds(const char *service, +static NTSTATUS get_srv_gss_creds(const char *service, const char *name, gss_cred_usage_t cred_type, gss_cred_id_t *p_srv_cred) @@ -154,9 +154,9 @@ static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) name_to_fqdn(fqdn, global_myname()); strlower_m(fqdn); - status = get_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); + status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); if (!NT_STATUS_IS_OK(status)) { - status = get_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); + status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); if (!NT_STATUS_IS_OK(status)) { return nt_status_squash(status); } -- cgit From 3678d69b82a109218211d6abc89cef9c460d3b45 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Apr 2007 12:00:08 +0000 Subject: r22262: fix the build on systems without GSS_C_NT_HOSTBASED_SERVICE metze (This used to be commit 402704b62972c223f3e70bcd6221dc7c3a64f4b9) --- source3/smbd/seal.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 66ae8419d4..259aff014a 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -103,6 +103,9 @@ static NTSTATUS get_srv_gss_creds(const char *service, char *host_princ_s = NULL; NTSTATUS status = NT_STATUS_OK; + gss_OID_desc nt_hostbased_service = + {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; + asprintf(&host_princ_s, "%s@%s", service, name); if (host_princ_s == NULL) { return NT_STATUS_NO_MEMORY; @@ -113,7 +116,7 @@ static NTSTATUS get_srv_gss_creds(const char *service, ret = gss_import_name(&min, &input_name, - GSS_C_NT_HOSTBASED_SERVICE, + &nt_hostbased_service, &srv_name); if (ret != GSS_S_COMPLETE) { -- cgit From 9812a7e32e515315302d3040a4145592640de7f7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Apr 2007 00:34:10 +0000 Subject: r22327: Finish the gss-spnego part of the seal code. Now for testing.... Jeremy. (This used to be commit 1c1f5360b67792f14b50835a2c5a4d4ac68aca8f) --- source3/smbd/seal.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 259aff014a..c6fab5f078 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -333,9 +333,12 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d OM_uint32 flags = 0; gss_buffer_desc in_buf, out_buf; struct smb_tran_enc_state_gss *gss_state; + DATA_BLOB auth_reply = data_blob(NULL,0); + DATA_BLOB response = data_blob(NULL,0); + NTSTATUS status; if (!partial_srv_trans_enc_ctx) { - NTSTATUS status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); + status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -361,8 +364,9 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d NULL, /* Ingore time. */ NULL); /* Ignore delegated creds. */ + status = gss_err_to_ntstatus(ret, min); if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { - return gss_err_to_ntstatus(ret, min); + return status; } /* Ensure we've got sign+seal available. */ @@ -376,20 +380,18 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d } } - SAFE_FREE(*ppdata); - *ppdata = memdup(out_buf.value, out_buf.length); - if (!*ppdata) { - gss_release_buffer(&min, &out_buf); - return NT_STATUS_NO_MEMORY; - } - *p_data_size = out_buf.length; + auth_reply = data_blob(out_buf.value, out_buf.length); gss_release_buffer(&min, &out_buf); - if (ret != GSS_S_CONTINUE_NEEDED) { - return NT_STATUS_MORE_PROCESSING_REQUIRED; - } else { - return NT_STATUS_OK; - } + /* Wrap in SPNEGO. */ + response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5); + data_blob_free(&auth_reply); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + + return status; } #endif -- cgit From 1adbf4af06a71ffea493a3a3750d163f85f62c7f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 00:35:18 +0000 Subject: r22350: Add some helpful debug messages. Jeremy. (This used to be commit bf2e6bd82dc0d35313677c6cb04357da1e74ce4f) --- source3/smbd/seal.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index c6fab5f078..c0682a8201 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -119,13 +119,16 @@ static NTSTATUS get_srv_gss_creds(const char *service, &nt_hostbased_service, &srv_name); + DEBUG(10,("get_srv_gss_creds: imported name %s\n", + host_princ_s )); + if (ret != GSS_S_COMPLETE) { SAFE_FREE(host_princ_s); return map_nt_error_from_gss(ret, min); } ret = gss_acquire_cred(&min, - &srv_name, + srv_name, GSS_C_INDEFINITE, GSS_C_NULL_OID_SET, cred_type, @@ -134,6 +137,9 @@ static NTSTATUS get_srv_gss_creds(const char *service, NULL); if (ret != GSS_S_COMPLETE) { + ADS_STATUS adss = ADS_ERROR_GSS(ret, min); + DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n", + ads_errstr(adss))); status = map_nt_error_from_gss(ret, min); } -- cgit From 226d96337fdb53f402569c12c6fd5b6a07123eb4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 00:40:08 +0000 Subject: r22351: Making progress in tests... Jeremy. (This used to be commit f1726e04eb1d63387cf955c907fe077b2201a3ae) --- source3/smbd/seal.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index c0682a8201..7dd6e3d7bb 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -127,6 +127,12 @@ static NTSTATUS get_srv_gss_creds(const char *service, return map_nt_error_from_gss(ret, min); } + /* + * We're accessing the krb5.keytab file here. + * ensure we have permissions to do so. + */ + become_root(); + ret = gss_acquire_cred(&min, srv_name, GSS_C_INDEFINITE, @@ -135,6 +141,7 @@ static NTSTATUS get_srv_gss_creds(const char *service, p_srv_cred, NULL, NULL); + unbecome_root(); if (ret != GSS_S_COMPLETE) { ADS_STATUS adss = ADS_ERROR_GSS(ret, min); -- cgit From d47868cb5e7db5b75848473b90ff2984c3162f8d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 00:44:39 +0000 Subject: r22352: Wow - working gss SMB sealing ! Jeremy. (This used to be commit abcb2a4b0709ef84c50c1d9a85191dc3866cd138) --- source3/smbd/seal.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 7dd6e3d7bb..07ef186e2e 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -365,6 +365,8 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d out_buf.value = NULL; out_buf.length = 0; + become_root(); + ret = gss_accept_sec_context(&min, &gss_state->gss_ctx, gss_state->creds, @@ -376,6 +378,7 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d &flags, NULL, /* Ingore time. */ NULL); /* Ignore delegated creds. */ + unbecome_root(); status = gss_err_to_ntstatus(ret, min); if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { -- cgit From 71921605995fa95d84301534760a6bc2db3fa74b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 May 2007 15:07:49 +0000 Subject: r22747: Fix some C++ warnings (This used to be commit a66a04e9f11f6c4462f2b56b447bae4eca7b177c) --- source3/smbd/seal.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 07ef186e2e..c4d60b0a60 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -492,8 +492,7 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* Return the context we're using for this encryption state. */ - *pparam = SMB_MALLOC(2); - if (!*pparam) { + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { return NT_STATUS_NO_MEMORY; } SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); @@ -542,8 +541,7 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* Return the context we're using for this encryption state. */ - *pparam = SMB_MALLOC(2); - if (!*pparam) { + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { return NT_STATUS_NO_MEMORY; } SSVAL(*pparam,0,ec->es->enc_ctx_num); @@ -593,8 +591,7 @@ static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, if (NT_STATUS_IS_OK(status)) { /* Return the context we're using for this encryption state. */ - *pparam = SMB_MALLOC(2); - if (!*pparam) { + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { return NT_STATUS_NO_MEMORY; } SSVAL(*pparam,0,ec->es->enc_ctx_num); -- cgit From b4a7b7a8889737e2891fc1176feabd4ce47f2737 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 14 May 2007 12:16:20 +0000 Subject: r22844: Introduce const DATA_BLOB data_blob_null = { NULL, 0, NULL }; and replace all data_blob(NULL, 0) calls. (This used to be commit 3d3d61687ef00181f4f04e001d42181d93ac931e) --- source3/smbd/seal.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index c4d60b0a60..5d8ef9b63c 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -346,8 +346,8 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d OM_uint32 flags = 0; gss_buffer_desc in_buf, out_buf; struct smb_tran_enc_state_gss *gss_state; - DATA_BLOB auth_reply = data_blob(NULL,0); - DATA_BLOB response = data_blob(NULL,0); + DATA_BLOB auth_reply = data_blob_null; + DATA_BLOB response = data_blob_null; NTSTATUS status; if (!partial_srv_trans_enc_ctx) { @@ -419,8 +419,8 @@ static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_d static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, BOOL spnego_wrap) { NTSTATUS status; - DATA_BLOB chal = data_blob(NULL, 0); - DATA_BLOB response = data_blob(NULL, 0); + DATA_BLOB chal = data_blob_null; + DATA_BLOB response = data_blob_null; status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); if (!NT_STATUS_IS_OK(status)) { @@ -459,8 +459,8 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, size_t *p_param_size) { NTSTATUS status; - DATA_BLOB blob = data_blob(NULL,0); - DATA_BLOB secblob = data_blob(NULL, 0); + DATA_BLOB blob = data_blob_null; + DATA_BLOB secblob = data_blob_null; BOOL got_kerberos_mechanism = False; blob = data_blob_const(*ppdata, *p_data_size); @@ -514,10 +514,10 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, size_t *p_param_size) { NTSTATUS status; - DATA_BLOB blob = data_blob(NULL,0); - DATA_BLOB auth = data_blob(NULL,0); - DATA_BLOB auth_reply = data_blob(NULL,0); - DATA_BLOB response = data_blob(NULL,0); + DATA_BLOB blob = data_blob_null; + DATA_BLOB auth = data_blob_null; + DATA_BLOB auth_reply = data_blob_null; + DATA_BLOB response = data_blob_null; struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; /* We must have a partial context here. */ @@ -567,7 +567,7 @@ static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, { NTSTATUS status; DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); - DATA_BLOB response = data_blob(NULL,0); + DATA_BLOB response = data_blob_null; struct smb_srv_trans_enc_ctx *ec; if (!partial_srv_trans_enc_ctx) { -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/seal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 5d8ef9b63c..b816af1e00 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -5,7 +5,7 @@ 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 + 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, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/seal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index b816af1e00..0276e34002 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -14,8 +14,7 @@ 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. + along with this program. If not, see . */ #include "includes.h" -- cgit From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/smbd/seal.c | 703 ---------------------------------------------------- 1 file changed, 703 deletions(-) delete mode 100644 source3/smbd/seal.c (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c deleted file mode 100644 index 0276e34002..0000000000 --- a/source3/smbd/seal.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB Transport encryption (sealing) code - server code. - Copyright (C) Jeremy Allison 2007. - - 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 . -*/ - -#include "includes.h" - -/****************************************************************************** - Server side encryption. -******************************************************************************/ - -/****************************************************************************** - Global server state. -******************************************************************************/ - -struct smb_srv_trans_enc_ctx { - struct smb_trans_enc_state *es; - AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */ -}; - -static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx; -static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx; - -/****************************************************************************** - Is server encryption on ? -******************************************************************************/ - -BOOL srv_encryption_on(void) -{ - if (srv_trans_enc_ctx) { - return common_encryption_on(srv_trans_enc_ctx->es); - } - return False; -} - -/****************************************************************************** - Create an auth_ntlmssp_state and ensure pointer copy is correct. -******************************************************************************/ - -static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) -{ - NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); - } - - /* - * We must remember to update the pointer copy for the common - * functions after any auth_ntlmssp_start/auth_ntlmssp_end. - */ - ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; - return status; -} - -/****************************************************************************** - Destroy an auth_ntlmssp_state and ensure pointer copy is correct. -******************************************************************************/ - -static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) -{ - /* - * We must remember to update the pointer copy for the common - * functions after any auth_ntlmssp_start/auth_ntlmssp_end. - */ - - if (ec->auth_ntlmssp_state) { - auth_ntlmssp_end(&ec->auth_ntlmssp_state); - /* The auth_ntlmssp_end killed this already. */ - ec->es->s.ntlmssp_state = NULL; - } -} - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - -/****************************************************************************** - Import a name. -******************************************************************************/ - -static NTSTATUS get_srv_gss_creds(const char *service, - const char *name, - gss_cred_usage_t cred_type, - gss_cred_id_t *p_srv_cred) -{ - OM_uint32 ret; - OM_uint32 min; - gss_name_t srv_name; - gss_buffer_desc input_name; - char *host_princ_s = NULL; - NTSTATUS status = NT_STATUS_OK; - - gss_OID_desc nt_hostbased_service = - {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; - - asprintf(&host_princ_s, "%s@%s", service, name); - if (host_princ_s == NULL) { - return NT_STATUS_NO_MEMORY; - } - - input_name.value = host_princ_s; - input_name.length = strlen(host_princ_s) + 1; - - ret = gss_import_name(&min, - &input_name, - &nt_hostbased_service, - &srv_name); - - DEBUG(10,("get_srv_gss_creds: imported name %s\n", - host_princ_s )); - - if (ret != GSS_S_COMPLETE) { - SAFE_FREE(host_princ_s); - return map_nt_error_from_gss(ret, min); - } - - /* - * We're accessing the krb5.keytab file here. - * ensure we have permissions to do so. - */ - become_root(); - - ret = gss_acquire_cred(&min, - srv_name, - GSS_C_INDEFINITE, - GSS_C_NULL_OID_SET, - cred_type, - p_srv_cred, - NULL, - NULL); - unbecome_root(); - - if (ret != GSS_S_COMPLETE) { - ADS_STATUS adss = ADS_ERROR_GSS(ret, min); - DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n", - ads_errstr(adss))); - status = map_nt_error_from_gss(ret, min); - } - - SAFE_FREE(host_princ_s); - gss_release_name(&min, &srv_name); - return status; -} - -/****************************************************************************** - Create a gss state. - Try and get the cifs/server@realm principal first, then fall back to - host/server@realm. -******************************************************************************/ - -static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) -{ - NTSTATUS status; - gss_cred_id_t srv_cred; - fstring fqdn; - - name_to_fqdn(fqdn, global_myname()); - strlower_m(fqdn); - - status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); - if (!NT_STATUS_IS_OK(status)) { - status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); - } - } - - ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss); - if (!ec->es->s.gss_state) { - OM_uint32 min; - gss_release_cred(&min, &srv_cred); - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(ec->es->s.gss_state); - ec->es->s.gss_state->creds = srv_cred; - - /* No context yet. */ - ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT; - - return NT_STATUS_OK; -} -#endif - -/****************************************************************************** - Shutdown a server encryption context. -******************************************************************************/ - -static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) -{ - struct smb_srv_trans_enc_ctx *ec = *pp_ec; - - if (!ec) { - return; - } - - if (ec->es) { - switch (ec->es->smb_enc_type) { - case SMB_TRANS_ENC_NTLM: - destroy_auth_ntlmssp(ec); - break; -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - case SMB_TRANS_ENC_GSS: - break; -#endif - } - common_free_encryption_state(&ec->es); - } - - SAFE_FREE(ec); - *pp_ec = NULL; -} - -/****************************************************************************** - Create a server encryption context. -******************************************************************************/ - -static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec) -{ - struct smb_srv_trans_enc_ctx *ec; - - *pp_ec = NULL; - - ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); - if (!ec) { - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(partial_srv_trans_enc_ctx); - ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); - if (!ec->es) { - SAFE_FREE(ec); - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(ec->es); - ec->es->smb_enc_type = smb_enc_type; - switch (smb_enc_type) { - case SMB_TRANS_ENC_NTLM: - { - NTSTATUS status = make_auth_ntlmssp(ec); - if (!NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&ec); - return status; - } - } - break; - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - case SMB_TRANS_ENC_GSS: - /* Acquire our credentials by calling gss_acquire_cred here. */ - { - NTSTATUS status = make_auth_gss(ec); - if (!NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&ec); - return status; - } - } - break; -#endif - default: - srv_free_encryption_context(&ec); - return NT_STATUS_INVALID_PARAMETER; - } - *pp_ec = ec; - return NT_STATUS_OK; -} - -/****************************************************************************** - Free an encryption-allocated buffer. -******************************************************************************/ - -void srv_free_enc_buffer(char *buf) -{ - /* We know this is an smb buffer, and we - * didn't malloc, only copy, for a keepalive, - * so ignore session keepalives. */ - - if(CVAL(buf,0) == SMBkeepalive) { - return; - } - - if (srv_trans_enc_ctx) { - common_free_enc_buffer(srv_trans_enc_ctx->es, buf); - } -} - -/****************************************************************************** - Decrypt an incoming buffer. -******************************************************************************/ - -NTSTATUS srv_decrypt_buffer(char *buf) -{ - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { - return NT_STATUS_OK; - } - - if (srv_trans_enc_ctx) { - return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); - } - - return NT_STATUS_OK; -} - -/****************************************************************************** - Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. -******************************************************************************/ - -NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) -{ - *buf_out = buf; - - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { - return NT_STATUS_OK; - } - - if (srv_trans_enc_ctx) { - return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out); - } - /* Not encrypting. */ - return NT_STATUS_OK; -} - -/****************************************************************************** - Do the gss encryption negotiation. Parameters are in/out. - Until success we do everything on the partial enc ctx. -******************************************************************************/ - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) -static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) -{ - OM_uint32 ret; - OM_uint32 min; - OM_uint32 flags = 0; - gss_buffer_desc in_buf, out_buf; - struct smb_tran_enc_state_gss *gss_state; - DATA_BLOB auth_reply = data_blob_null; - DATA_BLOB response = data_blob_null; - NTSTATUS status; - - if (!partial_srv_trans_enc_ctx) { - status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - } - - gss_state = partial_srv_trans_enc_ctx->es->s.gss_state; - - in_buf.value = secblob.data; - in_buf.length = secblob.length; - - out_buf.value = NULL; - out_buf.length = 0; - - become_root(); - - ret = gss_accept_sec_context(&min, - &gss_state->gss_ctx, - gss_state->creds, - &in_buf, - GSS_C_NO_CHANNEL_BINDINGS, - NULL, - NULL, /* Ignore oids. */ - &out_buf, /* To return. */ - &flags, - NULL, /* Ingore time. */ - NULL); /* Ignore delegated creds. */ - unbecome_root(); - - status = gss_err_to_ntstatus(ret, min); - if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { - return status; - } - - /* Ensure we've got sign+seal available. */ - if (ret == GSS_S_COMPLETE) { - if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) != - (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) { - DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough " - "for SMB sealing.\n")); - gss_release_buffer(&min, &out_buf); - return NT_STATUS_ACCESS_DENIED; - } - } - - auth_reply = data_blob(out_buf.value, out_buf.length); - gss_release_buffer(&min, &out_buf); - - /* Wrap in SPNEGO. */ - response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5); - data_blob_free(&auth_reply); - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - - return status; -} -#endif - -/****************************************************************************** - Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out. - Until success we do everything on the partial enc ctx. -******************************************************************************/ - -static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, BOOL spnego_wrap) -{ - NTSTATUS status; - DATA_BLOB chal = data_blob_null; - DATA_BLOB response = data_blob_null; - - status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); - - /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED - * for success ... */ - - if (spnego_wrap) { - response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); - data_blob_free(&chal); - } else { - /* Return the raw blob. */ - response = chal; - } - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - return status; -} - -/****************************************************************************** - Do the SPNEGO encryption negotiation. Parameters are in/out. - Based off code in smbd/sesssionsetup.c - Until success we do everything on the partial enc ctx. -******************************************************************************/ - -static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_null; - DATA_BLOB secblob = data_blob_null; - BOOL got_kerberos_mechanism = False; - - blob = data_blob_const(*ppdata, *p_data_size); - - status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism); - if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); - } - - /* We should have no partial context at this point. */ - - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { - status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); - } else -#endif - { - status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, True); - } - - data_blob_free(&secblob); - - if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return nt_status_squash(status); - } - - if (NT_STATUS_IS_OK(status)) { - /* Return the context we're using for this encryption state. */ - if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { - return NT_STATUS_NO_MEMORY; - } - SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); - *p_param_size = 2; - } - - return status; -} - -/****************************************************************************** - Complete a SPNEGO encryption negotiation. Parameters are in/out. - We only get this for a NTLM auth second stage. -******************************************************************************/ - -static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_null; - DATA_BLOB auth = data_blob_null; - DATA_BLOB auth_reply = data_blob_null; - DATA_BLOB response = data_blob_null; - struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; - - /* We must have a partial context here. */ - - if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - blob = data_blob_const(*ppdata, *p_data_size); - if (!spnego_parse_auth(blob, &auth)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); - data_blob_free(&auth); - - response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); - data_blob_free(&auth_reply); - - if (NT_STATUS_IS_OK(status)) { - /* Return the context we're using for this encryption state. */ - if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { - return NT_STATUS_NO_MEMORY; - } - SSVAL(*pparam,0,ec->es->enc_ctx_num); - *p_param_size = 2; - } - - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - return status; -} - -/****************************************************************************** - Raw NTLM encryption negotiation. Parameters are in/out. - This function does both steps. -******************************************************************************/ - -static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); - DATA_BLOB response = data_blob_null; - struct smb_srv_trans_enc_ctx *ec; - - if (!partial_srv_trans_enc_ctx) { - /* This is the initial step. */ - status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, False); - if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return nt_status_squash(status); - } - return status; - } - - ec = partial_srv_trans_enc_ctx; - if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - return NT_STATUS_INVALID_PARAMETER; - } - - /* Second step. */ - status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); - - if (NT_STATUS_IS_OK(status)) { - /* Return the context we're using for this encryption state. */ - if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { - return NT_STATUS_NO_MEMORY; - } - SSVAL(*pparam,0,ec->es->enc_ctx_num); - *p_param_size = 2; - } - - /* Return the raw blob. */ - SAFE_FREE(*ppdata); - *ppdata = response.data; - *p_data_size = response.length; - return status; -} - -/****************************************************************************** - Do the SPNEGO encryption negotiation. Parameters are in/out. -******************************************************************************/ - -NTSTATUS srv_request_encryption_setup(connection_struct *conn, - unsigned char **ppdata, - size_t *p_data_size, - unsigned char **pparam, - size_t *p_param_size) -{ - unsigned char *pdata = *ppdata; - - SAFE_FREE(*pparam); - *p_param_size = 0; - - if (*p_data_size < 1) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (pdata[0] == ASN1_APPLICATION(0)) { - /* its a negTokenTarg packet */ - return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size); - } - - if (pdata[0] == ASN1_CONTEXT(1)) { - /* It's an auth packet */ - return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); - } - - /* Maybe it's a raw unwrapped auth ? */ - if (*p_data_size < 7) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { - return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); - } - - DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); - - return NT_STATUS_LOGON_FAILURE; -} - -/****************************************************************************** - Negotiation was successful - turn on server-side encryption. -******************************************************************************/ - -static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) -{ - if (!ec || !ec->es) { - return NT_STATUS_LOGON_FAILURE; - } - - if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { - if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != - (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { - return NT_STATUS_INVALID_PARAMETER; - } - } - /* Todo - check gssapi case. */ - - return NT_STATUS_OK; -} - -/****************************************************************************** - Negotiation was successful - turn on server-side encryption. -******************************************************************************/ - -NTSTATUS srv_encryption_start(connection_struct *conn) -{ - NTSTATUS status; - - /* Check that we are really doing sign+seal. */ - status = check_enc_good(partial_srv_trans_enc_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* Throw away the context we're using currently (if any). */ - srv_free_encryption_context(&srv_trans_enc_ctx); - - /* Steal the partial pointer. Deliberate shallow copy. */ - srv_trans_enc_ctx = partial_srv_trans_enc_ctx; - srv_trans_enc_ctx->es->enc_on = True; - - partial_srv_trans_enc_ctx = NULL; - return NT_STATUS_OK; -} - -/****************************************************************************** - Shutdown all server contexts. -******************************************************************************/ - -void server_encryption_shutdown(void) -{ - srv_free_encryption_context(&partial_srv_trans_enc_ctx); - srv_free_encryption_context(&srv_trans_enc_ctx); -} -- cgit From afc93255d183eefb68e45b8ec6275f6a62cf9795 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Dec 2007 17:12:36 -0800 Subject: Add SMB encryption. Still fixing client decrypt but negotiation works. Jeremy. (This used to be commit d78045601af787731f0737b8627450018902b104) --- source3/smbd/seal.c | 703 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 703 insertions(+) create mode 100644 source3/smbd/seal.c (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c new file mode 100644 index 0000000000..14a427bb9c --- /dev/null +++ b/source3/smbd/seal.c @@ -0,0 +1,703 @@ +/* + Unix SMB/CIFS implementation. + SMB Transport encryption (sealing) code - server code. + Copyright (C) Jeremy Allison 2007. + + 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 . +*/ + +#include "includes.h" + +/****************************************************************************** + Server side encryption. +******************************************************************************/ + +/****************************************************************************** + Global server state. +******************************************************************************/ + +struct smb_srv_trans_enc_ctx { + struct smb_trans_enc_state *es; + AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */ +}; + +static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx; +static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx; + +/****************************************************************************** + Is server encryption on ? +******************************************************************************/ + +bool srv_encryption_on(void) +{ + if (srv_trans_enc_ctx) { + return common_encryption_on(srv_trans_enc_ctx->es); + } + return false; +} + +/****************************************************************************** + Create an auth_ntlmssp_state and ensure pointer copy is correct. +******************************************************************************/ + +static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) +{ + NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + /* + * We must remember to update the pointer copy for the common + * functions after any auth_ntlmssp_start/auth_ntlmssp_end. + */ + ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; + return status; +} + +/****************************************************************************** + Destroy an auth_ntlmssp_state and ensure pointer copy is correct. +******************************************************************************/ + +static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) +{ + /* + * We must remember to update the pointer copy for the common + * functions after any auth_ntlmssp_start/auth_ntlmssp_end. + */ + + if (ec->auth_ntlmssp_state) { + auth_ntlmssp_end(&ec->auth_ntlmssp_state); + /* The auth_ntlmssp_end killed this already. */ + ec->es->s.ntlmssp_state = NULL; + } +} + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + +/****************************************************************************** + Import a name. +******************************************************************************/ + +static NTSTATUS get_srv_gss_creds(const char *service, + const char *name, + gss_cred_usage_t cred_type, + gss_cred_id_t *p_srv_cred) +{ + OM_uint32 ret; + OM_uint32 min; + gss_name_t srv_name; + gss_buffer_desc input_name; + char *host_princ_s = NULL; + NTSTATUS status = NT_STATUS_OK; + + gss_OID_desc nt_hostbased_service = + {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; + + asprintf(&host_princ_s, "%s@%s", service, name); + if (host_princ_s == NULL) { + return NT_STATUS_NO_MEMORY; + } + + input_name.value = host_princ_s; + input_name.length = strlen(host_princ_s) + 1; + + ret = gss_import_name(&min, + &input_name, + &nt_hostbased_service, + &srv_name); + + DEBUG(10,("get_srv_gss_creds: imported name %s\n", + host_princ_s )); + + if (ret != GSS_S_COMPLETE) { + SAFE_FREE(host_princ_s); + return map_nt_error_from_gss(ret, min); + } + + /* + * We're accessing the krb5.keytab file here. + * ensure we have permissions to do so. + */ + become_root(); + + ret = gss_acquire_cred(&min, + srv_name, + GSS_C_INDEFINITE, + GSS_C_NULL_OID_SET, + cred_type, + p_srv_cred, + NULL, + NULL); + unbecome_root(); + + if (ret != GSS_S_COMPLETE) { + ADS_STATUS adss = ADS_ERROR_GSS(ret, min); + DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n", + ads_errstr(adss))); + status = map_nt_error_from_gss(ret, min); + } + + SAFE_FREE(host_princ_s); + gss_release_name(&min, &srv_name); + return status; +} + +/****************************************************************************** + Create a gss state. + Try and get the cifs/server@realm principal first, then fall back to + host/server@realm. +******************************************************************************/ + +static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) +{ + NTSTATUS status; + gss_cred_id_t srv_cred; + fstring fqdn; + + name_to_fqdn(fqdn, global_myname()); + strlower_m(fqdn); + + status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); + if (!NT_STATUS_IS_OK(status)) { + status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + } + + ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss); + if (!ec->es->s.gss_state) { + OM_uint32 min; + gss_release_cred(&min, &srv_cred); + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(ec->es->s.gss_state); + ec->es->s.gss_state->creds = srv_cred; + + /* No context yet. */ + ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT; + + return NT_STATUS_OK; +} +#endif + +/****************************************************************************** + Shutdown a server encryption context. +******************************************************************************/ + +static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) +{ + struct smb_srv_trans_enc_ctx *ec = *pp_ec; + + if (!ec) { + return; + } + + if (ec->es) { + switch (ec->es->smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + destroy_auth_ntlmssp(ec); + break; +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + break; +#endif + } + common_free_encryption_state(&ec->es); + } + + SAFE_FREE(ec); + *pp_ec = NULL; +} + +/****************************************************************************** + Create a server encryption context. +******************************************************************************/ + +static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec) +{ + struct smb_srv_trans_enc_ctx *ec; + + *pp_ec = NULL; + + ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); + if (!ec) { + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(partial_srv_trans_enc_ctx); + ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); + if (!ec->es) { + SAFE_FREE(ec); + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(ec->es); + ec->es->smb_enc_type = smb_enc_type; + switch (smb_enc_type) { + case SMB_TRANS_ENC_NTLM: + { + NTSTATUS status = make_auth_ntlmssp(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return status; + } + } + break; + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + case SMB_TRANS_ENC_GSS: + /* Acquire our credentials by calling gss_acquire_cred here. */ + { + NTSTATUS status = make_auth_gss(ec); + if (!NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&ec); + return status; + } + } + break; +#endif + default: + srv_free_encryption_context(&ec); + return NT_STATUS_INVALID_PARAMETER; + } + *pp_ec = ec; + return NT_STATUS_OK; +} + +/****************************************************************************** + Free an encryption-allocated buffer. +******************************************************************************/ + +void srv_free_enc_buffer(char *buf) +{ + /* We know this is an smb buffer, and we + * didn't malloc, only copy, for a keepalive, + * so ignore session keepalives. */ + + if(CVAL(buf,0) == SMBkeepalive) { + return; + } + + if (srv_trans_enc_ctx) { + common_free_enc_buffer(srv_trans_enc_ctx->es, buf); + } +} + +/****************************************************************************** + Decrypt an incoming buffer. +******************************************************************************/ + +NTSTATUS srv_decrypt_buffer(char *buf) +{ + /* Ignore session keepalives. */ + if(CVAL(buf,0) == SMBkeepalive) { + return NT_STATUS_OK; + } + + if (srv_trans_enc_ctx) { + return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); + } + + return NT_STATUS_OK; +} + +/****************************************************************************** + Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. +******************************************************************************/ + +NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) +{ + *buf_out = buf; + + /* Ignore session keepalives. */ + if(CVAL(buf,0) == SMBkeepalive) { + return NT_STATUS_OK; + } + + if (srv_trans_enc_ctx) { + return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out); + } + /* Not encrypting. */ + return NT_STATUS_OK; +} + +/****************************************************************************** + Do the gss encryption negotiation. Parameters are in/out. + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) +static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) +{ + OM_uint32 ret; + OM_uint32 min; + OM_uint32 flags = 0; + gss_buffer_desc in_buf, out_buf; + struct smb_tran_enc_state_gss *gss_state; + DATA_BLOB auth_reply = data_blob_null; + DATA_BLOB response = data_blob_null; + NTSTATUS status; + + if (!partial_srv_trans_enc_ctx) { + status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + gss_state = partial_srv_trans_enc_ctx->es->s.gss_state; + + in_buf.value = secblob.data; + in_buf.length = secblob.length; + + out_buf.value = NULL; + out_buf.length = 0; + + become_root(); + + ret = gss_accept_sec_context(&min, + &gss_state->gss_ctx, + gss_state->creds, + &in_buf, + GSS_C_NO_CHANNEL_BINDINGS, + NULL, + NULL, /* Ignore oids. */ + &out_buf, /* To return. */ + &flags, + NULL, /* Ingore time. */ + NULL); /* Ignore delegated creds. */ + unbecome_root(); + + status = gss_err_to_ntstatus(ret, min); + if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { + return status; + } + + /* Ensure we've got sign+seal available. */ + if (ret == GSS_S_COMPLETE) { + if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) != + (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) { + DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough " + "for SMB sealing.\n")); + gss_release_buffer(&min, &out_buf); + return NT_STATUS_ACCESS_DENIED; + } + } + + auth_reply = data_blob(out_buf.value, out_buf.length); + gss_release_buffer(&min, &out_buf); + + /* Wrap in SPNEGO. */ + response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5); + data_blob_free(&auth_reply); + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + + return status; +} +#endif + +/****************************************************************************** + Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out. + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, bool spnego_wrap) +{ + NTSTATUS status; + DATA_BLOB chal = data_blob_null; + DATA_BLOB response = data_blob_null; + + status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); + + /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED + * for success ... */ + + if (spnego_wrap) { + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + data_blob_free(&chal); + } else { + /* Return the raw blob. */ + response = chal; + } + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + +/****************************************************************************** + Do the SPNEGO encryption negotiation. Parameters are in/out. + Based off code in smbd/sesssionsetup.c + Until success we do everything on the partial enc ctx. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob_null; + DATA_BLOB secblob = data_blob_null; + bool got_kerberos_mechanism = false; + + blob = data_blob_const(*ppdata, *p_data_size); + + status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism); + if (!NT_STATUS_IS_OK(status)) { + return nt_status_squash(status); + } + + /* We should have no partial context at this point. */ + + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + +#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { + status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); + } else +#endif + { + status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true); + } + + data_blob_free(&secblob); + + if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); + *p_param_size = 2; + } + + return status; +} + +/****************************************************************************** + Complete a SPNEGO encryption negotiation. Parameters are in/out. + We only get this for a NTLM auth second stage. +******************************************************************************/ + +static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob_null; + DATA_BLOB auth = data_blob_null; + DATA_BLOB auth_reply = data_blob_null; + DATA_BLOB response = data_blob_null; + struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; + + /* We must have a partial context here. */ + + if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + blob = data_blob_const(*ppdata, *p_data_size); + if (!spnego_parse_auth(blob, &auth)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); + data_blob_free(&auth); + + response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); + data_blob_free(&auth_reply); + + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,ec->es->enc_ctx_num); + *p_param_size = 2; + } + + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + +/****************************************************************************** + Raw NTLM encryption negotiation. Parameters are in/out. + This function does both steps. +******************************************************************************/ + +static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) +{ + NTSTATUS status; + DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); + DATA_BLOB response = data_blob_null; + struct smb_srv_trans_enc_ctx *ec; + + if (!partial_srv_trans_enc_ctx) { + /* This is the initial step. */ + status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, false); + if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return nt_status_squash(status); + } + return status; + } + + ec = partial_srv_trans_enc_ctx; + if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + return NT_STATUS_INVALID_PARAMETER; + } + + /* Second step. */ + status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); + + if (NT_STATUS_IS_OK(status)) { + /* Return the context we're using for this encryption state. */ + if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { + return NT_STATUS_NO_MEMORY; + } + SSVAL(*pparam,0,ec->es->enc_ctx_num); + *p_param_size = 2; + } + + /* Return the raw blob. */ + SAFE_FREE(*ppdata); + *ppdata = response.data; + *p_data_size = response.length; + return status; +} + +/****************************************************************************** + Do the SPNEGO encryption negotiation. Parameters are in/out. +******************************************************************************/ + +NTSTATUS srv_request_encryption_setup(connection_struct *conn, + unsigned char **ppdata, + size_t *p_data_size, + unsigned char **pparam, + size_t *p_param_size) +{ + unsigned char *pdata = *ppdata; + + SAFE_FREE(*pparam); + *p_param_size = 0; + + if (*p_data_size < 1) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (pdata[0] == ASN1_APPLICATION(0)) { + /* its a negTokenTarg packet */ + return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size); + } + + if (pdata[0] == ASN1_CONTEXT(1)) { + /* It's an auth packet */ + return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); + } + + /* Maybe it's a raw unwrapped auth ? */ + if (*p_data_size < 7) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { + return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); + } + + DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); + + return NT_STATUS_LOGON_FAILURE; +} + +/****************************************************************************** + Negotiation was successful - turn on server-side encryption. +******************************************************************************/ + +static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) +{ + if (!ec || !ec->es) { + return NT_STATUS_LOGON_FAILURE; + } + + if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { + if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != + (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { + return NT_STATUS_INVALID_PARAMETER; + } + } + /* Todo - check gssapi case. */ + + return NT_STATUS_OK; +} + +/****************************************************************************** + Negotiation was successful - turn on server-side encryption. +******************************************************************************/ + +NTSTATUS srv_encryption_start(connection_struct *conn) +{ + NTSTATUS status; + + /* Check that we are really doing sign+seal. */ + status = check_enc_good(partial_srv_trans_enc_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* Throw away the context we're using currently (if any). */ + srv_free_encryption_context(&srv_trans_enc_ctx); + + /* Steal the partial pointer. Deliberate shallow copy. */ + srv_trans_enc_ctx = partial_srv_trans_enc_ctx; + srv_trans_enc_ctx->es->enc_on = true; + + partial_srv_trans_enc_ctx = NULL; + return NT_STATUS_OK; +} + +/****************************************************************************** + Shutdown all server contexts. +******************************************************************************/ + +void server_encryption_shutdown(void) +{ + srv_free_encryption_context(&partial_srv_trans_enc_ctx); + srv_free_encryption_context(&srv_trans_enc_ctx); +} -- cgit From c6646f115ebca2fe8b05c898d3529832b3599056 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 30 Dec 2007 13:10:29 -0800 Subject: As the encryption is stream based there's no reason oplock breaks can't be encrypted. If we have multiple contexts I should probably attach them to the connection struct, but for now use the global context number. Jeremy. (This used to be commit 5b4b335ed0d1dc738f1f099e5c638361f3aede07) --- source3/smbd/seal.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 14a427bb9c..24ecb77fd5 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -47,6 +47,15 @@ bool srv_encryption_on(void) return false; } +/****************************************************************************** + Return global enc context - this must change if we ever do multiple contexts. +******************************************************************************/ + +uint16 srv_enc_ctx(void) +{ + return srv_trans_enc_ctx->es->enc_ctx_num; +} + /****************************************************************************** Create an auth_ntlmssp_state and ensure pointer copy is correct. ******************************************************************************/ -- cgit From 9254bb4ef1c3c3a52ea8e935edb0e7a86ec3ea7a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 12:56:23 -0800 Subject: Refactor the crypto code after a very helpful conversation with Volker. Mostly making sure we have data on the incoming packet type, not stored in the smb header. Jeremy. (This used to be commit c4e5a505043965eec77b5bb9bc60957e8f3b97c8) --- source3/smbd/seal.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 24ecb77fd5..21fca73fea 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -36,24 +36,37 @@ static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx; static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx; /****************************************************************************** - Is server encryption on ? + Return global enc context - this must change if we ever do multiple contexts. ******************************************************************************/ -bool srv_encryption_on(void) +uint16_t srv_enc_ctx(void) { - if (srv_trans_enc_ctx) { - return common_encryption_on(srv_trans_enc_ctx->es); - } - return false; + return srv_trans_enc_ctx->es->enc_ctx_num; } /****************************************************************************** - Return global enc context - this must change if we ever do multiple contexts. + Is this an incoming encrypted packet ? ******************************************************************************/ -uint16 srv_enc_ctx(void) +bool is_encrypted_packet(const uint8_t *inbuf) { - return srv_trans_enc_ctx->es->enc_ctx_num; + NTSTATUS status; + uint16_t enc_num; + + /* Ignore non-session messages. */ + if(CVAL(inbuf,0)) { + return false; + } + + status = get_enc_ctx_num(inbuf, &enc_num); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + + if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) { + return true; + } + return false; } /****************************************************************************** @@ -292,9 +305,9 @@ void srv_free_enc_buffer(char *buf) { /* We know this is an smb buffer, and we * didn't malloc, only copy, for a keepalive, - * so ignore session keepalives. */ + * so ignore non-session messages. */ - if(CVAL(buf,0) == SMBkeepalive) { + if(CVAL(buf,0)) { return; } @@ -309,8 +322,8 @@ void srv_free_enc_buffer(char *buf) NTSTATUS srv_decrypt_buffer(char *buf) { - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { + /* Ignore non-session messages. */ + if(CVAL(buf,0)) { return NT_STATUS_OK; } @@ -329,8 +342,8 @@ NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) { *buf_out = buf; - /* Ignore session keepalives. */ - if(CVAL(buf,0) == SMBkeepalive) { + /* Ignore non-session messages. */ + if(CVAL(buf,0)) { return NT_STATUS_OK; } @@ -698,6 +711,7 @@ NTSTATUS srv_encryption_start(connection_struct *conn) srv_trans_enc_ctx->es->enc_on = true; partial_srv_trans_enc_ctx = NULL; + return NT_STATUS_OK; } -- cgit From 80158198eee90cf05396989df068f77f8bb7e064 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jan 2008 15:57:08 -0800 Subject: Correctly identify enc/non-enc packets. Jeremy. (This used to be commit 647f13d0f1a270a68263b3b0403436f9d6cf1a0e) --- source3/smbd/seal.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 21fca73fea..51a5f23f03 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -53,8 +53,8 @@ bool is_encrypted_packet(const uint8_t *inbuf) NTSTATUS status; uint16_t enc_num; - /* Ignore non-session messages. */ - if(CVAL(inbuf,0)) { + /* Ignore non-session messages or 0xFF'SMB' messages. */ + if(CVAL(inbuf,0) || IVAL(inbuf,4) == 0x424d53ff) { return false; } @@ -63,7 +63,9 @@ bool is_encrypted_packet(const uint8_t *inbuf) return false; } - if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) { + if (SVAL(inbuf,4) == 0x45FF && + srv_trans_enc_ctx && + enc_num == srv_enc_ctx()) { return true; } return false; -- cgit From 7febec3c58bebb20d7866ea98c43bb41f0c09db4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jan 2008 16:08:39 -0800 Subject: Simplify... plus add a debug message. Jeremy. (This used to be commit bedc493874adaf783362ba7b821e2a6d985b96ea) --- source3/smbd/seal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 51a5f23f03..ea017e08d8 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -53,8 +53,8 @@ bool is_encrypted_packet(const uint8_t *inbuf) NTSTATUS status; uint16_t enc_num; - /* Ignore non-session messages or 0xFF'SMB' messages. */ - if(CVAL(inbuf,0) || IVAL(inbuf,4) == 0x424d53ff) { + /* Ignore non-session messages or non 0xFF'E' messages. */ + if(CVAL(inbuf,0) || !(inbuf[4] == 0xFF && inbuf[5] == 'E')) { return false; } @@ -63,9 +63,8 @@ bool is_encrypted_packet(const uint8_t *inbuf) return false; } - if (SVAL(inbuf,4) == 0x45FF && - srv_trans_enc_ctx && - enc_num == srv_enc_ctx()) { + /* Encrypted messages are 0xFF'E' */ + if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) { return true; } return false; @@ -714,6 +713,7 @@ NTSTATUS srv_encryption_start(connection_struct *conn) partial_srv_trans_enc_ctx = NULL; + DEBUG(1,("srv_encryption_start: context negotiated\n")); return NT_STATUS_OK; } -- cgit From 81d6133b0363be3736e60d8336a90129d67d7e4a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2008 18:07:27 -0800 Subject: Currently we don't SPNEGO negotiate back to NTLMSSP. Note this. Jeremy. (This used to be commit 8cd04b948bfba3896d40c9e314a197f60ad76833) --- source3/smbd/seal.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index ea017e08d8..d4394e5bca 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -496,12 +496,15 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, srv_free_encryption_context(&partial_srv_trans_enc_ctx); + if (got_kerberos_mechanism) { #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) - if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) { status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); - } else +#else + /* Currently we don't SPNEGO negotiate + * back to NTLMSSP as we do in sessionsetupX. We should... */ + return NT_STATUS_LOGON_FAILURE; #endif - { + } else { status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true); } @@ -558,7 +561,16 @@ static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); data_blob_free(&auth); - response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP); + /* From RFC4178. + * + * supportedMech + * + * This field SHALL only be present in the first reply from the + * target. + * So set mechOID to NULL here. + */ + + response = spnego_gen_auth_response(&auth_reply, status, NULL); data_blob_free(&auth_reply); if (NT_STATUS_IS_OK(status)) { -- cgit From f700ee6418c7b861efdb0f8eaa61b99ad598b7c3 Mon Sep 17 00:00:00 2001 From: Bill Ricker Date: Mon, 7 Apr 2008 15:02:56 -0700 Subject: Fix Kerberos interop with Mac OS X 10.5 clients. Ignore optional req_flags. Use the Kerberos mechanism OID negotiated with the client rather than hardcoding OID_KERBEROS5_OLD. (This used to be commit 59a2bcf30fef14ecc826271862b645dd3a61cb48) --- source3/smbd/seal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index d4394e5bca..955ca471bc 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -484,10 +484,11 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, DATA_BLOB blob = data_blob_null; DATA_BLOB secblob = data_blob_null; bool got_kerberos_mechanism = false; + char *kerb_mech = NULL; blob = data_blob_const(*ppdata, *p_data_size); - status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism); + status = parse_spnego_mechanisms(blob, &secblob, &kerb_mech); if (!NT_STATUS_IS_OK(status)) { return nt_status_squash(status); } @@ -496,7 +497,9 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, srv_free_encryption_context(&partial_srv_trans_enc_ctx); - if (got_kerberos_mechanism) { + if (kerb_mech) { + SAFE_FREE(kerb_mech); + #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); #else -- cgit From f863cb2ef45a19e092d72b93427b5b3c4e0c0a42 Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 7 Apr 2008 15:28:10 -0700 Subject: Remove unused variable. (This used to be commit 3ed2c65bde0c2e5ad10cf777dae8a2d3e626a42c) --- source3/smbd/seal.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd/seal.c') diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 955ca471bc..e9dc46aa3c 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -483,7 +483,6 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, NTSTATUS status; DATA_BLOB blob = data_blob_null; DATA_BLOB secblob = data_blob_null; - bool got_kerberos_mechanism = false; char *kerb_mech = NULL; blob = data_blob_const(*ppdata, *p_data_size); -- cgit