diff options
author | Jeremy Allison <jra@samba.org> | 2007-03-27 21:13:31 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:18:58 -0500 |
commit | 4a66d0e232271968ba96da50274428916a393975 (patch) | |
tree | 89e40c8ad86d96458905940839a5ddba4f1bd747 /source3/libsmb | |
parent | 34dac35e48ca0c03d2744d9925566665285eb973 (diff) | |
download | samba-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.c | 7 | ||||
-rw-r--r-- | source3/libsmb/clifsinfo.c | 10 | ||||
-rw-r--r-- | source3/libsmb/smb_seal.c | 111 |
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(¶m_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, ¶m_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); } |