s3-libsmb: move smb encryption structs into own header.
[Samba.git] / source3 / libsmb / smb_seal.c
blob0eed15d4a3c1ff28ae90d51914ee32612a3cf9e2
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 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/>.
20 #include "includes.h"
21 #include "../libcli/auth/ntlmssp.h"
22 #include "smb_crypt.h"
24 /******************************************************************************
25 Pull out the encryption context for this packet. 0 means global context.
26 ******************************************************************************/
28 NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
30 if (smb_len(buf) < 8) {
31 return NT_STATUS_INVALID_BUFFER_SIZE;
34 if (buf[4] == 0xFF) {
35 if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
36 /* Not an encrypted buffer. */
37 return NT_STATUS_NOT_FOUND;
39 if (buf[5] == 'E') {
40 *p_enc_ctx_num = SVAL(buf,6);
41 return NT_STATUS_OK;
44 return NT_STATUS_INVALID_NETWORK_RESPONSE;
47 /******************************************************************************
48 Generic code for client and server.
49 Is encryption turned on ?
50 ******************************************************************************/
52 bool common_encryption_on(struct smb_trans_enc_state *es)
54 return ((es != NULL) && es->enc_on);
57 /******************************************************************************
58 Generic code for client and server.
59 NTLM decrypt an incoming buffer.
60 Abartlett tells me that SSPI puts the signature first before the encrypted
61 output, so cope with the same for compatibility.
62 ******************************************************************************/
64 NTSTATUS common_ntlm_decrypt_buffer(struct ntlmssp_state *ntlmssp_state, char *buf)
66 NTSTATUS status;
67 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
68 size_t data_len;
69 char *inbuf;
70 DATA_BLOB sig;
72 if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
73 return NT_STATUS_BUFFER_TOO_SMALL;
76 inbuf = (char *)smb_xmemdup(buf, buf_len);
78 /* Adjust for the signature. */
79 data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
81 /* Point at the signature. */
82 sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
84 status = ntlmssp_unseal_packet(ntlmssp_state,
85 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
86 data_len,
87 (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
88 data_len,
89 &sig);
91 if (!NT_STATUS_IS_OK(status)) {
92 SAFE_FREE(inbuf);
93 return status;
96 memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
98 /* Reset the length and overwrite the header. */
99 smb_setlen(buf,data_len + 4);
101 SAFE_FREE(inbuf);
102 return NT_STATUS_OK;
105 /******************************************************************************
106 Generic code for client and server.
107 NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
108 Abartlett tells me that SSPI puts the signature first before the encrypted
109 output, so do the same for compatibility.
110 ******************************************************************************/
112 NTSTATUS common_ntlm_encrypt_buffer(struct ntlmssp_state *ntlmssp_state,
113 uint16 enc_ctx_num,
114 char *buf,
115 char **ppbuf_out)
117 NTSTATUS status;
118 char *buf_out;
119 size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
120 DATA_BLOB sig;
121 TALLOC_CTX *frame;
122 *ppbuf_out = NULL;
124 if (data_len == 0) {
125 return NT_STATUS_BUFFER_TOO_SMALL;
128 frame = talloc_stackframe();
130 * We know smb_len can't return a value > 128k, so no int overflow
131 * check needed.
134 buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
136 /* Copy the data from the original buffer. */
138 memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
140 smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
142 ZERO_STRUCT(sig);
144 status = ntlmssp_seal_packet(ntlmssp_state,
145 frame,
146 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
147 data_len,
148 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
149 data_len,
150 &sig);
152 if (!NT_STATUS_IS_OK(status)) {
153 talloc_free(frame);
154 SAFE_FREE(buf_out);
155 return status;
158 /* First 16 data bytes are signature for SSPI compatibility. */
159 memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
160 talloc_free(frame);
161 *ppbuf_out = buf_out;
162 return NT_STATUS_OK;
165 /******************************************************************************
166 Generic code for client and server.
167 gss-api decrypt an incoming buffer. We insist that the size of the
168 unwrapped buffer must be smaller or identical to the incoming buffer.
169 ******************************************************************************/
171 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
172 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
174 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
175 OM_uint32 ret = 0;
176 OM_uint32 minor = 0;
177 int flags_got = 0;
178 gss_buffer_desc in_buf, out_buf;
179 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
181 if (buf_len < 8) {
182 return NT_STATUS_BUFFER_TOO_SMALL;
185 in_buf.value = buf + 8;
186 in_buf.length = buf_len - 8;
188 ret = gss_unwrap(&minor,
189 gss_ctx,
190 &in_buf,
191 &out_buf,
192 &flags_got, /* did we get sign+seal ? */
193 (gss_qop_t *) NULL);
195 if (ret != GSS_S_COMPLETE) {
196 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
197 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
198 ads_errstr(adss) ));
199 return map_nt_error_from_gss(ret, minor);
202 if (out_buf.length > in_buf.length) {
203 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
204 (unsigned int)out_buf.length,
205 (unsigned int)in_buf.length ));
206 gss_release_buffer(&minor, &out_buf);
207 return NT_STATUS_INVALID_PARAMETER;
210 memcpy(buf + 8, out_buf.value, out_buf.length);
211 /* Reset the length and overwrite the header. */
212 smb_setlen(buf, out_buf.length + 4);
214 gss_release_buffer(&minor, &out_buf);
215 return NT_STATUS_OK;
218 /******************************************************************************
219 Generic code for client and server.
220 gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
221 ******************************************************************************/
223 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
224 uint16 enc_ctx_num,
225 char *buf,
226 char **ppbuf_out)
228 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
229 OM_uint32 ret = 0;
230 OM_uint32 minor = 0;
231 int flags_got = 0;
232 gss_buffer_desc in_buf, out_buf;
233 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
235 *ppbuf_out = NULL;
237 if (buf_len < 8) {
238 return NT_STATUS_BUFFER_TOO_SMALL;
241 in_buf.value = buf + 8;
242 in_buf.length = buf_len - 8;
244 ret = gss_wrap(&minor,
245 gss_ctx,
246 true, /* we want sign+seal. */
247 GSS_C_QOP_DEFAULT,
248 &in_buf,
249 &flags_got, /* did we get sign+seal ? */
250 &out_buf);
252 if (ret != GSS_S_COMPLETE) {
253 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
254 DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
255 ads_errstr(adss) ));
256 return map_nt_error_from_gss(ret, minor);
259 if (!flags_got) {
260 /* Sign+seal not supported. */
261 gss_release_buffer(&minor, &out_buf);
262 return NT_STATUS_NOT_SUPPORTED;
265 /* Ya see - this is why I *hate* gss-api. I don't
266 * want to have to malloc another buffer of the
267 * same size + 8 bytes just to get a continuous
268 * header + buffer, but gss won't let me pass in
269 * a pre-allocated buffer. Bastards (and you know
270 * who you are....). I might fix this by
271 * going to "encrypt_and_send" passing in a file
272 * descriptor and doing scatter-gather write with
273 * TCP cork on Linux. But I shouldn't have to
274 * bother :-*(. JRA.
277 *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
278 if (!*ppbuf_out) {
279 gss_release_buffer(&minor, &out_buf);
280 return NT_STATUS_NO_MEMORY;
283 memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
284 smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
286 gss_release_buffer(&minor, &out_buf);
287 return NT_STATUS_OK;
289 #endif
291 /******************************************************************************
292 Generic code for client and server.
293 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
294 ******************************************************************************/
296 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
298 if (!common_encryption_on(es)) {
299 /* Not encrypting. */
300 *buf_out = buffer;
301 return NT_STATUS_OK;
304 switch (es->smb_enc_type) {
305 case SMB_TRANS_ENC_NTLM:
306 return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
307 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
308 case SMB_TRANS_ENC_GSS:
309 return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
310 #endif
311 default:
312 return NT_STATUS_NOT_SUPPORTED;
316 /******************************************************************************
317 Generic code for client and server.
318 Decrypt an incoming SMB buffer. Replaces the data within it.
319 New data must be less than or equal to the current length.
320 ******************************************************************************/
322 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
324 if (!common_encryption_on(es)) {
325 /* Not decrypting. */
326 return NT_STATUS_OK;
329 switch (es->smb_enc_type) {
330 case SMB_TRANS_ENC_NTLM:
331 return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
332 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
333 case SMB_TRANS_ENC_GSS:
334 return common_gss_decrypt_buffer(es->s.gss_state, buf);
335 #endif
336 default:
337 return NT_STATUS_NOT_SUPPORTED;
341 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
342 /******************************************************************************
343 Shutdown a gss encryption state.
344 ******************************************************************************/
346 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
348 OM_uint32 minor = 0;
349 struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
351 if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
352 gss_release_cred(&minor, &gss_state->creds);
354 if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
355 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
357 SAFE_FREE(*pp_gss_state);
359 #endif
361 /******************************************************************************
362 Shutdown an encryption state.
363 ******************************************************************************/
365 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
367 struct smb_trans_enc_state *es = *pp_es;
369 if (es == NULL) {
370 return;
373 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
374 if (es->s.ntlmssp_state) {
375 TALLOC_FREE(es->s.ntlmssp_state);
378 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
379 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
380 /* Free the gss context handle. */
381 if (es->s.gss_state) {
382 common_free_gss_state(&es->s.gss_state);
385 #endif
386 SAFE_FREE(es);
387 *pp_es = NULL;
390 /******************************************************************************
391 Free an encryption-allocated buffer.
392 ******************************************************************************/
394 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
396 uint16_t enc_ctx_num;
398 if (!common_encryption_on(es)) {
399 return;
402 if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
403 &enc_ctx_num))) {
404 return;
407 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
408 SAFE_FREE(buf);
409 return;
412 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
413 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
414 OM_uint32 min;
415 gss_buffer_desc rel_buf;
416 rel_buf.value = buf;
417 rel_buf.length = smb_len(buf) + 4;
418 gss_release_buffer(&min, &rel_buf);
420 #endif
423 /******************************************************************************
424 Client side encryption.
425 ******************************************************************************/
427 /******************************************************************************
428 Is client encryption on ?
429 ******************************************************************************/
431 bool cli_encryption_on(struct cli_state *cli)
433 /* If we supported multiple encrytion contexts
434 * here we'd look up based on tid.
436 return common_encryption_on(cli->trans_enc_state);
439 /******************************************************************************
440 Shutdown a client encryption state.
441 ******************************************************************************/
443 void cli_free_encryption_context(struct cli_state *cli)
445 common_free_encryption_state(&cli->trans_enc_state);
448 /******************************************************************************
449 Free an encryption-allocated buffer.
450 ******************************************************************************/
452 void cli_free_enc_buffer(struct cli_state *cli, char *buf)
454 /* We know this is an smb buffer, and we
455 * didn't malloc, only copy, for a keepalive,
456 * so ignore non-session messages. */
458 if(CVAL(buf,0)) {
459 return;
462 /* If we supported multiple encrytion contexts
463 * here we'd look up based on tid.
465 common_free_enc_buffer(cli->trans_enc_state, buf);
468 /******************************************************************************
469 Decrypt an incoming buffer.
470 ******************************************************************************/
472 NTSTATUS cli_decrypt_message(struct cli_state *cli)
474 NTSTATUS status;
475 uint16 enc_ctx_num;
477 /* Ignore non-session messages. */
478 if(CVAL(cli->inbuf,0)) {
479 return NT_STATUS_OK;
482 status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
483 if (!NT_STATUS_IS_OK(status)) {
484 return status;
487 if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
488 return NT_STATUS_INVALID_HANDLE;
491 return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
494 /******************************************************************************
495 Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
496 ******************************************************************************/
498 NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out)
500 /* Ignore non-session messages. */
501 if (CVAL(buf,0)) {
502 return NT_STATUS_OK;
505 /* If we supported multiple encrytion contexts
506 * here we'd look up based on tid.
508 return common_encrypt_buffer(cli->trans_enc_state, buf, buf_out);