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