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 const char *attrs[] = {"unicodePwd", "userAccountControl",
414 "objectSid", "samAccountName", NULL};
415 uint32_t server_flags = 0;
416 uint32_t negotiate_flags = 0;
418 ZERO_STRUCTP(r->out.return_credentials);
419 *r->out.negotiate_flags = 0;
422 pipe_state = dcesrv_iface_state_find_conn(dce_call,
423 NETLOGON_SERVER_PIPE_STATE_MAGIC,
424 struct netlogon_server_pipe_state);
425 if (pipe_state != NULL) {
427 * If we had a challenge remembered on the connection
428 * consider this for usage. This can't be cleanup
431 * This is the default code path for typical clients
432 * which call netr_ServerReqChallenge() and
433 * netr_ServerAuthenticate3() on the same dcerpc connection.
435 challenge = *pipe_state;
437 challenge_valid = true;
443 * Fallback and try to get the challenge from
446 * If too many clients are using this code path,
447 * they may destroy their cache entries as the
448 * TDB has a fixed size limited via a lossy hash
450 * The TDB used is the schannel store, which is
451 * initialised at startup.
453 * NOTE: The challenge is deleted from the DB as soon as it is
454 * fetched, to prevent reuse.
458 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
459 &challenge.client_challenge,
460 &challenge.server_challenge,
461 r->in.computer_name);
463 if (!NT_STATUS_IS_OK(ntstatus)) {
464 ZERO_STRUCT(challenge);
466 challenge_valid = true;
470 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
471 NETLOGON_NEG_PERSISTENT_SAMREPL |
472 NETLOGON_NEG_ARCFOUR |
473 NETLOGON_NEG_PROMOTION_COUNT |
474 NETLOGON_NEG_CHANGELOG_BDC |
475 NETLOGON_NEG_FULL_SYNC_REPL |
476 NETLOGON_NEG_MULTIPLE_SIDS |
478 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
479 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
480 NETLOGON_NEG_GENERIC_PASSTHROUGH |
481 NETLOGON_NEG_CONCURRENT_RPC |
482 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
483 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
484 NETLOGON_NEG_STRONG_KEYS |
485 NETLOGON_NEG_TRANSITIVE_TRUSTS |
486 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
487 NETLOGON_NEG_PASSWORD_SET2 |
488 NETLOGON_NEG_GETDOMAININFO |
489 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
490 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
491 NETLOGON_NEG_RODC_PASSTHROUGH |
492 NETLOGON_NEG_SUPPORTS_AES |
493 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
494 NETLOGON_NEG_AUTHENTICATED_RPC;
497 * If weak crypto is disabled, do not announce that we support RC4.
499 if (lpcfg_weak_crypto(dce_call->conn->dce_ctx->lp_ctx) ==
500 SAMBA_WEAK_CRYPTO_DISALLOWED) {
501 server_flags &= ~NETLOGON_NEG_ARCFOUR;
504 negotiate_flags = *r->in.negotiate_flags & server_flags;
506 switch (r->in.secure_channel_type) {
508 case SEC_CHAN_DNS_DOMAIN:
509 case SEC_CHAN_DOMAIN:
514 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
515 dce_call, r, pipe_state, negotiate_flags,
516 NULL, /* trust_account_in_db */
517 NT_STATUS_INVALID_PARAMETER);
519 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
520 r->in.secure_channel_type));
521 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
522 dce_call, r, pipe_state, negotiate_flags,
523 NULL, /* trust_account_in_db */
524 NT_STATUS_INVALID_PARAMETER);
527 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
528 if (sam_ctx == NULL) {
529 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
530 dce_call, r, pipe_state, negotiate_flags,
531 NULL, /* trust_account_in_db */
532 NT_STATUS_INVALID_SYSTEM_SERVICE);
535 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
536 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
538 struct ldb_message *tdo_msg = NULL;
539 const char * const tdo_attrs[] = {
545 char *encoded_name = NULL;
547 const char *flatname = NULL;
549 bool require_trailer = true;
550 const char *netbios = NULL;
551 const char *dns = NULL;
553 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
555 require_trailer = false;
558 encoded_name = ldb_binary_encode_string(mem_ctx,
560 if (encoded_name == NULL) {
561 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
562 dce_call, r, pipe_state, negotiate_flags,
563 NULL, /* trust_account_in_db */
564 NT_STATUS_NO_MEMORY);
567 len = strlen(encoded_name);
569 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
570 dce_call, r, pipe_state, negotiate_flags,
571 NULL, /* trust_account_in_db */
572 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
575 if (require_trailer && encoded_name[len - 1] != trailer) {
576 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
577 dce_call, r, pipe_state, negotiate_flags,
578 NULL, /* trust_account_in_db */
579 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
581 encoded_name[len - 1] = '\0';
583 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
586 netbios = encoded_name;
589 nt_status = dsdb_trust_search_tdo(sam_ctx,
591 tdo_attrs, mem_ctx, &tdo_msg);
592 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
593 DEBUG(2, ("Client asked for a trusted domain secure channel, "
594 "but there's no tdo for [%s] => [%s] \n",
595 log_escape(mem_ctx, r->in.account_name),
597 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
598 dce_call, r, pipe_state, negotiate_flags,
599 NULL, /* trust_account_in_db */
600 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
602 if (!NT_STATUS_IS_OK(nt_status)) {
603 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
604 dce_call, r, pipe_state, negotiate_flags,
605 NULL, /* trust_account_in_db */
609 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
612 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
613 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
614 dce_call, r, pipe_state, negotiate_flags,
615 NULL, /* trust_account_in_db */
616 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
618 if (!NT_STATUS_IS_OK(nt_status)) {
619 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
620 dce_call, r, pipe_state, negotiate_flags,
621 NULL, /* trust_account_in_db */
625 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
626 if (flatname == NULL) {
627 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
628 dce_call, r, pipe_state, negotiate_flags,
629 NULL, /* trust_account_in_db */
630 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
633 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
634 if (*trust_account_for_search == NULL) {
635 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
636 dce_call, r, pipe_state, negotiate_flags,
637 NULL, /* trust_account_in_db */
638 NT_STATUS_NO_MEMORY);
641 *trust_account_for_search = r->in.account_name;
644 /* pull the user attributes */
645 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
646 "(&(sAMAccountName=%s)(objectclass=user))",
647 ldb_binary_encode_string(mem_ctx,
648 *trust_account_for_search));
650 if (num_records == 0) {
651 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
652 log_escape(mem_ctx, r->in.account_name)));
653 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
654 dce_call, r, pipe_state, negotiate_flags,
655 NULL, /* trust_account_in_db */
656 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
659 if (num_records > 1) {
660 DEBUG(0,("Found %d records matching user [%s]\n",
662 log_escape(mem_ctx, r->in.account_name)));
663 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
664 dce_call, r, pipe_state, negotiate_flags,
665 NULL, /* trust_account_in_db */
666 NT_STATUS_INTERNAL_DB_CORRUPTION);
669 *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
672 if (*trust_account_in_db == NULL) {
673 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
674 r->in.account_name));
675 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
676 dce_call, r, pipe_state, negotiate_flags,
677 NULL, /* trust_account_in_db */
678 NT_STATUS_INTERNAL_DB_CORRUPTION);
681 nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
682 dce_call, r, pipe_state, negotiate_flags,
683 *trust_account_in_db,
685 if (!NT_STATUS_IS_OK(nt_status)) {
689 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
691 if (user_account_control & UF_ACCOUNTDISABLE) {
692 DEBUG(1, ("Account [%s] is disabled\n",
693 log_escape(mem_ctx, r->in.account_name)));
694 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
697 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
698 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
699 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
700 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
702 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
703 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
704 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
705 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
707 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
709 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
710 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
711 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
712 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
714 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
715 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
716 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
717 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
720 /* we should never reach this */
721 return NT_STATUS_INTERNAL_ERROR;
724 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
725 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
726 dce_call->conn->dce_ctx->lp_ctx,
727 msgs[0], &curNtHash);
728 if (!NT_STATUS_IS_OK(nt_status)) {
729 return NT_STATUS_ACCESS_DENIED;
733 if (curNtHash == NULL) {
734 return NT_STATUS_ACCESS_DENIED;
737 if (!challenge_valid) {
738 DEBUG(1, ("No challenge requested by client [%s/%s], "
739 "cannot authenticate\n",
740 log_escape(mem_ctx, r->in.computer_name),
741 log_escape(mem_ctx, r->in.account_name)));
742 return NT_STATUS_ACCESS_DENIED;
745 creds = netlogon_creds_server_init(mem_ctx,
748 r->in.secure_channel_type,
749 &challenge.client_challenge,
750 &challenge.server_challenge,
753 r->out.return_credentials,
755 if (creds == NULL && prevNtHash != NULL) {
757 * We fallback to the previous password for domain trusts.
759 * Note that lpcfg_old_password_allowed_period() doesn't
762 creds = netlogon_creds_server_init(mem_ctx,
765 r->in.secure_channel_type,
766 &challenge.client_challenge,
767 &challenge.server_challenge,
770 r->out.return_credentials,
775 return NT_STATUS_ACCESS_DENIED;
777 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
778 *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
780 nt_status = schannel_save_creds_state(mem_ctx,
781 dce_call->conn->dce_ctx->lp_ctx,
783 if (!NT_STATUS_IS_OK(nt_status)) {
784 ZERO_STRUCTP(r->out.return_credentials);
788 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
795 * Log a netr_ServerAuthenticate3 request, and then invoke
796 * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
798 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
799 struct dcesrv_call_state *dce_call,
801 struct netr_ServerAuthenticate3 *r)
804 struct dom_sid *sid = NULL;
805 const char *trust_account_for_search = NULL;
806 const char *trust_account_in_db = NULL;
807 struct imessaging_context *imsg_ctx =
808 dcesrv_imessaging_context(dce_call->conn);
809 struct auth_usersupplied_info ui = {
810 .local_host = dce_call->conn->local_address,
811 .remote_host = dce_call->conn->remote_address,
813 .account_name = r->in.account_name,
814 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
816 .service_description = "NETLOGON",
817 .auth_description = "ServerAuthenticate",
818 .netlogon_trust_account = {
819 .computer_name = r->in.computer_name,
820 .negotiate_flags = *r->in.negotiate_flags,
821 .secure_channel_type = r->in.secure_channel_type,
825 status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
828 &trust_account_for_search,
829 &trust_account_in_db,
831 ui.netlogon_trust_account.sid = sid;
832 ui.netlogon_trust_account.account_name = trust_account_in_db;
833 ui.mapped.account_name = trust_account_for_search;
834 log_authentication_event(
836 dce_call->conn->dce_ctx->lp_ctx,
840 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
843 NULL /* client_audit_info */,
844 NULL /* server_audit_info */);
848 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
849 struct netr_ServerAuthenticate *r)
851 struct netr_ServerAuthenticate3 a;
854 * negotiate_flags is used as an [in] parameter
855 * so it need to be initialised.
857 * (I think ... = 0; seems wrong here --metze)
859 uint32_t negotiate_flags_in = 0;
860 uint32_t negotiate_flags_out = 0;
862 a.in.server_name = r->in.server_name;
863 a.in.account_name = r->in.account_name;
864 a.in.secure_channel_type = r->in.secure_channel_type;
865 a.in.computer_name = r->in.computer_name;
866 a.in.credentials = r->in.credentials;
867 a.in.negotiate_flags = &negotiate_flags_in;
869 a.out.return_credentials = r->out.return_credentials;
871 a.out.negotiate_flags = &negotiate_flags_out;
873 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
876 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
877 struct netr_ServerAuthenticate2 *r)
879 struct netr_ServerAuthenticate3 r3;
882 r3.in.server_name = r->in.server_name;
883 r3.in.account_name = r->in.account_name;
884 r3.in.secure_channel_type = r->in.secure_channel_type;
885 r3.in.computer_name = r->in.computer_name;
886 r3.in.credentials = r->in.credentials;
887 r3.out.return_credentials = r->out.return_credentials;
888 r3.in.negotiate_flags = r->in.negotiate_flags;
889 r3.out.negotiate_flags = r->out.negotiate_flags;
892 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
896 Change the machine account password for the currently connected
897 client. Supplies only the NT#.
900 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
901 struct netr_ServerPasswordSet *r)
903 struct netlogon_creds_CredentialState *creds;
904 struct ldb_context *sam_ctx;
907 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
910 r->in.credential, r->out.return_authenticator,
912 NT_STATUS_NOT_OK_RETURN(nt_status);
914 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
915 if (sam_ctx == NULL) {
916 return NT_STATUS_INVALID_SYSTEM_SERVICE;
919 nt_status = netlogon_creds_des_decrypt(creds, r->in.new_password);
920 NT_STATUS_NOT_OK_RETURN(nt_status);
922 /* Using the sid for the account as the key, set the password */
923 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
925 NULL, /* Don't have version */
926 NULL, /* Don't have plaintext */
928 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
934 Change the machine account password for the currently connected
935 client. Supplies new plaintext.
937 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
938 struct netr_ServerPasswordSet2 *r)
940 struct netlogon_creds_CredentialState *creds;
941 struct ldb_context *sam_ctx;
942 struct NL_PASSWORD_VERSION version = {};
943 const uint32_t *new_version = NULL;
945 DATA_BLOB new_password = data_blob_null;
946 size_t confounder_len;
947 DATA_BLOB dec_blob = data_blob_null;
948 DATA_BLOB enc_blob = data_blob_null;
949 struct samr_CryptPassword password_buf;
951 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
954 r->in.credential, r->out.return_authenticator,
956 NT_STATUS_NOT_OK_RETURN(nt_status);
958 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
959 if (sam_ctx == NULL) {
960 return NT_STATUS_INVALID_SYSTEM_SERVICE;
963 memcpy(password_buf.data, r->in.new_password->data, 512);
964 SIVAL(password_buf.data, 512, r->in.new_password->length);
966 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
967 nt_status = netlogon_creds_aes_decrypt(creds,
971 nt_status = netlogon_creds_arcfour_crypt(creds,
976 if (!NT_STATUS_IS_OK(nt_status)) {
980 switch (creds->secure_channel_type) {
981 case SEC_CHAN_DOMAIN:
982 case SEC_CHAN_DNS_DOMAIN: {
983 uint32_t len = IVAL(password_buf.data, 512);
985 uint32_t ofs = 500 - len;
988 p = password_buf.data + ofs;
990 version.ReservedField = IVAL(p, 0);
991 version.PasswordVersionNumber = IVAL(p, 4);
992 version.PasswordVersionPresent = IVAL(p, 8);
994 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
995 new_version = &version.PasswordVersionNumber;
1003 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
1004 DEBUG(3,("samr: failed to decode password buffer\n"));
1005 return NT_STATUS_WRONG_PASSWORD;
1009 * Make sure the length field was encrypted,
1010 * otherwise we are under attack.
1012 if (new_password.length == r->in.new_password->length) {
1013 DBG_WARNING("Length[%zu] field not encrypted\n",
1014 new_password.length);
1015 return NT_STATUS_WRONG_PASSWORD;
1019 * We don't allow empty passwords for machine accounts.
1021 if (new_password.length < 2) {
1022 DBG_WARNING("Empty password Length[%zu]\n",
1023 new_password.length);
1024 return NT_STATUS_WRONG_PASSWORD;
1028 * Make sure the confounder part of CryptPassword
1029 * buffer was encrypted, otherwise we are under attack.
1031 confounder_len = 512 - new_password.length;
1032 enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
1033 dec_blob = data_blob_const(password_buf.data, confounder_len);
1034 if (confounder_len > 0 && data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1035 DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
1037 return NT_STATUS_WRONG_PASSWORD;
1041 * Check that the password part was actually encrypted,
1042 * otherwise we are under attack.
1044 enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
1045 new_password.length);
1046 dec_blob = data_blob_const(password_buf.data + confounder_len,
1047 new_password.length);
1048 if (data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1049 DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
1050 new_password.length);
1051 return NT_STATUS_WRONG_PASSWORD;
1055 * don't allow zero buffers
1057 if (all_zero(new_password.data, new_password.length)) {
1058 DBG_WARNING("Password zero buffer Length[%zu]\n",
1059 new_password.length);
1060 return NT_STATUS_WRONG_PASSWORD;
1063 /* Using the sid for the account as the key, set the password */
1064 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1067 &new_password, /* we have plaintext */
1069 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1078 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1079 struct netr_LogonUasLogon *r)
1081 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1088 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1089 struct netr_LogonUasLogoff *r)
1091 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1095 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
1096 const struct netr_LogonSamLogonEx *r)
1098 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1100 switch (r->in.logon_level) {
1101 case NetlogonInteractiveInformation:
1102 case NetlogonServiceInformation:
1103 case NetlogonInteractiveTransitiveInformation:
1104 case NetlogonServiceTransitiveInformation:
1105 if (r->in.logon->password == NULL) {
1106 return NT_STATUS_INVALID_PARAMETER;
1109 switch (r->in.validation_level) {
1110 case NetlogonValidationSamInfo: /* 2 */
1111 case NetlogonValidationSamInfo2: /* 3 */
1112 case NetlogonValidationSamInfo4: /* 6 */
1115 return NT_STATUS_INVALID_INFO_CLASS;
1119 case NetlogonNetworkInformation:
1120 case NetlogonNetworkTransitiveInformation:
1121 if (r->in.logon->network == NULL) {
1122 return NT_STATUS_INVALID_PARAMETER;
1125 switch (r->in.validation_level) {
1126 case NetlogonValidationSamInfo: /* 2 */
1127 case NetlogonValidationSamInfo2: /* 3 */
1128 case NetlogonValidationSamInfo4: /* 6 */
1131 return NT_STATUS_INVALID_INFO_CLASS;
1136 case NetlogonGenericInformation:
1137 if (r->in.logon->generic == NULL) {
1138 return NT_STATUS_INVALID_PARAMETER;
1141 switch (r->in.validation_level) {
1142 /* TODO: case NetlogonValidationGenericInfo: 4 */
1143 case NetlogonValidationGenericInfo2: /* 5 */
1146 return NT_STATUS_INVALID_INFO_CLASS;
1151 return NT_STATUS_INVALID_PARAMETER;
1154 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
1156 switch (r->in.validation_level) {
1157 case NetlogonValidationSamInfo4: /* 6 */
1158 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1159 return NT_STATUS_INVALID_PARAMETER;
1167 return NT_STATUS_OK;
1170 struct dcesrv_netr_LogonSamLogon_base_state {
1171 struct dcesrv_call_state *dce_call;
1173 TALLOC_CTX *mem_ctx;
1175 struct netlogon_creds_CredentialState *creds;
1177 struct netr_LogonSamLogonEx r;
1179 uint32_t _ignored_flags;
1182 struct netr_LogonSamLogon *lsl;
1183 struct netr_LogonSamLogonWithFlags *lslwf;
1184 struct netr_LogonSamLogonEx *lslex;
1187 struct kdc_check_generic_kerberos kr;
1190 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
1191 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
1192 static void dcesrv_netr_LogonSamLogon_base_reply(
1193 struct dcesrv_netr_LogonSamLogon_base_state *state);
1196 netr_LogonSamLogon_base
1198 This version of the function allows other wrappers to say 'do not check the credentials'
1200 We can't do the traditional 'wrapping' format completely, as this
1201 function must only run under schannel
1203 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
1205 struct dcesrv_call_state *dce_call = state->dce_call;
1206 struct imessaging_context *imsg_ctx =
1207 dcesrv_imessaging_context(dce_call->conn);
1208 TALLOC_CTX *mem_ctx = state->mem_ctx;
1209 struct netr_LogonSamLogonEx *r = &state->r;
1210 struct netlogon_creds_CredentialState *creds = state->creds;
1211 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1212 const char *workgroup = lpcfg_workgroup(lp_ctx);
1213 struct auth4_context *auth_context = NULL;
1214 struct auth_usersupplied_info *user_info = NULL;
1216 struct tevent_req *subreq = NULL;
1217 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1218 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1220 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1222 switch (dce_call->pkt.u.request.opnum) {
1223 case NDR_NETR_LOGONSAMLOGON:
1224 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
1226 * These already called dcesrv_netr_check_schannel()
1227 * via dcesrv_netr_creds_server_step_check()
1230 case NDR_NETR_LOGONSAMLOGONEX:
1232 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1233 return NT_STATUS_ACCESS_DENIED;
1236 nt_status = dcesrv_netr_check_schannel(dce_call,
1240 dce_call->pkt.u.request.opnum);
1241 if (!NT_STATUS_IS_OK(nt_status)) {
1247 *r->out.authoritative = 1;
1249 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
1251 * Currently we're always the forest root ourself.
1253 return NT_STATUS_NO_SUCH_USER;
1256 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
1258 * Currently we don't support trusts correctly yet.
1260 return NT_STATUS_NO_SUCH_USER;
1263 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1264 NT_STATUS_HAVE_NO_MEMORY(user_info);
1266 user_info->service_description = "SamLogon";
1268 nt_status = netlogon_creds_decrypt_samlogon_logon(creds,
1271 NT_STATUS_NOT_OK_RETURN(nt_status);
1273 switch (r->in.logon_level) {
1274 case NetlogonInteractiveInformation:
1275 case NetlogonServiceInformation:
1276 case NetlogonInteractiveTransitiveInformation:
1277 case NetlogonServiceTransitiveInformation:
1278 case NetlogonNetworkInformation:
1279 case NetlogonNetworkTransitiveInformation:
1281 nt_status = auth_context_create_for_netlogon(mem_ctx,
1282 dce_call->event_ctx,
1284 dce_call->conn->dce_ctx->lp_ctx,
1286 NT_STATUS_NOT_OK_RETURN(nt_status);
1288 user_info->remote_host = dce_call->conn->remote_address;
1289 user_info->local_host = dce_call->conn->local_address;
1291 user_info->netlogon_trust_account.secure_channel_type
1292 = creds->secure_channel_type;
1293 user_info->netlogon_trust_account.negotiate_flags
1294 = creds->negotiate_flags;
1297 * These two can be unrelated when the account is
1298 * actually that of a trusted domain, so we want to
1299 * know which DC in that trusted domain contacted
1302 user_info->netlogon_trust_account.computer_name
1303 = creds->computer_name;
1304 user_info->netlogon_trust_account.account_name
1305 = creds->account_name;
1306 user_info->netlogon_trust_account.sid
1311 /* We do not need to set up the user_info in this case */
1315 switch (r->in.logon_level) {
1316 case NetlogonInteractiveInformation:
1317 case NetlogonServiceInformation:
1318 case NetlogonInteractiveTransitiveInformation:
1319 case NetlogonServiceTransitiveInformation:
1320 user_info->auth_description = "interactive";
1322 user_info->logon_parameters
1323 = r->in.logon->password->identity_info.parameter_control;
1324 user_info->client.account_name
1325 = r->in.logon->password->identity_info.account_name.string;
1326 user_info->client.domain_name
1327 = r->in.logon->password->identity_info.domain_name.string;
1328 user_info->workstation_name
1329 = r->in.logon->password->identity_info.workstation.string;
1330 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1331 user_info->password_state = AUTH_PASSWORD_HASH;
1333 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1334 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1335 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1337 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1338 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1339 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1342 = r->in.logon->password->identity_info.logon_id;
1345 case NetlogonNetworkInformation:
1346 case NetlogonNetworkTransitiveInformation:
1347 user_info->auth_description = "network";
1349 nt_status = auth_context_set_challenge(
1351 r->in.logon->network->challenge,
1352 "netr_LogonSamLogonWithFlags");
1353 NT_STATUS_NOT_OK_RETURN(nt_status);
1355 user_info->logon_parameters
1356 = r->in.logon->network->identity_info.parameter_control;
1357 user_info->client.account_name
1358 = r->in.logon->network->identity_info.account_name.string;
1359 user_info->client.domain_name
1360 = r->in.logon->network->identity_info.domain_name.string;
1361 user_info->workstation_name
1362 = r->in.logon->network->identity_info.workstation.string;
1364 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1365 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1366 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1369 = r->in.logon->network->identity_info.logon_id;
1371 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1372 user_info->client.account_name,
1373 user_info->client.domain_name,
1374 user_info->password.response.nt,
1376 NT_STATUS_NOT_OK_RETURN(nt_status);
1381 case NetlogonGenericInformation:
1383 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1385 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1388 /* Using DES to verify kerberos tickets makes no sense */
1389 return NT_STATUS_INVALID_PARAMETER;
1392 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1393 struct dcerpc_binding_handle *irpc_handle;
1394 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1395 NT_STATUS_HAVE_NO_MEMORY(generic);
1397 r->out.validation->generic = generic;
1400 = r->in.logon->generic->identity_info.logon_id;
1402 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1406 if (irpc_handle == NULL) {
1407 return NT_STATUS_NO_LOGON_SERVERS;
1410 state->kr.in.generic_request =
1411 data_blob_const(r->in.logon->generic->data,
1412 r->in.logon->generic->length);
1415 * 60 seconds should be enough
1417 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1418 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1419 state->dce_call->event_ctx,
1420 irpc_handle, &state->kr);
1421 if (subreq == NULL) {
1422 return NT_STATUS_NO_MEMORY;
1424 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1425 tevent_req_set_callback(subreq,
1426 dcesrv_netr_LogonSamLogon_base_krb5_done,
1428 return NT_STATUS_OK;
1431 /* Until we get an implementation of these other packages */
1432 return NT_STATUS_INVALID_PARAMETER;
1435 return NT_STATUS_INVALID_PARAMETER;
1438 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1439 auth_context, user_info);
1440 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1441 tevent_req_set_callback(subreq,
1442 dcesrv_netr_LogonSamLogon_base_auth_done,
1444 return NT_STATUS_OK;
1447 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1449 struct dcesrv_netr_LogonSamLogon_base_state *state =
1450 tevent_req_callback_data(subreq,
1451 struct dcesrv_netr_LogonSamLogon_base_state);
1452 TALLOC_CTX *mem_ctx = state->mem_ctx;
1453 struct netr_LogonSamLogonEx *r = &state->r;
1454 struct auth_user_info_dc *user_info_dc = NULL;
1455 struct netr_SamInfo2 *sam2 = NULL;
1456 struct netr_SamInfo3 *sam3 = NULL;
1457 struct netr_SamInfo6 *sam6 = NULL;
1460 nt_status = auth_check_password_recv(subreq, mem_ctx,
1462 r->out.authoritative);
1463 TALLOC_FREE(subreq);
1464 if (!NT_STATUS_IS_OK(nt_status)) {
1465 r->out.result = nt_status;
1466 dcesrv_netr_LogonSamLogon_base_reply(state);
1470 switch (r->in.validation_level) {
1472 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1474 AUTH_INCLUDE_RESOURCE_GROUPS,
1476 if (!NT_STATUS_IS_OK(nt_status)) {
1477 r->out.result = nt_status;
1478 dcesrv_netr_LogonSamLogon_base_reply(state);
1482 r->out.validation->sam2 = sam2;
1486 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1488 AUTH_INCLUDE_RESOURCE_GROUPS,
1490 if (!NT_STATUS_IS_OK(nt_status)) {
1491 r->out.result = nt_status;
1492 dcesrv_netr_LogonSamLogon_base_reply(state);
1496 r->out.validation->sam3 = sam3;
1500 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1502 AUTH_INCLUDE_RESOURCE_GROUPS,
1504 if (!NT_STATUS_IS_OK(nt_status)) {
1505 r->out.result = nt_status;
1506 dcesrv_netr_LogonSamLogon_base_reply(state);
1510 r->out.validation->sam6 = sam6;
1514 if (!NT_STATUS_IS_OK(nt_status)) {
1515 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1516 dcesrv_netr_LogonSamLogon_base_reply(state);
1521 /* TODO: Describe and deal with these flags */
1524 r->out.result = NT_STATUS_OK;
1526 dcesrv_netr_LogonSamLogon_base_reply(state);
1529 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1531 struct dcesrv_netr_LogonSamLogon_base_state *state =
1532 tevent_req_callback_data(subreq,
1533 struct dcesrv_netr_LogonSamLogon_base_state);
1534 TALLOC_CTX *mem_ctx = state->mem_ctx;
1535 struct netr_LogonSamLogonEx *r = &state->r;
1536 struct netr_GenericInfo2 *generic = NULL;
1539 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1540 TALLOC_FREE(subreq);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 r->out.result = status;
1543 dcesrv_netr_LogonSamLogon_base_reply(state);
1547 generic = r->out.validation->generic;
1548 generic->length = state->kr.out.generic_reply.length;
1549 generic->data = state->kr.out.generic_reply.data;
1551 /* TODO: Describe and deal with these flags */
1554 r->out.result = NT_STATUS_OK;
1556 dcesrv_netr_LogonSamLogon_base_reply(state);
1559 static void dcesrv_netr_LogonSamLogon_base_reply(
1560 struct dcesrv_netr_LogonSamLogon_base_state *state)
1562 struct netr_LogonSamLogonEx *r = &state->r;
1565 if (NT_STATUS_IS_OK(r->out.result)) {
1566 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
1567 r->in.validation_level,
1569 if (!NT_STATUS_IS_OK(status)) {
1570 DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
1576 if (state->_r.lslex != NULL) {
1577 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1578 _r->out.result = r->out.result;
1579 } else if (state->_r.lslwf != NULL) {
1580 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1581 _r->out.result = r->out.result;
1582 } else if (state->_r.lsl != NULL) {
1583 struct netr_LogonSamLogon *_r = state->_r.lsl;
1584 _r->out.result = r->out.result;
1587 status = dcesrv_reply(state->dce_call);
1588 if (!NT_STATUS_IS_OK(status)) {
1589 DBG_ERR("dcesrv_reply() failed - %s\n",
1594 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1595 struct netr_LogonSamLogonEx *r)
1597 struct dcesrv_netr_LogonSamLogon_base_state *state;
1600 *r->out.authoritative = 1;
1602 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1603 if (state == NULL) {
1604 return NT_STATUS_NO_MEMORY;
1607 state->dce_call = dce_call;
1608 state->mem_ctx = mem_ctx;
1610 state->r.in.server_name = r->in.server_name;
1611 state->r.in.computer_name = r->in.computer_name;
1612 state->r.in.logon_level = r->in.logon_level;
1613 state->r.in.logon = r->in.logon;
1614 state->r.in.validation_level = r->in.validation_level;
1615 state->r.in.flags = r->in.flags;
1616 state->r.out.validation = r->out.validation;
1617 state->r.out.authoritative = r->out.authoritative;
1618 state->r.out.flags = r->out.flags;
1620 state->_r.lslex = r;
1622 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1623 if (!NT_STATUS_IS_OK(nt_status)) {
1627 nt_status = schannel_get_creds_state(mem_ctx,
1628 dce_call->conn->dce_ctx->lp_ctx,
1629 r->in.computer_name, &state->creds);
1630 if (!NT_STATUS_IS_OK(nt_status)) {
1634 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1636 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1644 netr_LogonSamLogonWithFlags
1647 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1648 struct netr_LogonSamLogonWithFlags *r)
1650 struct dcesrv_netr_LogonSamLogon_base_state *state;
1653 *r->out.authoritative = 1;
1655 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1656 if (state == NULL) {
1657 return NT_STATUS_NO_MEMORY;
1660 state->dce_call = dce_call;
1661 state->mem_ctx = mem_ctx;
1663 state->r.in.server_name = r->in.server_name;
1664 state->r.in.computer_name = r->in.computer_name;
1665 state->r.in.logon_level = r->in.logon_level;
1666 state->r.in.logon = r->in.logon;
1667 state->r.in.validation_level = r->in.validation_level;
1668 state->r.in.flags = r->in.flags;
1669 state->r.out.validation = r->out.validation;
1670 state->r.out.authoritative = r->out.authoritative;
1671 state->r.out.flags = r->out.flags;
1673 state->_r.lslwf = r;
1675 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1676 if (!NT_STATUS_IS_OK(nt_status)) {
1680 r->out.return_authenticator = talloc_zero(mem_ctx,
1681 struct netr_Authenticator);
1682 if (r->out.return_authenticator == NULL) {
1683 return NT_STATUS_NO_MEMORY;
1686 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1688 r->in.computer_name,
1690 r->out.return_authenticator,
1692 if (!NT_STATUS_IS_OK(nt_status)) {
1696 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1698 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1708 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1709 struct netr_LogonSamLogon *r)
1711 struct dcesrv_netr_LogonSamLogon_base_state *state;
1714 *r->out.authoritative = 1;
1716 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1717 if (state == NULL) {
1718 return NT_STATUS_NO_MEMORY;
1721 state->dce_call = dce_call;
1722 state->mem_ctx = mem_ctx;
1724 state->r.in.server_name = r->in.server_name;
1725 state->r.in.computer_name = r->in.computer_name;
1726 state->r.in.logon_level = r->in.logon_level;
1727 state->r.in.logon = r->in.logon;
1728 state->r.in.validation_level = r->in.validation_level;
1729 state->r.in.flags = &state->_ignored_flags;
1730 state->r.out.validation = r->out.validation;
1731 state->r.out.authoritative = r->out.authoritative;
1732 state->r.out.flags = &state->_ignored_flags;
1736 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1737 if (!NT_STATUS_IS_OK(nt_status)) {
1741 r->out.return_authenticator = talloc_zero(mem_ctx,
1742 struct netr_Authenticator);
1743 if (r->out.return_authenticator == NULL) {
1744 return NT_STATUS_NO_MEMORY;
1747 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1749 r->in.computer_name,
1751 r->out.return_authenticator,
1753 if (!NT_STATUS_IS_OK(nt_status)) {
1757 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1759 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1770 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1771 struct netr_LogonSamLogoff *r)
1773 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1781 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1782 struct netr_DatabaseDeltas *r)
1784 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1791 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1792 struct netr_DatabaseSync2 *r)
1794 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1795 return NT_STATUS_NOT_IMPLEMENTED;
1802 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1803 struct netr_DatabaseSync *r)
1805 struct netr_DatabaseSync2 r2;
1810 r2.in.logon_server = r->in.logon_server;
1811 r2.in.computername = r->in.computername;
1812 r2.in.credential = r->in.credential;
1813 r2.in.database_id = r->in.database_id;
1814 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1815 r2.in.sync_context = r->in.sync_context;
1816 r2.out.sync_context = r->out.sync_context;
1817 r2.out.delta_enum_array = r->out.delta_enum_array;
1818 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1820 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1829 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1830 struct netr_AccountDeltas *r)
1832 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1833 return NT_STATUS_NOT_IMPLEMENTED;
1840 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1841 struct netr_AccountSync *r)
1843 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1844 return NT_STATUS_NOT_IMPLEMENTED;
1851 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1852 struct netr_GetDcName *r)
1854 const char * const attrs[] = { NULL };
1855 struct ldb_context *sam_ctx;
1856 struct ldb_message **res;
1857 struct ldb_dn *domain_dn;
1862 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1863 * that the domainname needs to be a valid netbios domain
1864 * name, if it is not NULL.
1866 if (r->in.domainname) {
1867 const char *dot = strchr(r->in.domainname, '.');
1868 size_t len = strlen(r->in.domainname);
1870 if (dot || len > 15) {
1871 return WERR_NERR_DCNOTFOUND;
1875 * TODO: Should we also verify that only valid
1876 * netbios name characters are used?
1880 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
1881 if (sam_ctx == NULL) {
1882 return WERR_DS_UNAVAILABLE;
1885 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1887 if (domain_dn == NULL) {
1888 return WERR_NO_SUCH_DOMAIN;
1891 ret = gendb_search_dn(sam_ctx, mem_ctx,
1892 domain_dn, &res, attrs);
1894 return WERR_NO_SUCH_DOMAIN;
1897 /* TODO: - return real IP address
1898 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1900 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1901 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1902 W_ERROR_HAVE_NO_MEMORY(dcname);
1904 *r->out.dcname = dcname;
1908 struct dcesrv_netr_LogonControl_base_state {
1909 struct dcesrv_call_state *dce_call;
1911 TALLOC_CTX *mem_ctx;
1913 struct netr_LogonControl2Ex r;
1916 struct netr_LogonControl *l;
1917 struct netr_LogonControl2 *l2;
1918 struct netr_LogonControl2Ex *l2ex;
1922 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1924 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1926 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1927 struct auth_session_info *session_info =
1928 dcesrv_call_session_info(state->dce_call);
1929 struct imessaging_context *imsg_ctx =
1930 dcesrv_imessaging_context(state->dce_call->conn);
1931 enum security_user_level security_level;
1932 struct dcerpc_binding_handle *irpc_handle;
1933 struct tevent_req *subreq;
1936 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1938 if (state->_r.l != NULL) {
1942 if (state->r.in.level == 0x00000002) {
1943 return WERR_NOT_SUPPORTED;
1944 } else if (state->r.in.level != 0x00000001) {
1945 return WERR_INVALID_LEVEL;
1948 switch (state->r.in.function_code) {
1949 case NETLOGON_CONTROL_QUERY:
1950 case NETLOGON_CONTROL_REPLICATE:
1951 case NETLOGON_CONTROL_SYNCHRONIZE:
1952 case NETLOGON_CONTROL_PDC_REPLICATE:
1953 case NETLOGON_CONTROL_BREAKPOINT:
1954 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1955 case NETLOGON_CONTROL_TRUNCATE_LOG:
1958 return WERR_NOT_SUPPORTED;
1962 if (state->r.in.level < 0x00000001) {
1963 return WERR_INVALID_LEVEL;
1966 if (state->r.in.level > 0x00000004) {
1967 return WERR_INVALID_LEVEL;
1970 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1971 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1972 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1974 switch (state->r.in.level) {
1976 info1 = talloc_zero(state->mem_ctx,
1977 struct netr_NETLOGON_INFO_1);
1978 if (info1 == NULL) {
1979 return WERR_NOT_ENOUGH_MEMORY;
1981 state->r.out.query->info1 = info1;
1985 info3 = talloc_zero(state->mem_ctx,
1986 struct netr_NETLOGON_INFO_3);
1987 if (info3 == NULL) {
1988 return WERR_NOT_ENOUGH_MEMORY;
1990 state->r.out.query->info3 = info3;
1994 return WERR_INVALID_PARAMETER;
1999 * Some validations are done before the access check
2000 * and some after the access check
2002 security_level = security_session_user_level(session_info, NULL);
2003 if (security_level < SECURITY_ADMINISTRATOR) {
2004 return WERR_ACCESS_DENIED;
2007 if (state->_r.l2 != NULL) {
2009 * netr_LogonControl2
2011 if (state->r.in.level == 0x00000004) {
2012 return WERR_INVALID_LEVEL;
2016 switch (state->r.in.level) {
2021 switch (state->r.in.function_code) {
2022 case NETLOGON_CONTROL_REDISCOVER:
2023 case NETLOGON_CONTROL_TC_QUERY:
2024 case NETLOGON_CONTROL_TC_VERIFY:
2027 return WERR_INVALID_PARAMETER;
2036 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
2037 return WERR_INVALID_PARAMETER;
2043 return WERR_INVALID_LEVEL;
2046 switch (state->r.in.function_code) {
2047 case NETLOGON_CONTROL_REDISCOVER:
2048 case NETLOGON_CONTROL_TC_QUERY:
2049 case NETLOGON_CONTROL_TC_VERIFY:
2050 if (state->r.in.level != 2) {
2051 return WERR_INVALID_PARAMETER;
2054 if (state->r.in.data == NULL) {
2055 return WERR_INVALID_PARAMETER;
2058 if (state->r.in.data->domain == NULL) {
2059 return WERR_INVALID_PARAMETER;
2064 case NETLOGON_CONTROL_CHANGE_PASSWORD:
2065 if (state->r.in.level != 1) {
2066 return WERR_INVALID_PARAMETER;
2069 if (state->r.in.data == NULL) {
2070 return WERR_INVALID_PARAMETER;
2073 if (state->r.in.data->domain == NULL) {
2074 return WERR_INVALID_PARAMETER;
2077 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
2078 state->r.in.data->domain);
2080 struct ldb_context *sam_ctx;
2082 sam_ctx = dcesrv_samdb_connect_as_system(state,
2084 if (sam_ctx == NULL) {
2085 return WERR_DS_UNAVAILABLE;
2089 * Secrets for trusted domains can only be triggered on
2092 ok = samdb_is_pdc(sam_ctx);
2093 TALLOC_FREE(sam_ctx);
2095 return WERR_INVALID_DOMAIN_ROLE;
2101 return WERR_NOT_SUPPORTED;
2104 irpc_handle = irpc_binding_handle_by_name(state,
2107 &ndr_table_winbind);
2108 if (irpc_handle == NULL) {
2109 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2110 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2111 return WERR_SERVICE_NOT_FOUND;
2115 * 60 seconds timeout should be enough
2117 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2119 subreq = dcerpc_winbind_LogonControl_send(state,
2120 state->dce_call->event_ctx,
2122 state->r.in.function_code,
2125 state->r.out.query);
2126 if (subreq == NULL) {
2127 return WERR_NOT_ENOUGH_MEMORY;
2129 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2130 tevent_req_set_callback(subreq,
2131 dcesrv_netr_LogonControl_base_done,
2137 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
2139 struct dcesrv_netr_LogonControl_base_state *state =
2140 tevent_req_callback_data(subreq,
2141 struct dcesrv_netr_LogonControl_base_state);
2144 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
2145 &state->r.out.result);
2146 TALLOC_FREE(subreq);
2147 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
2148 state->r.out.result = WERR_TIMEOUT;
2149 } else if (!NT_STATUS_IS_OK(status)) {
2150 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2151 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
2152 nt_errstr(status)));
2155 if (state->_r.l2ex != NULL) {
2156 struct netr_LogonControl2Ex *r = state->_r.l2ex;
2157 r->out.result = state->r.out.result;
2158 } else if (state->_r.l2 != NULL) {
2159 struct netr_LogonControl2 *r = state->_r.l2;
2160 r->out.result = state->r.out.result;
2161 } else if (state->_r.l != NULL) {
2162 struct netr_LogonControl *r = state->_r.l;
2163 r->out.result = state->r.out.result;
2166 status = dcesrv_reply(state->dce_call);
2167 if (!NT_STATUS_IS_OK(status)) {
2168 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2175 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2176 struct netr_LogonControl *r)
2178 struct dcesrv_netr_LogonControl_base_state *state;
2181 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2182 if (state == NULL) {
2183 return WERR_NOT_ENOUGH_MEMORY;
2186 state->dce_call = dce_call;
2187 state->mem_ctx = mem_ctx;
2189 state->r.in.logon_server = r->in.logon_server;
2190 state->r.in.function_code = r->in.function_code;
2191 state->r.in.level = r->in.level;
2192 state->r.in.data = NULL;
2193 state->r.out.query = r->out.query;
2197 werr = dcesrv_netr_LogonControl_base_call(state);
2199 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2209 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2210 struct netr_LogonControl2 *r)
2212 struct dcesrv_netr_LogonControl_base_state *state;
2215 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2216 if (state == NULL) {
2217 return WERR_NOT_ENOUGH_MEMORY;
2220 state->dce_call = dce_call;
2221 state->mem_ctx = mem_ctx;
2223 state->r.in.logon_server = r->in.logon_server;
2224 state->r.in.function_code = r->in.function_code;
2225 state->r.in.level = r->in.level;
2226 state->r.in.data = r->in.data;
2227 state->r.out.query = r->out.query;
2231 werr = dcesrv_netr_LogonControl_base_call(state);
2233 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2241 netr_LogonControl2Ex
2243 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2244 struct netr_LogonControl2Ex *r)
2246 struct dcesrv_netr_LogonControl_base_state *state;
2249 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2250 if (state == NULL) {
2251 return WERR_NOT_ENOUGH_MEMORY;
2254 state->dce_call = dce_call;
2255 state->mem_ctx = mem_ctx;
2260 werr = dcesrv_netr_LogonControl_base_call(state);
2262 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2269 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2270 struct ldb_context *sam_ctx,
2271 struct netr_DomainTrustList *trusts,
2272 uint32_t trust_flags);
2277 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2278 struct netr_GetAnyDCName *r)
2280 struct netr_DomainTrustList *trusts;
2281 struct ldb_context *sam_ctx;
2282 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2286 *r->out.dcname = NULL;
2288 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2289 /* if the domainname parameter wasn't set assume our domain */
2290 r->in.domainname = lpcfg_workgroup(lp_ctx);
2293 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2294 if (sam_ctx == NULL) {
2295 return WERR_DS_UNAVAILABLE;
2298 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2299 /* well we asked for a DC of our own domain */
2300 if (samdb_is_pdc(sam_ctx)) {
2301 /* we are the PDC of the specified domain */
2302 return WERR_NO_SUCH_DOMAIN;
2305 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2306 lpcfg_netbios_name(lp_ctx));
2307 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2312 /* Okay, now we have to consider the trusted domains */
2314 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2315 W_ERROR_HAVE_NO_MEMORY(trusts);
2319 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2320 NETR_TRUST_FLAG_INBOUND
2321 | NETR_TRUST_FLAG_OUTBOUND);
2322 W_ERROR_NOT_OK_RETURN(werr);
2324 for (i = 0; i < trusts->count; i++) {
2325 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2326 /* FIXME: Here we need to find a DC for the specified
2327 * trusted domain. */
2329 /* return WERR_OK; */
2330 return WERR_NO_SUCH_DOMAIN;
2334 return WERR_NO_SUCH_DOMAIN;
2341 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2342 struct netr_DatabaseRedo *r)
2344 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2349 netr_NetrEnumerateTrustedDomains
2351 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2352 struct netr_NetrEnumerateTrustedDomains *r)
2354 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2359 netr_LogonGetCapabilities
2361 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2362 struct netr_LogonGetCapabilities *r)
2364 struct netlogon_creds_CredentialState *creds;
2367 switch (r->in.query_level) {
2372 * Until we know the details behind KB5028166
2373 * just return DCERPC_NCA_S_FAULT_INVALID_TAG
2374 * like an unpatched Windows Server.
2379 * There would not be a way to marshall the
2380 * the response. Which would mean our final
2381 * ndr_push would fail an we would return
2382 * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA.
2384 * But it's important to match a Windows server
2385 * especially before KB5028166, see also our bug #15418
2386 * Otherwise Windows client would stop talking to us.
2388 DCESRV_FAULT(DCERPC_NCA_S_FAULT_INVALID_TAG);
2391 status = dcesrv_netr_creds_server_step_check(dce_call,
2393 r->in.computer_name,
2395 r->out.return_authenticator,
2397 if (!NT_STATUS_IS_OK(status)) {
2398 DEBUG(0,(__location__ " Bad credentials - error\n"));
2400 NT_STATUS_NOT_OK_RETURN(status);
2402 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2404 return NT_STATUS_OK;
2409 netr_NETRLOGONSETSERVICEBITS
2411 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2412 struct netr_NETRLOGONSETSERVICEBITS *r)
2414 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2419 netr_LogonGetTrustRid
2421 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2422 struct netr_LogonGetTrustRid *r)
2424 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2429 netr_NETRLOGONCOMPUTESERVERDIGEST
2431 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2432 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2434 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2439 netr_NETRLOGONCOMPUTECLIENTDIGEST
2441 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2442 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2444 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2452 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2453 struct netr_DsRGetSiteName *r)
2455 struct ldb_context *sam_ctx;
2457 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2458 if (sam_ctx == NULL) {
2459 return WERR_DS_UNAVAILABLE;
2463 * We assume to be a DC when we get called over NETLOGON. Hence we
2464 * get our site name always by using "samdb_server_site_name()"
2465 * and not "samdb_client_site_name()".
2467 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2468 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2475 fill in a netr_OneDomainInfo from our own domain/forest
2477 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2478 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2479 struct GUID domain_guid,
2480 struct netr_OneDomainInfo *info,
2485 if (is_trust_list) {
2486 struct netr_trust_extension *te = NULL;
2487 struct netr_trust_extension_info *tei = NULL;
2489 /* w2k8 only fills this on trusted domains */
2490 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2492 return NT_STATUS_NO_MEMORY;
2495 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2498 * We're always within a native forest
2500 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2501 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2503 /* For now we assume we're always the tree root */
2504 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2505 tei->parent_index = 0;
2507 tei->trust_type = our_tdo->trust_type;
2509 * This needs to be 0 instead of our_tdo->trust_attributes
2510 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2511 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2513 tei->trust_attributes = 0;
2515 info->trust_extension.info = te;
2518 if (is_trust_list) {
2519 info->dns_domainname.string = our_tdo->domain_name.string;
2521 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2522 info->dns_forestname.string = NULL;
2524 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2525 our_tdo->domain_name.string);
2526 if (info->dns_domainname.string == NULL) {
2527 return NT_STATUS_NO_MEMORY;
2530 info->dns_forestname.string = info->dns_domainname.string;
2533 info->domainname.string = our_tdo->netbios_name.string;
2534 info->domain_sid = our_tdo->sid;
2535 info->domain_guid = domain_guid;
2537 return NT_STATUS_OK;
2541 fill in a netr_OneDomainInfo from a trust tdo
2543 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2544 struct GUID domain_guid,
2545 const struct lsa_TrustDomainInfoInfoEx *tdo,
2546 struct netr_OneDomainInfo *info)
2548 struct netr_trust_extension *te = NULL;
2549 struct netr_trust_extension_info *tei = NULL;
2553 /* w2k8 only fills this on trusted domains */
2554 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2556 return NT_STATUS_NO_MEMORY;
2560 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2561 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2563 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2564 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2566 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2567 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2571 * TODO: once we support multiple domains within our forest,
2572 * we need to fill this correct (or let the caller do it
2573 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2575 tei->parent_index = 0;
2577 tei->trust_type = tdo->trust_type;
2578 tei->trust_attributes = tdo->trust_attributes;
2580 info->trust_extension.info = te;
2582 info->domainname.string = tdo->netbios_name.string;
2583 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2584 info->dns_domainname.string = tdo->domain_name.string;
2586 info->dns_domainname.string = NULL;
2588 info->domain_sid = tdo->sid;
2589 info->domain_guid = domain_guid;
2591 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2592 info->dns_forestname.string = NULL;
2594 return NT_STATUS_OK;
2598 netr_LogonGetDomainInfo
2599 this is called as part of the ADS domain logon procedure.
2601 It has an important role in convaying details about the client, such
2602 as Operating System, Version, Service Pack etc.
2604 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2605 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2607 struct netlogon_creds_CredentialState *creds;
2608 const char * const trusts_attrs[] = {
2609 "securityIdentifier",
2617 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2618 "msDS-SupportedEncryptionTypes", NULL };
2619 const char *sam_account_name, *old_dns_hostname;
2620 struct ldb_context *sam_ctx;
2621 const struct GUID *our_domain_guid = NULL;
2622 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2623 struct ldb_message **res1, *new_msg;
2624 struct ldb_result *trusts_res = NULL;
2625 struct ldb_dn *workstation_dn;
2626 struct netr_DomainInformation *domain_info;
2627 struct netr_LsaPolicyInformation *lsa_policy_info;
2628 struct auth_session_info *workstation_session_info = NULL;
2629 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2630 bool update_dns_hostname = true;
2634 status = dcesrv_netr_creds_server_step_check(dce_call,
2636 r->in.computer_name,
2638 r->out.return_authenticator,
2640 if (!NT_STATUS_IS_OK(status)) {
2642 char* remote = NULL;
2643 TALLOC_CTX *frame = talloc_stackframe();
2644 remote = tsocket_address_string(dce_call->conn->remote_address,
2646 local = tsocket_address_string(dce_call->conn->local_address,
2648 DBG_ERR("Bad credentials - "
2649 "computer[%s] remote[%s] local[%s]\n",
2650 log_escape(frame, r->in.computer_name),
2655 NT_STATUS_NOT_OK_RETURN(status);
2657 /* We want to avoid connecting as system. */
2658 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2659 if (sam_ctx == NULL) {
2660 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2663 switch (r->in.level) {
2664 case 1: /* Domain information */
2666 if (r->in.query->workstation_info == NULL) {
2667 return NT_STATUS_INVALID_PARAMETER;
2670 /* Prepares the workstation DN */
2671 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2672 dom_sid_string(mem_ctx, creds->sid));
2673 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2675 /* Get the workstation's session info from the database. */
2676 status = authsam_get_session_info_principal(mem_ctx,
2677 dce_call->conn->dce_ctx->lp_ctx,
2679 NULL, /* principal */
2681 0, /* session_info_flags */
2682 &workstation_session_info);
2683 if (!NT_STATUS_IS_OK(status)) {
2688 * Reconnect to samdb as the workstation, now that we have its
2689 * session info. We do this so the database update can be
2690 * attributed to the workstation account in the audit logs --
2691 * otherwise it might be incorrectly attributed to
2694 sam_ctx = dcesrv_samdb_connect_session_info(mem_ctx,
2696 workstation_session_info,
2697 workstation_session_info);
2698 if (sam_ctx == NULL) {
2699 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2702 /* Lookup for attributes in workstation object */
2703 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2706 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2709 /* Gets the sam account name which is checked against the DNS
2710 * hostname parameter. */
2711 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2714 if (sam_account_name == NULL) {
2715 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2718 if (r->in.query->workstation_info->dns_hostname == NULL) {
2719 update_dns_hostname = false;
2722 /* Gets the old DNS hostname */
2723 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2728 * Updates the DNS hostname when the client wishes that the
2729 * server should handle this for him
2730 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
2731 * See MS-NRPC section 3.5.4.3.9
2733 if ((r->in.query->workstation_info->workstation_flags
2734 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2735 update_dns_hostname = false;
2738 /* Gets host information and put them into our directory */
2740 new_msg = ldb_msg_new(mem_ctx);
2741 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2743 new_msg->dn = workstation_dn;
2745 /* Sets the OS name */
2747 if (r->in.query->workstation_info->os_name.string == NULL) {
2748 return NT_STATUS_INVALID_PARAMETER;
2751 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2752 r->in.query->workstation_info->os_name.string);
2753 if (ret != LDB_SUCCESS) {
2754 return NT_STATUS_NO_MEMORY;
2758 * Sets information from "os_version". On an empty structure
2759 * the values are cleared.
2761 if (r->in.query->workstation_info->os_version.os != NULL) {
2762 struct netr_OsVersionInfoEx *os_version;
2763 const char *os_version_str;
2765 os_version = &r->in.query->workstation_info->os_version.os->os;
2767 if (os_version->CSDVersion == NULL) {
2768 return NT_STATUS_INVALID_PARAMETER;
2771 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2772 os_version->MajorVersion,
2773 os_version->MinorVersion,
2774 os_version->BuildNumber);
2775 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2777 if (strlen(os_version->CSDVersion) != 0) {
2778 ret = ldb_msg_add_string(new_msg,
2779 "operatingSystemServicePack",
2780 os_version->CSDVersion);
2782 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2783 "operatingSystemServicePack");
2785 if (ret != LDB_SUCCESS) {
2786 return NT_STATUS_NO_MEMORY;
2789 ret = ldb_msg_add_string(new_msg,
2790 "operatingSystemVersion",
2792 if (ret != LDB_SUCCESS) {
2793 return NT_STATUS_NO_MEMORY;
2796 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2797 "operatingSystemServicePack");
2798 if (ret != LDB_SUCCESS) {
2799 return NT_STATUS_NO_MEMORY;
2802 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2803 "operatingSystemVersion");
2804 if (ret != LDB_SUCCESS) {
2805 return NT_STATUS_NO_MEMORY;
2810 * If the boolean "update_dns_hostname" remained true, then we
2811 * are fine to start the update.
2813 if (update_dns_hostname) {
2814 ret = ldb_msg_add_string(new_msg,
2816 r->in.query->workstation_info->dns_hostname);
2817 if (ret != LDB_SUCCESS) {
2818 return NT_STATUS_NO_MEMORY;
2821 /* This manual "servicePrincipalName" generation is
2822 * still needed! Since the update in the samldb LDB
2823 * module does only work if the entries already exist
2824 * which isn't always the case. */
2825 ret = ldb_msg_add_string(new_msg,
2826 "servicePrincipalName",
2827 talloc_asprintf(new_msg, "HOST/%s",
2828 r->in.computer_name));
2829 if (ret != LDB_SUCCESS) {
2830 return NT_STATUS_NO_MEMORY;
2833 ret = ldb_msg_add_string(new_msg,
2834 "servicePrincipalName",
2835 talloc_asprintf(new_msg, "HOST/%s",
2836 r->in.query->workstation_info->dns_hostname));
2837 if (ret != LDB_SUCCESS) {
2838 return NT_STATUS_NO_MEMORY;
2842 if (dsdb_replace(sam_ctx, new_msg, DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) != LDB_SUCCESS) {
2843 DEBUG(3,("Impossible to update samdb: %s\n",
2844 ldb_errstring(sam_ctx)));
2847 talloc_free(new_msg);
2849 /* Writes back the domain information */
2851 our_domain_guid = samdb_domain_guid(sam_ctx);
2852 if (our_domain_guid == NULL) {
2853 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2856 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2857 if (!NT_STATUS_IS_OK(status)) {
2861 status = dsdb_trust_search_tdos(sam_ctx,
2866 if (!NT_STATUS_IS_OK(status)) {
2870 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2871 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2873 ZERO_STRUCTP(domain_info);
2875 /* Information about the local and trusted domains */
2877 status = fill_our_one_domain_info(mem_ctx,
2880 &domain_info->primary_domain,
2882 if (!NT_STATUS_IS_OK(status)) {
2886 domain_info->trusted_domain_count = trusts_res->count + 1;
2887 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2888 struct netr_OneDomainInfo,
2889 domain_info->trusted_domain_count);
2890 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2892 for (i=0; i < trusts_res->count; i++) {
2893 struct netr_OneDomainInfo *o =
2894 &domain_info->trusted_domains[i];
2895 /* we can't know the guid of trusts outside our forest */
2896 struct GUID trust_domain_guid = GUID_zero();
2897 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2899 status = dsdb_trust_parse_tdo_info(mem_ctx,
2900 trusts_res->msgs[i],
2902 if (!NT_STATUS_IS_OK(status)) {
2906 status = fill_trust_one_domain_info(mem_ctx,
2910 if (!NT_STATUS_IS_OK(status)) {
2915 status = fill_our_one_domain_info(mem_ctx,
2918 &domain_info->trusted_domains[i],
2920 if (!NT_STATUS_IS_OK(status)) {
2924 /* Sets the supported encryption types */
2925 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2926 "msDS-SupportedEncryptionTypes",
2927 default_supported_enc_types);
2929 /* Other host domain information */
2931 lsa_policy_info = talloc(mem_ctx,
2932 struct netr_LsaPolicyInformation);
2933 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2934 ZERO_STRUCTP(lsa_policy_info);
2936 domain_info->lsa_policy = *lsa_policy_info;
2938 /* The DNS hostname is only returned back when there is a chance
2940 if ((r->in.query->workstation_info->workstation_flags
2941 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2942 domain_info->dns_hostname.string = old_dns_hostname;
2944 domain_info->dns_hostname.string = NULL;
2947 domain_info->workstation_flags =
2948 r->in.query->workstation_info->workstation_flags & (
2949 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2951 r->out.info->domain_info = domain_info;
2953 case 2: /* LSA policy information - not used at the moment */
2954 lsa_policy_info = talloc(mem_ctx,
2955 struct netr_LsaPolicyInformation);
2956 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2957 ZERO_STRUCTP(lsa_policy_info);
2959 r->out.info->lsa_policy_info = lsa_policy_info;
2962 return NT_STATUS_INVALID_LEVEL;
2966 return NT_STATUS_OK;
2971 netr_ServerPasswordGet
2973 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2974 struct netr_ServerPasswordGet *r)
2976 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2979 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2980 TALLOC_CTX *mem_ctx,
2981 struct dom_sid *user_sid,
2982 struct ldb_dn *obj_dn)
2984 const char *rodc_attrs[] = { "msDS-NeverRevealGroup",
2985 "msDS-RevealOnDemandGroup",
2986 "userAccountControl",
2988 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2989 struct ldb_dn *rodc_dn;
2991 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2994 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2995 dom_sid_string(mem_ctx, user_sid));
2996 if (!ldb_dn_validate(rodc_dn)) goto denied;
2999 * do the two searches we need
3000 * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list
3001 * out of the extended DNs
3003 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
3004 DSDB_SEARCH_SHOW_EXTENDED_DN);
3005 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
3007 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
3008 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
3010 werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx,
3015 if (W_ERROR_IS_OK(werr)) {
3026 netr_NetrLogonSendToSam
3028 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3029 struct netr_NetrLogonSendToSam *r)
3031 struct netlogon_creds_CredentialState *creds;
3032 struct ldb_context *sam_ctx;
3034 DATA_BLOB decrypted_blob;
3035 enum ndr_err_code ndr_err;
3036 struct netr_SendToSamBase base_msg = { 0 };
3038 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3040 r->in.computer_name,
3042 r->out.return_authenticator,
3045 NT_STATUS_NOT_OK_RETURN(nt_status);
3047 switch (creds->secure_channel_type) {
3051 case SEC_CHAN_WKSTA:
3052 case SEC_CHAN_DNS_DOMAIN:
3053 case SEC_CHAN_DOMAIN:
3055 return NT_STATUS_INVALID_PARAMETER;
3057 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
3058 creds->secure_channel_type));
3059 return NT_STATUS_INVALID_PARAMETER;
3062 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3063 if (sam_ctx == NULL) {
3064 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3067 /* Buffer is meant to be 16-bit aligned */
3068 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3069 nt_status = netlogon_creds_aes_decrypt(creds,
3070 r->in.opaque_buffer,
3073 nt_status = netlogon_creds_arcfour_crypt(creds,
3074 r->in.opaque_buffer,
3077 if (!NT_STATUS_IS_OK(nt_status)) {
3081 decrypted_blob.data = r->in.opaque_buffer;
3082 decrypted_blob.length = r->in.buffer_len;
3084 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
3085 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
3087 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3088 /* We only partially implement SendToSam */
3089 return NT_STATUS_NOT_IMPLEMENTED;
3092 /* Now 'send' to SAM */
3093 switch (base_msg.message_type) {
3094 case SendToSamResetBadPasswordCount:
3096 struct ldb_message *msg = ldb_msg_new(mem_ctx);
3097 struct ldb_dn *dn = NULL;
3101 ret = ldb_transaction_start(sam_ctx);
3102 if (ret != LDB_SUCCESS) {
3103 return NT_STATUS_INTERNAL_ERROR;
3106 ret = dsdb_find_dn_by_guid(sam_ctx,
3108 &base_msg.message.reset_bad_password.guid,
3111 if (ret != LDB_SUCCESS) {
3112 ldb_transaction_cancel(sam_ctx);
3113 return NT_STATUS_INVALID_PARAMETER;
3116 if (creds->secure_channel_type == SEC_CHAN_RODC &&
3117 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
3118 DEBUG(1, ("Client asked to reset bad password on "
3119 "an arbitrary user: %s\n",
3120 ldb_dn_get_linearized(dn)));
3121 ldb_transaction_cancel(sam_ctx);
3122 return NT_STATUS_INVALID_PARAMETER;
3127 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
3128 if (ret != LDB_SUCCESS) {
3129 ldb_transaction_cancel(sam_ctx);
3130 return NT_STATUS_INVALID_PARAMETER;
3133 ret = dsdb_replace(sam_ctx, msg, 0);
3134 if (ret != LDB_SUCCESS) {
3135 ldb_transaction_cancel(sam_ctx);
3136 return NT_STATUS_INVALID_PARAMETER;
3139 ret = ldb_transaction_commit(sam_ctx);
3140 if (ret != LDB_SUCCESS) {
3141 ldb_transaction_cancel(sam_ctx);
3142 return NT_STATUS_INTERNAL_ERROR;
3148 return NT_STATUS_NOT_IMPLEMENTED;
3151 return NT_STATUS_OK;
3154 struct dcesrv_netr_DsRGetDCName_base_state {
3155 struct dcesrv_call_state *dce_call;
3156 TALLOC_CTX *mem_ctx;
3158 struct netr_DsRGetDCNameEx2 r;
3159 const char *client_site;
3162 struct netr_DsRGetDCName *dc;
3163 struct netr_DsRGetDCNameEx *dcex;
3164 struct netr_DsRGetDCNameEx2 *dcex2;
3168 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
3170 /* Returns a nonzero value if multiple bits in 'val' are set. */
3171 static bool multiple_bits_set(uint32_t val)
3174 * Subtracting one from an integer has the effect of flipping all the
3175 * bits from the least significant bit up to and including the least
3176 * significant '1' bit. For example,
3182 * If 'val' is zero, all the bits will be flipped and thus the bitwise
3183 * AND of 'val' with 'val - 1' will be zero.
3185 * If the integer is nonzero, the least significant '1' bit will be
3186 * ANDed with a '0' bit and so will be reset in the final result, but
3187 * all other '1' bits will remain set. In other words, the effect of
3188 * this expression is to mask off the least significant bit that is
3189 * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
3190 * must contain multiple set bits.
3192 return val & (val - 1);
3195 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
3197 struct dcesrv_call_state *dce_call = state->dce_call;
3198 struct imessaging_context *imsg_ctx =
3199 dcesrv_imessaging_context(dce_call->conn);
3200 TALLOC_CTX *mem_ctx = state->mem_ctx;
3201 struct netr_DsRGetDCNameEx2 *r = &state->r;
3202 struct ldb_context *sam_ctx;
3203 struct netr_DsRGetDCNameInfo *info;
3204 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3205 const struct tsocket_address *local_address;
3206 char *local_addr = NULL;
3207 const struct tsocket_address *remote_address;
3208 char *remote_addr = NULL;
3209 const char *server_site_name;
3211 struct netlogon_samlogon_response response;
3213 const char *dc_name = NULL;
3214 const char *domain_name = NULL;
3216 bool different_domain = true;
3217 bool force_remote_lookup = false;
3218 uint32_t valid_flags;
3219 uint32_t this_dc_valid_flags;
3222 ZERO_STRUCTP(r->out.info);
3224 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3225 if (sam_ctx == NULL) {
3226 return WERR_DS_UNAVAILABLE;
3229 local_address = dcesrv_connection_get_local_address(dce_call->conn);
3230 if (tsocket_address_is_inet(local_address, "ip")) {
3231 local_addr = tsocket_address_inet_addr_string(local_address, state);
3232 W_ERROR_HAVE_NO_MEMORY(local_addr);
3235 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
3236 if (tsocket_address_is_inet(remote_address, "ip")) {
3237 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
3238 W_ERROR_HAVE_NO_MEMORY(remote_addr);
3241 /* "server_unc" is ignored by w2k3 */
3244 * With the following flags:
3245 * DS_FORCE_REDISCOVERY (Flag A)
3246 * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
3247 * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
3248 * DS_GC_SERVER_REQUIRED (Flag D)
3249 * DS_PDC_REQUIRED (Flag E)
3250 * DS_BACKGROUND_ONLY (Flag F)
3251 * DS_IP_REQUIRED (Flag G)
3252 * DS_KDC_REQUIRED (Flag H)
3253 * DS_TIMESERV_REQUIRED (Flag I)
3254 * DS_WRITABLE_REQUIRED (Flag J)
3255 * DS_GOOD_TIMESERV_PREFERRED (Flag K)
3256 * DS_AVOID_SELF (Flag L)
3257 * DS_ONLY_LDAP_NEEDED (Flag M)
3258 * DS_IS_FLAT_NAME (Flag N)
3259 * DS_IS_DNS_NAME (Flag O)
3260 * DS_TRY_NEXTCLOSEST_SITE (Flag P)
3261 * DS_DIRECTORY_SERVICE_6_REQUIRED (Flag Q)
3262 * DS_WEB_SERVICE_REQUIRED (Flag T)
3263 * DS_DIRECTORY_SERVICE_8_REQUIRED (Flag U)
3264 * DS_DIRECTORY_SERVICE_9_REQUIRED (Flag V)
3265 * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
3266 * DS_RETURN_DNS_NAME (Flag R)
3267 * DS_RETURN_FLAT_NAME (Flag S)
3269 * MS-NRPC 3.5.4.3.1 says:
3271 * On receiving this call, the server MUST perform the following Flags
3272 * parameter validations:
3273 * - Flags D, E, and H MUST NOT be combined with each other.
3274 * - Flag N MUST NOT be combined with the O flag.
3275 * - Flag R MUST NOT be combined with the S flag.
3276 * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
3277 * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or H.
3278 * - Flag P MUST NOT be set when the SiteName parameter is provided.
3279 * The server MUST return ERROR_INVALID_FLAGS for any of the previously
3280 * mentioned conflicting combinations.
3284 valid_flags = DSGETDC_VALID_FLAGS;
3286 if (r->in.flags & ~valid_flags) {
3288 * TODO: add tests to prove this (maybe based on the
3289 * msDS-Behavior-Version levels of dc, domain and/or forest
3291 return WERR_INVALID_FLAGS;
3294 /* Flags D, E, and H MUST NOT be combined with each other. */
3295 #define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
3296 if (multiple_bits_set(r->in.flags & _DEH)) {
3297 return WERR_INVALID_FLAGS;
3300 /* Flag N MUST NOT be combined with the O flag. */
3301 if (r->in.flags & DS_IS_FLAT_NAME &&
3302 r->in.flags & DS_IS_DNS_NAME) {
3303 return WERR_INVALID_FLAGS;
3306 /* Flag R MUST NOT be combined with the S flag. */
3307 if (r->in.flags & DS_RETURN_DNS_NAME &&
3308 r->in.flags & DS_RETURN_FLAT_NAME) {
3309 return WERR_INVALID_FLAGS;
3312 /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
3314 DS_DIRECTORY_SERVICE_REQUIRED | \
3315 DS_DIRECTORY_SERVICE_6_REQUIRED | \
3316 DS_DIRECTORY_SERVICE_8_REQUIRED | \
3317 DS_DIRECTORY_SERVICE_9_REQUIRED | \
3318 DS_DIRECTORY_SERVICE_10_REQUIRED | \
3320 if (multiple_bits_set(r->in.flags & _BQUVW)) {
3321 return WERR_INVALID_FLAGS;
3325 * Flag K MUST NOT be combined with any of the flags:
3328 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
3330 (DS_DIRECTORY_SERVICE_REQUIRED |
3331 DS_DIRECTORY_SERVICE_PREFERRED |
3332 DS_GC_SERVER_REQUIRED |
3335 return WERR_INVALID_FLAGS;
3338 /* Flag P MUST NOT be set when the SiteName parameter is provided. */
3339 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
3341 return WERR_INVALID_FLAGS;
3345 * If we send an all-zero GUID, we should ignore it as winbind actually
3346 * checks it with a DNS query. Windows also appears to ignore it.
3348 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
3349 r->in.domain_guid = NULL;
3352 /* Attempt winbind search only if we suspect the domain is incorrect */
3353 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
3354 if (r->in.flags & DS_IS_FLAT_NAME) {
3355 if (strcasecmp_m(r->in.domain_name,
3356 lpcfg_sam_name(lp_ctx)) == 0) {
3357 different_domain = false;
3359 } else if (r->in.flags & DS_IS_DNS_NAME) {
3360 if (strcasecmp_m(r->in.domain_name,
3361 lpcfg_dnsdomain(lp_ctx)) == 0) {
3362 different_domain = false;
3365 if (strcasecmp_m(r->in.domain_name,
3366 lpcfg_sam_name(lp_ctx)) == 0 ||
3367 strcasecmp_m(r->in.domain_name,
3368 lpcfg_dnsdomain(lp_ctx)) == 0) {
3369 different_domain = false;
3374 * We need to be able to handle empty domain names, where we
3375 * revert to our domain by default.
3377 different_domain = false;
3380 if (!different_domain) {
3381 dc_level = dsdb_dc_functional_level(sam_ctx);
3384 * Do not return a local response if we do not support the
3385 * functional level or feature (eg web services)
3387 this_dc_valid_flags = valid_flags;
3389 /* Samba does not implement this */
3390 this_dc_valid_flags &= ~DS_WEB_SERVICE_REQUIRED;
3392 if (dc_level < DS_DOMAIN_FUNCTION_2012) {
3393 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_8_REQUIRED;
3395 if (dc_level < DS_DOMAIN_FUNCTION_2012_R2) {
3396 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_9_REQUIRED;
3398 if (dc_level < DS_DOMAIN_FUNCTION_2016) {
3399 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_10_REQUIRED;
3401 if (r->in.flags & ~this_dc_valid_flags) {
3402 DBG_INFO("Forcing remote lookup to find another DC "
3403 "in this domain %s with more features, "
3404 "as this Samba DC is Functional level %d but flags are 0x08%x\n",
3405 r->in.domain_name, dc_level, (unsigned int)r->in.flags);
3406 force_remote_lookup = true;
3410 /* Proof server site parameter "site_name" if it was specified */
3411 server_site_name = samdb_server_site_name(sam_ctx, state);
3412 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3413 if (force_remote_lookup
3415 || (r->in.site_name != NULL &&
3416 (strcasecmp_m(r->in.site_name,
3417 server_site_name) != 0))) {
3419 struct dcerpc_binding_handle *irpc_handle = NULL;
3420 struct tevent_req *subreq = NULL;
3423 * Retrieve the client site to override the winbind response.
3425 * DO NOT use Windows fallback for client site.
3426 * In the case of multiple domains, this is plainly wrong.
3428 * Note: It's possible that the client may belong to multiple
3429 * subnets across domains. It's not clear what this would mean,
3430 * but here we only return what this domain knows.
3432 state->client_site = samdb_client_site_name(sam_ctx,
3438 irpc_handle = irpc_binding_handle_by_name(state,
3441 &ndr_table_winbind);
3442 if (irpc_handle == NULL) {
3443 DEBUG(0,("Failed to get binding_handle for "
3444 "winbind_server task\n"));
3445 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3446 return WERR_SERVICE_NOT_FOUND;
3449 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3451 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3453 subreq = dcerpc_wbint_DsGetDcName_send(state,
3454 dce_call->event_ctx,
3461 if (subreq == NULL) {
3462 return WERR_NOT_ENOUGH_MEMORY;
3465 tevent_req_set_callback(subreq,
3466 dcesrv_netr_DsRGetDCName_base_done,
3472 guid_str = r->in.domain_guid != NULL ?
3473 GUID_string(state, r->in.domain_guid) : NULL;
3475 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3479 r->in.client_account,
3480 r->in.mask, remote_addr,
3481 NETLOGON_NT_VERSION_5EX_WITH_IP,
3482 lp_ctx, &response, true);
3483 if (!NT_STATUS_IS_OK(status)) {
3484 return ntstatus_to_werror(status);
3488 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3489 * (O) flag when the returned forest name is in DNS format. This is here
3490 * always the case (see below).
3492 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3494 if (r->in.flags & DS_RETURN_DNS_NAME) {
3495 dc_name = response.data.nt5_ex.pdc_dns_name;
3496 domain_name = response.data.nt5_ex.dns_domain;
3498 * According to MS-NRPC 2.2.1.2.1 we should set the
3499 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3500 * the returned information is in DNS form.
3502 response.data.nt5_ex.server_type |=
3503 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3504 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3505 dc_name = response.data.nt5_ex.pdc_name;
3506 domain_name = response.data.nt5_ex.domain_name;
3510 * TODO: autodetect what we need to return
3511 * based on the given arguments
3513 dc_name = response.data.nt5_ex.pdc_name;
3514 domain_name = response.data.nt5_ex.domain_name;
3517 if (!dc_name || !dc_name[0]) {
3518 return WERR_NO_SUCH_DOMAIN;
3521 if (!domain_name || !domain_name[0]) {
3522 return WERR_NO_SUCH_DOMAIN;
3525 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3526 W_ERROR_HAVE_NO_MEMORY(info);
3527 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3528 dc_name[0] != '\\'? "\\\\":"",
3529 talloc_strdup(mem_ctx, dc_name));
3530 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3532 pdc_ip = local_addr;
3533 if (pdc_ip == NULL) {
3534 pdc_ip = "127.0.0.1";
3536 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3537 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3538 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3539 info->domain_guid = response.data.nt5_ex.domain_uuid;
3540 info->domain_name = domain_name;
3541 info->forest_name = response.data.nt5_ex.forest;
3542 info->dc_flags = response.data.nt5_ex.server_type;
3543 if (r->in.flags & DS_RETURN_DNS_NAME) {
3544 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3545 * returned if we are returning info->dc_unc containing a FQDN.
3546 * This attribute is called DomainControllerName in the specs,
3547 * it seems that we decide to return FQDN or netbios depending on
3548 * DS_RETURN_DNS_NAME.
3550 info->dc_flags |= DS_DNS_CONTROLLER;
3552 info->dc_site_name = response.data.nt5_ex.server_site;
3553 info->client_site_name = response.data.nt5_ex.client_site;
3555 *r->out.info = info;
3560 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3562 struct dcesrv_netr_DsRGetDCName_base_state *state =
3563 tevent_req_callback_data(subreq,
3564 struct dcesrv_netr_DsRGetDCName_base_state);
3565 struct dcesrv_call_state *dce_call = state->dce_call;
3566 NTSTATUS result, status;
3568 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3571 TALLOC_FREE(subreq);
3573 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3574 state->r.out.result = WERR_TIMEOUT;
3578 if (!NT_STATUS_IS_OK(status)) {
3579 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3581 state->r.out.result = WERR_GEN_FAILURE;
3585 if (!NT_STATUS_IS_OK(result)) {
3586 DBG_NOTICE("DC location via winbind failed - %s\n",
3588 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3592 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3593 DBG_ERR("DC location via winbind returned no results\n");
3594 state->r.out.result = WERR_GEN_FAILURE;
3598 if (state->r.out.info[0]->dc_unc == NULL) {
3599 DBG_ERR("DC location via winbind returned no DC unc\n");
3600 state->r.out.result = WERR_GEN_FAILURE;
3605 * Either the supplied site name is NULL (possibly via
3606 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3607 * the input match name.
3609 * TODO: Currently this means that requests with NETBIOS domain
3610 * names can fail because they do not return the site name.
3612 if (state->r.in.site_name == NULL ||
3613 strcasecmp_m("", state->r.in.site_name) == 0 ||
3614 (state->r.out.info[0]->dc_site_name != NULL &&
3615 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3616 state->r.in.site_name) == 0)) {
3618 state->r.out.info[0]->client_site_name =
3619 talloc_move(state->mem_ctx, &state->client_site);
3622 * Make sure to return our DC UNC with // prefix.
3623 * Winbind currently doesn't send the leading slashes
3626 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3627 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3628 const char *dc_unc = NULL;
3630 dc_unc = talloc_asprintf(state->mem_ctx,
3632 state->r.out.info[0]->dc_unc);
3633 state->r.out.info[0]->dc_unc = dc_unc;
3636 state->r.out.result = WERR_OK;
3638 state->r.out.info = NULL;
3639 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3643 if (state->_r.dcex2 != NULL) {
3644 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3645 r->out.result = state->r.out.result;
3646 } else if (state->_r.dcex != NULL) {
3647 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3648 r->out.result = state->r.out.result;
3649 } else if (state->_r.dc != NULL) {
3650 struct netr_DsRGetDCName *r = state->_r.dc;
3651 r->out.result = state->r.out.result;
3655 status = dcesrv_reply(dce_call);
3656 if (!NT_STATUS_IS_OK(status)) {
3657 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3658 nt_errstr(status)));
3663 netr_DsRGetDCNameEx2
3665 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3666 TALLOC_CTX *mem_ctx,
3667 struct netr_DsRGetDCNameEx2 *r)
3669 struct dcesrv_netr_DsRGetDCName_base_state *state;
3671 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3672 if (state == NULL) {
3673 return WERR_NOT_ENOUGH_MEMORY;
3676 state->dce_call = dce_call;
3677 state->mem_ctx = mem_ctx;
3680 state->_r.dcex2 = r;
3682 return dcesrv_netr_DsRGetDCName_base_call(state);
3688 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3689 struct netr_DsRGetDCNameEx *r)
3691 struct dcesrv_netr_DsRGetDCName_base_state *state;
3693 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3694 if (state == NULL) {
3695 return WERR_NOT_ENOUGH_MEMORY;
3698 state->dce_call = dce_call;
3699 state->mem_ctx = mem_ctx;
3701 state->r.in.server_unc = r->in.server_unc;
3702 state->r.in.client_account = NULL;
3703 state->r.in.mask = 0;
3704 state->r.in.domain_guid = r->in.domain_guid;
3705 state->r.in.domain_name = r->in.domain_name;
3706 state->r.in.site_name = r->in.site_name;
3707 state->r.in.flags = r->in.flags;
3708 state->r.out.info = r->out.info;
3712 return dcesrv_netr_DsRGetDCName_base_call(state);
3718 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3719 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3720 * insists that it be ignored.
3722 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3723 struct netr_DsRGetDCName *r)
3725 struct dcesrv_netr_DsRGetDCName_base_state *state;
3727 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3728 if (state == NULL) {
3729 return WERR_NOT_ENOUGH_MEMORY;
3732 state->dce_call = dce_call;
3733 state->mem_ctx = mem_ctx;
3735 state->r.in.server_unc = r->in.server_unc;
3736 state->r.in.client_account = NULL;
3737 state->r.in.mask = 0;
3738 state->r.in.domain_name = r->in.domain_name;
3739 state->r.in.domain_guid = r->in.domain_guid;
3741 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3742 state->r.in.flags = r->in.flags;
3743 state->r.out.info = r->out.info;
3747 return dcesrv_netr_DsRGetDCName_base_call(state);
3750 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3752 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3753 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3755 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3760 netr_NetrEnumerateTrustedDomainsEx
3762 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3763 struct netr_NetrEnumerateTrustedDomainsEx *r)
3765 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3770 netr_DsRAddressToSitenamesExW
3772 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3773 struct netr_DsRAddressToSitenamesExW *r)
3775 struct ldb_context *sam_ctx;
3776 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3777 sa_family_t sin_family;
3778 struct sockaddr_in *addr;
3780 struct sockaddr_in6 *addr6;
3781 char addr_str[INET6_ADDRSTRLEN];
3783 char addr_str[INET_ADDRSTRLEN];
3789 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3790 if (sam_ctx == NULL) {
3791 return WERR_DS_UNAVAILABLE;
3794 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3795 W_ERROR_HAVE_NO_MEMORY(ctr);
3799 ctr->count = r->in.count;
3800 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3801 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3802 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3803 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3805 for (i=0; i<ctr->count; i++) {
3806 ctr->sitename[i].string = NULL;
3807 ctr->subnetname[i].string = NULL;
3809 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3812 /* The first two byte of the buffer are reserved for the
3813 * "sin_family" but for now only the first one is used. */
3814 sin_family = r->in.addresses[i].buffer[0];
3816 switch (sin_family) {
3818 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3821 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3822 res = inet_ntop(AF_INET, &addr->sin_addr,
3823 addr_str, sizeof(addr_str));
3827 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3830 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3831 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3832 addr_str, sizeof(addr_str));
3843 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3848 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3849 ctr->subnetname[i].string = subnet_name;
3857 netr_DsRAddressToSitenamesW
3859 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3860 struct netr_DsRAddressToSitenamesW *r)
3862 struct netr_DsRAddressToSitenamesExW r2;
3863 struct netr_DsRAddressToSitenamesWCtr *ctr;
3869 r2.in.server_name = r->in.server_name;
3870 r2.in.count = r->in.count;
3871 r2.in.addresses = r->in.addresses;
3873 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3874 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3876 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3877 W_ERROR_HAVE_NO_MEMORY(ctr);
3881 ctr->count = r->in.count;
3882 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3883 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3885 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3887 for (i=0; i<ctr->count; i++) {
3888 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3896 netr_DsrGetDcSiteCoverageW
3898 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3899 struct netr_DsrGetDcSiteCoverageW *r)
3901 struct ldb_context *sam_ctx;
3902 struct DcSitesCtr *ctr;
3904 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3905 if (sam_ctx == NULL) {
3906 return WERR_DS_UNAVAILABLE;
3909 ctr = talloc(mem_ctx, struct DcSitesCtr);
3910 W_ERROR_HAVE_NO_MEMORY(ctr);
3914 /* For now only return our default site */
3916 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3917 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3918 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3919 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3925 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3926 struct ldb_context *sam_ctx,
3927 struct netr_DomainTrustList *trusts,
3928 uint32_t trust_flags)
3930 struct ldb_dn *system_dn;
3931 struct ldb_message **dom_res = NULL;
3932 const char *trust_attrs[] = { "flatname", "trustPartner",
3933 "securityIdentifier", "trustDirection",
3934 "trustType", "trustAttributes", NULL };
3939 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3940 NETR_TRUST_FLAG_OUTBOUND))) {
3941 return WERR_INVALID_FLAGS;
3944 system_dn = samdb_system_container_dn(sam_ctx, mem_ctx);
3945 if (system_dn == NULL) {
3946 return WERR_NOT_ENOUGH_MEMORY;
3949 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3950 &dom_res, trust_attrs,
3951 "(objectclass=trustedDomain)");
3953 for (i = 0; i < ret; i++) {
3954 unsigned int trust_dir;
3957 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3958 "trustDirection", 0);
3960 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3961 flags |= NETR_TRUST_FLAG_INBOUND;
3963 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3964 flags |= NETR_TRUST_FLAG_OUTBOUND;
3967 if (!(flags & trust_flags)) {
3968 /* this trust direction was not requested */
3973 trusts->array = talloc_realloc(trusts, trusts->array,
3974 struct netr_DomainTrust,
3976 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3978 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3979 if (!trusts->array[n].netbios_name) {
3980 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3981 "without flatname\n",
3982 ldb_dn_get_linearized(dom_res[i]->dn)));
3985 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3987 trusts->array[n].trust_flags = flags;
3988 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3989 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3990 /* TODO: find if we have parent in the list */
3991 trusts->array[n].parent_index = 0;
3994 trusts->array[n].trust_type =
3995 ldb_msg_find_attr_as_uint(dom_res[i],
3997 trusts->array[n].trust_attributes =
3998 ldb_msg_find_attr_as_uint(dom_res[i],
3999 "trustAttributes", 0);
4001 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
4002 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
4003 struct dom_sid zero_sid;
4004 ZERO_STRUCT(zero_sid);
4005 trusts->array[n].sid =
4006 dom_sid_dup(trusts, &zero_sid);
4008 trusts->array[n].sid =
4009 samdb_result_dom_sid(trusts, dom_res[i],
4010 "securityIdentifier");
4012 trusts->array[n].guid = GUID_zero();
4014 trusts->count = n + 1;
4017 talloc_free(dom_res);
4022 netr_DsrEnumerateDomainTrusts
4024 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
4025 TALLOC_CTX *mem_ctx,
4026 struct netr_DsrEnumerateDomainTrusts *r)
4028 struct netr_DomainTrustList *trusts;
4029 struct ldb_context *sam_ctx;
4031 struct ldb_message **dom_res;
4032 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
4033 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4034 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
4038 if (r->in.trust_flags & 0xFFFFFE00) {
4039 return WERR_INVALID_FLAGS;
4042 /* TODO: turn to hard check once we are sure this is 100% correct */
4043 if (!r->in.server_name) {
4044 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
4045 "But received NULL!\n", dnsdomain));
4047 p = strchr(r->in.server_name, '.');
4049 DEBUG(3, ("Invalid domain! Expected name in domain "
4050 "[%s]. But received [%s]!\n",
4051 dnsdomain, r->in.server_name));
4052 p = r->in.server_name;
4056 if (strcasecmp(p, dnsdomain)) {
4057 DEBUG(3, ("Invalid domain! Expected name in domain "
4058 "[%s]. But received [%s]!\n",
4059 dnsdomain, r->in.server_name));
4063 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
4064 W_ERROR_HAVE_NO_MEMORY(trusts);
4067 r->out.trusts = trusts;
4069 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4070 if (sam_ctx == NULL) {
4071 return WERR_GEN_FAILURE;
4074 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
4075 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
4077 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
4078 trusts, r->in.trust_flags);
4079 W_ERROR_NOT_OK_RETURN(werr);
4082 /* NOTE: we currently are always the root of the forest */
4083 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
4084 uint32_t n = trusts->count;
4086 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
4087 &dom_res, dom_attrs);
4089 return WERR_GEN_FAILURE;
4092 trusts->count = n + 1;
4093 trusts->array = talloc_realloc(trusts, trusts->array,
4094 struct netr_DomainTrust,
4096 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4098 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
4099 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
4100 trusts->array[n].trust_flags =
4101 NETR_TRUST_FLAG_NATIVE |
4102 NETR_TRUST_FLAG_TREEROOT |
4103 NETR_TRUST_FLAG_IN_FOREST |
4104 NETR_TRUST_FLAG_PRIMARY;
4105 /* we are always the root domain for now */
4106 trusts->array[n].parent_index = 0;
4107 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
4108 trusts->array[n].trust_attributes = 0;
4109 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
4112 trusts->array[n].guid = samdb_result_guid(dom_res[0],
4114 talloc_free(dom_res);
4122 netr_DsrDeregisterDNSHostRecords
4124 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4125 struct netr_DsrDeregisterDNSHostRecords *r)
4127 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4131 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4132 struct netr_ServerGetTrustInfo *r);
4135 netr_ServerTrustPasswordsGet
4137 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4138 struct netr_ServerTrustPasswordsGet *r)
4140 struct netr_ServerGetTrustInfo r2 = {};
4141 struct netr_TrustInfo *_ti = NULL;
4144 r2.in.server_name = r->in.server_name;
4145 r2.in.account_name = r->in.account_name;
4146 r2.in.secure_channel_type = r->in.secure_channel_type;
4147 r2.in.computer_name = r->in.computer_name;
4148 r2.in.credential = r->in.credential;
4150 r2.out.return_authenticator = r->out.return_authenticator;
4151 r2.out.new_owf_password = r->out.new_owf_password;
4152 r2.out.old_owf_password = r->out.old_owf_password;
4153 r2.out.trust_info = &_ti;
4155 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
4157 r->out.return_authenticator = r2.out.return_authenticator;
4158 r->out.new_owf_password = r2.out.new_owf_password;
4159 r->out.old_owf_password = r2.out.old_owf_password;
4165 netr_DsRGetForestTrustInformation
4167 struct dcesrv_netr_DsRGetForestTrustInformation_state {
4168 struct dcesrv_call_state *dce_call;
4169 TALLOC_CTX *mem_ctx;
4170 struct netr_DsRGetForestTrustInformation *r;
4173 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
4175 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
4176 TALLOC_CTX *mem_ctx,
4177 struct netr_DsRGetForestTrustInformation *r)
4179 struct auth_session_info *session_info =
4180 dcesrv_call_session_info(dce_call);
4181 struct imessaging_context *imsg_ctx =
4182 dcesrv_imessaging_context(dce_call->conn);
4183 enum security_user_level security_level;
4184 struct ldb_context *sam_ctx = NULL;
4185 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
4186 struct dcerpc_binding_handle *irpc_handle = NULL;
4187 struct tevent_req *subreq = NULL;
4188 struct ldb_dn *domain_dn = NULL;
4189 struct ldb_dn *forest_dn = NULL;
4193 security_level = security_session_user_level(session_info, NULL);
4194 if (security_level < SECURITY_USER) {
4195 return WERR_ACCESS_DENIED;
4198 if (r->in.flags & 0xFFFFFFFE) {
4199 return WERR_INVALID_FLAGS;
4202 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4203 if (sam_ctx == NULL) {
4204 return WERR_GEN_FAILURE;
4207 domain_dn = ldb_get_default_basedn(sam_ctx);
4208 if (domain_dn == NULL) {
4209 return WERR_GEN_FAILURE;
4212 forest_dn = ldb_get_root_basedn(sam_ctx);
4213 if (forest_dn == NULL) {
4214 return WERR_GEN_FAILURE;
4217 cmp = ldb_dn_compare(domain_dn, forest_dn);
4219 return WERR_NERR_ACFNOTLOADED;
4222 forest_level = dsdb_forest_functional_level(sam_ctx);
4223 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4224 return WERR_INVALID_FUNCTION;
4227 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
4228 if (!samdb_is_pdc(sam_ctx)) {
4229 return WERR_NERR_NOTPRIMARY;
4232 if (r->in.trusted_domain_name == NULL) {
4233 return WERR_INVALID_FLAGS;
4237 if (r->in.trusted_domain_name == NULL) {
4241 * information about our own domain
4243 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4244 r->out.forest_trust_info);
4245 if (!NT_STATUS_IS_OK(status)) {
4246 return ntstatus_to_werror(status);
4253 * Forward the request to winbindd
4256 state = talloc_zero(mem_ctx,
4257 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4258 if (state == NULL) {
4259 return WERR_NOT_ENOUGH_MEMORY;
4261 state->dce_call = dce_call;
4262 state->mem_ctx = mem_ctx;
4265 irpc_handle = irpc_binding_handle_by_name(state,
4268 &ndr_table_winbind);
4269 if (irpc_handle == NULL) {
4270 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
4271 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4272 return WERR_SERVICE_NOT_FOUND;
4276 * 60 seconds timeout should be enough
4278 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
4280 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
4281 state->dce_call->event_ctx,
4283 r->in.trusted_domain_name,
4285 r->out.forest_trust_info);
4286 if (subreq == NULL) {
4287 return WERR_NOT_ENOUGH_MEMORY;
4289 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4290 tevent_req_set_callback(subreq,
4291 dcesrv_netr_DsRGetForestTrustInformation_done,
4297 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
4299 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
4300 tevent_req_callback_data(subreq,
4301 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4304 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
4306 &state->r->out.result);
4307 TALLOC_FREE(subreq);
4308 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
4309 state->r->out.result = WERR_TIMEOUT;
4310 } else if (!NT_STATUS_IS_OK(status)) {
4311 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4312 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
4313 nt_errstr(status)));
4316 status = dcesrv_reply(state->dce_call);
4317 if (!NT_STATUS_IS_OK(status)) {
4318 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4323 netr_GetForestTrustInformation
4325 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
4326 TALLOC_CTX *mem_ctx,
4327 struct netr_GetForestTrustInformation *r)
4329 struct netlogon_creds_CredentialState *creds = NULL;
4330 struct ldb_context *sam_ctx = NULL;
4331 struct ldb_dn *domain_dn = NULL;
4332 struct ldb_dn *forest_dn = NULL;
4337 status = dcesrv_netr_creds_server_step_check(dce_call,
4339 r->in.computer_name,
4341 r->out.return_authenticator,
4343 if (!NT_STATUS_IS_OK(status)) {
4347 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
4348 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
4349 return NT_STATUS_NOT_IMPLEMENTED;
4352 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4353 if (sam_ctx == NULL) {
4354 return NT_STATUS_INTERNAL_ERROR;
4357 /* TODO: check r->in.server_name is our name */
4359 domain_dn = ldb_get_default_basedn(sam_ctx);
4360 if (domain_dn == NULL) {
4361 return NT_STATUS_INTERNAL_ERROR;
4364 forest_dn = ldb_get_root_basedn(sam_ctx);
4365 if (forest_dn == NULL) {
4366 return NT_STATUS_INTERNAL_ERROR;
4369 cmp = ldb_dn_compare(domain_dn, forest_dn);
4371 return NT_STATUS_INVALID_DOMAIN_STATE;
4374 forest_level = dsdb_forest_functional_level(sam_ctx);
4375 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4376 return NT_STATUS_INVALID_DOMAIN_STATE;
4379 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4380 r->out.forest_trust_info);
4381 if (!NT_STATUS_IS_OK(status)) {
4385 return NT_STATUS_OK;
4390 netr_ServerGetTrustInfo
4392 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4393 struct netr_ServerGetTrustInfo *r)
4395 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4396 struct netlogon_creds_CredentialState *creds = NULL;
4397 struct ldb_context *sam_ctx = NULL;
4398 const char * const attrs[] = {
4401 "userAccountControl",
4404 struct ldb_message **res = NULL;
4405 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4408 const char *asid = NULL;
4410 const char *aname = NULL;
4411 struct ldb_message *tdo_msg = NULL;
4412 const char * const tdo_attrs[] = {
4413 "trustAuthIncoming",
4417 struct netr_TrustInfo *trust_info = NULL;
4419 ZERO_STRUCTP(r->out.new_owf_password);
4420 ZERO_STRUCTP(r->out.old_owf_password);
4422 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4424 r->in.computer_name,
4426 r->out.return_authenticator,
4428 if (!NT_STATUS_IS_OK(nt_status)) {
4432 /* TODO: check r->in.server_name is our name */
4434 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4435 return NT_STATUS_INVALID_PARAMETER;
4438 if (r->in.secure_channel_type != creds->secure_channel_type) {
4439 return NT_STATUS_INVALID_PARAMETER;
4442 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4443 return NT_STATUS_INVALID_PARAMETER;
4446 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
4447 if (sam_ctx == NULL) {
4448 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4451 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4453 return NT_STATUS_NO_MEMORY;
4456 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4457 "(&(objectClass=user)(objectSid=%s))",
4460 return NT_STATUS_ACCOUNT_DISABLED;
4463 switch (creds->secure_channel_type) {
4464 case SEC_CHAN_DNS_DOMAIN:
4465 case SEC_CHAN_DOMAIN:
4466 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4468 if (uac & UF_ACCOUNTDISABLE) {
4469 return NT_STATUS_ACCOUNT_DISABLED;
4472 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4473 return NT_STATUS_ACCOUNT_DISABLED;
4476 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4477 if (aname == NULL) {
4478 return NT_STATUS_ACCOUNT_DISABLED;
4481 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4482 SEC_CHAN_DOMAIN, aname,
4483 tdo_attrs, mem_ctx, &tdo_msg);
4484 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4485 return NT_STATUS_ACCOUNT_DISABLED;
4487 if (!NT_STATUS_IS_OK(nt_status)) {
4491 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4494 if (!NT_STATUS_IS_OK(nt_status)) {
4498 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4499 if (trust_info == NULL) {
4500 return NT_STATUS_NO_MEMORY;
4503 trust_info->count = 1;
4504 trust_info->data = talloc_array(trust_info, uint32_t,
4506 if (trust_info->data == NULL) {
4507 return NT_STATUS_NO_MEMORY;
4510 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4516 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4519 if (!NT_STATUS_IS_OK(nt_status)) {
4523 prevNtHash = talloc(mem_ctx, struct samr_Password);
4524 if (prevNtHash == NULL) {
4525 return NT_STATUS_NO_MEMORY;
4528 E_md4hash("", prevNtHash->hash);
4532 if (curNtHash != NULL) {
4533 *r->out.new_owf_password = *curNtHash;
4534 nt_status = netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4535 if (!NT_STATUS_IS_OK(nt_status)) {
4539 if (prevNtHash != NULL) {
4540 *r->out.old_owf_password = *prevNtHash;
4541 nt_status = netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4542 if (!NT_STATUS_IS_OK(nt_status)) {
4547 if (trust_info != NULL) {
4548 *r->out.trust_info = trust_info;
4551 return NT_STATUS_OK;
4557 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4558 struct netr_Unused47 *r)
4560 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4564 struct netr_dnsupdate_RODC_state {
4565 struct dcesrv_call_state *dce_call;
4566 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4567 struct dnsupdate_RODC *r2;
4571 called when the forwarded RODC dns update request is finished
4573 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4575 struct netr_dnsupdate_RODC_state *st =
4576 tevent_req_callback_data(subreq,
4577 struct netr_dnsupdate_RODC_state);
4580 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4581 TALLOC_FREE(subreq);
4582 if (!NT_STATUS_IS_OK(status)) {
4583 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4584 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4587 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4589 status = dcesrv_reply(st->dce_call);
4590 if (!NT_STATUS_IS_OK(status)) {
4591 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4596 netr_DsrUpdateReadOnlyServerDnsRecords
4598 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4599 TALLOC_CTX *mem_ctx,
4600 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4602 struct netlogon_creds_CredentialState *creds;
4604 struct dcerpc_binding_handle *binding_handle;
4605 struct netr_dnsupdate_RODC_state *st;
4606 struct tevent_req *subreq;
4607 struct imessaging_context *imsg_ctx =
4608 dcesrv_imessaging_context(dce_call->conn);
4610 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4612 r->in.computer_name,
4614 r->out.return_authenticator,
4616 NT_STATUS_NOT_OK_RETURN(nt_status);
4618 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4619 return NT_STATUS_ACCESS_DENIED;
4622 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4623 NT_STATUS_HAVE_NO_MEMORY(st);
4625 st->dce_call = dce_call;
4627 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4628 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4630 st->r2->in.dom_sid = creds->sid;
4631 st->r2->in.site_name = r->in.site_name;
4632 st->r2->in.dns_ttl = r->in.dns_ttl;
4633 st->r2->in.dns_names = r->in.dns_names;
4634 st->r2->out.dns_names = r->out.dns_names;
4636 binding_handle = irpc_binding_handle_by_name(st,
4640 if (binding_handle == NULL) {
4641 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4642 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4643 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4646 /* forward the call */
4647 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4648 binding_handle, st->r2);
4649 NT_STATUS_HAVE_NO_MEMORY(subreq);
4651 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4653 /* setup the callback */
4654 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4656 return NT_STATUS_OK;
4660 /* include the generated boilerplate */
4661 #include "librpc/gen_ndr/ndr_netlogon_s.c"