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;
2759 struct netr_DsRGetDCName *dc;
2760 struct netr_DsRGetDCNameEx *dcex;
2761 struct netr_DsRGetDCNameEx2 *dcex2;
2765 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
2767 struct dcesrv_call_state *dce_call = state->dce_call;
2768 TALLOC_CTX *mem_ctx = state->mem_ctx;
2769 struct netr_DsRGetDCNameEx2 *r = &state->r;
2770 struct ldb_context *sam_ctx;
2771 struct netr_DsRGetDCNameInfo *info;
2772 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2773 const struct tsocket_address *local_address;
2774 char *local_addr = NULL;
2775 const struct tsocket_address *remote_address;
2776 char *remote_addr = NULL;
2777 const char *server_site_name;
2779 struct netlogon_samlogon_response response;
2781 const char *dc_name = NULL;
2782 const char *domain_name = NULL;
2785 ZERO_STRUCTP(r->out.info);
2787 sam_ctx = samdb_connect(state, dce_call->event_ctx, lp_ctx,
2788 dce_call->conn->auth_state.session_info, 0);
2789 if (sam_ctx == NULL) {
2790 return WERR_DS_UNAVAILABLE;
2793 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2794 if (tsocket_address_is_inet(local_address, "ip")) {
2795 local_addr = tsocket_address_inet_addr_string(local_address, state);
2796 W_ERROR_HAVE_NO_MEMORY(local_addr);
2799 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2800 if (tsocket_address_is_inet(remote_address, "ip")) {
2801 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
2802 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2805 /* "server_unc" is ignored by w2k3 */
2807 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2808 return WERR_INVALID_FLAGS;
2811 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2812 r->in.flags & DS_PDC_REQUIRED &&
2813 r->in.flags & DS_KDC_REQUIRED) {
2814 return WERR_INVALID_FLAGS;
2816 if (r->in.flags & DS_IS_FLAT_NAME &&
2817 r->in.flags & DS_IS_DNS_NAME) {
2818 return WERR_INVALID_FLAGS;
2820 if (r->in.flags & DS_RETURN_DNS_NAME &&
2821 r->in.flags & DS_RETURN_FLAT_NAME) {
2822 return WERR_INVALID_FLAGS;
2824 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2825 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2826 return WERR_INVALID_FLAGS;
2829 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2831 (DS_DIRECTORY_SERVICE_REQUIRED |
2832 DS_DIRECTORY_SERVICE_PREFERRED |
2833 DS_GC_SERVER_REQUIRED |
2836 return WERR_INVALID_FLAGS;
2839 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2841 return WERR_INVALID_FLAGS;
2844 /* Proof server site parameter "site_name" if it was specified */
2845 server_site_name = samdb_server_site_name(sam_ctx, state);
2846 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2847 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2848 server_site_name) != 0)) {
2849 return WERR_NO_SUCH_DOMAIN;
2852 guid_str = r->in.domain_guid != NULL ?
2853 GUID_string(state, r->in.domain_guid) : NULL;
2855 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2859 r->in.client_account,
2860 r->in.mask, remote_addr,
2861 NETLOGON_NT_VERSION_5EX_WITH_IP,
2862 lp_ctx, &response, true);
2863 if (!NT_STATUS_IS_OK(status)) {
2864 return ntstatus_to_werror(status);
2868 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2869 * (O) flag when the returned forest name is in DNS format. This is here
2870 * always the case (see below).
2872 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2874 if (r->in.flags & DS_RETURN_DNS_NAME) {
2875 dc_name = response.data.nt5_ex.pdc_dns_name;
2876 domain_name = response.data.nt5_ex.dns_domain;
2878 * According to MS-NRPC 2.2.1.2.1 we should set the
2879 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2880 * the returned information is in DNS form.
2882 response.data.nt5_ex.server_type |=
2883 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2884 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2885 dc_name = response.data.nt5_ex.pdc_name;
2886 domain_name = response.data.nt5_ex.domain_name;
2890 * TODO: autodetect what we need to return
2891 * based on the given arguments
2893 dc_name = response.data.nt5_ex.pdc_name;
2894 domain_name = response.data.nt5_ex.domain_name;
2897 if (!dc_name || !dc_name[0]) {
2898 return WERR_NO_SUCH_DOMAIN;
2901 if (!domain_name || !domain_name[0]) {
2902 return WERR_NO_SUCH_DOMAIN;
2905 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2906 W_ERROR_HAVE_NO_MEMORY(info);
2907 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2908 dc_name[0] != '\\'? "\\\\":"",
2909 talloc_strdup(mem_ctx, dc_name));
2910 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2912 pdc_ip = local_addr;
2913 if (pdc_ip == NULL) {
2914 pdc_ip = "127.0.0.1";
2916 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2917 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2918 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2919 info->domain_guid = response.data.nt5_ex.domain_uuid;
2920 info->domain_name = domain_name;
2921 info->forest_name = response.data.nt5_ex.forest;
2922 info->dc_flags = response.data.nt5_ex.server_type;
2923 if (r->in.flags & DS_RETURN_DNS_NAME) {
2924 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2925 * returned if we are returning info->dc_unc containing a FQDN.
2926 * This attribute is called DomainControllerName in the specs,
2927 * it seems that we decide to return FQDN or netbios depending on
2928 * DS_RETURN_DNS_NAME.
2930 info->dc_flags |= DS_DNS_CONTROLLER;
2932 info->dc_site_name = response.data.nt5_ex.server_site;
2933 info->client_site_name = response.data.nt5_ex.client_site;
2935 *r->out.info = info;
2941 netr_DsRGetDCNameEx2
2943 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2944 TALLOC_CTX *mem_ctx,
2945 struct netr_DsRGetDCNameEx2 *r)
2947 struct dcesrv_netr_DsRGetDCName_base_state *state;
2949 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
2950 if (state == NULL) {
2951 return WERR_NOT_ENOUGH_MEMORY;
2954 state->dce_call = dce_call;
2955 state->mem_ctx = mem_ctx;
2958 state->_r.dcex2 = r;
2960 return dcesrv_netr_DsRGetDCName_base_call(state);
2966 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2967 struct netr_DsRGetDCNameEx *r)
2969 struct dcesrv_netr_DsRGetDCName_base_state *state;
2971 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
2972 if (state == NULL) {
2973 return WERR_NOT_ENOUGH_MEMORY;
2976 state->dce_call = dce_call;
2977 state->mem_ctx = mem_ctx;
2979 state->r.in.server_unc = r->in.server_unc;
2980 state->r.in.client_account = NULL;
2981 state->r.in.mask = 0;
2982 state->r.in.domain_guid = r->in.domain_guid;
2983 state->r.in.domain_name = r->in.domain_name;
2984 state->r.in.site_name = r->in.site_name;
2985 state->r.in.flags = r->in.flags;
2986 state->r.out.info = r->out.info;
2990 return dcesrv_netr_DsRGetDCName_base_call(state);
2996 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
2997 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
2998 * insists that it be ignored.
3000 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3001 struct netr_DsRGetDCName *r)
3003 struct dcesrv_netr_DsRGetDCName_base_state *state;
3005 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3006 if (state == NULL) {
3007 return WERR_NOT_ENOUGH_MEMORY;
3010 state->dce_call = dce_call;
3011 state->mem_ctx = mem_ctx;
3013 state->r.in.server_unc = r->in.server_unc;
3014 state->r.in.client_account = NULL;
3015 state->r.in.mask = 0;
3016 state->r.in.domain_name = r->in.domain_name;
3017 state->r.in.domain_guid = r->in.domain_guid;
3019 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3020 state->r.in.flags = r->in.flags;
3021 state->r.out.info = r->out.info;
3025 return dcesrv_netr_DsRGetDCName_base_call(state);
3028 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3030 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3031 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3033 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3038 netr_NetrEnumerateTrustedDomainsEx
3040 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3041 struct netr_NetrEnumerateTrustedDomainsEx *r)
3043 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3048 netr_DsRAddressToSitenamesExW
3050 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3051 struct netr_DsRAddressToSitenamesExW *r)
3053 struct ldb_context *sam_ctx;
3054 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3055 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3056 sa_family_t sin_family;
3057 struct sockaddr_in *addr;
3059 struct sockaddr_in6 *addr6;
3060 char addr_str[INET6_ADDRSTRLEN];
3062 char addr_str[INET_ADDRSTRLEN];
3068 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3069 dce_call->conn->auth_state.session_info, 0);
3070 if (sam_ctx == NULL) {
3071 return WERR_DS_UNAVAILABLE;
3074 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3075 W_ERROR_HAVE_NO_MEMORY(ctr);
3079 ctr->count = r->in.count;
3080 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3081 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3082 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3083 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3085 for (i=0; i<ctr->count; i++) {
3086 ctr->sitename[i].string = NULL;
3087 ctr->subnetname[i].string = NULL;
3089 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3092 /* The first two byte of the buffer are reserved for the
3093 * "sin_family" but for now only the first one is used. */
3094 sin_family = r->in.addresses[i].buffer[0];
3096 switch (sin_family) {
3098 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3101 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3102 res = inet_ntop(AF_INET, &addr->sin_addr,
3103 addr_str, sizeof(addr_str));
3107 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3110 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3111 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3112 addr_str, sizeof(addr_str));
3123 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3128 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3129 ctr->subnetname[i].string = subnet_name;
3137 netr_DsRAddressToSitenamesW
3139 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3140 struct netr_DsRAddressToSitenamesW *r)
3142 struct netr_DsRAddressToSitenamesExW r2;
3143 struct netr_DsRAddressToSitenamesWCtr *ctr;
3149 r2.in.server_name = r->in.server_name;
3150 r2.in.count = r->in.count;
3151 r2.in.addresses = r->in.addresses;
3153 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3154 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3156 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3157 W_ERROR_HAVE_NO_MEMORY(ctr);
3161 ctr->count = r->in.count;
3162 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3163 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3165 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3167 for (i=0; i<ctr->count; i++) {
3168 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3176 netr_DsrGetDcSiteCoverageW
3178 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3179 struct netr_DsrGetDcSiteCoverageW *r)
3181 struct ldb_context *sam_ctx;
3182 struct DcSitesCtr *ctr;
3183 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3185 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3186 dce_call->conn->auth_state.session_info, 0);
3187 if (sam_ctx == NULL) {
3188 return WERR_DS_UNAVAILABLE;
3191 ctr = talloc(mem_ctx, struct DcSitesCtr);
3192 W_ERROR_HAVE_NO_MEMORY(ctr);
3196 /* For now only return our default site */
3198 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3199 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3200 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3201 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3207 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3208 struct ldb_context *sam_ctx,
3209 struct netr_DomainTrustList *trusts,
3210 uint32_t trust_flags)
3212 struct ldb_dn *system_dn;
3213 struct ldb_message **dom_res = NULL;
3214 const char *trust_attrs[] = { "flatname", "trustPartner",
3215 "securityIdentifier", "trustDirection",
3216 "trustType", "trustAttributes", NULL };
3221 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3222 NETR_TRUST_FLAG_OUTBOUND))) {
3223 return WERR_INVALID_FLAGS;
3226 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3227 ldb_get_default_basedn(sam_ctx),
3228 "(&(objectClass=container)(cn=System))");
3230 return WERR_GEN_FAILURE;
3233 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3234 &dom_res, trust_attrs,
3235 "(objectclass=trustedDomain)");
3237 for (i = 0; i < ret; i++) {
3238 unsigned int trust_dir;
3241 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3242 "trustDirection", 0);
3244 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3245 flags |= NETR_TRUST_FLAG_INBOUND;
3247 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3248 flags |= NETR_TRUST_FLAG_OUTBOUND;
3251 if (!(flags & trust_flags)) {
3252 /* this trust direction was not requested */
3257 trusts->array = talloc_realloc(trusts, trusts->array,
3258 struct netr_DomainTrust,
3260 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3262 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3263 if (!trusts->array[n].netbios_name) {
3264 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3265 "without flatname\n",
3266 ldb_dn_get_linearized(dom_res[i]->dn)));
3269 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3271 trusts->array[n].trust_flags = flags;
3272 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3273 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3274 /* TODO: find if we have parent in the list */
3275 trusts->array[n].parent_index = 0;
3278 trusts->array[n].trust_type =
3279 ldb_msg_find_attr_as_uint(dom_res[i],
3281 trusts->array[n].trust_attributes =
3282 ldb_msg_find_attr_as_uint(dom_res[i],
3283 "trustAttributes", 0);
3285 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3286 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3287 struct dom_sid zero_sid;
3288 ZERO_STRUCT(zero_sid);
3289 trusts->array[n].sid =
3290 dom_sid_dup(trusts, &zero_sid);
3292 trusts->array[n].sid =
3293 samdb_result_dom_sid(trusts, dom_res[i],
3294 "securityIdentifier");
3296 trusts->array[n].guid = GUID_zero();
3298 trusts->count = n + 1;
3301 talloc_free(dom_res);
3306 netr_DsrEnumerateDomainTrusts
3308 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3309 TALLOC_CTX *mem_ctx,
3310 struct netr_DsrEnumerateDomainTrusts *r)
3312 struct netr_DomainTrustList *trusts;
3313 struct ldb_context *sam_ctx;
3315 struct ldb_message **dom_res;
3316 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3317 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3318 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3322 if (r->in.trust_flags & 0xFFFFFE00) {
3323 return WERR_INVALID_FLAGS;
3326 /* TODO: turn to hard check once we are sure this is 100% correct */
3327 if (!r->in.server_name) {
3328 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3329 "But received NULL!\n", dnsdomain));
3331 p = strchr(r->in.server_name, '.');
3333 DEBUG(3, ("Invalid domain! Expected name in domain "
3334 "[%s]. But received [%s]!\n",
3335 dnsdomain, r->in.server_name));
3336 p = r->in.server_name;
3340 if (strcasecmp(p, dnsdomain)) {
3341 DEBUG(3, ("Invalid domain! Expected name in domain "
3342 "[%s]. But received [%s]!\n",
3343 dnsdomain, r->in.server_name));
3347 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3348 W_ERROR_HAVE_NO_MEMORY(trusts);
3351 r->out.trusts = trusts;
3353 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3354 dce_call->conn->auth_state.session_info, 0);
3355 if (sam_ctx == NULL) {
3356 return WERR_GEN_FAILURE;
3359 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3360 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3362 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3363 trusts, r->in.trust_flags);
3364 W_ERROR_NOT_OK_RETURN(werr);
3367 /* NOTE: we currently are always the root of the forest */
3368 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3369 uint32_t n = trusts->count;
3371 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3372 &dom_res, dom_attrs);
3374 return WERR_GEN_FAILURE;
3377 trusts->count = n + 1;
3378 trusts->array = talloc_realloc(trusts, trusts->array,
3379 struct netr_DomainTrust,
3381 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3383 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3384 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3385 trusts->array[n].trust_flags =
3386 NETR_TRUST_FLAG_NATIVE |
3387 NETR_TRUST_FLAG_TREEROOT |
3388 NETR_TRUST_FLAG_IN_FOREST |
3389 NETR_TRUST_FLAG_PRIMARY;
3390 /* we are always the root domain for now */
3391 trusts->array[n].parent_index = 0;
3392 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3393 trusts->array[n].trust_attributes = 0;
3394 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3397 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3399 talloc_free(dom_res);
3407 netr_DsrDeregisterDNSHostRecords
3409 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3410 struct netr_DsrDeregisterDNSHostRecords *r)
3412 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3416 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3417 struct netr_ServerGetTrustInfo *r);
3420 netr_ServerTrustPasswordsGet
3422 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3423 struct netr_ServerTrustPasswordsGet *r)
3425 struct netr_ServerGetTrustInfo r2 = {};
3426 struct netr_TrustInfo *_ti = NULL;
3429 r2.in.server_name = r->in.server_name;
3430 r2.in.account_name = r->in.account_name;
3431 r2.in.secure_channel_type = r->in.secure_channel_type;
3432 r2.in.computer_name = r->in.computer_name;
3433 r2.in.credential = r->in.credential;
3435 r2.out.return_authenticator = r->out.return_authenticator;
3436 r2.out.new_owf_password = r->out.new_owf_password;
3437 r2.out.old_owf_password = r->out.old_owf_password;
3438 r2.out.trust_info = &_ti;
3440 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3442 r->out.return_authenticator = r2.out.return_authenticator;
3443 r->out.new_owf_password = r2.out.new_owf_password;
3444 r->out.old_owf_password = r2.out.old_owf_password;
3450 netr_DsRGetForestTrustInformation
3452 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3453 struct dcesrv_call_state *dce_call;
3454 TALLOC_CTX *mem_ctx;
3455 struct netr_DsRGetForestTrustInformation *r;
3458 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3460 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3461 TALLOC_CTX *mem_ctx,
3462 struct netr_DsRGetForestTrustInformation *r)
3464 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3465 struct dcesrv_connection *conn = dce_call->conn;
3466 struct auth_session_info *session_info = conn->auth_state.session_info;
3467 enum security_user_level security_level;
3468 struct ldb_context *sam_ctx = NULL;
3469 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3470 struct dcerpc_binding_handle *irpc_handle = NULL;
3471 struct tevent_req *subreq = NULL;
3472 struct ldb_dn *domain_dn = NULL;
3473 struct ldb_dn *forest_dn = NULL;
3477 security_level = security_session_user_level(session_info, NULL);
3478 if (security_level < SECURITY_USER) {
3479 return WERR_ACCESS_DENIED;
3482 if (r->in.flags & 0xFFFFFFFE) {
3483 return WERR_INVALID_FLAGS;
3486 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3487 dce_call->conn->auth_state.session_info, 0);
3488 if (sam_ctx == NULL) {
3489 return WERR_GEN_FAILURE;
3492 domain_dn = ldb_get_default_basedn(sam_ctx);
3493 if (domain_dn == NULL) {
3494 return WERR_GEN_FAILURE;
3497 forest_dn = ldb_get_root_basedn(sam_ctx);
3498 if (forest_dn == NULL) {
3499 return WERR_GEN_FAILURE;
3502 cmp = ldb_dn_compare(domain_dn, forest_dn);
3504 return WERR_NERR_ACFNOTLOADED;
3507 forest_level = dsdb_forest_functional_level(sam_ctx);
3508 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3509 return WERR_INVALID_FUNCTION;
3512 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3513 if (!samdb_is_pdc(sam_ctx)) {
3514 return WERR_NERR_NOTPRIMARY;
3517 if (r->in.trusted_domain_name == NULL) {
3518 return WERR_INVALID_FLAGS;
3522 if (r->in.trusted_domain_name == NULL) {
3526 * information about our own domain
3528 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3529 r->out.forest_trust_info);
3530 if (!NT_STATUS_IS_OK(status)) {
3531 return ntstatus_to_werror(status);
3538 * Forward the request to winbindd
3541 state = talloc_zero(mem_ctx,
3542 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3543 if (state == NULL) {
3544 return WERR_NOT_ENOUGH_MEMORY;
3546 state->dce_call = dce_call;
3547 state->mem_ctx = mem_ctx;
3550 irpc_handle = irpc_binding_handle_by_name(state,
3551 state->dce_call->msg_ctx,
3553 &ndr_table_winbind);
3554 if (irpc_handle == NULL) {
3555 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3556 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3557 return WERR_SERVICE_NOT_FOUND;
3561 * 60 seconds timeout should be enough
3563 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3565 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3566 state->dce_call->event_ctx,
3568 r->in.trusted_domain_name,
3570 r->out.forest_trust_info);
3571 if (subreq == NULL) {
3572 return WERR_NOT_ENOUGH_MEMORY;
3574 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3575 tevent_req_set_callback(subreq,
3576 dcesrv_netr_DsRGetForestTrustInformation_done,
3582 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3584 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3585 tevent_req_callback_data(subreq,
3586 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3589 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3591 &state->r->out.result);
3592 TALLOC_FREE(subreq);
3593 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3594 state->r->out.result = WERR_TIMEOUT;
3595 } else if (!NT_STATUS_IS_OK(status)) {
3596 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3597 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3598 nt_errstr(status)));
3601 status = dcesrv_reply(state->dce_call);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3608 netr_GetForestTrustInformation
3610 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3611 TALLOC_CTX *mem_ctx,
3612 struct netr_GetForestTrustInformation *r)
3614 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3615 struct netlogon_creds_CredentialState *creds = NULL;
3616 struct ldb_context *sam_ctx = NULL;
3617 struct ldb_dn *domain_dn = NULL;
3618 struct ldb_dn *forest_dn = NULL;
3623 status = dcesrv_netr_creds_server_step_check(dce_call,
3625 r->in.computer_name,
3627 r->out.return_authenticator,
3629 if (!NT_STATUS_IS_OK(status)) {
3633 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3634 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3635 return NT_STATUS_NOT_IMPLEMENTED;
3638 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3639 dce_call->conn->auth_state.session_info, 0);
3640 if (sam_ctx == NULL) {
3641 return NT_STATUS_INTERNAL_ERROR;
3644 /* TODO: check r->in.server_name is our name */
3646 domain_dn = ldb_get_default_basedn(sam_ctx);
3647 if (domain_dn == NULL) {
3648 return NT_STATUS_INTERNAL_ERROR;
3651 forest_dn = ldb_get_root_basedn(sam_ctx);
3652 if (forest_dn == NULL) {
3653 return NT_STATUS_INTERNAL_ERROR;
3656 cmp = ldb_dn_compare(domain_dn, forest_dn);
3658 return NT_STATUS_INVALID_DOMAIN_STATE;
3661 forest_level = dsdb_forest_functional_level(sam_ctx);
3662 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3663 return NT_STATUS_INVALID_DOMAIN_STATE;
3666 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3667 r->out.forest_trust_info);
3668 if (!NT_STATUS_IS_OK(status)) {
3672 return NT_STATUS_OK;
3677 netr_ServerGetTrustInfo
3679 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3680 struct netr_ServerGetTrustInfo *r)
3682 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3683 struct netlogon_creds_CredentialState *creds = NULL;
3684 struct ldb_context *sam_ctx = NULL;
3685 const char * const attrs[] = {
3688 "userAccountControl",
3691 struct ldb_message **res = NULL;
3692 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3695 const char *asid = NULL;
3697 const char *aname = NULL;
3698 struct ldb_message *tdo_msg = NULL;
3699 const char * const tdo_attrs[] = {
3700 "trustAuthIncoming",
3704 struct netr_TrustInfo *trust_info = NULL;
3706 ZERO_STRUCTP(r->out.new_owf_password);
3707 ZERO_STRUCTP(r->out.old_owf_password);
3709 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3711 r->in.computer_name,
3713 r->out.return_authenticator,
3715 if (!NT_STATUS_IS_OK(nt_status)) {
3719 /* TODO: check r->in.server_name is our name */
3721 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3722 return NT_STATUS_INVALID_PARAMETER;
3725 if (r->in.secure_channel_type != creds->secure_channel_type) {
3726 return NT_STATUS_INVALID_PARAMETER;
3729 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3730 return NT_STATUS_INVALID_PARAMETER;
3733 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3734 lp_ctx, system_session(lp_ctx), 0);
3735 if (sam_ctx == NULL) {
3736 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3739 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3741 return NT_STATUS_NO_MEMORY;
3744 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3745 "(&(objectClass=user)(objectSid=%s))",
3748 return NT_STATUS_ACCOUNT_DISABLED;
3751 switch (creds->secure_channel_type) {
3752 case SEC_CHAN_DNS_DOMAIN:
3753 case SEC_CHAN_DOMAIN:
3754 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3756 if (uac & UF_ACCOUNTDISABLE) {
3757 return NT_STATUS_ACCOUNT_DISABLED;
3760 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3761 return NT_STATUS_ACCOUNT_DISABLED;
3764 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3765 if (aname == NULL) {
3766 return NT_STATUS_ACCOUNT_DISABLED;
3769 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3770 SEC_CHAN_DOMAIN, aname,
3771 tdo_attrs, mem_ctx, &tdo_msg);
3772 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3773 return NT_STATUS_ACCOUNT_DISABLED;
3775 if (!NT_STATUS_IS_OK(nt_status)) {
3779 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3782 if (!NT_STATUS_IS_OK(nt_status)) {
3786 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3787 if (trust_info == NULL) {
3788 return NT_STATUS_NO_MEMORY;
3791 trust_info->count = 1;
3792 trust_info->data = talloc_array(trust_info, uint32_t,
3794 if (trust_info->data == NULL) {
3795 return NT_STATUS_NO_MEMORY;
3798 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3804 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3807 if (!NT_STATUS_IS_OK(nt_status)) {
3811 prevNtHash = talloc(mem_ctx, struct samr_Password);
3812 if (prevNtHash == NULL) {
3813 return NT_STATUS_NO_MEMORY;
3816 E_md4hash("", prevNtHash->hash);
3820 if (curNtHash != NULL) {
3821 *r->out.new_owf_password = *curNtHash;
3822 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3824 if (prevNtHash != NULL) {
3825 *r->out.old_owf_password = *prevNtHash;
3826 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3829 if (trust_info != NULL) {
3830 *r->out.trust_info = trust_info;
3833 return NT_STATUS_OK;
3839 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840 struct netr_Unused47 *r)
3842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3846 struct netr_dnsupdate_RODC_state {
3847 struct dcesrv_call_state *dce_call;
3848 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3849 struct dnsupdate_RODC *r2;
3853 called when the forwarded RODC dns update request is finished
3855 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3857 struct netr_dnsupdate_RODC_state *st =
3858 tevent_req_callback_data(subreq,
3859 struct netr_dnsupdate_RODC_state);
3862 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3863 TALLOC_FREE(subreq);
3864 if (!NT_STATUS_IS_OK(status)) {
3865 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3866 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3869 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3871 status = dcesrv_reply(st->dce_call);
3872 if (!NT_STATUS_IS_OK(status)) {
3873 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3878 netr_DsrUpdateReadOnlyServerDnsRecords
3880 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3881 TALLOC_CTX *mem_ctx,
3882 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3884 struct netlogon_creds_CredentialState *creds;
3886 struct dcerpc_binding_handle *binding_handle;
3887 struct netr_dnsupdate_RODC_state *st;
3888 struct tevent_req *subreq;
3890 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3892 r->in.computer_name,
3894 r->out.return_authenticator,
3896 NT_STATUS_NOT_OK_RETURN(nt_status);
3898 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3899 return NT_STATUS_ACCESS_DENIED;
3902 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3903 NT_STATUS_HAVE_NO_MEMORY(st);
3905 st->dce_call = dce_call;
3907 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3908 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3910 st->r2->in.dom_sid = creds->sid;
3911 st->r2->in.site_name = r->in.site_name;
3912 st->r2->in.dns_ttl = r->in.dns_ttl;
3913 st->r2->in.dns_names = r->in.dns_names;
3914 st->r2->out.dns_names = r->out.dns_names;
3916 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3917 "dnsupdate", &ndr_table_irpc);
3918 if (binding_handle == NULL) {
3919 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3920 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3921 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3924 /* forward the call */
3925 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3926 binding_handle, st->r2);
3927 NT_STATUS_HAVE_NO_MEMORY(subreq);
3929 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3931 /* setup the callback */
3932 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3934 return NT_STATUS_OK;
3938 /* include the generated boilerplate */
3939 #include "librpc/gen_ndr/ndr_netlogon_s.c"