libsecurity: Simplify struct ace_condition_script
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob175ff532b4a49adc7f450cbcfac10db19223fe32
1 /*
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/>.
24 #include "includes.h"
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/common/util.h"
38 #include "dsdb/samdb/ldb_modules/util.h"
39 #include "lib/tsocket/tsocket.h"
40 #include "librpc/gen_ndr/ndr_netlogon.h"
41 #include "librpc/gen_ndr/ndr_lsa.h"
42 #include "librpc/gen_ndr/ndr_samr.h"
43 #include "librpc/gen_ndr/ndr_irpc.h"
44 #include "librpc/gen_ndr/ndr_winbind.h"
45 #include "librpc/gen_ndr/ndr_winbind_c.h"
46 #include "librpc/rpc/server/netlogon/schannel_util.h"
47 #include "lib/socket/netif.h"
48 #include "lib/util/util_str_escape.h"
49 #include "lib/param/loadparm.h"
51 #define DCESRV_INTERFACE_NETLOGON_BIND(context, iface) \
52 dcesrv_interface_netlogon_bind(context, iface)
54 #undef strcasecmp
57 * This #define allows the netlogon interface to accept invalid
58 * association groups, because association groups are to coordinate
59 * handles, and handles are not used in NETLOGON. This in turn avoids
60 * the need to coordinate these across multiple possible NETLOGON
61 * processes
63 #define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
65 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context *context,
66 const struct dcesrv_interface *iface)
68 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
69 bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
70 bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
71 int schannel = lpcfg_server_schannel(lp_ctx);
72 bool schannel_global_required = (schannel == true);
73 bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx);
74 static bool warned_global_nt4_once = false;
75 static bool warned_global_md5_once = false;
76 static bool warned_global_schannel_once = false;
77 static bool warned_global_seal_once = false;
79 if (global_allow_nt4_crypto && !warned_global_nt4_once) {
81 * We want admins to notice their misconfiguration!
83 D_ERR("CVE-2022-38023 (and others): "
84 "Please configure 'allow nt4 crypto = no' (the default), "
85 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
86 warned_global_nt4_once = true;
89 if (!global_reject_md5_client && !warned_global_md5_once) {
91 * We want admins to notice their misconfiguration!
93 D_ERR("CVE-2022-38023: "
94 "Please configure 'reject md5 clients = yes' (the default), "
95 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
96 warned_global_md5_once = true;
99 if (!schannel_global_required && !warned_global_schannel_once) {
101 * We want admins to notice their misconfiguration!
103 D_ERR("CVE-2020-1472(ZeroLogon): "
104 "Please configure 'server schannel = yes' (the default), "
105 "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n");
106 warned_global_schannel_once = true;
109 if (!global_require_seal && !warned_global_seal_once) {
111 * We want admins to notice their misconfiguration!
113 D_ERR("CVE-2022-38023 (and others): "
114 "Please configure 'server schannel require seal = yes' (the default), "
115 "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
116 warned_global_seal_once = true;
119 return dcesrv_interface_bind_reject_connect(context, iface);
122 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
123 struct netr_ServerReqChallenge *r)
125 struct netlogon_server_pipe_state *pipe_state = NULL;
126 NTSTATUS ntstatus;
128 ZERO_STRUCTP(r->out.return_credentials);
130 pipe_state = dcesrv_iface_state_find_conn(dce_call,
131 NETLOGON_SERVER_PIPE_STATE_MAGIC,
132 struct netlogon_server_pipe_state);
133 TALLOC_FREE(pipe_state);
135 pipe_state = talloc_zero(dce_call,
136 struct netlogon_server_pipe_state);
137 if (pipe_state == NULL) {
138 return NT_STATUS_NO_MEMORY;
141 pipe_state->client_challenge = *r->in.credentials;
143 netlogon_creds_random_challenge(&pipe_state->server_challenge);
145 *r->out.return_credentials = pipe_state->server_challenge;
147 ntstatus = dcesrv_iface_state_store_conn(dce_call,
148 NETLOGON_SERVER_PIPE_STATE_MAGIC,
149 pipe_state);
150 if (!NT_STATUS_IS_OK(ntstatus)) {
151 return ntstatus;
154 ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
155 &pipe_state->client_challenge,
156 &pipe_state->server_challenge,
157 r->in.computer_name);
158 if (!NT_STATUS_IS_OK(ntstatus)) {
159 TALLOC_FREE(pipe_state);
160 return ntstatus;
163 return NT_STATUS_OK;
166 static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
167 struct dcesrv_call_state *dce_call,
168 struct netr_ServerAuthenticate3 *r,
169 struct netlogon_server_pipe_state *pipe_state,
170 uint32_t negotiate_flags,
171 const char *trust_account_in_db,
172 NTSTATUS orig_status)
174 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
175 bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
176 bool account_allow_nt4_crypto = global_allow_nt4_crypto;
177 const char *explicit_nt4_opt = NULL;
178 bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
179 bool account_reject_md5_client = global_reject_md5_client;
180 const char *explicit_md5_opt = NULL;
181 bool reject_des_client;
182 bool allow_nt4_crypto;
183 bool reject_md5_client;
184 bool need_des = true;
185 bool need_md5 = true;
186 int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL,
187 "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
188 int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL,
189 "CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
192 * We don't use lpcfg_parm_bool(), as we
193 * need the explicit_opt pointer in order to
194 * adjust the debug messages.
197 if (trust_account_in_db != NULL) {
198 explicit_nt4_opt = lpcfg_get_parametric(lp_ctx,
199 NULL,
200 "allow nt4 crypto",
201 trust_account_in_db);
203 if (explicit_nt4_opt != NULL) {
204 account_allow_nt4_crypto = lp_bool(explicit_nt4_opt);
206 allow_nt4_crypto = account_allow_nt4_crypto;
207 if (trust_account_in_db != NULL) {
208 explicit_md5_opt = lpcfg_get_parametric(lp_ctx,
209 NULL,
210 "server reject md5 schannel",
211 trust_account_in_db);
213 if (explicit_md5_opt != NULL) {
214 account_reject_md5_client = lp_bool(explicit_md5_opt);
216 reject_md5_client = account_reject_md5_client;
218 reject_des_client = !allow_nt4_crypto;
221 * If weak crypto is disabled, do not announce that we support RC4.
223 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
224 /* Without RC4 and DES we require AES */
225 reject_des_client = true;
226 reject_md5_client = true;
229 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
230 need_des = false;
231 reject_des_client = false;
234 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
235 need_des = false;
236 need_md5 = false;
237 reject_des_client = false;
238 reject_md5_client = false;
241 if (reject_des_client || reject_md5_client) {
242 TALLOC_CTX *frame = talloc_stackframe();
244 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
245 if (CVE_2022_38023_error_level < DBGLVL_NOTICE) {
246 CVE_2022_38023_error_level = DBGLVL_NOTICE;
248 DEBUG(CVE_2022_38023_error_level, (
249 "CVE-2022-38023: "
250 "client_account[%s] computer_name[%s] "
251 "schannel_type[%u] "
252 "client_negotiate_flags[0x%x] "
253 "%s%s%s "
254 "NT_STATUS_DOWNGRADE_DETECTED "
255 "WEAK_CRYPTO_DISALLOWED\n",
256 log_escape(frame, r->in.account_name),
257 log_escape(frame, r->in.computer_name),
258 r->in.secure_channel_type,
259 (unsigned)*r->in.negotiate_flags,
260 trust_account_in_db ? "real_account[" : "",
261 trust_account_in_db ? trust_account_in_db : "",
262 trust_account_in_db ? "]" : ""));
263 goto return_downgrade;
266 DEBUG(CVE_2022_38023_error_level, (
267 "CVE-2022-38023: "
268 "client_account[%s] computer_name[%s] "
269 "schannel_type[%u] "
270 "client_negotiate_flags[0x%x] "
271 "%s%s%s "
272 "NT_STATUS_DOWNGRADE_DETECTED "
273 "reject_des[%u] reject_md5[%u]\n",
274 log_escape(frame, r->in.account_name),
275 log_escape(frame, r->in.computer_name),
276 r->in.secure_channel_type,
277 (unsigned)*r->in.negotiate_flags,
278 trust_account_in_db ? "real_account[" : "",
279 trust_account_in_db ? trust_account_in_db : "",
280 trust_account_in_db ? "]" : "",
281 reject_des_client,
282 reject_md5_client));
283 if (trust_account_in_db == NULL) {
284 goto return_downgrade;
287 if (reject_md5_client && explicit_md5_opt == NULL) {
288 DEBUG(CVE_2022_38023_error_level, (
289 "CVE-2022-38023: Check if option "
290 "'server reject md5 schannel:%s = no' "
291 "might be needed for a legacy client.\n",
292 trust_account_in_db));
294 if (reject_des_client && explicit_nt4_opt == NULL) {
295 DEBUG(CVE_2022_38023_error_level, (
296 "CVE-2022-38023: Check if option "
297 "'allow nt4 crypto:%s = yes' "
298 "might be needed for a legacy client.\n",
299 trust_account_in_db));
302 return_downgrade:
304 * Here we match Windows 2012 and return no flags.
306 *r->out.negotiate_flags = 0;
307 TALLOC_FREE(frame);
308 return NT_STATUS_DOWNGRADE_DETECTED;
312 * This talloc_free is important to prevent re-use of the
313 * challenge. We have to delay it this far due to NETApp
314 * servers per:
315 * https://bugzilla.samba.org/show_bug.cgi?id=11291
317 TALLOC_FREE(pipe_state);
320 * At this point we must also cleanup the TDB cache
321 * entry, if we fail the client needs to call
322 * netr_ServerReqChallenge again.
324 * Note: this handles a non existing record just fine,
325 * the r->in.computer_name might not be the one used
326 * in netr_ServerReqChallenge(), but we are trying to
327 * just tidy up the normal case to prevent re-use.
329 schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
330 r->in.computer_name);
333 * According to Microsoft (see bugid #6099)
334 * Windows 7 looks at the negotiate_flags
335 * returned in this structure *even if the
336 * call fails with access denied!
338 *r->out.negotiate_flags = negotiate_flags;
340 if (!NT_STATUS_IS_OK(orig_status) || trust_account_in_db == NULL) {
341 return orig_status;
344 if (global_reject_md5_client && account_reject_md5_client && explicit_md5_opt) {
345 D_INFO("CVE-2022-38023: Check if option "
346 "'server reject md5 schannel:%s = yes' not needed!?\n",
347 trust_account_in_db);
348 } else if (need_md5 && !account_reject_md5_client && explicit_md5_opt) {
349 D_INFO("CVE-2022-38023: Check if option "
350 "'server reject md5 schannel:%s = no' "
351 "still needed for a legacy client.\n",
352 trust_account_in_db);
353 } else if (need_md5 && explicit_md5_opt == NULL) {
354 DEBUG(CVE_2022_38023_error_level, (
355 "CVE-2022-38023: Check if option "
356 "'server reject md5 schannel:%s = no' "
357 "might be needed for a legacy client.\n",
358 trust_account_in_db));
359 } else if (!account_reject_md5_client && explicit_md5_opt) {
360 DEBUG(CVE_2022_38023_warn_level, (
361 "CVE-2022-38023: Check if option "
362 "'server reject md5 schannel:%s = no' not needed!?\n",
363 trust_account_in_db));
366 if (!global_allow_nt4_crypto && !account_allow_nt4_crypto && explicit_nt4_opt) {
367 D_INFO("CVE-2022-38023: Check if option "
368 "'allow nt4 crypto:%s = no' not needed!?\n",
369 trust_account_in_db);
370 } else if (need_des && account_allow_nt4_crypto && explicit_nt4_opt) {
371 D_INFO("CVE-2022-38023: Check if option "
372 "'allow nt4 crypto:%s = yes' "
373 "still needed for a legacy client.\n",
374 trust_account_in_db);
375 } else if (need_des && explicit_nt4_opt == NULL) {
376 DEBUG(CVE_2022_38023_error_level, (
377 "CVE-2022-38023: Check if option "
378 "'allow nt4 crypto:%s = yes' "
379 "might be needed for a legacy client.\n",
380 trust_account_in_db));
381 } else if (account_allow_nt4_crypto && explicit_nt4_opt) {
382 DEBUG(CVE_2022_38023_warn_level, (
383 "CVE-2022-38023: Check if option "
384 "'allow nt4 crypto:%s = yes' not needed!?\n",
385 trust_account_in_db));
388 return orig_status;
392 * Do the actual processing of a netr_ServerAuthenticate3 message.
393 * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
395 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
396 struct dcesrv_call_state *dce_call,
397 TALLOC_CTX *mem_ctx,
398 struct netr_ServerAuthenticate3 *r,
399 const char **trust_account_for_search,
400 const char **trust_account_in_db,
401 struct dom_sid **sid)
403 struct netlogon_server_pipe_state *pipe_state = NULL;
404 bool challenge_valid = false;
405 struct netlogon_server_pipe_state challenge;
406 struct netlogon_creds_CredentialState *creds;
407 struct ldb_context *sam_ctx;
408 struct samr_Password *curNtHash = NULL;
409 struct samr_Password *prevNtHash = NULL;
410 uint32_t user_account_control;
411 struct ldb_message **msgs;
412 NTSTATUS nt_status;
413 static const char *attrs[] = {
414 "unicodePwd",
415 "userAccountControl",
416 "objectSid",
417 "samAccountName",
418 /* Required for Group Managed Service Accounts. */
419 "msDS-ManagedPasswordId",
420 "msDS-ManagedPasswordInterval",
421 "objectClass",
422 "whenCreated",
423 NULL};
424 uint32_t server_flags = 0;
425 uint32_t negotiate_flags = 0;
427 ZERO_STRUCTP(r->out.return_credentials);
428 *r->out.negotiate_flags = 0;
429 *r->out.rid = 0;
431 pipe_state = dcesrv_iface_state_find_conn(dce_call,
432 NETLOGON_SERVER_PIPE_STATE_MAGIC,
433 struct netlogon_server_pipe_state);
434 if (pipe_state != NULL) {
436 * If we had a challenge remembered on the connection
437 * consider this for usage. This can't be cleanup
438 * by other clients.
440 * This is the default code path for typical clients
441 * which call netr_ServerReqChallenge() and
442 * netr_ServerAuthenticate3() on the same dcerpc connection.
444 challenge = *pipe_state;
446 challenge_valid = true;
448 } else {
449 NTSTATUS ntstatus;
452 * Fallback and try to get the challenge from
453 * the global cache.
455 * If too many clients are using this code path,
456 * they may destroy their cache entries as the
457 * TDB has a fixed size limited via a lossy hash
459 * The TDB used is the schannel store, which is
460 * initialised at startup.
462 * NOTE: The challenge is deleted from the DB as soon as it is
463 * fetched, to prevent reuse.
467 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
468 &challenge.client_challenge,
469 &challenge.server_challenge,
470 r->in.computer_name);
472 if (!NT_STATUS_IS_OK(ntstatus)) {
473 ZERO_STRUCT(challenge);
474 } else {
475 challenge_valid = true;
479 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
480 NETLOGON_NEG_PERSISTENT_SAMREPL |
481 NETLOGON_NEG_ARCFOUR |
482 NETLOGON_NEG_PROMOTION_COUNT |
483 NETLOGON_NEG_CHANGELOG_BDC |
484 NETLOGON_NEG_FULL_SYNC_REPL |
485 NETLOGON_NEG_MULTIPLE_SIDS |
486 NETLOGON_NEG_REDO |
487 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
488 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
489 NETLOGON_NEG_GENERIC_PASSTHROUGH |
490 NETLOGON_NEG_CONCURRENT_RPC |
491 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
492 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
493 NETLOGON_NEG_STRONG_KEYS |
494 NETLOGON_NEG_TRANSITIVE_TRUSTS |
495 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
496 NETLOGON_NEG_PASSWORD_SET2 |
497 NETLOGON_NEG_GETDOMAININFO |
498 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
499 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
500 NETLOGON_NEG_RODC_PASSTHROUGH |
501 NETLOGON_NEG_SUPPORTS_AES |
502 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
503 NETLOGON_NEG_AUTHENTICATED_RPC;
506 * If weak crypto is disabled, do not announce that we support RC4.
508 if (lpcfg_weak_crypto(dce_call->conn->dce_ctx->lp_ctx) ==
509 SAMBA_WEAK_CRYPTO_DISALLOWED) {
510 server_flags &= ~NETLOGON_NEG_ARCFOUR;
513 negotiate_flags = *r->in.negotiate_flags & server_flags;
515 switch (r->in.secure_channel_type) {
516 case SEC_CHAN_WKSTA:
517 case SEC_CHAN_DNS_DOMAIN:
518 case SEC_CHAN_DOMAIN:
519 case SEC_CHAN_BDC:
520 case SEC_CHAN_RODC:
521 break;
522 case SEC_CHAN_NULL:
523 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
524 dce_call, r, pipe_state, negotiate_flags,
525 NULL, /* trust_account_in_db */
526 NT_STATUS_INVALID_PARAMETER);
527 default:
528 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
529 r->in.secure_channel_type));
530 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
531 dce_call, r, pipe_state, negotiate_flags,
532 NULL, /* trust_account_in_db */
533 NT_STATUS_INVALID_PARAMETER);
536 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
537 if (sam_ctx == NULL) {
538 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
539 dce_call, r, pipe_state, negotiate_flags,
540 NULL, /* trust_account_in_db */
541 NT_STATUS_INVALID_SYSTEM_SERVICE);
544 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
545 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
547 struct ldb_message *tdo_msg = NULL;
548 static const char *const tdo_attrs[] = {"trustAuthIncoming",
549 "trustAttributes",
550 "flatName",
551 NULL};
552 char *encoded_name = NULL;
553 size_t len;
554 const char *flatname = NULL;
555 char trailer = '$';
556 bool require_trailer = true;
557 const char *netbios = NULL;
558 const char *dns = NULL;
560 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
561 trailer = '.';
562 require_trailer = false;
565 encoded_name = ldb_binary_encode_string(mem_ctx,
566 r->in.account_name);
567 if (encoded_name == NULL) {
568 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
569 dce_call, r, pipe_state, negotiate_flags,
570 NULL, /* trust_account_in_db */
571 NT_STATUS_NO_MEMORY);
574 len = strlen(encoded_name);
575 if (len < 2) {
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);
582 if (require_trailer && encoded_name[len - 1] != trailer) {
583 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
584 dce_call, r, pipe_state, negotiate_flags,
585 NULL, /* trust_account_in_db */
586 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
588 encoded_name[len - 1] = '\0';
590 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
591 dns = encoded_name;
592 } else {
593 netbios = encoded_name;
596 nt_status = dsdb_trust_search_tdo(sam_ctx,
597 netbios, dns,
598 tdo_attrs, mem_ctx, &tdo_msg);
599 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
600 DEBUG(2, ("Client asked for a trusted domain secure channel, "
601 "but there's no tdo for [%s] => [%s] \n",
602 log_escape(mem_ctx, r->in.account_name),
603 encoded_name));
604 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
605 dce_call, r, pipe_state, negotiate_flags,
606 NULL, /* trust_account_in_db */
607 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
609 if (!NT_STATUS_IS_OK(nt_status)) {
610 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
611 dce_call, r, pipe_state, negotiate_flags,
612 NULL, /* trust_account_in_db */
613 nt_status);
616 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
617 &curNtHash,
618 &prevNtHash);
619 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
620 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
621 dce_call, r, pipe_state, negotiate_flags,
622 NULL, /* trust_account_in_db */
623 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
625 if (!NT_STATUS_IS_OK(nt_status)) {
626 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
627 dce_call, r, pipe_state, negotiate_flags,
628 NULL, /* trust_account_in_db */
629 nt_status);
632 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
633 if (flatname == NULL) {
634 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
635 dce_call, r, pipe_state, negotiate_flags,
636 NULL, /* trust_account_in_db */
637 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
640 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
641 if (*trust_account_for_search == NULL) {
642 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
643 dce_call, r, pipe_state, negotiate_flags,
644 NULL, /* trust_account_in_db */
645 NT_STATUS_NO_MEMORY);
647 } else {
648 *trust_account_for_search = r->in.account_name;
652 struct ldb_result *res = NULL;
653 int ret;
655 /* pull the user attributes */
656 ret = dsdb_search(
657 sam_ctx,
658 mem_ctx,
659 &res,
660 ldb_get_default_basedn(sam_ctx),
661 LDB_SCOPE_SUBTREE,
662 attrs,
663 DSDB_SEARCH_ONE_ONLY | DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
664 "(&(sAMAccountName=%s)(objectclass=user))",
665 ldb_binary_encode_string(mem_ctx,
666 *trust_account_for_search));
667 if (ret) {
668 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
669 log_escape(mem_ctx, r->in.account_name)));
670 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
671 dce_call, r, pipe_state, negotiate_flags,
672 NULL, /* trust_account_in_db */
673 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
676 msgs = talloc_steal(mem_ctx, res->msgs);
677 talloc_free(res);
680 *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
681 "samAccountName",
682 NULL);
683 if (*trust_account_in_db == NULL) {
684 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
685 r->in.account_name));
686 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
687 dce_call, r, pipe_state, negotiate_flags,
688 NULL, /* trust_account_in_db */
689 NT_STATUS_INTERNAL_DB_CORRUPTION);
692 nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
693 dce_call, r, pipe_state, negotiate_flags,
694 *trust_account_in_db,
695 NT_STATUS_OK);
696 if (!NT_STATUS_IS_OK(nt_status)) {
697 return nt_status;
700 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
702 if (user_account_control & UF_ACCOUNTDISABLE) {
703 DEBUG(1, ("Account [%s] is disabled\n",
704 log_escape(mem_ctx, r->in.account_name)));
705 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
708 switch (r->in.secure_channel_type) {
709 case SEC_CHAN_WKSTA:
710 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
711 DBG_WARNING("Client asked for a workstation "
712 "secure channel, but is not a workstation "
713 "(member server) acb flags: 0x%x\n",
714 user_account_control);
715 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
717 break;
719 case SEC_CHAN_DOMAIN:
720 FALL_THROUGH;
721 case SEC_CHAN_DNS_DOMAIN:
722 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
723 DBG_WARNING("Client asked for a trusted domain "
724 "secure channel, but is not a trusted "
725 "domain: acb flags: 0x%x\n",
726 user_account_control);
727 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
729 break;
731 case SEC_CHAN_BDC:
732 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
733 DBG_WARNING("Client asked for a server "
734 "secure channel, but is not a server "
735 "(domain controller): acb flags: 0x%x\n",
736 user_account_control);
737 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
739 break;
741 case SEC_CHAN_RODC:
742 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
743 DBG_WARNING("Client asked for a RODC secure channel, "
744 "but is not a RODC: acb flags: 0x%x\n",
745 user_account_control);
746 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
748 break;
750 default:
751 /* we should never reach this */
752 return NT_STATUS_INTERNAL_ERROR;
755 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
756 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
757 dce_call->conn->dce_ctx->lp_ctx,
758 msgs[0], &curNtHash);
759 if (!NT_STATUS_IS_OK(nt_status)) {
760 return NT_STATUS_ACCESS_DENIED;
764 if (curNtHash == NULL) {
765 return NT_STATUS_ACCESS_DENIED;
768 if (!challenge_valid) {
769 DEBUG(1, ("No challenge requested by client [%s/%s], "
770 "cannot authenticate\n",
771 log_escape(mem_ctx, r->in.computer_name),
772 log_escape(mem_ctx, r->in.account_name)));
773 return NT_STATUS_ACCESS_DENIED;
776 creds = netlogon_creds_server_init(mem_ctx,
777 r->in.account_name,
778 r->in.computer_name,
779 r->in.secure_channel_type,
780 &challenge.client_challenge,
781 &challenge.server_challenge,
782 curNtHash,
783 r->in.credentials,
784 r->out.return_credentials,
785 negotiate_flags);
786 if (creds == NULL && prevNtHash != NULL) {
788 * We fallback to the previous password for domain trusts.
790 * Note that lpcfg_old_password_allowed_period() doesn't
791 * apply here.
793 creds = netlogon_creds_server_init(mem_ctx,
794 r->in.account_name,
795 r->in.computer_name,
796 r->in.secure_channel_type,
797 &challenge.client_challenge,
798 &challenge.server_challenge,
799 prevNtHash,
800 r->in.credentials,
801 r->out.return_credentials,
802 negotiate_flags);
805 if (creds == NULL) {
806 return NT_STATUS_ACCESS_DENIED;
808 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
809 *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
811 nt_status = schannel_save_creds_state(mem_ctx,
812 dce_call->conn->dce_ctx->lp_ctx,
813 creds);
814 if (!NT_STATUS_IS_OK(nt_status)) {
815 ZERO_STRUCTP(r->out.return_credentials);
816 return nt_status;
819 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
820 "objectSid", 0);
822 return NT_STATUS_OK;
826 * Log a netr_ServerAuthenticate3 request, and then invoke
827 * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
829 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
830 struct dcesrv_call_state *dce_call,
831 TALLOC_CTX *mem_ctx,
832 struct netr_ServerAuthenticate3 *r)
834 NTSTATUS status;
835 struct dom_sid *sid = NULL;
836 const char *trust_account_for_search = NULL;
837 const char *trust_account_in_db = NULL;
838 struct imessaging_context *imsg_ctx =
839 dcesrv_imessaging_context(dce_call->conn);
840 struct auth_usersupplied_info ui = {
841 .local_host = dce_call->conn->local_address,
842 .remote_host = dce_call->conn->remote_address,
843 .client = {
844 .account_name = r->in.account_name,
845 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
847 .service_description = "NETLOGON",
848 .auth_description = "ServerAuthenticate",
849 .netlogon_trust_account = {
850 .computer_name = r->in.computer_name,
851 .negotiate_flags = *r->in.negotiate_flags,
852 .secure_channel_type = r->in.secure_channel_type,
856 status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
857 mem_ctx,
859 &trust_account_for_search,
860 &trust_account_in_db,
861 &sid);
862 ui.netlogon_trust_account.sid = sid;
863 ui.netlogon_trust_account.account_name = trust_account_in_db;
864 ui.mapped.account_name = trust_account_for_search;
865 log_authentication_event(
866 imsg_ctx,
867 dce_call->conn->dce_ctx->lp_ctx,
868 NULL,
869 &ui,
870 status,
871 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
872 trust_account_in_db,
873 sid,
874 NULL /* client_audit_info */,
875 NULL /* server_audit_info */);
877 return status;
879 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
880 struct netr_ServerAuthenticate *r)
882 struct netr_ServerAuthenticate3 a;
883 uint32_t rid;
884 /* TODO:
885 * negotiate_flags is used as an [in] parameter
886 * so it need to be initialised.
888 * (I think ... = 0; seems wrong here --metze)
890 uint32_t negotiate_flags_in = 0;
891 uint32_t negotiate_flags_out = 0;
893 a.in.server_name = r->in.server_name;
894 a.in.account_name = r->in.account_name;
895 a.in.secure_channel_type = r->in.secure_channel_type;
896 a.in.computer_name = r->in.computer_name;
897 a.in.credentials = r->in.credentials;
898 a.in.negotiate_flags = &negotiate_flags_in;
900 a.out.return_credentials = r->out.return_credentials;
901 a.out.rid = &rid;
902 a.out.negotiate_flags = &negotiate_flags_out;
904 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
907 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
908 struct netr_ServerAuthenticate2 *r)
910 struct netr_ServerAuthenticate3 r3;
911 uint32_t rid = 0;
913 r3.in.server_name = r->in.server_name;
914 r3.in.account_name = r->in.account_name;
915 r3.in.secure_channel_type = r->in.secure_channel_type;
916 r3.in.computer_name = r->in.computer_name;
917 r3.in.credentials = r->in.credentials;
918 r3.out.return_credentials = r->out.return_credentials;
919 r3.in.negotiate_flags = r->in.negotiate_flags;
920 r3.out.negotiate_flags = r->out.negotiate_flags;
921 r3.out.rid = &rid;
923 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
927 Change the machine account password for the currently connected
928 client. Supplies only the NT#.
931 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
932 struct netr_ServerPasswordSet *r)
934 struct netlogon_creds_CredentialState *creds;
935 struct ldb_context *sam_ctx;
936 NTSTATUS nt_status;
938 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
939 mem_ctx,
940 r->in.computer_name,
941 r->in.credential, r->out.return_authenticator,
942 &creds);
943 NT_STATUS_NOT_OK_RETURN(nt_status);
945 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
946 if (sam_ctx == NULL) {
947 return NT_STATUS_INVALID_SYSTEM_SERVICE;
950 nt_status = netlogon_creds_des_decrypt(creds, r->in.new_password);
951 NT_STATUS_NOT_OK_RETURN(nt_status);
953 /* Using the sid for the account as the key, set the password */
954 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
955 creds->sid,
956 NULL, /* Don't have version */
957 NULL, /* Don't have plaintext */
958 r->in.new_password,
959 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
960 NULL, NULL);
961 return nt_status;
965 Change the machine account password for the currently connected
966 client. Supplies new plaintext.
968 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
969 struct netr_ServerPasswordSet2 *r)
971 struct netlogon_creds_CredentialState *creds;
972 struct ldb_context *sam_ctx;
973 struct NL_PASSWORD_VERSION version = {};
974 const uint32_t *new_version = NULL;
975 NTSTATUS nt_status;
976 DATA_BLOB new_password = data_blob_null;
977 size_t confounder_len;
978 DATA_BLOB dec_blob = data_blob_null;
979 DATA_BLOB enc_blob = data_blob_null;
980 struct samr_CryptPassword password_buf;
982 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
983 mem_ctx,
984 r->in.computer_name,
985 r->in.credential, r->out.return_authenticator,
986 &creds);
987 NT_STATUS_NOT_OK_RETURN(nt_status);
989 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
990 if (sam_ctx == NULL) {
991 return NT_STATUS_INVALID_SYSTEM_SERVICE;
994 memcpy(password_buf.data, r->in.new_password->data, 512);
995 SIVAL(password_buf.data, 512, r->in.new_password->length);
997 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
998 nt_status = netlogon_creds_aes_decrypt(creds,
999 password_buf.data,
1000 516);
1001 } else {
1002 nt_status = netlogon_creds_arcfour_crypt(creds,
1003 password_buf.data,
1004 516);
1007 if (!NT_STATUS_IS_OK(nt_status)) {
1008 return nt_status;
1011 switch (creds->secure_channel_type) {
1012 case SEC_CHAN_DOMAIN:
1013 case SEC_CHAN_DNS_DOMAIN: {
1014 uint32_t len = IVAL(password_buf.data, 512);
1015 if (len <= 500) {
1016 uint32_t ofs = 500 - len;
1017 uint8_t *p;
1019 p = password_buf.data + ofs;
1021 version.ReservedField = IVAL(p, 0);
1022 version.PasswordVersionNumber = IVAL(p, 4);
1023 version.PasswordVersionPresent = IVAL(p, 8);
1025 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
1026 new_version = &version.PasswordVersionNumber;
1029 break;
1030 default:
1031 break;
1034 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
1035 DEBUG(3,("samr: failed to decode password buffer\n"));
1036 return NT_STATUS_WRONG_PASSWORD;
1040 * Make sure the length field was encrypted,
1041 * otherwise we are under attack.
1043 if (new_password.length == r->in.new_password->length) {
1044 DBG_WARNING("Length[%zu] field not encrypted\n",
1045 new_password.length);
1046 return NT_STATUS_WRONG_PASSWORD;
1050 * We don't allow empty passwords for machine accounts.
1052 if (new_password.length < 2) {
1053 DBG_WARNING("Empty password Length[%zu]\n",
1054 new_password.length);
1055 return NT_STATUS_WRONG_PASSWORD;
1059 * Make sure the confounder part of CryptPassword
1060 * buffer was encrypted, otherwise we are under attack.
1062 confounder_len = 512 - new_password.length;
1063 enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
1064 dec_blob = data_blob_const(password_buf.data, confounder_len);
1065 if (confounder_len > 0 && data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1066 DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
1067 confounder_len);
1068 return NT_STATUS_WRONG_PASSWORD;
1072 * Check that the password part was actually encrypted,
1073 * otherwise we are under attack.
1075 enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
1076 new_password.length);
1077 dec_blob = data_blob_const(password_buf.data + confounder_len,
1078 new_password.length);
1079 if (data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1080 DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
1081 new_password.length);
1082 return NT_STATUS_WRONG_PASSWORD;
1086 * don't allow zero buffers
1088 if (all_zero(new_password.data, new_password.length)) {
1089 DBG_WARNING("Password zero buffer Length[%zu]\n",
1090 new_password.length);
1091 return NT_STATUS_WRONG_PASSWORD;
1094 /* Using the sid for the account as the key, set the password */
1095 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1096 creds->sid,
1097 new_version,
1098 &new_password, /* we have plaintext */
1099 NULL,
1100 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1101 NULL, NULL);
1102 return nt_status;
1107 netr_LogonUasLogon
1109 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1110 struct netr_LogonUasLogon *r)
1112 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1117 netr_LogonUasLogoff
1119 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1120 struct netr_LogonUasLogoff *r)
1122 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1126 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
1127 const struct netr_LogonSamLogonEx *r)
1129 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1131 switch (r->in.logon_level) {
1132 case NetlogonInteractiveInformation:
1133 case NetlogonServiceInformation:
1134 case NetlogonInteractiveTransitiveInformation:
1135 case NetlogonServiceTransitiveInformation:
1136 if (r->in.logon->password == NULL) {
1137 return NT_STATUS_INVALID_PARAMETER;
1140 switch (r->in.validation_level) {
1141 case NetlogonValidationSamInfo: /* 2 */
1142 case NetlogonValidationSamInfo2: /* 3 */
1143 case NetlogonValidationSamInfo4: /* 6 */
1144 break;
1145 default:
1146 return NT_STATUS_INVALID_INFO_CLASS;
1149 break;
1150 case NetlogonNetworkInformation:
1151 case NetlogonNetworkTransitiveInformation:
1152 if (r->in.logon->network == NULL) {
1153 return NT_STATUS_INVALID_PARAMETER;
1156 switch (r->in.validation_level) {
1157 case NetlogonValidationSamInfo: /* 2 */
1158 case NetlogonValidationSamInfo2: /* 3 */
1159 case NetlogonValidationSamInfo4: /* 6 */
1160 break;
1161 default:
1162 return NT_STATUS_INVALID_INFO_CLASS;
1165 break;
1167 case NetlogonGenericInformation:
1168 if (r->in.logon->generic == NULL) {
1169 return NT_STATUS_INVALID_PARAMETER;
1172 switch (r->in.validation_level) {
1173 /* TODO: case NetlogonValidationGenericInfo: 4 */
1174 case NetlogonValidationGenericInfo2: /* 5 */
1175 break;
1176 default:
1177 return NT_STATUS_INVALID_INFO_CLASS;
1180 break;
1181 default:
1182 return NT_STATUS_INVALID_PARAMETER;
1185 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
1187 switch (r->in.validation_level) {
1188 case NetlogonValidationSamInfo4: /* 6 */
1189 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1190 return NT_STATUS_INVALID_PARAMETER;
1192 break;
1194 default:
1195 break;
1198 return NT_STATUS_OK;
1201 struct dcesrv_netr_LogonSamLogon_base_state {
1202 struct dcesrv_call_state *dce_call;
1204 TALLOC_CTX *mem_ctx;
1206 struct netlogon_creds_CredentialState *creds;
1208 struct netr_LogonSamLogonEx r;
1210 uint32_t _ignored_flags;
1212 struct {
1213 struct netr_LogonSamLogon *lsl;
1214 struct netr_LogonSamLogonWithFlags *lslwf;
1215 struct netr_LogonSamLogonEx *lslex;
1216 } _r;
1218 struct kdc_check_generic_kerberos kr;
1221 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
1222 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
1223 static void dcesrv_netr_LogonSamLogon_base_reply(
1224 struct dcesrv_netr_LogonSamLogon_base_state *state);
1227 netr_LogonSamLogon_base
1229 This version of the function allows other wrappers to say 'do not check the credentials'
1231 We can't do the traditional 'wrapping' format completely, as this
1232 function must only run under schannel
1234 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
1236 struct dcesrv_call_state *dce_call = state->dce_call;
1237 struct imessaging_context *imsg_ctx =
1238 dcesrv_imessaging_context(dce_call->conn);
1239 TALLOC_CTX *mem_ctx = state->mem_ctx;
1240 struct netr_LogonSamLogonEx *r = &state->r;
1241 struct netlogon_creds_CredentialState *creds = state->creds;
1242 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1243 const char *workgroup = lpcfg_workgroup(lp_ctx);
1244 struct auth4_context *auth_context = NULL;
1245 struct auth_usersupplied_info *user_info = NULL;
1246 NTSTATUS nt_status;
1247 struct tevent_req *subreq = NULL;
1248 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1249 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1251 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1253 switch (dce_call->pkt.u.request.opnum) {
1254 case NDR_NETR_LOGONSAMLOGON:
1255 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
1257 * These already called dcesrv_netr_check_schannel()
1258 * via dcesrv_netr_creds_server_step_check()
1260 break;
1261 case NDR_NETR_LOGONSAMLOGONEX:
1262 default:
1263 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1264 return NT_STATUS_ACCESS_DENIED;
1267 nt_status = dcesrv_netr_check_schannel(dce_call,
1268 creds,
1269 auth_type,
1270 auth_level,
1271 dce_call->pkt.u.request.opnum);
1272 if (!NT_STATUS_IS_OK(nt_status)) {
1273 return nt_status;
1275 break;
1278 *r->out.authoritative = 1;
1280 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
1282 * Currently we're always the forest root ourself.
1284 return NT_STATUS_NO_SUCH_USER;
1287 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
1289 * Currently we don't support trusts correctly yet.
1291 return NT_STATUS_NO_SUCH_USER;
1294 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1295 NT_STATUS_HAVE_NO_MEMORY(user_info);
1297 user_info->service_description = "SamLogon";
1299 nt_status = netlogon_creds_decrypt_samlogon_logon(creds,
1300 r->in.logon_level,
1301 r->in.logon);
1302 NT_STATUS_NOT_OK_RETURN(nt_status);
1304 switch (r->in.logon_level) {
1305 case NetlogonInteractiveInformation:
1306 case NetlogonServiceInformation:
1307 case NetlogonInteractiveTransitiveInformation:
1308 case NetlogonServiceTransitiveInformation:
1309 case NetlogonNetworkInformation:
1310 case NetlogonNetworkTransitiveInformation:
1312 nt_status = auth_context_create_for_netlogon(mem_ctx,
1313 dce_call->event_ctx,
1314 imsg_ctx,
1315 dce_call->conn->dce_ctx->lp_ctx,
1316 &auth_context);
1317 NT_STATUS_NOT_OK_RETURN(nt_status);
1319 user_info->remote_host = dce_call->conn->remote_address;
1320 user_info->local_host = dce_call->conn->local_address;
1322 user_info->netlogon_trust_account.secure_channel_type
1323 = creds->secure_channel_type;
1324 user_info->netlogon_trust_account.negotiate_flags
1325 = creds->negotiate_flags;
1328 * These two can be unrelated when the account is
1329 * actually that of a trusted domain, so we want to
1330 * know which DC in that trusted domain contacted
1331 * us
1333 user_info->netlogon_trust_account.computer_name
1334 = creds->computer_name;
1335 user_info->netlogon_trust_account.account_name
1336 = creds->account_name;
1337 user_info->netlogon_trust_account.sid
1338 = creds->sid;
1340 break;
1341 default:
1342 /* We do not need to set up the user_info in this case */
1343 break;
1346 switch (r->in.logon_level) {
1347 case NetlogonInteractiveInformation:
1348 case NetlogonServiceInformation:
1349 case NetlogonInteractiveTransitiveInformation:
1350 case NetlogonServiceTransitiveInformation:
1351 user_info->auth_description = "interactive";
1353 user_info->logon_parameters
1354 = r->in.logon->password->identity_info.parameter_control;
1355 user_info->client.account_name
1356 = r->in.logon->password->identity_info.account_name.string;
1357 user_info->client.domain_name
1358 = r->in.logon->password->identity_info.domain_name.string;
1359 user_info->workstation_name
1360 = r->in.logon->password->identity_info.workstation.string;
1361 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1362 user_info->password_state = AUTH_PASSWORD_HASH;
1364 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1365 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1366 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1368 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1369 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1370 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1372 user_info->logon_id
1373 = r->in.logon->password->identity_info.logon_id;
1375 break;
1376 case NetlogonNetworkInformation:
1377 case NetlogonNetworkTransitiveInformation:
1378 user_info->auth_description = "network";
1380 nt_status = auth_context_set_challenge(
1381 auth_context,
1382 r->in.logon->network->challenge,
1383 "netr_LogonSamLogonWithFlags");
1384 NT_STATUS_NOT_OK_RETURN(nt_status);
1386 user_info->logon_parameters
1387 = r->in.logon->network->identity_info.parameter_control;
1388 user_info->client.account_name
1389 = r->in.logon->network->identity_info.account_name.string;
1390 user_info->client.domain_name
1391 = r->in.logon->network->identity_info.domain_name.string;
1392 user_info->workstation_name
1393 = r->in.logon->network->identity_info.workstation.string;
1395 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1396 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1397 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1399 user_info->logon_id
1400 = r->in.logon->network->identity_info.logon_id;
1402 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1403 user_info->client.account_name,
1404 user_info->client.domain_name,
1405 user_info->password.response.nt,
1406 creds, workgroup);
1407 NT_STATUS_NOT_OK_RETURN(nt_status);
1409 break;
1412 case NetlogonGenericInformation:
1414 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1415 /* OK */
1416 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1417 /* OK */
1418 } else {
1419 /* Using DES to verify kerberos tickets makes no sense */
1420 return NT_STATUS_INVALID_PARAMETER;
1423 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1424 struct dcerpc_binding_handle *irpc_handle;
1425 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1426 NT_STATUS_HAVE_NO_MEMORY(generic);
1428 r->out.validation->generic = generic;
1430 user_info->logon_id
1431 = r->in.logon->generic->identity_info.logon_id;
1433 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1434 imsg_ctx,
1435 "kdc_server",
1436 &ndr_table_irpc);
1437 if (irpc_handle == NULL) {
1438 return NT_STATUS_NO_LOGON_SERVERS;
1441 state->kr.in.generic_request =
1442 data_blob_const(r->in.logon->generic->data,
1443 r->in.logon->generic->length);
1446 * 60 seconds should be enough
1448 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1449 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1450 state->dce_call->event_ctx,
1451 irpc_handle, &state->kr);
1452 if (subreq == NULL) {
1453 return NT_STATUS_NO_MEMORY;
1455 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1456 tevent_req_set_callback(subreq,
1457 dcesrv_netr_LogonSamLogon_base_krb5_done,
1458 state);
1459 return NT_STATUS_OK;
1462 /* Until we get an implementation of these other packages */
1463 return NT_STATUS_INVALID_PARAMETER;
1465 default:
1466 return NT_STATUS_INVALID_PARAMETER;
1469 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1470 auth_context, user_info);
1471 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1472 tevent_req_set_callback(subreq,
1473 dcesrv_netr_LogonSamLogon_base_auth_done,
1474 state);
1475 return NT_STATUS_OK;
1478 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1480 struct dcesrv_netr_LogonSamLogon_base_state *state =
1481 tevent_req_callback_data(subreq,
1482 struct dcesrv_netr_LogonSamLogon_base_state);
1483 TALLOC_CTX *mem_ctx = state->mem_ctx;
1484 struct netr_LogonSamLogonEx *r = &state->r;
1485 struct auth_user_info_dc *user_info_dc = NULL;
1486 struct netr_SamInfo2 *sam2 = NULL;
1487 struct netr_SamInfo3 *sam3 = NULL;
1488 struct netr_SamInfo6 *sam6 = NULL;
1489 NTSTATUS nt_status;
1491 nt_status = auth_check_password_recv(subreq, mem_ctx,
1492 &user_info_dc,
1493 r->out.authoritative);
1494 TALLOC_FREE(subreq);
1495 if (!NT_STATUS_IS_OK(nt_status)) {
1496 r->out.result = nt_status;
1497 dcesrv_netr_LogonSamLogon_base_reply(state);
1498 return;
1501 switch (r->in.validation_level) {
1502 case 2:
1503 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1504 user_info_dc,
1505 AUTH_INCLUDE_RESOURCE_GROUPS,
1506 &sam2);
1507 if (!NT_STATUS_IS_OK(nt_status)) {
1508 r->out.result = nt_status;
1509 dcesrv_netr_LogonSamLogon_base_reply(state);
1510 return;
1513 r->out.validation->sam2 = sam2;
1514 break;
1516 case 3:
1517 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1518 user_info_dc,
1519 AUTH_INCLUDE_RESOURCE_GROUPS,
1520 &sam3, NULL);
1521 if (!NT_STATUS_IS_OK(nt_status)) {
1522 r->out.result = nt_status;
1523 dcesrv_netr_LogonSamLogon_base_reply(state);
1524 return;
1527 r->out.validation->sam3 = sam3;
1528 break;
1530 case 6:
1531 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1532 user_info_dc,
1533 AUTH_INCLUDE_RESOURCE_GROUPS,
1534 &sam6, NULL);
1535 if (!NT_STATUS_IS_OK(nt_status)) {
1536 r->out.result = nt_status;
1537 dcesrv_netr_LogonSamLogon_base_reply(state);
1538 return;
1541 r->out.validation->sam6 = sam6;
1542 break;
1544 default:
1545 if (!NT_STATUS_IS_OK(nt_status)) {
1546 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1547 dcesrv_netr_LogonSamLogon_base_reply(state);
1548 return;
1552 /* TODO: Describe and deal with these flags */
1553 *r->out.flags = 0;
1555 r->out.result = NT_STATUS_OK;
1557 dcesrv_netr_LogonSamLogon_base_reply(state);
1560 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1562 struct dcesrv_netr_LogonSamLogon_base_state *state =
1563 tevent_req_callback_data(subreq,
1564 struct dcesrv_netr_LogonSamLogon_base_state);
1565 TALLOC_CTX *mem_ctx = state->mem_ctx;
1566 struct netr_LogonSamLogonEx *r = &state->r;
1567 struct netr_GenericInfo2 *generic = NULL;
1568 NTSTATUS status;
1570 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1571 TALLOC_FREE(subreq);
1572 if (!NT_STATUS_IS_OK(status)) {
1573 r->out.result = status;
1574 dcesrv_netr_LogonSamLogon_base_reply(state);
1575 return;
1578 generic = r->out.validation->generic;
1579 generic->length = state->kr.out.generic_reply.length;
1580 generic->data = state->kr.out.generic_reply.data;
1582 /* TODO: Describe and deal with these flags */
1583 *r->out.flags = 0;
1585 r->out.result = NT_STATUS_OK;
1587 dcesrv_netr_LogonSamLogon_base_reply(state);
1590 static void dcesrv_netr_LogonSamLogon_base_reply(
1591 struct dcesrv_netr_LogonSamLogon_base_state *state)
1593 struct netr_LogonSamLogonEx *r = &state->r;
1594 NTSTATUS status;
1596 if (NT_STATUS_IS_OK(r->out.result)) {
1597 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
1598 r->in.validation_level,
1599 r->out.validation);
1600 if (!NT_STATUS_IS_OK(status)) {
1601 DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
1602 "failed - %s\n",
1603 nt_errstr(status));
1607 if (state->_r.lslex != NULL) {
1608 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1609 _r->out.result = r->out.result;
1610 } else if (state->_r.lslwf != NULL) {
1611 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1612 _r->out.result = r->out.result;
1613 } else if (state->_r.lsl != NULL) {
1614 struct netr_LogonSamLogon *_r = state->_r.lsl;
1615 _r->out.result = r->out.result;
1618 dcesrv_async_reply(state->dce_call);
1621 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1622 struct netr_LogonSamLogonEx *r)
1624 struct dcesrv_netr_LogonSamLogon_base_state *state;
1625 NTSTATUS nt_status;
1627 *r->out.authoritative = 1;
1629 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1630 if (state == NULL) {
1631 return NT_STATUS_NO_MEMORY;
1634 state->dce_call = dce_call;
1635 state->mem_ctx = mem_ctx;
1637 state->r.in.server_name = r->in.server_name;
1638 state->r.in.computer_name = r->in.computer_name;
1639 state->r.in.logon_level = r->in.logon_level;
1640 state->r.in.logon = r->in.logon;
1641 state->r.in.validation_level = r->in.validation_level;
1642 state->r.in.flags = r->in.flags;
1643 state->r.out.validation = r->out.validation;
1644 state->r.out.authoritative = r->out.authoritative;
1645 state->r.out.flags = r->out.flags;
1647 state->_r.lslex = r;
1649 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1650 if (!NT_STATUS_IS_OK(nt_status)) {
1651 return nt_status;
1654 nt_status = schannel_get_creds_state(mem_ctx,
1655 dce_call->conn->dce_ctx->lp_ctx,
1656 r->in.computer_name, &state->creds);
1657 if (!NT_STATUS_IS_OK(nt_status)) {
1658 return nt_status;
1661 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1663 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1664 return nt_status;
1667 return nt_status;
1671 netr_LogonSamLogonWithFlags
1674 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1675 struct netr_LogonSamLogonWithFlags *r)
1677 struct dcesrv_netr_LogonSamLogon_base_state *state;
1678 NTSTATUS nt_status;
1680 *r->out.authoritative = 1;
1682 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1683 if (state == NULL) {
1684 return NT_STATUS_NO_MEMORY;
1687 state->dce_call = dce_call;
1688 state->mem_ctx = mem_ctx;
1690 state->r.in.server_name = r->in.server_name;
1691 state->r.in.computer_name = r->in.computer_name;
1692 state->r.in.logon_level = r->in.logon_level;
1693 state->r.in.logon = r->in.logon;
1694 state->r.in.validation_level = r->in.validation_level;
1695 state->r.in.flags = r->in.flags;
1696 state->r.out.validation = r->out.validation;
1697 state->r.out.authoritative = r->out.authoritative;
1698 state->r.out.flags = r->out.flags;
1700 state->_r.lslwf = r;
1702 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1703 if (!NT_STATUS_IS_OK(nt_status)) {
1704 return nt_status;
1707 r->out.return_authenticator = talloc_zero(mem_ctx,
1708 struct netr_Authenticator);
1709 if (r->out.return_authenticator == NULL) {
1710 return NT_STATUS_NO_MEMORY;
1713 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1714 mem_ctx,
1715 r->in.computer_name,
1716 r->in.credential,
1717 r->out.return_authenticator,
1718 &state->creds);
1719 if (!NT_STATUS_IS_OK(nt_status)) {
1720 return nt_status;
1723 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1725 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1726 return nt_status;
1729 return nt_status;
1733 netr_LogonSamLogon
1735 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1736 struct netr_LogonSamLogon *r)
1738 struct dcesrv_netr_LogonSamLogon_base_state *state;
1739 NTSTATUS nt_status;
1741 *r->out.authoritative = 1;
1743 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1744 if (state == NULL) {
1745 return NT_STATUS_NO_MEMORY;
1748 state->dce_call = dce_call;
1749 state->mem_ctx = mem_ctx;
1751 state->r.in.server_name = r->in.server_name;
1752 state->r.in.computer_name = r->in.computer_name;
1753 state->r.in.logon_level = r->in.logon_level;
1754 state->r.in.logon = r->in.logon;
1755 state->r.in.validation_level = r->in.validation_level;
1756 state->r.in.flags = &state->_ignored_flags;
1757 state->r.out.validation = r->out.validation;
1758 state->r.out.authoritative = r->out.authoritative;
1759 state->r.out.flags = &state->_ignored_flags;
1761 state->_r.lsl = r;
1763 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1764 if (!NT_STATUS_IS_OK(nt_status)) {
1765 return nt_status;
1768 r->out.return_authenticator = talloc_zero(mem_ctx,
1769 struct netr_Authenticator);
1770 if (r->out.return_authenticator == NULL) {
1771 return NT_STATUS_NO_MEMORY;
1774 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1775 mem_ctx,
1776 r->in.computer_name,
1777 r->in.credential,
1778 r->out.return_authenticator,
1779 &state->creds);
1780 if (!NT_STATUS_IS_OK(nt_status)) {
1781 return nt_status;
1784 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1786 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1787 return nt_status;
1790 return nt_status;
1795 netr_LogonSamLogoff
1797 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1798 struct netr_LogonSamLogoff *r)
1800 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1806 netr_DatabaseDeltas
1808 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1809 struct netr_DatabaseDeltas *r)
1811 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1816 netr_DatabaseSync2
1818 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1819 struct netr_DatabaseSync2 *r)
1821 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1822 return NT_STATUS_NOT_IMPLEMENTED;
1827 netr_DatabaseSync
1829 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1830 struct netr_DatabaseSync *r)
1832 struct netr_DatabaseSync2 r2;
1833 NTSTATUS status;
1835 ZERO_STRUCT(r2);
1837 r2.in.logon_server = r->in.logon_server;
1838 r2.in.computername = r->in.computername;
1839 r2.in.credential = r->in.credential;
1840 r2.in.database_id = r->in.database_id;
1841 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1842 r2.in.sync_context = r->in.sync_context;
1843 r2.out.sync_context = r->out.sync_context;
1844 r2.out.delta_enum_array = r->out.delta_enum_array;
1845 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1847 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1849 return status;
1854 netr_AccountDeltas
1856 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1857 struct netr_AccountDeltas *r)
1859 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1860 return NT_STATUS_NOT_IMPLEMENTED;
1865 netr_AccountSync
1867 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1868 struct netr_AccountSync *r)
1870 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1871 return NT_STATUS_NOT_IMPLEMENTED;
1876 netr_GetDcName
1878 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1879 struct netr_GetDcName *r)
1881 const char * const attrs[] = { NULL };
1882 struct ldb_context *sam_ctx;
1883 struct ldb_message **res;
1884 struct ldb_dn *domain_dn;
1885 int ret;
1886 const char *dcname;
1889 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1890 * that the domainname needs to be a valid netbios domain
1891 * name, if it is not NULL.
1893 if (r->in.domainname) {
1894 const char *dot = strchr(r->in.domainname, '.');
1895 size_t len = strlen(r->in.domainname);
1897 if (dot || len > 15) {
1898 return WERR_NERR_DCNOTFOUND;
1902 * TODO: Should we also verify that only valid
1903 * netbios name characters are used?
1907 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
1908 if (sam_ctx == NULL) {
1909 return WERR_DS_UNAVAILABLE;
1912 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1913 r->in.domainname);
1914 if (domain_dn == NULL) {
1915 return WERR_NO_SUCH_DOMAIN;
1918 ret = gendb_search_dn(sam_ctx, mem_ctx,
1919 domain_dn, &res, attrs);
1920 if (ret != 1) {
1921 return WERR_NO_SUCH_DOMAIN;
1924 /* TODO: - return real IP address
1925 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1927 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1928 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1929 W_ERROR_HAVE_NO_MEMORY(dcname);
1931 *r->out.dcname = dcname;
1932 return WERR_OK;
1935 struct dcesrv_netr_LogonControl_base_state {
1936 struct dcesrv_call_state *dce_call;
1938 TALLOC_CTX *mem_ctx;
1940 struct netr_LogonControl2Ex r;
1942 struct {
1943 struct netr_LogonControl *l;
1944 struct netr_LogonControl2 *l2;
1945 struct netr_LogonControl2Ex *l2ex;
1946 } _r;
1949 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1951 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1953 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1954 struct auth_session_info *session_info =
1955 dcesrv_call_session_info(state->dce_call);
1956 struct imessaging_context *imsg_ctx =
1957 dcesrv_imessaging_context(state->dce_call->conn);
1958 enum security_user_level security_level;
1959 struct dcerpc_binding_handle *irpc_handle;
1960 struct tevent_req *subreq;
1961 bool ok;
1963 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1965 if (state->_r.l != NULL) {
1967 * netr_LogonControl
1969 if (state->r.in.level == 0x00000002) {
1970 return WERR_NOT_SUPPORTED;
1971 } else if (state->r.in.level != 0x00000001) {
1972 return WERR_INVALID_LEVEL;
1975 switch (state->r.in.function_code) {
1976 case NETLOGON_CONTROL_QUERY:
1977 case NETLOGON_CONTROL_REPLICATE:
1978 case NETLOGON_CONTROL_SYNCHRONIZE:
1979 case NETLOGON_CONTROL_PDC_REPLICATE:
1980 case NETLOGON_CONTROL_BREAKPOINT:
1981 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1982 case NETLOGON_CONTROL_TRUNCATE_LOG:
1983 break;
1984 default:
1985 return WERR_NOT_SUPPORTED;
1989 if (state->r.in.level < 0x00000001) {
1990 return WERR_INVALID_LEVEL;
1993 if (state->r.in.level > 0x00000004) {
1994 return WERR_INVALID_LEVEL;
1997 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1998 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1999 struct netr_NETLOGON_INFO_3 *info3 = NULL;
2001 switch (state->r.in.level) {
2002 case 0x00000001:
2003 info1 = talloc_zero(state->mem_ctx,
2004 struct netr_NETLOGON_INFO_1);
2005 if (info1 == NULL) {
2006 return WERR_NOT_ENOUGH_MEMORY;
2008 state->r.out.query->info1 = info1;
2009 return WERR_OK;
2011 case 0x00000003:
2012 info3 = talloc_zero(state->mem_ctx,
2013 struct netr_NETLOGON_INFO_3);
2014 if (info3 == NULL) {
2015 return WERR_NOT_ENOUGH_MEMORY;
2017 state->r.out.query->info3 = info3;
2018 return WERR_OK;
2020 default:
2021 return WERR_INVALID_PARAMETER;
2026 * Some validations are done before the access check
2027 * and some after the access check
2029 security_level = security_session_user_level(session_info, NULL);
2030 if (security_level < SECURITY_ADMINISTRATOR) {
2031 return WERR_ACCESS_DENIED;
2034 if (state->_r.l2 != NULL) {
2036 * netr_LogonControl2
2038 if (state->r.in.level == 0x00000004) {
2039 return WERR_INVALID_LEVEL;
2043 switch (state->r.in.level) {
2044 case 0x00000001:
2045 break;
2047 case 0x00000002:
2048 switch (state->r.in.function_code) {
2049 case NETLOGON_CONTROL_REDISCOVER:
2050 case NETLOGON_CONTROL_TC_QUERY:
2051 case NETLOGON_CONTROL_TC_VERIFY:
2052 break;
2053 default:
2054 return WERR_INVALID_PARAMETER;
2057 break;
2059 case 0x00000003:
2060 break;
2062 case 0x00000004:
2063 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
2064 return WERR_INVALID_PARAMETER;
2067 break;
2069 default:
2070 return WERR_INVALID_LEVEL;
2073 switch (state->r.in.function_code) {
2074 case NETLOGON_CONTROL_REDISCOVER:
2075 case NETLOGON_CONTROL_TC_QUERY:
2076 case NETLOGON_CONTROL_TC_VERIFY:
2077 if (state->r.in.level != 2) {
2078 return WERR_INVALID_PARAMETER;
2081 if (state->r.in.data == NULL) {
2082 return WERR_INVALID_PARAMETER;
2085 if (state->r.in.data->domain == NULL) {
2086 return WERR_INVALID_PARAMETER;
2089 break;
2091 case NETLOGON_CONTROL_CHANGE_PASSWORD:
2092 if (state->r.in.level != 1) {
2093 return WERR_INVALID_PARAMETER;
2096 if (state->r.in.data == NULL) {
2097 return WERR_INVALID_PARAMETER;
2100 if (state->r.in.data->domain == NULL) {
2101 return WERR_INVALID_PARAMETER;
2104 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
2105 state->r.in.data->domain);
2106 if (!ok) {
2107 struct ldb_context *sam_ctx;
2109 sam_ctx = dcesrv_samdb_connect_as_system(state,
2110 state->dce_call);
2111 if (sam_ctx == NULL) {
2112 return WERR_DS_UNAVAILABLE;
2116 * Secrets for trusted domains can only be triggered on
2117 * the PDC.
2119 ok = samdb_is_pdc(sam_ctx);
2120 TALLOC_FREE(sam_ctx);
2121 if (!ok) {
2122 return WERR_INVALID_DOMAIN_ROLE;
2126 break;
2127 default:
2128 return WERR_NOT_SUPPORTED;
2131 irpc_handle = irpc_binding_handle_by_name(state,
2132 imsg_ctx,
2133 "winbind_server",
2134 &ndr_table_winbind);
2135 if (irpc_handle == NULL) {
2136 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2137 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2138 return WERR_SERVICE_NOT_FOUND;
2142 * 60 seconds timeout should be enough
2144 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2146 subreq = dcerpc_winbind_LogonControl_send(state,
2147 state->dce_call->event_ctx,
2148 irpc_handle,
2149 state->r.in.function_code,
2150 state->r.in.level,
2151 state->r.in.data,
2152 state->r.out.query);
2153 if (subreq == NULL) {
2154 return WERR_NOT_ENOUGH_MEMORY;
2156 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2157 tevent_req_set_callback(subreq,
2158 dcesrv_netr_LogonControl_base_done,
2159 state);
2161 return WERR_OK;
2164 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
2166 struct dcesrv_netr_LogonControl_base_state *state =
2167 tevent_req_callback_data(subreq,
2168 struct dcesrv_netr_LogonControl_base_state);
2169 NTSTATUS status;
2171 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
2172 &state->r.out.result);
2173 TALLOC_FREE(subreq);
2174 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
2175 state->r.out.result = WERR_TIMEOUT;
2176 } else if (!NT_STATUS_IS_OK(status)) {
2177 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2178 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
2179 nt_errstr(status)));
2182 if (state->_r.l2ex != NULL) {
2183 struct netr_LogonControl2Ex *r = state->_r.l2ex;
2184 r->out.result = state->r.out.result;
2185 } else if (state->_r.l2 != NULL) {
2186 struct netr_LogonControl2 *r = state->_r.l2;
2187 r->out.result = state->r.out.result;
2188 } else if (state->_r.l != NULL) {
2189 struct netr_LogonControl *r = state->_r.l;
2190 r->out.result = state->r.out.result;
2193 dcesrv_async_reply(state->dce_call);
2197 netr_LogonControl
2199 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2200 struct netr_LogonControl *r)
2202 struct dcesrv_netr_LogonControl_base_state *state;
2203 WERROR werr;
2205 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2206 if (state == NULL) {
2207 return WERR_NOT_ENOUGH_MEMORY;
2210 state->dce_call = dce_call;
2211 state->mem_ctx = mem_ctx;
2213 state->r.in.logon_server = r->in.logon_server;
2214 state->r.in.function_code = r->in.function_code;
2215 state->r.in.level = r->in.level;
2216 state->r.in.data = NULL;
2217 state->r.out.query = r->out.query;
2219 state->_r.l = r;
2221 werr = dcesrv_netr_LogonControl_base_call(state);
2223 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2224 return werr;
2227 return werr;
2231 netr_LogonControl2
2233 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2234 struct netr_LogonControl2 *r)
2236 struct dcesrv_netr_LogonControl_base_state *state;
2237 WERROR werr;
2239 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2240 if (state == NULL) {
2241 return WERR_NOT_ENOUGH_MEMORY;
2244 state->dce_call = dce_call;
2245 state->mem_ctx = mem_ctx;
2247 state->r.in.logon_server = r->in.logon_server;
2248 state->r.in.function_code = r->in.function_code;
2249 state->r.in.level = r->in.level;
2250 state->r.in.data = r->in.data;
2251 state->r.out.query = r->out.query;
2253 state->_r.l2 = r;
2255 werr = dcesrv_netr_LogonControl_base_call(state);
2257 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2258 return werr;
2261 return werr;
2265 netr_LogonControl2Ex
2267 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2268 struct netr_LogonControl2Ex *r)
2270 struct dcesrv_netr_LogonControl_base_state *state;
2271 WERROR werr;
2273 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2274 if (state == NULL) {
2275 return WERR_NOT_ENOUGH_MEMORY;
2278 state->dce_call = dce_call;
2279 state->mem_ctx = mem_ctx;
2281 state->r = *r;
2282 state->_r.l2ex = r;
2284 werr = dcesrv_netr_LogonControl_base_call(state);
2286 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2287 return werr;
2290 return werr;
2293 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2294 struct ldb_context *sam_ctx,
2295 struct netr_DomainTrustList *trusts,
2296 uint32_t trust_flags);
2299 netr_GetAnyDCName
2301 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2302 struct netr_GetAnyDCName *r)
2304 struct netr_DomainTrustList *trusts;
2305 struct ldb_context *sam_ctx;
2306 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2307 uint32_t i;
2308 WERROR werr;
2310 *r->out.dcname = NULL;
2312 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2313 /* if the domainname parameter wasn't set assume our domain */
2314 r->in.domainname = lpcfg_workgroup(lp_ctx);
2317 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2318 if (sam_ctx == NULL) {
2319 return WERR_DS_UNAVAILABLE;
2322 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2323 /* well we asked for a DC of our own domain */
2324 if (samdb_is_pdc(sam_ctx)) {
2325 /* we are the PDC of the specified domain */
2326 return WERR_NO_SUCH_DOMAIN;
2329 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2330 lpcfg_netbios_name(lp_ctx));
2331 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2333 return WERR_OK;
2336 /* Okay, now we have to consider the trusted domains */
2338 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2339 W_ERROR_HAVE_NO_MEMORY(trusts);
2341 trusts->count = 0;
2343 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2344 NETR_TRUST_FLAG_INBOUND
2345 | NETR_TRUST_FLAG_OUTBOUND);
2346 W_ERROR_NOT_OK_RETURN(werr);
2348 for (i = 0; i < trusts->count; i++) {
2349 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2350 /* FIXME: Here we need to find a DC for the specified
2351 * trusted domain. */
2353 /* return WERR_OK; */
2354 return WERR_NO_SUCH_DOMAIN;
2358 return WERR_NO_SUCH_DOMAIN;
2363 netr_DatabaseRedo
2365 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2366 struct netr_DatabaseRedo *r)
2368 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2373 netr_NetrEnumerateTrustedDomains
2375 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2376 struct netr_NetrEnumerateTrustedDomains *r)
2378 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2383 netr_LogonGetCapabilities
2385 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2386 struct netr_LogonGetCapabilities *r)
2388 struct netlogon_creds_CredentialState *creds;
2389 NTSTATUS status;
2391 switch (r->in.query_level) {
2392 case 1:
2393 break;
2394 case 2:
2396 * Until we know the details behind KB5028166
2397 * just return DCERPC_NCA_S_FAULT_INVALID_TAG
2398 * like an unpatched Windows Server.
2400 FALL_THROUGH;
2401 default:
2403 * There would not be a way to marshall the
2404 * the response. Which would mean our final
2405 * ndr_push would fail an we would return
2406 * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA.
2408 * But it's important to match a Windows server
2409 * especially before KB5028166, see also our bug #15418
2410 * Otherwise Windows client would stop talking to us.
2412 DCESRV_FAULT(DCERPC_NCA_S_FAULT_INVALID_TAG);
2415 status = dcesrv_netr_creds_server_step_check(dce_call,
2416 mem_ctx,
2417 r->in.computer_name,
2418 r->in.credential,
2419 r->out.return_authenticator,
2420 &creds);
2421 if (!NT_STATUS_IS_OK(status)) {
2422 DEBUG(0,(__location__ " Bad credentials - error\n"));
2424 NT_STATUS_NOT_OK_RETURN(status);
2426 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2428 return NT_STATUS_OK;
2433 netr_NETRLOGONSETSERVICEBITS
2435 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2436 struct netr_NETRLOGONSETSERVICEBITS *r)
2438 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2443 netr_LogonGetTrustRid
2445 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2446 struct netr_LogonGetTrustRid *r)
2448 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2453 netr_NETRLOGONCOMPUTESERVERDIGEST
2455 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2456 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2458 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2463 netr_NETRLOGONCOMPUTECLIENTDIGEST
2465 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2466 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2468 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2474 netr_DsRGetSiteName
2476 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2477 struct netr_DsRGetSiteName *r)
2479 struct ldb_context *sam_ctx;
2481 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2482 if (sam_ctx == NULL) {
2483 return WERR_DS_UNAVAILABLE;
2487 * We assume to be a DC when we get called over NETLOGON. Hence we
2488 * get our site name always by using "samdb_server_site_name()"
2489 * and not "samdb_client_site_name()".
2491 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2492 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2494 return WERR_OK;
2499 fill in a netr_OneDomainInfo from our own domain/forest
2501 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2502 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2503 struct GUID domain_guid,
2504 struct netr_OneDomainInfo *info,
2505 bool is_trust_list)
2507 ZERO_STRUCTP(info);
2509 if (is_trust_list) {
2510 struct netr_trust_extension *te = NULL;
2511 struct netr_trust_extension_info *tei = NULL;
2513 /* w2k8 only fills this on trusted domains */
2514 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2515 if (te == NULL) {
2516 return NT_STATUS_NO_MEMORY;
2518 tei = &te->info;
2519 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2522 * We're always within a native forest
2524 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2525 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2527 /* For now we assume we're always the tree root */
2528 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2529 tei->parent_index = 0;
2531 tei->trust_type = our_tdo->trust_type;
2533 * This needs to be 0 instead of our_tdo->trust_attributes
2534 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2535 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2537 tei->trust_attributes = 0;
2539 info->trust_extension.info = te;
2542 if (is_trust_list) {
2543 info->dns_domainname.string = our_tdo->domain_name.string;
2545 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2546 info->dns_forestname.string = NULL;
2547 } else {
2548 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2549 our_tdo->domain_name.string);
2550 if (info->dns_domainname.string == NULL) {
2551 return NT_STATUS_NO_MEMORY;
2554 info->dns_forestname.string = info->dns_domainname.string;
2557 info->domainname.string = our_tdo->netbios_name.string;
2558 info->domain_sid = our_tdo->sid;
2559 info->domain_guid = domain_guid;
2561 return NT_STATUS_OK;
2565 fill in a netr_OneDomainInfo from a trust tdo
2567 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2568 struct GUID domain_guid,
2569 const struct lsa_TrustDomainInfoInfoEx *tdo,
2570 struct netr_OneDomainInfo *info)
2572 struct netr_trust_extension *te = NULL;
2573 struct netr_trust_extension_info *tei = NULL;
2575 ZERO_STRUCTP(info);
2577 /* w2k8 only fills this on trusted domains */
2578 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2579 if (te == NULL) {
2580 return NT_STATUS_NO_MEMORY;
2582 tei = &te->info;
2584 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2585 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2587 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2588 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2590 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2591 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2595 * TODO: once we support multiple domains within our forest,
2596 * we need to fill this correct (or let the caller do it
2597 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2599 tei->parent_index = 0;
2601 tei->trust_type = tdo->trust_type;
2602 tei->trust_attributes = tdo->trust_attributes;
2604 info->trust_extension.info = te;
2606 info->domainname.string = tdo->netbios_name.string;
2607 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2608 info->dns_domainname.string = tdo->domain_name.string;
2609 } else {
2610 info->dns_domainname.string = NULL;
2612 info->domain_sid = tdo->sid;
2613 info->domain_guid = domain_guid;
2615 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2616 info->dns_forestname.string = NULL;
2618 return NT_STATUS_OK;
2622 netr_LogonGetDomainInfo
2623 this is called as part of the ADS domain logon procedure.
2625 It has an important role in convaying details about the client, such
2626 as Operating System, Version, Service Pack etc.
2628 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2629 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2631 struct netlogon_creds_CredentialState *creds;
2632 static const char *const trusts_attrs[] = {"securityIdentifier",
2633 "flatName",
2634 "trustPartner",
2635 "trustAttributes",
2636 "trustDirection",
2637 "trustType",
2638 NULL};
2639 static const char *const attrs2[] = {"sAMAccountName",
2640 "dNSHostName",
2641 "msDS-SupportedEncryptionTypes",
2642 NULL};
2643 const char *sam_account_name, *old_dns_hostname;
2644 struct ldb_context *sam_ctx;
2645 const struct GUID *our_domain_guid = NULL;
2646 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2647 struct ldb_message **res1, *new_msg;
2648 struct ldb_result *trusts_res = NULL;
2649 struct ldb_dn *workstation_dn;
2650 struct netr_DomainInformation *domain_info;
2651 struct netr_LsaPolicyInformation *lsa_policy_info;
2652 struct auth_session_info *workstation_session_info = NULL;
2653 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2654 bool update_dns_hostname = true;
2655 int ret, i;
2656 NTSTATUS status;
2658 status = dcesrv_netr_creds_server_step_check(dce_call,
2659 mem_ctx,
2660 r->in.computer_name,
2661 r->in.credential,
2662 r->out.return_authenticator,
2663 &creds);
2664 if (!NT_STATUS_IS_OK(status)) {
2665 char* local = NULL;
2666 char* remote = NULL;
2667 TALLOC_CTX *frame = talloc_stackframe();
2668 remote = tsocket_address_string(dce_call->conn->remote_address,
2669 frame);
2670 local = tsocket_address_string(dce_call->conn->local_address,
2671 frame);
2672 DBG_ERR("Bad credentials - "
2673 "computer[%s] remote[%s] local[%s]\n",
2674 log_escape(frame, r->in.computer_name),
2675 remote,
2676 local);
2677 talloc_free(frame);
2679 NT_STATUS_NOT_OK_RETURN(status);
2681 /* We want to avoid connecting as system. */
2682 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2683 if (sam_ctx == NULL) {
2684 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2687 switch (r->in.level) {
2688 case 1: /* Domain information */
2690 if (r->in.query->workstation_info == NULL) {
2691 return NT_STATUS_INVALID_PARAMETER;
2694 /* Prepares the workstation DN */
2695 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2696 dom_sid_string(mem_ctx, creds->sid));
2697 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2699 /* Get the workstation's session info from the database. */
2700 status = authsam_get_session_info_principal(mem_ctx,
2701 dce_call->conn->dce_ctx->lp_ctx,
2702 sam_ctx,
2703 NULL, /* principal */
2704 workstation_dn,
2705 0, /* session_info_flags */
2706 &workstation_session_info);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 return status;
2712 * Reconnect to samdb as the workstation, now that we have its
2713 * session info. We do this so the database update can be
2714 * attributed to the workstation account in the audit logs --
2715 * otherwise it might be incorrectly attributed to
2716 * SID_NT_ANONYMOUS.
2718 sam_ctx = dcesrv_samdb_connect_session_info(mem_ctx,
2719 dce_call,
2720 workstation_session_info,
2721 workstation_session_info);
2722 if (sam_ctx == NULL) {
2723 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2726 /* Lookup for attributes in workstation object */
2727 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2728 attrs2);
2729 if (ret != 1) {
2730 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2733 /* Gets the sam account name which is checked against the DNS
2734 * hostname parameter. */
2735 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2736 "sAMAccountName",
2737 NULL);
2738 if (sam_account_name == NULL) {
2739 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2742 if (r->in.query->workstation_info->dns_hostname == NULL) {
2743 update_dns_hostname = false;
2746 /* Gets the old DNS hostname */
2747 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2748 "dNSHostName",
2749 NULL);
2752 * Updates the DNS hostname when the client wishes that the
2753 * server should handle this for him
2754 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
2755 * See MS-NRPC section 3.5.4.3.9
2757 if ((r->in.query->workstation_info->workstation_flags
2758 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2759 update_dns_hostname = false;
2762 /* Gets host information and put them into our directory */
2764 new_msg = ldb_msg_new(mem_ctx);
2765 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2767 new_msg->dn = workstation_dn;
2769 /* Sets the OS name */
2771 if (r->in.query->workstation_info->os_name.string == NULL) {
2772 return NT_STATUS_INVALID_PARAMETER;
2775 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2776 r->in.query->workstation_info->os_name.string);
2777 if (ret != LDB_SUCCESS) {
2778 return NT_STATUS_NO_MEMORY;
2782 * Sets information from "os_version". On an empty structure
2783 * the values are cleared.
2785 if (r->in.query->workstation_info->os_version.os != NULL) {
2786 struct netr_OsVersionInfoEx *os_version;
2787 const char *os_version_str;
2789 os_version = &r->in.query->workstation_info->os_version.os->os;
2791 if (os_version->CSDVersion == NULL) {
2792 return NT_STATUS_INVALID_PARAMETER;
2795 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2796 os_version->MajorVersion,
2797 os_version->MinorVersion,
2798 os_version->BuildNumber);
2799 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2801 if (strlen(os_version->CSDVersion) != 0) {
2802 ret = ldb_msg_add_string(new_msg,
2803 "operatingSystemServicePack",
2804 os_version->CSDVersion);
2805 } else {
2806 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2807 "operatingSystemServicePack");
2809 if (ret != LDB_SUCCESS) {
2810 return NT_STATUS_NO_MEMORY;
2813 ret = ldb_msg_add_string(new_msg,
2814 "operatingSystemVersion",
2815 os_version_str);
2816 if (ret != LDB_SUCCESS) {
2817 return NT_STATUS_NO_MEMORY;
2819 } else {
2820 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2821 "operatingSystemServicePack");
2822 if (ret != LDB_SUCCESS) {
2823 return NT_STATUS_NO_MEMORY;
2826 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2827 "operatingSystemVersion");
2828 if (ret != LDB_SUCCESS) {
2829 return NT_STATUS_NO_MEMORY;
2834 * If the boolean "update_dns_hostname" remained true, then we
2835 * are fine to start the update.
2837 if (update_dns_hostname) {
2838 ret = ldb_msg_add_string(new_msg,
2839 "dNSHostname",
2840 r->in.query->workstation_info->dns_hostname);
2841 if (ret != LDB_SUCCESS) {
2842 return NT_STATUS_NO_MEMORY;
2845 /* This manual "servicePrincipalName" generation is
2846 * still needed! Since the update in the samldb LDB
2847 * module does only work if the entries already exist
2848 * which isn't always the case. */
2849 ret = ldb_msg_add_string(new_msg,
2850 "servicePrincipalName",
2851 talloc_asprintf(new_msg, "HOST/%s",
2852 r->in.computer_name));
2853 if (ret != LDB_SUCCESS) {
2854 return NT_STATUS_NO_MEMORY;
2857 ret = ldb_msg_add_string(new_msg,
2858 "servicePrincipalName",
2859 talloc_asprintf(new_msg, "HOST/%s",
2860 r->in.query->workstation_info->dns_hostname));
2861 if (ret != LDB_SUCCESS) {
2862 return NT_STATUS_NO_MEMORY;
2866 if (dsdb_replace(sam_ctx, new_msg, DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) != LDB_SUCCESS) {
2867 DEBUG(3,("Impossible to update samdb: %s\n",
2868 ldb_errstring(sam_ctx)));
2871 talloc_free(new_msg);
2873 /* Writes back the domain information */
2875 our_domain_guid = samdb_domain_guid(sam_ctx);
2876 if (our_domain_guid == NULL) {
2877 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2880 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2881 if (!NT_STATUS_IS_OK(status)) {
2882 return status;
2885 status = dsdb_trust_search_tdos(sam_ctx,
2886 NULL, /* exclude */
2887 trusts_attrs,
2888 mem_ctx,
2889 &trusts_res);
2890 if (!NT_STATUS_IS_OK(status)) {
2891 return status;
2894 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2895 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2897 ZERO_STRUCTP(domain_info);
2899 /* Information about the local and trusted domains */
2901 status = fill_our_one_domain_info(mem_ctx,
2902 our_tdo,
2903 *our_domain_guid,
2904 &domain_info->primary_domain,
2905 false);
2906 if (!NT_STATUS_IS_OK(status)) {
2907 return status;
2910 domain_info->trusted_domain_count = trusts_res->count + 1;
2911 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2912 struct netr_OneDomainInfo,
2913 domain_info->trusted_domain_count);
2914 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2916 for (i=0; i < trusts_res->count; i++) {
2917 struct netr_OneDomainInfo *o =
2918 &domain_info->trusted_domains[i];
2919 /* we can't know the guid of trusts outside our forest */
2920 struct GUID trust_domain_guid = GUID_zero();
2921 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2923 status = dsdb_trust_parse_tdo_info(mem_ctx,
2924 trusts_res->msgs[i],
2925 &tdo);
2926 if (!NT_STATUS_IS_OK(status)) {
2927 return status;
2930 status = fill_trust_one_domain_info(mem_ctx,
2931 trust_domain_guid,
2932 tdo,
2934 if (!NT_STATUS_IS_OK(status)) {
2935 return status;
2939 status = fill_our_one_domain_info(mem_ctx,
2940 our_tdo,
2941 *our_domain_guid,
2942 &domain_info->trusted_domains[i],
2943 true);
2944 if (!NT_STATUS_IS_OK(status)) {
2945 return status;
2948 /* Sets the supported encryption types */
2949 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2950 "msDS-SupportedEncryptionTypes",
2951 default_supported_enc_types);
2953 /* Other host domain information */
2955 lsa_policy_info = talloc(mem_ctx,
2956 struct netr_LsaPolicyInformation);
2957 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2958 ZERO_STRUCTP(lsa_policy_info);
2960 domain_info->lsa_policy = *lsa_policy_info;
2962 /* The DNS hostname is only returned back when there is a chance
2963 * for a change. */
2964 if ((r->in.query->workstation_info->workstation_flags
2965 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2966 domain_info->dns_hostname.string = old_dns_hostname;
2967 } else {
2968 domain_info->dns_hostname.string = NULL;
2971 domain_info->workstation_flags =
2972 r->in.query->workstation_info->workstation_flags & (
2973 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2975 r->out.info->domain_info = domain_info;
2976 break;
2977 case 2: /* LSA policy information - not used at the moment */
2978 lsa_policy_info = talloc(mem_ctx,
2979 struct netr_LsaPolicyInformation);
2980 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2981 ZERO_STRUCTP(lsa_policy_info);
2983 r->out.info->lsa_policy_info = lsa_policy_info;
2984 break;
2985 default:
2986 return NT_STATUS_INVALID_LEVEL;
2987 break;
2990 return NT_STATUS_OK;
2995 netr_ServerPasswordGet
2997 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2998 struct netr_ServerPasswordGet *r)
3000 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3003 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
3004 TALLOC_CTX *mem_ctx,
3005 struct dom_sid *user_sid,
3006 struct ldb_dn *obj_dn)
3008 static const char *rodc_attrs[] = {"msDS-NeverRevealGroup",
3009 "msDS-RevealOnDemandGroup",
3010 "userAccountControl",
3011 NULL};
3012 static const char *obj_attrs[] = {"tokenGroups",
3013 "objectSid",
3014 "UserAccountControl",
3015 "msDS-KrbTgtLinkBL",
3016 NULL};
3017 struct ldb_dn *rodc_dn;
3018 int ret;
3019 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
3020 WERROR werr;
3022 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
3023 dom_sid_string(mem_ctx, user_sid));
3024 if (!ldb_dn_validate(rodc_dn)) goto denied;
3027 * do the two searches we need
3028 * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list
3029 * out of the extended DNs
3031 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
3032 DSDB_SEARCH_SHOW_EXTENDED_DN);
3033 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
3035 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
3036 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
3038 werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx,
3039 user_sid,
3040 rodc_res->msgs[0],
3041 obj_res->msgs[0]);
3043 if (W_ERROR_IS_OK(werr)) {
3044 goto allowed;
3046 denied:
3047 return false;
3048 allowed:
3049 return true;
3054 netr_NetrLogonSendToSam
3056 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3057 struct netr_NetrLogonSendToSam *r)
3059 struct netlogon_creds_CredentialState *creds;
3060 struct ldb_context *sam_ctx;
3061 NTSTATUS nt_status;
3062 DATA_BLOB decrypted_blob;
3063 enum ndr_err_code ndr_err;
3064 struct netr_SendToSamBase base_msg = { 0 };
3066 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3067 mem_ctx,
3068 r->in.computer_name,
3069 r->in.credential,
3070 r->out.return_authenticator,
3071 &creds);
3073 NT_STATUS_NOT_OK_RETURN(nt_status);
3075 switch (creds->secure_channel_type) {
3076 case SEC_CHAN_BDC:
3077 case SEC_CHAN_RODC:
3078 break;
3079 case SEC_CHAN_WKSTA:
3080 case SEC_CHAN_DNS_DOMAIN:
3081 case SEC_CHAN_DOMAIN:
3082 case SEC_CHAN_NULL:
3083 return NT_STATUS_INVALID_PARAMETER;
3084 default:
3085 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
3086 creds->secure_channel_type));
3087 return NT_STATUS_INVALID_PARAMETER;
3090 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3091 if (sam_ctx == NULL) {
3092 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3095 /* Buffer is meant to be 16-bit aligned */
3096 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3097 nt_status = netlogon_creds_aes_decrypt(creds,
3098 r->in.opaque_buffer,
3099 r->in.buffer_len);
3100 } else {
3101 nt_status = netlogon_creds_arcfour_crypt(creds,
3102 r->in.opaque_buffer,
3103 r->in.buffer_len);
3105 if (!NT_STATUS_IS_OK(nt_status)) {
3106 return nt_status;
3109 decrypted_blob.data = r->in.opaque_buffer;
3110 decrypted_blob.length = r->in.buffer_len;
3112 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
3113 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
3115 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3116 /* We only partially implement SendToSam */
3117 return NT_STATUS_NOT_IMPLEMENTED;
3120 /* Now 'send' to SAM */
3121 switch (base_msg.message_type) {
3122 case SendToSamResetBadPasswordCount:
3124 struct ldb_message *msg = ldb_msg_new(mem_ctx);
3125 struct ldb_dn *dn = NULL;
3126 int ret = 0;
3129 ret = ldb_transaction_start(sam_ctx);
3130 if (ret != LDB_SUCCESS) {
3131 return NT_STATUS_INTERNAL_ERROR;
3134 ret = dsdb_find_dn_by_guid(sam_ctx,
3135 mem_ctx,
3136 &base_msg.message.reset_bad_password.guid,
3138 &dn);
3139 if (ret != LDB_SUCCESS) {
3140 ldb_transaction_cancel(sam_ctx);
3141 return NT_STATUS_INVALID_PARAMETER;
3144 if (creds->secure_channel_type == SEC_CHAN_RODC &&
3145 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
3146 DEBUG(1, ("Client asked to reset bad password on "
3147 "an arbitrary user: %s\n",
3148 ldb_dn_get_linearized(dn)));
3149 ldb_transaction_cancel(sam_ctx);
3150 return NT_STATUS_INVALID_PARAMETER;
3153 msg->dn = dn;
3155 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
3156 if (ret != LDB_SUCCESS) {
3157 ldb_transaction_cancel(sam_ctx);
3158 return NT_STATUS_INVALID_PARAMETER;
3161 ret = dsdb_replace(sam_ctx, msg, 0);
3162 if (ret != LDB_SUCCESS) {
3163 ldb_transaction_cancel(sam_ctx);
3164 return NT_STATUS_INVALID_PARAMETER;
3167 ret = ldb_transaction_commit(sam_ctx);
3168 if (ret != LDB_SUCCESS) {
3169 ldb_transaction_cancel(sam_ctx);
3170 return NT_STATUS_INTERNAL_ERROR;
3173 break;
3175 default:
3176 return NT_STATUS_NOT_IMPLEMENTED;
3179 return NT_STATUS_OK;
3182 struct dcesrv_netr_DsRGetDCName_base_state {
3183 struct dcesrv_call_state *dce_call;
3184 TALLOC_CTX *mem_ctx;
3186 struct netr_DsRGetDCNameEx2 r;
3187 const char *client_site;
3189 struct {
3190 struct netr_DsRGetDCName *dc;
3191 struct netr_DsRGetDCNameEx *dcex;
3192 struct netr_DsRGetDCNameEx2 *dcex2;
3193 } _r;
3196 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
3198 /* Returns a nonzero value if multiple bits in 'val' are set. */
3199 static bool multiple_bits_set(uint32_t val)
3202 * Subtracting one from an integer has the effect of flipping all the
3203 * bits from the least significant bit up to and including the least
3204 * significant '1' bit. For example,
3206 * 0b101000 - 1
3207 * = 0b100111
3208 * ====
3210 * If 'val' is zero, all the bits will be flipped and thus the bitwise
3211 * AND of 'val' with 'val - 1' will be zero.
3213 * If the integer is nonzero, the least significant '1' bit will be
3214 * ANDed with a '0' bit and so will be reset in the final result, but
3215 * all other '1' bits will remain set. In other words, the effect of
3216 * this expression is to mask off the least significant bit that is
3217 * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
3218 * must contain multiple set bits.
3220 return val & (val - 1);
3223 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
3225 struct dcesrv_call_state *dce_call = state->dce_call;
3226 struct imessaging_context *imsg_ctx =
3227 dcesrv_imessaging_context(dce_call->conn);
3228 TALLOC_CTX *mem_ctx = state->mem_ctx;
3229 struct netr_DsRGetDCNameEx2 *r = &state->r;
3230 struct ldb_context *sam_ctx;
3231 struct netr_DsRGetDCNameInfo *info;
3232 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3233 const struct tsocket_address *local_address;
3234 char *local_addr = NULL;
3235 const struct tsocket_address *remote_address;
3236 char *remote_addr = NULL;
3237 const char *server_site_name;
3238 char *guid_str;
3239 struct netlogon_samlogon_response response;
3240 NTSTATUS status;
3241 const char *dc_name = NULL;
3242 const char *domain_name = NULL;
3243 const char *pdc_ip;
3244 bool different_domain = true;
3245 bool force_remote_lookup = false;
3246 uint32_t valid_flags;
3247 uint32_t this_dc_valid_flags;
3248 int dc_level;
3250 ZERO_STRUCTP(r->out.info);
3252 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3253 if (sam_ctx == NULL) {
3254 return WERR_DS_UNAVAILABLE;
3257 local_address = dcesrv_connection_get_local_address(dce_call->conn);
3258 if (tsocket_address_is_inet(local_address, "ip")) {
3259 local_addr = tsocket_address_inet_addr_string(local_address, state);
3260 W_ERROR_HAVE_NO_MEMORY(local_addr);
3263 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
3264 if (tsocket_address_is_inet(remote_address, "ip")) {
3265 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
3266 W_ERROR_HAVE_NO_MEMORY(remote_addr);
3269 /* "server_unc" is ignored by w2k3 */
3272 * With the following flags:
3273 * DS_FORCE_REDISCOVERY (Flag A)
3274 * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
3275 * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
3276 * DS_GC_SERVER_REQUIRED (Flag D)
3277 * DS_PDC_REQUIRED (Flag E)
3278 * DS_BACKGROUND_ONLY (Flag F)
3279 * DS_IP_REQUIRED (Flag G)
3280 * DS_KDC_REQUIRED (Flag H)
3281 * DS_TIMESERV_REQUIRED (Flag I)
3282 * DS_WRITABLE_REQUIRED (Flag J)
3283 * DS_GOOD_TIMESERV_PREFERRED (Flag K)
3284 * DS_AVOID_SELF (Flag L)
3285 * DS_ONLY_LDAP_NEEDED (Flag M)
3286 * DS_IS_FLAT_NAME (Flag N)
3287 * DS_IS_DNS_NAME (Flag O)
3288 * DS_TRY_NEXTCLOSEST_SITE (Flag P)
3289 * DS_DIRECTORY_SERVICE_6_REQUIRED (Flag Q)
3290 * DS_WEB_SERVICE_REQUIRED (Flag T)
3291 * DS_DIRECTORY_SERVICE_8_REQUIRED (Flag U)
3292 * DS_DIRECTORY_SERVICE_9_REQUIRED (Flag V)
3293 * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
3294 * DS_RETURN_DNS_NAME (Flag R)
3295 * DS_RETURN_FLAT_NAME (Flag S)
3297 * MS-NRPC 3.5.4.3.1 says:
3298 * ...
3299 * On receiving this call, the server MUST perform the following Flags
3300 * parameter validations:
3301 * - Flags D, E, and H MUST NOT be combined with each other.
3302 * - Flag N MUST NOT be combined with the O flag.
3303 * - Flag R MUST NOT be combined with the S flag.
3304 * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
3305 * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or H.
3306 * - Flag P MUST NOT be set when the SiteName parameter is provided.
3307 * The server MUST return ERROR_INVALID_FLAGS for any of the previously
3308 * mentioned conflicting combinations.
3309 * ...
3312 valid_flags = DSGETDC_VALID_FLAGS;
3314 if (r->in.flags & ~valid_flags) {
3316 * TODO: add tests to prove this (maybe based on the
3317 * msDS-Behavior-Version levels of dc, domain and/or forest
3319 return WERR_INVALID_FLAGS;
3322 /* Flags D, E, and H MUST NOT be combined with each other. */
3323 #define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
3324 if (multiple_bits_set(r->in.flags & _DEH)) {
3325 return WERR_INVALID_FLAGS;
3328 /* Flag N MUST NOT be combined with the O flag. */
3329 if (r->in.flags & DS_IS_FLAT_NAME &&
3330 r->in.flags & DS_IS_DNS_NAME) {
3331 return WERR_INVALID_FLAGS;
3334 /* Flag R MUST NOT be combined with the S flag. */
3335 if (r->in.flags & DS_RETURN_DNS_NAME &&
3336 r->in.flags & DS_RETURN_FLAT_NAME) {
3337 return WERR_INVALID_FLAGS;
3340 /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
3341 #define _BQUVW ( \
3342 DS_DIRECTORY_SERVICE_REQUIRED | \
3343 DS_DIRECTORY_SERVICE_6_REQUIRED | \
3344 DS_DIRECTORY_SERVICE_8_REQUIRED | \
3345 DS_DIRECTORY_SERVICE_9_REQUIRED | \
3346 DS_DIRECTORY_SERVICE_10_REQUIRED | \
3348 if (multiple_bits_set(r->in.flags & _BQUVW)) {
3349 return WERR_INVALID_FLAGS;
3353 * Flag K MUST NOT be combined with any of the flags:
3354 * B, C, D, E, or H.
3356 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
3357 r->in.flags &
3358 (DS_DIRECTORY_SERVICE_REQUIRED |
3359 DS_DIRECTORY_SERVICE_PREFERRED |
3360 DS_GC_SERVER_REQUIRED |
3361 DS_PDC_REQUIRED |
3362 DS_KDC_REQUIRED)) {
3363 return WERR_INVALID_FLAGS;
3366 /* Flag P MUST NOT be set when the SiteName parameter is provided. */
3367 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
3368 r->in.site_name) {
3369 return WERR_INVALID_FLAGS;
3373 * If we send an all-zero GUID, we should ignore it as winbind actually
3374 * checks it with a DNS query. Windows also appears to ignore it.
3376 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
3377 r->in.domain_guid = NULL;
3380 /* Attempt winbind search only if we suspect the domain is incorrect */
3381 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
3382 if (r->in.flags & DS_IS_FLAT_NAME) {
3383 if (strcasecmp_m(r->in.domain_name,
3384 lpcfg_sam_name(lp_ctx)) == 0) {
3385 different_domain = false;
3387 } else if (r->in.flags & DS_IS_DNS_NAME) {
3388 if (strcasecmp_m(r->in.domain_name,
3389 lpcfg_dnsdomain(lp_ctx)) == 0) {
3390 different_domain = false;
3392 } else {
3393 if (strcasecmp_m(r->in.domain_name,
3394 lpcfg_sam_name(lp_ctx)) == 0 ||
3395 strcasecmp_m(r->in.domain_name,
3396 lpcfg_dnsdomain(lp_ctx)) == 0) {
3397 different_domain = false;
3400 } else {
3402 * We need to be able to handle empty domain names, where we
3403 * revert to our domain by default.
3405 different_domain = false;
3408 if (!different_domain) {
3409 dc_level = dsdb_dc_functional_level(sam_ctx);
3412 * Do not return a local response if we do not support the
3413 * functional level or feature (eg web services)
3415 this_dc_valid_flags = valid_flags;
3417 /* Samba does not implement this */
3418 this_dc_valid_flags &= ~DS_WEB_SERVICE_REQUIRED;
3420 if (dc_level < DS_DOMAIN_FUNCTION_2012) {
3421 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_8_REQUIRED;
3423 if (dc_level < DS_DOMAIN_FUNCTION_2012_R2) {
3424 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_9_REQUIRED;
3426 if (dc_level < DS_DOMAIN_FUNCTION_2016) {
3427 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_10_REQUIRED;
3429 if (r->in.flags & ~this_dc_valid_flags) {
3430 DBG_INFO("Forcing remote lookup to find another DC "
3431 "in this domain %s with more features, "
3432 "as this Samba DC is Functional level %d but flags are 0x08%x\n",
3433 r->in.domain_name, dc_level, (unsigned int)r->in.flags);
3434 force_remote_lookup = true;
3438 /* Proof server site parameter "site_name" if it was specified */
3439 server_site_name = samdb_server_site_name(sam_ctx, state);
3440 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3441 if (force_remote_lookup
3442 || different_domain
3443 || (r->in.site_name != NULL &&
3444 (strcasecmp_m(r->in.site_name,
3445 server_site_name) != 0))) {
3447 struct dcerpc_binding_handle *irpc_handle = NULL;
3448 struct tevent_req *subreq = NULL;
3451 * Retrieve the client site to override the winbind response.
3453 * DO NOT use Windows fallback for client site.
3454 * In the case of multiple domains, this is plainly wrong.
3456 * Note: It's possible that the client may belong to multiple
3457 * subnets across domains. It's not clear what this would mean,
3458 * but here we only return what this domain knows.
3460 state->client_site = samdb_client_site_name(sam_ctx,
3461 state,
3462 remote_addr,
3463 NULL,
3464 false);
3466 irpc_handle = irpc_binding_handle_by_name(state,
3467 imsg_ctx,
3468 "winbind_server",
3469 &ndr_table_winbind);
3470 if (irpc_handle == NULL) {
3471 DEBUG(0,("Failed to get binding_handle for "
3472 "winbind_server task\n"));
3473 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3474 return WERR_SERVICE_NOT_FOUND;
3477 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3479 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3481 subreq = dcerpc_wbint_DsGetDcName_send(state,
3482 dce_call->event_ctx,
3483 irpc_handle,
3484 r->in.domain_name,
3485 r->in.domain_guid,
3486 r->in.site_name,
3487 r->in.flags,
3488 r->out.info);
3489 if (subreq == NULL) {
3490 return WERR_NOT_ENOUGH_MEMORY;
3493 tevent_req_set_callback(subreq,
3494 dcesrv_netr_DsRGetDCName_base_done,
3495 state);
3497 return WERR_OK;
3500 guid_str = r->in.domain_guid != NULL ?
3501 GUID_string(state, r->in.domain_guid) : NULL;
3503 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3504 r->in.domain_name,
3505 r->in.domain_name,
3506 NULL, guid_str,
3507 r->in.client_account,
3508 r->in.mask, remote_addr,
3509 NETLOGON_NT_VERSION_5EX_WITH_IP,
3510 lp_ctx, &response, true);
3511 if (!NT_STATUS_IS_OK(status)) {
3512 return ntstatus_to_werror(status);
3516 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3517 * (O) flag when the returned forest name is in DNS format. This is here
3518 * always the case (see below).
3520 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3522 if (r->in.flags & DS_RETURN_DNS_NAME) {
3523 dc_name = response.data.nt5_ex.pdc_dns_name;
3524 domain_name = response.data.nt5_ex.dns_domain;
3526 * According to MS-NRPC 2.2.1.2.1 we should set the
3527 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3528 * the returned information is in DNS form.
3530 response.data.nt5_ex.server_type |=
3531 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3532 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3533 dc_name = response.data.nt5_ex.pdc_name;
3534 domain_name = response.data.nt5_ex.domain_name;
3535 } else {
3538 * TODO: autodetect what we need to return
3539 * based on the given arguments
3541 dc_name = response.data.nt5_ex.pdc_name;
3542 domain_name = response.data.nt5_ex.domain_name;
3545 if (!dc_name || !dc_name[0]) {
3546 return WERR_NO_SUCH_DOMAIN;
3549 if (!domain_name || !domain_name[0]) {
3550 return WERR_NO_SUCH_DOMAIN;
3553 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3554 W_ERROR_HAVE_NO_MEMORY(info);
3555 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3556 dc_name[0] != '\\'? "\\\\":"",
3557 talloc_strdup(mem_ctx, dc_name));
3558 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3560 pdc_ip = local_addr;
3561 if (pdc_ip == NULL) {
3562 pdc_ip = "127.0.0.1";
3564 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3565 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3566 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3567 info->domain_guid = response.data.nt5_ex.domain_uuid;
3568 info->domain_name = domain_name;
3569 info->forest_name = response.data.nt5_ex.forest;
3570 info->dc_flags = response.data.nt5_ex.server_type;
3571 if (r->in.flags & DS_RETURN_DNS_NAME) {
3572 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3573 * returned if we are returning info->dc_unc containing a FQDN.
3574 * This attribute is called DomainControllerName in the specs,
3575 * it seems that we decide to return FQDN or netbios depending on
3576 * DS_RETURN_DNS_NAME.
3578 info->dc_flags |= DS_DNS_CONTROLLER;
3580 info->dc_site_name = response.data.nt5_ex.server_site;
3581 info->client_site_name = response.data.nt5_ex.client_site;
3583 *r->out.info = info;
3585 return WERR_OK;
3588 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3590 struct dcesrv_netr_DsRGetDCName_base_state *state =
3591 tevent_req_callback_data(subreq,
3592 struct dcesrv_netr_DsRGetDCName_base_state);
3593 struct dcesrv_call_state *dce_call = state->dce_call;
3594 NTSTATUS result, status;
3596 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3597 state->mem_ctx,
3598 &result);
3599 TALLOC_FREE(subreq);
3601 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3602 state->r.out.result = WERR_TIMEOUT;
3603 goto finished;
3606 if (!NT_STATUS_IS_OK(status)) {
3607 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3608 nt_errstr(status));
3609 state->r.out.result = WERR_GEN_FAILURE;
3610 goto finished;
3613 if (!NT_STATUS_IS_OK(result)) {
3614 DBG_NOTICE("DC location via winbind failed - %s\n",
3615 nt_errstr(result));
3616 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3617 goto finished;
3620 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3621 DBG_ERR("DC location via winbind returned no results\n");
3622 state->r.out.result = WERR_GEN_FAILURE;
3623 goto finished;
3626 if (state->r.out.info[0]->dc_unc == NULL) {
3627 DBG_ERR("DC location via winbind returned no DC unc\n");
3628 state->r.out.result = WERR_GEN_FAILURE;
3629 goto finished;
3633 * Either the supplied site name is NULL (possibly via
3634 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3635 * the input match name.
3637 * TODO: Currently this means that requests with NETBIOS domain
3638 * names can fail because they do not return the site name.
3640 if (state->r.in.site_name == NULL ||
3641 strcasecmp_m("", state->r.in.site_name) == 0 ||
3642 (state->r.out.info[0]->dc_site_name != NULL &&
3643 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3644 state->r.in.site_name) == 0)) {
3646 state->r.out.info[0]->client_site_name =
3647 talloc_move(state->mem_ctx, &state->client_site);
3650 * Make sure to return our DC UNC with // prefix.
3651 * Winbind currently doesn't send the leading slashes
3652 * for some reason.
3654 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3655 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3656 const char *dc_unc = NULL;
3658 dc_unc = talloc_asprintf(state->mem_ctx,
3659 "\\\\%s",
3660 state->r.out.info[0]->dc_unc);
3661 state->r.out.info[0]->dc_unc = dc_unc;
3664 state->r.out.result = WERR_OK;
3665 } else {
3666 state->r.out.info = NULL;
3667 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3670 finished:
3671 if (state->_r.dcex2 != NULL) {
3672 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3673 r->out.result = state->r.out.result;
3674 } else if (state->_r.dcex != NULL) {
3675 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3676 r->out.result = state->r.out.result;
3677 } else if (state->_r.dc != NULL) {
3678 struct netr_DsRGetDCName *r = state->_r.dc;
3679 r->out.result = state->r.out.result;
3682 TALLOC_FREE(state);
3683 dcesrv_async_reply(dce_call);
3687 netr_DsRGetDCNameEx2
3689 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3690 TALLOC_CTX *mem_ctx,
3691 struct netr_DsRGetDCNameEx2 *r)
3693 struct dcesrv_netr_DsRGetDCName_base_state *state;
3695 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3696 if (state == NULL) {
3697 return WERR_NOT_ENOUGH_MEMORY;
3700 state->dce_call = dce_call;
3701 state->mem_ctx = mem_ctx;
3703 state->r = *r;
3704 state->_r.dcex2 = r;
3706 return dcesrv_netr_DsRGetDCName_base_call(state);
3710 netr_DsRGetDCNameEx
3712 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3713 struct netr_DsRGetDCNameEx *r)
3715 struct dcesrv_netr_DsRGetDCName_base_state *state;
3717 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3718 if (state == NULL) {
3719 return WERR_NOT_ENOUGH_MEMORY;
3722 state->dce_call = dce_call;
3723 state->mem_ctx = mem_ctx;
3725 state->r.in.server_unc = r->in.server_unc;
3726 state->r.in.client_account = NULL;
3727 state->r.in.mask = 0;
3728 state->r.in.domain_guid = r->in.domain_guid;
3729 state->r.in.domain_name = r->in.domain_name;
3730 state->r.in.site_name = r->in.site_name;
3731 state->r.in.flags = r->in.flags;
3732 state->r.out.info = r->out.info;
3734 state->_r.dcex = r;
3736 return dcesrv_netr_DsRGetDCName_base_call(state);
3740 * netr_DsRGetDCName
3742 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3743 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3744 * insists that it be ignored.
3746 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3747 struct netr_DsRGetDCName *r)
3749 struct dcesrv_netr_DsRGetDCName_base_state *state;
3751 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3752 if (state == NULL) {
3753 return WERR_NOT_ENOUGH_MEMORY;
3756 state->dce_call = dce_call;
3757 state->mem_ctx = mem_ctx;
3759 state->r.in.server_unc = r->in.server_unc;
3760 state->r.in.client_account = NULL;
3761 state->r.in.mask = 0;
3762 state->r.in.domain_name = r->in.domain_name;
3763 state->r.in.domain_guid = r->in.domain_guid;
3765 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3766 state->r.in.flags = r->in.flags;
3767 state->r.out.info = r->out.info;
3769 state->_r.dc = r;
3771 return dcesrv_netr_DsRGetDCName_base_call(state);
3774 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3776 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3777 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3779 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3784 netr_NetrEnumerateTrustedDomainsEx
3786 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3787 struct netr_NetrEnumerateTrustedDomainsEx *r)
3789 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3794 netr_DsRAddressToSitenamesExW
3796 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3797 struct netr_DsRAddressToSitenamesExW *r)
3799 struct ldb_context *sam_ctx;
3800 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3801 sa_family_t sin_family;
3802 struct sockaddr_in *addr;
3803 #ifdef HAVE_IPV6
3804 struct sockaddr_in6 *addr6;
3805 char addr_str[INET6_ADDRSTRLEN];
3806 #else
3807 char addr_str[INET_ADDRSTRLEN];
3808 #endif
3809 char *subnet_name;
3810 const char *res;
3811 uint32_t i;
3813 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3814 if (sam_ctx == NULL) {
3815 return WERR_DS_UNAVAILABLE;
3818 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3819 W_ERROR_HAVE_NO_MEMORY(ctr);
3821 *r->out.ctr = ctr;
3823 ctr->count = r->in.count;
3824 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3825 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3826 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3827 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3829 for (i=0; i<ctr->count; i++) {
3830 ctr->sitename[i].string = NULL;
3831 ctr->subnetname[i].string = NULL;
3833 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3834 continue;
3836 /* The first two byte of the buffer are reserved for the
3837 * "sin_family" but for now only the first one is used. */
3838 sin_family = r->in.addresses[i].buffer[0];
3840 switch (sin_family) {
3841 case AF_INET:
3842 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3843 continue;
3845 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3846 res = inet_ntop(AF_INET, &addr->sin_addr,
3847 addr_str, sizeof(addr_str));
3848 break;
3849 #ifdef HAVE_IPV6
3850 case AF_INET6:
3851 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3852 continue;
3854 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3855 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3856 addr_str, sizeof(addr_str));
3857 break;
3858 #endif
3859 default:
3860 continue;
3863 if (res == NULL) {
3864 continue;
3867 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3868 mem_ctx,
3869 addr_str,
3870 &subnet_name,
3871 true);
3872 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3873 ctr->subnetname[i].string = subnet_name;
3876 return WERR_OK;
3881 netr_DsRAddressToSitenamesW
3883 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3884 struct netr_DsRAddressToSitenamesW *r)
3886 struct netr_DsRAddressToSitenamesExW r2;
3887 struct netr_DsRAddressToSitenamesWCtr *ctr;
3888 uint32_t i;
3889 WERROR werr;
3891 ZERO_STRUCT(r2);
3893 r2.in.server_name = r->in.server_name;
3894 r2.in.count = r->in.count;
3895 r2.in.addresses = r->in.addresses;
3897 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3898 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3900 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3901 W_ERROR_HAVE_NO_MEMORY(ctr);
3903 *r->out.ctr = ctr;
3905 ctr->count = r->in.count;
3906 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3907 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3909 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3911 for (i=0; i<ctr->count; i++) {
3912 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3915 return werr;
3920 netr_DsrGetDcSiteCoverageW
3922 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3923 struct netr_DsrGetDcSiteCoverageW *r)
3925 struct ldb_context *sam_ctx;
3926 struct DcSitesCtr *ctr;
3928 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3929 if (sam_ctx == NULL) {
3930 return WERR_DS_UNAVAILABLE;
3933 ctr = talloc(mem_ctx, struct DcSitesCtr);
3934 W_ERROR_HAVE_NO_MEMORY(ctr);
3936 *r->out.ctr = ctr;
3938 /* For now only return our default site */
3939 ctr->num_sites = 1;
3940 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3941 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3942 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3943 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3945 return WERR_OK;
3949 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3950 struct ldb_context *sam_ctx,
3951 struct netr_DomainTrustList *trusts,
3952 uint32_t trust_flags)
3954 struct ldb_dn *system_dn;
3955 struct ldb_message **dom_res = NULL;
3956 static const char *trust_attrs[] = {"flatname",
3957 "trustPartner",
3958 "securityIdentifier",
3959 "trustDirection",
3960 "trustType",
3961 "trustAttributes",
3962 NULL};
3963 uint32_t n;
3964 int i;
3965 int ret;
3967 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3968 NETR_TRUST_FLAG_OUTBOUND))) {
3969 return WERR_INVALID_FLAGS;
3972 system_dn = samdb_system_container_dn(sam_ctx, mem_ctx);
3973 if (system_dn == NULL) {
3974 return WERR_NOT_ENOUGH_MEMORY;
3977 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3978 &dom_res, trust_attrs,
3979 "(objectclass=trustedDomain)");
3981 for (i = 0; i < ret; i++) {
3982 unsigned int trust_dir;
3983 uint32_t flags = 0;
3985 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3986 "trustDirection", 0);
3988 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3989 flags |= NETR_TRUST_FLAG_INBOUND;
3991 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3992 flags |= NETR_TRUST_FLAG_OUTBOUND;
3995 if (!(flags & trust_flags)) {
3996 /* this trust direction was not requested */
3997 continue;
4000 n = trusts->count;
4001 trusts->array = talloc_realloc(trusts, trusts->array,
4002 struct netr_DomainTrust,
4003 n + 1);
4004 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4006 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
4007 if (!trusts->array[n].netbios_name) {
4008 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
4009 "without flatname\n",
4010 ldb_dn_get_linearized(dom_res[i]->dn)));
4013 trusts->array[n].trust_flags = flags;
4014 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
4015 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
4016 /* TODO: find if we have parent in the list */
4017 trusts->array[n].parent_index = 0;
4020 trusts->array[n].trust_type =
4021 ldb_msg_find_attr_as_uint(dom_res[i],
4022 "trustType", 0);
4023 trusts->array[n].trust_attributes =
4024 ldb_msg_find_attr_as_uint(dom_res[i],
4025 "trustAttributes", 0);
4027 if (trusts->array[n].trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
4028 trusts->array[n].dns_name = talloc_steal(
4029 trusts->array,
4030 ldb_msg_find_attr_as_string(dom_res[i],
4031 "trustPartner",
4032 NULL));
4033 } else {
4034 trusts->array[n].dns_name = NULL;
4037 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
4038 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
4039 struct dom_sid zero_sid;
4040 ZERO_STRUCT(zero_sid);
4041 trusts->array[n].sid =
4042 dom_sid_dup(trusts, &zero_sid);
4043 } else {
4044 trusts->array[n].sid =
4045 samdb_result_dom_sid(trusts, dom_res[i],
4046 "securityIdentifier");
4048 trusts->array[n].guid = GUID_zero();
4050 trusts->count = n + 1;
4053 talloc_free(dom_res);
4054 return WERR_OK;
4058 netr_DsrEnumerateDomainTrusts
4060 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
4061 TALLOC_CTX *mem_ctx,
4062 struct netr_DsrEnumerateDomainTrusts *r)
4064 struct netr_DomainTrustList *trusts;
4065 struct ldb_context *sam_ctx;
4066 int ret;
4067 struct ldb_message **dom_res;
4068 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
4069 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4070 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
4071 const char *p;
4072 WERROR werr;
4074 if (r->in.trust_flags & 0xFFFFFE00) {
4075 return WERR_INVALID_FLAGS;
4078 /* TODO: turn to hard check once we are sure this is 100% correct */
4079 if (!r->in.server_name) {
4080 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
4081 "But received NULL!\n", dnsdomain));
4082 } else {
4083 p = strchr(r->in.server_name, '.');
4084 if (!p) {
4085 DEBUG(3, ("Invalid domain! Expected name in domain "
4086 "[%s]. But received [%s]!\n",
4087 dnsdomain, r->in.server_name));
4088 p = r->in.server_name;
4089 } else {
4090 p++;
4092 if (strcasecmp(p, dnsdomain)) {
4093 DEBUG(3, ("Invalid domain! Expected name in domain "
4094 "[%s]. But received [%s]!\n",
4095 dnsdomain, r->in.server_name));
4099 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
4100 W_ERROR_HAVE_NO_MEMORY(trusts);
4102 trusts->count = 0;
4103 r->out.trusts = trusts;
4105 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4106 if (sam_ctx == NULL) {
4107 return WERR_GEN_FAILURE;
4110 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
4111 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
4113 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
4114 trusts, r->in.trust_flags);
4115 W_ERROR_NOT_OK_RETURN(werr);
4118 /* NOTE: we currently are always the root of the forest */
4119 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
4120 uint32_t n = trusts->count;
4122 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
4123 &dom_res, dom_attrs);
4124 if (ret != 1) {
4125 return WERR_GEN_FAILURE;
4128 trusts->count = n + 1;
4129 trusts->array = talloc_realloc(trusts, trusts->array,
4130 struct netr_DomainTrust,
4131 trusts->count);
4132 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4134 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
4135 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
4136 trusts->array[n].trust_flags =
4137 NETR_TRUST_FLAG_NATIVE |
4138 NETR_TRUST_FLAG_TREEROOT |
4139 NETR_TRUST_FLAG_IN_FOREST |
4140 NETR_TRUST_FLAG_PRIMARY;
4141 /* we are always the root domain for now */
4142 trusts->array[n].parent_index = 0;
4143 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
4144 trusts->array[n].trust_attributes = 0;
4145 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
4146 dom_res[0],
4147 "objectSid");
4148 trusts->array[n].guid = samdb_result_guid(dom_res[0],
4149 "objectGUID");
4150 talloc_free(dom_res);
4153 return WERR_OK;
4158 netr_DsrDeregisterDNSHostRecords
4160 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4161 struct netr_DsrDeregisterDNSHostRecords *r)
4163 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4167 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4168 struct netr_ServerGetTrustInfo *r);
4171 netr_ServerTrustPasswordsGet
4173 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4174 struct netr_ServerTrustPasswordsGet *r)
4176 struct netr_ServerGetTrustInfo r2 = {};
4177 struct netr_TrustInfo *_ti = NULL;
4178 NTSTATUS status;
4180 r2.in.server_name = r->in.server_name;
4181 r2.in.account_name = r->in.account_name;
4182 r2.in.secure_channel_type = r->in.secure_channel_type;
4183 r2.in.computer_name = r->in.computer_name;
4184 r2.in.credential = r->in.credential;
4186 r2.out.return_authenticator = r->out.return_authenticator;
4187 r2.out.new_owf_password = r->out.new_owf_password;
4188 r2.out.old_owf_password = r->out.old_owf_password;
4189 r2.out.trust_info = &_ti;
4191 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
4193 r->out.return_authenticator = r2.out.return_authenticator;
4194 r->out.new_owf_password = r2.out.new_owf_password;
4195 r->out.old_owf_password = r2.out.old_owf_password;
4197 return status;
4201 netr_DsRGetForestTrustInformation
4203 struct dcesrv_netr_DsRGetForestTrustInformation_state {
4204 struct dcesrv_call_state *dce_call;
4205 TALLOC_CTX *mem_ctx;
4206 struct netr_DsRGetForestTrustInformation *r;
4209 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
4211 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
4212 TALLOC_CTX *mem_ctx,
4213 struct netr_DsRGetForestTrustInformation *r)
4215 struct auth_session_info *session_info =
4216 dcesrv_call_session_info(dce_call);
4217 struct imessaging_context *imsg_ctx =
4218 dcesrv_imessaging_context(dce_call->conn);
4219 enum security_user_level security_level;
4220 struct ldb_context *sam_ctx = NULL;
4221 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
4222 struct dcerpc_binding_handle *irpc_handle = NULL;
4223 struct tevent_req *subreq = NULL;
4224 struct ldb_dn *domain_dn = NULL;
4225 struct ldb_dn *forest_dn = NULL;
4226 int cmp;
4227 int forest_level;
4229 security_level = security_session_user_level(session_info, NULL);
4230 if (security_level < SECURITY_USER) {
4231 return WERR_ACCESS_DENIED;
4234 if (r->in.flags & 0xFFFFFFFE) {
4235 return WERR_INVALID_FLAGS;
4238 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4239 if (sam_ctx == NULL) {
4240 return WERR_GEN_FAILURE;
4243 domain_dn = ldb_get_default_basedn(sam_ctx);
4244 if (domain_dn == NULL) {
4245 return WERR_GEN_FAILURE;
4248 forest_dn = ldb_get_root_basedn(sam_ctx);
4249 if (forest_dn == NULL) {
4250 return WERR_GEN_FAILURE;
4253 cmp = ldb_dn_compare(domain_dn, forest_dn);
4254 if (cmp != 0) {
4255 return WERR_NERR_ACFNOTLOADED;
4258 forest_level = dsdb_forest_functional_level(sam_ctx);
4259 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4260 return WERR_INVALID_FUNCTION;
4263 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
4264 if (!samdb_is_pdc(sam_ctx)) {
4265 return WERR_NERR_NOTPRIMARY;
4268 if (r->in.trusted_domain_name == NULL) {
4269 return WERR_INVALID_FLAGS;
4273 if (r->in.trusted_domain_name == NULL) {
4274 NTSTATUS status;
4277 * information about our own domain
4279 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4280 r->out.forest_trust_info);
4281 if (!NT_STATUS_IS_OK(status)) {
4282 return ntstatus_to_werror(status);
4285 return WERR_OK;
4289 * Forward the request to winbindd
4292 state = talloc_zero(mem_ctx,
4293 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4294 if (state == NULL) {
4295 return WERR_NOT_ENOUGH_MEMORY;
4297 state->dce_call = dce_call;
4298 state->mem_ctx = mem_ctx;
4299 state->r = r;
4301 irpc_handle = irpc_binding_handle_by_name(state,
4302 imsg_ctx,
4303 "winbind_server",
4304 &ndr_table_winbind);
4305 if (irpc_handle == NULL) {
4306 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
4307 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4308 return WERR_SERVICE_NOT_FOUND;
4312 * 60 seconds timeout should be enough
4314 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
4316 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
4317 state->dce_call->event_ctx,
4318 irpc_handle,
4319 r->in.trusted_domain_name,
4320 r->in.flags,
4321 r->out.forest_trust_info);
4322 if (subreq == NULL) {
4323 return WERR_NOT_ENOUGH_MEMORY;
4325 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4326 tevent_req_set_callback(subreq,
4327 dcesrv_netr_DsRGetForestTrustInformation_done,
4328 state);
4330 return WERR_OK;
4333 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
4335 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
4336 tevent_req_callback_data(subreq,
4337 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4338 NTSTATUS status;
4340 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
4341 state->mem_ctx,
4342 &state->r->out.result);
4343 TALLOC_FREE(subreq);
4344 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
4345 state->r->out.result = WERR_TIMEOUT;
4346 } else if (!NT_STATUS_IS_OK(status)) {
4347 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4348 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
4349 nt_errstr(status)));
4352 dcesrv_async_reply(state->dce_call);
4356 netr_GetForestTrustInformation
4358 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
4359 TALLOC_CTX *mem_ctx,
4360 struct netr_GetForestTrustInformation *r)
4362 struct netlogon_creds_CredentialState *creds = NULL;
4363 struct ldb_context *sam_ctx = NULL;
4364 struct ldb_dn *domain_dn = NULL;
4365 struct ldb_dn *forest_dn = NULL;
4366 int cmp;
4367 int forest_level;
4368 NTSTATUS status;
4370 status = dcesrv_netr_creds_server_step_check(dce_call,
4371 mem_ctx,
4372 r->in.computer_name,
4373 r->in.credential,
4374 r->out.return_authenticator,
4375 &creds);
4376 if (!NT_STATUS_IS_OK(status)) {
4377 return status;
4380 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
4381 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
4382 return NT_STATUS_NOT_IMPLEMENTED;
4385 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4386 if (sam_ctx == NULL) {
4387 return NT_STATUS_INTERNAL_ERROR;
4390 /* TODO: check r->in.server_name is our name */
4392 domain_dn = ldb_get_default_basedn(sam_ctx);
4393 if (domain_dn == NULL) {
4394 return NT_STATUS_INTERNAL_ERROR;
4397 forest_dn = ldb_get_root_basedn(sam_ctx);
4398 if (forest_dn == NULL) {
4399 return NT_STATUS_INTERNAL_ERROR;
4402 cmp = ldb_dn_compare(domain_dn, forest_dn);
4403 if (cmp != 0) {
4404 return NT_STATUS_INVALID_DOMAIN_STATE;
4407 forest_level = dsdb_forest_functional_level(sam_ctx);
4408 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4409 return NT_STATUS_INVALID_DOMAIN_STATE;
4412 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4413 r->out.forest_trust_info);
4414 if (!NT_STATUS_IS_OK(status)) {
4415 return status;
4418 return NT_STATUS_OK;
4423 netr_ServerGetTrustInfo
4425 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4426 struct netr_ServerGetTrustInfo *r)
4428 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4429 struct netlogon_creds_CredentialState *creds = NULL;
4430 struct ldb_context *sam_ctx = NULL;
4431 static const char * const attrs[] = {
4432 "unicodePwd",
4433 "sAMAccountName",
4434 "userAccountControl",
4435 /* Required for Group Managed Service Accounts. */
4436 "msDS-ManagedPasswordId",
4437 "msDS-ManagedPasswordInterval",
4438 "objectClass",
4439 "objectSid",
4440 "whenCreated",
4441 NULL
4443 struct ldb_message **res = NULL;
4444 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4445 NTSTATUS nt_status;
4446 int ret;
4447 const char *asid = NULL;
4448 uint32_t uac = 0;
4449 const char *aname = NULL;
4450 struct ldb_message *tdo_msg = NULL;
4451 const char * const tdo_attrs[] = {
4452 "trustAuthIncoming",
4453 "trustAttributes",
4454 NULL
4456 struct netr_TrustInfo *trust_info = NULL;
4458 ZERO_STRUCTP(r->out.new_owf_password);
4459 ZERO_STRUCTP(r->out.old_owf_password);
4461 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4462 mem_ctx,
4463 r->in.computer_name,
4464 r->in.credential,
4465 r->out.return_authenticator,
4466 &creds);
4467 if (!NT_STATUS_IS_OK(nt_status)) {
4468 return nt_status;
4471 /* TODO: check r->in.server_name is our name */
4473 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4474 return NT_STATUS_INVALID_PARAMETER;
4477 if (r->in.secure_channel_type != creds->secure_channel_type) {
4478 return NT_STATUS_INVALID_PARAMETER;
4481 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4482 return NT_STATUS_INVALID_PARAMETER;
4485 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
4486 if (sam_ctx == NULL) {
4487 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4490 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4491 if (asid == NULL) {
4492 return NT_STATUS_NO_MEMORY;
4496 struct ldb_result *result = NULL;
4498 ret = dsdb_search(sam_ctx,
4499 mem_ctx,
4500 &result,
4501 ldb_get_default_basedn(sam_ctx),
4502 LDB_SCOPE_SUBTREE,
4503 attrs,
4504 DSDB_SEARCH_ONE_ONLY |
4505 DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
4506 "(&(objectClass=user)(objectSid=%s))",
4507 asid);
4508 if (ret) {
4509 return NT_STATUS_ACCOUNT_DISABLED;
4512 res = talloc_steal(mem_ctx, result->msgs);
4513 talloc_free(result);
4516 switch (creds->secure_channel_type) {
4517 case SEC_CHAN_DNS_DOMAIN:
4518 case SEC_CHAN_DOMAIN:
4519 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4521 if (uac & UF_ACCOUNTDISABLE) {
4522 return NT_STATUS_ACCOUNT_DISABLED;
4525 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4526 return NT_STATUS_ACCOUNT_DISABLED;
4529 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4530 if (aname == NULL) {
4531 return NT_STATUS_ACCOUNT_DISABLED;
4534 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4535 SEC_CHAN_DOMAIN, aname,
4536 tdo_attrs, mem_ctx, &tdo_msg);
4537 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4538 return NT_STATUS_ACCOUNT_DISABLED;
4540 if (!NT_STATUS_IS_OK(nt_status)) {
4541 return nt_status;
4544 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4545 &curNtHash,
4546 &prevNtHash);
4547 if (!NT_STATUS_IS_OK(nt_status)) {
4548 return nt_status;
4551 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4552 if (trust_info == NULL) {
4553 return NT_STATUS_NO_MEMORY;
4556 trust_info->count = 1;
4557 trust_info->data = talloc_array(trust_info, uint32_t,
4558 trust_info->count);
4559 if (trust_info->data == NULL) {
4560 return NT_STATUS_NO_MEMORY;
4563 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4564 "trustAttributes",
4566 break;
4568 default:
4569 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4570 res[0],
4571 &curNtHash);
4572 if (!NT_STATUS_IS_OK(nt_status)) {
4573 return nt_status;
4576 prevNtHash = talloc(mem_ctx, struct samr_Password);
4577 if (prevNtHash == NULL) {
4578 return NT_STATUS_NO_MEMORY;
4581 E_md4hash("", prevNtHash->hash);
4582 break;
4585 if (curNtHash != NULL) {
4586 *r->out.new_owf_password = *curNtHash;
4587 nt_status = netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4588 if (!NT_STATUS_IS_OK(nt_status)) {
4589 return nt_status;
4592 if (prevNtHash != NULL) {
4593 *r->out.old_owf_password = *prevNtHash;
4594 nt_status = netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4595 if (!NT_STATUS_IS_OK(nt_status)) {
4596 return nt_status;
4600 if (trust_info != NULL) {
4601 *r->out.trust_info = trust_info;
4604 return NT_STATUS_OK;
4608 netr_Unused47
4610 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4611 struct netr_Unused47 *r)
4613 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4617 struct netr_dnsupdate_RODC_state {
4618 struct dcesrv_call_state *dce_call;
4619 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4620 struct dnsupdate_RODC *r2;
4624 called when the forwarded RODC dns update request is finished
4626 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4628 struct netr_dnsupdate_RODC_state *st =
4629 tevent_req_callback_data(subreq,
4630 struct netr_dnsupdate_RODC_state);
4631 NTSTATUS status;
4633 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4634 TALLOC_FREE(subreq);
4635 if (!NT_STATUS_IS_OK(status)) {
4636 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4637 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4640 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4642 dcesrv_async_reply(st->dce_call);
4646 netr_DsrUpdateReadOnlyServerDnsRecords
4648 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4649 TALLOC_CTX *mem_ctx,
4650 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4652 struct netlogon_creds_CredentialState *creds;
4653 NTSTATUS nt_status;
4654 struct dcerpc_binding_handle *binding_handle;
4655 struct netr_dnsupdate_RODC_state *st;
4656 struct tevent_req *subreq;
4657 struct imessaging_context *imsg_ctx =
4658 dcesrv_imessaging_context(dce_call->conn);
4660 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4661 mem_ctx,
4662 r->in.computer_name,
4663 r->in.credential,
4664 r->out.return_authenticator,
4665 &creds);
4666 NT_STATUS_NOT_OK_RETURN(nt_status);
4668 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4669 return NT_STATUS_ACCESS_DENIED;
4672 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4673 NT_STATUS_HAVE_NO_MEMORY(st);
4675 st->dce_call = dce_call;
4676 st->r = r;
4677 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4678 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4680 st->r2->in.dom_sid = creds->sid;
4681 st->r2->in.site_name = r->in.site_name;
4682 st->r2->in.dns_ttl = r->in.dns_ttl;
4683 st->r2->in.dns_names = r->in.dns_names;
4684 st->r2->out.dns_names = r->out.dns_names;
4686 binding_handle = irpc_binding_handle_by_name(st,
4687 imsg_ctx,
4688 "dnsupdate",
4689 &ndr_table_irpc);
4690 if (binding_handle == NULL) {
4691 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4692 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4693 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4696 /* forward the call */
4697 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4698 binding_handle, st->r2);
4699 NT_STATUS_HAVE_NO_MEMORY(subreq);
4701 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4703 /* setup the callback */
4704 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4706 return NT_STATUS_OK;
4710 /* include the generated boilerplate */
4711 #include "librpc/gen_ndr/ndr_netlogon_s.c"