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 "lib/crypto/crypto.h"
37 #include "libds/common/roles.h"
39 #include "lib/crypto/gnutls_helpers.h"
40 #include <gnutls/gnutls.h>
41 #include <gnutls/crypto.h>
44 #define DBGC_CLASS DBGC_AUTH
46 struct schannel_state {
47 struct gensec_security *gensec;
50 struct netlogon_creds_CredentialState *creds;
51 struct auth_user_info_dc *user_info_dc;
54 #define SETUP_SEQNUM(state, buf, initiator) do { \
55 uint8_t *_buf = buf; \
56 uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \
57 uint32_t _seq_num_high = (state)->seq_num >> 32; \
59 _seq_num_high |= 0x80000000; \
61 RSIVAL(_buf, 0, _seq_num_low); \
62 RSIVAL(_buf, 4, _seq_num_high); \
65 static struct schannel_state *netsec_create_state(
66 struct gensec_security *gensec,
67 struct netlogon_creds_CredentialState *creds,
70 struct schannel_state *state;
72 state = talloc_zero(gensec, struct schannel_state);
77 state->gensec = gensec;
78 state->initiator = initiator;
79 state->creds = netlogon_creds_copy(state, creds);
80 if (state->creds == NULL) {
85 gensec->private_data = state;
90 static void netsec_offset_and_sizes(struct schannel_state *state,
92 uint32_t *_min_sig_size,
93 uint32_t *_used_sig_size,
94 uint32_t *_checksum_length,
95 uint32_t *_confounder_ofs)
97 uint32_t min_sig_size;
98 uint32_t used_sig_size;
99 uint32_t checksum_length;
100 uint32_t confounder_ofs;
102 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
106 * Note: windows has a bug here and uses the old values...
108 * checksum_length = 32;
109 * confounder_ofs = 48;
125 *_min_sig_size = min_sig_size;
128 if (_used_sig_size) {
129 *_used_sig_size = used_sig_size;
132 if (_checksum_length) {
133 *_checksum_length = checksum_length;
136 if (_confounder_ofs) {
137 *_confounder_ofs = confounder_ofs;
141 /*******************************************************************
142 Encode or Decode the sequence number (which is symmetric)
143 ********************************************************************/
144 static NTSTATUS netsec_do_seq_num(struct schannel_state *state,
145 const uint8_t *checksum,
146 uint32_t checksum_length,
149 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
151 uint8_t iv[AES_BLOCK_SIZE];
153 AES_set_encrypt_key(state->creds->session_key, 128, &key);
155 memcpy(iv+0, checksum, 8);
156 memcpy(iv+8, checksum, 8);
158 aes_cfb8_encrypt(seq_num, seq_num, 8, &key, iv, AES_ENCRYPT);
160 static const uint8_t zeros[4];
161 uint8_t sequence_key[16];
165 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
166 state->creds->session_key,
167 sizeof(state->creds->session_key),
172 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
175 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
182 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
187 arcfour_crypt(seq_num, sequence_key, 8);
189 ZERO_ARRAY(sequence_key);
197 static void netsec_do_seal(struct schannel_state *state,
198 const uint8_t seq_num[8],
199 uint8_t confounder[8],
200 uint8_t *data, uint32_t length,
203 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
205 uint8_t iv[AES_BLOCK_SIZE];
206 uint8_t sess_kf0[16];
209 for (i = 0; i < 16; i++) {
210 sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
213 AES_set_encrypt_key(sess_kf0, 128, &key);
215 memcpy(iv+0, seq_num, 8);
216 memcpy(iv+8, seq_num, 8);
219 aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT);
220 aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT);
222 aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT);
223 aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT);
226 uint8_t sealing_key[16];
227 static const uint8_t zeros[4];
229 uint8_t sess_kf0[16];
233 for (i = 0; i < 16; i++) {
234 sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
237 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
248 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
259 arcfour_crypt(confounder, sealing_key, 8);
260 arcfour_crypt(data, sealing_key, length);
262 ZERO_ARRAY(sealing_key);
266 /*******************************************************************
267 Create a digest over the entire packet (including the data), and
268 MD5 it with the session key.
269 ********************************************************************/
270 static NTSTATUS netsec_do_sign(struct schannel_state *state,
271 const uint8_t *confounder,
272 const uint8_t *data, size_t length,
276 if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
277 gnutls_hmac_hd_t hmac_hnd = NULL;
280 rc = gnutls_hmac_init(&hmac_hnd,
282 state->creds->session_key,
283 sizeof(state->creds->session_key));
285 return NT_STATUS_NO_MEMORY;
289 SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
290 SSVAL(header, 2, NL_SEAL_AES128);
291 SSVAL(header, 4, 0xFFFF);
292 SSVAL(header, 6, 0x0000);
294 rc = gnutls_hmac(hmac_hnd, header, 8);
296 gnutls_hmac_deinit(hmac_hnd, NULL);
297 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
299 rc = gnutls_hmac(hmac_hnd, confounder, 8);
301 gnutls_hmac_deinit(hmac_hnd, NULL);
302 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
305 SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
306 SSVAL(header, 2, NL_SEAL_NONE);
307 SSVAL(header, 4, 0xFFFF);
308 SSVAL(header, 6, 0x0000);
310 rc = gnutls_hmac(hmac_hnd, header, 8);
312 gnutls_hmac_deinit(hmac_hnd, NULL);
313 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
317 rc = gnutls_hmac(hmac_hnd, data, length);
319 gnutls_hmac_deinit(hmac_hnd, NULL);
320 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
323 gnutls_hmac_deinit(hmac_hnd, checksum);
325 uint8_t packet_digest[16];
326 static const uint8_t zeros[4];
327 gnutls_hash_hd_t hash_hnd = NULL;
330 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
332 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
335 rc = gnutls_hash(hash_hnd, zeros, sizeof(zeros));
337 gnutls_hash_deinit(hash_hnd, NULL);
338 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
341 SSVAL(header, 0, NL_SIGN_HMAC_MD5);
342 SSVAL(header, 2, NL_SEAL_RC4);
343 SSVAL(header, 4, 0xFFFF);
344 SSVAL(header, 6, 0x0000);
346 rc = gnutls_hash(hash_hnd, header, 8);
348 gnutls_hash_deinit(hash_hnd, NULL);
349 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
351 rc = gnutls_hash(hash_hnd, confounder, 8);
353 gnutls_hash_deinit(hash_hnd, NULL);
354 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
357 SSVAL(header, 0, NL_SIGN_HMAC_MD5);
358 SSVAL(header, 2, NL_SEAL_NONE);
359 SSVAL(header, 4, 0xFFFF);
360 SSVAL(header, 6, 0x0000);
362 rc = gnutls_hash(hash_hnd, header, 8);
364 gnutls_hash_deinit(hash_hnd, NULL);
365 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
368 rc = gnutls_hash(hash_hnd, data, length);
370 gnutls_hash_deinit(hash_hnd, NULL);
371 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
373 gnutls_hash_deinit(hash_hnd, packet_digest);
375 rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
376 state->creds->session_key,
377 sizeof(state->creds->session_key),
379 sizeof(packet_digest),
381 ZERO_ARRAY(packet_digest);
383 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
390 static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
392 uint8_t *data, size_t length,
393 const uint8_t *whole_pdu, size_t pdu_length,
394 const DATA_BLOB *sig)
396 uint32_t min_sig_size = 0;
398 uint8_t checksum[32];
399 uint32_t checksum_length = sizeof(checksum_length);
400 uint8_t _confounder[8];
401 uint8_t *confounder = NULL;
402 uint32_t confounder_ofs = 0;
405 const uint8_t *sign_data = NULL;
406 size_t sign_length = 0;
409 netsec_offset_and_sizes(state,
416 if (sig->length < min_sig_size) {
417 return NT_STATUS_ACCESS_DENIED;
421 confounder = _confounder;
422 memcpy(confounder, sig->data+confounder_ofs, 8);
427 SETUP_SEQNUM(state, seq_num, !state->initiator);
430 netsec_do_seal(state, seq_num,
436 if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
437 sign_data = whole_pdu;
438 sign_length = pdu_length;
441 sign_length = length;
444 status = netsec_do_sign(state,
450 if (!NT_STATUS_IS_OK(status)) {
451 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
452 return NT_STATUS_ACCESS_DENIED;
455 ret = memcmp(checksum, sig->data+16, checksum_length);
457 dump_data_pw("calc digest:", checksum, checksum_length);
458 dump_data_pw("wire digest:", sig->data+16, checksum_length);
459 return NT_STATUS_ACCESS_DENIED;
462 status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
463 if (!NT_STATUS_IS_OK(status)) {
464 DBG_WARNING("netsec_do_seq_num failed: %s\n",
469 ZERO_ARRAY(checksum);
471 ret = memcmp(seq_num, sig->data+8, 8);
473 dump_data_pw("calc seq num:", seq_num, 8);
474 dump_data_pw("wire seq num:", sig->data+8, 8);
475 return NT_STATUS_ACCESS_DENIED;
481 static uint32_t netsec_outgoing_sig_size(struct schannel_state *state)
483 uint32_t sig_size = 0;
485 netsec_offset_and_sizes(state,
495 static NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
498 uint8_t *data, size_t length,
499 const uint8_t *whole_pdu, size_t pdu_length,
502 uint32_t min_sig_size = 0;
503 uint32_t used_sig_size = 0;
505 uint8_t checksum[32];
506 uint32_t checksum_length = sizeof(checksum_length);
507 uint8_t _confounder[8];
508 uint8_t *confounder = NULL;
509 uint32_t confounder_ofs = 0;
511 const uint8_t *sign_data = NULL;
512 size_t sign_length = 0;
515 netsec_offset_and_sizes(state,
522 SETUP_SEQNUM(state, seq_num, state->initiator);
525 confounder = _confounder;
526 generate_random_buffer(confounder, 8);
531 if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
532 sign_data = whole_pdu;
533 sign_length = pdu_length;
536 sign_length = length;
539 status = netsec_do_sign(state,
545 if (!NT_STATUS_IS_OK(status)) {
546 DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
547 return NT_STATUS_ACCESS_DENIED;
551 netsec_do_seal(state, seq_num,
557 status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
558 if (!NT_STATUS_IS_OK(status)) {
559 DBG_WARNING("netsec_do_seq_num failed: %s\n",
564 (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
566 memcpy(sig->data, header, 8);
567 memcpy(sig->data+8, seq_num, 8);
568 memcpy(sig->data+16, checksum, checksum_length);
571 memcpy(sig->data+confounder_ofs, confounder, 8);
574 dump_data_pw("signature:", sig->data+ 0, 8);
575 dump_data_pw("seq_num :", sig->data+ 8, 8);
576 dump_data_pw("digest :", sig->data+16, checksum_length);
577 dump_data_pw("confound :", sig->data+confounder_ofs, 8);
582 _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx);
584 static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size)
586 struct schannel_state *state =
587 talloc_get_type_abort(gensec_security->private_data,
588 struct schannel_state);
590 return netsec_outgoing_sig_size(state);
593 struct schannel_update_state {
598 static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
599 TALLOC_CTX *out_mem_ctx,
600 const DATA_BLOB in, DATA_BLOB *out);
602 static struct tevent_req *schannel_update_send(TALLOC_CTX *mem_ctx,
603 struct tevent_context *ev,
604 struct gensec_security *gensec_security,
607 struct tevent_req *req;
608 struct schannel_update_state *state = NULL;
611 req = tevent_req_create(mem_ctx, &state,
612 struct schannel_update_state);
617 status = schannel_update_internal(gensec_security,
620 state->status = status;
621 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
622 status = NT_STATUS_OK;
624 if (tevent_req_nterror(req, status)) {
625 return tevent_req_post(req, ev);
628 tevent_req_done(req);
629 return tevent_req_post(req, ev);
632 static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security,
633 TALLOC_CTX *out_mem_ctx,
634 const DATA_BLOB in, DATA_BLOB *out)
636 struct schannel_state *state =
637 talloc_get_type(gensec_security->private_data,
638 struct schannel_state);
640 enum ndr_err_code ndr_err;
641 struct NL_AUTH_MESSAGE bind_schannel = {
644 struct NL_AUTH_MESSAGE bind_schannel_ack;
645 struct netlogon_creds_CredentialState *creds;
646 const char *workstation;
649 *out = data_blob(NULL, 0);
651 if (gensec_security->dcerpc_auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
652 switch (gensec_security->gensec_role) {
654 return NT_STATUS_INVALID_PARAMETER_MIX;
656 return NT_STATUS_INVALID_PARAMETER;
658 return NT_STATUS_INTERNAL_ERROR;
661 switch (gensec_security->gensec_role) {
664 /* we could parse the bind ack, but we don't know what it is yet */
668 creds = cli_credentials_get_netlogon_creds(gensec_security->credentials);
670 return NT_STATUS_INVALID_PARAMETER_MIX;
673 state = netsec_create_state(gensec_security,
674 creds, true /* initiator */);
676 return NT_STATUS_NO_MEMORY;
679 bind_schannel.MessageType = NL_NEGOTIATE_REQUEST;
681 bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
682 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
683 bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials);
684 bind_schannel.oem_netbios_computer.a = creds->computer_name;
686 if (creds->secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
687 bind_schannel.Flags |= NL_FLAG_UTF8_DNS_DOMAIN_NAME;
688 bind_schannel.utf8_dns_domain.u = cli_credentials_get_realm(gensec_security->credentials);
690 bind_schannel.Flags |= NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME;
691 bind_schannel.utf8_netbios_computer.u = creds->computer_name;
694 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel,
695 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
696 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
697 status = ndr_map_error2ntstatus(ndr_err);
698 DEBUG(3, ("Could not create schannel bind: %s\n",
703 return NT_STATUS_MORE_PROCESSING_REQUIRED;
707 /* no third leg on this protocol */
708 return NT_STATUS_INVALID_PARAMETER;
711 /* parse the schannel startup blob */
712 ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel,
713 (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE);
714 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
715 status = ndr_map_error2ntstatus(ndr_err);
716 DEBUG(3, ("Could not parse incoming schannel bind: %s\n",
721 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) {
722 domain = bind_schannel.oem_netbios_domain.a;
723 if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) {
724 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
725 domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)));
726 return NT_STATUS_LOGON_FAILURE;
728 } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) {
729 domain = bind_schannel.utf8_dns_domain.u;
730 if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) {
731 DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n",
732 domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)));
733 return NT_STATUS_LOGON_FAILURE;
736 DEBUG(3, ("Request for schannel to without domain\n"));
737 return NT_STATUS_LOGON_FAILURE;
740 if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) {
741 workstation = bind_schannel.oem_netbios_computer.a;
742 } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) {
743 workstation = bind_schannel.utf8_netbios_computer.u;
745 DEBUG(3, ("Request for schannel to without netbios workstation\n"));
746 return NT_STATUS_LOGON_FAILURE;
749 status = schannel_get_creds_state(out_mem_ctx,
750 gensec_security->settings->lp_ctx,
751 workstation, &creds);
752 if (!NT_STATUS_IS_OK(status)) {
753 DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n",
754 workstation, nt_errstr(status)));
755 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
756 return NT_STATUS_LOGON_FAILURE;
761 state = netsec_create_state(gensec_security,
762 creds, false /* not initiator */);
764 return NT_STATUS_NO_MEMORY;
767 status = auth_anonymous_user_info_dc(state,
768 lpcfg_netbios_name(gensec_security->settings->lp_ctx),
769 &state->user_info_dc);
770 if (!NT_STATUS_IS_OK(status)) {
774 bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE;
775 bind_schannel_ack.Flags = 0;
776 bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think
781 ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack,
782 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
783 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
784 status = ndr_map_error2ntstatus(ndr_err);
785 DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n",
786 workstation, nt_errstr(status)));
792 return NT_STATUS_INVALID_PARAMETER;
795 static NTSTATUS schannel_update_recv(struct tevent_req *req,
796 TALLOC_CTX *out_mem_ctx,
799 struct schannel_update_state *state =
801 struct schannel_update_state);
804 *out = data_blob_null;
806 if (tevent_req_is_nterror(req, &status)) {
807 tevent_req_received(req);
811 status = state->status;
812 talloc_steal(out_mem_ctx, state->out.data);
814 tevent_req_received(req);
819 * Returns anonymous credentials for schannel, matching Win2k3.
823 static NTSTATUS schannel_session_info(struct gensec_security *gensec_security,
825 struct auth_session_info **_session_info)
827 struct schannel_state *state =
828 talloc_get_type(gensec_security->private_data,
829 struct schannel_state);
830 struct auth4_context *auth_ctx = gensec_security->auth_context;
831 struct auth_session_info *session_info = NULL;
832 uint32_t session_info_flags = 0;
835 if (auth_ctx == NULL) {
836 DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
837 return NT_STATUS_INTERNAL_ERROR;
840 if (auth_ctx->generate_session_info == NULL) {
841 DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
842 return NT_STATUS_INTERNAL_ERROR;
845 if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
846 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
849 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
851 status = auth_ctx->generate_session_info(
855 state->user_info_dc->info->account_name,
858 if (!NT_STATUS_IS_OK(status)) {
862 *_session_info = session_info;
867 * Reduce the attack surface by ensuring schannel is not availble when
870 static NTSTATUS schannel_server_start(struct gensec_security *gensec_security)
872 enum server_role server_role
873 = lpcfg_server_role(gensec_security->settings->lp_ctx);
875 switch (server_role) {
876 case ROLE_DOMAIN_BDC:
877 case ROLE_DOMAIN_PDC:
878 case ROLE_ACTIVE_DIRECTORY_DC:
881 return NT_STATUS_NOT_IMPLEMENTED;
885 static NTSTATUS schannel_client_start(struct gensec_security *gensec_security)
890 static bool schannel_have_feature(struct gensec_security *gensec_security,
893 if (gensec_security->dcerpc_auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
894 if (feature & GENSEC_FEATURE_SIGN) {
898 if (gensec_security->dcerpc_auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
899 if (feature & GENSEC_FEATURE_SEAL) {
903 if (feature & GENSEC_FEATURE_DCE_STYLE) {
906 if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
915 static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security,
916 uint8_t *data, size_t length,
917 const uint8_t *whole_pdu, size_t pdu_length,
918 const DATA_BLOB *sig)
920 struct schannel_state *state =
921 talloc_get_type_abort(gensec_security->private_data,
922 struct schannel_state);
924 return netsec_incoming_packet(state, true,
925 discard_const_p(uint8_t, data),
927 whole_pdu, pdu_length,
932 check the signature on a packet
934 static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security,
935 const uint8_t *data, size_t length,
936 const uint8_t *whole_pdu, size_t pdu_length,
937 const DATA_BLOB *sig)
939 struct schannel_state *state =
940 talloc_get_type_abort(gensec_security->private_data,
941 struct schannel_state);
943 return netsec_incoming_packet(state, false,
944 discard_const_p(uint8_t, data),
946 whole_pdu, pdu_length,
952 static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security,
954 uint8_t *data, size_t length,
955 const uint8_t *whole_pdu, size_t pdu_length,
958 struct schannel_state *state =
959 talloc_get_type_abort(gensec_security->private_data,
960 struct schannel_state);
962 return netsec_outgoing_packet(state, mem_ctx, true,
964 whole_pdu, pdu_length,
971 static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security,
973 const uint8_t *data, size_t length,
974 const uint8_t *whole_pdu, size_t pdu_length,
977 struct schannel_state *state =
978 talloc_get_type_abort(gensec_security->private_data,
979 struct schannel_state);
981 return netsec_outgoing_packet(state, mem_ctx, false,
982 discard_const_p(uint8_t, data),
984 whole_pdu, pdu_length,
988 static const struct gensec_security_ops gensec_schannel_security_ops = {
990 .auth_type = DCERPC_AUTH_TYPE_SCHANNEL,
991 .client_start = schannel_client_start,
992 .server_start = schannel_server_start,
993 .update_send = schannel_update_send,
994 .update_recv = schannel_update_recv,
995 .seal_packet = schannel_seal_packet,
996 .sign_packet = schannel_sign_packet,
997 .check_packet = schannel_check_packet,
998 .unseal_packet = schannel_unseal_packet,
999 .session_info = schannel_session_info,
1000 .sig_size = schannel_sig_size,
1001 .have_feature = schannel_have_feature,
1003 .priority = GENSEC_SCHANNEL
1006 _PUBLIC_ NTSTATUS gensec_schannel_init(TALLOC_CTX *ctx)
1009 ret = gensec_register(ctx, &gensec_schannel_security_ops);
1010 if (!NT_STATUS_IS_OK(ret)) {
1011 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1012 gensec_schannel_security_ops.name));