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