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 cryto 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 cryto 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),
846 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
847 struct netr_ServerAuthenticate *r)
849 struct netr_ServerAuthenticate3 a;
852 * negotiate_flags is used as an [in] parameter
853 * so it need to be initialised.
855 * (I think ... = 0; seems wrong here --metze)
857 uint32_t negotiate_flags_in = 0;
858 uint32_t negotiate_flags_out = 0;
860 a.in.server_name = r->in.server_name;
861 a.in.account_name = r->in.account_name;
862 a.in.secure_channel_type = r->in.secure_channel_type;
863 a.in.computer_name = r->in.computer_name;
864 a.in.credentials = r->in.credentials;
865 a.in.negotiate_flags = &negotiate_flags_in;
867 a.out.return_credentials = r->out.return_credentials;
869 a.out.negotiate_flags = &negotiate_flags_out;
871 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
874 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
875 struct netr_ServerAuthenticate2 *r)
877 struct netr_ServerAuthenticate3 r3;
880 r3.in.server_name = r->in.server_name;
881 r3.in.account_name = r->in.account_name;
882 r3.in.secure_channel_type = r->in.secure_channel_type;
883 r3.in.computer_name = r->in.computer_name;
884 r3.in.credentials = r->in.credentials;
885 r3.out.return_credentials = r->out.return_credentials;
886 r3.in.negotiate_flags = r->in.negotiate_flags;
887 r3.out.negotiate_flags = r->out.negotiate_flags;
890 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
894 Change the machine account password for the currently connected
895 client. Supplies only the NT#.
898 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
899 struct netr_ServerPasswordSet *r)
901 struct netlogon_creds_CredentialState *creds;
902 struct ldb_context *sam_ctx;
905 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
908 r->in.credential, r->out.return_authenticator,
910 NT_STATUS_NOT_OK_RETURN(nt_status);
912 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
913 if (sam_ctx == NULL) {
914 return NT_STATUS_INVALID_SYSTEM_SERVICE;
917 nt_status = netlogon_creds_des_decrypt(creds, r->in.new_password);
918 NT_STATUS_NOT_OK_RETURN(nt_status);
920 /* Using the sid for the account as the key, set the password */
921 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
923 NULL, /* Don't have version */
924 NULL, /* Don't have plaintext */
926 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
932 Change the machine account password for the currently connected
933 client. Supplies new plaintext.
935 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
936 struct netr_ServerPasswordSet2 *r)
938 struct netlogon_creds_CredentialState *creds;
939 struct ldb_context *sam_ctx;
940 struct NL_PASSWORD_VERSION version = {};
941 const uint32_t *new_version = NULL;
943 DATA_BLOB new_password = data_blob_null;
944 size_t confounder_len;
945 DATA_BLOB dec_blob = data_blob_null;
946 DATA_BLOB enc_blob = data_blob_null;
947 struct samr_CryptPassword password_buf;
949 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
952 r->in.credential, r->out.return_authenticator,
954 NT_STATUS_NOT_OK_RETURN(nt_status);
956 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
957 if (sam_ctx == NULL) {
958 return NT_STATUS_INVALID_SYSTEM_SERVICE;
961 memcpy(password_buf.data, r->in.new_password->data, 512);
962 SIVAL(password_buf.data, 512, r->in.new_password->length);
964 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
965 nt_status = netlogon_creds_aes_decrypt(creds,
969 nt_status = netlogon_creds_arcfour_crypt(creds,
974 if (!NT_STATUS_IS_OK(nt_status)) {
978 switch (creds->secure_channel_type) {
979 case SEC_CHAN_DOMAIN:
980 case SEC_CHAN_DNS_DOMAIN: {
981 uint32_t len = IVAL(password_buf.data, 512);
983 uint32_t ofs = 500 - len;
986 p = password_buf.data + ofs;
988 version.ReservedField = IVAL(p, 0);
989 version.PasswordVersionNumber = IVAL(p, 4);
990 version.PasswordVersionPresent = IVAL(p, 8);
992 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
993 new_version = &version.PasswordVersionNumber;
1001 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
1002 DEBUG(3,("samr: failed to decode password buffer\n"));
1003 return NT_STATUS_WRONG_PASSWORD;
1007 * Make sure the length field was encrypted,
1008 * otherwise we are under attack.
1010 if (new_password.length == r->in.new_password->length) {
1011 DBG_WARNING("Length[%zu] field not encrypted\n",
1012 new_password.length);
1013 return NT_STATUS_WRONG_PASSWORD;
1017 * We don't allow empty passwords for machine accounts.
1019 if (new_password.length < 2) {
1020 DBG_WARNING("Empty password Length[%zu]\n",
1021 new_password.length);
1022 return NT_STATUS_WRONG_PASSWORD;
1026 * Make sure the confounder part of CryptPassword
1027 * buffer was encrypted, otherwise we are under attack.
1029 confounder_len = 512 - new_password.length;
1030 enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
1031 dec_blob = data_blob_const(password_buf.data, confounder_len);
1032 if (confounder_len > 0 && data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1033 DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
1035 return NT_STATUS_WRONG_PASSWORD;
1039 * Check that the password part was actually encrypted,
1040 * otherwise we are under attack.
1042 enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
1043 new_password.length);
1044 dec_blob = data_blob_const(password_buf.data + confounder_len,
1045 new_password.length);
1046 if (data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1047 DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
1048 new_password.length);
1049 return NT_STATUS_WRONG_PASSWORD;
1053 * don't allow zero buffers
1055 if (all_zero(new_password.data, new_password.length)) {
1056 DBG_WARNING("Password zero buffer Length[%zu]\n",
1057 new_password.length);
1058 return NT_STATUS_WRONG_PASSWORD;
1061 /* Using the sid for the account as the key, set the password */
1062 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1065 &new_password, /* we have plaintext */
1067 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1076 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1077 struct netr_LogonUasLogon *r)
1079 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1086 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1087 struct netr_LogonUasLogoff *r)
1089 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1093 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
1094 const struct netr_LogonSamLogonEx *r)
1096 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1098 switch (r->in.logon_level) {
1099 case NetlogonInteractiveInformation:
1100 case NetlogonServiceInformation:
1101 case NetlogonInteractiveTransitiveInformation:
1102 case NetlogonServiceTransitiveInformation:
1103 if (r->in.logon->password == NULL) {
1104 return NT_STATUS_INVALID_PARAMETER;
1107 switch (r->in.validation_level) {
1108 case NetlogonValidationSamInfo: /* 2 */
1109 case NetlogonValidationSamInfo2: /* 3 */
1110 case NetlogonValidationSamInfo4: /* 6 */
1113 return NT_STATUS_INVALID_INFO_CLASS;
1117 case NetlogonNetworkInformation:
1118 case NetlogonNetworkTransitiveInformation:
1119 if (r->in.logon->network == NULL) {
1120 return NT_STATUS_INVALID_PARAMETER;
1123 switch (r->in.validation_level) {
1124 case NetlogonValidationSamInfo: /* 2 */
1125 case NetlogonValidationSamInfo2: /* 3 */
1126 case NetlogonValidationSamInfo4: /* 6 */
1129 return NT_STATUS_INVALID_INFO_CLASS;
1134 case NetlogonGenericInformation:
1135 if (r->in.logon->generic == NULL) {
1136 return NT_STATUS_INVALID_PARAMETER;
1139 switch (r->in.validation_level) {
1140 /* TODO: case NetlogonValidationGenericInfo: 4 */
1141 case NetlogonValidationGenericInfo2: /* 5 */
1144 return NT_STATUS_INVALID_INFO_CLASS;
1149 return NT_STATUS_INVALID_PARAMETER;
1152 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
1154 switch (r->in.validation_level) {
1155 case NetlogonValidationSamInfo4: /* 6 */
1156 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1157 return NT_STATUS_INVALID_PARAMETER;
1165 return NT_STATUS_OK;
1168 struct dcesrv_netr_LogonSamLogon_base_state {
1169 struct dcesrv_call_state *dce_call;
1171 TALLOC_CTX *mem_ctx;
1173 struct netlogon_creds_CredentialState *creds;
1175 struct netr_LogonSamLogonEx r;
1177 uint32_t _ignored_flags;
1180 struct netr_LogonSamLogon *lsl;
1181 struct netr_LogonSamLogonWithFlags *lslwf;
1182 struct netr_LogonSamLogonEx *lslex;
1185 struct kdc_check_generic_kerberos kr;
1188 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
1189 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
1190 static void dcesrv_netr_LogonSamLogon_base_reply(
1191 struct dcesrv_netr_LogonSamLogon_base_state *state);
1194 netr_LogonSamLogon_base
1196 This version of the function allows other wrappers to say 'do not check the credentials'
1198 We can't do the traditional 'wrapping' format completely, as this
1199 function must only run under schannel
1201 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
1203 struct dcesrv_call_state *dce_call = state->dce_call;
1204 struct imessaging_context *imsg_ctx =
1205 dcesrv_imessaging_context(dce_call->conn);
1206 TALLOC_CTX *mem_ctx = state->mem_ctx;
1207 struct netr_LogonSamLogonEx *r = &state->r;
1208 struct netlogon_creds_CredentialState *creds = state->creds;
1209 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1210 const char *workgroup = lpcfg_workgroup(lp_ctx);
1211 struct auth4_context *auth_context = NULL;
1212 struct auth_usersupplied_info *user_info = NULL;
1214 struct tevent_req *subreq = NULL;
1215 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1216 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1218 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1220 switch (dce_call->pkt.u.request.opnum) {
1221 case NDR_NETR_LOGONSAMLOGON:
1222 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
1224 * These already called dcesrv_netr_check_schannel()
1225 * via dcesrv_netr_creds_server_step_check()
1228 case NDR_NETR_LOGONSAMLOGONEX:
1230 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1231 return NT_STATUS_ACCESS_DENIED;
1234 nt_status = dcesrv_netr_check_schannel(dce_call,
1238 dce_call->pkt.u.request.opnum);
1239 if (!NT_STATUS_IS_OK(nt_status)) {
1245 *r->out.authoritative = 1;
1247 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
1249 * Currently we're always the forest root ourself.
1251 return NT_STATUS_NO_SUCH_USER;
1254 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
1256 * Currently we don't support trusts correctly yet.
1258 return NT_STATUS_NO_SUCH_USER;
1261 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1262 NT_STATUS_HAVE_NO_MEMORY(user_info);
1264 user_info->service_description = "SamLogon";
1266 nt_status = netlogon_creds_decrypt_samlogon_logon(creds,
1269 NT_STATUS_NOT_OK_RETURN(nt_status);
1271 switch (r->in.logon_level) {
1272 case NetlogonInteractiveInformation:
1273 case NetlogonServiceInformation:
1274 case NetlogonInteractiveTransitiveInformation:
1275 case NetlogonServiceTransitiveInformation:
1276 case NetlogonNetworkInformation:
1277 case NetlogonNetworkTransitiveInformation:
1279 nt_status = auth_context_create_for_netlogon(mem_ctx,
1280 dce_call->event_ctx,
1282 dce_call->conn->dce_ctx->lp_ctx,
1284 NT_STATUS_NOT_OK_RETURN(nt_status);
1286 user_info->remote_host = dce_call->conn->remote_address;
1287 user_info->local_host = dce_call->conn->local_address;
1289 user_info->netlogon_trust_account.secure_channel_type
1290 = creds->secure_channel_type;
1291 user_info->netlogon_trust_account.negotiate_flags
1292 = creds->negotiate_flags;
1295 * These two can be unrelated when the account is
1296 * actually that of a trusted domain, so we want to
1297 * know which DC in that trusted domain contacted
1300 user_info->netlogon_trust_account.computer_name
1301 = creds->computer_name;
1302 user_info->netlogon_trust_account.account_name
1303 = creds->account_name;
1304 user_info->netlogon_trust_account.sid
1309 /* We do not need to set up the user_info in this case */
1313 switch (r->in.logon_level) {
1314 case NetlogonInteractiveInformation:
1315 case NetlogonServiceInformation:
1316 case NetlogonInteractiveTransitiveInformation:
1317 case NetlogonServiceTransitiveInformation:
1318 user_info->auth_description = "interactive";
1320 user_info->logon_parameters
1321 = r->in.logon->password->identity_info.parameter_control;
1322 user_info->client.account_name
1323 = r->in.logon->password->identity_info.account_name.string;
1324 user_info->client.domain_name
1325 = r->in.logon->password->identity_info.domain_name.string;
1326 user_info->workstation_name
1327 = r->in.logon->password->identity_info.workstation.string;
1328 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1329 user_info->password_state = AUTH_PASSWORD_HASH;
1331 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1332 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1333 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1335 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1336 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1337 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1340 = r->in.logon->password->identity_info.logon_id;
1343 case NetlogonNetworkInformation:
1344 case NetlogonNetworkTransitiveInformation:
1345 user_info->auth_description = "network";
1347 nt_status = auth_context_set_challenge(
1349 r->in.logon->network->challenge,
1350 "netr_LogonSamLogonWithFlags");
1351 NT_STATUS_NOT_OK_RETURN(nt_status);
1353 user_info->logon_parameters
1354 = r->in.logon->network->identity_info.parameter_control;
1355 user_info->client.account_name
1356 = r->in.logon->network->identity_info.account_name.string;
1357 user_info->client.domain_name
1358 = r->in.logon->network->identity_info.domain_name.string;
1359 user_info->workstation_name
1360 = r->in.logon->network->identity_info.workstation.string;
1362 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1363 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1364 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1367 = r->in.logon->network->identity_info.logon_id;
1369 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1370 user_info->client.account_name,
1371 user_info->client.domain_name,
1372 user_info->password.response.nt,
1374 NT_STATUS_NOT_OK_RETURN(nt_status);
1379 case NetlogonGenericInformation:
1381 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1383 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1386 /* Using DES to verify kerberos tickets makes no sense */
1387 return NT_STATUS_INVALID_PARAMETER;
1390 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1391 struct dcerpc_binding_handle *irpc_handle;
1392 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1393 NT_STATUS_HAVE_NO_MEMORY(generic);
1395 r->out.validation->generic = generic;
1398 = r->in.logon->generic->identity_info.logon_id;
1400 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1404 if (irpc_handle == NULL) {
1405 return NT_STATUS_NO_LOGON_SERVERS;
1408 state->kr.in.generic_request =
1409 data_blob_const(r->in.logon->generic->data,
1410 r->in.logon->generic->length);
1413 * 60 seconds should be enough
1415 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1416 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1417 state->dce_call->event_ctx,
1418 irpc_handle, &state->kr);
1419 if (subreq == NULL) {
1420 return NT_STATUS_NO_MEMORY;
1422 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1423 tevent_req_set_callback(subreq,
1424 dcesrv_netr_LogonSamLogon_base_krb5_done,
1426 return NT_STATUS_OK;
1429 /* Until we get an implemetnation of these other packages */
1430 return NT_STATUS_INVALID_PARAMETER;
1433 return NT_STATUS_INVALID_PARAMETER;
1436 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1437 auth_context, user_info);
1438 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1439 tevent_req_set_callback(subreq,
1440 dcesrv_netr_LogonSamLogon_base_auth_done,
1442 return NT_STATUS_OK;
1445 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1447 struct dcesrv_netr_LogonSamLogon_base_state *state =
1448 tevent_req_callback_data(subreq,
1449 struct dcesrv_netr_LogonSamLogon_base_state);
1450 TALLOC_CTX *mem_ctx = state->mem_ctx;
1451 struct netr_LogonSamLogonEx *r = &state->r;
1452 struct auth_user_info_dc *user_info_dc = NULL;
1453 struct netr_SamInfo2 *sam2 = NULL;
1454 struct netr_SamInfo3 *sam3 = NULL;
1455 struct netr_SamInfo6 *sam6 = NULL;
1458 nt_status = auth_check_password_recv(subreq, mem_ctx,
1460 r->out.authoritative);
1461 TALLOC_FREE(subreq);
1462 if (!NT_STATUS_IS_OK(nt_status)) {
1463 r->out.result = nt_status;
1464 dcesrv_netr_LogonSamLogon_base_reply(state);
1468 switch (r->in.validation_level) {
1470 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1473 if (!NT_STATUS_IS_OK(nt_status)) {
1474 r->out.result = nt_status;
1475 dcesrv_netr_LogonSamLogon_base_reply(state);
1479 r->out.validation->sam2 = sam2;
1483 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1486 if (!NT_STATUS_IS_OK(nt_status)) {
1487 r->out.result = nt_status;
1488 dcesrv_netr_LogonSamLogon_base_reply(state);
1492 r->out.validation->sam3 = sam3;
1496 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1499 if (!NT_STATUS_IS_OK(nt_status)) {
1500 r->out.result = nt_status;
1501 dcesrv_netr_LogonSamLogon_base_reply(state);
1505 r->out.validation->sam6 = sam6;
1509 if (!NT_STATUS_IS_OK(nt_status)) {
1510 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1511 dcesrv_netr_LogonSamLogon_base_reply(state);
1516 /* TODO: Describe and deal with these flags */
1519 r->out.result = NT_STATUS_OK;
1521 dcesrv_netr_LogonSamLogon_base_reply(state);
1524 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1526 struct dcesrv_netr_LogonSamLogon_base_state *state =
1527 tevent_req_callback_data(subreq,
1528 struct dcesrv_netr_LogonSamLogon_base_state);
1529 TALLOC_CTX *mem_ctx = state->mem_ctx;
1530 struct netr_LogonSamLogonEx *r = &state->r;
1531 struct netr_GenericInfo2 *generic = NULL;
1534 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1535 TALLOC_FREE(subreq);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 r->out.result = status;
1538 dcesrv_netr_LogonSamLogon_base_reply(state);
1542 generic = r->out.validation->generic;
1543 generic->length = state->kr.out.generic_reply.length;
1544 generic->data = state->kr.out.generic_reply.data;
1546 /* TODO: Describe and deal with these flags */
1549 r->out.result = NT_STATUS_OK;
1551 dcesrv_netr_LogonSamLogon_base_reply(state);
1554 static void dcesrv_netr_LogonSamLogon_base_reply(
1555 struct dcesrv_netr_LogonSamLogon_base_state *state)
1557 struct netr_LogonSamLogonEx *r = &state->r;
1560 if (NT_STATUS_IS_OK(r->out.result)) {
1561 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
1562 r->in.validation_level,
1564 if (!NT_STATUS_IS_OK(status)) {
1565 DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
1571 if (state->_r.lslex != NULL) {
1572 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1573 _r->out.result = r->out.result;
1574 } else if (state->_r.lslwf != NULL) {
1575 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1576 _r->out.result = r->out.result;
1577 } else if (state->_r.lsl != NULL) {
1578 struct netr_LogonSamLogon *_r = state->_r.lsl;
1579 _r->out.result = r->out.result;
1582 status = dcesrv_reply(state->dce_call);
1583 if (!NT_STATUS_IS_OK(status)) {
1584 DBG_ERR("dcesrv_reply() failed - %s\n",
1589 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1590 struct netr_LogonSamLogonEx *r)
1592 struct dcesrv_netr_LogonSamLogon_base_state *state;
1595 *r->out.authoritative = 1;
1597 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1598 if (state == NULL) {
1599 return NT_STATUS_NO_MEMORY;
1602 state->dce_call = dce_call;
1603 state->mem_ctx = mem_ctx;
1605 state->r.in.server_name = r->in.server_name;
1606 state->r.in.computer_name = r->in.computer_name;
1607 state->r.in.logon_level = r->in.logon_level;
1608 state->r.in.logon = r->in.logon;
1609 state->r.in.validation_level = r->in.validation_level;
1610 state->r.in.flags = r->in.flags;
1611 state->r.out.validation = r->out.validation;
1612 state->r.out.authoritative = r->out.authoritative;
1613 state->r.out.flags = r->out.flags;
1615 state->_r.lslex = r;
1617 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1618 if (!NT_STATUS_IS_OK(nt_status)) {
1622 nt_status = schannel_get_creds_state(mem_ctx,
1623 dce_call->conn->dce_ctx->lp_ctx,
1624 r->in.computer_name, &state->creds);
1625 if (!NT_STATUS_IS_OK(nt_status)) {
1629 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1631 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1639 netr_LogonSamLogonWithFlags
1642 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1643 struct netr_LogonSamLogonWithFlags *r)
1645 struct dcesrv_netr_LogonSamLogon_base_state *state;
1648 *r->out.authoritative = 1;
1650 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1651 if (state == NULL) {
1652 return NT_STATUS_NO_MEMORY;
1655 state->dce_call = dce_call;
1656 state->mem_ctx = mem_ctx;
1658 state->r.in.server_name = r->in.server_name;
1659 state->r.in.computer_name = r->in.computer_name;
1660 state->r.in.logon_level = r->in.logon_level;
1661 state->r.in.logon = r->in.logon;
1662 state->r.in.validation_level = r->in.validation_level;
1663 state->r.in.flags = r->in.flags;
1664 state->r.out.validation = r->out.validation;
1665 state->r.out.authoritative = r->out.authoritative;
1666 state->r.out.flags = r->out.flags;
1668 state->_r.lslwf = r;
1670 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1671 if (!NT_STATUS_IS_OK(nt_status)) {
1675 r->out.return_authenticator = talloc_zero(mem_ctx,
1676 struct netr_Authenticator);
1677 if (r->out.return_authenticator == NULL) {
1678 return NT_STATUS_NO_MEMORY;
1681 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1683 r->in.computer_name,
1685 r->out.return_authenticator,
1687 if (!NT_STATUS_IS_OK(nt_status)) {
1691 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1693 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1703 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1704 struct netr_LogonSamLogon *r)
1706 struct dcesrv_netr_LogonSamLogon_base_state *state;
1709 *r->out.authoritative = 1;
1711 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1712 if (state == NULL) {
1713 return NT_STATUS_NO_MEMORY;
1716 state->dce_call = dce_call;
1717 state->mem_ctx = mem_ctx;
1719 state->r.in.server_name = r->in.server_name;
1720 state->r.in.computer_name = r->in.computer_name;
1721 state->r.in.logon_level = r->in.logon_level;
1722 state->r.in.logon = r->in.logon;
1723 state->r.in.validation_level = r->in.validation_level;
1724 state->r.in.flags = &state->_ignored_flags;
1725 state->r.out.validation = r->out.validation;
1726 state->r.out.authoritative = r->out.authoritative;
1727 state->r.out.flags = &state->_ignored_flags;
1731 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1732 if (!NT_STATUS_IS_OK(nt_status)) {
1736 r->out.return_authenticator = talloc_zero(mem_ctx,
1737 struct netr_Authenticator);
1738 if (r->out.return_authenticator == NULL) {
1739 return NT_STATUS_NO_MEMORY;
1742 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1744 r->in.computer_name,
1746 r->out.return_authenticator,
1748 if (!NT_STATUS_IS_OK(nt_status)) {
1752 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1754 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1765 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1766 struct netr_LogonSamLogoff *r)
1768 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1776 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1777 struct netr_DatabaseDeltas *r)
1779 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1786 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1787 struct netr_DatabaseSync2 *r)
1789 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1790 return NT_STATUS_NOT_IMPLEMENTED;
1797 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1798 struct netr_DatabaseSync *r)
1800 struct netr_DatabaseSync2 r2;
1805 r2.in.logon_server = r->in.logon_server;
1806 r2.in.computername = r->in.computername;
1807 r2.in.credential = r->in.credential;
1808 r2.in.database_id = r->in.database_id;
1809 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1810 r2.in.sync_context = r->in.sync_context;
1811 r2.out.sync_context = r->out.sync_context;
1812 r2.out.delta_enum_array = r->out.delta_enum_array;
1813 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1815 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1824 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1825 struct netr_AccountDeltas *r)
1827 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1828 return NT_STATUS_NOT_IMPLEMENTED;
1835 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1836 struct netr_AccountSync *r)
1838 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1839 return NT_STATUS_NOT_IMPLEMENTED;
1846 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1847 struct netr_GetDcName *r)
1849 const char * const attrs[] = { NULL };
1850 struct ldb_context *sam_ctx;
1851 struct ldb_message **res;
1852 struct ldb_dn *domain_dn;
1857 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1858 * that the domainname needs to be a valid netbios domain
1859 * name, if it is not NULL.
1861 if (r->in.domainname) {
1862 const char *dot = strchr(r->in.domainname, '.');
1863 size_t len = strlen(r->in.domainname);
1865 if (dot || len > 15) {
1866 return WERR_NERR_DCNOTFOUND;
1870 * TODO: Should we also varify that only valid
1871 * netbios name characters are used?
1875 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
1876 if (sam_ctx == NULL) {
1877 return WERR_DS_UNAVAILABLE;
1880 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1882 if (domain_dn == NULL) {
1883 return WERR_NO_SUCH_DOMAIN;
1886 ret = gendb_search_dn(sam_ctx, mem_ctx,
1887 domain_dn, &res, attrs);
1889 return WERR_NO_SUCH_DOMAIN;
1892 /* TODO: - return real IP address
1893 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1895 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1896 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1897 W_ERROR_HAVE_NO_MEMORY(dcname);
1899 *r->out.dcname = dcname;
1903 struct dcesrv_netr_LogonControl_base_state {
1904 struct dcesrv_call_state *dce_call;
1906 TALLOC_CTX *mem_ctx;
1908 struct netr_LogonControl2Ex r;
1911 struct netr_LogonControl *l;
1912 struct netr_LogonControl2 *l2;
1913 struct netr_LogonControl2Ex *l2ex;
1917 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1919 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1921 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1922 struct auth_session_info *session_info =
1923 dcesrv_call_session_info(state->dce_call);
1924 struct imessaging_context *imsg_ctx =
1925 dcesrv_imessaging_context(state->dce_call->conn);
1926 enum security_user_level security_level;
1927 struct dcerpc_binding_handle *irpc_handle;
1928 struct tevent_req *subreq;
1931 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1933 if (state->_r.l != NULL) {
1937 if (state->r.in.level == 0x00000002) {
1938 return WERR_NOT_SUPPORTED;
1939 } else if (state->r.in.level != 0x00000001) {
1940 return WERR_INVALID_LEVEL;
1943 switch (state->r.in.function_code) {
1944 case NETLOGON_CONTROL_QUERY:
1945 case NETLOGON_CONTROL_REPLICATE:
1946 case NETLOGON_CONTROL_SYNCHRONIZE:
1947 case NETLOGON_CONTROL_PDC_REPLICATE:
1948 case NETLOGON_CONTROL_BREAKPOINT:
1949 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1950 case NETLOGON_CONTROL_TRUNCATE_LOG:
1953 return WERR_NOT_SUPPORTED;
1957 if (state->r.in.level < 0x00000001) {
1958 return WERR_INVALID_LEVEL;
1961 if (state->r.in.level > 0x00000004) {
1962 return WERR_INVALID_LEVEL;
1965 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1966 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1967 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1969 switch (state->r.in.level) {
1971 info1 = talloc_zero(state->mem_ctx,
1972 struct netr_NETLOGON_INFO_1);
1973 if (info1 == NULL) {
1974 return WERR_NOT_ENOUGH_MEMORY;
1976 state->r.out.query->info1 = info1;
1980 info3 = talloc_zero(state->mem_ctx,
1981 struct netr_NETLOGON_INFO_3);
1982 if (info3 == NULL) {
1983 return WERR_NOT_ENOUGH_MEMORY;
1985 state->r.out.query->info3 = info3;
1989 return WERR_INVALID_PARAMETER;
1994 * Some validations are done before the access check
1995 * and some after the access check
1997 security_level = security_session_user_level(session_info, NULL);
1998 if (security_level < SECURITY_ADMINISTRATOR) {
1999 return WERR_ACCESS_DENIED;
2002 if (state->_r.l2 != NULL) {
2004 * netr_LogonControl2
2006 if (state->r.in.level == 0x00000004) {
2007 return WERR_INVALID_LEVEL;
2011 switch (state->r.in.level) {
2016 switch (state->r.in.function_code) {
2017 case NETLOGON_CONTROL_REDISCOVER:
2018 case NETLOGON_CONTROL_TC_QUERY:
2019 case NETLOGON_CONTROL_TC_VERIFY:
2022 return WERR_INVALID_PARAMETER;
2031 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
2032 return WERR_INVALID_PARAMETER;
2038 return WERR_INVALID_LEVEL;
2041 switch (state->r.in.function_code) {
2042 case NETLOGON_CONTROL_REDISCOVER:
2043 case NETLOGON_CONTROL_TC_QUERY:
2044 case NETLOGON_CONTROL_TC_VERIFY:
2045 if (state->r.in.level != 2) {
2046 return WERR_INVALID_PARAMETER;
2049 if (state->r.in.data == NULL) {
2050 return WERR_INVALID_PARAMETER;
2053 if (state->r.in.data->domain == NULL) {
2054 return WERR_INVALID_PARAMETER;
2059 case NETLOGON_CONTROL_CHANGE_PASSWORD:
2060 if (state->r.in.level != 1) {
2061 return WERR_INVALID_PARAMETER;
2064 if (state->r.in.data == NULL) {
2065 return WERR_INVALID_PARAMETER;
2068 if (state->r.in.data->domain == NULL) {
2069 return WERR_INVALID_PARAMETER;
2072 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
2073 state->r.in.data->domain);
2075 struct ldb_context *sam_ctx;
2077 sam_ctx = dcesrv_samdb_connect_as_system(state,
2079 if (sam_ctx == NULL) {
2080 return WERR_DS_UNAVAILABLE;
2084 * Secrets for trusted domains can only be triggered on
2087 ok = samdb_is_pdc(sam_ctx);
2088 TALLOC_FREE(sam_ctx);
2090 return WERR_INVALID_DOMAIN_ROLE;
2096 return WERR_NOT_SUPPORTED;
2099 irpc_handle = irpc_binding_handle_by_name(state,
2102 &ndr_table_winbind);
2103 if (irpc_handle == NULL) {
2104 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2105 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2106 return WERR_SERVICE_NOT_FOUND;
2110 * 60 seconds timeout should be enough
2112 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2114 subreq = dcerpc_winbind_LogonControl_send(state,
2115 state->dce_call->event_ctx,
2117 state->r.in.function_code,
2120 state->r.out.query);
2121 if (subreq == NULL) {
2122 return WERR_NOT_ENOUGH_MEMORY;
2124 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2125 tevent_req_set_callback(subreq,
2126 dcesrv_netr_LogonControl_base_done,
2132 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
2134 struct dcesrv_netr_LogonControl_base_state *state =
2135 tevent_req_callback_data(subreq,
2136 struct dcesrv_netr_LogonControl_base_state);
2139 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
2140 &state->r.out.result);
2141 TALLOC_FREE(subreq);
2142 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
2143 state->r.out.result = WERR_TIMEOUT;
2144 } else if (!NT_STATUS_IS_OK(status)) {
2145 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2146 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
2147 nt_errstr(status)));
2150 if (state->_r.l2ex != NULL) {
2151 struct netr_LogonControl2Ex *r = state->_r.l2ex;
2152 r->out.result = state->r.out.result;
2153 } else if (state->_r.l2 != NULL) {
2154 struct netr_LogonControl2 *r = state->_r.l2;
2155 r->out.result = state->r.out.result;
2156 } else if (state->_r.l != NULL) {
2157 struct netr_LogonControl *r = state->_r.l;
2158 r->out.result = state->r.out.result;
2161 status = dcesrv_reply(state->dce_call);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2170 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2171 struct netr_LogonControl *r)
2173 struct dcesrv_netr_LogonControl_base_state *state;
2176 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2177 if (state == NULL) {
2178 return WERR_NOT_ENOUGH_MEMORY;
2181 state->dce_call = dce_call;
2182 state->mem_ctx = mem_ctx;
2184 state->r.in.logon_server = r->in.logon_server;
2185 state->r.in.function_code = r->in.function_code;
2186 state->r.in.level = r->in.level;
2187 state->r.in.data = NULL;
2188 state->r.out.query = r->out.query;
2192 werr = dcesrv_netr_LogonControl_base_call(state);
2194 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2204 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2205 struct netr_LogonControl2 *r)
2207 struct dcesrv_netr_LogonControl_base_state *state;
2210 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2211 if (state == NULL) {
2212 return WERR_NOT_ENOUGH_MEMORY;
2215 state->dce_call = dce_call;
2216 state->mem_ctx = mem_ctx;
2218 state->r.in.logon_server = r->in.logon_server;
2219 state->r.in.function_code = r->in.function_code;
2220 state->r.in.level = r->in.level;
2221 state->r.in.data = r->in.data;
2222 state->r.out.query = r->out.query;
2226 werr = dcesrv_netr_LogonControl_base_call(state);
2228 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2236 netr_LogonControl2Ex
2238 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2239 struct netr_LogonControl2Ex *r)
2241 struct dcesrv_netr_LogonControl_base_state *state;
2244 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2245 if (state == NULL) {
2246 return WERR_NOT_ENOUGH_MEMORY;
2249 state->dce_call = dce_call;
2250 state->mem_ctx = mem_ctx;
2255 werr = dcesrv_netr_LogonControl_base_call(state);
2257 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2264 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2265 struct ldb_context *sam_ctx,
2266 struct netr_DomainTrustList *trusts,
2267 uint32_t trust_flags);
2272 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2273 struct netr_GetAnyDCName *r)
2275 struct netr_DomainTrustList *trusts;
2276 struct ldb_context *sam_ctx;
2277 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2281 *r->out.dcname = NULL;
2283 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2284 /* if the domainname parameter wasn't set assume our domain */
2285 r->in.domainname = lpcfg_workgroup(lp_ctx);
2288 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2289 if (sam_ctx == NULL) {
2290 return WERR_DS_UNAVAILABLE;
2293 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2294 /* well we asked for a DC of our own domain */
2295 if (samdb_is_pdc(sam_ctx)) {
2296 /* we are the PDC of the specified domain */
2297 return WERR_NO_SUCH_DOMAIN;
2300 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2301 lpcfg_netbios_name(lp_ctx));
2302 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2307 /* Okay, now we have to consider the trusted domains */
2309 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2310 W_ERROR_HAVE_NO_MEMORY(trusts);
2314 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2315 NETR_TRUST_FLAG_INBOUND
2316 | NETR_TRUST_FLAG_OUTBOUND);
2317 W_ERROR_NOT_OK_RETURN(werr);
2319 for (i = 0; i < trusts->count; i++) {
2320 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2321 /* FIXME: Here we need to find a DC for the specified
2322 * trusted domain. */
2324 /* return WERR_OK; */
2325 return WERR_NO_SUCH_DOMAIN;
2329 return WERR_NO_SUCH_DOMAIN;
2336 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2337 struct netr_DatabaseRedo *r)
2339 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2344 netr_NetrEnumerateTrustedDomains
2346 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2347 struct netr_NetrEnumerateTrustedDomains *r)
2349 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2354 netr_LogonGetCapabilities
2356 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2357 struct netr_LogonGetCapabilities *r)
2359 struct netlogon_creds_CredentialState *creds;
2362 status = dcesrv_netr_creds_server_step_check(dce_call,
2364 r->in.computer_name,
2366 r->out.return_authenticator,
2368 if (!NT_STATUS_IS_OK(status)) {
2369 DEBUG(0,(__location__ " Bad credentials - error\n"));
2371 NT_STATUS_NOT_OK_RETURN(status);
2373 if (r->in.query_level != 1) {
2374 return NT_STATUS_NOT_SUPPORTED;
2377 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2379 return NT_STATUS_OK;
2384 netr_NETRLOGONSETSERVICEBITS
2386 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2387 struct netr_NETRLOGONSETSERVICEBITS *r)
2389 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2394 netr_LogonGetTrustRid
2396 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2397 struct netr_LogonGetTrustRid *r)
2399 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2404 netr_NETRLOGONCOMPUTESERVERDIGEST
2406 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2407 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2409 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2414 netr_NETRLOGONCOMPUTECLIENTDIGEST
2416 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2417 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2419 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2427 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2428 struct netr_DsRGetSiteName *r)
2430 struct ldb_context *sam_ctx;
2432 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2433 if (sam_ctx == NULL) {
2434 return WERR_DS_UNAVAILABLE;
2438 * We assume to be a DC when we get called over NETLOGON. Hence we
2439 * get our site name always by using "samdb_server_site_name()"
2440 * and not "samdb_client_site_name()".
2442 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2443 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2450 fill in a netr_OneDomainInfo from our own domain/forest
2452 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2453 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2454 struct GUID domain_guid,
2455 struct netr_OneDomainInfo *info,
2460 if (is_trust_list) {
2461 struct netr_trust_extension *te = NULL;
2462 struct netr_trust_extension_info *tei = NULL;
2464 /* w2k8 only fills this on trusted domains */
2465 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2467 return NT_STATUS_NO_MEMORY;
2470 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2473 * We're always within a native forest
2475 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2476 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2478 /* For now we assume we're always the tree root */
2479 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2480 tei->parent_index = 0;
2482 tei->trust_type = our_tdo->trust_type;
2484 * This needs to be 0 instead of our_tdo->trust_attributes
2485 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2486 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2488 tei->trust_attributes = 0;
2490 info->trust_extension.info = te;
2493 if (is_trust_list) {
2494 info->dns_domainname.string = our_tdo->domain_name.string;
2496 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2497 info->dns_forestname.string = NULL;
2499 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2500 our_tdo->domain_name.string);
2501 if (info->dns_domainname.string == NULL) {
2502 return NT_STATUS_NO_MEMORY;
2505 info->dns_forestname.string = info->dns_domainname.string;
2508 info->domainname.string = our_tdo->netbios_name.string;
2509 info->domain_sid = our_tdo->sid;
2510 info->domain_guid = domain_guid;
2512 return NT_STATUS_OK;
2516 fill in a netr_OneDomainInfo from a trust tdo
2518 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2519 struct GUID domain_guid,
2520 const struct lsa_TrustDomainInfoInfoEx *tdo,
2521 struct netr_OneDomainInfo *info)
2523 struct netr_trust_extension *te = NULL;
2524 struct netr_trust_extension_info *tei = NULL;
2528 /* w2k8 only fills this on trusted domains */
2529 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2531 return NT_STATUS_NO_MEMORY;
2535 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2536 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2538 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2539 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2541 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2542 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2546 * TODO: once we support multiple domains within our forest,
2547 * we need to fill this correct (or let the caller do it
2548 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2550 tei->parent_index = 0;
2552 tei->trust_type = tdo->trust_type;
2553 tei->trust_attributes = tdo->trust_attributes;
2555 info->trust_extension.info = te;
2557 info->domainname.string = tdo->netbios_name.string;
2558 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2559 info->dns_domainname.string = tdo->domain_name.string;
2561 info->dns_domainname.string = NULL;
2563 info->domain_sid = tdo->sid;
2564 info->domain_guid = domain_guid;
2566 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2567 info->dns_forestname.string = NULL;
2569 return NT_STATUS_OK;
2573 netr_LogonGetDomainInfo
2574 this is called as part of the ADS domain logon procedure.
2576 It has an important role in convaying details about the client, such
2577 as Operating System, Version, Service Pack etc.
2579 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2580 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2582 struct netlogon_creds_CredentialState *creds;
2583 const char * const trusts_attrs[] = {
2584 "securityIdentifier",
2592 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2593 "msDS-SupportedEncryptionTypes", NULL };
2594 const char *sam_account_name, *old_dns_hostname;
2595 struct ldb_context *sam_ctx;
2596 const struct GUID *our_domain_guid = NULL;
2597 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2598 struct ldb_message **res1, *new_msg;
2599 struct ldb_result *trusts_res = NULL;
2600 struct ldb_dn *workstation_dn;
2601 struct netr_DomainInformation *domain_info;
2602 struct netr_LsaPolicyInformation *lsa_policy_info;
2603 struct auth_session_info *workstation_session_info = NULL;
2604 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2605 bool update_dns_hostname = true;
2609 status = dcesrv_netr_creds_server_step_check(dce_call,
2611 r->in.computer_name,
2613 r->out.return_authenticator,
2615 if (!NT_STATUS_IS_OK(status)) {
2617 char* remote = NULL;
2618 TALLOC_CTX *frame = talloc_stackframe();
2619 remote = tsocket_address_string(dce_call->conn->remote_address,
2621 local = tsocket_address_string(dce_call->conn->local_address,
2623 DBG_ERR(("Bad credentials - "
2624 "computer[%s] remote[%s] local[%s]\n"),
2625 log_escape(frame, r->in.computer_name),
2630 NT_STATUS_NOT_OK_RETURN(status);
2632 /* We want to avoid connecting as system. */
2633 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2634 if (sam_ctx == NULL) {
2635 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2638 switch (r->in.level) {
2639 case 1: /* Domain information */
2641 if (r->in.query->workstation_info == NULL) {
2642 return NT_STATUS_INVALID_PARAMETER;
2645 /* Prepares the workstation DN */
2646 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2647 dom_sid_string(mem_ctx, creds->sid));
2648 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2650 /* Get the workstation's session info from the database. */
2651 status = authsam_get_session_info_principal(mem_ctx,
2652 dce_call->conn->dce_ctx->lp_ctx,
2654 NULL, /* principal */
2656 0, /* session_info_flags */
2657 &workstation_session_info);
2658 if (!NT_STATUS_IS_OK(status)) {
2663 * Reconnect to samdb as the workstation, now that we have its
2664 * session info. We do this so the database update can be
2665 * attributed to the workstation account in the audit logs --
2666 * otherwise it might be incorrectly attributed to
2669 sam_ctx = dcesrv_samdb_connect_session_info(mem_ctx,
2671 workstation_session_info,
2672 workstation_session_info);
2673 if (sam_ctx == NULL) {
2674 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2677 /* Lookup for attributes in workstation object */
2678 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2681 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2684 /* Gets the sam account name which is checked against the DNS
2685 * hostname parameter. */
2686 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2689 if (sam_account_name == NULL) {
2690 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2693 if (r->in.query->workstation_info->dns_hostname == NULL) {
2694 update_dns_hostname = false;
2697 /* Gets the old DNS hostname */
2698 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2703 * Updates the DNS hostname when the client wishes that the
2704 * server should handle this for him
2705 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
2706 * See MS-NRPC section 3.5.4.3.9
2708 if ((r->in.query->workstation_info->workstation_flags
2709 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2710 update_dns_hostname = false;
2713 /* Gets host information and put them into our directory */
2715 new_msg = ldb_msg_new(mem_ctx);
2716 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2718 new_msg->dn = workstation_dn;
2720 /* Sets the OS name */
2722 if (r->in.query->workstation_info->os_name.string == NULL) {
2723 return NT_STATUS_INVALID_PARAMETER;
2726 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2727 r->in.query->workstation_info->os_name.string);
2728 if (ret != LDB_SUCCESS) {
2729 return NT_STATUS_NO_MEMORY;
2733 * Sets information from "os_version". On an empty structure
2734 * the values are cleared.
2736 if (r->in.query->workstation_info->os_version.os != NULL) {
2737 struct netr_OsVersionInfoEx *os_version;
2738 const char *os_version_str;
2740 os_version = &r->in.query->workstation_info->os_version.os->os;
2742 if (os_version->CSDVersion == NULL) {
2743 return NT_STATUS_INVALID_PARAMETER;
2746 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2747 os_version->MajorVersion,
2748 os_version->MinorVersion,
2749 os_version->BuildNumber);
2750 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2752 if (strlen(os_version->CSDVersion) != 0) {
2753 ret = ldb_msg_add_string(new_msg,
2754 "operatingSystemServicePack",
2755 os_version->CSDVersion);
2757 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2758 "operatingSystemServicePack");
2760 if (ret != LDB_SUCCESS) {
2761 return NT_STATUS_NO_MEMORY;
2764 ret = ldb_msg_add_string(new_msg,
2765 "operatingSystemVersion",
2767 if (ret != LDB_SUCCESS) {
2768 return NT_STATUS_NO_MEMORY;
2771 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2772 "operatingSystemServicePack");
2773 if (ret != LDB_SUCCESS) {
2774 return NT_STATUS_NO_MEMORY;
2777 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2778 "operatingSystemVersion");
2779 if (ret != LDB_SUCCESS) {
2780 return NT_STATUS_NO_MEMORY;
2785 * If the boolean "update_dns_hostname" remained true, then we
2786 * are fine to start the update.
2788 if (update_dns_hostname) {
2789 ret = ldb_msg_add_string(new_msg,
2791 r->in.query->workstation_info->dns_hostname);
2792 if (ret != LDB_SUCCESS) {
2793 return NT_STATUS_NO_MEMORY;
2796 /* This manual "servicePrincipalName" generation is
2797 * still needed! Since the update in the samldb LDB
2798 * module does only work if the entries already exist
2799 * which isn't always the case. */
2800 ret = ldb_msg_add_string(new_msg,
2801 "servicePrincipalName",
2802 talloc_asprintf(new_msg, "HOST/%s",
2803 r->in.computer_name));
2804 if (ret != LDB_SUCCESS) {
2805 return NT_STATUS_NO_MEMORY;
2808 ret = ldb_msg_add_string(new_msg,
2809 "servicePrincipalName",
2810 talloc_asprintf(new_msg, "HOST/%s",
2811 r->in.query->workstation_info->dns_hostname));
2812 if (ret != LDB_SUCCESS) {
2813 return NT_STATUS_NO_MEMORY;
2817 if (dsdb_replace(sam_ctx, new_msg, DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) != LDB_SUCCESS) {
2818 DEBUG(3,("Impossible to update samdb: %s\n",
2819 ldb_errstring(sam_ctx)));
2822 talloc_free(new_msg);
2824 /* Writes back the domain information */
2826 our_domain_guid = samdb_domain_guid(sam_ctx);
2827 if (our_domain_guid == NULL) {
2828 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2831 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2832 if (!NT_STATUS_IS_OK(status)) {
2836 status = dsdb_trust_search_tdos(sam_ctx,
2841 if (!NT_STATUS_IS_OK(status)) {
2845 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2846 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2848 ZERO_STRUCTP(domain_info);
2850 /* Informations about the local and trusted domains */
2852 status = fill_our_one_domain_info(mem_ctx,
2855 &domain_info->primary_domain,
2857 if (!NT_STATUS_IS_OK(status)) {
2861 domain_info->trusted_domain_count = trusts_res->count + 1;
2862 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2863 struct netr_OneDomainInfo,
2864 domain_info->trusted_domain_count);
2865 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2867 for (i=0; i < trusts_res->count; i++) {
2868 struct netr_OneDomainInfo *o =
2869 &domain_info->trusted_domains[i];
2870 /* we can't know the guid of trusts outside our forest */
2871 struct GUID trust_domain_guid = GUID_zero();
2872 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2874 status = dsdb_trust_parse_tdo_info(mem_ctx,
2875 trusts_res->msgs[i],
2877 if (!NT_STATUS_IS_OK(status)) {
2881 status = fill_trust_one_domain_info(mem_ctx,
2885 if (!NT_STATUS_IS_OK(status)) {
2890 status = fill_our_one_domain_info(mem_ctx,
2893 &domain_info->trusted_domains[i],
2895 if (!NT_STATUS_IS_OK(status)) {
2899 /* Sets the supported encryption types */
2900 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2901 "msDS-SupportedEncryptionTypes",
2902 default_supported_enc_types);
2904 /* Other host domain information */
2906 lsa_policy_info = talloc(mem_ctx,
2907 struct netr_LsaPolicyInformation);
2908 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2909 ZERO_STRUCTP(lsa_policy_info);
2911 domain_info->lsa_policy = *lsa_policy_info;
2913 /* The DNS hostname is only returned back when there is a chance
2915 if ((r->in.query->workstation_info->workstation_flags
2916 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2917 domain_info->dns_hostname.string = old_dns_hostname;
2919 domain_info->dns_hostname.string = NULL;
2922 domain_info->workstation_flags =
2923 r->in.query->workstation_info->workstation_flags & (
2924 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2926 r->out.info->domain_info = domain_info;
2928 case 2: /* LSA policy information - not used at the moment */
2929 lsa_policy_info = talloc(mem_ctx,
2930 struct netr_LsaPolicyInformation);
2931 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2932 ZERO_STRUCTP(lsa_policy_info);
2934 r->out.info->lsa_policy_info = lsa_policy_info;
2937 return NT_STATUS_INVALID_LEVEL;
2941 return NT_STATUS_OK;
2946 netr_ServerPasswordGet
2948 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2949 struct netr_ServerPasswordGet *r)
2951 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2954 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2955 TALLOC_CTX *mem_ctx,
2956 struct dom_sid *user_sid,
2957 struct ldb_dn *obj_dn)
2959 const char *rodc_attrs[] = { "msDS-NeverRevealGroup",
2960 "msDS-RevealOnDemandGroup",
2961 "userAccountControl",
2963 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2964 struct ldb_dn *rodc_dn;
2966 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2969 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2970 dom_sid_string(mem_ctx, user_sid));
2971 if (!ldb_dn_validate(rodc_dn)) goto denied;
2974 * do the two searches we need
2975 * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list
2976 * out of the extended DNs
2978 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2979 DSDB_SEARCH_SHOW_EXTENDED_DN);
2980 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2982 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2983 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2985 werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx,
2990 if (W_ERROR_IS_OK(werr)) {
3001 netr_NetrLogonSendToSam
3003 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3004 struct netr_NetrLogonSendToSam *r)
3006 struct netlogon_creds_CredentialState *creds;
3007 struct ldb_context *sam_ctx;
3009 DATA_BLOB decrypted_blob;
3010 enum ndr_err_code ndr_err;
3011 struct netr_SendToSamBase base_msg = { 0 };
3013 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3015 r->in.computer_name,
3017 r->out.return_authenticator,
3020 NT_STATUS_NOT_OK_RETURN(nt_status);
3022 switch (creds->secure_channel_type) {
3026 case SEC_CHAN_WKSTA:
3027 case SEC_CHAN_DNS_DOMAIN:
3028 case SEC_CHAN_DOMAIN:
3030 return NT_STATUS_INVALID_PARAMETER;
3032 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
3033 creds->secure_channel_type));
3034 return NT_STATUS_INVALID_PARAMETER;
3037 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3038 if (sam_ctx == NULL) {
3039 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3042 /* Buffer is meant to be 16-bit aligned */
3043 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3044 nt_status = netlogon_creds_aes_decrypt(creds,
3045 r->in.opaque_buffer,
3048 nt_status = netlogon_creds_arcfour_crypt(creds,
3049 r->in.opaque_buffer,
3052 if (!NT_STATUS_IS_OK(nt_status)) {
3056 decrypted_blob.data = r->in.opaque_buffer;
3057 decrypted_blob.length = r->in.buffer_len;
3059 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
3060 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
3062 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3063 /* We only partially implement SendToSam */
3064 return NT_STATUS_NOT_IMPLEMENTED;
3067 /* Now 'send' to SAM */
3068 switch (base_msg.message_type) {
3069 case SendToSamResetBadPasswordCount:
3071 struct ldb_message *msg = ldb_msg_new(mem_ctx);
3072 struct ldb_dn *dn = NULL;
3076 ret = ldb_transaction_start(sam_ctx);
3077 if (ret != LDB_SUCCESS) {
3078 return NT_STATUS_INTERNAL_ERROR;
3081 ret = dsdb_find_dn_by_guid(sam_ctx,
3083 &base_msg.message.reset_bad_password.guid,
3086 if (ret != LDB_SUCCESS) {
3087 ldb_transaction_cancel(sam_ctx);
3088 return NT_STATUS_INVALID_PARAMETER;
3091 if (creds->secure_channel_type == SEC_CHAN_RODC &&
3092 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
3093 DEBUG(1, ("Client asked to reset bad password on "
3094 "an arbitrary user: %s\n",
3095 ldb_dn_get_linearized(dn)));
3096 ldb_transaction_cancel(sam_ctx);
3097 return NT_STATUS_INVALID_PARAMETER;
3102 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
3103 if (ret != LDB_SUCCESS) {
3104 ldb_transaction_cancel(sam_ctx);
3105 return NT_STATUS_INVALID_PARAMETER;
3108 ret = dsdb_replace(sam_ctx, msg, 0);
3109 if (ret != LDB_SUCCESS) {
3110 ldb_transaction_cancel(sam_ctx);
3111 return NT_STATUS_INVALID_PARAMETER;
3114 ret = ldb_transaction_commit(sam_ctx);
3115 if (ret != LDB_SUCCESS) {
3116 ldb_transaction_cancel(sam_ctx);
3117 return NT_STATUS_INTERNAL_ERROR;
3123 return NT_STATUS_NOT_IMPLEMENTED;
3126 return NT_STATUS_OK;
3129 struct dcesrv_netr_DsRGetDCName_base_state {
3130 struct dcesrv_call_state *dce_call;
3131 TALLOC_CTX *mem_ctx;
3133 struct netr_DsRGetDCNameEx2 r;
3134 const char *client_site;
3137 struct netr_DsRGetDCName *dc;
3138 struct netr_DsRGetDCNameEx *dcex;
3139 struct netr_DsRGetDCNameEx2 *dcex2;
3143 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
3145 /* Returns a nonzero value if multiple bits in 'val' are set. */
3146 static bool multiple_bits_set(uint32_t val)
3149 * Subtracting one from an integer has the effect of flipping all the
3150 * bits from the least significant bit up to and including the least
3151 * significant '1' bit. For example,
3157 * If 'val' is zero, all the bits will be flipped and thus the bitwise
3158 * AND of 'val' with 'val - 1' will be zero.
3160 * If the integer is nonzero, the least significant '1' bit will be
3161 * ANDed with a '0' bit and so will be reset in the final result, but
3162 * all other '1' bits will remain set. In other words, the effect of
3163 * this expression is to mask off the least significant bit that is
3164 * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
3165 * must contain multiple set bits.
3167 return val & (val - 1);
3170 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
3172 struct dcesrv_call_state *dce_call = state->dce_call;
3173 struct imessaging_context *imsg_ctx =
3174 dcesrv_imessaging_context(dce_call->conn);
3175 TALLOC_CTX *mem_ctx = state->mem_ctx;
3176 struct netr_DsRGetDCNameEx2 *r = &state->r;
3177 struct ldb_context *sam_ctx;
3178 struct netr_DsRGetDCNameInfo *info;
3179 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3180 const struct tsocket_address *local_address;
3181 char *local_addr = NULL;
3182 const struct tsocket_address *remote_address;
3183 char *remote_addr = NULL;
3184 const char *server_site_name;
3186 struct netlogon_samlogon_response response;
3188 const char *dc_name = NULL;
3189 const char *domain_name = NULL;
3191 bool different_domain = true;
3192 uint32_t valid_flags;
3195 ZERO_STRUCTP(r->out.info);
3197 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3198 if (sam_ctx == NULL) {
3199 return WERR_DS_UNAVAILABLE;
3202 local_address = dcesrv_connection_get_local_address(dce_call->conn);
3203 if (tsocket_address_is_inet(local_address, "ip")) {
3204 local_addr = tsocket_address_inet_addr_string(local_address, state);
3205 W_ERROR_HAVE_NO_MEMORY(local_addr);
3208 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
3209 if (tsocket_address_is_inet(remote_address, "ip")) {
3210 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
3211 W_ERROR_HAVE_NO_MEMORY(remote_addr);
3214 /* "server_unc" is ignored by w2k3 */
3217 * With the following flags:
3218 * DS_FORCE_REDISCOVERY (Flag A)
3219 * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
3220 * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
3221 * DS_GC_SERVER_REQUIRED (Flag D)
3222 * DS_PDC_REQUIRED (Flag E)
3223 * DS_BACKGROUND_ONLY (Flag F)
3224 * DS_IP_REQUIRED (Flag G)
3225 * DS_KDC_REQUIRED (Flag H)
3226 * DS_TIMESERV_REQUIRED (Flag I)
3227 * DS_WRITABLE_REQUIRED (Flag J)
3228 * DS_GOOD_TIMESERV_PREFERRED (Flag K)
3229 * DS_AVOID_SELF (Flag L)
3230 * DS_ONLY_LDAP_NEEDED (Flag M)
3231 * DS_IS_FLAT_NAME (Flag N)
3232 * DS_IS_DNS_NAME (Flag O)
3233 * DS_TRY_NEXTCLOSEST_SITE (Flag P)
3234 * DS_DIRECTORY_SERVICE_6_REQUIRED (Flag Q)
3235 * DS_WEB_SERVICE_REQUIRED (Flag T)
3236 * DS_DIRECTORY_SERVICE_8_REQUIRED (Flag U)
3237 * DS_DIRECTORY_SERVICE_9_REQUIRED (Flag V)
3238 * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
3239 * DS_RETURN_DNS_NAME (Flag R)
3240 * DS_RETURN_FLAT_NAME (Flag S)
3242 * MS-NRPC 3.5.4.3.1 says:
3244 * On receiving this call, the server MUST perform the following Flags
3245 * parameter validations:
3246 * - Flags D, E, and H MUST NOT be combined with each other.
3247 * - Flag N MUST NOT be combined with the O flag.
3248 * - Flag R MUST NOT be combined with the S flag.
3249 * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
3250 * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or H.
3251 * - Flag P MUST NOT be set when the SiteName parameter is provided.
3252 * The server MUST return ERROR_INVALID_FLAGS for any of the previously
3253 * mentioned conflicting combinations.
3257 dc_level = dsdb_dc_functional_level(sam_ctx);
3258 valid_flags = DSGETDC_VALID_FLAGS;
3259 if (dc_level >= DS_DOMAIN_FUNCTION_2012) {
3260 valid_flags |= DS_DIRECTORY_SERVICE_8_REQUIRED;
3262 if (dc_level >= DS_DOMAIN_FUNCTION_2012_R2) {
3263 valid_flags |= DS_DIRECTORY_SERVICE_9_REQUIRED;
3265 if (dc_level >= DS_DOMAIN_FUNCTION_2016) {
3266 valid_flags |= DS_DIRECTORY_SERVICE_10_REQUIRED;
3268 if (r->in.flags & ~valid_flags) {
3270 * TODO: add tests to prove this (maybe based on the
3271 * msDS-Behavior-Version levels of dc, domain and/or forest
3273 return WERR_INVALID_FLAGS;
3276 /* Flags D, E, and H MUST NOT be combined with each other. */
3277 #define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
3278 if (multiple_bits_set(r->in.flags & _DEH)) {
3279 return WERR_INVALID_FLAGS;
3282 /* Flag N MUST NOT be combined with the O flag. */
3283 if (r->in.flags & DS_IS_FLAT_NAME &&
3284 r->in.flags & DS_IS_DNS_NAME) {
3285 return WERR_INVALID_FLAGS;
3288 /* Flag R MUST NOT be combined with the S flag. */
3289 if (r->in.flags & DS_RETURN_DNS_NAME &&
3290 r->in.flags & DS_RETURN_FLAT_NAME) {
3291 return WERR_INVALID_FLAGS;
3294 /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
3296 DS_DIRECTORY_SERVICE_REQUIRED | \
3297 DS_DIRECTORY_SERVICE_6_REQUIRED | \
3298 DS_DIRECTORY_SERVICE_8_REQUIRED | \
3299 DS_DIRECTORY_SERVICE_9_REQUIRED | \
3300 DS_DIRECTORY_SERVICE_10_REQUIRED | \
3302 if (multiple_bits_set(r->in.flags & _BQUVW)) {
3303 return WERR_INVALID_FLAGS;
3307 * Flag K MUST NOT be combined with any of the flags:
3310 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
3312 (DS_DIRECTORY_SERVICE_REQUIRED |
3313 DS_DIRECTORY_SERVICE_PREFERRED |
3314 DS_GC_SERVER_REQUIRED |
3317 return WERR_INVALID_FLAGS;
3320 /* Flag P MUST NOT be set when the SiteName parameter is provided. */
3321 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
3323 return WERR_INVALID_FLAGS;
3327 * If we send an all-zero GUID, we should ignore it as winbind actually
3328 * checks it with a DNS query. Windows also appears to ignore it.
3330 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
3331 r->in.domain_guid = NULL;
3334 /* Attempt winbind search only if we suspect the domain is incorrect */
3335 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
3336 if (r->in.flags & DS_IS_FLAT_NAME) {
3337 if (strcasecmp_m(r->in.domain_name,
3338 lpcfg_sam_name(lp_ctx)) == 0) {
3339 different_domain = false;
3341 } else if (r->in.flags & DS_IS_DNS_NAME) {
3342 if (strcasecmp_m(r->in.domain_name,
3343 lpcfg_dnsdomain(lp_ctx)) == 0) {
3344 different_domain = false;
3347 if (strcasecmp_m(r->in.domain_name,
3348 lpcfg_sam_name(lp_ctx)) == 0 ||
3349 strcasecmp_m(r->in.domain_name,
3350 lpcfg_dnsdomain(lp_ctx)) == 0) {
3351 different_domain = false;
3356 * We need to be able to handle empty domain names, where we
3357 * revert to our domain by default.
3359 different_domain = false;
3362 /* Proof server site parameter "site_name" if it was specified */
3363 server_site_name = samdb_server_site_name(sam_ctx, state);
3364 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3365 if (different_domain || (r->in.site_name != NULL &&
3366 (strcasecmp_m(r->in.site_name,
3367 server_site_name) != 0))) {
3369 struct dcerpc_binding_handle *irpc_handle = NULL;
3370 struct tevent_req *subreq = NULL;
3373 * Retrieve the client site to override the winbind response.
3375 * DO NOT use Windows fallback for client site.
3376 * In the case of multiple domains, this is plainly wrong.
3378 * Note: It's possible that the client may belong to multiple
3379 * subnets across domains. It's not clear what this would mean,
3380 * but here we only return what this domain knows.
3382 state->client_site = samdb_client_site_name(sam_ctx,
3388 irpc_handle = irpc_binding_handle_by_name(state,
3391 &ndr_table_winbind);
3392 if (irpc_handle == NULL) {
3393 DEBUG(0,("Failed to get binding_handle for "
3394 "winbind_server task\n"));
3395 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3396 return WERR_SERVICE_NOT_FOUND;
3399 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3401 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3403 subreq = dcerpc_wbint_DsGetDcName_send(state,
3404 dce_call->event_ctx,
3411 if (subreq == NULL) {
3412 return WERR_NOT_ENOUGH_MEMORY;
3415 tevent_req_set_callback(subreq,
3416 dcesrv_netr_DsRGetDCName_base_done,
3422 guid_str = r->in.domain_guid != NULL ?
3423 GUID_string(state, r->in.domain_guid) : NULL;
3425 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3429 r->in.client_account,
3430 r->in.mask, remote_addr,
3431 NETLOGON_NT_VERSION_5EX_WITH_IP,
3432 lp_ctx, &response, true);
3433 if (!NT_STATUS_IS_OK(status)) {
3434 return ntstatus_to_werror(status);
3438 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3439 * (O) flag when the returned forest name is in DNS format. This is here
3440 * always the case (see below).
3442 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3444 if (r->in.flags & DS_RETURN_DNS_NAME) {
3445 dc_name = response.data.nt5_ex.pdc_dns_name;
3446 domain_name = response.data.nt5_ex.dns_domain;
3448 * According to MS-NRPC 2.2.1.2.1 we should set the
3449 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3450 * the returned information is in DNS form.
3452 response.data.nt5_ex.server_type |=
3453 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3454 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3455 dc_name = response.data.nt5_ex.pdc_name;
3456 domain_name = response.data.nt5_ex.domain_name;
3460 * TODO: autodetect what we need to return
3461 * based on the given arguments
3463 dc_name = response.data.nt5_ex.pdc_name;
3464 domain_name = response.data.nt5_ex.domain_name;
3467 if (!dc_name || !dc_name[0]) {
3468 return WERR_NO_SUCH_DOMAIN;
3471 if (!domain_name || !domain_name[0]) {
3472 return WERR_NO_SUCH_DOMAIN;
3475 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3476 W_ERROR_HAVE_NO_MEMORY(info);
3477 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3478 dc_name[0] != '\\'? "\\\\":"",
3479 talloc_strdup(mem_ctx, dc_name));
3480 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3482 pdc_ip = local_addr;
3483 if (pdc_ip == NULL) {
3484 pdc_ip = "127.0.0.1";
3486 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3487 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3488 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3489 info->domain_guid = response.data.nt5_ex.domain_uuid;
3490 info->domain_name = domain_name;
3491 info->forest_name = response.data.nt5_ex.forest;
3492 info->dc_flags = response.data.nt5_ex.server_type;
3493 if (r->in.flags & DS_RETURN_DNS_NAME) {
3494 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3495 * returned if we are returning info->dc_unc containing a FQDN.
3496 * This attribute is called DomainControllerName in the specs,
3497 * it seems that we decide to return FQDN or netbios depending on
3498 * DS_RETURN_DNS_NAME.
3500 info->dc_flags |= DS_DNS_CONTROLLER;
3502 info->dc_site_name = response.data.nt5_ex.server_site;
3503 info->client_site_name = response.data.nt5_ex.client_site;
3505 *r->out.info = info;
3510 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3512 struct dcesrv_netr_DsRGetDCName_base_state *state =
3513 tevent_req_callback_data(subreq,
3514 struct dcesrv_netr_DsRGetDCName_base_state);
3515 struct dcesrv_call_state *dce_call = state->dce_call;
3516 NTSTATUS result, status;
3518 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3521 TALLOC_FREE(subreq);
3523 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3524 state->r.out.result = WERR_TIMEOUT;
3528 if (!NT_STATUS_IS_OK(status)) {
3529 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3531 state->r.out.result = WERR_GEN_FAILURE;
3535 if (!NT_STATUS_IS_OK(result)) {
3536 DBG_NOTICE("DC location via winbind failed - %s\n",
3538 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3542 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3543 DBG_ERR("DC location via winbind returned no results\n");
3544 state->r.out.result = WERR_GEN_FAILURE;
3548 if (state->r.out.info[0]->dc_unc == NULL) {
3549 DBG_ERR("DC location via winbind returned no DC unc\n");
3550 state->r.out.result = WERR_GEN_FAILURE;
3555 * Either the supplied site name is NULL (possibly via
3556 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3557 * the input match name.
3559 * TODO: Currently this means that requests with NETBIOS domain
3560 * names can fail because they do not return the site name.
3562 if (state->r.in.site_name == NULL ||
3563 strcasecmp_m("", state->r.in.site_name) == 0 ||
3564 (state->r.out.info[0]->dc_site_name != NULL &&
3565 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3566 state->r.in.site_name) == 0)) {
3568 state->r.out.info[0]->client_site_name =
3569 talloc_move(state->mem_ctx, &state->client_site);
3572 * Make sure to return our DC UNC with // prefix.
3573 * Winbind currently doesn't send the leading slashes
3576 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3577 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3578 const char *dc_unc = NULL;
3580 dc_unc = talloc_asprintf(state->mem_ctx,
3582 state->r.out.info[0]->dc_unc);
3583 state->r.out.info[0]->dc_unc = dc_unc;
3586 state->r.out.result = WERR_OK;
3588 state->r.out.info = NULL;
3589 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3593 if (state->_r.dcex2 != NULL) {
3594 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3595 r->out.result = state->r.out.result;
3596 } else if (state->_r.dcex != NULL) {
3597 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3598 r->out.result = state->r.out.result;
3599 } else if (state->_r.dc != NULL) {
3600 struct netr_DsRGetDCName *r = state->_r.dc;
3601 r->out.result = state->r.out.result;
3605 status = dcesrv_reply(dce_call);
3606 if (!NT_STATUS_IS_OK(status)) {
3607 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3608 nt_errstr(status)));
3613 netr_DsRGetDCNameEx2
3615 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3616 TALLOC_CTX *mem_ctx,
3617 struct netr_DsRGetDCNameEx2 *r)
3619 struct dcesrv_netr_DsRGetDCName_base_state *state;
3621 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3622 if (state == NULL) {
3623 return WERR_NOT_ENOUGH_MEMORY;
3626 state->dce_call = dce_call;
3627 state->mem_ctx = mem_ctx;
3630 state->_r.dcex2 = r;
3632 return dcesrv_netr_DsRGetDCName_base_call(state);
3638 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3639 struct netr_DsRGetDCNameEx *r)
3641 struct dcesrv_netr_DsRGetDCName_base_state *state;
3643 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3644 if (state == NULL) {
3645 return WERR_NOT_ENOUGH_MEMORY;
3648 state->dce_call = dce_call;
3649 state->mem_ctx = mem_ctx;
3651 state->r.in.server_unc = r->in.server_unc;
3652 state->r.in.client_account = NULL;
3653 state->r.in.mask = 0;
3654 state->r.in.domain_guid = r->in.domain_guid;
3655 state->r.in.domain_name = r->in.domain_name;
3656 state->r.in.site_name = r->in.site_name;
3657 state->r.in.flags = r->in.flags;
3658 state->r.out.info = r->out.info;
3662 return dcesrv_netr_DsRGetDCName_base_call(state);
3668 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3669 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3670 * insists that it be ignored.
3672 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3673 struct netr_DsRGetDCName *r)
3675 struct dcesrv_netr_DsRGetDCName_base_state *state;
3677 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3678 if (state == NULL) {
3679 return WERR_NOT_ENOUGH_MEMORY;
3682 state->dce_call = dce_call;
3683 state->mem_ctx = mem_ctx;
3685 state->r.in.server_unc = r->in.server_unc;
3686 state->r.in.client_account = NULL;
3687 state->r.in.mask = 0;
3688 state->r.in.domain_name = r->in.domain_name;
3689 state->r.in.domain_guid = r->in.domain_guid;
3691 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3692 state->r.in.flags = r->in.flags;
3693 state->r.out.info = r->out.info;
3697 return dcesrv_netr_DsRGetDCName_base_call(state);
3700 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3702 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3703 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3705 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3710 netr_NetrEnumerateTrustedDomainsEx
3712 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3713 struct netr_NetrEnumerateTrustedDomainsEx *r)
3715 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3720 netr_DsRAddressToSitenamesExW
3722 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3723 struct netr_DsRAddressToSitenamesExW *r)
3725 struct ldb_context *sam_ctx;
3726 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3727 sa_family_t sin_family;
3728 struct sockaddr_in *addr;
3730 struct sockaddr_in6 *addr6;
3731 char addr_str[INET6_ADDRSTRLEN];
3733 char addr_str[INET_ADDRSTRLEN];
3739 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3740 if (sam_ctx == NULL) {
3741 return WERR_DS_UNAVAILABLE;
3744 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3745 W_ERROR_HAVE_NO_MEMORY(ctr);
3749 ctr->count = r->in.count;
3750 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3751 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3752 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3753 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3755 for (i=0; i<ctr->count; i++) {
3756 ctr->sitename[i].string = NULL;
3757 ctr->subnetname[i].string = NULL;
3759 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3762 /* The first two byte of the buffer are reserved for the
3763 * "sin_family" but for now only the first one is used. */
3764 sin_family = r->in.addresses[i].buffer[0];
3766 switch (sin_family) {
3768 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3771 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3772 res = inet_ntop(AF_INET, &addr->sin_addr,
3773 addr_str, sizeof(addr_str));
3777 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3780 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3781 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3782 addr_str, sizeof(addr_str));
3793 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3798 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3799 ctr->subnetname[i].string = subnet_name;
3807 netr_DsRAddressToSitenamesW
3809 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3810 struct netr_DsRAddressToSitenamesW *r)
3812 struct netr_DsRAddressToSitenamesExW r2;
3813 struct netr_DsRAddressToSitenamesWCtr *ctr;
3819 r2.in.server_name = r->in.server_name;
3820 r2.in.count = r->in.count;
3821 r2.in.addresses = r->in.addresses;
3823 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3824 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3826 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3827 W_ERROR_HAVE_NO_MEMORY(ctr);
3831 ctr->count = r->in.count;
3832 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3833 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3835 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3837 for (i=0; i<ctr->count; i++) {
3838 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3846 netr_DsrGetDcSiteCoverageW
3848 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3849 struct netr_DsrGetDcSiteCoverageW *r)
3851 struct ldb_context *sam_ctx;
3852 struct DcSitesCtr *ctr;
3854 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3855 if (sam_ctx == NULL) {
3856 return WERR_DS_UNAVAILABLE;
3859 ctr = talloc(mem_ctx, struct DcSitesCtr);
3860 W_ERROR_HAVE_NO_MEMORY(ctr);
3864 /* For now only return our default site */
3866 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3867 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3868 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3869 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3875 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3876 struct ldb_context *sam_ctx,
3877 struct netr_DomainTrustList *trusts,
3878 uint32_t trust_flags)
3880 struct ldb_dn *system_dn;
3881 struct ldb_message **dom_res = NULL;
3882 const char *trust_attrs[] = { "flatname", "trustPartner",
3883 "securityIdentifier", "trustDirection",
3884 "trustType", "trustAttributes", NULL };
3889 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3890 NETR_TRUST_FLAG_OUTBOUND))) {
3891 return WERR_INVALID_FLAGS;
3894 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3895 ldb_get_default_basedn(sam_ctx),
3896 "(&(objectClass=container)(cn=System))");
3898 return WERR_GEN_FAILURE;
3901 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3902 &dom_res, trust_attrs,
3903 "(objectclass=trustedDomain)");
3905 for (i = 0; i < ret; i++) {
3906 unsigned int trust_dir;
3909 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3910 "trustDirection", 0);
3912 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3913 flags |= NETR_TRUST_FLAG_INBOUND;
3915 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3916 flags |= NETR_TRUST_FLAG_OUTBOUND;
3919 if (!(flags & trust_flags)) {
3920 /* this trust direction was not requested */
3925 trusts->array = talloc_realloc(trusts, trusts->array,
3926 struct netr_DomainTrust,
3928 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3930 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3931 if (!trusts->array[n].netbios_name) {
3932 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3933 "without flatname\n",
3934 ldb_dn_get_linearized(dom_res[i]->dn)));
3937 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3939 trusts->array[n].trust_flags = flags;
3940 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3941 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3942 /* TODO: find if we have parent in the list */
3943 trusts->array[n].parent_index = 0;
3946 trusts->array[n].trust_type =
3947 ldb_msg_find_attr_as_uint(dom_res[i],
3949 trusts->array[n].trust_attributes =
3950 ldb_msg_find_attr_as_uint(dom_res[i],
3951 "trustAttributes", 0);
3953 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3954 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3955 struct dom_sid zero_sid;
3956 ZERO_STRUCT(zero_sid);
3957 trusts->array[n].sid =
3958 dom_sid_dup(trusts, &zero_sid);
3960 trusts->array[n].sid =
3961 samdb_result_dom_sid(trusts, dom_res[i],
3962 "securityIdentifier");
3964 trusts->array[n].guid = GUID_zero();
3966 trusts->count = n + 1;
3969 talloc_free(dom_res);
3974 netr_DsrEnumerateDomainTrusts
3976 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3977 TALLOC_CTX *mem_ctx,
3978 struct netr_DsrEnumerateDomainTrusts *r)
3980 struct netr_DomainTrustList *trusts;
3981 struct ldb_context *sam_ctx;
3983 struct ldb_message **dom_res;
3984 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3985 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3986 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3990 if (r->in.trust_flags & 0xFFFFFE00) {
3991 return WERR_INVALID_FLAGS;
3994 /* TODO: turn to hard check once we are sure this is 100% correct */
3995 if (!r->in.server_name) {
3996 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3997 "But received NULL!\n", dnsdomain));
3999 p = strchr(r->in.server_name, '.');
4001 DEBUG(3, ("Invalid domain! Expected name in domain "
4002 "[%s]. But received [%s]!\n",
4003 dnsdomain, r->in.server_name));
4004 p = r->in.server_name;
4008 if (strcasecmp(p, dnsdomain)) {
4009 DEBUG(3, ("Invalid domain! Expected name in domain "
4010 "[%s]. But received [%s]!\n",
4011 dnsdomain, r->in.server_name));
4015 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
4016 W_ERROR_HAVE_NO_MEMORY(trusts);
4019 r->out.trusts = trusts;
4021 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4022 if (sam_ctx == NULL) {
4023 return WERR_GEN_FAILURE;
4026 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
4027 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
4029 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
4030 trusts, r->in.trust_flags);
4031 W_ERROR_NOT_OK_RETURN(werr);
4034 /* NOTE: we currently are always the root of the forest */
4035 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
4036 uint32_t n = trusts->count;
4038 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
4039 &dom_res, dom_attrs);
4041 return WERR_GEN_FAILURE;
4044 trusts->count = n + 1;
4045 trusts->array = talloc_realloc(trusts, trusts->array,
4046 struct netr_DomainTrust,
4048 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4050 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
4051 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
4052 trusts->array[n].trust_flags =
4053 NETR_TRUST_FLAG_NATIVE |
4054 NETR_TRUST_FLAG_TREEROOT |
4055 NETR_TRUST_FLAG_IN_FOREST |
4056 NETR_TRUST_FLAG_PRIMARY;
4057 /* we are always the root domain for now */
4058 trusts->array[n].parent_index = 0;
4059 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
4060 trusts->array[n].trust_attributes = 0;
4061 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
4064 trusts->array[n].guid = samdb_result_guid(dom_res[0],
4066 talloc_free(dom_res);
4074 netr_DsrDeregisterDNSHostRecords
4076 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4077 struct netr_DsrDeregisterDNSHostRecords *r)
4079 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4083 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4084 struct netr_ServerGetTrustInfo *r);
4087 netr_ServerTrustPasswordsGet
4089 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4090 struct netr_ServerTrustPasswordsGet *r)
4092 struct netr_ServerGetTrustInfo r2 = {};
4093 struct netr_TrustInfo *_ti = NULL;
4096 r2.in.server_name = r->in.server_name;
4097 r2.in.account_name = r->in.account_name;
4098 r2.in.secure_channel_type = r->in.secure_channel_type;
4099 r2.in.computer_name = r->in.computer_name;
4100 r2.in.credential = r->in.credential;
4102 r2.out.return_authenticator = r->out.return_authenticator;
4103 r2.out.new_owf_password = r->out.new_owf_password;
4104 r2.out.old_owf_password = r->out.old_owf_password;
4105 r2.out.trust_info = &_ti;
4107 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
4109 r->out.return_authenticator = r2.out.return_authenticator;
4110 r->out.new_owf_password = r2.out.new_owf_password;
4111 r->out.old_owf_password = r2.out.old_owf_password;
4117 netr_DsRGetForestTrustInformation
4119 struct dcesrv_netr_DsRGetForestTrustInformation_state {
4120 struct dcesrv_call_state *dce_call;
4121 TALLOC_CTX *mem_ctx;
4122 struct netr_DsRGetForestTrustInformation *r;
4125 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
4127 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
4128 TALLOC_CTX *mem_ctx,
4129 struct netr_DsRGetForestTrustInformation *r)
4131 struct auth_session_info *session_info =
4132 dcesrv_call_session_info(dce_call);
4133 struct imessaging_context *imsg_ctx =
4134 dcesrv_imessaging_context(dce_call->conn);
4135 enum security_user_level security_level;
4136 struct ldb_context *sam_ctx = NULL;
4137 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
4138 struct dcerpc_binding_handle *irpc_handle = NULL;
4139 struct tevent_req *subreq = NULL;
4140 struct ldb_dn *domain_dn = NULL;
4141 struct ldb_dn *forest_dn = NULL;
4145 security_level = security_session_user_level(session_info, NULL);
4146 if (security_level < SECURITY_USER) {
4147 return WERR_ACCESS_DENIED;
4150 if (r->in.flags & 0xFFFFFFFE) {
4151 return WERR_INVALID_FLAGS;
4154 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4155 if (sam_ctx == NULL) {
4156 return WERR_GEN_FAILURE;
4159 domain_dn = ldb_get_default_basedn(sam_ctx);
4160 if (domain_dn == NULL) {
4161 return WERR_GEN_FAILURE;
4164 forest_dn = ldb_get_root_basedn(sam_ctx);
4165 if (forest_dn == NULL) {
4166 return WERR_GEN_FAILURE;
4169 cmp = ldb_dn_compare(domain_dn, forest_dn);
4171 return WERR_NERR_ACFNOTLOADED;
4174 forest_level = dsdb_forest_functional_level(sam_ctx);
4175 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4176 return WERR_INVALID_FUNCTION;
4179 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
4180 if (!samdb_is_pdc(sam_ctx)) {
4181 return WERR_NERR_NOTPRIMARY;
4184 if (r->in.trusted_domain_name == NULL) {
4185 return WERR_INVALID_FLAGS;
4189 if (r->in.trusted_domain_name == NULL) {
4193 * information about our own domain
4195 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4196 r->out.forest_trust_info);
4197 if (!NT_STATUS_IS_OK(status)) {
4198 return ntstatus_to_werror(status);
4205 * Forward the request to winbindd
4208 state = talloc_zero(mem_ctx,
4209 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4210 if (state == NULL) {
4211 return WERR_NOT_ENOUGH_MEMORY;
4213 state->dce_call = dce_call;
4214 state->mem_ctx = mem_ctx;
4217 irpc_handle = irpc_binding_handle_by_name(state,
4220 &ndr_table_winbind);
4221 if (irpc_handle == NULL) {
4222 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
4223 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4224 return WERR_SERVICE_NOT_FOUND;
4228 * 60 seconds timeout should be enough
4230 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
4232 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
4233 state->dce_call->event_ctx,
4235 r->in.trusted_domain_name,
4237 r->out.forest_trust_info);
4238 if (subreq == NULL) {
4239 return WERR_NOT_ENOUGH_MEMORY;
4241 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4242 tevent_req_set_callback(subreq,
4243 dcesrv_netr_DsRGetForestTrustInformation_done,
4249 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
4251 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
4252 tevent_req_callback_data(subreq,
4253 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4256 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
4258 &state->r->out.result);
4259 TALLOC_FREE(subreq);
4260 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
4261 state->r->out.result = WERR_TIMEOUT;
4262 } else if (!NT_STATUS_IS_OK(status)) {
4263 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4264 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
4265 nt_errstr(status)));
4268 status = dcesrv_reply(state->dce_call);
4269 if (!NT_STATUS_IS_OK(status)) {
4270 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4275 netr_GetForestTrustInformation
4277 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
4278 TALLOC_CTX *mem_ctx,
4279 struct netr_GetForestTrustInformation *r)
4281 struct netlogon_creds_CredentialState *creds = NULL;
4282 struct ldb_context *sam_ctx = NULL;
4283 struct ldb_dn *domain_dn = NULL;
4284 struct ldb_dn *forest_dn = NULL;
4289 status = dcesrv_netr_creds_server_step_check(dce_call,
4291 r->in.computer_name,
4293 r->out.return_authenticator,
4295 if (!NT_STATUS_IS_OK(status)) {
4299 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
4300 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
4301 return NT_STATUS_NOT_IMPLEMENTED;
4304 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4305 if (sam_ctx == NULL) {
4306 return NT_STATUS_INTERNAL_ERROR;
4309 /* TODO: check r->in.server_name is our name */
4311 domain_dn = ldb_get_default_basedn(sam_ctx);
4312 if (domain_dn == NULL) {
4313 return NT_STATUS_INTERNAL_ERROR;
4316 forest_dn = ldb_get_root_basedn(sam_ctx);
4317 if (forest_dn == NULL) {
4318 return NT_STATUS_INTERNAL_ERROR;
4321 cmp = ldb_dn_compare(domain_dn, forest_dn);
4323 return NT_STATUS_INVALID_DOMAIN_STATE;
4326 forest_level = dsdb_forest_functional_level(sam_ctx);
4327 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4328 return NT_STATUS_INVALID_DOMAIN_STATE;
4331 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4332 r->out.forest_trust_info);
4333 if (!NT_STATUS_IS_OK(status)) {
4337 return NT_STATUS_OK;
4342 netr_ServerGetTrustInfo
4344 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4345 struct netr_ServerGetTrustInfo *r)
4347 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4348 struct netlogon_creds_CredentialState *creds = NULL;
4349 struct ldb_context *sam_ctx = NULL;
4350 const char * const attrs[] = {
4353 "userAccountControl",
4356 struct ldb_message **res = NULL;
4357 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4360 const char *asid = NULL;
4362 const char *aname = NULL;
4363 struct ldb_message *tdo_msg = NULL;
4364 const char * const tdo_attrs[] = {
4365 "trustAuthIncoming",
4369 struct netr_TrustInfo *trust_info = NULL;
4371 ZERO_STRUCTP(r->out.new_owf_password);
4372 ZERO_STRUCTP(r->out.old_owf_password);
4374 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4376 r->in.computer_name,
4378 r->out.return_authenticator,
4380 if (!NT_STATUS_IS_OK(nt_status)) {
4384 /* TODO: check r->in.server_name is our name */
4386 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4387 return NT_STATUS_INVALID_PARAMETER;
4390 if (r->in.secure_channel_type != creds->secure_channel_type) {
4391 return NT_STATUS_INVALID_PARAMETER;
4394 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4395 return NT_STATUS_INVALID_PARAMETER;
4398 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
4399 if (sam_ctx == NULL) {
4400 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4403 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4405 return NT_STATUS_NO_MEMORY;
4408 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4409 "(&(objectClass=user)(objectSid=%s))",
4412 return NT_STATUS_ACCOUNT_DISABLED;
4415 switch (creds->secure_channel_type) {
4416 case SEC_CHAN_DNS_DOMAIN:
4417 case SEC_CHAN_DOMAIN:
4418 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4420 if (uac & UF_ACCOUNTDISABLE) {
4421 return NT_STATUS_ACCOUNT_DISABLED;
4424 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4425 return NT_STATUS_ACCOUNT_DISABLED;
4428 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4429 if (aname == NULL) {
4430 return NT_STATUS_ACCOUNT_DISABLED;
4433 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4434 SEC_CHAN_DOMAIN, aname,
4435 tdo_attrs, mem_ctx, &tdo_msg);
4436 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4437 return NT_STATUS_ACCOUNT_DISABLED;
4439 if (!NT_STATUS_IS_OK(nt_status)) {
4443 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4446 if (!NT_STATUS_IS_OK(nt_status)) {
4450 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4451 if (trust_info == NULL) {
4452 return NT_STATUS_NO_MEMORY;
4455 trust_info->count = 1;
4456 trust_info->data = talloc_array(trust_info, uint32_t,
4458 if (trust_info->data == NULL) {
4459 return NT_STATUS_NO_MEMORY;
4462 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4468 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4471 if (!NT_STATUS_IS_OK(nt_status)) {
4475 prevNtHash = talloc(mem_ctx, struct samr_Password);
4476 if (prevNtHash == NULL) {
4477 return NT_STATUS_NO_MEMORY;
4480 E_md4hash("", prevNtHash->hash);
4484 if (curNtHash != NULL) {
4485 *r->out.new_owf_password = *curNtHash;
4486 nt_status = netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4487 if (!NT_STATUS_IS_OK(nt_status)) {
4491 if (prevNtHash != NULL) {
4492 *r->out.old_owf_password = *prevNtHash;
4493 nt_status = netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4494 if (!NT_STATUS_IS_OK(nt_status)) {
4499 if (trust_info != NULL) {
4500 *r->out.trust_info = trust_info;
4503 return NT_STATUS_OK;
4509 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4510 struct netr_Unused47 *r)
4512 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4516 struct netr_dnsupdate_RODC_state {
4517 struct dcesrv_call_state *dce_call;
4518 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4519 struct dnsupdate_RODC *r2;
4523 called when the forwarded RODC dns update request is finished
4525 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4527 struct netr_dnsupdate_RODC_state *st =
4528 tevent_req_callback_data(subreq,
4529 struct netr_dnsupdate_RODC_state);
4532 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4533 TALLOC_FREE(subreq);
4534 if (!NT_STATUS_IS_OK(status)) {
4535 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4536 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4539 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4541 status = dcesrv_reply(st->dce_call);
4542 if (!NT_STATUS_IS_OK(status)) {
4543 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4548 netr_DsrUpdateReadOnlyServerDnsRecords
4550 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4551 TALLOC_CTX *mem_ctx,
4552 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4554 struct netlogon_creds_CredentialState *creds;
4556 struct dcerpc_binding_handle *binding_handle;
4557 struct netr_dnsupdate_RODC_state *st;
4558 struct tevent_req *subreq;
4559 struct imessaging_context *imsg_ctx =
4560 dcesrv_imessaging_context(dce_call->conn);
4562 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4564 r->in.computer_name,
4566 r->out.return_authenticator,
4568 NT_STATUS_NOT_OK_RETURN(nt_status);
4570 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4571 return NT_STATUS_ACCESS_DENIED;
4574 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4575 NT_STATUS_HAVE_NO_MEMORY(st);
4577 st->dce_call = dce_call;
4579 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4580 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4582 st->r2->in.dom_sid = creds->sid;
4583 st->r2->in.site_name = r->in.site_name;
4584 st->r2->in.dns_ttl = r->in.dns_ttl;
4585 st->r2->in.dns_names = r->in.dns_names;
4586 st->r2->out.dns_names = r->out.dns_names;
4588 binding_handle = irpc_binding_handle_by_name(st,
4592 if (binding_handle == NULL) {
4593 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4594 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4595 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4598 /* forward the call */
4599 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4600 binding_handle, st->r2);
4601 NT_STATUS_HAVE_NO_MEMORY(subreq);
4603 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4605 /* setup the callback */
4606 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4608 return NT_STATUS_OK;
4612 /* include the generated boilerplate */
4613 #include "librpc/gen_ndr/ndr_netlogon_s.c"