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