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 "../auth/ntlmssp/ntlmssp.h"
22 #include "smb_crypt.h"
23 #include "libsmb/libsmb.h"
24 #include "ntlmssp_wrap.h"
27 /******************************************************************************
28 Pull out the encryption context for this packet. 0 means global context.
29 ******************************************************************************/
31 NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16_t *p_enc_ctx_num)
33 if (smb_len_nbt(buf) < 8) {
34 return NT_STATUS_INVALID_BUFFER_SIZE;
38 if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
39 /* Not an encrypted buffer. */
40 return NT_STATUS_NOT_FOUND;
43 *p_enc_ctx_num = SVAL(buf,6);
47 return NT_STATUS_INVALID_NETWORK_RESPONSE;
50 /*******************************************************************
51 Set the length and marker of an encrypted smb packet.
52 ********************************************************************/
54 static void smb_set_enclen(char *buf,int len,uint16_t enc_ctx_num)
56 _smb_setlen_nbt(buf,len);
60 SSVAL(buf,6,enc_ctx_num);
63 /******************************************************************************
64 Generic code for client and server.
65 Is encryption turned on ?
66 ******************************************************************************/
68 bool common_encryption_on(struct smb_trans_enc_state *es)
70 return ((es != NULL) && es->enc_on);
73 /******************************************************************************
74 Generic code for client and server.
75 NTLM decrypt an incoming buffer.
76 Abartlett tells me that SSPI puts the signature first before the encrypted
77 output, so cope with the same for compatibility.
78 ******************************************************************************/
80 static NTSTATUS common_ntlm_decrypt_buffer(struct auth_ntlmssp_state *auth_ntlmssp_state, char *buf)
83 size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
88 if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
89 return NT_STATUS_BUFFER_TOO_SMALL;
92 inbuf = (char *)smb_xmemdup(buf, buf_len);
94 /* Adjust for the signature. */
95 data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
97 /* Point at the signature. */
98 sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
100 status = auth_ntlmssp_unseal_packet(auth_ntlmssp_state,
101 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
103 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
107 if (!NT_STATUS_IS_OK(status)) {
112 memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
114 /* Reset the length and overwrite the header. */
115 smb_setlen_nbt(buf,data_len + 4);
121 /******************************************************************************
122 Generic code for client and server.
123 NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
124 Abartlett tells me that SSPI puts the signature first before the encrypted
125 output, so do the same for compatibility.
126 ******************************************************************************/
128 static NTSTATUS common_ntlm_encrypt_buffer(struct auth_ntlmssp_state *auth_ntlmssp_state,
129 uint16_t enc_ctx_num,
135 size_t data_len = smb_len_nbt(buf) - 4; /* Ignore the 0xFF SMB bytes. */
141 return NT_STATUS_BUFFER_TOO_SMALL;
144 frame = talloc_stackframe();
146 * We know smb_len_nbt can't return a value > 128k, so no int overflow
150 buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
152 /* Copy the data from the original buffer. */
154 memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
156 smb_set_enclen(buf_out, smb_len_nbt(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
160 status = auth_ntlmssp_seal_packet(auth_ntlmssp_state,
162 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
164 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
168 if (!NT_STATUS_IS_OK(status)) {
174 /* First 16 data bytes are signature for SSPI compatibility. */
175 memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
177 *ppbuf_out = buf_out;
181 /******************************************************************************
182 Generic code for client and server.
183 gss-api decrypt an incoming buffer. We insist that the size of the
184 unwrapped buffer must be smaller or identical to the incoming buffer.
185 ******************************************************************************/
187 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
188 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
190 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
194 gss_buffer_desc in_buf, out_buf;
195 size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
198 return NT_STATUS_BUFFER_TOO_SMALL;
201 in_buf.value = buf + 8;
202 in_buf.length = buf_len - 8;
204 ret = gss_unwrap(&minor,
208 &flags_got, /* did we get sign+seal ? */
211 if (ret != GSS_S_COMPLETE) {
212 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
213 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
215 return map_nt_error_from_gss(ret, minor);
218 if (out_buf.length > in_buf.length) {
219 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
220 (unsigned int)out_buf.length,
221 (unsigned int)in_buf.length ));
222 gss_release_buffer(&minor, &out_buf);
223 return NT_STATUS_INVALID_PARAMETER;
226 memcpy(buf + 8, out_buf.value, out_buf.length);
227 /* Reset the length and overwrite the header. */
228 smb_setlen_nbt(buf, out_buf.length + 4);
230 gss_release_buffer(&minor, &out_buf);
234 /******************************************************************************
235 Generic code for client and server.
236 gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
237 ******************************************************************************/
239 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
240 uint16_t enc_ctx_num,
244 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
248 gss_buffer_desc in_buf, out_buf;
249 size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
254 return NT_STATUS_BUFFER_TOO_SMALL;
257 in_buf.value = buf + 8;
258 in_buf.length = buf_len - 8;
260 ret = gss_wrap(&minor,
262 true, /* we want sign+seal. */
265 &flags_got, /* did we get sign+seal ? */
268 if (ret != GSS_S_COMPLETE) {
269 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
270 DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
272 return map_nt_error_from_gss(ret, minor);
276 /* Sign+seal not supported. */
277 gss_release_buffer(&minor, &out_buf);
278 return NT_STATUS_NOT_SUPPORTED;
281 /* Ya see - this is why I *hate* gss-api. I don't
282 * want to have to malloc another buffer of the
283 * same size + 8 bytes just to get a continuous
284 * header + buffer, but gss won't let me pass in
285 * a pre-allocated buffer. Bastards (and you know
286 * who you are....). I might fix this by
287 * going to "encrypt_and_send" passing in a file
288 * descriptor and doing scatter-gather write with
289 * TCP cork on Linux. But I shouldn't have to
293 *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
295 gss_release_buffer(&minor, &out_buf);
296 return NT_STATUS_NO_MEMORY;
299 memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
300 smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
302 gss_release_buffer(&minor, &out_buf);
307 /******************************************************************************
308 Generic code for client and server.
309 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
310 ******************************************************************************/
312 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
314 if (!common_encryption_on(es)) {
315 /* Not encrypting. */
320 switch (es->smb_enc_type) {
321 case SMB_TRANS_ENC_NTLM:
322 return common_ntlm_encrypt_buffer(es->s.auth_ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
323 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
324 case SMB_TRANS_ENC_GSS:
325 return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
328 return NT_STATUS_NOT_SUPPORTED;
332 /******************************************************************************
333 Generic code for client and server.
334 Decrypt an incoming SMB buffer. Replaces the data within it.
335 New data must be less than or equal to the current length.
336 ******************************************************************************/
338 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
340 if (!common_encryption_on(es)) {
341 /* Not decrypting. */
345 switch (es->smb_enc_type) {
346 case SMB_TRANS_ENC_NTLM:
347 return common_ntlm_decrypt_buffer(es->s.auth_ntlmssp_state, buf);
348 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
349 case SMB_TRANS_ENC_GSS:
350 return common_gss_decrypt_buffer(es->s.gss_state, buf);
353 return NT_STATUS_NOT_SUPPORTED;
357 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
358 /******************************************************************************
359 Shutdown a gss encryption state.
360 ******************************************************************************/
362 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
365 struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
367 if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
368 gss_release_cred(&minor, &gss_state->creds);
370 if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
371 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
373 SAFE_FREE(*pp_gss_state);
377 /******************************************************************************
378 Shutdown an encryption state.
379 ******************************************************************************/
381 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
383 struct smb_trans_enc_state *es = *pp_es;
389 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
390 if (es->s.auth_ntlmssp_state) {
391 TALLOC_FREE(es->s.auth_ntlmssp_state);
394 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
395 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
396 /* Free the gss context handle. */
397 if (es->s.gss_state) {
398 common_free_gss_state(&es->s.gss_state);
406 /******************************************************************************
407 Free an encryption-allocated buffer.
408 ******************************************************************************/
410 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
412 uint16_t enc_ctx_num;
414 if (!common_encryption_on(es)) {
418 if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
423 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
428 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
429 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
431 gss_buffer_desc rel_buf;
433 rel_buf.length = smb_len_nbt(buf) + 4;
434 gss_release_buffer(&min, &rel_buf);