s3-ntlmssp: Remove ntlmssp_end and let the talloc hierarchy handle it.
[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 "../libcli/auth/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         TALLOC_CTX *frame;
121         *ppbuf_out = NULL;
122
123         if (data_len == 0) {
124                 return NT_STATUS_BUFFER_TOO_SMALL;
125         }
126
127         frame = talloc_stackframe();
128         /* 
129          * We know smb_len can't return a value > 128k, so no int overflow
130          * check needed.
131          */
132
133         buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
134
135         /* Copy the data from the original buffer. */
136
137         memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
138
139         smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
140
141         ZERO_STRUCT(sig);
142
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);
150
151         if (!NT_STATUS_IS_OK(status)) {
152                 talloc_free(frame);
153                 SAFE_FREE(buf_out);
154                 return status;
155         }
156
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;
162 }
163
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 ******************************************************************************/
169
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)
172 {
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. */
179
180         if (buf_len < 8) {
181                 return NT_STATUS_BUFFER_TOO_SMALL;
182         }
183
184         in_buf.value = buf + 8;
185         in_buf.length = buf_len - 8;
186
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);    
193
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);
199         }
200
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;
207         }
208
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);
212
213         gss_release_buffer(&minor, &out_buf);
214         return NT_STATUS_OK;
215 }
216
217 /******************************************************************************
218  Generic code for client and server.
219  gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
220 ******************************************************************************/
221
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)
226 {
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. */
233
234         *ppbuf_out = NULL;
235
236         if (buf_len < 8) {
237                 return NT_STATUS_BUFFER_TOO_SMALL;
238         }
239
240         in_buf.value = buf + 8;
241         in_buf.length = buf_len - 8;
242
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);
250
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);
256         }
257
258         if (!flags_got) {
259                 /* Sign+seal not supported. */
260                 gss_release_buffer(&minor, &out_buf);
261                 return NT_STATUS_NOT_SUPPORTED;
262         }
263
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.
274          */
275
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;
280         }
281
282         memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
283         smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
284
285         gss_release_buffer(&minor, &out_buf);
286         return NT_STATUS_OK;
287 }
288 #endif
289
290 /******************************************************************************
291  Generic code for client and server.
292  Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
293 ******************************************************************************/
294
295 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
296 {
297         if (!common_encryption_on(es)) {
298                 /* Not encrypting. */
299                 *buf_out = buffer;
300                 return NT_STATUS_OK;
301         }
302
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;
312         }
313 }
314
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 ******************************************************************************/
320
321 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
322 {
323         if (!common_encryption_on(es)) {
324                 /* Not decrypting. */
325                 return NT_STATUS_OK;
326         }
327
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;
337         }
338 }
339
340 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
341 /******************************************************************************
342  Shutdown a gss encryption state.
343 ******************************************************************************/
344
345 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
346 {
347         OM_uint32 minor = 0;
348         struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
349
350         if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
351                 gss_release_cred(&minor, &gss_state->creds);
352         }
353         if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
354                 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
355         }
356         SAFE_FREE(*pp_gss_state);
357 }
358 #endif
359
360 /******************************************************************************
361  Shutdown an encryption state.
362 ******************************************************************************/
363
364 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
365 {
366         struct smb_trans_enc_state *es = *pp_es;
367
368         if (es == NULL) {
369                 return;
370         }
371
372         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
373                 if (es->s.ntlmssp_state) {
374                         TALLOC_FREE(es->s.ntlmssp_state);
375                 }
376         }
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);
382                 }
383         }
384 #endif
385         SAFE_FREE(es);
386         *pp_es = NULL;
387 }
388
389 /******************************************************************************
390  Free an encryption-allocated buffer.
391 ******************************************************************************/
392
393 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
394 {
395         uint16_t enc_ctx_num;
396
397         if (!common_encryption_on(es)) {
398                 return;
399         }
400
401         if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
402                         &enc_ctx_num))) {
403                 return;
404         }
405
406         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
407                 SAFE_FREE(buf);
408                 return;
409         }
410
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);
418         }
419 #endif
420 }
421
422 /******************************************************************************
423  Client side encryption.
424 ******************************************************************************/
425
426 /******************************************************************************
427  Is client encryption on ?
428 ******************************************************************************/
429
430 bool cli_encryption_on(struct cli_state *cli)
431 {
432         /* If we supported multiple encrytion contexts
433          * here we'd look up based on tid.
434          */
435         return common_encryption_on(cli->trans_enc_state);
436 }
437
438 /******************************************************************************
439  Shutdown a client encryption state.
440 ******************************************************************************/
441
442 void cli_free_encryption_context(struct cli_state *cli)
443 {
444         common_free_encryption_state(&cli->trans_enc_state);
445 }
446
447 /******************************************************************************
448  Free an encryption-allocated buffer.
449 ******************************************************************************/
450
451 void cli_free_enc_buffer(struct cli_state *cli, char *buf)
452 {
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. */
456
457         if(CVAL(buf,0)) {
458                 return;
459         }
460
461         /* If we supported multiple encrytion contexts
462          * here we'd look up based on tid.
463          */
464         common_free_enc_buffer(cli->trans_enc_state, buf);
465 }
466
467 /******************************************************************************
468  Decrypt an incoming buffer.
469 ******************************************************************************/
470
471 NTSTATUS cli_decrypt_message(struct cli_state *cli)
472 {
473         NTSTATUS status;
474         uint16 enc_ctx_num;
475
476         /* Ignore non-session messages. */
477         if(CVAL(cli->inbuf,0)) {
478                 return NT_STATUS_OK;
479         }
480
481         status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
482         if (!NT_STATUS_IS_OK(status)) {
483                 return status;
484         }
485
486         if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
487                 return NT_STATUS_INVALID_HANDLE;
488         }
489
490         return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
491 }
492
493 /******************************************************************************
494  Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
495 ******************************************************************************/
496
497 NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out)
498 {
499         /* Ignore non-session messages. */
500         if (CVAL(buf,0)) {
501                 return NT_STATUS_OK;
502         }
503
504         /* If we supported multiple encrytion contexts
505          * here we'd look up based on tid.
506          */
507         return common_encrypt_buffer(cli->trans_enc_state, buf, buf_out);
508 }