ctdb-tests: Update statd-callout tests to handle both modes
[samba4-gss.git] / librpc / rpc / server / netlogon / schannel_util.c
blobfd2c4a1ff380bbd3f9604e25c44773c566c36256
1 /*
2 Unix SMB/CIFS implementation.
4 netlogon schannel utility functions
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "auth/auth.h"
26 #include "schannel_util.h"
27 #include "param/param.h"
28 #include "libcli/security/dom_sid.h"
29 #include "libcli/auth/schannel.h"
30 #include "librpc/rpc/dcesrv_core.h"
31 #include "librpc/gen_ndr/ndr_netlogon.h"
32 #include "lib/util/util_str_escape.h"
34 struct dcesrv_netr_check_schannel_state {
35 struct dom_sid account_sid;
36 enum dcerpc_AuthType auth_type;
37 enum dcerpc_AuthLevel auth_level;
39 bool kerberos_required;
41 bool schannel_global_required;
42 bool schannel_required;
43 bool schannel_explicitly_set;
45 bool seal_global_required;
46 bool seal_required;
47 bool seal_explicitly_set;
49 NTSTATUS result;
52 static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *dce_call,
53 const struct netlogon_creds_CredentialState *creds,
54 enum dcerpc_AuthType auth_type,
55 enum dcerpc_AuthLevel auth_level,
56 struct dcesrv_netr_check_schannel_state **_s)
58 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
59 int schannel = lpcfg_server_schannel(lp_ctx);
60 bool schannel_global_required = (schannel == true);
61 bool schannel_required = schannel_global_required;
62 const char *explicit_opt = NULL;
63 bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx);
64 bool require_seal = global_require_seal;
65 const char *explicit_seal_opt = NULL;
66 #define DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC (NETLOGON_SERVER_PIPE_STATE_MAGIC+1)
67 struct dcesrv_netr_check_schannel_state *s = NULL;
68 NTSTATUS status;
70 *_s = NULL;
72 if (creds->authenticate_kerberos) {
73 struct auth_session_info *session_info =
74 dcesrv_call_session_info(dce_call);
75 const struct dom_sid *auth_sid =
76 &session_info->security_token->sids[0];
78 if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
79 return NT_STATUS_ACCESS_DENIED;
82 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
83 return NT_STATUS_ACCESS_DENIED;
86 if (!dom_sid_equal(auth_sid, &creds->client_sid)) {
87 return NT_STATUS_ACCESS_DENIED;
91 s = dcesrv_iface_state_find_conn(dce_call,
92 DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC,
93 struct dcesrv_netr_check_schannel_state);
94 if (s != NULL) {
95 if (!dom_sid_equal(&s->account_sid, &creds->client_sid)) {
96 goto new_state;
98 if (s->auth_type != auth_type) {
99 goto new_state;
101 if (s->auth_level != auth_level) {
102 goto new_state;
105 *_s = s;
106 return NT_STATUS_OK;
109 new_state:
110 TALLOC_FREE(s);
111 s = talloc_zero(dce_call,
112 struct dcesrv_netr_check_schannel_state);
113 if (s == NULL) {
114 return NT_STATUS_NO_MEMORY;
117 s->account_sid = creds->client_sid;
118 s->auth_type = auth_type;
119 s->auth_level = auth_level;
120 s->result = NT_STATUS_MORE_PROCESSING_REQUIRED;
123 * We don't use lpcfg_parm_bool(), as we
124 * need the explicit_opt pointer in order to
125 * adjust the debug messages.
127 explicit_seal_opt = lpcfg_get_parametric(lp_ctx,
128 NULL,
129 "server schannel require seal",
130 creds->account_name);
131 if (explicit_seal_opt != NULL) {
132 require_seal = lp_bool(explicit_seal_opt);
136 * We don't use lpcfg_parm_bool(), as we
137 * need the explicit_opt pointer in order to
138 * adjust the debug messages.
140 explicit_opt = lpcfg_get_parametric(lp_ctx,
141 NULL,
142 "server require schannel",
143 creds->account_name);
144 if (explicit_opt != NULL) {
145 schannel_required = lp_bool(explicit_opt);
148 s->schannel_global_required = schannel_global_required;
149 s->schannel_required = schannel_required;
150 s->schannel_explicitly_set = explicit_opt != NULL;
152 s->seal_global_required = global_require_seal;
153 s->seal_required = require_seal;
154 s->seal_explicitly_set = explicit_seal_opt != NULL;
156 if (creds->authenticate_kerberos) {
157 s->kerberos_required = true;
158 s->seal_required = true;
161 status = dcesrv_iface_state_store_conn(dce_call,
162 DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC,
164 if (!NT_STATUS_IS_OK(status)) {
165 return status;
168 *_s = s;
169 return NT_STATUS_OK;
172 static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_call,
173 struct dcesrv_netr_check_schannel_state *s,
174 const struct netlogon_creds_CredentialState *creds,
175 uint16_t opnum)
177 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
178 int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL,
179 "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
180 int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL,
181 "CVE_2020_1472", "error_debug_level", DBGLVL_ERR);
182 int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL,
183 "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
184 int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL,
185 "CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
186 TALLOC_CTX *frame = talloc_stackframe();
187 unsigned int dbg_lvl = DBGLVL_DEBUG;
188 const char *opname = "<unknown>";
189 const char *reason = "<unknown>";
191 if (opnum < ndr_table_netlogon.num_calls) {
192 opname = ndr_table_netlogon.calls[opnum].name;
195 if (s->auth_type == DCERPC_AUTH_TYPE_KRB5) {
196 if (s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
197 reason = "KRB5 WITH SEALED";
198 } else if (s->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
199 reason = "KRB5 ONLY WITH SIGNED";
200 dbg_lvl = DBGLVL_ERR;
201 s->result = NT_STATUS_ACCESS_DENIED;
202 } else {
203 reason = "KRB5 WITH INVALID";
204 dbg_lvl = DBGLVL_ERR;
205 s->result = NT_STATUS_ACCESS_DENIED;
207 } else if (s->kerberos_required) {
208 s->result = NT_STATUS_ACCESS_DENIED;
209 reason = "WITHOUT KRB5";
210 } else if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
211 if (s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
212 reason = "WITH SEALED";
213 } else if (s->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
214 reason = "WITH SIGNED";
215 } else {
216 reason = "WITH INVALID";
217 dbg_lvl = DBGLVL_ERR;
218 s->result = NT_STATUS_INTERNAL_ERROR;
220 } else {
221 reason = "WITHOUT";
224 if (!NT_STATUS_EQUAL(s->result, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
225 if (!NT_STATUS_IS_OK(s->result)) {
226 dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
229 DEBUG(dbg_lvl, (
230 "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
231 "%s request (opnum[%u]) %s schannel from "
232 "client_account[%s] client_computer_name[%s] %s\n",
233 opname, opnum, reason,
234 log_escape(frame, creds->account_name),
235 log_escape(frame, creds->computer_name),
236 nt_errstr(s->result)));
237 TALLOC_FREE(frame);
238 return s->result;
241 if (s->auth_type == DCERPC_AUTH_TYPE_KRB5 &&
242 s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY)
244 s->result = NT_STATUS_OK;
245 TALLOC_FREE(frame);
246 return s->result;
249 if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL &&
250 s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY)
252 s->result = NT_STATUS_OK;
254 if (s->schannel_explicitly_set && !s->schannel_required) {
255 dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level);
256 } else if (!s->schannel_required) {
257 dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
259 if (s->seal_explicitly_set && !s->seal_required) {
260 dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level);
261 } else if (!s->seal_required) {
262 dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
265 DEBUG(dbg_lvl, (
266 "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
267 "%s request (opnum[%u]) %s schannel from "
268 "client_account[%s] client_computer_name[%s] %s\n",
269 opname, opnum, reason,
270 log_escape(frame, creds->account_name),
271 log_escape(frame, creds->computer_name),
272 nt_errstr(s->result)));
274 if (s->schannel_explicitly_set && !s->schannel_required) {
275 DEBUG(CVE_2020_1472_warn_level, (
276 "CVE-2020-1472(ZeroLogon): "
277 "Option 'server require schannel:%s = no' not needed for '%s'!\n",
278 log_escape(frame, creds->account_name),
279 log_escape(frame, creds->computer_name)));
282 if (s->seal_explicitly_set && !s->seal_required) {
283 DEBUG(CVE_2022_38023_warn_level, (
284 "CVE-2022-38023: "
285 "Option 'server schannel require seal:%s = no' not needed for '%s'!\n",
286 log_escape(frame, creds->account_name),
287 log_escape(frame, creds->computer_name)));
290 TALLOC_FREE(frame);
291 return s->result;
294 if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
295 if (s->seal_required) {
296 s->result = NT_STATUS_ACCESS_DENIED;
298 if (s->seal_explicitly_set) {
299 dbg_lvl = DBGLVL_NOTICE;
300 } else {
301 dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
303 if (s->schannel_explicitly_set && !s->schannel_required) {
304 dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level);
307 DEBUG(dbg_lvl, (
308 "CVE-2022-38023: "
309 "%s request (opnum[%u]) %s schannel from "
310 "from client_account[%s] client_computer_name[%s] %s\n",
311 opname, opnum, reason,
312 log_escape(frame, creds->account_name),
313 log_escape(frame, creds->computer_name),
314 nt_errstr(s->result)));
315 if (s->seal_explicitly_set) {
316 D_NOTICE("CVE-2022-38023: Option "
317 "'server schannel require seal:%s = yes' "
318 "rejects access for client.\n",
319 log_escape(frame, creds->account_name));
320 } else {
321 DEBUG(CVE_2020_1472_error_level, (
322 "CVE-2022-38023: Check if option "
323 "'server schannel require seal:%s = no' "
324 "might be needed for a legacy client.\n",
325 log_escape(frame, creds->account_name)));
327 if (s->schannel_explicitly_set && !s->schannel_required) {
328 DEBUG(CVE_2020_1472_warn_level, (
329 "CVE-2020-1472(ZeroLogon): Option "
330 "'server require schannel:%s = no' "
331 "not needed for '%s'!\n",
332 log_escape(frame, creds->account_name),
333 log_escape(frame, creds->computer_name)));
335 TALLOC_FREE(frame);
336 return s->result;
339 s->result = NT_STATUS_OK;
341 if (s->schannel_explicitly_set && !s->schannel_required) {
342 dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level);
343 } else if (!s->schannel_required) {
344 dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
346 if (s->seal_explicitly_set && !s->seal_required) {
347 dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
348 } else if (!s->seal_required) {
349 dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
352 DEBUG(dbg_lvl, (
353 "CVE-2020-1472(ZeroLogon): "
354 "%s request (opnum[%u]) %s schannel from "
355 "client_account[%s] client_computer_name[%s] %s\n",
356 opname, opnum, reason,
357 log_escape(frame, creds->account_name),
358 log_escape(frame, creds->computer_name),
359 nt_errstr(s->result)));
360 if (s->schannel_explicitly_set && !s->schannel_required) {
361 DEBUG(CVE_2020_1472_warn_level, (
362 "CVE-2020-1472(ZeroLogon): "
363 "Option 'server require schannel:%s = no' not needed for '%s'!\n",
364 log_escape(frame, creds->account_name),
365 log_escape(frame, creds->computer_name)));
367 if (s->seal_explicitly_set && !s->seal_required) {
368 D_INFO("CVE-2022-38023: "
369 "Option 'server schannel require seal:%s = no' still needed for '%s'!\n",
370 log_escape(frame, creds->account_name),
371 log_escape(frame, creds->computer_name));
372 } else if (!s->seal_required) {
374 * admins should set
375 * server schannel require seal:COMPUTER$ = no
376 * in order to avoid the level 0 messages.
377 * Over time they can switch the global value
378 * to be strict.
380 DEBUG(CVE_2022_38023_error_level, (
381 "CVE-2022-38023: "
382 "Please use 'server schannel require seal:%s = no' "
383 "for '%s' to avoid this warning!\n",
384 log_escape(frame, creds->account_name),
385 log_escape(frame, creds->computer_name)));
388 TALLOC_FREE(frame);
389 return s->result;
392 if (s->seal_required) {
393 s->result = NT_STATUS_ACCESS_DENIED;
395 if (s->seal_explicitly_set) {
396 dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
397 } else {
398 dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
400 if (!s->schannel_explicitly_set) {
401 dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
402 } else if (s->schannel_required) {
403 dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
406 DEBUG(dbg_lvl, (
407 "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
408 "%s request (opnum[%u]) %s schannel from "
409 "from client_account[%s] client_computer_name[%s] %s\n",
410 opname, opnum, reason,
411 log_escape(frame, creds->account_name),
412 log_escape(frame, creds->computer_name),
413 nt_errstr(s->result)));
414 if (s->seal_explicitly_set) {
415 D_NOTICE("CVE-2022-38023: Option "
416 "'server schannel require seal:%s = yes' "
417 "rejects access for client.\n",
418 log_escape(frame, creds->account_name));
419 } else {
420 DEBUG(CVE_2022_38023_error_level, (
421 "CVE-2022-38023: Check if option "
422 "'server schannel require seal:%s = no' "
423 "might be needed for a legacy client.\n",
424 log_escape(frame, creds->account_name)));
426 if (!s->schannel_explicitly_set) {
427 DEBUG(CVE_2020_1472_error_level, (
428 "CVE-2020-1472(ZeroLogon): Check if option "
429 "'server require schannel:%s = no' "
430 "might be needed for a legacy client.\n",
431 log_escape(frame, creds->account_name)));
432 } else if (s->schannel_required) {
433 D_NOTICE("CVE-2022-38023: Option "
434 "'server require schannel:%s = yes' "
435 "also rejects access for client.\n",
436 log_escape(frame, creds->account_name));
438 TALLOC_FREE(frame);
439 return s->result;
442 if (s->schannel_required) {
443 s->result = NT_STATUS_ACCESS_DENIED;
445 if (s->schannel_explicitly_set) {
446 dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
447 } else {
448 dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
450 if (!s->seal_explicitly_set) {
451 dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
454 DEBUG(dbg_lvl, (
455 "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
456 "%s request (opnum[%u]) %s schannel from "
457 "client_account[%s] client_computer_name[%s] %s\n",
458 opname, opnum, reason,
459 log_escape(frame, creds->account_name),
460 log_escape(frame, creds->computer_name),
461 nt_errstr(s->result)));
462 if (s->schannel_explicitly_set) {
463 D_NOTICE("CVE-2020-1472(ZeroLogon): Option "
464 "'server require schannel:%s = yes' "
465 "rejects access for client.\n",
466 log_escape(frame, creds->account_name));
467 } else {
468 DEBUG(CVE_2020_1472_error_level, (
469 "CVE-2020-1472(ZeroLogon): Check if option "
470 "'server require schannel:%s = no' "
471 "might be needed for a legacy client.\n",
472 log_escape(frame, creds->account_name)));
474 if (!s->seal_explicitly_set) {
475 DEBUG(CVE_2022_38023_error_level, (
476 "CVE-2022-38023: Check if option "
477 "'server schannel require seal:%s = no' "
478 "might be needed for a legacy client.\n",
479 log_escape(frame, creds->account_name)));
481 TALLOC_FREE(frame);
482 return s->result;
485 s->result = NT_STATUS_OK;
487 if (s->seal_explicitly_set) {
488 dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
489 } else {
490 dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
493 if (s->schannel_explicitly_set) {
494 dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
495 } else {
496 dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
499 DEBUG(dbg_lvl, (
500 "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
501 "%s request (opnum[%u]) %s schannel from "
502 "client_account[%s] client_computer_name[%s] %s\n",
503 opname, opnum, reason,
504 log_escape(frame, creds->account_name),
505 log_escape(frame, creds->computer_name),
506 nt_errstr(s->result)));
508 if (s->seal_explicitly_set) {
509 D_INFO("CVE-2022-38023: Option "
510 "'server schannel require seal:%s = no' "
511 "still needed for '%s'!\n",
512 log_escape(frame, creds->account_name),
513 log_escape(frame, creds->computer_name));
514 } else {
516 * admins should set
517 * server schannel require seal:COMPUTER$ = no
518 * in order to avoid the level 0 messages.
519 * Over time they can switch the global value
520 * to be strict.
522 DEBUG(CVE_2022_38023_error_level, (
523 "CVE-2022-38023: Please use "
524 "'server schannel require seal:%s = no' "
525 "for '%s' to avoid this warning!\n",
526 log_escape(frame, creds->account_name),
527 log_escape(frame, creds->computer_name)));
530 if (s->schannel_explicitly_set) {
531 D_INFO("CVE-2020-1472(ZeroLogon): Option "
532 "'server require schannel:%s = no' "
533 "still needed for '%s'!\n",
534 log_escape(frame, creds->account_name),
535 log_escape(frame, creds->computer_name));
536 } else {
538 * admins should set
539 * server require schannel:COMPUTER$ = no
540 * in order to avoid the level 0 messages.
541 * Over time they can switch the global value
542 * to be strict.
544 DEBUG(CVE_2020_1472_error_level, (
545 "CVE-2020-1472(ZeroLogon): "
546 "Please use 'server require schannel:%s = no' "
547 "for '%s' to avoid this warning!\n",
548 log_escape(frame, creds->account_name),
549 log_escape(frame, creds->computer_name)));
552 TALLOC_FREE(frame);
553 return s->result;
556 NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
557 const struct netlogon_creds_CredentialState *creds,
558 enum dcerpc_AuthType auth_type,
559 enum dcerpc_AuthLevel auth_level,
560 uint16_t opnum)
562 struct dcesrv_netr_check_schannel_state *s = NULL;
563 NTSTATUS status;
565 status = dcesrv_netr_check_schannel_get_state(dce_call,
566 creds,
567 auth_type,
568 auth_level,
569 &s);
570 if (!NT_STATUS_IS_OK(status)) {
571 return status;
574 status = dcesrv_netr_check_schannel_once(dce_call, s, creds, opnum);
575 if (!NT_STATUS_IS_OK(status)) {
576 return status;
579 return NT_STATUS_OK;
582 struct dcesrv_netr_step_access_state {
583 struct dcesrv_call_state *dce_call;
584 enum dcerpc_AuthType auth_type;
585 enum dcerpc_AuthLevel auth_level;
586 uint16_t opnum;
587 NTSTATUS status;
590 static NTSTATUS dcesrv_netr_step_access_cb(
591 struct netlogon_creds_CredentialState *creds,
592 NTSTATUS step_status,
593 bool *store,
594 void *access_check_private)
596 struct dcesrv_netr_step_access_state *s =
597 (struct dcesrv_netr_step_access_state *)access_check_private;
598 struct dcesrv_call_state *dce_call =
599 talloc_get_type_abort(s->dce_call,
600 struct dcesrv_call_state);
602 if (NT_STATUS_EQUAL(step_status, NT_STATUS_ACCESS_DENIED)) {
603 s->status = step_status;
604 *store = true;
605 return NT_STATUS_OK;
608 if (!NT_STATUS_IS_OK(step_status)) {
609 *store = false;
610 return step_status;
613 s->status = dcesrv_netr_check_schannel(dce_call,
614 creds,
615 s->auth_type,
616 s->auth_level,
617 s->opnum);
619 if (!NT_STATUS_IS_OK(s->status)) {
620 *store = false;
621 } else {
622 *store = true;
625 return NT_STATUS_OK;
628 NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
629 TALLOC_CTX *mem_ctx,
630 const char *computer_name,
631 struct netr_Authenticator *received_authenticator,
632 struct netr_Authenticator *return_authenticator,
633 struct netlogon_creds_CredentialState **creds_out)
635 NTSTATUS nt_status;
636 struct netlogon_creds_CredentialState *creds = NULL;
637 struct dcesrv_netr_step_access_state state = {
638 .dce_call = dce_call,
639 .auth_type = DCERPC_AUTH_TYPE_NONE,
640 .auth_level = DCERPC_AUTH_LEVEL_NONE,
641 .opnum = dce_call->pkt.u.request.opnum,
642 .status = NT_STATUS_INTERNAL_ERROR,
645 dcesrv_call_auth_info(dce_call, &state.auth_type, &state.auth_level);
647 nt_status = schannel_check_creds_state(mem_ctx,
648 dce_call->conn->dce_ctx->lp_ctx,
649 computer_name,
650 received_authenticator,
651 return_authenticator,
652 state.auth_type,
653 state.auth_level,
654 dcesrv_netr_step_access_cb,
655 &state,
656 &creds);
657 if (!NT_STATUS_IS_OK(nt_status)) {
658 ZERO_STRUCTP(return_authenticator);
659 return nt_status;
662 nt_status = state.status;
663 if (!NT_STATUS_IS_OK(nt_status)) {
664 TALLOC_FREE(creds);
665 ZERO_STRUCTP(return_authenticator);
666 return nt_status;
669 *creds_out = creds;
670 return NT_STATUS_OK;