diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/smb_seal.c | 178 |
1 files changed, 176 insertions, 2 deletions
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c index eb35fc05f9..90efa05f0b 100644 --- a/source3/libsmb/smb_seal.c +++ b/source3/libsmb/smb_seal.c @@ -30,12 +30,186 @@ NTSTATUS cli_encrypt_message(struct cli_state *cli) return NT_STATUS_OK; } -NTSTATUS srv_decrypt_buffer(char *buffer) +/* Server state if we're encrypting SMBs. If NULL then enc is off. */ + +static struct smb_trans_enc_state *srv_trans_enc_state; + +/****************************************************************************** + Is server encryption on ? +******************************************************************************/ + +BOOL srv_encryption_on(void) +{ + return srv_trans_enc_state != NULL; +} + +/****************************************************************************** + Free an encryption-allocated buffer. +******************************************************************************/ + +void srv_free_buffer(char *buf_out) { + if (!srv_trans_enc_state) { + return; + } + + if (srv_trans_enc_state->smb_enc_type == SMB_TRANS_ENC_NTLM) { + SAFE_FREE(buf_out); + return; + } + +#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) + /* gss-api free buffer.... */ +#endif +} + +/****************************************************************************** + gss-api decrypt an incoming buffer. +******************************************************************************/ + +#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) +static NTSTATUS srv_gss_decrypt_buffer(gss_ctx_id_t context_handle, char *buf) +{ + return NT_STATUS_NOT_SUPPORTED; +} +#endif + +/****************************************************************************** + NTLM decrypt an incoming buffer. +******************************************************************************/ + +static NTSTATUS srv_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf) +{ + NTSTATUS status; + size_t orig_len = smb_len(buf); + size_t new_len = orig_len - NTLMSSP_SIG_SIZE; + DATA_BLOB sig; + + if (orig_len < 8 + NTLMSSP_SIG_SIZE) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + /* Save off the signature. */ + sig = data_blob(buf+orig_len-NTLMSSP_SIG_SIZE, NTLMSSP_SIG_SIZE); + + status = ntlmssp_unseal_packet(ntlmssp_state, + (unsigned char *)buf + 8, /* 4 byte len + 0xFF 'S' 'M' 'B' */ + new_len - 8, + (unsigned char *)buf, + new_len, + &sig); + + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&sig); + return status; + } + /* Reset the length. */ + smb_setlen(buf, new_len); return NT_STATUS_OK; } -NTSTATUS srv_encrypt_buffer(char *buffer) +/****************************************************************************** + Decrypt an incoming buffer. +******************************************************************************/ + +NTSTATUS srv_decrypt_buffer(char *buf) { + if (!srv_trans_enc_state) { + /* Not decrypting. */ + return NT_STATUS_OK; + } + if (srv_trans_enc_state->smb_enc_type == SMB_TRANS_ENC_NTLM) { + return srv_ntlm_decrypt_buffer(srv_trans_enc_state->ntlmssp_state, buf); + } else { +#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) + return srv_gss_decrypt_buffer(srv_trans_enc_state->context_handle, buf); +#else + return NT_STATUS_NOT_SUPPORTED; +#endif + } +} + +/****************************************************************************** + gss-api encrypt an outgoing buffer. Return the encrypted pointer in buf_out. +******************************************************************************/ + +#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) +static NTSTATUS srv_gss_encrypt_buffer(gss_ctx_id_t context_handle, char *buf, char **buf_out) +{ + return NT_STATUS_NOT_SUPPORTED; +} +#endif + +/****************************************************************************** + NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out. +******************************************************************************/ + +static NTSTATUS srv_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf, char **ppbuf_out) +{ + NTSTATUS status; + char *buf_out; + size_t orig_len = smb_len(buf); + size_t new_len = orig_len + NTLMSSP_SIG_SIZE; + DATA_BLOB sig; + + *ppbuf_out = NULL; + + if (orig_len < 8) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + /* + * We know smb_len can't return a value > 128k, so no int overflow + * check needed. + */ + + /* Copy the original buffer. */ + + buf_out = SMB_XMALLOC_ARRAY(char, new_len); + memcpy(buf_out, buf, orig_len); + /* Last 16 bytes undefined here... */ + + smb_setlen(buf_out, new_len); + + 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' */ + orig_len - 8, + (unsigned char *)buf_out, + orig_len, + &sig); + + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&sig); + SAFE_FREE(buf_out); + return status; + } + + memcpy(buf_out+orig_len, sig.data, NTLMSSP_SIG_SIZE); + *ppbuf_out = buf_out; 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_state) { + /* Not encrypting. */ + *buf_out = buffer; + return NT_STATUS_OK; + } + + if (srv_trans_enc_state->smb_enc_type == SMB_TRANS_ENC_NTLM) { + return srv_ntlm_encrypt_buffer(srv_trans_enc_state->ntlmssp_state, buffer, buf_out); + } else { +#if defined(HAVE_GSSAPI_SUPPORT) && defined(HAVE_KRB5) + return srv_gss_encrypt_buffer(srv_trans_enc_state->context_handle, buffer, buf_out); +#else + return NT_STATUS_NOT_SUPPORTED; +#endif + } +} |