diff options
-rw-r--r-- | source3/libsmb/smb_seal.c | 64 | ||||
-rw-r--r-- | source3/smbd/seal.c | 6 |
2 files changed, 41 insertions, 29 deletions
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c index 891673ed15..fac451a6c5 100644 --- a/source3/libsmb/smb_seal.c +++ b/source3/libsmb/smb_seal.c @@ -30,13 +30,15 @@ NTSTATUS get_enc_ctx_num(char *buf, uint16 *p_enc_ctx_num) return NT_STATUS_INVALID_BUFFER_SIZE; } - if (buf[4] == (char)0xFF && buf[5] == 'S') { - if (buf [6] == 'M' && buf[7] == 'B') { + if (buf[4] == (char)0xFF) { + if (buf[5] == 'S' && 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; + if (buf[5] == 'E') { + *p_enc_ctx_num = SVAL(buf,6); + return NT_STATUS_OK; + } } return NT_STATUS_INVALID_NETWORK_RESPONSE; } @@ -54,44 +56,55 @@ BOOL common_encryption_on(struct smb_trans_enc_state *es) /****************************************************************************** Generic code for client and server. NTLM decrypt an incoming buffer. + Abartlett tells me that SSPI puts the signature first before the encrypted + output, so cope with the same for compatibility. ******************************************************************************/ NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf) { NTSTATUS status; size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */ + size_t data_len; + char *inbuf; DATA_BLOB sig; if (buf_len < 8 + NTLMSSP_SIG_SIZE) { return NT_STATUS_BUFFER_TOO_SMALL; } + inbuf = smb_xmemdup(buf, buf_len); + /* Adjust for the signature. */ - buf_len -= NTLMSSP_SIG_SIZE; + data_len = buf_len - 8 - NTLMSSP_SIG_SIZE; - /* Save off the signature. */ - sig = data_blob(buf+buf_len, NTLMSSP_SIG_SIZE); + /* Point at the signature. */ + sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE); status = ntlmssp_unseal_packet(ntlmssp_state, - (unsigned char *)buf + 8, /* 4 byte len + 0xFF 'S' <enc> <ctx> */ - buf_len - 8, - (unsigned char *)buf + 8, - buf_len - 8, + (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */ + data_len, + (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, + data_len, &sig); if (!NT_STATUS_IS_OK(status)) { - data_blob_free(&sig); + SAFE_FREE(inbuf); return status; } + memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len); + SAFE_FREE(inbuf); + /* Reset the length. */ - smb_setlen(buf, smb_len(buf) - NTLMSSP_SIG_SIZE); + smb_setlen(buf, data_len + 4); return NT_STATUS_OK; } /****************************************************************************** Generic code for client and server. NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out. + Abartlett tells me that SSPI puts the signature first before the encrypted + output, so do the same for compatibility. ******************************************************************************/ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, @@ -101,12 +114,12 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, { NTSTATUS status; char *buf_out; - size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */ + size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */ DATA_BLOB sig; *ppbuf_out = NULL; - if (buf_len < 8) { + if (data_len == 0) { return NT_STATUS_BUFFER_TOO_SMALL; } @@ -115,21 +128,21 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, * check needed. */ - /* Copy the original buffer. */ + buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len); + + /* Copy the data from the original buffer. */ - buf_out = SMB_XMALLOC_ARRAY(char, buf_len + NTLMSSP_SIG_SIZE); - memcpy(buf_out, buf, buf_len); - /* Last 16 bytes undefined here... */ + memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len); 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' <enc> <ctx> */ - buf_len - 8, - (unsigned char *)buf_out + 8, - buf_len - 8, + (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */ + data_len, + (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, + data_len, &sig); if (!NT_STATUS_IS_OK(status)) { @@ -138,7 +151,8 @@ NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state, return status; } - memcpy(buf_out+buf_len, sig.data, NTLMSSP_SIG_SIZE); + /* First 16 data bytes are signature for SSPI compatibility. */ + memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE); *ppbuf_out = buf_out; return NT_STATUS_OK; } @@ -195,14 +209,12 @@ NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, cha gss_release_buffer(&minor, &out_buf); return NT_STATUS_OK; } -#endif /****************************************************************************** Generic code for client and server. gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out. ******************************************************************************/ -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state, uint16 enc_ctx_num, char *buf, 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); } |