2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
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/>.
25 #include "rpc_server/dcerpc_server.h"
26 #include "rpc_server/common/common.h"
27 #include "auth/auth.h"
28 #include "auth/auth_sam_reply.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "../lib/util/util_ldb.h"
31 #include "../libcli/auth/schannel.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "lib/messaging/irpc.h"
35 #include "librpc/gen_ndr/ndr_irpc_c.h"
36 #include "../libcli/ldap/ldap_ndr.h"
37 #include "dsdb/samdb/ldb_modules/util.h"
38 #include "lib/tsocket/tsocket.h"
39 #include "librpc/gen_ndr/ndr_netlogon.h"
40 #include "librpc/gen_ndr/ndr_lsa.h"
41 #include "librpc/gen_ndr/ndr_samr.h"
42 #include "librpc/gen_ndr/ndr_irpc.h"
43 #include "librpc/gen_ndr/ndr_winbind.h"
44 #include "librpc/gen_ndr/ndr_winbind_c.h"
45 #include "librpc/rpc/server/netlogon/schannel_util.h"
46 #include "lib/socket/netif.h"
47 #include "lib/util/util_str_escape.h"
48 #include "lib/param/loadparm.h"
50 #define DCESRV_INTERFACE_NETLOGON_BIND(context, iface) \
51 dcesrv_interface_netlogon_bind(context, iface)
56 * This #define allows the netlogon interface to accept invalid
57 * association groups, because association groups are to coordinate
58 * handles, and handles are not used in NETLOGON. This in turn avoids
59 * the need to coordinate these across multiple possible NETLOGON
62 #define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
64 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context *context,
65 const struct dcesrv_interface *iface)
67 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
68 bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
69 bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
70 int schannel = lpcfg_server_schannel(lp_ctx);
71 bool schannel_global_required = (schannel == true);
72 bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx);
73 static bool warned_global_nt4_once = false;
74 static bool warned_global_md5_once = false;
75 static bool warned_global_schannel_once = false;
76 static bool warned_global_seal_once = false;
78 if (global_allow_nt4_crypto && !warned_global_nt4_once) {
80 * We want admins to notice their misconfiguration!
82 D_ERR("CVE-2022-38023 (and others): "
83 "Please configure 'allow nt4 crypto = no' (the default), "
84 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
85 warned_global_nt4_once = true;
88 if (!global_reject_md5_client && !warned_global_md5_once) {
90 * We want admins to notice their misconfiguration!
92 D_ERR("CVE-2022-38023: "
93 "Please configure 'reject md5 clients = yes' (the default), "
94 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
95 warned_global_md5_once = true;
98 if (!schannel_global_required && !warned_global_schannel_once) {
100 * We want admins to notice their misconfiguration!
102 D_ERR("CVE-2020-1472(ZeroLogon): "
103 "Please configure 'server schannel = yes' (the default), "
104 "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n");
105 warned_global_schannel_once = true;
108 if (!global_require_seal && !warned_global_seal_once) {
110 * We want admins to notice their misconfiguration!
112 D_ERR("CVE-2022-38023 (and others): "
113 "Please configure 'server schannel require seal = yes' (the default), "
114 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
115 warned_global_seal_once = true;
118 return dcesrv_interface_bind_reject_connect(context, iface);
121 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
122 struct netr_ServerReqChallenge *r)
124 struct netlogon_server_pipe_state *pipe_state = NULL;
127 ZERO_STRUCTP(r->out.return_credentials);
129 pipe_state = dcesrv_iface_state_find_conn(dce_call,
130 NETLOGON_SERVER_PIPE_STATE_MAGIC,
131 struct netlogon_server_pipe_state);
132 TALLOC_FREE(pipe_state);
134 pipe_state = talloc_zero(dce_call,
135 struct netlogon_server_pipe_state);
136 if (pipe_state == NULL) {
137 return NT_STATUS_NO_MEMORY;
140 pipe_state->client_challenge = *r->in.credentials;
142 netlogon_creds_random_challenge(&pipe_state->server_challenge);
144 *r->out.return_credentials = pipe_state->server_challenge;
146 ntstatus = dcesrv_iface_state_store_conn(dce_call,
147 NETLOGON_SERVER_PIPE_STATE_MAGIC,
149 if (!NT_STATUS_IS_OK(ntstatus)) {
153 ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
154 &pipe_state->client_challenge,
155 &pipe_state->server_challenge,
156 r->in.computer_name);
157 if (!NT_STATUS_IS_OK(ntstatus)) {
158 TALLOC_FREE(pipe_state);
165 static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
166 struct dcesrv_call_state *dce_call,
167 struct netr_ServerAuthenticate3 *r,
168 struct netlogon_server_pipe_state *pipe_state,
169 uint32_t negotiate_flags,
170 const char *trust_account_in_db,
171 NTSTATUS orig_status)
173 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
174 bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
175 bool account_allow_nt4_crypto = global_allow_nt4_crypto;
176 const char *explicit_nt4_opt = NULL;
177 bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
178 bool account_reject_md5_client = global_reject_md5_client;
179 const char *explicit_md5_opt = NULL;
180 bool reject_des_client;
181 bool allow_nt4_crypto;
182 bool reject_md5_client;
183 bool need_des = true;
184 bool need_md5 = true;
185 int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL,
186 "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
187 int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL,
188 "CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
191 * We don't use lpcfg_parm_bool(), as we
192 * need the explicit_opt pointer in order to
193 * adjust the debug messages.
196 if (trust_account_in_db != NULL) {
197 explicit_nt4_opt = lpcfg_get_parametric(lp_ctx,
200 trust_account_in_db);
202 if (explicit_nt4_opt != NULL) {
203 account_allow_nt4_crypto = lp_bool(explicit_nt4_opt);
205 allow_nt4_crypto = account_allow_nt4_crypto;
206 if (trust_account_in_db != NULL) {
207 explicit_md5_opt = lpcfg_get_parametric(lp_ctx,
209 "server reject md5 schannel",
210 trust_account_in_db);
212 if (explicit_md5_opt != NULL) {
213 account_reject_md5_client = lp_bool(explicit_md5_opt);
215 reject_md5_client = account_reject_md5_client;
217 reject_des_client = !allow_nt4_crypto;
220 * If weak crypto is disabled, do not announce that we support RC4.
222 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
223 /* Without RC4 and DES we require AES */
224 reject_des_client = true;
225 reject_md5_client = true;
228 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
230 reject_des_client = false;
233 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
236 reject_des_client = false;
237 reject_md5_client = false;
240 if (reject_des_client || reject_md5_client) {
241 TALLOC_CTX *frame = talloc_stackframe();
243 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
244 if (CVE_2022_38023_error_level < DBGLVL_NOTICE) {
245 CVE_2022_38023_error_level = DBGLVL_NOTICE;
247 DEBUG(CVE_2022_38023_error_level, (
249 "client_account[%s] computer_name[%s] "
251 "client_negotiate_flags[0x%x] "
253 "NT_STATUS_DOWNGRADE_DETECTED "
254 "WEAK_CRYPTO_DISALLOWED\n",
255 log_escape(frame, r->in.account_name),
256 log_escape(frame, r->in.computer_name),
257 r->in.secure_channel_type,
258 (unsigned)*r->in.negotiate_flags,
259 trust_account_in_db ? "real_account[" : "",
260 trust_account_in_db ? trust_account_in_db : "",
261 trust_account_in_db ? "]" : ""));
262 goto return_downgrade;
265 DEBUG(CVE_2022_38023_error_level, (
267 "client_account[%s] computer_name[%s] "
269 "client_negotiate_flags[0x%x] "
271 "NT_STATUS_DOWNGRADE_DETECTED "
272 "reject_des[%u] reject_md5[%u]\n",
273 log_escape(frame, r->in.account_name),
274 log_escape(frame, r->in.computer_name),
275 r->in.secure_channel_type,
276 (unsigned)*r->in.negotiate_flags,
277 trust_account_in_db ? "real_account[" : "",
278 trust_account_in_db ? trust_account_in_db : "",
279 trust_account_in_db ? "]" : "",
282 if (trust_account_in_db == NULL) {
283 goto return_downgrade;
286 if (reject_md5_client && explicit_md5_opt == NULL) {
287 DEBUG(CVE_2022_38023_error_level, (
288 "CVE-2022-38023: Check if option "
289 "'server reject md5 schannel:%s = no' "
290 "might be needed for a legacy client.\n",
291 trust_account_in_db));
293 if (reject_des_client && explicit_nt4_opt == NULL) {
294 DEBUG(CVE_2022_38023_error_level, (
295 "CVE-2022-38023: Check if option "
296 "'allow nt4 crypto:%s = yes' "
297 "might be needed for a legacy client.\n",
298 trust_account_in_db));
303 * Here we match Windows 2012 and return no flags.
305 *r->out.negotiate_flags = 0;
307 return NT_STATUS_DOWNGRADE_DETECTED;
311 * This talloc_free is important to prevent re-use of the
312 * challenge. We have to delay it this far due to NETApp
314 * https://bugzilla.samba.org/show_bug.cgi?id=11291
316 TALLOC_FREE(pipe_state);
319 * At this point we must also cleanup the TDB cache
320 * entry, if we fail the client needs to call
321 * netr_ServerReqChallenge again.
323 * Note: this handles a non existing record just fine,
324 * the r->in.computer_name might not be the one used
325 * in netr_ServerReqChallenge(), but we are trying to
326 * just tidy up the normal case to prevent re-use.
328 schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
329 r->in.computer_name);
332 * According to Microsoft (see bugid #6099)
333 * Windows 7 looks at the negotiate_flags
334 * returned in this structure *even if the
335 * call fails with access denied!
337 *r->out.negotiate_flags = negotiate_flags;
339 if (!NT_STATUS_IS_OK(orig_status) || trust_account_in_db == NULL) {
343 if (global_reject_md5_client && account_reject_md5_client && explicit_md5_opt) {
344 D_INFO("CVE-2022-38023: Check if option "
345 "'server reject md5 schannel:%s = yes' not needed!?\n",
346 trust_account_in_db);
347 } else if (need_md5 && !account_reject_md5_client && explicit_md5_opt) {
348 D_INFO("CVE-2022-38023: Check if option "
349 "'server reject md5 schannel:%s = no' "
350 "still needed for a legacy client.\n",
351 trust_account_in_db);
352 } else if (need_md5 && explicit_md5_opt == NULL) {
353 DEBUG(CVE_2022_38023_error_level, (
354 "CVE-2022-38023: Check if option "
355 "'server reject md5 schannel:%s = no' "
356 "might be needed for a legacy client.\n",
357 trust_account_in_db));
358 } else if (!account_reject_md5_client && explicit_md5_opt) {
359 DEBUG(CVE_2022_38023_warn_level, (
360 "CVE-2022-38023: Check if option "
361 "'server reject md5 schannel:%s = no' not needed!?\n",
362 trust_account_in_db));
365 if (!global_allow_nt4_crypto && !account_allow_nt4_crypto && explicit_nt4_opt) {
366 D_INFO("CVE-2022-38023: Check if option "
367 "'allow nt4 crypto:%s = no' not needed!?\n",
368 trust_account_in_db);
369 } else if (need_des && account_allow_nt4_crypto && explicit_nt4_opt) {
370 D_INFO("CVE-2022-38023: Check if option "
371 "'allow nt4 crypto:%s = yes' "
372 "still needed for a legacy client.\n",
373 trust_account_in_db);
374 } else if (need_des && explicit_nt4_opt == NULL) {
375 DEBUG(CVE_2022_38023_error_level, (
376 "CVE-2022-38023: Check if option "
377 "'allow nt4 crypto:%s = yes' "
378 "might be needed for a legacy client.\n",
379 trust_account_in_db));
380 } else if (account_allow_nt4_crypto && explicit_nt4_opt) {
381 DEBUG(CVE_2022_38023_warn_level, (
382 "CVE-2022-38023: Check if option "
383 "'allow nt4 crypto:%s = yes' not needed!?\n",
384 trust_account_in_db));
391 * Do the actual processing of a netr_ServerAuthenticate3 message.
392 * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
394 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
395 struct dcesrv_call_state *dce_call,
397 struct netr_ServerAuthenticate3 *r,
398 const char **trust_account_for_search,
399 const char **trust_account_in_db,
400 struct dom_sid **sid)
402 struct netlogon_server_pipe_state *pipe_state = NULL;
403 bool challenge_valid = false;
404 struct netlogon_server_pipe_state challenge;
405 struct netlogon_creds_CredentialState *creds;
406 struct ldb_context *sam_ctx;
407 struct samr_Password *curNtHash = NULL;
408 struct samr_Password *prevNtHash = NULL;
409 uint32_t user_account_control;
411 struct ldb_message **msgs;
413 static const char *attrs[] = {"unicodePwd",
414 "userAccountControl",
418 uint32_t server_flags = 0;
419 uint32_t negotiate_flags = 0;
421 ZERO_STRUCTP(r->out.return_credentials);
422 *r->out.negotiate_flags = 0;
425 pipe_state = dcesrv_iface_state_find_conn(dce_call,
426 NETLOGON_SERVER_PIPE_STATE_MAGIC,
427 struct netlogon_server_pipe_state);
428 if (pipe_state != NULL) {
430 * If we had a challenge remembered on the connection
431 * consider this for usage. This can't be cleanup
434 * This is the default code path for typical clients
435 * which call netr_ServerReqChallenge() and
436 * netr_ServerAuthenticate3() on the same dcerpc connection.
438 challenge = *pipe_state;
440 challenge_valid = true;
446 * Fallback and try to get the challenge from
449 * If too many clients are using this code path,
450 * they may destroy their cache entries as the
451 * TDB has a fixed size limited via a lossy hash
453 * The TDB used is the schannel store, which is
454 * initialised at startup.
456 * NOTE: The challenge is deleted from the DB as soon as it is
457 * fetched, to prevent reuse.
461 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
462 &challenge.client_challenge,
463 &challenge.server_challenge,
464 r->in.computer_name);
466 if (!NT_STATUS_IS_OK(ntstatus)) {
467 ZERO_STRUCT(challenge);
469 challenge_valid = true;
473 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
474 NETLOGON_NEG_PERSISTENT_SAMREPL |
475 NETLOGON_NEG_ARCFOUR |
476 NETLOGON_NEG_PROMOTION_COUNT |
477 NETLOGON_NEG_CHANGELOG_BDC |
478 NETLOGON_NEG_FULL_SYNC_REPL |
479 NETLOGON_NEG_MULTIPLE_SIDS |
481 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
482 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
483 NETLOGON_NEG_GENERIC_PASSTHROUGH |
484 NETLOGON_NEG_CONCURRENT_RPC |
485 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
486 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
487 NETLOGON_NEG_STRONG_KEYS |
488 NETLOGON_NEG_TRANSITIVE_TRUSTS |
489 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
490 NETLOGON_NEG_PASSWORD_SET2 |
491 NETLOGON_NEG_GETDOMAININFO |
492 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
493 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
494 NETLOGON_NEG_RODC_PASSTHROUGH |
495 NETLOGON_NEG_SUPPORTS_AES |
496 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
497 NETLOGON_NEG_AUTHENTICATED_RPC;
500 * If weak crypto is disabled, do not announce that we support RC4.
502 if (lpcfg_weak_crypto(dce_call->conn->dce_ctx->lp_ctx) ==
503 SAMBA_WEAK_CRYPTO_DISALLOWED) {
504 server_flags &= ~NETLOGON_NEG_ARCFOUR;
507 negotiate_flags = *r->in.negotiate_flags & server_flags;
509 switch (r->in.secure_channel_type) {
511 case SEC_CHAN_DNS_DOMAIN:
512 case SEC_CHAN_DOMAIN:
517 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
518 dce_call, r, pipe_state, negotiate_flags,
519 NULL, /* trust_account_in_db */
520 NT_STATUS_INVALID_PARAMETER);
522 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
523 r->in.secure_channel_type));
524 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
525 dce_call, r, pipe_state, negotiate_flags,
526 NULL, /* trust_account_in_db */
527 NT_STATUS_INVALID_PARAMETER);
530 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
531 if (sam_ctx == NULL) {
532 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
533 dce_call, r, pipe_state, negotiate_flags,
534 NULL, /* trust_account_in_db */
535 NT_STATUS_INVALID_SYSTEM_SERVICE);
538 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
539 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
541 struct ldb_message *tdo_msg = NULL;
542 static const char *const tdo_attrs[] = {"trustAuthIncoming",
546 char *encoded_name = NULL;
548 const char *flatname = NULL;
550 bool require_trailer = true;
551 const char *netbios = NULL;
552 const char *dns = NULL;
554 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
556 require_trailer = false;
559 encoded_name = ldb_binary_encode_string(mem_ctx,
561 if (encoded_name == NULL) {
562 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
563 dce_call, r, pipe_state, negotiate_flags,
564 NULL, /* trust_account_in_db */
565 NT_STATUS_NO_MEMORY);
568 len = strlen(encoded_name);
570 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
571 dce_call, r, pipe_state, negotiate_flags,
572 NULL, /* trust_account_in_db */
573 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
576 if (require_trailer && encoded_name[len - 1] != trailer) {
577 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
578 dce_call, r, pipe_state, negotiate_flags,
579 NULL, /* trust_account_in_db */
580 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
582 encoded_name[len - 1] = '\0';
584 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
587 netbios = encoded_name;
590 nt_status = dsdb_trust_search_tdo(sam_ctx,
592 tdo_attrs, mem_ctx, &tdo_msg);
593 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
594 DEBUG(2, ("Client asked for a trusted domain secure channel, "
595 "but there's no tdo for [%s] => [%s] \n",
596 log_escape(mem_ctx, r->in.account_name),
598 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
599 dce_call, r, pipe_state, negotiate_flags,
600 NULL, /* trust_account_in_db */
601 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
603 if (!NT_STATUS_IS_OK(nt_status)) {
604 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
605 dce_call, r, pipe_state, negotiate_flags,
606 NULL, /* trust_account_in_db */
610 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
613 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
614 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
615 dce_call, r, pipe_state, negotiate_flags,
616 NULL, /* trust_account_in_db */
617 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
619 if (!NT_STATUS_IS_OK(nt_status)) {
620 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
621 dce_call, r, pipe_state, negotiate_flags,
622 NULL, /* trust_account_in_db */
626 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
627 if (flatname == NULL) {
628 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
629 dce_call, r, pipe_state, negotiate_flags,
630 NULL, /* trust_account_in_db */
631 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
634 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
635 if (*trust_account_for_search == NULL) {
636 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
637 dce_call, r, pipe_state, negotiate_flags,
638 NULL, /* trust_account_in_db */
639 NT_STATUS_NO_MEMORY);
642 *trust_account_for_search = r->in.account_name;
645 /* pull the user attributes */
646 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
647 "(&(sAMAccountName=%s)(objectclass=user))",
648 ldb_binary_encode_string(mem_ctx,
649 *trust_account_for_search));
651 if (num_records == 0) {
652 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
653 log_escape(mem_ctx, r->in.account_name)));
654 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
655 dce_call, r, pipe_state, negotiate_flags,
656 NULL, /* trust_account_in_db */
657 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
660 if (num_records > 1) {
661 DEBUG(0,("Found %d records matching user [%s]\n",
663 log_escape(mem_ctx, r->in.account_name)));
664 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
665 dce_call, r, pipe_state, negotiate_flags,
666 NULL, /* trust_account_in_db */
667 NT_STATUS_INTERNAL_DB_CORRUPTION);
670 *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
673 if (*trust_account_in_db == NULL) {
674 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
675 r->in.account_name));
676 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
677 dce_call, r, pipe_state, negotiate_flags,
678 NULL, /* trust_account_in_db */
679 NT_STATUS_INTERNAL_DB_CORRUPTION);
682 nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
683 dce_call, r, pipe_state, negotiate_flags,
684 *trust_account_in_db,
686 if (!NT_STATUS_IS_OK(nt_status)) {
690 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
692 if (user_account_control & UF_ACCOUNTDISABLE) {
693 DEBUG(1, ("Account [%s] is disabled\n",
694 log_escape(mem_ctx, r->in.account_name)));
695 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
698 switch (r->in.secure_channel_type) {
700 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
701 DBG_WARNING("Client asked for a workstation "
702 "secure channel, but is not a workstation "
703 "(member server) acb flags: 0x%x\n",
704 user_account_control);
705 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
709 case SEC_CHAN_DOMAIN:
711 case SEC_CHAN_DNS_DOMAIN:
712 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
713 DBG_WARNING("Client asked for a trusted domain "
714 "secure channel, but is not a trusted "
715 "domain: acb flags: 0x%x\n",
716 user_account_control);
717 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
722 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
723 DBG_WARNING("Client asked for a server "
724 "secure channel, but is not a server "
725 "(domain controller): acb flags: 0x%x\n",
726 user_account_control);
727 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
732 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
733 DBG_WARNING("Client asked for a RODC secure channel, "
734 "but is not a RODC: acb flags: 0x%x\n",
735 user_account_control);
736 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
741 /* we should never reach this */
742 return NT_STATUS_INTERNAL_ERROR;
745 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
746 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
747 dce_call->conn->dce_ctx->lp_ctx,
748 msgs[0], &curNtHash);
749 if (!NT_STATUS_IS_OK(nt_status)) {
750 return NT_STATUS_ACCESS_DENIED;
754 if (curNtHash == NULL) {
755 return NT_STATUS_ACCESS_DENIED;
758 if (!challenge_valid) {
759 DEBUG(1, ("No challenge requested by client [%s/%s], "
760 "cannot authenticate\n",
761 log_escape(mem_ctx, r->in.computer_name),
762 log_escape(mem_ctx, r->in.account_name)));
763 return NT_STATUS_ACCESS_DENIED;
766 creds = netlogon_creds_server_init(mem_ctx,
769 r->in.secure_channel_type,
770 &challenge.client_challenge,
771 &challenge.server_challenge,
774 r->out.return_credentials,
776 if (creds == NULL && prevNtHash != NULL) {
778 * We fallback to the previous password for domain trusts.
780 * Note that lpcfg_old_password_allowed_period() doesn't
783 creds = netlogon_creds_server_init(mem_ctx,
786 r->in.secure_channel_type,
787 &challenge.client_challenge,
788 &challenge.server_challenge,
791 r->out.return_credentials,
796 return NT_STATUS_ACCESS_DENIED;
798 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
799 *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
801 nt_status = schannel_save_creds_state(mem_ctx,
802 dce_call->conn->dce_ctx->lp_ctx,
804 if (!NT_STATUS_IS_OK(nt_status)) {
805 ZERO_STRUCTP(r->out.return_credentials);
809 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
816 * Log a netr_ServerAuthenticate3 request, and then invoke
817 * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
819 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
820 struct dcesrv_call_state *dce_call,
822 struct netr_ServerAuthenticate3 *r)
825 struct dom_sid *sid = NULL;
826 const char *trust_account_for_search = NULL;
827 const char *trust_account_in_db = NULL;
828 struct imessaging_context *imsg_ctx =
829 dcesrv_imessaging_context(dce_call->conn);
830 struct auth_usersupplied_info ui = {
831 .local_host = dce_call->conn->local_address,
832 .remote_host = dce_call->conn->remote_address,
834 .account_name = r->in.account_name,
835 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
837 .service_description = "NETLOGON",
838 .auth_description = "ServerAuthenticate",
839 .netlogon_trust_account = {
840 .computer_name = r->in.computer_name,
841 .negotiate_flags = *r->in.negotiate_flags,
842 .secure_channel_type = r->in.secure_channel_type,
846 status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
849 &trust_account_for_search,
850 &trust_account_in_db,
852 ui.netlogon_trust_account.sid = sid;
853 ui.netlogon_trust_account.account_name = trust_account_in_db;
854 ui.mapped.account_name = trust_account_for_search;
855 log_authentication_event(
857 dce_call->conn->dce_ctx->lp_ctx,
861 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
864 NULL /* client_audit_info */,
865 NULL /* server_audit_info */);
869 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
870 struct netr_ServerAuthenticate *r)
872 struct netr_ServerAuthenticate3 a;
875 * negotiate_flags is used as an [in] parameter
876 * so it need to be initialised.
878 * (I think ... = 0; seems wrong here --metze)
880 uint32_t negotiate_flags_in = 0;
881 uint32_t negotiate_flags_out = 0;
883 a.in.server_name = r->in.server_name;
884 a.in.account_name = r->in.account_name;
885 a.in.secure_channel_type = r->in.secure_channel_type;
886 a.in.computer_name = r->in.computer_name;
887 a.in.credentials = r->in.credentials;
888 a.in.negotiate_flags = &negotiate_flags_in;
890 a.out.return_credentials = r->out.return_credentials;
892 a.out.negotiate_flags = &negotiate_flags_out;
894 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
897 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
898 struct netr_ServerAuthenticate2 *r)
900 struct netr_ServerAuthenticate3 r3;
903 r3.in.server_name = r->in.server_name;
904 r3.in.account_name = r->in.account_name;
905 r3.in.secure_channel_type = r->in.secure_channel_type;
906 r3.in.computer_name = r->in.computer_name;
907 r3.in.credentials = r->in.credentials;
908 r3.out.return_credentials = r->out.return_credentials;
909 r3.in.negotiate_flags = r->in.negotiate_flags;
910 r3.out.negotiate_flags = r->out.negotiate_flags;
913 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
917 Change the machine account password for the currently connected
918 client. Supplies only the NT#.
921 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
922 struct netr_ServerPasswordSet *r)
924 struct netlogon_creds_CredentialState *creds;
925 struct ldb_context *sam_ctx;
928 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
931 r->in.credential, r->out.return_authenticator,
933 NT_STATUS_NOT_OK_RETURN(nt_status);
935 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
936 if (sam_ctx == NULL) {
937 return NT_STATUS_INVALID_SYSTEM_SERVICE;
940 nt_status = netlogon_creds_des_decrypt(creds, r->in.new_password);
941 NT_STATUS_NOT_OK_RETURN(nt_status);
943 /* Using the sid for the account as the key, set the password */
944 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
946 NULL, /* Don't have version */
947 NULL, /* Don't have plaintext */
949 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
955 Change the machine account password for the currently connected
956 client. Supplies new plaintext.
958 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
959 struct netr_ServerPasswordSet2 *r)
961 struct netlogon_creds_CredentialState *creds;
962 struct ldb_context *sam_ctx;
963 struct NL_PASSWORD_VERSION version = {};
964 const uint32_t *new_version = NULL;
966 DATA_BLOB new_password = data_blob_null;
967 size_t confounder_len;
968 DATA_BLOB dec_blob = data_blob_null;
969 DATA_BLOB enc_blob = data_blob_null;
970 struct samr_CryptPassword password_buf;
972 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
975 r->in.credential, r->out.return_authenticator,
977 NT_STATUS_NOT_OK_RETURN(nt_status);
979 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
980 if (sam_ctx == NULL) {
981 return NT_STATUS_INVALID_SYSTEM_SERVICE;
984 memcpy(password_buf.data, r->in.new_password->data, 512);
985 SIVAL(password_buf.data, 512, r->in.new_password->length);
987 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
988 nt_status = netlogon_creds_aes_decrypt(creds,
992 nt_status = netlogon_creds_arcfour_crypt(creds,
997 if (!NT_STATUS_IS_OK(nt_status)) {
1001 switch (creds->secure_channel_type) {
1002 case SEC_CHAN_DOMAIN:
1003 case SEC_CHAN_DNS_DOMAIN: {
1004 uint32_t len = IVAL(password_buf.data, 512);
1006 uint32_t ofs = 500 - len;
1009 p = password_buf.data + ofs;
1011 version.ReservedField = IVAL(p, 0);
1012 version.PasswordVersionNumber = IVAL(p, 4);
1013 version.PasswordVersionPresent = IVAL(p, 8);
1015 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
1016 new_version = &version.PasswordVersionNumber;
1024 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
1025 DEBUG(3,("samr: failed to decode password buffer\n"));
1026 return NT_STATUS_WRONG_PASSWORD;
1030 * Make sure the length field was encrypted,
1031 * otherwise we are under attack.
1033 if (new_password.length == r->in.new_password->length) {
1034 DBG_WARNING("Length[%zu] field not encrypted\n",
1035 new_password.length);
1036 return NT_STATUS_WRONG_PASSWORD;
1040 * We don't allow empty passwords for machine accounts.
1042 if (new_password.length < 2) {
1043 DBG_WARNING("Empty password Length[%zu]\n",
1044 new_password.length);
1045 return NT_STATUS_WRONG_PASSWORD;
1049 * Make sure the confounder part of CryptPassword
1050 * buffer was encrypted, otherwise we are under attack.
1052 confounder_len = 512 - new_password.length;
1053 enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
1054 dec_blob = data_blob_const(password_buf.data, confounder_len);
1055 if (confounder_len > 0 && data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1056 DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
1058 return NT_STATUS_WRONG_PASSWORD;
1062 * Check that the password part was actually encrypted,
1063 * otherwise we are under attack.
1065 enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
1066 new_password.length);
1067 dec_blob = data_blob_const(password_buf.data + confounder_len,
1068 new_password.length);
1069 if (data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1070 DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
1071 new_password.length);
1072 return NT_STATUS_WRONG_PASSWORD;
1076 * don't allow zero buffers
1078 if (all_zero(new_password.data, new_password.length)) {
1079 DBG_WARNING("Password zero buffer Length[%zu]\n",
1080 new_password.length);
1081 return NT_STATUS_WRONG_PASSWORD;
1084 /* Using the sid for the account as the key, set the password */
1085 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1088 &new_password, /* we have plaintext */
1090 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1099 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1100 struct netr_LogonUasLogon *r)
1102 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1109 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1110 struct netr_LogonUasLogoff *r)
1112 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1116 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
1117 const struct netr_LogonSamLogonEx *r)
1119 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1121 switch (r->in.logon_level) {
1122 case NetlogonInteractiveInformation:
1123 case NetlogonServiceInformation:
1124 case NetlogonInteractiveTransitiveInformation:
1125 case NetlogonServiceTransitiveInformation:
1126 if (r->in.logon->password == NULL) {
1127 return NT_STATUS_INVALID_PARAMETER;
1130 switch (r->in.validation_level) {
1131 case NetlogonValidationSamInfo: /* 2 */
1132 case NetlogonValidationSamInfo2: /* 3 */
1133 case NetlogonValidationSamInfo4: /* 6 */
1136 return NT_STATUS_INVALID_INFO_CLASS;
1140 case NetlogonNetworkInformation:
1141 case NetlogonNetworkTransitiveInformation:
1142 if (r->in.logon->network == NULL) {
1143 return NT_STATUS_INVALID_PARAMETER;
1146 switch (r->in.validation_level) {
1147 case NetlogonValidationSamInfo: /* 2 */
1148 case NetlogonValidationSamInfo2: /* 3 */
1149 case NetlogonValidationSamInfo4: /* 6 */
1152 return NT_STATUS_INVALID_INFO_CLASS;
1157 case NetlogonGenericInformation:
1158 if (r->in.logon->generic == NULL) {
1159 return NT_STATUS_INVALID_PARAMETER;
1162 switch (r->in.validation_level) {
1163 /* TODO: case NetlogonValidationGenericInfo: 4 */
1164 case NetlogonValidationGenericInfo2: /* 5 */
1167 return NT_STATUS_INVALID_INFO_CLASS;
1172 return NT_STATUS_INVALID_PARAMETER;
1175 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
1177 switch (r->in.validation_level) {
1178 case NetlogonValidationSamInfo4: /* 6 */
1179 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1180 return NT_STATUS_INVALID_PARAMETER;
1188 return NT_STATUS_OK;
1191 struct dcesrv_netr_LogonSamLogon_base_state {
1192 struct dcesrv_call_state *dce_call;
1194 TALLOC_CTX *mem_ctx;
1196 struct netlogon_creds_CredentialState *creds;
1198 struct netr_LogonSamLogonEx r;
1200 uint32_t _ignored_flags;
1203 struct netr_LogonSamLogon *lsl;
1204 struct netr_LogonSamLogonWithFlags *lslwf;
1205 struct netr_LogonSamLogonEx *lslex;
1208 struct kdc_check_generic_kerberos kr;
1211 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
1212 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
1213 static void dcesrv_netr_LogonSamLogon_base_reply(
1214 struct dcesrv_netr_LogonSamLogon_base_state *state);
1217 netr_LogonSamLogon_base
1219 This version of the function allows other wrappers to say 'do not check the credentials'
1221 We can't do the traditional 'wrapping' format completely, as this
1222 function must only run under schannel
1224 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
1226 struct dcesrv_call_state *dce_call = state->dce_call;
1227 struct imessaging_context *imsg_ctx =
1228 dcesrv_imessaging_context(dce_call->conn);
1229 TALLOC_CTX *mem_ctx = state->mem_ctx;
1230 struct netr_LogonSamLogonEx *r = &state->r;
1231 struct netlogon_creds_CredentialState *creds = state->creds;
1232 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1233 const char *workgroup = lpcfg_workgroup(lp_ctx);
1234 struct auth4_context *auth_context = NULL;
1235 struct auth_usersupplied_info *user_info = NULL;
1237 struct tevent_req *subreq = NULL;
1238 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1239 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1241 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1243 switch (dce_call->pkt.u.request.opnum) {
1244 case NDR_NETR_LOGONSAMLOGON:
1245 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
1247 * These already called dcesrv_netr_check_schannel()
1248 * via dcesrv_netr_creds_server_step_check()
1251 case NDR_NETR_LOGONSAMLOGONEX:
1253 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1254 return NT_STATUS_ACCESS_DENIED;
1257 nt_status = dcesrv_netr_check_schannel(dce_call,
1261 dce_call->pkt.u.request.opnum);
1262 if (!NT_STATUS_IS_OK(nt_status)) {
1268 *r->out.authoritative = 1;
1270 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
1272 * Currently we're always the forest root ourself.
1274 return NT_STATUS_NO_SUCH_USER;
1277 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
1279 * Currently we don't support trusts correctly yet.
1281 return NT_STATUS_NO_SUCH_USER;
1284 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1285 NT_STATUS_HAVE_NO_MEMORY(user_info);
1287 user_info->service_description = "SamLogon";
1289 nt_status = netlogon_creds_decrypt_samlogon_logon(creds,
1292 NT_STATUS_NOT_OK_RETURN(nt_status);
1294 switch (r->in.logon_level) {
1295 case NetlogonInteractiveInformation:
1296 case NetlogonServiceInformation:
1297 case NetlogonInteractiveTransitiveInformation:
1298 case NetlogonServiceTransitiveInformation:
1299 case NetlogonNetworkInformation:
1300 case NetlogonNetworkTransitiveInformation:
1302 nt_status = auth_context_create_for_netlogon(mem_ctx,
1303 dce_call->event_ctx,
1305 dce_call->conn->dce_ctx->lp_ctx,
1307 NT_STATUS_NOT_OK_RETURN(nt_status);
1309 user_info->remote_host = dce_call->conn->remote_address;
1310 user_info->local_host = dce_call->conn->local_address;
1312 user_info->netlogon_trust_account.secure_channel_type
1313 = creds->secure_channel_type;
1314 user_info->netlogon_trust_account.negotiate_flags
1315 = creds->negotiate_flags;
1318 * These two can be unrelated when the account is
1319 * actually that of a trusted domain, so we want to
1320 * know which DC in that trusted domain contacted
1323 user_info->netlogon_trust_account.computer_name
1324 = creds->computer_name;
1325 user_info->netlogon_trust_account.account_name
1326 = creds->account_name;
1327 user_info->netlogon_trust_account.sid
1332 /* We do not need to set up the user_info in this case */
1336 switch (r->in.logon_level) {
1337 case NetlogonInteractiveInformation:
1338 case NetlogonServiceInformation:
1339 case NetlogonInteractiveTransitiveInformation:
1340 case NetlogonServiceTransitiveInformation:
1341 user_info->auth_description = "interactive";
1343 user_info->logon_parameters
1344 = r->in.logon->password->identity_info.parameter_control;
1345 user_info->client.account_name
1346 = r->in.logon->password->identity_info.account_name.string;
1347 user_info->client.domain_name
1348 = r->in.logon->password->identity_info.domain_name.string;
1349 user_info->workstation_name
1350 = r->in.logon->password->identity_info.workstation.string;
1351 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1352 user_info->password_state = AUTH_PASSWORD_HASH;
1354 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1355 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1356 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1358 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1359 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1360 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1363 = r->in.logon->password->identity_info.logon_id;
1366 case NetlogonNetworkInformation:
1367 case NetlogonNetworkTransitiveInformation:
1368 user_info->auth_description = "network";
1370 nt_status = auth_context_set_challenge(
1372 r->in.logon->network->challenge,
1373 "netr_LogonSamLogonWithFlags");
1374 NT_STATUS_NOT_OK_RETURN(nt_status);
1376 user_info->logon_parameters
1377 = r->in.logon->network->identity_info.parameter_control;
1378 user_info->client.account_name
1379 = r->in.logon->network->identity_info.account_name.string;
1380 user_info->client.domain_name
1381 = r->in.logon->network->identity_info.domain_name.string;
1382 user_info->workstation_name
1383 = r->in.logon->network->identity_info.workstation.string;
1385 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1386 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1387 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1390 = r->in.logon->network->identity_info.logon_id;
1392 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1393 user_info->client.account_name,
1394 user_info->client.domain_name,
1395 user_info->password.response.nt,
1397 NT_STATUS_NOT_OK_RETURN(nt_status);
1402 case NetlogonGenericInformation:
1404 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1406 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1409 /* Using DES to verify kerberos tickets makes no sense */
1410 return NT_STATUS_INVALID_PARAMETER;
1413 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1414 struct dcerpc_binding_handle *irpc_handle;
1415 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1416 NT_STATUS_HAVE_NO_MEMORY(generic);
1418 r->out.validation->generic = generic;
1421 = r->in.logon->generic->identity_info.logon_id;
1423 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1427 if (irpc_handle == NULL) {
1428 return NT_STATUS_NO_LOGON_SERVERS;
1431 state->kr.in.generic_request =
1432 data_blob_const(r->in.logon->generic->data,
1433 r->in.logon->generic->length);
1436 * 60 seconds should be enough
1438 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1439 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1440 state->dce_call->event_ctx,
1441 irpc_handle, &state->kr);
1442 if (subreq == NULL) {
1443 return NT_STATUS_NO_MEMORY;
1445 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1446 tevent_req_set_callback(subreq,
1447 dcesrv_netr_LogonSamLogon_base_krb5_done,
1449 return NT_STATUS_OK;
1452 /* Until we get an implementation of these other packages */
1453 return NT_STATUS_INVALID_PARAMETER;
1456 return NT_STATUS_INVALID_PARAMETER;
1459 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1460 auth_context, user_info);
1461 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1462 tevent_req_set_callback(subreq,
1463 dcesrv_netr_LogonSamLogon_base_auth_done,
1465 return NT_STATUS_OK;
1468 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1470 struct dcesrv_netr_LogonSamLogon_base_state *state =
1471 tevent_req_callback_data(subreq,
1472 struct dcesrv_netr_LogonSamLogon_base_state);
1473 TALLOC_CTX *mem_ctx = state->mem_ctx;
1474 struct netr_LogonSamLogonEx *r = &state->r;
1475 struct auth_user_info_dc *user_info_dc = NULL;
1476 struct netr_SamInfo2 *sam2 = NULL;
1477 struct netr_SamInfo3 *sam3 = NULL;
1478 struct netr_SamInfo6 *sam6 = NULL;
1481 nt_status = auth_check_password_recv(subreq, mem_ctx,
1483 r->out.authoritative);
1484 TALLOC_FREE(subreq);
1485 if (!NT_STATUS_IS_OK(nt_status)) {
1486 r->out.result = nt_status;
1487 dcesrv_netr_LogonSamLogon_base_reply(state);
1491 switch (r->in.validation_level) {
1493 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1495 AUTH_INCLUDE_RESOURCE_GROUPS,
1497 if (!NT_STATUS_IS_OK(nt_status)) {
1498 r->out.result = nt_status;
1499 dcesrv_netr_LogonSamLogon_base_reply(state);
1503 r->out.validation->sam2 = sam2;
1507 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1509 AUTH_INCLUDE_RESOURCE_GROUPS,
1511 if (!NT_STATUS_IS_OK(nt_status)) {
1512 r->out.result = nt_status;
1513 dcesrv_netr_LogonSamLogon_base_reply(state);
1517 r->out.validation->sam3 = sam3;
1521 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1523 AUTH_INCLUDE_RESOURCE_GROUPS,
1525 if (!NT_STATUS_IS_OK(nt_status)) {
1526 r->out.result = nt_status;
1527 dcesrv_netr_LogonSamLogon_base_reply(state);
1531 r->out.validation->sam6 = sam6;
1535 if (!NT_STATUS_IS_OK(nt_status)) {
1536 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1537 dcesrv_netr_LogonSamLogon_base_reply(state);
1542 /* TODO: Describe and deal with these flags */
1545 r->out.result = NT_STATUS_OK;
1547 dcesrv_netr_LogonSamLogon_base_reply(state);
1550 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1552 struct dcesrv_netr_LogonSamLogon_base_state *state =
1553 tevent_req_callback_data(subreq,
1554 struct dcesrv_netr_LogonSamLogon_base_state);
1555 TALLOC_CTX *mem_ctx = state->mem_ctx;
1556 struct netr_LogonSamLogonEx *r = &state->r;
1557 struct netr_GenericInfo2 *generic = NULL;
1560 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1561 TALLOC_FREE(subreq);
1562 if (!NT_STATUS_IS_OK(status)) {
1563 r->out.result = status;
1564 dcesrv_netr_LogonSamLogon_base_reply(state);
1568 generic = r->out.validation->generic;
1569 generic->length = state->kr.out.generic_reply.length;
1570 generic->data = state->kr.out.generic_reply.data;
1572 /* TODO: Describe and deal with these flags */
1575 r->out.result = NT_STATUS_OK;
1577 dcesrv_netr_LogonSamLogon_base_reply(state);
1580 static void dcesrv_netr_LogonSamLogon_base_reply(
1581 struct dcesrv_netr_LogonSamLogon_base_state *state)
1583 struct netr_LogonSamLogonEx *r = &state->r;
1586 if (NT_STATUS_IS_OK(r->out.result)) {
1587 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
1588 r->in.validation_level,
1590 if (!NT_STATUS_IS_OK(status)) {
1591 DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
1597 if (state->_r.lslex != NULL) {
1598 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1599 _r->out.result = r->out.result;
1600 } else if (state->_r.lslwf != NULL) {
1601 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1602 _r->out.result = r->out.result;
1603 } else if (state->_r.lsl != NULL) {
1604 struct netr_LogonSamLogon *_r = state->_r.lsl;
1605 _r->out.result = r->out.result;
1608 dcesrv_async_reply(state->dce_call);
1611 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1612 struct netr_LogonSamLogonEx *r)
1614 struct dcesrv_netr_LogonSamLogon_base_state *state;
1617 *r->out.authoritative = 1;
1619 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1620 if (state == NULL) {
1621 return NT_STATUS_NO_MEMORY;
1624 state->dce_call = dce_call;
1625 state->mem_ctx = mem_ctx;
1627 state->r.in.server_name = r->in.server_name;
1628 state->r.in.computer_name = r->in.computer_name;
1629 state->r.in.logon_level = r->in.logon_level;
1630 state->r.in.logon = r->in.logon;
1631 state->r.in.validation_level = r->in.validation_level;
1632 state->r.in.flags = r->in.flags;
1633 state->r.out.validation = r->out.validation;
1634 state->r.out.authoritative = r->out.authoritative;
1635 state->r.out.flags = r->out.flags;
1637 state->_r.lslex = r;
1639 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1640 if (!NT_STATUS_IS_OK(nt_status)) {
1644 nt_status = schannel_get_creds_state(mem_ctx,
1645 dce_call->conn->dce_ctx->lp_ctx,
1646 r->in.computer_name, &state->creds);
1647 if (!NT_STATUS_IS_OK(nt_status)) {
1651 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1653 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1661 netr_LogonSamLogonWithFlags
1664 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1665 struct netr_LogonSamLogonWithFlags *r)
1667 struct dcesrv_netr_LogonSamLogon_base_state *state;
1670 *r->out.authoritative = 1;
1672 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1673 if (state == NULL) {
1674 return NT_STATUS_NO_MEMORY;
1677 state->dce_call = dce_call;
1678 state->mem_ctx = mem_ctx;
1680 state->r.in.server_name = r->in.server_name;
1681 state->r.in.computer_name = r->in.computer_name;
1682 state->r.in.logon_level = r->in.logon_level;
1683 state->r.in.logon = r->in.logon;
1684 state->r.in.validation_level = r->in.validation_level;
1685 state->r.in.flags = r->in.flags;
1686 state->r.out.validation = r->out.validation;
1687 state->r.out.authoritative = r->out.authoritative;
1688 state->r.out.flags = r->out.flags;
1690 state->_r.lslwf = r;
1692 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1693 if (!NT_STATUS_IS_OK(nt_status)) {
1697 r->out.return_authenticator = talloc_zero(mem_ctx,
1698 struct netr_Authenticator);
1699 if (r->out.return_authenticator == NULL) {
1700 return NT_STATUS_NO_MEMORY;
1703 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1705 r->in.computer_name,
1707 r->out.return_authenticator,
1709 if (!NT_STATUS_IS_OK(nt_status)) {
1713 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1715 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1725 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1726 struct netr_LogonSamLogon *r)
1728 struct dcesrv_netr_LogonSamLogon_base_state *state;
1731 *r->out.authoritative = 1;
1733 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1734 if (state == NULL) {
1735 return NT_STATUS_NO_MEMORY;
1738 state->dce_call = dce_call;
1739 state->mem_ctx = mem_ctx;
1741 state->r.in.server_name = r->in.server_name;
1742 state->r.in.computer_name = r->in.computer_name;
1743 state->r.in.logon_level = r->in.logon_level;
1744 state->r.in.logon = r->in.logon;
1745 state->r.in.validation_level = r->in.validation_level;
1746 state->r.in.flags = &state->_ignored_flags;
1747 state->r.out.validation = r->out.validation;
1748 state->r.out.authoritative = r->out.authoritative;
1749 state->r.out.flags = &state->_ignored_flags;
1753 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1754 if (!NT_STATUS_IS_OK(nt_status)) {
1758 r->out.return_authenticator = talloc_zero(mem_ctx,
1759 struct netr_Authenticator);
1760 if (r->out.return_authenticator == NULL) {
1761 return NT_STATUS_NO_MEMORY;
1764 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1766 r->in.computer_name,
1768 r->out.return_authenticator,
1770 if (!NT_STATUS_IS_OK(nt_status)) {
1774 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1776 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1787 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1788 struct netr_LogonSamLogoff *r)
1790 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1798 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1799 struct netr_DatabaseDeltas *r)
1801 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1808 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1809 struct netr_DatabaseSync2 *r)
1811 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1812 return NT_STATUS_NOT_IMPLEMENTED;
1819 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1820 struct netr_DatabaseSync *r)
1822 struct netr_DatabaseSync2 r2;
1827 r2.in.logon_server = r->in.logon_server;
1828 r2.in.computername = r->in.computername;
1829 r2.in.credential = r->in.credential;
1830 r2.in.database_id = r->in.database_id;
1831 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1832 r2.in.sync_context = r->in.sync_context;
1833 r2.out.sync_context = r->out.sync_context;
1834 r2.out.delta_enum_array = r->out.delta_enum_array;
1835 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1837 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1846 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1847 struct netr_AccountDeltas *r)
1849 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1850 return NT_STATUS_NOT_IMPLEMENTED;
1857 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1858 struct netr_AccountSync *r)
1860 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1861 return NT_STATUS_NOT_IMPLEMENTED;
1868 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1869 struct netr_GetDcName *r)
1871 const char * const attrs[] = { NULL };
1872 struct ldb_context *sam_ctx;
1873 struct ldb_message **res;
1874 struct ldb_dn *domain_dn;
1879 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1880 * that the domainname needs to be a valid netbios domain
1881 * name, if it is not NULL.
1883 if (r->in.domainname) {
1884 const char *dot = strchr(r->in.domainname, '.');
1885 size_t len = strlen(r->in.domainname);
1887 if (dot || len > 15) {
1888 return WERR_NERR_DCNOTFOUND;
1892 * TODO: Should we also verify that only valid
1893 * netbios name characters are used?
1897 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
1898 if (sam_ctx == NULL) {
1899 return WERR_DS_UNAVAILABLE;
1902 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1904 if (domain_dn == NULL) {
1905 return WERR_NO_SUCH_DOMAIN;
1908 ret = gendb_search_dn(sam_ctx, mem_ctx,
1909 domain_dn, &res, attrs);
1911 return WERR_NO_SUCH_DOMAIN;
1914 /* TODO: - return real IP address
1915 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1917 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1918 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1919 W_ERROR_HAVE_NO_MEMORY(dcname);
1921 *r->out.dcname = dcname;
1925 struct dcesrv_netr_LogonControl_base_state {
1926 struct dcesrv_call_state *dce_call;
1928 TALLOC_CTX *mem_ctx;
1930 struct netr_LogonControl2Ex r;
1933 struct netr_LogonControl *l;
1934 struct netr_LogonControl2 *l2;
1935 struct netr_LogonControl2Ex *l2ex;
1939 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1941 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1943 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1944 struct auth_session_info *session_info =
1945 dcesrv_call_session_info(state->dce_call);
1946 struct imessaging_context *imsg_ctx =
1947 dcesrv_imessaging_context(state->dce_call->conn);
1948 enum security_user_level security_level;
1949 struct dcerpc_binding_handle *irpc_handle;
1950 struct tevent_req *subreq;
1953 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1955 if (state->_r.l != NULL) {
1959 if (state->r.in.level == 0x00000002) {
1960 return WERR_NOT_SUPPORTED;
1961 } else if (state->r.in.level != 0x00000001) {
1962 return WERR_INVALID_LEVEL;
1965 switch (state->r.in.function_code) {
1966 case NETLOGON_CONTROL_QUERY:
1967 case NETLOGON_CONTROL_REPLICATE:
1968 case NETLOGON_CONTROL_SYNCHRONIZE:
1969 case NETLOGON_CONTROL_PDC_REPLICATE:
1970 case NETLOGON_CONTROL_BREAKPOINT:
1971 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1972 case NETLOGON_CONTROL_TRUNCATE_LOG:
1975 return WERR_NOT_SUPPORTED;
1979 if (state->r.in.level < 0x00000001) {
1980 return WERR_INVALID_LEVEL;
1983 if (state->r.in.level > 0x00000004) {
1984 return WERR_INVALID_LEVEL;
1987 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1988 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1989 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1991 switch (state->r.in.level) {
1993 info1 = talloc_zero(state->mem_ctx,
1994 struct netr_NETLOGON_INFO_1);
1995 if (info1 == NULL) {
1996 return WERR_NOT_ENOUGH_MEMORY;
1998 state->r.out.query->info1 = info1;
2002 info3 = talloc_zero(state->mem_ctx,
2003 struct netr_NETLOGON_INFO_3);
2004 if (info3 == NULL) {
2005 return WERR_NOT_ENOUGH_MEMORY;
2007 state->r.out.query->info3 = info3;
2011 return WERR_INVALID_PARAMETER;
2016 * Some validations are done before the access check
2017 * and some after the access check
2019 security_level = security_session_user_level(session_info, NULL);
2020 if (security_level < SECURITY_ADMINISTRATOR) {
2021 return WERR_ACCESS_DENIED;
2024 if (state->_r.l2 != NULL) {
2026 * netr_LogonControl2
2028 if (state->r.in.level == 0x00000004) {
2029 return WERR_INVALID_LEVEL;
2033 switch (state->r.in.level) {
2038 switch (state->r.in.function_code) {
2039 case NETLOGON_CONTROL_REDISCOVER:
2040 case NETLOGON_CONTROL_TC_QUERY:
2041 case NETLOGON_CONTROL_TC_VERIFY:
2044 return WERR_INVALID_PARAMETER;
2053 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
2054 return WERR_INVALID_PARAMETER;
2060 return WERR_INVALID_LEVEL;
2063 switch (state->r.in.function_code) {
2064 case NETLOGON_CONTROL_REDISCOVER:
2065 case NETLOGON_CONTROL_TC_QUERY:
2066 case NETLOGON_CONTROL_TC_VERIFY:
2067 if (state->r.in.level != 2) {
2068 return WERR_INVALID_PARAMETER;
2071 if (state->r.in.data == NULL) {
2072 return WERR_INVALID_PARAMETER;
2075 if (state->r.in.data->domain == NULL) {
2076 return WERR_INVALID_PARAMETER;
2081 case NETLOGON_CONTROL_CHANGE_PASSWORD:
2082 if (state->r.in.level != 1) {
2083 return WERR_INVALID_PARAMETER;
2086 if (state->r.in.data == NULL) {
2087 return WERR_INVALID_PARAMETER;
2090 if (state->r.in.data->domain == NULL) {
2091 return WERR_INVALID_PARAMETER;
2094 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
2095 state->r.in.data->domain);
2097 struct ldb_context *sam_ctx;
2099 sam_ctx = dcesrv_samdb_connect_as_system(state,
2101 if (sam_ctx == NULL) {
2102 return WERR_DS_UNAVAILABLE;
2106 * Secrets for trusted domains can only be triggered on
2109 ok = samdb_is_pdc(sam_ctx);
2110 TALLOC_FREE(sam_ctx);
2112 return WERR_INVALID_DOMAIN_ROLE;
2118 return WERR_NOT_SUPPORTED;
2121 irpc_handle = irpc_binding_handle_by_name(state,
2124 &ndr_table_winbind);
2125 if (irpc_handle == NULL) {
2126 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2127 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2128 return WERR_SERVICE_NOT_FOUND;
2132 * 60 seconds timeout should be enough
2134 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2136 subreq = dcerpc_winbind_LogonControl_send(state,
2137 state->dce_call->event_ctx,
2139 state->r.in.function_code,
2142 state->r.out.query);
2143 if (subreq == NULL) {
2144 return WERR_NOT_ENOUGH_MEMORY;
2146 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2147 tevent_req_set_callback(subreq,
2148 dcesrv_netr_LogonControl_base_done,
2154 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
2156 struct dcesrv_netr_LogonControl_base_state *state =
2157 tevent_req_callback_data(subreq,
2158 struct dcesrv_netr_LogonControl_base_state);
2161 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
2162 &state->r.out.result);
2163 TALLOC_FREE(subreq);
2164 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
2165 state->r.out.result = WERR_TIMEOUT;
2166 } else if (!NT_STATUS_IS_OK(status)) {
2167 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2168 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
2169 nt_errstr(status)));
2172 if (state->_r.l2ex != NULL) {
2173 struct netr_LogonControl2Ex *r = state->_r.l2ex;
2174 r->out.result = state->r.out.result;
2175 } else if (state->_r.l2 != NULL) {
2176 struct netr_LogonControl2 *r = state->_r.l2;
2177 r->out.result = state->r.out.result;
2178 } else if (state->_r.l != NULL) {
2179 struct netr_LogonControl *r = state->_r.l;
2180 r->out.result = state->r.out.result;
2183 dcesrv_async_reply(state->dce_call);
2189 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2190 struct netr_LogonControl *r)
2192 struct dcesrv_netr_LogonControl_base_state *state;
2195 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2196 if (state == NULL) {
2197 return WERR_NOT_ENOUGH_MEMORY;
2200 state->dce_call = dce_call;
2201 state->mem_ctx = mem_ctx;
2203 state->r.in.logon_server = r->in.logon_server;
2204 state->r.in.function_code = r->in.function_code;
2205 state->r.in.level = r->in.level;
2206 state->r.in.data = NULL;
2207 state->r.out.query = r->out.query;
2211 werr = dcesrv_netr_LogonControl_base_call(state);
2213 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2223 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2224 struct netr_LogonControl2 *r)
2226 struct dcesrv_netr_LogonControl_base_state *state;
2229 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2230 if (state == NULL) {
2231 return WERR_NOT_ENOUGH_MEMORY;
2234 state->dce_call = dce_call;
2235 state->mem_ctx = mem_ctx;
2237 state->r.in.logon_server = r->in.logon_server;
2238 state->r.in.function_code = r->in.function_code;
2239 state->r.in.level = r->in.level;
2240 state->r.in.data = r->in.data;
2241 state->r.out.query = r->out.query;
2245 werr = dcesrv_netr_LogonControl_base_call(state);
2247 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2255 netr_LogonControl2Ex
2257 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2258 struct netr_LogonControl2Ex *r)
2260 struct dcesrv_netr_LogonControl_base_state *state;
2263 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2264 if (state == NULL) {
2265 return WERR_NOT_ENOUGH_MEMORY;
2268 state->dce_call = dce_call;
2269 state->mem_ctx = mem_ctx;
2274 werr = dcesrv_netr_LogonControl_base_call(state);
2276 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2283 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2284 struct ldb_context *sam_ctx,
2285 struct netr_DomainTrustList *trusts,
2286 uint32_t trust_flags);
2291 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2292 struct netr_GetAnyDCName *r)
2294 struct netr_DomainTrustList *trusts;
2295 struct ldb_context *sam_ctx;
2296 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2300 *r->out.dcname = NULL;
2302 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2303 /* if the domainname parameter wasn't set assume our domain */
2304 r->in.domainname = lpcfg_workgroup(lp_ctx);
2307 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2308 if (sam_ctx == NULL) {
2309 return WERR_DS_UNAVAILABLE;
2312 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2313 /* well we asked for a DC of our own domain */
2314 if (samdb_is_pdc(sam_ctx)) {
2315 /* we are the PDC of the specified domain */
2316 return WERR_NO_SUCH_DOMAIN;
2319 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2320 lpcfg_netbios_name(lp_ctx));
2321 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2326 /* Okay, now we have to consider the trusted domains */
2328 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2329 W_ERROR_HAVE_NO_MEMORY(trusts);
2333 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2334 NETR_TRUST_FLAG_INBOUND
2335 | NETR_TRUST_FLAG_OUTBOUND);
2336 W_ERROR_NOT_OK_RETURN(werr);
2338 for (i = 0; i < trusts->count; i++) {
2339 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2340 /* FIXME: Here we need to find a DC for the specified
2341 * trusted domain. */
2343 /* return WERR_OK; */
2344 return WERR_NO_SUCH_DOMAIN;
2348 return WERR_NO_SUCH_DOMAIN;
2355 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2356 struct netr_DatabaseRedo *r)
2358 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2363 netr_NetrEnumerateTrustedDomains
2365 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2366 struct netr_NetrEnumerateTrustedDomains *r)
2368 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2373 netr_LogonGetCapabilities
2375 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2376 struct netr_LogonGetCapabilities *r)
2378 struct netlogon_creds_CredentialState *creds;
2381 switch (r->in.query_level) {
2386 * Until we know the details behind KB5028166
2387 * just return DCERPC_NCA_S_FAULT_INVALID_TAG
2388 * like an unpatched Windows Server.
2393 * There would not be a way to marshall the
2394 * the response. Which would mean our final
2395 * ndr_push would fail an we would return
2396 * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA.
2398 * But it's important to match a Windows server
2399 * especially before KB5028166, see also our bug #15418
2400 * Otherwise Windows client would stop talking to us.
2402 DCESRV_FAULT(DCERPC_NCA_S_FAULT_INVALID_TAG);
2405 status = dcesrv_netr_creds_server_step_check(dce_call,
2407 r->in.computer_name,
2409 r->out.return_authenticator,
2411 if (!NT_STATUS_IS_OK(status)) {
2412 DEBUG(0,(__location__ " Bad credentials - error\n"));
2414 NT_STATUS_NOT_OK_RETURN(status);
2416 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2418 return NT_STATUS_OK;
2423 netr_NETRLOGONSETSERVICEBITS
2425 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2426 struct netr_NETRLOGONSETSERVICEBITS *r)
2428 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2433 netr_LogonGetTrustRid
2435 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2436 struct netr_LogonGetTrustRid *r)
2438 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2443 netr_NETRLOGONCOMPUTESERVERDIGEST
2445 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2446 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2448 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2453 netr_NETRLOGONCOMPUTECLIENTDIGEST
2455 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2456 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2458 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2466 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2467 struct netr_DsRGetSiteName *r)
2469 struct ldb_context *sam_ctx;
2471 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2472 if (sam_ctx == NULL) {
2473 return WERR_DS_UNAVAILABLE;
2477 * We assume to be a DC when we get called over NETLOGON. Hence we
2478 * get our site name always by using "samdb_server_site_name()"
2479 * and not "samdb_client_site_name()".
2481 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2482 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2489 fill in a netr_OneDomainInfo from our own domain/forest
2491 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2492 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2493 struct GUID domain_guid,
2494 struct netr_OneDomainInfo *info,
2499 if (is_trust_list) {
2500 struct netr_trust_extension *te = NULL;
2501 struct netr_trust_extension_info *tei = NULL;
2503 /* w2k8 only fills this on trusted domains */
2504 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2506 return NT_STATUS_NO_MEMORY;
2509 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2512 * We're always within a native forest
2514 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2515 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2517 /* For now we assume we're always the tree root */
2518 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2519 tei->parent_index = 0;
2521 tei->trust_type = our_tdo->trust_type;
2523 * This needs to be 0 instead of our_tdo->trust_attributes
2524 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2525 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2527 tei->trust_attributes = 0;
2529 info->trust_extension.info = te;
2532 if (is_trust_list) {
2533 info->dns_domainname.string = our_tdo->domain_name.string;
2535 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2536 info->dns_forestname.string = NULL;
2538 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2539 our_tdo->domain_name.string);
2540 if (info->dns_domainname.string == NULL) {
2541 return NT_STATUS_NO_MEMORY;
2544 info->dns_forestname.string = info->dns_domainname.string;
2547 info->domainname.string = our_tdo->netbios_name.string;
2548 info->domain_sid = our_tdo->sid;
2549 info->domain_guid = domain_guid;
2551 return NT_STATUS_OK;
2555 fill in a netr_OneDomainInfo from a trust tdo
2557 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2558 struct GUID domain_guid,
2559 const struct lsa_TrustDomainInfoInfoEx *tdo,
2560 struct netr_OneDomainInfo *info)
2562 struct netr_trust_extension *te = NULL;
2563 struct netr_trust_extension_info *tei = NULL;
2567 /* w2k8 only fills this on trusted domains */
2568 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2570 return NT_STATUS_NO_MEMORY;
2574 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2575 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2577 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2578 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2580 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2581 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2585 * TODO: once we support multiple domains within our forest,
2586 * we need to fill this correct (or let the caller do it
2587 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2589 tei->parent_index = 0;
2591 tei->trust_type = tdo->trust_type;
2592 tei->trust_attributes = tdo->trust_attributes;
2594 info->trust_extension.info = te;
2596 info->domainname.string = tdo->netbios_name.string;
2597 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2598 info->dns_domainname.string = tdo->domain_name.string;
2600 info->dns_domainname.string = NULL;
2602 info->domain_sid = tdo->sid;
2603 info->domain_guid = domain_guid;
2605 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2606 info->dns_forestname.string = NULL;
2608 return NT_STATUS_OK;
2612 netr_LogonGetDomainInfo
2613 this is called as part of the ADS domain logon procedure.
2615 It has an important role in convaying details about the client, such
2616 as Operating System, Version, Service Pack etc.
2618 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2619 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2621 struct netlogon_creds_CredentialState *creds;
2622 static const char *const trusts_attrs[] = {"securityIdentifier",
2629 static const char *const attrs2[] = {"sAMAccountName",
2631 "msDS-SupportedEncryptionTypes",
2633 const char *sam_account_name, *old_dns_hostname;
2634 struct ldb_context *sam_ctx;
2635 const struct GUID *our_domain_guid = NULL;
2636 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2637 struct ldb_message **res1, *new_msg;
2638 struct ldb_result *trusts_res = NULL;
2639 struct ldb_dn *workstation_dn;
2640 struct netr_DomainInformation *domain_info;
2641 struct netr_LsaPolicyInformation *lsa_policy_info;
2642 struct auth_session_info *workstation_session_info = NULL;
2643 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2644 bool update_dns_hostname = true;
2648 status = dcesrv_netr_creds_server_step_check(dce_call,
2650 r->in.computer_name,
2652 r->out.return_authenticator,
2654 if (!NT_STATUS_IS_OK(status)) {
2656 char* remote = NULL;
2657 TALLOC_CTX *frame = talloc_stackframe();
2658 remote = tsocket_address_string(dce_call->conn->remote_address,
2660 local = tsocket_address_string(dce_call->conn->local_address,
2662 DBG_ERR("Bad credentials - "
2663 "computer[%s] remote[%s] local[%s]\n",
2664 log_escape(frame, r->in.computer_name),
2669 NT_STATUS_NOT_OK_RETURN(status);
2671 /* We want to avoid connecting as system. */
2672 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2673 if (sam_ctx == NULL) {
2674 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2677 switch (r->in.level) {
2678 case 1: /* Domain information */
2680 if (r->in.query->workstation_info == NULL) {
2681 return NT_STATUS_INVALID_PARAMETER;
2684 /* Prepares the workstation DN */
2685 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2686 dom_sid_string(mem_ctx, creds->sid));
2687 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2689 /* Get the workstation's session info from the database. */
2690 status = authsam_get_session_info_principal(mem_ctx,
2691 dce_call->conn->dce_ctx->lp_ctx,
2693 NULL, /* principal */
2695 0, /* session_info_flags */
2696 &workstation_session_info);
2697 if (!NT_STATUS_IS_OK(status)) {
2702 * Reconnect to samdb as the workstation, now that we have its
2703 * session info. We do this so the database update can be
2704 * attributed to the workstation account in the audit logs --
2705 * otherwise it might be incorrectly attributed to
2708 sam_ctx = dcesrv_samdb_connect_session_info(mem_ctx,
2710 workstation_session_info,
2711 workstation_session_info);
2712 if (sam_ctx == NULL) {
2713 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2716 /* Lookup for attributes in workstation object */
2717 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2720 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2723 /* Gets the sam account name which is checked against the DNS
2724 * hostname parameter. */
2725 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2728 if (sam_account_name == NULL) {
2729 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2732 if (r->in.query->workstation_info->dns_hostname == NULL) {
2733 update_dns_hostname = false;
2736 /* Gets the old DNS hostname */
2737 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2742 * Updates the DNS hostname when the client wishes that the
2743 * server should handle this for him
2744 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
2745 * See MS-NRPC section 3.5.4.3.9
2747 if ((r->in.query->workstation_info->workstation_flags
2748 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2749 update_dns_hostname = false;
2752 /* Gets host information and put them into our directory */
2754 new_msg = ldb_msg_new(mem_ctx);
2755 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2757 new_msg->dn = workstation_dn;
2759 /* Sets the OS name */
2761 if (r->in.query->workstation_info->os_name.string == NULL) {
2762 return NT_STATUS_INVALID_PARAMETER;
2765 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2766 r->in.query->workstation_info->os_name.string);
2767 if (ret != LDB_SUCCESS) {
2768 return NT_STATUS_NO_MEMORY;
2772 * Sets information from "os_version". On an empty structure
2773 * the values are cleared.
2775 if (r->in.query->workstation_info->os_version.os != NULL) {
2776 struct netr_OsVersionInfoEx *os_version;
2777 const char *os_version_str;
2779 os_version = &r->in.query->workstation_info->os_version.os->os;
2781 if (os_version->CSDVersion == NULL) {
2782 return NT_STATUS_INVALID_PARAMETER;
2785 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2786 os_version->MajorVersion,
2787 os_version->MinorVersion,
2788 os_version->BuildNumber);
2789 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2791 if (strlen(os_version->CSDVersion) != 0) {
2792 ret = ldb_msg_add_string(new_msg,
2793 "operatingSystemServicePack",
2794 os_version->CSDVersion);
2796 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2797 "operatingSystemServicePack");
2799 if (ret != LDB_SUCCESS) {
2800 return NT_STATUS_NO_MEMORY;
2803 ret = ldb_msg_add_string(new_msg,
2804 "operatingSystemVersion",
2806 if (ret != LDB_SUCCESS) {
2807 return NT_STATUS_NO_MEMORY;
2810 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2811 "operatingSystemServicePack");
2812 if (ret != LDB_SUCCESS) {
2813 return NT_STATUS_NO_MEMORY;
2816 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2817 "operatingSystemVersion");
2818 if (ret != LDB_SUCCESS) {
2819 return NT_STATUS_NO_MEMORY;
2824 * If the boolean "update_dns_hostname" remained true, then we
2825 * are fine to start the update.
2827 if (update_dns_hostname) {
2828 ret = ldb_msg_add_string(new_msg,
2830 r->in.query->workstation_info->dns_hostname);
2831 if (ret != LDB_SUCCESS) {
2832 return NT_STATUS_NO_MEMORY;
2835 /* This manual "servicePrincipalName" generation is
2836 * still needed! Since the update in the samldb LDB
2837 * module does only work if the entries already exist
2838 * which isn't always the case. */
2839 ret = ldb_msg_add_string(new_msg,
2840 "servicePrincipalName",
2841 talloc_asprintf(new_msg, "HOST/%s",
2842 r->in.computer_name));
2843 if (ret != LDB_SUCCESS) {
2844 return NT_STATUS_NO_MEMORY;
2847 ret = ldb_msg_add_string(new_msg,
2848 "servicePrincipalName",
2849 talloc_asprintf(new_msg, "HOST/%s",
2850 r->in.query->workstation_info->dns_hostname));
2851 if (ret != LDB_SUCCESS) {
2852 return NT_STATUS_NO_MEMORY;
2856 if (dsdb_replace(sam_ctx, new_msg, DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) != LDB_SUCCESS) {
2857 DEBUG(3,("Impossible to update samdb: %s\n",
2858 ldb_errstring(sam_ctx)));
2861 talloc_free(new_msg);
2863 /* Writes back the domain information */
2865 our_domain_guid = samdb_domain_guid(sam_ctx);
2866 if (our_domain_guid == NULL) {
2867 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2870 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2871 if (!NT_STATUS_IS_OK(status)) {
2875 status = dsdb_trust_search_tdos(sam_ctx,
2880 if (!NT_STATUS_IS_OK(status)) {
2884 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2885 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2887 ZERO_STRUCTP(domain_info);
2889 /* Information about the local and trusted domains */
2891 status = fill_our_one_domain_info(mem_ctx,
2894 &domain_info->primary_domain,
2896 if (!NT_STATUS_IS_OK(status)) {
2900 domain_info->trusted_domain_count = trusts_res->count + 1;
2901 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2902 struct netr_OneDomainInfo,
2903 domain_info->trusted_domain_count);
2904 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2906 for (i=0; i < trusts_res->count; i++) {
2907 struct netr_OneDomainInfo *o =
2908 &domain_info->trusted_domains[i];
2909 /* we can't know the guid of trusts outside our forest */
2910 struct GUID trust_domain_guid = GUID_zero();
2911 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2913 status = dsdb_trust_parse_tdo_info(mem_ctx,
2914 trusts_res->msgs[i],
2916 if (!NT_STATUS_IS_OK(status)) {
2920 status = fill_trust_one_domain_info(mem_ctx,
2924 if (!NT_STATUS_IS_OK(status)) {
2929 status = fill_our_one_domain_info(mem_ctx,
2932 &domain_info->trusted_domains[i],
2934 if (!NT_STATUS_IS_OK(status)) {
2938 /* Sets the supported encryption types */
2939 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2940 "msDS-SupportedEncryptionTypes",
2941 default_supported_enc_types);
2943 /* Other host domain information */
2945 lsa_policy_info = talloc(mem_ctx,
2946 struct netr_LsaPolicyInformation);
2947 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2948 ZERO_STRUCTP(lsa_policy_info);
2950 domain_info->lsa_policy = *lsa_policy_info;
2952 /* The DNS hostname is only returned back when there is a chance
2954 if ((r->in.query->workstation_info->workstation_flags
2955 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2956 domain_info->dns_hostname.string = old_dns_hostname;
2958 domain_info->dns_hostname.string = NULL;
2961 domain_info->workstation_flags =
2962 r->in.query->workstation_info->workstation_flags & (
2963 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2965 r->out.info->domain_info = domain_info;
2967 case 2: /* LSA policy information - not used at the moment */
2968 lsa_policy_info = talloc(mem_ctx,
2969 struct netr_LsaPolicyInformation);
2970 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2971 ZERO_STRUCTP(lsa_policy_info);
2973 r->out.info->lsa_policy_info = lsa_policy_info;
2976 return NT_STATUS_INVALID_LEVEL;
2980 return NT_STATUS_OK;
2985 netr_ServerPasswordGet
2987 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2988 struct netr_ServerPasswordGet *r)
2990 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2993 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2994 TALLOC_CTX *mem_ctx,
2995 struct dom_sid *user_sid,
2996 struct ldb_dn *obj_dn)
2998 static const char *rodc_attrs[] = {"msDS-NeverRevealGroup",
2999 "msDS-RevealOnDemandGroup",
3000 "userAccountControl",
3002 static const char *obj_attrs[] = {"tokenGroups",
3004 "UserAccountControl",
3005 "msDS-KrbTgtLinkBL",
3007 struct ldb_dn *rodc_dn;
3009 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
3012 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
3013 dom_sid_string(mem_ctx, user_sid));
3014 if (!ldb_dn_validate(rodc_dn)) goto denied;
3017 * do the two searches we need
3018 * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list
3019 * out of the extended DNs
3021 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
3022 DSDB_SEARCH_SHOW_EXTENDED_DN);
3023 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
3025 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
3026 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
3028 werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx,
3033 if (W_ERROR_IS_OK(werr)) {
3044 netr_NetrLogonSendToSam
3046 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3047 struct netr_NetrLogonSendToSam *r)
3049 struct netlogon_creds_CredentialState *creds;
3050 struct ldb_context *sam_ctx;
3052 DATA_BLOB decrypted_blob;
3053 enum ndr_err_code ndr_err;
3054 struct netr_SendToSamBase base_msg = { 0 };
3056 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3058 r->in.computer_name,
3060 r->out.return_authenticator,
3063 NT_STATUS_NOT_OK_RETURN(nt_status);
3065 switch (creds->secure_channel_type) {
3069 case SEC_CHAN_WKSTA:
3070 case SEC_CHAN_DNS_DOMAIN:
3071 case SEC_CHAN_DOMAIN:
3073 return NT_STATUS_INVALID_PARAMETER;
3075 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
3076 creds->secure_channel_type));
3077 return NT_STATUS_INVALID_PARAMETER;
3080 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3081 if (sam_ctx == NULL) {
3082 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3085 /* Buffer is meant to be 16-bit aligned */
3086 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3087 nt_status = netlogon_creds_aes_decrypt(creds,
3088 r->in.opaque_buffer,
3091 nt_status = netlogon_creds_arcfour_crypt(creds,
3092 r->in.opaque_buffer,
3095 if (!NT_STATUS_IS_OK(nt_status)) {
3099 decrypted_blob.data = r->in.opaque_buffer;
3100 decrypted_blob.length = r->in.buffer_len;
3102 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
3103 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
3105 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3106 /* We only partially implement SendToSam */
3107 return NT_STATUS_NOT_IMPLEMENTED;
3109 NDR_PRINT_DEBUG(netr_SendToSamBase, &base_msg);
3111 /* Now 'send' to SAM */
3112 switch (base_msg.message_type) {
3113 case SendToSamResetBadPasswordCount:
3115 struct ldb_message *msg = ldb_msg_new(mem_ctx);
3116 struct ldb_dn *dn = NULL;
3120 ret = ldb_transaction_start(sam_ctx);
3121 if (ret != LDB_SUCCESS) {
3122 return NT_STATUS_INTERNAL_ERROR;
3125 ret = dsdb_find_dn_by_guid(sam_ctx,
3127 &base_msg.message.reset_bad_password.guid,
3130 if (ret != LDB_SUCCESS) {
3131 ldb_transaction_cancel(sam_ctx);
3132 return NT_STATUS_INVALID_PARAMETER;
3135 if (creds->secure_channel_type == SEC_CHAN_RODC &&
3136 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
3137 DEBUG(1, ("Client asked to reset bad password on "
3138 "an arbitrary user: %s\n",
3139 ldb_dn_get_linearized(dn)));
3140 ldb_transaction_cancel(sam_ctx);
3141 return NT_STATUS_INVALID_PARAMETER;
3144 DBG_ERR("Reset bad password on user: %s\n",
3145 ldb_dn_get_linearized(dn));
3149 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
3150 if (ret != LDB_SUCCESS) {
3151 ldb_transaction_cancel(sam_ctx);
3152 return NT_STATUS_INVALID_PARAMETER;
3155 ret = dsdb_replace(sam_ctx, msg, 0);
3156 if (ret != LDB_SUCCESS) {
3157 ldb_transaction_cancel(sam_ctx);
3158 return NT_STATUS_INVALID_PARAMETER;
3161 ret = ldb_transaction_commit(sam_ctx);
3162 if (ret != LDB_SUCCESS) {
3163 ldb_transaction_cancel(sam_ctx);
3164 return NT_STATUS_INTERNAL_ERROR;
3167 DBG_ERR("Committed bad password reset on user: %s\n",
3168 ldb_dn_get_linearized(dn));
3172 return NT_STATUS_NOT_IMPLEMENTED;
3175 return NT_STATUS_OK;
3178 struct dcesrv_netr_DsRGetDCName_base_state {
3179 struct dcesrv_call_state *dce_call;
3180 TALLOC_CTX *mem_ctx;
3182 struct netr_DsRGetDCNameEx2 r;
3183 const char *client_site;
3186 struct netr_DsRGetDCName *dc;
3187 struct netr_DsRGetDCNameEx *dcex;
3188 struct netr_DsRGetDCNameEx2 *dcex2;
3192 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
3194 /* Returns a nonzero value if multiple bits in 'val' are set. */
3195 static bool multiple_bits_set(uint32_t val)
3198 * Subtracting one from an integer has the effect of flipping all the
3199 * bits from the least significant bit up to and including the least
3200 * significant '1' bit. For example,
3206 * If 'val' is zero, all the bits will be flipped and thus the bitwise
3207 * AND of 'val' with 'val - 1' will be zero.
3209 * If the integer is nonzero, the least significant '1' bit will be
3210 * ANDed with a '0' bit and so will be reset in the final result, but
3211 * all other '1' bits will remain set. In other words, the effect of
3212 * this expression is to mask off the least significant bit that is
3213 * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
3214 * must contain multiple set bits.
3216 return val & (val - 1);
3219 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
3221 struct dcesrv_call_state *dce_call = state->dce_call;
3222 struct imessaging_context *imsg_ctx =
3223 dcesrv_imessaging_context(dce_call->conn);
3224 TALLOC_CTX *mem_ctx = state->mem_ctx;
3225 struct netr_DsRGetDCNameEx2 *r = &state->r;
3226 struct ldb_context *sam_ctx;
3227 struct netr_DsRGetDCNameInfo *info;
3228 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3229 const struct tsocket_address *local_address;
3230 char *local_addr = NULL;
3231 const struct tsocket_address *remote_address;
3232 char *remote_addr = NULL;
3233 const char *server_site_name;
3235 struct netlogon_samlogon_response response;
3237 const char *dc_name = NULL;
3238 const char *domain_name = NULL;
3240 bool different_domain = true;
3241 bool force_remote_lookup = false;
3242 uint32_t valid_flags;
3243 uint32_t this_dc_valid_flags;
3246 ZERO_STRUCTP(r->out.info);
3248 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3249 if (sam_ctx == NULL) {
3250 return WERR_DS_UNAVAILABLE;
3253 local_address = dcesrv_connection_get_local_address(dce_call->conn);
3254 if (tsocket_address_is_inet(local_address, "ip")) {
3255 local_addr = tsocket_address_inet_addr_string(local_address, state);
3256 W_ERROR_HAVE_NO_MEMORY(local_addr);
3259 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
3260 if (tsocket_address_is_inet(remote_address, "ip")) {
3261 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
3262 W_ERROR_HAVE_NO_MEMORY(remote_addr);
3265 /* "server_unc" is ignored by w2k3 */
3268 * With the following flags:
3269 * DS_FORCE_REDISCOVERY (Flag A)
3270 * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
3271 * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
3272 * DS_GC_SERVER_REQUIRED (Flag D)
3273 * DS_PDC_REQUIRED (Flag E)
3274 * DS_BACKGROUND_ONLY (Flag F)
3275 * DS_IP_REQUIRED (Flag G)
3276 * DS_KDC_REQUIRED (Flag H)
3277 * DS_TIMESERV_REQUIRED (Flag I)
3278 * DS_WRITABLE_REQUIRED (Flag J)
3279 * DS_GOOD_TIMESERV_PREFERRED (Flag K)
3280 * DS_AVOID_SELF (Flag L)
3281 * DS_ONLY_LDAP_NEEDED (Flag M)
3282 * DS_IS_FLAT_NAME (Flag N)
3283 * DS_IS_DNS_NAME (Flag O)
3284 * DS_TRY_NEXTCLOSEST_SITE (Flag P)
3285 * DS_DIRECTORY_SERVICE_6_REQUIRED (Flag Q)
3286 * DS_WEB_SERVICE_REQUIRED (Flag T)
3287 * DS_DIRECTORY_SERVICE_8_REQUIRED (Flag U)
3288 * DS_DIRECTORY_SERVICE_9_REQUIRED (Flag V)
3289 * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
3290 * DS_RETURN_DNS_NAME (Flag R)
3291 * DS_RETURN_FLAT_NAME (Flag S)
3293 * MS-NRPC 3.5.4.3.1 says:
3295 * On receiving this call, the server MUST perform the following Flags
3296 * parameter validations:
3297 * - Flags D, E, and H MUST NOT be combined with each other.
3298 * - Flag N MUST NOT be combined with the O flag.
3299 * - Flag R MUST NOT be combined with the S flag.
3300 * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
3301 * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or H.
3302 * - Flag P MUST NOT be set when the SiteName parameter is provided.
3303 * The server MUST return ERROR_INVALID_FLAGS for any of the previously
3304 * mentioned conflicting combinations.
3308 valid_flags = DSGETDC_VALID_FLAGS;
3310 if (r->in.flags & ~valid_flags) {
3312 * TODO: add tests to prove this (maybe based on the
3313 * msDS-Behavior-Version levels of dc, domain and/or forest
3315 return WERR_INVALID_FLAGS;
3318 /* Flags D, E, and H MUST NOT be combined with each other. */
3319 #define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
3320 if (multiple_bits_set(r->in.flags & _DEH)) {
3321 return WERR_INVALID_FLAGS;
3324 /* Flag N MUST NOT be combined with the O flag. */
3325 if (r->in.flags & DS_IS_FLAT_NAME &&
3326 r->in.flags & DS_IS_DNS_NAME) {
3327 return WERR_INVALID_FLAGS;
3330 /* Flag R MUST NOT be combined with the S flag. */
3331 if (r->in.flags & DS_RETURN_DNS_NAME &&
3332 r->in.flags & DS_RETURN_FLAT_NAME) {
3333 return WERR_INVALID_FLAGS;
3336 /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
3338 DS_DIRECTORY_SERVICE_REQUIRED | \
3339 DS_DIRECTORY_SERVICE_6_REQUIRED | \
3340 DS_DIRECTORY_SERVICE_8_REQUIRED | \
3341 DS_DIRECTORY_SERVICE_9_REQUIRED | \
3342 DS_DIRECTORY_SERVICE_10_REQUIRED | \
3344 if (multiple_bits_set(r->in.flags & _BQUVW)) {
3345 return WERR_INVALID_FLAGS;
3349 * Flag K MUST NOT be combined with any of the flags:
3352 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
3354 (DS_DIRECTORY_SERVICE_REQUIRED |
3355 DS_DIRECTORY_SERVICE_PREFERRED |
3356 DS_GC_SERVER_REQUIRED |
3359 return WERR_INVALID_FLAGS;
3362 /* Flag P MUST NOT be set when the SiteName parameter is provided. */
3363 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
3365 return WERR_INVALID_FLAGS;
3369 * If we send an all-zero GUID, we should ignore it as winbind actually
3370 * checks it with a DNS query. Windows also appears to ignore it.
3372 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
3373 r->in.domain_guid = NULL;
3376 /* Attempt winbind search only if we suspect the domain is incorrect */
3377 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
3378 if (r->in.flags & DS_IS_FLAT_NAME) {
3379 if (strcasecmp_m(r->in.domain_name,
3380 lpcfg_sam_name(lp_ctx)) == 0) {
3381 different_domain = false;
3383 } else if (r->in.flags & DS_IS_DNS_NAME) {
3384 if (strcasecmp_m(r->in.domain_name,
3385 lpcfg_dnsdomain(lp_ctx)) == 0) {
3386 different_domain = false;
3389 if (strcasecmp_m(r->in.domain_name,
3390 lpcfg_sam_name(lp_ctx)) == 0 ||
3391 strcasecmp_m(r->in.domain_name,
3392 lpcfg_dnsdomain(lp_ctx)) == 0) {
3393 different_domain = false;
3398 * We need to be able to handle empty domain names, where we
3399 * revert to our domain by default.
3401 different_domain = false;
3404 if (!different_domain) {
3405 dc_level = dsdb_dc_functional_level(sam_ctx);
3408 * Do not return a local response if we do not support the
3409 * functional level or feature (eg web services)
3411 this_dc_valid_flags = valid_flags;
3413 /* Samba does not implement this */
3414 this_dc_valid_flags &= ~DS_WEB_SERVICE_REQUIRED;
3416 if (dc_level < DS_DOMAIN_FUNCTION_2012) {
3417 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_8_REQUIRED;
3419 if (dc_level < DS_DOMAIN_FUNCTION_2012_R2) {
3420 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_9_REQUIRED;
3422 if (dc_level < DS_DOMAIN_FUNCTION_2016) {
3423 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_10_REQUIRED;
3425 if (r->in.flags & ~this_dc_valid_flags) {
3426 DBG_INFO("Forcing remote lookup to find another DC "
3427 "in this domain %s with more features, "
3428 "as this Samba DC is Functional level %d but flags are 0x08%x\n",
3429 r->in.domain_name, dc_level, (unsigned int)r->in.flags);
3430 force_remote_lookup = true;
3434 /* Proof server site parameter "site_name" if it was specified */
3435 server_site_name = samdb_server_site_name(sam_ctx, state);
3436 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3437 if (force_remote_lookup
3439 || (r->in.site_name != NULL &&
3440 (strcasecmp_m(r->in.site_name,
3441 server_site_name) != 0))) {
3443 struct dcerpc_binding_handle *irpc_handle = NULL;
3444 struct tevent_req *subreq = NULL;
3447 * Retrieve the client site to override the winbind response.
3449 * DO NOT use Windows fallback for client site.
3450 * In the case of multiple domains, this is plainly wrong.
3452 * Note: It's possible that the client may belong to multiple
3453 * subnets across domains. It's not clear what this would mean,
3454 * but here we only return what this domain knows.
3456 state->client_site = samdb_client_site_name(sam_ctx,
3462 irpc_handle = irpc_binding_handle_by_name(state,
3465 &ndr_table_winbind);
3466 if (irpc_handle == NULL) {
3467 DEBUG(0,("Failed to get binding_handle for "
3468 "winbind_server task\n"));
3469 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3470 return WERR_SERVICE_NOT_FOUND;
3473 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3475 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3477 subreq = dcerpc_wbint_DsGetDcName_send(state,
3478 dce_call->event_ctx,
3485 if (subreq == NULL) {
3486 return WERR_NOT_ENOUGH_MEMORY;
3489 tevent_req_set_callback(subreq,
3490 dcesrv_netr_DsRGetDCName_base_done,
3496 guid_str = r->in.domain_guid != NULL ?
3497 GUID_string(state, r->in.domain_guid) : NULL;
3499 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3503 r->in.client_account,
3504 r->in.mask, remote_addr,
3505 NETLOGON_NT_VERSION_5EX_WITH_IP,
3506 lp_ctx, &response, true);
3507 if (!NT_STATUS_IS_OK(status)) {
3508 return ntstatus_to_werror(status);
3512 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3513 * (O) flag when the returned forest name is in DNS format. This is here
3514 * always the case (see below).
3516 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3518 if (r->in.flags & DS_RETURN_DNS_NAME) {
3519 dc_name = response.data.nt5_ex.pdc_dns_name;
3520 domain_name = response.data.nt5_ex.dns_domain;
3522 * According to MS-NRPC 2.2.1.2.1 we should set the
3523 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3524 * the returned information is in DNS form.
3526 response.data.nt5_ex.server_type |=
3527 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3528 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3529 dc_name = response.data.nt5_ex.pdc_name;
3530 domain_name = response.data.nt5_ex.domain_name;
3534 * TODO: autodetect what we need to return
3535 * based on the given arguments
3537 dc_name = response.data.nt5_ex.pdc_name;
3538 domain_name = response.data.nt5_ex.domain_name;
3541 if (!dc_name || !dc_name[0]) {
3542 return WERR_NO_SUCH_DOMAIN;
3545 if (!domain_name || !domain_name[0]) {
3546 return WERR_NO_SUCH_DOMAIN;
3549 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3550 W_ERROR_HAVE_NO_MEMORY(info);
3551 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3552 dc_name[0] != '\\'? "\\\\":"",
3553 talloc_strdup(mem_ctx, dc_name));
3554 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3556 pdc_ip = local_addr;
3557 if (pdc_ip == NULL) {
3558 pdc_ip = "127.0.0.1";
3560 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3561 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3562 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3563 info->domain_guid = response.data.nt5_ex.domain_uuid;
3564 info->domain_name = domain_name;
3565 info->forest_name = response.data.nt5_ex.forest;
3566 info->dc_flags = response.data.nt5_ex.server_type;
3567 if (r->in.flags & DS_RETURN_DNS_NAME) {
3568 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3569 * returned if we are returning info->dc_unc containing a FQDN.
3570 * This attribute is called DomainControllerName in the specs,
3571 * it seems that we decide to return FQDN or netbios depending on
3572 * DS_RETURN_DNS_NAME.
3574 info->dc_flags |= DS_DNS_CONTROLLER;
3576 info->dc_site_name = response.data.nt5_ex.server_site;
3577 info->client_site_name = response.data.nt5_ex.client_site;
3579 *r->out.info = info;
3584 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3586 struct dcesrv_netr_DsRGetDCName_base_state *state =
3587 tevent_req_callback_data(subreq,
3588 struct dcesrv_netr_DsRGetDCName_base_state);
3589 struct dcesrv_call_state *dce_call = state->dce_call;
3590 NTSTATUS result, status;
3592 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3595 TALLOC_FREE(subreq);
3597 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3598 state->r.out.result = WERR_TIMEOUT;
3602 if (!NT_STATUS_IS_OK(status)) {
3603 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3605 state->r.out.result = WERR_GEN_FAILURE;
3609 if (!NT_STATUS_IS_OK(result)) {
3610 DBG_NOTICE("DC location via winbind failed - %s\n",
3612 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3616 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3617 DBG_ERR("DC location via winbind returned no results\n");
3618 state->r.out.result = WERR_GEN_FAILURE;
3622 if (state->r.out.info[0]->dc_unc == NULL) {
3623 DBG_ERR("DC location via winbind returned no DC unc\n");
3624 state->r.out.result = WERR_GEN_FAILURE;
3629 * Either the supplied site name is NULL (possibly via
3630 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3631 * the input match name.
3633 * TODO: Currently this means that requests with NETBIOS domain
3634 * names can fail because they do not return the site name.
3636 if (state->r.in.site_name == NULL ||
3637 strcasecmp_m("", state->r.in.site_name) == 0 ||
3638 (state->r.out.info[0]->dc_site_name != NULL &&
3639 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3640 state->r.in.site_name) == 0)) {
3642 state->r.out.info[0]->client_site_name =
3643 talloc_move(state->mem_ctx, &state->client_site);
3646 * Make sure to return our DC UNC with // prefix.
3647 * Winbind currently doesn't send the leading slashes
3650 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3651 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3652 const char *dc_unc = NULL;
3654 dc_unc = talloc_asprintf(state->mem_ctx,
3656 state->r.out.info[0]->dc_unc);
3657 state->r.out.info[0]->dc_unc = dc_unc;
3660 state->r.out.result = WERR_OK;
3662 state->r.out.info = NULL;
3663 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3667 if (state->_r.dcex2 != NULL) {
3668 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3669 r->out.result = state->r.out.result;
3670 } else if (state->_r.dcex != NULL) {
3671 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3672 r->out.result = state->r.out.result;
3673 } else if (state->_r.dc != NULL) {
3674 struct netr_DsRGetDCName *r = state->_r.dc;
3675 r->out.result = state->r.out.result;
3679 dcesrv_async_reply(dce_call);
3683 netr_DsRGetDCNameEx2
3685 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3686 TALLOC_CTX *mem_ctx,
3687 struct netr_DsRGetDCNameEx2 *r)
3689 struct dcesrv_netr_DsRGetDCName_base_state *state;
3691 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3692 if (state == NULL) {
3693 return WERR_NOT_ENOUGH_MEMORY;
3696 state->dce_call = dce_call;
3697 state->mem_ctx = mem_ctx;
3700 state->_r.dcex2 = r;
3702 return dcesrv_netr_DsRGetDCName_base_call(state);
3708 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3709 struct netr_DsRGetDCNameEx *r)
3711 struct dcesrv_netr_DsRGetDCName_base_state *state;
3713 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3714 if (state == NULL) {
3715 return WERR_NOT_ENOUGH_MEMORY;
3718 state->dce_call = dce_call;
3719 state->mem_ctx = mem_ctx;
3721 state->r.in.server_unc = r->in.server_unc;
3722 state->r.in.client_account = NULL;
3723 state->r.in.mask = 0;
3724 state->r.in.domain_guid = r->in.domain_guid;
3725 state->r.in.domain_name = r->in.domain_name;
3726 state->r.in.site_name = r->in.site_name;
3727 state->r.in.flags = r->in.flags;
3728 state->r.out.info = r->out.info;
3732 return dcesrv_netr_DsRGetDCName_base_call(state);
3738 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3739 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3740 * insists that it be ignored.
3742 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3743 struct netr_DsRGetDCName *r)
3745 struct dcesrv_netr_DsRGetDCName_base_state *state;
3747 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3748 if (state == NULL) {
3749 return WERR_NOT_ENOUGH_MEMORY;
3752 state->dce_call = dce_call;
3753 state->mem_ctx = mem_ctx;
3755 state->r.in.server_unc = r->in.server_unc;
3756 state->r.in.client_account = NULL;
3757 state->r.in.mask = 0;
3758 state->r.in.domain_name = r->in.domain_name;
3759 state->r.in.domain_guid = r->in.domain_guid;
3761 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3762 state->r.in.flags = r->in.flags;
3763 state->r.out.info = r->out.info;
3767 return dcesrv_netr_DsRGetDCName_base_call(state);
3770 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3772 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3773 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3775 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3780 netr_NetrEnumerateTrustedDomainsEx
3782 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3783 struct netr_NetrEnumerateTrustedDomainsEx *r)
3785 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3790 netr_DsRAddressToSitenamesExW
3792 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3793 struct netr_DsRAddressToSitenamesExW *r)
3795 struct ldb_context *sam_ctx;
3796 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3797 sa_family_t sin_family;
3798 struct sockaddr_in *addr;
3800 struct sockaddr_in6 *addr6;
3801 char addr_str[INET6_ADDRSTRLEN];
3803 char addr_str[INET_ADDRSTRLEN];
3809 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3810 if (sam_ctx == NULL) {
3811 return WERR_DS_UNAVAILABLE;
3814 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3815 W_ERROR_HAVE_NO_MEMORY(ctr);
3819 ctr->count = r->in.count;
3820 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3821 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3822 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3823 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3825 for (i=0; i<ctr->count; i++) {
3826 ctr->sitename[i].string = NULL;
3827 ctr->subnetname[i].string = NULL;
3829 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3832 /* The first two byte of the buffer are reserved for the
3833 * "sin_family" but for now only the first one is used. */
3834 sin_family = r->in.addresses[i].buffer[0];
3836 switch (sin_family) {
3838 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3841 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3842 res = inet_ntop(AF_INET, &addr->sin_addr,
3843 addr_str, sizeof(addr_str));
3847 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3850 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3851 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3852 addr_str, sizeof(addr_str));
3863 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3868 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3869 ctr->subnetname[i].string = subnet_name;
3877 netr_DsRAddressToSitenamesW
3879 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3880 struct netr_DsRAddressToSitenamesW *r)
3882 struct netr_DsRAddressToSitenamesExW r2;
3883 struct netr_DsRAddressToSitenamesWCtr *ctr;
3889 r2.in.server_name = r->in.server_name;
3890 r2.in.count = r->in.count;
3891 r2.in.addresses = r->in.addresses;
3893 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3894 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3896 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3897 W_ERROR_HAVE_NO_MEMORY(ctr);
3901 ctr->count = r->in.count;
3902 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3903 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3905 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3907 for (i=0; i<ctr->count; i++) {
3908 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3916 netr_DsrGetDcSiteCoverageW
3918 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3919 struct netr_DsrGetDcSiteCoverageW *r)
3921 struct ldb_context *sam_ctx;
3922 struct DcSitesCtr *ctr;
3924 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3925 if (sam_ctx == NULL) {
3926 return WERR_DS_UNAVAILABLE;
3929 ctr = talloc(mem_ctx, struct DcSitesCtr);
3930 W_ERROR_HAVE_NO_MEMORY(ctr);
3934 /* For now only return our default site */
3936 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3937 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3938 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3939 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3945 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3946 struct ldb_context *sam_ctx,
3947 struct netr_DomainTrustList *trusts,
3948 uint32_t trust_flags)
3950 struct ldb_dn *system_dn;
3951 struct ldb_message **dom_res = NULL;
3952 static const char *trust_attrs[] = {"flatname",
3954 "securityIdentifier",
3963 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3964 NETR_TRUST_FLAG_OUTBOUND))) {
3965 return WERR_INVALID_FLAGS;
3968 system_dn = samdb_system_container_dn(sam_ctx, mem_ctx);
3969 if (system_dn == NULL) {
3970 return WERR_NOT_ENOUGH_MEMORY;
3973 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3974 &dom_res, trust_attrs,
3975 "(objectclass=trustedDomain)");
3977 for (i = 0; i < ret; i++) {
3978 unsigned int trust_dir;
3981 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3982 "trustDirection", 0);
3984 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3985 flags |= NETR_TRUST_FLAG_INBOUND;
3987 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3988 flags |= NETR_TRUST_FLAG_OUTBOUND;
3991 if (!(flags & trust_flags)) {
3992 /* this trust direction was not requested */
3997 trusts->array = talloc_realloc(trusts, trusts->array,
3998 struct netr_DomainTrust,
4000 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4002 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
4003 if (!trusts->array[n].netbios_name) {
4004 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
4005 "without flatname\n",
4006 ldb_dn_get_linearized(dom_res[i]->dn)));
4009 trusts->array[n].trust_flags = flags;
4010 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
4011 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
4012 /* TODO: find if we have parent in the list */
4013 trusts->array[n].parent_index = 0;
4016 trusts->array[n].trust_type =
4017 ldb_msg_find_attr_as_uint(dom_res[i],
4019 trusts->array[n].trust_attributes =
4020 ldb_msg_find_attr_as_uint(dom_res[i],
4021 "trustAttributes", 0);
4023 if (trusts->array[n].trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
4024 trusts->array[n].dns_name = talloc_steal(
4026 ldb_msg_find_attr_as_string(dom_res[i],
4030 trusts->array[n].dns_name = NULL;
4033 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
4034 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
4035 struct dom_sid zero_sid;
4036 ZERO_STRUCT(zero_sid);
4037 trusts->array[n].sid =
4038 dom_sid_dup(trusts, &zero_sid);
4040 trusts->array[n].sid =
4041 samdb_result_dom_sid(trusts, dom_res[i],
4042 "securityIdentifier");
4044 trusts->array[n].guid = GUID_zero();
4046 trusts->count = n + 1;
4049 talloc_free(dom_res);
4054 netr_DsrEnumerateDomainTrusts
4056 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
4057 TALLOC_CTX *mem_ctx,
4058 struct netr_DsrEnumerateDomainTrusts *r)
4060 struct netr_DomainTrustList *trusts;
4061 struct ldb_context *sam_ctx;
4063 struct ldb_message **dom_res;
4064 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
4065 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4066 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
4070 if (r->in.trust_flags & 0xFFFFFE00) {
4071 return WERR_INVALID_FLAGS;
4074 /* TODO: turn to hard check once we are sure this is 100% correct */
4075 if (!r->in.server_name) {
4076 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
4077 "But received NULL!\n", dnsdomain));
4079 p = strchr(r->in.server_name, '.');
4081 DEBUG(3, ("Invalid domain! Expected name in domain "
4082 "[%s]. But received [%s]!\n",
4083 dnsdomain, r->in.server_name));
4084 p = r->in.server_name;
4088 if (strcasecmp(p, dnsdomain)) {
4089 DEBUG(3, ("Invalid domain! Expected name in domain "
4090 "[%s]. But received [%s]!\n",
4091 dnsdomain, r->in.server_name));
4095 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
4096 W_ERROR_HAVE_NO_MEMORY(trusts);
4099 r->out.trusts = trusts;
4101 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4102 if (sam_ctx == NULL) {
4103 return WERR_GEN_FAILURE;
4106 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
4107 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
4109 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
4110 trusts, r->in.trust_flags);
4111 W_ERROR_NOT_OK_RETURN(werr);
4114 /* NOTE: we currently are always the root of the forest */
4115 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
4116 uint32_t n = trusts->count;
4118 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
4119 &dom_res, dom_attrs);
4121 return WERR_GEN_FAILURE;
4124 trusts->count = n + 1;
4125 trusts->array = talloc_realloc(trusts, trusts->array,
4126 struct netr_DomainTrust,
4128 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4130 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
4131 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
4132 trusts->array[n].trust_flags =
4133 NETR_TRUST_FLAG_NATIVE |
4134 NETR_TRUST_FLAG_TREEROOT |
4135 NETR_TRUST_FLAG_IN_FOREST |
4136 NETR_TRUST_FLAG_PRIMARY;
4137 /* we are always the root domain for now */
4138 trusts->array[n].parent_index = 0;
4139 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
4140 trusts->array[n].trust_attributes = 0;
4141 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
4144 trusts->array[n].guid = samdb_result_guid(dom_res[0],
4146 talloc_free(dom_res);
4154 netr_DsrDeregisterDNSHostRecords
4156 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4157 struct netr_DsrDeregisterDNSHostRecords *r)
4159 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4163 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4164 struct netr_ServerGetTrustInfo *r);
4167 netr_ServerTrustPasswordsGet
4169 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4170 struct netr_ServerTrustPasswordsGet *r)
4172 struct netr_ServerGetTrustInfo r2 = {};
4173 struct netr_TrustInfo *_ti = NULL;
4176 r2.in.server_name = r->in.server_name;
4177 r2.in.account_name = r->in.account_name;
4178 r2.in.secure_channel_type = r->in.secure_channel_type;
4179 r2.in.computer_name = r->in.computer_name;
4180 r2.in.credential = r->in.credential;
4182 r2.out.return_authenticator = r->out.return_authenticator;
4183 r2.out.new_owf_password = r->out.new_owf_password;
4184 r2.out.old_owf_password = r->out.old_owf_password;
4185 r2.out.trust_info = &_ti;
4187 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
4189 r->out.return_authenticator = r2.out.return_authenticator;
4190 r->out.new_owf_password = r2.out.new_owf_password;
4191 r->out.old_owf_password = r2.out.old_owf_password;
4197 netr_DsRGetForestTrustInformation
4199 struct dcesrv_netr_DsRGetForestTrustInformation_state {
4200 struct dcesrv_call_state *dce_call;
4201 TALLOC_CTX *mem_ctx;
4202 struct netr_DsRGetForestTrustInformation *r;
4205 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
4207 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
4208 TALLOC_CTX *mem_ctx,
4209 struct netr_DsRGetForestTrustInformation *r)
4211 struct auth_session_info *session_info =
4212 dcesrv_call_session_info(dce_call);
4213 struct imessaging_context *imsg_ctx =
4214 dcesrv_imessaging_context(dce_call->conn);
4215 enum security_user_level security_level;
4216 struct ldb_context *sam_ctx = NULL;
4217 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
4218 struct dcerpc_binding_handle *irpc_handle = NULL;
4219 struct tevent_req *subreq = NULL;
4220 struct ldb_dn *domain_dn = NULL;
4221 struct ldb_dn *forest_dn = NULL;
4225 security_level = security_session_user_level(session_info, NULL);
4226 if (security_level < SECURITY_USER) {
4227 return WERR_ACCESS_DENIED;
4230 if (r->in.flags & 0xFFFFFFFE) {
4231 return WERR_INVALID_FLAGS;
4234 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4235 if (sam_ctx == NULL) {
4236 return WERR_GEN_FAILURE;
4239 domain_dn = ldb_get_default_basedn(sam_ctx);
4240 if (domain_dn == NULL) {
4241 return WERR_GEN_FAILURE;
4244 forest_dn = ldb_get_root_basedn(sam_ctx);
4245 if (forest_dn == NULL) {
4246 return WERR_GEN_FAILURE;
4249 cmp = ldb_dn_compare(domain_dn, forest_dn);
4251 return WERR_NERR_ACFNOTLOADED;
4254 forest_level = dsdb_forest_functional_level(sam_ctx);
4255 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4256 return WERR_INVALID_FUNCTION;
4259 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
4260 if (!samdb_is_pdc(sam_ctx)) {
4261 return WERR_NERR_NOTPRIMARY;
4264 if (r->in.trusted_domain_name == NULL) {
4265 return WERR_INVALID_FLAGS;
4269 if (r->in.trusted_domain_name == NULL) {
4273 * information about our own domain
4275 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4276 r->out.forest_trust_info);
4277 if (!NT_STATUS_IS_OK(status)) {
4278 return ntstatus_to_werror(status);
4285 * Forward the request to winbindd
4288 state = talloc_zero(mem_ctx,
4289 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4290 if (state == NULL) {
4291 return WERR_NOT_ENOUGH_MEMORY;
4293 state->dce_call = dce_call;
4294 state->mem_ctx = mem_ctx;
4297 irpc_handle = irpc_binding_handle_by_name(state,
4300 &ndr_table_winbind);
4301 if (irpc_handle == NULL) {
4302 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
4303 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4304 return WERR_SERVICE_NOT_FOUND;
4308 * 60 seconds timeout should be enough
4310 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
4312 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
4313 state->dce_call->event_ctx,
4315 r->in.trusted_domain_name,
4317 r->out.forest_trust_info);
4318 if (subreq == NULL) {
4319 return WERR_NOT_ENOUGH_MEMORY;
4321 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4322 tevent_req_set_callback(subreq,
4323 dcesrv_netr_DsRGetForestTrustInformation_done,
4329 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
4331 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
4332 tevent_req_callback_data(subreq,
4333 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4336 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
4338 &state->r->out.result);
4339 TALLOC_FREE(subreq);
4340 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
4341 state->r->out.result = WERR_TIMEOUT;
4342 } else if (!NT_STATUS_IS_OK(status)) {
4343 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4344 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
4345 nt_errstr(status)));
4348 dcesrv_async_reply(state->dce_call);
4352 netr_GetForestTrustInformation
4354 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
4355 TALLOC_CTX *mem_ctx,
4356 struct netr_GetForestTrustInformation *r)
4358 struct netlogon_creds_CredentialState *creds = NULL;
4359 struct ldb_context *sam_ctx = NULL;
4360 struct ldb_dn *domain_dn = NULL;
4361 struct ldb_dn *forest_dn = NULL;
4366 status = dcesrv_netr_creds_server_step_check(dce_call,
4368 r->in.computer_name,
4370 r->out.return_authenticator,
4372 if (!NT_STATUS_IS_OK(status)) {
4376 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
4377 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
4378 return NT_STATUS_NOT_IMPLEMENTED;
4381 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4382 if (sam_ctx == NULL) {
4383 return NT_STATUS_INTERNAL_ERROR;
4386 /* TODO: check r->in.server_name is our name */
4388 domain_dn = ldb_get_default_basedn(sam_ctx);
4389 if (domain_dn == NULL) {
4390 return NT_STATUS_INTERNAL_ERROR;
4393 forest_dn = ldb_get_root_basedn(sam_ctx);
4394 if (forest_dn == NULL) {
4395 return NT_STATUS_INTERNAL_ERROR;
4398 cmp = ldb_dn_compare(domain_dn, forest_dn);
4400 return NT_STATUS_INVALID_DOMAIN_STATE;
4403 forest_level = dsdb_forest_functional_level(sam_ctx);
4404 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4405 return NT_STATUS_INVALID_DOMAIN_STATE;
4408 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4409 r->out.forest_trust_info);
4410 if (!NT_STATUS_IS_OK(status)) {
4414 return NT_STATUS_OK;
4419 netr_ServerGetTrustInfo
4421 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4422 struct netr_ServerGetTrustInfo *r)
4424 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4425 struct netlogon_creds_CredentialState *creds = NULL;
4426 struct ldb_context *sam_ctx = NULL;
4427 const char * const attrs[] = {
4430 "userAccountControl",
4433 struct ldb_message **res = NULL;
4434 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4437 const char *asid = NULL;
4439 const char *aname = NULL;
4440 struct ldb_message *tdo_msg = NULL;
4441 const char * const tdo_attrs[] = {
4442 "trustAuthIncoming",
4446 struct netr_TrustInfo *trust_info = NULL;
4448 ZERO_STRUCTP(r->out.new_owf_password);
4449 ZERO_STRUCTP(r->out.old_owf_password);
4451 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4453 r->in.computer_name,
4455 r->out.return_authenticator,
4457 if (!NT_STATUS_IS_OK(nt_status)) {
4461 /* TODO: check r->in.server_name is our name */
4463 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4464 return NT_STATUS_INVALID_PARAMETER;
4467 if (r->in.secure_channel_type != creds->secure_channel_type) {
4468 return NT_STATUS_INVALID_PARAMETER;
4471 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4472 return NT_STATUS_INVALID_PARAMETER;
4475 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
4476 if (sam_ctx == NULL) {
4477 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4480 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4482 return NT_STATUS_NO_MEMORY;
4485 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4486 "(&(objectClass=user)(objectSid=%s))",
4489 return NT_STATUS_ACCOUNT_DISABLED;
4492 switch (creds->secure_channel_type) {
4493 case SEC_CHAN_DNS_DOMAIN:
4494 case SEC_CHAN_DOMAIN:
4495 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4497 if (uac & UF_ACCOUNTDISABLE) {
4498 return NT_STATUS_ACCOUNT_DISABLED;
4501 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4502 return NT_STATUS_ACCOUNT_DISABLED;
4505 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4506 if (aname == NULL) {
4507 return NT_STATUS_ACCOUNT_DISABLED;
4510 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4511 SEC_CHAN_DOMAIN, aname,
4512 tdo_attrs, mem_ctx, &tdo_msg);
4513 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4514 return NT_STATUS_ACCOUNT_DISABLED;
4516 if (!NT_STATUS_IS_OK(nt_status)) {
4520 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4523 if (!NT_STATUS_IS_OK(nt_status)) {
4527 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4528 if (trust_info == NULL) {
4529 return NT_STATUS_NO_MEMORY;
4532 trust_info->count = 1;
4533 trust_info->data = talloc_array(trust_info, uint32_t,
4535 if (trust_info->data == NULL) {
4536 return NT_STATUS_NO_MEMORY;
4539 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4545 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4548 if (!NT_STATUS_IS_OK(nt_status)) {
4552 prevNtHash = talloc(mem_ctx, struct samr_Password);
4553 if (prevNtHash == NULL) {
4554 return NT_STATUS_NO_MEMORY;
4557 E_md4hash("", prevNtHash->hash);
4561 if (curNtHash != NULL) {
4562 *r->out.new_owf_password = *curNtHash;
4563 nt_status = netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4564 if (!NT_STATUS_IS_OK(nt_status)) {
4568 if (prevNtHash != NULL) {
4569 *r->out.old_owf_password = *prevNtHash;
4570 nt_status = netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4571 if (!NT_STATUS_IS_OK(nt_status)) {
4576 if (trust_info != NULL) {
4577 *r->out.trust_info = trust_info;
4580 return NT_STATUS_OK;
4586 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4587 struct netr_Unused47 *r)
4589 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4593 struct netr_dnsupdate_RODC_state {
4594 struct dcesrv_call_state *dce_call;
4595 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4596 struct dnsupdate_RODC *r2;
4600 called when the forwarded RODC dns update request is finished
4602 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4604 struct netr_dnsupdate_RODC_state *st =
4605 tevent_req_callback_data(subreq,
4606 struct netr_dnsupdate_RODC_state);
4609 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4610 TALLOC_FREE(subreq);
4611 if (!NT_STATUS_IS_OK(status)) {
4612 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4613 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4616 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4618 dcesrv_async_reply(st->dce_call);
4622 netr_DsrUpdateReadOnlyServerDnsRecords
4624 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4625 TALLOC_CTX *mem_ctx,
4626 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4628 struct netlogon_creds_CredentialState *creds;
4630 struct dcerpc_binding_handle *binding_handle;
4631 struct netr_dnsupdate_RODC_state *st;
4632 struct tevent_req *subreq;
4633 struct imessaging_context *imsg_ctx =
4634 dcesrv_imessaging_context(dce_call->conn);
4636 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4638 r->in.computer_name,
4640 r->out.return_authenticator,
4642 NT_STATUS_NOT_OK_RETURN(nt_status);
4644 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4645 return NT_STATUS_ACCESS_DENIED;
4648 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4649 NT_STATUS_HAVE_NO_MEMORY(st);
4651 st->dce_call = dce_call;
4653 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4654 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4656 st->r2->in.dom_sid = creds->sid;
4657 st->r2->in.site_name = r->in.site_name;
4658 st->r2->in.dns_ttl = r->in.dns_ttl;
4659 st->r2->in.dns_names = r->in.dns_names;
4660 st->r2->out.dns_names = r->out.dns_names;
4662 binding_handle = irpc_binding_handle_by_name(st,
4666 if (binding_handle == NULL) {
4667 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4668 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4669 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4672 /* forward the call */
4673 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4674 binding_handle, st->r2);
4675 NT_STATUS_HAVE_NO_MEMORY(subreq);
4677 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4679 /* setup the callback */
4680 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4682 return NT_STATUS_OK;
4686 /* include the generated boilerplate */
4687 #include "librpc/gen_ndr/ndr_netlogon_s.c"