summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-03-27 21:13:31 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:18:58 -0500
commit4a66d0e232271968ba96da50274428916a393975 (patch)
tree89e40c8ad86d96458905940839a5ddba4f1bd747 /source3/libsmb
parent34dac35e48ca0c03d2744d9925566665285eb973 (diff)
downloadsamba-4a66d0e232271968ba96da50274428916a393975.tar.gz
samba-4a66d0e232271968ba96da50274428916a393975.tar.bz2
samba-4a66d0e232271968ba96da50274428916a393975.zip
r21991: I hate Steve French :-). Add support for encryption
contexts.... Jeremy. (This used to be commit ae8f3649f773b8a8dcb55921536d038d3475322e)
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/clientgen.c7
-rw-r--r--source3/libsmb/clifsinfo.c10
-rw-r--r--source3/libsmb/smb_seal.c111
3 files changed, 95 insertions, 33 deletions
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 92fc72fd5c..fc88f7f1e2 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -167,6 +167,7 @@ BOOL cli_send_smb(struct cli_state *cli)
size_t nwritten=0;
ssize_t ret;
char *buf_out = cli->outbuf;
+ BOOL enc_on = cli_encryption_on(cli);
/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
if (cli->fd == -1) {
@@ -175,7 +176,7 @@ BOOL cli_send_smb(struct cli_state *cli)
cli_calculate_sign_mac(cli);
- if (cli_encryption_on(cli)) {
+ if (enc_on) {
NTSTATUS status = cli_encrypt_message(cli, &buf_out);
if (!NT_STATUS_IS_OK(status)) {
close(cli->fd);
@@ -192,7 +193,9 @@ BOOL cli_send_smb(struct cli_state *cli)
while (nwritten < len) {
ret = write_socket(cli->fd,buf_out+nwritten,len - nwritten);
if (ret <= 0) {
- cli_free_enc_buffer(cli, buf_out);
+ if (enc_on) {
+ cli_free_enc_buffer(cli, buf_out);
+ }
close(cli->fd);
cli->fd = -1;
cli->smb_rw_error = WRITE_ERROR;
diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c
index 92537ed317..149af32574 100644
--- a/source3/libsmb/clifsinfo.c
+++ b/source3/libsmb/clifsinfo.c
@@ -307,7 +307,7 @@ cleanup:
Send/receive the request encryption blob.
******************************************************************************/
-static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA_BLOB *out)
+static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA_BLOB *out, DATA_BLOB *param_out)
{
uint16 setup;
char param[4];
@@ -345,6 +345,7 @@ static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA
}
*out = data_blob(rdata, rdata_count);
+ *param_out = data_blob(rparam, rparam_count);
out:
@@ -364,6 +365,7 @@ NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli,
{
DATA_BLOB blob_in = data_blob(NULL, 0);
DATA_BLOB blob_out = data_blob(NULL, 0);
+ DATA_BLOB param_out = data_blob(NULL, 0);
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
struct smb_trans_enc_state *es = NULL;
@@ -394,8 +396,12 @@ NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli,
do {
status = ntlmssp_update(es->s.ntlmssp_state, blob_in, &blob_out);
data_blob_free(&blob_in);
+ data_blob_free(&param_out);
if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(status)) {
- status = enc_blob_send_receive(cli, &blob_out, &blob_in);
+ status = enc_blob_send_receive(cli, &blob_out, &blob_in, &param_out);
+ }
+ if (param_out.length == 2) {
+ es->enc_ctx_num = SVAL(param_out.data, 0);
}
data_blob_free(&blob_out);
} while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c
index f0e79b404c..c80b7f0a90 100644
--- a/source3/libsmb/smb_seal.c
+++ b/source3/libsmb/smb_seal.c
@@ -21,6 +21,27 @@
#include "includes.h"
/******************************************************************************
+ Pull out the encryption context for this packet. 0 means global context.
+******************************************************************************/
+
+NTSTATUS get_enc_ctx_num(char *buf, uint16 *p_enc_ctx_num)
+{
+ if (smb_len(buf) < 8) {
+ return NT_STATUS_INVALID_BUFFER_SIZE;
+ }
+
+ if (buf[4] == (char)0xFF && buf[5] == 'S') {
+ if (buf [6] == 'M' && buf[7] == 'B') {
+ /* Not an encrypted buffer. */
+ return NT_STATUS_NOT_FOUND;
+ }
+ *p_enc_ctx_num = SVAL(buf,6);
+ return NT_STATUS_OK;
+ }
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+}
+
+/******************************************************************************
Generic code for client and server.
Is encryption turned on ?
******************************************************************************/
@@ -52,7 +73,7 @@ NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
sig = data_blob(buf+buf_len, NTLMSSP_SIG_SIZE);
status = ntlmssp_unseal_packet(ntlmssp_state,
- (unsigned char *)buf + 8, /* 4 byte len + 0xFF 'S' 'M' 'B' */
+ (unsigned char *)buf + 8, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
buf_len - 8,
(unsigned char *)buf + 8,
buf_len - 8,
@@ -73,7 +94,10 @@ NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
******************************************************************************/
-NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, char **ppbuf_out)
+NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state,
+ uint16 enc_ctx_num,
+ char *buf,
+ char **ppbuf_out)
{
NTSTATUS status;
char *buf_out;
@@ -97,12 +121,12 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha
memcpy(buf_out, buf, buf_len);
/* Last 16 bytes undefined here... */
- smb_setlen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE);
+ smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
status = ntlmssp_seal_packet(ntlmssp_state,
- (unsigned char *)buf_out + 8, /* 4 byte len + 0xFF 'S' 'M' 'B' */
+ (unsigned char *)buf_out + 8, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
buf_len - 8,
(unsigned char *)buf_out + 8,
buf_len - 8,
@@ -126,7 +150,7 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha
******************************************************************************/
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
- NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
+NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
{
gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
OM_uint32 ret = 0;
@@ -179,7 +203,10 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha
******************************************************************************/
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
- NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf, char **ppbuf_out)
+NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
+ uint16 enc_ctx_num,
+ char *buf,
+ char **ppbuf_out)
{
gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
OM_uint32 ret = 0;
@@ -238,7 +265,7 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, cha
}
memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
- smb_setlen(*ppbuf_out, out_buf.length + 4);
+ smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
gss_release_buffer(&minor, &out_buf);
return NT_STATUS_OK;
@@ -258,18 +285,12 @@ NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, cha
return NT_STATUS_OK;
}
- /* Ignore session keepalives. */
- if(CVAL(buffer,0) == SMBkeepalive) {
- *buf_out = buffer;
- return NT_STATUS_OK;
- }
-
switch (es->smb_enc_type) {
case SMB_TRANS_ENC_NTLM:
- return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, buffer, buf_out);
+ return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
case SMB_TRANS_ENC_GSS:
- return common_gss_encrypt_buffer(es->s.gss_state, buffer, buf_out);
+ return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
#endif
default:
return NT_STATUS_NOT_SUPPORTED;
@@ -289,11 +310,6 @@ NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
return NT_STATUS_OK;
}
- /* Ignore session keepalives. */
- if(CVAL(buf,0) == SMBkeepalive) {
- return NT_STATUS_OK;
- }
-
switch (es->smb_enc_type) {
case SMB_TRANS_ENC_NTLM:
return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
@@ -361,21 +377,19 @@ void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
return;
}
- /* 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 (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
SAFE_FREE(buf);
return;
}
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
- /* gss-api free buffer.... */
+ if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
+ OM_uint32 min;
+ gss_buffer_desc rel_buf;
+ rel_buf.value = buf;
+ rel_buf.length = smb_len(buf) + 4;
+ gss_release_buffer(&min, &rel_buf);
+ }
#endif
}
@@ -389,6 +403,9 @@ void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
BOOL cli_encryption_on(struct cli_state *cli)
{
+ /* If we supported multiple encrytion contexts
+ * here we'd look up based on tid.
+ */
return common_encryption_on(cli->trans_enc_state);
}
@@ -407,6 +424,17 @@ void cli_free_encryption_context(struct cli_state *cli)
void cli_free_enc_buffer(struct cli_state *cli, 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 we supported multiple encrytion contexts
+ * here we'd look up based on tid.
+ */
common_free_enc_buffer(cli->trans_enc_state, buf);
}
@@ -416,6 +444,23 @@ void cli_free_enc_buffer(struct cli_state *cli, char *buf)
NTSTATUS cli_decrypt_message(struct cli_state *cli)
{
+ NTSTATUS status;
+ uint16 enc_ctx_num;
+
+ /* Ignore session keepalives. */
+ if(CVAL(cli->inbuf,0) == SMBkeepalive) {
+ return NT_STATUS_OK;
+ }
+
+ status = get_enc_ctx_num(cli->inbuf, &enc_ctx_num);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
}
@@ -425,5 +470,13 @@ NTSTATUS cli_decrypt_message(struct cli_state *cli)
NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
{
+ /* Ignore session keepalives. */
+ if(CVAL(cli->inbuf,0) == SMBkeepalive) {
+ return NT_STATUS_OK;
+ }
+
+ /* If we supported multiple encrytion contexts
+ * here we'd look up based on tid.
+ */
return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out);
}