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"
26 #include "auth/gensec/gensec.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 NTLM decrypt an incoming buffer.
79 Abartlett tells me that SSPI puts the signature first before the encrypted
80 output, so cope with the same for compatibility.
81 ******************************************************************************/
83 static NTSTATUS common_ntlm_decrypt_buffer(struct auth_ntlmssp_state *auth_ntlmssp_state, char *buf)
86 size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
91 if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
92 return NT_STATUS_BUFFER_TOO_SMALL;
95 inbuf = (char *)smb_xmemdup(buf, buf_len);
97 /* Adjust for the signature. */
98 data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
100 /* Point at the signature. */
101 sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
103 status = gensec_unseal_packet(auth_ntlmssp_state->gensec_security,
104 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
106 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
110 if (!NT_STATUS_IS_OK(status)) {
115 memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
117 /* Reset the length and overwrite the header. */
118 smb_setlen_nbt(buf,data_len + 4);
124 /******************************************************************************
125 Generic code for client and server.
126 NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
127 Abartlett tells me that SSPI puts the signature first before the encrypted
128 output, so do the same for compatibility.
129 ******************************************************************************/
131 static NTSTATUS common_ntlm_encrypt_buffer(struct auth_ntlmssp_state *auth_ntlmssp_state,
132 uint16_t enc_ctx_num,
138 size_t data_len = smb_len_nbt(buf) - 4; /* Ignore the 0xFF SMB bytes. */
144 return NT_STATUS_BUFFER_TOO_SMALL;
147 frame = talloc_stackframe();
149 * We know smb_len_nbt can't return a value > 128k, so no int overflow
153 buf_out = (char *)malloc(8 + NTLMSSP_SIG_SIZE + data_len);
154 if (buf_out == NULL) {
156 return NT_STATUS_NO_MEMORY;
159 /* Copy the data from the original buffer. */
161 memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
163 smb_set_enclen(buf_out, smb_len_nbt(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
167 status = gensec_seal_packet(auth_ntlmssp_state->gensec_security,
169 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
171 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
175 if (!NT_STATUS_IS_OK(status)) {
181 /* First 16 data bytes are signature for SSPI compatibility. */
182 memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
184 *ppbuf_out = buf_out;
188 /******************************************************************************
189 Generic code for client and server.
190 gss-api decrypt an incoming buffer. We insist that the size of the
191 unwrapped buffer must be smaller or identical to the incoming buffer.
192 ******************************************************************************/
194 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
195 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
197 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
201 gss_buffer_desc in_buf, out_buf;
202 size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
205 return NT_STATUS_BUFFER_TOO_SMALL;
208 in_buf.value = buf + 8;
209 in_buf.length = buf_len - 8;
211 ret = gss_unwrap(&minor,
215 &flags_got, /* did we get sign+seal ? */
218 if (ret != GSS_S_COMPLETE) {
219 NTSTATUS status = NT_STATUS_ACCESS_DENIED;
222 gss_err = gssapi_error_string(talloc_tos(),
225 DEBUG(0,("common_gss_decrypt_buffer: gss_unwrap failed. "
226 "Error [%d/%d] - %s - %s\n",
227 ret, minor, nt_errstr(status),
228 gss_err ? gss_err : "<unknown>"));
229 talloc_free(gss_err);
234 if (out_buf.length > in_buf.length) {
235 DEBUG(0,("common_gss_decrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
236 (unsigned int)out_buf.length,
237 (unsigned int)in_buf.length ));
238 gss_release_buffer(&minor, &out_buf);
239 return NT_STATUS_INVALID_PARAMETER;
242 memcpy(buf + 8, out_buf.value, out_buf.length);
243 /* Reset the length and overwrite the header. */
244 smb_setlen_nbt(buf, out_buf.length + 4);
246 gss_release_buffer(&minor, &out_buf);
250 /******************************************************************************
251 Generic code for client and server.
252 gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
253 ******************************************************************************/
255 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
256 uint16_t enc_ctx_num,
260 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
264 gss_buffer_desc in_buf, out_buf;
265 size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
270 return NT_STATUS_BUFFER_TOO_SMALL;
273 in_buf.value = buf + 8;
274 in_buf.length = buf_len - 8;
276 ret = gss_wrap(&minor,
278 true, /* we want sign+seal. */
281 &flags_got, /* did we get sign+seal ? */
284 if (ret != GSS_S_COMPLETE) {
285 NTSTATUS status = NT_STATUS_ACCESS_DENIED;
288 gss_err = gssapi_error_string(talloc_tos(),
291 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. "
292 "Error [%d/%d] - %s - %s\n",
293 ret, minor, nt_errstr(status),
294 gss_err ? gss_err : "<unknown>"));
295 talloc_free(gss_err);
301 /* Sign+seal not supported. */
302 gss_release_buffer(&minor, &out_buf);
303 return NT_STATUS_NOT_SUPPORTED;
306 /* Ya see - this is why I *hate* gss-api. I don't
307 * want to have to malloc another buffer of the
308 * same size + 8 bytes just to get a continuous
309 * header + buffer, but gss won't let me pass in
310 * a pre-allocated buffer. Bastards (and you know
311 * who you are....). I might fix this by
312 * going to "encrypt_and_send" passing in a file
313 * descriptor and doing scatter-gather write with
314 * TCP cork on Linux. But I shouldn't have to
318 *ppbuf_out = (char *)malloc(out_buf.length + 8); /* We know this can't wrap. */
320 gss_release_buffer(&minor, &out_buf);
321 return NT_STATUS_NO_MEMORY;
324 memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
325 smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
327 gss_release_buffer(&minor, &out_buf);
332 /******************************************************************************
333 Generic code for client and server.
334 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
335 ******************************************************************************/
337 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
339 if (!common_encryption_on(es)) {
340 /* Not encrypting. */
345 switch (es->smb_enc_type) {
346 case SMB_TRANS_ENC_NTLM:
347 return common_ntlm_encrypt_buffer(es->s.auth_ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
348 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
349 case SMB_TRANS_ENC_GSS:
350 return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
353 return NT_STATUS_NOT_SUPPORTED;
357 /******************************************************************************
358 Generic code for client and server.
359 Decrypt an incoming SMB buffer. Replaces the data within it.
360 New data must be less than or equal to the current length.
361 ******************************************************************************/
363 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
365 if (!common_encryption_on(es)) {
366 /* Not decrypting. */
370 switch (es->smb_enc_type) {
371 case SMB_TRANS_ENC_NTLM:
372 return common_ntlm_decrypt_buffer(es->s.auth_ntlmssp_state, buf);
373 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
374 case SMB_TRANS_ENC_GSS:
375 return common_gss_decrypt_buffer(es->s.gss_state, buf);
378 return NT_STATUS_NOT_SUPPORTED;
382 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
383 /******************************************************************************
384 Shutdown a gss encryption state.
385 ******************************************************************************/
387 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
390 struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
392 if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
393 gss_release_cred(&minor, &gss_state->creds);
395 if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
396 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
398 SAFE_FREE(*pp_gss_state);
402 /******************************************************************************
403 Shutdown an encryption state.
404 ******************************************************************************/
406 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
408 struct smb_trans_enc_state *es = *pp_es;
414 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
415 if (es->s.auth_ntlmssp_state) {
416 TALLOC_FREE(es->s.auth_ntlmssp_state);
419 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
420 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
421 /* Free the gss context handle. */
422 if (es->s.gss_state) {
423 common_free_gss_state(&es->s.gss_state);
431 /******************************************************************************
432 Free an encryption-allocated buffer.
433 ******************************************************************************/
435 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
437 uint16_t enc_ctx_num;
439 if (!common_encryption_on(es)) {
443 if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,