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.
623 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
625 const char *computer_name,
626 struct netr_Authenticator *received_authenticator,
627 struct netr_Authenticator *return_authenticator,
628 struct netlogon_creds_CredentialState **creds_out)
631 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
632 bool schannel_global_required = (schannel == true);
634 if (schannel_global_required) {
635 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
637 dcesrv_call_auth_info(dce_call, &auth_type, NULL);
639 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
640 DBG_ERR("[%s] is not using schannel\n",
642 return NT_STATUS_ACCESS_DENIED;
646 nt_status = schannel_check_creds_state(mem_ctx,
647 dce_call->conn->dce_ctx->lp_ctx,
649 received_authenticator,
650 return_authenticator,
656 Change the machine account password for the currently connected
657 client. Supplies only the NT#.
660 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
661 struct netr_ServerPasswordSet *r)
663 struct netlogon_creds_CredentialState *creds;
664 struct ldb_context *sam_ctx;
665 const char * const attrs[] = { "unicodePwd", NULL };
666 struct ldb_message **res;
667 struct samr_Password *oldNtHash;
671 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
674 r->in.credential, r->out.return_authenticator,
676 NT_STATUS_NOT_OK_RETURN(nt_status);
678 sam_ctx = samdb_connect(mem_ctx,
680 dce_call->conn->dce_ctx->lp_ctx,
681 system_session(dce_call->conn->dce_ctx->lp_ctx),
682 dce_call->conn->remote_address,
684 if (sam_ctx == NULL) {
685 return NT_STATUS_INVALID_SYSTEM_SERVICE;
688 netlogon_creds_des_decrypt(creds, r->in.new_password);
690 /* fetch the old password hashes (the NT hash has to exist) */
692 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
693 "(&(objectClass=user)(objectSid=%s))",
694 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
696 return NT_STATUS_WRONG_PASSWORD;
699 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
700 dce_call->conn->dce_ctx->lp_ctx,
701 res[0], NULL, &oldNtHash);
702 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
703 return NT_STATUS_WRONG_PASSWORD;
706 /* Using the sid for the account as the key, set the password */
707 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
709 NULL, /* Don't have version */
710 NULL, /* Don't have plaintext */
711 NULL, r->in.new_password,
712 NULL, oldNtHash, /* Password change */
718 Change the machine account password for the currently connected
719 client. Supplies new plaintext.
721 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
722 struct netr_ServerPasswordSet2 *r)
724 struct netlogon_creds_CredentialState *creds;
725 struct ldb_context *sam_ctx;
726 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
727 struct ldb_message **res;
728 struct samr_Password *oldLmHash, *oldNtHash;
729 struct NL_PASSWORD_VERSION version = {};
730 const uint32_t *new_version = NULL;
732 DATA_BLOB new_password;
734 struct samr_CryptPassword password_buf;
736 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
739 r->in.credential, r->out.return_authenticator,
741 NT_STATUS_NOT_OK_RETURN(nt_status);
743 sam_ctx = samdb_connect(mem_ctx,
745 dce_call->conn->dce_ctx->lp_ctx,
746 system_session(dce_call->conn->dce_ctx->lp_ctx),
747 dce_call->conn->remote_address,
749 if (sam_ctx == NULL) {
750 return NT_STATUS_INVALID_SYSTEM_SERVICE;
753 memcpy(password_buf.data, r->in.new_password->data, 512);
754 SIVAL(password_buf.data, 512, r->in.new_password->length);
756 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
757 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
759 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
762 switch (creds->secure_channel_type) {
763 case SEC_CHAN_DOMAIN:
764 case SEC_CHAN_DNS_DOMAIN: {
765 uint32_t len = IVAL(password_buf.data, 512);
767 uint32_t ofs = 500 - len;
770 p = password_buf.data + ofs;
772 version.ReservedField = IVAL(p, 0);
773 version.PasswordVersionNumber = IVAL(p, 4);
774 version.PasswordVersionPresent = IVAL(p, 8);
776 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
777 new_version = &version.PasswordVersionNumber;
785 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
786 DEBUG(3,("samr: failed to decode password buffer\n"));
787 return NT_STATUS_WRONG_PASSWORD;
790 /* fetch the old password hashes (at least one of both has to exist) */
792 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
793 "(&(objectClass=user)(objectSid=%s))",
794 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
796 return NT_STATUS_WRONG_PASSWORD;
799 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
800 dce_call->conn->dce_ctx->lp_ctx,
801 res[0], &oldLmHash, &oldNtHash);
802 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
803 return NT_STATUS_WRONG_PASSWORD;
806 /* Using the sid for the account as the key, set the password */
807 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
810 &new_password, /* we have plaintext */
812 oldLmHash, oldNtHash, /* Password change */
821 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
822 struct netr_LogonUasLogon *r)
824 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
831 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
832 struct netr_LogonUasLogoff *r)
834 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
838 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
839 const struct netr_LogonSamLogonEx *r)
841 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
843 switch (r->in.logon_level) {
844 case NetlogonInteractiveInformation:
845 case NetlogonServiceInformation:
846 case NetlogonInteractiveTransitiveInformation:
847 case NetlogonServiceTransitiveInformation:
848 if (r->in.logon->password == NULL) {
849 return NT_STATUS_INVALID_PARAMETER;
852 switch (r->in.validation_level) {
853 case NetlogonValidationSamInfo: /* 2 */
854 case NetlogonValidationSamInfo2: /* 3 */
855 case NetlogonValidationSamInfo4: /* 6 */
858 return NT_STATUS_INVALID_INFO_CLASS;
862 case NetlogonNetworkInformation:
863 case NetlogonNetworkTransitiveInformation:
864 if (r->in.logon->network == NULL) {
865 return NT_STATUS_INVALID_PARAMETER;
868 switch (r->in.validation_level) {
869 case NetlogonValidationSamInfo: /* 2 */
870 case NetlogonValidationSamInfo2: /* 3 */
871 case NetlogonValidationSamInfo4: /* 6 */
874 return NT_STATUS_INVALID_INFO_CLASS;
879 case NetlogonGenericInformation:
880 if (r->in.logon->generic == NULL) {
881 return NT_STATUS_INVALID_PARAMETER;
884 switch (r->in.validation_level) {
885 /* TODO: case NetlogonValidationGenericInfo: 4 */
886 case NetlogonValidationGenericInfo2: /* 5 */
889 return NT_STATUS_INVALID_INFO_CLASS;
894 return NT_STATUS_INVALID_PARAMETER;
897 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
899 switch (r->in.validation_level) {
900 case NetlogonValidationSamInfo4: /* 6 */
901 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
902 return NT_STATUS_INVALID_PARAMETER;
913 struct dcesrv_netr_LogonSamLogon_base_state {
914 struct dcesrv_call_state *dce_call;
918 struct netlogon_creds_CredentialState *creds;
920 struct netr_LogonSamLogonEx r;
922 uint32_t _ignored_flags;
925 struct netr_LogonSamLogon *lsl;
926 struct netr_LogonSamLogonWithFlags *lslwf;
927 struct netr_LogonSamLogonEx *lslex;
930 struct kdc_check_generic_kerberos kr;
933 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
934 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
935 static void dcesrv_netr_LogonSamLogon_base_reply(
936 struct dcesrv_netr_LogonSamLogon_base_state *state);
939 netr_LogonSamLogon_base
941 This version of the function allows other wrappers to say 'do not check the credentials'
943 We can't do the traditional 'wrapping' format completely, as this
944 function must only run under schannel
946 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
948 struct dcesrv_call_state *dce_call = state->dce_call;
949 TALLOC_CTX *mem_ctx = state->mem_ctx;
950 struct netr_LogonSamLogonEx *r = &state->r;
951 struct netlogon_creds_CredentialState *creds = state->creds;
952 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
953 const char *workgroup = lpcfg_workgroup(lp_ctx);
954 struct auth4_context *auth_context = NULL;
955 struct auth_usersupplied_info *user_info = NULL;
957 struct tevent_req *subreq = NULL;
959 *r->out.authoritative = 1;
961 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
963 * Currently we're always the forest root ourself.
965 return NT_STATUS_NO_SUCH_USER;
968 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
970 * Currently we don't support trusts correctly yet.
972 return NT_STATUS_NO_SUCH_USER;
975 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
976 NT_STATUS_HAVE_NO_MEMORY(user_info);
978 user_info->service_description = "SamLogon";
980 netlogon_creds_decrypt_samlogon_logon(creds,
984 switch (r->in.logon_level) {
985 case NetlogonInteractiveInformation:
986 case NetlogonServiceInformation:
987 case NetlogonInteractiveTransitiveInformation:
988 case NetlogonServiceTransitiveInformation:
989 case NetlogonNetworkInformation:
990 case NetlogonNetworkTransitiveInformation:
992 nt_status = auth_context_create_for_netlogon(mem_ctx,
993 dce_call->event_ctx, dce_call->msg_ctx,
994 dce_call->conn->dce_ctx->lp_ctx,
996 NT_STATUS_NOT_OK_RETURN(nt_status);
998 user_info->remote_host = dce_call->conn->remote_address;
999 user_info->local_host = dce_call->conn->local_address;
1001 user_info->netlogon_trust_account.secure_channel_type
1002 = creds->secure_channel_type;
1003 user_info->netlogon_trust_account.negotiate_flags
1004 = creds->negotiate_flags;
1007 * These two can be unrelated when the account is
1008 * actually that of a trusted domain, so we want to
1009 * know which DC in that trusted domain contacted
1012 user_info->netlogon_trust_account.computer_name
1013 = creds->computer_name;
1014 user_info->netlogon_trust_account.account_name
1015 = creds->account_name;
1016 user_info->netlogon_trust_account.sid
1020 /* We do not need to set up the user_info in this case */
1024 switch (r->in.logon_level) {
1025 case NetlogonInteractiveInformation:
1026 case NetlogonServiceInformation:
1027 case NetlogonInteractiveTransitiveInformation:
1028 case NetlogonServiceTransitiveInformation:
1029 user_info->auth_description = "interactive";
1031 user_info->logon_parameters
1032 = r->in.logon->password->identity_info.parameter_control;
1033 user_info->client.account_name
1034 = r->in.logon->password->identity_info.account_name.string;
1035 user_info->client.domain_name
1036 = r->in.logon->password->identity_info.domain_name.string;
1037 user_info->workstation_name
1038 = r->in.logon->password->identity_info.workstation.string;
1039 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1040 user_info->password_state = AUTH_PASSWORD_HASH;
1042 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1043 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1044 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1046 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1047 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1048 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1051 case NetlogonNetworkInformation:
1052 case NetlogonNetworkTransitiveInformation:
1053 user_info->auth_description = "network";
1055 nt_status = auth_context_set_challenge(
1057 r->in.logon->network->challenge,
1058 "netr_LogonSamLogonWithFlags");
1059 NT_STATUS_NOT_OK_RETURN(nt_status);
1061 user_info->logon_parameters
1062 = r->in.logon->network->identity_info.parameter_control;
1063 user_info->client.account_name
1064 = r->in.logon->network->identity_info.account_name.string;
1065 user_info->client.domain_name
1066 = r->in.logon->network->identity_info.domain_name.string;
1067 user_info->workstation_name
1068 = r->in.logon->network->identity_info.workstation.string;
1070 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1071 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1072 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1074 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1075 user_info->client.account_name,
1076 user_info->client.domain_name,
1077 user_info->password.response.nt,
1079 NT_STATUS_NOT_OK_RETURN(nt_status);
1084 case NetlogonGenericInformation:
1086 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1088 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1091 /* Using DES to verify kerberos tickets makes no sense */
1092 return NT_STATUS_INVALID_PARAMETER;
1095 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1096 struct dcerpc_binding_handle *irpc_handle;
1097 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1098 NT_STATUS_HAVE_NO_MEMORY(generic);
1100 r->out.validation->generic = generic;
1102 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1106 if (irpc_handle == NULL) {
1107 return NT_STATUS_NO_LOGON_SERVERS;
1110 state->kr.in.generic_request =
1111 data_blob_const(r->in.logon->generic->data,
1112 r->in.logon->generic->length);
1115 * 60 seconds should be enough
1117 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1118 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1119 state->dce_call->event_ctx,
1120 irpc_handle, &state->kr);
1121 if (subreq == NULL) {
1122 return NT_STATUS_NO_MEMORY;
1124 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1125 tevent_req_set_callback(subreq,
1126 dcesrv_netr_LogonSamLogon_base_krb5_done,
1128 return NT_STATUS_OK;
1131 /* Until we get an implemetnation of these other packages */
1132 return NT_STATUS_INVALID_PARAMETER;
1135 return NT_STATUS_INVALID_PARAMETER;
1138 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1139 auth_context, user_info);
1140 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1141 tevent_req_set_callback(subreq,
1142 dcesrv_netr_LogonSamLogon_base_auth_done,
1144 return NT_STATUS_OK;
1147 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1149 struct dcesrv_netr_LogonSamLogon_base_state *state =
1150 tevent_req_callback_data(subreq,
1151 struct dcesrv_netr_LogonSamLogon_base_state);
1152 TALLOC_CTX *mem_ctx = state->mem_ctx;
1153 struct netr_LogonSamLogonEx *r = &state->r;
1154 struct auth_user_info_dc *user_info_dc = NULL;
1155 struct netr_SamInfo2 *sam2 = NULL;
1156 struct netr_SamInfo3 *sam3 = NULL;
1157 struct netr_SamInfo6 *sam6 = NULL;
1160 nt_status = auth_check_password_recv(subreq, mem_ctx,
1162 r->out.authoritative);
1163 TALLOC_FREE(subreq);
1164 if (!NT_STATUS_IS_OK(nt_status)) {
1165 r->out.result = nt_status;
1166 dcesrv_netr_LogonSamLogon_base_reply(state);
1170 switch (r->in.validation_level) {
1172 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1175 if (!NT_STATUS_IS_OK(nt_status)) {
1176 r->out.result = nt_status;
1177 dcesrv_netr_LogonSamLogon_base_reply(state);
1181 r->out.validation->sam2 = sam2;
1185 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1188 if (!NT_STATUS_IS_OK(nt_status)) {
1189 r->out.result = nt_status;
1190 dcesrv_netr_LogonSamLogon_base_reply(state);
1194 r->out.validation->sam3 = sam3;
1198 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1201 if (!NT_STATUS_IS_OK(nt_status)) {
1202 r->out.result = nt_status;
1203 dcesrv_netr_LogonSamLogon_base_reply(state);
1207 r->out.validation->sam6 = sam6;
1211 if (!NT_STATUS_IS_OK(nt_status)) {
1212 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1213 dcesrv_netr_LogonSamLogon_base_reply(state);
1218 /* TODO: Describe and deal with these flags */
1221 r->out.result = NT_STATUS_OK;
1223 dcesrv_netr_LogonSamLogon_base_reply(state);
1226 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1228 struct dcesrv_netr_LogonSamLogon_base_state *state =
1229 tevent_req_callback_data(subreq,
1230 struct dcesrv_netr_LogonSamLogon_base_state);
1231 TALLOC_CTX *mem_ctx = state->mem_ctx;
1232 struct netr_LogonSamLogonEx *r = &state->r;
1233 struct netr_GenericInfo2 *generic = NULL;
1236 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1237 TALLOC_FREE(subreq);
1238 if (!NT_STATUS_IS_OK(status)) {
1239 r->out.result = status;
1240 dcesrv_netr_LogonSamLogon_base_reply(state);
1244 generic = r->out.validation->generic;
1245 generic->length = state->kr.out.generic_reply.length;
1246 generic->data = state->kr.out.generic_reply.data;
1248 /* TODO: Describe and deal with these flags */
1251 r->out.result = NT_STATUS_OK;
1253 dcesrv_netr_LogonSamLogon_base_reply(state);
1256 static void dcesrv_netr_LogonSamLogon_base_reply(
1257 struct dcesrv_netr_LogonSamLogon_base_state *state)
1259 struct netr_LogonSamLogonEx *r = &state->r;
1262 if (NT_STATUS_IS_OK(r->out.result)) {
1263 netlogon_creds_encrypt_samlogon_validation(state->creds,
1264 r->in.validation_level,
1268 if (state->_r.lslex != NULL) {
1269 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1270 _r->out.result = r->out.result;
1271 } else if (state->_r.lslwf != NULL) {
1272 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1273 _r->out.result = r->out.result;
1274 } else if (state->_r.lsl != NULL) {
1275 struct netr_LogonSamLogon *_r = state->_r.lsl;
1276 _r->out.result = r->out.result;
1279 status = dcesrv_reply(state->dce_call);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 DBG_ERR("dcesrv_reply() failed - %s\n",
1286 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1287 struct netr_LogonSamLogonEx *r)
1289 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1290 struct dcesrv_netr_LogonSamLogon_base_state *state;
1293 *r->out.authoritative = 1;
1295 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1296 if (state == NULL) {
1297 return NT_STATUS_NO_MEMORY;
1300 state->dce_call = dce_call;
1301 state->mem_ctx = mem_ctx;
1303 state->r.in.server_name = r->in.server_name;
1304 state->r.in.computer_name = r->in.computer_name;
1305 state->r.in.logon_level = r->in.logon_level;
1306 state->r.in.logon = r->in.logon;
1307 state->r.in.validation_level = r->in.validation_level;
1308 state->r.in.flags = r->in.flags;
1309 state->r.out.validation = r->out.validation;
1310 state->r.out.authoritative = r->out.authoritative;
1311 state->r.out.flags = r->out.flags;
1313 state->_r.lslex = r;
1315 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1316 if (!NT_STATUS_IS_OK(nt_status)) {
1320 nt_status = schannel_get_creds_state(mem_ctx,
1321 dce_call->conn->dce_ctx->lp_ctx,
1322 r->in.computer_name, &state->creds);
1323 if (!NT_STATUS_IS_OK(nt_status)) {
1327 dcesrv_call_auth_info(dce_call, &auth_type, NULL);
1329 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1330 return NT_STATUS_ACCESS_DENIED;
1333 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1335 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1343 netr_LogonSamLogonWithFlags
1346 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1347 struct netr_LogonSamLogonWithFlags *r)
1349 struct dcesrv_netr_LogonSamLogon_base_state *state;
1352 *r->out.authoritative = 1;
1354 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1355 if (state == NULL) {
1356 return NT_STATUS_NO_MEMORY;
1359 state->dce_call = dce_call;
1360 state->mem_ctx = mem_ctx;
1362 state->r.in.server_name = r->in.server_name;
1363 state->r.in.computer_name = r->in.computer_name;
1364 state->r.in.logon_level = r->in.logon_level;
1365 state->r.in.logon = r->in.logon;
1366 state->r.in.validation_level = r->in.validation_level;
1367 state->r.in.flags = r->in.flags;
1368 state->r.out.validation = r->out.validation;
1369 state->r.out.authoritative = r->out.authoritative;
1370 state->r.out.flags = r->out.flags;
1372 state->_r.lslwf = r;
1374 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1375 if (!NT_STATUS_IS_OK(nt_status)) {
1379 r->out.return_authenticator = talloc_zero(mem_ctx,
1380 struct netr_Authenticator);
1381 if (r->out.return_authenticator == NULL) {
1382 return NT_STATUS_NO_MEMORY;
1385 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1387 r->in.computer_name,
1389 r->out.return_authenticator,
1391 if (!NT_STATUS_IS_OK(nt_status)) {
1395 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1397 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1407 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1408 struct netr_LogonSamLogon *r)
1410 struct dcesrv_netr_LogonSamLogon_base_state *state;
1413 *r->out.authoritative = 1;
1415 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1416 if (state == NULL) {
1417 return NT_STATUS_NO_MEMORY;
1420 state->dce_call = dce_call;
1421 state->mem_ctx = mem_ctx;
1423 state->r.in.server_name = r->in.server_name;
1424 state->r.in.computer_name = r->in.computer_name;
1425 state->r.in.logon_level = r->in.logon_level;
1426 state->r.in.logon = r->in.logon;
1427 state->r.in.validation_level = r->in.validation_level;
1428 state->r.in.flags = &state->_ignored_flags;
1429 state->r.out.validation = r->out.validation;
1430 state->r.out.authoritative = r->out.authoritative;
1431 state->r.out.flags = &state->_ignored_flags;
1435 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1436 if (!NT_STATUS_IS_OK(nt_status)) {
1440 r->out.return_authenticator = talloc_zero(mem_ctx,
1441 struct netr_Authenticator);
1442 if (r->out.return_authenticator == NULL) {
1443 return NT_STATUS_NO_MEMORY;
1446 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1448 r->in.computer_name,
1450 r->out.return_authenticator,
1452 if (!NT_STATUS_IS_OK(nt_status)) {
1456 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1458 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1469 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1470 struct netr_LogonSamLogoff *r)
1472 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1480 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1481 struct netr_DatabaseDeltas *r)
1483 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1490 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1491 struct netr_DatabaseSync2 *r)
1493 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1494 return NT_STATUS_NOT_IMPLEMENTED;
1501 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1502 struct netr_DatabaseSync *r)
1504 struct netr_DatabaseSync2 r2;
1509 r2.in.logon_server = r->in.logon_server;
1510 r2.in.computername = r->in.computername;
1511 r2.in.credential = r->in.credential;
1512 r2.in.database_id = r->in.database_id;
1513 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1514 r2.in.sync_context = r->in.sync_context;
1515 r2.out.sync_context = r->out.sync_context;
1516 r2.out.delta_enum_array = r->out.delta_enum_array;
1517 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1519 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1528 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1529 struct netr_AccountDeltas *r)
1531 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1532 return NT_STATUS_NOT_IMPLEMENTED;
1539 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1540 struct netr_AccountSync *r)
1542 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1543 return NT_STATUS_NOT_IMPLEMENTED;
1550 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1551 struct netr_GetDcName *r)
1553 struct auth_session_info *session_info =
1554 dcesrv_call_session_info(dce_call);
1555 const char * const attrs[] = { NULL };
1556 struct ldb_context *sam_ctx;
1557 struct ldb_message **res;
1558 struct ldb_dn *domain_dn;
1563 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1564 * that the domainname needs to be a valid netbios domain
1565 * name, if it is not NULL.
1567 if (r->in.domainname) {
1568 const char *dot = strchr(r->in.domainname, '.');
1569 size_t len = strlen(r->in.domainname);
1571 if (dot || len > 15) {
1572 return WERR_NERR_DCNOTFOUND;
1576 * TODO: Should we also varify that only valid
1577 * netbios name characters are used?
1581 sam_ctx = samdb_connect(mem_ctx,
1582 dce_call->event_ctx,
1583 dce_call->conn->dce_ctx->lp_ctx,
1585 dce_call->conn->remote_address,
1587 if (sam_ctx == NULL) {
1588 return WERR_DS_UNAVAILABLE;
1591 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1593 if (domain_dn == NULL) {
1594 return WERR_NO_SUCH_DOMAIN;
1597 ret = gendb_search_dn(sam_ctx, mem_ctx,
1598 domain_dn, &res, attrs);
1600 return WERR_NO_SUCH_DOMAIN;
1603 /* TODO: - return real IP address
1604 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1606 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1607 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1608 W_ERROR_HAVE_NO_MEMORY(dcname);
1610 *r->out.dcname = dcname;
1614 struct dcesrv_netr_LogonControl_base_state {
1615 struct dcesrv_call_state *dce_call;
1617 TALLOC_CTX *mem_ctx;
1619 struct netr_LogonControl2Ex r;
1622 struct netr_LogonControl *l;
1623 struct netr_LogonControl2 *l2;
1624 struct netr_LogonControl2Ex *l2ex;
1628 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1630 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1632 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1633 struct auth_session_info *session_info =
1634 dcesrv_call_session_info(state->dce_call);
1635 enum security_user_level security_level;
1636 struct dcerpc_binding_handle *irpc_handle;
1637 struct tevent_req *subreq;
1640 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1642 if (state->_r.l != NULL) {
1646 if (state->r.in.level == 0x00000002) {
1647 return WERR_NOT_SUPPORTED;
1648 } else if (state->r.in.level != 0x00000001) {
1649 return WERR_INVALID_LEVEL;
1652 switch (state->r.in.function_code) {
1653 case NETLOGON_CONTROL_QUERY:
1654 case NETLOGON_CONTROL_REPLICATE:
1655 case NETLOGON_CONTROL_SYNCHRONIZE:
1656 case NETLOGON_CONTROL_PDC_REPLICATE:
1657 case NETLOGON_CONTROL_BREAKPOINT:
1658 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1659 case NETLOGON_CONTROL_TRUNCATE_LOG:
1662 return WERR_NOT_SUPPORTED;
1666 if (state->r.in.level < 0x00000001) {
1667 return WERR_INVALID_LEVEL;
1670 if (state->r.in.level > 0x00000004) {
1671 return WERR_INVALID_LEVEL;
1674 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1675 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1676 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1678 switch (state->r.in.level) {
1680 info1 = talloc_zero(state->mem_ctx,
1681 struct netr_NETLOGON_INFO_1);
1682 if (info1 == NULL) {
1683 return WERR_NOT_ENOUGH_MEMORY;
1685 state->r.out.query->info1 = info1;
1689 info3 = talloc_zero(state->mem_ctx,
1690 struct netr_NETLOGON_INFO_3);
1691 if (info3 == NULL) {
1692 return WERR_NOT_ENOUGH_MEMORY;
1694 state->r.out.query->info3 = info3;
1698 return WERR_INVALID_PARAMETER;
1703 * Some validations are done before the access check
1704 * and some after the access check
1706 security_level = security_session_user_level(session_info, NULL);
1707 if (security_level < SECURITY_ADMINISTRATOR) {
1708 return WERR_ACCESS_DENIED;
1711 if (state->_r.l2 != NULL) {
1713 * netr_LogonControl2
1715 if (state->r.in.level == 0x00000004) {
1716 return WERR_INVALID_LEVEL;
1720 switch (state->r.in.level) {
1725 switch (state->r.in.function_code) {
1726 case NETLOGON_CONTROL_REDISCOVER:
1727 case NETLOGON_CONTROL_TC_QUERY:
1728 case NETLOGON_CONTROL_TC_VERIFY:
1731 return WERR_INVALID_PARAMETER;
1740 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1741 return WERR_INVALID_PARAMETER;
1747 return WERR_INVALID_LEVEL;
1750 switch (state->r.in.function_code) {
1751 case NETLOGON_CONTROL_REDISCOVER:
1752 case NETLOGON_CONTROL_TC_QUERY:
1753 case NETLOGON_CONTROL_TC_VERIFY:
1754 if (state->r.in.level != 2) {
1755 return WERR_INVALID_PARAMETER;
1758 if (state->r.in.data == NULL) {
1759 return WERR_INVALID_PARAMETER;
1762 if (state->r.in.data->domain == NULL) {
1763 return WERR_INVALID_PARAMETER;
1768 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1769 if (state->r.in.level != 1) {
1770 return WERR_INVALID_PARAMETER;
1773 if (state->r.in.data == NULL) {
1774 return WERR_INVALID_PARAMETER;
1777 if (state->r.in.data->domain == NULL) {
1778 return WERR_INVALID_PARAMETER;
1781 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1782 state->r.in.data->domain);
1784 struct ldb_context *sam_ctx;
1786 sam_ctx = samdb_connect(
1788 state->dce_call->event_ctx,
1790 system_session(lp_ctx),
1791 state->dce_call->conn->remote_address,
1793 if (sam_ctx == NULL) {
1794 return WERR_DS_UNAVAILABLE;
1798 * Secrets for trusted domains can only be triggered on
1801 ok = samdb_is_pdc(sam_ctx);
1802 TALLOC_FREE(sam_ctx);
1804 return WERR_INVALID_DOMAIN_ROLE;
1810 return WERR_NOT_SUPPORTED;
1813 irpc_handle = irpc_binding_handle_by_name(state,
1814 state->dce_call->msg_ctx,
1816 &ndr_table_winbind);
1817 if (irpc_handle == NULL) {
1818 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1819 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1820 return WERR_SERVICE_NOT_FOUND;
1824 * 60 seconds timeout should be enough
1826 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1828 subreq = dcerpc_winbind_LogonControl_send(state,
1829 state->dce_call->event_ctx,
1831 state->r.in.function_code,
1834 state->r.out.query);
1835 if (subreq == NULL) {
1836 return WERR_NOT_ENOUGH_MEMORY;
1838 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1839 tevent_req_set_callback(subreq,
1840 dcesrv_netr_LogonControl_base_done,
1846 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1848 struct dcesrv_netr_LogonControl_base_state *state =
1849 tevent_req_callback_data(subreq,
1850 struct dcesrv_netr_LogonControl_base_state);
1853 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1854 &state->r.out.result);
1855 TALLOC_FREE(subreq);
1856 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1857 state->r.out.result = WERR_TIMEOUT;
1858 } else if (!NT_STATUS_IS_OK(status)) {
1859 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1860 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1861 nt_errstr(status)));
1864 if (state->_r.l2ex != NULL) {
1865 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1866 r->out.result = state->r.out.result;
1867 } else if (state->_r.l2 != NULL) {
1868 struct netr_LogonControl2 *r = state->_r.l2;
1869 r->out.result = state->r.out.result;
1870 } else if (state->_r.l != NULL) {
1871 struct netr_LogonControl *r = state->_r.l;
1872 r->out.result = state->r.out.result;
1875 status = dcesrv_reply(state->dce_call);
1876 if (!NT_STATUS_IS_OK(status)) {
1877 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1884 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1885 struct netr_LogonControl *r)
1887 struct dcesrv_netr_LogonControl_base_state *state;
1890 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1891 if (state == NULL) {
1892 return WERR_NOT_ENOUGH_MEMORY;
1895 state->dce_call = dce_call;
1896 state->mem_ctx = mem_ctx;
1898 state->r.in.logon_server = r->in.logon_server;
1899 state->r.in.function_code = r->in.function_code;
1900 state->r.in.level = r->in.level;
1901 state->r.in.data = NULL;
1902 state->r.out.query = r->out.query;
1906 werr = dcesrv_netr_LogonControl_base_call(state);
1908 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1918 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1919 struct netr_LogonControl2 *r)
1921 struct dcesrv_netr_LogonControl_base_state *state;
1924 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1925 if (state == NULL) {
1926 return WERR_NOT_ENOUGH_MEMORY;
1929 state->dce_call = dce_call;
1930 state->mem_ctx = mem_ctx;
1932 state->r.in.logon_server = r->in.logon_server;
1933 state->r.in.function_code = r->in.function_code;
1934 state->r.in.level = r->in.level;
1935 state->r.in.data = r->in.data;
1936 state->r.out.query = r->out.query;
1940 werr = dcesrv_netr_LogonControl_base_call(state);
1942 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1950 netr_LogonControl2Ex
1952 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1953 struct netr_LogonControl2Ex *r)
1955 struct dcesrv_netr_LogonControl_base_state *state;
1958 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1959 if (state == NULL) {
1960 return WERR_NOT_ENOUGH_MEMORY;
1963 state->dce_call = dce_call;
1964 state->mem_ctx = mem_ctx;
1969 werr = dcesrv_netr_LogonControl_base_call(state);
1971 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1978 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1979 struct ldb_context *sam_ctx,
1980 struct netr_DomainTrustList *trusts,
1981 uint32_t trust_flags);
1986 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1987 struct netr_GetAnyDCName *r)
1989 struct auth_session_info *session_info =
1990 dcesrv_call_session_info(dce_call);
1991 struct netr_DomainTrustList *trusts;
1992 struct ldb_context *sam_ctx;
1993 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1997 *r->out.dcname = NULL;
1999 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2000 /* if the domainname parameter wasn't set assume our domain */
2001 r->in.domainname = lpcfg_workgroup(lp_ctx);
2004 sam_ctx = samdb_connect(mem_ctx,
2005 dce_call->event_ctx,
2008 dce_call->conn->remote_address,
2010 if (sam_ctx == NULL) {
2011 return WERR_DS_UNAVAILABLE;
2014 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2015 /* well we asked for a DC of our own domain */
2016 if (samdb_is_pdc(sam_ctx)) {
2017 /* we are the PDC of the specified domain */
2018 return WERR_NO_SUCH_DOMAIN;
2021 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2022 lpcfg_netbios_name(lp_ctx));
2023 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2028 /* Okay, now we have to consider the trusted domains */
2030 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2031 W_ERROR_HAVE_NO_MEMORY(trusts);
2035 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2036 NETR_TRUST_FLAG_INBOUND
2037 | NETR_TRUST_FLAG_OUTBOUND);
2038 W_ERROR_NOT_OK_RETURN(werr);
2040 for (i = 0; i < trusts->count; i++) {
2041 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2042 /* FIXME: Here we need to find a DC for the specified
2043 * trusted domain. */
2045 /* return WERR_OK; */
2046 return WERR_NO_SUCH_DOMAIN;
2050 return WERR_NO_SUCH_DOMAIN;
2057 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2058 struct netr_DatabaseRedo *r)
2060 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2065 netr_NetrEnumerateTrustedDomains
2067 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2068 struct netr_NetrEnumerateTrustedDomains *r)
2070 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2075 netr_LogonGetCapabilities
2077 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2078 struct netr_LogonGetCapabilities *r)
2080 struct netlogon_creds_CredentialState *creds;
2083 status = dcesrv_netr_creds_server_step_check(dce_call,
2085 r->in.computer_name,
2087 r->out.return_authenticator,
2089 if (!NT_STATUS_IS_OK(status)) {
2090 DEBUG(0,(__location__ " Bad credentials - error\n"));
2092 NT_STATUS_NOT_OK_RETURN(status);
2094 if (r->in.query_level != 1) {
2095 return NT_STATUS_NOT_SUPPORTED;
2098 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2100 return NT_STATUS_OK;
2105 netr_NETRLOGONSETSERVICEBITS
2107 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2108 struct netr_NETRLOGONSETSERVICEBITS *r)
2110 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2115 netr_LogonGetTrustRid
2117 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2118 struct netr_LogonGetTrustRid *r)
2120 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2125 netr_NETRLOGONCOMPUTESERVERDIGEST
2127 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2128 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2130 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2135 netr_NETRLOGONCOMPUTECLIENTDIGEST
2137 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2138 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2140 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2148 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2149 struct netr_DsRGetSiteName *r)
2151 struct auth_session_info *session_info =
2152 dcesrv_call_session_info(dce_call);
2153 struct ldb_context *sam_ctx;
2154 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2156 sam_ctx = samdb_connect(mem_ctx,
2157 dce_call->event_ctx,
2160 dce_call->conn->remote_address,
2162 if (sam_ctx == NULL) {
2163 return WERR_DS_UNAVAILABLE;
2167 * We assume to be a DC when we get called over NETLOGON. Hence we
2168 * get our site name always by using "samdb_server_site_name()"
2169 * and not "samdb_client_site_name()".
2171 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2172 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2179 fill in a netr_OneDomainInfo from our own domain/forest
2181 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2182 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2183 struct GUID domain_guid,
2184 struct netr_OneDomainInfo *info,
2189 if (is_trust_list) {
2190 struct netr_trust_extension *tei = NULL;
2192 /* w2k8 only fills this on trusted domains */
2193 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2195 return NT_STATUS_NO_MEMORY;
2197 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2200 * We're always within a native forest
2202 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2203 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2205 /* For now we assume we're always the tree root */
2206 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2207 tei->parent_index = 0;
2209 tei->trust_type = our_tdo->trust_type;
2211 * This needs to be 0 instead of our_tdo->trust_attributes
2212 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2213 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2215 tei->trust_attributes = 0;
2217 info->trust_extension.info = tei;
2218 info->trust_extension.length = 16;
2221 if (is_trust_list) {
2222 info->dns_domainname.string = our_tdo->domain_name.string;
2224 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2225 info->dns_forestname.string = NULL;
2227 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2228 our_tdo->domain_name.string);
2229 if (info->dns_domainname.string == NULL) {
2230 return NT_STATUS_NO_MEMORY;
2233 info->dns_forestname.string = info->dns_domainname.string;
2236 info->domainname.string = our_tdo->netbios_name.string;
2237 info->domain_sid = our_tdo->sid;
2238 info->domain_guid = domain_guid;
2240 return NT_STATUS_OK;
2244 fill in a netr_OneDomainInfo from a trust tdo
2246 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2247 struct GUID domain_guid,
2248 const struct lsa_TrustDomainInfoInfoEx *tdo,
2249 struct netr_OneDomainInfo *info)
2251 struct netr_trust_extension *tei = NULL;
2255 /* w2k8 only fills this on trusted domains */
2256 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2258 return NT_STATUS_NO_MEMORY;
2261 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2262 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2264 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2265 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2267 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2268 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2272 * TODO: once we support multiple domains within our forest,
2273 * we need to fill this correct (or let the caller do it
2274 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2276 tei->parent_index = 0;
2278 tei->trust_type = tdo->trust_type;
2279 tei->trust_attributes = tdo->trust_attributes;
2281 info->trust_extension.info = tei;
2282 info->trust_extension.length = 16;
2284 info->domainname.string = tdo->netbios_name.string;
2285 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2286 info->dns_domainname.string = tdo->domain_name.string;
2288 info->dns_domainname.string = NULL;
2290 info->domain_sid = tdo->sid;
2291 info->domain_guid = domain_guid;
2293 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2294 info->dns_forestname.string = NULL;
2296 return NT_STATUS_OK;
2300 netr_LogonGetDomainInfo
2301 this is called as part of the ADS domain logon procedure.
2303 It has an important role in convaying details about the client, such
2304 as Operating System, Version, Service Pack etc.
2306 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2307 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2309 struct netlogon_creds_CredentialState *creds;
2310 const char * const trusts_attrs[] = {
2311 "securityIdentifier",
2319 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2320 "msDS-SupportedEncryptionTypes", NULL };
2321 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
2322 struct ldb_context *sam_ctx;
2323 const struct GUID *our_domain_guid = NULL;
2324 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2325 struct ldb_message **res1, *new_msg;
2326 struct ldb_result *trusts_res = NULL;
2327 struct ldb_dn *workstation_dn;
2328 struct netr_DomainInformation *domain_info;
2329 struct netr_LsaPolicyInformation *lsa_policy_info;
2330 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2331 bool update_dns_hostname = true;
2335 status = dcesrv_netr_creds_server_step_check(dce_call,
2337 r->in.computer_name,
2339 r->out.return_authenticator,
2341 if (!NT_STATUS_IS_OK(status)) {
2343 char* remote = NULL;
2344 TALLOC_CTX *frame = talloc_stackframe();
2345 remote = tsocket_address_string(dce_call->conn->remote_address,
2347 local = tsocket_address_string(dce_call->conn->local_address,
2349 DBG_ERR(("Bad credentials - "
2350 "computer[%s] remote[%s] local[%s]\n"),
2351 log_escape(frame, r->in.computer_name),
2356 NT_STATUS_NOT_OK_RETURN(status);
2358 sam_ctx = samdb_connect(mem_ctx,
2359 dce_call->event_ctx,
2360 dce_call->conn->dce_ctx->lp_ctx,
2361 system_session(dce_call->conn->dce_ctx->lp_ctx),
2362 dce_call->conn->remote_address,
2364 if (sam_ctx == NULL) {
2365 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2368 switch (r->in.level) {
2369 case 1: /* Domain information */
2371 if (r->in.query->workstation_info == NULL) {
2372 return NT_STATUS_INVALID_PARAMETER;
2375 /* Prepares the workstation DN */
2376 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2377 dom_sid_string(mem_ctx, creds->sid));
2378 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2380 /* Lookup for attributes in workstation object */
2381 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2384 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2387 /* Gets the sam account name which is checked against the DNS
2388 * hostname parameter. */
2389 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2392 if (sam_account_name == NULL) {
2393 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2397 * Checks that the sam account name without a possible "$"
2398 * matches as prefix with the DNS hostname in the workstation
2401 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2402 strcspn(sam_account_name, "$"));
2403 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2404 if (r->in.query->workstation_info->dns_hostname != NULL) {
2405 prefix2 = talloc_strndup(mem_ctx,
2406 r->in.query->workstation_info->dns_hostname,
2407 strcspn(r->in.query->workstation_info->dns_hostname, "."));
2408 NT_STATUS_HAVE_NO_MEMORY(prefix2);
2410 if (strcasecmp(prefix1, prefix2) != 0) {
2411 update_dns_hostname = false;
2414 update_dns_hostname = false;
2417 /* Gets the old DNS hostname */
2418 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2423 * Updates the DNS hostname when the client wishes that the
2424 * server should handle this for him
2425 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2426 * obviously only checked when we do already have a
2428 * See MS-NRPC section 3.5.4.3.9
2430 if ((old_dns_hostname != NULL) &&
2431 (r->in.query->workstation_info->workstation_flags
2432 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2433 update_dns_hostname = false;
2436 /* Gets host information and put them into our directory */
2438 new_msg = ldb_msg_new(mem_ctx);
2439 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2441 new_msg->dn = workstation_dn;
2443 /* Sets the OS name */
2445 if (r->in.query->workstation_info->os_name.string == NULL) {
2446 return NT_STATUS_INVALID_PARAMETER;
2449 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2450 r->in.query->workstation_info->os_name.string);
2451 if (ret != LDB_SUCCESS) {
2452 return NT_STATUS_NO_MEMORY;
2456 * Sets information from "os_version". On an empty structure
2457 * the values are cleared.
2459 if (r->in.query->workstation_info->os_version.os != NULL) {
2460 struct netr_OsVersionInfoEx *os_version;
2461 const char *os_version_str;
2463 os_version = &r->in.query->workstation_info->os_version.os->os;
2465 if (os_version->CSDVersion == NULL) {
2466 return NT_STATUS_INVALID_PARAMETER;
2469 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2470 os_version->MajorVersion,
2471 os_version->MinorVersion,
2472 os_version->BuildNumber);
2473 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2475 ret = ldb_msg_add_string(new_msg,
2476 "operatingSystemServicePack",
2477 os_version->CSDVersion);
2478 if (ret != LDB_SUCCESS) {
2479 return NT_STATUS_NO_MEMORY;
2482 ret = ldb_msg_add_string(new_msg,
2483 "operatingSystemVersion",
2485 if (ret != LDB_SUCCESS) {
2486 return NT_STATUS_NO_MEMORY;
2489 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2490 "operatingSystemServicePack");
2491 if (ret != LDB_SUCCESS) {
2492 return NT_STATUS_NO_MEMORY;
2495 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2496 "operatingSystemVersion");
2497 if (ret != LDB_SUCCESS) {
2498 return NT_STATUS_NO_MEMORY;
2503 * If the boolean "update_dns_hostname" remained true, then we
2504 * are fine to start the update.
2506 if (update_dns_hostname) {
2507 ret = ldb_msg_add_string(new_msg,
2509 r->in.query->workstation_info->dns_hostname);
2510 if (ret != LDB_SUCCESS) {
2511 return NT_STATUS_NO_MEMORY;
2514 /* This manual "servicePrincipalName" generation is
2515 * still needed! Since the update in the samldb LDB
2516 * module does only work if the entries already exist
2517 * which isn't always the case. */
2518 ret = ldb_msg_add_string(new_msg,
2519 "servicePrincipalName",
2520 talloc_asprintf(new_msg, "HOST/%s",
2521 r->in.computer_name));
2522 if (ret != LDB_SUCCESS) {
2523 return NT_STATUS_NO_MEMORY;
2526 ret = ldb_msg_add_string(new_msg,
2527 "servicePrincipalName",
2528 talloc_asprintf(new_msg, "HOST/%s",
2529 r->in.query->workstation_info->dns_hostname));
2530 if (ret != LDB_SUCCESS) {
2531 return NT_STATUS_NO_MEMORY;
2535 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2536 DEBUG(3,("Impossible to update samdb: %s\n",
2537 ldb_errstring(sam_ctx)));
2540 talloc_free(new_msg);
2542 /* Writes back the domain information */
2544 our_domain_guid = samdb_domain_guid(sam_ctx);
2545 if (our_domain_guid == NULL) {
2546 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2549 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2550 if (!NT_STATUS_IS_OK(status)) {
2554 status = dsdb_trust_search_tdos(sam_ctx,
2559 if (!NT_STATUS_IS_OK(status)) {
2563 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2564 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2566 ZERO_STRUCTP(domain_info);
2568 /* Informations about the local and trusted domains */
2570 status = fill_our_one_domain_info(mem_ctx,
2573 &domain_info->primary_domain,
2575 if (!NT_STATUS_IS_OK(status)) {
2579 domain_info->trusted_domain_count = trusts_res->count + 1;
2580 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2581 struct netr_OneDomainInfo,
2582 domain_info->trusted_domain_count);
2583 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2585 for (i=0; i < trusts_res->count; i++) {
2586 struct netr_OneDomainInfo *o =
2587 &domain_info->trusted_domains[i];
2588 /* we can't know the guid of trusts outside our forest */
2589 struct GUID trust_domain_guid = GUID_zero();
2590 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2592 status = dsdb_trust_parse_tdo_info(mem_ctx,
2593 trusts_res->msgs[i],
2595 if (!NT_STATUS_IS_OK(status)) {
2599 status = fill_trust_one_domain_info(mem_ctx,
2603 if (!NT_STATUS_IS_OK(status)) {
2608 status = fill_our_one_domain_info(mem_ctx,
2611 &domain_info->trusted_domains[i],
2613 if (!NT_STATUS_IS_OK(status)) {
2617 /* Sets the supported encryption types */
2618 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2619 "msDS-SupportedEncryptionTypes",
2620 default_supported_enc_types);
2622 /* Other host domain information */
2624 lsa_policy_info = talloc(mem_ctx,
2625 struct netr_LsaPolicyInformation);
2626 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2627 ZERO_STRUCTP(lsa_policy_info);
2629 domain_info->lsa_policy = *lsa_policy_info;
2631 /* The DNS hostname is only returned back when there is a chance
2633 if ((r->in.query->workstation_info->workstation_flags
2634 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2635 domain_info->dns_hostname.string = old_dns_hostname;
2637 domain_info->dns_hostname.string = NULL;
2640 domain_info->workstation_flags =
2641 r->in.query->workstation_info->workstation_flags & (
2642 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2644 r->out.info->domain_info = domain_info;
2646 case 2: /* LSA policy information - not used at the moment */
2647 lsa_policy_info = talloc(mem_ctx,
2648 struct netr_LsaPolicyInformation);
2649 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2650 ZERO_STRUCTP(lsa_policy_info);
2652 r->out.info->lsa_policy_info = lsa_policy_info;
2655 return NT_STATUS_INVALID_LEVEL;
2659 return NT_STATUS_OK;
2664 netr_ServerPasswordGet
2666 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2667 struct netr_ServerPasswordGet *r)
2669 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2672 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2673 TALLOC_CTX *mem_ctx,
2674 struct dom_sid *user_sid,
2675 struct ldb_dn *obj_dn)
2677 const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
2678 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2679 struct ldb_dn *rodc_dn;
2681 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2682 const struct dom_sid *additional_sids[] = { NULL, NULL };
2684 struct dom_sid *object_sid;
2685 const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
2687 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2688 dom_sid_string(mem_ctx, user_sid));
2689 if (!ldb_dn_validate(rodc_dn)) goto denied;
2691 /* do the two searches we need */
2692 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2693 DSDB_SEARCH_SHOW_EXTENDED_DN);
2694 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2696 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2697 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2699 object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
2701 additional_sids[0] = object_sid;
2703 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2704 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
2705 if (!W_ERROR_IS_OK(werr)) {
2709 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2710 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
2711 if (!W_ERROR_IS_OK(werr)) {
2716 * The SID list needs to include itself as well as the tokenGroups.
2718 * TODO determine if sIDHistory is required for this check
2720 werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
2721 mem_ctx, "tokenGroups", &token_sids,
2722 additional_sids, 1);
2723 if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
2727 if (never_reveal_sids &&
2728 sid_list_match(token_sids, never_reveal_sids)) {
2733 sid_list_match(token_sids, reveal_sids)) {
2745 netr_NetrLogonSendToSam
2747 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2748 struct netr_NetrLogonSendToSam *r)
2750 struct netlogon_creds_CredentialState *creds;
2751 struct ldb_context *sam_ctx;
2753 DATA_BLOB decrypted_blob;
2754 enum ndr_err_code ndr_err;
2755 struct netr_SendToSamBase base_msg = { 0 };
2757 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2759 r->in.computer_name,
2761 r->out.return_authenticator,
2764 NT_STATUS_NOT_OK_RETURN(nt_status);
2766 switch (creds->secure_channel_type) {
2770 case SEC_CHAN_WKSTA:
2771 case SEC_CHAN_DNS_DOMAIN:
2772 case SEC_CHAN_DOMAIN:
2774 return NT_STATUS_INVALID_PARAMETER;
2776 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
2777 creds->secure_channel_type));
2778 return NT_STATUS_INVALID_PARAMETER;
2781 sam_ctx = samdb_connect(mem_ctx,
2782 dce_call->event_ctx,
2783 dce_call->conn->dce_ctx->lp_ctx,
2784 system_session(dce_call->conn->dce_ctx->lp_ctx),
2785 dce_call->conn->remote_address,
2787 if (sam_ctx == NULL) {
2788 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2791 /* Buffer is meant to be 16-bit aligned */
2792 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2793 netlogon_creds_aes_decrypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2795 netlogon_creds_arcfour_crypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2798 decrypted_blob.data = r->in.opaque_buffer;
2799 decrypted_blob.length = r->in.buffer_len;
2801 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
2802 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
2804 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2805 /* We only partially implement SendToSam */
2806 return NT_STATUS_NOT_IMPLEMENTED;
2809 /* Now 'send' to SAM */
2810 switch (base_msg.message_type) {
2811 case SendToSamResetBadPasswordCount:
2813 struct ldb_message *msg = ldb_msg_new(mem_ctx);
2814 struct ldb_dn *dn = NULL;
2818 ret = ldb_transaction_start(sam_ctx);
2819 if (ret != LDB_SUCCESS) {
2820 return NT_STATUS_INTERNAL_ERROR;
2823 ret = dsdb_find_dn_by_guid(sam_ctx,
2825 &base_msg.message.reset_bad_password.guid,
2828 if (ret != LDB_SUCCESS) {
2829 ldb_transaction_cancel(sam_ctx);
2830 return NT_STATUS_INVALID_PARAMETER;
2833 if (creds->secure_channel_type == SEC_CHAN_RODC &&
2834 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
2835 DEBUG(1, ("Client asked to reset bad password on "
2836 "an arbitrary user: %s\n",
2837 ldb_dn_get_linearized(dn)));
2838 ldb_transaction_cancel(sam_ctx);
2839 return NT_STATUS_INVALID_PARAMETER;
2844 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
2845 if (ret != LDB_SUCCESS) {
2846 ldb_transaction_cancel(sam_ctx);
2847 return NT_STATUS_INVALID_PARAMETER;
2850 ret = dsdb_replace(sam_ctx, msg, 0);
2851 if (ret != LDB_SUCCESS) {
2852 ldb_transaction_cancel(sam_ctx);
2853 return NT_STATUS_INVALID_PARAMETER;
2856 ret = ldb_transaction_commit(sam_ctx);
2857 if (ret != LDB_SUCCESS) {
2858 ldb_transaction_cancel(sam_ctx);
2859 return NT_STATUS_INTERNAL_ERROR;
2865 return NT_STATUS_NOT_IMPLEMENTED;
2868 return NT_STATUS_OK;
2871 struct dcesrv_netr_DsRGetDCName_base_state {
2872 struct dcesrv_call_state *dce_call;
2873 TALLOC_CTX *mem_ctx;
2875 struct netr_DsRGetDCNameEx2 r;
2876 const char *client_site;
2879 struct netr_DsRGetDCName *dc;
2880 struct netr_DsRGetDCNameEx *dcex;
2881 struct netr_DsRGetDCNameEx2 *dcex2;
2885 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
2887 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
2889 struct dcesrv_call_state *dce_call = state->dce_call;
2890 struct auth_session_info *session_info =
2891 dcesrv_call_session_info(dce_call);
2892 TALLOC_CTX *mem_ctx = state->mem_ctx;
2893 struct netr_DsRGetDCNameEx2 *r = &state->r;
2894 struct ldb_context *sam_ctx;
2895 struct netr_DsRGetDCNameInfo *info;
2896 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2897 const struct tsocket_address *local_address;
2898 char *local_addr = NULL;
2899 const struct tsocket_address *remote_address;
2900 char *remote_addr = NULL;
2901 const char *server_site_name;
2903 struct netlogon_samlogon_response response;
2905 const char *dc_name = NULL;
2906 const char *domain_name = NULL;
2908 bool different_domain = true;
2910 ZERO_STRUCTP(r->out.info);
2912 sam_ctx = samdb_connect(state,
2913 dce_call->event_ctx,
2916 dce_call->conn->remote_address,
2918 if (sam_ctx == NULL) {
2919 return WERR_DS_UNAVAILABLE;
2922 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2923 if (tsocket_address_is_inet(local_address, "ip")) {
2924 local_addr = tsocket_address_inet_addr_string(local_address, state);
2925 W_ERROR_HAVE_NO_MEMORY(local_addr);
2928 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2929 if (tsocket_address_is_inet(remote_address, "ip")) {
2930 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
2931 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2934 /* "server_unc" is ignored by w2k3 */
2936 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2937 return WERR_INVALID_FLAGS;
2940 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2941 r->in.flags & DS_PDC_REQUIRED &&
2942 r->in.flags & DS_KDC_REQUIRED) {
2943 return WERR_INVALID_FLAGS;
2945 if (r->in.flags & DS_IS_FLAT_NAME &&
2946 r->in.flags & DS_IS_DNS_NAME) {
2947 return WERR_INVALID_FLAGS;
2949 if (r->in.flags & DS_RETURN_DNS_NAME &&
2950 r->in.flags & DS_RETURN_FLAT_NAME) {
2951 return WERR_INVALID_FLAGS;
2953 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2954 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2955 return WERR_INVALID_FLAGS;
2958 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2960 (DS_DIRECTORY_SERVICE_REQUIRED |
2961 DS_DIRECTORY_SERVICE_PREFERRED |
2962 DS_GC_SERVER_REQUIRED |
2965 return WERR_INVALID_FLAGS;
2968 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2970 return WERR_INVALID_FLAGS;
2974 * If we send an all-zero GUID, we should ignore it as winbind actually
2975 * checks it with a DNS query. Windows also appears to ignore it.
2977 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
2978 r->in.domain_guid = NULL;
2981 /* Attempt winbind search only if we suspect the domain is incorrect */
2982 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
2983 if (r->in.flags & DS_IS_FLAT_NAME) {
2984 if (strcasecmp_m(r->in.domain_name,
2985 lpcfg_sam_name(lp_ctx)) == 0) {
2986 different_domain = false;
2988 } else if (r->in.flags & DS_IS_DNS_NAME) {
2989 if (strcasecmp_m(r->in.domain_name,
2990 lpcfg_dnsdomain(lp_ctx)) == 0) {
2991 different_domain = false;
2994 if (strcasecmp_m(r->in.domain_name,
2995 lpcfg_sam_name(lp_ctx)) == 0 ||
2996 strcasecmp_m(r->in.domain_name,
2997 lpcfg_dnsdomain(lp_ctx)) == 0) {
2998 different_domain = false;
3003 * We need to be able to handle empty domain names, where we
3004 * revert to our domain by default.
3006 different_domain = false;
3009 /* Proof server site parameter "site_name" if it was specified */
3010 server_site_name = samdb_server_site_name(sam_ctx, state);
3011 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3012 if (different_domain || (r->in.site_name != NULL &&
3013 (strcasecmp_m(r->in.site_name,
3014 server_site_name) != 0))) {
3016 struct dcerpc_binding_handle *irpc_handle = NULL;
3017 struct tevent_req *subreq = NULL;
3020 * Retrieve the client site to override the winbind response.
3022 * DO NOT use Windows fallback for client site.
3023 * In the case of multiple domains, this is plainly wrong.
3025 * Note: It's possible that the client may belong to multiple
3026 * subnets across domains. It's not clear what this would mean,
3027 * but here we only return what this domain knows.
3029 state->client_site = samdb_client_site_name(sam_ctx,
3035 irpc_handle = irpc_binding_handle_by_name(state,
3038 &ndr_table_winbind);
3039 if (irpc_handle == NULL) {
3040 DEBUG(0,("Failed to get binding_handle for "
3041 "winbind_server task\n"));
3042 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3043 return WERR_SERVICE_NOT_FOUND;
3046 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3048 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3050 subreq = dcerpc_wbint_DsGetDcName_send(state,
3051 dce_call->event_ctx,
3058 if (subreq == NULL) {
3059 return WERR_NOT_ENOUGH_MEMORY;
3062 tevent_req_set_callback(subreq,
3063 dcesrv_netr_DsRGetDCName_base_done,
3069 guid_str = r->in.domain_guid != NULL ?
3070 GUID_string(state, r->in.domain_guid) : NULL;
3072 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3076 r->in.client_account,
3077 r->in.mask, remote_addr,
3078 NETLOGON_NT_VERSION_5EX_WITH_IP,
3079 lp_ctx, &response, true);
3080 if (!NT_STATUS_IS_OK(status)) {
3081 return ntstatus_to_werror(status);
3085 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3086 * (O) flag when the returned forest name is in DNS format. This is here
3087 * always the case (see below).
3089 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3091 if (r->in.flags & DS_RETURN_DNS_NAME) {
3092 dc_name = response.data.nt5_ex.pdc_dns_name;
3093 domain_name = response.data.nt5_ex.dns_domain;
3095 * According to MS-NRPC 2.2.1.2.1 we should set the
3096 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3097 * the returned information is in DNS form.
3099 response.data.nt5_ex.server_type |=
3100 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3101 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3102 dc_name = response.data.nt5_ex.pdc_name;
3103 domain_name = response.data.nt5_ex.domain_name;
3107 * TODO: autodetect what we need to return
3108 * based on the given arguments
3110 dc_name = response.data.nt5_ex.pdc_name;
3111 domain_name = response.data.nt5_ex.domain_name;
3114 if (!dc_name || !dc_name[0]) {
3115 return WERR_NO_SUCH_DOMAIN;
3118 if (!domain_name || !domain_name[0]) {
3119 return WERR_NO_SUCH_DOMAIN;
3122 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3123 W_ERROR_HAVE_NO_MEMORY(info);
3124 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3125 dc_name[0] != '\\'? "\\\\":"",
3126 talloc_strdup(mem_ctx, dc_name));
3127 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3129 pdc_ip = local_addr;
3130 if (pdc_ip == NULL) {
3131 pdc_ip = "127.0.0.1";
3133 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3134 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3135 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3136 info->domain_guid = response.data.nt5_ex.domain_uuid;
3137 info->domain_name = domain_name;
3138 info->forest_name = response.data.nt5_ex.forest;
3139 info->dc_flags = response.data.nt5_ex.server_type;
3140 if (r->in.flags & DS_RETURN_DNS_NAME) {
3141 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3142 * returned if we are returning info->dc_unc containing a FQDN.
3143 * This attribute is called DomainControllerName in the specs,
3144 * it seems that we decide to return FQDN or netbios depending on
3145 * DS_RETURN_DNS_NAME.
3147 info->dc_flags |= DS_DNS_CONTROLLER;
3149 info->dc_site_name = response.data.nt5_ex.server_site;
3150 info->client_site_name = response.data.nt5_ex.client_site;
3152 *r->out.info = info;
3157 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3159 struct dcesrv_netr_DsRGetDCName_base_state *state =
3160 tevent_req_callback_data(subreq,
3161 struct dcesrv_netr_DsRGetDCName_base_state);
3162 struct dcesrv_call_state *dce_call = state->dce_call;
3163 NTSTATUS result, status;
3165 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3168 TALLOC_FREE(subreq);
3170 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3171 state->r.out.result = WERR_TIMEOUT;
3175 if (!NT_STATUS_IS_OK(status)) {
3176 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3178 state->r.out.result = WERR_GEN_FAILURE;
3182 if (!NT_STATUS_IS_OK(result)) {
3183 DBG_NOTICE("DC location via winbind failed - %s\n",
3185 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3189 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3190 DBG_ERR("DC location via winbind returned no results\n");
3191 state->r.out.result = WERR_GEN_FAILURE;
3195 if (state->r.out.info[0]->dc_unc == NULL) {
3196 DBG_ERR("DC location via winbind returned no DC unc\n");
3197 state->r.out.result = WERR_GEN_FAILURE;
3202 * Either the supplied site name is NULL (possibly via
3203 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3204 * the input match name.
3206 * TODO: Currently this means that requests with NETBIOS domain
3207 * names can fail because they do not return the site name.
3209 if (state->r.in.site_name == NULL ||
3210 strcasecmp_m("", state->r.in.site_name) == 0 ||
3211 (state->r.out.info[0]->dc_site_name != NULL &&
3212 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3213 state->r.in.site_name) == 0)) {
3215 state->r.out.info[0]->client_site_name =
3216 talloc_move(state->mem_ctx, &state->client_site);
3219 * Make sure to return our DC UNC with // prefix.
3220 * Winbind currently doesn't send the leading slashes
3223 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3224 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3225 const char *dc_unc = NULL;
3227 dc_unc = talloc_asprintf(state->mem_ctx,
3229 state->r.out.info[0]->dc_unc);
3230 state->r.out.info[0]->dc_unc = dc_unc;
3233 state->r.out.result = WERR_OK;
3235 state->r.out.info = NULL;
3236 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3240 if (state->_r.dcex2 != NULL) {
3241 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3242 r->out.result = state->r.out.result;
3243 } else if (state->_r.dcex != NULL) {
3244 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3245 r->out.result = state->r.out.result;
3246 } else if (state->_r.dc != NULL) {
3247 struct netr_DsRGetDCName *r = state->_r.dc;
3248 r->out.result = state->r.out.result;
3252 status = dcesrv_reply(dce_call);
3253 if (!NT_STATUS_IS_OK(status)) {
3254 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3255 nt_errstr(status)));
3260 netr_DsRGetDCNameEx2
3262 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3263 TALLOC_CTX *mem_ctx,
3264 struct netr_DsRGetDCNameEx2 *r)
3266 struct dcesrv_netr_DsRGetDCName_base_state *state;
3268 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3269 if (state == NULL) {
3270 return WERR_NOT_ENOUGH_MEMORY;
3273 state->dce_call = dce_call;
3274 state->mem_ctx = mem_ctx;
3277 state->_r.dcex2 = r;
3279 return dcesrv_netr_DsRGetDCName_base_call(state);
3285 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3286 struct netr_DsRGetDCNameEx *r)
3288 struct dcesrv_netr_DsRGetDCName_base_state *state;
3290 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3291 if (state == NULL) {
3292 return WERR_NOT_ENOUGH_MEMORY;
3295 state->dce_call = dce_call;
3296 state->mem_ctx = mem_ctx;
3298 state->r.in.server_unc = r->in.server_unc;
3299 state->r.in.client_account = NULL;
3300 state->r.in.mask = 0;
3301 state->r.in.domain_guid = r->in.domain_guid;
3302 state->r.in.domain_name = r->in.domain_name;
3303 state->r.in.site_name = r->in.site_name;
3304 state->r.in.flags = r->in.flags;
3305 state->r.out.info = r->out.info;
3309 return dcesrv_netr_DsRGetDCName_base_call(state);
3315 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3316 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3317 * insists that it be ignored.
3319 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3320 struct netr_DsRGetDCName *r)
3322 struct dcesrv_netr_DsRGetDCName_base_state *state;
3324 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3325 if (state == NULL) {
3326 return WERR_NOT_ENOUGH_MEMORY;
3329 state->dce_call = dce_call;
3330 state->mem_ctx = mem_ctx;
3332 state->r.in.server_unc = r->in.server_unc;
3333 state->r.in.client_account = NULL;
3334 state->r.in.mask = 0;
3335 state->r.in.domain_name = r->in.domain_name;
3336 state->r.in.domain_guid = r->in.domain_guid;
3338 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3339 state->r.in.flags = r->in.flags;
3340 state->r.out.info = r->out.info;
3344 return dcesrv_netr_DsRGetDCName_base_call(state);
3347 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3349 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3350 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3352 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3357 netr_NetrEnumerateTrustedDomainsEx
3359 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3360 struct netr_NetrEnumerateTrustedDomainsEx *r)
3362 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3367 netr_DsRAddressToSitenamesExW
3369 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3370 struct netr_DsRAddressToSitenamesExW *r)
3372 struct auth_session_info *session_info =
3373 dcesrv_call_session_info(dce_call);
3374 struct ldb_context *sam_ctx;
3375 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3376 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3377 sa_family_t sin_family;
3378 struct sockaddr_in *addr;
3380 struct sockaddr_in6 *addr6;
3381 char addr_str[INET6_ADDRSTRLEN];
3383 char addr_str[INET_ADDRSTRLEN];
3389 sam_ctx = samdb_connect(mem_ctx,
3390 dce_call->event_ctx,
3393 dce_call->conn->remote_address,
3395 if (sam_ctx == NULL) {
3396 return WERR_DS_UNAVAILABLE;
3399 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3400 W_ERROR_HAVE_NO_MEMORY(ctr);
3404 ctr->count = r->in.count;
3405 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3406 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3407 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3408 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3410 for (i=0; i<ctr->count; i++) {
3411 ctr->sitename[i].string = NULL;
3412 ctr->subnetname[i].string = NULL;
3414 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3417 /* The first two byte of the buffer are reserved for the
3418 * "sin_family" but for now only the first one is used. */
3419 sin_family = r->in.addresses[i].buffer[0];
3421 switch (sin_family) {
3423 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3426 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3427 res = inet_ntop(AF_INET, &addr->sin_addr,
3428 addr_str, sizeof(addr_str));
3432 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3435 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3436 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3437 addr_str, sizeof(addr_str));
3448 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3453 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3454 ctr->subnetname[i].string = subnet_name;
3462 netr_DsRAddressToSitenamesW
3464 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3465 struct netr_DsRAddressToSitenamesW *r)
3467 struct netr_DsRAddressToSitenamesExW r2;
3468 struct netr_DsRAddressToSitenamesWCtr *ctr;
3474 r2.in.server_name = r->in.server_name;
3475 r2.in.count = r->in.count;
3476 r2.in.addresses = r->in.addresses;
3478 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3479 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3481 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3482 W_ERROR_HAVE_NO_MEMORY(ctr);
3486 ctr->count = r->in.count;
3487 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3488 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3490 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3492 for (i=0; i<ctr->count; i++) {
3493 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3501 netr_DsrGetDcSiteCoverageW
3503 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3504 struct netr_DsrGetDcSiteCoverageW *r)
3506 struct auth_session_info *session_info =
3507 dcesrv_call_session_info(dce_call);
3508 struct ldb_context *sam_ctx;
3509 struct DcSitesCtr *ctr;
3510 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3512 sam_ctx = samdb_connect(mem_ctx,
3513 dce_call->event_ctx,
3516 dce_call->conn->remote_address,
3518 if (sam_ctx == NULL) {
3519 return WERR_DS_UNAVAILABLE;
3522 ctr = talloc(mem_ctx, struct DcSitesCtr);
3523 W_ERROR_HAVE_NO_MEMORY(ctr);
3527 /* For now only return our default site */
3529 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3530 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3531 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3532 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3538 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3539 struct ldb_context *sam_ctx,
3540 struct netr_DomainTrustList *trusts,
3541 uint32_t trust_flags)
3543 struct ldb_dn *system_dn;
3544 struct ldb_message **dom_res = NULL;
3545 const char *trust_attrs[] = { "flatname", "trustPartner",
3546 "securityIdentifier", "trustDirection",
3547 "trustType", "trustAttributes", NULL };
3552 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3553 NETR_TRUST_FLAG_OUTBOUND))) {
3554 return WERR_INVALID_FLAGS;
3557 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3558 ldb_get_default_basedn(sam_ctx),
3559 "(&(objectClass=container)(cn=System))");
3561 return WERR_GEN_FAILURE;
3564 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3565 &dom_res, trust_attrs,
3566 "(objectclass=trustedDomain)");
3568 for (i = 0; i < ret; i++) {
3569 unsigned int trust_dir;
3572 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3573 "trustDirection", 0);
3575 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3576 flags |= NETR_TRUST_FLAG_INBOUND;
3578 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3579 flags |= NETR_TRUST_FLAG_OUTBOUND;
3582 if (!(flags & trust_flags)) {
3583 /* this trust direction was not requested */
3588 trusts->array = talloc_realloc(trusts, trusts->array,
3589 struct netr_DomainTrust,
3591 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3593 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3594 if (!trusts->array[n].netbios_name) {
3595 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3596 "without flatname\n",
3597 ldb_dn_get_linearized(dom_res[i]->dn)));
3600 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3602 trusts->array[n].trust_flags = flags;
3603 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3604 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3605 /* TODO: find if we have parent in the list */
3606 trusts->array[n].parent_index = 0;
3609 trusts->array[n].trust_type =
3610 ldb_msg_find_attr_as_uint(dom_res[i],
3612 trusts->array[n].trust_attributes =
3613 ldb_msg_find_attr_as_uint(dom_res[i],
3614 "trustAttributes", 0);
3616 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3617 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3618 struct dom_sid zero_sid;
3619 ZERO_STRUCT(zero_sid);
3620 trusts->array[n].sid =
3621 dom_sid_dup(trusts, &zero_sid);
3623 trusts->array[n].sid =
3624 samdb_result_dom_sid(trusts, dom_res[i],
3625 "securityIdentifier");
3627 trusts->array[n].guid = GUID_zero();
3629 trusts->count = n + 1;
3632 talloc_free(dom_res);
3637 netr_DsrEnumerateDomainTrusts
3639 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3640 TALLOC_CTX *mem_ctx,
3641 struct netr_DsrEnumerateDomainTrusts *r)
3643 struct auth_session_info *session_info =
3644 dcesrv_call_session_info(dce_call);
3645 struct netr_DomainTrustList *trusts;
3646 struct ldb_context *sam_ctx;
3648 struct ldb_message **dom_res;
3649 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3650 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3651 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3655 if (r->in.trust_flags & 0xFFFFFE00) {
3656 return WERR_INVALID_FLAGS;
3659 /* TODO: turn to hard check once we are sure this is 100% correct */
3660 if (!r->in.server_name) {
3661 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3662 "But received NULL!\n", dnsdomain));
3664 p = strchr(r->in.server_name, '.');
3666 DEBUG(3, ("Invalid domain! Expected name in domain "
3667 "[%s]. But received [%s]!\n",
3668 dnsdomain, r->in.server_name));
3669 p = r->in.server_name;
3673 if (strcasecmp(p, dnsdomain)) {
3674 DEBUG(3, ("Invalid domain! Expected name in domain "
3675 "[%s]. But received [%s]!\n",
3676 dnsdomain, r->in.server_name));
3680 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3681 W_ERROR_HAVE_NO_MEMORY(trusts);
3684 r->out.trusts = trusts;
3686 sam_ctx = samdb_connect(mem_ctx,
3687 dce_call->event_ctx,
3690 dce_call->conn->remote_address,
3692 if (sam_ctx == NULL) {
3693 return WERR_GEN_FAILURE;
3696 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3697 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3699 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3700 trusts, r->in.trust_flags);
3701 W_ERROR_NOT_OK_RETURN(werr);
3704 /* NOTE: we currently are always the root of the forest */
3705 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3706 uint32_t n = trusts->count;
3708 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3709 &dom_res, dom_attrs);
3711 return WERR_GEN_FAILURE;
3714 trusts->count = n + 1;
3715 trusts->array = talloc_realloc(trusts, trusts->array,
3716 struct netr_DomainTrust,
3718 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3720 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3721 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3722 trusts->array[n].trust_flags =
3723 NETR_TRUST_FLAG_NATIVE |
3724 NETR_TRUST_FLAG_TREEROOT |
3725 NETR_TRUST_FLAG_IN_FOREST |
3726 NETR_TRUST_FLAG_PRIMARY;
3727 /* we are always the root domain for now */
3728 trusts->array[n].parent_index = 0;
3729 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3730 trusts->array[n].trust_attributes = 0;
3731 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3734 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3736 talloc_free(dom_res);
3744 netr_DsrDeregisterDNSHostRecords
3746 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3747 struct netr_DsrDeregisterDNSHostRecords *r)
3749 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3753 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3754 struct netr_ServerGetTrustInfo *r);
3757 netr_ServerTrustPasswordsGet
3759 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3760 struct netr_ServerTrustPasswordsGet *r)
3762 struct netr_ServerGetTrustInfo r2 = {};
3763 struct netr_TrustInfo *_ti = NULL;
3766 r2.in.server_name = r->in.server_name;
3767 r2.in.account_name = r->in.account_name;
3768 r2.in.secure_channel_type = r->in.secure_channel_type;
3769 r2.in.computer_name = r->in.computer_name;
3770 r2.in.credential = r->in.credential;
3772 r2.out.return_authenticator = r->out.return_authenticator;
3773 r2.out.new_owf_password = r->out.new_owf_password;
3774 r2.out.old_owf_password = r->out.old_owf_password;
3775 r2.out.trust_info = &_ti;
3777 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3779 r->out.return_authenticator = r2.out.return_authenticator;
3780 r->out.new_owf_password = r2.out.new_owf_password;
3781 r->out.old_owf_password = r2.out.old_owf_password;
3787 netr_DsRGetForestTrustInformation
3789 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3790 struct dcesrv_call_state *dce_call;
3791 TALLOC_CTX *mem_ctx;
3792 struct netr_DsRGetForestTrustInformation *r;
3795 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3797 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3798 TALLOC_CTX *mem_ctx,
3799 struct netr_DsRGetForestTrustInformation *r)
3801 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3802 struct auth_session_info *session_info =
3803 dcesrv_call_session_info(dce_call);
3804 enum security_user_level security_level;
3805 struct ldb_context *sam_ctx = NULL;
3806 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3807 struct dcerpc_binding_handle *irpc_handle = NULL;
3808 struct tevent_req *subreq = NULL;
3809 struct ldb_dn *domain_dn = NULL;
3810 struct ldb_dn *forest_dn = NULL;
3814 security_level = security_session_user_level(session_info, NULL);
3815 if (security_level < SECURITY_USER) {
3816 return WERR_ACCESS_DENIED;
3819 if (r->in.flags & 0xFFFFFFFE) {
3820 return WERR_INVALID_FLAGS;
3823 sam_ctx = samdb_connect(mem_ctx,
3824 dce_call->event_ctx,
3827 dce_call->conn->remote_address,
3829 if (sam_ctx == NULL) {
3830 return WERR_GEN_FAILURE;
3833 domain_dn = ldb_get_default_basedn(sam_ctx);
3834 if (domain_dn == NULL) {
3835 return WERR_GEN_FAILURE;
3838 forest_dn = ldb_get_root_basedn(sam_ctx);
3839 if (forest_dn == NULL) {
3840 return WERR_GEN_FAILURE;
3843 cmp = ldb_dn_compare(domain_dn, forest_dn);
3845 return WERR_NERR_ACFNOTLOADED;
3848 forest_level = dsdb_forest_functional_level(sam_ctx);
3849 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3850 return WERR_INVALID_FUNCTION;
3853 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3854 if (!samdb_is_pdc(sam_ctx)) {
3855 return WERR_NERR_NOTPRIMARY;
3858 if (r->in.trusted_domain_name == NULL) {
3859 return WERR_INVALID_FLAGS;
3863 if (r->in.trusted_domain_name == NULL) {
3867 * information about our own domain
3869 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3870 r->out.forest_trust_info);
3871 if (!NT_STATUS_IS_OK(status)) {
3872 return ntstatus_to_werror(status);
3879 * Forward the request to winbindd
3882 state = talloc_zero(mem_ctx,
3883 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3884 if (state == NULL) {
3885 return WERR_NOT_ENOUGH_MEMORY;
3887 state->dce_call = dce_call;
3888 state->mem_ctx = mem_ctx;
3891 irpc_handle = irpc_binding_handle_by_name(state,
3892 state->dce_call->msg_ctx,
3894 &ndr_table_winbind);
3895 if (irpc_handle == NULL) {
3896 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3897 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3898 return WERR_SERVICE_NOT_FOUND;
3902 * 60 seconds timeout should be enough
3904 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3906 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3907 state->dce_call->event_ctx,
3909 r->in.trusted_domain_name,
3911 r->out.forest_trust_info);
3912 if (subreq == NULL) {
3913 return WERR_NOT_ENOUGH_MEMORY;
3915 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3916 tevent_req_set_callback(subreq,
3917 dcesrv_netr_DsRGetForestTrustInformation_done,
3923 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3925 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3926 tevent_req_callback_data(subreq,
3927 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3930 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3932 &state->r->out.result);
3933 TALLOC_FREE(subreq);
3934 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3935 state->r->out.result = WERR_TIMEOUT;
3936 } else if (!NT_STATUS_IS_OK(status)) {
3937 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3938 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3939 nt_errstr(status)));
3942 status = dcesrv_reply(state->dce_call);
3943 if (!NT_STATUS_IS_OK(status)) {
3944 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3949 netr_GetForestTrustInformation
3951 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3952 TALLOC_CTX *mem_ctx,
3953 struct netr_GetForestTrustInformation *r)
3955 struct auth_session_info *session_info =
3956 dcesrv_call_session_info(dce_call);
3957 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3958 struct netlogon_creds_CredentialState *creds = NULL;
3959 struct ldb_context *sam_ctx = NULL;
3960 struct ldb_dn *domain_dn = NULL;
3961 struct ldb_dn *forest_dn = NULL;
3966 status = dcesrv_netr_creds_server_step_check(dce_call,
3968 r->in.computer_name,
3970 r->out.return_authenticator,
3972 if (!NT_STATUS_IS_OK(status)) {
3976 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3977 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3978 return NT_STATUS_NOT_IMPLEMENTED;
3981 sam_ctx = samdb_connect(mem_ctx,
3982 dce_call->event_ctx,
3985 dce_call->conn->remote_address,
3987 if (sam_ctx == NULL) {
3988 return NT_STATUS_INTERNAL_ERROR;
3991 /* TODO: check r->in.server_name is our name */
3993 domain_dn = ldb_get_default_basedn(sam_ctx);
3994 if (domain_dn == NULL) {
3995 return NT_STATUS_INTERNAL_ERROR;
3998 forest_dn = ldb_get_root_basedn(sam_ctx);
3999 if (forest_dn == NULL) {
4000 return NT_STATUS_INTERNAL_ERROR;
4003 cmp = ldb_dn_compare(domain_dn, forest_dn);
4005 return NT_STATUS_INVALID_DOMAIN_STATE;
4008 forest_level = dsdb_forest_functional_level(sam_ctx);
4009 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4010 return NT_STATUS_INVALID_DOMAIN_STATE;
4013 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4014 r->out.forest_trust_info);
4015 if (!NT_STATUS_IS_OK(status)) {
4019 return NT_STATUS_OK;
4024 netr_ServerGetTrustInfo
4026 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4027 struct netr_ServerGetTrustInfo *r)
4029 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4030 struct netlogon_creds_CredentialState *creds = NULL;
4031 struct ldb_context *sam_ctx = NULL;
4032 const char * const attrs[] = {
4035 "userAccountControl",
4038 struct ldb_message **res = NULL;
4039 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4042 const char *asid = NULL;
4044 const char *aname = NULL;
4045 struct ldb_message *tdo_msg = NULL;
4046 const char * const tdo_attrs[] = {
4047 "trustAuthIncoming",
4051 struct netr_TrustInfo *trust_info = NULL;
4053 ZERO_STRUCTP(r->out.new_owf_password);
4054 ZERO_STRUCTP(r->out.old_owf_password);
4056 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4058 r->in.computer_name,
4060 r->out.return_authenticator,
4062 if (!NT_STATUS_IS_OK(nt_status)) {
4066 /* TODO: check r->in.server_name is our name */
4068 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4069 return NT_STATUS_INVALID_PARAMETER;
4072 if (r->in.secure_channel_type != creds->secure_channel_type) {
4073 return NT_STATUS_INVALID_PARAMETER;
4076 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4077 return NT_STATUS_INVALID_PARAMETER;
4080 sam_ctx = samdb_connect(mem_ctx,
4081 dce_call->event_ctx,
4083 system_session(lp_ctx),
4084 dce_call->conn->remote_address,
4086 if (sam_ctx == NULL) {
4087 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4090 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4092 return NT_STATUS_NO_MEMORY;
4095 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4096 "(&(objectClass=user)(objectSid=%s))",
4099 return NT_STATUS_ACCOUNT_DISABLED;
4102 switch (creds->secure_channel_type) {
4103 case SEC_CHAN_DNS_DOMAIN:
4104 case SEC_CHAN_DOMAIN:
4105 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4107 if (uac & UF_ACCOUNTDISABLE) {
4108 return NT_STATUS_ACCOUNT_DISABLED;
4111 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4112 return NT_STATUS_ACCOUNT_DISABLED;
4115 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4116 if (aname == NULL) {
4117 return NT_STATUS_ACCOUNT_DISABLED;
4120 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4121 SEC_CHAN_DOMAIN, aname,
4122 tdo_attrs, mem_ctx, &tdo_msg);
4123 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4124 return NT_STATUS_ACCOUNT_DISABLED;
4126 if (!NT_STATUS_IS_OK(nt_status)) {
4130 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4133 if (!NT_STATUS_IS_OK(nt_status)) {
4137 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4138 if (trust_info == NULL) {
4139 return NT_STATUS_NO_MEMORY;
4142 trust_info->count = 1;
4143 trust_info->data = talloc_array(trust_info, uint32_t,
4145 if (trust_info->data == NULL) {
4146 return NT_STATUS_NO_MEMORY;
4149 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4155 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4158 if (!NT_STATUS_IS_OK(nt_status)) {
4162 prevNtHash = talloc(mem_ctx, struct samr_Password);
4163 if (prevNtHash == NULL) {
4164 return NT_STATUS_NO_MEMORY;
4167 E_md4hash("", prevNtHash->hash);
4171 if (curNtHash != NULL) {
4172 *r->out.new_owf_password = *curNtHash;
4173 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4175 if (prevNtHash != NULL) {
4176 *r->out.old_owf_password = *prevNtHash;
4177 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4180 if (trust_info != NULL) {
4181 *r->out.trust_info = trust_info;
4184 return NT_STATUS_OK;
4190 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4191 struct netr_Unused47 *r)
4193 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4197 struct netr_dnsupdate_RODC_state {
4198 struct dcesrv_call_state *dce_call;
4199 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4200 struct dnsupdate_RODC *r2;
4204 called when the forwarded RODC dns update request is finished
4206 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4208 struct netr_dnsupdate_RODC_state *st =
4209 tevent_req_callback_data(subreq,
4210 struct netr_dnsupdate_RODC_state);
4213 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4214 TALLOC_FREE(subreq);
4215 if (!NT_STATUS_IS_OK(status)) {
4216 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4217 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4220 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4222 status = dcesrv_reply(st->dce_call);
4223 if (!NT_STATUS_IS_OK(status)) {
4224 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4229 netr_DsrUpdateReadOnlyServerDnsRecords
4231 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4232 TALLOC_CTX *mem_ctx,
4233 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4235 struct netlogon_creds_CredentialState *creds;
4237 struct dcerpc_binding_handle *binding_handle;
4238 struct netr_dnsupdate_RODC_state *st;
4239 struct tevent_req *subreq;
4241 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4243 r->in.computer_name,
4245 r->out.return_authenticator,
4247 NT_STATUS_NOT_OK_RETURN(nt_status);
4249 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4250 return NT_STATUS_ACCESS_DENIED;
4253 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4254 NT_STATUS_HAVE_NO_MEMORY(st);
4256 st->dce_call = dce_call;
4258 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4259 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4261 st->r2->in.dom_sid = creds->sid;
4262 st->r2->in.site_name = r->in.site_name;
4263 st->r2->in.dns_ttl = r->in.dns_ttl;
4264 st->r2->in.dns_names = r->in.dns_names;
4265 st->r2->out.dns_names = r->out.dns_names;
4267 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
4268 "dnsupdate", &ndr_table_irpc);
4269 if (binding_handle == NULL) {
4270 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4271 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4272 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4275 /* forward the call */
4276 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4277 binding_handle, st->r2);
4278 NT_STATUS_HAVE_NO_MEMORY(subreq);
4280 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4282 /* setup the callback */
4283 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4285 return NT_STATUS_OK;
4289 /* include the generated boilerplate */
4290 #include "librpc/gen_ndr/ndr_netlogon_s.c"