/src/samba/auth/ntlmssp/ntlmssp_sign.c
Line | Count | Source |
1 | | /* |
2 | | * Unix SMB/CIFS implementation. |
3 | | * Version 3.0 |
4 | | * NTLMSSP Signing routines |
5 | | * Copyright (C) Andrew Bartlett 2003-2005 |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 3 of the License, or |
10 | | * (at your option) any later version. |
11 | | * |
12 | | * This program is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU General Public License |
18 | | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include "includes.h" |
22 | | #include "../auth/ntlmssp/ntlmssp.h" |
23 | | #include "../libcli/auth/libcli_auth.h" |
24 | | #include "zlib.h" |
25 | | #include "../auth/ntlmssp/ntlmssp_private.h" |
26 | | |
27 | | #include "lib/crypto/gnutls_helpers.h" |
28 | | #include <gnutls/gnutls.h> |
29 | | #include <gnutls/crypto.h> |
30 | | |
31 | | #undef DBGC_CLASS |
32 | 0 | #define DBGC_CLASS DBGC_AUTH |
33 | | |
34 | 0 | #define CLI_SIGN "session key to client-to-server signing key magic constant" |
35 | 0 | #define CLI_SEAL "session key to client-to-server sealing key magic constant" |
36 | 0 | #define SRV_SIGN "session key to server-to-client signing key magic constant" |
37 | 0 | #define SRV_SEAL "session key to server-to-client sealing key magic constant" |
38 | | |
39 | | /** |
40 | | * Some notes on the NTLM2 code: |
41 | | * |
42 | | * NTLM2 is a AEAD system. This means that the data encrypted is not |
43 | | * all the data that is signed. In DCE-RPC case, the headers of the |
44 | | * DCE-RPC packets are also signed. This prevents some of the |
45 | | * fun-and-games one might have by changing them. |
46 | | * |
47 | | */ |
48 | | |
49 | | static void dump_arc4_state(const char *description, |
50 | | gnutls_cipher_hd_t *state) |
51 | 0 | { |
52 | 0 | DBG_DEBUG("%s\n", description); |
53 | 0 | } |
54 | | |
55 | | static NTSTATUS calc_ntlmv2_key(uint8_t subkey[16], |
56 | | DATA_BLOB session_key, |
57 | | const char *constant) |
58 | 0 | { |
59 | 0 | gnutls_hash_hd_t hash_hnd = NULL; |
60 | 0 | int rc; |
61 | |
|
62 | 0 | rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5); |
63 | 0 | if (rc < 0) { |
64 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
65 | 0 | } |
66 | 0 | rc = gnutls_hash(hash_hnd, session_key.data, session_key.length); |
67 | 0 | if (rc < 0) { |
68 | 0 | gnutls_hash_deinit(hash_hnd, NULL); |
69 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
70 | 0 | } |
71 | 0 | rc = gnutls_hash(hash_hnd, constant, strlen(constant) + 1); |
72 | 0 | if (rc < 0) { |
73 | 0 | gnutls_hash_deinit(hash_hnd, NULL); |
74 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
75 | 0 | } |
76 | 0 | gnutls_hash_deinit(hash_hnd, subkey); |
77 | |
|
78 | 0 | return NT_STATUS_OK; |
79 | 0 | } |
80 | | |
81 | | enum ntlmssp_direction { |
82 | | NTLMSSP_SEND, |
83 | | NTLMSSP_RECEIVE |
84 | | }; |
85 | | |
86 | | static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_state, |
87 | | TALLOC_CTX *sig_mem_ctx, |
88 | | const uint8_t *data, size_t length, |
89 | | const uint8_t *whole_pdu, size_t pdu_length, |
90 | | enum ntlmssp_direction direction, |
91 | | DATA_BLOB *sig, bool encrypt_sig) |
92 | 0 | { |
93 | 0 | NTSTATUS status = NT_STATUS_UNSUCCESSFUL; |
94 | 0 | int rc; |
95 | |
|
96 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { |
97 | 0 | gnutls_hmac_hd_t hmac_hnd = NULL; |
98 | 0 | uint8_t digest[16]; |
99 | 0 | uint8_t seq_num[4]; |
100 | |
|
101 | 0 | *sig = data_blob_talloc(sig_mem_ctx, NULL, NTLMSSP_SIG_SIZE); |
102 | 0 | if (!sig->data) { |
103 | 0 | return NT_STATUS_NO_MEMORY; |
104 | 0 | } |
105 | | |
106 | 0 | switch (direction) { |
107 | 0 | case NTLMSSP_SEND: |
108 | 0 | DEBUG(100,("ntlmssp_make_packet_signature: SEND seq = %u, len = %u, pdu_len = %u\n", |
109 | 0 | ntlmssp_state->crypt->ntlm2.sending.seq_num, |
110 | 0 | (unsigned int)length, |
111 | 0 | (unsigned int)pdu_length)); |
112 | |
|
113 | 0 | SIVAL(seq_num, 0, ntlmssp_state->crypt->ntlm2.sending.seq_num); |
114 | 0 | ntlmssp_state->crypt->ntlm2.sending.seq_num++; |
115 | |
|
116 | 0 | rc = gnutls_hmac_init(&hmac_hnd, |
117 | 0 | GNUTLS_MAC_MD5, |
118 | 0 | ntlmssp_state->crypt->ntlm2.sending.sign_key, |
119 | 0 | 16); |
120 | 0 | if (rc < 0) { |
121 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
122 | 0 | } |
123 | 0 | break; |
124 | 0 | case NTLMSSP_RECEIVE: |
125 | |
|
126 | 0 | DEBUG(100,("ntlmssp_make_packet_signature: RECV seq = %u, len = %u, pdu_len = %u\n", |
127 | 0 | ntlmssp_state->crypt->ntlm2.receiving.seq_num, |
128 | 0 | (unsigned int)length, |
129 | 0 | (unsigned int)pdu_length)); |
130 | |
|
131 | 0 | SIVAL(seq_num, 0, ntlmssp_state->crypt->ntlm2.receiving.seq_num); |
132 | 0 | ntlmssp_state->crypt->ntlm2.receiving.seq_num++; |
133 | |
|
134 | 0 | rc = gnutls_hmac_init(&hmac_hnd, |
135 | 0 | GNUTLS_MAC_MD5, |
136 | 0 | ntlmssp_state->crypt->ntlm2.receiving.sign_key, |
137 | 0 | 16); |
138 | 0 | if (rc < 0) { |
139 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
140 | 0 | } |
141 | 0 | break; |
142 | 0 | } |
143 | | |
144 | 0 | dump_data_pw("pdu data ", whole_pdu, pdu_length); |
145 | |
|
146 | 0 | rc = gnutls_hmac(hmac_hnd, seq_num, sizeof(seq_num)); |
147 | 0 | if (rc < 0) { |
148 | 0 | gnutls_hmac_deinit(hmac_hnd, NULL); |
149 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
150 | 0 | } |
151 | 0 | rc = gnutls_hmac(hmac_hnd, whole_pdu, pdu_length); |
152 | 0 | if (rc < 0) { |
153 | 0 | gnutls_hmac_deinit(hmac_hnd, NULL); |
154 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
155 | 0 | } |
156 | 0 | gnutls_hmac_deinit(hmac_hnd, digest); |
157 | |
|
158 | 0 | if (encrypt_sig && (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) { |
159 | 0 | switch (direction) { |
160 | 0 | case NTLMSSP_SEND: |
161 | 0 | rc = gnutls_cipher_encrypt(ntlmssp_state->crypt->ntlm2.sending.seal_state, |
162 | 0 | digest, |
163 | 0 | 8); |
164 | 0 | break; |
165 | 0 | case NTLMSSP_RECEIVE: |
166 | 0 | rc = gnutls_cipher_encrypt(ntlmssp_state->crypt->ntlm2.receiving.seal_state, |
167 | 0 | digest, |
168 | 0 | 8); |
169 | 0 | break; |
170 | 0 | } |
171 | 0 | if (rc < 0) { |
172 | 0 | DBG_ERR("gnutls_cipher_encrypt for NTLMv2 EXCH " |
173 | 0 | "%s packet signature failed: %s\n", |
174 | 0 | direction == NTLMSSP_SEND ? |
175 | 0 | "send" : "receive", |
176 | 0 | gnutls_strerror(rc)); |
177 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
178 | 0 | } |
179 | 0 | } |
180 | | |
181 | 0 | SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION); |
182 | 0 | memcpy(sig->data + 4, digest, 8); |
183 | 0 | ZERO_ARRAY(digest); |
184 | 0 | memcpy(sig->data + 12, seq_num, 4); |
185 | 0 | ZERO_ARRAY(seq_num); |
186 | |
|
187 | 0 | dump_data_pw("ntlmssp v2 sig ", sig->data, sig->length); |
188 | |
|
189 | 0 | } else { |
190 | 0 | uint32_t crc; |
191 | |
|
192 | 0 | crc = crc32(0, Z_NULL, 0); |
193 | 0 | crc = crc32(crc, data, length); |
194 | |
|
195 | 0 | status = msrpc_gen(sig_mem_ctx, |
196 | 0 | sig, "dddd", |
197 | 0 | NTLMSSP_SIGN_VERSION, 0, crc, |
198 | 0 | ntlmssp_state->crypt->ntlm.seq_num); |
199 | 0 | if (!NT_STATUS_IS_OK(status)) { |
200 | 0 | return status; |
201 | 0 | } |
202 | | |
203 | 0 | ntlmssp_state->crypt->ntlm.seq_num++; |
204 | |
|
205 | 0 | dump_arc4_state("ntlmssp hash: \n", |
206 | 0 | &ntlmssp_state->crypt->ntlm.seal_state); |
207 | 0 | rc = gnutls_cipher_encrypt(ntlmssp_state->crypt->ntlm.seal_state, |
208 | 0 | sig->data + 4, |
209 | 0 | sig->length - 4); |
210 | 0 | if (rc < 0) { |
211 | 0 | DBG_ERR("gnutls_cipher_encrypt for NTLM packet " |
212 | 0 | "signature failed: %s\n", |
213 | 0 | gnutls_strerror(rc)); |
214 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
215 | 0 | } |
216 | 0 | } |
217 | | |
218 | 0 | return NT_STATUS_OK; |
219 | 0 | } |
220 | | |
221 | | NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state, |
222 | | TALLOC_CTX *sig_mem_ctx, |
223 | | const uint8_t *data, size_t length, |
224 | | const uint8_t *whole_pdu, size_t pdu_length, |
225 | | DATA_BLOB *sig) |
226 | 0 | { |
227 | 0 | NTSTATUS nt_status; |
228 | |
|
229 | 0 | if (!(ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) { |
230 | 0 | DEBUG(3, ("NTLMSSP Signing not negotiated - cannot sign packet!\n")); |
231 | 0 | return NT_STATUS_INVALID_PARAMETER; |
232 | 0 | } |
233 | | |
234 | 0 | if (!ntlmssp_state->session_key.length) { |
235 | 0 | DEBUG(3, ("NO session key, cannot check sign packet\n")); |
236 | 0 | return NT_STATUS_NO_USER_SESSION_KEY; |
237 | 0 | } |
238 | | |
239 | 0 | nt_status = ntlmssp_make_packet_signature(ntlmssp_state, |
240 | 0 | sig_mem_ctx, |
241 | 0 | data, length, |
242 | 0 | whole_pdu, pdu_length, |
243 | 0 | NTLMSSP_SEND, sig, true); |
244 | |
|
245 | 0 | return nt_status; |
246 | 0 | } |
247 | | |
248 | | /** |
249 | | * Check the signature of an incoming packet |
250 | | * @note caller *must* check that the signature is the size it expects |
251 | | * |
252 | | */ |
253 | | |
254 | | NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state, |
255 | | const uint8_t *data, size_t length, |
256 | | const uint8_t *whole_pdu, size_t pdu_length, |
257 | | const DATA_BLOB *sig) |
258 | 0 | { |
259 | 0 | DATA_BLOB local_sig; |
260 | 0 | NTSTATUS nt_status; |
261 | 0 | TALLOC_CTX *tmp_ctx; |
262 | |
|
263 | 0 | if (!ntlmssp_state->session_key.length) { |
264 | 0 | DEBUG(3, ("NO session key, cannot check packet signature\n")); |
265 | 0 | return NT_STATUS_NO_USER_SESSION_KEY; |
266 | 0 | } |
267 | | |
268 | 0 | if (sig->length < 8) { |
269 | 0 | DEBUG(0, ("NTLMSSP packet check failed due to short signature (%lu bytes)!\n", |
270 | 0 | (unsigned long)sig->length)); |
271 | 0 | } |
272 | |
|
273 | 0 | tmp_ctx = talloc_new(ntlmssp_state); |
274 | 0 | if (!tmp_ctx) { |
275 | 0 | return NT_STATUS_NO_MEMORY; |
276 | 0 | } |
277 | | |
278 | 0 | nt_status = ntlmssp_make_packet_signature(ntlmssp_state, |
279 | 0 | tmp_ctx, |
280 | 0 | data, length, |
281 | 0 | whole_pdu, pdu_length, |
282 | 0 | NTLMSSP_RECEIVE, |
283 | 0 | &local_sig, true); |
284 | |
|
285 | 0 | if (!NT_STATUS_IS_OK(nt_status)) { |
286 | 0 | DEBUG(0,("NTLMSSP packet sig creation failed with %s\n", |
287 | 0 | nt_errstr(nt_status))); |
288 | 0 | talloc_free(tmp_ctx); |
289 | 0 | return nt_status; |
290 | 0 | } |
291 | | |
292 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { |
293 | 0 | if (local_sig.length != sig->length || |
294 | 0 | !mem_equal_const_time(local_sig.data, sig->data, sig->length)) { |
295 | 0 | DEBUG(5, ("BAD SIG NTLM2: wanted signature of\n")); |
296 | 0 | dump_data(5, local_sig.data, local_sig.length); |
297 | |
|
298 | 0 | DEBUG(5, ("BAD SIG: got signature of\n")); |
299 | 0 | dump_data(5, sig->data, sig->length); |
300 | |
|
301 | 0 | DEBUG(0, ("NTLMSSP NTLM2 packet check failed due to invalid signature!\n")); |
302 | 0 | talloc_free(tmp_ctx); |
303 | 0 | return NT_STATUS_ACCESS_DENIED; |
304 | 0 | } |
305 | 0 | } else { |
306 | 0 | if (local_sig.length != sig->length || |
307 | 0 | !mem_equal_const_time(local_sig.data + 8, sig->data + 8, sig->length - 8)) { |
308 | 0 | DEBUG(5, ("BAD SIG NTLM1: wanted signature of\n")); |
309 | 0 | dump_data(5, local_sig.data, local_sig.length); |
310 | |
|
311 | 0 | DEBUG(5, ("BAD SIG: got signature of\n")); |
312 | 0 | dump_data(5, sig->data, sig->length); |
313 | |
|
314 | 0 | DEBUG(0, ("NTLMSSP NTLM1 packet check failed due to invalid signature!\n")); |
315 | 0 | talloc_free(tmp_ctx); |
316 | 0 | return NT_STATUS_ACCESS_DENIED; |
317 | 0 | } |
318 | 0 | } |
319 | 0 | dump_data_pw("checked ntlmssp signature\n", sig->data, sig->length); |
320 | 0 | DEBUG(10,("ntlmssp_check_packet: NTLMSSP signature OK !\n")); |
321 | |
|
322 | 0 | talloc_free(tmp_ctx); |
323 | 0 | return NT_STATUS_OK; |
324 | 0 | } |
325 | | |
326 | | /** |
327 | | * Seal data with the NTLMSSP algorithm |
328 | | * |
329 | | */ |
330 | | |
331 | | NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state, |
332 | | TALLOC_CTX *sig_mem_ctx, |
333 | | uint8_t *data, size_t length, |
334 | | const uint8_t *whole_pdu, size_t pdu_length, |
335 | | DATA_BLOB *sig) |
336 | 0 | { |
337 | 0 | int rc; |
338 | |
|
339 | 0 | if (!(ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) { |
340 | 0 | DEBUG(3, ("NTLMSSP Sealing not negotiated - cannot seal packet!\n")); |
341 | 0 | return NT_STATUS_INVALID_PARAMETER; |
342 | 0 | } |
343 | | |
344 | 0 | if (!(ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) { |
345 | 0 | DEBUG(3, ("NTLMSSP Sealing not negotiated - cannot seal packet!\n")); |
346 | 0 | return NT_STATUS_INVALID_PARAMETER; |
347 | 0 | } |
348 | | |
349 | 0 | if (!ntlmssp_state->session_key.length) { |
350 | 0 | DEBUG(3, ("NO session key, cannot seal packet\n")); |
351 | 0 | return NT_STATUS_NO_USER_SESSION_KEY; |
352 | 0 | } |
353 | | |
354 | 0 | DEBUG(10,("ntlmssp_seal_data: seal\n")); |
355 | 0 | dump_data_pw("ntlmssp clear data\n", data, length); |
356 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { |
357 | 0 | NTSTATUS nt_status; |
358 | | /* |
359 | | * The order of these two operations matters - we |
360 | | * must first seal the packet, then seal the |
361 | | * sequence number - this is because the |
362 | | * send_seal_hash is not constant, but is rather |
363 | | * updated with each iteration |
364 | | */ |
365 | 0 | nt_status = ntlmssp_make_packet_signature(ntlmssp_state, |
366 | 0 | sig_mem_ctx, |
367 | 0 | data, length, |
368 | 0 | whole_pdu, pdu_length, |
369 | 0 | NTLMSSP_SEND, |
370 | 0 | sig, false); |
371 | 0 | if (!NT_STATUS_IS_OK(nt_status)) { |
372 | 0 | return nt_status; |
373 | 0 | } |
374 | | |
375 | 0 | rc = gnutls_cipher_encrypt(ntlmssp_state->crypt->ntlm2.sending.seal_state, |
376 | 0 | data, |
377 | 0 | length); |
378 | 0 | if (rc < 0) { |
379 | 0 | DBG_ERR("gnutls_cipher_encrypt ntlmv2 sealing the data " |
380 | 0 | "failed: %s\n", |
381 | 0 | gnutls_strerror(rc)); |
382 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
383 | 0 | } |
384 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { |
385 | 0 | rc = gnutls_cipher_encrypt(ntlmssp_state->crypt->ntlm2.sending.seal_state, |
386 | 0 | sig->data + 4, |
387 | 0 | 8); |
388 | 0 | if (rc < 0) { |
389 | 0 | DBG_ERR("gnutls_cipher_encrypt ntlmv2 sealing " |
390 | 0 | "the EXCH signature data failed: %s\n", |
391 | 0 | gnutls_strerror(rc)); |
392 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
393 | 0 | } |
394 | 0 | } |
395 | 0 | } else { |
396 | 0 | NTSTATUS status; |
397 | 0 | uint32_t crc; |
398 | |
|
399 | 0 | crc = crc32(0, Z_NULL, 0); |
400 | 0 | crc = crc32(crc, data, length); |
401 | |
|
402 | 0 | status = msrpc_gen(sig_mem_ctx, |
403 | 0 | sig, "dddd", |
404 | 0 | NTLMSSP_SIGN_VERSION, 0, crc, |
405 | 0 | ntlmssp_state->crypt->ntlm.seq_num); |
406 | 0 | if (!NT_STATUS_IS_OK(status)) { |
407 | 0 | return status; |
408 | 0 | } |
409 | | |
410 | | /* |
411 | | * The order of these two operations matters - we |
412 | | * must first seal the packet, then seal the |
413 | | * sequence number - this is because the ntlmv1_arc4_state |
414 | | * is not constant, but is rather updated with |
415 | | * each iteration |
416 | | */ |
417 | 0 | dump_arc4_state("ntlmv1 arc4 state:\n", |
418 | 0 | &ntlmssp_state->crypt->ntlm.seal_state); |
419 | 0 | rc = gnutls_cipher_encrypt(ntlmssp_state->crypt->ntlm.seal_state, |
420 | 0 | data, |
421 | 0 | length); |
422 | 0 | if (rc < 0) { |
423 | 0 | DBG_ERR("gnutls_cipher_encrypt ntlmv1 sealing data" |
424 | 0 | "failed: %s\n", |
425 | 0 | gnutls_strerror(rc)); |
426 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
427 | 0 | } |
428 | | |
429 | 0 | dump_arc4_state("ntlmv1 arc4 state:\n", |
430 | 0 | &ntlmssp_state->crypt->ntlm.seal_state); |
431 | |
|
432 | 0 | rc = gnutls_cipher_encrypt(ntlmssp_state->crypt->ntlm.seal_state, |
433 | 0 | sig->data + 4, |
434 | 0 | sig->length - 4); |
435 | 0 | if (rc < 0) { |
436 | 0 | DBG_ERR("gnutls_cipher_encrypt ntlmv1 sealing signing " |
437 | 0 | "data failed: %s\n", |
438 | 0 | gnutls_strerror(rc)); |
439 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
440 | 0 | } |
441 | | |
442 | 0 | ntlmssp_state->crypt->ntlm.seq_num++; |
443 | 0 | } |
444 | 0 | dump_data_pw("ntlmssp signature\n", sig->data, sig->length); |
445 | 0 | dump_data_pw("ntlmssp sealed data\n", data, length); |
446 | |
|
447 | 0 | return NT_STATUS_OK; |
448 | 0 | } |
449 | | |
450 | | /** |
451 | | * Unseal data with the NTLMSSP algorithm |
452 | | * |
453 | | */ |
454 | | |
455 | | NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state, |
456 | | uint8_t *data, size_t length, |
457 | | const uint8_t *whole_pdu, size_t pdu_length, |
458 | | const DATA_BLOB *sig) |
459 | 0 | { |
460 | 0 | NTSTATUS status; |
461 | 0 | int rc; |
462 | |
|
463 | 0 | if (!ntlmssp_state->session_key.length) { |
464 | 0 | DEBUG(3, ("NO session key, cannot unseal packet\n")); |
465 | 0 | return NT_STATUS_NO_USER_SESSION_KEY; |
466 | 0 | } |
467 | | |
468 | 0 | DEBUG(10,("ntlmssp_unseal_packet: seal\n")); |
469 | 0 | dump_data_pw("ntlmssp sealed data\n", data, length); |
470 | |
|
471 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { |
472 | | /* First unseal the data. */ |
473 | 0 | rc = gnutls_cipher_decrypt(ntlmssp_state->crypt->ntlm2.receiving.seal_state, |
474 | 0 | data, |
475 | 0 | length); |
476 | 0 | if (rc < 0) { |
477 | 0 | DBG_ERR("gnutls_cipher_decrypt ntlmv2 unsealing the " |
478 | 0 | "data failed: %s\n", |
479 | 0 | gnutls_strerror(rc)); |
480 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
481 | 0 | } |
482 | 0 | dump_data_pw("ntlmv2 clear data\n", data, length); |
483 | 0 | } else { |
484 | 0 | rc = gnutls_cipher_decrypt(ntlmssp_state->crypt->ntlm.seal_state, |
485 | 0 | data, |
486 | 0 | length); |
487 | 0 | if (rc < 0) { |
488 | 0 | DBG_ERR("gnutls_cipher_decrypt ntlmv1 unsealing the " |
489 | 0 | "data failed: %s\n", |
490 | 0 | gnutls_strerror(rc)); |
491 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
492 | 0 | } |
493 | 0 | dump_data_pw("ntlmv1 clear data\n", data, length); |
494 | 0 | } |
495 | | |
496 | 0 | status = ntlmssp_check_packet(ntlmssp_state, |
497 | 0 | data, length, |
498 | 0 | whole_pdu, pdu_length, |
499 | 0 | sig); |
500 | |
|
501 | 0 | if (!NT_STATUS_IS_OK(status)) { |
502 | 0 | DEBUG(1,("NTLMSSP packet check for unseal failed due to invalid signature on %llu bytes of input:\n", |
503 | 0 | (unsigned long long)length)); |
504 | 0 | } |
505 | 0 | return status; |
506 | 0 | } |
507 | | |
508 | | NTSTATUS ntlmssp_wrap(struct ntlmssp_state *ntlmssp_state, |
509 | | TALLOC_CTX *out_mem_ctx, |
510 | | const DATA_BLOB *in, |
511 | | DATA_BLOB *out) |
512 | 0 | { |
513 | 0 | NTSTATUS nt_status; |
514 | 0 | DATA_BLOB sig; |
515 | |
|
516 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { |
517 | 0 | if (in->length + NTLMSSP_SIG_SIZE < in->length) { |
518 | 0 | return NT_STATUS_INVALID_PARAMETER; |
519 | 0 | } |
520 | | |
521 | 0 | *out = data_blob_talloc(out_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); |
522 | 0 | if (!out->data) { |
523 | 0 | return NT_STATUS_NO_MEMORY; |
524 | 0 | } |
525 | 0 | memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); |
526 | |
|
527 | 0 | nt_status = ntlmssp_seal_packet(ntlmssp_state, out_mem_ctx, |
528 | 0 | out->data + NTLMSSP_SIG_SIZE, |
529 | 0 | out->length - NTLMSSP_SIG_SIZE, |
530 | 0 | out->data + NTLMSSP_SIG_SIZE, |
531 | 0 | out->length - NTLMSSP_SIG_SIZE, |
532 | 0 | &sig); |
533 | |
|
534 | 0 | if (NT_STATUS_IS_OK(nt_status)) { |
535 | 0 | memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); |
536 | 0 | talloc_free(sig.data); |
537 | 0 | } |
538 | 0 | return nt_status; |
539 | |
|
540 | 0 | } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { |
541 | 0 | if (in->length + NTLMSSP_SIG_SIZE < in->length) { |
542 | 0 | return NT_STATUS_INVALID_PARAMETER; |
543 | 0 | } |
544 | | |
545 | 0 | *out = data_blob_talloc(out_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); |
546 | 0 | if (!out->data) { |
547 | 0 | return NT_STATUS_NO_MEMORY; |
548 | 0 | } |
549 | 0 | memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); |
550 | |
|
551 | 0 | nt_status = ntlmssp_sign_packet(ntlmssp_state, out_mem_ctx, |
552 | 0 | out->data + NTLMSSP_SIG_SIZE, |
553 | 0 | out->length - NTLMSSP_SIG_SIZE, |
554 | 0 | out->data + NTLMSSP_SIG_SIZE, |
555 | 0 | out->length - NTLMSSP_SIG_SIZE, |
556 | 0 | &sig); |
557 | |
|
558 | 0 | if (NT_STATUS_IS_OK(nt_status)) { |
559 | 0 | memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); |
560 | 0 | talloc_free(sig.data); |
561 | 0 | } |
562 | 0 | return nt_status; |
563 | 0 | } else { |
564 | 0 | *out = data_blob_talloc(out_mem_ctx, in->data, in->length); |
565 | 0 | if (!out->data) { |
566 | 0 | return NT_STATUS_NO_MEMORY; |
567 | 0 | } |
568 | 0 | return NT_STATUS_OK; |
569 | 0 | } |
570 | 0 | } |
571 | | |
572 | | NTSTATUS ntlmssp_unwrap(struct ntlmssp_state *ntlmssp_state, |
573 | | TALLOC_CTX *out_mem_ctx, |
574 | | const DATA_BLOB *in, |
575 | | DATA_BLOB *out) |
576 | 0 | { |
577 | 0 | DATA_BLOB sig; |
578 | |
|
579 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { |
580 | 0 | if (in->length < NTLMSSP_SIG_SIZE) { |
581 | 0 | return NT_STATUS_INVALID_PARAMETER; |
582 | 0 | } |
583 | 0 | sig.data = in->data; |
584 | 0 | sig.length = NTLMSSP_SIG_SIZE; |
585 | |
|
586 | 0 | *out = data_blob_talloc(out_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); |
587 | |
|
588 | 0 | return ntlmssp_unseal_packet(ntlmssp_state, |
589 | 0 | out->data, out->length, |
590 | 0 | out->data, out->length, |
591 | 0 | &sig); |
592 | |
|
593 | 0 | } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { |
594 | 0 | if (in->length < NTLMSSP_SIG_SIZE) { |
595 | 0 | return NT_STATUS_INVALID_PARAMETER; |
596 | 0 | } |
597 | 0 | sig.data = in->data; |
598 | 0 | sig.length = NTLMSSP_SIG_SIZE; |
599 | |
|
600 | 0 | *out = data_blob_talloc(out_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); |
601 | |
|
602 | 0 | return ntlmssp_check_packet(ntlmssp_state, |
603 | 0 | out->data, out->length, |
604 | 0 | out->data, out->length, |
605 | 0 | &sig); |
606 | 0 | } else { |
607 | 0 | *out = data_blob_talloc(out_mem_ctx, in->data, in->length); |
608 | 0 | if (!out->data) { |
609 | 0 | return NT_STATUS_NO_MEMORY; |
610 | 0 | } |
611 | 0 | return NT_STATUS_OK; |
612 | 0 | } |
613 | 0 | } |
614 | | |
615 | | /** |
616 | | Initialise the state for NTLMSSP signing. |
617 | | */ |
618 | | NTSTATUS ntlmssp_sign_reset(struct ntlmssp_state *ntlmssp_state, |
619 | | bool reset_seqnums) |
620 | 0 | { |
621 | 0 | int rc; |
622 | |
|
623 | 0 | DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n")); |
624 | 0 | debug_ntlmssp_flags(ntlmssp_state->neg_flags); |
625 | |
|
626 | 0 | if (ntlmssp_state->crypt == NULL) { |
627 | 0 | return NT_STATUS_INVALID_PARAMETER_MIX; |
628 | 0 | } |
629 | | |
630 | 0 | if (ntlmssp_state->force_wrap_seal && |
631 | 0 | (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) |
632 | 0 | { |
633 | | /* |
634 | | * We need to handle NTLMSSP_NEGOTIATE_SIGN as |
635 | | * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE |
636 | | * is requested. |
637 | | * |
638 | | * The negotiation of flags (and authentication) |
639 | | * is completed when ntlmssp_sign_init() is called |
640 | | * so we can safely pretent NTLMSSP_NEGOTIATE_SEAL |
641 | | * was negotiated. |
642 | | */ |
643 | 0 | ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; |
644 | 0 | } |
645 | |
|
646 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { |
647 | 0 | DATA_BLOB weak_session_key = ntlmssp_state->session_key; |
648 | 0 | const char *send_sign_const; |
649 | 0 | const char *send_seal_const; |
650 | 0 | const char *recv_sign_const; |
651 | 0 | const char *recv_seal_const; |
652 | 0 | uint8_t send_seal_key[16] = {0}; |
653 | 0 | gnutls_datum_t send_seal_blob = { |
654 | 0 | .data = send_seal_key, |
655 | 0 | .size = sizeof(send_seal_key), |
656 | 0 | }; |
657 | 0 | uint8_t recv_seal_key[16] = {0}; |
658 | 0 | gnutls_datum_t recv_seal_blob = { |
659 | 0 | .data = recv_seal_key, |
660 | 0 | .size = sizeof(recv_seal_key), |
661 | 0 | }; |
662 | 0 | NTSTATUS status; |
663 | |
|
664 | 0 | switch (ntlmssp_state->role) { |
665 | 0 | case NTLMSSP_CLIENT: |
666 | 0 | send_sign_const = CLI_SIGN; |
667 | 0 | send_seal_const = CLI_SEAL; |
668 | 0 | recv_sign_const = SRV_SIGN; |
669 | 0 | recv_seal_const = SRV_SEAL; |
670 | 0 | break; |
671 | 0 | case NTLMSSP_SERVER: |
672 | 0 | send_sign_const = SRV_SIGN; |
673 | 0 | send_seal_const = SRV_SEAL; |
674 | 0 | recv_sign_const = CLI_SIGN; |
675 | 0 | recv_seal_const = CLI_SEAL; |
676 | 0 | break; |
677 | 0 | default: |
678 | 0 | return NT_STATUS_INTERNAL_ERROR; |
679 | 0 | } |
680 | | |
681 | | /* |
682 | | * Weaken NTLMSSP keys to cope with down-level |
683 | | * clients, servers and export restrictions. |
684 | | * |
685 | | * We probably should have some parameters to |
686 | | * control this, once we get NTLM2 working. |
687 | | * |
688 | | * Key weakening was not performed on the master key |
689 | | * for NTLM2, but must be done on the encryption subkeys only. |
690 | | */ |
691 | | |
692 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) { |
693 | | /* nothing to do */ |
694 | 0 | } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { |
695 | 0 | weak_session_key.length = 7; |
696 | 0 | } else { /* forty bits */ |
697 | 0 | weak_session_key.length = 5; |
698 | 0 | } |
699 | |
|
700 | 0 | dump_data_pw("NTLMSSP weakend master key:\n", |
701 | 0 | weak_session_key.data, |
702 | 0 | weak_session_key.length); |
703 | | |
704 | | /* SEND: sign key */ |
705 | 0 | status = calc_ntlmv2_key(ntlmssp_state->crypt->ntlm2.sending.sign_key, |
706 | 0 | ntlmssp_state->session_key, send_sign_const); |
707 | 0 | if (!NT_STATUS_IS_OK(status)) { |
708 | 0 | return status; |
709 | 0 | } |
710 | 0 | dump_data_pw("NTLMSSP send sign key:\n", |
711 | 0 | ntlmssp_state->crypt->ntlm2.sending.sign_key, 16); |
712 | | |
713 | | /* SEND: seal ARCFOUR pad */ |
714 | 0 | status = calc_ntlmv2_key(send_seal_key, |
715 | 0 | weak_session_key, |
716 | 0 | send_seal_const); |
717 | 0 | if (!NT_STATUS_IS_OK(status)) { |
718 | 0 | return status; |
719 | 0 | } |
720 | 0 | dump_data_pw("NTLMSSP send seal key:\n", |
721 | 0 | send_seal_key, |
722 | 0 | sizeof(send_seal_key)); |
723 | |
|
724 | 0 | if (ntlmssp_state->crypt->ntlm2.sending.seal_state != NULL) { |
725 | 0 | gnutls_cipher_deinit(ntlmssp_state->crypt->ntlm2.sending.seal_state); |
726 | 0 | } |
727 | 0 | rc = gnutls_cipher_init(&ntlmssp_state->crypt->ntlm2.sending.seal_state, |
728 | 0 | GNUTLS_CIPHER_ARCFOUR_128, |
729 | 0 | &send_seal_blob, |
730 | 0 | NULL); |
731 | 0 | if (rc < 0) { |
732 | 0 | DBG_ERR("gnutls_cipher_init failed: %s\n", |
733 | 0 | gnutls_strerror(rc)); |
734 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
735 | 0 | } |
736 | | |
737 | 0 | dump_arc4_state("NTLMSSP send seal arc4 state:\n", |
738 | 0 | &ntlmssp_state->crypt->ntlm2.sending.seal_state); |
739 | | |
740 | | /* SEND: seq num */ |
741 | 0 | if (reset_seqnums) { |
742 | 0 | ntlmssp_state->crypt->ntlm2.sending.seq_num = 0; |
743 | 0 | } |
744 | | |
745 | | /* RECV: sign key */ |
746 | 0 | status = calc_ntlmv2_key(ntlmssp_state->crypt->ntlm2.receiving.sign_key, |
747 | 0 | ntlmssp_state->session_key, recv_sign_const); |
748 | 0 | if (!NT_STATUS_IS_OK(status)) { |
749 | 0 | return status; |
750 | 0 | } |
751 | 0 | dump_data_pw("NTLMSSP recv sign key:\n", |
752 | 0 | ntlmssp_state->crypt->ntlm2.receiving.sign_key, 16); |
753 | | |
754 | | /* RECV: seal ARCFOUR pad */ |
755 | 0 | status = calc_ntlmv2_key(recv_seal_key, |
756 | 0 | weak_session_key, |
757 | 0 | recv_seal_const); |
758 | 0 | if (!NT_STATUS_IS_OK(status)) { |
759 | 0 | return status; |
760 | 0 | } |
761 | 0 | dump_data_pw("NTLMSSP recv seal key:\n", |
762 | 0 | recv_seal_key, |
763 | 0 | sizeof(recv_seal_key)); |
764 | |
|
765 | 0 | if (ntlmssp_state->crypt->ntlm2.receiving.seal_state != NULL) { |
766 | 0 | gnutls_cipher_deinit(ntlmssp_state->crypt->ntlm2.receiving.seal_state); |
767 | 0 | } |
768 | 0 | rc = gnutls_cipher_init(&ntlmssp_state->crypt->ntlm2.receiving.seal_state, |
769 | 0 | GNUTLS_CIPHER_ARCFOUR_128, |
770 | 0 | &recv_seal_blob, |
771 | 0 | NULL); |
772 | 0 | if (rc < 0) { |
773 | 0 | DBG_ERR("gnutls_cipher_init failed: %s\n", |
774 | 0 | gnutls_strerror(rc)); |
775 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
776 | 0 | } |
777 | | |
778 | 0 | dump_arc4_state("NTLMSSP recv seal arc4 state:\n", |
779 | 0 | &ntlmssp_state->crypt->ntlm2.receiving.seal_state); |
780 | | |
781 | | /* RECV: seq num */ |
782 | 0 | if (reset_seqnums) { |
783 | 0 | ntlmssp_state->crypt->ntlm2.receiving.seq_num = 0; |
784 | 0 | } |
785 | 0 | } else { |
786 | 0 | gnutls_datum_t seal_session_key = { |
787 | 0 | .data = ntlmssp_state->session_key.data, |
788 | 0 | .size = ntlmssp_state->session_key.length, |
789 | 0 | }; |
790 | 0 | bool do_weak = false; |
791 | |
|
792 | 0 | DEBUG(5, ("NTLMSSP Sign/Seal - using NTLM1\n")); |
793 | | |
794 | | /* |
795 | | * Key weakening not performed on the master key for NTLM2 |
796 | | * and does not occur for NTLM1. Therefore we only need |
797 | | * to do this for the LM_KEY. |
798 | | */ |
799 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { |
800 | 0 | do_weak = true; |
801 | 0 | } |
802 | | |
803 | | /* |
804 | | * Nothing to weaken. |
805 | | * We certainly don't want to 'extend' the length... |
806 | | */ |
807 | 0 | if (ntlmssp_state->session_key.length < 16) { |
808 | | /* TODO: is this really correct? */ |
809 | 0 | do_weak = false; |
810 | 0 | } |
811 | |
|
812 | 0 | if (do_weak) { |
813 | 0 | uint8_t weak_session_key[8]; |
814 | |
|
815 | 0 | memcpy(weak_session_key, seal_session_key.data, 8); |
816 | 0 | seal_session_key = (gnutls_datum_t) { |
817 | 0 | .data = weak_session_key, |
818 | 0 | .size = sizeof(weak_session_key), |
819 | 0 | }; |
820 | | |
821 | | /* |
822 | | * LM key doesn't support 128 bit crypto, so this is |
823 | | * the best we can do. If you negotiate 128 bit, but |
824 | | * not 56, you end up with 40 bit... |
825 | | */ |
826 | 0 | if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { |
827 | 0 | weak_session_key[7] = 0xa0; |
828 | 0 | } else { /* forty bits */ |
829 | 0 | weak_session_key[5] = 0xe5; |
830 | 0 | weak_session_key[6] = 0x38; |
831 | 0 | weak_session_key[7] = 0xb0; |
832 | 0 | } |
833 | 0 | } |
834 | |
|
835 | 0 | if (ntlmssp_state->crypt->ntlm.seal_state != NULL) { |
836 | 0 | gnutls_cipher_deinit(ntlmssp_state->crypt->ntlm.seal_state); |
837 | 0 | } |
838 | 0 | rc = gnutls_cipher_init(&ntlmssp_state->crypt->ntlm.seal_state, |
839 | 0 | GNUTLS_CIPHER_ARCFOUR_128, |
840 | 0 | &seal_session_key, |
841 | 0 | NULL); |
842 | 0 | if (rc < 0) { |
843 | 0 | DBG_ERR("gnutls_cipher_init failed: %s\n", |
844 | 0 | gnutls_strerror(rc)); |
845 | 0 | return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED); |
846 | 0 | } |
847 | | |
848 | 0 | dump_arc4_state("NTLMv1 arc4 state:\n", |
849 | 0 | &ntlmssp_state->crypt->ntlm.seal_state); |
850 | |
|
851 | 0 | if (reset_seqnums) { |
852 | 0 | ntlmssp_state->crypt->ntlm.seq_num = 0; |
853 | 0 | } |
854 | 0 | } |
855 | | |
856 | 0 | return NT_STATUS_OK; |
857 | 0 | } |
858 | | |
859 | | static int ntlmssp_crypt_free_gnutls_cipher_state(union ntlmssp_crypt_state *c) |
860 | 0 | { |
861 | 0 | if (c->ntlm2.sending.seal_state != NULL) { |
862 | 0 | gnutls_cipher_deinit(c->ntlm2.sending.seal_state); |
863 | 0 | c->ntlm2.sending.seal_state = NULL; |
864 | 0 | } |
865 | 0 | if (c->ntlm2.receiving.seal_state != NULL) { |
866 | 0 | gnutls_cipher_deinit(c->ntlm2.receiving.seal_state); |
867 | 0 | c->ntlm2.receiving.seal_state = NULL; |
868 | 0 | } |
869 | 0 | if (c->ntlm.seal_state != NULL) { |
870 | 0 | gnutls_cipher_deinit(c->ntlm.seal_state); |
871 | 0 | c->ntlm.seal_state = NULL; |
872 | 0 | } |
873 | |
|
874 | 0 | return 0; |
875 | 0 | } |
876 | | |
877 | | NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state) |
878 | 0 | { |
879 | 0 | if (ntlmssp_state->session_key.length < 8) { |
880 | 0 | DEBUG(3, ("NO session key, cannot initialise signing\n")); |
881 | 0 | return NT_STATUS_NO_USER_SESSION_KEY; |
882 | 0 | } |
883 | | |
884 | 0 | ntlmssp_state->crypt = talloc_zero(ntlmssp_state, |
885 | 0 | union ntlmssp_crypt_state); |
886 | 0 | if (ntlmssp_state->crypt == NULL) { |
887 | 0 | return NT_STATUS_NO_MEMORY; |
888 | 0 | } |
889 | 0 | talloc_set_destructor(ntlmssp_state->crypt, |
890 | 0 | ntlmssp_crypt_free_gnutls_cipher_state); |
891 | |
|
892 | | return ntlmssp_sign_reset(ntlmssp_state, true); |
893 | 0 | } |