2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "dsdb/samdb/ldb_modules/util.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_lsa.h"
40 #include "librpc/gen_ndr/ndr_samr.h"
41 #include "librpc/gen_ndr/ndr_irpc.h"
42 #include "librpc/gen_ndr/ndr_winbind.h"
43 #include "librpc/gen_ndr/ndr_winbind_c.h"
44 #include "lib/socket/netif.h"
45 #include "rpc_server/common/sid_helper.h"
46 #include "lib/util/util_str_escape.h"
48 #define DCESRV_INTERFACE_NETLOGON_BIND(call, iface) \
49 dcesrv_interface_netlogon_bind(call, iface)
52 * This #define allows the netlogon interface to accept invalid
53 * association groups, because association groups are to coordinate
54 * handles, and handles are not used in NETLOGON. This in turn avoids
55 * the need to coordinate these across multiple possible NETLOGON
58 #define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
60 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_call_state *dce_call,
61 const struct dcesrv_interface *iface)
63 return dcesrv_interface_bind_reject_connect(dce_call, iface);
66 struct netlogon_server_pipe_state {
67 struct netr_Credential client_challenge;
68 struct netr_Credential server_challenge;
71 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
72 struct netr_ServerReqChallenge *r)
74 struct netlogon_server_pipe_state *pipe_state =
75 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
78 ZERO_STRUCTP(r->out.return_credentials);
81 talloc_free(pipe_state);
82 dce_call->context->private_data = NULL;
85 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
86 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
88 pipe_state->client_challenge = *r->in.credentials;
90 generate_random_buffer(pipe_state->server_challenge.data,
91 sizeof(pipe_state->server_challenge.data));
93 *r->out.return_credentials = pipe_state->server_challenge;
95 dce_call->context->private_data = pipe_state;
97 ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
98 &pipe_state->client_challenge,
99 &pipe_state->server_challenge,
100 r->in.computer_name);
101 if (!NT_STATUS_IS_OK(ntstatus)) {
109 * Do the actual processing of a netr_ServerAuthenticate3 message.
110 * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
112 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
113 struct dcesrv_call_state *dce_call,
115 struct netr_ServerAuthenticate3 *r,
116 const char **trust_account_for_search,
117 const char **trust_account_in_db,
118 struct dom_sid **sid)
120 struct netlogon_server_pipe_state *pipe_state =
121 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
122 bool challenge_valid = false;
123 struct netlogon_server_pipe_state challenge;
124 struct netlogon_creds_CredentialState *creds;
125 struct ldb_context *sam_ctx;
126 struct samr_Password *curNtHash = NULL;
127 struct samr_Password *prevNtHash = NULL;
128 uint32_t user_account_control;
130 struct ldb_message **msgs;
132 const char *attrs[] = {"unicodePwd", "userAccountControl",
133 "objectSid", "samAccountName", NULL};
134 uint32_t server_flags = 0;
135 uint32_t negotiate_flags = 0;
136 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
137 bool reject_des_client = !allow_nt4_crypto;
138 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
139 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
140 bool reject_none_rpc = (schannel == true);
142 ZERO_STRUCTP(r->out.return_credentials);
145 if (pipe_state != NULL) {
146 dce_call->context->private_data = NULL;
149 * If we had a challenge remembered on the connection
150 * consider this for usage. This can't be cleanup
153 * This is the default code path for typical clients
154 * which call netr_ServerReqChallenge() and
155 * netr_ServerAuthenticate3() on the same dcerpc connection.
157 challenge = *pipe_state;
159 challenge_valid = true;
165 * Fallback and try to get the challenge from
168 * If too many clients are using this code path,
169 * they may destroy their cache entries as the
170 * TDB has a fixed size limited via a lossy hash
172 * The TDB used is the schannel store, which is
173 * initialised at startup.
175 * NOTE: The challenge is deleted from the DB as soon as it is
176 * fetched, to prevent reuse.
180 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
181 &challenge.client_challenge,
182 &challenge.server_challenge,
183 r->in.computer_name);
185 if (!NT_STATUS_IS_OK(ntstatus)) {
186 ZERO_STRUCT(challenge);
188 challenge_valid = true;
192 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
193 NETLOGON_NEG_PERSISTENT_SAMREPL |
194 NETLOGON_NEG_ARCFOUR |
195 NETLOGON_NEG_PROMOTION_COUNT |
196 NETLOGON_NEG_CHANGELOG_BDC |
197 NETLOGON_NEG_FULL_SYNC_REPL |
198 NETLOGON_NEG_MULTIPLE_SIDS |
200 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
201 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
202 NETLOGON_NEG_GENERIC_PASSTHROUGH |
203 NETLOGON_NEG_CONCURRENT_RPC |
204 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
205 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
206 NETLOGON_NEG_STRONG_KEYS |
207 NETLOGON_NEG_TRANSITIVE_TRUSTS |
208 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
209 NETLOGON_NEG_PASSWORD_SET2 |
210 NETLOGON_NEG_GETDOMAININFO |
211 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
212 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
213 NETLOGON_NEG_RODC_PASSTHROUGH |
214 NETLOGON_NEG_SUPPORTS_AES |
215 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
216 NETLOGON_NEG_AUTHENTICATED_RPC;
218 negotiate_flags = *r->in.negotiate_flags & server_flags;
220 if (negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
221 reject_none_rpc = false;
224 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
225 reject_des_client = false;
228 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
229 reject_des_client = false;
230 reject_md5_client = false;
233 if (reject_des_client || reject_md5_client) {
235 * Here we match Windows 2012 and return no flags.
237 *r->out.negotiate_flags = 0;
238 return NT_STATUS_DOWNGRADE_DETECTED;
242 * This talloc_free is important to prevent re-use of the
243 * challenge. We have to delay it this far due to NETApp
245 * https://bugzilla.samba.org/show_bug.cgi?id=11291
247 TALLOC_FREE(pipe_state);
250 * At this point we must also cleanup the TDB cache
251 * entry, if we fail the client needs to call
252 * netr_ServerReqChallenge again.
254 * Note: this handles a non existing record just fine,
255 * the r->in.computer_name might not be the one used
256 * in netr_ServerReqChallenge(), but we are trying to
257 * just tidy up the normal case to prevent re-use.
259 schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
260 r->in.computer_name);
263 * According to Microsoft (see bugid #6099)
264 * Windows 7 looks at the negotiate_flags
265 * returned in this structure *even if the
266 * call fails with access denied!
268 *r->out.negotiate_flags = negotiate_flags;
270 if (reject_none_rpc) {
271 /* schannel must be used, but client did not offer it. */
272 DEBUG(0,("%s: schannel required but client failed "
273 "to offer it. Client was %s\n",
275 log_escape(mem_ctx, r->in.account_name)));
276 return NT_STATUS_ACCESS_DENIED;
279 switch (r->in.secure_channel_type) {
281 case SEC_CHAN_DNS_DOMAIN:
282 case SEC_CHAN_DOMAIN:
287 return NT_STATUS_INVALID_PARAMETER;
289 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
290 r->in.secure_channel_type));
291 return NT_STATUS_INVALID_PARAMETER;
294 sam_ctx = samdb_connect(mem_ctx,
296 dce_call->conn->dce_ctx->lp_ctx,
297 system_session(dce_call->conn->dce_ctx->lp_ctx),
298 dce_call->conn->remote_address,
300 if (sam_ctx == NULL) {
301 return NT_STATUS_INVALID_SYSTEM_SERVICE;
304 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
305 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
307 struct ldb_message *tdo_msg = NULL;
308 const char * const tdo_attrs[] = {
314 char *encoded_name = NULL;
316 const char *flatname = NULL;
318 bool require_trailer = true;
319 const char *netbios = NULL;
320 const char *dns = NULL;
322 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
324 require_trailer = false;
327 encoded_name = ldb_binary_encode_string(mem_ctx,
329 if (encoded_name == NULL) {
330 return NT_STATUS_NO_MEMORY;
333 len = strlen(encoded_name);
335 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
338 if (require_trailer && encoded_name[len - 1] != trailer) {
339 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
341 encoded_name[len - 1] = '\0';
343 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
346 netbios = encoded_name;
349 nt_status = dsdb_trust_search_tdo(sam_ctx,
351 tdo_attrs, mem_ctx, &tdo_msg);
352 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
353 DEBUG(2, ("Client asked for a trusted domain secure channel, "
354 "but there's no tdo for [%s] => [%s] \n",
355 log_escape(mem_ctx, r->in.account_name),
357 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
359 if (!NT_STATUS_IS_OK(nt_status)) {
363 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
366 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
367 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
369 if (!NT_STATUS_IS_OK(nt_status)) {
373 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
374 if (flatname == NULL) {
375 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
378 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
379 if (*trust_account_for_search == NULL) {
380 return NT_STATUS_NO_MEMORY;
383 *trust_account_for_search = r->in.account_name;
386 /* pull the user attributes */
387 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
388 "(&(sAMAccountName=%s)(objectclass=user))",
389 ldb_binary_encode_string(mem_ctx,
390 *trust_account_for_search));
392 if (num_records == 0) {
393 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
394 log_escape(mem_ctx, r->in.account_name)));
395 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
398 if (num_records > 1) {
399 DEBUG(0,("Found %d records matching user [%s]\n",
401 log_escape(mem_ctx, r->in.account_name)));
402 return NT_STATUS_INTERNAL_DB_CORRUPTION;
405 *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
408 if (*trust_account_in_db == NULL) {
409 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
410 r->in.account_name));
411 return NT_STATUS_INTERNAL_DB_CORRUPTION;
414 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
416 if (user_account_control & UF_ACCOUNTDISABLE) {
417 DEBUG(1, ("Account [%s] is disabled\n",
418 log_escape(mem_ctx, r->in.account_name)));
419 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
422 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
423 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
424 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
425 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
427 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
428 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
429 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
430 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
432 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
434 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
435 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
436 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
437 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
439 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
440 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
441 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
442 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
445 /* we should never reach this */
446 return NT_STATUS_INTERNAL_ERROR;
449 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
450 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
451 dce_call->conn->dce_ctx->lp_ctx,
452 msgs[0], NULL, &curNtHash);
453 if (!NT_STATUS_IS_OK(nt_status)) {
454 return NT_STATUS_ACCESS_DENIED;
458 if (curNtHash == NULL) {
459 return NT_STATUS_ACCESS_DENIED;
462 if (!challenge_valid) {
463 DEBUG(1, ("No challenge requested by client [%s/%s], "
464 "cannot authenticate\n",
465 log_escape(mem_ctx, r->in.computer_name),
466 log_escape(mem_ctx, r->in.account_name)));
467 return NT_STATUS_ACCESS_DENIED;
470 creds = netlogon_creds_server_init(mem_ctx,
473 r->in.secure_channel_type,
474 &challenge.client_challenge,
475 &challenge.server_challenge,
478 r->out.return_credentials,
480 if (creds == NULL && prevNtHash != NULL) {
482 * We fallback to the previous password for domain trusts.
484 * Note that lpcfg_old_password_allowed_period() doesn't
487 creds = netlogon_creds_server_init(mem_ctx,
490 r->in.secure_channel_type,
491 &challenge.client_challenge,
492 &challenge.server_challenge,
495 r->out.return_credentials,
500 return NT_STATUS_ACCESS_DENIED;
502 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
503 *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
505 nt_status = schannel_save_creds_state(mem_ctx,
506 dce_call->conn->dce_ctx->lp_ctx,
508 if (!NT_STATUS_IS_OK(nt_status)) {
509 ZERO_STRUCTP(r->out.return_credentials);
513 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
520 * Log a netr_ServerAuthenticate3 request, and then invoke
521 * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
523 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
524 struct dcesrv_call_state *dce_call,
526 struct netr_ServerAuthenticate3 *r)
529 struct dom_sid *sid = NULL;
530 const char *trust_account_for_search = NULL;
531 const char *trust_account_in_db = NULL;
532 struct auth_usersupplied_info ui = {
533 .local_host = dce_call->conn->local_address,
534 .remote_host = dce_call->conn->remote_address,
536 .account_name = r->in.account_name,
537 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
539 .service_description = "NETLOGON",
540 .auth_description = "ServerAuthenticate",
541 .netlogon_trust_account = {
542 .computer_name = r->in.computer_name,
543 .negotiate_flags = *r->in.negotiate_flags,
544 .secure_channel_type = r->in.secure_channel_type,
548 status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
551 &trust_account_for_search,
552 &trust_account_in_db,
554 ui.netlogon_trust_account.sid = sid;
555 ui.netlogon_trust_account.account_name = trust_account_in_db;
556 ui.mapped.account_name = trust_account_for_search;
557 log_authentication_event(
558 dce_call->conn->msg_ctx,
559 dce_call->conn->dce_ctx->lp_ctx,
563 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
570 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
571 struct netr_ServerAuthenticate *r)
573 struct netr_ServerAuthenticate3 a;
576 * negotiate_flags is used as an [in] parameter
577 * so it need to be initialised.
579 * (I think ... = 0; seems wrong here --metze)
581 uint32_t negotiate_flags_in = 0;
582 uint32_t negotiate_flags_out = 0;
584 a.in.server_name = r->in.server_name;
585 a.in.account_name = r->in.account_name;
586 a.in.secure_channel_type = r->in.secure_channel_type;
587 a.in.computer_name = r->in.computer_name;
588 a.in.credentials = r->in.credentials;
589 a.in.negotiate_flags = &negotiate_flags_in;
591 a.out.return_credentials = r->out.return_credentials;
593 a.out.negotiate_flags = &negotiate_flags_out;
595 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
598 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
599 struct netr_ServerAuthenticate2 *r)
601 struct netr_ServerAuthenticate3 r3;
604 r3.in.server_name = r->in.server_name;
605 r3.in.account_name = r->in.account_name;
606 r3.in.secure_channel_type = r->in.secure_channel_type;
607 r3.in.computer_name = r->in.computer_name;
608 r3.in.credentials = r->in.credentials;
609 r3.out.return_credentials = r->out.return_credentials;
610 r3.in.negotiate_flags = r->in.negotiate_flags;
611 r3.out.negotiate_flags = r->out.negotiate_flags;
614 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
618 * NOTE: The following functions are nearly identical to the ones available in
619 * source3/rpc_server/srv_nelog_nt.c
620 * The reason we keep 2 copies is that they use different structures to
621 * represent the auth_info and the decrpc pipes.
625 * If schannel is required for this call test that it actually is available.
627 static NTSTATUS schannel_check_required(const struct dcesrv_auth *auth_info,
628 const char *computer_name,
629 bool integrity, bool privacy)
632 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
633 if (!privacy && !integrity) {
637 if ((!privacy && integrity) &&
638 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
642 if ((privacy || integrity) &&
643 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
648 /* test didn't pass */
649 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
652 return NT_STATUS_ACCESS_DENIED;
655 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
657 const char *computer_name,
658 struct netr_Authenticator *received_authenticator,
659 struct netr_Authenticator *return_authenticator,
660 struct netlogon_creds_CredentialState **creds_out)
663 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
664 bool schannel_global_required = (schannel == true);
666 if (schannel_global_required) {
667 nt_status = schannel_check_required(&dce_call->conn->auth_state,
670 if (!NT_STATUS_IS_OK(nt_status)) {
675 nt_status = schannel_check_creds_state(mem_ctx,
676 dce_call->conn->dce_ctx->lp_ctx,
678 received_authenticator,
679 return_authenticator,
685 Change the machine account password for the currently connected
686 client. Supplies only the NT#.
689 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
690 struct netr_ServerPasswordSet *r)
692 struct netlogon_creds_CredentialState *creds;
693 struct ldb_context *sam_ctx;
694 const char * const attrs[] = { "unicodePwd", NULL };
695 struct ldb_message **res;
696 struct samr_Password *oldNtHash;
700 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
703 r->in.credential, r->out.return_authenticator,
705 NT_STATUS_NOT_OK_RETURN(nt_status);
707 sam_ctx = samdb_connect(mem_ctx,
709 dce_call->conn->dce_ctx->lp_ctx,
710 system_session(dce_call->conn->dce_ctx->lp_ctx),
711 dce_call->conn->remote_address,
713 if (sam_ctx == NULL) {
714 return NT_STATUS_INVALID_SYSTEM_SERVICE;
717 netlogon_creds_des_decrypt(creds, r->in.new_password);
719 /* fetch the old password hashes (the NT hash has to exist) */
721 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
722 "(&(objectClass=user)(objectSid=%s))",
723 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
725 return NT_STATUS_WRONG_PASSWORD;
728 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
729 dce_call->conn->dce_ctx->lp_ctx,
730 res[0], NULL, &oldNtHash);
731 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
732 return NT_STATUS_WRONG_PASSWORD;
735 /* Using the sid for the account as the key, set the password */
736 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
738 NULL, /* Don't have version */
739 NULL, /* Don't have plaintext */
740 NULL, r->in.new_password,
741 NULL, oldNtHash, /* Password change */
747 Change the machine account password for the currently connected
748 client. Supplies new plaintext.
750 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
751 struct netr_ServerPasswordSet2 *r)
753 struct netlogon_creds_CredentialState *creds;
754 struct ldb_context *sam_ctx;
755 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
756 struct ldb_message **res;
757 struct samr_Password *oldLmHash, *oldNtHash;
758 struct NL_PASSWORD_VERSION version = {};
759 const uint32_t *new_version = NULL;
761 DATA_BLOB new_password;
763 struct samr_CryptPassword password_buf;
765 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
768 r->in.credential, r->out.return_authenticator,
770 NT_STATUS_NOT_OK_RETURN(nt_status);
772 sam_ctx = samdb_connect(mem_ctx,
774 dce_call->conn->dce_ctx->lp_ctx,
775 system_session(dce_call->conn->dce_ctx->lp_ctx),
776 dce_call->conn->remote_address,
778 if (sam_ctx == NULL) {
779 return NT_STATUS_INVALID_SYSTEM_SERVICE;
782 memcpy(password_buf.data, r->in.new_password->data, 512);
783 SIVAL(password_buf.data, 512, r->in.new_password->length);
785 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
786 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
788 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
791 switch (creds->secure_channel_type) {
792 case SEC_CHAN_DOMAIN:
793 case SEC_CHAN_DNS_DOMAIN: {
794 uint32_t len = IVAL(password_buf.data, 512);
796 uint32_t ofs = 500 - len;
799 p = password_buf.data + ofs;
801 version.ReservedField = IVAL(p, 0);
802 version.PasswordVersionNumber = IVAL(p, 4);
803 version.PasswordVersionPresent = IVAL(p, 8);
805 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
806 new_version = &version.PasswordVersionNumber;
814 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
815 DEBUG(3,("samr: failed to decode password buffer\n"));
816 return NT_STATUS_WRONG_PASSWORD;
819 /* fetch the old password hashes (at least one of both has to exist) */
821 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
822 "(&(objectClass=user)(objectSid=%s))",
823 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
825 return NT_STATUS_WRONG_PASSWORD;
828 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
829 dce_call->conn->dce_ctx->lp_ctx,
830 res[0], &oldLmHash, &oldNtHash);
831 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
832 return NT_STATUS_WRONG_PASSWORD;
835 /* Using the sid for the account as the key, set the password */
836 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
839 &new_password, /* we have plaintext */
841 oldLmHash, oldNtHash, /* Password change */
850 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
851 struct netr_LogonUasLogon *r)
853 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
860 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
861 struct netr_LogonUasLogoff *r)
863 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
867 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
868 const struct netr_LogonSamLogonEx *r)
870 switch (r->in.logon_level) {
871 case NetlogonInteractiveInformation:
872 case NetlogonServiceInformation:
873 case NetlogonInteractiveTransitiveInformation:
874 case NetlogonServiceTransitiveInformation:
875 if (r->in.logon->password == NULL) {
876 return NT_STATUS_INVALID_PARAMETER;
879 switch (r->in.validation_level) {
880 case NetlogonValidationSamInfo: /* 2 */
881 case NetlogonValidationSamInfo2: /* 3 */
882 case NetlogonValidationSamInfo4: /* 6 */
885 return NT_STATUS_INVALID_INFO_CLASS;
889 case NetlogonNetworkInformation:
890 case NetlogonNetworkTransitiveInformation:
891 if (r->in.logon->network == NULL) {
892 return NT_STATUS_INVALID_PARAMETER;
895 switch (r->in.validation_level) {
896 case NetlogonValidationSamInfo: /* 2 */
897 case NetlogonValidationSamInfo2: /* 3 */
898 case NetlogonValidationSamInfo4: /* 6 */
901 return NT_STATUS_INVALID_INFO_CLASS;
906 case NetlogonGenericInformation:
907 if (r->in.logon->generic == NULL) {
908 return NT_STATUS_INVALID_PARAMETER;
911 switch (r->in.validation_level) {
912 /* TODO: case NetlogonValidationGenericInfo: 4 */
913 case NetlogonValidationGenericInfo2: /* 5 */
916 return NT_STATUS_INVALID_INFO_CLASS;
921 return NT_STATUS_INVALID_PARAMETER;
924 switch (r->in.validation_level) {
925 case NetlogonValidationSamInfo4: /* 6 */
926 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
927 return NT_STATUS_INVALID_PARAMETER;
938 struct dcesrv_netr_LogonSamLogon_base_state {
939 struct dcesrv_call_state *dce_call;
943 struct netlogon_creds_CredentialState *creds;
945 struct netr_LogonSamLogonEx r;
947 uint32_t _ignored_flags;
950 struct netr_LogonSamLogon *lsl;
951 struct netr_LogonSamLogonWithFlags *lslwf;
952 struct netr_LogonSamLogonEx *lslex;
955 struct kdc_check_generic_kerberos kr;
958 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
959 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
960 static void dcesrv_netr_LogonSamLogon_base_reply(
961 struct dcesrv_netr_LogonSamLogon_base_state *state);
964 netr_LogonSamLogon_base
966 This version of the function allows other wrappers to say 'do not check the credentials'
968 We can't do the traditional 'wrapping' format completely, as this
969 function must only run under schannel
971 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
973 struct dcesrv_call_state *dce_call = state->dce_call;
974 TALLOC_CTX *mem_ctx = state->mem_ctx;
975 struct netr_LogonSamLogonEx *r = &state->r;
976 struct netlogon_creds_CredentialState *creds = state->creds;
977 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
978 const char *workgroup = lpcfg_workgroup(lp_ctx);
979 struct auth4_context *auth_context = NULL;
980 struct auth_usersupplied_info *user_info = NULL;
982 struct tevent_req *subreq = NULL;
984 *r->out.authoritative = 1;
986 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
988 * Currently we're always the forest root ourself.
990 return NT_STATUS_NO_SUCH_USER;
993 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
995 * Currently we don't support trusts correctly yet.
997 return NT_STATUS_NO_SUCH_USER;
1000 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1001 NT_STATUS_HAVE_NO_MEMORY(user_info);
1003 user_info->service_description = "SamLogon";
1005 netlogon_creds_decrypt_samlogon_logon(creds,
1009 switch (r->in.logon_level) {
1010 case NetlogonInteractiveInformation:
1011 case NetlogonServiceInformation:
1012 case NetlogonInteractiveTransitiveInformation:
1013 case NetlogonServiceTransitiveInformation:
1014 case NetlogonNetworkInformation:
1015 case NetlogonNetworkTransitiveInformation:
1017 nt_status = auth_context_create_for_netlogon(mem_ctx,
1018 dce_call->event_ctx, dce_call->msg_ctx,
1019 dce_call->conn->dce_ctx->lp_ctx,
1021 NT_STATUS_NOT_OK_RETURN(nt_status);
1023 user_info->remote_host = dce_call->conn->remote_address;
1024 user_info->local_host = dce_call->conn->local_address;
1026 user_info->netlogon_trust_account.secure_channel_type
1027 = creds->secure_channel_type;
1028 user_info->netlogon_trust_account.negotiate_flags
1029 = creds->negotiate_flags;
1032 * These two can be unrelated when the account is
1033 * actually that of a trusted domain, so we want to
1034 * know which DC in that trusted domain contacted
1037 user_info->netlogon_trust_account.computer_name
1038 = creds->computer_name;
1039 user_info->netlogon_trust_account.account_name
1040 = creds->account_name;
1041 user_info->netlogon_trust_account.sid
1045 /* We do not need to set up the user_info in this case */
1049 switch (r->in.logon_level) {
1050 case NetlogonInteractiveInformation:
1051 case NetlogonServiceInformation:
1052 case NetlogonInteractiveTransitiveInformation:
1053 case NetlogonServiceTransitiveInformation:
1054 user_info->auth_description = "interactive";
1056 user_info->logon_parameters
1057 = r->in.logon->password->identity_info.parameter_control;
1058 user_info->client.account_name
1059 = r->in.logon->password->identity_info.account_name.string;
1060 user_info->client.domain_name
1061 = r->in.logon->password->identity_info.domain_name.string;
1062 user_info->workstation_name
1063 = r->in.logon->password->identity_info.workstation.string;
1064 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1065 user_info->password_state = AUTH_PASSWORD_HASH;
1067 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1068 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1069 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1071 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1072 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1073 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1076 case NetlogonNetworkInformation:
1077 case NetlogonNetworkTransitiveInformation:
1078 user_info->auth_description = "network";
1080 nt_status = auth_context_set_challenge(
1082 r->in.logon->network->challenge,
1083 "netr_LogonSamLogonWithFlags");
1084 NT_STATUS_NOT_OK_RETURN(nt_status);
1086 user_info->logon_parameters
1087 = r->in.logon->network->identity_info.parameter_control;
1088 user_info->client.account_name
1089 = r->in.logon->network->identity_info.account_name.string;
1090 user_info->client.domain_name
1091 = r->in.logon->network->identity_info.domain_name.string;
1092 user_info->workstation_name
1093 = r->in.logon->network->identity_info.workstation.string;
1095 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1096 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1097 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1099 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1100 user_info->client.account_name,
1101 user_info->client.domain_name,
1102 user_info->password.response.nt,
1104 NT_STATUS_NOT_OK_RETURN(nt_status);
1109 case NetlogonGenericInformation:
1111 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1113 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1116 /* Using DES to verify kerberos tickets makes no sense */
1117 return NT_STATUS_INVALID_PARAMETER;
1120 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1121 struct dcerpc_binding_handle *irpc_handle;
1122 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1123 NT_STATUS_HAVE_NO_MEMORY(generic);
1125 r->out.validation->generic = generic;
1127 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1131 if (irpc_handle == NULL) {
1132 return NT_STATUS_NO_LOGON_SERVERS;
1135 state->kr.in.generic_request =
1136 data_blob_const(r->in.logon->generic->data,
1137 r->in.logon->generic->length);
1140 * 60 seconds should be enough
1142 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1143 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1144 state->dce_call->event_ctx,
1145 irpc_handle, &state->kr);
1146 if (subreq == NULL) {
1147 return NT_STATUS_NO_MEMORY;
1149 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1150 tevent_req_set_callback(subreq,
1151 dcesrv_netr_LogonSamLogon_base_krb5_done,
1153 return NT_STATUS_OK;
1156 /* Until we get an implemetnation of these other packages */
1157 return NT_STATUS_INVALID_PARAMETER;
1160 return NT_STATUS_INVALID_PARAMETER;
1163 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1164 auth_context, user_info);
1165 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1166 tevent_req_set_callback(subreq,
1167 dcesrv_netr_LogonSamLogon_base_auth_done,
1169 return NT_STATUS_OK;
1172 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1174 struct dcesrv_netr_LogonSamLogon_base_state *state =
1175 tevent_req_callback_data(subreq,
1176 struct dcesrv_netr_LogonSamLogon_base_state);
1177 TALLOC_CTX *mem_ctx = state->mem_ctx;
1178 struct netr_LogonSamLogonEx *r = &state->r;
1179 struct auth_user_info_dc *user_info_dc = NULL;
1180 struct netr_SamInfo2 *sam2 = NULL;
1181 struct netr_SamInfo3 *sam3 = NULL;
1182 struct netr_SamInfo6 *sam6 = NULL;
1185 nt_status = auth_check_password_recv(subreq, mem_ctx,
1187 r->out.authoritative);
1188 TALLOC_FREE(subreq);
1189 if (!NT_STATUS_IS_OK(nt_status)) {
1190 r->out.result = nt_status;
1191 dcesrv_netr_LogonSamLogon_base_reply(state);
1195 switch (r->in.validation_level) {
1197 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1200 if (!NT_STATUS_IS_OK(nt_status)) {
1201 r->out.result = nt_status;
1202 dcesrv_netr_LogonSamLogon_base_reply(state);
1206 r->out.validation->sam2 = sam2;
1210 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1213 if (!NT_STATUS_IS_OK(nt_status)) {
1214 r->out.result = nt_status;
1215 dcesrv_netr_LogonSamLogon_base_reply(state);
1219 r->out.validation->sam3 = sam3;
1223 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1226 if (!NT_STATUS_IS_OK(nt_status)) {
1227 r->out.result = nt_status;
1228 dcesrv_netr_LogonSamLogon_base_reply(state);
1232 r->out.validation->sam6 = sam6;
1236 if (!NT_STATUS_IS_OK(nt_status)) {
1237 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1238 dcesrv_netr_LogonSamLogon_base_reply(state);
1243 /* TODO: Describe and deal with these flags */
1246 r->out.result = NT_STATUS_OK;
1248 dcesrv_netr_LogonSamLogon_base_reply(state);
1251 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1253 struct dcesrv_netr_LogonSamLogon_base_state *state =
1254 tevent_req_callback_data(subreq,
1255 struct dcesrv_netr_LogonSamLogon_base_state);
1256 TALLOC_CTX *mem_ctx = state->mem_ctx;
1257 struct netr_LogonSamLogonEx *r = &state->r;
1258 struct netr_GenericInfo2 *generic = NULL;
1261 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1262 TALLOC_FREE(subreq);
1263 if (!NT_STATUS_IS_OK(status)) {
1264 r->out.result = status;
1265 dcesrv_netr_LogonSamLogon_base_reply(state);
1269 generic = r->out.validation->generic;
1270 generic->length = state->kr.out.generic_reply.length;
1271 generic->data = state->kr.out.generic_reply.data;
1273 /* TODO: Describe and deal with these flags */
1276 r->out.result = NT_STATUS_OK;
1278 dcesrv_netr_LogonSamLogon_base_reply(state);
1281 static void dcesrv_netr_LogonSamLogon_base_reply(
1282 struct dcesrv_netr_LogonSamLogon_base_state *state)
1284 struct netr_LogonSamLogonEx *r = &state->r;
1287 if (NT_STATUS_IS_OK(r->out.result)) {
1288 netlogon_creds_encrypt_samlogon_validation(state->creds,
1289 r->in.validation_level,
1293 if (state->_r.lslex != NULL) {
1294 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1295 _r->out.result = r->out.result;
1296 } else if (state->_r.lslwf != NULL) {
1297 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1298 _r->out.result = r->out.result;
1299 } else if (state->_r.lsl != NULL) {
1300 struct netr_LogonSamLogon *_r = state->_r.lsl;
1301 _r->out.result = r->out.result;
1304 status = dcesrv_reply(state->dce_call);
1305 if (!NT_STATUS_IS_OK(status)) {
1306 DBG_ERR("dcesrv_reply() failed - %s\n",
1311 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1312 struct netr_LogonSamLogonEx *r)
1314 struct dcesrv_netr_LogonSamLogon_base_state *state;
1317 *r->out.authoritative = 1;
1319 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1320 if (state == NULL) {
1321 return NT_STATUS_NO_MEMORY;
1324 state->dce_call = dce_call;
1325 state->mem_ctx = mem_ctx;
1327 state->r.in.server_name = r->in.server_name;
1328 state->r.in.computer_name = r->in.computer_name;
1329 state->r.in.logon_level = r->in.logon_level;
1330 state->r.in.logon = r->in.logon;
1331 state->r.in.validation_level = r->in.validation_level;
1332 state->r.in.flags = r->in.flags;
1333 state->r.out.validation = r->out.validation;
1334 state->r.out.authoritative = r->out.authoritative;
1335 state->r.out.flags = r->out.flags;
1337 state->_r.lslex = r;
1339 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1340 if (!NT_STATUS_IS_OK(nt_status)) {
1344 nt_status = schannel_get_creds_state(mem_ctx,
1345 dce_call->conn->dce_ctx->lp_ctx,
1346 r->in.computer_name, &state->creds);
1347 if (!NT_STATUS_IS_OK(nt_status)) {
1351 if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1352 return NT_STATUS_ACCESS_DENIED;
1355 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1357 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1365 netr_LogonSamLogonWithFlags
1368 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1369 struct netr_LogonSamLogonWithFlags *r)
1371 struct dcesrv_netr_LogonSamLogon_base_state *state;
1374 *r->out.authoritative = 1;
1376 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1377 if (state == NULL) {
1378 return NT_STATUS_NO_MEMORY;
1381 state->dce_call = dce_call;
1382 state->mem_ctx = mem_ctx;
1384 state->r.in.server_name = r->in.server_name;
1385 state->r.in.computer_name = r->in.computer_name;
1386 state->r.in.logon_level = r->in.logon_level;
1387 state->r.in.logon = r->in.logon;
1388 state->r.in.validation_level = r->in.validation_level;
1389 state->r.in.flags = r->in.flags;
1390 state->r.out.validation = r->out.validation;
1391 state->r.out.authoritative = r->out.authoritative;
1392 state->r.out.flags = r->out.flags;
1394 state->_r.lslwf = r;
1396 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1397 if (!NT_STATUS_IS_OK(nt_status)) {
1401 r->out.return_authenticator = talloc_zero(mem_ctx,
1402 struct netr_Authenticator);
1403 if (r->out.return_authenticator == NULL) {
1404 return NT_STATUS_NO_MEMORY;
1407 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1409 r->in.computer_name,
1411 r->out.return_authenticator,
1413 if (!NT_STATUS_IS_OK(nt_status)) {
1417 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1419 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1429 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1430 struct netr_LogonSamLogon *r)
1432 struct dcesrv_netr_LogonSamLogon_base_state *state;
1435 *r->out.authoritative = 1;
1437 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1438 if (state == NULL) {
1439 return NT_STATUS_NO_MEMORY;
1442 state->dce_call = dce_call;
1443 state->mem_ctx = mem_ctx;
1445 state->r.in.server_name = r->in.server_name;
1446 state->r.in.computer_name = r->in.computer_name;
1447 state->r.in.logon_level = r->in.logon_level;
1448 state->r.in.logon = r->in.logon;
1449 state->r.in.validation_level = r->in.validation_level;
1450 state->r.in.flags = &state->_ignored_flags;
1451 state->r.out.validation = r->out.validation;
1452 state->r.out.authoritative = r->out.authoritative;
1453 state->r.out.flags = &state->_ignored_flags;
1457 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1458 if (!NT_STATUS_IS_OK(nt_status)) {
1462 r->out.return_authenticator = talloc_zero(mem_ctx,
1463 struct netr_Authenticator);
1464 if (r->out.return_authenticator == NULL) {
1465 return NT_STATUS_NO_MEMORY;
1468 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1470 r->in.computer_name,
1472 r->out.return_authenticator,
1474 if (!NT_STATUS_IS_OK(nt_status)) {
1478 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1480 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1491 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1492 struct netr_LogonSamLogoff *r)
1494 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1502 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1503 struct netr_DatabaseDeltas *r)
1505 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1512 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1513 struct netr_DatabaseSync2 *r)
1515 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1516 return NT_STATUS_NOT_IMPLEMENTED;
1523 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1524 struct netr_DatabaseSync *r)
1526 struct netr_DatabaseSync2 r2;
1531 r2.in.logon_server = r->in.logon_server;
1532 r2.in.computername = r->in.computername;
1533 r2.in.credential = r->in.credential;
1534 r2.in.database_id = r->in.database_id;
1535 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1536 r2.in.sync_context = r->in.sync_context;
1537 r2.out.sync_context = r->out.sync_context;
1538 r2.out.delta_enum_array = r->out.delta_enum_array;
1539 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1541 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1550 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1551 struct netr_AccountDeltas *r)
1553 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1554 return NT_STATUS_NOT_IMPLEMENTED;
1561 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1562 struct netr_AccountSync *r)
1564 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1565 return NT_STATUS_NOT_IMPLEMENTED;
1572 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1573 struct netr_GetDcName *r)
1575 const char * const attrs[] = { NULL };
1576 struct ldb_context *sam_ctx;
1577 struct ldb_message **res;
1578 struct ldb_dn *domain_dn;
1583 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1584 * that the domainname needs to be a valid netbios domain
1585 * name, if it is not NULL.
1587 if (r->in.domainname) {
1588 const char *dot = strchr(r->in.domainname, '.');
1589 size_t len = strlen(r->in.domainname);
1591 if (dot || len > 15) {
1592 return WERR_NERR_DCNOTFOUND;
1596 * TODO: Should we also varify that only valid
1597 * netbios name characters are used?
1601 sam_ctx = samdb_connect(mem_ctx,
1602 dce_call->event_ctx,
1603 dce_call->conn->dce_ctx->lp_ctx,
1604 dce_call->conn->auth_state.session_info,
1605 dce_call->conn->remote_address,
1607 if (sam_ctx == NULL) {
1608 return WERR_DS_UNAVAILABLE;
1611 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1613 if (domain_dn == NULL) {
1614 return WERR_NO_SUCH_DOMAIN;
1617 ret = gendb_search_dn(sam_ctx, mem_ctx,
1618 domain_dn, &res, attrs);
1620 return WERR_NO_SUCH_DOMAIN;
1623 /* TODO: - return real IP address
1624 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1626 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1627 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1628 W_ERROR_HAVE_NO_MEMORY(dcname);
1630 *r->out.dcname = dcname;
1634 struct dcesrv_netr_LogonControl_base_state {
1635 struct dcesrv_call_state *dce_call;
1637 TALLOC_CTX *mem_ctx;
1639 struct netr_LogonControl2Ex r;
1642 struct netr_LogonControl *l;
1643 struct netr_LogonControl2 *l2;
1644 struct netr_LogonControl2Ex *l2ex;
1648 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1650 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1652 struct dcesrv_connection *conn = state->dce_call->conn;
1653 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1654 struct auth_session_info *session_info = conn->auth_state.session_info;
1655 enum security_user_level security_level;
1656 struct dcerpc_binding_handle *irpc_handle;
1657 struct tevent_req *subreq;
1660 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1662 if (state->_r.l != NULL) {
1666 if (state->r.in.level == 0x00000002) {
1667 return WERR_NOT_SUPPORTED;
1668 } else if (state->r.in.level != 0x00000001) {
1669 return WERR_INVALID_LEVEL;
1672 switch (state->r.in.function_code) {
1673 case NETLOGON_CONTROL_QUERY:
1674 case NETLOGON_CONTROL_REPLICATE:
1675 case NETLOGON_CONTROL_SYNCHRONIZE:
1676 case NETLOGON_CONTROL_PDC_REPLICATE:
1677 case NETLOGON_CONTROL_BREAKPOINT:
1678 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1679 case NETLOGON_CONTROL_TRUNCATE_LOG:
1682 return WERR_NOT_SUPPORTED;
1686 if (state->r.in.level < 0x00000001) {
1687 return WERR_INVALID_LEVEL;
1690 if (state->r.in.level > 0x00000004) {
1691 return WERR_INVALID_LEVEL;
1694 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1695 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1696 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1698 switch (state->r.in.level) {
1700 info1 = talloc_zero(state->mem_ctx,
1701 struct netr_NETLOGON_INFO_1);
1702 if (info1 == NULL) {
1703 return WERR_NOT_ENOUGH_MEMORY;
1705 state->r.out.query->info1 = info1;
1709 info3 = talloc_zero(state->mem_ctx,
1710 struct netr_NETLOGON_INFO_3);
1711 if (info3 == NULL) {
1712 return WERR_NOT_ENOUGH_MEMORY;
1714 state->r.out.query->info3 = info3;
1718 return WERR_INVALID_PARAMETER;
1723 * Some validations are done before the access check
1724 * and some after the access check
1726 security_level = security_session_user_level(session_info, NULL);
1727 if (security_level < SECURITY_ADMINISTRATOR) {
1728 return WERR_ACCESS_DENIED;
1731 if (state->_r.l2 != NULL) {
1733 * netr_LogonControl2
1735 if (state->r.in.level == 0x00000004) {
1736 return WERR_INVALID_LEVEL;
1740 switch (state->r.in.level) {
1745 switch (state->r.in.function_code) {
1746 case NETLOGON_CONTROL_REDISCOVER:
1747 case NETLOGON_CONTROL_TC_QUERY:
1748 case NETLOGON_CONTROL_TC_VERIFY:
1751 return WERR_INVALID_PARAMETER;
1760 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1761 return WERR_INVALID_PARAMETER;
1767 return WERR_INVALID_LEVEL;
1770 switch (state->r.in.function_code) {
1771 case NETLOGON_CONTROL_REDISCOVER:
1772 case NETLOGON_CONTROL_TC_QUERY:
1773 case NETLOGON_CONTROL_TC_VERIFY:
1774 if (state->r.in.level != 2) {
1775 return WERR_INVALID_PARAMETER;
1778 if (state->r.in.data == NULL) {
1779 return WERR_INVALID_PARAMETER;
1782 if (state->r.in.data->domain == NULL) {
1783 return WERR_INVALID_PARAMETER;
1788 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1789 if (state->r.in.level != 1) {
1790 return WERR_INVALID_PARAMETER;
1793 if (state->r.in.data == NULL) {
1794 return WERR_INVALID_PARAMETER;
1797 if (state->r.in.data->domain == NULL) {
1798 return WERR_INVALID_PARAMETER;
1801 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1802 state->r.in.data->domain);
1804 struct ldb_context *sam_ctx;
1806 sam_ctx = samdb_connect(
1808 state->dce_call->event_ctx,
1810 system_session(lp_ctx),
1811 state->dce_call->conn->remote_address,
1813 if (sam_ctx == NULL) {
1814 return WERR_DS_UNAVAILABLE;
1818 * Secrets for trusted domains can only be triggered on
1821 ok = samdb_is_pdc(sam_ctx);
1822 TALLOC_FREE(sam_ctx);
1824 return WERR_INVALID_DOMAIN_ROLE;
1830 return WERR_NOT_SUPPORTED;
1833 irpc_handle = irpc_binding_handle_by_name(state,
1834 state->dce_call->msg_ctx,
1836 &ndr_table_winbind);
1837 if (irpc_handle == NULL) {
1838 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1839 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1840 return WERR_SERVICE_NOT_FOUND;
1844 * 60 seconds timeout should be enough
1846 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1848 subreq = dcerpc_winbind_LogonControl_send(state,
1849 state->dce_call->event_ctx,
1851 state->r.in.function_code,
1854 state->r.out.query);
1855 if (subreq == NULL) {
1856 return WERR_NOT_ENOUGH_MEMORY;
1858 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1859 tevent_req_set_callback(subreq,
1860 dcesrv_netr_LogonControl_base_done,
1866 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1868 struct dcesrv_netr_LogonControl_base_state *state =
1869 tevent_req_callback_data(subreq,
1870 struct dcesrv_netr_LogonControl_base_state);
1873 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1874 &state->r.out.result);
1875 TALLOC_FREE(subreq);
1876 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1877 state->r.out.result = WERR_TIMEOUT;
1878 } else if (!NT_STATUS_IS_OK(status)) {
1879 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1880 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1881 nt_errstr(status)));
1884 if (state->_r.l2ex != NULL) {
1885 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1886 r->out.result = state->r.out.result;
1887 } else if (state->_r.l2 != NULL) {
1888 struct netr_LogonControl2 *r = state->_r.l2;
1889 r->out.result = state->r.out.result;
1890 } else if (state->_r.l != NULL) {
1891 struct netr_LogonControl *r = state->_r.l;
1892 r->out.result = state->r.out.result;
1895 status = dcesrv_reply(state->dce_call);
1896 if (!NT_STATUS_IS_OK(status)) {
1897 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1904 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1905 struct netr_LogonControl *r)
1907 struct dcesrv_netr_LogonControl_base_state *state;
1910 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1911 if (state == NULL) {
1912 return WERR_NOT_ENOUGH_MEMORY;
1915 state->dce_call = dce_call;
1916 state->mem_ctx = mem_ctx;
1918 state->r.in.logon_server = r->in.logon_server;
1919 state->r.in.function_code = r->in.function_code;
1920 state->r.in.level = r->in.level;
1921 state->r.in.data = NULL;
1922 state->r.out.query = r->out.query;
1926 werr = dcesrv_netr_LogonControl_base_call(state);
1928 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1938 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1939 struct netr_LogonControl2 *r)
1941 struct dcesrv_netr_LogonControl_base_state *state;
1944 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1945 if (state == NULL) {
1946 return WERR_NOT_ENOUGH_MEMORY;
1949 state->dce_call = dce_call;
1950 state->mem_ctx = mem_ctx;
1952 state->r.in.logon_server = r->in.logon_server;
1953 state->r.in.function_code = r->in.function_code;
1954 state->r.in.level = r->in.level;
1955 state->r.in.data = r->in.data;
1956 state->r.out.query = r->out.query;
1960 werr = dcesrv_netr_LogonControl_base_call(state);
1962 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1970 netr_LogonControl2Ex
1972 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1973 struct netr_LogonControl2Ex *r)
1975 struct dcesrv_netr_LogonControl_base_state *state;
1978 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1979 if (state == NULL) {
1980 return WERR_NOT_ENOUGH_MEMORY;
1983 state->dce_call = dce_call;
1984 state->mem_ctx = mem_ctx;
1989 werr = dcesrv_netr_LogonControl_base_call(state);
1991 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1998 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1999 struct ldb_context *sam_ctx,
2000 struct netr_DomainTrustList *trusts,
2001 uint32_t trust_flags);
2006 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2007 struct netr_GetAnyDCName *r)
2009 struct netr_DomainTrustList *trusts;
2010 struct ldb_context *sam_ctx;
2011 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2015 *r->out.dcname = NULL;
2017 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2018 /* if the domainname parameter wasn't set assume our domain */
2019 r->in.domainname = lpcfg_workgroup(lp_ctx);
2022 sam_ctx = samdb_connect(mem_ctx,
2023 dce_call->event_ctx,
2025 dce_call->conn->auth_state.session_info,
2026 dce_call->conn->remote_address,
2028 if (sam_ctx == NULL) {
2029 return WERR_DS_UNAVAILABLE;
2032 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2033 /* well we asked for a DC of our own domain */
2034 if (samdb_is_pdc(sam_ctx)) {
2035 /* we are the PDC of the specified domain */
2036 return WERR_NO_SUCH_DOMAIN;
2039 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2040 lpcfg_netbios_name(lp_ctx));
2041 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2046 /* Okay, now we have to consider the trusted domains */
2048 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2049 W_ERROR_HAVE_NO_MEMORY(trusts);
2053 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2054 NETR_TRUST_FLAG_INBOUND
2055 | NETR_TRUST_FLAG_OUTBOUND);
2056 W_ERROR_NOT_OK_RETURN(werr);
2058 for (i = 0; i < trusts->count; i++) {
2059 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2060 /* FIXME: Here we need to find a DC for the specified
2061 * trusted domain. */
2063 /* return WERR_OK; */
2064 return WERR_NO_SUCH_DOMAIN;
2068 return WERR_NO_SUCH_DOMAIN;
2075 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2076 struct netr_DatabaseRedo *r)
2078 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2083 netr_NetrEnumerateTrustedDomains
2085 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2086 struct netr_NetrEnumerateTrustedDomains *r)
2088 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2093 netr_LogonGetCapabilities
2095 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2096 struct netr_LogonGetCapabilities *r)
2098 struct netlogon_creds_CredentialState *creds;
2101 status = dcesrv_netr_creds_server_step_check(dce_call,
2103 r->in.computer_name,
2105 r->out.return_authenticator,
2107 if (!NT_STATUS_IS_OK(status)) {
2108 DEBUG(0,(__location__ " Bad credentials - error\n"));
2110 NT_STATUS_NOT_OK_RETURN(status);
2112 if (r->in.query_level != 1) {
2113 return NT_STATUS_NOT_SUPPORTED;
2116 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2118 return NT_STATUS_OK;
2123 netr_NETRLOGONSETSERVICEBITS
2125 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2126 struct netr_NETRLOGONSETSERVICEBITS *r)
2128 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2133 netr_LogonGetTrustRid
2135 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2136 struct netr_LogonGetTrustRid *r)
2138 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2143 netr_NETRLOGONCOMPUTESERVERDIGEST
2145 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2146 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2148 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2153 netr_NETRLOGONCOMPUTECLIENTDIGEST
2155 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2156 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2158 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2166 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2167 struct netr_DsRGetSiteName *r)
2169 struct ldb_context *sam_ctx;
2170 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2172 sam_ctx = samdb_connect(mem_ctx,
2173 dce_call->event_ctx,
2175 dce_call->conn->auth_state.session_info,
2176 dce_call->conn->remote_address,
2178 if (sam_ctx == NULL) {
2179 return WERR_DS_UNAVAILABLE;
2183 * We assume to be a DC when we get called over NETLOGON. Hence we
2184 * get our site name always by using "samdb_server_site_name()"
2185 * and not "samdb_client_site_name()".
2187 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2188 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2195 fill in a netr_OneDomainInfo from our own domain/forest
2197 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2198 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2199 struct GUID domain_guid,
2200 struct netr_OneDomainInfo *info,
2205 if (is_trust_list) {
2206 struct netr_trust_extension *tei = NULL;
2208 /* w2k8 only fills this on trusted domains */
2209 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2211 return NT_STATUS_NO_MEMORY;
2213 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2216 * We're always within a native forest
2218 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2219 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2221 /* For now we assume we're always the tree root */
2222 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2223 tei->parent_index = 0;
2225 tei->trust_type = our_tdo->trust_type;
2227 * This needs to be 0 instead of our_tdo->trust_attributes
2228 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2229 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2231 tei->trust_attributes = 0;
2233 info->trust_extension.info = tei;
2234 info->trust_extension.length = 16;
2237 if (is_trust_list) {
2238 info->dns_domainname.string = our_tdo->domain_name.string;
2240 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2241 info->dns_forestname.string = NULL;
2243 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2244 our_tdo->domain_name.string);
2245 if (info->dns_domainname.string == NULL) {
2246 return NT_STATUS_NO_MEMORY;
2249 info->dns_forestname.string = info->dns_domainname.string;
2252 info->domainname.string = our_tdo->netbios_name.string;
2253 info->domain_sid = our_tdo->sid;
2254 info->domain_guid = domain_guid;
2256 return NT_STATUS_OK;
2260 fill in a netr_OneDomainInfo from a trust tdo
2262 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2263 struct GUID domain_guid,
2264 const struct lsa_TrustDomainInfoInfoEx *tdo,
2265 struct netr_OneDomainInfo *info)
2267 struct netr_trust_extension *tei = NULL;
2271 /* w2k8 only fills this on trusted domains */
2272 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2274 return NT_STATUS_NO_MEMORY;
2277 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2278 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2280 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2281 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2283 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2284 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2288 * TODO: once we support multiple domains within our forest,
2289 * we need to fill this correct (or let the caller do it
2290 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2292 tei->parent_index = 0;
2294 tei->trust_type = tdo->trust_type;
2295 tei->trust_attributes = tdo->trust_attributes;
2297 info->trust_extension.info = tei;
2298 info->trust_extension.length = 16;
2300 info->domainname.string = tdo->netbios_name.string;
2301 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2302 info->dns_domainname.string = tdo->domain_name.string;
2304 info->dns_domainname.string = NULL;
2306 info->domain_sid = tdo->sid;
2307 info->domain_guid = domain_guid;
2309 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2310 info->dns_forestname.string = NULL;
2312 return NT_STATUS_OK;
2316 netr_LogonGetDomainInfo
2317 this is called as part of the ADS domain logon procedure.
2319 It has an important role in convaying details about the client, such
2320 as Operating System, Version, Service Pack etc.
2322 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2323 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2325 struct netlogon_creds_CredentialState *creds;
2326 const char * const trusts_attrs[] = {
2327 "securityIdentifier",
2335 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2336 "msDS-SupportedEncryptionTypes", NULL };
2337 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
2338 struct ldb_context *sam_ctx;
2339 const struct GUID *our_domain_guid = NULL;
2340 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2341 struct ldb_message **res1, *new_msg;
2342 struct ldb_result *trusts_res = NULL;
2343 struct ldb_dn *workstation_dn;
2344 struct netr_DomainInformation *domain_info;
2345 struct netr_LsaPolicyInformation *lsa_policy_info;
2346 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2347 bool update_dns_hostname = true;
2351 status = dcesrv_netr_creds_server_step_check(dce_call,
2353 r->in.computer_name,
2355 r->out.return_authenticator,
2357 if (!NT_STATUS_IS_OK(status)) {
2359 char* remote = NULL;
2360 TALLOC_CTX *frame = talloc_stackframe();
2361 remote = tsocket_address_string(dce_call->conn->remote_address,
2363 local = tsocket_address_string(dce_call->conn->local_address,
2365 DBG_ERR(("Bad credentials - "
2366 "computer[%s] remote[%s] local[%s]\n"),
2367 log_escape(frame, r->in.computer_name),
2372 NT_STATUS_NOT_OK_RETURN(status);
2374 sam_ctx = samdb_connect(mem_ctx,
2375 dce_call->event_ctx,
2376 dce_call->conn->dce_ctx->lp_ctx,
2377 system_session(dce_call->conn->dce_ctx->lp_ctx),
2378 dce_call->conn->remote_address,
2380 if (sam_ctx == NULL) {
2381 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2384 switch (r->in.level) {
2385 case 1: /* Domain information */
2387 if (r->in.query->workstation_info == NULL) {
2388 return NT_STATUS_INVALID_PARAMETER;
2391 /* Prepares the workstation DN */
2392 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2393 dom_sid_string(mem_ctx, creds->sid));
2394 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2396 /* Lookup for attributes in workstation object */
2397 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2400 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2403 /* Gets the sam account name which is checked against the DNS
2404 * hostname parameter. */
2405 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2408 if (sam_account_name == NULL) {
2409 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2413 * Checks that the sam account name without a possible "$"
2414 * matches as prefix with the DNS hostname in the workstation
2417 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2418 strcspn(sam_account_name, "$"));
2419 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2420 if (r->in.query->workstation_info->dns_hostname != NULL) {
2421 prefix2 = talloc_strndup(mem_ctx,
2422 r->in.query->workstation_info->dns_hostname,
2423 strcspn(r->in.query->workstation_info->dns_hostname, "."));
2424 NT_STATUS_HAVE_NO_MEMORY(prefix2);
2426 if (strcasecmp(prefix1, prefix2) != 0) {
2427 update_dns_hostname = false;
2430 update_dns_hostname = false;
2433 /* Gets the old DNS hostname */
2434 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2439 * Updates the DNS hostname when the client wishes that the
2440 * server should handle this for him
2441 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2442 * obviously only checked when we do already have a
2444 * See MS-NRPC section 3.5.4.3.9
2446 if ((old_dns_hostname != NULL) &&
2447 (r->in.query->workstation_info->workstation_flags
2448 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2449 update_dns_hostname = false;
2452 /* Gets host information and put them into our directory */
2454 new_msg = ldb_msg_new(mem_ctx);
2455 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2457 new_msg->dn = workstation_dn;
2459 /* Sets the OS name */
2461 if (r->in.query->workstation_info->os_name.string == NULL) {
2462 return NT_STATUS_INVALID_PARAMETER;
2465 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2466 r->in.query->workstation_info->os_name.string);
2467 if (ret != LDB_SUCCESS) {
2468 return NT_STATUS_NO_MEMORY;
2472 * Sets information from "os_version". On an empty structure
2473 * the values are cleared.
2475 if (r->in.query->workstation_info->os_version.os != NULL) {
2476 struct netr_OsVersionInfoEx *os_version;
2477 const char *os_version_str;
2479 os_version = &r->in.query->workstation_info->os_version.os->os;
2481 if (os_version->CSDVersion == NULL) {
2482 return NT_STATUS_INVALID_PARAMETER;
2485 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2486 os_version->MajorVersion,
2487 os_version->MinorVersion,
2488 os_version->BuildNumber);
2489 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2491 ret = ldb_msg_add_string(new_msg,
2492 "operatingSystemServicePack",
2493 os_version->CSDVersion);
2494 if (ret != LDB_SUCCESS) {
2495 return NT_STATUS_NO_MEMORY;
2498 ret = ldb_msg_add_string(new_msg,
2499 "operatingSystemVersion",
2501 if (ret != LDB_SUCCESS) {
2502 return NT_STATUS_NO_MEMORY;
2505 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2506 "operatingSystemServicePack");
2507 if (ret != LDB_SUCCESS) {
2508 return NT_STATUS_NO_MEMORY;
2511 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2512 "operatingSystemVersion");
2513 if (ret != LDB_SUCCESS) {
2514 return NT_STATUS_NO_MEMORY;
2519 * If the boolean "update_dns_hostname" remained true, then we
2520 * are fine to start the update.
2522 if (update_dns_hostname) {
2523 ret = ldb_msg_add_string(new_msg,
2525 r->in.query->workstation_info->dns_hostname);
2526 if (ret != LDB_SUCCESS) {
2527 return NT_STATUS_NO_MEMORY;
2530 /* This manual "servicePrincipalName" generation is
2531 * still needed! Since the update in the samldb LDB
2532 * module does only work if the entries already exist
2533 * which isn't always the case. */
2534 ret = ldb_msg_add_string(new_msg,
2535 "servicePrincipalName",
2536 talloc_asprintf(new_msg, "HOST/%s",
2537 r->in.computer_name));
2538 if (ret != LDB_SUCCESS) {
2539 return NT_STATUS_NO_MEMORY;
2542 ret = ldb_msg_add_string(new_msg,
2543 "servicePrincipalName",
2544 talloc_asprintf(new_msg, "HOST/%s",
2545 r->in.query->workstation_info->dns_hostname));
2546 if (ret != LDB_SUCCESS) {
2547 return NT_STATUS_NO_MEMORY;
2551 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2552 DEBUG(3,("Impossible to update samdb: %s\n",
2553 ldb_errstring(sam_ctx)));
2556 talloc_free(new_msg);
2558 /* Writes back the domain information */
2560 our_domain_guid = samdb_domain_guid(sam_ctx);
2561 if (our_domain_guid == NULL) {
2562 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2565 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2566 if (!NT_STATUS_IS_OK(status)) {
2570 status = dsdb_trust_search_tdos(sam_ctx,
2575 if (!NT_STATUS_IS_OK(status)) {
2579 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2580 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2582 ZERO_STRUCTP(domain_info);
2584 /* Informations about the local and trusted domains */
2586 status = fill_our_one_domain_info(mem_ctx,
2589 &domain_info->primary_domain,
2591 if (!NT_STATUS_IS_OK(status)) {
2595 domain_info->trusted_domain_count = trusts_res->count + 1;
2596 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2597 struct netr_OneDomainInfo,
2598 domain_info->trusted_domain_count);
2599 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2601 for (i=0; i < trusts_res->count; i++) {
2602 struct netr_OneDomainInfo *o =
2603 &domain_info->trusted_domains[i];
2604 /* we can't know the guid of trusts outside our forest */
2605 struct GUID trust_domain_guid = GUID_zero();
2606 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2608 status = dsdb_trust_parse_tdo_info(mem_ctx,
2609 trusts_res->msgs[i],
2611 if (!NT_STATUS_IS_OK(status)) {
2615 status = fill_trust_one_domain_info(mem_ctx,
2619 if (!NT_STATUS_IS_OK(status)) {
2624 status = fill_our_one_domain_info(mem_ctx,
2627 &domain_info->trusted_domains[i],
2629 if (!NT_STATUS_IS_OK(status)) {
2633 /* Sets the supported encryption types */
2634 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2635 "msDS-SupportedEncryptionTypes",
2636 default_supported_enc_types);
2638 /* Other host domain information */
2640 lsa_policy_info = talloc(mem_ctx,
2641 struct netr_LsaPolicyInformation);
2642 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2643 ZERO_STRUCTP(lsa_policy_info);
2645 domain_info->lsa_policy = *lsa_policy_info;
2647 /* The DNS hostname is only returned back when there is a chance
2649 if ((r->in.query->workstation_info->workstation_flags
2650 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2651 domain_info->dns_hostname.string = old_dns_hostname;
2653 domain_info->dns_hostname.string = NULL;
2656 domain_info->workstation_flags =
2657 r->in.query->workstation_info->workstation_flags & (
2658 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2660 r->out.info->domain_info = domain_info;
2662 case 2: /* LSA policy information - not used at the moment */
2663 lsa_policy_info = talloc(mem_ctx,
2664 struct netr_LsaPolicyInformation);
2665 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2666 ZERO_STRUCTP(lsa_policy_info);
2668 r->out.info->lsa_policy_info = lsa_policy_info;
2671 return NT_STATUS_INVALID_LEVEL;
2675 return NT_STATUS_OK;
2680 netr_ServerPasswordGet
2682 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2683 struct netr_ServerPasswordGet *r)
2685 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2688 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2689 TALLOC_CTX *mem_ctx,
2690 struct dom_sid *user_sid,
2691 struct ldb_dn *obj_dn)
2693 const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
2694 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2695 struct ldb_dn *rodc_dn;
2697 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2698 const struct dom_sid *additional_sids[] = { NULL, NULL };
2700 struct dom_sid *object_sid;
2701 const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
2703 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2704 dom_sid_string(mem_ctx, user_sid));
2705 if (!ldb_dn_validate(rodc_dn)) goto denied;
2707 /* do the two searches we need */
2708 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2709 DSDB_SEARCH_SHOW_EXTENDED_DN);
2710 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2712 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2713 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2715 object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
2717 additional_sids[0] = object_sid;
2719 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2720 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
2721 if (!W_ERROR_IS_OK(werr)) {
2725 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2726 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
2727 if (!W_ERROR_IS_OK(werr)) {
2732 * The SID list needs to include itself as well as the tokenGroups.
2734 * TODO determine if sIDHistory is required for this check
2736 werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
2737 mem_ctx, "tokenGroups", &token_sids,
2738 additional_sids, 1);
2739 if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
2743 if (never_reveal_sids &&
2744 sid_list_match(token_sids, never_reveal_sids)) {
2749 sid_list_match(token_sids, reveal_sids)) {
2761 netr_NetrLogonSendToSam
2763 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2764 struct netr_NetrLogonSendToSam *r)
2766 struct netlogon_creds_CredentialState *creds;
2767 struct ldb_context *sam_ctx;
2769 DATA_BLOB decrypted_blob;
2770 enum ndr_err_code ndr_err;
2771 struct netr_SendToSamBase base_msg = { 0 };
2773 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2775 r->in.computer_name,
2777 r->out.return_authenticator,
2780 NT_STATUS_NOT_OK_RETURN(nt_status);
2782 switch (creds->secure_channel_type) {
2786 case SEC_CHAN_WKSTA:
2787 case SEC_CHAN_DNS_DOMAIN:
2788 case SEC_CHAN_DOMAIN:
2790 return NT_STATUS_INVALID_PARAMETER;
2792 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
2793 creds->secure_channel_type));
2794 return NT_STATUS_INVALID_PARAMETER;
2797 sam_ctx = samdb_connect(mem_ctx,
2798 dce_call->event_ctx,
2799 dce_call->conn->dce_ctx->lp_ctx,
2800 system_session(dce_call->conn->dce_ctx->lp_ctx),
2801 dce_call->conn->remote_address,
2803 if (sam_ctx == NULL) {
2804 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2807 /* Buffer is meant to be 16-bit aligned */
2808 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2809 netlogon_creds_aes_decrypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2811 netlogon_creds_arcfour_crypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2814 decrypted_blob.data = r->in.opaque_buffer;
2815 decrypted_blob.length = r->in.buffer_len;
2817 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
2818 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
2820 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2821 /* We only partially implement SendToSam */
2822 return NT_STATUS_NOT_IMPLEMENTED;
2825 /* Now 'send' to SAM */
2826 switch (base_msg.message_type) {
2827 case SendToSamResetBadPasswordCount:
2829 struct ldb_message *msg = ldb_msg_new(mem_ctx);
2830 struct ldb_dn *dn = NULL;
2834 ret = ldb_transaction_start(sam_ctx);
2835 if (ret != LDB_SUCCESS) {
2836 return NT_STATUS_INTERNAL_ERROR;
2839 ret = dsdb_find_dn_by_guid(sam_ctx,
2841 &base_msg.message.reset_bad_password.guid,
2844 if (ret != LDB_SUCCESS) {
2845 ldb_transaction_cancel(sam_ctx);
2846 return NT_STATUS_INVALID_PARAMETER;
2849 if (creds->secure_channel_type == SEC_CHAN_RODC &&
2850 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
2851 DEBUG(1, ("Client asked to reset bad password on "
2852 "an arbitrary user: %s\n",
2853 ldb_dn_get_linearized(dn)));
2854 ldb_transaction_cancel(sam_ctx);
2855 return NT_STATUS_INVALID_PARAMETER;
2860 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
2861 if (ret != LDB_SUCCESS) {
2862 ldb_transaction_cancel(sam_ctx);
2863 return NT_STATUS_INVALID_PARAMETER;
2866 ret = dsdb_replace(sam_ctx, msg, 0);
2867 if (ret != LDB_SUCCESS) {
2868 ldb_transaction_cancel(sam_ctx);
2869 return NT_STATUS_INVALID_PARAMETER;
2872 ret = ldb_transaction_commit(sam_ctx);
2873 if (ret != LDB_SUCCESS) {
2874 ldb_transaction_cancel(sam_ctx);
2875 return NT_STATUS_INTERNAL_ERROR;
2881 return NT_STATUS_NOT_IMPLEMENTED;
2884 return NT_STATUS_OK;
2887 struct dcesrv_netr_DsRGetDCName_base_state {
2888 struct dcesrv_call_state *dce_call;
2889 TALLOC_CTX *mem_ctx;
2891 struct netr_DsRGetDCNameEx2 r;
2892 const char *client_site;
2895 struct netr_DsRGetDCName *dc;
2896 struct netr_DsRGetDCNameEx *dcex;
2897 struct netr_DsRGetDCNameEx2 *dcex2;
2901 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
2903 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
2905 struct dcesrv_call_state *dce_call = state->dce_call;
2906 TALLOC_CTX *mem_ctx = state->mem_ctx;
2907 struct netr_DsRGetDCNameEx2 *r = &state->r;
2908 struct ldb_context *sam_ctx;
2909 struct netr_DsRGetDCNameInfo *info;
2910 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2911 const struct tsocket_address *local_address;
2912 char *local_addr = NULL;
2913 const struct tsocket_address *remote_address;
2914 char *remote_addr = NULL;
2915 const char *server_site_name;
2917 struct netlogon_samlogon_response response;
2919 const char *dc_name = NULL;
2920 const char *domain_name = NULL;
2922 bool different_domain = true;
2924 ZERO_STRUCTP(r->out.info);
2926 sam_ctx = samdb_connect(state,
2927 dce_call->event_ctx,
2929 dce_call->conn->auth_state.session_info,
2930 dce_call->conn->remote_address,
2932 if (sam_ctx == NULL) {
2933 return WERR_DS_UNAVAILABLE;
2936 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2937 if (tsocket_address_is_inet(local_address, "ip")) {
2938 local_addr = tsocket_address_inet_addr_string(local_address, state);
2939 W_ERROR_HAVE_NO_MEMORY(local_addr);
2942 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2943 if (tsocket_address_is_inet(remote_address, "ip")) {
2944 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
2945 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2948 /* "server_unc" is ignored by w2k3 */
2950 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2951 return WERR_INVALID_FLAGS;
2954 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2955 r->in.flags & DS_PDC_REQUIRED &&
2956 r->in.flags & DS_KDC_REQUIRED) {
2957 return WERR_INVALID_FLAGS;
2959 if (r->in.flags & DS_IS_FLAT_NAME &&
2960 r->in.flags & DS_IS_DNS_NAME) {
2961 return WERR_INVALID_FLAGS;
2963 if (r->in.flags & DS_RETURN_DNS_NAME &&
2964 r->in.flags & DS_RETURN_FLAT_NAME) {
2965 return WERR_INVALID_FLAGS;
2967 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2968 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2969 return WERR_INVALID_FLAGS;
2972 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2974 (DS_DIRECTORY_SERVICE_REQUIRED |
2975 DS_DIRECTORY_SERVICE_PREFERRED |
2976 DS_GC_SERVER_REQUIRED |
2979 return WERR_INVALID_FLAGS;
2982 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2984 return WERR_INVALID_FLAGS;
2988 * If we send an all-zero GUID, we should ignore it as winbind actually
2989 * checks it with a DNS query. Windows also appears to ignore it.
2991 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
2992 r->in.domain_guid = NULL;
2995 /* Attempt winbind search only if we suspect the domain is incorrect */
2996 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
2997 if (r->in.flags & DS_IS_FLAT_NAME) {
2998 if (strcasecmp_m(r->in.domain_name,
2999 lpcfg_sam_name(lp_ctx)) == 0) {
3000 different_domain = false;
3002 } else if (r->in.flags & DS_IS_DNS_NAME) {
3003 if (strcasecmp_m(r->in.domain_name,
3004 lpcfg_dnsdomain(lp_ctx)) == 0) {
3005 different_domain = false;
3008 if (strcasecmp_m(r->in.domain_name,
3009 lpcfg_sam_name(lp_ctx)) == 0 ||
3010 strcasecmp_m(r->in.domain_name,
3011 lpcfg_dnsdomain(lp_ctx)) == 0) {
3012 different_domain = false;
3017 * We need to be able to handle empty domain names, where we
3018 * revert to our domain by default.
3020 different_domain = false;
3023 /* Proof server site parameter "site_name" if it was specified */
3024 server_site_name = samdb_server_site_name(sam_ctx, state);
3025 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3026 if (different_domain || (r->in.site_name != NULL &&
3027 (strcasecmp_m(r->in.site_name,
3028 server_site_name) != 0))) {
3030 struct dcerpc_binding_handle *irpc_handle = NULL;
3031 struct tevent_req *subreq = NULL;
3034 * Retrieve the client site to override the winbind response.
3036 * DO NOT use Windows fallback for client site.
3037 * In the case of multiple domains, this is plainly wrong.
3039 * Note: It's possible that the client may belong to multiple
3040 * subnets across domains. It's not clear what this would mean,
3041 * but here we only return what this domain knows.
3043 state->client_site = samdb_client_site_name(sam_ctx,
3049 irpc_handle = irpc_binding_handle_by_name(state,
3052 &ndr_table_winbind);
3053 if (irpc_handle == NULL) {
3054 DEBUG(0,("Failed to get binding_handle for "
3055 "winbind_server task\n"));
3056 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3057 return WERR_SERVICE_NOT_FOUND;
3060 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3062 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3064 subreq = dcerpc_wbint_DsGetDcName_send(state,
3065 dce_call->event_ctx,
3072 if (subreq == NULL) {
3073 return WERR_NOT_ENOUGH_MEMORY;
3076 tevent_req_set_callback(subreq,
3077 dcesrv_netr_DsRGetDCName_base_done,
3083 guid_str = r->in.domain_guid != NULL ?
3084 GUID_string(state, r->in.domain_guid) : NULL;
3086 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3090 r->in.client_account,
3091 r->in.mask, remote_addr,
3092 NETLOGON_NT_VERSION_5EX_WITH_IP,
3093 lp_ctx, &response, true);
3094 if (!NT_STATUS_IS_OK(status)) {
3095 return ntstatus_to_werror(status);
3099 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3100 * (O) flag when the returned forest name is in DNS format. This is here
3101 * always the case (see below).
3103 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3105 if (r->in.flags & DS_RETURN_DNS_NAME) {
3106 dc_name = response.data.nt5_ex.pdc_dns_name;
3107 domain_name = response.data.nt5_ex.dns_domain;
3109 * According to MS-NRPC 2.2.1.2.1 we should set the
3110 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3111 * the returned information is in DNS form.
3113 response.data.nt5_ex.server_type |=
3114 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3115 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3116 dc_name = response.data.nt5_ex.pdc_name;
3117 domain_name = response.data.nt5_ex.domain_name;
3121 * TODO: autodetect what we need to return
3122 * based on the given arguments
3124 dc_name = response.data.nt5_ex.pdc_name;
3125 domain_name = response.data.nt5_ex.domain_name;
3128 if (!dc_name || !dc_name[0]) {
3129 return WERR_NO_SUCH_DOMAIN;
3132 if (!domain_name || !domain_name[0]) {
3133 return WERR_NO_SUCH_DOMAIN;
3136 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3137 W_ERROR_HAVE_NO_MEMORY(info);
3138 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3139 dc_name[0] != '\\'? "\\\\":"",
3140 talloc_strdup(mem_ctx, dc_name));
3141 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3143 pdc_ip = local_addr;
3144 if (pdc_ip == NULL) {
3145 pdc_ip = "127.0.0.1";
3147 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3148 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3149 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3150 info->domain_guid = response.data.nt5_ex.domain_uuid;
3151 info->domain_name = domain_name;
3152 info->forest_name = response.data.nt5_ex.forest;
3153 info->dc_flags = response.data.nt5_ex.server_type;
3154 if (r->in.flags & DS_RETURN_DNS_NAME) {
3155 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3156 * returned if we are returning info->dc_unc containing a FQDN.
3157 * This attribute is called DomainControllerName in the specs,
3158 * it seems that we decide to return FQDN or netbios depending on
3159 * DS_RETURN_DNS_NAME.
3161 info->dc_flags |= DS_DNS_CONTROLLER;
3163 info->dc_site_name = response.data.nt5_ex.server_site;
3164 info->client_site_name = response.data.nt5_ex.client_site;
3166 *r->out.info = info;
3171 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3173 struct dcesrv_netr_DsRGetDCName_base_state *state =
3174 tevent_req_callback_data(subreq,
3175 struct dcesrv_netr_DsRGetDCName_base_state);
3176 struct dcesrv_call_state *dce_call = state->dce_call;
3177 NTSTATUS result, status;
3179 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3182 TALLOC_FREE(subreq);
3184 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3185 state->r.out.result = WERR_TIMEOUT;
3189 if (!NT_STATUS_IS_OK(status)) {
3190 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3192 state->r.out.result = WERR_GEN_FAILURE;
3196 if (!NT_STATUS_IS_OK(result)) {
3197 DBG_NOTICE("DC location via winbind failed - %s\n",
3199 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3203 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3204 DBG_ERR("DC location via winbind returned no results\n");
3205 state->r.out.result = WERR_GEN_FAILURE;
3209 if (state->r.out.info[0]->dc_unc == NULL) {
3210 DBG_ERR("DC location via winbind returned no DC unc\n");
3211 state->r.out.result = WERR_GEN_FAILURE;
3216 * Either the supplied site name is NULL (possibly via
3217 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3218 * the input match name.
3220 * TODO: Currently this means that requests with NETBIOS domain
3221 * names can fail because they do not return the site name.
3223 if (state->r.in.site_name == NULL ||
3224 strcasecmp_m("", state->r.in.site_name) == 0 ||
3225 (state->r.out.info[0]->dc_site_name != NULL &&
3226 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3227 state->r.in.site_name) == 0)) {
3229 state->r.out.info[0]->client_site_name =
3230 talloc_move(state->mem_ctx, &state->client_site);
3233 * Make sure to return our DC UNC with // prefix.
3234 * Winbind currently doesn't send the leading slashes
3237 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3238 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3239 const char *dc_unc = NULL;
3241 dc_unc = talloc_asprintf(state->mem_ctx,
3243 state->r.out.info[0]->dc_unc);
3244 state->r.out.info[0]->dc_unc = dc_unc;
3247 state->r.out.result = WERR_OK;
3249 state->r.out.info = NULL;
3250 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3254 if (state->_r.dcex2 != NULL) {
3255 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3256 r->out.result = state->r.out.result;
3257 } else if (state->_r.dcex != NULL) {
3258 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3259 r->out.result = state->r.out.result;
3260 } else if (state->_r.dc != NULL) {
3261 struct netr_DsRGetDCName *r = state->_r.dc;
3262 r->out.result = state->r.out.result;
3266 status = dcesrv_reply(dce_call);
3267 if (!NT_STATUS_IS_OK(status)) {
3268 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3269 nt_errstr(status)));
3274 netr_DsRGetDCNameEx2
3276 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3277 TALLOC_CTX *mem_ctx,
3278 struct netr_DsRGetDCNameEx2 *r)
3280 struct dcesrv_netr_DsRGetDCName_base_state *state;
3282 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3283 if (state == NULL) {
3284 return WERR_NOT_ENOUGH_MEMORY;
3287 state->dce_call = dce_call;
3288 state->mem_ctx = mem_ctx;
3291 state->_r.dcex2 = r;
3293 return dcesrv_netr_DsRGetDCName_base_call(state);
3299 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3300 struct netr_DsRGetDCNameEx *r)
3302 struct dcesrv_netr_DsRGetDCName_base_state *state;
3304 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3305 if (state == NULL) {
3306 return WERR_NOT_ENOUGH_MEMORY;
3309 state->dce_call = dce_call;
3310 state->mem_ctx = mem_ctx;
3312 state->r.in.server_unc = r->in.server_unc;
3313 state->r.in.client_account = NULL;
3314 state->r.in.mask = 0;
3315 state->r.in.domain_guid = r->in.domain_guid;
3316 state->r.in.domain_name = r->in.domain_name;
3317 state->r.in.site_name = r->in.site_name;
3318 state->r.in.flags = r->in.flags;
3319 state->r.out.info = r->out.info;
3323 return dcesrv_netr_DsRGetDCName_base_call(state);
3329 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3330 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3331 * insists that it be ignored.
3333 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3334 struct netr_DsRGetDCName *r)
3336 struct dcesrv_netr_DsRGetDCName_base_state *state;
3338 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3339 if (state == NULL) {
3340 return WERR_NOT_ENOUGH_MEMORY;
3343 state->dce_call = dce_call;
3344 state->mem_ctx = mem_ctx;
3346 state->r.in.server_unc = r->in.server_unc;
3347 state->r.in.client_account = NULL;
3348 state->r.in.mask = 0;
3349 state->r.in.domain_name = r->in.domain_name;
3350 state->r.in.domain_guid = r->in.domain_guid;
3352 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3353 state->r.in.flags = r->in.flags;
3354 state->r.out.info = r->out.info;
3358 return dcesrv_netr_DsRGetDCName_base_call(state);
3361 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3363 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3364 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3366 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3371 netr_NetrEnumerateTrustedDomainsEx
3373 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3374 struct netr_NetrEnumerateTrustedDomainsEx *r)
3376 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3381 netr_DsRAddressToSitenamesExW
3383 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3384 struct netr_DsRAddressToSitenamesExW *r)
3386 struct ldb_context *sam_ctx;
3387 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3388 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3389 sa_family_t sin_family;
3390 struct sockaddr_in *addr;
3392 struct sockaddr_in6 *addr6;
3393 char addr_str[INET6_ADDRSTRLEN];
3395 char addr_str[INET_ADDRSTRLEN];
3401 sam_ctx = samdb_connect(mem_ctx,
3402 dce_call->event_ctx,
3404 dce_call->conn->auth_state.session_info,
3405 dce_call->conn->remote_address,
3407 if (sam_ctx == NULL) {
3408 return WERR_DS_UNAVAILABLE;
3411 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3412 W_ERROR_HAVE_NO_MEMORY(ctr);
3416 ctr->count = r->in.count;
3417 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3418 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3419 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3420 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3422 for (i=0; i<ctr->count; i++) {
3423 ctr->sitename[i].string = NULL;
3424 ctr->subnetname[i].string = NULL;
3426 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3429 /* The first two byte of the buffer are reserved for the
3430 * "sin_family" but for now only the first one is used. */
3431 sin_family = r->in.addresses[i].buffer[0];
3433 switch (sin_family) {
3435 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3438 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3439 res = inet_ntop(AF_INET, &addr->sin_addr,
3440 addr_str, sizeof(addr_str));
3444 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3447 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3448 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3449 addr_str, sizeof(addr_str));
3460 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3465 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3466 ctr->subnetname[i].string = subnet_name;
3474 netr_DsRAddressToSitenamesW
3476 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3477 struct netr_DsRAddressToSitenamesW *r)
3479 struct netr_DsRAddressToSitenamesExW r2;
3480 struct netr_DsRAddressToSitenamesWCtr *ctr;
3486 r2.in.server_name = r->in.server_name;
3487 r2.in.count = r->in.count;
3488 r2.in.addresses = r->in.addresses;
3490 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3491 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3493 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3494 W_ERROR_HAVE_NO_MEMORY(ctr);
3498 ctr->count = r->in.count;
3499 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3500 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3502 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3504 for (i=0; i<ctr->count; i++) {
3505 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3513 netr_DsrGetDcSiteCoverageW
3515 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3516 struct netr_DsrGetDcSiteCoverageW *r)
3518 struct ldb_context *sam_ctx;
3519 struct DcSitesCtr *ctr;
3520 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3522 sam_ctx = samdb_connect(mem_ctx,
3523 dce_call->event_ctx,
3525 dce_call->conn->auth_state.session_info,
3526 dce_call->conn->remote_address,
3528 if (sam_ctx == NULL) {
3529 return WERR_DS_UNAVAILABLE;
3532 ctr = talloc(mem_ctx, struct DcSitesCtr);
3533 W_ERROR_HAVE_NO_MEMORY(ctr);
3537 /* For now only return our default site */
3539 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3540 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3541 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3542 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3548 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3549 struct ldb_context *sam_ctx,
3550 struct netr_DomainTrustList *trusts,
3551 uint32_t trust_flags)
3553 struct ldb_dn *system_dn;
3554 struct ldb_message **dom_res = NULL;
3555 const char *trust_attrs[] = { "flatname", "trustPartner",
3556 "securityIdentifier", "trustDirection",
3557 "trustType", "trustAttributes", NULL };
3562 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3563 NETR_TRUST_FLAG_OUTBOUND))) {
3564 return WERR_INVALID_FLAGS;
3567 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3568 ldb_get_default_basedn(sam_ctx),
3569 "(&(objectClass=container)(cn=System))");
3571 return WERR_GEN_FAILURE;
3574 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3575 &dom_res, trust_attrs,
3576 "(objectclass=trustedDomain)");
3578 for (i = 0; i < ret; i++) {
3579 unsigned int trust_dir;
3582 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3583 "trustDirection", 0);
3585 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3586 flags |= NETR_TRUST_FLAG_INBOUND;
3588 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3589 flags |= NETR_TRUST_FLAG_OUTBOUND;
3592 if (!(flags & trust_flags)) {
3593 /* this trust direction was not requested */
3598 trusts->array = talloc_realloc(trusts, trusts->array,
3599 struct netr_DomainTrust,
3601 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3603 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3604 if (!trusts->array[n].netbios_name) {
3605 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3606 "without flatname\n",
3607 ldb_dn_get_linearized(dom_res[i]->dn)));
3610 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3612 trusts->array[n].trust_flags = flags;
3613 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3614 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3615 /* TODO: find if we have parent in the list */
3616 trusts->array[n].parent_index = 0;
3619 trusts->array[n].trust_type =
3620 ldb_msg_find_attr_as_uint(dom_res[i],
3622 trusts->array[n].trust_attributes =
3623 ldb_msg_find_attr_as_uint(dom_res[i],
3624 "trustAttributes", 0);
3626 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3627 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3628 struct dom_sid zero_sid;
3629 ZERO_STRUCT(zero_sid);
3630 trusts->array[n].sid =
3631 dom_sid_dup(trusts, &zero_sid);
3633 trusts->array[n].sid =
3634 samdb_result_dom_sid(trusts, dom_res[i],
3635 "securityIdentifier");
3637 trusts->array[n].guid = GUID_zero();
3639 trusts->count = n + 1;
3642 talloc_free(dom_res);
3647 netr_DsrEnumerateDomainTrusts
3649 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3650 TALLOC_CTX *mem_ctx,
3651 struct netr_DsrEnumerateDomainTrusts *r)
3653 struct netr_DomainTrustList *trusts;
3654 struct ldb_context *sam_ctx;
3656 struct ldb_message **dom_res;
3657 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3658 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3659 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3663 if (r->in.trust_flags & 0xFFFFFE00) {
3664 return WERR_INVALID_FLAGS;
3667 /* TODO: turn to hard check once we are sure this is 100% correct */
3668 if (!r->in.server_name) {
3669 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3670 "But received NULL!\n", dnsdomain));
3672 p = strchr(r->in.server_name, '.');
3674 DEBUG(3, ("Invalid domain! Expected name in domain "
3675 "[%s]. But received [%s]!\n",
3676 dnsdomain, r->in.server_name));
3677 p = r->in.server_name;
3681 if (strcasecmp(p, dnsdomain)) {
3682 DEBUG(3, ("Invalid domain! Expected name in domain "
3683 "[%s]. But received [%s]!\n",
3684 dnsdomain, r->in.server_name));
3688 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3689 W_ERROR_HAVE_NO_MEMORY(trusts);
3692 r->out.trusts = trusts;
3694 sam_ctx = samdb_connect(mem_ctx,
3695 dce_call->event_ctx,
3697 dce_call->conn->auth_state.session_info,
3698 dce_call->conn->remote_address,
3700 if (sam_ctx == NULL) {
3701 return WERR_GEN_FAILURE;
3704 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3705 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3707 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3708 trusts, r->in.trust_flags);
3709 W_ERROR_NOT_OK_RETURN(werr);
3712 /* NOTE: we currently are always the root of the forest */
3713 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3714 uint32_t n = trusts->count;
3716 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3717 &dom_res, dom_attrs);
3719 return WERR_GEN_FAILURE;
3722 trusts->count = n + 1;
3723 trusts->array = talloc_realloc(trusts, trusts->array,
3724 struct netr_DomainTrust,
3726 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3728 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3729 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3730 trusts->array[n].trust_flags =
3731 NETR_TRUST_FLAG_NATIVE |
3732 NETR_TRUST_FLAG_TREEROOT |
3733 NETR_TRUST_FLAG_IN_FOREST |
3734 NETR_TRUST_FLAG_PRIMARY;
3735 /* we are always the root domain for now */
3736 trusts->array[n].parent_index = 0;
3737 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3738 trusts->array[n].trust_attributes = 0;
3739 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3742 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3744 talloc_free(dom_res);
3752 netr_DsrDeregisterDNSHostRecords
3754 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3755 struct netr_DsrDeregisterDNSHostRecords *r)
3757 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3761 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3762 struct netr_ServerGetTrustInfo *r);
3765 netr_ServerTrustPasswordsGet
3767 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3768 struct netr_ServerTrustPasswordsGet *r)
3770 struct netr_ServerGetTrustInfo r2 = {};
3771 struct netr_TrustInfo *_ti = NULL;
3774 r2.in.server_name = r->in.server_name;
3775 r2.in.account_name = r->in.account_name;
3776 r2.in.secure_channel_type = r->in.secure_channel_type;
3777 r2.in.computer_name = r->in.computer_name;
3778 r2.in.credential = r->in.credential;
3780 r2.out.return_authenticator = r->out.return_authenticator;
3781 r2.out.new_owf_password = r->out.new_owf_password;
3782 r2.out.old_owf_password = r->out.old_owf_password;
3783 r2.out.trust_info = &_ti;
3785 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3787 r->out.return_authenticator = r2.out.return_authenticator;
3788 r->out.new_owf_password = r2.out.new_owf_password;
3789 r->out.old_owf_password = r2.out.old_owf_password;
3795 netr_DsRGetForestTrustInformation
3797 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3798 struct dcesrv_call_state *dce_call;
3799 TALLOC_CTX *mem_ctx;
3800 struct netr_DsRGetForestTrustInformation *r;
3803 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3805 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3806 TALLOC_CTX *mem_ctx,
3807 struct netr_DsRGetForestTrustInformation *r)
3809 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3810 struct dcesrv_connection *conn = dce_call->conn;
3811 struct auth_session_info *session_info = conn->auth_state.session_info;
3812 enum security_user_level security_level;
3813 struct ldb_context *sam_ctx = NULL;
3814 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3815 struct dcerpc_binding_handle *irpc_handle = NULL;
3816 struct tevent_req *subreq = NULL;
3817 struct ldb_dn *domain_dn = NULL;
3818 struct ldb_dn *forest_dn = NULL;
3822 security_level = security_session_user_level(session_info, NULL);
3823 if (security_level < SECURITY_USER) {
3824 return WERR_ACCESS_DENIED;
3827 if (r->in.flags & 0xFFFFFFFE) {
3828 return WERR_INVALID_FLAGS;
3831 sam_ctx = samdb_connect(mem_ctx,
3832 dce_call->event_ctx,
3834 dce_call->conn->auth_state.session_info,
3835 dce_call->conn->remote_address,
3837 if (sam_ctx == NULL) {
3838 return WERR_GEN_FAILURE;
3841 domain_dn = ldb_get_default_basedn(sam_ctx);
3842 if (domain_dn == NULL) {
3843 return WERR_GEN_FAILURE;
3846 forest_dn = ldb_get_root_basedn(sam_ctx);
3847 if (forest_dn == NULL) {
3848 return WERR_GEN_FAILURE;
3851 cmp = ldb_dn_compare(domain_dn, forest_dn);
3853 return WERR_NERR_ACFNOTLOADED;
3856 forest_level = dsdb_forest_functional_level(sam_ctx);
3857 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3858 return WERR_INVALID_FUNCTION;
3861 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3862 if (!samdb_is_pdc(sam_ctx)) {
3863 return WERR_NERR_NOTPRIMARY;
3866 if (r->in.trusted_domain_name == NULL) {
3867 return WERR_INVALID_FLAGS;
3871 if (r->in.trusted_domain_name == NULL) {
3875 * information about our own domain
3877 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3878 r->out.forest_trust_info);
3879 if (!NT_STATUS_IS_OK(status)) {
3880 return ntstatus_to_werror(status);
3887 * Forward the request to winbindd
3890 state = talloc_zero(mem_ctx,
3891 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3892 if (state == NULL) {
3893 return WERR_NOT_ENOUGH_MEMORY;
3895 state->dce_call = dce_call;
3896 state->mem_ctx = mem_ctx;
3899 irpc_handle = irpc_binding_handle_by_name(state,
3900 state->dce_call->msg_ctx,
3902 &ndr_table_winbind);
3903 if (irpc_handle == NULL) {
3904 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3905 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3906 return WERR_SERVICE_NOT_FOUND;
3910 * 60 seconds timeout should be enough
3912 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3914 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3915 state->dce_call->event_ctx,
3917 r->in.trusted_domain_name,
3919 r->out.forest_trust_info);
3920 if (subreq == NULL) {
3921 return WERR_NOT_ENOUGH_MEMORY;
3923 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3924 tevent_req_set_callback(subreq,
3925 dcesrv_netr_DsRGetForestTrustInformation_done,
3931 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3933 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3934 tevent_req_callback_data(subreq,
3935 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3938 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3940 &state->r->out.result);
3941 TALLOC_FREE(subreq);
3942 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3943 state->r->out.result = WERR_TIMEOUT;
3944 } else if (!NT_STATUS_IS_OK(status)) {
3945 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3946 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3947 nt_errstr(status)));
3950 status = dcesrv_reply(state->dce_call);
3951 if (!NT_STATUS_IS_OK(status)) {
3952 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3957 netr_GetForestTrustInformation
3959 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3960 TALLOC_CTX *mem_ctx,
3961 struct netr_GetForestTrustInformation *r)
3963 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3964 struct netlogon_creds_CredentialState *creds = NULL;
3965 struct ldb_context *sam_ctx = NULL;
3966 struct ldb_dn *domain_dn = NULL;
3967 struct ldb_dn *forest_dn = NULL;
3972 status = dcesrv_netr_creds_server_step_check(dce_call,
3974 r->in.computer_name,
3976 r->out.return_authenticator,
3978 if (!NT_STATUS_IS_OK(status)) {
3982 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3983 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3984 return NT_STATUS_NOT_IMPLEMENTED;
3987 sam_ctx = samdb_connect(mem_ctx,
3988 dce_call->event_ctx,
3990 dce_call->conn->auth_state.session_info,
3991 dce_call->conn->remote_address,
3993 if (sam_ctx == NULL) {
3994 return NT_STATUS_INTERNAL_ERROR;
3997 /* TODO: check r->in.server_name is our name */
3999 domain_dn = ldb_get_default_basedn(sam_ctx);
4000 if (domain_dn == NULL) {
4001 return NT_STATUS_INTERNAL_ERROR;
4004 forest_dn = ldb_get_root_basedn(sam_ctx);
4005 if (forest_dn == NULL) {
4006 return NT_STATUS_INTERNAL_ERROR;
4009 cmp = ldb_dn_compare(domain_dn, forest_dn);
4011 return NT_STATUS_INVALID_DOMAIN_STATE;
4014 forest_level = dsdb_forest_functional_level(sam_ctx);
4015 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4016 return NT_STATUS_INVALID_DOMAIN_STATE;
4019 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4020 r->out.forest_trust_info);
4021 if (!NT_STATUS_IS_OK(status)) {
4025 return NT_STATUS_OK;
4030 netr_ServerGetTrustInfo
4032 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4033 struct netr_ServerGetTrustInfo *r)
4035 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4036 struct netlogon_creds_CredentialState *creds = NULL;
4037 struct ldb_context *sam_ctx = NULL;
4038 const char * const attrs[] = {
4041 "userAccountControl",
4044 struct ldb_message **res = NULL;
4045 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4048 const char *asid = NULL;
4050 const char *aname = NULL;
4051 struct ldb_message *tdo_msg = NULL;
4052 const char * const tdo_attrs[] = {
4053 "trustAuthIncoming",
4057 struct netr_TrustInfo *trust_info = NULL;
4059 ZERO_STRUCTP(r->out.new_owf_password);
4060 ZERO_STRUCTP(r->out.old_owf_password);
4062 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4064 r->in.computer_name,
4066 r->out.return_authenticator,
4068 if (!NT_STATUS_IS_OK(nt_status)) {
4072 /* TODO: check r->in.server_name is our name */
4074 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4075 return NT_STATUS_INVALID_PARAMETER;
4078 if (r->in.secure_channel_type != creds->secure_channel_type) {
4079 return NT_STATUS_INVALID_PARAMETER;
4082 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4083 return NT_STATUS_INVALID_PARAMETER;
4086 sam_ctx = samdb_connect(mem_ctx,
4087 dce_call->event_ctx,
4089 system_session(lp_ctx),
4090 dce_call->conn->remote_address,
4092 if (sam_ctx == NULL) {
4093 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4096 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4098 return NT_STATUS_NO_MEMORY;
4101 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4102 "(&(objectClass=user)(objectSid=%s))",
4105 return NT_STATUS_ACCOUNT_DISABLED;
4108 switch (creds->secure_channel_type) {
4109 case SEC_CHAN_DNS_DOMAIN:
4110 case SEC_CHAN_DOMAIN:
4111 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4113 if (uac & UF_ACCOUNTDISABLE) {
4114 return NT_STATUS_ACCOUNT_DISABLED;
4117 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4118 return NT_STATUS_ACCOUNT_DISABLED;
4121 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4122 if (aname == NULL) {
4123 return NT_STATUS_ACCOUNT_DISABLED;
4126 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4127 SEC_CHAN_DOMAIN, aname,
4128 tdo_attrs, mem_ctx, &tdo_msg);
4129 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4130 return NT_STATUS_ACCOUNT_DISABLED;
4132 if (!NT_STATUS_IS_OK(nt_status)) {
4136 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4139 if (!NT_STATUS_IS_OK(nt_status)) {
4143 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4144 if (trust_info == NULL) {
4145 return NT_STATUS_NO_MEMORY;
4148 trust_info->count = 1;
4149 trust_info->data = talloc_array(trust_info, uint32_t,
4151 if (trust_info->data == NULL) {
4152 return NT_STATUS_NO_MEMORY;
4155 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4161 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4164 if (!NT_STATUS_IS_OK(nt_status)) {
4168 prevNtHash = talloc(mem_ctx, struct samr_Password);
4169 if (prevNtHash == NULL) {
4170 return NT_STATUS_NO_MEMORY;
4173 E_md4hash("", prevNtHash->hash);
4177 if (curNtHash != NULL) {
4178 *r->out.new_owf_password = *curNtHash;
4179 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4181 if (prevNtHash != NULL) {
4182 *r->out.old_owf_password = *prevNtHash;
4183 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4186 if (trust_info != NULL) {
4187 *r->out.trust_info = trust_info;
4190 return NT_STATUS_OK;
4196 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4197 struct netr_Unused47 *r)
4199 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4203 struct netr_dnsupdate_RODC_state {
4204 struct dcesrv_call_state *dce_call;
4205 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4206 struct dnsupdate_RODC *r2;
4210 called when the forwarded RODC dns update request is finished
4212 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4214 struct netr_dnsupdate_RODC_state *st =
4215 tevent_req_callback_data(subreq,
4216 struct netr_dnsupdate_RODC_state);
4219 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4220 TALLOC_FREE(subreq);
4221 if (!NT_STATUS_IS_OK(status)) {
4222 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4223 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4226 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4228 status = dcesrv_reply(st->dce_call);
4229 if (!NT_STATUS_IS_OK(status)) {
4230 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4235 netr_DsrUpdateReadOnlyServerDnsRecords
4237 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4238 TALLOC_CTX *mem_ctx,
4239 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4241 struct netlogon_creds_CredentialState *creds;
4243 struct dcerpc_binding_handle *binding_handle;
4244 struct netr_dnsupdate_RODC_state *st;
4245 struct tevent_req *subreq;
4247 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4249 r->in.computer_name,
4251 r->out.return_authenticator,
4253 NT_STATUS_NOT_OK_RETURN(nt_status);
4255 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4256 return NT_STATUS_ACCESS_DENIED;
4259 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4260 NT_STATUS_HAVE_NO_MEMORY(st);
4262 st->dce_call = dce_call;
4264 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4265 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4267 st->r2->in.dom_sid = creds->sid;
4268 st->r2->in.site_name = r->in.site_name;
4269 st->r2->in.dns_ttl = r->in.dns_ttl;
4270 st->r2->in.dns_names = r->in.dns_names;
4271 st->r2->out.dns_names = r->out.dns_names;
4273 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
4274 "dnsupdate", &ndr_table_irpc);
4275 if (binding_handle == NULL) {
4276 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4277 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4278 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4281 /* forward the call */
4282 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4283 binding_handle, st->r2);
4284 NT_STATUS_HAVE_NO_MEMORY(subreq);
4286 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4288 /* setup the callback */
4289 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4291 return NT_STATUS_OK;
4295 /* include the generated boilerplate */
4296 #include "librpc/gen_ndr/ndr_netlogon_s.c"