2 Unix SMB/CIFS implementation.
3 SMB Transport encryption (sealing) code.
4 Copyright (C) Jeremy Allison 2007.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "smb_common.h"
23 #include "lib/krb5_wrap/krb5_samba.h"
25 #include "auth/gensec/gensec.h"
26 #include "libcli/smb/smb_seal.h"
30 /******************************************************************************
31 Pull out the encryption context for this packet. 0 means global context.
32 ******************************************************************************/
34 NTSTATUS
get_enc_ctx_num(const uint8_t *buf
, uint16_t *p_enc_ctx_num
)
36 if (smb_len_nbt(buf
) < 8) {
37 return NT_STATUS_INVALID_BUFFER_SIZE
;
41 if (buf
[5] == 'S' && buf
[6] == 'M' && buf
[7] == 'B') {
42 /* Not an encrypted buffer. */
43 return NT_STATUS_NOT_FOUND
;
46 *p_enc_ctx_num
= SVAL(buf
,6);
50 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
53 /*******************************************************************
54 Set the length and marker of an encrypted smb packet.
55 ********************************************************************/
57 static void smb_set_enclen(char *buf
,int len
,uint16_t enc_ctx_num
)
59 _smb_setlen_nbt(buf
,len
);
63 SSVAL(buf
,6,enc_ctx_num
);
66 /******************************************************************************
67 Generic code for client and server.
68 Is encryption turned on ?
69 ******************************************************************************/
71 bool common_encryption_on(struct smb_trans_enc_state
*es
)
73 return ((es
!= NULL
) && es
->enc_on
);
76 /******************************************************************************
77 Generic code for client and server.
78 GENSEC decrypt an incoming buffer.
79 ******************************************************************************/
81 static NTSTATUS
common_gensec_decrypt_buffer(struct gensec_security
*gensec
,
85 size_t buf_len
= smb_len_nbt(buf
) + 4; /* Don't forget the 4 length bytes. */
86 DATA_BLOB in_buf
, out_buf
;
90 return NT_STATUS_BUFFER_TOO_SMALL
;
93 frame
= talloc_stackframe();
95 in_buf
= data_blob_const(buf
+ 8, buf_len
- 8);
97 status
= gensec_unwrap(gensec
, frame
, &in_buf
, &out_buf
);
99 if (!NT_STATUS_IS_OK(status
)) {
100 DEBUG(0,("common_gensec_decrypt_buffer: gensec_unwrap failed. Error %s\n",
106 if (out_buf
.length
> in_buf
.length
) {
107 DEBUG(0,("common_gensec_decrypt_buffer: gensec_unwrap size (%u) too large (%u) !\n",
108 (unsigned int)out_buf
.length
,
109 (unsigned int)in_buf
.length
));
111 return NT_STATUS_INVALID_PARAMETER
;
114 memcpy(buf
+ 8, out_buf
.data
, out_buf
.length
);
116 /* Reset the length and overwrite the header. */
117 smb_setlen_nbt(buf
, out_buf
.length
+ 4);
124 /******************************************************************************
125 Generic code for client and server.
126 NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
127 ******************************************************************************/
129 static NTSTATUS
common_gensec_encrypt_buffer(struct gensec_security
*gensec
,
130 uint16_t enc_ctx_num
,
135 DATA_BLOB in_buf
, out_buf
;
136 size_t buf_len
= smb_len_nbt(buf
) + 4; /* Don't forget the 4 length bytes. */
142 return NT_STATUS_BUFFER_TOO_SMALL
;
144 in_buf
= data_blob_const(buf
+ 8, buf_len
- 8);
146 frame
= talloc_stackframe();
148 status
= gensec_wrap(gensec
, frame
, &in_buf
, &out_buf
);
149 if (!NT_STATUS_IS_OK(status
)) {
150 DEBUG(0,("common_gensec_encrypt_buffer: gensec_wrap failed. Error %s\n",
156 *ppbuf_out
= (char *)malloc(out_buf
.length
+ 8); /* We know this can't wrap. */
159 return NT_STATUS_NO_MEMORY
;
162 memcpy(*ppbuf_out
+8, out_buf
.data
, out_buf
.length
);
163 smb_set_enclen(*ppbuf_out
, out_buf
.length
+ 4, enc_ctx_num
);
170 /******************************************************************************
171 Generic code for client and server.
172 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
173 ******************************************************************************/
175 NTSTATUS
common_encrypt_buffer(struct smb_trans_enc_state
*es
, char *buffer
, char **buf_out
)
177 if (!common_encryption_on(es
)) {
178 /* Not encrypting. */
183 return common_gensec_encrypt_buffer(es
->gensec_security
, es
->enc_ctx_num
, buffer
, buf_out
);
186 /******************************************************************************
187 Generic code for client and server.
188 Decrypt an incoming SMB buffer. Replaces the data within it.
189 New data must be less than or equal to the current length.
190 ******************************************************************************/
192 NTSTATUS
common_decrypt_buffer(struct smb_trans_enc_state
*es
, char *buf
)
194 if (!common_encryption_on(es
)) {
195 /* Not decrypting. */
199 return common_gensec_decrypt_buffer(es
->gensec_security
, buf
);
202 /******************************************************************************
203 Free an encryption-allocated buffer.
204 ******************************************************************************/
206 void common_free_enc_buffer(struct smb_trans_enc_state
*es
, char *buf
)
208 uint16_t enc_ctx_num
;
210 if (!common_encryption_on(es
)) {
214 if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf
,