r25068: Older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for every opcode on the
[Samba.git] / source / libsmb / smb_seal.c
blob81c6ff1bac210599271c67ac3517f2673473a655
1 /*
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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 /******************************************************************************
24 Pull out the encryption context for this packet. 0 means global context.
25 ******************************************************************************/
27 NTSTATUS get_enc_ctx_num(char *buf, uint16 *p_enc_ctx_num)
29 if (smb_len(buf) < 8) {
30 return NT_STATUS_INVALID_BUFFER_SIZE;
33 if (buf[4] == (char)0xFF) {
34 if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
35 /* Not an encrypted buffer. */
36 return NT_STATUS_NOT_FOUND;
38 if (buf[5] == 'E') {
39 *p_enc_ctx_num = SVAL(buf,6);
40 return NT_STATUS_OK;
43 return NT_STATUS_INVALID_NETWORK_RESPONSE;
46 /******************************************************************************
47 Generic code for client and server.
48 Is encryption turned on ?
49 ******************************************************************************/
51 BOOL common_encryption_on(struct smb_trans_enc_state *es)
53 return ((es != NULL) && es->enc_on);
56 /******************************************************************************
57 Generic code for client and server.
58 NTLM decrypt an incoming buffer.
59 Abartlett tells me that SSPI puts the signature first before the encrypted
60 output, so cope with the same for compatibility.
61 ******************************************************************************/
63 NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
65 NTSTATUS status;
66 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
67 size_t data_len;
68 char *inbuf;
69 DATA_BLOB sig;
71 if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
72 return NT_STATUS_BUFFER_TOO_SMALL;
75 inbuf = (char *)smb_xmemdup(buf, buf_len);
77 /* Adjust for the signature. */
78 data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
80 /* Point at the signature. */
81 sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
83 status = ntlmssp_unseal_packet(ntlmssp_state,
84 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
85 data_len,
86 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
87 data_len,
88 &sig);
90 if (!NT_STATUS_IS_OK(status)) {
91 SAFE_FREE(inbuf);
92 return status;
95 memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
97 /* Reset the length. */
98 smb_setlen(inbuf, buf, data_len + 4);
100 SAFE_FREE(inbuf);
101 return NT_STATUS_OK;
104 /******************************************************************************
105 Generic code for client and server.
106 NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
107 Abartlett tells me that SSPI puts the signature first before the encrypted
108 output, so do the same for compatibility.
109 ******************************************************************************/
111 NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state,
112 uint16 enc_ctx_num,
113 char *buf,
114 char **ppbuf_out)
116 NTSTATUS status;
117 char *buf_out;
118 size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
119 DATA_BLOB sig;
121 *ppbuf_out = NULL;
123 if (data_len == 0) {
124 return NT_STATUS_BUFFER_TOO_SMALL;
128 * We know smb_len can't return a value > 128k, so no int overflow
129 * check needed.
132 buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
134 /* Copy the data from the original buffer. */
136 memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
138 smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
140 sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
142 status = ntlmssp_seal_packet(ntlmssp_state,
143 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
144 data_len,
145 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
146 data_len,
147 &sig);
149 if (!NT_STATUS_IS_OK(status)) {
150 data_blob_free(&sig);
151 SAFE_FREE(buf_out);
152 return status;
155 /* First 16 data bytes are signature for SSPI compatibility. */
156 memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
157 *ppbuf_out = buf_out;
158 return NT_STATUS_OK;
161 /******************************************************************************
162 Generic code for client and server.
163 gss-api decrypt an incoming buffer. We insist that the size of the
164 unwrapped buffer must be smaller or identical to the incoming buffer.
165 ******************************************************************************/
167 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
168 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
170 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
171 OM_uint32 ret = 0;
172 OM_uint32 minor = 0;
173 int flags_got = 0;
174 gss_buffer_desc in_buf, out_buf;
175 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
177 if (buf_len < 8) {
178 return NT_STATUS_BUFFER_TOO_SMALL;
181 in_buf.value = buf + 8;
182 in_buf.length = buf_len - 8;
184 ret = gss_unwrap(&minor,
185 gss_ctx,
186 &in_buf,
187 &out_buf,
188 &flags_got, /* did we get sign+seal ? */
189 (gss_qop_t *) NULL);
191 if (ret != GSS_S_COMPLETE) {
192 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
193 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
194 ads_errstr(adss) ));
195 return map_nt_error_from_gss(ret, minor);
198 if (out_buf.length > in_buf.length) {
199 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
200 (unsigned int)out_buf.length,
201 (unsigned int)in_buf.length ));
202 gss_release_buffer(&minor, &out_buf);
203 return NT_STATUS_INVALID_PARAMETER;
206 memcpy(buf + 8, out_buf.value, out_buf.length);
207 smb_setlen((char *)out_buf.value, buf, out_buf.length + 4);
209 gss_release_buffer(&minor, &out_buf);
210 return NT_STATUS_OK;
213 /******************************************************************************
214 Generic code for client and server.
215 gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
216 ******************************************************************************/
218 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
219 uint16 enc_ctx_num,
220 char *buf,
221 char **ppbuf_out)
223 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
224 OM_uint32 ret = 0;
225 OM_uint32 minor = 0;
226 int flags_got = 0;
227 gss_buffer_desc in_buf, out_buf;
228 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
230 *ppbuf_out = NULL;
232 if (buf_len < 8) {
233 return NT_STATUS_BUFFER_TOO_SMALL;
236 in_buf.value = buf + 8;
237 in_buf.length = buf_len - 8;
239 ret = gss_wrap(&minor,
240 gss_ctx,
241 True, /* we want sign+seal. */
242 GSS_C_QOP_DEFAULT,
243 &in_buf,
244 &flags_got, /* did we get sign+seal ? */
245 &out_buf);
247 if (ret != GSS_S_COMPLETE) {
248 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
249 DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
250 ads_errstr(adss) ));
251 return map_nt_error_from_gss(ret, minor);
254 if (!flags_got) {
255 /* Sign+seal not supported. */
256 gss_release_buffer(&minor, &out_buf);
257 return NT_STATUS_NOT_SUPPORTED;
260 /* Ya see - this is why I *hate* gss-api. I don't
261 * want to have to malloc another buffer of the
262 * same size + 8 bytes just to get a continuous
263 * header + buffer, but gss won't let me pass in
264 * a pre-allocated buffer. Bastards (and you know
265 * who you are....). I might fix this by
266 * going to "encrypt_and_send" passing in a file
267 * descriptor and doing scatter-gather write with
268 * TCP cork on Linux. But I shouldn't have to
269 * bother :-*(. JRA.
272 *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
273 if (!*ppbuf_out) {
274 gss_release_buffer(&minor, &out_buf);
275 return NT_STATUS_NO_MEMORY;
278 memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
279 smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
281 gss_release_buffer(&minor, &out_buf);
282 return NT_STATUS_OK;
284 #endif
286 /******************************************************************************
287 Generic code for client and server.
288 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
289 ******************************************************************************/
291 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
293 if (!common_encryption_on(es)) {
294 /* Not encrypting. */
295 *buf_out = buffer;
296 return NT_STATUS_OK;
299 switch (es->smb_enc_type) {
300 case SMB_TRANS_ENC_NTLM:
301 return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
302 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
303 case SMB_TRANS_ENC_GSS:
304 return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
305 #endif
306 default:
307 return NT_STATUS_NOT_SUPPORTED;
311 /******************************************************************************
312 Generic code for client and server.
313 Decrypt an incoming SMB buffer. Replaces the data within it.
314 New data must be less than or equal to the current length.
315 ******************************************************************************/
317 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
319 if (!common_encryption_on(es)) {
320 /* Not decrypting. */
321 return NT_STATUS_OK;
324 switch (es->smb_enc_type) {
325 case SMB_TRANS_ENC_NTLM:
326 return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
327 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
328 case SMB_TRANS_ENC_GSS:
329 return common_gss_decrypt_buffer(es->s.gss_state, buf);
330 #endif
331 default:
332 return NT_STATUS_NOT_SUPPORTED;
336 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
337 /******************************************************************************
338 Shutdown a gss encryption state.
339 ******************************************************************************/
341 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
343 OM_uint32 minor = 0;
344 struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
346 if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
347 gss_release_cred(&minor, &gss_state->creds);
349 if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
350 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
352 SAFE_FREE(*pp_gss_state);
354 #endif
356 /******************************************************************************
357 Shutdown an encryption state.
358 ******************************************************************************/
360 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
362 struct smb_trans_enc_state *es = *pp_es;
364 if (es == NULL) {
365 return;
368 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
369 if (es->s.ntlmssp_state) {
370 ntlmssp_end(&es->s.ntlmssp_state);
373 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
374 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
375 /* Free the gss context handle. */
376 if (es->s.gss_state) {
377 common_free_gss_state(&es->s.gss_state);
380 #endif
381 SAFE_FREE(es);
382 *pp_es = NULL;
385 /******************************************************************************
386 Free an encryption-allocated buffer.
387 ******************************************************************************/
389 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
391 if (!common_encryption_on(es)) {
392 return;
395 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
396 SAFE_FREE(buf);
397 return;
400 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
401 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
402 OM_uint32 min;
403 gss_buffer_desc rel_buf;
404 rel_buf.value = buf;
405 rel_buf.length = smb_len(buf) + 4;
406 gss_release_buffer(&min, &rel_buf);
408 #endif
411 /******************************************************************************
412 Client side encryption.
413 ******************************************************************************/
415 /******************************************************************************
416 Is client encryption on ?
417 ******************************************************************************/
419 BOOL cli_encryption_on(struct cli_state *cli)
421 /* If we supported multiple encrytion contexts
422 * here we'd look up based on tid.
424 return common_encryption_on(cli->trans_enc_state);
427 /******************************************************************************
428 Shutdown a client encryption state.
429 ******************************************************************************/
431 void cli_free_encryption_context(struct cli_state *cli)
433 common_free_encryption_state(&cli->trans_enc_state);
436 /******************************************************************************
437 Free an encryption-allocated buffer.
438 ******************************************************************************/
440 void cli_free_enc_buffer(struct cli_state *cli, char *buf)
442 /* We know this is an smb buffer, and we
443 * didn't malloc, only copy, for a keepalive,
444 * so ignore session keepalives. */
446 if(CVAL(buf,0) == SMBkeepalive) {
447 return;
450 /* If we supported multiple encrytion contexts
451 * here we'd look up based on tid.
453 common_free_enc_buffer(cli->trans_enc_state, buf);
456 /******************************************************************************
457 Decrypt an incoming buffer.
458 ******************************************************************************/
460 NTSTATUS cli_decrypt_message(struct cli_state *cli)
462 NTSTATUS status;
463 uint16 enc_ctx_num;
465 /* Ignore session keepalives. */
466 if(CVAL(cli->inbuf,0) == SMBkeepalive) {
467 return NT_STATUS_OK;
470 status = get_enc_ctx_num(cli->inbuf, &enc_ctx_num);
471 if (!NT_STATUS_IS_OK(status)) {
472 return status;
475 if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
476 return NT_STATUS_INVALID_HANDLE;
479 return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
482 /******************************************************************************
483 Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
484 ******************************************************************************/
486 NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
488 /* Ignore session keepalives. */
489 if(CVAL(cli->outbuf,0) == SMBkeepalive) {
490 return NT_STATUS_OK;
493 /* If we supported multiple encrytion contexts
494 * here we'd look up based on tid.
496 return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out);