2 Unix SMB/CIFS implementation.
4 dcerpc schannel operations
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
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.
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.
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/>.
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"
38 #ifndef HAVE_GNUTLS_AES_CFB8
39 #include "lib/crypto/aes.h"
42 #include "lib/crypto/gnutls_helpers.h"
43 #include <gnutls/gnutls.h>
44 #include <gnutls/crypto.h>
47 #define DBGC_CLASS DBGC_AUTH
49 struct schannel_state {
50 struct gensec_security *gensec;
53 struct netlogon_creds_CredentialState *creds;
54 struct auth_user_info_dc *user_info_dc;
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; \
62 _seq_num_high |= 0x80000000; \
64 RSIVAL(_buf, 0, _seq_num_low); \
65 RSIVAL(_buf, 4, _seq_num_high); \
68 static struct schannel_state *netsec_create_state(
69 struct gensec_security *gensec,
70 struct netlogon_creds_CredentialState *creds,
73 struct schannel_state *state;
75 state = talloc_zero(gensec, struct schannel_state);
80 state->gensec = gensec;
81 state->initiator = initiator;
82 state->creds = netlogon_creds_copy(state, creds);
83 if (state->creds == NULL) {
88 gensec->private_data = state;
93 static void netsec_offset_and_sizes(struct schannel_state *state,
95 uint32_t *_min_sig_size,
96 uint32_t *_used_sig_size,
97 uint32_t *_checksum_length,
98 uint32_t *_confounder_ofs)
100 uint32_t min_sig_size;
101 uint32_t used_sig_size;
102 uint32_t checksum_length;
103 uint32_t confounder_ofs;
105 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
109 * Note: windows has a bug here and uses the old values...
111 * checksum_length = 32;
112 * confounder_ofs = 48;
128 *_min_sig_size = min_sig_size;
131 if (_used_sig_size) {
132 *_used_sig_size = used_sig_size;
135 if (_checksum_length) {
136 *_checksum_length = checksum_length;
139 if (_confounder_ofs) {
140 *_confounder_ofs = confounder_ofs;
144 /*******************************************************************
145 Encode or Decode the sequence number (which is symmetric)
146 ********************************************************************/
147 static NTSTATUS netsec_do_seq_num(struct schannel_state *state,
148 const uint8_t *checksum,
149 uint32_t checksum_length,
152 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
153 #ifdef HAVE_GNUTLS_AES_CFB8
154 gnutls_cipher_hd_t cipher_hnd = NULL;
155 gnutls_datum_t key = {
156 .data = state->creds->session_key,
157 .size = sizeof(state->creds->session_key),
160 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
161 uint8_t _iv[iv_size];
162 gnutls_datum_t iv = {
170 memcpy(iv.data + 0, checksum, 8);
171 memcpy(iv.data + 8, checksum, 8);
173 rc = gnutls_cipher_init(&cipher_hnd,
174 GNUTLS_CIPHER_AES_128_CFB8,
178 return gnutls_error_to_ntstatus(rc,
179 NT_STATUS_CRYPTO_SYSTEM_INVALID);
182 rc = gnutls_cipher_encrypt(cipher_hnd, seq_num, 8);
183 gnutls_cipher_deinit(cipher_hnd);
185 return gnutls_error_to_ntstatus(rc,
186 NT_STATUS_CRYPTO_SYSTEM_INVALID);
189 #else /* NOT HAVE_GNUTLS_AES_CFB8 */
191 uint8_t iv[AES_BLOCK_SIZE];
193 AES_set_encrypt_key(state->creds->session_key, 128, &key);
195 memcpy(iv+0, checksum, 8);
196 memcpy(iv+8, checksum, 8);
198 aes_cfb8_encrypt(seq_num, seq_num, 8, &key, iv, AES_ENCRYPT);
199 #endif /* HAVE_GNUTLS_AES_CFB8 */
201 static const uint8_t zeros[4];
202 uint8_t _sequence_key[16];
203 gnutls_cipher_hd_t cipher_hnd;
204 gnutls_datum_t sequence_key = {
205 .data = _sequence_key,
206 .size = sizeof(_sequence_key),
211 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
212 state->creds->session_key,
213 sizeof(state->creds->session_key),
218 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
221 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
228 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
233 rc = gnutls_cipher_init(&cipher_hnd,
234 GNUTLS_CIPHER_ARCFOUR_128,
238 ZERO_ARRAY(_sequence_key);
239 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
242 rc = gnutls_cipher_encrypt(cipher_hnd,
245 gnutls_cipher_deinit(cipher_hnd);
246 ZERO_ARRAY(_sequence_key);
248 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
257 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,
263 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
264 #ifdef HAVE_GNUTLS_AES_CFB8
265 gnutls_cipher_hd_t cipher_hnd = NULL;
266 uint8_t sess_kf0[16] = {0};
267 gnutls_datum_t key = {
269 .size = sizeof(sess_kf0),
272 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
273 uint8_t _iv[iv_size];
274 gnutls_datum_t iv = {
281 for (i = 0; i < key.size; i++) {
282 key.data[i] = state->creds->session_key[i] ^ 0xf0;
287 memcpy(iv.data + 0, seq_num, 8);
288 memcpy(iv.data + 8, seq_num, 8);
290 rc = gnutls_cipher_init(&cipher_hnd,
291 GNUTLS_CIPHER_AES_128_CFB8,
295 DBG_ERR("ERROR: gnutls_cipher_init: %s\n",
296 gnutls_strerror(rc));
297 return NT_STATUS_NO_MEMORY;
301 rc = gnutls_cipher_encrypt(cipher_hnd,
305 DBG_ERR("ERROR: gnutls_cipher_encrypt: %s\n",
306 gnutls_strerror(errno));
307 gnutls_cipher_deinit(cipher_hnd);
308 return NT_STATUS_INTERNAL_ERROR;
312 * Looks like we have to reuse the initial IV which is
313 * cryptographically wrong!
315 gnutls_cipher_set_iv(cipher_hnd, iv.data, iv.size);
316 rc = gnutls_cipher_encrypt(cipher_hnd,
320 DBG_ERR("ERROR: gnutls_cipher_encrypt: %s\n",
321 gnutls_strerror(errno));
322 gnutls_cipher_deinit(cipher_hnd);
323 return NT_STATUS_INTERNAL_ERROR;
326 rc = gnutls_cipher_decrypt(cipher_hnd,
330 DBG_ERR("ERROR: gnutls_cipher_decrypt: %s\n",
331 gnutls_strerror(errno));
332 gnutls_cipher_deinit(cipher_hnd);
333 return NT_STATUS_INTERNAL_ERROR;
337 * Looks like we have to reuse the initial IV which is
338 * cryptographically wrong!
340 gnutls_cipher_set_iv(cipher_hnd, iv.data, iv.size);
341 rc = gnutls_cipher_decrypt(cipher_hnd,
345 DBG_ERR("ERROR: gnutls_cipher_decrypt: %s\n",
346 gnutls_strerror(errno));
347 gnutls_cipher_deinit(cipher_hnd);
348 return NT_STATUS_INTERNAL_ERROR;
351 gnutls_cipher_deinit(cipher_hnd);
352 #else /* NOT HAVE_GNUTLS_AES_CFB8 */
354 uint8_t iv[AES_BLOCK_SIZE];
355 uint8_t sess_kf0[16];
358 for (i = 0; i < 16; i++) {
359 sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
362 AES_set_encrypt_key(sess_kf0, 128, &key);
364 memcpy(iv+0, seq_num, 8);
365 memcpy(iv+8, seq_num, 8);
368 aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT);
369 aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT);
371 aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT);
372 aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT);
374 #endif /* HAVE_GNUTLS_AES_CFB8 */
376 gnutls_cipher_hd_t cipher_hnd;
377 uint8_t _sealing_key[16];
378 gnutls_datum_t sealing_key = {
379 .data = _sealing_key,
380 .size = sizeof(_sealing_key),
382 static const uint8_t zeros[4];
384 uint8_t sess_kf0[16];
388 for (i = 0; i < 16; i++) {
389 sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
392 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
400 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
403 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
412 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
415 rc = gnutls_cipher_init(&cipher_hnd,
416 GNUTLS_CIPHER_ARCFOUR_128,
420 ZERO_ARRAY(_sealing_key);
421 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
423 rc = gnutls_cipher_encrypt(cipher_hnd,
427 ZERO_ARRAY(_sealing_key);
428 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
430 rc = gnutls_cipher_encrypt(cipher_hnd,
433 gnutls_cipher_deinit(cipher_hnd);
434 ZERO_ARRAY(_sealing_key);
436 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
443 /*******************************************************************
444 Create a digest over the entire packet (including the data), and
445 MD5 it with the session key.
446 ********************************************************************/
447 static NTSTATUS netsec_do_sign(struct schannel_state *state,
448 const uint8_t *confounder,
449 const uint8_t *data, size_t length,
453 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
454 gnutls_hmac_hd_t hmac_hnd = NULL;
457 rc = gnutls_hmac_init(&hmac_hnd,
459 state->creds->session_key,
460 sizeof(state->creds->session_key));
462 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
466 SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
467 SSVAL(header, 2, NL_SEAL_AES128);
468 SSVAL(header, 4, 0xFFFF);
469 SSVAL(header, 6, 0x0000);
471 rc = gnutls_hmac(hmac_hnd, header, 8);
473 gnutls_hmac_deinit(hmac_hnd, NULL);
474 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
476 rc = gnutls_hmac(hmac_hnd, confounder, 8);
478 gnutls_hmac_deinit(hmac_hnd, NULL);
479 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
482 SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
483 SSVAL(header, 2, NL_SEAL_NONE);
484 SSVAL(header, 4, 0xFFFF);
485 SSVAL(header, 6, 0x0000);
487 rc = gnutls_hmac(hmac_hnd, header, 8);
489 gnutls_hmac_deinit(hmac_hnd, NULL);
490 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
494 rc = gnutls_hmac(hmac_hnd, data, length);
496 gnutls_hmac_deinit(hmac_hnd, NULL);
497 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
500 gnutls_hmac_deinit(hmac_hnd, checksum);
502 uint8_t packet_digest[16];
503 static const uint8_t zeros[4];
504 gnutls_hash_hd_t hash_hnd = NULL;
507 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
509 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
512 rc = gnutls_hash(hash_hnd, zeros, sizeof(zeros));
514 gnutls_hash_deinit(hash_hnd, NULL);
515 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
518 SSVAL(header, 0, NL_SIGN_HMAC_MD5);
519 SSVAL(header, 2, NL_SEAL_RC4);
520 SSVAL(header, 4, 0xFFFF);
521 SSVAL(header, 6, 0x0000);
523 rc = gnutls_hash(hash_hnd, header, 8);
525 gnutls_hash_deinit(hash_hnd, NULL);
526 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
528 rc = gnutls_hash(hash_hnd, confounder, 8);
530 gnutls_hash_deinit(hash_hnd, NULL);
531 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
534 SSVAL(header, 0, NL_SIGN_HMAC_MD5);
535 SSVAL(header, 2, NL_SEAL_NONE);
536 SSVAL(header, 4, 0xFFFF);
537 SSVAL(header, 6, 0x0000);
539 rc = gnutls_hash(hash_hnd, header, 8);
541 gnutls_hash_deinit(hash_hnd, NULL);
542 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
545 rc = gnutls_hash(hash_hnd, data, length);
547 gnutls_hash_deinit(hash_hnd, NULL);
548 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
550 gnutls_hash_deinit(hash_hnd, packet_digest);
552 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
553 state->creds->session_key,
554 sizeof(state->creds->session_key),
556 sizeof(packet_digest),
558 ZERO_ARRAY(packet_digest);
560 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
567 static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
569 uint8_t *data, size_t length,
570 const uint8_t *whole_pdu, size_t pdu_length,
571 const DATA_BLOB *sig)
573 uint32_t min_sig_size = 0;
575 uint8_t checksum[32];
576 uint32_t checksum_length = sizeof(checksum_length);
577 uint8_t _confounder[8];
578 uint8_t *confounder = NULL;
579 uint32_t confounder_ofs = 0;
582 const uint8_t *sign_data = NULL;
583 size_t sign_length = 0;
586 netsec_offset_and_sizes(state,
593 if (sig->length < min_sig_size) {
594 return NT_STATUS_ACCESS_DENIED;
598 confounder = _confounder;
599 memcpy(confounder, sig->data+confounder_ofs, 8);
604 SETUP_SEQNUM(state, seq_num, !state->initiator);
607 status = netsec_do_seal(state,
613 if (!NT_STATUS_IS_OK(status)) {
614 DBG_WARNING("netsec_do_seal failed: %s\n", nt_errstr(status));
615 return NT_STATUS_ACCESS_DENIED;
619 if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
620 sign_data = whole_pdu;
621 sign_length = pdu_length;
624 sign_length = length;
627 status = netsec_do_sign(state,
633 if (!NT_STATUS_IS_OK(status)) {
634 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
635 return NT_STATUS_ACCESS_DENIED;
638 ret = memcmp(checksum, sig->data+16, checksum_length);
640 dump_data_pw("calc digest:", checksum, checksum_length);
641 dump_data_pw("wire digest:", sig->data+16, checksum_length);
642 return NT_STATUS_ACCESS_DENIED;
645 status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
646 if (!NT_STATUS_IS_OK(status)) {
647 DBG_WARNING("netsec_do_seq_num failed: %s\n",
652 ZERO_ARRAY(checksum);
654 ret = memcmp(seq_num, sig->data+8, 8);
656 dump_data_pw("calc seq num:", seq_num, 8);
657 dump_data_pw("wire seq num:", sig->data+8, 8);
658 return NT_STATUS_ACCESS_DENIED;
664 static uint32_t netsec_outgoing_sig_size(struct schannel_state *state)
666 uint32_t sig_size = 0;
668 netsec_offset_and_sizes(state,
678 static NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
681 uint8_t *data, size_t length,
682 const uint8_t *whole_pdu, size_t pdu_length,
685 uint32_t min_sig_size = 0;
686 uint32_t used_sig_size = 0;
688 uint8_t checksum[32];
689 uint32_t checksum_length = sizeof(checksum_length);
690 uint8_t _confounder[8];
691 uint8_t *confounder = NULL;
692 uint32_t confounder_ofs = 0;
694 const uint8_t *sign_data = NULL;
695 size_t sign_length = 0;
698 netsec_offset_and_sizes(state,
705 SETUP_SEQNUM(state, seq_num, state->initiator);
708 confounder = _confounder;
709 generate_random_buffer(confounder, 8);
714 if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
715 sign_data = whole_pdu;
716 sign_length = pdu_length;
719 sign_length = length;
722 status = netsec_do_sign(state,
728 if (!NT_STATUS_IS_OK(status)) {
729 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
730 return NT_STATUS_ACCESS_DENIED;
734 status = netsec_do_seal(state,
740 if (!NT_STATUS_IS_OK(status)) {
741 DBG_WARNING("netsec_do_seal failed: %s\n",
747 status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
748 if (!NT_STATUS_IS_OK(status)) {
749 DBG_WARNING("netsec_do_seq_num failed: %s\n",
754 (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
756 memcpy(sig->data, header, 8);
757 memcpy(sig->data+8, seq_num, 8);
758 memcpy(sig->data+16, checksum, checksum_length);
761 memcpy(sig->data+confounder_ofs, confounder, 8);
764 dump_data_pw("signature:", sig->data+ 0, 8);
765 dump_data_pw("seq_num :", sig->data+ 8, 8);
766 dump_data_pw("digest :", sig->data+16, checksum_length);
767 dump_data_pw("confound :", sig->data+confounder_ofs, 8);
772 _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx);
774 static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size)
776 struct schannel_state *state =
777 talloc_get_type_abort(gensec_security->private_data,
778 struct schannel_state);
780 return netsec_outgoing_sig_size(state);
783 struct schannel_update_state {
788 static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
789 TALLOC_CTX *out_mem_ctx,
790 const DATA_BLOB in, DATA_BLOB *out);
792 static struct tevent_req *schannel_update_send(TALLOC_CTX *mem_ctx,
793 struct tevent_context *ev,
794 struct gensec_security *gensec_security,
797 struct tevent_req *req;
798 struct schannel_update_state *state = NULL;
801 req = tevent_req_create(mem_ctx, &state,
802 struct schannel_update_state);
807 status = schannel_update_internal(gensec_security,
810 state->status = status;
811 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
812 status = NT_STATUS_OK;
814 if (tevent_req_nterror(req, status)) {
815 return tevent_req_post(req, ev);
818 tevent_req_done(req);
819 return tevent_req_post(req, ev);
822 static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
823 TALLOC_CTX *out_mem_ctx,
824 const DATA_BLOB in, DATA_BLOB *out)
826 struct schannel_state *state =
827 talloc_get_type(gensec_security->private_data,
828 struct schannel_state);
830 enum ndr_err_code ndr_err;
831 struct NL_AUTH_MESSAGE bind_schannel = {
834 struct NL_AUTH_MESSAGE bind_schannel_ack;
835 struct netlogon_creds_CredentialState *creds;
836 const char *workstation;
839 *out = data_blob(NULL, 0);
841 if (gensec_security->dcerpc_auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
842 switch (gensec_security->gensec_role) {
844 return NT_STATUS_INVALID_PARAMETER_MIX;
846 return NT_STATUS_INVALID_PARAMETER;
848 return NT_STATUS_INTERNAL_ERROR;
851 switch (gensec_security->gensec_role) {
854 /* we could parse the bind ack, but we don't know what it is yet */
858 creds = cli_credentials_get_netlogon_creds(gensec_security->credentials);
860 return NT_STATUS_INVALID_PARAMETER_MIX;
863 state = netsec_create_state(gensec_security,
864 creds, true /* initiator */);
866 return NT_STATUS_NO_MEMORY;
869 bind_schannel.MessageType = NL_NEGOTIATE_REQUEST;
871 bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
872 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
873 bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials);
874 bind_schannel.oem_netbios_computer.a = creds->computer_name;
876 if (creds->secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
877 bind_schannel.Flags |= NL_FLAG_UTF8_DNS_DOMAIN_NAME;
878 bind_schannel.utf8_dns_domain.u = cli_credentials_get_realm(gensec_security->credentials);
880 bind_schannel.Flags |= NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME;
881 bind_schannel.utf8_netbios_computer.u = creds->computer_name;
884 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel,
885 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
886 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
887 status = ndr_map_error2ntstatus(ndr_err);
888 DEBUG(3, ("Could not create schannel bind: %s\n",
893 return NT_STATUS_MORE_PROCESSING_REQUIRED;
897 /* no third leg on this protocol */
898 return NT_STATUS_INVALID_PARAMETER;
901 /* parse the schannel startup blob */
902 ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel,
903 (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE);
904 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
905 status = ndr_map_error2ntstatus(ndr_err);
906 DEBUG(3, ("Could not parse incoming schannel bind: %s\n",
911 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) {
912 domain = bind_schannel.oem_netbios_domain.a;
913 if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) {
914 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
915 domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)));
916 return NT_STATUS_LOGON_FAILURE;
918 } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) {
919 domain = bind_schannel.utf8_dns_domain.u;
920 if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) {
921 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
922 domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)));
923 return NT_STATUS_LOGON_FAILURE;
926 DEBUG(3, ("Request for schannel to without domain\n"));
927 return NT_STATUS_LOGON_FAILURE;
930 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) {
931 workstation = bind_schannel.oem_netbios_computer.a;
932 } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) {
933 workstation = bind_schannel.utf8_netbios_computer.u;
935 DEBUG(3, ("Request for schannel to without netbios workstation\n"));
936 return NT_STATUS_LOGON_FAILURE;
939 status = schannel_get_creds_state(out_mem_ctx,
940 gensec_security->settings->lp_ctx,
941 workstation, &creds);
942 if (!NT_STATUS_IS_OK(status)) {
943 DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n",
944 workstation, nt_errstr(status)));
945 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
946 return NT_STATUS_LOGON_FAILURE;
951 state = netsec_create_state(gensec_security,
952 creds, false /* not initiator */);
954 return NT_STATUS_NO_MEMORY;
957 status = auth_anonymous_user_info_dc(state,
958 lpcfg_netbios_name(gensec_security->settings->lp_ctx),
959 &state->user_info_dc);
960 if (!NT_STATUS_IS_OK(status)) {
964 bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE;
965 bind_schannel_ack.Flags = 0;
966 bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think
971 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack,
972 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
973 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
974 status = ndr_map_error2ntstatus(ndr_err);
975 DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n",
976 workstation, nt_errstr(status)));
982 return NT_STATUS_INVALID_PARAMETER;
985 static NTSTATUS schannel_update_recv(struct tevent_req *req,
986 TALLOC_CTX *out_mem_ctx,
989 struct schannel_update_state *state =
991 struct schannel_update_state);
994 *out = data_blob_null;
996 if (tevent_req_is_nterror(req, &status)) {
997 tevent_req_received(req);
1001 status = state->status;
1002 talloc_steal(out_mem_ctx, state->out.data);
1004 tevent_req_received(req);
1009 * Returns anonymous credentials for schannel, matching Win2k3.
1013 static NTSTATUS schannel_session_info(struct gensec_security *gensec_security,
1014 TALLOC_CTX *mem_ctx,
1015 struct auth_session_info **_session_info)
1017 struct schannel_state *state =
1018 talloc_get_type(gensec_security->private_data,
1019 struct schannel_state);
1020 struct auth4_context *auth_ctx = gensec_security->auth_context;
1021 struct auth_session_info *session_info = NULL;
1022 uint32_t session_info_flags = 0;
1025 if (auth_ctx == NULL) {
1026 DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
1027 return NT_STATUS_INTERNAL_ERROR;
1030 if (auth_ctx->generate_session_info == NULL) {
1031 DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
1032 return NT_STATUS_INTERNAL_ERROR;
1035 if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
1036 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
1039 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
1041 status = auth_ctx->generate_session_info(
1044 state->user_info_dc,
1045 state->user_info_dc->info->account_name,
1048 if (!NT_STATUS_IS_OK(status)) {
1052 *_session_info = session_info;
1053 return NT_STATUS_OK;
1057 * Reduce the attack surface by ensuring schannel is not availble when
1060 static NTSTATUS schannel_server_start(struct gensec_security *gensec_security)
1062 enum server_role server_role
1063 = lpcfg_server_role(gensec_security->settings->lp_ctx);
1065 switch (server_role) {
1066 case ROLE_DOMAIN_BDC:
1067 case ROLE_DOMAIN_PDC:
1068 case ROLE_ACTIVE_DIRECTORY_DC:
1069 return NT_STATUS_OK;
1071 return NT_STATUS_NOT_IMPLEMENTED;
1075 static NTSTATUS schannel_client_start(struct gensec_security *gensec_security)
1077 return NT_STATUS_OK;
1080 static bool schannel_have_feature(struct gensec_security *gensec_security,
1083 if (gensec_security->dcerpc_auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1084 if (feature & GENSEC_FEATURE_SIGN) {
1088 if (gensec_security->dcerpc_auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
1089 if (feature & GENSEC_FEATURE_SEAL) {
1093 if (feature & GENSEC_FEATURE_DCE_STYLE) {
1096 if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1105 static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security,
1106 uint8_t *data, size_t length,
1107 const uint8_t *whole_pdu, size_t pdu_length,
1108 const DATA_BLOB *sig)
1110 struct schannel_state *state =
1111 talloc_get_type_abort(gensec_security->private_data,
1112 struct schannel_state);
1114 return netsec_incoming_packet(state, true,
1115 discard_const_p(uint8_t, data),
1117 whole_pdu, pdu_length,
1122 check the signature on a packet
1124 static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security,
1125 const uint8_t *data, size_t length,
1126 const uint8_t *whole_pdu, size_t pdu_length,
1127 const DATA_BLOB *sig)
1129 struct schannel_state *state =
1130 talloc_get_type_abort(gensec_security->private_data,
1131 struct schannel_state);
1133 return netsec_incoming_packet(state, false,
1134 discard_const_p(uint8_t, data),
1136 whole_pdu, pdu_length,
1142 static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security,
1143 TALLOC_CTX *mem_ctx,
1144 uint8_t *data, size_t length,
1145 const uint8_t *whole_pdu, size_t pdu_length,
1148 struct schannel_state *state =
1149 talloc_get_type_abort(gensec_security->private_data,
1150 struct schannel_state);
1152 return netsec_outgoing_packet(state, mem_ctx, true,
1154 whole_pdu, pdu_length,
1161 static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security,
1162 TALLOC_CTX *mem_ctx,
1163 const uint8_t *data, size_t length,
1164 const uint8_t *whole_pdu, size_t pdu_length,
1167 struct schannel_state *state =
1168 talloc_get_type_abort(gensec_security->private_data,
1169 struct schannel_state);
1171 return netsec_outgoing_packet(state, mem_ctx, false,
1172 discard_const_p(uint8_t, data),
1174 whole_pdu, pdu_length,
1178 static const struct gensec_security_ops gensec_schannel_security_ops = {
1180 .auth_type = DCERPC_AUTH_TYPE_SCHANNEL,
1181 .client_start = schannel_client_start,
1182 .server_start = schannel_server_start,
1183 .update_send = schannel_update_send,
1184 .update_recv = schannel_update_recv,
1185 .seal_packet = schannel_seal_packet,
1186 .sign_packet = schannel_sign_packet,
1187 .check_packet = schannel_check_packet,
1188 .unseal_packet = schannel_unseal_packet,
1189 .session_info = schannel_session_info,
1190 .sig_size = schannel_sig_size,
1191 .have_feature = schannel_have_feature,
1193 .priority = GENSEC_SCHANNEL
1196 _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx)
1199 ret = gensec_register(ctx, &gensec_schannel_security_ops);
1200 if (!NT_STATUS_IS_OK(ret)) {
1201 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1202 gensec_schannel_security_ops.name));