s4/heimdal_build: use GetTimeOfDay macro instead of gettimeofday
[Samba/ita.git] / source3 / libsmb / smb_seal.c
blob4610850638a190ccddc0bd6f67a7dade70b013ad
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"
23 /******************************************************************************
24 Pull out the encryption context for this packet. 0 means global context.
25 ******************************************************************************/
27 NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
29 if (smb_len(buf) < 8) {
30 return NT_STATUS_INVALID_BUFFER_SIZE;
33 if (buf[4] == 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(struct 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 and overwrite the header. */
98 smb_setlen(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(struct 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;
120 TALLOC_CTX *frame;
121 *ppbuf_out = NULL;
123 if (data_len == 0) {
124 return NT_STATUS_BUFFER_TOO_SMALL;
127 frame = talloc_stackframe();
129 * We know smb_len can't return a value > 128k, so no int overflow
130 * check needed.
133 buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
135 /* Copy the data from the original buffer. */
137 memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
139 smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
141 ZERO_STRUCT(sig);
143 status = ntlmssp_seal_packet(ntlmssp_state,
144 frame,
145 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
146 data_len,
147 (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
148 data_len,
149 &sig);
151 if (!NT_STATUS_IS_OK(status)) {
152 talloc_free(frame);
153 SAFE_FREE(buf_out);
154 return status;
157 /* First 16 data bytes are signature for SSPI compatibility. */
158 memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
159 talloc_free(frame);
160 *ppbuf_out = buf_out;
161 return NT_STATUS_OK;
164 /******************************************************************************
165 Generic code for client and server.
166 gss-api decrypt an incoming buffer. We insist that the size of the
167 unwrapped buffer must be smaller or identical to the incoming buffer.
168 ******************************************************************************/
170 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
171 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
173 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
174 OM_uint32 ret = 0;
175 OM_uint32 minor = 0;
176 int flags_got = 0;
177 gss_buffer_desc in_buf, out_buf;
178 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
180 if (buf_len < 8) {
181 return NT_STATUS_BUFFER_TOO_SMALL;
184 in_buf.value = buf + 8;
185 in_buf.length = buf_len - 8;
187 ret = gss_unwrap(&minor,
188 gss_ctx,
189 &in_buf,
190 &out_buf,
191 &flags_got, /* did we get sign+seal ? */
192 (gss_qop_t *) NULL);
194 if (ret != GSS_S_COMPLETE) {
195 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
196 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
197 ads_errstr(adss) ));
198 return map_nt_error_from_gss(ret, minor);
201 if (out_buf.length > in_buf.length) {
202 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
203 (unsigned int)out_buf.length,
204 (unsigned int)in_buf.length ));
205 gss_release_buffer(&minor, &out_buf);
206 return NT_STATUS_INVALID_PARAMETER;
209 memcpy(buf + 8, out_buf.value, out_buf.length);
210 /* Reset the length and overwrite the header. */
211 smb_setlen(buf, out_buf.length + 4);
213 gss_release_buffer(&minor, &out_buf);
214 return NT_STATUS_OK;
217 /******************************************************************************
218 Generic code for client and server.
219 gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
220 ******************************************************************************/
222 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
223 uint16 enc_ctx_num,
224 char *buf,
225 char **ppbuf_out)
227 gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
228 OM_uint32 ret = 0;
229 OM_uint32 minor = 0;
230 int flags_got = 0;
231 gss_buffer_desc in_buf, out_buf;
232 size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
234 *ppbuf_out = NULL;
236 if (buf_len < 8) {
237 return NT_STATUS_BUFFER_TOO_SMALL;
240 in_buf.value = buf + 8;
241 in_buf.length = buf_len - 8;
243 ret = gss_wrap(&minor,
244 gss_ctx,
245 true, /* we want sign+seal. */
246 GSS_C_QOP_DEFAULT,
247 &in_buf,
248 &flags_got, /* did we get sign+seal ? */
249 &out_buf);
251 if (ret != GSS_S_COMPLETE) {
252 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
253 DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
254 ads_errstr(adss) ));
255 return map_nt_error_from_gss(ret, minor);
258 if (!flags_got) {
259 /* Sign+seal not supported. */
260 gss_release_buffer(&minor, &out_buf);
261 return NT_STATUS_NOT_SUPPORTED;
264 /* Ya see - this is why I *hate* gss-api. I don't
265 * want to have to malloc another buffer of the
266 * same size + 8 bytes just to get a continuous
267 * header + buffer, but gss won't let me pass in
268 * a pre-allocated buffer. Bastards (and you know
269 * who you are....). I might fix this by
270 * going to "encrypt_and_send" passing in a file
271 * descriptor and doing scatter-gather write with
272 * TCP cork on Linux. But I shouldn't have to
273 * bother :-*(. JRA.
276 *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
277 if (!*ppbuf_out) {
278 gss_release_buffer(&minor, &out_buf);
279 return NT_STATUS_NO_MEMORY;
282 memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
283 smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
285 gss_release_buffer(&minor, &out_buf);
286 return NT_STATUS_OK;
288 #endif
290 /******************************************************************************
291 Generic code for client and server.
292 Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
293 ******************************************************************************/
295 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
297 if (!common_encryption_on(es)) {
298 /* Not encrypting. */
299 *buf_out = buffer;
300 return NT_STATUS_OK;
303 switch (es->smb_enc_type) {
304 case SMB_TRANS_ENC_NTLM:
305 return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
306 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
307 case SMB_TRANS_ENC_GSS:
308 return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
309 #endif
310 default:
311 return NT_STATUS_NOT_SUPPORTED;
315 /******************************************************************************
316 Generic code for client and server.
317 Decrypt an incoming SMB buffer. Replaces the data within it.
318 New data must be less than or equal to the current length.
319 ******************************************************************************/
321 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
323 if (!common_encryption_on(es)) {
324 /* Not decrypting. */
325 return NT_STATUS_OK;
328 switch (es->smb_enc_type) {
329 case SMB_TRANS_ENC_NTLM:
330 return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
331 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
332 case SMB_TRANS_ENC_GSS:
333 return common_gss_decrypt_buffer(es->s.gss_state, buf);
334 #endif
335 default:
336 return NT_STATUS_NOT_SUPPORTED;
340 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
341 /******************************************************************************
342 Shutdown a gss encryption state.
343 ******************************************************************************/
345 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
347 OM_uint32 minor = 0;
348 struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
350 if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
351 gss_release_cred(&minor, &gss_state->creds);
353 if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
354 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
356 SAFE_FREE(*pp_gss_state);
358 #endif
360 /******************************************************************************
361 Shutdown an encryption state.
362 ******************************************************************************/
364 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
366 struct smb_trans_enc_state *es = *pp_es;
368 if (es == NULL) {
369 return;
372 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
373 if (es->s.ntlmssp_state) {
374 TALLOC_FREE(es->s.ntlmssp_state);
377 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
378 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
379 /* Free the gss context handle. */
380 if (es->s.gss_state) {
381 common_free_gss_state(&es->s.gss_state);
384 #endif
385 SAFE_FREE(es);
386 *pp_es = NULL;
389 /******************************************************************************
390 Free an encryption-allocated buffer.
391 ******************************************************************************/
393 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
395 uint16_t enc_ctx_num;
397 if (!common_encryption_on(es)) {
398 return;
401 if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
402 &enc_ctx_num))) {
403 return;
406 if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
407 SAFE_FREE(buf);
408 return;
411 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
412 if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
413 OM_uint32 min;
414 gss_buffer_desc rel_buf;
415 rel_buf.value = buf;
416 rel_buf.length = smb_len(buf) + 4;
417 gss_release_buffer(&min, &rel_buf);
419 #endif
422 /******************************************************************************
423 Client side encryption.
424 ******************************************************************************/
426 /******************************************************************************
427 Is client encryption on ?
428 ******************************************************************************/
430 bool cli_encryption_on(struct cli_state *cli)
432 /* If we supported multiple encrytion contexts
433 * here we'd look up based on tid.
435 return common_encryption_on(cli->trans_enc_state);
438 /******************************************************************************
439 Shutdown a client encryption state.
440 ******************************************************************************/
442 void cli_free_encryption_context(struct cli_state *cli)
444 common_free_encryption_state(&cli->trans_enc_state);
447 /******************************************************************************
448 Free an encryption-allocated buffer.
449 ******************************************************************************/
451 void cli_free_enc_buffer(struct cli_state *cli, char *buf)
453 /* We know this is an smb buffer, and we
454 * didn't malloc, only copy, for a keepalive,
455 * so ignore non-session messages. */
457 if(CVAL(buf,0)) {
458 return;
461 /* If we supported multiple encrytion contexts
462 * here we'd look up based on tid.
464 common_free_enc_buffer(cli->trans_enc_state, buf);
467 /******************************************************************************
468 Decrypt an incoming buffer.
469 ******************************************************************************/
471 NTSTATUS cli_decrypt_message(struct cli_state *cli)
473 NTSTATUS status;
474 uint16 enc_ctx_num;
476 /* Ignore non-session messages. */
477 if(CVAL(cli->inbuf,0)) {
478 return NT_STATUS_OK;
481 status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
482 if (!NT_STATUS_IS_OK(status)) {
483 return status;
486 if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
487 return NT_STATUS_INVALID_HANDLE;
490 return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
493 /******************************************************************************
494 Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
495 ******************************************************************************/
497 NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out)
499 /* Ignore non-session messages. */
500 if (CVAL(buf,0)) {
501 return NT_STATUS_OK;
504 /* If we supported multiple encrytion contexts
505 * here we'd look up based on tid.
507 return common_encrypt_buffer(cli->trans_enc_state, buf, buf_out);