drsuapi.idl: fix source_dsa spelling
[samba4-gss.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob9d7fc4ac0da9bbfa1579c5b992d8260d8bdc7b40
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 "objectGUID",
629 NULL};
630 char *encoded_name = NULL;
631 size_t len;
632 const char *flatname = NULL;
633 char trailer = '$';
634 bool require_trailer = true;
635 const char *netbios = NULL;
636 const char *dns = NULL;
638 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
639 trailer = '.';
640 require_trailer = false;
643 encoded_name = ldb_binary_encode_string(mem_ctx,
644 r->in.account_name);
645 if (encoded_name == NULL) {
646 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
647 dce_call, r, pipe_state, negotiate_flags,
648 NULL, /* trust_account_in_db */
649 NT_STATUS_NO_MEMORY);
652 len = strlen(encoded_name);
653 if (len < 2) {
654 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
655 dce_call, r, pipe_state, negotiate_flags,
656 NULL, /* trust_account_in_db */
657 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
660 if (require_trailer && encoded_name[len - 1] != trailer) {
661 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
662 dce_call, r, pipe_state, negotiate_flags,
663 NULL, /* trust_account_in_db */
664 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
666 encoded_name[len - 1] = '\0';
668 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
669 dns = encoded_name;
670 } else {
671 netbios = encoded_name;
674 nt_status = dsdb_trust_search_tdo(sam_ctx,
675 netbios, dns,
676 tdo_attrs, mem_ctx, &tdo_msg);
677 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
678 DEBUG(2, ("Client asked for a trusted domain secure channel, "
679 "but there's no tdo for [%s] => [%s] \n",
680 log_escape(mem_ctx, r->in.account_name),
681 encoded_name));
682 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
683 dce_call, r, pipe_state, negotiate_flags,
684 NULL, /* trust_account_in_db */
685 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
687 if (!NT_STATUS_IS_OK(nt_status)) {
688 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
689 dce_call, r, pipe_state, negotiate_flags,
690 NULL, /* trust_account_in_db */
691 nt_status);
694 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
695 if (flatname == NULL) {
696 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
697 dce_call, r, pipe_state, negotiate_flags,
698 NULL, /* trust_account_in_db */
699 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
702 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
703 if (*trust_account_for_search == NULL) {
704 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
705 dce_call, r, pipe_state, negotiate_flags,
706 NULL, /* trust_account_in_db */
707 NT_STATUS_NO_MEMORY);
709 } else {
710 *trust_account_for_search = r->in.account_name;
714 struct ldb_result *res = NULL;
715 int ret;
717 /* pull the user attributes */
718 ret = dsdb_search(
719 sam_ctx,
720 mem_ctx,
721 &res,
722 ldb_get_default_basedn(sam_ctx),
723 LDB_SCOPE_SUBTREE,
724 attrs,
725 DSDB_SEARCH_ONE_ONLY | DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
726 "(&(sAMAccountName=%s)(objectclass=user))",
727 ldb_binary_encode_string(mem_ctx,
728 *trust_account_for_search));
729 if (ret) {
730 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
731 log_escape(mem_ctx, r->in.account_name)));
732 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
733 dce_call, r, pipe_state, negotiate_flags,
734 NULL, /* trust_account_in_db */
735 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
738 msgs = talloc_steal(mem_ctx, res->msgs);
739 talloc_free(res);
742 *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
743 "sAMAccountName",
744 NULL);
745 if (*trust_account_in_db == NULL) {
746 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
747 r->in.account_name));
748 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
749 dce_call, r, pipe_state, negotiate_flags,
750 NULL, /* trust_account_in_db */
751 NT_STATUS_INTERNAL_DB_CORRUPTION);
754 nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
755 dce_call, r, pipe_state, negotiate_flags,
756 *trust_account_in_db,
757 NT_STATUS_OK);
758 if (!NT_STATUS_IS_OK(nt_status)) {
759 return nt_status;
762 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
764 if (user_account_control & UF_ACCOUNTDISABLE) {
765 DEBUG(1, ("Account [%s] is disabled\n",
766 log_escape(mem_ctx, r->in.account_name)));
767 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
770 switch (r->in.secure_channel_type) {
771 case SEC_CHAN_WKSTA:
772 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
773 DBG_WARNING("Client asked for a workstation "
774 "secure channel, but is not a workstation "
775 "(member server) acb flags: 0x%x\n",
776 user_account_control);
777 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
779 break;
781 case SEC_CHAN_DOMAIN:
782 FALL_THROUGH;
783 case SEC_CHAN_DNS_DOMAIN:
784 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
785 DBG_WARNING("Client asked for a trusted domain "
786 "secure channel, but is not a trusted "
787 "domain: acb flags: 0x%x\n",
788 user_account_control);
789 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
791 break;
793 case SEC_CHAN_BDC:
794 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
795 DBG_WARNING("Client asked for a server "
796 "secure channel, but is not a server "
797 "(domain controller): acb flags: 0x%x\n",
798 user_account_control);
799 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
801 break;
803 case SEC_CHAN_RODC:
804 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
805 DBG_WARNING("Client asked for a RODC secure channel, "
806 "but is not a RODC: acb flags: 0x%x\n",
807 user_account_control);
808 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
810 break;
812 default:
813 /* we should never reach this */
814 return NT_STATUS_INTERNAL_ERROR;
817 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
818 tdo_msg = NULL;
821 *sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid");
822 if (*sid == NULL) {
823 return NT_STATUS_ACCESS_DENIED;
826 nt_status = auth_fn(dce_call,
827 challenge_valid ? &challenge : NULL,
829 client_flags,
830 *sid,
831 negotiate_flags,
832 msgs[0],
833 tdo_msg,
834 mem_ctx,
835 &creds);
836 if (!NT_STATUS_IS_OK(nt_status)) {
837 ZERO_STRUCTP(r->out.return_credentials);
838 return nt_status;
841 nt_status = schannel_save_creds_state(mem_ctx,
842 dce_call->conn->dce_ctx->lp_ctx,
843 creds);
844 if (!NT_STATUS_IS_OK(nt_status)) {
845 ZERO_STRUCTP(r->out.return_credentials);
846 return nt_status;
849 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
850 "objectSid", 0);
852 return NT_STATUS_OK;
855 static NTSTATUS dcesrv_netr_ServerAuthenticateNTHash_cb(
856 struct dcesrv_call_state *dce_call,
857 const struct netlogon_server_pipe_state *challenge,
858 const struct netr_ServerAuthenticate3 *r,
859 uint32_t client_flags,
860 const struct dom_sid *client_sid,
861 uint32_t negotiate_flags,
862 const struct ldb_message *sam_msg,
863 const struct ldb_message *tdo_msg,
864 TALLOC_CTX *mem_ctx,
865 struct netlogon_creds_CredentialState **_creds)
867 TALLOC_CTX *frame = talloc_stackframe();
868 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
869 struct netlogon_creds_CredentialState *creds = NULL;
870 struct samr_Password *curNtHash = NULL;
871 struct samr_Password *prevNtHash = NULL;
872 NTSTATUS status;
873 struct GUID tdo_guid = { 0, };
875 if (tdo_msg != NULL) {
876 status = dsdb_trust_get_incoming_passwords(tdo_msg,
877 frame,
878 &curNtHash,
879 &prevNtHash);
880 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_DISABLED)) {
881 status = NT_STATUS_NO_TRUST_SAM_ACCOUNT;
883 if (!NT_STATUS_IS_OK(status)) {
884 TALLOC_FREE(frame);
885 return status;
888 tdo_guid = samdb_result_guid(tdo_msg, "objectGUID");
889 } else {
890 status = samdb_result_passwords_no_lockout(frame,
891 lp_ctx,
892 sam_msg,
893 &curNtHash);
894 if (!NT_STATUS_IS_OK(status)) {
895 TALLOC_FREE(frame);
896 return NT_STATUS_ACCESS_DENIED;
900 if (curNtHash == NULL) {
901 TALLOC_FREE(frame);
902 return NT_STATUS_ACCESS_DENIED;
905 if (challenge == NULL) {
906 TALLOC_FREE(frame);
907 return NT_STATUS_ACCESS_DENIED;
910 creds = netlogon_creds_server_init(mem_ctx,
911 r->in.account_name,
912 r->in.computer_name,
913 r->in.secure_channel_type,
914 &challenge->client_challenge,
915 &challenge->server_challenge,
916 curNtHash,
917 r->in.credentials,
918 r->out.return_credentials,
919 client_flags,
920 client_sid,
921 negotiate_flags);
922 if (creds == NULL && prevNtHash != NULL) {
924 * We fallback to the previous password for domain trusts.
926 * Note that lpcfg_old_password_allowed_period() doesn't
927 * apply here.
929 creds = netlogon_creds_server_init(mem_ctx,
930 r->in.account_name,
931 r->in.computer_name,
932 r->in.secure_channel_type,
933 &challenge->client_challenge,
934 &challenge->server_challenge,
935 prevNtHash,
936 r->in.credentials,
937 r->out.return_credentials,
938 client_flags,
939 client_sid,
940 negotiate_flags);
943 if (creds == NULL) {
944 TALLOC_FREE(frame);
945 return NT_STATUS_ACCESS_DENIED;
948 creds->tdo_guid = tdo_guid;
950 *_creds = creds;
951 TALLOC_FREE(frame);
952 return NT_STATUS_OK;
956 * Do the actual processing of a netr_ServerAuthenticate3 message.
957 * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
959 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
960 struct dcesrv_call_state *dce_call,
961 TALLOC_CTX *mem_ctx,
962 struct netr_ServerAuthenticate3 *r,
963 const char **trust_account_for_search,
964 const char **trust_account_in_db,
965 struct dom_sid **sid)
967 dcesrv_netr_ServerAuthenticateGenericCallback_fn auth_fn =
968 dcesrv_netr_ServerAuthenticateNTHash_cb;
970 return dcesrv_netr_ServerAuthenticateGeneric(dce_call,
971 mem_ctx,
973 auth_fn,
974 trust_account_for_search,
975 trust_account_in_db,
976 sid);
980 * Log a netr_ServerAuthenticate3 request, and then invoke
981 * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
983 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
984 struct dcesrv_call_state *dce_call,
985 TALLOC_CTX *mem_ctx,
986 struct netr_ServerAuthenticate3 *r)
988 NTSTATUS status;
989 struct dom_sid *sid = NULL;
990 const char *trust_account_for_search = NULL;
991 const char *trust_account_in_db = NULL;
992 struct imessaging_context *imsg_ctx =
993 dcesrv_imessaging_context(dce_call->conn);
994 struct auth_usersupplied_info ui = {
995 .local_host = dce_call->conn->local_address,
996 .remote_host = dce_call->conn->remote_address,
997 .client = {
998 .account_name = r->in.account_name,
999 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
1001 .service_description = "NETLOGON",
1002 .auth_description = "ServerAuthenticate",
1003 .netlogon_trust_account = {
1004 .computer_name = r->in.computer_name,
1005 .negotiate_flags = *r->in.negotiate_flags,
1006 .secure_channel_type = r->in.secure_channel_type,
1010 status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
1011 mem_ctx,
1013 &trust_account_for_search,
1014 &trust_account_in_db,
1015 &sid);
1016 ui.netlogon_trust_account.sid = sid;
1017 ui.netlogon_trust_account.account_name = trust_account_in_db;
1018 ui.mapped.account_name = trust_account_for_search;
1019 log_authentication_event(
1020 imsg_ctx,
1021 dce_call->conn->dce_ctx->lp_ctx,
1022 NULL,
1023 &ui,
1024 status,
1025 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
1026 trust_account_in_db,
1027 sid,
1028 NULL /* client_audit_info */,
1029 NULL /* server_audit_info */);
1031 return status;
1033 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1034 struct netr_ServerAuthenticate *r)
1036 struct netr_ServerAuthenticate3 a;
1037 uint32_t rid;
1038 /* TODO:
1039 * negotiate_flags is used as an [in] parameter
1040 * so it need to be initialised.
1042 * (I think ... = 0; seems wrong here --metze)
1044 uint32_t negotiate_flags_in = 0;
1045 uint32_t negotiate_flags_out = 0;
1047 a.in.server_name = r->in.server_name;
1048 a.in.account_name = r->in.account_name;
1049 a.in.secure_channel_type = r->in.secure_channel_type;
1050 a.in.computer_name = r->in.computer_name;
1051 a.in.credentials = r->in.credentials;
1052 a.in.negotiate_flags = &negotiate_flags_in;
1054 a.out.return_credentials = r->out.return_credentials;
1055 a.out.rid = &rid;
1056 a.out.negotiate_flags = &negotiate_flags_out;
1058 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
1061 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1062 struct netr_ServerAuthenticate2 *r)
1064 struct netr_ServerAuthenticate3 r3;
1065 uint32_t rid = 0;
1067 r3.in.server_name = r->in.server_name;
1068 r3.in.account_name = r->in.account_name;
1069 r3.in.secure_channel_type = r->in.secure_channel_type;
1070 r3.in.computer_name = r->in.computer_name;
1071 r3.in.credentials = r->in.credentials;
1072 r3.out.return_credentials = r->out.return_credentials;
1073 r3.in.negotiate_flags = r->in.negotiate_flags;
1074 r3.out.negotiate_flags = r->out.negotiate_flags;
1075 r3.out.rid = &rid;
1077 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
1081 Change the machine account password for the currently connected
1082 client. Supplies only the NT#.
1085 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1086 struct netr_ServerPasswordSet *r)
1088 struct netlogon_creds_CredentialState *creds;
1089 const struct dom_sid *client_sid = NULL;
1090 struct ldb_context *sam_ctx;
1091 NTSTATUS nt_status;
1092 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1093 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1095 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1097 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1098 mem_ctx,
1099 r->in.computer_name,
1100 r->in.credential, r->out.return_authenticator,
1101 &creds);
1102 NT_STATUS_NOT_OK_RETURN(nt_status);
1103 client_sid = &creds->client_sid;
1105 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
1106 if (sam_ctx == NULL) {
1107 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1110 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
1111 return NT_STATUS_NOT_SUPPORTED;
1114 nt_status = netlogon_creds_decrypt_samr_Password(creds,
1115 r->in.new_password,
1116 auth_type,
1117 auth_level);
1118 NT_STATUS_NOT_OK_RETURN(nt_status);
1120 /* Using the sid for the account as the key, set the password */
1121 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1122 client_sid,
1123 NULL, /* Don't have version */
1124 NULL, /* Don't have plaintext */
1125 r->in.new_password,
1126 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1127 NULL, NULL);
1128 return nt_status;
1132 Change the machine account password for the currently connected
1133 client. Supplies new plaintext.
1135 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1136 struct netr_ServerPasswordSet2 *r)
1138 struct netlogon_creds_CredentialState *creds;
1139 const struct dom_sid *client_sid = NULL;
1140 struct ldb_context *sam_ctx;
1141 struct NL_PASSWORD_VERSION version = {};
1142 const uint32_t *new_version = NULL;
1143 NTSTATUS nt_status;
1144 DATA_BLOB new_password = data_blob_null;
1145 size_t confounder_len;
1146 DATA_BLOB dec_blob = data_blob_null;
1147 DATA_BLOB enc_blob = data_blob_null;
1148 struct samr_CryptPassword password_buf;
1149 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1150 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1152 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1154 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1155 mem_ctx,
1156 r->in.computer_name,
1157 r->in.credential, r->out.return_authenticator,
1158 &creds);
1159 NT_STATUS_NOT_OK_RETURN(nt_status);
1160 client_sid = &creds->client_sid;
1162 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
1163 if (sam_ctx == NULL) {
1164 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1167 memcpy(password_buf.data, r->in.new_password->data, 512);
1168 SIVAL(password_buf.data, 512, r->in.new_password->length);
1170 nt_status = netlogon_creds_decrypt_samr_CryptPassword(creds,
1171 &password_buf,
1172 auth_type,
1173 auth_level);
1174 if (!NT_STATUS_IS_OK(nt_status)) {
1175 return nt_status;
1178 switch (creds->secure_channel_type) {
1179 case SEC_CHAN_DOMAIN:
1180 case SEC_CHAN_DNS_DOMAIN: {
1181 uint32_t len = IVAL(password_buf.data, 512);
1182 if (len <= 500) {
1183 uint32_t ofs = 500 - len;
1184 uint8_t *p;
1186 p = password_buf.data + ofs;
1188 version.ReservedField = IVAL(p, 0);
1189 version.PasswordVersionNumber = IVAL(p, 4);
1190 version.PasswordVersionPresent = IVAL(p, 8);
1192 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
1193 new_version = &version.PasswordVersionNumber;
1196 break;
1197 default:
1198 break;
1201 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
1202 DEBUG(3,("samr: failed to decode password buffer\n"));
1203 return NT_STATUS_ACCESS_DENIED;
1207 * We don't allow empty passwords for machine accounts.
1209 if (new_password.length < 2) {
1210 DBG_WARNING("Empty password Length[%zu]\n",
1211 new_password.length);
1212 return NT_STATUS_WRONG_PASSWORD;
1215 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
1217 * netlogon_creds_decrypt_samr_CryptPassword
1218 * already checked for DCERPC_AUTH_LEVEL_PRIVACY
1220 goto checked_encryption;
1221 } else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1223 * check it's encrypted
1225 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1227 * check it's encrypted
1229 } else {
1231 * netlogon_creds_decrypt_samr_CryptPassword
1232 * already checked for DCERPC_AUTH_LEVEL_PRIVACY
1234 goto checked_encryption;
1238 * Make sure the length field was encrypted,
1239 * otherwise we are under attack.
1241 if (new_password.length == r->in.new_password->length) {
1242 DBG_WARNING("Length[%zu] field not encrypted\n",
1243 new_password.length);
1244 return NT_STATUS_WRONG_PASSWORD;
1248 * Make sure the confounder part of CryptPassword
1249 * buffer was encrypted, otherwise we are under attack.
1251 confounder_len = 512 - new_password.length;
1252 enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
1253 dec_blob = data_blob_const(password_buf.data, confounder_len);
1254 if (confounder_len > 0 && data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1255 DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
1256 confounder_len);
1257 return NT_STATUS_WRONG_PASSWORD;
1261 * Check that the password part was actually encrypted,
1262 * otherwise we are under attack.
1264 enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
1265 new_password.length);
1266 dec_blob = data_blob_const(password_buf.data + confounder_len,
1267 new_password.length);
1268 if (data_blob_equal_const_time(&dec_blob, &enc_blob)) {
1269 DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
1270 new_password.length);
1271 return NT_STATUS_WRONG_PASSWORD;
1274 checked_encryption:
1277 * don't allow zero buffers
1279 if (all_zero(new_password.data, new_password.length)) {
1280 DBG_WARNING("Password zero buffer Length[%zu]\n",
1281 new_password.length);
1282 return NT_STATUS_WRONG_PASSWORD;
1285 /* Using the sid for the account as the key, set the password */
1286 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
1287 client_sid,
1288 new_version,
1289 &new_password, /* we have plaintext */
1290 NULL,
1291 DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
1292 NULL, NULL);
1293 return nt_status;
1298 netr_LogonUasLogon
1300 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1301 struct netr_LogonUasLogon *r)
1303 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1308 netr_LogonUasLogoff
1310 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1311 struct netr_LogonUasLogoff *r)
1313 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1317 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
1318 const struct netr_LogonSamLogonEx *r)
1320 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1322 switch (r->in.logon_level) {
1323 case NetlogonInteractiveInformation:
1324 case NetlogonServiceInformation:
1325 case NetlogonInteractiveTransitiveInformation:
1326 case NetlogonServiceTransitiveInformation:
1327 if (r->in.logon->password == NULL) {
1328 return NT_STATUS_INVALID_PARAMETER;
1331 switch (r->in.validation_level) {
1332 case NetlogonValidationSamInfo: /* 2 */
1333 case NetlogonValidationSamInfo2: /* 3 */
1334 case NetlogonValidationSamInfo4: /* 6 */
1335 break;
1336 default:
1337 return NT_STATUS_INVALID_INFO_CLASS;
1340 break;
1341 case NetlogonNetworkInformation:
1342 case NetlogonNetworkTransitiveInformation:
1343 if (r->in.logon->network == NULL) {
1344 return NT_STATUS_INVALID_PARAMETER;
1347 switch (r->in.validation_level) {
1348 case NetlogonValidationSamInfo: /* 2 */
1349 case NetlogonValidationSamInfo2: /* 3 */
1350 case NetlogonValidationSamInfo4: /* 6 */
1351 break;
1352 default:
1353 return NT_STATUS_INVALID_INFO_CLASS;
1356 break;
1358 case NetlogonGenericInformation:
1359 if (r->in.logon->generic == NULL) {
1360 return NT_STATUS_INVALID_PARAMETER;
1363 switch (r->in.validation_level) {
1364 /* TODO: case NetlogonValidationGenericInfo: 4 */
1365 case NetlogonValidationGenericInfo2: /* 5 */
1366 break;
1367 default:
1368 return NT_STATUS_INVALID_INFO_CLASS;
1371 break;
1372 default:
1373 return NT_STATUS_INVALID_PARAMETER;
1376 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
1378 switch (r->in.validation_level) {
1379 case NetlogonValidationSamInfo4: /* 6 */
1380 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1381 return NT_STATUS_INVALID_PARAMETER;
1383 break;
1385 default:
1386 break;
1389 return NT_STATUS_OK;
1392 struct dcesrv_netr_LogonSamLogon_base_state {
1393 struct dcesrv_call_state *dce_call;
1395 TALLOC_CTX *mem_ctx;
1397 struct netlogon_creds_CredentialState *creds;
1399 struct netr_LogonSamLogonEx r;
1401 uint32_t _ignored_flags;
1403 struct {
1404 struct netr_LogonSamLogon *lsl;
1405 struct netr_LogonSamLogonWithFlags *lslwf;
1406 struct netr_LogonSamLogonEx *lslex;
1407 } _r;
1409 struct kdc_check_generic_kerberos kr;
1412 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
1413 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
1414 static void dcesrv_netr_LogonSamLogon_base_reply(
1415 struct dcesrv_netr_LogonSamLogon_base_state *state);
1418 netr_LogonSamLogon_base
1420 This version of the function allows other wrappers to say 'do not check the credentials'
1422 We can't do the traditional 'wrapping' format completely, as this
1423 function must only run under schannel
1425 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
1427 struct dcesrv_call_state *dce_call = state->dce_call;
1428 struct imessaging_context *imsg_ctx =
1429 dcesrv_imessaging_context(dce_call->conn);
1430 TALLOC_CTX *mem_ctx = state->mem_ctx;
1431 struct netr_LogonSamLogonEx *r = &state->r;
1432 struct netlogon_creds_CredentialState *creds = state->creds;
1433 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1434 const char *workgroup = lpcfg_workgroup(lp_ctx);
1435 struct auth4_context *auth_context = NULL;
1436 struct auth_usersupplied_info *user_info = NULL;
1437 NTSTATUS nt_status;
1438 struct tevent_req *subreq = NULL;
1439 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1440 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1442 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
1444 switch (dce_call->pkt.u.request.opnum) {
1445 case NDR_NETR_LOGONSAMLOGON:
1446 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
1448 * These already called dcesrv_netr_check_schannel()
1449 * via dcesrv_netr_creds_server_step_check()
1451 break;
1452 case NDR_NETR_LOGONSAMLOGONEX:
1453 default:
1454 nt_status = dcesrv_netr_check_schannel(dce_call,
1455 creds,
1456 auth_type,
1457 auth_level,
1458 dce_call->pkt.u.request.opnum);
1459 if (!NT_STATUS_IS_OK(nt_status)) {
1460 return nt_status;
1463 if (!creds->authenticate_kerberos &&
1464 auth_type != DCERPC_AUTH_TYPE_SCHANNEL)
1466 return NT_STATUS_ACCESS_DENIED;
1469 break;
1472 *r->out.authoritative = 1;
1474 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
1476 * Currently we're always the forest root ourself.
1478 return NT_STATUS_NO_SUCH_USER;
1481 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
1483 * Currently we don't support trusts correctly yet.
1485 return NT_STATUS_NO_SUCH_USER;
1488 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1489 NT_STATUS_HAVE_NO_MEMORY(user_info);
1491 user_info->service_description = "SamLogon";
1493 nt_status = netlogon_creds_decrypt_samlogon_logon(creds,
1494 r->in.logon_level,
1495 r->in.logon,
1496 auth_type,
1497 auth_level);
1498 NT_STATUS_NOT_OK_RETURN(nt_status);
1500 switch (r->in.logon_level) {
1501 case NetlogonInteractiveInformation:
1502 case NetlogonServiceInformation:
1503 case NetlogonInteractiveTransitiveInformation:
1504 case NetlogonServiceTransitiveInformation:
1505 case NetlogonNetworkInformation:
1506 case NetlogonNetworkTransitiveInformation:
1508 nt_status = auth_context_create_for_netlogon(mem_ctx,
1509 dce_call->event_ctx,
1510 imsg_ctx,
1511 dce_call->conn->dce_ctx->lp_ctx,
1512 &auth_context);
1513 NT_STATUS_NOT_OK_RETURN(nt_status);
1515 user_info->remote_host = dce_call->conn->remote_address;
1516 user_info->local_host = dce_call->conn->local_address;
1518 user_info->netlogon_trust_account.secure_channel_type
1519 = creds->secure_channel_type;
1520 user_info->netlogon_trust_account.negotiate_flags
1521 = creds->negotiate_flags;
1524 * These two can be unrelated when the account is
1525 * actually that of a trusted domain, so we want to
1526 * know which DC in that trusted domain contacted
1527 * us
1529 user_info->netlogon_trust_account.computer_name
1530 = creds->computer_name;
1531 user_info->netlogon_trust_account.account_name
1532 = creds->account_name;
1533 user_info->netlogon_trust_account.sid
1534 = &creds->client_sid;
1536 break;
1537 default:
1538 /* We do not need to set up the user_info in this case */
1539 break;
1542 switch (r->in.logon_level) {
1543 case NetlogonInteractiveInformation:
1544 case NetlogonServiceInformation:
1545 case NetlogonInteractiveTransitiveInformation:
1546 case NetlogonServiceTransitiveInformation:
1547 user_info->auth_description = "interactive";
1549 user_info->logon_parameters
1550 = r->in.logon->password->identity_info.parameter_control;
1551 user_info->client.account_name
1552 = r->in.logon->password->identity_info.account_name.string;
1553 user_info->client.domain_name
1554 = r->in.logon->password->identity_info.domain_name.string;
1555 user_info->workstation_name
1556 = r->in.logon->password->identity_info.workstation.string;
1557 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1558 user_info->password_state = AUTH_PASSWORD_HASH;
1560 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1561 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1562 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1564 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1565 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1566 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1568 user_info->logon_id
1569 = r->in.logon->password->identity_info.logon_id;
1571 break;
1572 case NetlogonNetworkInformation:
1573 case NetlogonNetworkTransitiveInformation:
1574 user_info->auth_description = "network";
1576 nt_status = auth_context_set_challenge(
1577 auth_context,
1578 r->in.logon->network->challenge,
1579 "netr_LogonSamLogonWithFlags");
1580 NT_STATUS_NOT_OK_RETURN(nt_status);
1582 user_info->logon_parameters
1583 = r->in.logon->network->identity_info.parameter_control;
1584 user_info->client.account_name
1585 = r->in.logon->network->identity_info.account_name.string;
1586 user_info->client.domain_name
1587 = r->in.logon->network->identity_info.domain_name.string;
1588 user_info->workstation_name
1589 = r->in.logon->network->identity_info.workstation.string;
1591 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1592 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1593 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1595 user_info->logon_id
1596 = r->in.logon->network->identity_info.logon_id;
1598 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1599 user_info->client.account_name,
1600 user_info->client.domain_name,
1601 user_info->password.response.nt,
1602 creds, workgroup);
1603 NT_STATUS_NOT_OK_RETURN(nt_status);
1605 break;
1608 case NetlogonGenericInformation:
1610 if (creds->authenticate_kerberos) {
1611 /* OK */
1612 } else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1613 /* OK */
1614 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1615 /* OK */
1616 } else {
1617 /* Using DES to verify kerberos tickets makes no sense */
1618 return NT_STATUS_INVALID_PARAMETER;
1621 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1622 struct dcerpc_binding_handle *irpc_handle;
1623 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1624 NT_STATUS_HAVE_NO_MEMORY(generic);
1626 r->out.validation->generic = generic;
1628 user_info->logon_id
1629 = r->in.logon->generic->identity_info.logon_id;
1631 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1632 imsg_ctx,
1633 "kdc_server",
1634 &ndr_table_irpc);
1635 if (irpc_handle == NULL) {
1636 return NT_STATUS_NO_LOGON_SERVERS;
1639 state->kr.in.generic_request =
1640 data_blob_const(r->in.logon->generic->data,
1641 r->in.logon->generic->length);
1644 * 60 seconds should be enough
1646 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1647 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1648 state->dce_call->event_ctx,
1649 irpc_handle, &state->kr);
1650 if (subreq == NULL) {
1651 return NT_STATUS_NO_MEMORY;
1653 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1654 tevent_req_set_callback(subreq,
1655 dcesrv_netr_LogonSamLogon_base_krb5_done,
1656 state);
1657 return NT_STATUS_OK;
1660 /* Until we get an implementation of these other packages */
1661 return NT_STATUS_INVALID_PARAMETER;
1663 default:
1664 return NT_STATUS_INVALID_PARAMETER;
1667 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1668 auth_context, user_info);
1669 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1670 tevent_req_set_callback(subreq,
1671 dcesrv_netr_LogonSamLogon_base_auth_done,
1672 state);
1673 return NT_STATUS_OK;
1676 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1678 struct dcesrv_netr_LogonSamLogon_base_state *state =
1679 tevent_req_callback_data(subreq,
1680 struct dcesrv_netr_LogonSamLogon_base_state);
1681 TALLOC_CTX *mem_ctx = state->mem_ctx;
1682 struct netr_LogonSamLogonEx *r = &state->r;
1683 struct auth_user_info_dc *user_info_dc = NULL;
1684 struct netr_SamInfo2 *sam2 = NULL;
1685 struct netr_SamInfo3 *sam3 = NULL;
1686 struct netr_SamInfo6 *sam6 = NULL;
1687 NTSTATUS nt_status;
1689 nt_status = auth_check_password_recv(subreq, mem_ctx,
1690 &user_info_dc,
1691 r->out.authoritative);
1692 TALLOC_FREE(subreq);
1693 if (!NT_STATUS_IS_OK(nt_status)) {
1694 r->out.result = nt_status;
1695 dcesrv_netr_LogonSamLogon_base_reply(state);
1696 return;
1699 switch (r->in.validation_level) {
1700 case 2:
1701 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1702 user_info_dc,
1703 AUTH_INCLUDE_RESOURCE_GROUPS,
1704 &sam2);
1705 if (!NT_STATUS_IS_OK(nt_status)) {
1706 r->out.result = nt_status;
1707 dcesrv_netr_LogonSamLogon_base_reply(state);
1708 return;
1711 r->out.validation->sam2 = sam2;
1712 break;
1714 case 3:
1715 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1716 user_info_dc,
1717 AUTH_INCLUDE_RESOURCE_GROUPS,
1718 &sam3, NULL);
1719 if (!NT_STATUS_IS_OK(nt_status)) {
1720 r->out.result = nt_status;
1721 dcesrv_netr_LogonSamLogon_base_reply(state);
1722 return;
1725 r->out.validation->sam3 = sam3;
1726 break;
1728 case 6:
1729 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1730 user_info_dc,
1731 AUTH_INCLUDE_RESOURCE_GROUPS,
1732 &sam6, NULL);
1733 if (!NT_STATUS_IS_OK(nt_status)) {
1734 r->out.result = nt_status;
1735 dcesrv_netr_LogonSamLogon_base_reply(state);
1736 return;
1739 r->out.validation->sam6 = sam6;
1740 break;
1742 default:
1743 if (!NT_STATUS_IS_OK(nt_status)) {
1744 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1745 dcesrv_netr_LogonSamLogon_base_reply(state);
1746 return;
1750 /* TODO: Describe and deal with these flags */
1751 *r->out.flags = 0;
1753 r->out.result = NT_STATUS_OK;
1755 dcesrv_netr_LogonSamLogon_base_reply(state);
1758 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1760 struct dcesrv_netr_LogonSamLogon_base_state *state =
1761 tevent_req_callback_data(subreq,
1762 struct dcesrv_netr_LogonSamLogon_base_state);
1763 TALLOC_CTX *mem_ctx = state->mem_ctx;
1764 struct netr_LogonSamLogonEx *r = &state->r;
1765 struct netr_GenericInfo2 *generic = NULL;
1766 NTSTATUS status;
1768 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1769 TALLOC_FREE(subreq);
1770 if (!NT_STATUS_IS_OK(status)) {
1771 r->out.result = status;
1772 dcesrv_netr_LogonSamLogon_base_reply(state);
1773 return;
1776 generic = r->out.validation->generic;
1777 generic->length = state->kr.out.generic_reply.length;
1778 generic->data = state->kr.out.generic_reply.data;
1780 /* TODO: Describe and deal with these flags */
1781 *r->out.flags = 0;
1783 r->out.result = NT_STATUS_OK;
1785 dcesrv_netr_LogonSamLogon_base_reply(state);
1788 static void dcesrv_netr_LogonSamLogon_base_reply(
1789 struct dcesrv_netr_LogonSamLogon_base_state *state)
1791 struct netr_LogonSamLogonEx *r = &state->r;
1792 NTSTATUS status;
1794 if (NT_STATUS_IS_OK(r->out.result)) {
1795 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1796 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
1798 dcesrv_call_auth_info(state->dce_call, &auth_type, &auth_level);
1800 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
1801 r->in.validation_level,
1802 r->out.validation,
1803 auth_type,
1804 auth_level);
1805 if (!NT_STATUS_IS_OK(status)) {
1806 DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
1807 "failed - %s\n",
1808 nt_errstr(status));
1809 if (r->out.validation != NULL) {
1810 ZERO_STRUCTP(r->out.validation);
1812 *r->out.authoritative = true;
1813 *r->out.flags = 0;
1814 r->out.result = status;
1818 if (state->_r.lslex != NULL) {
1819 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1820 _r->out.result = r->out.result;
1821 } else if (state->_r.lslwf != NULL) {
1822 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1823 _r->out.result = r->out.result;
1824 } else if (state->_r.lsl != NULL) {
1825 struct netr_LogonSamLogon *_r = state->_r.lsl;
1826 _r->out.result = r->out.result;
1829 dcesrv_async_reply(state->dce_call);
1832 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1833 struct netr_LogonSamLogonEx *r)
1835 struct dcesrv_netr_LogonSamLogon_base_state *state;
1836 NTSTATUS nt_status;
1838 *r->out.authoritative = 1;
1840 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1841 if (state == NULL) {
1842 return NT_STATUS_NO_MEMORY;
1845 state->dce_call = dce_call;
1846 state->mem_ctx = mem_ctx;
1848 state->r.in.server_name = r->in.server_name;
1849 state->r.in.computer_name = r->in.computer_name;
1850 state->r.in.logon_level = r->in.logon_level;
1851 state->r.in.logon = r->in.logon;
1852 state->r.in.validation_level = r->in.validation_level;
1853 state->r.in.flags = r->in.flags;
1854 state->r.out.validation = r->out.validation;
1855 state->r.out.authoritative = r->out.authoritative;
1856 state->r.out.flags = r->out.flags;
1858 state->_r.lslex = r;
1860 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1861 if (!NT_STATUS_IS_OK(nt_status)) {
1862 return nt_status;
1865 nt_status = schannel_get_creds_state(mem_ctx,
1866 dce_call->conn->dce_ctx->lp_ctx,
1867 r->in.computer_name, &state->creds);
1868 if (!NT_STATUS_IS_OK(nt_status)) {
1869 return nt_status;
1872 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1874 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1875 return nt_status;
1878 return nt_status;
1882 netr_LogonSamLogonWithFlags
1885 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1886 struct netr_LogonSamLogonWithFlags *r)
1888 struct dcesrv_netr_LogonSamLogon_base_state *state;
1889 NTSTATUS nt_status;
1891 *r->out.authoritative = 1;
1893 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1894 if (state == NULL) {
1895 return NT_STATUS_NO_MEMORY;
1898 state->dce_call = dce_call;
1899 state->mem_ctx = mem_ctx;
1901 state->r.in.server_name = r->in.server_name;
1902 state->r.in.computer_name = r->in.computer_name;
1903 state->r.in.logon_level = r->in.logon_level;
1904 state->r.in.logon = r->in.logon;
1905 state->r.in.validation_level = r->in.validation_level;
1906 state->r.in.flags = r->in.flags;
1907 state->r.out.validation = r->out.validation;
1908 state->r.out.authoritative = r->out.authoritative;
1909 state->r.out.flags = r->out.flags;
1911 state->_r.lslwf = r;
1913 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1914 if (!NT_STATUS_IS_OK(nt_status)) {
1915 return nt_status;
1918 r->out.return_authenticator = talloc_zero(mem_ctx,
1919 struct netr_Authenticator);
1920 if (r->out.return_authenticator == NULL) {
1921 return NT_STATUS_NO_MEMORY;
1924 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1925 mem_ctx,
1926 r->in.computer_name,
1927 r->in.credential,
1928 r->out.return_authenticator,
1929 &state->creds);
1930 if (!NT_STATUS_IS_OK(nt_status)) {
1931 return nt_status;
1934 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1936 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1937 return nt_status;
1940 return nt_status;
1944 netr_LogonSamLogon
1946 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1947 struct netr_LogonSamLogon *r)
1949 struct dcesrv_netr_LogonSamLogon_base_state *state;
1950 NTSTATUS nt_status;
1952 *r->out.authoritative = 1;
1954 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1955 if (state == NULL) {
1956 return NT_STATUS_NO_MEMORY;
1959 state->dce_call = dce_call;
1960 state->mem_ctx = mem_ctx;
1962 state->r.in.server_name = r->in.server_name;
1963 state->r.in.computer_name = r->in.computer_name;
1964 state->r.in.logon_level = r->in.logon_level;
1965 state->r.in.logon = r->in.logon;
1966 state->r.in.validation_level = r->in.validation_level;
1967 state->r.in.flags = &state->_ignored_flags;
1968 state->r.out.validation = r->out.validation;
1969 state->r.out.authoritative = r->out.authoritative;
1970 state->r.out.flags = &state->_ignored_flags;
1972 state->_r.lsl = r;
1974 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1975 if (!NT_STATUS_IS_OK(nt_status)) {
1976 return nt_status;
1979 r->out.return_authenticator = talloc_zero(mem_ctx,
1980 struct netr_Authenticator);
1981 if (r->out.return_authenticator == NULL) {
1982 return NT_STATUS_NO_MEMORY;
1985 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1986 mem_ctx,
1987 r->in.computer_name,
1988 r->in.credential,
1989 r->out.return_authenticator,
1990 &state->creds);
1991 if (!NT_STATUS_IS_OK(nt_status)) {
1992 return nt_status;
1995 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1997 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1998 return nt_status;
2001 return nt_status;
2006 netr_LogonSamLogoff
2008 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2009 struct netr_LogonSamLogoff *r)
2011 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2017 netr_DatabaseDeltas
2019 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2020 struct netr_DatabaseDeltas *r)
2022 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2027 netr_DatabaseSync2
2029 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2030 struct netr_DatabaseSync2 *r)
2032 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
2033 return NT_STATUS_NOT_IMPLEMENTED;
2038 netr_DatabaseSync
2040 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2041 struct netr_DatabaseSync *r)
2043 struct netr_DatabaseSync2 r2;
2044 NTSTATUS status;
2046 ZERO_STRUCT(r2);
2048 r2.in.logon_server = r->in.logon_server;
2049 r2.in.computername = r->in.computername;
2050 r2.in.credential = r->in.credential;
2051 r2.in.database_id = r->in.database_id;
2052 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
2053 r2.in.sync_context = r->in.sync_context;
2054 r2.out.sync_context = r->out.sync_context;
2055 r2.out.delta_enum_array = r->out.delta_enum_array;
2056 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
2058 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
2060 return status;
2065 netr_AccountDeltas
2067 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2068 struct netr_AccountDeltas *r)
2070 /* w2k3 returns "NOT IMPLEMENTED" for this call */
2071 return NT_STATUS_NOT_IMPLEMENTED;
2076 netr_AccountSync
2078 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2079 struct netr_AccountSync *r)
2081 /* w2k3 returns "NOT IMPLEMENTED" for this call */
2082 return NT_STATUS_NOT_IMPLEMENTED;
2087 netr_GetDcName
2089 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2090 struct netr_GetDcName *r)
2092 const char * const attrs[] = { NULL };
2093 struct ldb_context *sam_ctx;
2094 struct ldb_message **res;
2095 struct ldb_dn *domain_dn;
2096 int ret;
2097 const char *dcname;
2100 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
2101 * that the domainname needs to be a valid netbios domain
2102 * name, if it is not NULL.
2104 if (r->in.domainname) {
2105 const char *dot = strchr(r->in.domainname, '.');
2106 size_t len = strlen(r->in.domainname);
2108 if (dot || len > 15) {
2109 return WERR_NERR_DCNOTFOUND;
2113 * TODO: Should we also verify that only valid
2114 * netbios name characters are used?
2118 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2119 if (sam_ctx == NULL) {
2120 return WERR_DS_UNAVAILABLE;
2123 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
2124 r->in.domainname);
2125 if (domain_dn == NULL) {
2126 return WERR_NO_SUCH_DOMAIN;
2129 ret = gendb_search_dn(sam_ctx, mem_ctx,
2130 domain_dn, &res, attrs);
2131 if (ret != 1) {
2132 return WERR_NO_SUCH_DOMAIN;
2135 /* TODO: - return real IP address
2136 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
2138 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
2139 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
2140 W_ERROR_HAVE_NO_MEMORY(dcname);
2142 *r->out.dcname = dcname;
2143 return WERR_OK;
2146 struct dcesrv_netr_LogonControl_base_state {
2147 struct dcesrv_call_state *dce_call;
2149 TALLOC_CTX *mem_ctx;
2151 struct netr_LogonControl2Ex r;
2153 struct {
2154 struct netr_LogonControl *l;
2155 struct netr_LogonControl2 *l2;
2156 struct netr_LogonControl2Ex *l2ex;
2157 } _r;
2160 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
2162 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
2164 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
2165 struct auth_session_info *session_info =
2166 dcesrv_call_session_info(state->dce_call);
2167 struct imessaging_context *imsg_ctx =
2168 dcesrv_imessaging_context(state->dce_call->conn);
2169 enum security_user_level security_level;
2170 struct dcerpc_binding_handle *irpc_handle;
2171 struct tevent_req *subreq;
2172 bool ok;
2174 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
2176 if (state->_r.l != NULL) {
2178 * netr_LogonControl
2180 if (state->r.in.level == 0x00000002) {
2181 return WERR_NOT_SUPPORTED;
2182 } else if (state->r.in.level != 0x00000001) {
2183 return WERR_INVALID_LEVEL;
2186 switch (state->r.in.function_code) {
2187 case NETLOGON_CONTROL_QUERY:
2188 case NETLOGON_CONTROL_REPLICATE:
2189 case NETLOGON_CONTROL_SYNCHRONIZE:
2190 case NETLOGON_CONTROL_PDC_REPLICATE:
2191 case NETLOGON_CONTROL_BREAKPOINT:
2192 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
2193 case NETLOGON_CONTROL_TRUNCATE_LOG:
2194 break;
2195 default:
2196 return WERR_NOT_SUPPORTED;
2200 if (state->r.in.level < 0x00000001) {
2201 return WERR_INVALID_LEVEL;
2204 if (state->r.in.level > 0x00000004) {
2205 return WERR_INVALID_LEVEL;
2208 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
2209 struct netr_NETLOGON_INFO_1 *info1 = NULL;
2210 struct netr_NETLOGON_INFO_3 *info3 = NULL;
2212 switch (state->r.in.level) {
2213 case 0x00000001:
2214 info1 = talloc_zero(state->mem_ctx,
2215 struct netr_NETLOGON_INFO_1);
2216 if (info1 == NULL) {
2217 return WERR_NOT_ENOUGH_MEMORY;
2219 state->r.out.query->info1 = info1;
2220 return WERR_OK;
2222 case 0x00000003:
2223 info3 = talloc_zero(state->mem_ctx,
2224 struct netr_NETLOGON_INFO_3);
2225 if (info3 == NULL) {
2226 return WERR_NOT_ENOUGH_MEMORY;
2228 state->r.out.query->info3 = info3;
2229 return WERR_OK;
2231 default:
2232 return WERR_INVALID_PARAMETER;
2237 * Some validations are done before the access check
2238 * and some after the access check
2240 security_level = security_session_user_level(session_info, NULL);
2241 if (security_level < SECURITY_ADMINISTRATOR) {
2242 return WERR_ACCESS_DENIED;
2245 if (state->_r.l2 != NULL) {
2247 * netr_LogonControl2
2249 if (state->r.in.level == 0x00000004) {
2250 return WERR_INVALID_LEVEL;
2254 switch (state->r.in.level) {
2255 case 0x00000001:
2256 break;
2258 case 0x00000002:
2259 switch (state->r.in.function_code) {
2260 case NETLOGON_CONTROL_REDISCOVER:
2261 case NETLOGON_CONTROL_TC_QUERY:
2262 case NETLOGON_CONTROL_TC_VERIFY:
2263 break;
2264 default:
2265 return WERR_INVALID_PARAMETER;
2268 break;
2270 case 0x00000003:
2271 break;
2273 case 0x00000004:
2274 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
2275 return WERR_INVALID_PARAMETER;
2278 break;
2280 default:
2281 return WERR_INVALID_LEVEL;
2284 switch (state->r.in.function_code) {
2285 case NETLOGON_CONTROL_REDISCOVER:
2286 case NETLOGON_CONTROL_TC_QUERY:
2287 case NETLOGON_CONTROL_TC_VERIFY:
2288 if (state->r.in.level != 2) {
2289 return WERR_INVALID_PARAMETER;
2292 if (state->r.in.data == NULL) {
2293 return WERR_INVALID_PARAMETER;
2296 if (state->r.in.data->domain == NULL) {
2297 return WERR_INVALID_PARAMETER;
2300 break;
2302 case NETLOGON_CONTROL_CHANGE_PASSWORD:
2303 if (state->r.in.level != 1) {
2304 return WERR_INVALID_PARAMETER;
2307 if (state->r.in.data == NULL) {
2308 return WERR_INVALID_PARAMETER;
2311 if (state->r.in.data->domain == NULL) {
2312 return WERR_INVALID_PARAMETER;
2315 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
2316 state->r.in.data->domain);
2317 if (!ok) {
2318 struct ldb_context *sam_ctx;
2320 sam_ctx = dcesrv_samdb_connect_as_system(state,
2321 state->dce_call);
2322 if (sam_ctx == NULL) {
2323 return WERR_DS_UNAVAILABLE;
2327 * Secrets for trusted domains can only be triggered on
2328 * the PDC.
2330 ok = samdb_is_pdc(sam_ctx);
2331 TALLOC_FREE(sam_ctx);
2332 if (!ok) {
2333 return WERR_INVALID_DOMAIN_ROLE;
2337 break;
2338 default:
2339 return WERR_NOT_SUPPORTED;
2342 irpc_handle = irpc_binding_handle_by_name(state,
2343 imsg_ctx,
2344 "winbind_server",
2345 &ndr_table_winbind);
2346 if (irpc_handle == NULL) {
2347 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2348 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2349 return WERR_SERVICE_NOT_FOUND;
2353 * 60 seconds timeout should be enough
2355 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2357 subreq = dcerpc_winbind_LogonControl_send(state,
2358 state->dce_call->event_ctx,
2359 irpc_handle,
2360 state->r.in.function_code,
2361 state->r.in.level,
2362 state->r.in.data,
2363 state->r.out.query);
2364 if (subreq == NULL) {
2365 return WERR_NOT_ENOUGH_MEMORY;
2367 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2368 tevent_req_set_callback(subreq,
2369 dcesrv_netr_LogonControl_base_done,
2370 state);
2372 return WERR_OK;
2375 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
2377 struct dcesrv_netr_LogonControl_base_state *state =
2378 tevent_req_callback_data(subreq,
2379 struct dcesrv_netr_LogonControl_base_state);
2380 NTSTATUS status;
2382 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
2383 &state->r.out.result);
2384 TALLOC_FREE(subreq);
2385 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
2386 state->r.out.result = WERR_TIMEOUT;
2387 } else if (!NT_STATUS_IS_OK(status)) {
2388 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2389 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
2390 nt_errstr(status)));
2393 if (state->_r.l2ex != NULL) {
2394 struct netr_LogonControl2Ex *r = state->_r.l2ex;
2395 r->out.result = state->r.out.result;
2396 } else if (state->_r.l2 != NULL) {
2397 struct netr_LogonControl2 *r = state->_r.l2;
2398 r->out.result = state->r.out.result;
2399 } else if (state->_r.l != NULL) {
2400 struct netr_LogonControl *r = state->_r.l;
2401 r->out.result = state->r.out.result;
2404 dcesrv_async_reply(state->dce_call);
2408 netr_LogonControl
2410 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2411 struct netr_LogonControl *r)
2413 struct dcesrv_netr_LogonControl_base_state *state;
2414 WERROR werr;
2416 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2417 if (state == NULL) {
2418 return WERR_NOT_ENOUGH_MEMORY;
2421 state->dce_call = dce_call;
2422 state->mem_ctx = mem_ctx;
2424 state->r.in.logon_server = r->in.logon_server;
2425 state->r.in.function_code = r->in.function_code;
2426 state->r.in.level = r->in.level;
2427 state->r.in.data = NULL;
2428 state->r.out.query = r->out.query;
2430 state->_r.l = r;
2432 werr = dcesrv_netr_LogonControl_base_call(state);
2434 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2435 return werr;
2438 return werr;
2442 netr_LogonControl2
2444 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2445 struct netr_LogonControl2 *r)
2447 struct dcesrv_netr_LogonControl_base_state *state;
2448 WERROR werr;
2450 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2451 if (state == NULL) {
2452 return WERR_NOT_ENOUGH_MEMORY;
2455 state->dce_call = dce_call;
2456 state->mem_ctx = mem_ctx;
2458 state->r.in.logon_server = r->in.logon_server;
2459 state->r.in.function_code = r->in.function_code;
2460 state->r.in.level = r->in.level;
2461 state->r.in.data = r->in.data;
2462 state->r.out.query = r->out.query;
2464 state->_r.l2 = r;
2466 werr = dcesrv_netr_LogonControl_base_call(state);
2468 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2469 return werr;
2472 return werr;
2476 netr_LogonControl2Ex
2478 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2479 struct netr_LogonControl2Ex *r)
2481 struct dcesrv_netr_LogonControl_base_state *state;
2482 WERROR werr;
2484 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
2485 if (state == NULL) {
2486 return WERR_NOT_ENOUGH_MEMORY;
2489 state->dce_call = dce_call;
2490 state->mem_ctx = mem_ctx;
2492 state->r = *r;
2493 state->_r.l2ex = r;
2495 werr = dcesrv_netr_LogonControl_base_call(state);
2497 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
2498 return werr;
2501 return werr;
2504 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2505 struct ldb_context *sam_ctx,
2506 struct netr_DomainTrustList *trusts,
2507 uint32_t trust_flags);
2510 netr_GetAnyDCName
2512 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2513 struct netr_GetAnyDCName *r)
2515 struct netr_DomainTrustList *trusts;
2516 struct ldb_context *sam_ctx;
2517 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2518 uint32_t i;
2519 WERROR werr;
2521 *r->out.dcname = NULL;
2523 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2524 /* if the domainname parameter wasn't set assume our domain */
2525 r->in.domainname = lpcfg_workgroup(lp_ctx);
2528 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2529 if (sam_ctx == NULL) {
2530 return WERR_DS_UNAVAILABLE;
2533 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2534 /* well we asked for a DC of our own domain */
2535 if (samdb_is_pdc(sam_ctx)) {
2536 /* we are the PDC of the specified domain */
2537 return WERR_NO_SUCH_DOMAIN;
2540 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2541 lpcfg_netbios_name(lp_ctx));
2542 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2544 return WERR_OK;
2547 /* Okay, now we have to consider the trusted domains */
2549 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2550 W_ERROR_HAVE_NO_MEMORY(trusts);
2552 trusts->count = 0;
2554 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2555 NETR_TRUST_FLAG_INBOUND
2556 | NETR_TRUST_FLAG_OUTBOUND);
2557 W_ERROR_NOT_OK_RETURN(werr);
2559 for (i = 0; i < trusts->count; i++) {
2560 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2561 /* FIXME: Here we need to find a DC for the specified
2562 * trusted domain. */
2564 /* return WERR_OK; */
2565 return WERR_NO_SUCH_DOMAIN;
2569 return WERR_NO_SUCH_DOMAIN;
2574 netr_DatabaseRedo
2576 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2577 struct netr_DatabaseRedo *r)
2579 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2584 netr_NetrEnumerateTrustedDomains
2586 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2587 struct netr_NetrEnumerateTrustedDomains *r)
2589 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2594 netr_LogonGetCapabilities
2596 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2597 struct netr_LogonGetCapabilities *r)
2599 struct netlogon_creds_CredentialState *creds;
2600 NTSTATUS status;
2602 switch (r->in.query_level) {
2603 case 1:
2604 break;
2605 case 2:
2606 break;
2607 default:
2609 * There would not be a way to marshall the
2610 * the response. Which would mean our final
2611 * ndr_push would fail an we would return
2612 * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA.
2614 * But it's important to match a Windows server
2615 * especially before KB5028166, see also our bug #15418
2616 * Otherwise Windows client would stop talking to us.
2618 DCESRV_FAULT(DCERPC_NCA_S_FAULT_INVALID_TAG);
2621 status = dcesrv_netr_creds_server_step_check(dce_call,
2622 mem_ctx,
2623 r->in.computer_name,
2624 r->in.credential,
2625 r->out.return_authenticator,
2626 &creds);
2627 if (!NT_STATUS_IS_OK(status)) {
2628 DEBUG(0,(__location__ " Bad credentials - error\n"));
2630 NT_STATUS_NOT_OK_RETURN(status);
2632 switch (r->in.query_level) {
2633 case 1:
2634 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2635 break;
2636 case 2:
2637 r->out.capabilities->requested_flags =
2638 creds->client_requested_flags;
2639 break;
2642 return NT_STATUS_OK;
2647 netr_NETRLOGONSETSERVICEBITS
2649 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2650 struct netr_NETRLOGONSETSERVICEBITS *r)
2652 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2657 netr_LogonGetTrustRid
2659 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2660 struct netr_LogonGetTrustRid *r)
2662 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2667 netr_NETRLOGONCOMPUTESERVERDIGEST
2669 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2670 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2672 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2677 netr_NETRLOGONCOMPUTECLIENTDIGEST
2679 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2680 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2682 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2688 netr_DsRGetSiteName
2690 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2691 struct netr_DsRGetSiteName *r)
2693 struct ldb_context *sam_ctx;
2695 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2696 if (sam_ctx == NULL) {
2697 return WERR_DS_UNAVAILABLE;
2701 * We assume to be a DC when we get called over NETLOGON. Hence we
2702 * get our site name always by using "samdb_server_site_name()"
2703 * and not "samdb_client_site_name()".
2705 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2706 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2708 return WERR_OK;
2713 fill in a netr_OneDomainInfo from our own domain/forest
2715 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2716 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2717 struct GUID domain_guid,
2718 struct netr_OneDomainInfo *info,
2719 bool is_trust_list)
2721 ZERO_STRUCTP(info);
2723 if (is_trust_list) {
2724 struct netr_trust_extension *te = NULL;
2725 struct netr_trust_extension_info *tei = NULL;
2727 /* w2k8 only fills this on trusted domains */
2728 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2729 if (te == NULL) {
2730 return NT_STATUS_NO_MEMORY;
2732 tei = &te->info;
2733 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2736 * We're always within a native forest
2738 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2739 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2741 /* For now we assume we're always the tree root */
2742 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2743 tei->parent_index = 0;
2745 tei->trust_type = our_tdo->trust_type;
2747 * This needs to be 0 instead of our_tdo->trust_attributes
2748 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2749 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2751 tei->trust_attributes = 0;
2753 info->trust_extension.info = te;
2756 if (is_trust_list) {
2757 info->dns_domainname.string = our_tdo->domain_name.string;
2759 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2760 info->dns_forestname.string = NULL;
2761 } else {
2762 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2763 our_tdo->domain_name.string);
2764 if (info->dns_domainname.string == NULL) {
2765 return NT_STATUS_NO_MEMORY;
2768 info->dns_forestname.string = info->dns_domainname.string;
2771 info->domainname.string = our_tdo->netbios_name.string;
2772 info->domain_sid = our_tdo->sid;
2773 info->domain_guid = domain_guid;
2775 return NT_STATUS_OK;
2779 fill in a netr_OneDomainInfo from a trust tdo
2781 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2782 struct GUID domain_guid,
2783 const struct lsa_TrustDomainInfoInfoEx *tdo,
2784 struct netr_OneDomainInfo *info)
2786 struct netr_trust_extension *te = NULL;
2787 struct netr_trust_extension_info *tei = NULL;
2789 ZERO_STRUCTP(info);
2791 /* w2k8 only fills this on trusted domains */
2792 te = talloc_zero(mem_ctx, struct netr_trust_extension);
2793 if (te == NULL) {
2794 return NT_STATUS_NO_MEMORY;
2796 tei = &te->info;
2798 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2799 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2801 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2802 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2804 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2805 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2809 * TODO: once we support multiple domains within our forest,
2810 * we need to fill this correct (or let the caller do it
2811 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2813 tei->parent_index = 0;
2815 tei->trust_type = tdo->trust_type;
2816 tei->trust_attributes = tdo->trust_attributes;
2818 info->trust_extension.info = te;
2820 info->domainname.string = tdo->netbios_name.string;
2821 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2822 info->dns_domainname.string = tdo->domain_name.string;
2823 } else {
2824 info->dns_domainname.string = NULL;
2826 info->domain_sid = tdo->sid;
2827 info->domain_guid = domain_guid;
2829 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2830 info->dns_forestname.string = NULL;
2832 return NT_STATUS_OK;
2836 netr_LogonGetDomainInfo
2837 this is called as part of the ADS domain logon procedure.
2839 It has an important role in convaying details about the client, such
2840 as Operating System, Version, Service Pack etc.
2842 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2843 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2845 struct netlogon_creds_CredentialState *creds;
2846 const struct dom_sid *client_sid = NULL;
2847 static const char *const trusts_attrs[] = {"securityIdentifier",
2848 "flatName",
2849 "trustPartner",
2850 "trustAttributes",
2851 "trustDirection",
2852 "trustType",
2853 NULL};
2854 static const char *const attrs2[] = {"sAMAccountName",
2855 "dNSHostName",
2856 "msDS-SupportedEncryptionTypes",
2857 NULL};
2858 const char *sam_account_name, *old_dns_hostname;
2859 struct ldb_context *sam_ctx;
2860 const struct GUID *our_domain_guid = NULL;
2861 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2862 struct ldb_message **res1, *new_msg;
2863 struct ldb_result *trusts_res = NULL;
2864 struct ldb_dn *workstation_dn;
2865 struct netr_DomainInformation *domain_info;
2866 struct netr_LsaPolicyInformation *lsa_policy_info;
2867 struct auth_session_info *workstation_session_info = NULL;
2868 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2869 bool update_dns_hostname = true;
2870 int ret, i;
2871 NTSTATUS status;
2873 status = dcesrv_netr_creds_server_step_check(dce_call,
2874 mem_ctx,
2875 r->in.computer_name,
2876 r->in.credential,
2877 r->out.return_authenticator,
2878 &creds);
2879 if (!NT_STATUS_IS_OK(status)) {
2880 char* local = NULL;
2881 char* remote = NULL;
2882 TALLOC_CTX *frame = talloc_stackframe();
2883 remote = tsocket_address_string(dce_call->conn->remote_address,
2884 frame);
2885 local = tsocket_address_string(dce_call->conn->local_address,
2886 frame);
2887 DBG_ERR("Bad credentials - "
2888 "computer[%s] remote[%s] local[%s]\n",
2889 log_escape(frame, r->in.computer_name),
2890 remote,
2891 local);
2892 talloc_free(frame);
2894 NT_STATUS_NOT_OK_RETURN(status);
2895 client_sid = &creds->client_sid;
2897 /* We want to avoid connecting as system. */
2898 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
2899 if (sam_ctx == NULL) {
2900 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2903 switch (r->in.level) {
2904 case 1: /* Domain information */
2906 if (r->in.query->workstation_info == NULL) {
2907 return NT_STATUS_INVALID_PARAMETER;
2910 /* Prepares the workstation DN */
2911 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2912 dom_sid_string(mem_ctx, client_sid));
2913 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2915 /* Get the workstation's session info from the database. */
2916 status = authsam_get_session_info_principal(mem_ctx,
2917 dce_call->conn->dce_ctx->lp_ctx,
2918 sam_ctx,
2919 NULL, /* principal */
2920 workstation_dn,
2921 0, /* session_info_flags */
2922 &workstation_session_info);
2923 if (!NT_STATUS_IS_OK(status)) {
2924 return status;
2928 * Reconnect to samdb as the workstation, now that we have its
2929 * session info. We do this so the database update can be
2930 * attributed to the workstation account in the audit logs --
2931 * otherwise it might be incorrectly attributed to
2932 * SID_NT_ANONYMOUS.
2934 sam_ctx = dcesrv_samdb_connect_session_info(mem_ctx,
2935 dce_call,
2936 workstation_session_info,
2937 workstation_session_info);
2938 if (sam_ctx == NULL) {
2939 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2942 /* Lookup for attributes in workstation object */
2943 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2944 attrs2);
2945 if (ret != 1) {
2946 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2949 /* Gets the sam account name which is checked against the DNS
2950 * hostname parameter. */
2951 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2952 "sAMAccountName",
2953 NULL);
2954 if (sam_account_name == NULL) {
2955 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2958 if (r->in.query->workstation_info->dns_hostname == NULL) {
2959 update_dns_hostname = false;
2962 /* Gets the old DNS hostname */
2963 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2964 "dNSHostName",
2965 NULL);
2968 * Updates the DNS hostname when the client wishes that the
2969 * server should handle this for him
2970 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
2971 * See MS-NRPC section 3.5.4.3.9
2973 if ((r->in.query->workstation_info->workstation_flags
2974 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2975 update_dns_hostname = false;
2978 /* Gets host information and put them into our directory */
2980 new_msg = ldb_msg_new(mem_ctx);
2981 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2983 new_msg->dn = workstation_dn;
2985 /* Sets the OS name */
2987 if (r->in.query->workstation_info->os_name.string == NULL) {
2988 return NT_STATUS_INVALID_PARAMETER;
2991 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2992 r->in.query->workstation_info->os_name.string);
2993 if (ret != LDB_SUCCESS) {
2994 return NT_STATUS_NO_MEMORY;
2998 * Sets information from "os_version". On an empty structure
2999 * the values are cleared.
3001 if (r->in.query->workstation_info->os_version.os != NULL) {
3002 struct netr_OsVersionInfoEx *os_version;
3003 const char *os_version_str;
3005 os_version = &r->in.query->workstation_info->os_version.os->os;
3007 if (os_version->CSDVersion == NULL) {
3008 return NT_STATUS_INVALID_PARAMETER;
3011 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
3012 os_version->MajorVersion,
3013 os_version->MinorVersion,
3014 os_version->BuildNumber);
3015 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
3017 if (strlen(os_version->CSDVersion) != 0) {
3018 ret = ldb_msg_add_string(new_msg,
3019 "operatingSystemServicePack",
3020 os_version->CSDVersion);
3021 } else {
3022 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
3023 "operatingSystemServicePack");
3025 if (ret != LDB_SUCCESS) {
3026 return NT_STATUS_NO_MEMORY;
3029 ret = ldb_msg_add_string(new_msg,
3030 "operatingSystemVersion",
3031 os_version_str);
3032 if (ret != LDB_SUCCESS) {
3033 return NT_STATUS_NO_MEMORY;
3035 } else {
3036 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
3037 "operatingSystemServicePack");
3038 if (ret != LDB_SUCCESS) {
3039 return NT_STATUS_NO_MEMORY;
3042 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
3043 "operatingSystemVersion");
3044 if (ret != LDB_SUCCESS) {
3045 return NT_STATUS_NO_MEMORY;
3050 * If the boolean "update_dns_hostname" remained true, then we
3051 * are fine to start the update.
3053 if (update_dns_hostname) {
3054 ret = ldb_msg_add_string(new_msg,
3055 "dNSHostname",
3056 r->in.query->workstation_info->dns_hostname);
3057 if (ret != LDB_SUCCESS) {
3058 return NT_STATUS_NO_MEMORY;
3061 /* This manual "servicePrincipalName" generation is
3062 * still needed! Since the update in the samldb LDB
3063 * module does only work if the entries already exist
3064 * which isn't always the case. */
3065 ret = ldb_msg_add_string(new_msg,
3066 "servicePrincipalName",
3067 talloc_asprintf(new_msg, "HOST/%s",
3068 r->in.computer_name));
3069 if (ret != LDB_SUCCESS) {
3070 return NT_STATUS_NO_MEMORY;
3073 ret = ldb_msg_add_string(new_msg,
3074 "servicePrincipalName",
3075 talloc_asprintf(new_msg, "HOST/%s",
3076 r->in.query->workstation_info->dns_hostname));
3077 if (ret != LDB_SUCCESS) {
3078 return NT_STATUS_NO_MEMORY;
3082 if (dsdb_replace(sam_ctx, new_msg, DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) != LDB_SUCCESS) {
3083 DEBUG(3,("Impossible to update samdb: %s\n",
3084 ldb_errstring(sam_ctx)));
3087 talloc_free(new_msg);
3089 /* Writes back the domain information */
3091 our_domain_guid = samdb_domain_guid(sam_ctx);
3092 if (our_domain_guid == NULL) {
3093 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3096 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
3097 if (!NT_STATUS_IS_OK(status)) {
3098 return status;
3101 status = dsdb_trust_search_tdos(sam_ctx,
3102 NULL, /* exclude */
3103 trusts_attrs,
3104 mem_ctx,
3105 &trusts_res);
3106 if (!NT_STATUS_IS_OK(status)) {
3107 return status;
3110 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
3111 NT_STATUS_HAVE_NO_MEMORY(domain_info);
3113 ZERO_STRUCTP(domain_info);
3115 /* Information about the local and trusted domains */
3117 status = fill_our_one_domain_info(mem_ctx,
3118 our_tdo,
3119 *our_domain_guid,
3120 &domain_info->primary_domain,
3121 false);
3122 if (!NT_STATUS_IS_OK(status)) {
3123 return status;
3126 domain_info->trusted_domain_count = trusts_res->count + 1;
3127 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
3128 struct netr_OneDomainInfo,
3129 domain_info->trusted_domain_count);
3130 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
3132 for (i=0; i < trusts_res->count; i++) {
3133 struct netr_OneDomainInfo *o =
3134 &domain_info->trusted_domains[i];
3135 /* we can't know the guid of trusts outside our forest */
3136 struct GUID trust_domain_guid = GUID_zero();
3137 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
3139 status = dsdb_trust_parse_tdo_info(mem_ctx,
3140 trusts_res->msgs[i],
3141 &tdo);
3142 if (!NT_STATUS_IS_OK(status)) {
3143 return status;
3146 status = fill_trust_one_domain_info(mem_ctx,
3147 trust_domain_guid,
3148 tdo,
3150 if (!NT_STATUS_IS_OK(status)) {
3151 return status;
3155 status = fill_our_one_domain_info(mem_ctx,
3156 our_tdo,
3157 *our_domain_guid,
3158 &domain_info->trusted_domains[i],
3159 true);
3160 if (!NT_STATUS_IS_OK(status)) {
3161 return status;
3164 /* Sets the supported encryption types */
3165 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
3166 "msDS-SupportedEncryptionTypes",
3167 default_supported_enc_types);
3169 /* Other host domain information */
3171 lsa_policy_info = talloc(mem_ctx,
3172 struct netr_LsaPolicyInformation);
3173 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
3174 ZERO_STRUCTP(lsa_policy_info);
3176 domain_info->lsa_policy = *lsa_policy_info;
3178 /* The DNS hostname is only returned back when there is a chance
3179 * for a change. */
3180 if ((r->in.query->workstation_info->workstation_flags
3181 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
3182 domain_info->dns_hostname.string = old_dns_hostname;
3183 } else {
3184 domain_info->dns_hostname.string = NULL;
3187 domain_info->workstation_flags =
3188 r->in.query->workstation_info->workstation_flags & (
3189 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
3191 r->out.info->domain_info = domain_info;
3192 break;
3193 case 2: /* LSA policy information - not used at the moment */
3194 lsa_policy_info = talloc(mem_ctx,
3195 struct netr_LsaPolicyInformation);
3196 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
3197 ZERO_STRUCTP(lsa_policy_info);
3199 r->out.info->lsa_policy_info = lsa_policy_info;
3200 break;
3201 default:
3202 return NT_STATUS_INVALID_LEVEL;
3203 break;
3206 return NT_STATUS_OK;
3210 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3211 struct netr_ServerGetTrustInfo *r);
3214 netr_ServerPasswordGet
3216 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3217 struct netr_ServerPasswordGet *r)
3219 struct netr_ServerGetTrustInfo r2 = {};
3220 struct samr_Password old_owf_password = {};
3221 struct netr_TrustInfo *_ti = NULL;
3222 NTSTATUS status;
3224 r2.in.server_name = r->in.server_name;
3225 r2.in.account_name = r->in.account_name;
3226 r2.in.secure_channel_type = r->in.secure_channel_type;
3227 r2.in.computer_name = r->in.computer_name;
3228 r2.in.credential = r->in.credential;
3230 r2.out.return_authenticator = r->out.return_authenticator;
3231 r2.out.new_owf_password = r->out.password;
3232 r2.out.old_owf_password = &old_owf_password;
3233 r2.out.trust_info = &_ti;
3235 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3237 r->out.return_authenticator = r2.out.return_authenticator;
3238 r->out.password = r2.out.new_owf_password;
3240 ZERO_STRUCT(old_owf_password);
3241 switch (r->in.secure_channel_type) {
3242 case SEC_CHAN_BDC:
3243 break;
3244 default:
3245 ZERO_STRUCTP(r->out.password);
3246 return NT_STATUS_ACCESS_DENIED;
3249 return status;
3252 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
3253 TALLOC_CTX *mem_ctx,
3254 const struct dom_sid *user_sid,
3255 struct ldb_dn *obj_dn)
3257 static const char *rodc_attrs[] = {"msDS-NeverRevealGroup",
3258 "msDS-RevealOnDemandGroup",
3259 "userAccountControl",
3260 NULL};
3261 static const char *obj_attrs[] = {"tokenGroups",
3262 "objectSid",
3263 "UserAccountControl",
3264 "msDS-KrbTgtLinkBL",
3265 NULL};
3266 struct ldb_dn *rodc_dn;
3267 int ret;
3268 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
3269 WERROR werr;
3271 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
3272 dom_sid_string(mem_ctx, user_sid));
3273 if (!ldb_dn_validate(rodc_dn)) goto denied;
3276 * do the two searches we need
3277 * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list
3278 * out of the extended DNs
3280 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
3281 DSDB_SEARCH_SHOW_EXTENDED_DN);
3282 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
3284 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
3285 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
3287 werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx,
3288 user_sid,
3289 rodc_res->msgs[0],
3290 obj_res->msgs[0]);
3292 if (W_ERROR_IS_OK(werr)) {
3293 goto allowed;
3295 denied:
3296 return false;
3297 allowed:
3298 return true;
3303 netr_NetrLogonSendToSam
3305 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3306 struct netr_NetrLogonSendToSam *r)
3308 struct netlogon_creds_CredentialState *creds;
3309 const struct dom_sid *client_sid = NULL;
3310 struct ldb_context *sam_ctx;
3311 NTSTATUS nt_status;
3312 DATA_BLOB decrypted_blob;
3313 enum ndr_err_code ndr_err;
3314 struct netr_SendToSamBase base_msg = { 0 };
3315 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
3316 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
3318 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
3320 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3321 mem_ctx,
3322 r->in.computer_name,
3323 r->in.credential,
3324 r->out.return_authenticator,
3325 &creds);
3327 NT_STATUS_NOT_OK_RETURN(nt_status);
3328 client_sid = &creds->client_sid;
3330 switch (creds->secure_channel_type) {
3331 case SEC_CHAN_BDC:
3332 case SEC_CHAN_RODC:
3333 break;
3334 case SEC_CHAN_WKSTA:
3335 case SEC_CHAN_DNS_DOMAIN:
3336 case SEC_CHAN_DOMAIN:
3337 case SEC_CHAN_NULL:
3338 return NT_STATUS_ACCESS_DENIED;
3339 default:
3340 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
3341 creds->secure_channel_type));
3342 return NT_STATUS_INVALID_PARAMETER;
3345 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
3346 if (sam_ctx == NULL) {
3347 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3350 /* Buffer is meant to be 16-bit aligned */
3352 nt_status = netlogon_creds_decrypt_SendToSam(creds,
3353 r->in.opaque_buffer,
3354 r->in.buffer_len,
3355 auth_type,
3356 auth_level);
3357 if (!NT_STATUS_IS_OK(nt_status)) {
3358 return nt_status;
3361 decrypted_blob.data = r->in.opaque_buffer;
3362 decrypted_blob.length = r->in.buffer_len;
3364 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
3365 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
3367 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3368 return NT_STATUS_INVALID_PARAMETER;
3371 /* Now 'send' to SAM */
3372 switch (base_msg.message_type) {
3373 case SendToSamResetBadPasswordCount:
3375 struct ldb_message *msg = ldb_msg_new(mem_ctx);
3376 struct ldb_dn *dn = NULL;
3377 int ret = 0;
3380 ret = ldb_transaction_start(sam_ctx);
3381 if (ret != LDB_SUCCESS) {
3382 return NT_STATUS_INTERNAL_ERROR;
3385 ret = dsdb_find_dn_by_guid(sam_ctx,
3386 mem_ctx,
3387 &base_msg.message.reset_bad_password.guid,
3389 &dn);
3390 if (ret != LDB_SUCCESS) {
3391 ldb_transaction_cancel(sam_ctx);
3392 if (creds->secure_channel_type == SEC_CHAN_RODC) {
3393 return NT_STATUS_INTERNAL_ERROR;
3395 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3398 if (creds->secure_channel_type == SEC_CHAN_RODC &&
3399 !sam_rodc_access_check(sam_ctx, mem_ctx, client_sid, dn)) {
3400 DEBUG(1, ("Client asked to reset bad password on "
3401 "an arbitrary user: %s\n",
3402 ldb_dn_get_linearized(dn)));
3403 ldb_transaction_cancel(sam_ctx);
3404 return NT_STATUS_ACCESS_DENIED;
3407 msg->dn = dn;
3409 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
3410 if (ret != LDB_SUCCESS) {
3411 ldb_transaction_cancel(sam_ctx);
3412 return NT_STATUS_INVALID_PARAMETER;
3415 ret = dsdb_replace(sam_ctx, msg, 0);
3416 if (ret != LDB_SUCCESS) {
3417 ldb_transaction_cancel(sam_ctx);
3418 return NT_STATUS_INVALID_PARAMETER;
3421 ret = ldb_transaction_commit(sam_ctx);
3422 if (ret != LDB_SUCCESS) {
3423 ldb_transaction_cancel(sam_ctx);
3424 return NT_STATUS_INTERNAL_ERROR;
3427 break;
3429 default:
3430 return NT_STATUS_NOT_IMPLEMENTED;
3433 return NT_STATUS_OK;
3436 struct dcesrv_netr_DsRGetDCName_base_state {
3437 struct dcesrv_call_state *dce_call;
3438 TALLOC_CTX *mem_ctx;
3440 struct netr_DsRGetDCNameEx2 r;
3441 const char *client_site;
3443 struct {
3444 struct netr_DsRGetDCName *dc;
3445 struct netr_DsRGetDCNameEx *dcex;
3446 struct netr_DsRGetDCNameEx2 *dcex2;
3447 } _r;
3450 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
3452 /* Returns a nonzero value if multiple bits in 'val' are set. */
3453 static bool multiple_bits_set(uint32_t val)
3456 * Subtracting one from an integer has the effect of flipping all the
3457 * bits from the least significant bit up to and including the least
3458 * significant '1' bit. For example,
3460 * 0b101000 - 1
3461 * = 0b100111
3462 * ====
3464 * If 'val' is zero, all the bits will be flipped and thus the bitwise
3465 * AND of 'val' with 'val - 1' will be zero.
3467 * If the integer is nonzero, the least significant '1' bit will be
3468 * ANDed with a '0' bit and so will be reset in the final result, but
3469 * all other '1' bits will remain set. In other words, the effect of
3470 * this expression is to mask off the least significant bit that is
3471 * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
3472 * must contain multiple set bits.
3474 return val & (val - 1);
3477 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
3479 struct dcesrv_call_state *dce_call = state->dce_call;
3480 struct imessaging_context *imsg_ctx =
3481 dcesrv_imessaging_context(dce_call->conn);
3482 TALLOC_CTX *mem_ctx = state->mem_ctx;
3483 struct netr_DsRGetDCNameEx2 *r = &state->r;
3484 struct ldb_context *sam_ctx;
3485 struct netr_DsRGetDCNameInfo *info;
3486 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3487 const struct tsocket_address *local_address;
3488 char *local_addr = NULL;
3489 const struct tsocket_address *remote_address;
3490 char *remote_addr = NULL;
3491 const char *server_site_name;
3492 char *guid_str;
3493 struct netlogon_samlogon_response response;
3494 NTSTATUS status;
3495 const char *dc_name = NULL;
3496 const char *domain_name = NULL;
3497 const char *pdc_ip;
3498 bool different_domain = true;
3499 bool force_remote_lookup = false;
3500 uint32_t valid_flags;
3501 uint32_t this_dc_valid_flags;
3502 int dc_level;
3504 ZERO_STRUCTP(r->out.info);
3506 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
3507 if (sam_ctx == NULL) {
3508 return WERR_DS_UNAVAILABLE;
3511 local_address = dcesrv_connection_get_local_address(dce_call->conn);
3512 if (tsocket_address_is_inet(local_address, "ip")) {
3513 local_addr = tsocket_address_inet_addr_string(local_address, state);
3514 W_ERROR_HAVE_NO_MEMORY(local_addr);
3517 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
3518 if (tsocket_address_is_inet(remote_address, "ip")) {
3519 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
3520 W_ERROR_HAVE_NO_MEMORY(remote_addr);
3523 /* "server_unc" is ignored by w2k3 */
3526 * With the following flags:
3527 * DS_FORCE_REDISCOVERY (Flag A)
3528 * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
3529 * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
3530 * DS_GC_SERVER_REQUIRED (Flag D)
3531 * DS_PDC_REQUIRED (Flag E)
3532 * DS_BACKGROUND_ONLY (Flag F)
3533 * DS_IP_REQUIRED (Flag G)
3534 * DS_KDC_REQUIRED (Flag H)
3535 * DS_TIMESERV_REQUIRED (Flag I)
3536 * DS_WRITABLE_REQUIRED (Flag J)
3537 * DS_GOOD_TIMESERV_PREFERRED (Flag K)
3538 * DS_AVOID_SELF (Flag L)
3539 * DS_ONLY_LDAP_NEEDED (Flag M)
3540 * DS_IS_FLAT_NAME (Flag N)
3541 * DS_IS_DNS_NAME (Flag O)
3542 * DS_TRY_NEXTCLOSEST_SITE (Flag P)
3543 * DS_DIRECTORY_SERVICE_6_REQUIRED (Flag Q)
3544 * DS_WEB_SERVICE_REQUIRED (Flag T)
3545 * DS_DIRECTORY_SERVICE_8_REQUIRED (Flag U)
3546 * DS_DIRECTORY_SERVICE_9_REQUIRED (Flag V)
3547 * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
3548 * DS_RETURN_DNS_NAME (Flag R)
3549 * DS_RETURN_FLAT_NAME (Flag S)
3551 * MS-NRPC 3.5.4.3.1 says:
3552 * ...
3553 * On receiving this call, the server MUST perform the following Flags
3554 * parameter validations:
3555 * - Flags D, E, and H MUST NOT be combined with each other.
3556 * - Flag N MUST NOT be combined with the O flag.
3557 * - Flag R MUST NOT be combined with the S flag.
3558 * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
3559 * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or H.
3560 * - Flag P MUST NOT be set when the SiteName parameter is provided.
3561 * The server MUST return ERROR_INVALID_FLAGS for any of the previously
3562 * mentioned conflicting combinations.
3563 * ...
3566 valid_flags = DSGETDC_VALID_FLAGS;
3568 if (r->in.flags & ~valid_flags) {
3570 * TODO: add tests to prove this (maybe based on the
3571 * msDS-Behavior-Version levels of dc, domain and/or forest
3573 return WERR_INVALID_FLAGS;
3576 /* Flags D, E, and H MUST NOT be combined with each other. */
3577 #define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
3578 if (multiple_bits_set(r->in.flags & _DEH)) {
3579 return WERR_INVALID_FLAGS;
3582 /* Flag N MUST NOT be combined with the O flag. */
3583 if (r->in.flags & DS_IS_FLAT_NAME &&
3584 r->in.flags & DS_IS_DNS_NAME) {
3585 return WERR_INVALID_FLAGS;
3588 /* Flag R MUST NOT be combined with the S flag. */
3589 if (r->in.flags & DS_RETURN_DNS_NAME &&
3590 r->in.flags & DS_RETURN_FLAT_NAME) {
3591 return WERR_INVALID_FLAGS;
3594 /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
3595 #define _BQUVW ( \
3596 DS_DIRECTORY_SERVICE_REQUIRED | \
3597 DS_DIRECTORY_SERVICE_6_REQUIRED | \
3598 DS_DIRECTORY_SERVICE_8_REQUIRED | \
3599 DS_DIRECTORY_SERVICE_9_REQUIRED | \
3600 DS_DIRECTORY_SERVICE_10_REQUIRED | \
3602 if (multiple_bits_set(r->in.flags & _BQUVW)) {
3603 return WERR_INVALID_FLAGS;
3607 * Flag K MUST NOT be combined with any of the flags:
3608 * B, C, D, E, or H.
3610 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
3611 r->in.flags &
3612 (DS_DIRECTORY_SERVICE_REQUIRED |
3613 DS_DIRECTORY_SERVICE_PREFERRED |
3614 DS_GC_SERVER_REQUIRED |
3615 DS_PDC_REQUIRED |
3616 DS_KDC_REQUIRED)) {
3617 return WERR_INVALID_FLAGS;
3620 /* Flag P MUST NOT be set when the SiteName parameter is provided. */
3621 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
3622 r->in.site_name) {
3623 return WERR_INVALID_FLAGS;
3627 * If we send an all-zero GUID, we should ignore it as winbind actually
3628 * checks it with a DNS query. Windows also appears to ignore it.
3630 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
3631 r->in.domain_guid = NULL;
3634 /* Attempt winbind search only if we suspect the domain is incorrect */
3635 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
3636 if (r->in.flags & DS_IS_FLAT_NAME) {
3637 if (strcasecmp_m(r->in.domain_name,
3638 lpcfg_sam_name(lp_ctx)) == 0) {
3639 different_domain = false;
3641 } else if (r->in.flags & DS_IS_DNS_NAME) {
3642 if (strcasecmp_m(r->in.domain_name,
3643 lpcfg_dnsdomain(lp_ctx)) == 0) {
3644 different_domain = false;
3646 } else {
3647 if (strcasecmp_m(r->in.domain_name,
3648 lpcfg_sam_name(lp_ctx)) == 0 ||
3649 strcasecmp_m(r->in.domain_name,
3650 lpcfg_dnsdomain(lp_ctx)) == 0) {
3651 different_domain = false;
3654 } else {
3656 * We need to be able to handle empty domain names, where we
3657 * revert to our domain by default.
3659 different_domain = false;
3662 if (!different_domain) {
3663 dc_level = dsdb_dc_functional_level(sam_ctx);
3666 * Do not return a local response if we do not support the
3667 * functional level or feature (eg web services)
3669 this_dc_valid_flags = valid_flags;
3671 /* Samba does not implement this */
3672 this_dc_valid_flags &= ~DS_WEB_SERVICE_REQUIRED;
3674 if (dc_level < DS_DOMAIN_FUNCTION_2012) {
3675 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_8_REQUIRED;
3677 if (dc_level < DS_DOMAIN_FUNCTION_2012_R2) {
3678 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_9_REQUIRED;
3680 if (dc_level < DS_DOMAIN_FUNCTION_2016) {
3681 this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_10_REQUIRED;
3683 if (r->in.flags & ~this_dc_valid_flags) {
3684 DBG_INFO("Forcing remote lookup to find another DC "
3685 "in this domain %s with more features, "
3686 "as this Samba DC is Functional level %d but flags are 0x08%x\n",
3687 r->in.domain_name, dc_level, (unsigned int)r->in.flags);
3688 force_remote_lookup = true;
3692 /* Proof server site parameter "site_name" if it was specified */
3693 server_site_name = samdb_server_site_name(sam_ctx, state);
3694 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3695 if (force_remote_lookup
3696 || different_domain
3697 || (r->in.site_name != NULL &&
3698 (strcasecmp_m(r->in.site_name,
3699 server_site_name) != 0))) {
3701 struct dcerpc_binding_handle *irpc_handle = NULL;
3702 struct tevent_req *subreq = NULL;
3705 * Retrieve the client site to override the winbind response.
3707 * DO NOT use Windows fallback for client site.
3708 * In the case of multiple domains, this is plainly wrong.
3710 * Note: It's possible that the client may belong to multiple
3711 * subnets across domains. It's not clear what this would mean,
3712 * but here we only return what this domain knows.
3714 state->client_site = samdb_client_site_name(sam_ctx,
3715 state,
3716 remote_addr,
3717 NULL,
3718 false);
3720 irpc_handle = irpc_binding_handle_by_name(state,
3721 imsg_ctx,
3722 "winbind_server",
3723 &ndr_table_winbind);
3724 if (irpc_handle == NULL) {
3725 DEBUG(0,("Failed to get binding_handle for "
3726 "winbind_server task\n"));
3727 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3728 return WERR_SERVICE_NOT_FOUND;
3731 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3733 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3735 subreq = dcerpc_wbint_DsGetDcName_send(state,
3736 dce_call->event_ctx,
3737 irpc_handle,
3738 r->in.domain_name,
3739 r->in.domain_guid,
3740 r->in.site_name,
3741 r->in.flags,
3742 r->out.info);
3743 if (subreq == NULL) {
3744 return WERR_NOT_ENOUGH_MEMORY;
3747 tevent_req_set_callback(subreq,
3748 dcesrv_netr_DsRGetDCName_base_done,
3749 state);
3751 return WERR_OK;
3754 guid_str = r->in.domain_guid != NULL ?
3755 GUID_string(state, r->in.domain_guid) : NULL;
3757 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3758 r->in.domain_name,
3759 r->in.domain_name,
3760 NULL, guid_str,
3761 r->in.client_account,
3762 r->in.mask, remote_addr,
3763 NETLOGON_NT_VERSION_5EX_WITH_IP,
3764 lp_ctx, &response, true);
3765 if (!NT_STATUS_IS_OK(status)) {
3766 return ntstatus_to_werror(status);
3770 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3771 * (O) flag when the returned forest name is in DNS format. This is here
3772 * always the case (see below).
3774 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3776 if (r->in.flags & DS_RETURN_DNS_NAME) {
3777 dc_name = response.data.nt5_ex.pdc_dns_name;
3778 domain_name = response.data.nt5_ex.dns_domain;
3780 * According to MS-NRPC 2.2.1.2.1 we should set the
3781 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3782 * the returned information is in DNS form.
3784 response.data.nt5_ex.server_type |=
3785 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3786 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3787 dc_name = response.data.nt5_ex.pdc_name;
3788 domain_name = response.data.nt5_ex.domain_name;
3789 } else {
3792 * TODO: autodetect what we need to return
3793 * based on the given arguments
3795 dc_name = response.data.nt5_ex.pdc_name;
3796 domain_name = response.data.nt5_ex.domain_name;
3799 if (!dc_name || !dc_name[0]) {
3800 return WERR_NO_SUCH_DOMAIN;
3803 if (!domain_name || !domain_name[0]) {
3804 return WERR_NO_SUCH_DOMAIN;
3807 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3808 W_ERROR_HAVE_NO_MEMORY(info);
3809 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3810 dc_name[0] != '\\'? "\\\\":"",
3811 talloc_strdup(mem_ctx, dc_name));
3812 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3814 pdc_ip = local_addr;
3815 if (pdc_ip == NULL) {
3816 pdc_ip = "127.0.0.1";
3818 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3819 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3820 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3821 info->domain_guid = response.data.nt5_ex.domain_uuid;
3822 info->domain_name = domain_name;
3823 info->forest_name = response.data.nt5_ex.forest;
3824 info->dc_flags = response.data.nt5_ex.server_type;
3825 if (r->in.flags & DS_RETURN_DNS_NAME) {
3826 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3827 * returned if we are returning info->dc_unc containing a FQDN.
3828 * This attribute is called DomainControllerName in the specs,
3829 * it seems that we decide to return FQDN or netbios depending on
3830 * DS_RETURN_DNS_NAME.
3832 info->dc_flags |= DS_DNS_CONTROLLER;
3834 info->dc_site_name = response.data.nt5_ex.server_site;
3835 info->client_site_name = response.data.nt5_ex.client_site;
3837 *r->out.info = info;
3839 return WERR_OK;
3842 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3844 struct dcesrv_netr_DsRGetDCName_base_state *state =
3845 tevent_req_callback_data(subreq,
3846 struct dcesrv_netr_DsRGetDCName_base_state);
3847 struct dcesrv_call_state *dce_call = state->dce_call;
3848 NTSTATUS result, status;
3850 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3851 state->mem_ctx,
3852 &result);
3853 TALLOC_FREE(subreq);
3855 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3856 state->r.out.result = WERR_TIMEOUT;
3857 goto finished;
3860 if (!NT_STATUS_IS_OK(status)) {
3861 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3862 nt_errstr(status));
3863 state->r.out.result = WERR_GEN_FAILURE;
3864 goto finished;
3867 if (!NT_STATUS_IS_OK(result)) {
3868 DBG_NOTICE("DC location via winbind failed - %s\n",
3869 nt_errstr(result));
3870 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3871 goto finished;
3874 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3875 DBG_ERR("DC location via winbind returned no results\n");
3876 state->r.out.result = WERR_GEN_FAILURE;
3877 goto finished;
3880 if (state->r.out.info[0]->dc_unc == NULL) {
3881 DBG_ERR("DC location via winbind returned no DC unc\n");
3882 state->r.out.result = WERR_GEN_FAILURE;
3883 goto finished;
3887 * Either the supplied site name is NULL (possibly via
3888 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3889 * the input match name.
3891 * TODO: Currently this means that requests with NETBIOS domain
3892 * names can fail because they do not return the site name.
3894 if (state->r.in.site_name == NULL ||
3895 strcasecmp_m("", state->r.in.site_name) == 0 ||
3896 (state->r.out.info[0]->dc_site_name != NULL &&
3897 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3898 state->r.in.site_name) == 0)) {
3900 state->r.out.info[0]->client_site_name =
3901 talloc_move(state->mem_ctx, &state->client_site);
3904 * Make sure to return our DC UNC with // prefix.
3905 * Winbind currently doesn't send the leading slashes
3906 * for some reason.
3908 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3909 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3910 const char *dc_unc = NULL;
3912 dc_unc = talloc_asprintf(state->mem_ctx,
3913 "\\\\%s",
3914 state->r.out.info[0]->dc_unc);
3915 state->r.out.info[0]->dc_unc = dc_unc;
3918 state->r.out.result = WERR_OK;
3919 } else {
3920 state->r.out.info = NULL;
3921 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3924 finished:
3925 if (state->_r.dcex2 != NULL) {
3926 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3927 r->out.result = state->r.out.result;
3928 } else if (state->_r.dcex != NULL) {
3929 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3930 r->out.result = state->r.out.result;
3931 } else if (state->_r.dc != NULL) {
3932 struct netr_DsRGetDCName *r = state->_r.dc;
3933 r->out.result = state->r.out.result;
3936 TALLOC_FREE(state);
3937 dcesrv_async_reply(dce_call);
3941 netr_DsRGetDCNameEx2
3943 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3944 TALLOC_CTX *mem_ctx,
3945 struct netr_DsRGetDCNameEx2 *r)
3947 struct dcesrv_netr_DsRGetDCName_base_state *state;
3949 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3950 if (state == NULL) {
3951 return WERR_NOT_ENOUGH_MEMORY;
3954 state->dce_call = dce_call;
3955 state->mem_ctx = mem_ctx;
3957 state->r = *r;
3958 state->_r.dcex2 = r;
3960 return dcesrv_netr_DsRGetDCName_base_call(state);
3964 netr_DsRGetDCNameEx
3966 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3967 struct netr_DsRGetDCNameEx *r)
3969 struct dcesrv_netr_DsRGetDCName_base_state *state;
3971 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3972 if (state == NULL) {
3973 return WERR_NOT_ENOUGH_MEMORY;
3976 state->dce_call = dce_call;
3977 state->mem_ctx = mem_ctx;
3979 state->r.in.server_unc = r->in.server_unc;
3980 state->r.in.client_account = NULL;
3981 state->r.in.mask = 0;
3982 state->r.in.domain_guid = r->in.domain_guid;
3983 state->r.in.domain_name = r->in.domain_name;
3984 state->r.in.site_name = r->in.site_name;
3985 state->r.in.flags = r->in.flags;
3986 state->r.out.info = r->out.info;
3988 state->_r.dcex = r;
3990 return dcesrv_netr_DsRGetDCName_base_call(state);
3994 * netr_DsRGetDCName
3996 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3997 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3998 * insists that it be ignored.
4000 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4001 struct netr_DsRGetDCName *r)
4003 struct dcesrv_netr_DsRGetDCName_base_state *state;
4005 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
4006 if (state == NULL) {
4007 return WERR_NOT_ENOUGH_MEMORY;
4010 state->dce_call = dce_call;
4011 state->mem_ctx = mem_ctx;
4013 state->r.in.server_unc = r->in.server_unc;
4014 state->r.in.client_account = NULL;
4015 state->r.in.mask = 0;
4016 state->r.in.domain_name = r->in.domain_name;
4017 state->r.in.domain_guid = r->in.domain_guid;
4019 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
4020 state->r.in.flags = r->in.flags;
4021 state->r.out.info = r->out.info;
4023 state->_r.dc = r;
4025 return dcesrv_netr_DsRGetDCName_base_call(state);
4028 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
4030 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4031 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
4033 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4038 netr_NetrEnumerateTrustedDomainsEx
4040 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4041 struct netr_NetrEnumerateTrustedDomainsEx *r)
4043 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4048 netr_DsRAddressToSitenamesExW
4050 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4051 struct netr_DsRAddressToSitenamesExW *r)
4053 struct ldb_context *sam_ctx;
4054 struct netr_DsRAddressToSitenamesExWCtr *ctr;
4055 sa_family_t sin_family;
4056 struct sockaddr_in *addr;
4057 #ifdef HAVE_IPV6
4058 struct sockaddr_in6 *addr6;
4059 char addr_str[INET6_ADDRSTRLEN];
4060 #else
4061 char addr_str[INET_ADDRSTRLEN];
4062 #endif
4063 char *subnet_name;
4064 const char *res;
4065 uint32_t i;
4067 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4068 if (sam_ctx == NULL) {
4069 return WERR_DS_UNAVAILABLE;
4072 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
4073 W_ERROR_HAVE_NO_MEMORY(ctr);
4075 *r->out.ctr = ctr;
4077 ctr->count = r->in.count;
4078 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
4079 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
4080 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
4081 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
4083 for (i=0; i<ctr->count; i++) {
4084 ctr->sitename[i].string = NULL;
4085 ctr->subnetname[i].string = NULL;
4087 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
4088 continue;
4090 /* The first two byte of the buffer are reserved for the
4091 * "sin_family" but for now only the first one is used. */
4092 sin_family = r->in.addresses[i].buffer[0];
4094 switch (sin_family) {
4095 case AF_INET:
4096 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
4097 continue;
4099 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
4100 res = inet_ntop(AF_INET, &addr->sin_addr,
4101 addr_str, sizeof(addr_str));
4102 break;
4103 #ifdef HAVE_IPV6
4104 case AF_INET6:
4105 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
4106 continue;
4108 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
4109 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
4110 addr_str, sizeof(addr_str));
4111 break;
4112 #endif
4113 default:
4114 continue;
4117 if (res == NULL) {
4118 continue;
4121 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
4122 mem_ctx,
4123 addr_str,
4124 &subnet_name,
4125 true);
4126 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
4127 ctr->subnetname[i].string = subnet_name;
4130 return WERR_OK;
4135 netr_DsRAddressToSitenamesW
4137 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4138 struct netr_DsRAddressToSitenamesW *r)
4140 struct netr_DsRAddressToSitenamesExW r2;
4141 struct netr_DsRAddressToSitenamesWCtr *ctr;
4142 uint32_t i;
4143 WERROR werr;
4145 ZERO_STRUCT(r2);
4147 r2.in.server_name = r->in.server_name;
4148 r2.in.count = r->in.count;
4149 r2.in.addresses = r->in.addresses;
4151 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
4152 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
4154 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
4155 W_ERROR_HAVE_NO_MEMORY(ctr);
4157 *r->out.ctr = ctr;
4159 ctr->count = r->in.count;
4160 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
4161 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
4163 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
4165 for (i=0; i<ctr->count; i++) {
4166 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
4169 return werr;
4174 netr_DsrGetDcSiteCoverageW
4176 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4177 struct netr_DsrGetDcSiteCoverageW *r)
4179 struct ldb_context *sam_ctx;
4180 struct DcSitesCtr *ctr;
4182 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4183 if (sam_ctx == NULL) {
4184 return WERR_DS_UNAVAILABLE;
4187 ctr = talloc(mem_ctx, struct DcSitesCtr);
4188 W_ERROR_HAVE_NO_MEMORY(ctr);
4190 *r->out.ctr = ctr;
4192 /* For now only return our default site */
4193 ctr->num_sites = 1;
4194 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
4195 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
4196 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
4197 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
4199 return WERR_OK;
4203 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
4204 struct ldb_context *sam_ctx,
4205 struct netr_DomainTrustList *trusts,
4206 uint32_t trust_flags)
4208 struct ldb_dn *system_dn;
4209 struct ldb_message **dom_res = NULL;
4210 static const char *trust_attrs[] = {"flatname",
4211 "trustPartner",
4212 "securityIdentifier",
4213 "trustDirection",
4214 "trustType",
4215 "trustAttributes",
4216 NULL};
4217 uint32_t n;
4218 int i;
4219 int ret;
4221 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
4222 NETR_TRUST_FLAG_OUTBOUND))) {
4223 return WERR_INVALID_FLAGS;
4226 system_dn = samdb_system_container_dn(sam_ctx, mem_ctx);
4227 if (system_dn == NULL) {
4228 return WERR_NOT_ENOUGH_MEMORY;
4231 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
4232 &dom_res, trust_attrs,
4233 "(objectclass=trustedDomain)");
4235 for (i = 0; i < ret; i++) {
4236 unsigned int trust_dir;
4237 uint32_t flags = 0;
4239 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
4240 "trustDirection", 0);
4242 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
4243 flags |= NETR_TRUST_FLAG_INBOUND;
4245 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
4246 flags |= NETR_TRUST_FLAG_OUTBOUND;
4249 if (!(flags & trust_flags)) {
4250 /* this trust direction was not requested */
4251 continue;
4254 n = trusts->count;
4255 trusts->array = talloc_realloc(trusts, trusts->array,
4256 struct netr_DomainTrust,
4257 n + 1);
4258 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4260 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
4261 if (!trusts->array[n].netbios_name) {
4262 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
4263 "without flatname\n",
4264 ldb_dn_get_linearized(dom_res[i]->dn)));
4267 trusts->array[n].trust_flags = flags;
4268 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
4269 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
4270 /* TODO: find if we have parent in the list */
4271 trusts->array[n].parent_index = 0;
4274 trusts->array[n].trust_type =
4275 ldb_msg_find_attr_as_uint(dom_res[i],
4276 "trustType", 0);
4277 trusts->array[n].trust_attributes =
4278 ldb_msg_find_attr_as_uint(dom_res[i],
4279 "trustAttributes", 0);
4281 if (trusts->array[n].trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
4282 trusts->array[n].dns_name = talloc_steal(
4283 trusts->array,
4284 ldb_msg_find_attr_as_string(dom_res[i],
4285 "trustPartner",
4286 NULL));
4287 } else {
4288 trusts->array[n].dns_name = NULL;
4291 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
4292 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
4293 struct dom_sid zero_sid;
4294 ZERO_STRUCT(zero_sid);
4295 trusts->array[n].sid =
4296 dom_sid_dup(trusts, &zero_sid);
4297 } else {
4298 trusts->array[n].sid =
4299 samdb_result_dom_sid(trusts, dom_res[i],
4300 "securityIdentifier");
4302 trusts->array[n].guid = GUID_zero();
4304 trusts->count = n + 1;
4307 talloc_free(dom_res);
4308 return WERR_OK;
4312 netr_DsrEnumerateDomainTrusts
4314 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
4315 TALLOC_CTX *mem_ctx,
4316 struct netr_DsrEnumerateDomainTrusts *r)
4318 struct netr_DomainTrustList *trusts;
4319 struct ldb_context *sam_ctx;
4320 int ret;
4321 struct ldb_message **dom_res;
4322 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
4323 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4324 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
4325 const char *p;
4326 WERROR werr;
4328 if (r->in.trust_flags & 0xFFFFFE00) {
4329 return WERR_INVALID_FLAGS;
4332 /* TODO: turn to hard check once we are sure this is 100% correct */
4333 if (!r->in.server_name) {
4334 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
4335 "But received NULL!\n", dnsdomain));
4336 } else {
4337 p = strchr(r->in.server_name, '.');
4338 if (!p) {
4339 DEBUG(3, ("Invalid domain! Expected name in domain "
4340 "[%s]. But received [%s]!\n",
4341 dnsdomain, r->in.server_name));
4342 p = r->in.server_name;
4343 } else {
4344 p++;
4346 if (strcasecmp(p, dnsdomain)) {
4347 DEBUG(3, ("Invalid domain! Expected name in domain "
4348 "[%s]. But received [%s]!\n",
4349 dnsdomain, r->in.server_name));
4353 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
4354 W_ERROR_HAVE_NO_MEMORY(trusts);
4356 trusts->count = 0;
4357 r->out.trusts = trusts;
4359 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4360 if (sam_ctx == NULL) {
4361 return WERR_GEN_FAILURE;
4364 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
4365 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
4367 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
4368 trusts, r->in.trust_flags);
4369 W_ERROR_NOT_OK_RETURN(werr);
4372 /* NOTE: we currently are always the root of the forest */
4373 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
4374 uint32_t n = trusts->count;
4376 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
4377 &dom_res, dom_attrs);
4378 if (ret != 1) {
4379 return WERR_GEN_FAILURE;
4382 trusts->count = n + 1;
4383 trusts->array = talloc_realloc(trusts, trusts->array,
4384 struct netr_DomainTrust,
4385 trusts->count);
4386 W_ERROR_HAVE_NO_MEMORY(trusts->array);
4388 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
4389 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
4390 trusts->array[n].trust_flags =
4391 NETR_TRUST_FLAG_NATIVE |
4392 NETR_TRUST_FLAG_TREEROOT |
4393 NETR_TRUST_FLAG_IN_FOREST |
4394 NETR_TRUST_FLAG_PRIMARY;
4395 /* we are always the root domain for now */
4396 trusts->array[n].parent_index = 0;
4397 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
4398 trusts->array[n].trust_attributes = 0;
4399 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
4400 dom_res[0],
4401 "objectSid");
4402 trusts->array[n].guid = samdb_result_guid(dom_res[0],
4403 "objectGUID");
4404 talloc_free(dom_res);
4407 return WERR_OK;
4412 netr_DsrDeregisterDNSHostRecords
4414 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4415 struct netr_DsrDeregisterDNSHostRecords *r)
4417 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4422 netr_ServerTrustPasswordsGet
4424 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4425 struct netr_ServerTrustPasswordsGet *r)
4427 struct netr_ServerGetTrustInfo r2 = {};
4428 struct netr_TrustInfo *_ti = NULL;
4429 NTSTATUS status;
4431 r2.in.server_name = r->in.server_name;
4432 r2.in.account_name = r->in.account_name;
4433 r2.in.secure_channel_type = r->in.secure_channel_type;
4434 r2.in.computer_name = r->in.computer_name;
4435 r2.in.credential = r->in.credential;
4437 r2.out.return_authenticator = r->out.return_authenticator;
4438 r2.out.new_owf_password = r->out.new_owf_password;
4439 r2.out.old_owf_password = r->out.old_owf_password;
4440 r2.out.trust_info = &_ti;
4442 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
4444 r->out.return_authenticator = r2.out.return_authenticator;
4445 r->out.new_owf_password = r2.out.new_owf_password;
4446 r->out.old_owf_password = r2.out.old_owf_password;
4448 return status;
4452 netr_DsRGetForestTrustInformation
4454 struct dcesrv_netr_DsRGetForestTrustInformation_state {
4455 struct dcesrv_call_state *dce_call;
4456 TALLOC_CTX *mem_ctx;
4457 struct netr_DsRGetForestTrustInformation *r;
4460 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
4462 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
4463 TALLOC_CTX *mem_ctx,
4464 struct netr_DsRGetForestTrustInformation *r)
4466 struct auth_session_info *session_info =
4467 dcesrv_call_session_info(dce_call);
4468 struct imessaging_context *imsg_ctx =
4469 dcesrv_imessaging_context(dce_call->conn);
4470 enum security_user_level security_level;
4471 struct ldb_context *sam_ctx = NULL;
4472 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
4473 struct dcerpc_binding_handle *irpc_handle = NULL;
4474 struct tevent_req *subreq = NULL;
4475 struct ldb_dn *domain_dn = NULL;
4476 struct ldb_dn *forest_dn = NULL;
4477 int cmp;
4478 int forest_level;
4480 security_level = security_session_user_level(session_info, NULL);
4481 if (security_level < SECURITY_USER) {
4482 return WERR_ACCESS_DENIED;
4485 if (r->in.flags & 0xFFFFFFFE) {
4486 return WERR_INVALID_FLAGS;
4489 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4490 if (sam_ctx == NULL) {
4491 return WERR_GEN_FAILURE;
4494 domain_dn = ldb_get_default_basedn(sam_ctx);
4495 if (domain_dn == NULL) {
4496 return WERR_GEN_FAILURE;
4499 forest_dn = ldb_get_root_basedn(sam_ctx);
4500 if (forest_dn == NULL) {
4501 return WERR_GEN_FAILURE;
4504 cmp = ldb_dn_compare(domain_dn, forest_dn);
4505 if (cmp != 0) {
4506 return WERR_NERR_ACFNOTLOADED;
4509 forest_level = dsdb_forest_functional_level(sam_ctx);
4510 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4511 return WERR_INVALID_FUNCTION;
4514 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
4515 if (!samdb_is_pdc(sam_ctx)) {
4516 return WERR_NERR_NOTPRIMARY;
4519 if (r->in.trusted_domain_name == NULL) {
4520 return WERR_INVALID_FLAGS;
4524 if (r->in.trusted_domain_name == NULL) {
4525 NTSTATUS status;
4528 * information about our own domain
4530 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4531 r->out.forest_trust_info);
4532 if (!NT_STATUS_IS_OK(status)) {
4533 return ntstatus_to_werror(status);
4536 return WERR_OK;
4540 * Forward the request to winbindd
4543 state = talloc_zero(mem_ctx,
4544 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4545 if (state == NULL) {
4546 return WERR_NOT_ENOUGH_MEMORY;
4548 state->dce_call = dce_call;
4549 state->mem_ctx = mem_ctx;
4550 state->r = r;
4552 irpc_handle = irpc_binding_handle_by_name(state,
4553 imsg_ctx,
4554 "winbind_server",
4555 &ndr_table_winbind);
4556 if (irpc_handle == NULL) {
4557 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
4558 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4559 return WERR_SERVICE_NOT_FOUND;
4563 * 60 seconds timeout should be enough
4565 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
4567 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
4568 state->dce_call->event_ctx,
4569 irpc_handle,
4570 r->in.trusted_domain_name,
4571 r->in.flags,
4572 r->out.forest_trust_info);
4573 if (subreq == NULL) {
4574 return WERR_NOT_ENOUGH_MEMORY;
4576 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4577 tevent_req_set_callback(subreq,
4578 dcesrv_netr_DsRGetForestTrustInformation_done,
4579 state);
4581 return WERR_OK;
4584 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
4586 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
4587 tevent_req_callback_data(subreq,
4588 struct dcesrv_netr_DsRGetForestTrustInformation_state);
4589 NTSTATUS status;
4591 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
4592 state->mem_ctx,
4593 &state->r->out.result);
4594 TALLOC_FREE(subreq);
4595 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
4596 state->r->out.result = WERR_TIMEOUT;
4597 } else if (!NT_STATUS_IS_OK(status)) {
4598 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4599 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
4600 nt_errstr(status)));
4603 dcesrv_async_reply(state->dce_call);
4607 netr_GetForestTrustInformation
4609 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
4610 TALLOC_CTX *mem_ctx,
4611 struct netr_GetForestTrustInformation *r)
4613 struct netlogon_creds_CredentialState *creds = NULL;
4614 struct ldb_context *sam_ctx = NULL;
4615 struct ldb_dn *domain_dn = NULL;
4616 struct ldb_dn *forest_dn = NULL;
4617 int cmp;
4618 int forest_level;
4619 NTSTATUS status;
4621 status = dcesrv_netr_creds_server_step_check(dce_call,
4622 mem_ctx,
4623 r->in.computer_name,
4624 r->in.credential,
4625 r->out.return_authenticator,
4626 &creds);
4627 if (!NT_STATUS_IS_OK(status)) {
4628 return status;
4631 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
4632 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
4633 return NT_STATUS_NOT_IMPLEMENTED;
4636 sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
4637 if (sam_ctx == NULL) {
4638 return NT_STATUS_INTERNAL_ERROR;
4641 /* TODO: check r->in.server_name is our name */
4643 domain_dn = ldb_get_default_basedn(sam_ctx);
4644 if (domain_dn == NULL) {
4645 return NT_STATUS_INTERNAL_ERROR;
4648 forest_dn = ldb_get_root_basedn(sam_ctx);
4649 if (forest_dn == NULL) {
4650 return NT_STATUS_INTERNAL_ERROR;
4653 cmp = ldb_dn_compare(domain_dn, forest_dn);
4654 if (cmp != 0) {
4655 return NT_STATUS_INVALID_DOMAIN_STATE;
4658 forest_level = dsdb_forest_functional_level(sam_ctx);
4659 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4660 return NT_STATUS_INVALID_DOMAIN_STATE;
4663 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4664 r->out.forest_trust_info);
4665 if (!NT_STATUS_IS_OK(status)) {
4666 return status;
4669 return NT_STATUS_OK;
4674 netr_ServerGetTrustInfo
4676 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4677 struct netr_ServerGetTrustInfo *r)
4679 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4680 struct netlogon_creds_CredentialState *creds = NULL;
4681 const struct dom_sid *client_sid = NULL;
4682 struct ldb_context *sam_ctx = NULL;
4683 static const char * const attrs[] = {
4684 "unicodePwd",
4685 "sAMAccountName",
4686 "userAccountControl",
4687 /* Required for Group Managed Service Accounts. */
4688 "msDS-ManagedPasswordId",
4689 "msDS-ManagedPasswordInterval",
4690 "objectClass",
4691 "objectSid",
4692 "whenCreated",
4693 NULL
4695 struct ldb_message **res = NULL;
4696 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4697 NTSTATUS nt_status;
4698 int ret;
4699 const char *asid = NULL;
4700 uint32_t uac = 0;
4701 const char *aname = NULL;
4702 struct ldb_message *tdo_msg = NULL;
4703 const char * const tdo_attrs[] = {
4704 "trustAuthIncoming",
4705 "trustAttributes",
4706 NULL
4708 struct netr_TrustInfo *trust_info = NULL;
4709 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
4710 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
4712 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
4714 ZERO_STRUCTP(r->out.new_owf_password);
4715 ZERO_STRUCTP(r->out.old_owf_password);
4717 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4718 mem_ctx,
4719 r->in.computer_name,
4720 r->in.credential,
4721 r->out.return_authenticator,
4722 &creds);
4723 if (!NT_STATUS_IS_OK(nt_status)) {
4724 return nt_status;
4726 client_sid = &creds->client_sid;
4728 /* TODO: check r->in.server_name is our name */
4730 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4731 return NT_STATUS_INVALID_PARAMETER;
4734 if (r->in.secure_channel_type != creds->secure_channel_type) {
4735 return NT_STATUS_INVALID_PARAMETER;
4738 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4739 return NT_STATUS_INVALID_PARAMETER;
4742 sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
4743 if (sam_ctx == NULL) {
4744 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4747 asid = ldap_encode_ndr_dom_sid(mem_ctx, client_sid);
4748 if (asid == NULL) {
4749 return NT_STATUS_NO_MEMORY;
4753 struct ldb_result *result = NULL;
4755 ret = dsdb_search(sam_ctx,
4756 mem_ctx,
4757 &result,
4758 ldb_get_default_basedn(sam_ctx),
4759 LDB_SCOPE_SUBTREE,
4760 attrs,
4761 DSDB_SEARCH_ONE_ONLY |
4762 DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
4763 "(&(objectClass=user)(objectSid=%s))",
4764 asid);
4765 if (ret) {
4766 return NT_STATUS_ACCOUNT_DISABLED;
4769 res = talloc_steal(mem_ctx, result->msgs);
4770 talloc_free(result);
4773 switch (creds->secure_channel_type) {
4774 case SEC_CHAN_DNS_DOMAIN:
4775 case SEC_CHAN_DOMAIN:
4776 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4778 if (uac & UF_ACCOUNTDISABLE) {
4779 return NT_STATUS_ACCOUNT_DISABLED;
4782 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4783 return NT_STATUS_ACCOUNT_DISABLED;
4786 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4787 if (aname == NULL) {
4788 return NT_STATUS_ACCOUNT_DISABLED;
4791 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4792 SEC_CHAN_DOMAIN, aname,
4793 tdo_attrs, mem_ctx, &tdo_msg);
4794 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4795 return NT_STATUS_ACCOUNT_DISABLED;
4797 if (!NT_STATUS_IS_OK(nt_status)) {
4798 return nt_status;
4801 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4802 &curNtHash,
4803 &prevNtHash);
4804 if (!NT_STATUS_IS_OK(nt_status)) {
4805 return nt_status;
4808 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4809 if (trust_info == NULL) {
4810 return NT_STATUS_NO_MEMORY;
4813 trust_info->count = 1;
4814 trust_info->data = talloc_array(trust_info, uint32_t,
4815 trust_info->count);
4816 if (trust_info->data == NULL) {
4817 return NT_STATUS_NO_MEMORY;
4820 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4821 "trustAttributes",
4823 break;
4825 default:
4826 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4827 res[0],
4828 &curNtHash);
4829 if (!NT_STATUS_IS_OK(nt_status)) {
4830 return nt_status;
4833 prevNtHash = talloc(mem_ctx, struct samr_Password);
4834 if (prevNtHash == NULL) {
4835 return NT_STATUS_NO_MEMORY;
4838 E_md4hash("", prevNtHash->hash);
4839 break;
4842 if (curNtHash != NULL) {
4843 *r->out.new_owf_password = *curNtHash;
4844 nt_status = netlogon_creds_encrypt_samr_Password(creds,
4845 r->out.new_owf_password,
4846 auth_type,
4847 auth_level);
4848 if (!NT_STATUS_IS_OK(nt_status)) {
4849 return nt_status;
4852 if (prevNtHash != NULL) {
4853 *r->out.old_owf_password = *prevNtHash;
4854 nt_status = netlogon_creds_encrypt_samr_Password(creds,
4855 r->out.old_owf_password,
4856 auth_type,
4857 auth_level);
4858 if (!NT_STATUS_IS_OK(nt_status)) {
4859 return nt_status;
4863 if (trust_info != NULL) {
4864 *r->out.trust_info = trust_info;
4867 return NT_STATUS_OK;
4871 netr_Unused47
4873 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4874 struct netr_Unused47 *r)
4876 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4880 struct netr_dnsupdate_RODC_state {
4881 struct dcesrv_call_state *dce_call;
4882 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4883 struct dnsupdate_RODC *r2;
4887 called when the forwarded RODC dns update request is finished
4889 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4891 struct netr_dnsupdate_RODC_state *st =
4892 tevent_req_callback_data(subreq,
4893 struct netr_dnsupdate_RODC_state);
4894 NTSTATUS status;
4896 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4897 TALLOC_FREE(subreq);
4898 if (!NT_STATUS_IS_OK(status)) {
4899 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4900 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4903 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4905 dcesrv_async_reply(st->dce_call);
4909 netr_DsrUpdateReadOnlyServerDnsRecords
4911 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4912 TALLOC_CTX *mem_ctx,
4913 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4915 struct netlogon_creds_CredentialState *creds;
4916 NTSTATUS nt_status;
4917 struct dcerpc_binding_handle *binding_handle;
4918 struct netr_dnsupdate_RODC_state *st;
4919 struct tevent_req *subreq;
4920 struct imessaging_context *imsg_ctx =
4921 dcesrv_imessaging_context(dce_call->conn);
4922 struct dom_sid *client_sid = NULL;
4924 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4925 mem_ctx,
4926 r->in.computer_name,
4927 r->in.credential,
4928 r->out.return_authenticator,
4929 &creds);
4930 NT_STATUS_NOT_OK_RETURN(nt_status);
4931 client_sid = &creds->client_sid;
4933 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4934 return NT_STATUS_ACCESS_DENIED;
4937 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4938 NT_STATUS_HAVE_NO_MEMORY(st);
4940 st->dce_call = dce_call;
4941 st->r = r;
4942 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4943 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4945 st->r2->in.dom_sid = client_sid;
4946 st->r2->in.site_name = r->in.site_name;
4947 st->r2->in.dns_ttl = r->in.dns_ttl;
4948 st->r2->in.dns_names = r->in.dns_names;
4949 st->r2->out.dns_names = r->out.dns_names;
4951 binding_handle = irpc_binding_handle_by_name(st,
4952 imsg_ctx,
4953 "dnsupdate",
4954 &ndr_table_irpc);
4955 if (binding_handle == NULL) {
4956 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4957 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4958 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4961 /* forward the call */
4962 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4963 binding_handle, st->r2);
4964 NT_STATUS_HAVE_NO_MEMORY(subreq);
4966 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4968 /* setup the callback */
4969 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4971 return NT_STATUS_OK;
4974 DCESRV_NOT_USED_ON_WIRE(netr_Opnum49NotUsedOnWire)
4975 DCESRV_NOT_USED_ON_WIRE(netr_Opnum50NotUsedOnWire)
4976 DCESRV_NOT_USED_ON_WIRE(netr_Opnum51NotUsedOnWire)
4977 DCESRV_NOT_USED_ON_WIRE(netr_Opnum52NotUsedOnWire)
4978 DCESRV_NOT_USED_ON_WIRE(netr_Opnum53NotUsedOnWire)
4981 netr_ChainSetClientAttributes
4983 static NTSTATUS dcesrv_netr_ChainSetClientAttributes(struct dcesrv_call_state *dce_call,
4984 TALLOC_CTX *mem_ctx,
4985 struct netr_ChainSetClientAttributes *r)
4987 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4990 DCESRV_NOT_USED_ON_WIRE(netr_Opnum55NotUsedOnWire)
4991 DCESRV_NOT_USED_ON_WIRE(netr_Opnum56NotUsedOnWire)
4992 DCESRV_NOT_USED_ON_WIRE(netr_Opnum57NotUsedOnWire)
4993 DCESRV_NOT_USED_ON_WIRE(netr_Opnum58NotUsedOnWire)
4995 static NTSTATUS dcesrv_netr_ServerAuthenticateKerberos_cb(
4996 struct dcesrv_call_state *dce_call,
4997 const struct netlogon_server_pipe_state *challenge,
4998 const struct netr_ServerAuthenticate3 *r,
4999 uint32_t client_flags,
5000 const struct dom_sid *client_sid,
5001 uint32_t negotiate_flags,
5002 const struct ldb_message *sam_msg,
5003 const struct ldb_message *tdo_msg,
5004 TALLOC_CTX *mem_ctx,
5005 struct netlogon_creds_CredentialState **_creds)
5007 TALLOC_CTX *frame = talloc_stackframe();
5008 struct netlogon_creds_CredentialState *creds = NULL;
5009 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
5010 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
5011 struct auth_session_info *session_info =
5012 dcesrv_call_session_info(dce_call);
5013 const struct dom_sid *auth_sid =
5014 &session_info->security_token->sids[0];
5015 struct GUID tdo_guid = { 0, };
5017 dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
5020 * The client needs to come via a
5021 * connection encrypted with kerberos.
5023 * And the SID from the PAC needs to
5024 * match the sid for the requested
5025 * account name
5028 if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
5029 TALLOC_FREE(frame);
5030 return NT_STATUS_ACCESS_DENIED;
5032 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
5033 TALLOC_FREE(frame);
5034 return NT_STATUS_ACCESS_DENIED;
5037 if (!dom_sid_equal(client_sid, auth_sid)) {
5038 TALLOC_FREE(frame);
5039 return NT_STATUS_ACCESS_DENIED;
5042 SMB_ASSERT(r->in.credentials == NULL);
5043 SMB_ASSERT(r->out.return_credentials == NULL);
5045 if (tdo_msg != NULL) {
5046 tdo_guid = samdb_result_guid(tdo_msg, "objectGUID");
5049 creds = netlogon_creds_kerberos_init(mem_ctx,
5050 r->in.account_name,
5051 r->in.computer_name,
5052 r->in.secure_channel_type,
5053 client_flags,
5054 client_sid,
5055 negotiate_flags);
5056 if (creds == NULL) {
5057 TALLOC_FREE(frame);
5058 return NT_STATUS_ACCESS_DENIED;
5061 creds->tdo_guid = tdo_guid;
5063 *_creds = creds;
5064 TALLOC_FREE(frame);
5065 return NT_STATUS_OK;
5069 netr_ServerAuthenticateKerberos
5071 static NTSTATUS dcesrv_netr_ServerAuthenticateKerberos(struct dcesrv_call_state *dce_call,
5072 TALLOC_CTX *mem_ctx,
5073 struct netr_ServerAuthenticateKerberos *r)
5075 NTSTATUS status;
5076 struct dom_sid *sid = NULL;
5077 const char *trust_account_for_search = NULL;
5078 const char *trust_account_in_db = NULL;
5079 struct imessaging_context *imsg_ctx =
5080 dcesrv_imessaging_context(dce_call->conn);
5081 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
5082 bool server_support_krb5_netlogon = lpcfg_server_support_krb5_netlogon(lp_ctx);
5083 struct auth_usersupplied_info ui = {
5084 .local_host = dce_call->conn->local_address,
5085 .remote_host = dce_call->conn->remote_address,
5086 .client = {
5087 .account_name = r->in.account_name,
5088 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
5090 .service_description = "NETLOGON",
5091 .auth_description = "ServerAuthenticate",
5092 .netlogon_trust_account = {
5093 .computer_name = r->in.computer_name,
5094 .negotiate_flags = *r->in.negotiate_flags,
5095 .authenticate_kerberos = true,
5096 .secure_channel_type = r->in.account_type,
5099 struct netr_ServerAuthenticate3 r3 = {
5100 .in = {
5101 .server_name = r->in.server_name,
5102 .account_name = r->in.account_name,
5103 .secure_channel_type = r->in.account_type,
5104 .computer_name = r->in.computer_name,
5105 .credentials = NULL,
5106 .negotiate_flags = r->in.negotiate_flags,
5108 .out = {
5109 .return_credentials = NULL,
5110 .rid = r->out.rid,
5111 .negotiate_flags = r->out.negotiate_flags,
5112 .result = NT_STATUS_INTERNAL_ERROR,
5115 dcesrv_netr_ServerAuthenticateGenericCallback_fn auth_fn =
5116 dcesrv_netr_ServerAuthenticateKerberos_cb;
5118 if (!server_support_krb5_netlogon) {
5119 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
5122 status = dcesrv_netr_ServerAuthenticateGeneric(dce_call,
5123 mem_ctx,
5124 &r3,
5125 auth_fn,
5126 &trust_account_for_search,
5127 &trust_account_in_db,
5128 &sid);
5129 ui.netlogon_trust_account.sid = sid;
5130 ui.netlogon_trust_account.account_name = trust_account_in_db;
5131 ui.mapped.account_name = trust_account_for_search;
5132 log_authentication_event(
5133 imsg_ctx,
5134 dce_call->conn->dce_ctx->lp_ctx,
5135 NULL,
5136 &ui,
5137 status,
5138 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
5139 trust_account_in_db,
5140 sid,
5141 NULL /* client_audit_info */,
5142 NULL /* server_audit_info */);
5144 return status;
5147 /* include the generated boilerplate */
5148 #include "librpc/gen_ndr/ndr_netlogon_s.c"