r25598: Add missing become_root/unbecome_root around calls of add_aliases.
[sfrench/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
22 /******************************************************************************
23  Pull out the encryption context for this packet. 0 means global context.
24 ******************************************************************************/
25
26 NTSTATUS get_enc_ctx_num(char *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] == (char)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. */
97         smb_setlen(inbuf, 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         sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
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         *ppbuf_out = buf_out;
157         return NT_STATUS_OK;
158 }
159
160 /******************************************************************************
161  Generic code for client and server.
162  gss-api decrypt an incoming buffer. We insist that the size of the
163  unwrapped buffer must be smaller or identical to the incoming buffer.
164 ******************************************************************************/
165
166 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
167 static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
168 {
169         gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
170         OM_uint32 ret = 0;
171         OM_uint32 minor = 0;
172         int flags_got = 0;
173         gss_buffer_desc in_buf, out_buf;
174         size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
175
176         if (buf_len < 8) {
177                 return NT_STATUS_BUFFER_TOO_SMALL;
178         }
179
180         in_buf.value = buf + 8;
181         in_buf.length = buf_len - 8;
182
183         ret = gss_unwrap(&minor,
184                         gss_ctx,
185                         &in_buf,
186                         &out_buf,
187                         &flags_got,             /* did we get sign+seal ? */
188                         (gss_qop_t *) NULL);    
189
190         if (ret != GSS_S_COMPLETE) {
191                 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
192                 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
193                         ads_errstr(adss) ));
194                 return map_nt_error_from_gss(ret, minor);
195         }
196
197         if (out_buf.length > in_buf.length) {
198                 DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
199                         (unsigned int)out_buf.length,
200                         (unsigned int)in_buf.length ));
201                 gss_release_buffer(&minor, &out_buf);
202                 return NT_STATUS_INVALID_PARAMETER;
203         }
204
205         memcpy(buf + 8, out_buf.value, out_buf.length);
206         smb_setlen((char *)out_buf.value, buf, out_buf.length + 4);
207
208         gss_release_buffer(&minor, &out_buf);
209         return NT_STATUS_OK;
210 }
211
212 /******************************************************************************
213  Generic code for client and server.
214  gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
215 ******************************************************************************/
216
217 static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
218                                         uint16 enc_ctx_num,
219                                         char *buf,
220                                         char **ppbuf_out)
221 {
222         gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
223         OM_uint32 ret = 0;
224         OM_uint32 minor = 0;
225         int flags_got = 0;
226         gss_buffer_desc in_buf, out_buf;
227         size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
228
229         *ppbuf_out = NULL;
230
231         if (buf_len < 8) {
232                 return NT_STATUS_BUFFER_TOO_SMALL;
233         }
234
235         in_buf.value = buf + 8;
236         in_buf.length = buf_len - 8;
237
238         ret = gss_wrap(&minor,
239                         gss_ctx,
240                         True,                   /* we want sign+seal. */
241                         GSS_C_QOP_DEFAULT,
242                         &in_buf,
243                         &flags_got,             /* did we get sign+seal ? */
244                         &out_buf);
245
246         if (ret != GSS_S_COMPLETE) {
247                 ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
248                 DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
249                         ads_errstr(adss) ));
250                 return map_nt_error_from_gss(ret, minor);
251         }
252
253         if (!flags_got) {
254                 /* Sign+seal not supported. */
255                 gss_release_buffer(&minor, &out_buf);
256                 return NT_STATUS_NOT_SUPPORTED;
257         }
258
259         /* Ya see - this is why I *hate* gss-api. I don't 
260          * want to have to malloc another buffer of the
261          * same size + 8 bytes just to get a continuous
262          * header + buffer, but gss won't let me pass in
263          * a pre-allocated buffer. Bastards (and you know
264          * who you are....). I might fix this by
265          * going to "encrypt_and_send" passing in a file
266          * descriptor and doing scatter-gather write with
267          * TCP cork on Linux. But I shouldn't have to
268          * bother :-*(. JRA.
269          */
270
271         *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
272         if (!*ppbuf_out) {
273                 gss_release_buffer(&minor, &out_buf);
274                 return NT_STATUS_NO_MEMORY;
275         }
276
277         memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
278         smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
279
280         gss_release_buffer(&minor, &out_buf);
281         return NT_STATUS_OK;
282 }
283 #endif
284
285 /******************************************************************************
286  Generic code for client and server.
287  Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
288 ******************************************************************************/
289
290 NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
291 {
292         if (!common_encryption_on(es)) {
293                 /* Not encrypting. */
294                 *buf_out = buffer;
295                 return NT_STATUS_OK;
296         }
297
298         switch (es->smb_enc_type) {
299                 case SMB_TRANS_ENC_NTLM:
300                         return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
301 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
302                 case SMB_TRANS_ENC_GSS:
303                         return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
304 #endif
305                 default:
306                         return NT_STATUS_NOT_SUPPORTED;
307         }
308 }
309
310 /******************************************************************************
311  Generic code for client and server.
312  Decrypt an incoming SMB buffer. Replaces the data within it.
313  New data must be less than or equal to the current length.
314 ******************************************************************************/
315
316 NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
317 {
318         if (!common_encryption_on(es)) {
319                 /* Not decrypting. */
320                 return NT_STATUS_OK;
321         }
322
323         switch (es->smb_enc_type) {
324                 case SMB_TRANS_ENC_NTLM:
325                         return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
326 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
327                 case SMB_TRANS_ENC_GSS:
328                         return common_gss_decrypt_buffer(es->s.gss_state, buf);
329 #endif
330                 default:
331                         return NT_STATUS_NOT_SUPPORTED;
332         }
333 }
334
335 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
336 /******************************************************************************
337  Shutdown a gss encryption state.
338 ******************************************************************************/
339
340 static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
341 {
342         OM_uint32 minor = 0;
343         struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
344
345         if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
346                 gss_release_cred(&minor, &gss_state->creds);
347         }
348         if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
349                 gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
350         }
351         SAFE_FREE(*pp_gss_state);
352 }
353 #endif
354
355 /******************************************************************************
356  Shutdown an encryption state.
357 ******************************************************************************/
358
359 void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
360 {
361         struct smb_trans_enc_state *es = *pp_es;
362
363         if (es == NULL) {
364                 return;
365         }
366
367         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
368                 if (es->s.ntlmssp_state) {
369                         ntlmssp_end(&es->s.ntlmssp_state);
370                 }
371         }
372 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
373         if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
374                 /* Free the gss context handle. */
375                 if (es->s.gss_state) {
376                         common_free_gss_state(&es->s.gss_state);
377                 }
378         }
379 #endif
380         SAFE_FREE(es);
381         *pp_es = NULL;
382 }
383
384 /******************************************************************************
385  Free an encryption-allocated buffer.
386 ******************************************************************************/
387
388 void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
389 {
390         if (!common_encryption_on(es)) {
391                 return;
392         }
393
394         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
395                 SAFE_FREE(buf);
396                 return;
397         }
398
399 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
400         if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
401                 OM_uint32 min;
402                 gss_buffer_desc rel_buf;
403                 rel_buf.value = buf;
404                 rel_buf.length = smb_len(buf) + 4;
405                 gss_release_buffer(&min, &rel_buf);
406         }
407 #endif
408 }
409
410 /******************************************************************************
411  Client side encryption.
412 ******************************************************************************/
413
414 /******************************************************************************
415  Is client encryption on ?
416 ******************************************************************************/
417
418 BOOL cli_encryption_on(struct cli_state *cli)
419 {
420         /* If we supported multiple encrytion contexts
421          * here we'd look up based on tid.
422          */
423         return common_encryption_on(cli->trans_enc_state);
424 }
425
426 /******************************************************************************
427  Shutdown a client encryption state.
428 ******************************************************************************/
429
430 void cli_free_encryption_context(struct cli_state *cli)
431 {
432         common_free_encryption_state(&cli->trans_enc_state);
433 }
434
435 /******************************************************************************
436  Free an encryption-allocated buffer.
437 ******************************************************************************/
438
439 void cli_free_enc_buffer(struct cli_state *cli, char *buf)
440 {
441         /* We know this is an smb buffer, and we
442          * didn't malloc, only copy, for a keepalive,
443          * so ignore session keepalives. */
444
445         if(CVAL(buf,0) == SMBkeepalive) {
446                 return;
447         }
448
449         /* If we supported multiple encrytion contexts
450          * here we'd look up based on tid.
451          */
452         common_free_enc_buffer(cli->trans_enc_state, buf);
453 }
454
455 /******************************************************************************
456  Decrypt an incoming buffer.
457 ******************************************************************************/
458
459 NTSTATUS cli_decrypt_message(struct cli_state *cli)
460 {
461         NTSTATUS status;
462         uint16 enc_ctx_num;
463
464         /* Ignore session keepalives. */
465         if(CVAL(cli->inbuf,0) == SMBkeepalive) {
466                 return NT_STATUS_OK;
467         }
468
469         status = get_enc_ctx_num(cli->inbuf, &enc_ctx_num);
470         if (!NT_STATUS_IS_OK(status)) {
471                 return status;
472         }
473
474         if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
475                 return NT_STATUS_INVALID_HANDLE;
476         }
477
478         return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
479 }
480
481 /******************************************************************************
482  Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
483 ******************************************************************************/
484
485 NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
486 {
487         /* Ignore session keepalives. */
488         if(CVAL(cli->outbuf,0) == SMBkeepalive) {
489                 return NT_STATUS_OK;
490         }
491
492         /* If we supported multiple encrytion contexts
493          * here we'd look up based on tid.
494          */
495         return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out);
496 }