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"
25 #include "libcli/auth/krb5_wrap.h"
28 /******************************************************************************
29 Pull out the encryption context for this packet. 0 means global context.
30 ******************************************************************************/
32 NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16_t *p_enc_ctx_num)
34 if (smb_len_nbt(buf) < 8) {
35 return NT_STATUS_INVALID_BUFFER_SIZE;
39 if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
40 /* Not an encrypted buffer. */
41 return NT_STATUS_NOT_FOUND;
44 *p_enc_ctx_num = SVAL(buf,6);
48 return NT_STATUS_INVALID_NETWORK_RESPONSE;
51 /*******************************************************************
52 Set the length and marker of an encrypted smb packet.
53 ********************************************************************/
55 static void smb_set_enclen(char *buf,int len,uint16_t enc_ctx_num)
57 _smb_setlen_nbt(buf,len);
61 SSVAL(buf,6,enc_ctx_num);
64 /******************************************************************************
65 Generic code for client and server.
66 Is encryption turned on ?
67 ******************************************************************************/
69 bool common_encryption_on(struct smb_trans_enc_state *es)
71 return ((es != NULL) && es->enc_on);
74 /******************************************************************************
75 Generic code for client and server.
76 NTLM decrypt an incoming buffer.
77 Abartlett tells me that SSPI puts the signature first before the encrypted
78 output, so cope with the same for compatibility.
79 ******************************************************************************/
81 static NTSTATUS common_ntlm_decrypt_buffer(struct auth_ntlmssp_state *auth_ntlmssp_state, char *buf)
84 size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
89 if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
90 return NT_STATUS_BUFFER_TOO_SMALL;
93 inbuf = (char *)smb_xmemdup(buf, buf_len);
95 /* Adjust for the signature. */
96 data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
98 /* Point at the signature. */
99 sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
101 status = auth_ntlmssp_unseal_packet(auth_ntlmssp_state,
102 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
104 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
108 if (!NT_STATUS_IS_OK(status)) {
113 memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
115 /* Reset the length and overwrite the header. */
116 smb_setlen_nbt(buf,data_len + 4);
122 /******************************************************************************
123 Generic code for client and server.
124 NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
125 Abartlett tells me that SSPI puts the signature first before the encrypted
126 output, so do the same for compatibility.
127 ******************************************************************************/
129 static NTSTATUS common_ntlm_encrypt_buffer(struct auth_ntlmssp_state *auth_ntlmssp_state,
130 uint16_t enc_ctx_num,
136 size_t data_len = smb_len_nbt(buf) - 4; /* Ignore the 0xFF SMB bytes. */
142 return NT_STATUS_BUFFER_TOO_SMALL;
145 frame = talloc_stackframe();
147 * We know smb_len_nbt can't return a value > 128k, so no int overflow
151 buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
153 /* Copy the data from the original buffer. */
155 memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
157 smb_set_enclen(buf_out, smb_len_nbt(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
161 status = auth_ntlmssp_seal_packet(auth_ntlmssp_state,
163 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
165 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
169 if (!NT_STATUS_IS_OK(status)) {
175 /* First 16 data bytes are signature for SSPI compatibility. */
176 memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
178 *ppbuf_out = buf_out;
182 /******************************************************************************
183 Generic code for client and server.
184 gss-api decrypt an incoming buffer. We insist that the size of the
185 unwrapped buffer must be smaller or identical to the incoming buffer.
186 ******************************************************************************/
188 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
189 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
191 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
195 gss_buffer_desc in_buf, out_buf;
196 size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
199 return NT_STATUS_BUFFER_TOO_SMALL;
202 in_buf.value = buf + 8;
203 in_buf.length = buf_len - 8;
205 ret = gss_unwrap(&minor,
209 &flags_got, /* did we get sign+seal ? */
212 if (ret != GSS_S_COMPLETE) {
213 NTSTATUS status = NT_STATUS_ACCESS_DENIED;
216 gss_err = gssapi_error_string(talloc_tos(),
219 DEBUG(0,("common_gss_decrypt_buffer: gss_unwrap failed. "
220 "Error [%d/%d] - %s - %s\n",
221 ret, minor, nt_errstr(status),
222 gss_err ? gss_err : "<unknown>"));
223 talloc_free(gss_err);
228 if (out_buf.length > in_buf.length) {
229 DEBUG(0,("common_gss_decrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
230 (unsigned int)out_buf.length,
231 (unsigned int)in_buf.length ));
232 gss_release_buffer(&minor, &out_buf);
233 return NT_STATUS_INVALID_PARAMETER;
236 memcpy(buf + 8, out_buf.value, out_buf.length);
237 /* Reset the length and overwrite the header. */
238 smb_setlen_nbt(buf, out_buf.length + 4);
240 gss_release_buffer(&minor, &out_buf);
244 /******************************************************************************
245 Generic code for client and server.
246 gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
247 ******************************************************************************/
249 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
250 uint16_t enc_ctx_num,
254 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
258 gss_buffer_desc in_buf, out_buf;
259 size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
264 return NT_STATUS_BUFFER_TOO_SMALL;
267 in_buf.value = buf + 8;
268 in_buf.length = buf_len - 8;
270 ret = gss_wrap(&minor,
272 true, /* we want sign+seal. */
275 &flags_got, /* did we get sign+seal ? */
278 if (ret != GSS_S_COMPLETE) {
279 NTSTATUS status = NT_STATUS_ACCESS_DENIED;
282 gss_err = gssapi_error_string(talloc_tos(),
285 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. "
286 "Error [%d/%d] - %s - %s\n",
287 ret, minor, nt_errstr(status),
288 gss_err ? gss_err : "<unknown>"));
289 talloc_free(gss_err);
295 /* Sign+seal not supported. */
296 gss_release_buffer(&minor, &out_buf);
297 return NT_STATUS_NOT_SUPPORTED;
300 /* Ya see - this is why I *hate* gss-api. I don't
301 * want to have to malloc another buffer of the
302 * same size + 8 bytes just to get a continuous
303 * header + buffer, but gss won't let me pass in
304 * a pre-allocated buffer. Bastards (and you know
305 * who you are....). I might fix this by
306 * going to "encrypt_and_send" passing in a file
307 * descriptor and doing scatter-gather write with
308 * TCP cork on Linux. But I shouldn't have to
312 *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
314 gss_release_buffer(&minor, &out_buf);
315 return NT_STATUS_NO_MEMORY;
318 memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
319 smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
321 gss_release_buffer(&minor, &out_buf);
326 /******************************************************************************
327 Generic code for client and server.
328 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
329 ******************************************************************************/
331 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
333 if (!common_encryption_on(es)) {
334 /* Not encrypting. */
339 switch (es->smb_enc_type) {
340 case SMB_TRANS_ENC_NTLM:
341 return common_ntlm_encrypt_buffer(es->s.auth_ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
342 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
343 case SMB_TRANS_ENC_GSS:
344 return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
347 return NT_STATUS_NOT_SUPPORTED;
351 /******************************************************************************
352 Generic code for client and server.
353 Decrypt an incoming SMB buffer. Replaces the data within it.
354 New data must be less than or equal to the current length.
355 ******************************************************************************/
357 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
359 if (!common_encryption_on(es)) {
360 /* Not decrypting. */
364 switch (es->smb_enc_type) {
365 case SMB_TRANS_ENC_NTLM:
366 return common_ntlm_decrypt_buffer(es->s.auth_ntlmssp_state, buf);
367 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
368 case SMB_TRANS_ENC_GSS:
369 return common_gss_decrypt_buffer(es->s.gss_state, buf);
372 return NT_STATUS_NOT_SUPPORTED;
376 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
377 /******************************************************************************
378 Shutdown a gss encryption state.
379 ******************************************************************************/
381 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
384 struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
386 if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
387 gss_release_cred(&minor, &gss_state->creds);
389 if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
390 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
392 SAFE_FREE(*pp_gss_state);
396 /******************************************************************************
397 Shutdown an encryption state.
398 ******************************************************************************/
400 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
402 struct smb_trans_enc_state *es = *pp_es;
408 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
409 if (es->s.auth_ntlmssp_state) {
410 TALLOC_FREE(es->s.auth_ntlmssp_state);
413 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
414 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
415 /* Free the gss context handle. */
416 if (es->s.gss_state) {
417 common_free_gss_state(&es->s.gss_state);
425 /******************************************************************************
426 Free an encryption-allocated buffer.
427 ******************************************************************************/
429 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
431 uint16_t enc_ctx_num;
433 if (!common_encryption_on(es)) {
437 if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
442 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
447 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
448 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
450 gss_buffer_desc rel_buf;
452 rel_buf.length = smb_len_nbt(buf) + 4;
453 gss_release_buffer(&min, &rel_buf);