r6738: My version of the patch by metze that I just reverted (-r 6734).
[ira/wip.git] / source4 / auth / ntlmssp / ntlmssp_sign.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Version 3.0
4  *  NTLMSSP Signing routines
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2001
6  *  Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2005
7  *  
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *  
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *  
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software Foundation,
20  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "auth/ntlmssp/ntlmssp.h"
26 #include "lib/crypto/crypto.h"
27
28 #define CLI_SIGN "session key to client-to-server signing key magic constant"
29 #define CLI_SEAL "session key to client-to-server sealing key magic constant"
30 #define SRV_SIGN "session key to server-to-client signing key magic constant"
31 #define SRV_SEAL "session key to server-to-client sealing key magic constant"
32
33 /**
34  * Some notes on then NTLM2 code:
35  *
36  * NTLM2 is a AEAD system.  This means that the data encrypted is not
37  * all the data that is signed.  In DCE-RPC case, the headers of the
38  * DCE-RPC packets are also signed.  This prevents some of the
39  * fun-and-games one might have by changing them.
40  *
41  */
42
43 static void calc_ntlmv2_key(TALLOC_CTX *mem_ctx, 
44                             DATA_BLOB *subkey,
45                             DATA_BLOB session_key, 
46                             const char *constant)
47 {
48         struct MD5Context ctx3;
49         *subkey = data_blob_talloc(mem_ctx, NULL, 16);
50         MD5Init(&ctx3);
51         MD5Update(&ctx3, session_key.data, session_key.length);
52         MD5Update(&ctx3, constant, strlen(constant)+1);
53         MD5Final(subkey->data, &ctx3);
54 }
55
56 enum ntlmssp_direction {
57         NTLMSSP_SEND,
58         NTLMSSP_RECEIVE
59 };
60
61 static NTSTATUS ntlmssp_make_packet_signature(struct gensec_ntlmssp_state *gensec_ntlmssp_state,
62                                               TALLOC_CTX *sig_mem_ctx, 
63                                               const uint8_t *data, size_t length, 
64                                               const uint8_t *whole_pdu, size_t pdu_length, 
65                                               enum ntlmssp_direction direction,
66                                               DATA_BLOB *sig, BOOL encrypt_sig)
67 {
68         if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
69
70                 HMACMD5Context ctx;
71                 uint8_t digest[16];
72                 uint8_t seq_num[4];
73
74                 *sig = data_blob_talloc(sig_mem_ctx, NULL, NTLMSSP_SIG_SIZE);
75                 if (!sig->data) {
76                         return NT_STATUS_NO_MEMORY;
77                 }
78                         
79                 switch (direction) {
80                 case NTLMSSP_SEND:
81                         SIVAL(seq_num, 0, gensec_ntlmssp_state->crypt.ntlm2.send_seq_num);
82                         gensec_ntlmssp_state->crypt.ntlm2.send_seq_num++;
83                         hmac_md5_init_limK_to_64(gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.data, 
84                                                  gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.length, &ctx);
85                         break;
86                 case NTLMSSP_RECEIVE:
87                         SIVAL(seq_num, 0, gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num);
88                         gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num++;
89                         hmac_md5_init_limK_to_64(gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.data, 
90                                                  gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.length, &ctx);
91                         break;
92                 }
93                 hmac_md5_update(seq_num, sizeof(seq_num), &ctx);
94                 hmac_md5_update(whole_pdu, pdu_length, &ctx);
95                 hmac_md5_final(digest, &ctx);
96
97                 if (encrypt_sig && gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
98                         switch (direction) {
99                         case NTLMSSP_SEND:
100                                 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, digest, 8);
101                                 break;
102                         case NTLMSSP_RECEIVE:
103                                 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state, digest, 8);
104                                 break;
105                         }
106                 }
107
108                 SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION);
109                 memcpy(sig->data + 4, digest, 8);
110                 memcpy(sig->data + 12, seq_num, 4);
111
112         } else {
113                 uint32_t crc;
114                 crc = crc32_calc_buffer(data, length);
115                 if (!msrpc_gen(sig_mem_ctx, sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, gensec_ntlmssp_state->crypt.ntlm.seq_num)) {
116                         return NT_STATUS_NO_MEMORY;
117                 }
118                 gensec_ntlmssp_state->crypt.ntlm.seq_num++;
119
120                 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, sig->data+4, sig->length-4);
121         }
122         dump_data_pw("calculated ntlmssp signature\n", sig->data, sig->length);
123         return NT_STATUS_OK;
124 }
125
126 NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 
127                                     TALLOC_CTX *sig_mem_ctx, 
128                                     const uint8_t *data, size_t length, 
129                                     const uint8_t *whole_pdu, size_t pdu_length, 
130                                     DATA_BLOB *sig)
131 {
132         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
133
134         if (!gensec_ntlmssp_state->session_key.length) {
135                 DEBUG(3, ("NO session key, cannot check sign packet\n"));
136                 return NT_STATUS_NO_USER_SESSION_KEY;
137         }
138         
139         if (!(gensec_security->want_features & GENSEC_FEATURE_SIGN)) {
140                 DEBUG(3, ("GENSEC Signing not requested - cannot seal packet!\n"));
141                 return NT_STATUS_INVALID_PARAMETER;
142         }
143
144         if (!gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
145                 DEBUG(3, ("NTLMSSP Signing not negotiated - cannot sign packet!\n"));
146                 return NT_STATUS_INVALID_PARAMETER;
147         }
148         
149         return ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 
150                                              data, length, 
151                                              whole_pdu, pdu_length, 
152                                              NTLMSSP_SEND, sig, True);
153 }
154
155 /**
156  * Check the signature of an incoming packet 
157  *
158  */
159
160 NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 
161                                      TALLOC_CTX *sig_mem_ctx, 
162                                      const uint8_t *data, size_t length, 
163                                      const uint8_t *whole_pdu, size_t pdu_length, 
164                                      const DATA_BLOB *sig)
165 {
166         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
167
168         DATA_BLOB local_sig;
169         NTSTATUS nt_status;
170
171         if (!gensec_ntlmssp_state->session_key.length) {
172                 DEBUG(3, ("NO session key, cannot check packet signature\n"));
173                 return NT_STATUS_NO_USER_SESSION_KEY;
174         }
175
176         if (!(gensec_security->want_features & (GENSEC_FEATURE_SEAL|GENSEC_FEATURE_SIGN))) {
177                 DEBUG(3, ("GENSEC Signing/Sealing not requested - cannot check packet!\n"));
178                 return NT_STATUS_INVALID_PARAMETER;
179         }
180
181         if (sig->length < 8) {
182                 DEBUG(0, ("NTLMSSP packet check failed due to short signature (%lu bytes)!\n", 
183                           (unsigned long)sig->length));
184         }
185
186         nt_status = ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 
187                                                   data, length, 
188                                                   whole_pdu, pdu_length, 
189                                                   NTLMSSP_RECEIVE, &local_sig, True);
190         
191         if (!NT_STATUS_IS_OK(nt_status)) {
192                 DEBUG(0, ("NTLMSSP packet check failed with %s\n", nt_errstr(nt_status)));
193                 return nt_status;
194         }
195
196         if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
197                 if (local_sig.length != sig->length ||
198                     memcmp(local_sig.data, 
199                            sig->data, sig->length) != 0) {
200                         DEBUG(5, ("BAD SIG NTLM2: wanted signature of\n"));
201                         dump_data(5, local_sig.data, local_sig.length);
202                         
203                         DEBUG(5, ("BAD SIG: got signature of\n"));
204                         dump_data(5, sig->data, sig->length);
205                         
206                         DEBUG(0, ("NTLMSSP NTLM2 packet check failed due to invalid signature!\n"));
207                         return NT_STATUS_ACCESS_DENIED;
208                 }
209         } else {
210                 if (local_sig.length != sig->length ||
211                     memcmp(local_sig.data + 8, 
212                            sig->data + 8, sig->length - 8) != 0) {
213                         DEBUG(5, ("BAD SIG NTLM1: wanted signature of\n"));
214                         dump_data(5, local_sig.data, local_sig.length);
215                         
216                         DEBUG(5, ("BAD SIG: got signature of\n"));
217                         dump_data(5, sig->data, sig->length);
218                         
219                         DEBUG(0, ("NTLMSSP NTLM1 packet check failed due to invalid signature!\n"));
220                         return NT_STATUS_ACCESS_DENIED;
221                 }
222         }
223         dump_data_pw("checked ntlmssp signature\n", sig->data, sig->length);
224
225         return NT_STATUS_OK;
226 }
227
228
229 /**
230  * Seal data with the NTLMSSP algorithm
231  *
232  */
233
234 NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 
235                                     TALLOC_CTX *sig_mem_ctx, 
236                                     uint8_t *data, size_t length, 
237                                     const uint8_t *whole_pdu, size_t pdu_length, 
238                                     DATA_BLOB *sig)
239 {
240         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
241         NTSTATUS nt_status;
242         if (!gensec_ntlmssp_state->session_key.length) {
243                 DEBUG(3, ("NO session key, cannot seal packet\n"));
244                 return NT_STATUS_NO_USER_SESSION_KEY;
245         }
246
247         if (!(gensec_security->want_features & GENSEC_FEATURE_SEAL)) {
248                 DEBUG(3, ("GENSEC Sealing not requested - cannot seal packet!\n"));
249                 return NT_STATUS_INVALID_PARAMETER;
250         }
251
252         if (!gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
253                 DEBUG(3, ("NTLMSSP Sealing not negotiated - cannot seal packet!\n"));
254                 return NT_STATUS_INVALID_PARAMETER;
255         }
256
257
258         DEBUG(10,("ntlmssp_seal_data: seal\n"));
259         dump_data_pw("ntlmssp clear data\n", data, length);
260         if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
261                 /* The order of these two operations matters - we must first seal the packet,
262                    then seal the sequence number - this is becouse the send_seal_hash is not
263                    constant, but is is rather updated with each iteration */
264                 nt_status = ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 
265                                                           data, length, 
266                                                           whole_pdu, pdu_length, 
267                                                           NTLMSSP_SEND, sig, False);
268                 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, data, length);
269                 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
270                         arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, sig->data+4, 8);
271                 }
272         } else {
273                 uint32_t crc;
274                 crc = crc32_calc_buffer(data, length);
275                 if (!msrpc_gen(sig_mem_ctx, sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, gensec_ntlmssp_state->crypt.ntlm.seq_num)) {
276                         return NT_STATUS_NO_MEMORY;
277                 }
278
279                 /* The order of these two operations matters - we must
280                    first seal the packet, then seal the sequence
281                    number - this is becouse the ntlmssp_hash is not
282                    constant, but is is rather updated with each
283                    iteration */
284
285                 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, data, length);
286                 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, sig->data+4, sig->length-4);
287                 /* increment counter on send */
288                 gensec_ntlmssp_state->crypt.ntlm.seq_num++;
289                 nt_status = NT_STATUS_OK;
290         }
291         dump_data_pw("ntlmssp signature\n", sig->data, sig->length);
292         dump_data_pw("ntlmssp sealed data\n", data, length);
293
294
295         return nt_status;
296 }
297
298 /**
299  * Unseal data with the NTLMSSP algorithm
300  *
301  */
302
303 /*
304   wrappers for the ntlmssp_*() functions
305 */
306 NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 
307                                       TALLOC_CTX *sig_mem_ctx, 
308                                       uint8_t *data, size_t length, 
309                                       const uint8_t *whole_pdu, size_t pdu_length, 
310                                       const DATA_BLOB *sig)
311 {
312         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
313         DATA_BLOB local_sig;
314         NTSTATUS nt_status;
315         if (!gensec_ntlmssp_state->session_key.length) {
316                 DEBUG(3, ("NO session key, cannot unseal packet\n"));
317                 return NT_STATUS_NO_USER_SESSION_KEY;
318         }
319
320         if (!(gensec_security->want_features & GENSEC_FEATURE_SEAL)) {
321                 DEBUG(3, ("GENSEC Sealing not requested - cannot unseal packet!\n"));
322                 return NT_STATUS_INVALID_PARAMETER;
323         }
324
325         dump_data_pw("ntlmssp sealed data\n", data, length);
326         if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
327                 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state, data, length);
328
329                 nt_status = ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 
330                                                           data, length, 
331                                                           whole_pdu, pdu_length, 
332                                                           NTLMSSP_RECEIVE, &local_sig, True);
333                 if (!NT_STATUS_IS_OK(nt_status)) {
334                         return nt_status;
335                 }
336
337                 if (local_sig.length != sig->length ||
338                     memcmp(local_sig.data, 
339                            sig->data, sig->length) != 0) {
340                         DEBUG(5, ("BAD SIG NTLM2: wanted signature of\n"));
341                         dump_data(5, local_sig.data, local_sig.length);
342                         
343                         DEBUG(5, ("BAD SIG: got signature of\n"));
344                         dump_data(5, sig->data, sig->length);
345                         
346                         DEBUG(0, ("NTLMSSP NTLM2 packet check failed due to invalid signature!\n"));
347                         return NT_STATUS_ACCESS_DENIED;
348                 }
349
350                 dump_data_pw("ntlmssp clear data\n", data, length);
351                 return NT_STATUS_OK;
352         } else {
353                 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, data, length);
354                 dump_data_pw("ntlmssp clear data\n", data, length);
355                 return gensec_ntlmssp_check_packet(gensec_security, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig);
356         }
357 }
358
359 /**
360    Initialise the state for NTLMSSP signing.
361 */
362 NTSTATUS ntlmssp_sign_init(struct gensec_ntlmssp_state *gensec_ntlmssp_state)
363 {
364         uint8_t p24[24];
365         ZERO_STRUCT(p24);
366
367         DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n"));
368         debug_ntlmssp_flags(gensec_ntlmssp_state->neg_flags);
369
370         if (!gensec_ntlmssp_state->session_key.length) {
371                 DEBUG(3, ("NO session key, cannot intialise signing\n"));
372                 return NT_STATUS_NO_USER_SESSION_KEY;
373         }
374
375         if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
376         {
377                 DATA_BLOB weak_session_key = gensec_ntlmssp_state->session_key;
378                 const char *send_sign_const;
379                 const char *send_seal_const;
380                 const char *recv_sign_const;
381                 const char *recv_seal_const;
382
383                 DATA_BLOB send_seal_key;
384                 DATA_BLOB recv_seal_key;
385
386                 switch (gensec_ntlmssp_state->role) {
387                 case NTLMSSP_CLIENT:
388                         send_sign_const = CLI_SIGN;
389                         send_seal_const = CLI_SEAL;
390                         recv_sign_const = SRV_SIGN;
391                         recv_seal_const = SRV_SEAL;
392                         break;
393                 case NTLMSSP_SERVER:
394                         send_sign_const = SRV_SIGN;
395                         send_seal_const = SRV_SEAL;
396                         recv_sign_const = CLI_SIGN;
397                         recv_seal_const = CLI_SEAL;
398                         break;
399                 default:
400                         return NT_STATUS_INTERNAL_ERROR;
401                 }
402                 
403                 gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state = talloc(gensec_ntlmssp_state, struct arcfour_state);
404                 NT_STATUS_HAVE_NO_MEMORY(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state);
405                 gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state = talloc(gensec_ntlmssp_state, struct arcfour_state);
406                 NT_STATUS_HAVE_NO_MEMORY(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state);
407
408                 /**
409                    Weaken NTLMSSP keys to cope with down-level clients, servers and export restrictions.
410                    
411                    We probably should have some parameters to control this, once we get NTLM2 working.
412                 */
413
414
415                 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) {
416                         
417                 } else if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {
418                         weak_session_key.length = 6;
419                 } else { /* forty bits */
420                         weak_session_key.length = 5;
421                 }
422                 dump_data_pw("NTLMSSP weakend master key:\n",
423                              weak_session_key.data, 
424                              weak_session_key.length);
425
426                 /* SEND */
427                 calc_ntlmv2_key(gensec_ntlmssp_state, 
428                                 &gensec_ntlmssp_state->crypt.ntlm2.send_sign_key, 
429                                 gensec_ntlmssp_state->session_key, send_sign_const);
430                 dump_data_pw("NTLMSSP send sign key:\n",
431                              gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.data, 
432                              gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.length);
433                 
434                 calc_ntlmv2_key(gensec_ntlmssp_state, 
435                                 &send_seal_key, 
436                                 weak_session_key, send_seal_const);
437                 dump_data_pw("NTLMSSP send seal key:\n",
438                              send_seal_key.data, 
439                              send_seal_key.length);
440
441                 arcfour_init(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, 
442                              &send_seal_key);
443
444                 dump_data_pw("NTLMSSP send sesl hash:\n", 
445                              gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state->sbox, 
446                              sizeof(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state->sbox));
447
448                 /* RECV */
449                 calc_ntlmv2_key(gensec_ntlmssp_state, 
450                                 &gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key, 
451                                 gensec_ntlmssp_state->session_key, recv_sign_const);
452                 dump_data_pw("NTLMSSP recv sign key:\n",
453                              gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.data, 
454                              gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.length);
455
456                 calc_ntlmv2_key(gensec_ntlmssp_state, 
457                                 &recv_seal_key, 
458                                 weak_session_key, recv_seal_const);
459                 dump_data_pw("NTLMSSP recv seal key:\n",
460                              recv_seal_key.data, 
461                              recv_seal_key.length);
462                 arcfour_init(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state, 
463                              &recv_seal_key);
464
465                 dump_data_pw("NTLMSSP receive seal hash:\n", 
466                              gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state->sbox, 
467                              sizeof(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state->sbox));
468
469                 gensec_ntlmssp_state->crypt.ntlm2.send_seq_num = 0;
470                 gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num = 0;
471
472         } else {
473                 DEBUG(5, ("NTLMSSP Sign/Seal - using NTLM1\n"));
474
475                 gensec_ntlmssp_state->crypt.ntlm.arcfour_state = talloc(gensec_ntlmssp_state, struct arcfour_state);
476                 NT_STATUS_HAVE_NO_MEMORY(gensec_ntlmssp_state->crypt.ntlm.arcfour_state);
477
478                 arcfour_init(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, 
479                              &gensec_ntlmssp_state->session_key);
480                 dump_data_pw("NTLMSSP hash:\n", gensec_ntlmssp_state->crypt.ntlm.arcfour_state->sbox,
481                              sizeof(gensec_ntlmssp_state->crypt.ntlm.arcfour_state->sbox));
482
483                 gensec_ntlmssp_state->crypt.ntlm.seq_num = 0;
484         }
485
486         return NT_STATUS_OK;
487 }
488
489 size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) 
490 {
491         return NTLMSSP_SIG_SIZE;
492 }
493
494 NTSTATUS gensec_ntlmssp_wrap(struct gensec_security *gensec_security, 
495                              TALLOC_CTX *sig_mem_ctx, 
496                              const DATA_BLOB *in, 
497                              DATA_BLOB *out)
498 {
499         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
500         DATA_BLOB sig;
501         NTSTATUS nt_status;
502
503         if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
504
505                 *out = data_blob_talloc(sig_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
506                 memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
507
508                 nt_status = gensec_ntlmssp_seal_packet(gensec_security, sig_mem_ctx, 
509                                                        out->data + NTLMSSP_SIG_SIZE, 
510                                                        out->length - NTLMSSP_SIG_SIZE, 
511                                                        out->data + NTLMSSP_SIG_SIZE, 
512                                                        out->length - NTLMSSP_SIG_SIZE, 
513                                                        &sig);
514
515                 if (NT_STATUS_IS_OK(nt_status)) {
516                         memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE);
517                 }
518                 return nt_status;
519
520         } else if ((gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
521                    || (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
522
523                 *out = data_blob_talloc(sig_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
524                 memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
525
526                 nt_status = gensec_ntlmssp_sign_packet(gensec_security, sig_mem_ctx, 
527                                                 out->data + NTLMSSP_SIG_SIZE, 
528                                                 out->length - NTLMSSP_SIG_SIZE, 
529                                                 out->data + NTLMSSP_SIG_SIZE, 
530                                                 out->length - NTLMSSP_SIG_SIZE, 
531                                                 &sig);
532
533                 if (NT_STATUS_IS_OK(nt_status)) {
534                         memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE);
535                 }
536                 return nt_status;
537
538         } else {
539                 *out = *in;
540                 return NT_STATUS_OK;
541         }
542 }
543
544
545 NTSTATUS gensec_ntlmssp_unwrap(struct gensec_security *gensec_security, 
546                                TALLOC_CTX *sig_mem_ctx, 
547                                const DATA_BLOB *in, 
548                                DATA_BLOB *out)
549 {
550         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
551         DATA_BLOB sig;
552
553         if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
554                 if (in->length < NTLMSSP_SIG_SIZE) {
555                         return NT_STATUS_INVALID_PARAMETER;
556                 }
557                 sig.data = in->data;
558                 sig.length = NTLMSSP_SIG_SIZE;
559
560                 *out = data_blob_talloc(sig_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
561                 
562                 return gensec_ntlmssp_unseal_packet(gensec_security, sig_mem_ctx, 
563                                                     out->data, out->length, 
564                                                     out->data, out->length, 
565                                                     &sig);
566                                                   
567         } else if ((gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
568                    || (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
569                 if (in->length < NTLMSSP_SIG_SIZE) {
570                         return NT_STATUS_INVALID_PARAMETER;
571                 }
572                 sig.data = in->data;
573                 sig.length = NTLMSSP_SIG_SIZE;
574
575                 *out = data_blob_talloc(sig_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
576                 
577                 return gensec_ntlmssp_check_packet(gensec_security, sig_mem_ctx, 
578                                             out->data, out->length, 
579                                             out->data, out->length, 
580                                             &sig);
581         } else {
582                 *out = *in;
583                 return NT_STATUS_OK;
584         }
585 }
586