2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "dsdb/samdb/ldb_modules/util.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_lsa.h"
40 #include "librpc/gen_ndr/ndr_samr.h"
41 #include "librpc/gen_ndr/ndr_irpc.h"
42 #include "librpc/gen_ndr/ndr_winbind.h"
43 #include "librpc/gen_ndr/ndr_winbind_c.h"
44 #include "lib/socket/netif.h"
45 #include "rpc_server/common/sid_helper.h"
46 #include "lib/util/util_str_escape.h"
48 #define DCESRV_INTERFACE_NETLOGON_BIND(call, iface) \
49 dcesrv_interface_netlogon_bind(call, iface)
52 * This #define allows the netlogon interface to accept invalid
53 * association groups, because association groups are to coordinate
54 * handles, and handles are not used in NETLOGON. This in turn avoids
55 * the need to coordinate these across multiple possible NETLOGON
58 #define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
60 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_call_state *dce_call,
61 const struct dcesrv_interface *iface)
63 return dcesrv_interface_bind_reject_connect(dce_call, iface);
66 struct netlogon_server_pipe_state {
67 struct netr_Credential client_challenge;
68 struct netr_Credential server_challenge;
71 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
72 struct netr_ServerReqChallenge *r)
74 struct netlogon_server_pipe_state *pipe_state =
75 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
78 ZERO_STRUCTP(r->out.return_credentials);
81 talloc_free(pipe_state);
82 dce_call->context->private_data = NULL;
85 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
86 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
88 pipe_state->client_challenge = *r->in.credentials;
90 generate_random_buffer(pipe_state->server_challenge.data,
91 sizeof(pipe_state->server_challenge.data));
93 *r->out.return_credentials = pipe_state->server_challenge;
95 dce_call->context->private_data = pipe_state;
97 ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
98 &pipe_state->client_challenge,
99 &pipe_state->server_challenge,
100 r->in.computer_name);
101 if (!NT_STATUS_IS_OK(ntstatus)) {
109 * Do the actual processing of a netr_ServerAuthenticate3 message.
110 * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
112 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
113 struct dcesrv_call_state *dce_call,
115 struct netr_ServerAuthenticate3 *r,
116 const char **trust_account_for_search,
117 const char **trust_account_in_db,
118 struct dom_sid **sid)
120 struct netlogon_server_pipe_state *pipe_state =
121 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
122 bool challenge_valid = false;
123 struct netlogon_server_pipe_state challenge;
124 struct netlogon_creds_CredentialState *creds;
125 struct ldb_context *sam_ctx;
126 struct samr_Password *curNtHash = NULL;
127 struct samr_Password *prevNtHash = NULL;
128 uint32_t user_account_control;
130 struct ldb_message **msgs;
132 const char *attrs[] = {"unicodePwd", "userAccountControl",
133 "objectSid", "samAccountName", NULL};
134 uint32_t server_flags = 0;
135 uint32_t negotiate_flags = 0;
136 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
137 bool reject_des_client = !allow_nt4_crypto;
138 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
139 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
140 bool reject_none_rpc = (schannel == true);
142 ZERO_STRUCTP(r->out.return_credentials);
145 if (pipe_state != NULL) {
146 dce_call->context->private_data = NULL;
149 * If we had a challenge remembered on the connection
150 * consider this for usage. This can't be cleanup
153 * This is the default code path for typical clients
154 * which call netr_ServerReqChallenge() and
155 * netr_ServerAuthenticate3() on the same dcerpc connection.
157 challenge = *pipe_state;
159 challenge_valid = true;
165 * Fallback and try to get the challenge from
168 * If too many clients are using this code path,
169 * they may destroy their cache entries as the
170 * TDB has a fixed size limited via a lossy hash
172 * The TDB used is the schannel store, which is
173 * initialised at startup.
175 * NOTE: The challenge is deleted from the DB as soon as it is
176 * fetched, to prevent reuse.
180 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
181 &challenge.client_challenge,
182 &challenge.server_challenge,
183 r->in.computer_name);
185 if (!NT_STATUS_IS_OK(ntstatus)) {
186 ZERO_STRUCT(challenge);
188 challenge_valid = true;
192 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
193 NETLOGON_NEG_PERSISTENT_SAMREPL |
194 NETLOGON_NEG_ARCFOUR |
195 NETLOGON_NEG_PROMOTION_COUNT |
196 NETLOGON_NEG_CHANGELOG_BDC |
197 NETLOGON_NEG_FULL_SYNC_REPL |
198 NETLOGON_NEG_MULTIPLE_SIDS |
200 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
201 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
202 NETLOGON_NEG_GENERIC_PASSTHROUGH |
203 NETLOGON_NEG_CONCURRENT_RPC |
204 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
205 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
206 NETLOGON_NEG_STRONG_KEYS |
207 NETLOGON_NEG_TRANSITIVE_TRUSTS |
208 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
209 NETLOGON_NEG_PASSWORD_SET2 |
210 NETLOGON_NEG_GETDOMAININFO |
211 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
212 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
213 NETLOGON_NEG_RODC_PASSTHROUGH |
214 NETLOGON_NEG_SUPPORTS_AES |
215 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
216 NETLOGON_NEG_AUTHENTICATED_RPC;
218 negotiate_flags = *r->in.negotiate_flags & server_flags;
220 if (negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
221 reject_none_rpc = false;
224 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
225 reject_des_client = false;
228 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
229 reject_des_client = false;
230 reject_md5_client = false;
233 if (reject_des_client || reject_md5_client) {
235 * Here we match Windows 2012 and return no flags.
237 *r->out.negotiate_flags = 0;
238 return NT_STATUS_DOWNGRADE_DETECTED;
242 * This talloc_free is important to prevent re-use of the
243 * challenge. We have to delay it this far due to NETApp
245 * https://bugzilla.samba.org/show_bug.cgi?id=11291
247 TALLOC_FREE(pipe_state);
250 * At this point we must also cleanup the TDB cache
251 * entry, if we fail the client needs to call
252 * netr_ServerReqChallenge again.
254 * Note: this handles a non existing record just fine,
255 * the r->in.computer_name might not be the one used
256 * in netr_ServerReqChallenge(), but we are trying to
257 * just tidy up the normal case to prevent re-use.
259 schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
260 r->in.computer_name);
263 * According to Microsoft (see bugid #6099)
264 * Windows 7 looks at the negotiate_flags
265 * returned in this structure *even if the
266 * call fails with access denied!
268 *r->out.negotiate_flags = negotiate_flags;
270 if (reject_none_rpc) {
271 /* schannel must be used, but client did not offer it. */
272 DEBUG(0,("%s: schannel required but client failed "
273 "to offer it. Client was %s\n",
275 log_escape(mem_ctx, r->in.account_name)));
276 return NT_STATUS_ACCESS_DENIED;
279 switch (r->in.secure_channel_type) {
281 case SEC_CHAN_DNS_DOMAIN:
282 case SEC_CHAN_DOMAIN:
287 return NT_STATUS_INVALID_PARAMETER;
289 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
290 r->in.secure_channel_type));
291 return NT_STATUS_INVALID_PARAMETER;
294 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
295 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
296 if (sam_ctx == NULL) {
297 return NT_STATUS_INVALID_SYSTEM_SERVICE;
300 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
301 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
303 struct ldb_message *tdo_msg = NULL;
304 const char * const tdo_attrs[] = {
310 char *encoded_name = NULL;
312 const char *flatname = NULL;
314 bool require_trailer = true;
315 const char *netbios = NULL;
316 const char *dns = NULL;
318 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
320 require_trailer = false;
323 encoded_name = ldb_binary_encode_string(mem_ctx,
325 if (encoded_name == NULL) {
326 return NT_STATUS_NO_MEMORY;
329 len = strlen(encoded_name);
331 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
334 if (require_trailer && encoded_name[len - 1] != trailer) {
335 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
337 encoded_name[len - 1] = '\0';
339 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
342 netbios = encoded_name;
345 nt_status = dsdb_trust_search_tdo(sam_ctx,
347 tdo_attrs, mem_ctx, &tdo_msg);
348 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
349 DEBUG(2, ("Client asked for a trusted domain secure channel, "
350 "but there's no tdo for [%s] => [%s] \n",
351 log_escape(mem_ctx, r->in.account_name),
353 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
355 if (!NT_STATUS_IS_OK(nt_status)) {
359 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
362 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
363 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
365 if (!NT_STATUS_IS_OK(nt_status)) {
369 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
370 if (flatname == NULL) {
371 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
374 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
375 if (*trust_account_for_search == NULL) {
376 return NT_STATUS_NO_MEMORY;
379 *trust_account_for_search = r->in.account_name;
382 /* pull the user attributes */
383 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
384 "(&(sAMAccountName=%s)(objectclass=user))",
385 ldb_binary_encode_string(mem_ctx,
386 *trust_account_for_search));
388 if (num_records == 0) {
389 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
390 log_escape(mem_ctx, r->in.account_name)));
391 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
394 if (num_records > 1) {
395 DEBUG(0,("Found %d records matching user [%s]\n",
397 log_escape(mem_ctx, r->in.account_name)));
398 return NT_STATUS_INTERNAL_DB_CORRUPTION;
401 *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
404 if (*trust_account_in_db == NULL) {
405 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
406 r->in.account_name));
407 return NT_STATUS_INTERNAL_DB_CORRUPTION;
410 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
412 if (user_account_control & UF_ACCOUNTDISABLE) {
413 DEBUG(1, ("Account [%s] is disabled\n",
414 log_escape(mem_ctx, r->in.account_name)));
415 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
418 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
419 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
420 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
421 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
423 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
424 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
425 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
426 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
428 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
430 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
431 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
432 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
433 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
435 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
436 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
437 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
438 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
441 /* we should never reach this */
442 return NT_STATUS_INTERNAL_ERROR;
445 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
446 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
447 dce_call->conn->dce_ctx->lp_ctx,
448 msgs[0], NULL, &curNtHash);
449 if (!NT_STATUS_IS_OK(nt_status)) {
450 return NT_STATUS_ACCESS_DENIED;
454 if (curNtHash == NULL) {
455 return NT_STATUS_ACCESS_DENIED;
458 if (!challenge_valid) {
459 DEBUG(1, ("No challenge requested by client [%s/%s], "
460 "cannot authenticate\n",
461 log_escape(mem_ctx, r->in.computer_name),
462 log_escape(mem_ctx, r->in.account_name)));
463 return NT_STATUS_ACCESS_DENIED;
466 creds = netlogon_creds_server_init(mem_ctx,
469 r->in.secure_channel_type,
470 &challenge.client_challenge,
471 &challenge.server_challenge,
474 r->out.return_credentials,
476 if (creds == NULL && prevNtHash != NULL) {
478 * We fallback to the previous password for domain trusts.
480 * Note that lpcfg_old_password_allowed_period() doesn't
483 creds = netlogon_creds_server_init(mem_ctx,
486 r->in.secure_channel_type,
487 &challenge.client_challenge,
488 &challenge.server_challenge,
491 r->out.return_credentials,
496 return NT_STATUS_ACCESS_DENIED;
498 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
499 *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
501 nt_status = schannel_save_creds_state(mem_ctx,
502 dce_call->conn->dce_ctx->lp_ctx,
504 if (!NT_STATUS_IS_OK(nt_status)) {
505 ZERO_STRUCTP(r->out.return_credentials);
509 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
516 * Log a netr_ServerAuthenticate3 request, and then invoke
517 * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
519 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
520 struct dcesrv_call_state *dce_call,
522 struct netr_ServerAuthenticate3 *r)
525 struct dom_sid *sid = NULL;
526 const char *trust_account_for_search = NULL;
527 const char *trust_account_in_db = NULL;
528 struct auth_usersupplied_info ui = {
529 .local_host = dce_call->conn->local_address,
530 .remote_host = dce_call->conn->remote_address,
532 .account_name = r->in.account_name,
533 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
535 .service_description = "NETLOGON",
536 .auth_description = "ServerAuthenticate",
537 .netlogon_trust_account = {
538 .computer_name = r->in.computer_name,
539 .negotiate_flags = *r->in.negotiate_flags,
540 .secure_channel_type = r->in.secure_channel_type,
544 status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
547 &trust_account_for_search,
548 &trust_account_in_db,
550 ui.netlogon_trust_account.sid = sid;
551 ui.netlogon_trust_account.account_name = trust_account_in_db;
552 ui.mapped.account_name = trust_account_for_search;
553 log_authentication_event(
554 dce_call->conn->msg_ctx,
555 dce_call->conn->dce_ctx->lp_ctx,
558 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
565 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
566 struct netr_ServerAuthenticate *r)
568 struct netr_ServerAuthenticate3 a;
571 * negotiate_flags is used as an [in] parameter
572 * so it need to be initialised.
574 * (I think ... = 0; seems wrong here --metze)
576 uint32_t negotiate_flags_in = 0;
577 uint32_t negotiate_flags_out = 0;
579 a.in.server_name = r->in.server_name;
580 a.in.account_name = r->in.account_name;
581 a.in.secure_channel_type = r->in.secure_channel_type;
582 a.in.computer_name = r->in.computer_name;
583 a.in.credentials = r->in.credentials;
584 a.in.negotiate_flags = &negotiate_flags_in;
586 a.out.return_credentials = r->out.return_credentials;
588 a.out.negotiate_flags = &negotiate_flags_out;
590 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
593 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
594 struct netr_ServerAuthenticate2 *r)
596 struct netr_ServerAuthenticate3 r3;
599 r3.in.server_name = r->in.server_name;
600 r3.in.account_name = r->in.account_name;
601 r3.in.secure_channel_type = r->in.secure_channel_type;
602 r3.in.computer_name = r->in.computer_name;
603 r3.in.credentials = r->in.credentials;
604 r3.out.return_credentials = r->out.return_credentials;
605 r3.in.negotiate_flags = r->in.negotiate_flags;
606 r3.out.negotiate_flags = r->out.negotiate_flags;
609 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
613 * NOTE: The following functions are nearly identical to the ones available in
614 * source3/rpc_server/srv_nelog_nt.c
615 * The reason we keep 2 copies is that they use different structures to
616 * represent the auth_info and the decrpc pipes.
620 * If schannel is required for this call test that it actually is available.
622 static NTSTATUS schannel_check_required(const struct dcesrv_auth *auth_info,
623 const char *computer_name,
624 bool integrity, bool privacy)
627 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
628 if (!privacy && !integrity) {
632 if ((!privacy && integrity) &&
633 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
637 if ((privacy || integrity) &&
638 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
643 /* test didn't pass */
644 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
647 return NT_STATUS_ACCESS_DENIED;
650 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
652 const char *computer_name,
653 struct netr_Authenticator *received_authenticator,
654 struct netr_Authenticator *return_authenticator,
655 struct netlogon_creds_CredentialState **creds_out)
658 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
659 bool schannel_global_required = (schannel == true);
661 if (schannel_global_required) {
662 nt_status = schannel_check_required(&dce_call->conn->auth_state,
665 if (!NT_STATUS_IS_OK(nt_status)) {
670 nt_status = schannel_check_creds_state(mem_ctx,
671 dce_call->conn->dce_ctx->lp_ctx,
673 received_authenticator,
674 return_authenticator,
680 Change the machine account password for the currently connected
681 client. Supplies only the NT#.
684 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
685 struct netr_ServerPasswordSet *r)
687 struct netlogon_creds_CredentialState *creds;
688 struct ldb_context *sam_ctx;
689 const char * const attrs[] = { "unicodePwd", NULL };
690 struct ldb_message **res;
691 struct samr_Password *oldNtHash;
695 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
698 r->in.credential, r->out.return_authenticator,
700 NT_STATUS_NOT_OK_RETURN(nt_status);
702 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
703 if (sam_ctx == NULL) {
704 return NT_STATUS_INVALID_SYSTEM_SERVICE;
707 netlogon_creds_des_decrypt(creds, r->in.new_password);
709 /* fetch the old password hashes (the NT hash has to exist) */
711 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
712 "(&(objectClass=user)(objectSid=%s))",
713 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
715 return NT_STATUS_WRONG_PASSWORD;
718 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
719 dce_call->conn->dce_ctx->lp_ctx,
720 res[0], NULL, &oldNtHash);
721 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
722 return NT_STATUS_WRONG_PASSWORD;
725 /* Using the sid for the account as the key, set the password */
726 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
728 NULL, /* Don't have version */
729 NULL, /* Don't have plaintext */
730 NULL, r->in.new_password,
731 NULL, oldNtHash, /* Password change */
737 Change the machine account password for the currently connected
738 client. Supplies new plaintext.
740 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
741 struct netr_ServerPasswordSet2 *r)
743 struct netlogon_creds_CredentialState *creds;
744 struct ldb_context *sam_ctx;
745 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
746 struct ldb_message **res;
747 struct samr_Password *oldLmHash, *oldNtHash;
748 struct NL_PASSWORD_VERSION version = {};
749 const uint32_t *new_version = NULL;
751 DATA_BLOB new_password;
753 struct samr_CryptPassword password_buf;
755 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
758 r->in.credential, r->out.return_authenticator,
760 NT_STATUS_NOT_OK_RETURN(nt_status);
762 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
763 if (sam_ctx == NULL) {
764 return NT_STATUS_INVALID_SYSTEM_SERVICE;
767 memcpy(password_buf.data, r->in.new_password->data, 512);
768 SIVAL(password_buf.data, 512, r->in.new_password->length);
770 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
771 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
773 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
776 switch (creds->secure_channel_type) {
777 case SEC_CHAN_DOMAIN:
778 case SEC_CHAN_DNS_DOMAIN: {
779 uint32_t len = IVAL(password_buf.data, 512);
781 uint32_t ofs = 500 - len;
784 p = password_buf.data + ofs;
786 version.ReservedField = IVAL(p, 0);
787 version.PasswordVersionNumber = IVAL(p, 4);
788 version.PasswordVersionPresent = IVAL(p, 8);
790 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
791 new_version = &version.PasswordVersionNumber;
799 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
800 DEBUG(3,("samr: failed to decode password buffer\n"));
801 return NT_STATUS_WRONG_PASSWORD;
804 /* fetch the old password hashes (at least one of both has to exist) */
806 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
807 "(&(objectClass=user)(objectSid=%s))",
808 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
810 return NT_STATUS_WRONG_PASSWORD;
813 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
814 dce_call->conn->dce_ctx->lp_ctx,
815 res[0], &oldLmHash, &oldNtHash);
816 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
817 return NT_STATUS_WRONG_PASSWORD;
820 /* Using the sid for the account as the key, set the password */
821 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
824 &new_password, /* we have plaintext */
826 oldLmHash, oldNtHash, /* Password change */
835 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
836 struct netr_LogonUasLogon *r)
838 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
845 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
846 struct netr_LogonUasLogoff *r)
848 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
852 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
853 const struct netr_LogonSamLogonEx *r)
855 switch (r->in.logon_level) {
856 case NetlogonInteractiveInformation:
857 case NetlogonServiceInformation:
858 case NetlogonInteractiveTransitiveInformation:
859 case NetlogonServiceTransitiveInformation:
860 if (r->in.logon->password == NULL) {
861 return NT_STATUS_INVALID_PARAMETER;
864 switch (r->in.validation_level) {
865 case NetlogonValidationSamInfo: /* 2 */
866 case NetlogonValidationSamInfo2: /* 3 */
867 case NetlogonValidationSamInfo4: /* 6 */
870 return NT_STATUS_INVALID_INFO_CLASS;
874 case NetlogonNetworkInformation:
875 case NetlogonNetworkTransitiveInformation:
876 if (r->in.logon->network == NULL) {
877 return NT_STATUS_INVALID_PARAMETER;
880 switch (r->in.validation_level) {
881 case NetlogonValidationSamInfo: /* 2 */
882 case NetlogonValidationSamInfo2: /* 3 */
883 case NetlogonValidationSamInfo4: /* 6 */
886 return NT_STATUS_INVALID_INFO_CLASS;
891 case NetlogonGenericInformation:
892 if (r->in.logon->generic == NULL) {
893 return NT_STATUS_INVALID_PARAMETER;
896 switch (r->in.validation_level) {
897 /* TODO: case NetlogonValidationGenericInfo: 4 */
898 case NetlogonValidationGenericInfo2: /* 5 */
901 return NT_STATUS_INVALID_INFO_CLASS;
906 return NT_STATUS_INVALID_PARAMETER;
909 switch (r->in.validation_level) {
910 case NetlogonValidationSamInfo4: /* 6 */
911 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
912 return NT_STATUS_INVALID_PARAMETER;
923 struct dcesrv_netr_LogonSamLogon_base_state {
924 struct dcesrv_call_state *dce_call;
928 struct netlogon_creds_CredentialState *creds;
930 struct netr_LogonSamLogonEx r;
932 uint32_t _ignored_flags;
935 struct netr_LogonSamLogon *lsl;
936 struct netr_LogonSamLogonWithFlags *lslwf;
937 struct netr_LogonSamLogonEx *lslex;
940 struct kdc_check_generic_kerberos kr;
943 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
944 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
945 static void dcesrv_netr_LogonSamLogon_base_reply(
946 struct dcesrv_netr_LogonSamLogon_base_state *state);
949 netr_LogonSamLogon_base
951 This version of the function allows other wrappers to say 'do not check the credentials'
953 We can't do the traditional 'wrapping' format completely, as this
954 function must only run under schannel
956 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
958 struct dcesrv_call_state *dce_call = state->dce_call;
959 TALLOC_CTX *mem_ctx = state->mem_ctx;
960 struct netr_LogonSamLogonEx *r = &state->r;
961 struct netlogon_creds_CredentialState *creds = state->creds;
962 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
963 const char *workgroup = lpcfg_workgroup(lp_ctx);
964 struct auth4_context *auth_context = NULL;
965 struct auth_usersupplied_info *user_info = NULL;
967 struct tevent_req *subreq = NULL;
969 *r->out.authoritative = 1;
971 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
973 * Currently we're always the forest root ourself.
975 return NT_STATUS_NO_SUCH_USER;
978 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
980 * Currently we don't support trusts correctly yet.
982 return NT_STATUS_NO_SUCH_USER;
985 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
986 NT_STATUS_HAVE_NO_MEMORY(user_info);
988 user_info->service_description = "SamLogon";
990 netlogon_creds_decrypt_samlogon_logon(creds,
994 switch (r->in.logon_level) {
995 case NetlogonInteractiveInformation:
996 case NetlogonServiceInformation:
997 case NetlogonInteractiveTransitiveInformation:
998 case NetlogonServiceTransitiveInformation:
999 case NetlogonNetworkInformation:
1000 case NetlogonNetworkTransitiveInformation:
1002 nt_status = auth_context_create_for_netlogon(mem_ctx,
1003 dce_call->event_ctx, dce_call->msg_ctx,
1004 dce_call->conn->dce_ctx->lp_ctx,
1006 NT_STATUS_NOT_OK_RETURN(nt_status);
1008 user_info->remote_host = dce_call->conn->remote_address;
1009 user_info->local_host = dce_call->conn->local_address;
1011 user_info->netlogon_trust_account.secure_channel_type
1012 = creds->secure_channel_type;
1013 user_info->netlogon_trust_account.negotiate_flags
1014 = creds->negotiate_flags;
1017 * These two can be unrelated when the account is
1018 * actually that of a trusted domain, so we want to
1019 * know which DC in that trusted domain contacted
1022 user_info->netlogon_trust_account.computer_name
1023 = creds->computer_name;
1024 user_info->netlogon_trust_account.account_name
1025 = creds->account_name;
1026 user_info->netlogon_trust_account.sid
1030 /* We do not need to set up the user_info in this case */
1034 switch (r->in.logon_level) {
1035 case NetlogonInteractiveInformation:
1036 case NetlogonServiceInformation:
1037 case NetlogonInteractiveTransitiveInformation:
1038 case NetlogonServiceTransitiveInformation:
1039 user_info->auth_description = "interactive";
1041 user_info->logon_parameters
1042 = r->in.logon->password->identity_info.parameter_control;
1043 user_info->client.account_name
1044 = r->in.logon->password->identity_info.account_name.string;
1045 user_info->client.domain_name
1046 = r->in.logon->password->identity_info.domain_name.string;
1047 user_info->workstation_name
1048 = r->in.logon->password->identity_info.workstation.string;
1049 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1050 user_info->password_state = AUTH_PASSWORD_HASH;
1052 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1053 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1054 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1056 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1057 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1058 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1061 case NetlogonNetworkInformation:
1062 case NetlogonNetworkTransitiveInformation:
1063 user_info->auth_description = "network";
1065 nt_status = auth_context_set_challenge(
1067 r->in.logon->network->challenge,
1068 "netr_LogonSamLogonWithFlags");
1069 NT_STATUS_NOT_OK_RETURN(nt_status);
1071 user_info->logon_parameters
1072 = r->in.logon->network->identity_info.parameter_control;
1073 user_info->client.account_name
1074 = r->in.logon->network->identity_info.account_name.string;
1075 user_info->client.domain_name
1076 = r->in.logon->network->identity_info.domain_name.string;
1077 user_info->workstation_name
1078 = r->in.logon->network->identity_info.workstation.string;
1080 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1081 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1082 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1084 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1085 user_info->client.account_name,
1086 user_info->client.domain_name,
1087 user_info->password.response.nt,
1089 NT_STATUS_NOT_OK_RETURN(nt_status);
1094 case NetlogonGenericInformation:
1096 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1098 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1101 /* Using DES to verify kerberos tickets makes no sense */
1102 return NT_STATUS_INVALID_PARAMETER;
1105 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1106 struct dcerpc_binding_handle *irpc_handle;
1107 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1108 NT_STATUS_HAVE_NO_MEMORY(generic);
1110 r->out.validation->generic = generic;
1112 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1116 if (irpc_handle == NULL) {
1117 return NT_STATUS_NO_LOGON_SERVERS;
1120 state->kr.in.generic_request =
1121 data_blob_const(r->in.logon->generic->data,
1122 r->in.logon->generic->length);
1125 * 60 seconds should be enough
1127 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1128 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1129 state->dce_call->event_ctx,
1130 irpc_handle, &state->kr);
1131 if (subreq == NULL) {
1132 return NT_STATUS_NO_MEMORY;
1134 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1135 tevent_req_set_callback(subreq,
1136 dcesrv_netr_LogonSamLogon_base_krb5_done,
1138 return NT_STATUS_OK;
1141 /* Until we get an implemetnation of these other packages */
1142 return NT_STATUS_INVALID_PARAMETER;
1145 return NT_STATUS_INVALID_PARAMETER;
1148 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1149 auth_context, user_info);
1150 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1151 tevent_req_set_callback(subreq,
1152 dcesrv_netr_LogonSamLogon_base_auth_done,
1154 return NT_STATUS_OK;
1157 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1159 struct dcesrv_netr_LogonSamLogon_base_state *state =
1160 tevent_req_callback_data(subreq,
1161 struct dcesrv_netr_LogonSamLogon_base_state);
1162 TALLOC_CTX *mem_ctx = state->mem_ctx;
1163 struct netr_LogonSamLogonEx *r = &state->r;
1164 struct auth_user_info_dc *user_info_dc = NULL;
1165 struct netr_SamInfo2 *sam2 = NULL;
1166 struct netr_SamInfo3 *sam3 = NULL;
1167 struct netr_SamInfo6 *sam6 = NULL;
1170 nt_status = auth_check_password_recv(subreq, mem_ctx,
1172 r->out.authoritative);
1173 TALLOC_FREE(subreq);
1174 if (!NT_STATUS_IS_OK(nt_status)) {
1175 r->out.result = nt_status;
1176 dcesrv_netr_LogonSamLogon_base_reply(state);
1180 switch (r->in.validation_level) {
1182 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1185 if (!NT_STATUS_IS_OK(nt_status)) {
1186 r->out.result = nt_status;
1187 dcesrv_netr_LogonSamLogon_base_reply(state);
1191 r->out.validation->sam2 = sam2;
1195 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1198 if (!NT_STATUS_IS_OK(nt_status)) {
1199 r->out.result = nt_status;
1200 dcesrv_netr_LogonSamLogon_base_reply(state);
1204 r->out.validation->sam3 = sam3;
1208 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1211 if (!NT_STATUS_IS_OK(nt_status)) {
1212 r->out.result = nt_status;
1213 dcesrv_netr_LogonSamLogon_base_reply(state);
1217 r->out.validation->sam6 = sam6;
1221 if (!NT_STATUS_IS_OK(nt_status)) {
1222 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1223 dcesrv_netr_LogonSamLogon_base_reply(state);
1228 /* TODO: Describe and deal with these flags */
1231 r->out.result = NT_STATUS_OK;
1233 dcesrv_netr_LogonSamLogon_base_reply(state);
1236 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1238 struct dcesrv_netr_LogonSamLogon_base_state *state =
1239 tevent_req_callback_data(subreq,
1240 struct dcesrv_netr_LogonSamLogon_base_state);
1241 TALLOC_CTX *mem_ctx = state->mem_ctx;
1242 struct netr_LogonSamLogonEx *r = &state->r;
1243 struct netr_GenericInfo2 *generic = NULL;
1246 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1247 TALLOC_FREE(subreq);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 r->out.result = status;
1250 dcesrv_netr_LogonSamLogon_base_reply(state);
1254 generic = r->out.validation->generic;
1255 generic->length = state->kr.out.generic_reply.length;
1256 generic->data = state->kr.out.generic_reply.data;
1258 /* TODO: Describe and deal with these flags */
1261 r->out.result = NT_STATUS_OK;
1263 dcesrv_netr_LogonSamLogon_base_reply(state);
1266 static void dcesrv_netr_LogonSamLogon_base_reply(
1267 struct dcesrv_netr_LogonSamLogon_base_state *state)
1269 struct netr_LogonSamLogonEx *r = &state->r;
1272 if (NT_STATUS_IS_OK(r->out.result)) {
1273 netlogon_creds_encrypt_samlogon_validation(state->creds,
1274 r->in.validation_level,
1278 if (state->_r.lslex != NULL) {
1279 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1280 _r->out.result = r->out.result;
1281 } else if (state->_r.lslwf != NULL) {
1282 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1283 _r->out.result = r->out.result;
1284 } else if (state->_r.lsl != NULL) {
1285 struct netr_LogonSamLogon *_r = state->_r.lsl;
1286 _r->out.result = r->out.result;
1289 status = dcesrv_reply(state->dce_call);
1290 if (!NT_STATUS_IS_OK(status)) {
1291 DBG_ERR("dcesrv_reply() failed - %s\n",
1296 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1297 struct netr_LogonSamLogonEx *r)
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 if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1337 return NT_STATUS_ACCESS_DENIED;
1340 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1342 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1350 netr_LogonSamLogonWithFlags
1353 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1354 struct netr_LogonSamLogonWithFlags *r)
1356 struct dcesrv_netr_LogonSamLogon_base_state *state;
1359 *r->out.authoritative = 1;
1361 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1362 if (state == NULL) {
1363 return NT_STATUS_NO_MEMORY;
1366 state->dce_call = dce_call;
1367 state->mem_ctx = mem_ctx;
1369 state->r.in.server_name = r->in.server_name;
1370 state->r.in.computer_name = r->in.computer_name;
1371 state->r.in.logon_level = r->in.logon_level;
1372 state->r.in.logon = r->in.logon;
1373 state->r.in.validation_level = r->in.validation_level;
1374 state->r.in.flags = r->in.flags;
1375 state->r.out.validation = r->out.validation;
1376 state->r.out.authoritative = r->out.authoritative;
1377 state->r.out.flags = r->out.flags;
1379 state->_r.lslwf = r;
1381 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1382 if (!NT_STATUS_IS_OK(nt_status)) {
1386 r->out.return_authenticator = talloc_zero(mem_ctx,
1387 struct netr_Authenticator);
1388 if (r->out.return_authenticator == NULL) {
1389 return NT_STATUS_NO_MEMORY;
1392 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1394 r->in.computer_name,
1396 r->out.return_authenticator,
1398 if (!NT_STATUS_IS_OK(nt_status)) {
1402 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1404 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1414 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1415 struct netr_LogonSamLogon *r)
1417 struct dcesrv_netr_LogonSamLogon_base_state *state;
1420 *r->out.authoritative = 1;
1422 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1423 if (state == NULL) {
1424 return NT_STATUS_NO_MEMORY;
1427 state->dce_call = dce_call;
1428 state->mem_ctx = mem_ctx;
1430 state->r.in.server_name = r->in.server_name;
1431 state->r.in.computer_name = r->in.computer_name;
1432 state->r.in.logon_level = r->in.logon_level;
1433 state->r.in.logon = r->in.logon;
1434 state->r.in.validation_level = r->in.validation_level;
1435 state->r.in.flags = &state->_ignored_flags;
1436 state->r.out.validation = r->out.validation;
1437 state->r.out.authoritative = r->out.authoritative;
1438 state->r.out.flags = &state->_ignored_flags;
1442 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1443 if (!NT_STATUS_IS_OK(nt_status)) {
1447 r->out.return_authenticator = talloc_zero(mem_ctx,
1448 struct netr_Authenticator);
1449 if (r->out.return_authenticator == NULL) {
1450 return NT_STATUS_NO_MEMORY;
1453 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1455 r->in.computer_name,
1457 r->out.return_authenticator,
1459 if (!NT_STATUS_IS_OK(nt_status)) {
1463 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1465 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1476 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1477 struct netr_LogonSamLogoff *r)
1479 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1487 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1488 struct netr_DatabaseDeltas *r)
1490 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1497 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1498 struct netr_DatabaseSync2 *r)
1500 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1501 return NT_STATUS_NOT_IMPLEMENTED;
1508 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1509 struct netr_DatabaseSync *r)
1511 struct netr_DatabaseSync2 r2;
1516 r2.in.logon_server = r->in.logon_server;
1517 r2.in.computername = r->in.computername;
1518 r2.in.credential = r->in.credential;
1519 r2.in.database_id = r->in.database_id;
1520 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1521 r2.in.sync_context = r->in.sync_context;
1522 r2.out.sync_context = r->out.sync_context;
1523 r2.out.delta_enum_array = r->out.delta_enum_array;
1524 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1526 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1535 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1536 struct netr_AccountDeltas *r)
1538 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1539 return NT_STATUS_NOT_IMPLEMENTED;
1546 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1547 struct netr_AccountSync *r)
1549 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1550 return NT_STATUS_NOT_IMPLEMENTED;
1557 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1558 struct netr_GetDcName *r)
1560 const char * const attrs[] = { NULL };
1561 struct ldb_context *sam_ctx;
1562 struct ldb_message **res;
1563 struct ldb_dn *domain_dn;
1568 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1569 * that the domainname needs to be a valid netbios domain
1570 * name, if it is not NULL.
1572 if (r->in.domainname) {
1573 const char *dot = strchr(r->in.domainname, '.');
1574 size_t len = strlen(r->in.domainname);
1576 if (dot || len > 15) {
1577 return WERR_NERR_DCNOTFOUND;
1581 * TODO: Should we also varify that only valid
1582 * netbios name characters are used?
1586 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1587 dce_call->conn->dce_ctx->lp_ctx,
1588 dce_call->conn->auth_state.session_info, 0);
1589 if (sam_ctx == NULL) {
1590 return WERR_DS_UNAVAILABLE;
1593 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1595 if (domain_dn == NULL) {
1596 return WERR_NO_SUCH_DOMAIN;
1599 ret = gendb_search_dn(sam_ctx, mem_ctx,
1600 domain_dn, &res, attrs);
1602 return WERR_NO_SUCH_DOMAIN;
1605 /* TODO: - return real IP address
1606 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1608 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1609 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1610 W_ERROR_HAVE_NO_MEMORY(dcname);
1612 *r->out.dcname = dcname;
1616 struct dcesrv_netr_LogonControl_base_state {
1617 struct dcesrv_call_state *dce_call;
1619 TALLOC_CTX *mem_ctx;
1621 struct netr_LogonControl2Ex r;
1624 struct netr_LogonControl *l;
1625 struct netr_LogonControl2 *l2;
1626 struct netr_LogonControl2Ex *l2ex;
1630 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1632 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1634 struct dcesrv_connection *conn = state->dce_call->conn;
1635 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1636 struct auth_session_info *session_info = conn->auth_state.session_info;
1637 enum security_user_level security_level;
1638 struct dcerpc_binding_handle *irpc_handle;
1639 struct tevent_req *subreq;
1642 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1644 if (state->_r.l != NULL) {
1648 if (state->r.in.level == 0x00000002) {
1649 return WERR_NOT_SUPPORTED;
1650 } else if (state->r.in.level != 0x00000001) {
1651 return WERR_INVALID_LEVEL;
1654 switch (state->r.in.function_code) {
1655 case NETLOGON_CONTROL_QUERY:
1656 case NETLOGON_CONTROL_REPLICATE:
1657 case NETLOGON_CONTROL_SYNCHRONIZE:
1658 case NETLOGON_CONTROL_PDC_REPLICATE:
1659 case NETLOGON_CONTROL_BREAKPOINT:
1660 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1661 case NETLOGON_CONTROL_TRUNCATE_LOG:
1664 return WERR_NOT_SUPPORTED;
1668 if (state->r.in.level < 0x00000001) {
1669 return WERR_INVALID_LEVEL;
1672 if (state->r.in.level > 0x00000004) {
1673 return WERR_INVALID_LEVEL;
1676 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1677 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1678 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1680 switch (state->r.in.level) {
1682 info1 = talloc_zero(state->mem_ctx,
1683 struct netr_NETLOGON_INFO_1);
1684 if (info1 == NULL) {
1685 return WERR_NOT_ENOUGH_MEMORY;
1687 state->r.out.query->info1 = info1;
1691 info3 = talloc_zero(state->mem_ctx,
1692 struct netr_NETLOGON_INFO_3);
1693 if (info3 == NULL) {
1694 return WERR_NOT_ENOUGH_MEMORY;
1696 state->r.out.query->info3 = info3;
1700 return WERR_INVALID_PARAMETER;
1705 * Some validations are done before the access check
1706 * and some after the access check
1708 security_level = security_session_user_level(session_info, NULL);
1709 if (security_level < SECURITY_ADMINISTRATOR) {
1710 return WERR_ACCESS_DENIED;
1713 if (state->_r.l2 != NULL) {
1715 * netr_LogonControl2
1717 if (state->r.in.level == 0x00000004) {
1718 return WERR_INVALID_LEVEL;
1722 switch (state->r.in.level) {
1727 switch (state->r.in.function_code) {
1728 case NETLOGON_CONTROL_REDISCOVER:
1729 case NETLOGON_CONTROL_TC_QUERY:
1730 case NETLOGON_CONTROL_TC_VERIFY:
1733 return WERR_INVALID_PARAMETER;
1742 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1743 return WERR_INVALID_PARAMETER;
1749 return WERR_INVALID_LEVEL;
1752 switch (state->r.in.function_code) {
1753 case NETLOGON_CONTROL_REDISCOVER:
1754 case NETLOGON_CONTROL_TC_QUERY:
1755 case NETLOGON_CONTROL_TC_VERIFY:
1756 if (state->r.in.level != 2) {
1757 return WERR_INVALID_PARAMETER;
1760 if (state->r.in.data == NULL) {
1761 return WERR_INVALID_PARAMETER;
1764 if (state->r.in.data->domain == NULL) {
1765 return WERR_INVALID_PARAMETER;
1770 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1771 if (state->r.in.level != 1) {
1772 return WERR_INVALID_PARAMETER;
1775 if (state->r.in.data == NULL) {
1776 return WERR_INVALID_PARAMETER;
1779 if (state->r.in.data->domain == NULL) {
1780 return WERR_INVALID_PARAMETER;
1783 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1784 state->r.in.data->domain);
1786 struct ldb_context *sam_ctx;
1788 sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1789 lp_ctx, system_session(lp_ctx), 0);
1790 if (sam_ctx == NULL) {
1791 return WERR_DS_UNAVAILABLE;
1795 * Secrets for trusted domains can only be triggered on
1798 ok = samdb_is_pdc(sam_ctx);
1799 TALLOC_FREE(sam_ctx);
1801 return WERR_INVALID_DOMAIN_ROLE;
1807 return WERR_NOT_SUPPORTED;
1810 irpc_handle = irpc_binding_handle_by_name(state,
1811 state->dce_call->msg_ctx,
1813 &ndr_table_winbind);
1814 if (irpc_handle == NULL) {
1815 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1816 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1817 return WERR_SERVICE_NOT_FOUND;
1821 * 60 seconds timeout should be enough
1823 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1825 subreq = dcerpc_winbind_LogonControl_send(state,
1826 state->dce_call->event_ctx,
1828 state->r.in.function_code,
1831 state->r.out.query);
1832 if (subreq == NULL) {
1833 return WERR_NOT_ENOUGH_MEMORY;
1835 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1836 tevent_req_set_callback(subreq,
1837 dcesrv_netr_LogonControl_base_done,
1843 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1845 struct dcesrv_netr_LogonControl_base_state *state =
1846 tevent_req_callback_data(subreq,
1847 struct dcesrv_netr_LogonControl_base_state);
1850 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1851 &state->r.out.result);
1852 TALLOC_FREE(subreq);
1853 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1854 state->r.out.result = WERR_TIMEOUT;
1855 } else if (!NT_STATUS_IS_OK(status)) {
1856 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1857 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1858 nt_errstr(status)));
1861 if (state->_r.l2ex != NULL) {
1862 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1863 r->out.result = state->r.out.result;
1864 } else if (state->_r.l2 != NULL) {
1865 struct netr_LogonControl2 *r = state->_r.l2;
1866 r->out.result = state->r.out.result;
1867 } else if (state->_r.l != NULL) {
1868 struct netr_LogonControl *r = state->_r.l;
1869 r->out.result = state->r.out.result;
1872 status = dcesrv_reply(state->dce_call);
1873 if (!NT_STATUS_IS_OK(status)) {
1874 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1881 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1882 struct netr_LogonControl *r)
1884 struct dcesrv_netr_LogonControl_base_state *state;
1887 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1888 if (state == NULL) {
1889 return WERR_NOT_ENOUGH_MEMORY;
1892 state->dce_call = dce_call;
1893 state->mem_ctx = mem_ctx;
1895 state->r.in.logon_server = r->in.logon_server;
1896 state->r.in.function_code = r->in.function_code;
1897 state->r.in.level = r->in.level;
1898 state->r.in.data = NULL;
1899 state->r.out.query = r->out.query;
1903 werr = dcesrv_netr_LogonControl_base_call(state);
1905 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1915 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1916 struct netr_LogonControl2 *r)
1918 struct dcesrv_netr_LogonControl_base_state *state;
1921 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1922 if (state == NULL) {
1923 return WERR_NOT_ENOUGH_MEMORY;
1926 state->dce_call = dce_call;
1927 state->mem_ctx = mem_ctx;
1929 state->r.in.logon_server = r->in.logon_server;
1930 state->r.in.function_code = r->in.function_code;
1931 state->r.in.level = r->in.level;
1932 state->r.in.data = r->in.data;
1933 state->r.out.query = r->out.query;
1937 werr = dcesrv_netr_LogonControl_base_call(state);
1939 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1947 netr_LogonControl2Ex
1949 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1950 struct netr_LogonControl2Ex *r)
1952 struct dcesrv_netr_LogonControl_base_state *state;
1955 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1956 if (state == NULL) {
1957 return WERR_NOT_ENOUGH_MEMORY;
1960 state->dce_call = dce_call;
1961 state->mem_ctx = mem_ctx;
1966 werr = dcesrv_netr_LogonControl_base_call(state);
1968 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1975 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1976 struct ldb_context *sam_ctx,
1977 struct netr_DomainTrustList *trusts,
1978 uint32_t trust_flags);
1983 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1984 struct netr_GetAnyDCName *r)
1986 struct netr_DomainTrustList *trusts;
1987 struct ldb_context *sam_ctx;
1988 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1992 *r->out.dcname = NULL;
1994 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1995 /* if the domainname parameter wasn't set assume our domain */
1996 r->in.domainname = lpcfg_workgroup(lp_ctx);
1999 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2000 dce_call->conn->auth_state.session_info, 0);
2001 if (sam_ctx == NULL) {
2002 return WERR_DS_UNAVAILABLE;
2005 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2006 /* well we asked for a DC of our own domain */
2007 if (samdb_is_pdc(sam_ctx)) {
2008 /* we are the PDC of the specified domain */
2009 return WERR_NO_SUCH_DOMAIN;
2012 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2013 lpcfg_netbios_name(lp_ctx));
2014 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2019 /* Okay, now we have to consider the trusted domains */
2021 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2022 W_ERROR_HAVE_NO_MEMORY(trusts);
2026 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2027 NETR_TRUST_FLAG_INBOUND
2028 | NETR_TRUST_FLAG_OUTBOUND);
2029 W_ERROR_NOT_OK_RETURN(werr);
2031 for (i = 0; i < trusts->count; i++) {
2032 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2033 /* FIXME: Here we need to find a DC for the specified
2034 * trusted domain. */
2036 /* return WERR_OK; */
2037 return WERR_NO_SUCH_DOMAIN;
2041 return WERR_NO_SUCH_DOMAIN;
2048 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2049 struct netr_DatabaseRedo *r)
2051 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2056 netr_NetrEnumerateTrustedDomains
2058 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2059 struct netr_NetrEnumerateTrustedDomains *r)
2061 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2066 netr_LogonGetCapabilities
2068 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2069 struct netr_LogonGetCapabilities *r)
2071 struct netlogon_creds_CredentialState *creds;
2074 status = dcesrv_netr_creds_server_step_check(dce_call,
2076 r->in.computer_name,
2078 r->out.return_authenticator,
2080 if (!NT_STATUS_IS_OK(status)) {
2081 DEBUG(0,(__location__ " Bad credentials - error\n"));
2083 NT_STATUS_NOT_OK_RETURN(status);
2085 if (r->in.query_level != 1) {
2086 return NT_STATUS_NOT_SUPPORTED;
2089 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2091 return NT_STATUS_OK;
2096 netr_NETRLOGONSETSERVICEBITS
2098 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2099 struct netr_NETRLOGONSETSERVICEBITS *r)
2101 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2106 netr_LogonGetTrustRid
2108 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2109 struct netr_LogonGetTrustRid *r)
2111 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2116 netr_NETRLOGONCOMPUTESERVERDIGEST
2118 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2119 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2121 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2126 netr_NETRLOGONCOMPUTECLIENTDIGEST
2128 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2129 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2131 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2139 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2140 struct netr_DsRGetSiteName *r)
2142 struct ldb_context *sam_ctx;
2143 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2145 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2146 dce_call->conn->auth_state.session_info, 0);
2147 if (sam_ctx == NULL) {
2148 return WERR_DS_UNAVAILABLE;
2152 * We assume to be a DC when we get called over NETLOGON. Hence we
2153 * get our site name always by using "samdb_server_site_name()"
2154 * and not "samdb_client_site_name()".
2156 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2157 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2164 fill in a netr_OneDomainInfo from a ldb search result
2166 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
2167 struct loadparm_context *lp_ctx,
2168 struct ldb_context *sam_ctx,
2169 struct ldb_message *res,
2170 struct netr_OneDomainInfo *info,
2171 bool is_local, bool is_trust_list)
2175 if (is_trust_list) {
2176 /* w2k8 only fills this on trusted domains */
2177 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
2178 info->trust_extension.length = 16;
2179 info->trust_extension.info->flags =
2180 NETR_TRUST_FLAG_TREEROOT |
2181 NETR_TRUST_FLAG_IN_FOREST |
2182 NETR_TRUST_FLAG_PRIMARY |
2183 NETR_TRUST_FLAG_NATIVE;
2185 info->trust_extension.info->parent_index = 0; /* should be index into array
2187 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
2188 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
2191 if (is_trust_list) {
2192 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2193 info->dns_forestname.string = NULL;
2195 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
2196 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
2197 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
2198 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
2202 info->domainname.string = lpcfg_workgroup(lp_ctx);
2203 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
2204 info->domain_guid = samdb_result_guid(res, "objectGUID");
2205 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
2207 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
2208 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
2209 info->domain_guid = samdb_result_guid(res, "objectGUID");
2210 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
2212 if (!is_trust_list) {
2213 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
2216 return NT_STATUS_OK;
2220 netr_LogonGetDomainInfo
2221 this is called as part of the ADS domain logon procedure.
2223 It has an important role in convaying details about the client, such
2224 as Operating System, Version, Service Pack etc.
2226 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2227 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2229 struct netlogon_creds_CredentialState *creds;
2230 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
2231 "securityIdentifier", "trustPartner", NULL };
2232 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2233 "msDS-SupportedEncryptionTypes", NULL };
2234 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
2235 struct ldb_context *sam_ctx;
2236 struct ldb_message **res1, **res2, **res3, *new_msg;
2237 struct ldb_dn *workstation_dn;
2238 struct netr_DomainInformation *domain_info;
2239 struct netr_LsaPolicyInformation *lsa_policy_info;
2240 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2241 bool update_dns_hostname = true;
2245 status = dcesrv_netr_creds_server_step_check(dce_call,
2247 r->in.computer_name,
2249 r->out.return_authenticator,
2251 if (!NT_STATUS_IS_OK(status)) {
2253 char* remote = NULL;
2254 TALLOC_CTX *frame = talloc_stackframe();
2255 remote = tsocket_address_string(dce_call->conn->remote_address,
2257 local = tsocket_address_string(dce_call->conn->local_address,
2259 DBG_ERR(("Bad credentials - "
2260 "computer[%s] remote[%s] local[%s]\n"),
2261 log_escape(frame, r->in.computer_name),
2266 NT_STATUS_NOT_OK_RETURN(status);
2268 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
2269 dce_call->conn->dce_ctx->lp_ctx,
2270 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
2271 if (sam_ctx == NULL) {
2272 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2275 switch (r->in.level) {
2276 case 1: /* Domain information */
2278 if (r->in.query->workstation_info == NULL) {
2279 return NT_STATUS_INVALID_PARAMETER;
2282 /* Prepares the workstation DN */
2283 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2284 dom_sid_string(mem_ctx, creds->sid));
2285 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2287 /* Lookup for attributes in workstation object */
2288 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2291 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2294 /* Gets the sam account name which is checked against the DNS
2295 * hostname parameter. */
2296 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2299 if (sam_account_name == NULL) {
2300 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2304 * Checks that the sam account name without a possible "$"
2305 * matches as prefix with the DNS hostname in the workstation
2308 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2309 strcspn(sam_account_name, "$"));
2310 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2311 if (r->in.query->workstation_info->dns_hostname != NULL) {
2312 prefix2 = talloc_strndup(mem_ctx,
2313 r->in.query->workstation_info->dns_hostname,
2314 strcspn(r->in.query->workstation_info->dns_hostname, "."));
2315 NT_STATUS_HAVE_NO_MEMORY(prefix2);
2317 if (strcasecmp(prefix1, prefix2) != 0) {
2318 update_dns_hostname = false;
2321 update_dns_hostname = false;
2324 /* Gets the old DNS hostname */
2325 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2330 * Updates the DNS hostname when the client wishes that the
2331 * server should handle this for him
2332 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2333 * obviously only checked when we do already have a
2335 * See MS-NRPC section 3.5.4.3.9
2337 if ((old_dns_hostname != NULL) &&
2338 (r->in.query->workstation_info->workstation_flags
2339 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2340 update_dns_hostname = false;
2343 /* Gets host information and put them into our directory */
2345 new_msg = ldb_msg_new(mem_ctx);
2346 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2348 new_msg->dn = workstation_dn;
2350 /* Sets the OS name */
2352 if (r->in.query->workstation_info->os_name.string == NULL) {
2353 return NT_STATUS_INVALID_PARAMETER;
2356 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2357 r->in.query->workstation_info->os_name.string);
2358 if (ret != LDB_SUCCESS) {
2359 return NT_STATUS_NO_MEMORY;
2363 * Sets information from "os_version". On an empty structure
2364 * the values are cleared.
2366 if (r->in.query->workstation_info->os_version.os != NULL) {
2367 struct netr_OsVersionInfoEx *os_version;
2368 const char *os_version_str;
2370 os_version = &r->in.query->workstation_info->os_version.os->os;
2372 if (os_version->CSDVersion == NULL) {
2373 return NT_STATUS_INVALID_PARAMETER;
2376 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2377 os_version->MajorVersion,
2378 os_version->MinorVersion,
2379 os_version->BuildNumber);
2380 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2382 ret = ldb_msg_add_string(new_msg,
2383 "operatingSystemServicePack",
2384 os_version->CSDVersion);
2385 if (ret != LDB_SUCCESS) {
2386 return NT_STATUS_NO_MEMORY;
2389 ret = ldb_msg_add_string(new_msg,
2390 "operatingSystemVersion",
2392 if (ret != LDB_SUCCESS) {
2393 return NT_STATUS_NO_MEMORY;
2396 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2397 "operatingSystemServicePack");
2398 if (ret != LDB_SUCCESS) {
2399 return NT_STATUS_NO_MEMORY;
2402 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2403 "operatingSystemVersion");
2404 if (ret != LDB_SUCCESS) {
2405 return NT_STATUS_NO_MEMORY;
2410 * If the boolean "update_dns_hostname" remained true, then we
2411 * are fine to start the update.
2413 if (update_dns_hostname) {
2414 ret = ldb_msg_add_string(new_msg,
2416 r->in.query->workstation_info->dns_hostname);
2417 if (ret != LDB_SUCCESS) {
2418 return NT_STATUS_NO_MEMORY;
2421 /* This manual "servicePrincipalName" generation is
2422 * still needed! Since the update in the samldb LDB
2423 * module does only work if the entries already exist
2424 * which isn't always the case. */
2425 ret = ldb_msg_add_string(new_msg,
2426 "servicePrincipalName",
2427 talloc_asprintf(new_msg, "HOST/%s",
2428 r->in.computer_name));
2429 if (ret != LDB_SUCCESS) {
2430 return NT_STATUS_NO_MEMORY;
2433 ret = ldb_msg_add_string(new_msg,
2434 "servicePrincipalName",
2435 talloc_asprintf(new_msg, "HOST/%s",
2436 r->in.query->workstation_info->dns_hostname));
2437 if (ret != LDB_SUCCESS) {
2438 return NT_STATUS_NO_MEMORY;
2442 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2443 DEBUG(3,("Impossible to update samdb: %s\n",
2444 ldb_errstring(sam_ctx)));
2447 talloc_free(new_msg);
2449 /* Writes back the domain information */
2451 /* We need to do two searches. The first will pull our primary
2452 domain and the second will pull any trusted domains. Our
2453 primary domain is also a "trusted" domain, so we need to
2454 put the primary domain into the lists of returned trusts as
2456 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2459 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2462 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2463 "(objectClass=trustedDomain)");
2465 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2468 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2469 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2471 ZERO_STRUCTP(domain_info);
2473 /* Informations about the local and trusted domains */
2475 status = fill_one_domain_info(mem_ctx,
2476 dce_call->conn->dce_ctx->lp_ctx,
2477 sam_ctx, res2[0], &domain_info->primary_domain,
2479 NT_STATUS_NOT_OK_RETURN(status);
2481 domain_info->trusted_domain_count = ret3 + 1;
2482 domain_info->trusted_domains = talloc_array(mem_ctx,
2483 struct netr_OneDomainInfo,
2484 domain_info->trusted_domain_count);
2485 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2487 for (i=0;i<ret3;i++) {
2488 status = fill_one_domain_info(mem_ctx,
2489 dce_call->conn->dce_ctx->lp_ctx,
2491 &domain_info->trusted_domains[i],
2493 NT_STATUS_NOT_OK_RETURN(status);
2496 status = fill_one_domain_info(mem_ctx,
2497 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2498 &domain_info->trusted_domains[i], true, true);
2499 NT_STATUS_NOT_OK_RETURN(status);
2501 /* Sets the supported encryption types */
2502 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2503 "msDS-SupportedEncryptionTypes",
2504 default_supported_enc_types);
2506 /* Other host domain information */
2508 lsa_policy_info = talloc(mem_ctx,
2509 struct netr_LsaPolicyInformation);
2510 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2511 ZERO_STRUCTP(lsa_policy_info);
2513 domain_info->lsa_policy = *lsa_policy_info;
2515 /* The DNS hostname is only returned back when there is a chance
2517 if ((r->in.query->workstation_info->workstation_flags
2518 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2519 domain_info->dns_hostname.string = old_dns_hostname;
2521 domain_info->dns_hostname.string = NULL;
2524 domain_info->workstation_flags =
2525 r->in.query->workstation_info->workstation_flags & (
2526 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2528 r->out.info->domain_info = domain_info;
2530 case 2: /* LSA policy information - not used at the moment */
2531 lsa_policy_info = talloc(mem_ctx,
2532 struct netr_LsaPolicyInformation);
2533 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2534 ZERO_STRUCTP(lsa_policy_info);
2536 r->out.info->lsa_policy_info = lsa_policy_info;
2539 return NT_STATUS_INVALID_LEVEL;
2543 return NT_STATUS_OK;
2548 netr_ServerPasswordGet
2550 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2551 struct netr_ServerPasswordGet *r)
2553 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2556 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2557 TALLOC_CTX *mem_ctx,
2558 struct dom_sid *user_sid,
2559 struct ldb_dn *obj_dn)
2561 const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
2562 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2563 struct ldb_dn *rodc_dn;
2565 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2566 const struct dom_sid *additional_sids[] = { NULL, NULL };
2568 struct dom_sid *object_sid;
2569 const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
2571 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2572 dom_sid_string(mem_ctx, user_sid));
2573 if (!ldb_dn_validate(rodc_dn)) goto denied;
2575 /* do the two searches we need */
2576 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2577 DSDB_SEARCH_SHOW_EXTENDED_DN);
2578 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2580 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2581 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2583 object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
2585 additional_sids[0] = object_sid;
2587 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2588 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
2589 if (!W_ERROR_IS_OK(werr)) {
2593 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2594 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
2595 if (!W_ERROR_IS_OK(werr)) {
2600 * The SID list needs to include itself as well as the tokenGroups.
2602 * TODO determine if sIDHistory is required for this check
2604 werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
2605 mem_ctx, "tokenGroups", &token_sids,
2606 additional_sids, 1);
2607 if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
2611 if (never_reveal_sids &&
2612 sid_list_match(token_sids, never_reveal_sids)) {
2617 sid_list_match(token_sids, reveal_sids)) {
2629 netr_NetrLogonSendToSam
2631 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2632 struct netr_NetrLogonSendToSam *r)
2634 struct netlogon_creds_CredentialState *creds;
2635 struct ldb_context *sam_ctx;
2637 DATA_BLOB decrypted_blob;
2638 enum ndr_err_code ndr_err;
2639 struct netr_SendToSamBase base_msg = { 0 };
2641 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2643 r->in.computer_name,
2645 r->out.return_authenticator,
2648 NT_STATUS_NOT_OK_RETURN(nt_status);
2650 switch (creds->secure_channel_type) {
2654 case SEC_CHAN_WKSTA:
2655 case SEC_CHAN_DNS_DOMAIN:
2656 case SEC_CHAN_DOMAIN:
2658 return NT_STATUS_INVALID_PARAMETER;
2660 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
2661 creds->secure_channel_type));
2662 return NT_STATUS_INVALID_PARAMETER;
2665 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
2666 dce_call->conn->dce_ctx->lp_ctx,
2667 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
2668 if (sam_ctx == NULL) {
2669 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2672 /* Buffer is meant to be 16-bit aligned */
2673 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2674 netlogon_creds_aes_decrypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2676 netlogon_creds_arcfour_crypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2679 decrypted_blob.data = r->in.opaque_buffer;
2680 decrypted_blob.length = r->in.buffer_len;
2682 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
2683 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
2685 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2686 /* We only partially implement SendToSam */
2687 return NT_STATUS_NOT_IMPLEMENTED;
2690 /* Now 'send' to SAM */
2691 switch (base_msg.message_type) {
2692 case SendToSamResetBadPasswordCount:
2694 struct ldb_message *msg = ldb_msg_new(mem_ctx);
2695 struct ldb_dn *dn = NULL;
2699 ret = ldb_transaction_start(sam_ctx);
2700 if (ret != LDB_SUCCESS) {
2701 return NT_STATUS_INTERNAL_ERROR;
2704 ret = dsdb_find_dn_by_guid(sam_ctx,
2706 &base_msg.message.reset_bad_password.guid,
2709 if (ret != LDB_SUCCESS) {
2710 ldb_transaction_cancel(sam_ctx);
2711 return NT_STATUS_INVALID_PARAMETER;
2714 if (creds->secure_channel_type == SEC_CHAN_RODC &&
2715 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
2716 DEBUG(1, ("Client asked to reset bad password on "
2717 "an arbitrary user: %s\n",
2718 ldb_dn_get_linearized(dn)));
2719 ldb_transaction_cancel(sam_ctx);
2720 return NT_STATUS_INVALID_PARAMETER;
2725 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
2726 if (ret != LDB_SUCCESS) {
2727 ldb_transaction_cancel(sam_ctx);
2728 return NT_STATUS_INVALID_PARAMETER;
2731 ret = dsdb_replace(sam_ctx, msg, 0);
2732 if (ret != LDB_SUCCESS) {
2733 ldb_transaction_cancel(sam_ctx);
2734 return NT_STATUS_INVALID_PARAMETER;
2737 ret = ldb_transaction_commit(sam_ctx);
2738 if (ret != LDB_SUCCESS) {
2739 ldb_transaction_cancel(sam_ctx);
2740 return NT_STATUS_INTERNAL_ERROR;
2746 return NT_STATUS_NOT_IMPLEMENTED;
2749 return NT_STATUS_OK;
2752 struct dcesrv_netr_DsRGetDCName_base_state {
2753 struct dcesrv_call_state *dce_call;
2754 TALLOC_CTX *mem_ctx;
2756 struct netr_DsRGetDCNameEx2 r;
2757 const char *client_site;
2760 struct netr_DsRGetDCName *dc;
2761 struct netr_DsRGetDCNameEx *dcex;
2762 struct netr_DsRGetDCNameEx2 *dcex2;
2766 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
2768 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
2770 struct dcesrv_call_state *dce_call = state->dce_call;
2771 TALLOC_CTX *mem_ctx = state->mem_ctx;
2772 struct netr_DsRGetDCNameEx2 *r = &state->r;
2773 struct ldb_context *sam_ctx;
2774 struct netr_DsRGetDCNameInfo *info;
2775 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2776 const struct tsocket_address *local_address;
2777 char *local_addr = NULL;
2778 const struct tsocket_address *remote_address;
2779 char *remote_addr = NULL;
2780 const char *server_site_name;
2782 struct netlogon_samlogon_response response;
2784 const char *dc_name = NULL;
2785 const char *domain_name = NULL;
2787 bool different_domain = true;
2789 ZERO_STRUCTP(r->out.info);
2791 sam_ctx = samdb_connect(state, dce_call->event_ctx, lp_ctx,
2792 dce_call->conn->auth_state.session_info, 0);
2793 if (sam_ctx == NULL) {
2794 return WERR_DS_UNAVAILABLE;
2797 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2798 if (tsocket_address_is_inet(local_address, "ip")) {
2799 local_addr = tsocket_address_inet_addr_string(local_address, state);
2800 W_ERROR_HAVE_NO_MEMORY(local_addr);
2803 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2804 if (tsocket_address_is_inet(remote_address, "ip")) {
2805 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
2806 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2809 /* "server_unc" is ignored by w2k3 */
2811 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2812 return WERR_INVALID_FLAGS;
2815 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2816 r->in.flags & DS_PDC_REQUIRED &&
2817 r->in.flags & DS_KDC_REQUIRED) {
2818 return WERR_INVALID_FLAGS;
2820 if (r->in.flags & DS_IS_FLAT_NAME &&
2821 r->in.flags & DS_IS_DNS_NAME) {
2822 return WERR_INVALID_FLAGS;
2824 if (r->in.flags & DS_RETURN_DNS_NAME &&
2825 r->in.flags & DS_RETURN_FLAT_NAME) {
2826 return WERR_INVALID_FLAGS;
2828 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2829 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2830 return WERR_INVALID_FLAGS;
2833 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2835 (DS_DIRECTORY_SERVICE_REQUIRED |
2836 DS_DIRECTORY_SERVICE_PREFERRED |
2837 DS_GC_SERVER_REQUIRED |
2840 return WERR_INVALID_FLAGS;
2843 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2845 return WERR_INVALID_FLAGS;
2848 /* Attempt winbind search only if we suspect the domain is incorrect */
2849 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
2850 if (r->in.flags & DS_IS_FLAT_NAME) {
2851 if (strcasecmp_m(r->in.domain_name,
2852 lpcfg_sam_name(lp_ctx)) == 0) {
2853 different_domain = false;
2855 } else if (r->in.flags & DS_IS_DNS_NAME) {
2856 if (strcasecmp_m(r->in.domain_name,
2857 lpcfg_dnsdomain(lp_ctx)) == 0) {
2858 different_domain = false;
2861 if (strcasecmp_m(r->in.domain_name,
2862 lpcfg_sam_name(lp_ctx)) == 0 ||
2863 strcasecmp_m(r->in.domain_name,
2864 lpcfg_dnsdomain(lp_ctx)) == 0) {
2865 different_domain = false;
2870 * We need to be able to handle empty domain names, where we
2871 * revert to our domain by default.
2873 different_domain = false;
2876 /* Proof server site parameter "site_name" if it was specified */
2877 server_site_name = samdb_server_site_name(sam_ctx, state);
2878 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2879 if (different_domain || (r->in.site_name != NULL &&
2880 (strcasecmp_m(r->in.site_name,
2881 server_site_name) != 0))) {
2883 struct dcerpc_binding_handle *irpc_handle = NULL;
2884 struct tevent_req *subreq = NULL;
2887 * Retrieve the client site to override the winbind response.
2889 * DO NOT use Windows fallback for client site.
2890 * In the case of multiple domains, this is plainly wrong.
2892 * Note: It's possible that the client may belong to multiple
2893 * subnets across domains. It's not clear what this would mean,
2894 * but here we only return what this domain knows.
2896 state->client_site = samdb_client_site_name(sam_ctx,
2902 irpc_handle = irpc_binding_handle_by_name(state,
2905 &ndr_table_winbind);
2906 if (irpc_handle == NULL) {
2907 DEBUG(0,("Failed to get binding_handle for "
2908 "winbind_server task\n"));
2909 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2910 return WERR_SERVICE_NOT_FOUND;
2913 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2915 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2917 subreq = dcerpc_wbint_DsGetDcName_send(state,
2918 dce_call->event_ctx,
2925 if (subreq == NULL) {
2926 return WERR_NOT_ENOUGH_MEMORY;
2929 tevent_req_set_callback(subreq,
2930 dcesrv_netr_DsRGetDCName_base_done,
2936 guid_str = r->in.domain_guid != NULL ?
2937 GUID_string(state, r->in.domain_guid) : NULL;
2939 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2943 r->in.client_account,
2944 r->in.mask, remote_addr,
2945 NETLOGON_NT_VERSION_5EX_WITH_IP,
2946 lp_ctx, &response, true);
2947 if (!NT_STATUS_IS_OK(status)) {
2948 return ntstatus_to_werror(status);
2952 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2953 * (O) flag when the returned forest name is in DNS format. This is here
2954 * always the case (see below).
2956 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2958 if (r->in.flags & DS_RETURN_DNS_NAME) {
2959 dc_name = response.data.nt5_ex.pdc_dns_name;
2960 domain_name = response.data.nt5_ex.dns_domain;
2962 * According to MS-NRPC 2.2.1.2.1 we should set the
2963 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2964 * the returned information is in DNS form.
2966 response.data.nt5_ex.server_type |=
2967 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2968 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2969 dc_name = response.data.nt5_ex.pdc_name;
2970 domain_name = response.data.nt5_ex.domain_name;
2974 * TODO: autodetect what we need to return
2975 * based on the given arguments
2977 dc_name = response.data.nt5_ex.pdc_name;
2978 domain_name = response.data.nt5_ex.domain_name;
2981 if (!dc_name || !dc_name[0]) {
2982 return WERR_NO_SUCH_DOMAIN;
2985 if (!domain_name || !domain_name[0]) {
2986 return WERR_NO_SUCH_DOMAIN;
2989 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2990 W_ERROR_HAVE_NO_MEMORY(info);
2991 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2992 dc_name[0] != '\\'? "\\\\":"",
2993 talloc_strdup(mem_ctx, dc_name));
2994 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2996 pdc_ip = local_addr;
2997 if (pdc_ip == NULL) {
2998 pdc_ip = "127.0.0.1";
3000 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3001 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3002 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3003 info->domain_guid = response.data.nt5_ex.domain_uuid;
3004 info->domain_name = domain_name;
3005 info->forest_name = response.data.nt5_ex.forest;
3006 info->dc_flags = response.data.nt5_ex.server_type;
3007 if (r->in.flags & DS_RETURN_DNS_NAME) {
3008 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3009 * returned if we are returning info->dc_unc containing a FQDN.
3010 * This attribute is called DomainControllerName in the specs,
3011 * it seems that we decide to return FQDN or netbios depending on
3012 * DS_RETURN_DNS_NAME.
3014 info->dc_flags |= DS_DNS_CONTROLLER;
3016 info->dc_site_name = response.data.nt5_ex.server_site;
3017 info->client_site_name = response.data.nt5_ex.client_site;
3019 *r->out.info = info;
3024 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3026 struct dcesrv_netr_DsRGetDCName_base_state *state =
3027 tevent_req_callback_data(subreq,
3028 struct dcesrv_netr_DsRGetDCName_base_state);
3029 struct dcesrv_call_state *dce_call = state->dce_call;
3030 NTSTATUS result, status;
3032 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3035 TALLOC_FREE(subreq);
3037 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3038 state->r.out.result = WERR_TIMEOUT;
3042 if (!NT_STATUS_IS_OK(status)) {
3043 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3045 state->r.out.result = WERR_GEN_FAILURE;
3049 if (!NT_STATUS_IS_OK(result)) {
3050 DBG_NOTICE("DC location via winbind failed - %s\n",
3052 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3056 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3057 DBG_ERR("DC location via winbind returned no results\n");
3058 state->r.out.result = WERR_GEN_FAILURE;
3062 if (state->r.out.info[0]->dc_unc == NULL) {
3063 DBG_ERR("DC location via winbind returned no DC unc\n");
3064 state->r.out.result = WERR_GEN_FAILURE;
3069 * Either the supplied site name is NULL (possibly via
3070 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3071 * the input match name.
3073 * TODO: Currently this means that requests with NETBIOS domain
3074 * names can fail because they do not return the site name.
3076 if (state->r.in.site_name == NULL ||
3077 strcasecmp_m("", state->r.in.site_name) == 0 ||
3078 (state->r.out.info[0]->dc_site_name != NULL &&
3079 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3080 state->r.in.site_name) == 0)) {
3082 state->r.out.info[0]->client_site_name =
3083 talloc_move(state->mem_ctx, &state->client_site);
3086 * Make sure to return our DC UNC with // prefix.
3087 * Winbind currently doesn't send the leading slashes
3090 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3091 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3092 const char *dc_unc = NULL;
3094 dc_unc = talloc_asprintf(state->mem_ctx,
3096 state->r.out.info[0]->dc_unc);
3097 state->r.out.info[0]->dc_unc = dc_unc;
3100 state->r.out.result = WERR_OK;
3102 state->r.out.info = NULL;
3103 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3107 if (state->_r.dcex2 != NULL) {
3108 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3109 r->out.result = state->r.out.result;
3110 } else if (state->_r.dcex != NULL) {
3111 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3112 r->out.result = state->r.out.result;
3113 } else if (state->_r.dc != NULL) {
3114 struct netr_DsRGetDCName *r = state->_r.dc;
3115 r->out.result = state->r.out.result;
3119 status = dcesrv_reply(dce_call);
3120 if (!NT_STATUS_IS_OK(status)) {
3121 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3122 nt_errstr(status)));
3127 netr_DsRGetDCNameEx2
3129 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3130 TALLOC_CTX *mem_ctx,
3131 struct netr_DsRGetDCNameEx2 *r)
3133 struct dcesrv_netr_DsRGetDCName_base_state *state;
3135 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3136 if (state == NULL) {
3137 return WERR_NOT_ENOUGH_MEMORY;
3140 state->dce_call = dce_call;
3141 state->mem_ctx = mem_ctx;
3144 state->_r.dcex2 = r;
3146 return dcesrv_netr_DsRGetDCName_base_call(state);
3152 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3153 struct netr_DsRGetDCNameEx *r)
3155 struct dcesrv_netr_DsRGetDCName_base_state *state;
3157 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3158 if (state == NULL) {
3159 return WERR_NOT_ENOUGH_MEMORY;
3162 state->dce_call = dce_call;
3163 state->mem_ctx = mem_ctx;
3165 state->r.in.server_unc = r->in.server_unc;
3166 state->r.in.client_account = NULL;
3167 state->r.in.mask = 0;
3168 state->r.in.domain_guid = r->in.domain_guid;
3169 state->r.in.domain_name = r->in.domain_name;
3170 state->r.in.site_name = r->in.site_name;
3171 state->r.in.flags = r->in.flags;
3172 state->r.out.info = r->out.info;
3176 return dcesrv_netr_DsRGetDCName_base_call(state);
3182 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3183 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3184 * insists that it be ignored.
3186 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3187 struct netr_DsRGetDCName *r)
3189 struct dcesrv_netr_DsRGetDCName_base_state *state;
3191 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3192 if (state == NULL) {
3193 return WERR_NOT_ENOUGH_MEMORY;
3196 state->dce_call = dce_call;
3197 state->mem_ctx = mem_ctx;
3199 state->r.in.server_unc = r->in.server_unc;
3200 state->r.in.client_account = NULL;
3201 state->r.in.mask = 0;
3202 state->r.in.domain_name = r->in.domain_name;
3203 state->r.in.domain_guid = r->in.domain_guid;
3205 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3206 state->r.in.flags = r->in.flags;
3207 state->r.out.info = r->out.info;
3211 return dcesrv_netr_DsRGetDCName_base_call(state);
3214 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3216 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3217 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3219 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3224 netr_NetrEnumerateTrustedDomainsEx
3226 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3227 struct netr_NetrEnumerateTrustedDomainsEx *r)
3229 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3234 netr_DsRAddressToSitenamesExW
3236 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3237 struct netr_DsRAddressToSitenamesExW *r)
3239 struct ldb_context *sam_ctx;
3240 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3241 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3242 sa_family_t sin_family;
3243 struct sockaddr_in *addr;
3245 struct sockaddr_in6 *addr6;
3246 char addr_str[INET6_ADDRSTRLEN];
3248 char addr_str[INET_ADDRSTRLEN];
3254 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3255 dce_call->conn->auth_state.session_info, 0);
3256 if (sam_ctx == NULL) {
3257 return WERR_DS_UNAVAILABLE;
3260 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3261 W_ERROR_HAVE_NO_MEMORY(ctr);
3265 ctr->count = r->in.count;
3266 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3267 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3268 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3269 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3271 for (i=0; i<ctr->count; i++) {
3272 ctr->sitename[i].string = NULL;
3273 ctr->subnetname[i].string = NULL;
3275 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3278 /* The first two byte of the buffer are reserved for the
3279 * "sin_family" but for now only the first one is used. */
3280 sin_family = r->in.addresses[i].buffer[0];
3282 switch (sin_family) {
3284 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3287 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3288 res = inet_ntop(AF_INET, &addr->sin_addr,
3289 addr_str, sizeof(addr_str));
3293 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3296 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3297 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3298 addr_str, sizeof(addr_str));
3309 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3314 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3315 ctr->subnetname[i].string = subnet_name;
3323 netr_DsRAddressToSitenamesW
3325 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3326 struct netr_DsRAddressToSitenamesW *r)
3328 struct netr_DsRAddressToSitenamesExW r2;
3329 struct netr_DsRAddressToSitenamesWCtr *ctr;
3335 r2.in.server_name = r->in.server_name;
3336 r2.in.count = r->in.count;
3337 r2.in.addresses = r->in.addresses;
3339 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3340 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3342 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3343 W_ERROR_HAVE_NO_MEMORY(ctr);
3347 ctr->count = r->in.count;
3348 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3349 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3351 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3353 for (i=0; i<ctr->count; i++) {
3354 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3362 netr_DsrGetDcSiteCoverageW
3364 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3365 struct netr_DsrGetDcSiteCoverageW *r)
3367 struct ldb_context *sam_ctx;
3368 struct DcSitesCtr *ctr;
3369 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3371 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3372 dce_call->conn->auth_state.session_info, 0);
3373 if (sam_ctx == NULL) {
3374 return WERR_DS_UNAVAILABLE;
3377 ctr = talloc(mem_ctx, struct DcSitesCtr);
3378 W_ERROR_HAVE_NO_MEMORY(ctr);
3382 /* For now only return our default site */
3384 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3385 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3386 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3387 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3393 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3394 struct ldb_context *sam_ctx,
3395 struct netr_DomainTrustList *trusts,
3396 uint32_t trust_flags)
3398 struct ldb_dn *system_dn;
3399 struct ldb_message **dom_res = NULL;
3400 const char *trust_attrs[] = { "flatname", "trustPartner",
3401 "securityIdentifier", "trustDirection",
3402 "trustType", "trustAttributes", NULL };
3407 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3408 NETR_TRUST_FLAG_OUTBOUND))) {
3409 return WERR_INVALID_FLAGS;
3412 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3413 ldb_get_default_basedn(sam_ctx),
3414 "(&(objectClass=container)(cn=System))");
3416 return WERR_GEN_FAILURE;
3419 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3420 &dom_res, trust_attrs,
3421 "(objectclass=trustedDomain)");
3423 for (i = 0; i < ret; i++) {
3424 unsigned int trust_dir;
3427 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3428 "trustDirection", 0);
3430 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3431 flags |= NETR_TRUST_FLAG_INBOUND;
3433 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3434 flags |= NETR_TRUST_FLAG_OUTBOUND;
3437 if (!(flags & trust_flags)) {
3438 /* this trust direction was not requested */
3443 trusts->array = talloc_realloc(trusts, trusts->array,
3444 struct netr_DomainTrust,
3446 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3448 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3449 if (!trusts->array[n].netbios_name) {
3450 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3451 "without flatname\n",
3452 ldb_dn_get_linearized(dom_res[i]->dn)));
3455 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3457 trusts->array[n].trust_flags = flags;
3458 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3459 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3460 /* TODO: find if we have parent in the list */
3461 trusts->array[n].parent_index = 0;
3464 trusts->array[n].trust_type =
3465 ldb_msg_find_attr_as_uint(dom_res[i],
3467 trusts->array[n].trust_attributes =
3468 ldb_msg_find_attr_as_uint(dom_res[i],
3469 "trustAttributes", 0);
3471 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3472 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3473 struct dom_sid zero_sid;
3474 ZERO_STRUCT(zero_sid);
3475 trusts->array[n].sid =
3476 dom_sid_dup(trusts, &zero_sid);
3478 trusts->array[n].sid =
3479 samdb_result_dom_sid(trusts, dom_res[i],
3480 "securityIdentifier");
3482 trusts->array[n].guid = GUID_zero();
3484 trusts->count = n + 1;
3487 talloc_free(dom_res);
3492 netr_DsrEnumerateDomainTrusts
3494 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3495 TALLOC_CTX *mem_ctx,
3496 struct netr_DsrEnumerateDomainTrusts *r)
3498 struct netr_DomainTrustList *trusts;
3499 struct ldb_context *sam_ctx;
3501 struct ldb_message **dom_res;
3502 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3503 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3504 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3508 if (r->in.trust_flags & 0xFFFFFE00) {
3509 return WERR_INVALID_FLAGS;
3512 /* TODO: turn to hard check once we are sure this is 100% correct */
3513 if (!r->in.server_name) {
3514 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3515 "But received NULL!\n", dnsdomain));
3517 p = strchr(r->in.server_name, '.');
3519 DEBUG(3, ("Invalid domain! Expected name in domain "
3520 "[%s]. But received [%s]!\n",
3521 dnsdomain, r->in.server_name));
3522 p = r->in.server_name;
3526 if (strcasecmp(p, dnsdomain)) {
3527 DEBUG(3, ("Invalid domain! Expected name in domain "
3528 "[%s]. But received [%s]!\n",
3529 dnsdomain, r->in.server_name));
3533 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3534 W_ERROR_HAVE_NO_MEMORY(trusts);
3537 r->out.trusts = trusts;
3539 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3540 dce_call->conn->auth_state.session_info, 0);
3541 if (sam_ctx == NULL) {
3542 return WERR_GEN_FAILURE;
3545 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3546 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3548 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3549 trusts, r->in.trust_flags);
3550 W_ERROR_NOT_OK_RETURN(werr);
3553 /* NOTE: we currently are always the root of the forest */
3554 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3555 uint32_t n = trusts->count;
3557 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3558 &dom_res, dom_attrs);
3560 return WERR_GEN_FAILURE;
3563 trusts->count = n + 1;
3564 trusts->array = talloc_realloc(trusts, trusts->array,
3565 struct netr_DomainTrust,
3567 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3569 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3570 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3571 trusts->array[n].trust_flags =
3572 NETR_TRUST_FLAG_NATIVE |
3573 NETR_TRUST_FLAG_TREEROOT |
3574 NETR_TRUST_FLAG_IN_FOREST |
3575 NETR_TRUST_FLAG_PRIMARY;
3576 /* we are always the root domain for now */
3577 trusts->array[n].parent_index = 0;
3578 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3579 trusts->array[n].trust_attributes = 0;
3580 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3583 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3585 talloc_free(dom_res);
3593 netr_DsrDeregisterDNSHostRecords
3595 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3596 struct netr_DsrDeregisterDNSHostRecords *r)
3598 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3602 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3603 struct netr_ServerGetTrustInfo *r);
3606 netr_ServerTrustPasswordsGet
3608 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3609 struct netr_ServerTrustPasswordsGet *r)
3611 struct netr_ServerGetTrustInfo r2 = {};
3612 struct netr_TrustInfo *_ti = NULL;
3615 r2.in.server_name = r->in.server_name;
3616 r2.in.account_name = r->in.account_name;
3617 r2.in.secure_channel_type = r->in.secure_channel_type;
3618 r2.in.computer_name = r->in.computer_name;
3619 r2.in.credential = r->in.credential;
3621 r2.out.return_authenticator = r->out.return_authenticator;
3622 r2.out.new_owf_password = r->out.new_owf_password;
3623 r2.out.old_owf_password = r->out.old_owf_password;
3624 r2.out.trust_info = &_ti;
3626 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3628 r->out.return_authenticator = r2.out.return_authenticator;
3629 r->out.new_owf_password = r2.out.new_owf_password;
3630 r->out.old_owf_password = r2.out.old_owf_password;
3636 netr_DsRGetForestTrustInformation
3638 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3639 struct dcesrv_call_state *dce_call;
3640 TALLOC_CTX *mem_ctx;
3641 struct netr_DsRGetForestTrustInformation *r;
3644 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3646 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3647 TALLOC_CTX *mem_ctx,
3648 struct netr_DsRGetForestTrustInformation *r)
3650 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3651 struct dcesrv_connection *conn = dce_call->conn;
3652 struct auth_session_info *session_info = conn->auth_state.session_info;
3653 enum security_user_level security_level;
3654 struct ldb_context *sam_ctx = NULL;
3655 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3656 struct dcerpc_binding_handle *irpc_handle = NULL;
3657 struct tevent_req *subreq = NULL;
3658 struct ldb_dn *domain_dn = NULL;
3659 struct ldb_dn *forest_dn = NULL;
3663 security_level = security_session_user_level(session_info, NULL);
3664 if (security_level < SECURITY_USER) {
3665 return WERR_ACCESS_DENIED;
3668 if (r->in.flags & 0xFFFFFFFE) {
3669 return WERR_INVALID_FLAGS;
3672 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3673 dce_call->conn->auth_state.session_info, 0);
3674 if (sam_ctx == NULL) {
3675 return WERR_GEN_FAILURE;
3678 domain_dn = ldb_get_default_basedn(sam_ctx);
3679 if (domain_dn == NULL) {
3680 return WERR_GEN_FAILURE;
3683 forest_dn = ldb_get_root_basedn(sam_ctx);
3684 if (forest_dn == NULL) {
3685 return WERR_GEN_FAILURE;
3688 cmp = ldb_dn_compare(domain_dn, forest_dn);
3690 return WERR_NERR_ACFNOTLOADED;
3693 forest_level = dsdb_forest_functional_level(sam_ctx);
3694 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3695 return WERR_INVALID_FUNCTION;
3698 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3699 if (!samdb_is_pdc(sam_ctx)) {
3700 return WERR_NERR_NOTPRIMARY;
3703 if (r->in.trusted_domain_name == NULL) {
3704 return WERR_INVALID_FLAGS;
3708 if (r->in.trusted_domain_name == NULL) {
3712 * information about our own domain
3714 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3715 r->out.forest_trust_info);
3716 if (!NT_STATUS_IS_OK(status)) {
3717 return ntstatus_to_werror(status);
3724 * Forward the request to winbindd
3727 state = talloc_zero(mem_ctx,
3728 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3729 if (state == NULL) {
3730 return WERR_NOT_ENOUGH_MEMORY;
3732 state->dce_call = dce_call;
3733 state->mem_ctx = mem_ctx;
3736 irpc_handle = irpc_binding_handle_by_name(state,
3737 state->dce_call->msg_ctx,
3739 &ndr_table_winbind);
3740 if (irpc_handle == NULL) {
3741 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3742 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3743 return WERR_SERVICE_NOT_FOUND;
3747 * 60 seconds timeout should be enough
3749 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3751 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3752 state->dce_call->event_ctx,
3754 r->in.trusted_domain_name,
3756 r->out.forest_trust_info);
3757 if (subreq == NULL) {
3758 return WERR_NOT_ENOUGH_MEMORY;
3760 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3761 tevent_req_set_callback(subreq,
3762 dcesrv_netr_DsRGetForestTrustInformation_done,
3768 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3770 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3771 tevent_req_callback_data(subreq,
3772 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3775 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3777 &state->r->out.result);
3778 TALLOC_FREE(subreq);
3779 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3780 state->r->out.result = WERR_TIMEOUT;
3781 } else if (!NT_STATUS_IS_OK(status)) {
3782 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3783 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3784 nt_errstr(status)));
3787 status = dcesrv_reply(state->dce_call);
3788 if (!NT_STATUS_IS_OK(status)) {
3789 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3794 netr_GetForestTrustInformation
3796 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3797 TALLOC_CTX *mem_ctx,
3798 struct netr_GetForestTrustInformation *r)
3800 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3801 struct netlogon_creds_CredentialState *creds = NULL;
3802 struct ldb_context *sam_ctx = NULL;
3803 struct ldb_dn *domain_dn = NULL;
3804 struct ldb_dn *forest_dn = NULL;
3809 status = dcesrv_netr_creds_server_step_check(dce_call,
3811 r->in.computer_name,
3813 r->out.return_authenticator,
3815 if (!NT_STATUS_IS_OK(status)) {
3819 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3820 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3821 return NT_STATUS_NOT_IMPLEMENTED;
3824 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3825 dce_call->conn->auth_state.session_info, 0);
3826 if (sam_ctx == NULL) {
3827 return NT_STATUS_INTERNAL_ERROR;
3830 /* TODO: check r->in.server_name is our name */
3832 domain_dn = ldb_get_default_basedn(sam_ctx);
3833 if (domain_dn == NULL) {
3834 return NT_STATUS_INTERNAL_ERROR;
3837 forest_dn = ldb_get_root_basedn(sam_ctx);
3838 if (forest_dn == NULL) {
3839 return NT_STATUS_INTERNAL_ERROR;
3842 cmp = ldb_dn_compare(domain_dn, forest_dn);
3844 return NT_STATUS_INVALID_DOMAIN_STATE;
3847 forest_level = dsdb_forest_functional_level(sam_ctx);
3848 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3849 return NT_STATUS_INVALID_DOMAIN_STATE;
3852 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3853 r->out.forest_trust_info);
3854 if (!NT_STATUS_IS_OK(status)) {
3858 return NT_STATUS_OK;
3863 netr_ServerGetTrustInfo
3865 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3866 struct netr_ServerGetTrustInfo *r)
3868 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3869 struct netlogon_creds_CredentialState *creds = NULL;
3870 struct ldb_context *sam_ctx = NULL;
3871 const char * const attrs[] = {
3874 "userAccountControl",
3877 struct ldb_message **res = NULL;
3878 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3881 const char *asid = NULL;
3883 const char *aname = NULL;
3884 struct ldb_message *tdo_msg = NULL;
3885 const char * const tdo_attrs[] = {
3886 "trustAuthIncoming",
3890 struct netr_TrustInfo *trust_info = NULL;
3892 ZERO_STRUCTP(r->out.new_owf_password);
3893 ZERO_STRUCTP(r->out.old_owf_password);
3895 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3897 r->in.computer_name,
3899 r->out.return_authenticator,
3901 if (!NT_STATUS_IS_OK(nt_status)) {
3905 /* TODO: check r->in.server_name is our name */
3907 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3908 return NT_STATUS_INVALID_PARAMETER;
3911 if (r->in.secure_channel_type != creds->secure_channel_type) {
3912 return NT_STATUS_INVALID_PARAMETER;
3915 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3916 return NT_STATUS_INVALID_PARAMETER;
3919 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3920 lp_ctx, system_session(lp_ctx), 0);
3921 if (sam_ctx == NULL) {
3922 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3925 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3927 return NT_STATUS_NO_MEMORY;
3930 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3931 "(&(objectClass=user)(objectSid=%s))",
3934 return NT_STATUS_ACCOUNT_DISABLED;
3937 switch (creds->secure_channel_type) {
3938 case SEC_CHAN_DNS_DOMAIN:
3939 case SEC_CHAN_DOMAIN:
3940 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3942 if (uac & UF_ACCOUNTDISABLE) {
3943 return NT_STATUS_ACCOUNT_DISABLED;
3946 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3947 return NT_STATUS_ACCOUNT_DISABLED;
3950 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3951 if (aname == NULL) {
3952 return NT_STATUS_ACCOUNT_DISABLED;
3955 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3956 SEC_CHAN_DOMAIN, aname,
3957 tdo_attrs, mem_ctx, &tdo_msg);
3958 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3959 return NT_STATUS_ACCOUNT_DISABLED;
3961 if (!NT_STATUS_IS_OK(nt_status)) {
3965 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3968 if (!NT_STATUS_IS_OK(nt_status)) {
3972 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3973 if (trust_info == NULL) {
3974 return NT_STATUS_NO_MEMORY;
3977 trust_info->count = 1;
3978 trust_info->data = talloc_array(trust_info, uint32_t,
3980 if (trust_info->data == NULL) {
3981 return NT_STATUS_NO_MEMORY;
3984 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3990 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3993 if (!NT_STATUS_IS_OK(nt_status)) {
3997 prevNtHash = talloc(mem_ctx, struct samr_Password);
3998 if (prevNtHash == NULL) {
3999 return NT_STATUS_NO_MEMORY;
4002 E_md4hash("", prevNtHash->hash);
4006 if (curNtHash != NULL) {
4007 *r->out.new_owf_password = *curNtHash;
4008 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4010 if (prevNtHash != NULL) {
4011 *r->out.old_owf_password = *prevNtHash;
4012 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4015 if (trust_info != NULL) {
4016 *r->out.trust_info = trust_info;
4019 return NT_STATUS_OK;
4025 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4026 struct netr_Unused47 *r)
4028 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4032 struct netr_dnsupdate_RODC_state {
4033 struct dcesrv_call_state *dce_call;
4034 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4035 struct dnsupdate_RODC *r2;
4039 called when the forwarded RODC dns update request is finished
4041 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4043 struct netr_dnsupdate_RODC_state *st =
4044 tevent_req_callback_data(subreq,
4045 struct netr_dnsupdate_RODC_state);
4048 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4049 TALLOC_FREE(subreq);
4050 if (!NT_STATUS_IS_OK(status)) {
4051 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4052 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4055 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4057 status = dcesrv_reply(st->dce_call);
4058 if (!NT_STATUS_IS_OK(status)) {
4059 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4064 netr_DsrUpdateReadOnlyServerDnsRecords
4066 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4067 TALLOC_CTX *mem_ctx,
4068 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4070 struct netlogon_creds_CredentialState *creds;
4072 struct dcerpc_binding_handle *binding_handle;
4073 struct netr_dnsupdate_RODC_state *st;
4074 struct tevent_req *subreq;
4076 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4078 r->in.computer_name,
4080 r->out.return_authenticator,
4082 NT_STATUS_NOT_OK_RETURN(nt_status);
4084 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4085 return NT_STATUS_ACCESS_DENIED;
4088 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4089 NT_STATUS_HAVE_NO_MEMORY(st);
4091 st->dce_call = dce_call;
4093 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4094 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4096 st->r2->in.dom_sid = creds->sid;
4097 st->r2->in.site_name = r->in.site_name;
4098 st->r2->in.dns_ttl = r->in.dns_ttl;
4099 st->r2->in.dns_names = r->in.dns_names;
4100 st->r2->out.dns_names = r->out.dns_names;
4102 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
4103 "dnsupdate", &ndr_table_irpc);
4104 if (binding_handle == NULL) {
4105 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4106 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4107 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4110 /* forward the call */
4111 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4112 binding_handle, st->r2);
4113 NT_STATUS_HAVE_NO_MEMORY(subreq);
4115 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4117 /* setup the callback */
4118 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4120 return NT_STATUS_OK;
4124 /* include the generated boilerplate */
4125 #include "librpc/gen_ndr/ndr_netlogon_s.c"