ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob7fce61c5792a9ecbce1312444e76c18c0a8a1a1d
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 global_reject_aes_client = lpcfg_server_reject_aes_schannel(lp_ctx);
182 bool account_reject_aes_client = global_reject_aes_client;
183 const char *explicit_aes_opt = NULL;
184 bool reject_des_client;
185 bool allow_nt4_crypto;
186 bool reject_md5_client;
187 bool reject_aes_client;
188 bool need_des = true;
189 bool need_md5 = true;
190 bool need_aes = true;
191 int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL,
192 "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
193 int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL,
194 "CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
195 int NETLOGON_AES_usage_level = lpcfg_parm_int(lp_ctx, NULL,
196 "NETLOGON_AES", "usage_debug_level", DBGLVL_INFO);
199 * We don't use lpcfg_parm_bool(), as we
200 * need the explicit_opt pointer in order to
201 * adjust the debug messages.
204 if (trust_account_in_db != NULL) {
205 explicit_nt4_opt = lpcfg_get_parametric(lp_ctx,
206 NULL,
207 "allow nt4 crypto",
208 trust_account_in_db);
210 if (explicit_nt4_opt != NULL) {
211 account_allow_nt4_crypto = lp_bool(explicit_nt4_opt);
213 allow_nt4_crypto = account_allow_nt4_crypto;
214 if (trust_account_in_db != NULL) {
215 explicit_md5_opt = lpcfg_get_parametric(lp_ctx,
216 NULL,
217 "server reject md5 schannel",
218 trust_account_in_db);
220 if (explicit_md5_opt != NULL) {
221 account_reject_md5_client = lp_bool(explicit_md5_opt);
223 reject_md5_client = account_reject_md5_client;
225 if (trust_account_in_db != NULL) {
226 explicit_aes_opt = lpcfg_get_parametric(lp_ctx,
227 NULL,
228 "server reject aes schannel",
229 trust_account_in_db);
231 if (explicit_aes_opt != NULL) {
232 account_reject_aes_client = lp_bool(explicit_aes_opt);
234 reject_aes_client = account_reject_aes_client;
236 reject_des_client = !allow_nt4_crypto;
239 * If weak crypto is disabled, do not announce that we support RC4.
241 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
242 /* Without RC4 and DES we require AES */
243 reject_des_client = true;
244 reject_md5_client = true;
247 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
248 need_des = false;
249 reject_des_client = false;
252 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
253 need_des = false;
254 need_md5 = false;
255 reject_des_client = false;
256 reject_md5_client = false;
259 if (dce_call->pkt.u.request.opnum == NDR_NETR_SERVERAUTHENTICATEKERBEROS) {
260 need_des = false;
261 need_md5 = false;
262 need_aes = false;
263 reject_des_client = false;
264 reject_md5_client = false;
265 reject_aes_client = false;
268 if (reject_des_client || reject_md5_client || reject_aes_client) {
269 TALLOC_CTX *frame = talloc_stackframe();
271 if (need_aes && lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
272 if (CVE_2022_38023_error_level < DBGLVL_NOTICE) {
273 CVE_2022_38023_error_level = DBGLVL_NOTICE;
275 DEBUG(CVE_2022_38023_error_level, (
276 "CVE-2022-38023: "
277 "client_account[%s] computer_name[%s] "
278 "schannel_type[%u] "
279 "client_negotiate_flags[0x%x] "
280 "%s%s%s "
281 "NT_STATUS_DOWNGRADE_DETECTED "
282 "WEAK_CRYPTO_DISALLOWED\n",
283 log_escape(frame, r->in.account_name),
284 log_escape(frame, r->in.computer_name),
285 r->in.secure_channel_type,
286 (unsigned)*r->in.negotiate_flags,
287 trust_account_in_db ? "real_account[" : "",
288 trust_account_in_db ? trust_account_in_db : "",
289 trust_account_in_db ? "]" : ""));
290 goto return_downgrade;
293 DEBUG(CVE_2022_38023_error_level, (
294 "CVE-2022-38023: "
295 "client_account[%s] computer_name[%s] "
296 "schannel_type[%u] "
297 "client_negotiate_flags[0x%x] "
298 "%s%s%s "
299 "NT_STATUS_DOWNGRADE_DETECTED "
300 "reject_des[%u] reject_md5[%u] "
301 "reject_aes[%u]\n",
302 log_escape(frame, r->in.account_name),
303 log_escape(frame, r->in.computer_name),
304 r->in.secure_channel_type,
305 (unsigned)*r->in.negotiate_flags,
306 trust_account_in_db ? "real_account[" : "",
307 trust_account_in_db ? trust_account_in_db : "",
308 trust_account_in_db ? "]" : "",
309 reject_des_client,
310 reject_md5_client,
311 reject_aes_client));
312 if (trust_account_in_db == NULL) {
313 goto return_downgrade;
316 if (reject_aes_client && explicit_aes_opt == NULL) {
317 DEBUG(CVE_2022_38023_error_level, (
318 "CVE-2022-38023: Check if option "
319 "'server reject aes schannel:%s = no' "
320 "might be needed for a legacy client.\n",
321 trust_account_in_db));
323 if (reject_md5_client && explicit_md5_opt == NULL) {
324 DEBUG(CVE_2022_38023_error_level, (
325 "CVE-2022-38023: Check if option "
326 "'server reject md5 schannel:%s = no' "
327 "might be needed for a legacy client.\n",
328 trust_account_in_db));
330 if (reject_des_client && explicit_nt4_opt == NULL) {
331 DEBUG(CVE_2022_38023_error_level, (
332 "CVE-2022-38023: Check if option "
333 "'allow nt4 crypto:%s = yes' "
334 "might be needed for a legacy client.\n",
335 trust_account_in_db));
338 return_downgrade:
340 * Here we match Windows 2012 and return no flags.
342 *r->out.negotiate_flags = 0;
343 TALLOC_FREE(frame);
344 return NT_STATUS_DOWNGRADE_DETECTED;
348 * This talloc_free is important to prevent re-use of the
349 * challenge. We have to delay it this far due to NETApp
350 * servers per:
351 * https://bugzilla.samba.org/show_bug.cgi?id=11291
353 TALLOC_FREE(pipe_state);
356 * At this point we must also cleanup the TDB cache
357 * entry, if we fail the client needs to call
358 * netr_ServerReqChallenge again.
360 * Note: this handles a non existing record just fine,
361 * the r->in.computer_name might not be the one used
362 * in netr_ServerReqChallenge(), but we are trying to
363 * just tidy up the normal case to prevent re-use.
365 schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
366 r->in.computer_name);
369 * According to Microsoft (see bugid #6099)
370 * Windows 7 looks at the negotiate_flags
371 * returned in this structure *even if the
372 * call fails with access denied!
374 *r->out.negotiate_flags = negotiate_flags;
376 if (!NT_STATUS_IS_OK(orig_status) || trust_account_in_db == NULL) {
377 return orig_status;
380 if (global_reject_aes_client && account_reject_aes_client && explicit_aes_opt) {
381 D_INFO("NETLOGON-AES: Check if option "
382 "'server reject aes schannel:%s = yes' not needed!?\n",
383 trust_account_in_db);
384 } else if (need_aes && !account_reject_aes_client && explicit_aes_opt) {
385 D_INFO("NETLOGON-AES: Check if option "
386 "'server reject aes schannel:%s = no' "
387 "still needed for a client.\n",
388 trust_account_in_db);
389 } else if (need_aes && explicit_aes_opt == NULL) {
390 DEBUG(NETLOGON_AES_usage_level, (
391 "NETLOGON-AES: Check if option "
392 "'server reject aes schannel:%s = no' "
393 "might be needed for a client.\n",
394 trust_account_in_db));
395 } else if (!account_reject_aes_client && explicit_aes_opt) {
396 DEBUG(CVE_2022_38023_warn_level, (
397 "CVE-2022-38023: Check if option "
398 "'server reject aes schannel:%s = no' not needed!?\n",
399 trust_account_in_db));
402 if (global_reject_md5_client && account_reject_md5_client && explicit_md5_opt) {
403 D_INFO("CVE-2022-38023: Check if option "
404 "'server reject md5 schannel:%s = yes' not needed!?\n",
405 trust_account_in_db);
406 } else if (need_md5 && !account_reject_md5_client && explicit_md5_opt) {
407 D_INFO("CVE-2022-38023: Check if option "
408 "'server reject md5 schannel:%s = no' "
409 "still needed for a legacy client.\n",
410 trust_account_in_db);
411 } else if (need_md5 && explicit_md5_opt == NULL) {
412 DEBUG(CVE_2022_38023_error_level, (
413 "CVE-2022-38023: Check if option "
414 "'server reject md5 schannel:%s = no' "
415 "might be needed for a legacy client.\n",
416 trust_account_in_db));
417 } else if (!account_reject_md5_client && explicit_md5_opt) {
418 DEBUG(CVE_2022_38023_warn_level, (
419 "CVE-2022-38023: Check if option "
420 "'server reject md5 schannel:%s = no' not needed!?\n",
421 trust_account_in_db));
424 if (!global_allow_nt4_crypto && !account_allow_nt4_crypto && explicit_nt4_opt) {
425 D_INFO("CVE-2022-38023: Check if option "
426 "'allow nt4 crypto:%s = no' not needed!?\n",
427 trust_account_in_db);
428 } else if (need_des && account_allow_nt4_crypto && explicit_nt4_opt) {
429 D_INFO("CVE-2022-38023: Check if option "
430 "'allow nt4 crypto:%s = yes' "
431 "still needed for a legacy client.\n",
432 trust_account_in_db);
433 } else if (need_des && explicit_nt4_opt == NULL) {
434 DEBUG(CVE_2022_38023_error_level, (
435 "CVE-2022-38023: Check if option "
436 "'allow nt4 crypto:%s = yes' "
437 "might be needed for a legacy client.\n",
438 trust_account_in_db));
439 } else if (account_allow_nt4_crypto && explicit_nt4_opt) {
440 DEBUG(CVE_2022_38023_warn_level, (
441 "CVE-2022-38023: Check if option "
442 "'allow nt4 crypto:%s = yes' not needed!?\n",
443 trust_account_in_db));
446 return orig_status;
449 typedef NTSTATUS (*dcesrv_netr_ServerAuthenticateGenericCallback_fn)(
450 struct dcesrv_call_state *dce_call,
451 const struct netlogon_server_pipe_state *challenge,
452 const struct netr_ServerAuthenticate3 *r,
453 uint32_t client_flags,
454 const struct dom_sid *client_sid,
455 uint32_t negotiate_flags,
456 const struct ldb_message *sam_msg,
457 const struct ldb_message *tdo_msg,
458 TALLOC_CTX *mem_ctx,
459 struct netlogon_creds_CredentialState **_creds);
461 static NTSTATUS dcesrv_netr_ServerAuthenticateGeneric(
462 struct dcesrv_call_state *dce_call,
463 TALLOC_CTX *mem_ctx,
464 struct netr_ServerAuthenticate3 *r,
465 dcesrv_netr_ServerAuthenticateGenericCallback_fn auth_fn,
466 const char **trust_account_for_search,
467 const char **trust_account_in_db,
468 struct dom_sid **sid)
470 struct netlogon_server_pipe_state *pipe_state = NULL;
471 bool challenge_valid = false;
472 struct netlogon_server_pipe_state challenge;
473 struct netlogon_creds_CredentialState *creds;
474 struct ldb_context *sam_ctx;
475 uint32_t user_account_control;
476 struct ldb_message **msgs;
477 struct ldb_message *tdo_msg = NULL;
478 NTSTATUS nt_status;
479 static const char *attrs[] = {
480 "unicodePwd",
481 "userAccountControl",
482 "objectSid",
483 "samAccountName",
484 /* Required for Group Managed Service Accounts. */
485 "msDS-ManagedPasswordId",
486 "msDS-ManagedPasswordInterval",
487 "objectClass",
488 "whenCreated",
489 NULL};
490 uint32_t server_flags = 0;
491 uint32_t client_flags = 0;
492 uint32_t negotiate_flags = 0;
493 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
494 bool server_support_krb5_netlogon = lpcfg_server_support_krb5_netlogon(lp_ctx);
496 ZERO_STRUCTP(r->out.return_credentials);
497 *r->out.negotiate_flags = 0;
498 *r->out.rid = 0;
500 pipe_state = dcesrv_iface_state_find_conn(dce_call,
501 NETLOGON_SERVER_PIPE_STATE_MAGIC,
502 struct netlogon_server_pipe_state);
503 if (pipe_state != NULL) {
505 * If we had a challenge remembered on the connection
506 * consider this for usage. This can't be cleanup
507 * by other clients.
509 * This is the default code path for typical clients
510 * which call netr_ServerReqChallenge() and
511 * netr_ServerAuthenticate3() on the same dcerpc connection.
513 challenge = *pipe_state;
515 challenge_valid = true;
517 } else {
518 NTSTATUS ntstatus;
521 * Fallback and try to get the challenge from
522 * the global cache.
524 * If too many clients are using this code path,
525 * they may destroy their cache entries as the
526 * TDB has a fixed size limited via a lossy hash
528 * The TDB used is the schannel store, which is
529 * initialised at startup.
531 * NOTE: The challenge is deleted from the DB as soon as it is
532 * fetched, to prevent reuse.
536 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
537 &challenge.client_challenge,
538 &challenge.server_challenge,
539 r->in.computer_name);
541 if (!NT_STATUS_IS_OK(ntstatus)) {
542 ZERO_STRUCT(challenge);
543 } else {
544 challenge_valid = true;
548 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
549 NETLOGON_NEG_PERSISTENT_SAMREPL |
550 NETLOGON_NEG_ARCFOUR |
551 NETLOGON_NEG_PROMOTION_COUNT |
552 NETLOGON_NEG_CHANGELOG_BDC |
553 NETLOGON_NEG_FULL_SYNC_REPL |
554 NETLOGON_NEG_MULTIPLE_SIDS |
555 NETLOGON_NEG_REDO |
556 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
557 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
558 NETLOGON_NEG_GENERIC_PASSTHROUGH |
559 NETLOGON_NEG_CONCURRENT_RPC |
560 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
561 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
562 NETLOGON_NEG_STRONG_KEYS |
563 NETLOGON_NEG_TRANSITIVE_TRUSTS |
564 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
565 NETLOGON_NEG_PASSWORD_SET2 |
566 NETLOGON_NEG_GETDOMAININFO |
567 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
568 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
569 NETLOGON_NEG_RODC_PASSTHROUGH |
570 NETLOGON_NEG_SUPPORTS_AES |
571 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
572 NETLOGON_NEG_AUTHENTICATED_RPC;
573 if (server_support_krb5_netlogon) {
574 server_flags |= NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH;
578 * With SAMBA_WEAK_CRYPTO_DISALLOWED
579 * dcesrv_netr_ServerAuthenticate3_check_downgrade() will return
580 * DOWNGRADE_DETECTED with negotiate_flags = 0,
581 * if NETLOGON_NEG_SUPPORTS_AES was not negotiated...
583 * And if NETLOGON_NEG_SUPPORTS_AES was negotiated there's no harm in
584 * returning the NETLOGON_NEG_ARCFOUR flag too...
586 * So there's no reason to remove NETLOGON_NEG_ARCFOUR nor
587 * NETLOGON_NEG_STRONG_KEYS from server_flags...
590 client_flags = *r->in.negotiate_flags;
591 negotiate_flags = client_flags & server_flags;
593 switch (r->in.secure_channel_type) {
594 case SEC_CHAN_WKSTA:
595 case SEC_CHAN_DNS_DOMAIN:
596 case SEC_CHAN_DOMAIN:
597 case SEC_CHAN_BDC:
598 case SEC_CHAN_RODC:
599 break;
600 case SEC_CHAN_NULL:
601 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
602 dce_call, r, pipe_state, negotiate_flags,
603 NULL, /* trust_account_in_db */
604 NT_STATUS_INVALID_PARAMETER);
605 default:
606 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
607 r->in.secure_channel_type));
608 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
609 dce_call, r, pipe_state, negotiate_flags,
610 NULL, /* trust_account_in_db */
611 NT_STATUS_INVALID_PARAMETER);
614 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
615 if (sam_ctx == NULL) {
616 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
617 dce_call, r, pipe_state, negotiate_flags,
618 NULL, /* trust_account_in_db */
619 NT_STATUS_INVALID_SYSTEM_SERVICE);
622 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
623 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
625 static const char *const tdo_attrs[] = {"trustAuthIncoming",
626 "trustAttributes",
627 "flatName",
628 NULL};
629 char *encoded_name = NULL;
630 size_t len;
631 const char *flatname = NULL;
632 char trailer = '$';
633 bool require_trailer = true;
634 const char *netbios = NULL;
635 const char *dns = NULL;
637 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
638 trailer = '.';
639 require_trailer = false;
642 encoded_name = ldb_binary_encode_string(mem_ctx,
643 r->in.account_name);
644 if (encoded_name == NULL) {
645 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
646 dce_call, r, pipe_state, negotiate_flags,
647 NULL, /* trust_account_in_db */
648 NT_STATUS_NO_MEMORY);
651 len = strlen(encoded_name);
652 if (len < 2) {
653 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
654 dce_call, r, pipe_state, negotiate_flags,
655 NULL, /* trust_account_in_db */
656 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
659 if (require_trailer && encoded_name[len - 1] != trailer) {
660 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
661 dce_call, r, pipe_state, negotiate_flags,
662 NULL, /* trust_account_in_db */
663 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
665 encoded_name[len - 1] = '\0';
667 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
668 dns = encoded_name;
669 } else {
670 netbios = encoded_name;
673 nt_status = dsdb_trust_search_tdo(sam_ctx,
674 netbios, dns,
675 tdo_attrs, mem_ctx, &tdo_msg);
676 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
677 DEBUG(2, ("Client asked for a trusted domain secure channel, "
678 "but there's no tdo for [%s] => [%s] \n",
679 log_escape(mem_ctx, r->in.account_name),
680 encoded_name));
681 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
682 dce_call, r, pipe_state, negotiate_flags,
683 NULL, /* trust_account_in_db */
684 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
686 if (!NT_STATUS_IS_OK(nt_status)) {
687 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
688 dce_call, r, pipe_state, negotiate_flags,
689 NULL, /* trust_account_in_db */
690 nt_status);
693 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
694 if (flatname == NULL) {
695 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
696 dce_call, r, pipe_state, negotiate_flags,
697 NULL, /* trust_account_in_db */
698 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
701 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
702 if (*trust_account_for_search == NULL) {
703 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
704 dce_call, r, pipe_state, negotiate_flags,
705 NULL, /* trust_account_in_db */
706 NT_STATUS_NO_MEMORY);
708 } else {
709 *trust_account_for_search = r->in.account_name;
713 struct ldb_result *res = NULL;
714 int ret;
716 /* pull the user attributes */
717 ret = dsdb_search(
718 sam_ctx,
719 mem_ctx,
720 &res,
721 ldb_get_default_basedn(sam_ctx),
722 LDB_SCOPE_SUBTREE,
723 attrs,
724 DSDB_SEARCH_ONE_ONLY | DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
725 "(&(sAMAccountName=%s)(objectclass=user))",
726 ldb_binary_encode_string(mem_ctx,
727 *trust_account_for_search));
728 if (ret) {
729 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
730 log_escape(mem_ctx, r->in.account_name)));
731 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
732 dce_call, r, pipe_state, negotiate_flags,
733 NULL, /* trust_account_in_db */
734 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
737 msgs = talloc_steal(mem_ctx, res->msgs);
738 talloc_free(res);
741 *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
742 "samAccountName",
743 NULL);
744 if (*trust_account_in_db == NULL) {
745 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
746 r->in.account_name));
747 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
748 dce_call, r, pipe_state, negotiate_flags,
749 NULL, /* trust_account_in_db */
750 NT_STATUS_INTERNAL_DB_CORRUPTION);
753 nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
754 dce_call, r, pipe_state, negotiate_flags,
755 *trust_account_in_db,
756 NT_STATUS_OK);
757 if (!NT_STATUS_IS_OK(nt_status)) {
758 return nt_status;
761 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
763 if (user_account_control & UF_ACCOUNTDISABLE) {
764 DEBUG(1, ("Account [%s] is disabled\n",
765 log_escape(mem_ctx, r->in.account_name)));
766 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
769 switch (r->in.secure_channel_type) {
770 case SEC_CHAN_WKSTA:
771 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
772 DBG_WARNING("Client asked for a workstation "
773 "secure channel, but is not a workstation "
774 "(member server) acb flags: 0x%x\n",
775 user_account_control);
776 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
778 break;
780 case SEC_CHAN_DOMAIN:
781 FALL_THROUGH;
782 case SEC_CHAN_DNS_DOMAIN:
783 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
784 DBG_WARNING("Client asked for a trusted domain "
785 "secure channel, but is not a trusted "
786 "domain: acb flags: 0x%x\n",
787 user_account_control);
788 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
790 break;
792 case SEC_CHAN_BDC:
793 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
794 DBG_WARNING("Client asked for a server "
795 "secure channel, but is not a server "
796 "(domain controller): acb flags: 0x%x\n",
797 user_account_control);
798 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
800 break;
802 case SEC_CHAN_RODC:
803 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
804 DBG_WARNING("Client asked for a RODC secure channel, "
805 "but is not a RODC: acb flags: 0x%x\n",
806 user_account_control);
807 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
809 break;
811 default:
812 /* we should never reach this */
813 return NT_STATUS_INTERNAL_ERROR;
816 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
817 tdo_msg = NULL;
820 *sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid");
821 if (*sid == NULL) {
822 return NT_STATUS_ACCESS_DENIED;
825 nt_status = auth_fn(dce_call,
826 challenge_valid ? &challenge : NULL,
828 client_flags,
829 *sid,
830 negotiate_flags,
831 msgs[0],
832 tdo_msg,
833 mem_ctx,
834 &creds);
835 if (!NT_STATUS_IS_OK(nt_status)) {
836 ZERO_STRUCTP(r->out.return_credentials);
837 return nt_status;
840 nt_status = schannel_save_creds_state(mem_ctx,
841 dce_call->conn->dce_ctx->lp_ctx,
842 creds);
843 if (!NT_STATUS_IS_OK(nt_status)) {
844 ZERO_STRUCTP(r->out.return_credentials);
845 return nt_status;
848 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
849 "objectSid", 0);
851 return NT_STATUS_OK;
854 static NTSTATUS dcesrv_netr_ServerAuthenticateNTHash_cb(
855 struct dcesrv_call_state *dce_call,
856 const struct netlogon_server_pipe_state *challenge,
857 const struct netr_ServerAuthenticate3 *r,
858 uint32_t client_flags,
859 const struct dom_sid *client_sid,
860 uint32_t negotiate_flags,
861 const struct ldb_message *sam_msg,
862 const struct ldb_message *tdo_msg,
863 TALLOC_CTX *mem_ctx,
864 struct netlogon_creds_CredentialState **_creds)
866 TALLOC_CTX *frame = talloc_stackframe();
867 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
868 struct netlogon_creds_CredentialState *creds = NULL;
869 struct samr_Password *curNtHash = NULL;
870 struct samr_Password *prevNtHash = NULL;
871 NTSTATUS status;
873 if (tdo_msg != NULL) {
874 status = dsdb_trust_get_incoming_passwords(tdo_msg,
875 frame,
876 &curNtHash,
877 &prevNtHash);
878 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_DISABLED)) {
879 status = NT_STATUS_NO_TRUST_SAM_ACCOUNT;
881 if (!NT_STATUS_IS_OK(status)) {
882 TALLOC_FREE(frame);
883 return status;
885 } else {
886 status = samdb_result_passwords_no_lockout(frame,
887 lp_ctx,
888 sam_msg,
889 &curNtHash);
890 if (!NT_STATUS_IS_OK(status)) {
891 TALLOC_FREE(frame);
892 return NT_STATUS_ACCESS_DENIED;
896 if (curNtHash == NULL) {
897 TALLOC_FREE(frame);
898 return NT_STATUS_ACCESS_DENIED;
901 if (challenge == NULL) {
902 TALLOC_FREE(frame);
903 return NT_STATUS_ACCESS_DENIED;
906 creds = netlogon_creds_server_init(mem_ctx,
907 r->in.account_name,
908 r->in.computer_name,
909 r->in.secure_channel_type,
910 &challenge->client_challenge,
911 &challenge->server_challenge,
912 curNtHash,
913 r->in.credentials,
914 r->out.return_credentials,
915 client_flags,
916 client_sid,
917 negotiate_flags);
918 if (creds == NULL && prevNtHash != NULL) {
920 * We fallback to the previous password for domain trusts.
922 * Note that lpcfg_old_password_allowed_period() doesn't
923 * apply here.
925 creds = netlogon_creds_server_init(mem_ctx,
926 r->in.account_name,
927 r->in.computer_name,
928 r->in.secure_channel_type,
929 &challenge->client_challenge,
930 &challenge->server_challenge,
931 prevNtHash,
932 r->in.credentials,
933 r->out.return_credentials,
934 client_flags,
935 client_sid,
936 negotiate_flags);
939 if (creds == NULL) {
940 TALLOC_FREE(frame);
941 return NT_STATUS_ACCESS_DENIED;
944 *_creds = creds;
945 TALLOC_FREE(frame);
946 return NT_STATUS_OK;
950 * Do the actual processing of a netr_ServerAuthenticate3 message.
951 * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
953 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
954 struct dcesrv_call_state *dce_call,
955 TALLOC_CTX *mem_ctx,
956 struct netr_ServerAuthenticate3 *r,
957 const char **trust_account_for_search,
958 const char **trust_account_in_db,
959 struct dom_sid **sid)
961 dcesrv_netr_ServerAuthenticateGenericCallback_fn auth_fn =
962 dcesrv_netr_ServerAuthenticateNTHash_cb;
964 return dcesrv_netr_ServerAuthenticateGeneric(dce_call,
965 mem_ctx,
967 auth_fn,
968 trust_account_for_search,
969 trust_account_in_db,
970 sid);
974 * Log a netr_ServerAuthenticate3 request, and then invoke
975 * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
977 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
978 struct dcesrv_call_state *dce_call,
979 TALLOC_CTX *mem_ctx,
980 struct netr_ServerAuthenticate3 *r)
982 NTSTATUS status;
983 struct dom_sid *sid = NULL;
984 const char *trust_account_for_search = NULL;
985 const char *trust_account_in_db = NULL;
986 struct imessaging_context *imsg_ctx =
987 dcesrv_imessaging_context(dce_call->conn);
988 struct auth_usersupplied_info ui = {
989 .local_host = dce_call->conn->local_address,
990 .remote_host = dce_call->conn->remote_address,
991 .client = {
992 .account_name = r->in.account_name,
993 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
995 .service_description = "NETLOGON",
996 .auth_description = "ServerAuthenticate",
997 .netlogon_trust_account = {
998 .computer_name = r->in.computer_name,
999 .negotiate_flags = *r->in.negotiate_flags,
1000 .secure_channel_type = r->in.secure_channel_type,
1004 status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
1005 mem_ctx,
1007 &trust_account_for_search,
1008 &trust_account_in_db,
1009 &sid);
1010 ui.netlogon_trust_account.sid = sid;
1011 ui.netlogon_trust_account.account_name = trust_account_in_db;
1012 ui.mapped.account_name = trust_account_for_search;
1013 log_authentication_event(
1014 imsg_ctx,
1015 dce_call->conn->dce_ctx->lp_ctx,
1016 NULL,
1017 &ui,
1018 status,
1019 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
1020 trust_account_in_db,
1021 sid,
1022 NULL /* client_audit_info */,
1023 NULL /* server_audit_info */);
1025 return status;
1027 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1028 struct netr_ServerAuthenticate *r)
1030 struct netr_ServerAuthenticate3 a;
1031 uint32_t rid;
1032 /* TODO:
1033 * negotiate_flags is used as an [in] parameter
1034 * so it need to be initialised.
1036 * (I think ... = 0; seems wrong here --metze)
1038 uint32_t negotiate_flags_in = 0;
1039 uint32_t negotiate_flags_out = 0;
1041 a.in.server_name = r->in.server_name;
1042 a.in.account_name = r->in.account_name;
1043 a.in.secure_channel_type = r->in.secure_channel_type;
1044 a.in.computer_name = r->in.computer_name;
1045 a.in.credentials = r->in.credentials;
1046 a.in.negotiate_flags = &negotiate_flags_in;
1048 a.out.return_credentials = r->out.return_credentials;
1049 a.out.rid = &rid;
1050 a.out.negotiate_flags = &negotiate_flags_out;
1052 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
1055 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1056 struct netr_ServerAuthenticate2 *r)
1058 struct netr_ServerAuthenticate3 r3;
1059 uint32_t rid = 0;
1061 r3.in.server_name = r->in.server_name;
1062 r3.in.account_name = r->in.account_name;
1063 r3.in.secure_channel_type = r->in.secure_channel_type;
1064 r3.in.computer_name = r->in.computer_name;
1065 r3.in.credentials = r->in.credentials;
1066 r3.out.return_credentials = r->out.return_credentials;
1067 r3.in.negotiate_flags = r->in.negotiate_flags;
1068 r3.out.negotiate_flags = r->out.negotiate_flags;
1069 r3.out.rid = &rid;
1071 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
1075 Change the machine account password for the currently connected
1076 client. Supplies only the NT#.
1079 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1080 struct netr_ServerPasswordSet *r)
1082 struct netlogon_creds_CredentialState *creds;
1083 const struct dom_sid *client_sid = NULL;
1084 struct ldb_context *sam_ctx;
1085 NTSTATUS nt_status;
1086 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1087 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1089 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1091 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1092 mem_ctx,
1093 r->in.computer_name,
1094 r->in.credential, r->out.return_authenticator,
1095 &creds);
1096 NT_STATUS_NOT_OK_RETURN(nt_status);
1097 client_sid = &creds->client_sid;
1099 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
1100 if (sam_ctx == NULL) {
1101 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1104 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
1105 return NT_STATUS_NOT_SUPPORTED;
1108 nt_status = netlogon_creds_decrypt_samr_Password(creds,
1109 r->in.new_password,
1110 auth_type,
1111 auth_level);
1112 NT_STATUS_NOT_OK_RETURN(nt_status);
1114 /* Using the sid for the account as the key, set the password */
1115 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1116 client_sid,
1117 NULL, /* Don't have version */
1118 NULL, /* Don't have plaintext */
1119 r->in.new_password,
1120 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1121 NULL, NULL);
1122 return nt_status;
1126 Change the machine account password for the currently connected
1127 client. Supplies new plaintext.
1129 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1130 struct netr_ServerPasswordSet2 *r)
1132 struct netlogon_creds_CredentialState *creds;
1133 const struct dom_sid *client_sid = NULL;
1134 struct ldb_context *sam_ctx;
1135 struct NL_PASSWORD_VERSION version = {};
1136 const uint32_t *new_version = NULL;
1137 NTSTATUS nt_status;
1138 DATA_BLOB new_password = data_blob_null;
1139 size_t confounder_len;
1140 DATA_BLOB dec_blob = data_blob_null;
1141 DATA_BLOB enc_blob = data_blob_null;
1142 struct samr_CryptPassword password_buf;
1143 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1144 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1146 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1148 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1149 mem_ctx,
1150 r->in.computer_name,
1151 r->in.credential, r->out.return_authenticator,
1152 &creds);
1153 NT_STATUS_NOT_OK_RETURN(nt_status);
1154 client_sid = &creds->client_sid;
1156 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
1157 if (sam_ctx == NULL) {
1158 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1161 memcpy(password_buf.data, r->in.new_password->data, 512);
1162 SIVAL(password_buf.data, 512, r->in.new_password->length);
1164 nt_status = netlogon_creds_decrypt_samr_CryptPassword(creds,
1165 &password_buf,
1166 auth_type,
1167 auth_level);
1168 if (!NT_STATUS_IS_OK(nt_status)) {
1169 return nt_status;
1172 switch (creds->secure_channel_type) {
1173 case SEC_CHAN_DOMAIN:
1174 case SEC_CHAN_DNS_DOMAIN: {
1175 uint32_t len = IVAL(password_buf.data, 512);
1176 if (len <= 500) {
1177 uint32_t ofs = 500 - len;
1178 uint8_t *p;
1180 p = password_buf.data + ofs;
1182 version.ReservedField = IVAL(p, 0);
1183 version.PasswordVersionNumber = IVAL(p, 4);
1184 version.PasswordVersionPresent = IVAL(p, 8);
1186 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
1187 new_version = &version.PasswordVersionNumber;
1190 break;
1191 default:
1192 break;
1195 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
1196 DEBUG(3,("samr: failed to decode password buffer\n"));
1197 return NT_STATUS_ACCESS_DENIED;
1201 * We don't allow empty passwords for machine accounts.
1203 if (new_password.length < 2) {
1204 DBG_WARNING("Empty password Length[%zu]\n",
1205 new_password.length);
1206 return NT_STATUS_WRONG_PASSWORD;
1209 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
1211 * netlogon_creds_decrypt_samr_CryptPassword
1212 * already checked for DCERPC_AUTH_LEVEL_PRIVACY
1214 goto checked_encryption;
1215 } else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1217 * check it's encrypted
1219 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1221 * check it's encrypted
1223 } else {
1225 * netlogon_creds_decrypt_samr_CryptPassword
1226 * already checked for DCERPC_AUTH_LEVEL_PRIVACY
1228 goto checked_encryption;
1232 * Make sure the length field was encrypted,
1233 * otherwise we are under attack.
1235 if (new_password.length == r->in.new_password->length) {
1236 DBG_WARNING("Length[%zu] field not encrypted\n",
1237 new_password.length);
1238 return NT_STATUS_WRONG_PASSWORD;
1242 * Make sure the confounder part of CryptPassword
1243 * buffer was encrypted, otherwise we are under attack.
1245 confounder_len = 512 - new_password.length;
1246 enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
1247 dec_blob = data_blob_const(password_buf.data, confounder_len);
1248 if (confounder_len > 0 && data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1249 DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
1250 confounder_len);
1251 return NT_STATUS_WRONG_PASSWORD;
1255 * Check that the password part was actually encrypted,
1256 * otherwise we are under attack.
1258 enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
1259 new_password.length);
1260 dec_blob = data_blob_const(password_buf.data + confounder_len,
1261 new_password.length);
1262 if (data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1263 DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
1264 new_password.length);
1265 return NT_STATUS_WRONG_PASSWORD;
1268 checked_encryption:
1271 * don't allow zero buffers
1273 if (all_zero(new_password.data, new_password.length)) {
1274 DBG_WARNING("Password zero buffer Length[%zu]\n",
1275 new_password.length);
1276 return NT_STATUS_WRONG_PASSWORD;
1279 /* Using the sid for the account as the key, set the password */
1280 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1281 client_sid,
1282 new_version,
1283 &new_password, /* we have plaintext */
1284 NULL,
1285 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1286 NULL, NULL);
1287 return nt_status;
1292 netr_LogonUasLogon
1294 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1295 struct netr_LogonUasLogon *r)
1297 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1302 netr_LogonUasLogoff
1304 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1305 struct netr_LogonUasLogoff *r)
1307 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1311 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
1312 const struct netr_LogonSamLogonEx *r)
1314 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1316 switch (r->in.logon_level) {
1317 case NetlogonInteractiveInformation:
1318 case NetlogonServiceInformation:
1319 case NetlogonInteractiveTransitiveInformation:
1320 case NetlogonServiceTransitiveInformation:
1321 if (r->in.logon->password == NULL) {
1322 return NT_STATUS_INVALID_PARAMETER;
1325 switch (r->in.validation_level) {
1326 case NetlogonValidationSamInfo: /* 2 */
1327 case NetlogonValidationSamInfo2: /* 3 */
1328 case NetlogonValidationSamInfo4: /* 6 */
1329 break;
1330 default:
1331 return NT_STATUS_INVALID_INFO_CLASS;
1334 break;
1335 case NetlogonNetworkInformation:
1336 case NetlogonNetworkTransitiveInformation:
1337 if (r->in.logon->network == NULL) {
1338 return NT_STATUS_INVALID_PARAMETER;
1341 switch (r->in.validation_level) {
1342 case NetlogonValidationSamInfo: /* 2 */
1343 case NetlogonValidationSamInfo2: /* 3 */
1344 case NetlogonValidationSamInfo4: /* 6 */
1345 break;
1346 default:
1347 return NT_STATUS_INVALID_INFO_CLASS;
1350 break;
1352 case NetlogonGenericInformation:
1353 if (r->in.logon->generic == NULL) {
1354 return NT_STATUS_INVALID_PARAMETER;
1357 switch (r->in.validation_level) {
1358 /* TODO: case NetlogonValidationGenericInfo: 4 */
1359 case NetlogonValidationGenericInfo2: /* 5 */
1360 break;
1361 default:
1362 return NT_STATUS_INVALID_INFO_CLASS;
1365 break;
1366 default:
1367 return NT_STATUS_INVALID_PARAMETER;
1370 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
1372 switch (r->in.validation_level) {
1373 case NetlogonValidationSamInfo4: /* 6 */
1374 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1375 return NT_STATUS_INVALID_PARAMETER;
1377 break;
1379 default:
1380 break;
1383 return NT_STATUS_OK;
1386 struct dcesrv_netr_LogonSamLogon_base_state {
1387 struct dcesrv_call_state *dce_call;
1389 TALLOC_CTX *mem_ctx;
1391 struct netlogon_creds_CredentialState *creds;
1393 struct netr_LogonSamLogonEx r;
1395 uint32_t _ignored_flags;
1397 struct {
1398 struct netr_LogonSamLogon *lsl;
1399 struct netr_LogonSamLogonWithFlags *lslwf;
1400 struct netr_LogonSamLogonEx *lslex;
1401 } _r;
1403 struct kdc_check_generic_kerberos kr;
1406 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
1407 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
1408 static void dcesrv_netr_LogonSamLogon_base_reply(
1409 struct dcesrv_netr_LogonSamLogon_base_state *state);
1412 netr_LogonSamLogon_base
1414 This version of the function allows other wrappers to say 'do not check the credentials'
1416 We can't do the traditional 'wrapping' format completely, as this
1417 function must only run under schannel
1419 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
1421 struct dcesrv_call_state *dce_call = state->dce_call;
1422 struct imessaging_context *imsg_ctx =
1423 dcesrv_imessaging_context(dce_call->conn);
1424 TALLOC_CTX *mem_ctx = state->mem_ctx;
1425 struct netr_LogonSamLogonEx *r = &state->r;
1426 struct netlogon_creds_CredentialState *creds = state->creds;
1427 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1428 const char *workgroup = lpcfg_workgroup(lp_ctx);
1429 struct auth4_context *auth_context = NULL;
1430 struct auth_usersupplied_info *user_info = NULL;
1431 NTSTATUS nt_status;
1432 struct tevent_req *subreq = NULL;
1433 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1434 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1436 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1438 switch (dce_call->pkt.u.request.opnum) {
1439 case NDR_NETR_LOGONSAMLOGON:
1440 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
1442 * These already called dcesrv_netr_check_schannel()
1443 * via dcesrv_netr_creds_server_step_check()
1445 break;
1446 case NDR_NETR_LOGONSAMLOGONEX:
1447 default:
1448 nt_status = dcesrv_netr_check_schannel(dce_call,
1449 creds,
1450 auth_type,
1451 auth_level,
1452 dce_call->pkt.u.request.opnum);
1453 if (!NT_STATUS_IS_OK(nt_status)) {
1454 return nt_status;
1457 if (!creds->authenticate_kerberos &&
1458 auth_type != DCERPC_AUTH_TYPE_SCHANNEL)
1460 return NT_STATUS_ACCESS_DENIED;
1463 break;
1466 *r->out.authoritative = 1;
1468 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
1470 * Currently we're always the forest root ourself.
1472 return NT_STATUS_NO_SUCH_USER;
1475 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
1477 * Currently we don't support trusts correctly yet.
1479 return NT_STATUS_NO_SUCH_USER;
1482 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1483 NT_STATUS_HAVE_NO_MEMORY(user_info);
1485 user_info->service_description = "SamLogon";
1487 nt_status = netlogon_creds_decrypt_samlogon_logon(creds,
1488 r->in.logon_level,
1489 r->in.logon,
1490 auth_type,
1491 auth_level);
1492 NT_STATUS_NOT_OK_RETURN(nt_status);
1494 switch (r->in.logon_level) {
1495 case NetlogonInteractiveInformation:
1496 case NetlogonServiceInformation:
1497 case NetlogonInteractiveTransitiveInformation:
1498 case NetlogonServiceTransitiveInformation:
1499 case NetlogonNetworkInformation:
1500 case NetlogonNetworkTransitiveInformation:
1502 nt_status = auth_context_create_for_netlogon(mem_ctx,
1503 dce_call->event_ctx,
1504 imsg_ctx,
1505 dce_call->conn->dce_ctx->lp_ctx,
1506 &auth_context);
1507 NT_STATUS_NOT_OK_RETURN(nt_status);
1509 user_info->remote_host = dce_call->conn->remote_address;
1510 user_info->local_host = dce_call->conn->local_address;
1512 user_info->netlogon_trust_account.secure_channel_type
1513 = creds->secure_channel_type;
1514 user_info->netlogon_trust_account.negotiate_flags
1515 = creds->negotiate_flags;
1518 * These two can be unrelated when the account is
1519 * actually that of a trusted domain, so we want to
1520 * know which DC in that trusted domain contacted
1521 * us
1523 user_info->netlogon_trust_account.computer_name
1524 = creds->computer_name;
1525 user_info->netlogon_trust_account.account_name
1526 = creds->account_name;
1527 user_info->netlogon_trust_account.sid
1528 = &creds->client_sid;
1530 break;
1531 default:
1532 /* We do not need to set up the user_info in this case */
1533 break;
1536 switch (r->in.logon_level) {
1537 case NetlogonInteractiveInformation:
1538 case NetlogonServiceInformation:
1539 case NetlogonInteractiveTransitiveInformation:
1540 case NetlogonServiceTransitiveInformation:
1541 user_info->auth_description = "interactive";
1543 user_info->logon_parameters
1544 = r->in.logon->password->identity_info.parameter_control;
1545 user_info->client.account_name
1546 = r->in.logon->password->identity_info.account_name.string;
1547 user_info->client.domain_name
1548 = r->in.logon->password->identity_info.domain_name.string;
1549 user_info->workstation_name
1550 = r->in.logon->password->identity_info.workstation.string;
1551 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1552 user_info->password_state = AUTH_PASSWORD_HASH;
1554 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1555 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1556 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1558 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1559 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1560 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1562 user_info->logon_id
1563 = r->in.logon->password->identity_info.logon_id;
1565 break;
1566 case NetlogonNetworkInformation:
1567 case NetlogonNetworkTransitiveInformation:
1568 user_info->auth_description = "network";
1570 nt_status = auth_context_set_challenge(
1571 auth_context,
1572 r->in.logon->network->challenge,
1573 "netr_LogonSamLogonWithFlags");
1574 NT_STATUS_NOT_OK_RETURN(nt_status);
1576 user_info->logon_parameters
1577 = r->in.logon->network->identity_info.parameter_control;
1578 user_info->client.account_name
1579 = r->in.logon->network->identity_info.account_name.string;
1580 user_info->client.domain_name
1581 = r->in.logon->network->identity_info.domain_name.string;
1582 user_info->workstation_name
1583 = r->in.logon->network->identity_info.workstation.string;
1585 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1586 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1587 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1589 user_info->logon_id
1590 = r->in.logon->network->identity_info.logon_id;
1592 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1593 user_info->client.account_name,
1594 user_info->client.domain_name,
1595 user_info->password.response.nt,
1596 creds, workgroup);
1597 NT_STATUS_NOT_OK_RETURN(nt_status);
1599 break;
1602 case NetlogonGenericInformation:
1604 if (creds->authenticate_kerberos) {
1605 /* OK */
1606 } else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1607 /* OK */
1608 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1609 /* OK */
1610 } else {
1611 /* Using DES to verify kerberos tickets makes no sense */
1612 return NT_STATUS_INVALID_PARAMETER;
1615 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1616 struct dcerpc_binding_handle *irpc_handle;
1617 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1618 NT_STATUS_HAVE_NO_MEMORY(generic);
1620 r->out.validation->generic = generic;
1622 user_info->logon_id
1623 = r->in.logon->generic->identity_info.logon_id;
1625 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1626 imsg_ctx,
1627 "kdc_server",
1628 &ndr_table_irpc);
1629 if (irpc_handle == NULL) {
1630 return NT_STATUS_NO_LOGON_SERVERS;
1633 state->kr.in.generic_request =
1634 data_blob_const(r->in.logon->generic->data,
1635 r->in.logon->generic->length);
1638 * 60 seconds should be enough
1640 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1641 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1642 state->dce_call->event_ctx,
1643 irpc_handle, &state->kr);
1644 if (subreq == NULL) {
1645 return NT_STATUS_NO_MEMORY;
1647 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1648 tevent_req_set_callback(subreq,
1649 dcesrv_netr_LogonSamLogon_base_krb5_done,
1650 state);
1651 return NT_STATUS_OK;
1654 /* Until we get an implementation of these other packages */
1655 return NT_STATUS_INVALID_PARAMETER;
1657 default:
1658 return NT_STATUS_INVALID_PARAMETER;
1661 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1662 auth_context, user_info);
1663 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1664 tevent_req_set_callback(subreq,
1665 dcesrv_netr_LogonSamLogon_base_auth_done,
1666 state);
1667 return NT_STATUS_OK;
1670 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1672 struct dcesrv_netr_LogonSamLogon_base_state *state =
1673 tevent_req_callback_data(subreq,
1674 struct dcesrv_netr_LogonSamLogon_base_state);
1675 TALLOC_CTX *mem_ctx = state->mem_ctx;
1676 struct netr_LogonSamLogonEx *r = &state->r;
1677 struct auth_user_info_dc *user_info_dc = NULL;
1678 struct netr_SamInfo2 *sam2 = NULL;
1679 struct netr_SamInfo3 *sam3 = NULL;
1680 struct netr_SamInfo6 *sam6 = NULL;
1681 NTSTATUS nt_status;
1683 nt_status = auth_check_password_recv(subreq, mem_ctx,
1684 &user_info_dc,
1685 r->out.authoritative);
1686 TALLOC_FREE(subreq);
1687 if (!NT_STATUS_IS_OK(nt_status)) {
1688 r->out.result = nt_status;
1689 dcesrv_netr_LogonSamLogon_base_reply(state);
1690 return;
1693 switch (r->in.validation_level) {
1694 case 2:
1695 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1696 user_info_dc,
1697 AUTH_INCLUDE_RESOURCE_GROUPS,
1698 &sam2);
1699 if (!NT_STATUS_IS_OK(nt_status)) {
1700 r->out.result = nt_status;
1701 dcesrv_netr_LogonSamLogon_base_reply(state);
1702 return;
1705 r->out.validation->sam2 = sam2;
1706 break;
1708 case 3:
1709 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1710 user_info_dc,
1711 AUTH_INCLUDE_RESOURCE_GROUPS,
1712 &sam3, NULL);
1713 if (!NT_STATUS_IS_OK(nt_status)) {
1714 r->out.result = nt_status;
1715 dcesrv_netr_LogonSamLogon_base_reply(state);
1716 return;
1719 r->out.validation->sam3 = sam3;
1720 break;
1722 case 6:
1723 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1724 user_info_dc,
1725 AUTH_INCLUDE_RESOURCE_GROUPS,
1726 &sam6, NULL);
1727 if (!NT_STATUS_IS_OK(nt_status)) {
1728 r->out.result = nt_status;
1729 dcesrv_netr_LogonSamLogon_base_reply(state);
1730 return;
1733 r->out.validation->sam6 = sam6;
1734 break;
1736 default:
1737 if (!NT_STATUS_IS_OK(nt_status)) {
1738 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1739 dcesrv_netr_LogonSamLogon_base_reply(state);
1740 return;
1744 /* TODO: Describe and deal with these flags */
1745 *r->out.flags = 0;
1747 r->out.result = NT_STATUS_OK;
1749 dcesrv_netr_LogonSamLogon_base_reply(state);
1752 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1754 struct dcesrv_netr_LogonSamLogon_base_state *state =
1755 tevent_req_callback_data(subreq,
1756 struct dcesrv_netr_LogonSamLogon_base_state);
1757 TALLOC_CTX *mem_ctx = state->mem_ctx;
1758 struct netr_LogonSamLogonEx *r = &state->r;
1759 struct netr_GenericInfo2 *generic = NULL;
1760 NTSTATUS status;
1762 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1763 TALLOC_FREE(subreq);
1764 if (!NT_STATUS_IS_OK(status)) {
1765 r->out.result = status;
1766 dcesrv_netr_LogonSamLogon_base_reply(state);
1767 return;
1770 generic = r->out.validation->generic;
1771 generic->length = state->kr.out.generic_reply.length;
1772 generic->data = state->kr.out.generic_reply.data;
1774 /* TODO: Describe and deal with these flags */
1775 *r->out.flags = 0;
1777 r->out.result = NT_STATUS_OK;
1779 dcesrv_netr_LogonSamLogon_base_reply(state);
1782 static void dcesrv_netr_LogonSamLogon_base_reply(
1783 struct dcesrv_netr_LogonSamLogon_base_state *state)
1785 struct netr_LogonSamLogonEx *r = &state->r;
1786 NTSTATUS status;
1788 if (NT_STATUS_IS_OK(r->out.result)) {
1789 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1790 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1792 dcesrv_call_auth_info(state->dce_call, &auth_type, &auth_level);
1794 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
1795 r->in.validation_level,
1796 r->out.validation,
1797 auth_type,
1798 auth_level);
1799 if (!NT_STATUS_IS_OK(status)) {
1800 DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
1801 "failed - %s\n",
1802 nt_errstr(status));
1803 if (r->out.validation != NULL) {
1804 ZERO_STRUCTP(r->out.validation);
1806 *r->out.authoritative = true;
1807 *r->out.flags = 0;
1808 r->out.result = status;
1812 if (state->_r.lslex != NULL) {
1813 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1814 _r->out.result = r->out.result;
1815 } else if (state->_r.lslwf != NULL) {
1816 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1817 _r->out.result = r->out.result;
1818 } else if (state->_r.lsl != NULL) {
1819 struct netr_LogonSamLogon *_r = state->_r.lsl;
1820 _r->out.result = r->out.result;
1823 dcesrv_async_reply(state->dce_call);
1826 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1827 struct netr_LogonSamLogonEx *r)
1829 struct dcesrv_netr_LogonSamLogon_base_state *state;
1830 NTSTATUS nt_status;
1832 *r->out.authoritative = 1;
1834 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1835 if (state == NULL) {
1836 return NT_STATUS_NO_MEMORY;
1839 state->dce_call = dce_call;
1840 state->mem_ctx = mem_ctx;
1842 state->r.in.server_name = r->in.server_name;
1843 state->r.in.computer_name = r->in.computer_name;
1844 state->r.in.logon_level = r->in.logon_level;
1845 state->r.in.logon = r->in.logon;
1846 state->r.in.validation_level = r->in.validation_level;
1847 state->r.in.flags = r->in.flags;
1848 state->r.out.validation = r->out.validation;
1849 state->r.out.authoritative = r->out.authoritative;
1850 state->r.out.flags = r->out.flags;
1852 state->_r.lslex = r;
1854 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1855 if (!NT_STATUS_IS_OK(nt_status)) {
1856 return nt_status;
1859 nt_status = schannel_get_creds_state(mem_ctx,
1860 dce_call->conn->dce_ctx->lp_ctx,
1861 r->in.computer_name, &state->creds);
1862 if (!NT_STATUS_IS_OK(nt_status)) {
1863 return nt_status;
1866 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1868 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1869 return nt_status;
1872 return nt_status;
1876 netr_LogonSamLogonWithFlags
1879 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1880 struct netr_LogonSamLogonWithFlags *r)
1882 struct dcesrv_netr_LogonSamLogon_base_state *state;
1883 NTSTATUS nt_status;
1885 *r->out.authoritative = 1;
1887 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1888 if (state == NULL) {
1889 return NT_STATUS_NO_MEMORY;
1892 state->dce_call = dce_call;
1893 state->mem_ctx = mem_ctx;
1895 state->r.in.server_name = r->in.server_name;
1896 state->r.in.computer_name = r->in.computer_name;
1897 state->r.in.logon_level = r->in.logon_level;
1898 state->r.in.logon = r->in.logon;
1899 state->r.in.validation_level = r->in.validation_level;
1900 state->r.in.flags = r->in.flags;
1901 state->r.out.validation = r->out.validation;
1902 state->r.out.authoritative = r->out.authoritative;
1903 state->r.out.flags = r->out.flags;
1905 state->_r.lslwf = r;
1907 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1908 if (!NT_STATUS_IS_OK(nt_status)) {
1909 return nt_status;
1912 r->out.return_authenticator = talloc_zero(mem_ctx,
1913 struct netr_Authenticator);
1914 if (r->out.return_authenticator == NULL) {
1915 return NT_STATUS_NO_MEMORY;
1918 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1919 mem_ctx,
1920 r->in.computer_name,
1921 r->in.credential,
1922 r->out.return_authenticator,
1923 &state->creds);
1924 if (!NT_STATUS_IS_OK(nt_status)) {
1925 return nt_status;
1928 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1930 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1931 return nt_status;
1934 return nt_status;
1938 netr_LogonSamLogon
1940 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1941 struct netr_LogonSamLogon *r)
1943 struct dcesrv_netr_LogonSamLogon_base_state *state;
1944 NTSTATUS nt_status;
1946 *r->out.authoritative = 1;
1948 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1949 if (state == NULL) {
1950 return NT_STATUS_NO_MEMORY;
1953 state->dce_call = dce_call;
1954 state->mem_ctx = mem_ctx;
1956 state->r.in.server_name = r->in.server_name;
1957 state->r.in.computer_name = r->in.computer_name;
1958 state->r.in.logon_level = r->in.logon_level;
1959 state->r.in.logon = r->in.logon;
1960 state->r.in.validation_level = r->in.validation_level;
1961 state->r.in.flags = &state->_ignored_flags;
1962 state->r.out.validation = r->out.validation;
1963 state->r.out.authoritative = r->out.authoritative;
1964 state->r.out.flags = &state->_ignored_flags;
1966 state->_r.lsl = r;
1968 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1969 if (!NT_STATUS_IS_OK(nt_status)) {
1970 return nt_status;
1973 r->out.return_authenticator = talloc_zero(mem_ctx,
1974 struct netr_Authenticator);
1975 if (r->out.return_authenticator == NULL) {
1976 return NT_STATUS_NO_MEMORY;
1979 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1980 mem_ctx,
1981 r->in.computer_name,
1982 r->in.credential,
1983 r->out.return_authenticator,
1984 &state->creds);
1985 if (!NT_STATUS_IS_OK(nt_status)) {
1986 return nt_status;
1989 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1991 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1992 return nt_status;
1995 return nt_status;
2000 netr_LogonSamLogoff
2002 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2003 struct netr_LogonSamLogoff *r)
2005 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2011 netr_DatabaseDeltas
2013 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2014 struct netr_DatabaseDeltas *r)
2016 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2021 netr_DatabaseSync2
2023 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2024 struct netr_DatabaseSync2 *r)
2026 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
2027 return NT_STATUS_NOT_IMPLEMENTED;
2032 netr_DatabaseSync
2034 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2035 struct netr_DatabaseSync *r)
2037 struct netr_DatabaseSync2 r2;
2038 NTSTATUS status;
2040 ZERO_STRUCT(r2);
2042 r2.in.logon_server = r->in.logon_server;
2043 r2.in.computername = r->in.computername;
2044 r2.in.credential = r->in.credential;
2045 r2.in.database_id = r->in.database_id;
2046 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
2047 r2.in.sync_context = r->in.sync_context;
2048 r2.out.sync_context = r->out.sync_context;
2049 r2.out.delta_enum_array = r->out.delta_enum_array;
2050 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
2052 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
2054 return status;
2059 netr_AccountDeltas
2061 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2062 struct netr_AccountDeltas *r)
2064 /* w2k3 returns "NOT IMPLEMENTED" for this call */
2065 return NT_STATUS_NOT_IMPLEMENTED;
2070 netr_AccountSync
2072 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2073 struct netr_AccountSync *r)
2075 /* w2k3 returns "NOT IMPLEMENTED" for this call */
2076 return NT_STATUS_NOT_IMPLEMENTED;
2081 netr_GetDcName
2083 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2084 struct netr_GetDcName *r)
2086 const char * const attrs[] = { NULL };
2087 struct ldb_context *sam_ctx;
2088 struct ldb_message **res;
2089 struct ldb_dn *domain_dn;
2090 int ret;
2091 const char *dcname;
2094 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
2095 * that the domainname needs to be a valid netbios domain
2096 * name, if it is not NULL.
2098 if (r->in.domainname) {
2099 const char *dot = strchr(r->in.domainname, '.');
2100 size_t len = strlen(r->in.domainname);
2102 if (dot || len > 15) {
2103 return WERR_NERR_DCNOTFOUND;
2107 * TODO: Should we also verify that only valid
2108 * netbios name characters are used?
2112 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2113 if (sam_ctx == NULL) {
2114 return WERR_DS_UNAVAILABLE;
2117 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
2118 r->in.domainname);
2119 if (domain_dn == NULL) {
2120 return WERR_NO_SUCH_DOMAIN;
2123 ret = gendb_search_dn(sam_ctx, mem_ctx,
2124 domain_dn, &res, attrs);
2125 if (ret != 1) {
2126 return WERR_NO_SUCH_DOMAIN;
2129 /* TODO: - return real IP address
2130 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
2132 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
2133 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
2134 W_ERROR_HAVE_NO_MEMORY(dcname);
2136 *r->out.dcname = dcname;
2137 return WERR_OK;
2140 struct dcesrv_netr_LogonControl_base_state {
2141 struct dcesrv_call_state *dce_call;
2143 TALLOC_CTX *mem_ctx;
2145 struct netr_LogonControl2Ex r;
2147 struct {
2148 struct netr_LogonControl *l;
2149 struct netr_LogonControl2 *l2;
2150 struct netr_LogonControl2Ex *l2ex;
2151 } _r;
2154 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
2156 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
2158 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
2159 struct auth_session_info *session_info =
2160 dcesrv_call_session_info(state->dce_call);
2161 struct imessaging_context *imsg_ctx =
2162 dcesrv_imessaging_context(state->dce_call->conn);
2163 enum security_user_level security_level;
2164 struct dcerpc_binding_handle *irpc_handle;
2165 struct tevent_req *subreq;
2166 bool ok;
2168 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
2170 if (state->_r.l != NULL) {
2172 * netr_LogonControl
2174 if (state->r.in.level == 0x00000002) {
2175 return WERR_NOT_SUPPORTED;
2176 } else if (state->r.in.level != 0x00000001) {
2177 return WERR_INVALID_LEVEL;
2180 switch (state->r.in.function_code) {
2181 case NETLOGON_CONTROL_QUERY:
2182 case NETLOGON_CONTROL_REPLICATE:
2183 case NETLOGON_CONTROL_SYNCHRONIZE:
2184 case NETLOGON_CONTROL_PDC_REPLICATE:
2185 case NETLOGON_CONTROL_BREAKPOINT:
2186 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
2187 case NETLOGON_CONTROL_TRUNCATE_LOG:
2188 break;
2189 default:
2190 return WERR_NOT_SUPPORTED;
2194 if (state->r.in.level < 0x00000001) {
2195 return WERR_INVALID_LEVEL;
2198 if (state->r.in.level > 0x00000004) {
2199 return WERR_INVALID_LEVEL;
2202 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
2203 struct netr_NETLOGON_INFO_1 *info1 = NULL;
2204 struct netr_NETLOGON_INFO_3 *info3 = NULL;
2206 switch (state->r.in.level) {
2207 case 0x00000001:
2208 info1 = talloc_zero(state->mem_ctx,
2209 struct netr_NETLOGON_INFO_1);
2210 if (info1 == NULL) {
2211 return WERR_NOT_ENOUGH_MEMORY;
2213 state->r.out.query->info1 = info1;
2214 return WERR_OK;
2216 case 0x00000003:
2217 info3 = talloc_zero(state->mem_ctx,
2218 struct netr_NETLOGON_INFO_3);
2219 if (info3 == NULL) {
2220 return WERR_NOT_ENOUGH_MEMORY;
2222 state->r.out.query->info3 = info3;
2223 return WERR_OK;
2225 default:
2226 return WERR_INVALID_PARAMETER;
2231 * Some validations are done before the access check
2232 * and some after the access check
2234 security_level = security_session_user_level(session_info, NULL);
2235 if (security_level < SECURITY_ADMINISTRATOR) {
2236 return WERR_ACCESS_DENIED;
2239 if (state->_r.l2 != NULL) {
2241 * netr_LogonControl2
2243 if (state->r.in.level == 0x00000004) {
2244 return WERR_INVALID_LEVEL;
2248 switch (state->r.in.level) {
2249 case 0x00000001:
2250 break;
2252 case 0x00000002:
2253 switch (state->r.in.function_code) {
2254 case NETLOGON_CONTROL_REDISCOVER:
2255 case NETLOGON_CONTROL_TC_QUERY:
2256 case NETLOGON_CONTROL_TC_VERIFY:
2257 break;
2258 default:
2259 return WERR_INVALID_PARAMETER;
2262 break;
2264 case 0x00000003:
2265 break;
2267 case 0x00000004:
2268 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
2269 return WERR_INVALID_PARAMETER;
2272 break;
2274 default:
2275 return WERR_INVALID_LEVEL;
2278 switch (state->r.in.function_code) {
2279 case NETLOGON_CONTROL_REDISCOVER:
2280 case NETLOGON_CONTROL_TC_QUERY:
2281 case NETLOGON_CONTROL_TC_VERIFY:
2282 if (state->r.in.level != 2) {
2283 return WERR_INVALID_PARAMETER;
2286 if (state->r.in.data == NULL) {
2287 return WERR_INVALID_PARAMETER;
2290 if (state->r.in.data->domain == NULL) {
2291 return WERR_INVALID_PARAMETER;
2294 break;
2296 case NETLOGON_CONTROL_CHANGE_PASSWORD:
2297 if (state->r.in.level != 1) {
2298 return WERR_INVALID_PARAMETER;
2301 if (state->r.in.data == NULL) {
2302 return WERR_INVALID_PARAMETER;
2305 if (state->r.in.data->domain == NULL) {
2306 return WERR_INVALID_PARAMETER;
2309 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
2310 state->r.in.data->domain);
2311 if (!ok) {
2312 struct ldb_context *sam_ctx;
2314 sam_ctx = dcesrv_samdb_connect_as_system(state,
2315 state->dce_call);
2316 if (sam_ctx == NULL) {
2317 return WERR_DS_UNAVAILABLE;
2321 * Secrets for trusted domains can only be triggered on
2322 * the PDC.
2324 ok = samdb_is_pdc(sam_ctx);
2325 TALLOC_FREE(sam_ctx);
2326 if (!ok) {
2327 return WERR_INVALID_DOMAIN_ROLE;
2331 break;
2332 default:
2333 return WERR_NOT_SUPPORTED;
2336 irpc_handle = irpc_binding_handle_by_name(state,
2337 imsg_ctx,
2338 "winbind_server",
2339 &ndr_table_winbind);
2340 if (irpc_handle == NULL) {
2341 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2342 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2343 return WERR_SERVICE_NOT_FOUND;
2347 * 60 seconds timeout should be enough
2349 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2351 subreq = dcerpc_winbind_LogonControl_send(state,
2352 state->dce_call->event_ctx,
2353 irpc_handle,
2354 state->r.in.function_code,
2355 state->r.in.level,
2356 state->r.in.data,
2357 state->r.out.query);
2358 if (subreq == NULL) {
2359 return WERR_NOT_ENOUGH_MEMORY;
2361 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2362 tevent_req_set_callback(subreq,
2363 dcesrv_netr_LogonControl_base_done,
2364 state);
2366 return WERR_OK;
2369 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
2371 struct dcesrv_netr_LogonControl_base_state *state =
2372 tevent_req_callback_data(subreq,
2373 struct dcesrv_netr_LogonControl_base_state);
2374 NTSTATUS status;
2376 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
2377 &state->r.out.result);
2378 TALLOC_FREE(subreq);
2379 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
2380 state->r.out.result = WERR_TIMEOUT;
2381 } else if (!NT_STATUS_IS_OK(status)) {
2382 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2383 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
2384 nt_errstr(status)));
2387 if (state->_r.l2ex != NULL) {
2388 struct netr_LogonControl2Ex *r = state->_r.l2ex;
2389 r->out.result = state->r.out.result;
2390 } else if (state->_r.l2 != NULL) {
2391 struct netr_LogonControl2 *r = state->_r.l2;
2392 r->out.result = state->r.out.result;
2393 } else if (state->_r.l != NULL) {
2394 struct netr_LogonControl *r = state->_r.l;
2395 r->out.result = state->r.out.result;
2398 dcesrv_async_reply(state->dce_call);
2402 netr_LogonControl
2404 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2405 struct netr_LogonControl *r)
2407 struct dcesrv_netr_LogonControl_base_state *state;
2408 WERROR werr;
2410 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2411 if (state == NULL) {
2412 return WERR_NOT_ENOUGH_MEMORY;
2415 state->dce_call = dce_call;
2416 state->mem_ctx = mem_ctx;
2418 state->r.in.logon_server = r->in.logon_server;
2419 state->r.in.function_code = r->in.function_code;
2420 state->r.in.level = r->in.level;
2421 state->r.in.data = NULL;
2422 state->r.out.query = r->out.query;
2424 state->_r.l = r;
2426 werr = dcesrv_netr_LogonControl_base_call(state);
2428 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2429 return werr;
2432 return werr;
2436 netr_LogonControl2
2438 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2439 struct netr_LogonControl2 *r)
2441 struct dcesrv_netr_LogonControl_base_state *state;
2442 WERROR werr;
2444 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2445 if (state == NULL) {
2446 return WERR_NOT_ENOUGH_MEMORY;
2449 state->dce_call = dce_call;
2450 state->mem_ctx = mem_ctx;
2452 state->r.in.logon_server = r->in.logon_server;
2453 state->r.in.function_code = r->in.function_code;
2454 state->r.in.level = r->in.level;
2455 state->r.in.data = r->in.data;
2456 state->r.out.query = r->out.query;
2458 state->_r.l2 = r;
2460 werr = dcesrv_netr_LogonControl_base_call(state);
2462 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2463 return werr;
2466 return werr;
2470 netr_LogonControl2Ex
2472 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2473 struct netr_LogonControl2Ex *r)
2475 struct dcesrv_netr_LogonControl_base_state *state;
2476 WERROR werr;
2478 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2479 if (state == NULL) {
2480 return WERR_NOT_ENOUGH_MEMORY;
2483 state->dce_call = dce_call;
2484 state->mem_ctx = mem_ctx;
2486 state->r = *r;
2487 state->_r.l2ex = r;
2489 werr = dcesrv_netr_LogonControl_base_call(state);
2491 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2492 return werr;
2495 return werr;
2498 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2499 struct ldb_context *sam_ctx,
2500 struct netr_DomainTrustList *trusts,
2501 uint32_t trust_flags);
2504 netr_GetAnyDCName
2506 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2507 struct netr_GetAnyDCName *r)
2509 struct netr_DomainTrustList *trusts;
2510 struct ldb_context *sam_ctx;
2511 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2512 uint32_t i;
2513 WERROR werr;
2515 *r->out.dcname = NULL;
2517 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2518 /* if the domainname parameter wasn't set assume our domain */
2519 r->in.domainname = lpcfg_workgroup(lp_ctx);
2522 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2523 if (sam_ctx == NULL) {
2524 return WERR_DS_UNAVAILABLE;
2527 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2528 /* well we asked for a DC of our own domain */
2529 if (samdb_is_pdc(sam_ctx)) {
2530 /* we are the PDC of the specified domain */
2531 return WERR_NO_SUCH_DOMAIN;
2534 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2535 lpcfg_netbios_name(lp_ctx));
2536 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2538 return WERR_OK;
2541 /* Okay, now we have to consider the trusted domains */
2543 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2544 W_ERROR_HAVE_NO_MEMORY(trusts);
2546 trusts->count = 0;
2548 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2549 NETR_TRUST_FLAG_INBOUND
2550 | NETR_TRUST_FLAG_OUTBOUND);
2551 W_ERROR_NOT_OK_RETURN(werr);
2553 for (i = 0; i < trusts->count; i++) {
2554 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2555 /* FIXME: Here we need to find a DC for the specified
2556 * trusted domain. */
2558 /* return WERR_OK; */
2559 return WERR_NO_SUCH_DOMAIN;
2563 return WERR_NO_SUCH_DOMAIN;
2568 netr_DatabaseRedo
2570 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2571 struct netr_DatabaseRedo *r)
2573 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2578 netr_NetrEnumerateTrustedDomains
2580 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2581 struct netr_NetrEnumerateTrustedDomains *r)
2583 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2588 netr_LogonGetCapabilities
2590 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2591 struct netr_LogonGetCapabilities *r)
2593 struct netlogon_creds_CredentialState *creds;
2594 NTSTATUS status;
2596 switch (r->in.query_level) {
2597 case 1:
2598 break;
2599 case 2:
2600 break;
2601 default:
2603 * There would not be a way to marshall the
2604 * the response. Which would mean our final
2605 * ndr_push would fail an we would return
2606 * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA.
2608 * But it's important to match a Windows server
2609 * especially before KB5028166, see also our bug #15418
2610 * Otherwise Windows client would stop talking to us.
2612 DCESRV_FAULT(DCERPC_NCA_S_FAULT_INVALID_TAG);
2615 status = dcesrv_netr_creds_server_step_check(dce_call,
2616 mem_ctx,
2617 r->in.computer_name,
2618 r->in.credential,
2619 r->out.return_authenticator,
2620 &creds);
2621 if (!NT_STATUS_IS_OK(status)) {
2622 DEBUG(0,(__location__ " Bad credentials - error\n"));
2624 NT_STATUS_NOT_OK_RETURN(status);
2626 switch (r->in.query_level) {
2627 case 1:
2628 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2629 break;
2630 case 2:
2631 r->out.capabilities->requested_flags =
2632 creds->client_requested_flags;
2633 break;
2636 return NT_STATUS_OK;
2641 netr_NETRLOGONSETSERVICEBITS
2643 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2644 struct netr_NETRLOGONSETSERVICEBITS *r)
2646 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2651 netr_LogonGetTrustRid
2653 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2654 struct netr_LogonGetTrustRid *r)
2656 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2661 netr_NETRLOGONCOMPUTESERVERDIGEST
2663 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2664 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2666 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2671 netr_NETRLOGONCOMPUTECLIENTDIGEST
2673 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2674 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2676 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2682 netr_DsRGetSiteName
2684 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2685 struct netr_DsRGetSiteName *r)
2687 struct ldb_context *sam_ctx;
2689 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2690 if (sam_ctx == NULL) {
2691 return WERR_DS_UNAVAILABLE;
2695 * We assume to be a DC when we get called over NETLOGON. Hence we
2696 * get our site name always by using "samdb_server_site_name()"
2697 * and not "samdb_client_site_name()".
2699 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2700 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2702 return WERR_OK;
2707 fill in a netr_OneDomainInfo from our own domain/forest
2709 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2710 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2711 struct GUID domain_guid,
2712 struct netr_OneDomainInfo *info,
2713 bool is_trust_list)
2715 ZERO_STRUCTP(info);
2717 if (is_trust_list) {
2718 struct netr_trust_extension *te = NULL;
2719 struct netr_trust_extension_info *tei = NULL;
2721 /* w2k8 only fills this on trusted domains */
2722 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2723 if (te == NULL) {
2724 return NT_STATUS_NO_MEMORY;
2726 tei = &te->info;
2727 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2730 * We're always within a native forest
2732 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2733 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2735 /* For now we assume we're always the tree root */
2736 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2737 tei->parent_index = 0;
2739 tei->trust_type = our_tdo->trust_type;
2741 * This needs to be 0 instead of our_tdo->trust_attributes
2742 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2743 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2745 tei->trust_attributes = 0;
2747 info->trust_extension.info = te;
2750 if (is_trust_list) {
2751 info->dns_domainname.string = our_tdo->domain_name.string;
2753 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2754 info->dns_forestname.string = NULL;
2755 } else {
2756 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2757 our_tdo->domain_name.string);
2758 if (info->dns_domainname.string == NULL) {
2759 return NT_STATUS_NO_MEMORY;
2762 info->dns_forestname.string = info->dns_domainname.string;
2765 info->domainname.string = our_tdo->netbios_name.string;
2766 info->domain_sid = our_tdo->sid;
2767 info->domain_guid = domain_guid;
2769 return NT_STATUS_OK;
2773 fill in a netr_OneDomainInfo from a trust tdo
2775 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2776 struct GUID domain_guid,
2777 const struct lsa_TrustDomainInfoInfoEx *tdo,
2778 struct netr_OneDomainInfo *info)
2780 struct netr_trust_extension *te = NULL;
2781 struct netr_trust_extension_info *tei = NULL;
2783 ZERO_STRUCTP(info);
2785 /* w2k8 only fills this on trusted domains */
2786 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2787 if (te == NULL) {
2788 return NT_STATUS_NO_MEMORY;
2790 tei = &te->info;
2792 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2793 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2795 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2796 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2798 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2799 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2803 * TODO: once we support multiple domains within our forest,
2804 * we need to fill this correct (or let the caller do it
2805 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2807 tei->parent_index = 0;
2809 tei->trust_type = tdo->trust_type;
2810 tei->trust_attributes = tdo->trust_attributes;
2812 info->trust_extension.info = te;
2814 info->domainname.string = tdo->netbios_name.string;
2815 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2816 info->dns_domainname.string = tdo->domain_name.string;
2817 } else {
2818 info->dns_domainname.string = NULL;
2820 info->domain_sid = tdo->sid;
2821 info->domain_guid = domain_guid;
2823 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2824 info->dns_forestname.string = NULL;
2826 return NT_STATUS_OK;
2830 netr_LogonGetDomainInfo
2831 this is called as part of the ADS domain logon procedure.
2833 It has an important role in convaying details about the client, such
2834 as Operating System, Version, Service Pack etc.
2836 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2837 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2839 struct netlogon_creds_CredentialState *creds;
2840 const struct dom_sid *client_sid = NULL;
2841 static const char *const trusts_attrs[] = {"securityIdentifier",
2842 "flatName",
2843 "trustPartner",
2844 "trustAttributes",
2845 "trustDirection",
2846 "trustType",
2847 NULL};
2848 static const char *const attrs2[] = {"sAMAccountName",
2849 "dNSHostName",
2850 "msDS-SupportedEncryptionTypes",
2851 NULL};
2852 const char *sam_account_name, *old_dns_hostname;
2853 struct ldb_context *sam_ctx;
2854 const struct GUID *our_domain_guid = NULL;
2855 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2856 struct ldb_message **res1, *new_msg;
2857 struct ldb_result *trusts_res = NULL;
2858 struct ldb_dn *workstation_dn;
2859 struct netr_DomainInformation *domain_info;
2860 struct netr_LsaPolicyInformation *lsa_policy_info;
2861 struct auth_session_info *workstation_session_info = NULL;
2862 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2863 bool update_dns_hostname = true;
2864 int ret, i;
2865 NTSTATUS status;
2867 status = dcesrv_netr_creds_server_step_check(dce_call,
2868 mem_ctx,
2869 r->in.computer_name,
2870 r->in.credential,
2871 r->out.return_authenticator,
2872 &creds);
2873 if (!NT_STATUS_IS_OK(status)) {
2874 char* local = NULL;
2875 char* remote = NULL;
2876 TALLOC_CTX *frame = talloc_stackframe();
2877 remote = tsocket_address_string(dce_call->conn->remote_address,
2878 frame);
2879 local = tsocket_address_string(dce_call->conn->local_address,
2880 frame);
2881 DBG_ERR("Bad credentials - "
2882 "computer[%s] remote[%s] local[%s]\n",
2883 log_escape(frame, r->in.computer_name),
2884 remote,
2885 local);
2886 talloc_free(frame);
2888 NT_STATUS_NOT_OK_RETURN(status);
2889 client_sid = &creds->client_sid;
2891 /* We want to avoid connecting as system. */
2892 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2893 if (sam_ctx == NULL) {
2894 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2897 switch (r->in.level) {
2898 case 1: /* Domain information */
2900 if (r->in.query->workstation_info == NULL) {
2901 return NT_STATUS_INVALID_PARAMETER;
2904 /* Prepares the workstation DN */
2905 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2906 dom_sid_string(mem_ctx, client_sid));
2907 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2909 /* Get the workstation's session info from the database. */
2910 status = authsam_get_session_info_principal(mem_ctx,
2911 dce_call->conn->dce_ctx->lp_ctx,
2912 sam_ctx,
2913 NULL, /* principal */
2914 workstation_dn,
2915 0, /* session_info_flags */
2916 &workstation_session_info);
2917 if (!NT_STATUS_IS_OK(status)) {
2918 return status;
2922 * Reconnect to samdb as the workstation, now that we have its
2923 * session info. We do this so the database update can be
2924 * attributed to the workstation account in the audit logs --
2925 * otherwise it might be incorrectly attributed to
2926 * SID_NT_ANONYMOUS.
2928 sam_ctx = dcesrv_samdb_connect_session_info(mem_ctx,
2929 dce_call,
2930 workstation_session_info,
2931 workstation_session_info);
2932 if (sam_ctx == NULL) {
2933 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2936 /* Lookup for attributes in workstation object */
2937 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2938 attrs2);
2939 if (ret != 1) {
2940 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2943 /* Gets the sam account name which is checked against the DNS
2944 * hostname parameter. */
2945 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2946 "sAMAccountName",
2947 NULL);
2948 if (sam_account_name == NULL) {
2949 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2952 if (r->in.query->workstation_info->dns_hostname == NULL) {
2953 update_dns_hostname = false;
2956 /* Gets the old DNS hostname */
2957 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2958 "dNSHostName",
2959 NULL);
2962 * Updates the DNS hostname when the client wishes that the
2963 * server should handle this for him
2964 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
2965 * See MS-NRPC section 3.5.4.3.9
2967 if ((r->in.query->workstation_info->workstation_flags
2968 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2969 update_dns_hostname = false;
2972 /* Gets host information and put them into our directory */
2974 new_msg = ldb_msg_new(mem_ctx);
2975 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2977 new_msg->dn = workstation_dn;
2979 /* Sets the OS name */
2981 if (r->in.query->workstation_info->os_name.string == NULL) {
2982 return NT_STATUS_INVALID_PARAMETER;
2985 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2986 r->in.query->workstation_info->os_name.string);
2987 if (ret != LDB_SUCCESS) {
2988 return NT_STATUS_NO_MEMORY;
2992 * Sets information from "os_version". On an empty structure
2993 * the values are cleared.
2995 if (r->in.query->workstation_info->os_version.os != NULL) {
2996 struct netr_OsVersionInfoEx *os_version;
2997 const char *os_version_str;
2999 os_version = &r->in.query->workstation_info->os_version.os->os;
3001 if (os_version->CSDVersion == NULL) {
3002 return NT_STATUS_INVALID_PARAMETER;
3005 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
3006 os_version->MajorVersion,
3007 os_version->MinorVersion,
3008 os_version->BuildNumber);
3009 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
3011 if (strlen(os_version->CSDVersion) != 0) {
3012 ret = ldb_msg_add_string(new_msg,
3013 "operatingSystemServicePack",
3014 os_version->CSDVersion);
3015 } else {
3016 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
3017 "operatingSystemServicePack");
3019 if (ret != LDB_SUCCESS) {
3020 return NT_STATUS_NO_MEMORY;
3023 ret = ldb_msg_add_string(new_msg,
3024 "operatingSystemVersion",
3025 os_version_str);
3026 if (ret != LDB_SUCCESS) {
3027 return NT_STATUS_NO_MEMORY;
3029 } else {
3030 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
3031 "operatingSystemServicePack");
3032 if (ret != LDB_SUCCESS) {
3033 return NT_STATUS_NO_MEMORY;
3036 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
3037 "operatingSystemVersion");
3038 if (ret != LDB_SUCCESS) {
3039 return NT_STATUS_NO_MEMORY;
3044 * If the boolean "update_dns_hostname" remained true, then we
3045 * are fine to start the update.
3047 if (update_dns_hostname) {
3048 ret = ldb_msg_add_string(new_msg,
3049 "dNSHostname",
3050 r->in.query->workstation_info->dns_hostname);
3051 if (ret != LDB_SUCCESS) {
3052 return NT_STATUS_NO_MEMORY;
3055 /* This manual "servicePrincipalName" generation is
3056 * still needed! Since the update in the samldb LDB
3057 * module does only work if the entries already exist
3058 * which isn't always the case. */
3059 ret = ldb_msg_add_string(new_msg,
3060 "servicePrincipalName",
3061 talloc_asprintf(new_msg, "HOST/%s",
3062 r->in.computer_name));
3063 if (ret != LDB_SUCCESS) {
3064 return NT_STATUS_NO_MEMORY;
3067 ret = ldb_msg_add_string(new_msg,
3068 "servicePrincipalName",
3069 talloc_asprintf(new_msg, "HOST/%s",
3070 r->in.query->workstation_info->dns_hostname));
3071 if (ret != LDB_SUCCESS) {
3072 return NT_STATUS_NO_MEMORY;
3076 if (dsdb_replace(sam_ctx, new_msg, DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) != LDB_SUCCESS) {
3077 DEBUG(3,("Impossible to update samdb: %s\n",
3078 ldb_errstring(sam_ctx)));
3081 talloc_free(new_msg);
3083 /* Writes back the domain information */
3085 our_domain_guid = samdb_domain_guid(sam_ctx);
3086 if (our_domain_guid == NULL) {
3087 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3090 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
3091 if (!NT_STATUS_IS_OK(status)) {
3092 return status;
3095 status = dsdb_trust_search_tdos(sam_ctx,
3096 NULL, /* exclude */
3097 trusts_attrs,
3098 mem_ctx,
3099 &trusts_res);
3100 if (!NT_STATUS_IS_OK(status)) {
3101 return status;
3104 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
3105 NT_STATUS_HAVE_NO_MEMORY(domain_info);
3107 ZERO_STRUCTP(domain_info);
3109 /* Information about the local and trusted domains */
3111 status = fill_our_one_domain_info(mem_ctx,
3112 our_tdo,
3113 *our_domain_guid,
3114 &domain_info->primary_domain,
3115 false);
3116 if (!NT_STATUS_IS_OK(status)) {
3117 return status;
3120 domain_info->trusted_domain_count = trusts_res->count + 1;
3121 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
3122 struct netr_OneDomainInfo,
3123 domain_info->trusted_domain_count);
3124 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
3126 for (i=0; i < trusts_res->count; i++) {
3127 struct netr_OneDomainInfo *o =
3128 &domain_info->trusted_domains[i];
3129 /* we can't know the guid of trusts outside our forest */
3130 struct GUID trust_domain_guid = GUID_zero();
3131 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
3133 status = dsdb_trust_parse_tdo_info(mem_ctx,
3134 trusts_res->msgs[i],
3135 &tdo);
3136 if (!NT_STATUS_IS_OK(status)) {
3137 return status;
3140 status = fill_trust_one_domain_info(mem_ctx,
3141 trust_domain_guid,
3142 tdo,
3144 if (!NT_STATUS_IS_OK(status)) {
3145 return status;
3149 status = fill_our_one_domain_info(mem_ctx,
3150 our_tdo,
3151 *our_domain_guid,
3152 &domain_info->trusted_domains[i],
3153 true);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 return status;
3158 /* Sets the supported encryption types */
3159 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
3160 "msDS-SupportedEncryptionTypes",
3161 default_supported_enc_types);
3163 /* Other host domain information */
3165 lsa_policy_info = talloc(mem_ctx,
3166 struct netr_LsaPolicyInformation);
3167 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
3168 ZERO_STRUCTP(lsa_policy_info);
3170 domain_info->lsa_policy = *lsa_policy_info;
3172 /* The DNS hostname is only returned back when there is a chance
3173 * for a change. */
3174 if ((r->in.query->workstation_info->workstation_flags
3175 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
3176 domain_info->dns_hostname.string = old_dns_hostname;
3177 } else {
3178 domain_info->dns_hostname.string = NULL;
3181 domain_info->workstation_flags =
3182 r->in.query->workstation_info->workstation_flags & (
3183 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
3185 r->out.info->domain_info = domain_info;
3186 break;
3187 case 2: /* LSA policy information - not used at the moment */
3188 lsa_policy_info = talloc(mem_ctx,
3189 struct netr_LsaPolicyInformation);
3190 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
3191 ZERO_STRUCTP(lsa_policy_info);
3193 r->out.info->lsa_policy_info = lsa_policy_info;
3194 break;
3195 default:
3196 return NT_STATUS_INVALID_LEVEL;
3197 break;
3200 return NT_STATUS_OK;
3204 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3205 struct netr_ServerGetTrustInfo *r);
3208 netr_ServerPasswordGet
3210 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3211 struct netr_ServerPasswordGet *r)
3213 struct netr_ServerGetTrustInfo r2 = {};
3214 struct samr_Password old_owf_password = {};
3215 struct netr_TrustInfo *_ti = NULL;
3216 NTSTATUS status;
3218 r2.in.server_name = r->in.server_name;
3219 r2.in.account_name = r->in.account_name;
3220 r2.in.secure_channel_type = r->in.secure_channel_type;
3221 r2.in.computer_name = r->in.computer_name;
3222 r2.in.credential = r->in.credential;
3224 r2.out.return_authenticator = r->out.return_authenticator;
3225 r2.out.new_owf_password = r->out.password;
3226 r2.out.old_owf_password = &old_owf_password;
3227 r2.out.trust_info = &_ti;
3229 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3231 r->out.return_authenticator = r2.out.return_authenticator;
3232 r->out.password = r2.out.new_owf_password;
3234 ZERO_STRUCT(old_owf_password);
3235 switch (r->in.secure_channel_type) {
3236 case SEC_CHAN_BDC:
3237 case SEC_CHAN_RODC:
3238 break;
3239 default:
3240 ZERO_STRUCTP(r->out.password);
3241 return NT_STATUS_ACCESS_DENIED;
3244 return status;
3247 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
3248 TALLOC_CTX *mem_ctx,
3249 const struct dom_sid *user_sid,
3250 struct ldb_dn *obj_dn)
3252 static const char *rodc_attrs[] = {"msDS-NeverRevealGroup",
3253 "msDS-RevealOnDemandGroup",
3254 "userAccountControl",
3255 NULL};
3256 static const char *obj_attrs[] = {"tokenGroups",
3257 "objectSid",
3258 "UserAccountControl",
3259 "msDS-KrbTgtLinkBL",
3260 NULL};
3261 struct ldb_dn *rodc_dn;
3262 int ret;
3263 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
3264 WERROR werr;
3266 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
3267 dom_sid_string(mem_ctx, user_sid));
3268 if (!ldb_dn_validate(rodc_dn)) goto denied;
3271 * do the two searches we need
3272 * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list
3273 * out of the extended DNs
3275 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
3276 DSDB_SEARCH_SHOW_EXTENDED_DN);
3277 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
3279 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
3280 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
3282 werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx,
3283 user_sid,
3284 rodc_res->msgs[0],
3285 obj_res->msgs[0]);
3287 if (W_ERROR_IS_OK(werr)) {
3288 goto allowed;
3290 denied:
3291 return false;
3292 allowed:
3293 return true;
3298 netr_NetrLogonSendToSam
3300 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3301 struct netr_NetrLogonSendToSam *r)
3303 struct netlogon_creds_CredentialState *creds;
3304 const struct dom_sid *client_sid = NULL;
3305 struct ldb_context *sam_ctx;
3306 NTSTATUS nt_status;
3307 DATA_BLOB decrypted_blob;
3308 enum ndr_err_code ndr_err;
3309 struct netr_SendToSamBase base_msg = { 0 };
3310 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
3311 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
3313 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
3315 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3316 mem_ctx,
3317 r->in.computer_name,
3318 r->in.credential,
3319 r->out.return_authenticator,
3320 &creds);
3322 NT_STATUS_NOT_OK_RETURN(nt_status);
3323 client_sid = &creds->client_sid;
3325 switch (creds->secure_channel_type) {
3326 case SEC_CHAN_BDC:
3327 case SEC_CHAN_RODC:
3328 break;
3329 case SEC_CHAN_WKSTA:
3330 case SEC_CHAN_DNS_DOMAIN:
3331 case SEC_CHAN_DOMAIN:
3332 case SEC_CHAN_NULL:
3333 return NT_STATUS_ACCESS_DENIED;
3334 default:
3335 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
3336 creds->secure_channel_type));
3337 return NT_STATUS_INVALID_PARAMETER;
3340 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3341 if (sam_ctx == NULL) {
3342 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3345 /* Buffer is meant to be 16-bit aligned */
3347 nt_status = netlogon_creds_decrypt_SendToSam(creds,
3348 r->in.opaque_buffer,
3349 r->in.buffer_len,
3350 auth_type,
3351 auth_level);
3352 if (!NT_STATUS_IS_OK(nt_status)) {
3353 return nt_status;
3356 decrypted_blob.data = r->in.opaque_buffer;
3357 decrypted_blob.length = r->in.buffer_len;
3359 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
3360 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
3362 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3363 return NT_STATUS_INVALID_PARAMETER;
3366 /* Now 'send' to SAM */
3367 switch (base_msg.message_type) {
3368 case SendToSamResetBadPasswordCount:
3370 struct ldb_message *msg = ldb_msg_new(mem_ctx);
3371 struct ldb_dn *dn = NULL;
3372 int ret = 0;
3375 ret = ldb_transaction_start(sam_ctx);
3376 if (ret != LDB_SUCCESS) {
3377 return NT_STATUS_INTERNAL_ERROR;
3380 ret = dsdb_find_dn_by_guid(sam_ctx,
3381 mem_ctx,
3382 &base_msg.message.reset_bad_password.guid,
3384 &dn);
3385 if (ret != LDB_SUCCESS) {
3386 ldb_transaction_cancel(sam_ctx);
3387 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3390 if (creds->secure_channel_type == SEC_CHAN_RODC &&
3391 !sam_rodc_access_check(sam_ctx, mem_ctx, client_sid, dn)) {
3392 DEBUG(1, ("Client asked to reset bad password on "
3393 "an arbitrary user: %s\n",
3394 ldb_dn_get_linearized(dn)));
3395 ldb_transaction_cancel(sam_ctx);
3396 return NT_STATUS_INVALID_PARAMETER;
3399 msg->dn = dn;
3401 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
3402 if (ret != LDB_SUCCESS) {
3403 ldb_transaction_cancel(sam_ctx);
3404 return NT_STATUS_INVALID_PARAMETER;
3407 ret = dsdb_replace(sam_ctx, msg, 0);
3408 if (ret != LDB_SUCCESS) {
3409 ldb_transaction_cancel(sam_ctx);
3410 return NT_STATUS_INVALID_PARAMETER;
3413 ret = ldb_transaction_commit(sam_ctx);
3414 if (ret != LDB_SUCCESS) {
3415 ldb_transaction_cancel(sam_ctx);
3416 return NT_STATUS_INTERNAL_ERROR;
3419 break;
3421 default:
3422 return NT_STATUS_NOT_IMPLEMENTED;
3425 return NT_STATUS_OK;
3428 struct dcesrv_netr_DsRGetDCName_base_state {
3429 struct dcesrv_call_state *dce_call;
3430 TALLOC_CTX *mem_ctx;
3432 struct netr_DsRGetDCNameEx2 r;
3433 const char *client_site;
3435 struct {
3436 struct netr_DsRGetDCName *dc;
3437 struct netr_DsRGetDCNameEx *dcex;
3438 struct netr_DsRGetDCNameEx2 *dcex2;
3439 } _r;
3442 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
3444 /* Returns a nonzero value if multiple bits in 'val' are set. */
3445 static bool multiple_bits_set(uint32_t val)
3448 * Subtracting one from an integer has the effect of flipping all the
3449 * bits from the least significant bit up to and including the least
3450 * significant '1' bit. For example,
3452 * 0b101000 - 1
3453 * = 0b100111
3454 * ====
3456 * If 'val' is zero, all the bits will be flipped and thus the bitwise
3457 * AND of 'val' with 'val - 1' will be zero.
3459 * If the integer is nonzero, the least significant '1' bit will be
3460 * ANDed with a '0' bit and so will be reset in the final result, but
3461 * all other '1' bits will remain set. In other words, the effect of
3462 * this expression is to mask off the least significant bit that is
3463 * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
3464 * must contain multiple set bits.
3466 return val & (val - 1);
3469 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
3471 struct dcesrv_call_state *dce_call = state->dce_call;
3472 struct imessaging_context *imsg_ctx =
3473 dcesrv_imessaging_context(dce_call->conn);
3474 TALLOC_CTX *mem_ctx = state->mem_ctx;
3475 struct netr_DsRGetDCNameEx2 *r = &state->r;
3476 struct ldb_context *sam_ctx;
3477 struct netr_DsRGetDCNameInfo *info;
3478 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3479 const struct tsocket_address *local_address;
3480 char *local_addr = NULL;
3481 const struct tsocket_address *remote_address;
3482 char *remote_addr = NULL;
3483 const char *server_site_name;
3484 char *guid_str;
3485 struct netlogon_samlogon_response response;
3486 NTSTATUS status;
3487 const char *dc_name = NULL;
3488 const char *domain_name = NULL;
3489 const char *pdc_ip;
3490 bool different_domain = true;
3491 bool force_remote_lookup = false;
3492 uint32_t valid_flags;
3493 uint32_t this_dc_valid_flags;
3494 int dc_level;
3496 ZERO_STRUCTP(r->out.info);
3498 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3499 if (sam_ctx == NULL) {
3500 return WERR_DS_UNAVAILABLE;
3503 local_address = dcesrv_connection_get_local_address(dce_call->conn);
3504 if (tsocket_address_is_inet(local_address, "ip")) {
3505 local_addr = tsocket_address_inet_addr_string(local_address, state);
3506 W_ERROR_HAVE_NO_MEMORY(local_addr);
3509 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
3510 if (tsocket_address_is_inet(remote_address, "ip")) {
3511 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
3512 W_ERROR_HAVE_NO_MEMORY(remote_addr);
3515 /* "server_unc" is ignored by w2k3 */
3518 * With the following flags:
3519 * DS_FORCE_REDISCOVERY (Flag A)
3520 * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
3521 * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
3522 * DS_GC_SERVER_REQUIRED (Flag D)
3523 * DS_PDC_REQUIRED (Flag E)
3524 * DS_BACKGROUND_ONLY (Flag F)
3525 * DS_IP_REQUIRED (Flag G)
3526 * DS_KDC_REQUIRED (Flag H)
3527 * DS_TIMESERV_REQUIRED (Flag I)
3528 * DS_WRITABLE_REQUIRED (Flag J)
3529 * DS_GOOD_TIMESERV_PREFERRED (Flag K)
3530 * DS_AVOID_SELF (Flag L)
3531 * DS_ONLY_LDAP_NEEDED (Flag M)
3532 * DS_IS_FLAT_NAME (Flag N)
3533 * DS_IS_DNS_NAME (Flag O)
3534 * DS_TRY_NEXTCLOSEST_SITE (Flag P)
3535 * DS_DIRECTORY_SERVICE_6_REQUIRED (Flag Q)
3536 * DS_WEB_SERVICE_REQUIRED (Flag T)
3537 * DS_DIRECTORY_SERVICE_8_REQUIRED (Flag U)
3538 * DS_DIRECTORY_SERVICE_9_REQUIRED (Flag V)
3539 * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
3540 * DS_RETURN_DNS_NAME (Flag R)
3541 * DS_RETURN_FLAT_NAME (Flag S)
3543 * MS-NRPC 3.5.4.3.1 says:
3544 * ...
3545 * On receiving this call, the server MUST perform the following Flags
3546 * parameter validations:
3547 * - Flags D, E, and H MUST NOT be combined with each other.
3548 * - Flag N MUST NOT be combined with the O flag.
3549 * - Flag R MUST NOT be combined with the S flag.
3550 * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
3551 * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or H.
3552 * - Flag P MUST NOT be set when the SiteName parameter is provided.
3553 * The server MUST return ERROR_INVALID_FLAGS for any of the previously
3554 * mentioned conflicting combinations.
3555 * ...
3558 valid_flags = DSGETDC_VALID_FLAGS;
3560 if (r->in.flags & ~valid_flags) {
3562 * TODO: add tests to prove this (maybe based on the
3563 * msDS-Behavior-Version levels of dc, domain and/or forest
3565 return WERR_INVALID_FLAGS;
3568 /* Flags D, E, and H MUST NOT be combined with each other. */
3569 #define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
3570 if (multiple_bits_set(r->in.flags & _DEH)) {
3571 return WERR_INVALID_FLAGS;
3574 /* Flag N MUST NOT be combined with the O flag. */
3575 if (r->in.flags & DS_IS_FLAT_NAME &&
3576 r->in.flags & DS_IS_DNS_NAME) {
3577 return WERR_INVALID_FLAGS;
3580 /* Flag R MUST NOT be combined with the S flag. */
3581 if (r->in.flags & DS_RETURN_DNS_NAME &&
3582 r->in.flags & DS_RETURN_FLAT_NAME) {
3583 return WERR_INVALID_FLAGS;
3586 /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
3587 #define _BQUVW ( \
3588 DS_DIRECTORY_SERVICE_REQUIRED | \
3589 DS_DIRECTORY_SERVICE_6_REQUIRED | \
3590 DS_DIRECTORY_SERVICE_8_REQUIRED | \
3591 DS_DIRECTORY_SERVICE_9_REQUIRED | \
3592 DS_DIRECTORY_SERVICE_10_REQUIRED | \
3594 if (multiple_bits_set(r->in.flags & _BQUVW)) {
3595 return WERR_INVALID_FLAGS;
3599 * Flag K MUST NOT be combined with any of the flags:
3600 * B, C, D, E, or H.
3602 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
3603 r->in.flags &
3604 (DS_DIRECTORY_SERVICE_REQUIRED |
3605 DS_DIRECTORY_SERVICE_PREFERRED |
3606 DS_GC_SERVER_REQUIRED |
3607 DS_PDC_REQUIRED |
3608 DS_KDC_REQUIRED)) {
3609 return WERR_INVALID_FLAGS;
3612 /* Flag P MUST NOT be set when the SiteName parameter is provided. */
3613 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
3614 r->in.site_name) {
3615 return WERR_INVALID_FLAGS;
3619 * If we send an all-zero GUID, we should ignore it as winbind actually
3620 * checks it with a DNS query. Windows also appears to ignore it.
3622 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
3623 r->in.domain_guid = NULL;
3626 /* Attempt winbind search only if we suspect the domain is incorrect */
3627 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
3628 if (r->in.flags & DS_IS_FLAT_NAME) {
3629 if (strcasecmp_m(r->in.domain_name,
3630 lpcfg_sam_name(lp_ctx)) == 0) {
3631 different_domain = false;
3633 } else if (r->in.flags & DS_IS_DNS_NAME) {
3634 if (strcasecmp_m(r->in.domain_name,
3635 lpcfg_dnsdomain(lp_ctx)) == 0) {
3636 different_domain = false;
3638 } else {
3639 if (strcasecmp_m(r->in.domain_name,
3640 lpcfg_sam_name(lp_ctx)) == 0 ||
3641 strcasecmp_m(r->in.domain_name,
3642 lpcfg_dnsdomain(lp_ctx)) == 0) {
3643 different_domain = false;
3646 } else {
3648 * We need to be able to handle empty domain names, where we
3649 * revert to our domain by default.
3651 different_domain = false;
3654 if (!different_domain) {
3655 dc_level = dsdb_dc_functional_level(sam_ctx);
3658 * Do not return a local response if we do not support the
3659 * functional level or feature (eg web services)
3661 this_dc_valid_flags = valid_flags;
3663 /* Samba does not implement this */
3664 this_dc_valid_flags &= ~DS_WEB_SERVICE_REQUIRED;
3666 if (dc_level < DS_DOMAIN_FUNCTION_2012) {
3667 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_8_REQUIRED;
3669 if (dc_level < DS_DOMAIN_FUNCTION_2012_R2) {
3670 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_9_REQUIRED;
3672 if (dc_level < DS_DOMAIN_FUNCTION_2016) {
3673 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_10_REQUIRED;
3675 if (r->in.flags & ~this_dc_valid_flags) {
3676 DBG_INFO("Forcing remote lookup to find another DC "
3677 "in this domain %s with more features, "
3678 "as this Samba DC is Functional level %d but flags are 0x08%x\n",
3679 r->in.domain_name, dc_level, (unsigned int)r->in.flags);
3680 force_remote_lookup = true;
3684 /* Proof server site parameter "site_name" if it was specified */
3685 server_site_name = samdb_server_site_name(sam_ctx, state);
3686 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3687 if (force_remote_lookup
3688 || different_domain
3689 || (r->in.site_name != NULL &&
3690 (strcasecmp_m(r->in.site_name,
3691 server_site_name) != 0))) {
3693 struct dcerpc_binding_handle *irpc_handle = NULL;
3694 struct tevent_req *subreq = NULL;
3697 * Retrieve the client site to override the winbind response.
3699 * DO NOT use Windows fallback for client site.
3700 * In the case of multiple domains, this is plainly wrong.
3702 * Note: It's possible that the client may belong to multiple
3703 * subnets across domains. It's not clear what this would mean,
3704 * but here we only return what this domain knows.
3706 state->client_site = samdb_client_site_name(sam_ctx,
3707 state,
3708 remote_addr,
3709 NULL,
3710 false);
3712 irpc_handle = irpc_binding_handle_by_name(state,
3713 imsg_ctx,
3714 "winbind_server",
3715 &ndr_table_winbind);
3716 if (irpc_handle == NULL) {
3717 DEBUG(0,("Failed to get binding_handle for "
3718 "winbind_server task\n"));
3719 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3720 return WERR_SERVICE_NOT_FOUND;
3723 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3725 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3727 subreq = dcerpc_wbint_DsGetDcName_send(state,
3728 dce_call->event_ctx,
3729 irpc_handle,
3730 r->in.domain_name,
3731 r->in.domain_guid,
3732 r->in.site_name,
3733 r->in.flags,
3734 r->out.info);
3735 if (subreq == NULL) {
3736 return WERR_NOT_ENOUGH_MEMORY;
3739 tevent_req_set_callback(subreq,
3740 dcesrv_netr_DsRGetDCName_base_done,
3741 state);
3743 return WERR_OK;
3746 guid_str = r->in.domain_guid != NULL ?
3747 GUID_string(state, r->in.domain_guid) : NULL;
3749 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3750 r->in.domain_name,
3751 r->in.domain_name,
3752 NULL, guid_str,
3753 r->in.client_account,
3754 r->in.mask, remote_addr,
3755 NETLOGON_NT_VERSION_5EX_WITH_IP,
3756 lp_ctx, &response, true);
3757 if (!NT_STATUS_IS_OK(status)) {
3758 return ntstatus_to_werror(status);
3762 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3763 * (O) flag when the returned forest name is in DNS format. This is here
3764 * always the case (see below).
3766 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3768 if (r->in.flags & DS_RETURN_DNS_NAME) {
3769 dc_name = response.data.nt5_ex.pdc_dns_name;
3770 domain_name = response.data.nt5_ex.dns_domain;
3772 * According to MS-NRPC 2.2.1.2.1 we should set the
3773 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3774 * the returned information is in DNS form.
3776 response.data.nt5_ex.server_type |=
3777 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3778 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3779 dc_name = response.data.nt5_ex.pdc_name;
3780 domain_name = response.data.nt5_ex.domain_name;
3781 } else {
3784 * TODO: autodetect what we need to return
3785 * based on the given arguments
3787 dc_name = response.data.nt5_ex.pdc_name;
3788 domain_name = response.data.nt5_ex.domain_name;
3791 if (!dc_name || !dc_name[0]) {
3792 return WERR_NO_SUCH_DOMAIN;
3795 if (!domain_name || !domain_name[0]) {
3796 return WERR_NO_SUCH_DOMAIN;
3799 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3800 W_ERROR_HAVE_NO_MEMORY(info);
3801 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3802 dc_name[0] != '\\'? "\\\\":"",
3803 talloc_strdup(mem_ctx, dc_name));
3804 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3806 pdc_ip = local_addr;
3807 if (pdc_ip == NULL) {
3808 pdc_ip = "127.0.0.1";
3810 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3811 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3812 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3813 info->domain_guid = response.data.nt5_ex.domain_uuid;
3814 info->domain_name = domain_name;
3815 info->forest_name = response.data.nt5_ex.forest;
3816 info->dc_flags = response.data.nt5_ex.server_type;
3817 if (r->in.flags & DS_RETURN_DNS_NAME) {
3818 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3819 * returned if we are returning info->dc_unc containing a FQDN.
3820 * This attribute is called DomainControllerName in the specs,
3821 * it seems that we decide to return FQDN or netbios depending on
3822 * DS_RETURN_DNS_NAME.
3824 info->dc_flags |= DS_DNS_CONTROLLER;
3826 info->dc_site_name = response.data.nt5_ex.server_site;
3827 info->client_site_name = response.data.nt5_ex.client_site;
3829 *r->out.info = info;
3831 return WERR_OK;
3834 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3836 struct dcesrv_netr_DsRGetDCName_base_state *state =
3837 tevent_req_callback_data(subreq,
3838 struct dcesrv_netr_DsRGetDCName_base_state);
3839 struct dcesrv_call_state *dce_call = state->dce_call;
3840 NTSTATUS result, status;
3842 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3843 state->mem_ctx,
3844 &result);
3845 TALLOC_FREE(subreq);
3847 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3848 state->r.out.result = WERR_TIMEOUT;
3849 goto finished;
3852 if (!NT_STATUS_IS_OK(status)) {
3853 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3854 nt_errstr(status));
3855 state->r.out.result = WERR_GEN_FAILURE;
3856 goto finished;
3859 if (!NT_STATUS_IS_OK(result)) {
3860 DBG_NOTICE("DC location via winbind failed - %s\n",
3861 nt_errstr(result));
3862 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3863 goto finished;
3866 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3867 DBG_ERR("DC location via winbind returned no results\n");
3868 state->r.out.result = WERR_GEN_FAILURE;
3869 goto finished;
3872 if (state->r.out.info[0]->dc_unc == NULL) {
3873 DBG_ERR("DC location via winbind returned no DC unc\n");
3874 state->r.out.result = WERR_GEN_FAILURE;
3875 goto finished;
3879 * Either the supplied site name is NULL (possibly via
3880 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3881 * the input match name.
3883 * TODO: Currently this means that requests with NETBIOS domain
3884 * names can fail because they do not return the site name.
3886 if (state->r.in.site_name == NULL ||
3887 strcasecmp_m("", state->r.in.site_name) == 0 ||
3888 (state->r.out.info[0]->dc_site_name != NULL &&
3889 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3890 state->r.in.site_name) == 0)) {
3892 state->r.out.info[0]->client_site_name =
3893 talloc_move(state->mem_ctx, &state->client_site);
3896 * Make sure to return our DC UNC with // prefix.
3897 * Winbind currently doesn't send the leading slashes
3898 * for some reason.
3900 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3901 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3902 const char *dc_unc = NULL;
3904 dc_unc = talloc_asprintf(state->mem_ctx,
3905 "\\\\%s",
3906 state->r.out.info[0]->dc_unc);
3907 state->r.out.info[0]->dc_unc = dc_unc;
3910 state->r.out.result = WERR_OK;
3911 } else {
3912 state->r.out.info = NULL;
3913 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3916 finished:
3917 if (state->_r.dcex2 != NULL) {
3918 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3919 r->out.result = state->r.out.result;
3920 } else if (state->_r.dcex != NULL) {
3921 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3922 r->out.result = state->r.out.result;
3923 } else if (state->_r.dc != NULL) {
3924 struct netr_DsRGetDCName *r = state->_r.dc;
3925 r->out.result = state->r.out.result;
3928 TALLOC_FREE(state);
3929 dcesrv_async_reply(dce_call);
3933 netr_DsRGetDCNameEx2
3935 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3936 TALLOC_CTX *mem_ctx,
3937 struct netr_DsRGetDCNameEx2 *r)
3939 struct dcesrv_netr_DsRGetDCName_base_state *state;
3941 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3942 if (state == NULL) {
3943 return WERR_NOT_ENOUGH_MEMORY;
3946 state->dce_call = dce_call;
3947 state->mem_ctx = mem_ctx;
3949 state->r = *r;
3950 state->_r.dcex2 = r;
3952 return dcesrv_netr_DsRGetDCName_base_call(state);
3956 netr_DsRGetDCNameEx
3958 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3959 struct netr_DsRGetDCNameEx *r)
3961 struct dcesrv_netr_DsRGetDCName_base_state *state;
3963 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3964 if (state == NULL) {
3965 return WERR_NOT_ENOUGH_MEMORY;
3968 state->dce_call = dce_call;
3969 state->mem_ctx = mem_ctx;
3971 state->r.in.server_unc = r->in.server_unc;
3972 state->r.in.client_account = NULL;
3973 state->r.in.mask = 0;
3974 state->r.in.domain_guid = r->in.domain_guid;
3975 state->r.in.domain_name = r->in.domain_name;
3976 state->r.in.site_name = r->in.site_name;
3977 state->r.in.flags = r->in.flags;
3978 state->r.out.info = r->out.info;
3980 state->_r.dcex = r;
3982 return dcesrv_netr_DsRGetDCName_base_call(state);
3986 * netr_DsRGetDCName
3988 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3989 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3990 * insists that it be ignored.
3992 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3993 struct netr_DsRGetDCName *r)
3995 struct dcesrv_netr_DsRGetDCName_base_state *state;
3997 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3998 if (state == NULL) {
3999 return WERR_NOT_ENOUGH_MEMORY;
4002 state->dce_call = dce_call;
4003 state->mem_ctx = mem_ctx;
4005 state->r.in.server_unc = r->in.server_unc;
4006 state->r.in.client_account = NULL;
4007 state->r.in.mask = 0;
4008 state->r.in.domain_name = r->in.domain_name;
4009 state->r.in.domain_guid = r->in.domain_guid;
4011 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
4012 state->r.in.flags = r->in.flags;
4013 state->r.out.info = r->out.info;
4015 state->_r.dc = r;
4017 return dcesrv_netr_DsRGetDCName_base_call(state);
4020 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
4022 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4023 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
4025 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4030 netr_NetrEnumerateTrustedDomainsEx
4032 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4033 struct netr_NetrEnumerateTrustedDomainsEx *r)
4035 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4040 netr_DsRAddressToSitenamesExW
4042 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4043 struct netr_DsRAddressToSitenamesExW *r)
4045 struct ldb_context *sam_ctx;
4046 struct netr_DsRAddressToSitenamesExWCtr *ctr;
4047 sa_family_t sin_family;
4048 struct sockaddr_in *addr;
4049 #ifdef HAVE_IPV6
4050 struct sockaddr_in6 *addr6;
4051 char addr_str[INET6_ADDRSTRLEN];
4052 #else
4053 char addr_str[INET_ADDRSTRLEN];
4054 #endif
4055 char *subnet_name;
4056 const char *res;
4057 uint32_t i;
4059 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4060 if (sam_ctx == NULL) {
4061 return WERR_DS_UNAVAILABLE;
4064 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
4065 W_ERROR_HAVE_NO_MEMORY(ctr);
4067 *r->out.ctr = ctr;
4069 ctr->count = r->in.count;
4070 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
4071 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
4072 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
4073 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
4075 for (i=0; i<ctr->count; i++) {
4076 ctr->sitename[i].string = NULL;
4077 ctr->subnetname[i].string = NULL;
4079 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
4080 continue;
4082 /* The first two byte of the buffer are reserved for the
4083 * "sin_family" but for now only the first one is used. */
4084 sin_family = r->in.addresses[i].buffer[0];
4086 switch (sin_family) {
4087 case AF_INET:
4088 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
4089 continue;
4091 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
4092 res = inet_ntop(AF_INET, &addr->sin_addr,
4093 addr_str, sizeof(addr_str));
4094 break;
4095 #ifdef HAVE_IPV6
4096 case AF_INET6:
4097 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
4098 continue;
4100 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
4101 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
4102 addr_str, sizeof(addr_str));
4103 break;
4104 #endif
4105 default:
4106 continue;
4109 if (res == NULL) {
4110 continue;
4113 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
4114 mem_ctx,
4115 addr_str,
4116 &subnet_name,
4117 true);
4118 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
4119 ctr->subnetname[i].string = subnet_name;
4122 return WERR_OK;
4127 netr_DsRAddressToSitenamesW
4129 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4130 struct netr_DsRAddressToSitenamesW *r)
4132 struct netr_DsRAddressToSitenamesExW r2;
4133 struct netr_DsRAddressToSitenamesWCtr *ctr;
4134 uint32_t i;
4135 WERROR werr;
4137 ZERO_STRUCT(r2);
4139 r2.in.server_name = r->in.server_name;
4140 r2.in.count = r->in.count;
4141 r2.in.addresses = r->in.addresses;
4143 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
4144 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
4146 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
4147 W_ERROR_HAVE_NO_MEMORY(ctr);
4149 *r->out.ctr = ctr;
4151 ctr->count = r->in.count;
4152 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
4153 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
4155 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
4157 for (i=0; i<ctr->count; i++) {
4158 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
4161 return werr;
4166 netr_DsrGetDcSiteCoverageW
4168 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4169 struct netr_DsrGetDcSiteCoverageW *r)
4171 struct ldb_context *sam_ctx;
4172 struct DcSitesCtr *ctr;
4174 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4175 if (sam_ctx == NULL) {
4176 return WERR_DS_UNAVAILABLE;
4179 ctr = talloc(mem_ctx, struct DcSitesCtr);
4180 W_ERROR_HAVE_NO_MEMORY(ctr);
4182 *r->out.ctr = ctr;
4184 /* For now only return our default site */
4185 ctr->num_sites = 1;
4186 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
4187 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
4188 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
4189 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
4191 return WERR_OK;
4195 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
4196 struct ldb_context *sam_ctx,
4197 struct netr_DomainTrustList *trusts,
4198 uint32_t trust_flags)
4200 struct ldb_dn *system_dn;
4201 struct ldb_message **dom_res = NULL;
4202 static const char *trust_attrs[] = {"flatname",
4203 "trustPartner",
4204 "securityIdentifier",
4205 "trustDirection",
4206 "trustType",
4207 "trustAttributes",
4208 NULL};
4209 uint32_t n;
4210 int i;
4211 int ret;
4213 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
4214 NETR_TRUST_FLAG_OUTBOUND))) {
4215 return WERR_INVALID_FLAGS;
4218 system_dn = samdb_system_container_dn(sam_ctx, mem_ctx);
4219 if (system_dn == NULL) {
4220 return WERR_NOT_ENOUGH_MEMORY;
4223 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
4224 &dom_res, trust_attrs,
4225 "(objectclass=trustedDomain)");
4227 for (i = 0; i < ret; i++) {
4228 unsigned int trust_dir;
4229 uint32_t flags = 0;
4231 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
4232 "trustDirection", 0);
4234 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
4235 flags |= NETR_TRUST_FLAG_INBOUND;
4237 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
4238 flags |= NETR_TRUST_FLAG_OUTBOUND;
4241 if (!(flags & trust_flags)) {
4242 /* this trust direction was not requested */
4243 continue;
4246 n = trusts->count;
4247 trusts->array = talloc_realloc(trusts, trusts->array,
4248 struct netr_DomainTrust,
4249 n + 1);
4250 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4252 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
4253 if (!trusts->array[n].netbios_name) {
4254 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
4255 "without flatname\n",
4256 ldb_dn_get_linearized(dom_res[i]->dn)));
4259 trusts->array[n].trust_flags = flags;
4260 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
4261 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
4262 /* TODO: find if we have parent in the list */
4263 trusts->array[n].parent_index = 0;
4266 trusts->array[n].trust_type =
4267 ldb_msg_find_attr_as_uint(dom_res[i],
4268 "trustType", 0);
4269 trusts->array[n].trust_attributes =
4270 ldb_msg_find_attr_as_uint(dom_res[i],
4271 "trustAttributes", 0);
4273 if (trusts->array[n].trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
4274 trusts->array[n].dns_name = talloc_steal(
4275 trusts->array,
4276 ldb_msg_find_attr_as_string(dom_res[i],
4277 "trustPartner",
4278 NULL));
4279 } else {
4280 trusts->array[n].dns_name = NULL;
4283 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
4284 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
4285 struct dom_sid zero_sid;
4286 ZERO_STRUCT(zero_sid);
4287 trusts->array[n].sid =
4288 dom_sid_dup(trusts, &zero_sid);
4289 } else {
4290 trusts->array[n].sid =
4291 samdb_result_dom_sid(trusts, dom_res[i],
4292 "securityIdentifier");
4294 trusts->array[n].guid = GUID_zero();
4296 trusts->count = n + 1;
4299 talloc_free(dom_res);
4300 return WERR_OK;
4304 netr_DsrEnumerateDomainTrusts
4306 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
4307 TALLOC_CTX *mem_ctx,
4308 struct netr_DsrEnumerateDomainTrusts *r)
4310 struct netr_DomainTrustList *trusts;
4311 struct ldb_context *sam_ctx;
4312 int ret;
4313 struct ldb_message **dom_res;
4314 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
4315 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4316 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
4317 const char *p;
4318 WERROR werr;
4320 if (r->in.trust_flags & 0xFFFFFE00) {
4321 return WERR_INVALID_FLAGS;
4324 /* TODO: turn to hard check once we are sure this is 100% correct */
4325 if (!r->in.server_name) {
4326 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
4327 "But received NULL!\n", dnsdomain));
4328 } else {
4329 p = strchr(r->in.server_name, '.');
4330 if (!p) {
4331 DEBUG(3, ("Invalid domain! Expected name in domain "
4332 "[%s]. But received [%s]!\n",
4333 dnsdomain, r->in.server_name));
4334 p = r->in.server_name;
4335 } else {
4336 p++;
4338 if (strcasecmp(p, dnsdomain)) {
4339 DEBUG(3, ("Invalid domain! Expected name in domain "
4340 "[%s]. But received [%s]!\n",
4341 dnsdomain, r->in.server_name));
4345 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
4346 W_ERROR_HAVE_NO_MEMORY(trusts);
4348 trusts->count = 0;
4349 r->out.trusts = trusts;
4351 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4352 if (sam_ctx == NULL) {
4353 return WERR_GEN_FAILURE;
4356 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
4357 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
4359 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
4360 trusts, r->in.trust_flags);
4361 W_ERROR_NOT_OK_RETURN(werr);
4364 /* NOTE: we currently are always the root of the forest */
4365 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
4366 uint32_t n = trusts->count;
4368 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
4369 &dom_res, dom_attrs);
4370 if (ret != 1) {
4371 return WERR_GEN_FAILURE;
4374 trusts->count = n + 1;
4375 trusts->array = talloc_realloc(trusts, trusts->array,
4376 struct netr_DomainTrust,
4377 trusts->count);
4378 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4380 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
4381 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
4382 trusts->array[n].trust_flags =
4383 NETR_TRUST_FLAG_NATIVE |
4384 NETR_TRUST_FLAG_TREEROOT |
4385 NETR_TRUST_FLAG_IN_FOREST |
4386 NETR_TRUST_FLAG_PRIMARY;
4387 /* we are always the root domain for now */
4388 trusts->array[n].parent_index = 0;
4389 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
4390 trusts->array[n].trust_attributes = 0;
4391 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
4392 dom_res[0],
4393 "objectSid");
4394 trusts->array[n].guid = samdb_result_guid(dom_res[0],
4395 "objectGUID");
4396 talloc_free(dom_res);
4399 return WERR_OK;
4404 netr_DsrDeregisterDNSHostRecords
4406 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4407 struct netr_DsrDeregisterDNSHostRecords *r)
4409 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4414 netr_ServerTrustPasswordsGet
4416 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4417 struct netr_ServerTrustPasswordsGet *r)
4419 struct netr_ServerGetTrustInfo r2 = {};
4420 struct netr_TrustInfo *_ti = NULL;
4421 NTSTATUS status;
4423 r2.in.server_name = r->in.server_name;
4424 r2.in.account_name = r->in.account_name;
4425 r2.in.secure_channel_type = r->in.secure_channel_type;
4426 r2.in.computer_name = r->in.computer_name;
4427 r2.in.credential = r->in.credential;
4429 r2.out.return_authenticator = r->out.return_authenticator;
4430 r2.out.new_owf_password = r->out.new_owf_password;
4431 r2.out.old_owf_password = r->out.old_owf_password;
4432 r2.out.trust_info = &_ti;
4434 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
4436 r->out.return_authenticator = r2.out.return_authenticator;
4437 r->out.new_owf_password = r2.out.new_owf_password;
4438 r->out.old_owf_password = r2.out.old_owf_password;
4440 return status;
4444 netr_DsRGetForestTrustInformation
4446 struct dcesrv_netr_DsRGetForestTrustInformation_state {
4447 struct dcesrv_call_state *dce_call;
4448 TALLOC_CTX *mem_ctx;
4449 struct netr_DsRGetForestTrustInformation *r;
4452 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
4454 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
4455 TALLOC_CTX *mem_ctx,
4456 struct netr_DsRGetForestTrustInformation *r)
4458 struct auth_session_info *session_info =
4459 dcesrv_call_session_info(dce_call);
4460 struct imessaging_context *imsg_ctx =
4461 dcesrv_imessaging_context(dce_call->conn);
4462 enum security_user_level security_level;
4463 struct ldb_context *sam_ctx = NULL;
4464 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
4465 struct dcerpc_binding_handle *irpc_handle = NULL;
4466 struct tevent_req *subreq = NULL;
4467 struct ldb_dn *domain_dn = NULL;
4468 struct ldb_dn *forest_dn = NULL;
4469 int cmp;
4470 int forest_level;
4472 security_level = security_session_user_level(session_info, NULL);
4473 if (security_level < SECURITY_USER) {
4474 return WERR_ACCESS_DENIED;
4477 if (r->in.flags & 0xFFFFFFFE) {
4478 return WERR_INVALID_FLAGS;
4481 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4482 if (sam_ctx == NULL) {
4483 return WERR_GEN_FAILURE;
4486 domain_dn = ldb_get_default_basedn(sam_ctx);
4487 if (domain_dn == NULL) {
4488 return WERR_GEN_FAILURE;
4491 forest_dn = ldb_get_root_basedn(sam_ctx);
4492 if (forest_dn == NULL) {
4493 return WERR_GEN_FAILURE;
4496 cmp = ldb_dn_compare(domain_dn, forest_dn);
4497 if (cmp != 0) {
4498 return WERR_NERR_ACFNOTLOADED;
4501 forest_level = dsdb_forest_functional_level(sam_ctx);
4502 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4503 return WERR_INVALID_FUNCTION;
4506 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
4507 if (!samdb_is_pdc(sam_ctx)) {
4508 return WERR_NERR_NOTPRIMARY;
4511 if (r->in.trusted_domain_name == NULL) {
4512 return WERR_INVALID_FLAGS;
4516 if (r->in.trusted_domain_name == NULL) {
4517 NTSTATUS status;
4520 * information about our own domain
4522 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4523 r->out.forest_trust_info);
4524 if (!NT_STATUS_IS_OK(status)) {
4525 return ntstatus_to_werror(status);
4528 return WERR_OK;
4532 * Forward the request to winbindd
4535 state = talloc_zero(mem_ctx,
4536 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4537 if (state == NULL) {
4538 return WERR_NOT_ENOUGH_MEMORY;
4540 state->dce_call = dce_call;
4541 state->mem_ctx = mem_ctx;
4542 state->r = r;
4544 irpc_handle = irpc_binding_handle_by_name(state,
4545 imsg_ctx,
4546 "winbind_server",
4547 &ndr_table_winbind);
4548 if (irpc_handle == NULL) {
4549 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
4550 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4551 return WERR_SERVICE_NOT_FOUND;
4555 * 60 seconds timeout should be enough
4557 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
4559 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
4560 state->dce_call->event_ctx,
4561 irpc_handle,
4562 r->in.trusted_domain_name,
4563 r->in.flags,
4564 r->out.forest_trust_info);
4565 if (subreq == NULL) {
4566 return WERR_NOT_ENOUGH_MEMORY;
4568 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4569 tevent_req_set_callback(subreq,
4570 dcesrv_netr_DsRGetForestTrustInformation_done,
4571 state);
4573 return WERR_OK;
4576 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
4578 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
4579 tevent_req_callback_data(subreq,
4580 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4581 NTSTATUS status;
4583 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
4584 state->mem_ctx,
4585 &state->r->out.result);
4586 TALLOC_FREE(subreq);
4587 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
4588 state->r->out.result = WERR_TIMEOUT;
4589 } else if (!NT_STATUS_IS_OK(status)) {
4590 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4591 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
4592 nt_errstr(status)));
4595 dcesrv_async_reply(state->dce_call);
4599 netr_GetForestTrustInformation
4601 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
4602 TALLOC_CTX *mem_ctx,
4603 struct netr_GetForestTrustInformation *r)
4605 struct netlogon_creds_CredentialState *creds = NULL;
4606 struct ldb_context *sam_ctx = NULL;
4607 struct ldb_dn *domain_dn = NULL;
4608 struct ldb_dn *forest_dn = NULL;
4609 int cmp;
4610 int forest_level;
4611 NTSTATUS status;
4613 status = dcesrv_netr_creds_server_step_check(dce_call,
4614 mem_ctx,
4615 r->in.computer_name,
4616 r->in.credential,
4617 r->out.return_authenticator,
4618 &creds);
4619 if (!NT_STATUS_IS_OK(status)) {
4620 return status;
4623 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
4624 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
4625 return NT_STATUS_NOT_IMPLEMENTED;
4628 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4629 if (sam_ctx == NULL) {
4630 return NT_STATUS_INTERNAL_ERROR;
4633 /* TODO: check r->in.server_name is our name */
4635 domain_dn = ldb_get_default_basedn(sam_ctx);
4636 if (domain_dn == NULL) {
4637 return NT_STATUS_INTERNAL_ERROR;
4640 forest_dn = ldb_get_root_basedn(sam_ctx);
4641 if (forest_dn == NULL) {
4642 return NT_STATUS_INTERNAL_ERROR;
4645 cmp = ldb_dn_compare(domain_dn, forest_dn);
4646 if (cmp != 0) {
4647 return NT_STATUS_INVALID_DOMAIN_STATE;
4650 forest_level = dsdb_forest_functional_level(sam_ctx);
4651 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4652 return NT_STATUS_INVALID_DOMAIN_STATE;
4655 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4656 r->out.forest_trust_info);
4657 if (!NT_STATUS_IS_OK(status)) {
4658 return status;
4661 return NT_STATUS_OK;
4666 netr_ServerGetTrustInfo
4668 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4669 struct netr_ServerGetTrustInfo *r)
4671 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4672 struct netlogon_creds_CredentialState *creds = NULL;
4673 const struct dom_sid *client_sid = NULL;
4674 struct ldb_context *sam_ctx = NULL;
4675 static const char * const attrs[] = {
4676 "unicodePwd",
4677 "sAMAccountName",
4678 "userAccountControl",
4679 /* Required for Group Managed Service Accounts. */
4680 "msDS-ManagedPasswordId",
4681 "msDS-ManagedPasswordInterval",
4682 "objectClass",
4683 "objectSid",
4684 "whenCreated",
4685 NULL
4687 struct ldb_message **res = NULL;
4688 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4689 NTSTATUS nt_status;
4690 int ret;
4691 const char *asid = NULL;
4692 uint32_t uac = 0;
4693 const char *aname = NULL;
4694 struct ldb_message *tdo_msg = NULL;
4695 const char * const tdo_attrs[] = {
4696 "trustAuthIncoming",
4697 "trustAttributes",
4698 NULL
4700 struct netr_TrustInfo *trust_info = NULL;
4701 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
4702 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
4704 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
4706 ZERO_STRUCTP(r->out.new_owf_password);
4707 ZERO_STRUCTP(r->out.old_owf_password);
4709 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4710 mem_ctx,
4711 r->in.computer_name,
4712 r->in.credential,
4713 r->out.return_authenticator,
4714 &creds);
4715 if (!NT_STATUS_IS_OK(nt_status)) {
4716 return nt_status;
4718 client_sid = &creds->client_sid;
4720 /* TODO: check r->in.server_name is our name */
4722 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4723 return NT_STATUS_INVALID_PARAMETER;
4726 if (r->in.secure_channel_type != creds->secure_channel_type) {
4727 return NT_STATUS_INVALID_PARAMETER;
4730 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4731 return NT_STATUS_INVALID_PARAMETER;
4734 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
4735 if (sam_ctx == NULL) {
4736 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4739 asid = ldap_encode_ndr_dom_sid(mem_ctx, client_sid);
4740 if (asid == NULL) {
4741 return NT_STATUS_NO_MEMORY;
4745 struct ldb_result *result = NULL;
4747 ret = dsdb_search(sam_ctx,
4748 mem_ctx,
4749 &result,
4750 ldb_get_default_basedn(sam_ctx),
4751 LDB_SCOPE_SUBTREE,
4752 attrs,
4753 DSDB_SEARCH_ONE_ONLY |
4754 DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
4755 "(&(objectClass=user)(objectSid=%s))",
4756 asid);
4757 if (ret) {
4758 return NT_STATUS_ACCOUNT_DISABLED;
4761 res = talloc_steal(mem_ctx, result->msgs);
4762 talloc_free(result);
4765 switch (creds->secure_channel_type) {
4766 case SEC_CHAN_DNS_DOMAIN:
4767 case SEC_CHAN_DOMAIN:
4768 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4770 if (uac & UF_ACCOUNTDISABLE) {
4771 return NT_STATUS_ACCOUNT_DISABLED;
4774 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4775 return NT_STATUS_ACCOUNT_DISABLED;
4778 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4779 if (aname == NULL) {
4780 return NT_STATUS_ACCOUNT_DISABLED;
4783 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4784 SEC_CHAN_DOMAIN, aname,
4785 tdo_attrs, mem_ctx, &tdo_msg);
4786 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4787 return NT_STATUS_ACCOUNT_DISABLED;
4789 if (!NT_STATUS_IS_OK(nt_status)) {
4790 return nt_status;
4793 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4794 &curNtHash,
4795 &prevNtHash);
4796 if (!NT_STATUS_IS_OK(nt_status)) {
4797 return nt_status;
4800 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4801 if (trust_info == NULL) {
4802 return NT_STATUS_NO_MEMORY;
4805 trust_info->count = 1;
4806 trust_info->data = talloc_array(trust_info, uint32_t,
4807 trust_info->count);
4808 if (trust_info->data == NULL) {
4809 return NT_STATUS_NO_MEMORY;
4812 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4813 "trustAttributes",
4815 break;
4817 default:
4818 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4819 res[0],
4820 &curNtHash);
4821 if (!NT_STATUS_IS_OK(nt_status)) {
4822 return nt_status;
4825 prevNtHash = talloc(mem_ctx, struct samr_Password);
4826 if (prevNtHash == NULL) {
4827 return NT_STATUS_NO_MEMORY;
4830 E_md4hash("", prevNtHash->hash);
4831 break;
4834 if (curNtHash != NULL) {
4835 *r->out.new_owf_password = *curNtHash;
4836 nt_status = netlogon_creds_encrypt_samr_Password(creds,
4837 r->out.new_owf_password,
4838 auth_type,
4839 auth_level);
4840 if (!NT_STATUS_IS_OK(nt_status)) {
4841 return nt_status;
4844 if (prevNtHash != NULL) {
4845 *r->out.old_owf_password = *prevNtHash;
4846 nt_status = netlogon_creds_encrypt_samr_Password(creds,
4847 r->out.old_owf_password,
4848 auth_type,
4849 auth_level);
4850 if (!NT_STATUS_IS_OK(nt_status)) {
4851 return nt_status;
4855 if (trust_info != NULL) {
4856 *r->out.trust_info = trust_info;
4859 return NT_STATUS_OK;
4863 netr_Unused47
4865 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4866 struct netr_Unused47 *r)
4868 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4872 struct netr_dnsupdate_RODC_state {
4873 struct dcesrv_call_state *dce_call;
4874 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4875 struct dnsupdate_RODC *r2;
4879 called when the forwarded RODC dns update request is finished
4881 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4883 struct netr_dnsupdate_RODC_state *st =
4884 tevent_req_callback_data(subreq,
4885 struct netr_dnsupdate_RODC_state);
4886 NTSTATUS status;
4888 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4889 TALLOC_FREE(subreq);
4890 if (!NT_STATUS_IS_OK(status)) {
4891 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4892 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4895 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4897 dcesrv_async_reply(st->dce_call);
4901 netr_DsrUpdateReadOnlyServerDnsRecords
4903 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4904 TALLOC_CTX *mem_ctx,
4905 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4907 struct netlogon_creds_CredentialState *creds;
4908 NTSTATUS nt_status;
4909 struct dcerpc_binding_handle *binding_handle;
4910 struct netr_dnsupdate_RODC_state *st;
4911 struct tevent_req *subreq;
4912 struct imessaging_context *imsg_ctx =
4913 dcesrv_imessaging_context(dce_call->conn);
4914 struct dom_sid *client_sid = NULL;
4916 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4917 mem_ctx,
4918 r->in.computer_name,
4919 r->in.credential,
4920 r->out.return_authenticator,
4921 &creds);
4922 NT_STATUS_NOT_OK_RETURN(nt_status);
4923 client_sid = &creds->client_sid;
4925 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4926 return NT_STATUS_ACCESS_DENIED;
4929 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4930 NT_STATUS_HAVE_NO_MEMORY(st);
4932 st->dce_call = dce_call;
4933 st->r = r;
4934 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4935 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4937 st->r2->in.dom_sid = client_sid;
4938 st->r2->in.site_name = r->in.site_name;
4939 st->r2->in.dns_ttl = r->in.dns_ttl;
4940 st->r2->in.dns_names = r->in.dns_names;
4941 st->r2->out.dns_names = r->out.dns_names;
4943 binding_handle = irpc_binding_handle_by_name(st,
4944 imsg_ctx,
4945 "dnsupdate",
4946 &ndr_table_irpc);
4947 if (binding_handle == NULL) {
4948 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4949 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4950 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4953 /* forward the call */
4954 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4955 binding_handle, st->r2);
4956 NT_STATUS_HAVE_NO_MEMORY(subreq);
4958 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4960 /* setup the callback */
4961 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4963 return NT_STATUS_OK;
4966 DCESRV_NOT_USED_ON_WIRE(netr_Opnum49NotUsedOnWire)
4967 DCESRV_NOT_USED_ON_WIRE(netr_Opnum50NotUsedOnWire)
4968 DCESRV_NOT_USED_ON_WIRE(netr_Opnum51NotUsedOnWire)
4969 DCESRV_NOT_USED_ON_WIRE(netr_Opnum52NotUsedOnWire)
4970 DCESRV_NOT_USED_ON_WIRE(netr_Opnum53NotUsedOnWire)
4973 netr_ChainSetClientAttributes
4975 static NTSTATUS dcesrv_netr_ChainSetClientAttributes(struct dcesrv_call_state *dce_call,
4976 TALLOC_CTX *mem_ctx,
4977 struct netr_ChainSetClientAttributes *r)
4979 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4982 DCESRV_NOT_USED_ON_WIRE(netr_Opnum55NotUsedOnWire)
4983 DCESRV_NOT_USED_ON_WIRE(netr_Opnum56NotUsedOnWire)
4984 DCESRV_NOT_USED_ON_WIRE(netr_Opnum57NotUsedOnWire)
4985 DCESRV_NOT_USED_ON_WIRE(netr_Opnum58NotUsedOnWire)
4987 static NTSTATUS dcesrv_netr_ServerAuthenticateKerberos_cb(
4988 struct dcesrv_call_state *dce_call,
4989 const struct netlogon_server_pipe_state *challenge,
4990 const struct netr_ServerAuthenticate3 *r,
4991 uint32_t client_flags,
4992 const struct dom_sid *client_sid,
4993 uint32_t negotiate_flags,
4994 const struct ldb_message *sam_msg,
4995 const struct ldb_message *tdo_msg,
4996 TALLOC_CTX *mem_ctx,
4997 struct netlogon_creds_CredentialState **_creds)
4999 TALLOC_CTX *frame = talloc_stackframe();
5000 struct netlogon_creds_CredentialState *creds = NULL;
5001 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
5002 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
5003 struct auth_session_info *session_info =
5004 dcesrv_call_session_info(dce_call);
5005 const struct dom_sid *auth_sid =
5006 &session_info->security_token->sids[0];
5008 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
5011 * The client needs to come via a
5012 * connection encrypted with kerberos.
5014 * And the SID from the PAC needs to
5015 * match the sid for the requested
5016 * account name
5019 if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
5020 TALLOC_FREE(frame);
5021 return NT_STATUS_ACCESS_DENIED;
5023 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
5024 TALLOC_FREE(frame);
5025 return NT_STATUS_ACCESS_DENIED;
5028 if (!dom_sid_equal(client_sid, auth_sid)) {
5029 TALLOC_FREE(frame);
5030 return NT_STATUS_ACCESS_DENIED;
5033 SMB_ASSERT(r->in.credentials == NULL);
5034 SMB_ASSERT(r->out.return_credentials == NULL);
5036 creds = netlogon_creds_kerberos_init(mem_ctx,
5037 r->in.account_name,
5038 r->in.computer_name,
5039 r->in.secure_channel_type,
5040 client_flags,
5041 client_sid,
5042 negotiate_flags);
5043 if (creds == NULL) {
5044 TALLOC_FREE(frame);
5045 return NT_STATUS_ACCESS_DENIED;
5048 *_creds = creds;
5049 TALLOC_FREE(frame);
5050 return NT_STATUS_OK;
5054 netr_ServerAuthenticateKerberos
5056 static NTSTATUS dcesrv_netr_ServerAuthenticateKerberos(struct dcesrv_call_state *dce_call,
5057 TALLOC_CTX *mem_ctx,
5058 struct netr_ServerAuthenticateKerberos *r)
5060 NTSTATUS status;
5061 struct dom_sid *sid = NULL;
5062 const char *trust_account_for_search = NULL;
5063 const char *trust_account_in_db = NULL;
5064 struct imessaging_context *imsg_ctx =
5065 dcesrv_imessaging_context(dce_call->conn);
5066 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
5067 bool server_support_krb5_netlogon = lpcfg_server_support_krb5_netlogon(lp_ctx);
5068 struct auth_usersupplied_info ui = {
5069 .local_host = dce_call->conn->local_address,
5070 .remote_host = dce_call->conn->remote_address,
5071 .client = {
5072 .account_name = r->in.account_name,
5073 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
5075 .service_description = "NETLOGON",
5076 .auth_description = "ServerAuthenticate",
5077 .netlogon_trust_account = {
5078 .computer_name = r->in.computer_name,
5079 .negotiate_flags = *r->in.negotiate_flags,
5080 .authenticate_kerberos = true,
5081 .secure_channel_type = r->in.account_type,
5084 struct netr_ServerAuthenticate3 r3 = {
5085 .in = {
5086 .server_name = r->in.server_name,
5087 .account_name = r->in.account_name,
5088 .secure_channel_type = r->in.account_type,
5089 .computer_name = r->in.computer_name,
5090 .credentials = NULL,
5091 .negotiate_flags = r->in.negotiate_flags,
5093 .out = {
5094 .return_credentials = NULL,
5095 .rid = r->out.rid,
5096 .negotiate_flags = r->out.negotiate_flags,
5097 .result = NT_STATUS_INTERNAL_ERROR,
5100 dcesrv_netr_ServerAuthenticateGenericCallback_fn auth_fn =
5101 dcesrv_netr_ServerAuthenticateKerberos_cb;
5103 if (!server_support_krb5_netlogon) {
5104 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5107 status = dcesrv_netr_ServerAuthenticateGeneric(dce_call,
5108 mem_ctx,
5109 &r3,
5110 auth_fn,
5111 &trust_account_for_search,
5112 &trust_account_in_db,
5113 &sid);
5114 ui.netlogon_trust_account.sid = sid;
5115 ui.netlogon_trust_account.account_name = trust_account_in_db;
5116 ui.mapped.account_name = trust_account_for_search;
5117 log_authentication_event(
5118 imsg_ctx,
5119 dce_call->conn->dce_ctx->lp_ctx,
5120 NULL,
5121 &ui,
5122 status,
5123 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
5124 trust_account_in_db,
5125 sid,
5126 NULL /* client_audit_info */,
5127 NULL /* server_audit_info */);
5129 return status;
5132 /* include the generated boilerplate */
5133 #include "librpc/gen_ndr/ndr_netlogon_s.c"