import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / libsmb / 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 2003
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
25 #define CLI_SIGN "session key to client-to-server signing key magic constant"
26 #define CLI_SEAL "session key to client-to-server sealing key magic constant"
27 #define SRV_SIGN "session key to server-to-client signing key magic constant"
28 #define SRV_SEAL "session key to server-to-client sealing key magic constant"
29
30 static void NTLMSSPcalc_ap( unsigned char *hash, unsigned char *data, int len)
31 {
32     unsigned char index_i = hash[256];
33     unsigned char index_j = hash[257];
34     int ind;
35
36     for (ind = 0; ind < len; ind++)
37     {
38         unsigned char tc;
39         unsigned char t;
40
41         index_i++;
42         index_j += hash[index_i];
43
44         tc = hash[index_i];
45         hash[index_i] = hash[index_j];
46         hash[index_j] = tc;
47
48         t = hash[index_i] + hash[index_j];
49         data[ind] = data[ind] ^ hash[t];
50     }
51
52     hash[256] = index_i;
53     hash[257] = index_j;
54 }
55
56 static void calc_hash(unsigned char hash[258], const char *k2, int k2l)
57 {
58         unsigned char j = 0;
59         int ind;
60
61         for (ind = 0; ind < 256; ind++)
62         {
63                 hash[ind] = (unsigned char)ind;
64         }
65
66         for (ind = 0; ind < 256; ind++)
67         {
68                 unsigned char tc;
69
70                 j += (hash[ind] + k2[ind%k2l]);
71
72                 tc = hash[ind];
73                 hash[ind] = hash[j];
74                 hash[j] = tc;
75         }
76
77         hash[256] = 0;
78         hash[257] = 0;
79 }
80
81 static void calc_ntlmv2_hash(unsigned char hash[258], unsigned char digest[16],
82                              DATA_BLOB session_key, 
83                              const char *constant)
84 {
85         struct MD5Context ctx3;
86
87         /* NOTE:  This code is currently complate fantasy - it's
88            got more in common with reality than the previous code
89            (the LM session key is not the right thing to use) but
90            it still needs work */
91
92         MD5Init(&ctx3);
93         MD5Update(&ctx3, session_key.data, session_key.length);
94         MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant)+1);
95         MD5Final(digest, &ctx3);
96
97         calc_hash(hash, digest, 16);
98 }
99
100 enum ntlmssp_direction {
101         NTLMSSP_SEND,
102         NTLMSSP_RECEIVE
103 };
104
105 static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
106                                               const uchar *data, size_t length, 
107                                               enum ntlmssp_direction direction,
108                                               DATA_BLOB *sig) 
109 {
110         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
111                 HMACMD5Context ctx;
112                 uchar seq_num[4];
113                 uchar digest[16];
114                 SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
115
116                 hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
117                 hmac_md5_update(seq_num, 4, &ctx);
118                 hmac_md5_update(data, length, &ctx);
119                 hmac_md5_final(digest, &ctx);
120
121                 if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */
122                                , ntlmssp_state->ntlmssp_seq_num)) {
123                         return NT_STATUS_NO_MEMORY;
124                 }
125
126                 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
127                         switch (direction) {
128                         case NTLMSSP_SEND:
129                                 NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
130                                 break;
131                         case NTLMSSP_RECEIVE:
132                                 NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash,  sig->data+4, sig->length-4);
133                                 break;
134                         }
135                 }
136         } else {
137                 uint32 crc;
138                 crc = crc32_calc_buffer((const char *)data, length);
139                 if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
140                         return NT_STATUS_NO_MEMORY;
141                 }
142                 
143                 dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
144                              sizeof(ntlmssp_state->ntlmssp_hash));
145                 NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
146         }
147         return NT_STATUS_OK;
148 }
149
150 NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state,
151                                     const uchar *data, size_t length, 
152                                     DATA_BLOB *sig) 
153 {
154         NTSTATUS nt_status;
155         if (!ntlmssp_state->session_key.length) {
156                 DEBUG(3, ("NO session key, cannot check sign packet\n"));
157                 return NT_STATUS_NO_USER_SESSION_KEY;
158         }
159
160         nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig);
161
162         /* increment counter on send */
163         ntlmssp_state->ntlmssp_seq_num++;
164         return nt_status;
165 }
166
167 /**
168  * Check the signature of an incoming packet 
169  * @note caller *must* check that the signature is the size it expects 
170  *
171  */
172
173 NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
174                               const uchar *data, size_t length, 
175                               const DATA_BLOB *sig) 
176 {
177         DATA_BLOB local_sig;
178         NTSTATUS nt_status;
179
180         if (!ntlmssp_state->session_key.length) {
181                 DEBUG(3, ("NO session key, cannot check packet signature\n"));
182                 return NT_STATUS_NO_USER_SESSION_KEY;
183         }
184
185         if (sig->length < 8) {
186                 DEBUG(0, ("NTLMSSP packet check failed due to short signature (%lu bytes)!\n", 
187                           (unsigned long)sig->length));
188         }
189
190         nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, 
191                                                   length, NTLMSSP_RECEIVE, &local_sig);
192         
193         if (!NT_STATUS_IS_OK(nt_status)) {
194                 DEBUG(0, ("NTLMSSP packet check failed with %s\n", nt_errstr(nt_status)));
195                 return nt_status;
196         }
197         
198         if (memcmp(sig->data+sig->length - 8, local_sig.data+local_sig.length - 8, 8) != 0) {
199                 DEBUG(5, ("BAD SIG: wanted signature of\n"));
200                 dump_data(5, (const char *)local_sig.data, local_sig.length);
201                 
202                 DEBUG(5, ("BAD SIG: got signature of\n"));
203                 dump_data(5, (const char *)(sig->data), sig->length);
204
205                 DEBUG(0, ("NTLMSSP packet check failed due to invalid signature!\n"));
206                 return NT_STATUS_ACCESS_DENIED;
207         }
208
209         /* increment counter on recieive */
210         ntlmssp_state->ntlmssp_seq_num++;
211
212         return NT_STATUS_OK;
213 }
214
215
216 /**
217  * Seal data with the NTLMSSP algorithm
218  *
219  */
220
221 NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
222                              uchar *data, size_t length,
223                              DATA_BLOB *sig)
224 {       
225         if (!ntlmssp_state->session_key.length) {
226                 DEBUG(3, ("NO session key, cannot seal packet\n"));
227                 return NT_STATUS_NO_USER_SESSION_KEY;
228         }
229
230         DEBUG(10,("ntlmssp_seal_data: seal\n"));
231         dump_data_pw("ntlmssp clear data\n", data, length);
232         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
233                 HMACMD5Context ctx;
234                 char seq_num[4];
235                 uchar digest[16];
236                 SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
237
238                 hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
239                 hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
240                 hmac_md5_update(data, length, &ctx);
241                 hmac_md5_final(digest, &ctx);
242
243                 if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */
244                                , ntlmssp_state->ntlmssp_seq_num)) {
245                         return NT_STATUS_NO_MEMORY;
246                 }
247
248                 dump_data_pw("ntlmssp client sealing hash:\n", 
249                              ntlmssp_state->send_seal_hash,
250                              sizeof(ntlmssp_state->send_seal_hash));
251                 NTLMSSPcalc_ap(ntlmssp_state->send_seal_hash, data, length);
252                 dump_data_pw("ntlmssp client signing hash:\n", 
253                              ntlmssp_state->send_sign_hash,
254                              sizeof(ntlmssp_state->send_sign_hash));
255                 NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
256         } else {
257                 uint32 crc;
258                 crc = crc32_calc_buffer((const char *)data, length);
259                 if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
260                         return NT_STATUS_NO_MEMORY;
261                 }
262
263                 /* The order of these two operations matters - we must first seal the packet,
264                    then seal the sequence number - this is becouse the ntlmssp_hash is not
265                    constant, but is is rather updated with each iteration */
266                 
267                 dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
268                              sizeof(ntlmssp_state->ntlmssp_hash));
269                 NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length);
270
271                 dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
272                              sizeof(ntlmssp_state->ntlmssp_hash));
273                 NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
274         }
275         dump_data_pw("ntlmssp sealed data\n", data, length);
276
277         /* increment counter on send */
278         ntlmssp_state->ntlmssp_seq_num++;
279
280         return NT_STATUS_OK;
281 }
282
283 /**
284  * Unseal data with the NTLMSSP algorithm
285  *
286  */
287
288 NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state,
289                                       uchar *data, size_t length,
290                                       DATA_BLOB *sig)
291 {
292         if (!ntlmssp_state->session_key.length) {
293                 DEBUG(3, ("NO session key, cannot unseal packet\n"));
294                 return NT_STATUS_NO_USER_SESSION_KEY;
295         }
296
297         DEBUG(10,("ntlmssp__unseal_data: seal\n"));
298         dump_data_pw("ntlmssp sealed data\n", data, length);
299         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
300                 NTLMSSPcalc_ap(ntlmssp_state->recv_seal_hash, data, length);
301         } else {
302                 dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
303                              sizeof(ntlmssp_state->ntlmssp_hash));
304                 NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length);
305         }
306         dump_data_pw("ntlmssp clear data\n", data, length);
307
308         return ntlmssp_check_packet(ntlmssp_state, data, length, sig);
309 }
310
311 /**
312    Initialise the state for NTLMSSP signing.
313 */
314 NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
315 {
316         unsigned char p24[24];
317         ZERO_STRUCT(p24);
318
319         DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n"));
320         debug_ntlmssp_flags(ntlmssp_state->neg_flags);
321
322         if (!ntlmssp_state->session_key.length) {
323                 DEBUG(3, ("NO session key, cannot intialise signing\n"));
324                 return NT_STATUS_NO_USER_SESSION_KEY;
325         }
326
327         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
328         {
329                 const char *send_sign_const;
330                 const char *send_seal_const;
331                 const char *recv_sign_const;
332                 const char *recv_seal_const;
333
334                 switch (ntlmssp_state->role) {
335                 case NTLMSSP_CLIENT:
336                         send_sign_const = CLI_SIGN;
337                         send_seal_const = CLI_SEAL;
338                         recv_sign_const = SRV_SIGN;
339                         recv_seal_const = SRV_SEAL;
340                         break;
341                 case NTLMSSP_SERVER:
342                         send_sign_const = SRV_SIGN;
343                         send_seal_const = SRV_SEAL;
344                         recv_sign_const = CLI_SIGN;
345                         recv_seal_const = CLI_SEAL;
346                         break;
347                 }
348
349                 calc_ntlmv2_hash(ntlmssp_state->send_sign_hash, 
350                                  ntlmssp_state->send_sign_const, 
351                                  ntlmssp_state->session_key, send_sign_const);
352                 dump_data_pw("NTLMSSP send sign hash:\n", 
353                              ntlmssp_state->send_sign_hash, 
354                              sizeof(ntlmssp_state->send_sign_hash));
355
356                 calc_ntlmv2_hash(ntlmssp_state->send_seal_hash, 
357                                  ntlmssp_state->send_seal_const, 
358                                  ntlmssp_state->session_key, send_seal_const);
359                 dump_data_pw("NTLMSSP send sesl hash:\n", 
360                              ntlmssp_state->send_seal_hash, 
361                              sizeof(ntlmssp_state->send_seal_hash));
362
363                 calc_ntlmv2_hash(ntlmssp_state->recv_sign_hash, 
364                                  ntlmssp_state->recv_sign_const, 
365                                  ntlmssp_state->session_key, recv_sign_const);
366                 dump_data_pw("NTLMSSP receive sign hash:\n", 
367                              ntlmssp_state->recv_sign_hash, 
368                              sizeof(ntlmssp_state->recv_sign_hash));
369
370                 calc_ntlmv2_hash(ntlmssp_state->recv_seal_hash, 
371                                  ntlmssp_state->recv_seal_const, 
372                                  ntlmssp_state->session_key, recv_seal_const);
373                 dump_data_pw("NTLMSSP receive seal hash:\n", 
374                              ntlmssp_state->recv_sign_hash, 
375                              sizeof(ntlmssp_state->recv_sign_hash));
376
377         } 
378         else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
379                 if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 8) {
380                         /* can't sign or check signatures yet */ 
381                         DEBUG(5, ("NTLMSSP Sign/Seal - cannot use LM KEY yet\n"));      
382                         return NT_STATUS_UNSUCCESSFUL;
383                 }
384                 
385                 DEBUG(5, ("NTLMSSP Sign/Seal - using LM KEY\n"));
386
387                 calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 8);
388                 dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
389                              sizeof(ntlmssp_state->ntlmssp_hash));
390         } else {
391                 if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 16) {
392                         /* can't sign or check signatures yet */ 
393                         DEBUG(5, ("NTLMSSP Sign/Seal - cannot use NT KEY yet\n"));
394                         return NT_STATUS_UNSUCCESSFUL;
395                 }
396                 
397                 DEBUG(5, ("NTLMSSP Sign/Seal - using NT KEY\n"));
398
399                 calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 16);
400                 dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
401                              sizeof(ntlmssp_state->ntlmssp_hash));
402         }
403
404         ntlmssp_state->ntlmssp_seq_num = 0;
405
406         return NT_STATUS_OK;
407 }