Merge branch 'master' of git://git.samba.org/samba
[rusty/samba.git] / source3 / libsmb / smb_seal.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB Transport encryption (sealing) code.
4    Copyright (C) Jeremy Allison 2007.
5    
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.
10    
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.
15    
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/>.
18 */
19
20 #include "includes.h"
21 #include "ntlmssp.h"
22
23 /******************************************************************************
24  Pull out the encryption context for this packet. 0 means global context.
25 ******************************************************************************/
26
27 NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
28 {
29         if (smb_len(buf) < 8) {
30                 return NT_STATUS_INVALID_BUFFER_SIZE;
31         }
32
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;
37                 }
38                 if (buf[5] == 'E') {
39                         *p_enc_ctx_num = SVAL(buf,6);
40                         return NT_STATUS_OK;
41                 }
42         }
43         return NT_STATUS_INVALID_NETWORK_RESPONSE;
44 }
45
46 /******************************************************************************
47  Generic code for client and server.
48  Is encryption turned on ?
49 ******************************************************************************/
50
51 bool common_encryption_on(struct smb_trans_enc_state *es)
52 {
53         return ((es != NULL) && es->enc_on);
54 }
55
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 ******************************************************************************/
62
63 NTSTATUS common_ntlm_decrypt_buffer(struct ntlmssp_state *ntlmssp_state, char *buf)
64 {
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;
70
71         if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
72                 return NT_STATUS_BUFFER_TOO_SMALL;
73         }
74
75         inbuf = (char *)smb_xmemdup(buf, buf_len);
76
77         /* Adjust for the signature. */
78         data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
79
80         /* Point at the signature. */
81         sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
82
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);
89
90         if (!NT_STATUS_IS_OK(status)) {
91                 SAFE_FREE(inbuf);
92                 return status;
93         }
94
95         memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
96
97         /* Reset the length and overwrite the header. */
98         smb_setlen(buf,data_len + 4);
99
100         SAFE_FREE(inbuf);
101         return NT_STATUS_OK;
102 }
103
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 ******************************************************************************/
110
111 NTSTATUS common_ntlm_encrypt_buffer(struct ntlmssp_state *ntlmssp_state,
112                                 uint16 enc_ctx_num,
113                                 char *buf,
114                                 char **ppbuf_out)
115 {
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
121         *ppbuf_out = NULL;
122
123         if (data_len == 0) {
124                 return NT_STATUS_BUFFER_TOO_SMALL;
125         }
126
127         /* 
128          * We know smb_len can't return a value > 128k, so no int overflow
129          * check needed.
130          */
131
132         buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
133
134         /* Copy the data from the original buffer. */
135
136         memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
137
138         smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
139
140         ZERO_STRUCT(sig);
141
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);
148
149         if (!NT_STATUS_IS_OK(status)) {
150                 data_blob_free(&sig);
151                 SAFE_FREE(buf_out);
152                 return status;
153         }
154
155         /* First 16 data bytes are signature for SSPI compatibility. */
156         memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
157         data_blob_free(&sig);
158         *ppbuf_out = buf_out;
159         return NT_STATUS_OK;
160 }
161
162 /******************************************************************************
163  Generic code for client and server.
164  gss-api decrypt an incoming buffer. We insist that the size of the
165  unwrapped buffer must be smaller or identical to the incoming buffer.
166 ******************************************************************************/
167
168 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
169 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
170 {
171         gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
172         OM_uint32 ret = 0;
173         OM_uint32 minor = 0;
174         int flags_got = 0;
175         gss_buffer_desc in_buf, out_buf;
176         size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
177
178         if (buf_len < 8) {
179                 return NT_STATUS_BUFFER_TOO_SMALL;
180         }
181
182         in_buf.value = buf + 8;
183         in_buf.length = buf_len - 8;
184
185         ret = gss_unwrap(&minor,
186                         gss_ctx,
187                         &in_buf,
188                         &out_buf,
189                         &flags_got,             /* did we get sign+seal ? */
190                         (gss_qop_t *) NULL);    
191
192         if (ret != GSS_S_COMPLETE) {
193                 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
194                 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
195                         ads_errstr(adss) ));
196                 return map_nt_error_from_gss(ret, minor);
197         }
198
199         if (out_buf.length > in_buf.length) {
200                 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
201                         (unsigned int)out_buf.length,
202                         (unsigned int)in_buf.length ));
203                 gss_release_buffer(&minor, &out_buf);
204                 return NT_STATUS_INVALID_PARAMETER;
205         }
206
207         memcpy(buf + 8, out_buf.value, out_buf.length);
208         /* Reset the length and overwrite the header. */
209         smb_setlen(buf, out_buf.length + 4);
210
211         gss_release_buffer(&minor, &out_buf);
212         return NT_STATUS_OK;
213 }
214
215 /******************************************************************************
216  Generic code for client and server.
217  gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
218 ******************************************************************************/
219
220 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
221                                         uint16 enc_ctx_num,
222                                         char *buf,
223                                         char **ppbuf_out)
224 {
225         gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
226         OM_uint32 ret = 0;
227         OM_uint32 minor = 0;
228         int flags_got = 0;
229         gss_buffer_desc in_buf, out_buf;
230         size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
231
232         *ppbuf_out = NULL;
233
234         if (buf_len < 8) {
235                 return NT_STATUS_BUFFER_TOO_SMALL;
236         }
237
238         in_buf.value = buf + 8;
239         in_buf.length = buf_len - 8;
240
241         ret = gss_wrap(&minor,
242                         gss_ctx,
243                         true,                   /* we want sign+seal. */
244                         GSS_C_QOP_DEFAULT,
245                         &in_buf,
246                         &flags_got,             /* did we get sign+seal ? */
247                         &out_buf);
248
249         if (ret != GSS_S_COMPLETE) {
250                 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
251                 DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
252                         ads_errstr(adss) ));
253                 return map_nt_error_from_gss(ret, minor);
254         }
255
256         if (!flags_got) {
257                 /* Sign+seal not supported. */
258                 gss_release_buffer(&minor, &out_buf);
259                 return NT_STATUS_NOT_SUPPORTED;
260         }
261
262         /* Ya see - this is why I *hate* gss-api. I don't 
263          * want to have to malloc another buffer of the
264          * same size + 8 bytes just to get a continuous
265          * header + buffer, but gss won't let me pass in
266          * a pre-allocated buffer. Bastards (and you know
267          * who you are....). I might fix this by
268          * going to "encrypt_and_send" passing in a file
269          * descriptor and doing scatter-gather write with
270          * TCP cork on Linux. But I shouldn't have to
271          * bother :-*(. JRA.
272          */
273
274         *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
275         if (!*ppbuf_out) {
276                 gss_release_buffer(&minor, &out_buf);
277                 return NT_STATUS_NO_MEMORY;
278         }
279
280         memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
281         smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
282
283         gss_release_buffer(&minor, &out_buf);
284         return NT_STATUS_OK;
285 }
286 #endif
287
288 /******************************************************************************
289  Generic code for client and server.
290  Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
291 ******************************************************************************/
292
293 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
294 {
295         if (!common_encryption_on(es)) {
296                 /* Not encrypting. */
297                 *buf_out = buffer;
298                 return NT_STATUS_OK;
299         }
300
301         switch (es->smb_enc_type) {
302                 case SMB_TRANS_ENC_NTLM:
303                         return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
304 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
305                 case SMB_TRANS_ENC_GSS:
306                         return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
307 #endif
308                 default:
309                         return NT_STATUS_NOT_SUPPORTED;
310         }
311 }
312
313 /******************************************************************************
314  Generic code for client and server.
315  Decrypt an incoming SMB buffer. Replaces the data within it.
316  New data must be less than or equal to the current length.
317 ******************************************************************************/
318
319 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
320 {
321         if (!common_encryption_on(es)) {
322                 /* Not decrypting. */
323                 return NT_STATUS_OK;
324         }
325
326         switch (es->smb_enc_type) {
327                 case SMB_TRANS_ENC_NTLM:
328                         return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
329 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
330                 case SMB_TRANS_ENC_GSS:
331                         return common_gss_decrypt_buffer(es->s.gss_state, buf);
332 #endif
333                 default:
334                         return NT_STATUS_NOT_SUPPORTED;
335         }
336 }
337
338 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
339 /******************************************************************************
340  Shutdown a gss encryption state.
341 ******************************************************************************/
342
343 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
344 {
345         OM_uint32 minor = 0;
346         struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
347
348         if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
349                 gss_release_cred(&minor, &gss_state->creds);
350         }
351         if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
352                 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
353         }
354         SAFE_FREE(*pp_gss_state);
355 }
356 #endif
357
358 /******************************************************************************
359  Shutdown an encryption state.
360 ******************************************************************************/
361
362 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
363 {
364         struct smb_trans_enc_state *es = *pp_es;
365
366         if (es == NULL) {
367                 return;
368         }
369
370         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
371                 if (es->s.ntlmssp_state) {
372                         ntlmssp_end(&es->s.ntlmssp_state);
373                 }
374         }
375 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
376         if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
377                 /* Free the gss context handle. */
378                 if (es->s.gss_state) {
379                         common_free_gss_state(&es->s.gss_state);
380                 }
381         }
382 #endif
383         SAFE_FREE(es);
384         *pp_es = NULL;
385 }
386
387 /******************************************************************************
388  Free an encryption-allocated buffer.
389 ******************************************************************************/
390
391 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
392 {
393         uint16_t enc_ctx_num;
394
395         if (!common_encryption_on(es)) {
396                 return;
397         }
398
399         if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
400                         &enc_ctx_num))) {
401                 return;
402         }
403
404         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
405                 SAFE_FREE(buf);
406                 return;
407         }
408
409 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
410         if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
411                 OM_uint32 min;
412                 gss_buffer_desc rel_buf;
413                 rel_buf.value = buf;
414                 rel_buf.length = smb_len(buf) + 4;
415                 gss_release_buffer(&min, &rel_buf);
416         }
417 #endif
418 }
419
420 /******************************************************************************
421  Client side encryption.
422 ******************************************************************************/
423
424 /******************************************************************************
425  Is client encryption on ?
426 ******************************************************************************/
427
428 bool cli_encryption_on(struct cli_state *cli)
429 {
430         /* If we supported multiple encrytion contexts
431          * here we'd look up based on tid.
432          */
433         return common_encryption_on(cli->trans_enc_state);
434 }
435
436 /******************************************************************************
437  Shutdown a client encryption state.
438 ******************************************************************************/
439
440 void cli_free_encryption_context(struct cli_state *cli)
441 {
442         common_free_encryption_state(&cli->trans_enc_state);
443 }
444
445 /******************************************************************************
446  Free an encryption-allocated buffer.
447 ******************************************************************************/
448
449 void cli_free_enc_buffer(struct cli_state *cli, char *buf)
450 {
451         /* We know this is an smb buffer, and we
452          * didn't malloc, only copy, for a keepalive,
453          * so ignore non-session messages. */
454
455         if(CVAL(buf,0)) {
456                 return;
457         }
458
459         /* If we supported multiple encrytion contexts
460          * here we'd look up based on tid.
461          */
462         common_free_enc_buffer(cli->trans_enc_state, buf);
463 }
464
465 /******************************************************************************
466  Decrypt an incoming buffer.
467 ******************************************************************************/
468
469 NTSTATUS cli_decrypt_message(struct cli_state *cli)
470 {
471         NTSTATUS status;
472         uint16 enc_ctx_num;
473
474         /* Ignore non-session messages. */
475         if(CVAL(cli->inbuf,0)) {
476                 return NT_STATUS_OK;
477         }
478
479         status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
480         if (!NT_STATUS_IS_OK(status)) {
481                 return status;
482         }
483
484         if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
485                 return NT_STATUS_INVALID_HANDLE;
486         }
487
488         return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
489 }
490
491 /******************************************************************************
492  Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
493 ******************************************************************************/
494
495 NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out)
496 {
497         /* Ignore non-session messages. */
498         if (CVAL(buf,0)) {
499                 return NT_STATUS_OK;
500         }
501
502         /* If we supported multiple encrytion contexts
503          * here we'd look up based on tid.
504          */
505         return common_encrypt_buffer(cli->trans_enc_state, buf, buf_out);
506 }