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),
843 NULL /* client_audit_info */,
844 NULL /* server_audit_info */);
848 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
849 struct netr_ServerAuthenticate *r)
851 struct netr_ServerAuthenticate3 a;
854 * negotiate_flags is used as an [in] parameter
855 * so it need to be initialised.
857 * (I think ... = 0; seems wrong here --metze)
859 uint32_t negotiate_flags_in = 0;
860 uint32_t negotiate_flags_out = 0;
862 a.in.server_name = r->in.server_name;
863 a.in.account_name = r->in.account_name;
864 a.in.secure_channel_type = r->in.secure_channel_type;
865 a.in.computer_name = r->in.computer_name;
866 a.in.credentials = r->in.credentials;
867 a.in.negotiate_flags = &negotiate_flags_in;
869 a.out.return_credentials = r->out.return_credentials;
871 a.out.negotiate_flags = &negotiate_flags_out;
873 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
876 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
877 struct netr_ServerAuthenticate2 *r)
879 struct netr_ServerAuthenticate3 r3;
882 r3.in.server_name = r->in.server_name;
883 r3.in.account_name = r->in.account_name;
884 r3.in.secure_channel_type = r->in.secure_channel_type;
885 r3.in.computer_name = r->in.computer_name;
886 r3.in.credentials = r->in.credentials;
887 r3.out.return_credentials = r->out.return_credentials;
888 r3.in.negotiate_flags = r->in.negotiate_flags;
889 r3.out.negotiate_flags = r->out.negotiate_flags;
892 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
896 Change the machine account password for the currently connected
897 client. Supplies only the NT#.
900 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
901 struct netr_ServerPasswordSet *r)
903 struct netlogon_creds_CredentialState *creds;
904 struct ldb_context *sam_ctx;
907 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
910 r->in.credential, r->out.return_authenticator,
912 NT_STATUS_NOT_OK_RETURN(nt_status);
914 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
915 if (sam_ctx == NULL) {
916 return NT_STATUS_INVALID_SYSTEM_SERVICE;
919 nt_status = netlogon_creds_des_decrypt(creds, r->in.new_password);
920 NT_STATUS_NOT_OK_RETURN(nt_status);
922 /* Using the sid for the account as the key, set the password */
923 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
925 NULL, /* Don't have version */
926 NULL, /* Don't have plaintext */
928 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
934 Change the machine account password for the currently connected
935 client. Supplies new plaintext.
937 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
938 struct netr_ServerPasswordSet2 *r)
940 struct netlogon_creds_CredentialState *creds;
941 struct ldb_context *sam_ctx;
942 struct NL_PASSWORD_VERSION version = {};
943 const uint32_t *new_version = NULL;
945 DATA_BLOB new_password = data_blob_null;
946 size_t confounder_len;
947 DATA_BLOB dec_blob = data_blob_null;
948 DATA_BLOB enc_blob = data_blob_null;
949 struct samr_CryptPassword password_buf;
951 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
954 r->in.credential, r->out.return_authenticator,
956 NT_STATUS_NOT_OK_RETURN(nt_status);
958 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
959 if (sam_ctx == NULL) {
960 return NT_STATUS_INVALID_SYSTEM_SERVICE;
963 memcpy(password_buf.data, r->in.new_password->data, 512);
964 SIVAL(password_buf.data, 512, r->in.new_password->length);
966 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
967 nt_status = netlogon_creds_aes_decrypt(creds,
971 nt_status = netlogon_creds_arcfour_crypt(creds,
976 if (!NT_STATUS_IS_OK(nt_status)) {
980 switch (creds->secure_channel_type) {
981 case SEC_CHAN_DOMAIN:
982 case SEC_CHAN_DNS_DOMAIN: {
983 uint32_t len = IVAL(password_buf.data, 512);
985 uint32_t ofs = 500 - len;
988 p = password_buf.data + ofs;
990 version.ReservedField = IVAL(p, 0);
991 version.PasswordVersionNumber = IVAL(p, 4);
992 version.PasswordVersionPresent = IVAL(p, 8);
994 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
995 new_version = &version.PasswordVersionNumber;
1003 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
1004 DEBUG(3,("samr: failed to decode password buffer\n"));
1005 return NT_STATUS_WRONG_PASSWORD;
1009 * Make sure the length field was encrypted,
1010 * otherwise we are under attack.
1012 if (new_password.length == r->in.new_password->length) {
1013 DBG_WARNING("Length[%zu] field not encrypted\n",
1014 new_password.length);
1015 return NT_STATUS_WRONG_PASSWORD;
1019 * We don't allow empty passwords for machine accounts.
1021 if (new_password.length < 2) {
1022 DBG_WARNING("Empty password Length[%zu]\n",
1023 new_password.length);
1024 return NT_STATUS_WRONG_PASSWORD;
1028 * Make sure the confounder part of CryptPassword
1029 * buffer was encrypted, otherwise we are under attack.
1031 confounder_len = 512 - new_password.length;
1032 enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
1033 dec_blob = data_blob_const(password_buf.data, confounder_len);
1034 if (confounder_len > 0 && data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1035 DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
1037 return NT_STATUS_WRONG_PASSWORD;
1041 * Check that the password part was actually encrypted,
1042 * otherwise we are under attack.
1044 enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
1045 new_password.length);
1046 dec_blob = data_blob_const(password_buf.data + confounder_len,
1047 new_password.length);
1048 if (data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1049 DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
1050 new_password.length);
1051 return NT_STATUS_WRONG_PASSWORD;
1055 * don't allow zero buffers
1057 if (all_zero(new_password.data, new_password.length)) {
1058 DBG_WARNING("Password zero buffer Length[%zu]\n",
1059 new_password.length);
1060 return NT_STATUS_WRONG_PASSWORD;
1063 /* Using the sid for the account as the key, set the password */
1064 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1067 &new_password, /* we have plaintext */
1069 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1078 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1079 struct netr_LogonUasLogon *r)
1081 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1088 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1089 struct netr_LogonUasLogoff *r)
1091 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1095 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
1096 const struct netr_LogonSamLogonEx *r)
1098 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1100 switch (r->in.logon_level) {
1101 case NetlogonInteractiveInformation:
1102 case NetlogonServiceInformation:
1103 case NetlogonInteractiveTransitiveInformation:
1104 case NetlogonServiceTransitiveInformation:
1105 if (r->in.logon->password == NULL) {
1106 return NT_STATUS_INVALID_PARAMETER;
1109 switch (r->in.validation_level) {
1110 case NetlogonValidationSamInfo: /* 2 */
1111 case NetlogonValidationSamInfo2: /* 3 */
1112 case NetlogonValidationSamInfo4: /* 6 */
1115 return NT_STATUS_INVALID_INFO_CLASS;
1119 case NetlogonNetworkInformation:
1120 case NetlogonNetworkTransitiveInformation:
1121 if (r->in.logon->network == NULL) {
1122 return NT_STATUS_INVALID_PARAMETER;
1125 switch (r->in.validation_level) {
1126 case NetlogonValidationSamInfo: /* 2 */
1127 case NetlogonValidationSamInfo2: /* 3 */
1128 case NetlogonValidationSamInfo4: /* 6 */
1131 return NT_STATUS_INVALID_INFO_CLASS;
1136 case NetlogonGenericInformation:
1137 if (r->in.logon->generic == NULL) {
1138 return NT_STATUS_INVALID_PARAMETER;
1141 switch (r->in.validation_level) {
1142 /* TODO: case NetlogonValidationGenericInfo: 4 */
1143 case NetlogonValidationGenericInfo2: /* 5 */
1146 return NT_STATUS_INVALID_INFO_CLASS;
1151 return NT_STATUS_INVALID_PARAMETER;
1154 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
1156 switch (r->in.validation_level) {
1157 case NetlogonValidationSamInfo4: /* 6 */
1158 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1159 return NT_STATUS_INVALID_PARAMETER;
1167 return NT_STATUS_OK;
1170 struct dcesrv_netr_LogonSamLogon_base_state {
1171 struct dcesrv_call_state *dce_call;
1173 TALLOC_CTX *mem_ctx;
1175 struct netlogon_creds_CredentialState *creds;
1177 struct netr_LogonSamLogonEx r;
1179 uint32_t _ignored_flags;
1182 struct netr_LogonSamLogon *lsl;
1183 struct netr_LogonSamLogonWithFlags *lslwf;
1184 struct netr_LogonSamLogonEx *lslex;
1187 struct kdc_check_generic_kerberos kr;
1190 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
1191 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
1192 static void dcesrv_netr_LogonSamLogon_base_reply(
1193 struct dcesrv_netr_LogonSamLogon_base_state *state);
1196 netr_LogonSamLogon_base
1198 This version of the function allows other wrappers to say 'do not check the credentials'
1200 We can't do the traditional 'wrapping' format completely, as this
1201 function must only run under schannel
1203 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
1205 struct dcesrv_call_state *dce_call = state->dce_call;
1206 struct imessaging_context *imsg_ctx =
1207 dcesrv_imessaging_context(dce_call->conn);
1208 TALLOC_CTX *mem_ctx = state->mem_ctx;
1209 struct netr_LogonSamLogonEx *r = &state->r;
1210 struct netlogon_creds_CredentialState *creds = state->creds;
1211 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1212 const char *workgroup = lpcfg_workgroup(lp_ctx);
1213 struct auth4_context *auth_context = NULL;
1214 struct auth_usersupplied_info *user_info = NULL;
1216 struct tevent_req *subreq = NULL;
1217 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1218 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1220 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1222 switch (dce_call->pkt.u.request.opnum) {
1223 case NDR_NETR_LOGONSAMLOGON:
1224 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
1226 * These already called dcesrv_netr_check_schannel()
1227 * via dcesrv_netr_creds_server_step_check()
1230 case NDR_NETR_LOGONSAMLOGONEX:
1232 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1233 return NT_STATUS_ACCESS_DENIED;
1236 nt_status = dcesrv_netr_check_schannel(dce_call,
1240 dce_call->pkt.u.request.opnum);
1241 if (!NT_STATUS_IS_OK(nt_status)) {
1247 *r->out.authoritative = 1;
1249 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
1251 * Currently we're always the forest root ourself.
1253 return NT_STATUS_NO_SUCH_USER;
1256 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
1258 * Currently we don't support trusts correctly yet.
1260 return NT_STATUS_NO_SUCH_USER;
1263 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1264 NT_STATUS_HAVE_NO_MEMORY(user_info);
1266 user_info->service_description = "SamLogon";
1268 nt_status = netlogon_creds_decrypt_samlogon_logon(creds,
1271 NT_STATUS_NOT_OK_RETURN(nt_status);
1273 switch (r->in.logon_level) {
1274 case NetlogonInteractiveInformation:
1275 case NetlogonServiceInformation:
1276 case NetlogonInteractiveTransitiveInformation:
1277 case NetlogonServiceTransitiveInformation:
1278 case NetlogonNetworkInformation:
1279 case NetlogonNetworkTransitiveInformation:
1281 nt_status = auth_context_create_for_netlogon(mem_ctx,
1282 dce_call->event_ctx,
1284 dce_call->conn->dce_ctx->lp_ctx,
1286 NT_STATUS_NOT_OK_RETURN(nt_status);
1288 user_info->remote_host = dce_call->conn->remote_address;
1289 user_info->local_host = dce_call->conn->local_address;
1291 user_info->netlogon_trust_account.secure_channel_type
1292 = creds->secure_channel_type;
1293 user_info->netlogon_trust_account.negotiate_flags
1294 = creds->negotiate_flags;
1297 * These two can be unrelated when the account is
1298 * actually that of a trusted domain, so we want to
1299 * know which DC in that trusted domain contacted
1302 user_info->netlogon_trust_account.computer_name
1303 = creds->computer_name;
1304 user_info->netlogon_trust_account.account_name
1305 = creds->account_name;
1306 user_info->netlogon_trust_account.sid
1311 /* We do not need to set up the user_info in this case */
1315 switch (r->in.logon_level) {
1316 case NetlogonInteractiveInformation:
1317 case NetlogonServiceInformation:
1318 case NetlogonInteractiveTransitiveInformation:
1319 case NetlogonServiceTransitiveInformation:
1320 user_info->auth_description = "interactive";
1322 user_info->logon_parameters
1323 = r->in.logon->password->identity_info.parameter_control;
1324 user_info->client.account_name
1325 = r->in.logon->password->identity_info.account_name.string;
1326 user_info->client.domain_name
1327 = r->in.logon->password->identity_info.domain_name.string;
1328 user_info->workstation_name
1329 = r->in.logon->password->identity_info.workstation.string;
1330 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1331 user_info->password_state = AUTH_PASSWORD_HASH;
1333 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1334 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1335 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1337 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1338 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1339 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1342 = r->in.logon->password->identity_info.logon_id;
1345 case NetlogonNetworkInformation:
1346 case NetlogonNetworkTransitiveInformation:
1347 user_info->auth_description = "network";
1349 nt_status = auth_context_set_challenge(
1351 r->in.logon->network->challenge,
1352 "netr_LogonSamLogonWithFlags");
1353 NT_STATUS_NOT_OK_RETURN(nt_status);
1355 user_info->logon_parameters
1356 = r->in.logon->network->identity_info.parameter_control;
1357 user_info->client.account_name
1358 = r->in.logon->network->identity_info.account_name.string;
1359 user_info->client.domain_name
1360 = r->in.logon->network->identity_info.domain_name.string;
1361 user_info->workstation_name
1362 = r->in.logon->network->identity_info.workstation.string;
1364 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1365 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1366 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1369 = r->in.logon->network->identity_info.logon_id;
1371 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1372 user_info->client.account_name,
1373 user_info->client.domain_name,
1374 user_info->password.response.nt,
1376 NT_STATUS_NOT_OK_RETURN(nt_status);
1381 case NetlogonGenericInformation:
1383 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1385 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1388 /* Using DES to verify kerberos tickets makes no sense */
1389 return NT_STATUS_INVALID_PARAMETER;
1392 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1393 struct dcerpc_binding_handle *irpc_handle;
1394 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1395 NT_STATUS_HAVE_NO_MEMORY(generic);
1397 r->out.validation->generic = generic;
1400 = r->in.logon->generic->identity_info.logon_id;
1402 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1406 if (irpc_handle == NULL) {
1407 return NT_STATUS_NO_LOGON_SERVERS;
1410 state->kr.in.generic_request =
1411 data_blob_const(r->in.logon->generic->data,
1412 r->in.logon->generic->length);
1415 * 60 seconds should be enough
1417 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1418 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1419 state->dce_call->event_ctx,
1420 irpc_handle, &state->kr);
1421 if (subreq == NULL) {
1422 return NT_STATUS_NO_MEMORY;
1424 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1425 tevent_req_set_callback(subreq,
1426 dcesrv_netr_LogonSamLogon_base_krb5_done,
1428 return NT_STATUS_OK;
1431 /* Until we get an implemetnation of these other packages */
1432 return NT_STATUS_INVALID_PARAMETER;
1435 return NT_STATUS_INVALID_PARAMETER;
1438 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1439 auth_context, user_info);
1440 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1441 tevent_req_set_callback(subreq,
1442 dcesrv_netr_LogonSamLogon_base_auth_done,
1444 return NT_STATUS_OK;
1447 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1449 struct dcesrv_netr_LogonSamLogon_base_state *state =
1450 tevent_req_callback_data(subreq,
1451 struct dcesrv_netr_LogonSamLogon_base_state);
1452 TALLOC_CTX *mem_ctx = state->mem_ctx;
1453 struct netr_LogonSamLogonEx *r = &state->r;
1454 struct auth_user_info_dc *user_info_dc = NULL;
1455 struct netr_SamInfo2 *sam2 = NULL;
1456 struct netr_SamInfo3 *sam3 = NULL;
1457 struct netr_SamInfo6 *sam6 = NULL;
1460 nt_status = auth_check_password_recv(subreq, mem_ctx,
1462 r->out.authoritative);
1463 TALLOC_FREE(subreq);
1464 if (!NT_STATUS_IS_OK(nt_status)) {
1465 r->out.result = nt_status;
1466 dcesrv_netr_LogonSamLogon_base_reply(state);
1470 switch (r->in.validation_level) {
1472 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1474 AUTH_INCLUDE_RESOURCE_GROUPS,
1476 if (!NT_STATUS_IS_OK(nt_status)) {
1477 r->out.result = nt_status;
1478 dcesrv_netr_LogonSamLogon_base_reply(state);
1482 r->out.validation->sam2 = sam2;
1486 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1488 AUTH_INCLUDE_RESOURCE_GROUPS,
1490 if (!NT_STATUS_IS_OK(nt_status)) {
1491 r->out.result = nt_status;
1492 dcesrv_netr_LogonSamLogon_base_reply(state);
1496 r->out.validation->sam3 = sam3;
1500 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1502 AUTH_INCLUDE_RESOURCE_GROUPS,
1504 if (!NT_STATUS_IS_OK(nt_status)) {
1505 r->out.result = nt_status;
1506 dcesrv_netr_LogonSamLogon_base_reply(state);
1510 r->out.validation->sam6 = sam6;
1514 if (!NT_STATUS_IS_OK(nt_status)) {
1515 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1516 dcesrv_netr_LogonSamLogon_base_reply(state);
1521 /* TODO: Describe and deal with these flags */
1524 r->out.result = NT_STATUS_OK;
1526 dcesrv_netr_LogonSamLogon_base_reply(state);
1529 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1531 struct dcesrv_netr_LogonSamLogon_base_state *state =
1532 tevent_req_callback_data(subreq,
1533 struct dcesrv_netr_LogonSamLogon_base_state);
1534 TALLOC_CTX *mem_ctx = state->mem_ctx;
1535 struct netr_LogonSamLogonEx *r = &state->r;
1536 struct netr_GenericInfo2 *generic = NULL;
1539 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1540 TALLOC_FREE(subreq);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 r->out.result = status;
1543 dcesrv_netr_LogonSamLogon_base_reply(state);
1547 generic = r->out.validation->generic;
1548 generic->length = state->kr.out.generic_reply.length;
1549 generic->data = state->kr.out.generic_reply.data;
1551 /* TODO: Describe and deal with these flags */
1554 r->out.result = NT_STATUS_OK;
1556 dcesrv_netr_LogonSamLogon_base_reply(state);
1559 static void dcesrv_netr_LogonSamLogon_base_reply(
1560 struct dcesrv_netr_LogonSamLogon_base_state *state)
1562 struct netr_LogonSamLogonEx *r = &state->r;
1565 if (NT_STATUS_IS_OK(r->out.result)) {
1566 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
1567 r->in.validation_level,
1569 if (!NT_STATUS_IS_OK(status)) {
1570 DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
1576 if (state->_r.lslex != NULL) {
1577 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1578 _r->out.result = r->out.result;
1579 } else if (state->_r.lslwf != NULL) {
1580 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1581 _r->out.result = r->out.result;
1582 } else if (state->_r.lsl != NULL) {
1583 struct netr_LogonSamLogon *_r = state->_r.lsl;
1584 _r->out.result = r->out.result;
1587 status = dcesrv_reply(state->dce_call);
1588 if (!NT_STATUS_IS_OK(status)) {
1589 DBG_ERR("dcesrv_reply() failed - %s\n",
1594 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1595 struct netr_LogonSamLogonEx *r)
1597 struct dcesrv_netr_LogonSamLogon_base_state *state;
1600 *r->out.authoritative = 1;
1602 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1603 if (state == NULL) {
1604 return NT_STATUS_NO_MEMORY;
1607 state->dce_call = dce_call;
1608 state->mem_ctx = mem_ctx;
1610 state->r.in.server_name = r->in.server_name;
1611 state->r.in.computer_name = r->in.computer_name;
1612 state->r.in.logon_level = r->in.logon_level;
1613 state->r.in.logon = r->in.logon;
1614 state->r.in.validation_level = r->in.validation_level;
1615 state->r.in.flags = r->in.flags;
1616 state->r.out.validation = r->out.validation;
1617 state->r.out.authoritative = r->out.authoritative;
1618 state->r.out.flags = r->out.flags;
1620 state->_r.lslex = r;
1622 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1623 if (!NT_STATUS_IS_OK(nt_status)) {
1627 nt_status = schannel_get_creds_state(mem_ctx,
1628 dce_call->conn->dce_ctx->lp_ctx,
1629 r->in.computer_name, &state->creds);
1630 if (!NT_STATUS_IS_OK(nt_status)) {
1634 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1636 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1644 netr_LogonSamLogonWithFlags
1647 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1648 struct netr_LogonSamLogonWithFlags *r)
1650 struct dcesrv_netr_LogonSamLogon_base_state *state;
1653 *r->out.authoritative = 1;
1655 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1656 if (state == NULL) {
1657 return NT_STATUS_NO_MEMORY;
1660 state->dce_call = dce_call;
1661 state->mem_ctx = mem_ctx;
1663 state->r.in.server_name = r->in.server_name;
1664 state->r.in.computer_name = r->in.computer_name;
1665 state->r.in.logon_level = r->in.logon_level;
1666 state->r.in.logon = r->in.logon;
1667 state->r.in.validation_level = r->in.validation_level;
1668 state->r.in.flags = r->in.flags;
1669 state->r.out.validation = r->out.validation;
1670 state->r.out.authoritative = r->out.authoritative;
1671 state->r.out.flags = r->out.flags;
1673 state->_r.lslwf = r;
1675 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1676 if (!NT_STATUS_IS_OK(nt_status)) {
1680 r->out.return_authenticator = talloc_zero(mem_ctx,
1681 struct netr_Authenticator);
1682 if (r->out.return_authenticator == NULL) {
1683 return NT_STATUS_NO_MEMORY;
1686 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1688 r->in.computer_name,
1690 r->out.return_authenticator,
1692 if (!NT_STATUS_IS_OK(nt_status)) {
1696 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1698 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1708 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1709 struct netr_LogonSamLogon *r)
1711 struct dcesrv_netr_LogonSamLogon_base_state *state;
1714 *r->out.authoritative = 1;
1716 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1717 if (state == NULL) {
1718 return NT_STATUS_NO_MEMORY;
1721 state->dce_call = dce_call;
1722 state->mem_ctx = mem_ctx;
1724 state->r.in.server_name = r->in.server_name;
1725 state->r.in.computer_name = r->in.computer_name;
1726 state->r.in.logon_level = r->in.logon_level;
1727 state->r.in.logon = r->in.logon;
1728 state->r.in.validation_level = r->in.validation_level;
1729 state->r.in.flags = &state->_ignored_flags;
1730 state->r.out.validation = r->out.validation;
1731 state->r.out.authoritative = r->out.authoritative;
1732 state->r.out.flags = &state->_ignored_flags;
1736 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1737 if (!NT_STATUS_IS_OK(nt_status)) {
1741 r->out.return_authenticator = talloc_zero(mem_ctx,
1742 struct netr_Authenticator);
1743 if (r->out.return_authenticator == NULL) {
1744 return NT_STATUS_NO_MEMORY;
1747 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1749 r->in.computer_name,
1751 r->out.return_authenticator,
1753 if (!NT_STATUS_IS_OK(nt_status)) {
1757 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1759 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1770 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1771 struct netr_LogonSamLogoff *r)
1773 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1781 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1782 struct netr_DatabaseDeltas *r)
1784 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1791 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1792 struct netr_DatabaseSync2 *r)
1794 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1795 return NT_STATUS_NOT_IMPLEMENTED;
1802 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1803 struct netr_DatabaseSync *r)
1805 struct netr_DatabaseSync2 r2;
1810 r2.in.logon_server = r->in.logon_server;
1811 r2.in.computername = r->in.computername;
1812 r2.in.credential = r->in.credential;
1813 r2.in.database_id = r->in.database_id;
1814 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1815 r2.in.sync_context = r->in.sync_context;
1816 r2.out.sync_context = r->out.sync_context;
1817 r2.out.delta_enum_array = r->out.delta_enum_array;
1818 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1820 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1829 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1830 struct netr_AccountDeltas *r)
1832 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1833 return NT_STATUS_NOT_IMPLEMENTED;
1840 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1841 struct netr_AccountSync *r)
1843 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1844 return NT_STATUS_NOT_IMPLEMENTED;
1851 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1852 struct netr_GetDcName *r)
1854 const char * const attrs[] = { NULL };
1855 struct ldb_context *sam_ctx;
1856 struct ldb_message **res;
1857 struct ldb_dn *domain_dn;
1862 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1863 * that the domainname needs to be a valid netbios domain
1864 * name, if it is not NULL.
1866 if (r->in.domainname) {
1867 const char *dot = strchr(r->in.domainname, '.');
1868 size_t len = strlen(r->in.domainname);
1870 if (dot || len > 15) {
1871 return WERR_NERR_DCNOTFOUND;
1875 * TODO: Should we also varify that only valid
1876 * netbios name characters are used?
1880 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
1881 if (sam_ctx == NULL) {
1882 return WERR_DS_UNAVAILABLE;
1885 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1887 if (domain_dn == NULL) {
1888 return WERR_NO_SUCH_DOMAIN;
1891 ret = gendb_search_dn(sam_ctx, mem_ctx,
1892 domain_dn, &res, attrs);
1894 return WERR_NO_SUCH_DOMAIN;
1897 /* TODO: - return real IP address
1898 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1900 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1901 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1902 W_ERROR_HAVE_NO_MEMORY(dcname);
1904 *r->out.dcname = dcname;
1908 struct dcesrv_netr_LogonControl_base_state {
1909 struct dcesrv_call_state *dce_call;
1911 TALLOC_CTX *mem_ctx;
1913 struct netr_LogonControl2Ex r;
1916 struct netr_LogonControl *l;
1917 struct netr_LogonControl2 *l2;
1918 struct netr_LogonControl2Ex *l2ex;
1922 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1924 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1926 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1927 struct auth_session_info *session_info =
1928 dcesrv_call_session_info(state->dce_call);
1929 struct imessaging_context *imsg_ctx =
1930 dcesrv_imessaging_context(state->dce_call->conn);
1931 enum security_user_level security_level;
1932 struct dcerpc_binding_handle *irpc_handle;
1933 struct tevent_req *subreq;
1936 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1938 if (state->_r.l != NULL) {
1942 if (state->r.in.level == 0x00000002) {
1943 return WERR_NOT_SUPPORTED;
1944 } else if (state->r.in.level != 0x00000001) {
1945 return WERR_INVALID_LEVEL;
1948 switch (state->r.in.function_code) {
1949 case NETLOGON_CONTROL_QUERY:
1950 case NETLOGON_CONTROL_REPLICATE:
1951 case NETLOGON_CONTROL_SYNCHRONIZE:
1952 case NETLOGON_CONTROL_PDC_REPLICATE:
1953 case NETLOGON_CONTROL_BREAKPOINT:
1954 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1955 case NETLOGON_CONTROL_TRUNCATE_LOG:
1958 return WERR_NOT_SUPPORTED;
1962 if (state->r.in.level < 0x00000001) {
1963 return WERR_INVALID_LEVEL;
1966 if (state->r.in.level > 0x00000004) {
1967 return WERR_INVALID_LEVEL;
1970 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1971 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1972 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1974 switch (state->r.in.level) {
1976 info1 = talloc_zero(state->mem_ctx,
1977 struct netr_NETLOGON_INFO_1);
1978 if (info1 == NULL) {
1979 return WERR_NOT_ENOUGH_MEMORY;
1981 state->r.out.query->info1 = info1;
1985 info3 = talloc_zero(state->mem_ctx,
1986 struct netr_NETLOGON_INFO_3);
1987 if (info3 == NULL) {
1988 return WERR_NOT_ENOUGH_MEMORY;
1990 state->r.out.query->info3 = info3;
1994 return WERR_INVALID_PARAMETER;
1999 * Some validations are done before the access check
2000 * and some after the access check
2002 security_level = security_session_user_level(session_info, NULL);
2003 if (security_level < SECURITY_ADMINISTRATOR) {
2004 return WERR_ACCESS_DENIED;
2007 if (state->_r.l2 != NULL) {
2009 * netr_LogonControl2
2011 if (state->r.in.level == 0x00000004) {
2012 return WERR_INVALID_LEVEL;
2016 switch (state->r.in.level) {
2021 switch (state->r.in.function_code) {
2022 case NETLOGON_CONTROL_REDISCOVER:
2023 case NETLOGON_CONTROL_TC_QUERY:
2024 case NETLOGON_CONTROL_TC_VERIFY:
2027 return WERR_INVALID_PARAMETER;
2036 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
2037 return WERR_INVALID_PARAMETER;
2043 return WERR_INVALID_LEVEL;
2046 switch (state->r.in.function_code) {
2047 case NETLOGON_CONTROL_REDISCOVER:
2048 case NETLOGON_CONTROL_TC_QUERY:
2049 case NETLOGON_CONTROL_TC_VERIFY:
2050 if (state->r.in.level != 2) {
2051 return WERR_INVALID_PARAMETER;
2054 if (state->r.in.data == NULL) {
2055 return WERR_INVALID_PARAMETER;
2058 if (state->r.in.data->domain == NULL) {
2059 return WERR_INVALID_PARAMETER;
2064 case NETLOGON_CONTROL_CHANGE_PASSWORD:
2065 if (state->r.in.level != 1) {
2066 return WERR_INVALID_PARAMETER;
2069 if (state->r.in.data == NULL) {
2070 return WERR_INVALID_PARAMETER;
2073 if (state->r.in.data->domain == NULL) {
2074 return WERR_INVALID_PARAMETER;
2077 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
2078 state->r.in.data->domain);
2080 struct ldb_context *sam_ctx;
2082 sam_ctx = dcesrv_samdb_connect_as_system(state,
2084 if (sam_ctx == NULL) {
2085 return WERR_DS_UNAVAILABLE;
2089 * Secrets for trusted domains can only be triggered on
2092 ok = samdb_is_pdc(sam_ctx);
2093 TALLOC_FREE(sam_ctx);
2095 return WERR_INVALID_DOMAIN_ROLE;
2101 return WERR_NOT_SUPPORTED;
2104 irpc_handle = irpc_binding_handle_by_name(state,
2107 &ndr_table_winbind);
2108 if (irpc_handle == NULL) {
2109 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2110 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2111 return WERR_SERVICE_NOT_FOUND;
2115 * 60 seconds timeout should be enough
2117 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2119 subreq = dcerpc_winbind_LogonControl_send(state,
2120 state->dce_call->event_ctx,
2122 state->r.in.function_code,
2125 state->r.out.query);
2126 if (subreq == NULL) {
2127 return WERR_NOT_ENOUGH_MEMORY;
2129 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2130 tevent_req_set_callback(subreq,
2131 dcesrv_netr_LogonControl_base_done,
2137 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
2139 struct dcesrv_netr_LogonControl_base_state *state =
2140 tevent_req_callback_data(subreq,
2141 struct dcesrv_netr_LogonControl_base_state);
2144 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
2145 &state->r.out.result);
2146 TALLOC_FREE(subreq);
2147 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
2148 state->r.out.result = WERR_TIMEOUT;
2149 } else if (!NT_STATUS_IS_OK(status)) {
2150 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2151 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
2152 nt_errstr(status)));
2155 if (state->_r.l2ex != NULL) {
2156 struct netr_LogonControl2Ex *r = state->_r.l2ex;
2157 r->out.result = state->r.out.result;
2158 } else if (state->_r.l2 != NULL) {
2159 struct netr_LogonControl2 *r = state->_r.l2;
2160 r->out.result = state->r.out.result;
2161 } else if (state->_r.l != NULL) {
2162 struct netr_LogonControl *r = state->_r.l;
2163 r->out.result = state->r.out.result;
2166 status = dcesrv_reply(state->dce_call);
2167 if (!NT_STATUS_IS_OK(status)) {
2168 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2175 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2176 struct netr_LogonControl *r)
2178 struct dcesrv_netr_LogonControl_base_state *state;
2181 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2182 if (state == NULL) {
2183 return WERR_NOT_ENOUGH_MEMORY;
2186 state->dce_call = dce_call;
2187 state->mem_ctx = mem_ctx;
2189 state->r.in.logon_server = r->in.logon_server;
2190 state->r.in.function_code = r->in.function_code;
2191 state->r.in.level = r->in.level;
2192 state->r.in.data = NULL;
2193 state->r.out.query = r->out.query;
2197 werr = dcesrv_netr_LogonControl_base_call(state);
2199 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2209 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2210 struct netr_LogonControl2 *r)
2212 struct dcesrv_netr_LogonControl_base_state *state;
2215 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2216 if (state == NULL) {
2217 return WERR_NOT_ENOUGH_MEMORY;
2220 state->dce_call = dce_call;
2221 state->mem_ctx = mem_ctx;
2223 state->r.in.logon_server = r->in.logon_server;
2224 state->r.in.function_code = r->in.function_code;
2225 state->r.in.level = r->in.level;
2226 state->r.in.data = r->in.data;
2227 state->r.out.query = r->out.query;
2231 werr = dcesrv_netr_LogonControl_base_call(state);
2233 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2241 netr_LogonControl2Ex
2243 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2244 struct netr_LogonControl2Ex *r)
2246 struct dcesrv_netr_LogonControl_base_state *state;
2249 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2250 if (state == NULL) {
2251 return WERR_NOT_ENOUGH_MEMORY;
2254 state->dce_call = dce_call;
2255 state->mem_ctx = mem_ctx;
2260 werr = dcesrv_netr_LogonControl_base_call(state);
2262 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2269 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2270 struct ldb_context *sam_ctx,
2271 struct netr_DomainTrustList *trusts,
2272 uint32_t trust_flags);
2277 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2278 struct netr_GetAnyDCName *r)
2280 struct netr_DomainTrustList *trusts;
2281 struct ldb_context *sam_ctx;
2282 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2286 *r->out.dcname = NULL;
2288 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2289 /* if the domainname parameter wasn't set assume our domain */
2290 r->in.domainname = lpcfg_workgroup(lp_ctx);
2293 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2294 if (sam_ctx == NULL) {
2295 return WERR_DS_UNAVAILABLE;
2298 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2299 /* well we asked for a DC of our own domain */
2300 if (samdb_is_pdc(sam_ctx)) {
2301 /* we are the PDC of the specified domain */
2302 return WERR_NO_SUCH_DOMAIN;
2305 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2306 lpcfg_netbios_name(lp_ctx));
2307 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2312 /* Okay, now we have to consider the trusted domains */
2314 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2315 W_ERROR_HAVE_NO_MEMORY(trusts);
2319 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2320 NETR_TRUST_FLAG_INBOUND
2321 | NETR_TRUST_FLAG_OUTBOUND);
2322 W_ERROR_NOT_OK_RETURN(werr);
2324 for (i = 0; i < trusts->count; i++) {
2325 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2326 /* FIXME: Here we need to find a DC for the specified
2327 * trusted domain. */
2329 /* return WERR_OK; */
2330 return WERR_NO_SUCH_DOMAIN;
2334 return WERR_NO_SUCH_DOMAIN;
2341 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2342 struct netr_DatabaseRedo *r)
2344 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2349 netr_NetrEnumerateTrustedDomains
2351 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2352 struct netr_NetrEnumerateTrustedDomains *r)
2354 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2359 netr_LogonGetCapabilities
2361 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2362 struct netr_LogonGetCapabilities *r)
2364 struct netlogon_creds_CredentialState *creds;
2367 status = dcesrv_netr_creds_server_step_check(dce_call,
2369 r->in.computer_name,
2371 r->out.return_authenticator,
2373 if (!NT_STATUS_IS_OK(status)) {
2374 DEBUG(0,(__location__ " Bad credentials - error\n"));
2376 NT_STATUS_NOT_OK_RETURN(status);
2378 if (r->in.query_level != 1) {
2379 return NT_STATUS_NOT_SUPPORTED;
2382 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2384 return NT_STATUS_OK;
2389 netr_NETRLOGONSETSERVICEBITS
2391 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2392 struct netr_NETRLOGONSETSERVICEBITS *r)
2394 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2399 netr_LogonGetTrustRid
2401 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2402 struct netr_LogonGetTrustRid *r)
2404 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2409 netr_NETRLOGONCOMPUTESERVERDIGEST
2411 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2412 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2414 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2419 netr_NETRLOGONCOMPUTECLIENTDIGEST
2421 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2422 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2424 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2432 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2433 struct netr_DsRGetSiteName *r)
2435 struct ldb_context *sam_ctx;
2437 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2438 if (sam_ctx == NULL) {
2439 return WERR_DS_UNAVAILABLE;
2443 * We assume to be a DC when we get called over NETLOGON. Hence we
2444 * get our site name always by using "samdb_server_site_name()"
2445 * and not "samdb_client_site_name()".
2447 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2448 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2455 fill in a netr_OneDomainInfo from our own domain/forest
2457 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2458 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2459 struct GUID domain_guid,
2460 struct netr_OneDomainInfo *info,
2465 if (is_trust_list) {
2466 struct netr_trust_extension *te = NULL;
2467 struct netr_trust_extension_info *tei = NULL;
2469 /* w2k8 only fills this on trusted domains */
2470 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2472 return NT_STATUS_NO_MEMORY;
2475 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2478 * We're always within a native forest
2480 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2481 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2483 /* For now we assume we're always the tree root */
2484 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2485 tei->parent_index = 0;
2487 tei->trust_type = our_tdo->trust_type;
2489 * This needs to be 0 instead of our_tdo->trust_attributes
2490 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2491 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2493 tei->trust_attributes = 0;
2495 info->trust_extension.info = te;
2498 if (is_trust_list) {
2499 info->dns_domainname.string = our_tdo->domain_name.string;
2501 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2502 info->dns_forestname.string = NULL;
2504 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2505 our_tdo->domain_name.string);
2506 if (info->dns_domainname.string == NULL) {
2507 return NT_STATUS_NO_MEMORY;
2510 info->dns_forestname.string = info->dns_domainname.string;
2513 info->domainname.string = our_tdo->netbios_name.string;
2514 info->domain_sid = our_tdo->sid;
2515 info->domain_guid = domain_guid;
2517 return NT_STATUS_OK;
2521 fill in a netr_OneDomainInfo from a trust tdo
2523 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2524 struct GUID domain_guid,
2525 const struct lsa_TrustDomainInfoInfoEx *tdo,
2526 struct netr_OneDomainInfo *info)
2528 struct netr_trust_extension *te = NULL;
2529 struct netr_trust_extension_info *tei = NULL;
2533 /* w2k8 only fills this on trusted domains */
2534 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2536 return NT_STATUS_NO_MEMORY;
2540 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2541 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2543 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2544 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2546 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2547 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2551 * TODO: once we support multiple domains within our forest,
2552 * we need to fill this correct (or let the caller do it
2553 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2555 tei->parent_index = 0;
2557 tei->trust_type = tdo->trust_type;
2558 tei->trust_attributes = tdo->trust_attributes;
2560 info->trust_extension.info = te;
2562 info->domainname.string = tdo->netbios_name.string;
2563 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2564 info->dns_domainname.string = tdo->domain_name.string;
2566 info->dns_domainname.string = NULL;
2568 info->domain_sid = tdo->sid;
2569 info->domain_guid = domain_guid;
2571 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2572 info->dns_forestname.string = NULL;
2574 return NT_STATUS_OK;
2578 netr_LogonGetDomainInfo
2579 this is called as part of the ADS domain logon procedure.
2581 It has an important role in convaying details about the client, such
2582 as Operating System, Version, Service Pack etc.
2584 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2585 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2587 struct netlogon_creds_CredentialState *creds;
2588 const char * const trusts_attrs[] = {
2589 "securityIdentifier",
2597 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2598 "msDS-SupportedEncryptionTypes", NULL };
2599 const char *sam_account_name, *old_dns_hostname;
2600 struct ldb_context *sam_ctx;
2601 const struct GUID *our_domain_guid = NULL;
2602 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2603 struct ldb_message **res1, *new_msg;
2604 struct ldb_result *trusts_res = NULL;
2605 struct ldb_dn *workstation_dn;
2606 struct netr_DomainInformation *domain_info;
2607 struct netr_LsaPolicyInformation *lsa_policy_info;
2608 struct auth_session_info *workstation_session_info = NULL;
2609 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2610 bool update_dns_hostname = true;
2614 status = dcesrv_netr_creds_server_step_check(dce_call,
2616 r->in.computer_name,
2618 r->out.return_authenticator,
2620 if (!NT_STATUS_IS_OK(status)) {
2622 char* remote = NULL;
2623 TALLOC_CTX *frame = talloc_stackframe();
2624 remote = tsocket_address_string(dce_call->conn->remote_address,
2626 local = tsocket_address_string(dce_call->conn->local_address,
2628 DBG_ERR(("Bad credentials - "
2629 "computer[%s] remote[%s] local[%s]\n"),
2630 log_escape(frame, r->in.computer_name),
2635 NT_STATUS_NOT_OK_RETURN(status);
2637 /* We want to avoid connecting as system. */
2638 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2639 if (sam_ctx == NULL) {
2640 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2643 switch (r->in.level) {
2644 case 1: /* Domain information */
2646 if (r->in.query->workstation_info == NULL) {
2647 return NT_STATUS_INVALID_PARAMETER;
2650 /* Prepares the workstation DN */
2651 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2652 dom_sid_string(mem_ctx, creds->sid));
2653 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2655 /* Get the workstation's session info from the database. */
2656 status = authsam_get_session_info_principal(mem_ctx,
2657 dce_call->conn->dce_ctx->lp_ctx,
2659 NULL, /* principal */
2661 0, /* session_info_flags */
2662 &workstation_session_info);
2663 if (!NT_STATUS_IS_OK(status)) {
2668 * Reconnect to samdb as the workstation, now that we have its
2669 * session info. We do this so the database update can be
2670 * attributed to the workstation account in the audit logs --
2671 * otherwise it might be incorrectly attributed to
2674 sam_ctx = dcesrv_samdb_connect_session_info(mem_ctx,
2676 workstation_session_info,
2677 workstation_session_info);
2678 if (sam_ctx == NULL) {
2679 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2682 /* Lookup for attributes in workstation object */
2683 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2686 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2689 /* Gets the sam account name which is checked against the DNS
2690 * hostname parameter. */
2691 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2694 if (sam_account_name == NULL) {
2695 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2698 if (r->in.query->workstation_info->dns_hostname == NULL) {
2699 update_dns_hostname = false;
2702 /* Gets the old DNS hostname */
2703 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2708 * Updates the DNS hostname when the client wishes that the
2709 * server should handle this for him
2710 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
2711 * See MS-NRPC section 3.5.4.3.9
2713 if ((r->in.query->workstation_info->workstation_flags
2714 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2715 update_dns_hostname = false;
2718 /* Gets host information and put them into our directory */
2720 new_msg = ldb_msg_new(mem_ctx);
2721 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2723 new_msg->dn = workstation_dn;
2725 /* Sets the OS name */
2727 if (r->in.query->workstation_info->os_name.string == NULL) {
2728 return NT_STATUS_INVALID_PARAMETER;
2731 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2732 r->in.query->workstation_info->os_name.string);
2733 if (ret != LDB_SUCCESS) {
2734 return NT_STATUS_NO_MEMORY;
2738 * Sets information from "os_version". On an empty structure
2739 * the values are cleared.
2741 if (r->in.query->workstation_info->os_version.os != NULL) {
2742 struct netr_OsVersionInfoEx *os_version;
2743 const char *os_version_str;
2745 os_version = &r->in.query->workstation_info->os_version.os->os;
2747 if (os_version->CSDVersion == NULL) {
2748 return NT_STATUS_INVALID_PARAMETER;
2751 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2752 os_version->MajorVersion,
2753 os_version->MinorVersion,
2754 os_version->BuildNumber);
2755 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2757 if (strlen(os_version->CSDVersion) != 0) {
2758 ret = ldb_msg_add_string(new_msg,
2759 "operatingSystemServicePack",
2760 os_version->CSDVersion);
2762 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2763 "operatingSystemServicePack");
2765 if (ret != LDB_SUCCESS) {
2766 return NT_STATUS_NO_MEMORY;
2769 ret = ldb_msg_add_string(new_msg,
2770 "operatingSystemVersion",
2772 if (ret != LDB_SUCCESS) {
2773 return NT_STATUS_NO_MEMORY;
2776 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2777 "operatingSystemServicePack");
2778 if (ret != LDB_SUCCESS) {
2779 return NT_STATUS_NO_MEMORY;
2782 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2783 "operatingSystemVersion");
2784 if (ret != LDB_SUCCESS) {
2785 return NT_STATUS_NO_MEMORY;
2790 * If the boolean "update_dns_hostname" remained true, then we
2791 * are fine to start the update.
2793 if (update_dns_hostname) {
2794 ret = ldb_msg_add_string(new_msg,
2796 r->in.query->workstation_info->dns_hostname);
2797 if (ret != LDB_SUCCESS) {
2798 return NT_STATUS_NO_MEMORY;
2801 /* This manual "servicePrincipalName" generation is
2802 * still needed! Since the update in the samldb LDB
2803 * module does only work if the entries already exist
2804 * which isn't always the case. */
2805 ret = ldb_msg_add_string(new_msg,
2806 "servicePrincipalName",
2807 talloc_asprintf(new_msg, "HOST/%s",
2808 r->in.computer_name));
2809 if (ret != LDB_SUCCESS) {
2810 return NT_STATUS_NO_MEMORY;
2813 ret = ldb_msg_add_string(new_msg,
2814 "servicePrincipalName",
2815 talloc_asprintf(new_msg, "HOST/%s",
2816 r->in.query->workstation_info->dns_hostname));
2817 if (ret != LDB_SUCCESS) {
2818 return NT_STATUS_NO_MEMORY;
2822 if (dsdb_replace(sam_ctx, new_msg, DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) != LDB_SUCCESS) {
2823 DEBUG(3,("Impossible to update samdb: %s\n",
2824 ldb_errstring(sam_ctx)));
2827 talloc_free(new_msg);
2829 /* Writes back the domain information */
2831 our_domain_guid = samdb_domain_guid(sam_ctx);
2832 if (our_domain_guid == NULL) {
2833 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2836 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2837 if (!NT_STATUS_IS_OK(status)) {
2841 status = dsdb_trust_search_tdos(sam_ctx,
2846 if (!NT_STATUS_IS_OK(status)) {
2850 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2851 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2853 ZERO_STRUCTP(domain_info);
2855 /* Informations about the local and trusted domains */
2857 status = fill_our_one_domain_info(mem_ctx,
2860 &domain_info->primary_domain,
2862 if (!NT_STATUS_IS_OK(status)) {
2866 domain_info->trusted_domain_count = trusts_res->count + 1;
2867 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2868 struct netr_OneDomainInfo,
2869 domain_info->trusted_domain_count);
2870 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2872 for (i=0; i < trusts_res->count; i++) {
2873 struct netr_OneDomainInfo *o =
2874 &domain_info->trusted_domains[i];
2875 /* we can't know the guid of trusts outside our forest */
2876 struct GUID trust_domain_guid = GUID_zero();
2877 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2879 status = dsdb_trust_parse_tdo_info(mem_ctx,
2880 trusts_res->msgs[i],
2882 if (!NT_STATUS_IS_OK(status)) {
2886 status = fill_trust_one_domain_info(mem_ctx,
2890 if (!NT_STATUS_IS_OK(status)) {
2895 status = fill_our_one_domain_info(mem_ctx,
2898 &domain_info->trusted_domains[i],
2900 if (!NT_STATUS_IS_OK(status)) {
2904 /* Sets the supported encryption types */
2905 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2906 "msDS-SupportedEncryptionTypes",
2907 default_supported_enc_types);
2909 /* Other host domain information */
2911 lsa_policy_info = talloc(mem_ctx,
2912 struct netr_LsaPolicyInformation);
2913 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2914 ZERO_STRUCTP(lsa_policy_info);
2916 domain_info->lsa_policy = *lsa_policy_info;
2918 /* The DNS hostname is only returned back when there is a chance
2920 if ((r->in.query->workstation_info->workstation_flags
2921 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2922 domain_info->dns_hostname.string = old_dns_hostname;
2924 domain_info->dns_hostname.string = NULL;
2927 domain_info->workstation_flags =
2928 r->in.query->workstation_info->workstation_flags & (
2929 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2931 r->out.info->domain_info = domain_info;
2933 case 2: /* LSA policy information - not used at the moment */
2934 lsa_policy_info = talloc(mem_ctx,
2935 struct netr_LsaPolicyInformation);
2936 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2937 ZERO_STRUCTP(lsa_policy_info);
2939 r->out.info->lsa_policy_info = lsa_policy_info;
2942 return NT_STATUS_INVALID_LEVEL;
2946 return NT_STATUS_OK;
2951 netr_ServerPasswordGet
2953 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2954 struct netr_ServerPasswordGet *r)
2956 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2959 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2960 TALLOC_CTX *mem_ctx,
2961 struct dom_sid *user_sid,
2962 struct ldb_dn *obj_dn)
2964 const char *rodc_attrs[] = { "msDS-NeverRevealGroup",
2965 "msDS-RevealOnDemandGroup",
2966 "userAccountControl",
2968 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2969 struct ldb_dn *rodc_dn;
2971 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2974 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2975 dom_sid_string(mem_ctx, user_sid));
2976 if (!ldb_dn_validate(rodc_dn)) goto denied;
2979 * do the two searches we need
2980 * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list
2981 * out of the extended DNs
2983 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2984 DSDB_SEARCH_SHOW_EXTENDED_DN);
2985 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2987 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2988 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2990 werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx,
2995 if (W_ERROR_IS_OK(werr)) {
3006 netr_NetrLogonSendToSam
3008 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3009 struct netr_NetrLogonSendToSam *r)
3011 struct netlogon_creds_CredentialState *creds;
3012 struct ldb_context *sam_ctx;
3014 DATA_BLOB decrypted_blob;
3015 enum ndr_err_code ndr_err;
3016 struct netr_SendToSamBase base_msg = { 0 };
3018 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3020 r->in.computer_name,
3022 r->out.return_authenticator,
3025 NT_STATUS_NOT_OK_RETURN(nt_status);
3027 switch (creds->secure_channel_type) {
3031 case SEC_CHAN_WKSTA:
3032 case SEC_CHAN_DNS_DOMAIN:
3033 case SEC_CHAN_DOMAIN:
3035 return NT_STATUS_INVALID_PARAMETER;
3037 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
3038 creds->secure_channel_type));
3039 return NT_STATUS_INVALID_PARAMETER;
3042 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3043 if (sam_ctx == NULL) {
3044 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3047 /* Buffer is meant to be 16-bit aligned */
3048 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3049 nt_status = netlogon_creds_aes_decrypt(creds,
3050 r->in.opaque_buffer,
3053 nt_status = netlogon_creds_arcfour_crypt(creds,
3054 r->in.opaque_buffer,
3057 if (!NT_STATUS_IS_OK(nt_status)) {
3061 decrypted_blob.data = r->in.opaque_buffer;
3062 decrypted_blob.length = r->in.buffer_len;
3064 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
3065 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
3067 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3068 /* We only partially implement SendToSam */
3069 return NT_STATUS_NOT_IMPLEMENTED;
3072 /* Now 'send' to SAM */
3073 switch (base_msg.message_type) {
3074 case SendToSamResetBadPasswordCount:
3076 struct ldb_message *msg = ldb_msg_new(mem_ctx);
3077 struct ldb_dn *dn = NULL;
3081 ret = ldb_transaction_start(sam_ctx);
3082 if (ret != LDB_SUCCESS) {
3083 return NT_STATUS_INTERNAL_ERROR;
3086 ret = dsdb_find_dn_by_guid(sam_ctx,
3088 &base_msg.message.reset_bad_password.guid,
3091 if (ret != LDB_SUCCESS) {
3092 ldb_transaction_cancel(sam_ctx);
3093 return NT_STATUS_INVALID_PARAMETER;
3096 if (creds->secure_channel_type == SEC_CHAN_RODC &&
3097 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
3098 DEBUG(1, ("Client asked to reset bad password on "
3099 "an arbitrary user: %s\n",
3100 ldb_dn_get_linearized(dn)));
3101 ldb_transaction_cancel(sam_ctx);
3102 return NT_STATUS_INVALID_PARAMETER;
3107 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
3108 if (ret != LDB_SUCCESS) {
3109 ldb_transaction_cancel(sam_ctx);
3110 return NT_STATUS_INVALID_PARAMETER;
3113 ret = dsdb_replace(sam_ctx, msg, 0);
3114 if (ret != LDB_SUCCESS) {
3115 ldb_transaction_cancel(sam_ctx);
3116 return NT_STATUS_INVALID_PARAMETER;
3119 ret = ldb_transaction_commit(sam_ctx);
3120 if (ret != LDB_SUCCESS) {
3121 ldb_transaction_cancel(sam_ctx);
3122 return NT_STATUS_INTERNAL_ERROR;
3128 return NT_STATUS_NOT_IMPLEMENTED;
3131 return NT_STATUS_OK;
3134 struct dcesrv_netr_DsRGetDCName_base_state {
3135 struct dcesrv_call_state *dce_call;
3136 TALLOC_CTX *mem_ctx;
3138 struct netr_DsRGetDCNameEx2 r;
3139 const char *client_site;
3142 struct netr_DsRGetDCName *dc;
3143 struct netr_DsRGetDCNameEx *dcex;
3144 struct netr_DsRGetDCNameEx2 *dcex2;
3148 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
3150 /* Returns a nonzero value if multiple bits in 'val' are set. */
3151 static bool multiple_bits_set(uint32_t val)
3154 * Subtracting one from an integer has the effect of flipping all the
3155 * bits from the least significant bit up to and including the least
3156 * significant '1' bit. For example,
3162 * If 'val' is zero, all the bits will be flipped and thus the bitwise
3163 * AND of 'val' with 'val - 1' will be zero.
3165 * If the integer is nonzero, the least significant '1' bit will be
3166 * ANDed with a '0' bit and so will be reset in the final result, but
3167 * all other '1' bits will remain set. In other words, the effect of
3168 * this expression is to mask off the least significant bit that is
3169 * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
3170 * must contain multiple set bits.
3172 return val & (val - 1);
3175 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
3177 struct dcesrv_call_state *dce_call = state->dce_call;
3178 struct imessaging_context *imsg_ctx =
3179 dcesrv_imessaging_context(dce_call->conn);
3180 TALLOC_CTX *mem_ctx = state->mem_ctx;
3181 struct netr_DsRGetDCNameEx2 *r = &state->r;
3182 struct ldb_context *sam_ctx;
3183 struct netr_DsRGetDCNameInfo *info;
3184 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3185 const struct tsocket_address *local_address;
3186 char *local_addr = NULL;
3187 const struct tsocket_address *remote_address;
3188 char *remote_addr = NULL;
3189 const char *server_site_name;
3191 struct netlogon_samlogon_response response;
3193 const char *dc_name = NULL;
3194 const char *domain_name = NULL;
3196 bool different_domain = true;
3197 bool force_remote_lookup = false;
3198 uint32_t valid_flags;
3199 uint32_t this_dc_valid_flags;
3202 ZERO_STRUCTP(r->out.info);
3204 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3205 if (sam_ctx == NULL) {
3206 return WERR_DS_UNAVAILABLE;
3209 local_address = dcesrv_connection_get_local_address(dce_call->conn);
3210 if (tsocket_address_is_inet(local_address, "ip")) {
3211 local_addr = tsocket_address_inet_addr_string(local_address, state);
3212 W_ERROR_HAVE_NO_MEMORY(local_addr);
3215 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
3216 if (tsocket_address_is_inet(remote_address, "ip")) {
3217 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
3218 W_ERROR_HAVE_NO_MEMORY(remote_addr);
3221 /* "server_unc" is ignored by w2k3 */
3224 * With the following flags:
3225 * DS_FORCE_REDISCOVERY (Flag A)
3226 * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
3227 * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
3228 * DS_GC_SERVER_REQUIRED (Flag D)
3229 * DS_PDC_REQUIRED (Flag E)
3230 * DS_BACKGROUND_ONLY (Flag F)
3231 * DS_IP_REQUIRED (Flag G)
3232 * DS_KDC_REQUIRED (Flag H)
3233 * DS_TIMESERV_REQUIRED (Flag I)
3234 * DS_WRITABLE_REQUIRED (Flag J)
3235 * DS_GOOD_TIMESERV_PREFERRED (Flag K)
3236 * DS_AVOID_SELF (Flag L)
3237 * DS_ONLY_LDAP_NEEDED (Flag M)
3238 * DS_IS_FLAT_NAME (Flag N)
3239 * DS_IS_DNS_NAME (Flag O)
3240 * DS_TRY_NEXTCLOSEST_SITE (Flag P)
3241 * DS_DIRECTORY_SERVICE_6_REQUIRED (Flag Q)
3242 * DS_WEB_SERVICE_REQUIRED (Flag T)
3243 * DS_DIRECTORY_SERVICE_8_REQUIRED (Flag U)
3244 * DS_DIRECTORY_SERVICE_9_REQUIRED (Flag V)
3245 * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
3246 * DS_RETURN_DNS_NAME (Flag R)
3247 * DS_RETURN_FLAT_NAME (Flag S)
3249 * MS-NRPC 3.5.4.3.1 says:
3251 * On receiving this call, the server MUST perform the following Flags
3252 * parameter validations:
3253 * - Flags D, E, and H MUST NOT be combined with each other.
3254 * - Flag N MUST NOT be combined with the O flag.
3255 * - Flag R MUST NOT be combined with the S flag.
3256 * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
3257 * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or H.
3258 * - Flag P MUST NOT be set when the SiteName parameter is provided.
3259 * The server MUST return ERROR_INVALID_FLAGS for any of the previously
3260 * mentioned conflicting combinations.
3264 valid_flags = DSGETDC_VALID_FLAGS;
3266 if (r->in.flags & ~valid_flags) {
3268 * TODO: add tests to prove this (maybe based on the
3269 * msDS-Behavior-Version levels of dc, domain and/or forest
3271 return WERR_INVALID_FLAGS;
3274 /* Flags D, E, and H MUST NOT be combined with each other. */
3275 #define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
3276 if (multiple_bits_set(r->in.flags & _DEH)) {
3277 return WERR_INVALID_FLAGS;
3280 /* Flag N MUST NOT be combined with the O flag. */
3281 if (r->in.flags & DS_IS_FLAT_NAME &&
3282 r->in.flags & DS_IS_DNS_NAME) {
3283 return WERR_INVALID_FLAGS;
3286 /* Flag R MUST NOT be combined with the S flag. */
3287 if (r->in.flags & DS_RETURN_DNS_NAME &&
3288 r->in.flags & DS_RETURN_FLAT_NAME) {
3289 return WERR_INVALID_FLAGS;
3292 /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
3294 DS_DIRECTORY_SERVICE_REQUIRED | \
3295 DS_DIRECTORY_SERVICE_6_REQUIRED | \
3296 DS_DIRECTORY_SERVICE_8_REQUIRED | \
3297 DS_DIRECTORY_SERVICE_9_REQUIRED | \
3298 DS_DIRECTORY_SERVICE_10_REQUIRED | \
3300 if (multiple_bits_set(r->in.flags & _BQUVW)) {
3301 return WERR_INVALID_FLAGS;
3305 * Flag K MUST NOT be combined with any of the flags:
3308 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
3310 (DS_DIRECTORY_SERVICE_REQUIRED |
3311 DS_DIRECTORY_SERVICE_PREFERRED |
3312 DS_GC_SERVER_REQUIRED |
3315 return WERR_INVALID_FLAGS;
3318 /* Flag P MUST NOT be set when the SiteName parameter is provided. */
3319 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
3321 return WERR_INVALID_FLAGS;
3325 * If we send an all-zero GUID, we should ignore it as winbind actually
3326 * checks it with a DNS query. Windows also appears to ignore it.
3328 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
3329 r->in.domain_guid = NULL;
3332 /* Attempt winbind search only if we suspect the domain is incorrect */
3333 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
3334 if (r->in.flags & DS_IS_FLAT_NAME) {
3335 if (strcasecmp_m(r->in.domain_name,
3336 lpcfg_sam_name(lp_ctx)) == 0) {
3337 different_domain = false;
3339 } else if (r->in.flags & DS_IS_DNS_NAME) {
3340 if (strcasecmp_m(r->in.domain_name,
3341 lpcfg_dnsdomain(lp_ctx)) == 0) {
3342 different_domain = false;
3345 if (strcasecmp_m(r->in.domain_name,
3346 lpcfg_sam_name(lp_ctx)) == 0 ||
3347 strcasecmp_m(r->in.domain_name,
3348 lpcfg_dnsdomain(lp_ctx)) == 0) {
3349 different_domain = false;
3354 * We need to be able to handle empty domain names, where we
3355 * revert to our domain by default.
3357 different_domain = false;
3360 if (!different_domain) {
3361 dc_level = dsdb_dc_functional_level(sam_ctx);
3364 * Do not return a local response if we do not support the
3365 * functional level or feature (eg web services)
3367 this_dc_valid_flags = valid_flags;
3369 /* Samba does not implement this */
3370 this_dc_valid_flags &= ~DS_WEB_SERVICE_REQUIRED;
3372 if (dc_level < DS_DOMAIN_FUNCTION_2012) {
3373 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_8_REQUIRED;
3375 if (dc_level < DS_DOMAIN_FUNCTION_2012_R2) {
3376 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_9_REQUIRED;
3378 if (dc_level < DS_DOMAIN_FUNCTION_2016) {
3379 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_10_REQUIRED;
3381 if (r->in.flags & ~this_dc_valid_flags) {
3382 DBG_INFO("Forcing remote lookup to find another DC "
3383 "in this domain %s with more features, "
3384 "as this Samba DC is Functional level %d but flags are 0x08%x\n",
3385 r->in.domain_name, dc_level, (unsigned int)r->in.flags);
3386 force_remote_lookup = true;
3390 /* Proof server site parameter "site_name" if it was specified */
3391 server_site_name = samdb_server_site_name(sam_ctx, state);
3392 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3393 if (force_remote_lookup
3395 || (r->in.site_name != NULL &&
3396 (strcasecmp_m(r->in.site_name,
3397 server_site_name) != 0))) {
3399 struct dcerpc_binding_handle *irpc_handle = NULL;
3400 struct tevent_req *subreq = NULL;
3403 * Retrieve the client site to override the winbind response.
3405 * DO NOT use Windows fallback for client site.
3406 * In the case of multiple domains, this is plainly wrong.
3408 * Note: It's possible that the client may belong to multiple
3409 * subnets across domains. It's not clear what this would mean,
3410 * but here we only return what this domain knows.
3412 state->client_site = samdb_client_site_name(sam_ctx,
3418 irpc_handle = irpc_binding_handle_by_name(state,
3421 &ndr_table_winbind);
3422 if (irpc_handle == NULL) {
3423 DEBUG(0,("Failed to get binding_handle for "
3424 "winbind_server task\n"));
3425 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3426 return WERR_SERVICE_NOT_FOUND;
3429 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3431 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3433 subreq = dcerpc_wbint_DsGetDcName_send(state,
3434 dce_call->event_ctx,
3441 if (subreq == NULL) {
3442 return WERR_NOT_ENOUGH_MEMORY;
3445 tevent_req_set_callback(subreq,
3446 dcesrv_netr_DsRGetDCName_base_done,
3452 guid_str = r->in.domain_guid != NULL ?
3453 GUID_string(state, r->in.domain_guid) : NULL;
3455 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3459 r->in.client_account,
3460 r->in.mask, remote_addr,
3461 NETLOGON_NT_VERSION_5EX_WITH_IP,
3462 lp_ctx, &response, true);
3463 if (!NT_STATUS_IS_OK(status)) {
3464 return ntstatus_to_werror(status);
3468 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3469 * (O) flag when the returned forest name is in DNS format. This is here
3470 * always the case (see below).
3472 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3474 if (r->in.flags & DS_RETURN_DNS_NAME) {
3475 dc_name = response.data.nt5_ex.pdc_dns_name;
3476 domain_name = response.data.nt5_ex.dns_domain;
3478 * According to MS-NRPC 2.2.1.2.1 we should set the
3479 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3480 * the returned information is in DNS form.
3482 response.data.nt5_ex.server_type |=
3483 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3484 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3485 dc_name = response.data.nt5_ex.pdc_name;
3486 domain_name = response.data.nt5_ex.domain_name;
3490 * TODO: autodetect what we need to return
3491 * based on the given arguments
3493 dc_name = response.data.nt5_ex.pdc_name;
3494 domain_name = response.data.nt5_ex.domain_name;
3497 if (!dc_name || !dc_name[0]) {
3498 return WERR_NO_SUCH_DOMAIN;
3501 if (!domain_name || !domain_name[0]) {
3502 return WERR_NO_SUCH_DOMAIN;
3505 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3506 W_ERROR_HAVE_NO_MEMORY(info);
3507 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3508 dc_name[0] != '\\'? "\\\\":"",
3509 talloc_strdup(mem_ctx, dc_name));
3510 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3512 pdc_ip = local_addr;
3513 if (pdc_ip == NULL) {
3514 pdc_ip = "127.0.0.1";
3516 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3517 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3518 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3519 info->domain_guid = response.data.nt5_ex.domain_uuid;
3520 info->domain_name = domain_name;
3521 info->forest_name = response.data.nt5_ex.forest;
3522 info->dc_flags = response.data.nt5_ex.server_type;
3523 if (r->in.flags & DS_RETURN_DNS_NAME) {
3524 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3525 * returned if we are returning info->dc_unc containing a FQDN.
3526 * This attribute is called DomainControllerName in the specs,
3527 * it seems that we decide to return FQDN or netbios depending on
3528 * DS_RETURN_DNS_NAME.
3530 info->dc_flags |= DS_DNS_CONTROLLER;
3532 info->dc_site_name = response.data.nt5_ex.server_site;
3533 info->client_site_name = response.data.nt5_ex.client_site;
3535 *r->out.info = info;
3540 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3542 struct dcesrv_netr_DsRGetDCName_base_state *state =
3543 tevent_req_callback_data(subreq,
3544 struct dcesrv_netr_DsRGetDCName_base_state);
3545 struct dcesrv_call_state *dce_call = state->dce_call;
3546 NTSTATUS result, status;
3548 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3551 TALLOC_FREE(subreq);
3553 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3554 state->r.out.result = WERR_TIMEOUT;
3558 if (!NT_STATUS_IS_OK(status)) {
3559 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3561 state->r.out.result = WERR_GEN_FAILURE;
3565 if (!NT_STATUS_IS_OK(result)) {
3566 DBG_NOTICE("DC location via winbind failed - %s\n",
3568 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3572 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3573 DBG_ERR("DC location via winbind returned no results\n");
3574 state->r.out.result = WERR_GEN_FAILURE;
3578 if (state->r.out.info[0]->dc_unc == NULL) {
3579 DBG_ERR("DC location via winbind returned no DC unc\n");
3580 state->r.out.result = WERR_GEN_FAILURE;
3585 * Either the supplied site name is NULL (possibly via
3586 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3587 * the input match name.
3589 * TODO: Currently this means that requests with NETBIOS domain
3590 * names can fail because they do not return the site name.
3592 if (state->r.in.site_name == NULL ||
3593 strcasecmp_m("", state->r.in.site_name) == 0 ||
3594 (state->r.out.info[0]->dc_site_name != NULL &&
3595 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3596 state->r.in.site_name) == 0)) {
3598 state->r.out.info[0]->client_site_name =
3599 talloc_move(state->mem_ctx, &state->client_site);
3602 * Make sure to return our DC UNC with // prefix.
3603 * Winbind currently doesn't send the leading slashes
3606 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3607 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3608 const char *dc_unc = NULL;
3610 dc_unc = talloc_asprintf(state->mem_ctx,
3612 state->r.out.info[0]->dc_unc);
3613 state->r.out.info[0]->dc_unc = dc_unc;
3616 state->r.out.result = WERR_OK;
3618 state->r.out.info = NULL;
3619 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3623 if (state->_r.dcex2 != NULL) {
3624 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3625 r->out.result = state->r.out.result;
3626 } else if (state->_r.dcex != NULL) {
3627 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3628 r->out.result = state->r.out.result;
3629 } else if (state->_r.dc != NULL) {
3630 struct netr_DsRGetDCName *r = state->_r.dc;
3631 r->out.result = state->r.out.result;
3635 status = dcesrv_reply(dce_call);
3636 if (!NT_STATUS_IS_OK(status)) {
3637 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3638 nt_errstr(status)));
3643 netr_DsRGetDCNameEx2
3645 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3646 TALLOC_CTX *mem_ctx,
3647 struct netr_DsRGetDCNameEx2 *r)
3649 struct dcesrv_netr_DsRGetDCName_base_state *state;
3651 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3652 if (state == NULL) {
3653 return WERR_NOT_ENOUGH_MEMORY;
3656 state->dce_call = dce_call;
3657 state->mem_ctx = mem_ctx;
3660 state->_r.dcex2 = r;
3662 return dcesrv_netr_DsRGetDCName_base_call(state);
3668 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3669 struct netr_DsRGetDCNameEx *r)
3671 struct dcesrv_netr_DsRGetDCName_base_state *state;
3673 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3674 if (state == NULL) {
3675 return WERR_NOT_ENOUGH_MEMORY;
3678 state->dce_call = dce_call;
3679 state->mem_ctx = mem_ctx;
3681 state->r.in.server_unc = r->in.server_unc;
3682 state->r.in.client_account = NULL;
3683 state->r.in.mask = 0;
3684 state->r.in.domain_guid = r->in.domain_guid;
3685 state->r.in.domain_name = r->in.domain_name;
3686 state->r.in.site_name = r->in.site_name;
3687 state->r.in.flags = r->in.flags;
3688 state->r.out.info = r->out.info;
3692 return dcesrv_netr_DsRGetDCName_base_call(state);
3698 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3699 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3700 * insists that it be ignored.
3702 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3703 struct netr_DsRGetDCName *r)
3705 struct dcesrv_netr_DsRGetDCName_base_state *state;
3707 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3708 if (state == NULL) {
3709 return WERR_NOT_ENOUGH_MEMORY;
3712 state->dce_call = dce_call;
3713 state->mem_ctx = mem_ctx;
3715 state->r.in.server_unc = r->in.server_unc;
3716 state->r.in.client_account = NULL;
3717 state->r.in.mask = 0;
3718 state->r.in.domain_name = r->in.domain_name;
3719 state->r.in.domain_guid = r->in.domain_guid;
3721 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3722 state->r.in.flags = r->in.flags;
3723 state->r.out.info = r->out.info;
3727 return dcesrv_netr_DsRGetDCName_base_call(state);
3730 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3732 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3733 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3735 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3740 netr_NetrEnumerateTrustedDomainsEx
3742 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3743 struct netr_NetrEnumerateTrustedDomainsEx *r)
3745 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3750 netr_DsRAddressToSitenamesExW
3752 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3753 struct netr_DsRAddressToSitenamesExW *r)
3755 struct ldb_context *sam_ctx;
3756 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3757 sa_family_t sin_family;
3758 struct sockaddr_in *addr;
3760 struct sockaddr_in6 *addr6;
3761 char addr_str[INET6_ADDRSTRLEN];
3763 char addr_str[INET_ADDRSTRLEN];
3769 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3770 if (sam_ctx == NULL) {
3771 return WERR_DS_UNAVAILABLE;
3774 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3775 W_ERROR_HAVE_NO_MEMORY(ctr);
3779 ctr->count = r->in.count;
3780 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3781 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3782 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3783 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3785 for (i=0; i<ctr->count; i++) {
3786 ctr->sitename[i].string = NULL;
3787 ctr->subnetname[i].string = NULL;
3789 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3792 /* The first two byte of the buffer are reserved for the
3793 * "sin_family" but for now only the first one is used. */
3794 sin_family = r->in.addresses[i].buffer[0];
3796 switch (sin_family) {
3798 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3801 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3802 res = inet_ntop(AF_INET, &addr->sin_addr,
3803 addr_str, sizeof(addr_str));
3807 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3810 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3811 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3812 addr_str, sizeof(addr_str));
3823 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3828 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3829 ctr->subnetname[i].string = subnet_name;
3837 netr_DsRAddressToSitenamesW
3839 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840 struct netr_DsRAddressToSitenamesW *r)
3842 struct netr_DsRAddressToSitenamesExW r2;
3843 struct netr_DsRAddressToSitenamesWCtr *ctr;
3849 r2.in.server_name = r->in.server_name;
3850 r2.in.count = r->in.count;
3851 r2.in.addresses = r->in.addresses;
3853 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3854 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3856 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3857 W_ERROR_HAVE_NO_MEMORY(ctr);
3861 ctr->count = r->in.count;
3862 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3863 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3865 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3867 for (i=0; i<ctr->count; i++) {
3868 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3876 netr_DsrGetDcSiteCoverageW
3878 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3879 struct netr_DsrGetDcSiteCoverageW *r)
3881 struct ldb_context *sam_ctx;
3882 struct DcSitesCtr *ctr;
3884 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3885 if (sam_ctx == NULL) {
3886 return WERR_DS_UNAVAILABLE;
3889 ctr = talloc(mem_ctx, struct DcSitesCtr);
3890 W_ERROR_HAVE_NO_MEMORY(ctr);
3894 /* For now only return our default site */
3896 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3897 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3898 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3899 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3905 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3906 struct ldb_context *sam_ctx,
3907 struct netr_DomainTrustList *trusts,
3908 uint32_t trust_flags)
3910 struct ldb_dn *system_dn;
3911 struct ldb_message **dom_res = NULL;
3912 const char *trust_attrs[] = { "flatname", "trustPartner",
3913 "securityIdentifier", "trustDirection",
3914 "trustType", "trustAttributes", NULL };
3919 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3920 NETR_TRUST_FLAG_OUTBOUND))) {
3921 return WERR_INVALID_FLAGS;
3924 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3925 ldb_get_default_basedn(sam_ctx),
3926 "(&(objectClass=container)(cn=System))");
3928 return WERR_GEN_FAILURE;
3931 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3932 &dom_res, trust_attrs,
3933 "(objectclass=trustedDomain)");
3935 for (i = 0; i < ret; i++) {
3936 unsigned int trust_dir;
3939 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3940 "trustDirection", 0);
3942 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3943 flags |= NETR_TRUST_FLAG_INBOUND;
3945 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3946 flags |= NETR_TRUST_FLAG_OUTBOUND;
3949 if (!(flags & trust_flags)) {
3950 /* this trust direction was not requested */
3955 trusts->array = talloc_realloc(trusts, trusts->array,
3956 struct netr_DomainTrust,
3958 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3960 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3961 if (!trusts->array[n].netbios_name) {
3962 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3963 "without flatname\n",
3964 ldb_dn_get_linearized(dom_res[i]->dn)));
3967 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3969 trusts->array[n].trust_flags = flags;
3970 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3971 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3972 /* TODO: find if we have parent in the list */
3973 trusts->array[n].parent_index = 0;
3976 trusts->array[n].trust_type =
3977 ldb_msg_find_attr_as_uint(dom_res[i],
3979 trusts->array[n].trust_attributes =
3980 ldb_msg_find_attr_as_uint(dom_res[i],
3981 "trustAttributes", 0);
3983 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3984 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3985 struct dom_sid zero_sid;
3986 ZERO_STRUCT(zero_sid);
3987 trusts->array[n].sid =
3988 dom_sid_dup(trusts, &zero_sid);
3990 trusts->array[n].sid =
3991 samdb_result_dom_sid(trusts, dom_res[i],
3992 "securityIdentifier");
3994 trusts->array[n].guid = GUID_zero();
3996 trusts->count = n + 1;
3999 talloc_free(dom_res);
4004 netr_DsrEnumerateDomainTrusts
4006 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
4007 TALLOC_CTX *mem_ctx,
4008 struct netr_DsrEnumerateDomainTrusts *r)
4010 struct netr_DomainTrustList *trusts;
4011 struct ldb_context *sam_ctx;
4013 struct ldb_message **dom_res;
4014 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
4015 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4016 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
4020 if (r->in.trust_flags & 0xFFFFFE00) {
4021 return WERR_INVALID_FLAGS;
4024 /* TODO: turn to hard check once we are sure this is 100% correct */
4025 if (!r->in.server_name) {
4026 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
4027 "But received NULL!\n", dnsdomain));
4029 p = strchr(r->in.server_name, '.');
4031 DEBUG(3, ("Invalid domain! Expected name in domain "
4032 "[%s]. But received [%s]!\n",
4033 dnsdomain, r->in.server_name));
4034 p = r->in.server_name;
4038 if (strcasecmp(p, dnsdomain)) {
4039 DEBUG(3, ("Invalid domain! Expected name in domain "
4040 "[%s]. But received [%s]!\n",
4041 dnsdomain, r->in.server_name));
4045 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
4046 W_ERROR_HAVE_NO_MEMORY(trusts);
4049 r->out.trusts = trusts;
4051 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4052 if (sam_ctx == NULL) {
4053 return WERR_GEN_FAILURE;
4056 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
4057 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
4059 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
4060 trusts, r->in.trust_flags);
4061 W_ERROR_NOT_OK_RETURN(werr);
4064 /* NOTE: we currently are always the root of the forest */
4065 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
4066 uint32_t n = trusts->count;
4068 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
4069 &dom_res, dom_attrs);
4071 return WERR_GEN_FAILURE;
4074 trusts->count = n + 1;
4075 trusts->array = talloc_realloc(trusts, trusts->array,
4076 struct netr_DomainTrust,
4078 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4080 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
4081 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
4082 trusts->array[n].trust_flags =
4083 NETR_TRUST_FLAG_NATIVE |
4084 NETR_TRUST_FLAG_TREEROOT |
4085 NETR_TRUST_FLAG_IN_FOREST |
4086 NETR_TRUST_FLAG_PRIMARY;
4087 /* we are always the root domain for now */
4088 trusts->array[n].parent_index = 0;
4089 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
4090 trusts->array[n].trust_attributes = 0;
4091 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
4094 trusts->array[n].guid = samdb_result_guid(dom_res[0],
4096 talloc_free(dom_res);
4104 netr_DsrDeregisterDNSHostRecords
4106 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4107 struct netr_DsrDeregisterDNSHostRecords *r)
4109 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4113 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4114 struct netr_ServerGetTrustInfo *r);
4117 netr_ServerTrustPasswordsGet
4119 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4120 struct netr_ServerTrustPasswordsGet *r)
4122 struct netr_ServerGetTrustInfo r2 = {};
4123 struct netr_TrustInfo *_ti = NULL;
4126 r2.in.server_name = r->in.server_name;
4127 r2.in.account_name = r->in.account_name;
4128 r2.in.secure_channel_type = r->in.secure_channel_type;
4129 r2.in.computer_name = r->in.computer_name;
4130 r2.in.credential = r->in.credential;
4132 r2.out.return_authenticator = r->out.return_authenticator;
4133 r2.out.new_owf_password = r->out.new_owf_password;
4134 r2.out.old_owf_password = r->out.old_owf_password;
4135 r2.out.trust_info = &_ti;
4137 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
4139 r->out.return_authenticator = r2.out.return_authenticator;
4140 r->out.new_owf_password = r2.out.new_owf_password;
4141 r->out.old_owf_password = r2.out.old_owf_password;
4147 netr_DsRGetForestTrustInformation
4149 struct dcesrv_netr_DsRGetForestTrustInformation_state {
4150 struct dcesrv_call_state *dce_call;
4151 TALLOC_CTX *mem_ctx;
4152 struct netr_DsRGetForestTrustInformation *r;
4155 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
4157 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
4158 TALLOC_CTX *mem_ctx,
4159 struct netr_DsRGetForestTrustInformation *r)
4161 struct auth_session_info *session_info =
4162 dcesrv_call_session_info(dce_call);
4163 struct imessaging_context *imsg_ctx =
4164 dcesrv_imessaging_context(dce_call->conn);
4165 enum security_user_level security_level;
4166 struct ldb_context *sam_ctx = NULL;
4167 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
4168 struct dcerpc_binding_handle *irpc_handle = NULL;
4169 struct tevent_req *subreq = NULL;
4170 struct ldb_dn *domain_dn = NULL;
4171 struct ldb_dn *forest_dn = NULL;
4175 security_level = security_session_user_level(session_info, NULL);
4176 if (security_level < SECURITY_USER) {
4177 return WERR_ACCESS_DENIED;
4180 if (r->in.flags & 0xFFFFFFFE) {
4181 return WERR_INVALID_FLAGS;
4184 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4185 if (sam_ctx == NULL) {
4186 return WERR_GEN_FAILURE;
4189 domain_dn = ldb_get_default_basedn(sam_ctx);
4190 if (domain_dn == NULL) {
4191 return WERR_GEN_FAILURE;
4194 forest_dn = ldb_get_root_basedn(sam_ctx);
4195 if (forest_dn == NULL) {
4196 return WERR_GEN_FAILURE;
4199 cmp = ldb_dn_compare(domain_dn, forest_dn);
4201 return WERR_NERR_ACFNOTLOADED;
4204 forest_level = dsdb_forest_functional_level(sam_ctx);
4205 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4206 return WERR_INVALID_FUNCTION;
4209 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
4210 if (!samdb_is_pdc(sam_ctx)) {
4211 return WERR_NERR_NOTPRIMARY;
4214 if (r->in.trusted_domain_name == NULL) {
4215 return WERR_INVALID_FLAGS;
4219 if (r->in.trusted_domain_name == NULL) {
4223 * information about our own domain
4225 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4226 r->out.forest_trust_info);
4227 if (!NT_STATUS_IS_OK(status)) {
4228 return ntstatus_to_werror(status);
4235 * Forward the request to winbindd
4238 state = talloc_zero(mem_ctx,
4239 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4240 if (state == NULL) {
4241 return WERR_NOT_ENOUGH_MEMORY;
4243 state->dce_call = dce_call;
4244 state->mem_ctx = mem_ctx;
4247 irpc_handle = irpc_binding_handle_by_name(state,
4250 &ndr_table_winbind);
4251 if (irpc_handle == NULL) {
4252 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
4253 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4254 return WERR_SERVICE_NOT_FOUND;
4258 * 60 seconds timeout should be enough
4260 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
4262 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
4263 state->dce_call->event_ctx,
4265 r->in.trusted_domain_name,
4267 r->out.forest_trust_info);
4268 if (subreq == NULL) {
4269 return WERR_NOT_ENOUGH_MEMORY;
4271 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4272 tevent_req_set_callback(subreq,
4273 dcesrv_netr_DsRGetForestTrustInformation_done,
4279 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
4281 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
4282 tevent_req_callback_data(subreq,
4283 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4286 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
4288 &state->r->out.result);
4289 TALLOC_FREE(subreq);
4290 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
4291 state->r->out.result = WERR_TIMEOUT;
4292 } else if (!NT_STATUS_IS_OK(status)) {
4293 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4294 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
4295 nt_errstr(status)));
4298 status = dcesrv_reply(state->dce_call);
4299 if (!NT_STATUS_IS_OK(status)) {
4300 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4305 netr_GetForestTrustInformation
4307 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
4308 TALLOC_CTX *mem_ctx,
4309 struct netr_GetForestTrustInformation *r)
4311 struct netlogon_creds_CredentialState *creds = NULL;
4312 struct ldb_context *sam_ctx = NULL;
4313 struct ldb_dn *domain_dn = NULL;
4314 struct ldb_dn *forest_dn = NULL;
4319 status = dcesrv_netr_creds_server_step_check(dce_call,
4321 r->in.computer_name,
4323 r->out.return_authenticator,
4325 if (!NT_STATUS_IS_OK(status)) {
4329 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
4330 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
4331 return NT_STATUS_NOT_IMPLEMENTED;
4334 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4335 if (sam_ctx == NULL) {
4336 return NT_STATUS_INTERNAL_ERROR;
4339 /* TODO: check r->in.server_name is our name */
4341 domain_dn = ldb_get_default_basedn(sam_ctx);
4342 if (domain_dn == NULL) {
4343 return NT_STATUS_INTERNAL_ERROR;
4346 forest_dn = ldb_get_root_basedn(sam_ctx);
4347 if (forest_dn == NULL) {
4348 return NT_STATUS_INTERNAL_ERROR;
4351 cmp = ldb_dn_compare(domain_dn, forest_dn);
4353 return NT_STATUS_INVALID_DOMAIN_STATE;
4356 forest_level = dsdb_forest_functional_level(sam_ctx);
4357 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4358 return NT_STATUS_INVALID_DOMAIN_STATE;
4361 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4362 r->out.forest_trust_info);
4363 if (!NT_STATUS_IS_OK(status)) {
4367 return NT_STATUS_OK;
4372 netr_ServerGetTrustInfo
4374 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4375 struct netr_ServerGetTrustInfo *r)
4377 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4378 struct netlogon_creds_CredentialState *creds = NULL;
4379 struct ldb_context *sam_ctx = NULL;
4380 const char * const attrs[] = {
4383 "userAccountControl",
4386 struct ldb_message **res = NULL;
4387 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4390 const char *asid = NULL;
4392 const char *aname = NULL;
4393 struct ldb_message *tdo_msg = NULL;
4394 const char * const tdo_attrs[] = {
4395 "trustAuthIncoming",
4399 struct netr_TrustInfo *trust_info = NULL;
4401 ZERO_STRUCTP(r->out.new_owf_password);
4402 ZERO_STRUCTP(r->out.old_owf_password);
4404 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4406 r->in.computer_name,
4408 r->out.return_authenticator,
4410 if (!NT_STATUS_IS_OK(nt_status)) {
4414 /* TODO: check r->in.server_name is our name */
4416 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4417 return NT_STATUS_INVALID_PARAMETER;
4420 if (r->in.secure_channel_type != creds->secure_channel_type) {
4421 return NT_STATUS_INVALID_PARAMETER;
4424 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4425 return NT_STATUS_INVALID_PARAMETER;
4428 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
4429 if (sam_ctx == NULL) {
4430 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4433 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4435 return NT_STATUS_NO_MEMORY;
4438 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4439 "(&(objectClass=user)(objectSid=%s))",
4442 return NT_STATUS_ACCOUNT_DISABLED;
4445 switch (creds->secure_channel_type) {
4446 case SEC_CHAN_DNS_DOMAIN:
4447 case SEC_CHAN_DOMAIN:
4448 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4450 if (uac & UF_ACCOUNTDISABLE) {
4451 return NT_STATUS_ACCOUNT_DISABLED;
4454 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4455 return NT_STATUS_ACCOUNT_DISABLED;
4458 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4459 if (aname == NULL) {
4460 return NT_STATUS_ACCOUNT_DISABLED;
4463 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4464 SEC_CHAN_DOMAIN, aname,
4465 tdo_attrs, mem_ctx, &tdo_msg);
4466 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4467 return NT_STATUS_ACCOUNT_DISABLED;
4469 if (!NT_STATUS_IS_OK(nt_status)) {
4473 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4476 if (!NT_STATUS_IS_OK(nt_status)) {
4480 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4481 if (trust_info == NULL) {
4482 return NT_STATUS_NO_MEMORY;
4485 trust_info->count = 1;
4486 trust_info->data = talloc_array(trust_info, uint32_t,
4488 if (trust_info->data == NULL) {
4489 return NT_STATUS_NO_MEMORY;
4492 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4498 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4501 if (!NT_STATUS_IS_OK(nt_status)) {
4505 prevNtHash = talloc(mem_ctx, struct samr_Password);
4506 if (prevNtHash == NULL) {
4507 return NT_STATUS_NO_MEMORY;
4510 E_md4hash("", prevNtHash->hash);
4514 if (curNtHash != NULL) {
4515 *r->out.new_owf_password = *curNtHash;
4516 nt_status = netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4517 if (!NT_STATUS_IS_OK(nt_status)) {
4521 if (prevNtHash != NULL) {
4522 *r->out.old_owf_password = *prevNtHash;
4523 nt_status = netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4524 if (!NT_STATUS_IS_OK(nt_status)) {
4529 if (trust_info != NULL) {
4530 *r->out.trust_info = trust_info;
4533 return NT_STATUS_OK;
4539 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4540 struct netr_Unused47 *r)
4542 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4546 struct netr_dnsupdate_RODC_state {
4547 struct dcesrv_call_state *dce_call;
4548 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4549 struct dnsupdate_RODC *r2;
4553 called when the forwarded RODC dns update request is finished
4555 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4557 struct netr_dnsupdate_RODC_state *st =
4558 tevent_req_callback_data(subreq,
4559 struct netr_dnsupdate_RODC_state);
4562 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4563 TALLOC_FREE(subreq);
4564 if (!NT_STATUS_IS_OK(status)) {
4565 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4566 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4569 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4571 status = dcesrv_reply(st->dce_call);
4572 if (!NT_STATUS_IS_OK(status)) {
4573 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4578 netr_DsrUpdateReadOnlyServerDnsRecords
4580 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4581 TALLOC_CTX *mem_ctx,
4582 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4584 struct netlogon_creds_CredentialState *creds;
4586 struct dcerpc_binding_handle *binding_handle;
4587 struct netr_dnsupdate_RODC_state *st;
4588 struct tevent_req *subreq;
4589 struct imessaging_context *imsg_ctx =
4590 dcesrv_imessaging_context(dce_call->conn);
4592 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4594 r->in.computer_name,
4596 r->out.return_authenticator,
4598 NT_STATUS_NOT_OK_RETURN(nt_status);
4600 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4601 return NT_STATUS_ACCESS_DENIED;
4604 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4605 NT_STATUS_HAVE_NO_MEMORY(st);
4607 st->dce_call = dce_call;
4609 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4610 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4612 st->r2->in.dom_sid = creds->sid;
4613 st->r2->in.site_name = r->in.site_name;
4614 st->r2->in.dns_ttl = r->in.dns_ttl;
4615 st->r2->in.dns_names = r->in.dns_names;
4616 st->r2->out.dns_names = r->out.dns_names;
4618 binding_handle = irpc_binding_handle_by_name(st,
4622 if (binding_handle == NULL) {
4623 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4624 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4625 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4628 /* forward the call */
4629 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4630 binding_handle, st->r2);
4631 NT_STATUS_HAVE_NO_MEMORY(subreq);
4633 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4635 /* setup the callback */
4636 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4638 return NT_STATUS_OK;
4642 /* include the generated boilerplate */
4643 #include "librpc/gen_ndr/ndr_netlogon_s.c"