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 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
2959 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
2960 * insists that it be ignored.
2962 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2963 struct netr_DsRGetDCName *r)
2965 struct netr_DsRGetDCNameEx2 r2;
2970 r2.in.server_unc = r->in.server_unc;
2971 r2.in.client_account = NULL;
2973 r2.in.domain_name = r->in.domain_name;
2974 r2.in.domain_guid = r->in.domain_guid;
2976 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2977 r2.in.flags = r->in.flags;
2978 r2.out.info = r->out.info;
2980 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2985 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2987 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2988 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2990 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2995 netr_NetrEnumerateTrustedDomainsEx
2997 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2998 struct netr_NetrEnumerateTrustedDomainsEx *r)
3000 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3005 netr_DsRAddressToSitenamesExW
3007 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3008 struct netr_DsRAddressToSitenamesExW *r)
3010 struct ldb_context *sam_ctx;
3011 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3012 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3013 sa_family_t sin_family;
3014 struct sockaddr_in *addr;
3016 struct sockaddr_in6 *addr6;
3017 char addr_str[INET6_ADDRSTRLEN];
3019 char addr_str[INET_ADDRSTRLEN];
3025 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3026 dce_call->conn->auth_state.session_info, 0);
3027 if (sam_ctx == NULL) {
3028 return WERR_DS_UNAVAILABLE;
3031 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3032 W_ERROR_HAVE_NO_MEMORY(ctr);
3036 ctr->count = r->in.count;
3037 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3038 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3039 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3040 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3042 for (i=0; i<ctr->count; i++) {
3043 ctr->sitename[i].string = NULL;
3044 ctr->subnetname[i].string = NULL;
3046 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3049 /* The first two byte of the buffer are reserved for the
3050 * "sin_family" but for now only the first one is used. */
3051 sin_family = r->in.addresses[i].buffer[0];
3053 switch (sin_family) {
3055 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3058 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3059 res = inet_ntop(AF_INET, &addr->sin_addr,
3060 addr_str, sizeof(addr_str));
3064 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3067 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3068 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3069 addr_str, sizeof(addr_str));
3080 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3085 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3086 ctr->subnetname[i].string = subnet_name;
3094 netr_DsRAddressToSitenamesW
3096 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3097 struct netr_DsRAddressToSitenamesW *r)
3099 struct netr_DsRAddressToSitenamesExW r2;
3100 struct netr_DsRAddressToSitenamesWCtr *ctr;
3106 r2.in.server_name = r->in.server_name;
3107 r2.in.count = r->in.count;
3108 r2.in.addresses = r->in.addresses;
3110 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3111 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3113 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3114 W_ERROR_HAVE_NO_MEMORY(ctr);
3118 ctr->count = r->in.count;
3119 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3120 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3122 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3124 for (i=0; i<ctr->count; i++) {
3125 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3133 netr_DsrGetDcSiteCoverageW
3135 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3136 struct netr_DsrGetDcSiteCoverageW *r)
3138 struct ldb_context *sam_ctx;
3139 struct DcSitesCtr *ctr;
3140 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3142 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3143 dce_call->conn->auth_state.session_info, 0);
3144 if (sam_ctx == NULL) {
3145 return WERR_DS_UNAVAILABLE;
3148 ctr = talloc(mem_ctx, struct DcSitesCtr);
3149 W_ERROR_HAVE_NO_MEMORY(ctr);
3153 /* For now only return our default site */
3155 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3156 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3157 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3158 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3164 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3165 struct ldb_context *sam_ctx,
3166 struct netr_DomainTrustList *trusts,
3167 uint32_t trust_flags)
3169 struct ldb_dn *system_dn;
3170 struct ldb_message **dom_res = NULL;
3171 const char *trust_attrs[] = { "flatname", "trustPartner",
3172 "securityIdentifier", "trustDirection",
3173 "trustType", "trustAttributes", NULL };
3178 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3179 NETR_TRUST_FLAG_OUTBOUND))) {
3180 return WERR_INVALID_FLAGS;
3183 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3184 ldb_get_default_basedn(sam_ctx),
3185 "(&(objectClass=container)(cn=System))");
3187 return WERR_GEN_FAILURE;
3190 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3191 &dom_res, trust_attrs,
3192 "(objectclass=trustedDomain)");
3194 for (i = 0; i < ret; i++) {
3195 unsigned int trust_dir;
3198 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3199 "trustDirection", 0);
3201 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3202 flags |= NETR_TRUST_FLAG_INBOUND;
3204 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3205 flags |= NETR_TRUST_FLAG_OUTBOUND;
3208 if (!(flags & trust_flags)) {
3209 /* this trust direction was not requested */
3214 trusts->array = talloc_realloc(trusts, trusts->array,
3215 struct netr_DomainTrust,
3217 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3219 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3220 if (!trusts->array[n].netbios_name) {
3221 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3222 "without flatname\n",
3223 ldb_dn_get_linearized(dom_res[i]->dn)));
3226 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3228 trusts->array[n].trust_flags = flags;
3229 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3230 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3231 /* TODO: find if we have parent in the list */
3232 trusts->array[n].parent_index = 0;
3235 trusts->array[n].trust_type =
3236 ldb_msg_find_attr_as_uint(dom_res[i],
3238 trusts->array[n].trust_attributes =
3239 ldb_msg_find_attr_as_uint(dom_res[i],
3240 "trustAttributes", 0);
3242 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3243 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3244 struct dom_sid zero_sid;
3245 ZERO_STRUCT(zero_sid);
3246 trusts->array[n].sid =
3247 dom_sid_dup(trusts, &zero_sid);
3249 trusts->array[n].sid =
3250 samdb_result_dom_sid(trusts, dom_res[i],
3251 "securityIdentifier");
3253 trusts->array[n].guid = GUID_zero();
3255 trusts->count = n + 1;
3258 talloc_free(dom_res);
3263 netr_DsrEnumerateDomainTrusts
3265 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3266 TALLOC_CTX *mem_ctx,
3267 struct netr_DsrEnumerateDomainTrusts *r)
3269 struct netr_DomainTrustList *trusts;
3270 struct ldb_context *sam_ctx;
3272 struct ldb_message **dom_res;
3273 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3274 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3275 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3279 if (r->in.trust_flags & 0xFFFFFE00) {
3280 return WERR_INVALID_FLAGS;
3283 /* TODO: turn to hard check once we are sure this is 100% correct */
3284 if (!r->in.server_name) {
3285 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3286 "But received NULL!\n", dnsdomain));
3288 p = strchr(r->in.server_name, '.');
3290 DEBUG(3, ("Invalid domain! Expected name in domain "
3291 "[%s]. But received [%s]!\n",
3292 dnsdomain, r->in.server_name));
3293 p = r->in.server_name;
3297 if (strcasecmp(p, dnsdomain)) {
3298 DEBUG(3, ("Invalid domain! Expected name in domain "
3299 "[%s]. But received [%s]!\n",
3300 dnsdomain, r->in.server_name));
3304 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3305 W_ERROR_HAVE_NO_MEMORY(trusts);
3308 r->out.trusts = trusts;
3310 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3311 dce_call->conn->auth_state.session_info, 0);
3312 if (sam_ctx == NULL) {
3313 return WERR_GEN_FAILURE;
3316 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3317 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3319 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3320 trusts, r->in.trust_flags);
3321 W_ERROR_NOT_OK_RETURN(werr);
3324 /* NOTE: we currently are always the root of the forest */
3325 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3326 uint32_t n = trusts->count;
3328 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3329 &dom_res, dom_attrs);
3331 return WERR_GEN_FAILURE;
3334 trusts->count = n + 1;
3335 trusts->array = talloc_realloc(trusts, trusts->array,
3336 struct netr_DomainTrust,
3338 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3340 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3341 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3342 trusts->array[n].trust_flags =
3343 NETR_TRUST_FLAG_NATIVE |
3344 NETR_TRUST_FLAG_TREEROOT |
3345 NETR_TRUST_FLAG_IN_FOREST |
3346 NETR_TRUST_FLAG_PRIMARY;
3347 /* we are always the root domain for now */
3348 trusts->array[n].parent_index = 0;
3349 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3350 trusts->array[n].trust_attributes = 0;
3351 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3354 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3356 talloc_free(dom_res);
3364 netr_DsrDeregisterDNSHostRecords
3366 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3367 struct netr_DsrDeregisterDNSHostRecords *r)
3369 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3373 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3374 struct netr_ServerGetTrustInfo *r);
3377 netr_ServerTrustPasswordsGet
3379 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3380 struct netr_ServerTrustPasswordsGet *r)
3382 struct netr_ServerGetTrustInfo r2 = {};
3383 struct netr_TrustInfo *_ti = NULL;
3386 r2.in.server_name = r->in.server_name;
3387 r2.in.account_name = r->in.account_name;
3388 r2.in.secure_channel_type = r->in.secure_channel_type;
3389 r2.in.computer_name = r->in.computer_name;
3390 r2.in.credential = r->in.credential;
3392 r2.out.return_authenticator = r->out.return_authenticator;
3393 r2.out.new_owf_password = r->out.new_owf_password;
3394 r2.out.old_owf_password = r->out.old_owf_password;
3395 r2.out.trust_info = &_ti;
3397 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3399 r->out.return_authenticator = r2.out.return_authenticator;
3400 r->out.new_owf_password = r2.out.new_owf_password;
3401 r->out.old_owf_password = r2.out.old_owf_password;
3407 netr_DsRGetForestTrustInformation
3409 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3410 struct dcesrv_call_state *dce_call;
3411 TALLOC_CTX *mem_ctx;
3412 struct netr_DsRGetForestTrustInformation *r;
3415 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3417 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3418 TALLOC_CTX *mem_ctx,
3419 struct netr_DsRGetForestTrustInformation *r)
3421 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3422 struct dcesrv_connection *conn = dce_call->conn;
3423 struct auth_session_info *session_info = conn->auth_state.session_info;
3424 enum security_user_level security_level;
3425 struct ldb_context *sam_ctx = NULL;
3426 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3427 struct dcerpc_binding_handle *irpc_handle = NULL;
3428 struct tevent_req *subreq = NULL;
3429 struct ldb_dn *domain_dn = NULL;
3430 struct ldb_dn *forest_dn = NULL;
3434 security_level = security_session_user_level(session_info, NULL);
3435 if (security_level < SECURITY_USER) {
3436 return WERR_ACCESS_DENIED;
3439 if (r->in.flags & 0xFFFFFFFE) {
3440 return WERR_INVALID_FLAGS;
3443 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3444 dce_call->conn->auth_state.session_info, 0);
3445 if (sam_ctx == NULL) {
3446 return WERR_GEN_FAILURE;
3449 domain_dn = ldb_get_default_basedn(sam_ctx);
3450 if (domain_dn == NULL) {
3451 return WERR_GEN_FAILURE;
3454 forest_dn = ldb_get_root_basedn(sam_ctx);
3455 if (forest_dn == NULL) {
3456 return WERR_GEN_FAILURE;
3459 cmp = ldb_dn_compare(domain_dn, forest_dn);
3461 return WERR_NERR_ACFNOTLOADED;
3464 forest_level = dsdb_forest_functional_level(sam_ctx);
3465 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3466 return WERR_INVALID_FUNCTION;
3469 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3470 if (!samdb_is_pdc(sam_ctx)) {
3471 return WERR_NERR_NOTPRIMARY;
3474 if (r->in.trusted_domain_name == NULL) {
3475 return WERR_INVALID_FLAGS;
3479 if (r->in.trusted_domain_name == NULL) {
3483 * information about our own domain
3485 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3486 r->out.forest_trust_info);
3487 if (!NT_STATUS_IS_OK(status)) {
3488 return ntstatus_to_werror(status);
3495 * Forward the request to winbindd
3498 state = talloc_zero(mem_ctx,
3499 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3500 if (state == NULL) {
3501 return WERR_NOT_ENOUGH_MEMORY;
3503 state->dce_call = dce_call;
3504 state->mem_ctx = mem_ctx;
3507 irpc_handle = irpc_binding_handle_by_name(state,
3508 state->dce_call->msg_ctx,
3510 &ndr_table_winbind);
3511 if (irpc_handle == NULL) {
3512 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3513 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3514 return WERR_SERVICE_NOT_FOUND;
3518 * 60 seconds timeout should be enough
3520 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3522 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3523 state->dce_call->event_ctx,
3525 r->in.trusted_domain_name,
3527 r->out.forest_trust_info);
3528 if (subreq == NULL) {
3529 return WERR_NOT_ENOUGH_MEMORY;
3531 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3532 tevent_req_set_callback(subreq,
3533 dcesrv_netr_DsRGetForestTrustInformation_done,
3539 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3541 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3542 tevent_req_callback_data(subreq,
3543 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3546 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3548 &state->r->out.result);
3549 TALLOC_FREE(subreq);
3550 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3551 state->r->out.result = WERR_TIMEOUT;
3552 } else if (!NT_STATUS_IS_OK(status)) {
3553 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3554 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3555 nt_errstr(status)));
3558 status = dcesrv_reply(state->dce_call);
3559 if (!NT_STATUS_IS_OK(status)) {
3560 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3565 netr_GetForestTrustInformation
3567 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3568 TALLOC_CTX *mem_ctx,
3569 struct netr_GetForestTrustInformation *r)
3571 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3572 struct netlogon_creds_CredentialState *creds = NULL;
3573 struct ldb_context *sam_ctx = NULL;
3574 struct ldb_dn *domain_dn = NULL;
3575 struct ldb_dn *forest_dn = NULL;
3580 status = dcesrv_netr_creds_server_step_check(dce_call,
3582 r->in.computer_name,
3584 r->out.return_authenticator,
3586 if (!NT_STATUS_IS_OK(status)) {
3590 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3591 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3592 return NT_STATUS_NOT_IMPLEMENTED;
3595 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3596 dce_call->conn->auth_state.session_info, 0);
3597 if (sam_ctx == NULL) {
3598 return NT_STATUS_INTERNAL_ERROR;
3601 /* TODO: check r->in.server_name is our name */
3603 domain_dn = ldb_get_default_basedn(sam_ctx);
3604 if (domain_dn == NULL) {
3605 return NT_STATUS_INTERNAL_ERROR;
3608 forest_dn = ldb_get_root_basedn(sam_ctx);
3609 if (forest_dn == NULL) {
3610 return NT_STATUS_INTERNAL_ERROR;
3613 cmp = ldb_dn_compare(domain_dn, forest_dn);
3615 return NT_STATUS_INVALID_DOMAIN_STATE;
3618 forest_level = dsdb_forest_functional_level(sam_ctx);
3619 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3620 return NT_STATUS_INVALID_DOMAIN_STATE;
3623 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3624 r->out.forest_trust_info);
3625 if (!NT_STATUS_IS_OK(status)) {
3629 return NT_STATUS_OK;
3634 netr_ServerGetTrustInfo
3636 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3637 struct netr_ServerGetTrustInfo *r)
3639 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3640 struct netlogon_creds_CredentialState *creds = NULL;
3641 struct ldb_context *sam_ctx = NULL;
3642 const char * const attrs[] = {
3645 "userAccountControl",
3648 struct ldb_message **res = NULL;
3649 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3652 const char *asid = NULL;
3654 const char *aname = NULL;
3655 struct ldb_message *tdo_msg = NULL;
3656 const char * const tdo_attrs[] = {
3657 "trustAuthIncoming",
3661 struct netr_TrustInfo *trust_info = NULL;
3663 ZERO_STRUCTP(r->out.new_owf_password);
3664 ZERO_STRUCTP(r->out.old_owf_password);
3666 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3668 r->in.computer_name,
3670 r->out.return_authenticator,
3672 if (!NT_STATUS_IS_OK(nt_status)) {
3676 /* TODO: check r->in.server_name is our name */
3678 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3679 return NT_STATUS_INVALID_PARAMETER;
3682 if (r->in.secure_channel_type != creds->secure_channel_type) {
3683 return NT_STATUS_INVALID_PARAMETER;
3686 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3687 return NT_STATUS_INVALID_PARAMETER;
3690 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3691 lp_ctx, system_session(lp_ctx), 0);
3692 if (sam_ctx == NULL) {
3693 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3696 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3698 return NT_STATUS_NO_MEMORY;
3701 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3702 "(&(objectClass=user)(objectSid=%s))",
3705 return NT_STATUS_ACCOUNT_DISABLED;
3708 switch (creds->secure_channel_type) {
3709 case SEC_CHAN_DNS_DOMAIN:
3710 case SEC_CHAN_DOMAIN:
3711 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3713 if (uac & UF_ACCOUNTDISABLE) {
3714 return NT_STATUS_ACCOUNT_DISABLED;
3717 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3718 return NT_STATUS_ACCOUNT_DISABLED;
3721 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3722 if (aname == NULL) {
3723 return NT_STATUS_ACCOUNT_DISABLED;
3726 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3727 SEC_CHAN_DOMAIN, aname,
3728 tdo_attrs, mem_ctx, &tdo_msg);
3729 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3730 return NT_STATUS_ACCOUNT_DISABLED;
3732 if (!NT_STATUS_IS_OK(nt_status)) {
3736 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3739 if (!NT_STATUS_IS_OK(nt_status)) {
3743 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3744 if (trust_info == NULL) {
3745 return NT_STATUS_NO_MEMORY;
3748 trust_info->count = 1;
3749 trust_info->data = talloc_array(trust_info, uint32_t,
3751 if (trust_info->data == NULL) {
3752 return NT_STATUS_NO_MEMORY;
3755 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3761 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3764 if (!NT_STATUS_IS_OK(nt_status)) {
3768 prevNtHash = talloc(mem_ctx, struct samr_Password);
3769 if (prevNtHash == NULL) {
3770 return NT_STATUS_NO_MEMORY;
3773 E_md4hash("", prevNtHash->hash);
3777 if (curNtHash != NULL) {
3778 *r->out.new_owf_password = *curNtHash;
3779 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3781 if (prevNtHash != NULL) {
3782 *r->out.old_owf_password = *prevNtHash;
3783 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3786 if (trust_info != NULL) {
3787 *r->out.trust_info = trust_info;
3790 return NT_STATUS_OK;
3796 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3797 struct netr_Unused47 *r)
3799 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3803 struct netr_dnsupdate_RODC_state {
3804 struct dcesrv_call_state *dce_call;
3805 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3806 struct dnsupdate_RODC *r2;
3810 called when the forwarded RODC dns update request is finished
3812 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3814 struct netr_dnsupdate_RODC_state *st =
3815 tevent_req_callback_data(subreq,
3816 struct netr_dnsupdate_RODC_state);
3819 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3820 TALLOC_FREE(subreq);
3821 if (!NT_STATUS_IS_OK(status)) {
3822 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3823 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3826 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3828 status = dcesrv_reply(st->dce_call);
3829 if (!NT_STATUS_IS_OK(status)) {
3830 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3835 netr_DsrUpdateReadOnlyServerDnsRecords
3837 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3838 TALLOC_CTX *mem_ctx,
3839 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3841 struct netlogon_creds_CredentialState *creds;
3843 struct dcerpc_binding_handle *binding_handle;
3844 struct netr_dnsupdate_RODC_state *st;
3845 struct tevent_req *subreq;
3847 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3849 r->in.computer_name,
3851 r->out.return_authenticator,
3853 NT_STATUS_NOT_OK_RETURN(nt_status);
3855 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3856 return NT_STATUS_ACCESS_DENIED;
3859 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3860 NT_STATUS_HAVE_NO_MEMORY(st);
3862 st->dce_call = dce_call;
3864 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3865 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3867 st->r2->in.dom_sid = creds->sid;
3868 st->r2->in.site_name = r->in.site_name;
3869 st->r2->in.dns_ttl = r->in.dns_ttl;
3870 st->r2->in.dns_names = r->in.dns_names;
3871 st->r2->out.dns_names = r->out.dns_names;
3873 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3874 "dnsupdate", &ndr_table_irpc);
3875 if (binding_handle == NULL) {
3876 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3877 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3878 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3881 /* forward the call */
3882 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3883 binding_handle, st->r2);
3884 NT_STATUS_HAVE_NO_MEMORY(subreq);
3886 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3888 /* setup the callback */
3889 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3891 return NT_STATUS_OK;
3895 /* include the generated boilerplate */
3896 #include "librpc/gen_ndr/ndr_netlogon_s.c"