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;
2754 netr_DsRGetDCNameEx2
2756 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2757 TALLOC_CTX *mem_ctx,
2758 struct netr_DsRGetDCNameEx2 *r)
2760 struct ldb_context *sam_ctx;
2761 struct netr_DsRGetDCNameInfo *info;
2762 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2763 const struct tsocket_address *local_address;
2764 char *local_addr = NULL;
2765 const struct tsocket_address *remote_address;
2766 char *remote_addr = NULL;
2767 const char *server_site_name;
2769 struct netlogon_samlogon_response response;
2771 const char *dc_name = NULL;
2772 const char *domain_name = NULL;
2775 ZERO_STRUCTP(r->out.info);
2777 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2778 dce_call->conn->auth_state.session_info, 0);
2779 if (sam_ctx == NULL) {
2780 return WERR_DS_UNAVAILABLE;
2783 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2784 if (tsocket_address_is_inet(local_address, "ip")) {
2785 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2786 W_ERROR_HAVE_NO_MEMORY(local_addr);
2789 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2790 if (tsocket_address_is_inet(remote_address, "ip")) {
2791 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2792 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2795 /* "server_unc" is ignored by w2k3 */
2797 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2798 return WERR_INVALID_FLAGS;
2801 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2802 r->in.flags & DS_PDC_REQUIRED &&
2803 r->in.flags & DS_KDC_REQUIRED) {
2804 return WERR_INVALID_FLAGS;
2806 if (r->in.flags & DS_IS_FLAT_NAME &&
2807 r->in.flags & DS_IS_DNS_NAME) {
2808 return WERR_INVALID_FLAGS;
2810 if (r->in.flags & DS_RETURN_DNS_NAME &&
2811 r->in.flags & DS_RETURN_FLAT_NAME) {
2812 return WERR_INVALID_FLAGS;
2814 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2815 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2816 return WERR_INVALID_FLAGS;
2819 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2821 (DS_DIRECTORY_SERVICE_REQUIRED |
2822 DS_DIRECTORY_SERVICE_PREFERRED |
2823 DS_GC_SERVER_REQUIRED |
2826 return WERR_INVALID_FLAGS;
2829 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2831 return WERR_INVALID_FLAGS;
2834 /* Proof server site parameter "site_name" if it was specified */
2835 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2836 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2837 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2838 server_site_name) != 0)) {
2839 return WERR_NO_SUCH_DOMAIN;
2842 guid_str = r->in.domain_guid != NULL ?
2843 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2845 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2849 r->in.client_account,
2850 r->in.mask, remote_addr,
2851 NETLOGON_NT_VERSION_5EX_WITH_IP,
2852 lp_ctx, &response, true);
2853 if (!NT_STATUS_IS_OK(status)) {
2854 return ntstatus_to_werror(status);
2858 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2859 * (O) flag when the returned forest name is in DNS format. This is here
2860 * always the case (see below).
2862 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2864 if (r->in.flags & DS_RETURN_DNS_NAME) {
2865 dc_name = response.data.nt5_ex.pdc_dns_name;
2866 domain_name = response.data.nt5_ex.dns_domain;
2868 * According to MS-NRPC 2.2.1.2.1 we should set the
2869 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2870 * the returned information is in DNS form.
2872 response.data.nt5_ex.server_type |=
2873 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2874 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2875 dc_name = response.data.nt5_ex.pdc_name;
2876 domain_name = response.data.nt5_ex.domain_name;
2880 * TODO: autodetect what we need to return
2881 * based on the given arguments
2883 dc_name = response.data.nt5_ex.pdc_name;
2884 domain_name = response.data.nt5_ex.domain_name;
2887 if (!dc_name || !dc_name[0]) {
2888 return WERR_NO_SUCH_DOMAIN;
2891 if (!domain_name || !domain_name[0]) {
2892 return WERR_NO_SUCH_DOMAIN;
2895 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2896 W_ERROR_HAVE_NO_MEMORY(info);
2897 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2898 dc_name[0] != '\\'? "\\\\":"",
2899 talloc_strdup(mem_ctx, dc_name));
2900 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2902 pdc_ip = local_addr;
2903 if (pdc_ip == NULL) {
2904 pdc_ip = "127.0.0.1";
2906 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2907 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2908 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2909 info->domain_guid = response.data.nt5_ex.domain_uuid;
2910 info->domain_name = domain_name;
2911 info->forest_name = response.data.nt5_ex.forest;
2912 info->dc_flags = response.data.nt5_ex.server_type;
2913 if (r->in.flags & DS_RETURN_DNS_NAME) {
2914 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2915 * returned if we are returning info->dc_unc containing a FQDN.
2916 * This attribute is called DomainControllerName in the specs,
2917 * it seems that we decide to return FQDN or netbios depending on
2918 * DS_RETURN_DNS_NAME.
2920 info->dc_flags |= DS_DNS_CONTROLLER;
2922 info->dc_site_name = response.data.nt5_ex.server_site;
2923 info->client_site_name = response.data.nt5_ex.client_site;
2925 *r->out.info = info;
2933 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2934 struct netr_DsRGetDCNameEx *r)
2936 struct netr_DsRGetDCNameEx2 r2;
2941 r2.in.server_unc = r->in.server_unc;
2942 r2.in.client_account = NULL;
2944 r2.in.domain_guid = r->in.domain_guid;
2945 r2.in.domain_name = r->in.domain_name;
2946 r2.in.site_name = r->in.site_name;
2947 r2.in.flags = r->in.flags;
2948 r2.out.info = r->out.info;
2950 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2958 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2959 struct netr_DsRGetDCName *r)
2961 struct netr_DsRGetDCNameEx2 r2;
2966 r2.in.server_unc = r->in.server_unc;
2967 r2.in.client_account = NULL;
2969 r2.in.domain_name = r->in.domain_name;
2970 r2.in.domain_guid = r->in.domain_guid;
2972 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2973 r2.in.flags = r->in.flags;
2974 r2.out.info = r->out.info;
2976 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2981 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2983 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2984 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2986 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2991 netr_NetrEnumerateTrustedDomainsEx
2993 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2994 struct netr_NetrEnumerateTrustedDomainsEx *r)
2996 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3001 netr_DsRAddressToSitenamesExW
3003 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3004 struct netr_DsRAddressToSitenamesExW *r)
3006 struct ldb_context *sam_ctx;
3007 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3008 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3009 sa_family_t sin_family;
3010 struct sockaddr_in *addr;
3012 struct sockaddr_in6 *addr6;
3013 char addr_str[INET6_ADDRSTRLEN];
3015 char addr_str[INET_ADDRSTRLEN];
3021 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3022 dce_call->conn->auth_state.session_info, 0);
3023 if (sam_ctx == NULL) {
3024 return WERR_DS_UNAVAILABLE;
3027 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3028 W_ERROR_HAVE_NO_MEMORY(ctr);
3032 ctr->count = r->in.count;
3033 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3034 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3035 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3036 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3038 for (i=0; i<ctr->count; i++) {
3039 ctr->sitename[i].string = NULL;
3040 ctr->subnetname[i].string = NULL;
3042 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3045 /* The first two byte of the buffer are reserved for the
3046 * "sin_family" but for now only the first one is used. */
3047 sin_family = r->in.addresses[i].buffer[0];
3049 switch (sin_family) {
3051 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3054 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3055 res = inet_ntop(AF_INET, &addr->sin_addr,
3056 addr_str, sizeof(addr_str));
3060 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3063 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3064 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3065 addr_str, sizeof(addr_str));
3076 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3080 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3081 ctr->subnetname[i].string = subnet_name;
3089 netr_DsRAddressToSitenamesW
3091 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3092 struct netr_DsRAddressToSitenamesW *r)
3094 struct netr_DsRAddressToSitenamesExW r2;
3095 struct netr_DsRAddressToSitenamesWCtr *ctr;
3101 r2.in.server_name = r->in.server_name;
3102 r2.in.count = r->in.count;
3103 r2.in.addresses = r->in.addresses;
3105 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3106 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3108 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3109 W_ERROR_HAVE_NO_MEMORY(ctr);
3113 ctr->count = r->in.count;
3114 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3115 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3117 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3119 for (i=0; i<ctr->count; i++) {
3120 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3128 netr_DsrGetDcSiteCoverageW
3130 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3131 struct netr_DsrGetDcSiteCoverageW *r)
3133 struct ldb_context *sam_ctx;
3134 struct DcSitesCtr *ctr;
3135 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3137 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3138 dce_call->conn->auth_state.session_info, 0);
3139 if (sam_ctx == NULL) {
3140 return WERR_DS_UNAVAILABLE;
3143 ctr = talloc(mem_ctx, struct DcSitesCtr);
3144 W_ERROR_HAVE_NO_MEMORY(ctr);
3148 /* For now only return our default site */
3150 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3151 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3152 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3153 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3159 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3160 struct ldb_context *sam_ctx,
3161 struct netr_DomainTrustList *trusts,
3162 uint32_t trust_flags)
3164 struct ldb_dn *system_dn;
3165 struct ldb_message **dom_res = NULL;
3166 const char *trust_attrs[] = { "flatname", "trustPartner",
3167 "securityIdentifier", "trustDirection",
3168 "trustType", "trustAttributes", NULL };
3173 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3174 NETR_TRUST_FLAG_OUTBOUND))) {
3175 return WERR_INVALID_FLAGS;
3178 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3179 ldb_get_default_basedn(sam_ctx),
3180 "(&(objectClass=container)(cn=System))");
3182 return WERR_GEN_FAILURE;
3185 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3186 &dom_res, trust_attrs,
3187 "(objectclass=trustedDomain)");
3189 for (i = 0; i < ret; i++) {
3190 unsigned int trust_dir;
3193 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3194 "trustDirection", 0);
3196 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3197 flags |= NETR_TRUST_FLAG_INBOUND;
3199 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3200 flags |= NETR_TRUST_FLAG_OUTBOUND;
3203 if (!(flags & trust_flags)) {
3204 /* this trust direction was not requested */
3209 trusts->array = talloc_realloc(trusts, trusts->array,
3210 struct netr_DomainTrust,
3212 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3214 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3215 if (!trusts->array[n].netbios_name) {
3216 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3217 "without flatname\n",
3218 ldb_dn_get_linearized(dom_res[i]->dn)));
3221 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3223 trusts->array[n].trust_flags = flags;
3224 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3225 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3226 /* TODO: find if we have parent in the list */
3227 trusts->array[n].parent_index = 0;
3230 trusts->array[n].trust_type =
3231 ldb_msg_find_attr_as_uint(dom_res[i],
3233 trusts->array[n].trust_attributes =
3234 ldb_msg_find_attr_as_uint(dom_res[i],
3235 "trustAttributes", 0);
3237 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3238 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3239 struct dom_sid zero_sid;
3240 ZERO_STRUCT(zero_sid);
3241 trusts->array[n].sid =
3242 dom_sid_dup(trusts, &zero_sid);
3244 trusts->array[n].sid =
3245 samdb_result_dom_sid(trusts, dom_res[i],
3246 "securityIdentifier");
3248 trusts->array[n].guid = GUID_zero();
3250 trusts->count = n + 1;
3253 talloc_free(dom_res);
3258 netr_DsrEnumerateDomainTrusts
3260 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3261 TALLOC_CTX *mem_ctx,
3262 struct netr_DsrEnumerateDomainTrusts *r)
3264 struct netr_DomainTrustList *trusts;
3265 struct ldb_context *sam_ctx;
3267 struct ldb_message **dom_res;
3268 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3269 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3270 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3274 if (r->in.trust_flags & 0xFFFFFE00) {
3275 return WERR_INVALID_FLAGS;
3278 /* TODO: turn to hard check once we are sure this is 100% correct */
3279 if (!r->in.server_name) {
3280 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3281 "But received NULL!\n", dnsdomain));
3283 p = strchr(r->in.server_name, '.');
3285 DEBUG(3, ("Invalid domain! Expected name in domain "
3286 "[%s]. But received [%s]!\n",
3287 dnsdomain, r->in.server_name));
3288 p = r->in.server_name;
3292 if (strcasecmp(p, dnsdomain)) {
3293 DEBUG(3, ("Invalid domain! Expected name in domain "
3294 "[%s]. But received [%s]!\n",
3295 dnsdomain, r->in.server_name));
3299 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3300 W_ERROR_HAVE_NO_MEMORY(trusts);
3303 r->out.trusts = trusts;
3305 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3306 dce_call->conn->auth_state.session_info, 0);
3307 if (sam_ctx == NULL) {
3308 return WERR_GEN_FAILURE;
3311 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3312 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3314 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3315 trusts, r->in.trust_flags);
3316 W_ERROR_NOT_OK_RETURN(werr);
3319 /* NOTE: we currently are always the root of the forest */
3320 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3321 uint32_t n = trusts->count;
3323 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3324 &dom_res, dom_attrs);
3326 return WERR_GEN_FAILURE;
3329 trusts->count = n + 1;
3330 trusts->array = talloc_realloc(trusts, trusts->array,
3331 struct netr_DomainTrust,
3333 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3335 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3336 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3337 trusts->array[n].trust_flags =
3338 NETR_TRUST_FLAG_NATIVE |
3339 NETR_TRUST_FLAG_TREEROOT |
3340 NETR_TRUST_FLAG_IN_FOREST |
3341 NETR_TRUST_FLAG_PRIMARY;
3342 /* we are always the root domain for now */
3343 trusts->array[n].parent_index = 0;
3344 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3345 trusts->array[n].trust_attributes = 0;
3346 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3349 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3351 talloc_free(dom_res);
3359 netr_DsrDeregisterDNSHostRecords
3361 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3362 struct netr_DsrDeregisterDNSHostRecords *r)
3364 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3368 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3369 struct netr_ServerGetTrustInfo *r);
3372 netr_ServerTrustPasswordsGet
3374 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3375 struct netr_ServerTrustPasswordsGet *r)
3377 struct netr_ServerGetTrustInfo r2 = {};
3378 struct netr_TrustInfo *_ti = NULL;
3381 r2.in.server_name = r->in.server_name;
3382 r2.in.account_name = r->in.account_name;
3383 r2.in.secure_channel_type = r->in.secure_channel_type;
3384 r2.in.computer_name = r->in.computer_name;
3385 r2.in.credential = r->in.credential;
3387 r2.out.return_authenticator = r->out.return_authenticator;
3388 r2.out.new_owf_password = r->out.new_owf_password;
3389 r2.out.old_owf_password = r->out.old_owf_password;
3390 r2.out.trust_info = &_ti;
3392 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3394 r->out.return_authenticator = r2.out.return_authenticator;
3395 r->out.new_owf_password = r2.out.new_owf_password;
3396 r->out.old_owf_password = r2.out.old_owf_password;
3402 netr_DsRGetForestTrustInformation
3404 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3405 struct dcesrv_call_state *dce_call;
3406 TALLOC_CTX *mem_ctx;
3407 struct netr_DsRGetForestTrustInformation *r;
3410 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3412 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3413 TALLOC_CTX *mem_ctx,
3414 struct netr_DsRGetForestTrustInformation *r)
3416 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3417 struct dcesrv_connection *conn = dce_call->conn;
3418 struct auth_session_info *session_info = conn->auth_state.session_info;
3419 enum security_user_level security_level;
3420 struct ldb_context *sam_ctx = NULL;
3421 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3422 struct dcerpc_binding_handle *irpc_handle = NULL;
3423 struct tevent_req *subreq = NULL;
3424 struct ldb_dn *domain_dn = NULL;
3425 struct ldb_dn *forest_dn = NULL;
3429 security_level = security_session_user_level(session_info, NULL);
3430 if (security_level < SECURITY_USER) {
3431 return WERR_ACCESS_DENIED;
3434 if (r->in.flags & 0xFFFFFFFE) {
3435 return WERR_INVALID_FLAGS;
3438 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3439 dce_call->conn->auth_state.session_info, 0);
3440 if (sam_ctx == NULL) {
3441 return WERR_GEN_FAILURE;
3444 domain_dn = ldb_get_default_basedn(sam_ctx);
3445 if (domain_dn == NULL) {
3446 return WERR_GEN_FAILURE;
3449 forest_dn = ldb_get_root_basedn(sam_ctx);
3450 if (forest_dn == NULL) {
3451 return WERR_GEN_FAILURE;
3454 cmp = ldb_dn_compare(domain_dn, forest_dn);
3456 return WERR_NERR_ACFNOTLOADED;
3459 forest_level = dsdb_forest_functional_level(sam_ctx);
3460 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3461 return WERR_INVALID_FUNCTION;
3464 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3465 if (!samdb_is_pdc(sam_ctx)) {
3466 return WERR_NERR_NOTPRIMARY;
3469 if (r->in.trusted_domain_name == NULL) {
3470 return WERR_INVALID_FLAGS;
3474 if (r->in.trusted_domain_name == NULL) {
3478 * information about our own domain
3480 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3481 r->out.forest_trust_info);
3482 if (!NT_STATUS_IS_OK(status)) {
3483 return ntstatus_to_werror(status);
3490 * Forward the request to winbindd
3493 state = talloc_zero(mem_ctx,
3494 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3495 if (state == NULL) {
3496 return WERR_NOT_ENOUGH_MEMORY;
3498 state->dce_call = dce_call;
3499 state->mem_ctx = mem_ctx;
3502 irpc_handle = irpc_binding_handle_by_name(state,
3503 state->dce_call->msg_ctx,
3505 &ndr_table_winbind);
3506 if (irpc_handle == NULL) {
3507 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3508 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3509 return WERR_SERVICE_NOT_FOUND;
3513 * 60 seconds timeout should be enough
3515 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3517 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3518 state->dce_call->event_ctx,
3520 r->in.trusted_domain_name,
3522 r->out.forest_trust_info);
3523 if (subreq == NULL) {
3524 return WERR_NOT_ENOUGH_MEMORY;
3526 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3527 tevent_req_set_callback(subreq,
3528 dcesrv_netr_DsRGetForestTrustInformation_done,
3534 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3536 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3537 tevent_req_callback_data(subreq,
3538 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3541 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3543 &state->r->out.result);
3544 TALLOC_FREE(subreq);
3545 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3546 state->r->out.result = WERR_TIMEOUT;
3547 } else if (!NT_STATUS_IS_OK(status)) {
3548 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3549 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3550 nt_errstr(status)));
3553 status = dcesrv_reply(state->dce_call);
3554 if (!NT_STATUS_IS_OK(status)) {
3555 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3560 netr_GetForestTrustInformation
3562 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3563 TALLOC_CTX *mem_ctx,
3564 struct netr_GetForestTrustInformation *r)
3566 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3567 struct netlogon_creds_CredentialState *creds = NULL;
3568 struct ldb_context *sam_ctx = NULL;
3569 struct ldb_dn *domain_dn = NULL;
3570 struct ldb_dn *forest_dn = NULL;
3575 status = dcesrv_netr_creds_server_step_check(dce_call,
3577 r->in.computer_name,
3579 r->out.return_authenticator,
3581 if (!NT_STATUS_IS_OK(status)) {
3585 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3586 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3587 return NT_STATUS_NOT_IMPLEMENTED;
3590 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3591 dce_call->conn->auth_state.session_info, 0);
3592 if (sam_ctx == NULL) {
3593 return NT_STATUS_INTERNAL_ERROR;
3596 /* TODO: check r->in.server_name is our name */
3598 domain_dn = ldb_get_default_basedn(sam_ctx);
3599 if (domain_dn == NULL) {
3600 return NT_STATUS_INTERNAL_ERROR;
3603 forest_dn = ldb_get_root_basedn(sam_ctx);
3604 if (forest_dn == NULL) {
3605 return NT_STATUS_INTERNAL_ERROR;
3608 cmp = ldb_dn_compare(domain_dn, forest_dn);
3610 return NT_STATUS_INVALID_DOMAIN_STATE;
3613 forest_level = dsdb_forest_functional_level(sam_ctx);
3614 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3615 return NT_STATUS_INVALID_DOMAIN_STATE;
3618 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3619 r->out.forest_trust_info);
3620 if (!NT_STATUS_IS_OK(status)) {
3624 return NT_STATUS_OK;
3629 netr_ServerGetTrustInfo
3631 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3632 struct netr_ServerGetTrustInfo *r)
3634 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3635 struct netlogon_creds_CredentialState *creds = NULL;
3636 struct ldb_context *sam_ctx = NULL;
3637 const char * const attrs[] = {
3640 "userAccountControl",
3643 struct ldb_message **res = NULL;
3644 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3647 const char *asid = NULL;
3649 const char *aname = NULL;
3650 struct ldb_message *tdo_msg = NULL;
3651 const char * const tdo_attrs[] = {
3652 "trustAuthIncoming",
3656 struct netr_TrustInfo *trust_info = NULL;
3658 ZERO_STRUCTP(r->out.new_owf_password);
3659 ZERO_STRUCTP(r->out.old_owf_password);
3661 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3663 r->in.computer_name,
3665 r->out.return_authenticator,
3667 if (!NT_STATUS_IS_OK(nt_status)) {
3671 /* TODO: check r->in.server_name is our name */
3673 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3674 return NT_STATUS_INVALID_PARAMETER;
3677 if (r->in.secure_channel_type != creds->secure_channel_type) {
3678 return NT_STATUS_INVALID_PARAMETER;
3681 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3682 return NT_STATUS_INVALID_PARAMETER;
3685 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3686 lp_ctx, system_session(lp_ctx), 0);
3687 if (sam_ctx == NULL) {
3688 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3691 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3693 return NT_STATUS_NO_MEMORY;
3696 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3697 "(&(objectClass=user)(objectSid=%s))",
3700 return NT_STATUS_ACCOUNT_DISABLED;
3703 switch (creds->secure_channel_type) {
3704 case SEC_CHAN_DNS_DOMAIN:
3705 case SEC_CHAN_DOMAIN:
3706 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3708 if (uac & UF_ACCOUNTDISABLE) {
3709 return NT_STATUS_ACCOUNT_DISABLED;
3712 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3713 return NT_STATUS_ACCOUNT_DISABLED;
3716 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3717 if (aname == NULL) {
3718 return NT_STATUS_ACCOUNT_DISABLED;
3721 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3722 SEC_CHAN_DOMAIN, aname,
3723 tdo_attrs, mem_ctx, &tdo_msg);
3724 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3725 return NT_STATUS_ACCOUNT_DISABLED;
3727 if (!NT_STATUS_IS_OK(nt_status)) {
3731 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3734 if (!NT_STATUS_IS_OK(nt_status)) {
3738 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3739 if (trust_info == NULL) {
3740 return NT_STATUS_NO_MEMORY;
3743 trust_info->count = 1;
3744 trust_info->data = talloc_array(trust_info, uint32_t,
3746 if (trust_info->data == NULL) {
3747 return NT_STATUS_NO_MEMORY;
3750 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3756 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3759 if (!NT_STATUS_IS_OK(nt_status)) {
3763 prevNtHash = talloc(mem_ctx, struct samr_Password);
3764 if (prevNtHash == NULL) {
3765 return NT_STATUS_NO_MEMORY;
3768 E_md4hash("", prevNtHash->hash);
3772 if (curNtHash != NULL) {
3773 *r->out.new_owf_password = *curNtHash;
3774 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3776 if (prevNtHash != NULL) {
3777 *r->out.old_owf_password = *prevNtHash;
3778 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3781 if (trust_info != NULL) {
3782 *r->out.trust_info = trust_info;
3785 return NT_STATUS_OK;
3791 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3792 struct netr_Unused47 *r)
3794 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3798 struct netr_dnsupdate_RODC_state {
3799 struct dcesrv_call_state *dce_call;
3800 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3801 struct dnsupdate_RODC *r2;
3805 called when the forwarded RODC dns update request is finished
3807 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3809 struct netr_dnsupdate_RODC_state *st =
3810 tevent_req_callback_data(subreq,
3811 struct netr_dnsupdate_RODC_state);
3814 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3815 TALLOC_FREE(subreq);
3816 if (!NT_STATUS_IS_OK(status)) {
3817 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3818 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3821 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3823 status = dcesrv_reply(st->dce_call);
3824 if (!NT_STATUS_IS_OK(status)) {
3825 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3830 netr_DsrUpdateReadOnlyServerDnsRecords
3832 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3833 TALLOC_CTX *mem_ctx,
3834 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3836 struct netlogon_creds_CredentialState *creds;
3838 struct dcerpc_binding_handle *binding_handle;
3839 struct netr_dnsupdate_RODC_state *st;
3840 struct tevent_req *subreq;
3842 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3844 r->in.computer_name,
3846 r->out.return_authenticator,
3848 NT_STATUS_NOT_OK_RETURN(nt_status);
3850 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3851 return NT_STATUS_ACCESS_DENIED;
3854 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3855 NT_STATUS_HAVE_NO_MEMORY(st);
3857 st->dce_call = dce_call;
3859 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3860 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3862 st->r2->in.dom_sid = creds->sid;
3863 st->r2->in.site_name = r->in.site_name;
3864 st->r2->in.dns_ttl = r->in.dns_ttl;
3865 st->r2->in.dns_names = r->in.dns_names;
3866 st->r2->out.dns_names = r->out.dns_names;
3868 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3869 "dnsupdate", &ndr_table_irpc);
3870 if (binding_handle == NULL) {
3871 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3872 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3873 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3876 /* forward the call */
3877 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3878 binding_handle, st->r2);
3879 NT_STATUS_HAVE_NO_MEMORY(subreq);
3881 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3883 /* setup the callback */
3884 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3886 return NT_STATUS_OK;
3890 /* include the generated boilerplate */
3891 #include "librpc/gen_ndr/ndr_netlogon_s.c"