Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : dcerpc schannel operations
5 :
6 : Copyright (C) Andrew Tridgell 2004
7 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include <tevent.h>
25 : #include "lib/util/tevent_ntstatus.h"
26 : #include "librpc/gen_ndr/ndr_schannel.h"
27 : #include "auth/auth.h"
28 : #include "auth/credentials/credentials.h"
29 : #include "auth/gensec/gensec.h"
30 : #include "auth/gensec/gensec_internal.h"
31 : #include "auth/gensec/gensec_proto.h"
32 : #include "../libcli/auth/schannel.h"
33 : #include "librpc/gen_ndr/dcerpc.h"
34 : #include "param/param.h"
35 : #include "auth/gensec/gensec_toplevel_proto.h"
36 : #include "libds/common/roles.h"
37 :
38 : #ifndef HAVE_GNUTLS_AES_CFB8
39 : #include "lib/crypto/aes.h"
40 : #endif
41 :
42 : #include "lib/crypto/gnutls_helpers.h"
43 : #include <gnutls/gnutls.h>
44 : #include <gnutls/crypto.h>
45 :
46 : #undef DBGC_CLASS
47 : #define DBGC_CLASS DBGC_AUTH
48 :
49 : struct schannel_state {
50 : struct gensec_security *gensec;
51 : uint64_t seq_num;
52 : bool initiator;
53 : struct netlogon_creds_CredentialState *creds;
54 : struct auth_user_info_dc *user_info_dc;
55 : };
56 :
57 : #define SETUP_SEQNUM(state, buf, initiator) do { \
58 : uint8_t *_buf = buf; \
59 : uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \
60 : uint32_t _seq_num_high = (state)->seq_num >> 32; \
61 : if (initiator) { \
62 : _seq_num_high |= 0x80000000; \
63 : } \
64 : RSIVAL(_buf, 0, _seq_num_low); \
65 : RSIVAL(_buf, 4, _seq_num_high); \
66 : } while(0)
67 :
68 2115 : static struct schannel_state *netsec_create_state(
69 : struct gensec_security *gensec,
70 : struct netlogon_creds_CredentialState *creds,
71 : bool initiator)
72 : {
73 : struct schannel_state *state;
74 :
75 2115 : state = talloc_zero(gensec, struct schannel_state);
76 2115 : if (state == NULL) {
77 0 : return NULL;
78 : }
79 :
80 2115 : state->gensec = gensec;
81 2115 : state->initiator = initiator;
82 2115 : state->creds = netlogon_creds_copy(state, creds);
83 2115 : if (state->creds == NULL) {
84 0 : talloc_free(state);
85 0 : return NULL;
86 : }
87 :
88 2115 : gensec->private_data = state;
89 :
90 2115 : return state;
91 : }
92 :
93 86875 : static void netsec_offset_and_sizes(struct schannel_state *state,
94 : bool do_seal,
95 : uint32_t *_min_sig_size,
96 : uint32_t *_used_sig_size,
97 : uint32_t *_checksum_length,
98 : uint32_t *_confounder_ofs)
99 : {
100 : uint32_t min_sig_size;
101 : uint32_t used_sig_size;
102 : uint32_t checksum_length;
103 : uint32_t confounder_ofs;
104 :
105 86875 : if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
106 37441 : min_sig_size = 48;
107 37441 : used_sig_size = 56;
108 : /*
109 : * Note: windows has a bug here and uses the old values...
110 : *
111 : * checksum_length = 32;
112 : * confounder_ofs = 48;
113 : */
114 37441 : checksum_length = 8;
115 37441 : confounder_ofs = 24;
116 : } else {
117 49434 : min_sig_size = 24;
118 49434 : used_sig_size = 32;
119 49434 : checksum_length = 8;
120 49434 : confounder_ofs = 24;
121 : }
122 :
123 86875 : if (do_seal) {
124 75499 : min_sig_size += 8;
125 : }
126 :
127 86875 : if (_min_sig_size) {
128 57922 : *_min_sig_size = min_sig_size;
129 : }
130 :
131 86875 : if (_used_sig_size) {
132 57906 : *_used_sig_size = used_sig_size;
133 : }
134 :
135 86875 : if (_checksum_length) {
136 57922 : *_checksum_length = checksum_length;
137 : }
138 :
139 86875 : if (_confounder_ofs) {
140 57922 : *_confounder_ofs = confounder_ofs;
141 : }
142 86875 : }
143 :
144 : /*******************************************************************
145 : Encode or Decode the sequence number (which is symmetric)
146 : ********************************************************************/
147 57922 : static NTSTATUS netsec_do_seq_num(struct schannel_state *state,
148 : const uint8_t *checksum,
149 : uint32_t checksum_length,
150 : uint8_t seq_num[8])
151 : {
152 57922 : if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
153 : #ifdef HAVE_GNUTLS_AES_CFB8
154 2354 : gnutls_cipher_hd_t cipher_hnd = NULL;
155 2354 : gnutls_datum_t key = {
156 2354 : .data = state->creds->session_key,
157 : .size = sizeof(state->creds->session_key),
158 : };
159 : uint32_t iv_size =
160 2354 : gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
161 2354 : uint8_t _iv[iv_size];
162 2354 : gnutls_datum_t iv = {
163 : .data = _iv,
164 : .size = iv_size,
165 : };
166 : int rc;
167 :
168 2354 : ZERO_ARRAY(_iv);
169 :
170 2354 : memcpy(iv.data + 0, checksum, 8);
171 2354 : memcpy(iv.data + 8, checksum, 8);
172 :
173 2354 : rc = gnutls_cipher_init(&cipher_hnd,
174 : GNUTLS_CIPHER_AES_128_CFB8,
175 : &key,
176 : &iv);
177 2354 : if (rc < 0) {
178 0 : return gnutls_error_to_ntstatus(rc,
179 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
180 : }
181 :
182 2354 : rc = gnutls_cipher_encrypt(cipher_hnd, seq_num, 8);
183 2354 : gnutls_cipher_deinit(cipher_hnd);
184 2354 : if (rc < 0) {
185 0 : return gnutls_error_to_ntstatus(rc,
186 : NT_STATUS_CRYPTO_SYSTEM_INVALID);
187 : }
188 :
189 : #else /* NOT HAVE_GNUTLS_AES_CFB8 */
190 : AES_KEY key;
191 : uint8_t iv[AES_BLOCK_SIZE];
192 :
193 22612 : AES_set_encrypt_key(state->creds->session_key, 128, &key);
194 22612 : ZERO_STRUCT(iv);
195 22612 : memcpy(iv+0, checksum, 8);
196 22612 : memcpy(iv+8, checksum, 8);
197 :
198 22612 : aes_cfb8_encrypt(seq_num, seq_num, 8, &key, iv, AES_ENCRYPT);
199 : #endif /* HAVE_GNUTLS_AES_CFB8 */
200 : } else {
201 : static const uint8_t zeros[4];
202 : uint8_t _sequence_key[16];
203 : gnutls_cipher_hd_t cipher_hnd;
204 32956 : gnutls_datum_t sequence_key = {
205 : .data = _sequence_key,
206 : .size = sizeof(_sequence_key),
207 : };
208 : uint8_t digest1[16];
209 : int rc;
210 :
211 32956 : rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
212 32956 : state->creds->session_key,
213 : sizeof(state->creds->session_key),
214 : zeros,
215 : sizeof(zeros),
216 : digest1);
217 32956 : if (rc < 0) {
218 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
219 : }
220 :
221 32956 : rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
222 : digest1,
223 : sizeof(digest1),
224 : checksum,
225 : checksum_length,
226 : _sequence_key);
227 32956 : if (rc < 0) {
228 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
229 : }
230 :
231 32956 : ZERO_ARRAY(digest1);
232 :
233 32956 : rc = gnutls_cipher_init(&cipher_hnd,
234 : GNUTLS_CIPHER_ARCFOUR_128,
235 : &sequence_key,
236 : NULL);
237 32956 : if (rc < 0) {
238 0 : ZERO_ARRAY(_sequence_key);
239 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
240 : }
241 :
242 32956 : rc = gnutls_cipher_encrypt(cipher_hnd,
243 : seq_num,
244 : 8);
245 32956 : gnutls_cipher_deinit(cipher_hnd);
246 32956 : ZERO_ARRAY(_sequence_key);
247 32956 : if (rc < 0) {
248 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
249 : }
250 : }
251 :
252 57922 : state->seq_num++;
253 :
254 57922 : return NT_STATUS_OK;
255 : }
256 :
257 46546 : static NTSTATUS netsec_do_seal(struct schannel_state *state,
258 : const uint8_t seq_num[8],
259 : uint8_t confounder[8],
260 : uint8_t *data, uint32_t length,
261 : bool forward)
262 : {
263 46546 : if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
264 : #ifdef HAVE_GNUTLS_AES_CFB8
265 2354 : gnutls_cipher_hd_t cipher_hnd = NULL;
266 2354 : uint8_t sess_kf0[16] = {0};
267 2354 : gnutls_datum_t key = {
268 : .data = sess_kf0,
269 : .size = sizeof(sess_kf0),
270 : };
271 : uint32_t iv_size =
272 2354 : gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
273 2354 : uint8_t _iv[iv_size];
274 2354 : gnutls_datum_t iv = {
275 : .data = _iv,
276 : .size = iv_size,
277 : };
278 : uint32_t i;
279 : int rc;
280 :
281 40018 : for (i = 0; i < key.size; i++) {
282 37664 : key.data[i] = state->creds->session_key[i] ^ 0xf0;
283 : }
284 :
285 2354 : ZERO_ARRAY(_iv);
286 :
287 2354 : memcpy(iv.data + 0, seq_num, 8);
288 2354 : memcpy(iv.data + 8, seq_num, 8);
289 :
290 2354 : rc = gnutls_cipher_init(&cipher_hnd,
291 : GNUTLS_CIPHER_AES_128_CFB8,
292 : &key,
293 : &iv);
294 2354 : if (rc < 0) {
295 0 : DBG_ERR("ERROR: gnutls_cipher_init: %s\n",
296 : gnutls_strerror(rc));
297 0 : return NT_STATUS_NO_MEMORY;
298 : }
299 :
300 2354 : if (forward) {
301 1173 : rc = gnutls_cipher_encrypt(cipher_hnd,
302 : confounder,
303 : 8);
304 1173 : if (rc < 0) {
305 0 : gnutls_cipher_deinit(cipher_hnd);
306 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
307 : }
308 :
309 1173 : rc = gnutls_cipher_encrypt(cipher_hnd,
310 : data,
311 : length);
312 1173 : if (rc < 0) {
313 0 : gnutls_cipher_deinit(cipher_hnd);
314 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
315 : }
316 : } else {
317 :
318 : /*
319 : * Workaround bug present in gnutls 3.6.8:
320 : *
321 : * gnutls_cipher_decrypt() uses an optimization
322 : * internally that breaks decryption when processing
323 : * buffers with their length not being a multiple
324 : * of the blocksize.
325 : */
326 :
327 1181 : uint8_t tmp[16] = { 0, };
328 1181 : uint32_t tmp_dlength = MIN(length, sizeof(tmp) - 8);
329 :
330 1181 : memcpy(tmp, confounder, 8);
331 1181 : memcpy(tmp + 8, data, tmp_dlength);
332 :
333 1181 : rc = gnutls_cipher_decrypt(cipher_hnd,
334 : tmp,
335 1181 : 8 + tmp_dlength);
336 1181 : if (rc < 0) {
337 0 : ZERO_STRUCT(tmp);
338 0 : gnutls_cipher_deinit(cipher_hnd);
339 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
340 : }
341 :
342 1181 : memcpy(confounder, tmp, 8);
343 1181 : memcpy(data, tmp + 8, tmp_dlength);
344 1181 : ZERO_STRUCT(tmp);
345 :
346 1181 : if (length > tmp_dlength) {
347 1181 : rc = gnutls_cipher_decrypt(cipher_hnd,
348 1181 : data + tmp_dlength,
349 1181 : length - tmp_dlength);
350 1181 : if (rc < 0) {
351 0 : gnutls_cipher_deinit(cipher_hnd);
352 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
353 : }
354 : }
355 : }
356 2354 : gnutls_cipher_deinit(cipher_hnd);
357 : #else /* NOT HAVE_GNUTLS_AES_CFB8 */
358 : AES_KEY key;
359 : uint8_t iv[AES_BLOCK_SIZE];
360 : uint8_t sess_kf0[16];
361 : int i;
362 :
363 253436 : for (i = 0; i < 16; i++) {
364 238528 : sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
365 : }
366 :
367 14908 : AES_set_encrypt_key(sess_kf0, 128, &key);
368 14908 : ZERO_STRUCT(iv);
369 14908 : memcpy(iv+0, seq_num, 8);
370 14908 : memcpy(iv+8, seq_num, 8);
371 :
372 14908 : if (forward) {
373 7450 : aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT);
374 7450 : aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT);
375 : } else {
376 7458 : aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT);
377 7458 : aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT);
378 : }
379 : #endif /* HAVE_GNUTLS_AES_CFB8 */
380 : } else {
381 : gnutls_cipher_hd_t cipher_hnd;
382 : uint8_t _sealing_key[16];
383 29284 : gnutls_datum_t sealing_key = {
384 : .data = _sealing_key,
385 : .size = sizeof(_sealing_key),
386 : };
387 : static const uint8_t zeros[4];
388 : uint8_t digest2[16];
389 : uint8_t sess_kf0[16];
390 : int rc;
391 : int i;
392 :
393 497828 : for (i = 0; i < 16; i++) {
394 468544 : sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
395 : }
396 :
397 29284 : rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
398 : sess_kf0,
399 : sizeof(sess_kf0),
400 : zeros,
401 : 4,
402 : digest2);
403 29284 : if (rc < 0) {
404 0 : ZERO_ARRAY(digest2);
405 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
406 : }
407 :
408 29284 : rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
409 : digest2,
410 : sizeof(digest2),
411 : seq_num,
412 : 8,
413 : _sealing_key);
414 :
415 29284 : ZERO_ARRAY(digest2);
416 29284 : if (rc < 0) {
417 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
418 : }
419 :
420 29284 : rc = gnutls_cipher_init(&cipher_hnd,
421 : GNUTLS_CIPHER_ARCFOUR_128,
422 : &sealing_key,
423 : NULL);
424 29284 : if (rc < 0) {
425 0 : ZERO_ARRAY(_sealing_key);
426 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
427 : }
428 29284 : rc = gnutls_cipher_encrypt(cipher_hnd,
429 : confounder,
430 : 8);
431 29284 : if (rc < 0) {
432 0 : ZERO_ARRAY(_sealing_key);
433 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
434 : }
435 29284 : gnutls_cipher_deinit(cipher_hnd);
436 29284 : rc = gnutls_cipher_init(&cipher_hnd,
437 : GNUTLS_CIPHER_ARCFOUR_128,
438 : &sealing_key,
439 : NULL);
440 29284 : if (rc < 0) {
441 0 : ZERO_ARRAY(_sealing_key);
442 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
443 : }
444 29284 : rc = gnutls_cipher_encrypt(cipher_hnd,
445 : data,
446 : length);
447 29284 : gnutls_cipher_deinit(cipher_hnd);
448 29284 : ZERO_ARRAY(_sealing_key);
449 29284 : if (rc < 0) {
450 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
451 : }
452 : }
453 :
454 46546 : return NT_STATUS_OK;
455 : }
456 :
457 : /*******************************************************************
458 : Create a digest over the entire packet (including the data), and
459 : MD5 it with the session key.
460 : ********************************************************************/
461 57922 : static NTSTATUS netsec_do_sign(struct schannel_state *state,
462 : const uint8_t *confounder,
463 : const uint8_t *data, size_t length,
464 : uint8_t header[8],
465 : uint8_t *checksum)
466 : {
467 57922 : if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
468 24966 : gnutls_hmac_hd_t hmac_hnd = NULL;
469 : int rc;
470 :
471 24966 : rc = gnutls_hmac_init(&hmac_hnd,
472 : GNUTLS_MAC_SHA256,
473 24966 : state->creds->session_key,
474 : sizeof(state->creds->session_key));
475 24966 : if (rc < 0) {
476 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
477 : }
478 :
479 24966 : if (confounder) {
480 17262 : SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
481 17262 : SSVAL(header, 2, NL_SEAL_AES128);
482 17262 : SSVAL(header, 4, 0xFFFF);
483 17262 : SSVAL(header, 6, 0x0000);
484 :
485 17262 : rc = gnutls_hmac(hmac_hnd, header, 8);
486 17262 : if (rc < 0) {
487 0 : gnutls_hmac_deinit(hmac_hnd, NULL);
488 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
489 : }
490 17262 : rc = gnutls_hmac(hmac_hnd, confounder, 8);
491 17262 : if (rc < 0) {
492 0 : gnutls_hmac_deinit(hmac_hnd, NULL);
493 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
494 : }
495 : } else {
496 7704 : SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
497 7704 : SSVAL(header, 2, NL_SEAL_NONE);
498 7704 : SSVAL(header, 4, 0xFFFF);
499 7704 : SSVAL(header, 6, 0x0000);
500 :
501 7704 : rc = gnutls_hmac(hmac_hnd, header, 8);
502 7704 : if (rc < 0) {
503 0 : gnutls_hmac_deinit(hmac_hnd, NULL);
504 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
505 : }
506 : }
507 :
508 24966 : rc = gnutls_hmac(hmac_hnd, data, length);
509 24966 : if (rc < 0) {
510 0 : gnutls_hmac_deinit(hmac_hnd, NULL);
511 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
512 : }
513 :
514 24966 : gnutls_hmac_deinit(hmac_hnd, checksum);
515 : } else {
516 : uint8_t packet_digest[16];
517 : static const uint8_t zeros[4];
518 32956 : gnutls_hash_hd_t hash_hnd = NULL;
519 : int rc;
520 :
521 32956 : rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
522 32956 : if (rc < 0) {
523 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
524 : }
525 :
526 32956 : rc = gnutls_hash(hash_hnd, zeros, sizeof(zeros));
527 32956 : if (rc < 0) {
528 0 : gnutls_hash_deinit(hash_hnd, NULL);
529 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
530 : }
531 32956 : if (confounder) {
532 29284 : SSVAL(header, 0, NL_SIGN_HMAC_MD5);
533 29284 : SSVAL(header, 2, NL_SEAL_RC4);
534 29284 : SSVAL(header, 4, 0xFFFF);
535 29284 : SSVAL(header, 6, 0x0000);
536 :
537 29284 : rc = gnutls_hash(hash_hnd, header, 8);
538 29284 : if (rc < 0) {
539 0 : gnutls_hash_deinit(hash_hnd, NULL);
540 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
541 : }
542 29284 : rc = gnutls_hash(hash_hnd, confounder, 8);
543 29284 : if (rc < 0) {
544 0 : gnutls_hash_deinit(hash_hnd, NULL);
545 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
546 : }
547 : } else {
548 3672 : SSVAL(header, 0, NL_SIGN_HMAC_MD5);
549 3672 : SSVAL(header, 2, NL_SEAL_NONE);
550 3672 : SSVAL(header, 4, 0xFFFF);
551 3672 : SSVAL(header, 6, 0x0000);
552 :
553 3672 : rc = gnutls_hash(hash_hnd, header, 8);
554 3672 : if (rc < 0) {
555 0 : gnutls_hash_deinit(hash_hnd, NULL);
556 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
557 : }
558 : }
559 32956 : rc = gnutls_hash(hash_hnd, data, length);
560 32956 : if (rc < 0) {
561 0 : gnutls_hash_deinit(hash_hnd, NULL);
562 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
563 : }
564 32956 : gnutls_hash_deinit(hash_hnd, packet_digest);
565 :
566 32956 : rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
567 32956 : state->creds->session_key,
568 : sizeof(state->creds->session_key),
569 : packet_digest,
570 : sizeof(packet_digest),
571 : checksum);
572 32956 : ZERO_ARRAY(packet_digest);
573 32956 : if (rc < 0) {
574 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
575 : }
576 : }
577 :
578 57922 : return NT_STATUS_OK;
579 : }
580 :
581 28969 : static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
582 : bool do_unseal,
583 : uint8_t *data, size_t length,
584 : const uint8_t *whole_pdu, size_t pdu_length,
585 : const DATA_BLOB *sig)
586 : {
587 28969 : uint32_t min_sig_size = 0;
588 : uint8_t header[8];
589 : uint8_t checksum[32];
590 28969 : uint32_t checksum_length = sizeof(checksum_length);
591 : uint8_t _confounder[8];
592 28969 : uint8_t *confounder = NULL;
593 28969 : uint32_t confounder_ofs = 0;
594 : uint8_t seq_num[8];
595 : bool ret;
596 28969 : const uint8_t *sign_data = NULL;
597 28969 : size_t sign_length = 0;
598 : NTSTATUS status;
599 :
600 28969 : netsec_offset_and_sizes(state,
601 : do_unseal,
602 : &min_sig_size,
603 : NULL,
604 : &checksum_length,
605 : &confounder_ofs);
606 :
607 28969 : if (sig->length < min_sig_size) {
608 0 : return NT_STATUS_ACCESS_DENIED;
609 : }
610 :
611 28969 : if (do_unseal) {
612 23281 : confounder = _confounder;
613 23281 : memcpy(confounder, sig->data+confounder_ofs, 8);
614 : } else {
615 5688 : confounder = NULL;
616 : }
617 :
618 28969 : SETUP_SEQNUM(state, seq_num, !state->initiator);
619 :
620 28969 : if (do_unseal) {
621 23281 : status = netsec_do_seal(state,
622 : seq_num,
623 : confounder,
624 : data,
625 : length,
626 : false);
627 23281 : if (!NT_STATUS_IS_OK(status)) {
628 0 : DBG_WARNING("netsec_do_seal failed: %s\n", nt_errstr(status));
629 0 : return NT_STATUS_ACCESS_DENIED;
630 : }
631 : }
632 :
633 28969 : if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
634 28799 : sign_data = whole_pdu;
635 28799 : sign_length = pdu_length;
636 : } else {
637 170 : sign_data = data;
638 170 : sign_length = length;
639 : }
640 :
641 28969 : status = netsec_do_sign(state,
642 : confounder,
643 : sign_data,
644 : sign_length,
645 : header,
646 : checksum);
647 28969 : if (!NT_STATUS_IS_OK(status)) {
648 0 : DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
649 0 : return NT_STATUS_ACCESS_DENIED;
650 : }
651 :
652 28969 : ret = mem_equal_const_time(checksum, sig->data+16, checksum_length);
653 28969 : if (!ret) {
654 0 : dump_data_pw("calc digest:", checksum, checksum_length);
655 0 : dump_data_pw("wire digest:", sig->data+16, checksum_length);
656 0 : return NT_STATUS_ACCESS_DENIED;
657 : }
658 :
659 28969 : status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
660 28969 : if (!NT_STATUS_IS_OK(status)) {
661 0 : DBG_WARNING("netsec_do_seq_num failed: %s\n",
662 : nt_errstr(status));
663 0 : return status;
664 : }
665 :
666 28969 : ZERO_ARRAY(checksum);
667 :
668 28969 : ret = mem_equal_const_time(seq_num, sig->data+8, 8);
669 28969 : if (!ret) {
670 0 : dump_data_pw("calc seq num:", seq_num, 8);
671 0 : dump_data_pw("wire seq num:", sig->data+8, 8);
672 0 : return NT_STATUS_ACCESS_DENIED;
673 : }
674 :
675 28969 : return NT_STATUS_OK;
676 : }
677 :
678 28953 : static uint32_t netsec_outgoing_sig_size(struct schannel_state *state)
679 : {
680 28953 : uint32_t sig_size = 0;
681 :
682 28953 : netsec_offset_and_sizes(state,
683 : true,
684 : NULL,
685 : &sig_size,
686 : NULL,
687 : NULL);
688 :
689 28953 : return sig_size;
690 : }
691 :
692 28953 : static NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
693 : TALLOC_CTX *mem_ctx,
694 : bool do_seal,
695 : uint8_t *data, size_t length,
696 : const uint8_t *whole_pdu, size_t pdu_length,
697 : DATA_BLOB *sig)
698 : {
699 28953 : uint32_t min_sig_size = 0;
700 28953 : uint32_t used_sig_size = 0;
701 : uint8_t header[8];
702 : uint8_t checksum[32];
703 28953 : uint32_t checksum_length = sizeof(checksum_length);
704 : uint8_t _confounder[8];
705 28953 : uint8_t *confounder = NULL;
706 28953 : uint32_t confounder_ofs = 0;
707 : uint8_t seq_num[8];
708 28953 : const uint8_t *sign_data = NULL;
709 28953 : size_t sign_length = 0;
710 : NTSTATUS status;
711 :
712 28953 : netsec_offset_and_sizes(state,
713 : do_seal,
714 : &min_sig_size,
715 : &used_sig_size,
716 : &checksum_length,
717 : &confounder_ofs);
718 :
719 28953 : SETUP_SEQNUM(state, seq_num, state->initiator);
720 :
721 28953 : if (do_seal) {
722 23265 : confounder = _confounder;
723 23265 : generate_random_buffer(confounder, 8);
724 : } else {
725 5688 : confounder = NULL;
726 : }
727 :
728 28953 : if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
729 28783 : sign_data = whole_pdu;
730 28783 : sign_length = pdu_length;
731 : } else {
732 170 : sign_data = data;
733 170 : sign_length = length;
734 : }
735 :
736 28953 : status = netsec_do_sign(state,
737 : confounder,
738 : sign_data,
739 : sign_length,
740 : header,
741 : checksum);
742 28953 : if (!NT_STATUS_IS_OK(status)) {
743 0 : DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
744 0 : return NT_STATUS_ACCESS_DENIED;
745 : }
746 :
747 28953 : if (do_seal) {
748 23265 : status = netsec_do_seal(state,
749 : seq_num,
750 : confounder,
751 : data,
752 : length,
753 : true);
754 23265 : if (!NT_STATUS_IS_OK(status)) {
755 0 : DBG_WARNING("netsec_do_seal failed: %s\n",
756 : nt_errstr(status));
757 0 : return status;
758 : }
759 : }
760 :
761 28953 : status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
762 28953 : if (!NT_STATUS_IS_OK(status)) {
763 0 : DBG_WARNING("netsec_do_seq_num failed: %s\n",
764 : nt_errstr(status));
765 0 : return status;
766 : }
767 :
768 28953 : (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
769 :
770 28953 : memcpy(sig->data, header, 8);
771 28953 : memcpy(sig->data+8, seq_num, 8);
772 28953 : memcpy(sig->data+16, checksum, checksum_length);
773 :
774 28953 : if (confounder) {
775 23265 : memcpy(sig->data+confounder_ofs, confounder, 8);
776 : }
777 :
778 28953 : dump_data_pw("signature:", sig->data+ 0, 8);
779 28953 : dump_data_pw("seq_num :", sig->data+ 8, 8);
780 28953 : dump_data_pw("digest :", sig->data+16, checksum_length);
781 28953 : dump_data_pw("confound :", sig->data+confounder_ofs, 8);
782 :
783 28953 : return NT_STATUS_OK;
784 : }
785 :
786 : _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx);
787 :
788 28953 : static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size)
789 : {
790 27780 : struct schannel_state *state =
791 28953 : talloc_get_type_abort(gensec_security->private_data,
792 : struct schannel_state);
793 :
794 28953 : return netsec_outgoing_sig_size(state);
795 : }
796 :
797 : struct schannel_update_state {
798 : NTSTATUS status;
799 : DATA_BLOB out;
800 : };
801 :
802 : static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
803 : TALLOC_CTX *out_mem_ctx,
804 : const DATA_BLOB in, DATA_BLOB *out);
805 :
806 3103 : static struct tevent_req *schannel_update_send(TALLOC_CTX *mem_ctx,
807 : struct tevent_context *ev,
808 : struct gensec_security *gensec_security,
809 : const DATA_BLOB in)
810 : {
811 : struct tevent_req *req;
812 3103 : struct schannel_update_state *state = NULL;
813 : NTSTATUS status;
814 :
815 3103 : req = tevent_req_create(mem_ctx, &state,
816 : struct schannel_update_state);
817 3103 : if (req == NULL) {
818 0 : return NULL;
819 : }
820 :
821 3103 : status = schannel_update_internal(gensec_security,
822 : state, in,
823 3103 : &state->out);
824 3103 : state->status = status;
825 3103 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
826 988 : status = NT_STATUS_OK;
827 : }
828 3103 : if (tevent_req_nterror(req, status)) {
829 0 : return tevent_req_post(req, ev);
830 : }
831 :
832 3103 : tevent_req_done(req);
833 3103 : return tevent_req_post(req, ev);
834 : }
835 :
836 3103 : static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
837 : TALLOC_CTX *out_mem_ctx,
838 : const DATA_BLOB in, DATA_BLOB *out)
839 : {
840 2979 : struct schannel_state *state =
841 3103 : talloc_get_type(gensec_security->private_data,
842 : struct schannel_state);
843 : NTSTATUS status;
844 : enum ndr_err_code ndr_err;
845 3103 : struct NL_AUTH_MESSAGE bind_schannel = {
846 : .Flags = 0,
847 : };
848 : struct NL_AUTH_MESSAGE bind_schannel_ack;
849 : struct netlogon_creds_CredentialState *creds;
850 : const char *workstation;
851 : const char *domain;
852 :
853 3103 : *out = data_blob(NULL, 0);
854 :
855 3103 : if (gensec_security->dcerpc_auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
856 0 : switch (gensec_security->gensec_role) {
857 0 : case GENSEC_CLIENT:
858 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
859 0 : case GENSEC_SERVER:
860 0 : return NT_STATUS_INVALID_PARAMETER;
861 : }
862 0 : return NT_STATUS_INTERNAL_ERROR;
863 : }
864 :
865 3103 : switch (gensec_security->gensec_role) {
866 1976 : case GENSEC_CLIENT:
867 1976 : if (state != NULL) {
868 : /* we could parse the bind ack, but we don't know what it is yet */
869 988 : return NT_STATUS_OK;
870 : }
871 :
872 988 : creds = cli_credentials_get_netlogon_creds(gensec_security->credentials);
873 988 : if (creds == NULL) {
874 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
875 : }
876 :
877 988 : state = netsec_create_state(gensec_security,
878 : creds, true /* initiator */);
879 988 : if (state == NULL) {
880 0 : return NT_STATUS_NO_MEMORY;
881 : }
882 :
883 988 : bind_schannel.MessageType = NL_NEGOTIATE_REQUEST;
884 :
885 988 : bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
886 : NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
887 988 : bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials);
888 988 : bind_schannel.oem_netbios_computer.a = creds->computer_name;
889 :
890 988 : if (creds->secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
891 36 : bind_schannel.Flags |= NL_FLAG_UTF8_DNS_DOMAIN_NAME;
892 36 : bind_schannel.utf8_dns_domain.u = cli_credentials_get_realm(gensec_security->credentials);
893 :
894 36 : bind_schannel.Flags |= NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME;
895 36 : bind_schannel.utf8_netbios_computer.u = creds->computer_name;
896 : }
897 :
898 988 : ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel,
899 : (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
900 988 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
901 0 : status = ndr_map_error2ntstatus(ndr_err);
902 0 : DEBUG(3, ("Could not create schannel bind: %s\n",
903 : nt_errstr(status)));
904 0 : return status;
905 : }
906 :
907 988 : return NT_STATUS_MORE_PROCESSING_REQUIRED;
908 1127 : case GENSEC_SERVER:
909 :
910 1127 : if (state != NULL) {
911 : /* no third leg on this protocol */
912 0 : return NT_STATUS_INVALID_PARAMETER;
913 : }
914 :
915 : /* parse the schannel startup blob */
916 1127 : ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel,
917 : (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE);
918 1127 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
919 0 : status = ndr_map_error2ntstatus(ndr_err);
920 0 : DEBUG(3, ("Could not parse incoming schannel bind: %s\n",
921 : nt_errstr(status)));
922 0 : return status;
923 : }
924 :
925 1127 : if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) {
926 1127 : domain = bind_schannel.oem_netbios_domain.a;
927 1127 : if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) {
928 0 : DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
929 : domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)));
930 0 : return NT_STATUS_LOGON_FAILURE;
931 : }
932 0 : } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) {
933 0 : domain = bind_schannel.utf8_dns_domain.u;
934 0 : if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) {
935 0 : DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
936 : domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)));
937 0 : return NT_STATUS_LOGON_FAILURE;
938 : }
939 : } else {
940 0 : DEBUG(3, ("Request for schannel to without domain\n"));
941 0 : return NT_STATUS_LOGON_FAILURE;
942 : }
943 :
944 1127 : if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) {
945 1127 : workstation = bind_schannel.oem_netbios_computer.a;
946 0 : } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) {
947 0 : workstation = bind_schannel.utf8_netbios_computer.u;
948 : } else {
949 0 : DEBUG(3, ("Request for schannel to without netbios workstation\n"));
950 0 : return NT_STATUS_LOGON_FAILURE;
951 : }
952 :
953 1127 : status = schannel_get_creds_state(out_mem_ctx,
954 1127 : gensec_security->settings->lp_ctx,
955 : workstation, &creds);
956 1127 : if (!NT_STATUS_IS_OK(status)) {
957 0 : DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n",
958 : workstation, nt_errstr(status)));
959 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
960 0 : return NT_STATUS_LOGON_FAILURE;
961 : }
962 0 : return status;
963 : }
964 :
965 1127 : state = netsec_create_state(gensec_security,
966 : creds, false /* not initiator */);
967 1127 : if (state == NULL) {
968 0 : return NT_STATUS_NO_MEMORY;
969 : }
970 :
971 2166 : status = auth_anonymous_user_info_dc(state,
972 1127 : lpcfg_netbios_name(gensec_security->settings->lp_ctx),
973 : &state->user_info_dc);
974 1127 : if (!NT_STATUS_IS_OK(status)) {
975 0 : return status;
976 : }
977 :
978 1127 : bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE;
979 1127 : bind_schannel_ack.Flags = 0;
980 1127 : bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think
981 : * this does not have
982 : * any meaning here
983 : * - gd */
984 :
985 1127 : ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack,
986 : (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
987 1127 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
988 0 : status = ndr_map_error2ntstatus(ndr_err);
989 0 : DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n",
990 : workstation, nt_errstr(status)));
991 0 : return status;
992 : }
993 :
994 1127 : return NT_STATUS_OK;
995 : }
996 0 : return NT_STATUS_INVALID_PARAMETER;
997 : }
998 :
999 3103 : static NTSTATUS schannel_update_recv(struct tevent_req *req,
1000 : TALLOC_CTX *out_mem_ctx,
1001 : DATA_BLOB *out)
1002 : {
1003 2979 : struct schannel_update_state *state =
1004 3103 : tevent_req_data(req,
1005 : struct schannel_update_state);
1006 : NTSTATUS status;
1007 :
1008 3103 : *out = data_blob_null;
1009 :
1010 3103 : if (tevent_req_is_nterror(req, &status)) {
1011 0 : tevent_req_received(req);
1012 0 : return status;
1013 : }
1014 :
1015 3103 : status = state->status;
1016 3103 : talloc_steal(out_mem_ctx, state->out.data);
1017 3103 : *out = state->out;
1018 3103 : tevent_req_received(req);
1019 3103 : return status;
1020 : }
1021 :
1022 : /**
1023 : * Returns anonymous credentials for schannel, matching Win2k3.
1024 : *
1025 : */
1026 :
1027 1127 : static NTSTATUS schannel_session_info(struct gensec_security *gensec_security,
1028 : TALLOC_CTX *mem_ctx,
1029 : struct auth_session_info **_session_info)
1030 : {
1031 1039 : struct schannel_state *state =
1032 1127 : talloc_get_type(gensec_security->private_data,
1033 : struct schannel_state);
1034 1127 : struct auth4_context *auth_ctx = gensec_security->auth_context;
1035 1127 : struct auth_session_info *session_info = NULL;
1036 1127 : uint32_t session_info_flags = 0;
1037 : NTSTATUS status;
1038 :
1039 1127 : if (auth_ctx == NULL) {
1040 0 : DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
1041 0 : return NT_STATUS_INTERNAL_ERROR;
1042 : }
1043 :
1044 1127 : if (auth_ctx->generate_session_info == NULL) {
1045 0 : DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
1046 0 : return NT_STATUS_INTERNAL_ERROR;
1047 : }
1048 :
1049 1127 : if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
1050 0 : session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1051 : }
1052 :
1053 1127 : session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1054 :
1055 3205 : status = auth_ctx->generate_session_info(
1056 : auth_ctx,
1057 : mem_ctx,
1058 1127 : state->user_info_dc,
1059 1127 : state->user_info_dc->info->account_name,
1060 : session_info_flags,
1061 : &session_info);
1062 1127 : if (!NT_STATUS_IS_OK(status)) {
1063 0 : return status;
1064 : }
1065 :
1066 1127 : *_session_info = session_info;
1067 1127 : return NT_STATUS_OK;
1068 : }
1069 :
1070 : /*
1071 : * Reduce the attack surface by ensuring schannel is not availble when
1072 : * we are not a DC
1073 : */
1074 1127 : static NTSTATUS schannel_server_start(struct gensec_security *gensec_security)
1075 : {
1076 1127 : enum server_role server_role
1077 1127 : = lpcfg_server_role(gensec_security->settings->lp_ctx);
1078 :
1079 1127 : switch (server_role) {
1080 1127 : case ROLE_DOMAIN_BDC:
1081 : case ROLE_DOMAIN_PDC:
1082 : case ROLE_ACTIVE_DIRECTORY_DC:
1083 : case ROLE_IPA_DC:
1084 1127 : return NT_STATUS_OK;
1085 0 : default:
1086 0 : return NT_STATUS_NOT_IMPLEMENTED;
1087 : }
1088 : }
1089 :
1090 988 : static NTSTATUS schannel_client_start(struct gensec_security *gensec_security)
1091 : {
1092 988 : return NT_STATUS_OK;
1093 : }
1094 :
1095 270934 : static bool schannel_have_feature(struct gensec_security *gensec_security,
1096 : uint32_t feature)
1097 : {
1098 270934 : if (gensec_security->dcerpc_auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1099 270934 : if (feature & GENSEC_FEATURE_SIGN) {
1100 90421 : return true;
1101 : }
1102 : }
1103 180513 : if (gensec_security->dcerpc_auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
1104 167445 : if (feature & GENSEC_FEATURE_SEAL) {
1105 72027 : return true;
1106 : }
1107 : }
1108 108486 : if (feature & GENSEC_FEATURE_DCE_STYLE) {
1109 69811 : return true;
1110 : }
1111 38675 : if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1112 3103 : return true;
1113 : }
1114 35572 : return false;
1115 : }
1116 :
1117 : /*
1118 : unseal a packet
1119 : */
1120 23281 : static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security,
1121 : uint8_t *data, size_t length,
1122 : const uint8_t *whole_pdu, size_t pdu_length,
1123 : const DATA_BLOB *sig)
1124 : {
1125 22100 : struct schannel_state *state =
1126 23281 : talloc_get_type_abort(gensec_security->private_data,
1127 : struct schannel_state);
1128 :
1129 23281 : return netsec_incoming_packet(state, true,
1130 : discard_const_p(uint8_t, data),
1131 : length,
1132 : whole_pdu, pdu_length,
1133 : sig);
1134 : }
1135 :
1136 : /*
1137 : check the signature on a packet
1138 : */
1139 5688 : static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security,
1140 : const uint8_t *data, size_t length,
1141 : const uint8_t *whole_pdu, size_t pdu_length,
1142 : const DATA_BLOB *sig)
1143 : {
1144 5688 : struct schannel_state *state =
1145 5688 : talloc_get_type_abort(gensec_security->private_data,
1146 : struct schannel_state);
1147 :
1148 5688 : return netsec_incoming_packet(state, false,
1149 : discard_const_p(uint8_t, data),
1150 : length,
1151 : whole_pdu, pdu_length,
1152 : sig);
1153 : }
1154 : /*
1155 : seal a packet
1156 : */
1157 23265 : static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security,
1158 : TALLOC_CTX *mem_ctx,
1159 : uint8_t *data, size_t length,
1160 : const uint8_t *whole_pdu, size_t pdu_length,
1161 : DATA_BLOB *sig)
1162 : {
1163 22092 : struct schannel_state *state =
1164 23265 : talloc_get_type_abort(gensec_security->private_data,
1165 : struct schannel_state);
1166 :
1167 23265 : return netsec_outgoing_packet(state, mem_ctx, true,
1168 : data, length,
1169 : whole_pdu, pdu_length,
1170 : sig);
1171 : }
1172 :
1173 : /*
1174 : sign a packet
1175 : */
1176 5688 : static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security,
1177 : TALLOC_CTX *mem_ctx,
1178 : const uint8_t *data, size_t length,
1179 : const uint8_t *whole_pdu, size_t pdu_length,
1180 : DATA_BLOB *sig)
1181 : {
1182 5688 : struct schannel_state *state =
1183 5688 : talloc_get_type_abort(gensec_security->private_data,
1184 : struct schannel_state);
1185 :
1186 5688 : return netsec_outgoing_packet(state, mem_ctx, false,
1187 : discard_const_p(uint8_t, data),
1188 : length,
1189 : whole_pdu, pdu_length,
1190 : sig);
1191 : }
1192 :
1193 : static const struct gensec_security_ops gensec_schannel_security_ops = {
1194 : .name = "schannel",
1195 : .auth_type = DCERPC_AUTH_TYPE_SCHANNEL,
1196 : .client_start = schannel_client_start,
1197 : .server_start = schannel_server_start,
1198 : .update_send = schannel_update_send,
1199 : .update_recv = schannel_update_recv,
1200 : .seal_packet = schannel_seal_packet,
1201 : .sign_packet = schannel_sign_packet,
1202 : .check_packet = schannel_check_packet,
1203 : .unseal_packet = schannel_unseal_packet,
1204 : .session_info = schannel_session_info,
1205 : .sig_size = schannel_sig_size,
1206 : .have_feature = schannel_have_feature,
1207 : .enabled = true,
1208 : .priority = GENSEC_SCHANNEL
1209 : };
1210 :
1211 10467 : _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx)
1212 : {
1213 : NTSTATUS ret;
1214 10467 : ret = gensec_register(ctx, &gensec_schannel_security_ops);
1215 10467 : if (!NT_STATUS_IS_OK(ret)) {
1216 0 : DEBUG(0,("Failed to register '%s' gensec backend!\n",
1217 : gensec_schannel_security_ops.name));
1218 0 : return ret;
1219 : }
1220 :
1221 10467 : return ret;
1222 : }
|