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 #define NETLOGON_SERVER_PIPE_STATE_MAGIC 0x4f555358
67 struct netlogon_server_pipe_state {
68 struct netr_Credential client_challenge;
69 struct netr_Credential server_challenge;
72 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
73 struct netr_ServerReqChallenge *r)
75 struct netlogon_server_pipe_state *pipe_state = NULL;
78 ZERO_STRUCTP(r->out.return_credentials);
80 pipe_state = dcesrv_iface_state_find_conn(dce_call,
81 NETLOGON_SERVER_PIPE_STATE_MAGIC,
82 struct netlogon_server_pipe_state);
83 TALLOC_FREE(pipe_state);
85 pipe_state = talloc_zero(dce_call,
86 struct netlogon_server_pipe_state);
87 if (pipe_state == NULL) {
88 return NT_STATUS_NO_MEMORY;
91 pipe_state->client_challenge = *r->in.credentials;
93 generate_random_buffer(pipe_state->server_challenge.data,
94 sizeof(pipe_state->server_challenge.data));
96 *r->out.return_credentials = pipe_state->server_challenge;
98 ntstatus = dcesrv_iface_state_store_conn(dce_call,
99 NETLOGON_SERVER_PIPE_STATE_MAGIC,
101 if (!NT_STATUS_IS_OK(ntstatus)) {
105 ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
106 &pipe_state->client_challenge,
107 &pipe_state->server_challenge,
108 r->in.computer_name);
109 if (!NT_STATUS_IS_OK(ntstatus)) {
110 TALLOC_FREE(pipe_state);
118 * Do the actual processing of a netr_ServerAuthenticate3 message.
119 * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
121 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
122 struct dcesrv_call_state *dce_call,
124 struct netr_ServerAuthenticate3 *r,
125 const char **trust_account_for_search,
126 const char **trust_account_in_db,
127 struct dom_sid **sid)
129 struct netlogon_server_pipe_state *pipe_state = NULL;
130 bool challenge_valid = false;
131 struct netlogon_server_pipe_state challenge;
132 struct netlogon_creds_CredentialState *creds;
133 struct ldb_context *sam_ctx;
134 struct samr_Password *curNtHash = NULL;
135 struct samr_Password *prevNtHash = NULL;
136 uint32_t user_account_control;
138 struct ldb_message **msgs;
140 const char *attrs[] = {"unicodePwd", "userAccountControl",
141 "objectSid", "samAccountName", NULL};
142 uint32_t server_flags = 0;
143 uint32_t negotiate_flags = 0;
144 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
145 bool reject_des_client = !allow_nt4_crypto;
146 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
147 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
148 bool reject_none_rpc = (schannel == true);
150 ZERO_STRUCTP(r->out.return_credentials);
153 pipe_state = dcesrv_iface_state_find_conn(dce_call,
154 NETLOGON_SERVER_PIPE_STATE_MAGIC,
155 struct netlogon_server_pipe_state);
156 if (pipe_state != NULL) {
158 * If we had a challenge remembered on the connection
159 * consider this for usage. This can't be cleanup
162 * This is the default code path for typical clients
163 * which call netr_ServerReqChallenge() and
164 * netr_ServerAuthenticate3() on the same dcerpc connection.
166 challenge = *pipe_state;
168 challenge_valid = true;
174 * Fallback and try to get the challenge from
177 * If too many clients are using this code path,
178 * they may destroy their cache entries as the
179 * TDB has a fixed size limited via a lossy hash
181 * The TDB used is the schannel store, which is
182 * initialised at startup.
184 * NOTE: The challenge is deleted from the DB as soon as it is
185 * fetched, to prevent reuse.
189 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
190 &challenge.client_challenge,
191 &challenge.server_challenge,
192 r->in.computer_name);
194 if (!NT_STATUS_IS_OK(ntstatus)) {
195 ZERO_STRUCT(challenge);
197 challenge_valid = true;
201 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
202 NETLOGON_NEG_PERSISTENT_SAMREPL |
203 NETLOGON_NEG_ARCFOUR |
204 NETLOGON_NEG_PROMOTION_COUNT |
205 NETLOGON_NEG_CHANGELOG_BDC |
206 NETLOGON_NEG_FULL_SYNC_REPL |
207 NETLOGON_NEG_MULTIPLE_SIDS |
209 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
210 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
211 NETLOGON_NEG_GENERIC_PASSTHROUGH |
212 NETLOGON_NEG_CONCURRENT_RPC |
213 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
214 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
215 NETLOGON_NEG_STRONG_KEYS |
216 NETLOGON_NEG_TRANSITIVE_TRUSTS |
217 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
218 NETLOGON_NEG_PASSWORD_SET2 |
219 NETLOGON_NEG_GETDOMAININFO |
220 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
221 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
222 NETLOGON_NEG_RODC_PASSTHROUGH |
223 NETLOGON_NEG_SUPPORTS_AES |
224 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
225 NETLOGON_NEG_AUTHENTICATED_RPC;
227 negotiate_flags = *r->in.negotiate_flags & server_flags;
229 if (negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
230 reject_none_rpc = false;
233 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
234 reject_des_client = false;
237 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
238 reject_des_client = false;
239 reject_md5_client = false;
242 if (reject_des_client || reject_md5_client) {
244 * Here we match Windows 2012 and return no flags.
246 *r->out.negotiate_flags = 0;
247 return NT_STATUS_DOWNGRADE_DETECTED;
251 * This talloc_free is important to prevent re-use of the
252 * challenge. We have to delay it this far due to NETApp
254 * https://bugzilla.samba.org/show_bug.cgi?id=11291
256 TALLOC_FREE(pipe_state);
259 * At this point we must also cleanup the TDB cache
260 * entry, if we fail the client needs to call
261 * netr_ServerReqChallenge again.
263 * Note: this handles a non existing record just fine,
264 * the r->in.computer_name might not be the one used
265 * in netr_ServerReqChallenge(), but we are trying to
266 * just tidy up the normal case to prevent re-use.
268 schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
269 r->in.computer_name);
272 * According to Microsoft (see bugid #6099)
273 * Windows 7 looks at the negotiate_flags
274 * returned in this structure *even if the
275 * call fails with access denied!
277 *r->out.negotiate_flags = negotiate_flags;
279 if (reject_none_rpc) {
280 /* schannel must be used, but client did not offer it. */
281 DEBUG(0,("%s: schannel required but client failed "
282 "to offer it. Client was %s\n",
284 log_escape(mem_ctx, r->in.account_name)));
285 return NT_STATUS_ACCESS_DENIED;
288 switch (r->in.secure_channel_type) {
290 case SEC_CHAN_DNS_DOMAIN:
291 case SEC_CHAN_DOMAIN:
296 return NT_STATUS_INVALID_PARAMETER;
298 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
299 r->in.secure_channel_type));
300 return NT_STATUS_INVALID_PARAMETER;
303 sam_ctx = samdb_connect(mem_ctx,
305 dce_call->conn->dce_ctx->lp_ctx,
306 system_session(dce_call->conn->dce_ctx->lp_ctx),
307 dce_call->conn->remote_address,
309 if (sam_ctx == NULL) {
310 return NT_STATUS_INVALID_SYSTEM_SERVICE;
313 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
314 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
316 struct ldb_message *tdo_msg = NULL;
317 const char * const tdo_attrs[] = {
323 char *encoded_name = NULL;
325 const char *flatname = NULL;
327 bool require_trailer = true;
328 const char *netbios = NULL;
329 const char *dns = NULL;
331 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
333 require_trailer = false;
336 encoded_name = ldb_binary_encode_string(mem_ctx,
338 if (encoded_name == NULL) {
339 return NT_STATUS_NO_MEMORY;
342 len = strlen(encoded_name);
344 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
347 if (require_trailer && encoded_name[len - 1] != trailer) {
348 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
350 encoded_name[len - 1] = '\0';
352 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
355 netbios = encoded_name;
358 nt_status = dsdb_trust_search_tdo(sam_ctx,
360 tdo_attrs, mem_ctx, &tdo_msg);
361 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
362 DEBUG(2, ("Client asked for a trusted domain secure channel, "
363 "but there's no tdo for [%s] => [%s] \n",
364 log_escape(mem_ctx, r->in.account_name),
366 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
368 if (!NT_STATUS_IS_OK(nt_status)) {
372 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
375 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
376 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
378 if (!NT_STATUS_IS_OK(nt_status)) {
382 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
383 if (flatname == NULL) {
384 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
387 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
388 if (*trust_account_for_search == NULL) {
389 return NT_STATUS_NO_MEMORY;
392 *trust_account_for_search = r->in.account_name;
395 /* pull the user attributes */
396 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
397 "(&(sAMAccountName=%s)(objectclass=user))",
398 ldb_binary_encode_string(mem_ctx,
399 *trust_account_for_search));
401 if (num_records == 0) {
402 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
403 log_escape(mem_ctx, r->in.account_name)));
404 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
407 if (num_records > 1) {
408 DEBUG(0,("Found %d records matching user [%s]\n",
410 log_escape(mem_ctx, r->in.account_name)));
411 return NT_STATUS_INTERNAL_DB_CORRUPTION;
414 *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
417 if (*trust_account_in_db == NULL) {
418 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
419 r->in.account_name));
420 return NT_STATUS_INTERNAL_DB_CORRUPTION;
423 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
425 if (user_account_control & UF_ACCOUNTDISABLE) {
426 DEBUG(1, ("Account [%s] is disabled\n",
427 log_escape(mem_ctx, r->in.account_name)));
428 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
431 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
432 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
433 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
434 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
436 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
437 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
438 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
439 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
441 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
443 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
444 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
445 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
446 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
448 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
449 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
450 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
451 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
454 /* we should never reach this */
455 return NT_STATUS_INTERNAL_ERROR;
458 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
459 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
460 dce_call->conn->dce_ctx->lp_ctx,
461 msgs[0], NULL, &curNtHash);
462 if (!NT_STATUS_IS_OK(nt_status)) {
463 return NT_STATUS_ACCESS_DENIED;
467 if (curNtHash == NULL) {
468 return NT_STATUS_ACCESS_DENIED;
471 if (!challenge_valid) {
472 DEBUG(1, ("No challenge requested by client [%s/%s], "
473 "cannot authenticate\n",
474 log_escape(mem_ctx, r->in.computer_name),
475 log_escape(mem_ctx, r->in.account_name)));
476 return NT_STATUS_ACCESS_DENIED;
479 creds = netlogon_creds_server_init(mem_ctx,
482 r->in.secure_channel_type,
483 &challenge.client_challenge,
484 &challenge.server_challenge,
487 r->out.return_credentials,
489 if (creds == NULL && prevNtHash != NULL) {
491 * We fallback to the previous password for domain trusts.
493 * Note that lpcfg_old_password_allowed_period() doesn't
496 creds = netlogon_creds_server_init(mem_ctx,
499 r->in.secure_channel_type,
500 &challenge.client_challenge,
501 &challenge.server_challenge,
504 r->out.return_credentials,
509 return NT_STATUS_ACCESS_DENIED;
511 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
512 *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
514 nt_status = schannel_save_creds_state(mem_ctx,
515 dce_call->conn->dce_ctx->lp_ctx,
517 if (!NT_STATUS_IS_OK(nt_status)) {
518 ZERO_STRUCTP(r->out.return_credentials);
522 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
529 * Log a netr_ServerAuthenticate3 request, and then invoke
530 * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
532 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
533 struct dcesrv_call_state *dce_call,
535 struct netr_ServerAuthenticate3 *r)
538 struct dom_sid *sid = NULL;
539 const char *trust_account_for_search = NULL;
540 const char *trust_account_in_db = NULL;
541 struct auth_usersupplied_info ui = {
542 .local_host = dce_call->conn->local_address,
543 .remote_host = dce_call->conn->remote_address,
545 .account_name = r->in.account_name,
546 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
548 .service_description = "NETLOGON",
549 .auth_description = "ServerAuthenticate",
550 .netlogon_trust_account = {
551 .computer_name = r->in.computer_name,
552 .negotiate_flags = *r->in.negotiate_flags,
553 .secure_channel_type = r->in.secure_channel_type,
557 status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
560 &trust_account_for_search,
561 &trust_account_in_db,
563 ui.netlogon_trust_account.sid = sid;
564 ui.netlogon_trust_account.account_name = trust_account_in_db;
565 ui.mapped.account_name = trust_account_for_search;
566 log_authentication_event(
567 dce_call->conn->msg_ctx,
568 dce_call->conn->dce_ctx->lp_ctx,
572 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
579 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
580 struct netr_ServerAuthenticate *r)
582 struct netr_ServerAuthenticate3 a;
585 * negotiate_flags is used as an [in] parameter
586 * so it need to be initialised.
588 * (I think ... = 0; seems wrong here --metze)
590 uint32_t negotiate_flags_in = 0;
591 uint32_t negotiate_flags_out = 0;
593 a.in.server_name = r->in.server_name;
594 a.in.account_name = r->in.account_name;
595 a.in.secure_channel_type = r->in.secure_channel_type;
596 a.in.computer_name = r->in.computer_name;
597 a.in.credentials = r->in.credentials;
598 a.in.negotiate_flags = &negotiate_flags_in;
600 a.out.return_credentials = r->out.return_credentials;
602 a.out.negotiate_flags = &negotiate_flags_out;
604 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
607 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
608 struct netr_ServerAuthenticate2 *r)
610 struct netr_ServerAuthenticate3 r3;
613 r3.in.server_name = r->in.server_name;
614 r3.in.account_name = r->in.account_name;
615 r3.in.secure_channel_type = r->in.secure_channel_type;
616 r3.in.computer_name = r->in.computer_name;
617 r3.in.credentials = r->in.credentials;
618 r3.out.return_credentials = r->out.return_credentials;
619 r3.in.negotiate_flags = r->in.negotiate_flags;
620 r3.out.negotiate_flags = r->out.negotiate_flags;
623 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
627 * NOTE: The following functions are nearly identical to the ones available in
628 * source3/rpc_server/srv_nelog_nt.c
629 * The reason we keep 2 copies is that they use different structures to
630 * represent the auth_info and the decrpc pipes.
632 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
634 const char *computer_name,
635 struct netr_Authenticator *received_authenticator,
636 struct netr_Authenticator *return_authenticator,
637 struct netlogon_creds_CredentialState **creds_out)
640 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
641 bool schannel_global_required = (schannel == true);
643 if (schannel_global_required) {
644 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
646 dcesrv_call_auth_info(dce_call, &auth_type, NULL);
648 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
649 DBG_ERR("[%s] is not using schannel\n",
651 return NT_STATUS_ACCESS_DENIED;
655 nt_status = schannel_check_creds_state(mem_ctx,
656 dce_call->conn->dce_ctx->lp_ctx,
658 received_authenticator,
659 return_authenticator,
665 Change the machine account password for the currently connected
666 client. Supplies only the NT#.
669 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
670 struct netr_ServerPasswordSet *r)
672 struct netlogon_creds_CredentialState *creds;
673 struct ldb_context *sam_ctx;
674 const char * const attrs[] = { "unicodePwd", NULL };
675 struct ldb_message **res;
676 struct samr_Password *oldNtHash;
680 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
683 r->in.credential, r->out.return_authenticator,
685 NT_STATUS_NOT_OK_RETURN(nt_status);
687 sam_ctx = samdb_connect(mem_ctx,
689 dce_call->conn->dce_ctx->lp_ctx,
690 system_session(dce_call->conn->dce_ctx->lp_ctx),
691 dce_call->conn->remote_address,
693 if (sam_ctx == NULL) {
694 return NT_STATUS_INVALID_SYSTEM_SERVICE;
697 netlogon_creds_des_decrypt(creds, r->in.new_password);
699 /* fetch the old password hashes (the NT hash has to exist) */
701 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
702 "(&(objectClass=user)(objectSid=%s))",
703 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
705 return NT_STATUS_WRONG_PASSWORD;
708 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
709 dce_call->conn->dce_ctx->lp_ctx,
710 res[0], NULL, &oldNtHash);
711 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
712 return NT_STATUS_WRONG_PASSWORD;
715 /* Using the sid for the account as the key, set the password */
716 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
718 NULL, /* Don't have version */
719 NULL, /* Don't have plaintext */
720 NULL, r->in.new_password,
721 NULL, oldNtHash, /* Password change */
727 Change the machine account password for the currently connected
728 client. Supplies new plaintext.
730 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
731 struct netr_ServerPasswordSet2 *r)
733 struct netlogon_creds_CredentialState *creds;
734 struct ldb_context *sam_ctx;
735 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
736 struct ldb_message **res;
737 struct samr_Password *oldLmHash, *oldNtHash;
738 struct NL_PASSWORD_VERSION version = {};
739 const uint32_t *new_version = NULL;
741 DATA_BLOB new_password;
743 struct samr_CryptPassword password_buf;
745 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
748 r->in.credential, r->out.return_authenticator,
750 NT_STATUS_NOT_OK_RETURN(nt_status);
752 sam_ctx = samdb_connect(mem_ctx,
754 dce_call->conn->dce_ctx->lp_ctx,
755 system_session(dce_call->conn->dce_ctx->lp_ctx),
756 dce_call->conn->remote_address,
758 if (sam_ctx == NULL) {
759 return NT_STATUS_INVALID_SYSTEM_SERVICE;
762 memcpy(password_buf.data, r->in.new_password->data, 512);
763 SIVAL(password_buf.data, 512, r->in.new_password->length);
765 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
766 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
768 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
771 switch (creds->secure_channel_type) {
772 case SEC_CHAN_DOMAIN:
773 case SEC_CHAN_DNS_DOMAIN: {
774 uint32_t len = IVAL(password_buf.data, 512);
776 uint32_t ofs = 500 - len;
779 p = password_buf.data + ofs;
781 version.ReservedField = IVAL(p, 0);
782 version.PasswordVersionNumber = IVAL(p, 4);
783 version.PasswordVersionPresent = IVAL(p, 8);
785 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
786 new_version = &version.PasswordVersionNumber;
794 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
795 DEBUG(3,("samr: failed to decode password buffer\n"));
796 return NT_STATUS_WRONG_PASSWORD;
799 /* fetch the old password hashes (at least one of both has to exist) */
801 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
802 "(&(objectClass=user)(objectSid=%s))",
803 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
805 return NT_STATUS_WRONG_PASSWORD;
808 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
809 dce_call->conn->dce_ctx->lp_ctx,
810 res[0], &oldLmHash, &oldNtHash);
811 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
812 return NT_STATUS_WRONG_PASSWORD;
815 /* Using the sid for the account as the key, set the password */
816 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
819 &new_password, /* we have plaintext */
821 oldLmHash, oldNtHash, /* Password change */
830 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
831 struct netr_LogonUasLogon *r)
833 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
840 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
841 struct netr_LogonUasLogoff *r)
843 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
847 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
848 const struct netr_LogonSamLogonEx *r)
850 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
852 switch (r->in.logon_level) {
853 case NetlogonInteractiveInformation:
854 case NetlogonServiceInformation:
855 case NetlogonInteractiveTransitiveInformation:
856 case NetlogonServiceTransitiveInformation:
857 if (r->in.logon->password == NULL) {
858 return NT_STATUS_INVALID_PARAMETER;
861 switch (r->in.validation_level) {
862 case NetlogonValidationSamInfo: /* 2 */
863 case NetlogonValidationSamInfo2: /* 3 */
864 case NetlogonValidationSamInfo4: /* 6 */
867 return NT_STATUS_INVALID_INFO_CLASS;
871 case NetlogonNetworkInformation:
872 case NetlogonNetworkTransitiveInformation:
873 if (r->in.logon->network == NULL) {
874 return NT_STATUS_INVALID_PARAMETER;
877 switch (r->in.validation_level) {
878 case NetlogonValidationSamInfo: /* 2 */
879 case NetlogonValidationSamInfo2: /* 3 */
880 case NetlogonValidationSamInfo4: /* 6 */
883 return NT_STATUS_INVALID_INFO_CLASS;
888 case NetlogonGenericInformation:
889 if (r->in.logon->generic == NULL) {
890 return NT_STATUS_INVALID_PARAMETER;
893 switch (r->in.validation_level) {
894 /* TODO: case NetlogonValidationGenericInfo: 4 */
895 case NetlogonValidationGenericInfo2: /* 5 */
898 return NT_STATUS_INVALID_INFO_CLASS;
903 return NT_STATUS_INVALID_PARAMETER;
906 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
908 switch (r->in.validation_level) {
909 case NetlogonValidationSamInfo4: /* 6 */
910 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
911 return NT_STATUS_INVALID_PARAMETER;
922 struct dcesrv_netr_LogonSamLogon_base_state {
923 struct dcesrv_call_state *dce_call;
927 struct netlogon_creds_CredentialState *creds;
929 struct netr_LogonSamLogonEx r;
931 uint32_t _ignored_flags;
934 struct netr_LogonSamLogon *lsl;
935 struct netr_LogonSamLogonWithFlags *lslwf;
936 struct netr_LogonSamLogonEx *lslex;
939 struct kdc_check_generic_kerberos kr;
942 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
943 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
944 static void dcesrv_netr_LogonSamLogon_base_reply(
945 struct dcesrv_netr_LogonSamLogon_base_state *state);
948 netr_LogonSamLogon_base
950 This version of the function allows other wrappers to say 'do not check the credentials'
952 We can't do the traditional 'wrapping' format completely, as this
953 function must only run under schannel
955 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
957 struct dcesrv_call_state *dce_call = state->dce_call;
958 TALLOC_CTX *mem_ctx = state->mem_ctx;
959 struct netr_LogonSamLogonEx *r = &state->r;
960 struct netlogon_creds_CredentialState *creds = state->creds;
961 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
962 const char *workgroup = lpcfg_workgroup(lp_ctx);
963 struct auth4_context *auth_context = NULL;
964 struct auth_usersupplied_info *user_info = NULL;
966 struct tevent_req *subreq = NULL;
968 *r->out.authoritative = 1;
970 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
972 * Currently we're always the forest root ourself.
974 return NT_STATUS_NO_SUCH_USER;
977 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
979 * Currently we don't support trusts correctly yet.
981 return NT_STATUS_NO_SUCH_USER;
984 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
985 NT_STATUS_HAVE_NO_MEMORY(user_info);
987 user_info->service_description = "SamLogon";
989 netlogon_creds_decrypt_samlogon_logon(creds,
993 switch (r->in.logon_level) {
994 case NetlogonInteractiveInformation:
995 case NetlogonServiceInformation:
996 case NetlogonInteractiveTransitiveInformation:
997 case NetlogonServiceTransitiveInformation:
998 case NetlogonNetworkInformation:
999 case NetlogonNetworkTransitiveInformation:
1001 nt_status = auth_context_create_for_netlogon(mem_ctx,
1002 dce_call->event_ctx, dce_call->msg_ctx,
1003 dce_call->conn->dce_ctx->lp_ctx,
1005 NT_STATUS_NOT_OK_RETURN(nt_status);
1007 user_info->remote_host = dce_call->conn->remote_address;
1008 user_info->local_host = dce_call->conn->local_address;
1010 user_info->netlogon_trust_account.secure_channel_type
1011 = creds->secure_channel_type;
1012 user_info->netlogon_trust_account.negotiate_flags
1013 = creds->negotiate_flags;
1016 * These two can be unrelated when the account is
1017 * actually that of a trusted domain, so we want to
1018 * know which DC in that trusted domain contacted
1021 user_info->netlogon_trust_account.computer_name
1022 = creds->computer_name;
1023 user_info->netlogon_trust_account.account_name
1024 = creds->account_name;
1025 user_info->netlogon_trust_account.sid
1029 /* We do not need to set up the user_info in this case */
1033 switch (r->in.logon_level) {
1034 case NetlogonInteractiveInformation:
1035 case NetlogonServiceInformation:
1036 case NetlogonInteractiveTransitiveInformation:
1037 case NetlogonServiceTransitiveInformation:
1038 user_info->auth_description = "interactive";
1040 user_info->logon_parameters
1041 = r->in.logon->password->identity_info.parameter_control;
1042 user_info->client.account_name
1043 = r->in.logon->password->identity_info.account_name.string;
1044 user_info->client.domain_name
1045 = r->in.logon->password->identity_info.domain_name.string;
1046 user_info->workstation_name
1047 = r->in.logon->password->identity_info.workstation.string;
1048 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1049 user_info->password_state = AUTH_PASSWORD_HASH;
1051 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1052 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1053 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1055 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1056 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1057 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1060 case NetlogonNetworkInformation:
1061 case NetlogonNetworkTransitiveInformation:
1062 user_info->auth_description = "network";
1064 nt_status = auth_context_set_challenge(
1066 r->in.logon->network->challenge,
1067 "netr_LogonSamLogonWithFlags");
1068 NT_STATUS_NOT_OK_RETURN(nt_status);
1070 user_info->logon_parameters
1071 = r->in.logon->network->identity_info.parameter_control;
1072 user_info->client.account_name
1073 = r->in.logon->network->identity_info.account_name.string;
1074 user_info->client.domain_name
1075 = r->in.logon->network->identity_info.domain_name.string;
1076 user_info->workstation_name
1077 = r->in.logon->network->identity_info.workstation.string;
1079 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1080 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1081 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1083 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1084 user_info->client.account_name,
1085 user_info->client.domain_name,
1086 user_info->password.response.nt,
1088 NT_STATUS_NOT_OK_RETURN(nt_status);
1093 case NetlogonGenericInformation:
1095 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1097 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1100 /* Using DES to verify kerberos tickets makes no sense */
1101 return NT_STATUS_INVALID_PARAMETER;
1104 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1105 struct dcerpc_binding_handle *irpc_handle;
1106 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1107 NT_STATUS_HAVE_NO_MEMORY(generic);
1109 r->out.validation->generic = generic;
1111 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1115 if (irpc_handle == NULL) {
1116 return NT_STATUS_NO_LOGON_SERVERS;
1119 state->kr.in.generic_request =
1120 data_blob_const(r->in.logon->generic->data,
1121 r->in.logon->generic->length);
1124 * 60 seconds should be enough
1126 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1127 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1128 state->dce_call->event_ctx,
1129 irpc_handle, &state->kr);
1130 if (subreq == NULL) {
1131 return NT_STATUS_NO_MEMORY;
1133 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1134 tevent_req_set_callback(subreq,
1135 dcesrv_netr_LogonSamLogon_base_krb5_done,
1137 return NT_STATUS_OK;
1140 /* Until we get an implemetnation of these other packages */
1141 return NT_STATUS_INVALID_PARAMETER;
1144 return NT_STATUS_INVALID_PARAMETER;
1147 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1148 auth_context, user_info);
1149 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1150 tevent_req_set_callback(subreq,
1151 dcesrv_netr_LogonSamLogon_base_auth_done,
1153 return NT_STATUS_OK;
1156 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1158 struct dcesrv_netr_LogonSamLogon_base_state *state =
1159 tevent_req_callback_data(subreq,
1160 struct dcesrv_netr_LogonSamLogon_base_state);
1161 TALLOC_CTX *mem_ctx = state->mem_ctx;
1162 struct netr_LogonSamLogonEx *r = &state->r;
1163 struct auth_user_info_dc *user_info_dc = NULL;
1164 struct netr_SamInfo2 *sam2 = NULL;
1165 struct netr_SamInfo3 *sam3 = NULL;
1166 struct netr_SamInfo6 *sam6 = NULL;
1169 nt_status = auth_check_password_recv(subreq, mem_ctx,
1171 r->out.authoritative);
1172 TALLOC_FREE(subreq);
1173 if (!NT_STATUS_IS_OK(nt_status)) {
1174 r->out.result = nt_status;
1175 dcesrv_netr_LogonSamLogon_base_reply(state);
1179 switch (r->in.validation_level) {
1181 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1184 if (!NT_STATUS_IS_OK(nt_status)) {
1185 r->out.result = nt_status;
1186 dcesrv_netr_LogonSamLogon_base_reply(state);
1190 r->out.validation->sam2 = sam2;
1194 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1197 if (!NT_STATUS_IS_OK(nt_status)) {
1198 r->out.result = nt_status;
1199 dcesrv_netr_LogonSamLogon_base_reply(state);
1203 r->out.validation->sam3 = sam3;
1207 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1210 if (!NT_STATUS_IS_OK(nt_status)) {
1211 r->out.result = nt_status;
1212 dcesrv_netr_LogonSamLogon_base_reply(state);
1216 r->out.validation->sam6 = sam6;
1220 if (!NT_STATUS_IS_OK(nt_status)) {
1221 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1222 dcesrv_netr_LogonSamLogon_base_reply(state);
1227 /* TODO: Describe and deal with these flags */
1230 r->out.result = NT_STATUS_OK;
1232 dcesrv_netr_LogonSamLogon_base_reply(state);
1235 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1237 struct dcesrv_netr_LogonSamLogon_base_state *state =
1238 tevent_req_callback_data(subreq,
1239 struct dcesrv_netr_LogonSamLogon_base_state);
1240 TALLOC_CTX *mem_ctx = state->mem_ctx;
1241 struct netr_LogonSamLogonEx *r = &state->r;
1242 struct netr_GenericInfo2 *generic = NULL;
1245 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1246 TALLOC_FREE(subreq);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 r->out.result = status;
1249 dcesrv_netr_LogonSamLogon_base_reply(state);
1253 generic = r->out.validation->generic;
1254 generic->length = state->kr.out.generic_reply.length;
1255 generic->data = state->kr.out.generic_reply.data;
1257 /* TODO: Describe and deal with these flags */
1260 r->out.result = NT_STATUS_OK;
1262 dcesrv_netr_LogonSamLogon_base_reply(state);
1265 static void dcesrv_netr_LogonSamLogon_base_reply(
1266 struct dcesrv_netr_LogonSamLogon_base_state *state)
1268 struct netr_LogonSamLogonEx *r = &state->r;
1271 if (NT_STATUS_IS_OK(r->out.result)) {
1272 netlogon_creds_encrypt_samlogon_validation(state->creds,
1273 r->in.validation_level,
1277 if (state->_r.lslex != NULL) {
1278 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1279 _r->out.result = r->out.result;
1280 } else if (state->_r.lslwf != NULL) {
1281 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1282 _r->out.result = r->out.result;
1283 } else if (state->_r.lsl != NULL) {
1284 struct netr_LogonSamLogon *_r = state->_r.lsl;
1285 _r->out.result = r->out.result;
1288 status = dcesrv_reply(state->dce_call);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 DBG_ERR("dcesrv_reply() failed - %s\n",
1295 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1296 struct netr_LogonSamLogonEx *r)
1298 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1299 struct dcesrv_netr_LogonSamLogon_base_state *state;
1302 *r->out.authoritative = 1;
1304 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1305 if (state == NULL) {
1306 return NT_STATUS_NO_MEMORY;
1309 state->dce_call = dce_call;
1310 state->mem_ctx = mem_ctx;
1312 state->r.in.server_name = r->in.server_name;
1313 state->r.in.computer_name = r->in.computer_name;
1314 state->r.in.logon_level = r->in.logon_level;
1315 state->r.in.logon = r->in.logon;
1316 state->r.in.validation_level = r->in.validation_level;
1317 state->r.in.flags = r->in.flags;
1318 state->r.out.validation = r->out.validation;
1319 state->r.out.authoritative = r->out.authoritative;
1320 state->r.out.flags = r->out.flags;
1322 state->_r.lslex = r;
1324 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1325 if (!NT_STATUS_IS_OK(nt_status)) {
1329 nt_status = schannel_get_creds_state(mem_ctx,
1330 dce_call->conn->dce_ctx->lp_ctx,
1331 r->in.computer_name, &state->creds);
1332 if (!NT_STATUS_IS_OK(nt_status)) {
1336 dcesrv_call_auth_info(dce_call, &auth_type, NULL);
1338 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1339 return NT_STATUS_ACCESS_DENIED;
1342 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1344 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1352 netr_LogonSamLogonWithFlags
1355 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1356 struct netr_LogonSamLogonWithFlags *r)
1358 struct dcesrv_netr_LogonSamLogon_base_state *state;
1361 *r->out.authoritative = 1;
1363 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1364 if (state == NULL) {
1365 return NT_STATUS_NO_MEMORY;
1368 state->dce_call = dce_call;
1369 state->mem_ctx = mem_ctx;
1371 state->r.in.server_name = r->in.server_name;
1372 state->r.in.computer_name = r->in.computer_name;
1373 state->r.in.logon_level = r->in.logon_level;
1374 state->r.in.logon = r->in.logon;
1375 state->r.in.validation_level = r->in.validation_level;
1376 state->r.in.flags = r->in.flags;
1377 state->r.out.validation = r->out.validation;
1378 state->r.out.authoritative = r->out.authoritative;
1379 state->r.out.flags = r->out.flags;
1381 state->_r.lslwf = r;
1383 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1384 if (!NT_STATUS_IS_OK(nt_status)) {
1388 r->out.return_authenticator = talloc_zero(mem_ctx,
1389 struct netr_Authenticator);
1390 if (r->out.return_authenticator == NULL) {
1391 return NT_STATUS_NO_MEMORY;
1394 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1396 r->in.computer_name,
1398 r->out.return_authenticator,
1400 if (!NT_STATUS_IS_OK(nt_status)) {
1404 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1406 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1416 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1417 struct netr_LogonSamLogon *r)
1419 struct dcesrv_netr_LogonSamLogon_base_state *state;
1422 *r->out.authoritative = 1;
1424 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1425 if (state == NULL) {
1426 return NT_STATUS_NO_MEMORY;
1429 state->dce_call = dce_call;
1430 state->mem_ctx = mem_ctx;
1432 state->r.in.server_name = r->in.server_name;
1433 state->r.in.computer_name = r->in.computer_name;
1434 state->r.in.logon_level = r->in.logon_level;
1435 state->r.in.logon = r->in.logon;
1436 state->r.in.validation_level = r->in.validation_level;
1437 state->r.in.flags = &state->_ignored_flags;
1438 state->r.out.validation = r->out.validation;
1439 state->r.out.authoritative = r->out.authoritative;
1440 state->r.out.flags = &state->_ignored_flags;
1444 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1445 if (!NT_STATUS_IS_OK(nt_status)) {
1449 r->out.return_authenticator = talloc_zero(mem_ctx,
1450 struct netr_Authenticator);
1451 if (r->out.return_authenticator == NULL) {
1452 return NT_STATUS_NO_MEMORY;
1455 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1457 r->in.computer_name,
1459 r->out.return_authenticator,
1461 if (!NT_STATUS_IS_OK(nt_status)) {
1465 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1467 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1478 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1479 struct netr_LogonSamLogoff *r)
1481 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1489 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1490 struct netr_DatabaseDeltas *r)
1492 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1499 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1500 struct netr_DatabaseSync2 *r)
1502 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1503 return NT_STATUS_NOT_IMPLEMENTED;
1510 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1511 struct netr_DatabaseSync *r)
1513 struct netr_DatabaseSync2 r2;
1518 r2.in.logon_server = r->in.logon_server;
1519 r2.in.computername = r->in.computername;
1520 r2.in.credential = r->in.credential;
1521 r2.in.database_id = r->in.database_id;
1522 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1523 r2.in.sync_context = r->in.sync_context;
1524 r2.out.sync_context = r->out.sync_context;
1525 r2.out.delta_enum_array = r->out.delta_enum_array;
1526 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1528 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1537 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1538 struct netr_AccountDeltas *r)
1540 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1541 return NT_STATUS_NOT_IMPLEMENTED;
1548 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1549 struct netr_AccountSync *r)
1551 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1552 return NT_STATUS_NOT_IMPLEMENTED;
1559 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1560 struct netr_GetDcName *r)
1562 struct auth_session_info *session_info =
1563 dcesrv_call_session_info(dce_call);
1564 const char * const attrs[] = { NULL };
1565 struct ldb_context *sam_ctx;
1566 struct ldb_message **res;
1567 struct ldb_dn *domain_dn;
1572 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1573 * that the domainname needs to be a valid netbios domain
1574 * name, if it is not NULL.
1576 if (r->in.domainname) {
1577 const char *dot = strchr(r->in.domainname, '.');
1578 size_t len = strlen(r->in.domainname);
1580 if (dot || len > 15) {
1581 return WERR_NERR_DCNOTFOUND;
1585 * TODO: Should we also varify that only valid
1586 * netbios name characters are used?
1590 sam_ctx = samdb_connect(mem_ctx,
1591 dce_call->event_ctx,
1592 dce_call->conn->dce_ctx->lp_ctx,
1594 dce_call->conn->remote_address,
1596 if (sam_ctx == NULL) {
1597 return WERR_DS_UNAVAILABLE;
1600 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1602 if (domain_dn == NULL) {
1603 return WERR_NO_SUCH_DOMAIN;
1606 ret = gendb_search_dn(sam_ctx, mem_ctx,
1607 domain_dn, &res, attrs);
1609 return WERR_NO_SUCH_DOMAIN;
1612 /* TODO: - return real IP address
1613 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1615 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1616 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1617 W_ERROR_HAVE_NO_MEMORY(dcname);
1619 *r->out.dcname = dcname;
1623 struct dcesrv_netr_LogonControl_base_state {
1624 struct dcesrv_call_state *dce_call;
1626 TALLOC_CTX *mem_ctx;
1628 struct netr_LogonControl2Ex r;
1631 struct netr_LogonControl *l;
1632 struct netr_LogonControl2 *l2;
1633 struct netr_LogonControl2Ex *l2ex;
1637 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1639 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1641 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1642 struct auth_session_info *session_info =
1643 dcesrv_call_session_info(state->dce_call);
1644 enum security_user_level security_level;
1645 struct dcerpc_binding_handle *irpc_handle;
1646 struct tevent_req *subreq;
1649 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1651 if (state->_r.l != NULL) {
1655 if (state->r.in.level == 0x00000002) {
1656 return WERR_NOT_SUPPORTED;
1657 } else if (state->r.in.level != 0x00000001) {
1658 return WERR_INVALID_LEVEL;
1661 switch (state->r.in.function_code) {
1662 case NETLOGON_CONTROL_QUERY:
1663 case NETLOGON_CONTROL_REPLICATE:
1664 case NETLOGON_CONTROL_SYNCHRONIZE:
1665 case NETLOGON_CONTROL_PDC_REPLICATE:
1666 case NETLOGON_CONTROL_BREAKPOINT:
1667 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1668 case NETLOGON_CONTROL_TRUNCATE_LOG:
1671 return WERR_NOT_SUPPORTED;
1675 if (state->r.in.level < 0x00000001) {
1676 return WERR_INVALID_LEVEL;
1679 if (state->r.in.level > 0x00000004) {
1680 return WERR_INVALID_LEVEL;
1683 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1684 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1685 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1687 switch (state->r.in.level) {
1689 info1 = talloc_zero(state->mem_ctx,
1690 struct netr_NETLOGON_INFO_1);
1691 if (info1 == NULL) {
1692 return WERR_NOT_ENOUGH_MEMORY;
1694 state->r.out.query->info1 = info1;
1698 info3 = talloc_zero(state->mem_ctx,
1699 struct netr_NETLOGON_INFO_3);
1700 if (info3 == NULL) {
1701 return WERR_NOT_ENOUGH_MEMORY;
1703 state->r.out.query->info3 = info3;
1707 return WERR_INVALID_PARAMETER;
1712 * Some validations are done before the access check
1713 * and some after the access check
1715 security_level = security_session_user_level(session_info, NULL);
1716 if (security_level < SECURITY_ADMINISTRATOR) {
1717 return WERR_ACCESS_DENIED;
1720 if (state->_r.l2 != NULL) {
1722 * netr_LogonControl2
1724 if (state->r.in.level == 0x00000004) {
1725 return WERR_INVALID_LEVEL;
1729 switch (state->r.in.level) {
1734 switch (state->r.in.function_code) {
1735 case NETLOGON_CONTROL_REDISCOVER:
1736 case NETLOGON_CONTROL_TC_QUERY:
1737 case NETLOGON_CONTROL_TC_VERIFY:
1740 return WERR_INVALID_PARAMETER;
1749 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1750 return WERR_INVALID_PARAMETER;
1756 return WERR_INVALID_LEVEL;
1759 switch (state->r.in.function_code) {
1760 case NETLOGON_CONTROL_REDISCOVER:
1761 case NETLOGON_CONTROL_TC_QUERY:
1762 case NETLOGON_CONTROL_TC_VERIFY:
1763 if (state->r.in.level != 2) {
1764 return WERR_INVALID_PARAMETER;
1767 if (state->r.in.data == NULL) {
1768 return WERR_INVALID_PARAMETER;
1771 if (state->r.in.data->domain == NULL) {
1772 return WERR_INVALID_PARAMETER;
1777 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1778 if (state->r.in.level != 1) {
1779 return WERR_INVALID_PARAMETER;
1782 if (state->r.in.data == NULL) {
1783 return WERR_INVALID_PARAMETER;
1786 if (state->r.in.data->domain == NULL) {
1787 return WERR_INVALID_PARAMETER;
1790 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1791 state->r.in.data->domain);
1793 struct ldb_context *sam_ctx;
1795 sam_ctx = samdb_connect(
1797 state->dce_call->event_ctx,
1799 system_session(lp_ctx),
1800 state->dce_call->conn->remote_address,
1802 if (sam_ctx == NULL) {
1803 return WERR_DS_UNAVAILABLE;
1807 * Secrets for trusted domains can only be triggered on
1810 ok = samdb_is_pdc(sam_ctx);
1811 TALLOC_FREE(sam_ctx);
1813 return WERR_INVALID_DOMAIN_ROLE;
1819 return WERR_NOT_SUPPORTED;
1822 irpc_handle = irpc_binding_handle_by_name(state,
1823 state->dce_call->msg_ctx,
1825 &ndr_table_winbind);
1826 if (irpc_handle == NULL) {
1827 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1828 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1829 return WERR_SERVICE_NOT_FOUND;
1833 * 60 seconds timeout should be enough
1835 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1837 subreq = dcerpc_winbind_LogonControl_send(state,
1838 state->dce_call->event_ctx,
1840 state->r.in.function_code,
1843 state->r.out.query);
1844 if (subreq == NULL) {
1845 return WERR_NOT_ENOUGH_MEMORY;
1847 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1848 tevent_req_set_callback(subreq,
1849 dcesrv_netr_LogonControl_base_done,
1855 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1857 struct dcesrv_netr_LogonControl_base_state *state =
1858 tevent_req_callback_data(subreq,
1859 struct dcesrv_netr_LogonControl_base_state);
1862 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1863 &state->r.out.result);
1864 TALLOC_FREE(subreq);
1865 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1866 state->r.out.result = WERR_TIMEOUT;
1867 } else if (!NT_STATUS_IS_OK(status)) {
1868 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1869 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1870 nt_errstr(status)));
1873 if (state->_r.l2ex != NULL) {
1874 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1875 r->out.result = state->r.out.result;
1876 } else if (state->_r.l2 != NULL) {
1877 struct netr_LogonControl2 *r = state->_r.l2;
1878 r->out.result = state->r.out.result;
1879 } else if (state->_r.l != NULL) {
1880 struct netr_LogonControl *r = state->_r.l;
1881 r->out.result = state->r.out.result;
1884 status = dcesrv_reply(state->dce_call);
1885 if (!NT_STATUS_IS_OK(status)) {
1886 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1893 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1894 struct netr_LogonControl *r)
1896 struct dcesrv_netr_LogonControl_base_state *state;
1899 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1900 if (state == NULL) {
1901 return WERR_NOT_ENOUGH_MEMORY;
1904 state->dce_call = dce_call;
1905 state->mem_ctx = mem_ctx;
1907 state->r.in.logon_server = r->in.logon_server;
1908 state->r.in.function_code = r->in.function_code;
1909 state->r.in.level = r->in.level;
1910 state->r.in.data = NULL;
1911 state->r.out.query = r->out.query;
1915 werr = dcesrv_netr_LogonControl_base_call(state);
1917 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1927 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1928 struct netr_LogonControl2 *r)
1930 struct dcesrv_netr_LogonControl_base_state *state;
1933 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1934 if (state == NULL) {
1935 return WERR_NOT_ENOUGH_MEMORY;
1938 state->dce_call = dce_call;
1939 state->mem_ctx = mem_ctx;
1941 state->r.in.logon_server = r->in.logon_server;
1942 state->r.in.function_code = r->in.function_code;
1943 state->r.in.level = r->in.level;
1944 state->r.in.data = r->in.data;
1945 state->r.out.query = r->out.query;
1949 werr = dcesrv_netr_LogonControl_base_call(state);
1951 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1959 netr_LogonControl2Ex
1961 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1962 struct netr_LogonControl2Ex *r)
1964 struct dcesrv_netr_LogonControl_base_state *state;
1967 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1968 if (state == NULL) {
1969 return WERR_NOT_ENOUGH_MEMORY;
1972 state->dce_call = dce_call;
1973 state->mem_ctx = mem_ctx;
1978 werr = dcesrv_netr_LogonControl_base_call(state);
1980 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1987 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1988 struct ldb_context *sam_ctx,
1989 struct netr_DomainTrustList *trusts,
1990 uint32_t trust_flags);
1995 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1996 struct netr_GetAnyDCName *r)
1998 struct auth_session_info *session_info =
1999 dcesrv_call_session_info(dce_call);
2000 struct netr_DomainTrustList *trusts;
2001 struct ldb_context *sam_ctx;
2002 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2006 *r->out.dcname = NULL;
2008 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2009 /* if the domainname parameter wasn't set assume our domain */
2010 r->in.domainname = lpcfg_workgroup(lp_ctx);
2013 sam_ctx = samdb_connect(mem_ctx,
2014 dce_call->event_ctx,
2017 dce_call->conn->remote_address,
2019 if (sam_ctx == NULL) {
2020 return WERR_DS_UNAVAILABLE;
2023 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2024 /* well we asked for a DC of our own domain */
2025 if (samdb_is_pdc(sam_ctx)) {
2026 /* we are the PDC of the specified domain */
2027 return WERR_NO_SUCH_DOMAIN;
2030 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2031 lpcfg_netbios_name(lp_ctx));
2032 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2037 /* Okay, now we have to consider the trusted domains */
2039 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2040 W_ERROR_HAVE_NO_MEMORY(trusts);
2044 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2045 NETR_TRUST_FLAG_INBOUND
2046 | NETR_TRUST_FLAG_OUTBOUND);
2047 W_ERROR_NOT_OK_RETURN(werr);
2049 for (i = 0; i < trusts->count; i++) {
2050 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2051 /* FIXME: Here we need to find a DC for the specified
2052 * trusted domain. */
2054 /* return WERR_OK; */
2055 return WERR_NO_SUCH_DOMAIN;
2059 return WERR_NO_SUCH_DOMAIN;
2066 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2067 struct netr_DatabaseRedo *r)
2069 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2074 netr_NetrEnumerateTrustedDomains
2076 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2077 struct netr_NetrEnumerateTrustedDomains *r)
2079 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2084 netr_LogonGetCapabilities
2086 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2087 struct netr_LogonGetCapabilities *r)
2089 struct netlogon_creds_CredentialState *creds;
2092 status = dcesrv_netr_creds_server_step_check(dce_call,
2094 r->in.computer_name,
2096 r->out.return_authenticator,
2098 if (!NT_STATUS_IS_OK(status)) {
2099 DEBUG(0,(__location__ " Bad credentials - error\n"));
2101 NT_STATUS_NOT_OK_RETURN(status);
2103 if (r->in.query_level != 1) {
2104 return NT_STATUS_NOT_SUPPORTED;
2107 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2109 return NT_STATUS_OK;
2114 netr_NETRLOGONSETSERVICEBITS
2116 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2117 struct netr_NETRLOGONSETSERVICEBITS *r)
2119 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2124 netr_LogonGetTrustRid
2126 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2127 struct netr_LogonGetTrustRid *r)
2129 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2134 netr_NETRLOGONCOMPUTESERVERDIGEST
2136 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2137 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2139 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2144 netr_NETRLOGONCOMPUTECLIENTDIGEST
2146 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2147 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2149 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2157 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2158 struct netr_DsRGetSiteName *r)
2160 struct auth_session_info *session_info =
2161 dcesrv_call_session_info(dce_call);
2162 struct ldb_context *sam_ctx;
2163 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2165 sam_ctx = samdb_connect(mem_ctx,
2166 dce_call->event_ctx,
2169 dce_call->conn->remote_address,
2171 if (sam_ctx == NULL) {
2172 return WERR_DS_UNAVAILABLE;
2176 * We assume to be a DC when we get called over NETLOGON. Hence we
2177 * get our site name always by using "samdb_server_site_name()"
2178 * and not "samdb_client_site_name()".
2180 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2181 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2188 fill in a netr_OneDomainInfo from our own domain/forest
2190 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2191 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2192 struct GUID domain_guid,
2193 struct netr_OneDomainInfo *info,
2198 if (is_trust_list) {
2199 struct netr_trust_extension *tei = NULL;
2201 /* w2k8 only fills this on trusted domains */
2202 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2204 return NT_STATUS_NO_MEMORY;
2206 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2209 * We're always within a native forest
2211 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2212 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2214 /* For now we assume we're always the tree root */
2215 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2216 tei->parent_index = 0;
2218 tei->trust_type = our_tdo->trust_type;
2220 * This needs to be 0 instead of our_tdo->trust_attributes
2221 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2222 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2224 tei->trust_attributes = 0;
2226 info->trust_extension.info = tei;
2227 info->trust_extension.length = 16;
2230 if (is_trust_list) {
2231 info->dns_domainname.string = our_tdo->domain_name.string;
2233 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2234 info->dns_forestname.string = NULL;
2236 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2237 our_tdo->domain_name.string);
2238 if (info->dns_domainname.string == NULL) {
2239 return NT_STATUS_NO_MEMORY;
2242 info->dns_forestname.string = info->dns_domainname.string;
2245 info->domainname.string = our_tdo->netbios_name.string;
2246 info->domain_sid = our_tdo->sid;
2247 info->domain_guid = domain_guid;
2249 return NT_STATUS_OK;
2253 fill in a netr_OneDomainInfo from a trust tdo
2255 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2256 struct GUID domain_guid,
2257 const struct lsa_TrustDomainInfoInfoEx *tdo,
2258 struct netr_OneDomainInfo *info)
2260 struct netr_trust_extension *tei = NULL;
2264 /* w2k8 only fills this on trusted domains */
2265 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2267 return NT_STATUS_NO_MEMORY;
2270 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2271 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2273 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2274 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2276 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2277 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2281 * TODO: once we support multiple domains within our forest,
2282 * we need to fill this correct (or let the caller do it
2283 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2285 tei->parent_index = 0;
2287 tei->trust_type = tdo->trust_type;
2288 tei->trust_attributes = tdo->trust_attributes;
2290 info->trust_extension.info = tei;
2291 info->trust_extension.length = 16;
2293 info->domainname.string = tdo->netbios_name.string;
2294 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2295 info->dns_domainname.string = tdo->domain_name.string;
2297 info->dns_domainname.string = NULL;
2299 info->domain_sid = tdo->sid;
2300 info->domain_guid = domain_guid;
2302 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2303 info->dns_forestname.string = NULL;
2305 return NT_STATUS_OK;
2309 netr_LogonGetDomainInfo
2310 this is called as part of the ADS domain logon procedure.
2312 It has an important role in convaying details about the client, such
2313 as Operating System, Version, Service Pack etc.
2315 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2316 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2318 struct netlogon_creds_CredentialState *creds;
2319 const char * const trusts_attrs[] = {
2320 "securityIdentifier",
2328 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2329 "msDS-SupportedEncryptionTypes", NULL };
2330 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
2331 struct ldb_context *sam_ctx;
2332 const struct GUID *our_domain_guid = NULL;
2333 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2334 struct ldb_message **res1, *new_msg;
2335 struct ldb_result *trusts_res = NULL;
2336 struct ldb_dn *workstation_dn;
2337 struct netr_DomainInformation *domain_info;
2338 struct netr_LsaPolicyInformation *lsa_policy_info;
2339 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2340 bool update_dns_hostname = true;
2344 status = dcesrv_netr_creds_server_step_check(dce_call,
2346 r->in.computer_name,
2348 r->out.return_authenticator,
2350 if (!NT_STATUS_IS_OK(status)) {
2352 char* remote = NULL;
2353 TALLOC_CTX *frame = talloc_stackframe();
2354 remote = tsocket_address_string(dce_call->conn->remote_address,
2356 local = tsocket_address_string(dce_call->conn->local_address,
2358 DBG_ERR(("Bad credentials - "
2359 "computer[%s] remote[%s] local[%s]\n"),
2360 log_escape(frame, r->in.computer_name),
2365 NT_STATUS_NOT_OK_RETURN(status);
2367 sam_ctx = samdb_connect(mem_ctx,
2368 dce_call->event_ctx,
2369 dce_call->conn->dce_ctx->lp_ctx,
2370 system_session(dce_call->conn->dce_ctx->lp_ctx),
2371 dce_call->conn->remote_address,
2373 if (sam_ctx == NULL) {
2374 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2377 switch (r->in.level) {
2378 case 1: /* Domain information */
2380 if (r->in.query->workstation_info == NULL) {
2381 return NT_STATUS_INVALID_PARAMETER;
2384 /* Prepares the workstation DN */
2385 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2386 dom_sid_string(mem_ctx, creds->sid));
2387 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2389 /* Lookup for attributes in workstation object */
2390 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2393 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2396 /* Gets the sam account name which is checked against the DNS
2397 * hostname parameter. */
2398 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2401 if (sam_account_name == NULL) {
2402 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2406 * Checks that the sam account name without a possible "$"
2407 * matches as prefix with the DNS hostname in the workstation
2410 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2411 strcspn(sam_account_name, "$"));
2412 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2413 if (r->in.query->workstation_info->dns_hostname != NULL) {
2414 prefix2 = talloc_strndup(mem_ctx,
2415 r->in.query->workstation_info->dns_hostname,
2416 strcspn(r->in.query->workstation_info->dns_hostname, "."));
2417 NT_STATUS_HAVE_NO_MEMORY(prefix2);
2419 if (strcasecmp(prefix1, prefix2) != 0) {
2420 update_dns_hostname = false;
2423 update_dns_hostname = false;
2426 /* Gets the old DNS hostname */
2427 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2432 * Updates the DNS hostname when the client wishes that the
2433 * server should handle this for him
2434 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2435 * obviously only checked when we do already have a
2437 * See MS-NRPC section 3.5.4.3.9
2439 if ((old_dns_hostname != NULL) &&
2440 (r->in.query->workstation_info->workstation_flags
2441 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2442 update_dns_hostname = false;
2445 /* Gets host information and put them into our directory */
2447 new_msg = ldb_msg_new(mem_ctx);
2448 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2450 new_msg->dn = workstation_dn;
2452 /* Sets the OS name */
2454 if (r->in.query->workstation_info->os_name.string == NULL) {
2455 return NT_STATUS_INVALID_PARAMETER;
2458 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2459 r->in.query->workstation_info->os_name.string);
2460 if (ret != LDB_SUCCESS) {
2461 return NT_STATUS_NO_MEMORY;
2465 * Sets information from "os_version". On an empty structure
2466 * the values are cleared.
2468 if (r->in.query->workstation_info->os_version.os != NULL) {
2469 struct netr_OsVersionInfoEx *os_version;
2470 const char *os_version_str;
2472 os_version = &r->in.query->workstation_info->os_version.os->os;
2474 if (os_version->CSDVersion == NULL) {
2475 return NT_STATUS_INVALID_PARAMETER;
2478 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2479 os_version->MajorVersion,
2480 os_version->MinorVersion,
2481 os_version->BuildNumber);
2482 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2484 ret = ldb_msg_add_string(new_msg,
2485 "operatingSystemServicePack",
2486 os_version->CSDVersion);
2487 if (ret != LDB_SUCCESS) {
2488 return NT_STATUS_NO_MEMORY;
2491 ret = ldb_msg_add_string(new_msg,
2492 "operatingSystemVersion",
2494 if (ret != LDB_SUCCESS) {
2495 return NT_STATUS_NO_MEMORY;
2498 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2499 "operatingSystemServicePack");
2500 if (ret != LDB_SUCCESS) {
2501 return NT_STATUS_NO_MEMORY;
2504 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2505 "operatingSystemVersion");
2506 if (ret != LDB_SUCCESS) {
2507 return NT_STATUS_NO_MEMORY;
2512 * If the boolean "update_dns_hostname" remained true, then we
2513 * are fine to start the update.
2515 if (update_dns_hostname) {
2516 ret = ldb_msg_add_string(new_msg,
2518 r->in.query->workstation_info->dns_hostname);
2519 if (ret != LDB_SUCCESS) {
2520 return NT_STATUS_NO_MEMORY;
2523 /* This manual "servicePrincipalName" generation is
2524 * still needed! Since the update in the samldb LDB
2525 * module does only work if the entries already exist
2526 * which isn't always the case. */
2527 ret = ldb_msg_add_string(new_msg,
2528 "servicePrincipalName",
2529 talloc_asprintf(new_msg, "HOST/%s",
2530 r->in.computer_name));
2531 if (ret != LDB_SUCCESS) {
2532 return NT_STATUS_NO_MEMORY;
2535 ret = ldb_msg_add_string(new_msg,
2536 "servicePrincipalName",
2537 talloc_asprintf(new_msg, "HOST/%s",
2538 r->in.query->workstation_info->dns_hostname));
2539 if (ret != LDB_SUCCESS) {
2540 return NT_STATUS_NO_MEMORY;
2544 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2545 DEBUG(3,("Impossible to update samdb: %s\n",
2546 ldb_errstring(sam_ctx)));
2549 talloc_free(new_msg);
2551 /* Writes back the domain information */
2553 our_domain_guid = samdb_domain_guid(sam_ctx);
2554 if (our_domain_guid == NULL) {
2555 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2558 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2559 if (!NT_STATUS_IS_OK(status)) {
2563 status = dsdb_trust_search_tdos(sam_ctx,
2568 if (!NT_STATUS_IS_OK(status)) {
2572 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2573 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2575 ZERO_STRUCTP(domain_info);
2577 /* Informations about the local and trusted domains */
2579 status = fill_our_one_domain_info(mem_ctx,
2582 &domain_info->primary_domain,
2584 if (!NT_STATUS_IS_OK(status)) {
2588 domain_info->trusted_domain_count = trusts_res->count + 1;
2589 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2590 struct netr_OneDomainInfo,
2591 domain_info->trusted_domain_count);
2592 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2594 for (i=0; i < trusts_res->count; i++) {
2595 struct netr_OneDomainInfo *o =
2596 &domain_info->trusted_domains[i];
2597 /* we can't know the guid of trusts outside our forest */
2598 struct GUID trust_domain_guid = GUID_zero();
2599 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2601 status = dsdb_trust_parse_tdo_info(mem_ctx,
2602 trusts_res->msgs[i],
2604 if (!NT_STATUS_IS_OK(status)) {
2608 status = fill_trust_one_domain_info(mem_ctx,
2612 if (!NT_STATUS_IS_OK(status)) {
2617 status = fill_our_one_domain_info(mem_ctx,
2620 &domain_info->trusted_domains[i],
2622 if (!NT_STATUS_IS_OK(status)) {
2626 /* Sets the supported encryption types */
2627 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2628 "msDS-SupportedEncryptionTypes",
2629 default_supported_enc_types);
2631 /* Other host domain information */
2633 lsa_policy_info = talloc(mem_ctx,
2634 struct netr_LsaPolicyInformation);
2635 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2636 ZERO_STRUCTP(lsa_policy_info);
2638 domain_info->lsa_policy = *lsa_policy_info;
2640 /* The DNS hostname is only returned back when there is a chance
2642 if ((r->in.query->workstation_info->workstation_flags
2643 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2644 domain_info->dns_hostname.string = old_dns_hostname;
2646 domain_info->dns_hostname.string = NULL;
2649 domain_info->workstation_flags =
2650 r->in.query->workstation_info->workstation_flags & (
2651 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2653 r->out.info->domain_info = domain_info;
2655 case 2: /* LSA policy information - not used at the moment */
2656 lsa_policy_info = talloc(mem_ctx,
2657 struct netr_LsaPolicyInformation);
2658 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2659 ZERO_STRUCTP(lsa_policy_info);
2661 r->out.info->lsa_policy_info = lsa_policy_info;
2664 return NT_STATUS_INVALID_LEVEL;
2668 return NT_STATUS_OK;
2673 netr_ServerPasswordGet
2675 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2676 struct netr_ServerPasswordGet *r)
2678 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2681 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2682 TALLOC_CTX *mem_ctx,
2683 struct dom_sid *user_sid,
2684 struct ldb_dn *obj_dn)
2686 const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
2687 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2688 struct ldb_dn *rodc_dn;
2690 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2691 const struct dom_sid *additional_sids[] = { NULL, NULL };
2693 struct dom_sid *object_sid;
2694 const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
2696 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2697 dom_sid_string(mem_ctx, user_sid));
2698 if (!ldb_dn_validate(rodc_dn)) goto denied;
2700 /* do the two searches we need */
2701 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2702 DSDB_SEARCH_SHOW_EXTENDED_DN);
2703 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2705 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2706 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2708 object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
2710 additional_sids[0] = object_sid;
2712 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2713 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
2714 if (!W_ERROR_IS_OK(werr)) {
2718 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2719 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
2720 if (!W_ERROR_IS_OK(werr)) {
2725 * The SID list needs to include itself as well as the tokenGroups.
2727 * TODO determine if sIDHistory is required for this check
2729 werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
2730 mem_ctx, "tokenGroups", &token_sids,
2731 additional_sids, 1);
2732 if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
2736 if (never_reveal_sids &&
2737 sid_list_match(token_sids, never_reveal_sids)) {
2742 sid_list_match(token_sids, reveal_sids)) {
2754 netr_NetrLogonSendToSam
2756 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2757 struct netr_NetrLogonSendToSam *r)
2759 struct netlogon_creds_CredentialState *creds;
2760 struct ldb_context *sam_ctx;
2762 DATA_BLOB decrypted_blob;
2763 enum ndr_err_code ndr_err;
2764 struct netr_SendToSamBase base_msg = { 0 };
2766 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2768 r->in.computer_name,
2770 r->out.return_authenticator,
2773 NT_STATUS_NOT_OK_RETURN(nt_status);
2775 switch (creds->secure_channel_type) {
2779 case SEC_CHAN_WKSTA:
2780 case SEC_CHAN_DNS_DOMAIN:
2781 case SEC_CHAN_DOMAIN:
2783 return NT_STATUS_INVALID_PARAMETER;
2785 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
2786 creds->secure_channel_type));
2787 return NT_STATUS_INVALID_PARAMETER;
2790 sam_ctx = samdb_connect(mem_ctx,
2791 dce_call->event_ctx,
2792 dce_call->conn->dce_ctx->lp_ctx,
2793 system_session(dce_call->conn->dce_ctx->lp_ctx),
2794 dce_call->conn->remote_address,
2796 if (sam_ctx == NULL) {
2797 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2800 /* Buffer is meant to be 16-bit aligned */
2801 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2802 netlogon_creds_aes_decrypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2804 netlogon_creds_arcfour_crypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2807 decrypted_blob.data = r->in.opaque_buffer;
2808 decrypted_blob.length = r->in.buffer_len;
2810 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
2811 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
2813 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2814 /* We only partially implement SendToSam */
2815 return NT_STATUS_NOT_IMPLEMENTED;
2818 /* Now 'send' to SAM */
2819 switch (base_msg.message_type) {
2820 case SendToSamResetBadPasswordCount:
2822 struct ldb_message *msg = ldb_msg_new(mem_ctx);
2823 struct ldb_dn *dn = NULL;
2827 ret = ldb_transaction_start(sam_ctx);
2828 if (ret != LDB_SUCCESS) {
2829 return NT_STATUS_INTERNAL_ERROR;
2832 ret = dsdb_find_dn_by_guid(sam_ctx,
2834 &base_msg.message.reset_bad_password.guid,
2837 if (ret != LDB_SUCCESS) {
2838 ldb_transaction_cancel(sam_ctx);
2839 return NT_STATUS_INVALID_PARAMETER;
2842 if (creds->secure_channel_type == SEC_CHAN_RODC &&
2843 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
2844 DEBUG(1, ("Client asked to reset bad password on "
2845 "an arbitrary user: %s\n",
2846 ldb_dn_get_linearized(dn)));
2847 ldb_transaction_cancel(sam_ctx);
2848 return NT_STATUS_INVALID_PARAMETER;
2853 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
2854 if (ret != LDB_SUCCESS) {
2855 ldb_transaction_cancel(sam_ctx);
2856 return NT_STATUS_INVALID_PARAMETER;
2859 ret = dsdb_replace(sam_ctx, msg, 0);
2860 if (ret != LDB_SUCCESS) {
2861 ldb_transaction_cancel(sam_ctx);
2862 return NT_STATUS_INVALID_PARAMETER;
2865 ret = ldb_transaction_commit(sam_ctx);
2866 if (ret != LDB_SUCCESS) {
2867 ldb_transaction_cancel(sam_ctx);
2868 return NT_STATUS_INTERNAL_ERROR;
2874 return NT_STATUS_NOT_IMPLEMENTED;
2877 return NT_STATUS_OK;
2880 struct dcesrv_netr_DsRGetDCName_base_state {
2881 struct dcesrv_call_state *dce_call;
2882 TALLOC_CTX *mem_ctx;
2884 struct netr_DsRGetDCNameEx2 r;
2885 const char *client_site;
2888 struct netr_DsRGetDCName *dc;
2889 struct netr_DsRGetDCNameEx *dcex;
2890 struct netr_DsRGetDCNameEx2 *dcex2;
2894 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
2896 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
2898 struct dcesrv_call_state *dce_call = state->dce_call;
2899 struct auth_session_info *session_info =
2900 dcesrv_call_session_info(dce_call);
2901 TALLOC_CTX *mem_ctx = state->mem_ctx;
2902 struct netr_DsRGetDCNameEx2 *r = &state->r;
2903 struct ldb_context *sam_ctx;
2904 struct netr_DsRGetDCNameInfo *info;
2905 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2906 const struct tsocket_address *local_address;
2907 char *local_addr = NULL;
2908 const struct tsocket_address *remote_address;
2909 char *remote_addr = NULL;
2910 const char *server_site_name;
2912 struct netlogon_samlogon_response response;
2914 const char *dc_name = NULL;
2915 const char *domain_name = NULL;
2917 bool different_domain = true;
2919 ZERO_STRUCTP(r->out.info);
2921 sam_ctx = samdb_connect(state,
2922 dce_call->event_ctx,
2925 dce_call->conn->remote_address,
2927 if (sam_ctx == NULL) {
2928 return WERR_DS_UNAVAILABLE;
2931 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2932 if (tsocket_address_is_inet(local_address, "ip")) {
2933 local_addr = tsocket_address_inet_addr_string(local_address, state);
2934 W_ERROR_HAVE_NO_MEMORY(local_addr);
2937 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2938 if (tsocket_address_is_inet(remote_address, "ip")) {
2939 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
2940 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2943 /* "server_unc" is ignored by w2k3 */
2945 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2946 return WERR_INVALID_FLAGS;
2949 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2950 r->in.flags & DS_PDC_REQUIRED &&
2951 r->in.flags & DS_KDC_REQUIRED) {
2952 return WERR_INVALID_FLAGS;
2954 if (r->in.flags & DS_IS_FLAT_NAME &&
2955 r->in.flags & DS_IS_DNS_NAME) {
2956 return WERR_INVALID_FLAGS;
2958 if (r->in.flags & DS_RETURN_DNS_NAME &&
2959 r->in.flags & DS_RETURN_FLAT_NAME) {
2960 return WERR_INVALID_FLAGS;
2962 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2963 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2964 return WERR_INVALID_FLAGS;
2967 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2969 (DS_DIRECTORY_SERVICE_REQUIRED |
2970 DS_DIRECTORY_SERVICE_PREFERRED |
2971 DS_GC_SERVER_REQUIRED |
2974 return WERR_INVALID_FLAGS;
2977 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2979 return WERR_INVALID_FLAGS;
2983 * If we send an all-zero GUID, we should ignore it as winbind actually
2984 * checks it with a DNS query. Windows also appears to ignore it.
2986 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
2987 r->in.domain_guid = NULL;
2990 /* Attempt winbind search only if we suspect the domain is incorrect */
2991 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
2992 if (r->in.flags & DS_IS_FLAT_NAME) {
2993 if (strcasecmp_m(r->in.domain_name,
2994 lpcfg_sam_name(lp_ctx)) == 0) {
2995 different_domain = false;
2997 } else if (r->in.flags & DS_IS_DNS_NAME) {
2998 if (strcasecmp_m(r->in.domain_name,
2999 lpcfg_dnsdomain(lp_ctx)) == 0) {
3000 different_domain = false;
3003 if (strcasecmp_m(r->in.domain_name,
3004 lpcfg_sam_name(lp_ctx)) == 0 ||
3005 strcasecmp_m(r->in.domain_name,
3006 lpcfg_dnsdomain(lp_ctx)) == 0) {
3007 different_domain = false;
3012 * We need to be able to handle empty domain names, where we
3013 * revert to our domain by default.
3015 different_domain = false;
3018 /* Proof server site parameter "site_name" if it was specified */
3019 server_site_name = samdb_server_site_name(sam_ctx, state);
3020 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3021 if (different_domain || (r->in.site_name != NULL &&
3022 (strcasecmp_m(r->in.site_name,
3023 server_site_name) != 0))) {
3025 struct dcerpc_binding_handle *irpc_handle = NULL;
3026 struct tevent_req *subreq = NULL;
3029 * Retrieve the client site to override the winbind response.
3031 * DO NOT use Windows fallback for client site.
3032 * In the case of multiple domains, this is plainly wrong.
3034 * Note: It's possible that the client may belong to multiple
3035 * subnets across domains. It's not clear what this would mean,
3036 * but here we only return what this domain knows.
3038 state->client_site = samdb_client_site_name(sam_ctx,
3044 irpc_handle = irpc_binding_handle_by_name(state,
3047 &ndr_table_winbind);
3048 if (irpc_handle == NULL) {
3049 DEBUG(0,("Failed to get binding_handle for "
3050 "winbind_server task\n"));
3051 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3052 return WERR_SERVICE_NOT_FOUND;
3055 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3057 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3059 subreq = dcerpc_wbint_DsGetDcName_send(state,
3060 dce_call->event_ctx,
3067 if (subreq == NULL) {
3068 return WERR_NOT_ENOUGH_MEMORY;
3071 tevent_req_set_callback(subreq,
3072 dcesrv_netr_DsRGetDCName_base_done,
3078 guid_str = r->in.domain_guid != NULL ?
3079 GUID_string(state, r->in.domain_guid) : NULL;
3081 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3085 r->in.client_account,
3086 r->in.mask, remote_addr,
3087 NETLOGON_NT_VERSION_5EX_WITH_IP,
3088 lp_ctx, &response, true);
3089 if (!NT_STATUS_IS_OK(status)) {
3090 return ntstatus_to_werror(status);
3094 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3095 * (O) flag when the returned forest name is in DNS format. This is here
3096 * always the case (see below).
3098 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3100 if (r->in.flags & DS_RETURN_DNS_NAME) {
3101 dc_name = response.data.nt5_ex.pdc_dns_name;
3102 domain_name = response.data.nt5_ex.dns_domain;
3104 * According to MS-NRPC 2.2.1.2.1 we should set the
3105 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3106 * the returned information is in DNS form.
3108 response.data.nt5_ex.server_type |=
3109 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3110 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3111 dc_name = response.data.nt5_ex.pdc_name;
3112 domain_name = response.data.nt5_ex.domain_name;
3116 * TODO: autodetect what we need to return
3117 * based on the given arguments
3119 dc_name = response.data.nt5_ex.pdc_name;
3120 domain_name = response.data.nt5_ex.domain_name;
3123 if (!dc_name || !dc_name[0]) {
3124 return WERR_NO_SUCH_DOMAIN;
3127 if (!domain_name || !domain_name[0]) {
3128 return WERR_NO_SUCH_DOMAIN;
3131 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3132 W_ERROR_HAVE_NO_MEMORY(info);
3133 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3134 dc_name[0] != '\\'? "\\\\":"",
3135 talloc_strdup(mem_ctx, dc_name));
3136 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3138 pdc_ip = local_addr;
3139 if (pdc_ip == NULL) {
3140 pdc_ip = "127.0.0.1";
3142 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3143 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3144 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3145 info->domain_guid = response.data.nt5_ex.domain_uuid;
3146 info->domain_name = domain_name;
3147 info->forest_name = response.data.nt5_ex.forest;
3148 info->dc_flags = response.data.nt5_ex.server_type;
3149 if (r->in.flags & DS_RETURN_DNS_NAME) {
3150 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3151 * returned if we are returning info->dc_unc containing a FQDN.
3152 * This attribute is called DomainControllerName in the specs,
3153 * it seems that we decide to return FQDN or netbios depending on
3154 * DS_RETURN_DNS_NAME.
3156 info->dc_flags |= DS_DNS_CONTROLLER;
3158 info->dc_site_name = response.data.nt5_ex.server_site;
3159 info->client_site_name = response.data.nt5_ex.client_site;
3161 *r->out.info = info;
3166 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3168 struct dcesrv_netr_DsRGetDCName_base_state *state =
3169 tevent_req_callback_data(subreq,
3170 struct dcesrv_netr_DsRGetDCName_base_state);
3171 struct dcesrv_call_state *dce_call = state->dce_call;
3172 NTSTATUS result, status;
3174 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3177 TALLOC_FREE(subreq);
3179 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3180 state->r.out.result = WERR_TIMEOUT;
3184 if (!NT_STATUS_IS_OK(status)) {
3185 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3187 state->r.out.result = WERR_GEN_FAILURE;
3191 if (!NT_STATUS_IS_OK(result)) {
3192 DBG_NOTICE("DC location via winbind failed - %s\n",
3194 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3198 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3199 DBG_ERR("DC location via winbind returned no results\n");
3200 state->r.out.result = WERR_GEN_FAILURE;
3204 if (state->r.out.info[0]->dc_unc == NULL) {
3205 DBG_ERR("DC location via winbind returned no DC unc\n");
3206 state->r.out.result = WERR_GEN_FAILURE;
3211 * Either the supplied site name is NULL (possibly via
3212 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3213 * the input match name.
3215 * TODO: Currently this means that requests with NETBIOS domain
3216 * names can fail because they do not return the site name.
3218 if (state->r.in.site_name == NULL ||
3219 strcasecmp_m("", state->r.in.site_name) == 0 ||
3220 (state->r.out.info[0]->dc_site_name != NULL &&
3221 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3222 state->r.in.site_name) == 0)) {
3224 state->r.out.info[0]->client_site_name =
3225 talloc_move(state->mem_ctx, &state->client_site);
3228 * Make sure to return our DC UNC with // prefix.
3229 * Winbind currently doesn't send the leading slashes
3232 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3233 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3234 const char *dc_unc = NULL;
3236 dc_unc = talloc_asprintf(state->mem_ctx,
3238 state->r.out.info[0]->dc_unc);
3239 state->r.out.info[0]->dc_unc = dc_unc;
3242 state->r.out.result = WERR_OK;
3244 state->r.out.info = NULL;
3245 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3249 if (state->_r.dcex2 != NULL) {
3250 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3251 r->out.result = state->r.out.result;
3252 } else if (state->_r.dcex != NULL) {
3253 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3254 r->out.result = state->r.out.result;
3255 } else if (state->_r.dc != NULL) {
3256 struct netr_DsRGetDCName *r = state->_r.dc;
3257 r->out.result = state->r.out.result;
3261 status = dcesrv_reply(dce_call);
3262 if (!NT_STATUS_IS_OK(status)) {
3263 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3264 nt_errstr(status)));
3269 netr_DsRGetDCNameEx2
3271 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3272 TALLOC_CTX *mem_ctx,
3273 struct netr_DsRGetDCNameEx2 *r)
3275 struct dcesrv_netr_DsRGetDCName_base_state *state;
3277 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3278 if (state == NULL) {
3279 return WERR_NOT_ENOUGH_MEMORY;
3282 state->dce_call = dce_call;
3283 state->mem_ctx = mem_ctx;
3286 state->_r.dcex2 = r;
3288 return dcesrv_netr_DsRGetDCName_base_call(state);
3294 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3295 struct netr_DsRGetDCNameEx *r)
3297 struct dcesrv_netr_DsRGetDCName_base_state *state;
3299 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3300 if (state == NULL) {
3301 return WERR_NOT_ENOUGH_MEMORY;
3304 state->dce_call = dce_call;
3305 state->mem_ctx = mem_ctx;
3307 state->r.in.server_unc = r->in.server_unc;
3308 state->r.in.client_account = NULL;
3309 state->r.in.mask = 0;
3310 state->r.in.domain_guid = r->in.domain_guid;
3311 state->r.in.domain_name = r->in.domain_name;
3312 state->r.in.site_name = r->in.site_name;
3313 state->r.in.flags = r->in.flags;
3314 state->r.out.info = r->out.info;
3318 return dcesrv_netr_DsRGetDCName_base_call(state);
3324 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3325 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3326 * insists that it be ignored.
3328 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3329 struct netr_DsRGetDCName *r)
3331 struct dcesrv_netr_DsRGetDCName_base_state *state;
3333 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3334 if (state == NULL) {
3335 return WERR_NOT_ENOUGH_MEMORY;
3338 state->dce_call = dce_call;
3339 state->mem_ctx = mem_ctx;
3341 state->r.in.server_unc = r->in.server_unc;
3342 state->r.in.client_account = NULL;
3343 state->r.in.mask = 0;
3344 state->r.in.domain_name = r->in.domain_name;
3345 state->r.in.domain_guid = r->in.domain_guid;
3347 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3348 state->r.in.flags = r->in.flags;
3349 state->r.out.info = r->out.info;
3353 return dcesrv_netr_DsRGetDCName_base_call(state);
3356 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3358 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3359 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3361 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3366 netr_NetrEnumerateTrustedDomainsEx
3368 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3369 struct netr_NetrEnumerateTrustedDomainsEx *r)
3371 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3376 netr_DsRAddressToSitenamesExW
3378 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3379 struct netr_DsRAddressToSitenamesExW *r)
3381 struct auth_session_info *session_info =
3382 dcesrv_call_session_info(dce_call);
3383 struct ldb_context *sam_ctx;
3384 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3385 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3386 sa_family_t sin_family;
3387 struct sockaddr_in *addr;
3389 struct sockaddr_in6 *addr6;
3390 char addr_str[INET6_ADDRSTRLEN];
3392 char addr_str[INET_ADDRSTRLEN];
3398 sam_ctx = samdb_connect(mem_ctx,
3399 dce_call->event_ctx,
3402 dce_call->conn->remote_address,
3404 if (sam_ctx == NULL) {
3405 return WERR_DS_UNAVAILABLE;
3408 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3409 W_ERROR_HAVE_NO_MEMORY(ctr);
3413 ctr->count = r->in.count;
3414 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3415 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3416 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3417 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3419 for (i=0; i<ctr->count; i++) {
3420 ctr->sitename[i].string = NULL;
3421 ctr->subnetname[i].string = NULL;
3423 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3426 /* The first two byte of the buffer are reserved for the
3427 * "sin_family" but for now only the first one is used. */
3428 sin_family = r->in.addresses[i].buffer[0];
3430 switch (sin_family) {
3432 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3435 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3436 res = inet_ntop(AF_INET, &addr->sin_addr,
3437 addr_str, sizeof(addr_str));
3441 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3444 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3445 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3446 addr_str, sizeof(addr_str));
3457 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3462 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3463 ctr->subnetname[i].string = subnet_name;
3471 netr_DsRAddressToSitenamesW
3473 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3474 struct netr_DsRAddressToSitenamesW *r)
3476 struct netr_DsRAddressToSitenamesExW r2;
3477 struct netr_DsRAddressToSitenamesWCtr *ctr;
3483 r2.in.server_name = r->in.server_name;
3484 r2.in.count = r->in.count;
3485 r2.in.addresses = r->in.addresses;
3487 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3488 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3490 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3491 W_ERROR_HAVE_NO_MEMORY(ctr);
3495 ctr->count = r->in.count;
3496 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3497 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3499 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3501 for (i=0; i<ctr->count; i++) {
3502 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3510 netr_DsrGetDcSiteCoverageW
3512 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3513 struct netr_DsrGetDcSiteCoverageW *r)
3515 struct auth_session_info *session_info =
3516 dcesrv_call_session_info(dce_call);
3517 struct ldb_context *sam_ctx;
3518 struct DcSitesCtr *ctr;
3519 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3521 sam_ctx = samdb_connect(mem_ctx,
3522 dce_call->event_ctx,
3525 dce_call->conn->remote_address,
3527 if (sam_ctx == NULL) {
3528 return WERR_DS_UNAVAILABLE;
3531 ctr = talloc(mem_ctx, struct DcSitesCtr);
3532 W_ERROR_HAVE_NO_MEMORY(ctr);
3536 /* For now only return our default site */
3538 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3539 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3540 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3541 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3547 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3548 struct ldb_context *sam_ctx,
3549 struct netr_DomainTrustList *trusts,
3550 uint32_t trust_flags)
3552 struct ldb_dn *system_dn;
3553 struct ldb_message **dom_res = NULL;
3554 const char *trust_attrs[] = { "flatname", "trustPartner",
3555 "securityIdentifier", "trustDirection",
3556 "trustType", "trustAttributes", NULL };
3561 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3562 NETR_TRUST_FLAG_OUTBOUND))) {
3563 return WERR_INVALID_FLAGS;
3566 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3567 ldb_get_default_basedn(sam_ctx),
3568 "(&(objectClass=container)(cn=System))");
3570 return WERR_GEN_FAILURE;
3573 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3574 &dom_res, trust_attrs,
3575 "(objectclass=trustedDomain)");
3577 for (i = 0; i < ret; i++) {
3578 unsigned int trust_dir;
3581 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3582 "trustDirection", 0);
3584 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3585 flags |= NETR_TRUST_FLAG_INBOUND;
3587 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3588 flags |= NETR_TRUST_FLAG_OUTBOUND;
3591 if (!(flags & trust_flags)) {
3592 /* this trust direction was not requested */
3597 trusts->array = talloc_realloc(trusts, trusts->array,
3598 struct netr_DomainTrust,
3600 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3602 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3603 if (!trusts->array[n].netbios_name) {
3604 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3605 "without flatname\n",
3606 ldb_dn_get_linearized(dom_res[i]->dn)));
3609 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3611 trusts->array[n].trust_flags = flags;
3612 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3613 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3614 /* TODO: find if we have parent in the list */
3615 trusts->array[n].parent_index = 0;
3618 trusts->array[n].trust_type =
3619 ldb_msg_find_attr_as_uint(dom_res[i],
3621 trusts->array[n].trust_attributes =
3622 ldb_msg_find_attr_as_uint(dom_res[i],
3623 "trustAttributes", 0);
3625 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3626 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3627 struct dom_sid zero_sid;
3628 ZERO_STRUCT(zero_sid);
3629 trusts->array[n].sid =
3630 dom_sid_dup(trusts, &zero_sid);
3632 trusts->array[n].sid =
3633 samdb_result_dom_sid(trusts, dom_res[i],
3634 "securityIdentifier");
3636 trusts->array[n].guid = GUID_zero();
3638 trusts->count = n + 1;
3641 talloc_free(dom_res);
3646 netr_DsrEnumerateDomainTrusts
3648 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3649 TALLOC_CTX *mem_ctx,
3650 struct netr_DsrEnumerateDomainTrusts *r)
3652 struct auth_session_info *session_info =
3653 dcesrv_call_session_info(dce_call);
3654 struct netr_DomainTrustList *trusts;
3655 struct ldb_context *sam_ctx;
3657 struct ldb_message **dom_res;
3658 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3659 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3660 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3664 if (r->in.trust_flags & 0xFFFFFE00) {
3665 return WERR_INVALID_FLAGS;
3668 /* TODO: turn to hard check once we are sure this is 100% correct */
3669 if (!r->in.server_name) {
3670 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3671 "But received NULL!\n", dnsdomain));
3673 p = strchr(r->in.server_name, '.');
3675 DEBUG(3, ("Invalid domain! Expected name in domain "
3676 "[%s]. But received [%s]!\n",
3677 dnsdomain, r->in.server_name));
3678 p = r->in.server_name;
3682 if (strcasecmp(p, dnsdomain)) {
3683 DEBUG(3, ("Invalid domain! Expected name in domain "
3684 "[%s]. But received [%s]!\n",
3685 dnsdomain, r->in.server_name));
3689 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3690 W_ERROR_HAVE_NO_MEMORY(trusts);
3693 r->out.trusts = trusts;
3695 sam_ctx = samdb_connect(mem_ctx,
3696 dce_call->event_ctx,
3699 dce_call->conn->remote_address,
3701 if (sam_ctx == NULL) {
3702 return WERR_GEN_FAILURE;
3705 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3706 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3708 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3709 trusts, r->in.trust_flags);
3710 W_ERROR_NOT_OK_RETURN(werr);
3713 /* NOTE: we currently are always the root of the forest */
3714 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3715 uint32_t n = trusts->count;
3717 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3718 &dom_res, dom_attrs);
3720 return WERR_GEN_FAILURE;
3723 trusts->count = n + 1;
3724 trusts->array = talloc_realloc(trusts, trusts->array,
3725 struct netr_DomainTrust,
3727 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3729 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3730 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3731 trusts->array[n].trust_flags =
3732 NETR_TRUST_FLAG_NATIVE |
3733 NETR_TRUST_FLAG_TREEROOT |
3734 NETR_TRUST_FLAG_IN_FOREST |
3735 NETR_TRUST_FLAG_PRIMARY;
3736 /* we are always the root domain for now */
3737 trusts->array[n].parent_index = 0;
3738 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3739 trusts->array[n].trust_attributes = 0;
3740 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3743 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3745 talloc_free(dom_res);
3753 netr_DsrDeregisterDNSHostRecords
3755 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3756 struct netr_DsrDeregisterDNSHostRecords *r)
3758 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3762 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3763 struct netr_ServerGetTrustInfo *r);
3766 netr_ServerTrustPasswordsGet
3768 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3769 struct netr_ServerTrustPasswordsGet *r)
3771 struct netr_ServerGetTrustInfo r2 = {};
3772 struct netr_TrustInfo *_ti = NULL;
3775 r2.in.server_name = r->in.server_name;
3776 r2.in.account_name = r->in.account_name;
3777 r2.in.secure_channel_type = r->in.secure_channel_type;
3778 r2.in.computer_name = r->in.computer_name;
3779 r2.in.credential = r->in.credential;
3781 r2.out.return_authenticator = r->out.return_authenticator;
3782 r2.out.new_owf_password = r->out.new_owf_password;
3783 r2.out.old_owf_password = r->out.old_owf_password;
3784 r2.out.trust_info = &_ti;
3786 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3788 r->out.return_authenticator = r2.out.return_authenticator;
3789 r->out.new_owf_password = r2.out.new_owf_password;
3790 r->out.old_owf_password = r2.out.old_owf_password;
3796 netr_DsRGetForestTrustInformation
3798 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3799 struct dcesrv_call_state *dce_call;
3800 TALLOC_CTX *mem_ctx;
3801 struct netr_DsRGetForestTrustInformation *r;
3804 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3806 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3807 TALLOC_CTX *mem_ctx,
3808 struct netr_DsRGetForestTrustInformation *r)
3810 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3811 struct auth_session_info *session_info =
3812 dcesrv_call_session_info(dce_call);
3813 enum security_user_level security_level;
3814 struct ldb_context *sam_ctx = NULL;
3815 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3816 struct dcerpc_binding_handle *irpc_handle = NULL;
3817 struct tevent_req *subreq = NULL;
3818 struct ldb_dn *domain_dn = NULL;
3819 struct ldb_dn *forest_dn = NULL;
3823 security_level = security_session_user_level(session_info, NULL);
3824 if (security_level < SECURITY_USER) {
3825 return WERR_ACCESS_DENIED;
3828 if (r->in.flags & 0xFFFFFFFE) {
3829 return WERR_INVALID_FLAGS;
3832 sam_ctx = samdb_connect(mem_ctx,
3833 dce_call->event_ctx,
3836 dce_call->conn->remote_address,
3838 if (sam_ctx == NULL) {
3839 return WERR_GEN_FAILURE;
3842 domain_dn = ldb_get_default_basedn(sam_ctx);
3843 if (domain_dn == NULL) {
3844 return WERR_GEN_FAILURE;
3847 forest_dn = ldb_get_root_basedn(sam_ctx);
3848 if (forest_dn == NULL) {
3849 return WERR_GEN_FAILURE;
3852 cmp = ldb_dn_compare(domain_dn, forest_dn);
3854 return WERR_NERR_ACFNOTLOADED;
3857 forest_level = dsdb_forest_functional_level(sam_ctx);
3858 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3859 return WERR_INVALID_FUNCTION;
3862 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3863 if (!samdb_is_pdc(sam_ctx)) {
3864 return WERR_NERR_NOTPRIMARY;
3867 if (r->in.trusted_domain_name == NULL) {
3868 return WERR_INVALID_FLAGS;
3872 if (r->in.trusted_domain_name == NULL) {
3876 * information about our own domain
3878 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3879 r->out.forest_trust_info);
3880 if (!NT_STATUS_IS_OK(status)) {
3881 return ntstatus_to_werror(status);
3888 * Forward the request to winbindd
3891 state = talloc_zero(mem_ctx,
3892 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3893 if (state == NULL) {
3894 return WERR_NOT_ENOUGH_MEMORY;
3896 state->dce_call = dce_call;
3897 state->mem_ctx = mem_ctx;
3900 irpc_handle = irpc_binding_handle_by_name(state,
3901 state->dce_call->msg_ctx,
3903 &ndr_table_winbind);
3904 if (irpc_handle == NULL) {
3905 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3906 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3907 return WERR_SERVICE_NOT_FOUND;
3911 * 60 seconds timeout should be enough
3913 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3915 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3916 state->dce_call->event_ctx,
3918 r->in.trusted_domain_name,
3920 r->out.forest_trust_info);
3921 if (subreq == NULL) {
3922 return WERR_NOT_ENOUGH_MEMORY;
3924 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3925 tevent_req_set_callback(subreq,
3926 dcesrv_netr_DsRGetForestTrustInformation_done,
3932 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3934 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3935 tevent_req_callback_data(subreq,
3936 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3939 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3941 &state->r->out.result);
3942 TALLOC_FREE(subreq);
3943 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3944 state->r->out.result = WERR_TIMEOUT;
3945 } else if (!NT_STATUS_IS_OK(status)) {
3946 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3947 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3948 nt_errstr(status)));
3951 status = dcesrv_reply(state->dce_call);
3952 if (!NT_STATUS_IS_OK(status)) {
3953 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3958 netr_GetForestTrustInformation
3960 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3961 TALLOC_CTX *mem_ctx,
3962 struct netr_GetForestTrustInformation *r)
3964 struct auth_session_info *session_info =
3965 dcesrv_call_session_info(dce_call);
3966 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3967 struct netlogon_creds_CredentialState *creds = NULL;
3968 struct ldb_context *sam_ctx = NULL;
3969 struct ldb_dn *domain_dn = NULL;
3970 struct ldb_dn *forest_dn = NULL;
3975 status = dcesrv_netr_creds_server_step_check(dce_call,
3977 r->in.computer_name,
3979 r->out.return_authenticator,
3981 if (!NT_STATUS_IS_OK(status)) {
3985 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3986 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3987 return NT_STATUS_NOT_IMPLEMENTED;
3990 sam_ctx = samdb_connect(mem_ctx,
3991 dce_call->event_ctx,
3994 dce_call->conn->remote_address,
3996 if (sam_ctx == NULL) {
3997 return NT_STATUS_INTERNAL_ERROR;
4000 /* TODO: check r->in.server_name is our name */
4002 domain_dn = ldb_get_default_basedn(sam_ctx);
4003 if (domain_dn == NULL) {
4004 return NT_STATUS_INTERNAL_ERROR;
4007 forest_dn = ldb_get_root_basedn(sam_ctx);
4008 if (forest_dn == NULL) {
4009 return NT_STATUS_INTERNAL_ERROR;
4012 cmp = ldb_dn_compare(domain_dn, forest_dn);
4014 return NT_STATUS_INVALID_DOMAIN_STATE;
4017 forest_level = dsdb_forest_functional_level(sam_ctx);
4018 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4019 return NT_STATUS_INVALID_DOMAIN_STATE;
4022 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4023 r->out.forest_trust_info);
4024 if (!NT_STATUS_IS_OK(status)) {
4028 return NT_STATUS_OK;
4033 netr_ServerGetTrustInfo
4035 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4036 struct netr_ServerGetTrustInfo *r)
4038 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4039 struct netlogon_creds_CredentialState *creds = NULL;
4040 struct ldb_context *sam_ctx = NULL;
4041 const char * const attrs[] = {
4044 "userAccountControl",
4047 struct ldb_message **res = NULL;
4048 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4051 const char *asid = NULL;
4053 const char *aname = NULL;
4054 struct ldb_message *tdo_msg = NULL;
4055 const char * const tdo_attrs[] = {
4056 "trustAuthIncoming",
4060 struct netr_TrustInfo *trust_info = NULL;
4062 ZERO_STRUCTP(r->out.new_owf_password);
4063 ZERO_STRUCTP(r->out.old_owf_password);
4065 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4067 r->in.computer_name,
4069 r->out.return_authenticator,
4071 if (!NT_STATUS_IS_OK(nt_status)) {
4075 /* TODO: check r->in.server_name is our name */
4077 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4078 return NT_STATUS_INVALID_PARAMETER;
4081 if (r->in.secure_channel_type != creds->secure_channel_type) {
4082 return NT_STATUS_INVALID_PARAMETER;
4085 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4086 return NT_STATUS_INVALID_PARAMETER;
4089 sam_ctx = samdb_connect(mem_ctx,
4090 dce_call->event_ctx,
4092 system_session(lp_ctx),
4093 dce_call->conn->remote_address,
4095 if (sam_ctx == NULL) {
4096 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4099 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4101 return NT_STATUS_NO_MEMORY;
4104 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4105 "(&(objectClass=user)(objectSid=%s))",
4108 return NT_STATUS_ACCOUNT_DISABLED;
4111 switch (creds->secure_channel_type) {
4112 case SEC_CHAN_DNS_DOMAIN:
4113 case SEC_CHAN_DOMAIN:
4114 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4116 if (uac & UF_ACCOUNTDISABLE) {
4117 return NT_STATUS_ACCOUNT_DISABLED;
4120 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4121 return NT_STATUS_ACCOUNT_DISABLED;
4124 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4125 if (aname == NULL) {
4126 return NT_STATUS_ACCOUNT_DISABLED;
4129 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4130 SEC_CHAN_DOMAIN, aname,
4131 tdo_attrs, mem_ctx, &tdo_msg);
4132 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4133 return NT_STATUS_ACCOUNT_DISABLED;
4135 if (!NT_STATUS_IS_OK(nt_status)) {
4139 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4142 if (!NT_STATUS_IS_OK(nt_status)) {
4146 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4147 if (trust_info == NULL) {
4148 return NT_STATUS_NO_MEMORY;
4151 trust_info->count = 1;
4152 trust_info->data = talloc_array(trust_info, uint32_t,
4154 if (trust_info->data == NULL) {
4155 return NT_STATUS_NO_MEMORY;
4158 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4164 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4167 if (!NT_STATUS_IS_OK(nt_status)) {
4171 prevNtHash = talloc(mem_ctx, struct samr_Password);
4172 if (prevNtHash == NULL) {
4173 return NT_STATUS_NO_MEMORY;
4176 E_md4hash("", prevNtHash->hash);
4180 if (curNtHash != NULL) {
4181 *r->out.new_owf_password = *curNtHash;
4182 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4184 if (prevNtHash != NULL) {
4185 *r->out.old_owf_password = *prevNtHash;
4186 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4189 if (trust_info != NULL) {
4190 *r->out.trust_info = trust_info;
4193 return NT_STATUS_OK;
4199 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4200 struct netr_Unused47 *r)
4202 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4206 struct netr_dnsupdate_RODC_state {
4207 struct dcesrv_call_state *dce_call;
4208 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4209 struct dnsupdate_RODC *r2;
4213 called when the forwarded RODC dns update request is finished
4215 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4217 struct netr_dnsupdate_RODC_state *st =
4218 tevent_req_callback_data(subreq,
4219 struct netr_dnsupdate_RODC_state);
4222 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4223 TALLOC_FREE(subreq);
4224 if (!NT_STATUS_IS_OK(status)) {
4225 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4226 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4229 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4231 status = dcesrv_reply(st->dce_call);
4232 if (!NT_STATUS_IS_OK(status)) {
4233 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4238 netr_DsrUpdateReadOnlyServerDnsRecords
4240 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4241 TALLOC_CTX *mem_ctx,
4242 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4244 struct netlogon_creds_CredentialState *creds;
4246 struct dcerpc_binding_handle *binding_handle;
4247 struct netr_dnsupdate_RODC_state *st;
4248 struct tevent_req *subreq;
4250 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4252 r->in.computer_name,
4254 r->out.return_authenticator,
4256 NT_STATUS_NOT_OK_RETURN(nt_status);
4258 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4259 return NT_STATUS_ACCESS_DENIED;
4262 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4263 NT_STATUS_HAVE_NO_MEMORY(st);
4265 st->dce_call = dce_call;
4267 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4268 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4270 st->r2->in.dom_sid = creds->sid;
4271 st->r2->in.site_name = r->in.site_name;
4272 st->r2->in.dns_ttl = r->in.dns_ttl;
4273 st->r2->in.dns_names = r->in.dns_names;
4274 st->r2->out.dns_names = r->out.dns_names;
4276 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
4277 "dnsupdate", &ndr_table_irpc);
4278 if (binding_handle == NULL) {
4279 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4280 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4281 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4284 /* forward the call */
4285 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4286 binding_handle, st->r2);
4287 NT_STATUS_HAVE_NO_MEMORY(subreq);
4289 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4291 /* setup the callback */
4292 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4294 return NT_STATUS_OK;
4298 /* include the generated boilerplate */
4299 #include "librpc/gen_ndr/ndr_netlogon_s.c"