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;
942 netr_LogonSamLogon_base
944 This version of the function allows other wrappers to say 'do not check the credentials'
946 We can't do the traditional 'wrapping' format completely, as this
947 function must only run under schannel
949 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
951 struct dcesrv_call_state *dce_call = state->dce_call;
952 TALLOC_CTX *mem_ctx = state->mem_ctx;
953 struct netr_LogonSamLogonEx *r = &state->r;
954 struct netlogon_creds_CredentialState *creds = state->creds;
955 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
956 const char *workgroup = lpcfg_workgroup(lp_ctx);
957 struct auth4_context *auth_context = NULL;
958 struct auth_usersupplied_info *user_info = NULL;
959 struct auth_user_info_dc *user_info_dc = NULL;
961 struct netr_SamInfo2 *sam2 = NULL;
962 struct netr_SamInfo3 *sam3 = NULL;
963 struct netr_SamInfo6 *sam6 = NULL;
965 *r->out.authoritative = 1;
967 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
969 * Currently we're always the forest root ourself.
971 return NT_STATUS_NO_SUCH_USER;
974 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
976 * Currently we don't support trusts correctly yet.
978 return NT_STATUS_NO_SUCH_USER;
981 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
982 NT_STATUS_HAVE_NO_MEMORY(user_info);
984 user_info->service_description = "SamLogon";
986 netlogon_creds_decrypt_samlogon_logon(creds,
990 switch (r->in.logon_level) {
991 case NetlogonInteractiveInformation:
992 case NetlogonServiceInformation:
993 case NetlogonInteractiveTransitiveInformation:
994 case NetlogonServiceTransitiveInformation:
995 case NetlogonNetworkInformation:
996 case NetlogonNetworkTransitiveInformation:
998 nt_status = auth_context_create_for_netlogon(mem_ctx,
999 dce_call->event_ctx, dce_call->msg_ctx,
1000 dce_call->conn->dce_ctx->lp_ctx,
1002 NT_STATUS_NOT_OK_RETURN(nt_status);
1004 user_info->remote_host = dce_call->conn->remote_address;
1005 user_info->local_host = dce_call->conn->local_address;
1007 user_info->netlogon_trust_account.secure_channel_type
1008 = creds->secure_channel_type;
1009 user_info->netlogon_trust_account.negotiate_flags
1010 = creds->negotiate_flags;
1013 * These two can be unrelated when the account is
1014 * actually that of a trusted domain, so we want to
1015 * know which DC in that trusted domain contacted
1018 user_info->netlogon_trust_account.computer_name
1019 = creds->computer_name;
1020 user_info->netlogon_trust_account.account_name
1021 = creds->account_name;
1022 user_info->netlogon_trust_account.sid
1026 /* We do not need to set up the user_info in this case */
1030 switch (r->in.logon_level) {
1031 case NetlogonInteractiveInformation:
1032 case NetlogonServiceInformation:
1033 case NetlogonInteractiveTransitiveInformation:
1034 case NetlogonServiceTransitiveInformation:
1035 user_info->auth_description = "interactive";
1037 user_info->logon_parameters
1038 = r->in.logon->password->identity_info.parameter_control;
1039 user_info->client.account_name
1040 = r->in.logon->password->identity_info.account_name.string;
1041 user_info->client.domain_name
1042 = r->in.logon->password->identity_info.domain_name.string;
1043 user_info->workstation_name
1044 = r->in.logon->password->identity_info.workstation.string;
1045 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1046 user_info->password_state = AUTH_PASSWORD_HASH;
1048 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1049 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1050 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1052 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1053 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1054 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1057 case NetlogonNetworkInformation:
1058 case NetlogonNetworkTransitiveInformation:
1059 user_info->auth_description = "network";
1061 nt_status = auth_context_set_challenge(
1063 r->in.logon->network->challenge,
1064 "netr_LogonSamLogonWithFlags");
1065 NT_STATUS_NOT_OK_RETURN(nt_status);
1067 user_info->logon_parameters
1068 = r->in.logon->network->identity_info.parameter_control;
1069 user_info->client.account_name
1070 = r->in.logon->network->identity_info.account_name.string;
1071 user_info->client.domain_name
1072 = r->in.logon->network->identity_info.domain_name.string;
1073 user_info->workstation_name
1074 = r->in.logon->network->identity_info.workstation.string;
1076 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1077 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1078 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1080 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1081 user_info->client.account_name,
1082 user_info->client.domain_name,
1083 user_info->password.response.nt,
1085 NT_STATUS_NOT_OK_RETURN(nt_status);
1090 case NetlogonGenericInformation:
1092 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1094 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1097 /* Using DES to verify kerberos tickets makes no sense */
1098 return NT_STATUS_INVALID_PARAMETER;
1101 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1103 struct dcerpc_binding_handle *irpc_handle;
1104 struct kdc_check_generic_kerberos check;
1105 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1106 NT_STATUS_HAVE_NO_MEMORY(generic);
1107 *r->out.authoritative = 1;
1109 /* TODO: Describe and deal with these flags */
1112 r->out.validation->generic = generic;
1114 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1118 if (irpc_handle == NULL) {
1119 return NT_STATUS_NO_LOGON_SERVERS;
1122 check.in.generic_request =
1123 data_blob_const(r->in.logon->generic->data,
1124 r->in.logon->generic->length);
1127 * TODO: make this async and avoid
1128 * dcerpc_binding_handle_set_sync_ev()
1130 dcerpc_binding_handle_set_sync_ev(irpc_handle,
1131 dce_call->event_ctx);
1132 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
1135 if (!NT_STATUS_IS_OK(status)) {
1138 generic->length = check.out.generic_reply.length;
1139 generic->data = check.out.generic_reply.data;
1140 return NT_STATUS_OK;
1143 /* Until we get an implemetnation of these other packages */
1144 return NT_STATUS_INVALID_PARAMETER;
1147 return NT_STATUS_INVALID_PARAMETER;
1150 nt_status = auth_check_password(auth_context, mem_ctx, user_info,
1151 &user_info_dc, r->out.authoritative);
1152 NT_STATUS_NOT_OK_RETURN(nt_status);
1154 switch (r->in.validation_level) {
1156 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1159 NT_STATUS_NOT_OK_RETURN(nt_status);
1161 r->out.validation->sam2 = sam2;
1165 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1168 NT_STATUS_NOT_OK_RETURN(nt_status);
1170 r->out.validation->sam3 = sam3;
1174 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1177 NT_STATUS_NOT_OK_RETURN(nt_status);
1179 r->out.validation->sam6 = sam6;
1183 return NT_STATUS_INVALID_INFO_CLASS;
1186 netlogon_creds_encrypt_samlogon_validation(creds,
1187 r->in.validation_level,
1190 /* TODO: Describe and deal with these flags */
1193 return NT_STATUS_OK;
1196 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1197 struct netr_LogonSamLogonEx *r)
1199 struct dcesrv_netr_LogonSamLogon_base_state *state;
1202 *r->out.authoritative = 1;
1204 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1205 if (state == NULL) {
1206 return NT_STATUS_NO_MEMORY;
1209 state->dce_call = dce_call;
1210 state->mem_ctx = mem_ctx;
1212 state->r.in.server_name = r->in.server_name;
1213 state->r.in.computer_name = r->in.computer_name;
1214 state->r.in.logon_level = r->in.logon_level;
1215 state->r.in.logon = r->in.logon;
1216 state->r.in.validation_level = r->in.validation_level;
1217 state->r.in.flags = r->in.flags;
1218 state->r.out.validation = r->out.validation;
1219 state->r.out.authoritative = r->out.authoritative;
1220 state->r.out.flags = r->out.flags;
1222 state->_r.lslex = r;
1224 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1225 if (!NT_STATUS_IS_OK(nt_status)) {
1229 nt_status = schannel_get_creds_state(mem_ctx,
1230 dce_call->conn->dce_ctx->lp_ctx,
1231 r->in.computer_name, &state->creds);
1232 if (!NT_STATUS_IS_OK(nt_status)) {
1236 if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1237 return NT_STATUS_ACCESS_DENIED;
1240 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1242 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1250 netr_LogonSamLogonWithFlags
1253 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1254 struct netr_LogonSamLogonWithFlags *r)
1256 struct dcesrv_netr_LogonSamLogon_base_state *state;
1259 *r->out.authoritative = 1;
1261 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1262 if (state == NULL) {
1263 return NT_STATUS_NO_MEMORY;
1266 state->dce_call = dce_call;
1267 state->mem_ctx = mem_ctx;
1269 state->r.in.server_name = r->in.server_name;
1270 state->r.in.computer_name = r->in.computer_name;
1271 state->r.in.logon_level = r->in.logon_level;
1272 state->r.in.logon = r->in.logon;
1273 state->r.in.validation_level = r->in.validation_level;
1274 state->r.in.flags = r->in.flags;
1275 state->r.out.validation = r->out.validation;
1276 state->r.out.authoritative = r->out.authoritative;
1277 state->r.out.flags = r->out.flags;
1279 state->_r.lslwf = r;
1281 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1282 if (!NT_STATUS_IS_OK(nt_status)) {
1286 r->out.return_authenticator = talloc_zero(mem_ctx,
1287 struct netr_Authenticator);
1288 if (r->out.return_authenticator == NULL) {
1289 return NT_STATUS_NO_MEMORY;
1292 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1294 r->in.computer_name,
1296 r->out.return_authenticator,
1298 if (!NT_STATUS_IS_OK(nt_status)) {
1302 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1304 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1314 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1315 struct netr_LogonSamLogon *r)
1317 struct dcesrv_netr_LogonSamLogon_base_state *state;
1320 *r->out.authoritative = 1;
1322 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1323 if (state == NULL) {
1324 return NT_STATUS_NO_MEMORY;
1327 state->dce_call = dce_call;
1328 state->mem_ctx = mem_ctx;
1330 state->r.in.server_name = r->in.server_name;
1331 state->r.in.computer_name = r->in.computer_name;
1332 state->r.in.logon_level = r->in.logon_level;
1333 state->r.in.logon = r->in.logon;
1334 state->r.in.validation_level = r->in.validation_level;
1335 state->r.in.flags = &state->_ignored_flags;
1336 state->r.out.validation = r->out.validation;
1337 state->r.out.authoritative = r->out.authoritative;
1338 state->r.out.flags = &state->_ignored_flags;
1342 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1343 if (!NT_STATUS_IS_OK(nt_status)) {
1347 r->out.return_authenticator = talloc_zero(mem_ctx,
1348 struct netr_Authenticator);
1349 if (r->out.return_authenticator == NULL) {
1350 return NT_STATUS_NO_MEMORY;
1353 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1355 r->in.computer_name,
1357 r->out.return_authenticator,
1359 if (!NT_STATUS_IS_OK(nt_status)) {
1363 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1365 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1376 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1377 struct netr_LogonSamLogoff *r)
1379 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1387 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1388 struct netr_DatabaseDeltas *r)
1390 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1397 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1398 struct netr_DatabaseSync2 *r)
1400 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1401 return NT_STATUS_NOT_IMPLEMENTED;
1408 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1409 struct netr_DatabaseSync *r)
1411 struct netr_DatabaseSync2 r2;
1416 r2.in.logon_server = r->in.logon_server;
1417 r2.in.computername = r->in.computername;
1418 r2.in.credential = r->in.credential;
1419 r2.in.database_id = r->in.database_id;
1420 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1421 r2.in.sync_context = r->in.sync_context;
1422 r2.out.sync_context = r->out.sync_context;
1423 r2.out.delta_enum_array = r->out.delta_enum_array;
1424 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1426 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1435 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1436 struct netr_AccountDeltas *r)
1438 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1439 return NT_STATUS_NOT_IMPLEMENTED;
1446 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1447 struct netr_AccountSync *r)
1449 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1450 return NT_STATUS_NOT_IMPLEMENTED;
1457 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1458 struct netr_GetDcName *r)
1460 const char * const attrs[] = { NULL };
1461 struct ldb_context *sam_ctx;
1462 struct ldb_message **res;
1463 struct ldb_dn *domain_dn;
1468 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1469 * that the domainname needs to be a valid netbios domain
1470 * name, if it is not NULL.
1472 if (r->in.domainname) {
1473 const char *dot = strchr(r->in.domainname, '.');
1474 size_t len = strlen(r->in.domainname);
1476 if (dot || len > 15) {
1477 return WERR_NERR_DCNOTFOUND;
1481 * TODO: Should we also varify that only valid
1482 * netbios name characters are used?
1486 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1487 dce_call->conn->dce_ctx->lp_ctx,
1488 dce_call->conn->auth_state.session_info, 0);
1489 if (sam_ctx == NULL) {
1490 return WERR_DS_UNAVAILABLE;
1493 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1495 if (domain_dn == NULL) {
1496 return WERR_NO_SUCH_DOMAIN;
1499 ret = gendb_search_dn(sam_ctx, mem_ctx,
1500 domain_dn, &res, attrs);
1502 return WERR_NO_SUCH_DOMAIN;
1505 /* TODO: - return real IP address
1506 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1508 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1509 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1510 W_ERROR_HAVE_NO_MEMORY(dcname);
1512 *r->out.dcname = dcname;
1516 struct dcesrv_netr_LogonControl_base_state {
1517 struct dcesrv_call_state *dce_call;
1519 TALLOC_CTX *mem_ctx;
1521 struct netr_LogonControl2Ex r;
1524 struct netr_LogonControl *l;
1525 struct netr_LogonControl2 *l2;
1526 struct netr_LogonControl2Ex *l2ex;
1530 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1532 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1534 struct dcesrv_connection *conn = state->dce_call->conn;
1535 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1536 struct auth_session_info *session_info = conn->auth_state.session_info;
1537 enum security_user_level security_level;
1538 struct dcerpc_binding_handle *irpc_handle;
1539 struct tevent_req *subreq;
1542 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1544 if (state->_r.l != NULL) {
1548 if (state->r.in.level == 0x00000002) {
1549 return WERR_NOT_SUPPORTED;
1550 } else if (state->r.in.level != 0x00000001) {
1551 return WERR_INVALID_LEVEL;
1554 switch (state->r.in.function_code) {
1555 case NETLOGON_CONTROL_QUERY:
1556 case NETLOGON_CONTROL_REPLICATE:
1557 case NETLOGON_CONTROL_SYNCHRONIZE:
1558 case NETLOGON_CONTROL_PDC_REPLICATE:
1559 case NETLOGON_CONTROL_BREAKPOINT:
1560 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1561 case NETLOGON_CONTROL_TRUNCATE_LOG:
1564 return WERR_NOT_SUPPORTED;
1568 if (state->r.in.level < 0x00000001) {
1569 return WERR_INVALID_LEVEL;
1572 if (state->r.in.level > 0x00000004) {
1573 return WERR_INVALID_LEVEL;
1576 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1577 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1578 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1580 switch (state->r.in.level) {
1582 info1 = talloc_zero(state->mem_ctx,
1583 struct netr_NETLOGON_INFO_1);
1584 if (info1 == NULL) {
1585 return WERR_NOT_ENOUGH_MEMORY;
1587 state->r.out.query->info1 = info1;
1591 info3 = talloc_zero(state->mem_ctx,
1592 struct netr_NETLOGON_INFO_3);
1593 if (info3 == NULL) {
1594 return WERR_NOT_ENOUGH_MEMORY;
1596 state->r.out.query->info3 = info3;
1600 return WERR_INVALID_PARAMETER;
1605 * Some validations are done before the access check
1606 * and some after the access check
1608 security_level = security_session_user_level(session_info, NULL);
1609 if (security_level < SECURITY_ADMINISTRATOR) {
1610 return WERR_ACCESS_DENIED;
1613 if (state->_r.l2 != NULL) {
1615 * netr_LogonControl2
1617 if (state->r.in.level == 0x00000004) {
1618 return WERR_INVALID_LEVEL;
1622 switch (state->r.in.level) {
1627 switch (state->r.in.function_code) {
1628 case NETLOGON_CONTROL_REDISCOVER:
1629 case NETLOGON_CONTROL_TC_QUERY:
1630 case NETLOGON_CONTROL_TC_VERIFY:
1633 return WERR_INVALID_PARAMETER;
1642 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1643 return WERR_INVALID_PARAMETER;
1649 return WERR_INVALID_LEVEL;
1652 switch (state->r.in.function_code) {
1653 case NETLOGON_CONTROL_REDISCOVER:
1654 case NETLOGON_CONTROL_TC_QUERY:
1655 case NETLOGON_CONTROL_TC_VERIFY:
1656 if (state->r.in.level != 2) {
1657 return WERR_INVALID_PARAMETER;
1660 if (state->r.in.data == NULL) {
1661 return WERR_INVALID_PARAMETER;
1664 if (state->r.in.data->domain == NULL) {
1665 return WERR_INVALID_PARAMETER;
1670 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1671 if (state->r.in.level != 1) {
1672 return WERR_INVALID_PARAMETER;
1675 if (state->r.in.data == NULL) {
1676 return WERR_INVALID_PARAMETER;
1679 if (state->r.in.data->domain == NULL) {
1680 return WERR_INVALID_PARAMETER;
1683 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1684 state->r.in.data->domain);
1686 struct ldb_context *sam_ctx;
1688 sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1689 lp_ctx, system_session(lp_ctx), 0);
1690 if (sam_ctx == NULL) {
1691 return WERR_DS_UNAVAILABLE;
1695 * Secrets for trusted domains can only be triggered on
1698 ok = samdb_is_pdc(sam_ctx);
1699 TALLOC_FREE(sam_ctx);
1701 return WERR_INVALID_DOMAIN_ROLE;
1707 return WERR_NOT_SUPPORTED;
1710 irpc_handle = irpc_binding_handle_by_name(state,
1711 state->dce_call->msg_ctx,
1713 &ndr_table_winbind);
1714 if (irpc_handle == NULL) {
1715 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1716 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1717 return WERR_SERVICE_NOT_FOUND;
1721 * 60 seconds timeout should be enough
1723 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1725 subreq = dcerpc_winbind_LogonControl_send(state,
1726 state->dce_call->event_ctx,
1728 state->r.in.function_code,
1731 state->r.out.query);
1732 if (subreq == NULL) {
1733 return WERR_NOT_ENOUGH_MEMORY;
1735 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1736 tevent_req_set_callback(subreq,
1737 dcesrv_netr_LogonControl_base_done,
1743 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1745 struct dcesrv_netr_LogonControl_base_state *state =
1746 tevent_req_callback_data(subreq,
1747 struct dcesrv_netr_LogonControl_base_state);
1750 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1751 &state->r.out.result);
1752 TALLOC_FREE(subreq);
1753 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1754 state->r.out.result = WERR_TIMEOUT;
1755 } else if (!NT_STATUS_IS_OK(status)) {
1756 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1757 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1758 nt_errstr(status)));
1761 if (state->_r.l2ex != NULL) {
1762 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1763 r->out.result = state->r.out.result;
1764 } else if (state->_r.l2 != NULL) {
1765 struct netr_LogonControl2 *r = state->_r.l2;
1766 r->out.result = state->r.out.result;
1767 } else if (state->_r.l != NULL) {
1768 struct netr_LogonControl *r = state->_r.l;
1769 r->out.result = state->r.out.result;
1772 status = dcesrv_reply(state->dce_call);
1773 if (!NT_STATUS_IS_OK(status)) {
1774 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1781 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1782 struct netr_LogonControl *r)
1784 struct dcesrv_netr_LogonControl_base_state *state;
1787 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1788 if (state == NULL) {
1789 return WERR_NOT_ENOUGH_MEMORY;
1792 state->dce_call = dce_call;
1793 state->mem_ctx = mem_ctx;
1795 state->r.in.logon_server = r->in.logon_server;
1796 state->r.in.function_code = r->in.function_code;
1797 state->r.in.level = r->in.level;
1798 state->r.in.data = NULL;
1799 state->r.out.query = r->out.query;
1803 werr = dcesrv_netr_LogonControl_base_call(state);
1805 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1815 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1816 struct netr_LogonControl2 *r)
1818 struct dcesrv_netr_LogonControl_base_state *state;
1821 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1822 if (state == NULL) {
1823 return WERR_NOT_ENOUGH_MEMORY;
1826 state->dce_call = dce_call;
1827 state->mem_ctx = mem_ctx;
1829 state->r.in.logon_server = r->in.logon_server;
1830 state->r.in.function_code = r->in.function_code;
1831 state->r.in.level = r->in.level;
1832 state->r.in.data = r->in.data;
1833 state->r.out.query = r->out.query;
1837 werr = dcesrv_netr_LogonControl_base_call(state);
1839 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1847 netr_LogonControl2Ex
1849 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1850 struct netr_LogonControl2Ex *r)
1852 struct dcesrv_netr_LogonControl_base_state *state;
1855 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1856 if (state == NULL) {
1857 return WERR_NOT_ENOUGH_MEMORY;
1860 state->dce_call = dce_call;
1861 state->mem_ctx = mem_ctx;
1866 werr = dcesrv_netr_LogonControl_base_call(state);
1868 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1875 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1876 struct ldb_context *sam_ctx,
1877 struct netr_DomainTrustList *trusts,
1878 uint32_t trust_flags);
1883 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1884 struct netr_GetAnyDCName *r)
1886 struct netr_DomainTrustList *trusts;
1887 struct ldb_context *sam_ctx;
1888 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1892 *r->out.dcname = NULL;
1894 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1895 /* if the domainname parameter wasn't set assume our domain */
1896 r->in.domainname = lpcfg_workgroup(lp_ctx);
1899 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1900 dce_call->conn->auth_state.session_info, 0);
1901 if (sam_ctx == NULL) {
1902 return WERR_DS_UNAVAILABLE;
1905 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1906 /* well we asked for a DC of our own domain */
1907 if (samdb_is_pdc(sam_ctx)) {
1908 /* we are the PDC of the specified domain */
1909 return WERR_NO_SUCH_DOMAIN;
1912 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1913 lpcfg_netbios_name(lp_ctx));
1914 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1919 /* Okay, now we have to consider the trusted domains */
1921 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1922 W_ERROR_HAVE_NO_MEMORY(trusts);
1926 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1927 NETR_TRUST_FLAG_INBOUND
1928 | NETR_TRUST_FLAG_OUTBOUND);
1929 W_ERROR_NOT_OK_RETURN(werr);
1931 for (i = 0; i < trusts->count; i++) {
1932 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1933 /* FIXME: Here we need to find a DC for the specified
1934 * trusted domain. */
1936 /* return WERR_OK; */
1937 return WERR_NO_SUCH_DOMAIN;
1941 return WERR_NO_SUCH_DOMAIN;
1948 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1949 struct netr_DatabaseRedo *r)
1951 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1956 netr_NetrEnumerateTrustedDomains
1958 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1959 struct netr_NetrEnumerateTrustedDomains *r)
1961 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1966 netr_LogonGetCapabilities
1968 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1969 struct netr_LogonGetCapabilities *r)
1971 struct netlogon_creds_CredentialState *creds;
1974 status = dcesrv_netr_creds_server_step_check(dce_call,
1976 r->in.computer_name,
1978 r->out.return_authenticator,
1980 if (!NT_STATUS_IS_OK(status)) {
1981 DEBUG(0,(__location__ " Bad credentials - error\n"));
1983 NT_STATUS_NOT_OK_RETURN(status);
1985 if (r->in.query_level != 1) {
1986 return NT_STATUS_NOT_SUPPORTED;
1989 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1991 return NT_STATUS_OK;
1996 netr_NETRLOGONSETSERVICEBITS
1998 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1999 struct netr_NETRLOGONSETSERVICEBITS *r)
2001 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2006 netr_LogonGetTrustRid
2008 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2009 struct netr_LogonGetTrustRid *r)
2011 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2016 netr_NETRLOGONCOMPUTESERVERDIGEST
2018 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2019 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2021 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2026 netr_NETRLOGONCOMPUTECLIENTDIGEST
2028 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2029 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2031 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2039 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2040 struct netr_DsRGetSiteName *r)
2042 struct ldb_context *sam_ctx;
2043 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2045 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2046 dce_call->conn->auth_state.session_info, 0);
2047 if (sam_ctx == NULL) {
2048 return WERR_DS_UNAVAILABLE;
2052 * We assume to be a DC when we get called over NETLOGON. Hence we
2053 * get our site name always by using "samdb_server_site_name()"
2054 * and not "samdb_client_site_name()".
2056 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2057 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2064 fill in a netr_OneDomainInfo from a ldb search result
2066 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
2067 struct loadparm_context *lp_ctx,
2068 struct ldb_context *sam_ctx,
2069 struct ldb_message *res,
2070 struct netr_OneDomainInfo *info,
2071 bool is_local, bool is_trust_list)
2075 if (is_trust_list) {
2076 /* w2k8 only fills this on trusted domains */
2077 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
2078 info->trust_extension.length = 16;
2079 info->trust_extension.info->flags =
2080 NETR_TRUST_FLAG_TREEROOT |
2081 NETR_TRUST_FLAG_IN_FOREST |
2082 NETR_TRUST_FLAG_PRIMARY |
2083 NETR_TRUST_FLAG_NATIVE;
2085 info->trust_extension.info->parent_index = 0; /* should be index into array
2087 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
2088 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
2091 if (is_trust_list) {
2092 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2093 info->dns_forestname.string = NULL;
2095 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
2096 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
2097 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
2098 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
2102 info->domainname.string = lpcfg_workgroup(lp_ctx);
2103 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
2104 info->domain_guid = samdb_result_guid(res, "objectGUID");
2105 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
2107 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
2108 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
2109 info->domain_guid = samdb_result_guid(res, "objectGUID");
2110 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
2112 if (!is_trust_list) {
2113 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
2116 return NT_STATUS_OK;
2120 netr_LogonGetDomainInfo
2121 this is called as part of the ADS domain logon procedure.
2123 It has an important role in convaying details about the client, such
2124 as Operating System, Version, Service Pack etc.
2126 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2127 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2129 struct netlogon_creds_CredentialState *creds;
2130 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
2131 "securityIdentifier", "trustPartner", NULL };
2132 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2133 "msDS-SupportedEncryptionTypes", NULL };
2134 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
2135 struct ldb_context *sam_ctx;
2136 struct ldb_message **res1, **res2, **res3, *new_msg;
2137 struct ldb_dn *workstation_dn;
2138 struct netr_DomainInformation *domain_info;
2139 struct netr_LsaPolicyInformation *lsa_policy_info;
2140 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2141 bool update_dns_hostname = true;
2145 status = dcesrv_netr_creds_server_step_check(dce_call,
2147 r->in.computer_name,
2149 r->out.return_authenticator,
2151 if (!NT_STATUS_IS_OK(status)) {
2153 char* remote = NULL;
2154 TALLOC_CTX *frame = talloc_stackframe();
2155 remote = tsocket_address_string(dce_call->conn->remote_address,
2157 local = tsocket_address_string(dce_call->conn->local_address,
2159 DBG_ERR(("Bad credentials - "
2160 "computer[%s] remote[%s] local[%s]\n"),
2161 log_escape(frame, r->in.computer_name),
2166 NT_STATUS_NOT_OK_RETURN(status);
2168 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
2169 dce_call->conn->dce_ctx->lp_ctx,
2170 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
2171 if (sam_ctx == NULL) {
2172 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2175 switch (r->in.level) {
2176 case 1: /* Domain information */
2178 if (r->in.query->workstation_info == NULL) {
2179 return NT_STATUS_INVALID_PARAMETER;
2182 /* Prepares the workstation DN */
2183 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2184 dom_sid_string(mem_ctx, creds->sid));
2185 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2187 /* Lookup for attributes in workstation object */
2188 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2191 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2194 /* Gets the sam account name which is checked against the DNS
2195 * hostname parameter. */
2196 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2199 if (sam_account_name == NULL) {
2200 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2204 * Checks that the sam account name without a possible "$"
2205 * matches as prefix with the DNS hostname in the workstation
2208 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2209 strcspn(sam_account_name, "$"));
2210 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2211 if (r->in.query->workstation_info->dns_hostname != NULL) {
2212 prefix2 = talloc_strndup(mem_ctx,
2213 r->in.query->workstation_info->dns_hostname,
2214 strcspn(r->in.query->workstation_info->dns_hostname, "."));
2215 NT_STATUS_HAVE_NO_MEMORY(prefix2);
2217 if (strcasecmp(prefix1, prefix2) != 0) {
2218 update_dns_hostname = false;
2221 update_dns_hostname = false;
2224 /* Gets the old DNS hostname */
2225 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2230 * Updates the DNS hostname when the client wishes that the
2231 * server should handle this for him
2232 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2233 * obviously only checked when we do already have a
2235 * See MS-NRPC section 3.5.4.3.9
2237 if ((old_dns_hostname != NULL) &&
2238 (r->in.query->workstation_info->workstation_flags
2239 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2240 update_dns_hostname = false;
2243 /* Gets host information and put them into our directory */
2245 new_msg = ldb_msg_new(mem_ctx);
2246 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2248 new_msg->dn = workstation_dn;
2250 /* Sets the OS name */
2252 if (r->in.query->workstation_info->os_name.string == NULL) {
2253 return NT_STATUS_INVALID_PARAMETER;
2256 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2257 r->in.query->workstation_info->os_name.string);
2258 if (ret != LDB_SUCCESS) {
2259 return NT_STATUS_NO_MEMORY;
2263 * Sets information from "os_version". On an empty structure
2264 * the values are cleared.
2266 if (r->in.query->workstation_info->os_version.os != NULL) {
2267 struct netr_OsVersionInfoEx *os_version;
2268 const char *os_version_str;
2270 os_version = &r->in.query->workstation_info->os_version.os->os;
2272 if (os_version->CSDVersion == NULL) {
2273 return NT_STATUS_INVALID_PARAMETER;
2276 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2277 os_version->MajorVersion,
2278 os_version->MinorVersion,
2279 os_version->BuildNumber);
2280 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2282 ret = ldb_msg_add_string(new_msg,
2283 "operatingSystemServicePack",
2284 os_version->CSDVersion);
2285 if (ret != LDB_SUCCESS) {
2286 return NT_STATUS_NO_MEMORY;
2289 ret = ldb_msg_add_string(new_msg,
2290 "operatingSystemVersion",
2292 if (ret != LDB_SUCCESS) {
2293 return NT_STATUS_NO_MEMORY;
2296 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2297 "operatingSystemServicePack");
2298 if (ret != LDB_SUCCESS) {
2299 return NT_STATUS_NO_MEMORY;
2302 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2303 "operatingSystemVersion");
2304 if (ret != LDB_SUCCESS) {
2305 return NT_STATUS_NO_MEMORY;
2310 * If the boolean "update_dns_hostname" remained true, then we
2311 * are fine to start the update.
2313 if (update_dns_hostname) {
2314 ret = ldb_msg_add_string(new_msg,
2316 r->in.query->workstation_info->dns_hostname);
2317 if (ret != LDB_SUCCESS) {
2318 return NT_STATUS_NO_MEMORY;
2321 /* This manual "servicePrincipalName" generation is
2322 * still needed! Since the update in the samldb LDB
2323 * module does only work if the entries already exist
2324 * which isn't always the case. */
2325 ret = ldb_msg_add_string(new_msg,
2326 "servicePrincipalName",
2327 talloc_asprintf(new_msg, "HOST/%s",
2328 r->in.computer_name));
2329 if (ret != LDB_SUCCESS) {
2330 return NT_STATUS_NO_MEMORY;
2333 ret = ldb_msg_add_string(new_msg,
2334 "servicePrincipalName",
2335 talloc_asprintf(new_msg, "HOST/%s",
2336 r->in.query->workstation_info->dns_hostname));
2337 if (ret != LDB_SUCCESS) {
2338 return NT_STATUS_NO_MEMORY;
2342 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2343 DEBUG(3,("Impossible to update samdb: %s\n",
2344 ldb_errstring(sam_ctx)));
2347 talloc_free(new_msg);
2349 /* Writes back the domain information */
2351 /* We need to do two searches. The first will pull our primary
2352 domain and the second will pull any trusted domains. Our
2353 primary domain is also a "trusted" domain, so we need to
2354 put the primary domain into the lists of returned trusts as
2356 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2359 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2362 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2363 "(objectClass=trustedDomain)");
2365 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2368 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2369 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2371 ZERO_STRUCTP(domain_info);
2373 /* Informations about the local and trusted domains */
2375 status = fill_one_domain_info(mem_ctx,
2376 dce_call->conn->dce_ctx->lp_ctx,
2377 sam_ctx, res2[0], &domain_info->primary_domain,
2379 NT_STATUS_NOT_OK_RETURN(status);
2381 domain_info->trusted_domain_count = ret3 + 1;
2382 domain_info->trusted_domains = talloc_array(mem_ctx,
2383 struct netr_OneDomainInfo,
2384 domain_info->trusted_domain_count);
2385 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2387 for (i=0;i<ret3;i++) {
2388 status = fill_one_domain_info(mem_ctx,
2389 dce_call->conn->dce_ctx->lp_ctx,
2391 &domain_info->trusted_domains[i],
2393 NT_STATUS_NOT_OK_RETURN(status);
2396 status = fill_one_domain_info(mem_ctx,
2397 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2398 &domain_info->trusted_domains[i], true, true);
2399 NT_STATUS_NOT_OK_RETURN(status);
2401 /* Sets the supported encryption types */
2402 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2403 "msDS-SupportedEncryptionTypes",
2404 default_supported_enc_types);
2406 /* Other host domain information */
2408 lsa_policy_info = talloc(mem_ctx,
2409 struct netr_LsaPolicyInformation);
2410 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2411 ZERO_STRUCTP(lsa_policy_info);
2413 domain_info->lsa_policy = *lsa_policy_info;
2415 /* The DNS hostname is only returned back when there is a chance
2417 if ((r->in.query->workstation_info->workstation_flags
2418 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2419 domain_info->dns_hostname.string = old_dns_hostname;
2421 domain_info->dns_hostname.string = NULL;
2424 domain_info->workstation_flags =
2425 r->in.query->workstation_info->workstation_flags & (
2426 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2428 r->out.info->domain_info = domain_info;
2430 case 2: /* LSA policy information - not used at the moment */
2431 lsa_policy_info = talloc(mem_ctx,
2432 struct netr_LsaPolicyInformation);
2433 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2434 ZERO_STRUCTP(lsa_policy_info);
2436 r->out.info->lsa_policy_info = lsa_policy_info;
2439 return NT_STATUS_INVALID_LEVEL;
2443 return NT_STATUS_OK;
2448 netr_ServerPasswordGet
2450 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2451 struct netr_ServerPasswordGet *r)
2453 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2456 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2457 TALLOC_CTX *mem_ctx,
2458 struct dom_sid *user_sid,
2459 struct ldb_dn *obj_dn)
2461 const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
2462 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2463 struct ldb_dn *rodc_dn;
2465 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2466 const struct dom_sid *additional_sids[] = { NULL, NULL };
2468 struct dom_sid *object_sid;
2469 const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
2471 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2472 dom_sid_string(mem_ctx, user_sid));
2473 if (!ldb_dn_validate(rodc_dn)) goto denied;
2475 /* do the two searches we need */
2476 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2477 DSDB_SEARCH_SHOW_EXTENDED_DN);
2478 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2480 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2481 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2483 object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
2485 additional_sids[0] = object_sid;
2487 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2488 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
2489 if (!W_ERROR_IS_OK(werr)) {
2493 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2494 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
2495 if (!W_ERROR_IS_OK(werr)) {
2500 * The SID list needs to include itself as well as the tokenGroups.
2502 * TODO determine if sIDHistory is required for this check
2504 werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
2505 mem_ctx, "tokenGroups", &token_sids,
2506 additional_sids, 1);
2507 if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
2511 if (never_reveal_sids &&
2512 sid_list_match(token_sids, never_reveal_sids)) {
2517 sid_list_match(token_sids, reveal_sids)) {
2529 netr_NetrLogonSendToSam
2531 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2532 struct netr_NetrLogonSendToSam *r)
2534 struct netlogon_creds_CredentialState *creds;
2535 struct ldb_context *sam_ctx;
2537 DATA_BLOB decrypted_blob;
2538 enum ndr_err_code ndr_err;
2539 struct netr_SendToSamBase base_msg = { 0 };
2541 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2543 r->in.computer_name,
2545 r->out.return_authenticator,
2548 NT_STATUS_NOT_OK_RETURN(nt_status);
2550 switch (creds->secure_channel_type) {
2554 case SEC_CHAN_WKSTA:
2555 case SEC_CHAN_DNS_DOMAIN:
2556 case SEC_CHAN_DOMAIN:
2558 return NT_STATUS_INVALID_PARAMETER;
2560 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
2561 creds->secure_channel_type));
2562 return NT_STATUS_INVALID_PARAMETER;
2565 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
2566 dce_call->conn->dce_ctx->lp_ctx,
2567 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
2568 if (sam_ctx == NULL) {
2569 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2572 /* Buffer is meant to be 16-bit aligned */
2573 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2574 netlogon_creds_aes_decrypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2576 netlogon_creds_arcfour_crypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2579 decrypted_blob.data = r->in.opaque_buffer;
2580 decrypted_blob.length = r->in.buffer_len;
2582 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
2583 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
2585 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2586 /* We only partially implement SendToSam */
2587 return NT_STATUS_NOT_IMPLEMENTED;
2590 /* Now 'send' to SAM */
2591 switch (base_msg.message_type) {
2592 case SendToSamResetBadPasswordCount:
2594 struct ldb_message *msg = ldb_msg_new(mem_ctx);
2595 struct ldb_dn *dn = NULL;
2599 ret = ldb_transaction_start(sam_ctx);
2600 if (ret != LDB_SUCCESS) {
2601 return NT_STATUS_INTERNAL_ERROR;
2604 ret = dsdb_find_dn_by_guid(sam_ctx,
2606 &base_msg.message.reset_bad_password.guid,
2609 if (ret != LDB_SUCCESS) {
2610 ldb_transaction_cancel(sam_ctx);
2611 return NT_STATUS_INVALID_PARAMETER;
2614 if (creds->secure_channel_type == SEC_CHAN_RODC &&
2615 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
2616 DEBUG(1, ("Client asked to reset bad password on "
2617 "an arbitrary user: %s\n",
2618 ldb_dn_get_linearized(dn)));
2619 ldb_transaction_cancel(sam_ctx);
2620 return NT_STATUS_INVALID_PARAMETER;
2625 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
2626 if (ret != LDB_SUCCESS) {
2627 ldb_transaction_cancel(sam_ctx);
2628 return NT_STATUS_INVALID_PARAMETER;
2631 ret = dsdb_replace(sam_ctx, msg, 0);
2632 if (ret != LDB_SUCCESS) {
2633 ldb_transaction_cancel(sam_ctx);
2634 return NT_STATUS_INVALID_PARAMETER;
2637 ret = ldb_transaction_commit(sam_ctx);
2638 if (ret != LDB_SUCCESS) {
2639 ldb_transaction_cancel(sam_ctx);
2640 return NT_STATUS_INTERNAL_ERROR;
2646 return NT_STATUS_NOT_IMPLEMENTED;
2649 return NT_STATUS_OK;
2654 netr_DsRGetDCNameEx2
2656 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2657 TALLOC_CTX *mem_ctx,
2658 struct netr_DsRGetDCNameEx2 *r)
2660 struct ldb_context *sam_ctx;
2661 struct netr_DsRGetDCNameInfo *info;
2662 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2663 const struct tsocket_address *local_address;
2664 char *local_addr = NULL;
2665 const struct tsocket_address *remote_address;
2666 char *remote_addr = NULL;
2667 const char *server_site_name;
2669 struct netlogon_samlogon_response response;
2671 const char *dc_name = NULL;
2672 const char *domain_name = NULL;
2675 ZERO_STRUCTP(r->out.info);
2677 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2678 dce_call->conn->auth_state.session_info, 0);
2679 if (sam_ctx == NULL) {
2680 return WERR_DS_UNAVAILABLE;
2683 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2684 if (tsocket_address_is_inet(local_address, "ip")) {
2685 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2686 W_ERROR_HAVE_NO_MEMORY(local_addr);
2689 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2690 if (tsocket_address_is_inet(remote_address, "ip")) {
2691 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2692 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2695 /* "server_unc" is ignored by w2k3 */
2697 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2698 return WERR_INVALID_FLAGS;
2701 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2702 r->in.flags & DS_PDC_REQUIRED &&
2703 r->in.flags & DS_KDC_REQUIRED) {
2704 return WERR_INVALID_FLAGS;
2706 if (r->in.flags & DS_IS_FLAT_NAME &&
2707 r->in.flags & DS_IS_DNS_NAME) {
2708 return WERR_INVALID_FLAGS;
2710 if (r->in.flags & DS_RETURN_DNS_NAME &&
2711 r->in.flags & DS_RETURN_FLAT_NAME) {
2712 return WERR_INVALID_FLAGS;
2714 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2715 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2716 return WERR_INVALID_FLAGS;
2719 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2721 (DS_DIRECTORY_SERVICE_REQUIRED |
2722 DS_DIRECTORY_SERVICE_PREFERRED |
2723 DS_GC_SERVER_REQUIRED |
2726 return WERR_INVALID_FLAGS;
2729 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2731 return WERR_INVALID_FLAGS;
2734 /* Proof server site parameter "site_name" if it was specified */
2735 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2736 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2737 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2738 server_site_name) != 0)) {
2739 return WERR_NO_SUCH_DOMAIN;
2742 guid_str = r->in.domain_guid != NULL ?
2743 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2745 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2749 r->in.client_account,
2750 r->in.mask, remote_addr,
2751 NETLOGON_NT_VERSION_5EX_WITH_IP,
2752 lp_ctx, &response, true);
2753 if (!NT_STATUS_IS_OK(status)) {
2754 return ntstatus_to_werror(status);
2758 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2759 * (O) flag when the returned forest name is in DNS format. This is here
2760 * always the case (see below).
2762 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2764 if (r->in.flags & DS_RETURN_DNS_NAME) {
2765 dc_name = response.data.nt5_ex.pdc_dns_name;
2766 domain_name = response.data.nt5_ex.dns_domain;
2768 * According to MS-NRPC 2.2.1.2.1 we should set the
2769 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2770 * the returned information is in DNS form.
2772 response.data.nt5_ex.server_type |=
2773 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2774 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2775 dc_name = response.data.nt5_ex.pdc_name;
2776 domain_name = response.data.nt5_ex.domain_name;
2780 * TODO: autodetect what we need to return
2781 * based on the given arguments
2783 dc_name = response.data.nt5_ex.pdc_name;
2784 domain_name = response.data.nt5_ex.domain_name;
2787 if (!dc_name || !dc_name[0]) {
2788 return WERR_NO_SUCH_DOMAIN;
2791 if (!domain_name || !domain_name[0]) {
2792 return WERR_NO_SUCH_DOMAIN;
2795 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2796 W_ERROR_HAVE_NO_MEMORY(info);
2797 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2798 dc_name[0] != '\\'? "\\\\":"",
2799 talloc_strdup(mem_ctx, dc_name));
2800 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2802 pdc_ip = local_addr;
2803 if (pdc_ip == NULL) {
2804 pdc_ip = "127.0.0.1";
2806 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2807 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2808 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2809 info->domain_guid = response.data.nt5_ex.domain_uuid;
2810 info->domain_name = domain_name;
2811 info->forest_name = response.data.nt5_ex.forest;
2812 info->dc_flags = response.data.nt5_ex.server_type;
2813 if (r->in.flags & DS_RETURN_DNS_NAME) {
2814 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2815 * returned if we are returning info->dc_unc containing a FQDN.
2816 * This attribute is called DomainControllerName in the specs,
2817 * it seems that we decide to return FQDN or netbios depending on
2818 * DS_RETURN_DNS_NAME.
2820 info->dc_flags |= DS_DNS_CONTROLLER;
2822 info->dc_site_name = response.data.nt5_ex.server_site;
2823 info->client_site_name = response.data.nt5_ex.client_site;
2825 *r->out.info = info;
2833 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2834 struct netr_DsRGetDCNameEx *r)
2836 struct netr_DsRGetDCNameEx2 r2;
2841 r2.in.server_unc = r->in.server_unc;
2842 r2.in.client_account = NULL;
2844 r2.in.domain_guid = r->in.domain_guid;
2845 r2.in.domain_name = r->in.domain_name;
2846 r2.in.site_name = r->in.site_name;
2847 r2.in.flags = r->in.flags;
2848 r2.out.info = r->out.info;
2850 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2858 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2859 struct netr_DsRGetDCName *r)
2861 struct netr_DsRGetDCNameEx2 r2;
2866 r2.in.server_unc = r->in.server_unc;
2867 r2.in.client_account = NULL;
2869 r2.in.domain_name = r->in.domain_name;
2870 r2.in.domain_guid = r->in.domain_guid;
2872 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2873 r2.in.flags = r->in.flags;
2874 r2.out.info = r->out.info;
2876 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2881 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2883 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2884 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2886 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2891 netr_NetrEnumerateTrustedDomainsEx
2893 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2894 struct netr_NetrEnumerateTrustedDomainsEx *r)
2896 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2901 netr_DsRAddressToSitenamesExW
2903 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2904 struct netr_DsRAddressToSitenamesExW *r)
2906 struct ldb_context *sam_ctx;
2907 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2908 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2909 sa_family_t sin_family;
2910 struct sockaddr_in *addr;
2912 struct sockaddr_in6 *addr6;
2913 char addr_str[INET6_ADDRSTRLEN];
2915 char addr_str[INET_ADDRSTRLEN];
2921 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2922 dce_call->conn->auth_state.session_info, 0);
2923 if (sam_ctx == NULL) {
2924 return WERR_DS_UNAVAILABLE;
2927 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2928 W_ERROR_HAVE_NO_MEMORY(ctr);
2932 ctr->count = r->in.count;
2933 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2934 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2935 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2936 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2938 for (i=0; i<ctr->count; i++) {
2939 ctr->sitename[i].string = NULL;
2940 ctr->subnetname[i].string = NULL;
2942 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2945 /* The first two byte of the buffer are reserved for the
2946 * "sin_family" but for now only the first one is used. */
2947 sin_family = r->in.addresses[i].buffer[0];
2949 switch (sin_family) {
2951 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2954 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2955 res = inet_ntop(AF_INET, &addr->sin_addr,
2956 addr_str, sizeof(addr_str));
2960 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2963 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2964 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2965 addr_str, sizeof(addr_str));
2976 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2980 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2981 ctr->subnetname[i].string = subnet_name;
2989 netr_DsRAddressToSitenamesW
2991 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2992 struct netr_DsRAddressToSitenamesW *r)
2994 struct netr_DsRAddressToSitenamesExW r2;
2995 struct netr_DsRAddressToSitenamesWCtr *ctr;
3001 r2.in.server_name = r->in.server_name;
3002 r2.in.count = r->in.count;
3003 r2.in.addresses = r->in.addresses;
3005 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3006 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3008 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3009 W_ERROR_HAVE_NO_MEMORY(ctr);
3013 ctr->count = r->in.count;
3014 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3015 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3017 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3019 for (i=0; i<ctr->count; i++) {
3020 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3028 netr_DsrGetDcSiteCoverageW
3030 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3031 struct netr_DsrGetDcSiteCoverageW *r)
3033 struct ldb_context *sam_ctx;
3034 struct DcSitesCtr *ctr;
3035 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3037 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3038 dce_call->conn->auth_state.session_info, 0);
3039 if (sam_ctx == NULL) {
3040 return WERR_DS_UNAVAILABLE;
3043 ctr = talloc(mem_ctx, struct DcSitesCtr);
3044 W_ERROR_HAVE_NO_MEMORY(ctr);
3048 /* For now only return our default site */
3050 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3051 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3052 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3053 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3059 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3060 struct ldb_context *sam_ctx,
3061 struct netr_DomainTrustList *trusts,
3062 uint32_t trust_flags)
3064 struct ldb_dn *system_dn;
3065 struct ldb_message **dom_res = NULL;
3066 const char *trust_attrs[] = { "flatname", "trustPartner",
3067 "securityIdentifier", "trustDirection",
3068 "trustType", "trustAttributes", NULL };
3073 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3074 NETR_TRUST_FLAG_OUTBOUND))) {
3075 return WERR_INVALID_FLAGS;
3078 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3079 ldb_get_default_basedn(sam_ctx),
3080 "(&(objectClass=container)(cn=System))");
3082 return WERR_GEN_FAILURE;
3085 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3086 &dom_res, trust_attrs,
3087 "(objectclass=trustedDomain)");
3089 for (i = 0; i < ret; i++) {
3090 unsigned int trust_dir;
3093 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3094 "trustDirection", 0);
3096 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3097 flags |= NETR_TRUST_FLAG_INBOUND;
3099 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3100 flags |= NETR_TRUST_FLAG_OUTBOUND;
3103 if (!(flags & trust_flags)) {
3104 /* this trust direction was not requested */
3109 trusts->array = talloc_realloc(trusts, trusts->array,
3110 struct netr_DomainTrust,
3112 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3114 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3115 if (!trusts->array[n].netbios_name) {
3116 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3117 "without flatname\n",
3118 ldb_dn_get_linearized(dom_res[i]->dn)));
3121 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3123 trusts->array[n].trust_flags = flags;
3124 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3125 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3126 /* TODO: find if we have parent in the list */
3127 trusts->array[n].parent_index = 0;
3130 trusts->array[n].trust_type =
3131 ldb_msg_find_attr_as_uint(dom_res[i],
3133 trusts->array[n].trust_attributes =
3134 ldb_msg_find_attr_as_uint(dom_res[i],
3135 "trustAttributes", 0);
3137 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3138 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3139 struct dom_sid zero_sid;
3140 ZERO_STRUCT(zero_sid);
3141 trusts->array[n].sid =
3142 dom_sid_dup(trusts, &zero_sid);
3144 trusts->array[n].sid =
3145 samdb_result_dom_sid(trusts, dom_res[i],
3146 "securityIdentifier");
3148 trusts->array[n].guid = GUID_zero();
3150 trusts->count = n + 1;
3153 talloc_free(dom_res);
3158 netr_DsrEnumerateDomainTrusts
3160 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3161 TALLOC_CTX *mem_ctx,
3162 struct netr_DsrEnumerateDomainTrusts *r)
3164 struct netr_DomainTrustList *trusts;
3165 struct ldb_context *sam_ctx;
3167 struct ldb_message **dom_res;
3168 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3169 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3170 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3174 if (r->in.trust_flags & 0xFFFFFE00) {
3175 return WERR_INVALID_FLAGS;
3178 /* TODO: turn to hard check once we are sure this is 100% correct */
3179 if (!r->in.server_name) {
3180 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3181 "But received NULL!\n", dnsdomain));
3183 p = strchr(r->in.server_name, '.');
3185 DEBUG(3, ("Invalid domain! Expected name in domain "
3186 "[%s]. But received [%s]!\n",
3187 dnsdomain, r->in.server_name));
3188 p = r->in.server_name;
3192 if (strcasecmp(p, dnsdomain)) {
3193 DEBUG(3, ("Invalid domain! Expected name in domain "
3194 "[%s]. But received [%s]!\n",
3195 dnsdomain, r->in.server_name));
3199 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3200 W_ERROR_HAVE_NO_MEMORY(trusts);
3203 r->out.trusts = trusts;
3205 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3206 dce_call->conn->auth_state.session_info, 0);
3207 if (sam_ctx == NULL) {
3208 return WERR_GEN_FAILURE;
3211 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3212 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3214 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3215 trusts, r->in.trust_flags);
3216 W_ERROR_NOT_OK_RETURN(werr);
3219 /* NOTE: we currently are always the root of the forest */
3220 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3221 uint32_t n = trusts->count;
3223 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3224 &dom_res, dom_attrs);
3226 return WERR_GEN_FAILURE;
3229 trusts->count = n + 1;
3230 trusts->array = talloc_realloc(trusts, trusts->array,
3231 struct netr_DomainTrust,
3233 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3235 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3236 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3237 trusts->array[n].trust_flags =
3238 NETR_TRUST_FLAG_NATIVE |
3239 NETR_TRUST_FLAG_TREEROOT |
3240 NETR_TRUST_FLAG_IN_FOREST |
3241 NETR_TRUST_FLAG_PRIMARY;
3242 /* we are always the root domain for now */
3243 trusts->array[n].parent_index = 0;
3244 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3245 trusts->array[n].trust_attributes = 0;
3246 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3249 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3251 talloc_free(dom_res);
3259 netr_DsrDeregisterDNSHostRecords
3261 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3262 struct netr_DsrDeregisterDNSHostRecords *r)
3264 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3268 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3269 struct netr_ServerGetTrustInfo *r);
3272 netr_ServerTrustPasswordsGet
3274 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3275 struct netr_ServerTrustPasswordsGet *r)
3277 struct netr_ServerGetTrustInfo r2 = {};
3278 struct netr_TrustInfo *_ti = NULL;
3281 r2.in.server_name = r->in.server_name;
3282 r2.in.account_name = r->in.account_name;
3283 r2.in.secure_channel_type = r->in.secure_channel_type;
3284 r2.in.computer_name = r->in.computer_name;
3285 r2.in.credential = r->in.credential;
3287 r2.out.return_authenticator = r->out.return_authenticator;
3288 r2.out.new_owf_password = r->out.new_owf_password;
3289 r2.out.old_owf_password = r->out.old_owf_password;
3290 r2.out.trust_info = &_ti;
3292 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3294 r->out.return_authenticator = r2.out.return_authenticator;
3295 r->out.new_owf_password = r2.out.new_owf_password;
3296 r->out.old_owf_password = r2.out.old_owf_password;
3302 netr_DsRGetForestTrustInformation
3304 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3305 struct dcesrv_call_state *dce_call;
3306 TALLOC_CTX *mem_ctx;
3307 struct netr_DsRGetForestTrustInformation *r;
3310 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3312 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3313 TALLOC_CTX *mem_ctx,
3314 struct netr_DsRGetForestTrustInformation *r)
3316 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3317 struct dcesrv_connection *conn = dce_call->conn;
3318 struct auth_session_info *session_info = conn->auth_state.session_info;
3319 enum security_user_level security_level;
3320 struct ldb_context *sam_ctx = NULL;
3321 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3322 struct dcerpc_binding_handle *irpc_handle = NULL;
3323 struct tevent_req *subreq = NULL;
3324 struct ldb_dn *domain_dn = NULL;
3325 struct ldb_dn *forest_dn = NULL;
3329 security_level = security_session_user_level(session_info, NULL);
3330 if (security_level < SECURITY_USER) {
3331 return WERR_ACCESS_DENIED;
3334 if (r->in.flags & 0xFFFFFFFE) {
3335 return WERR_INVALID_FLAGS;
3338 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3339 dce_call->conn->auth_state.session_info, 0);
3340 if (sam_ctx == NULL) {
3341 return WERR_GEN_FAILURE;
3344 domain_dn = ldb_get_default_basedn(sam_ctx);
3345 if (domain_dn == NULL) {
3346 return WERR_GEN_FAILURE;
3349 forest_dn = ldb_get_root_basedn(sam_ctx);
3350 if (forest_dn == NULL) {
3351 return WERR_GEN_FAILURE;
3354 cmp = ldb_dn_compare(domain_dn, forest_dn);
3356 return WERR_NERR_ACFNOTLOADED;
3359 forest_level = dsdb_forest_functional_level(sam_ctx);
3360 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3361 return WERR_INVALID_FUNCTION;
3364 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3365 if (!samdb_is_pdc(sam_ctx)) {
3366 return WERR_NERR_NOTPRIMARY;
3369 if (r->in.trusted_domain_name == NULL) {
3370 return WERR_INVALID_FLAGS;
3374 if (r->in.trusted_domain_name == NULL) {
3378 * information about our own domain
3380 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3381 r->out.forest_trust_info);
3382 if (!NT_STATUS_IS_OK(status)) {
3383 return ntstatus_to_werror(status);
3390 * Forward the request to winbindd
3393 state = talloc_zero(mem_ctx,
3394 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3395 if (state == NULL) {
3396 return WERR_NOT_ENOUGH_MEMORY;
3398 state->dce_call = dce_call;
3399 state->mem_ctx = mem_ctx;
3402 irpc_handle = irpc_binding_handle_by_name(state,
3403 state->dce_call->msg_ctx,
3405 &ndr_table_winbind);
3406 if (irpc_handle == NULL) {
3407 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3408 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3409 return WERR_SERVICE_NOT_FOUND;
3413 * 60 seconds timeout should be enough
3415 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3417 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3418 state->dce_call->event_ctx,
3420 r->in.trusted_domain_name,
3422 r->out.forest_trust_info);
3423 if (subreq == NULL) {
3424 return WERR_NOT_ENOUGH_MEMORY;
3426 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3427 tevent_req_set_callback(subreq,
3428 dcesrv_netr_DsRGetForestTrustInformation_done,
3434 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3436 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3437 tevent_req_callback_data(subreq,
3438 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3441 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3443 &state->r->out.result);
3444 TALLOC_FREE(subreq);
3445 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3446 state->r->out.result = WERR_TIMEOUT;
3447 } else if (!NT_STATUS_IS_OK(status)) {
3448 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3449 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3450 nt_errstr(status)));
3453 status = dcesrv_reply(state->dce_call);
3454 if (!NT_STATUS_IS_OK(status)) {
3455 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3460 netr_GetForestTrustInformation
3462 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3463 TALLOC_CTX *mem_ctx,
3464 struct netr_GetForestTrustInformation *r)
3466 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3467 struct netlogon_creds_CredentialState *creds = NULL;
3468 struct ldb_context *sam_ctx = NULL;
3469 struct ldb_dn *domain_dn = NULL;
3470 struct ldb_dn *forest_dn = NULL;
3475 status = dcesrv_netr_creds_server_step_check(dce_call,
3477 r->in.computer_name,
3479 r->out.return_authenticator,
3481 if (!NT_STATUS_IS_OK(status)) {
3485 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3486 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3487 return NT_STATUS_NOT_IMPLEMENTED;
3490 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3491 dce_call->conn->auth_state.session_info, 0);
3492 if (sam_ctx == NULL) {
3493 return NT_STATUS_INTERNAL_ERROR;
3496 /* TODO: check r->in.server_name is our name */
3498 domain_dn = ldb_get_default_basedn(sam_ctx);
3499 if (domain_dn == NULL) {
3500 return NT_STATUS_INTERNAL_ERROR;
3503 forest_dn = ldb_get_root_basedn(sam_ctx);
3504 if (forest_dn == NULL) {
3505 return NT_STATUS_INTERNAL_ERROR;
3508 cmp = ldb_dn_compare(domain_dn, forest_dn);
3510 return NT_STATUS_INVALID_DOMAIN_STATE;
3513 forest_level = dsdb_forest_functional_level(sam_ctx);
3514 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3515 return NT_STATUS_INVALID_DOMAIN_STATE;
3518 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3519 r->out.forest_trust_info);
3520 if (!NT_STATUS_IS_OK(status)) {
3524 return NT_STATUS_OK;
3529 netr_ServerGetTrustInfo
3531 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3532 struct netr_ServerGetTrustInfo *r)
3534 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3535 struct netlogon_creds_CredentialState *creds = NULL;
3536 struct ldb_context *sam_ctx = NULL;
3537 const char * const attrs[] = {
3540 "userAccountControl",
3543 struct ldb_message **res = NULL;
3544 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3547 const char *asid = NULL;
3549 const char *aname = NULL;
3550 struct ldb_message *tdo_msg = NULL;
3551 const char * const tdo_attrs[] = {
3552 "trustAuthIncoming",
3556 struct netr_TrustInfo *trust_info = NULL;
3558 ZERO_STRUCTP(r->out.new_owf_password);
3559 ZERO_STRUCTP(r->out.old_owf_password);
3561 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3563 r->in.computer_name,
3565 r->out.return_authenticator,
3567 if (!NT_STATUS_IS_OK(nt_status)) {
3571 /* TODO: check r->in.server_name is our name */
3573 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3574 return NT_STATUS_INVALID_PARAMETER;
3577 if (r->in.secure_channel_type != creds->secure_channel_type) {
3578 return NT_STATUS_INVALID_PARAMETER;
3581 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3582 return NT_STATUS_INVALID_PARAMETER;
3585 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3586 lp_ctx, system_session(lp_ctx), 0);
3587 if (sam_ctx == NULL) {
3588 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3591 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3593 return NT_STATUS_NO_MEMORY;
3596 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3597 "(&(objectClass=user)(objectSid=%s))",
3600 return NT_STATUS_ACCOUNT_DISABLED;
3603 switch (creds->secure_channel_type) {
3604 case SEC_CHAN_DNS_DOMAIN:
3605 case SEC_CHAN_DOMAIN:
3606 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3608 if (uac & UF_ACCOUNTDISABLE) {
3609 return NT_STATUS_ACCOUNT_DISABLED;
3612 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3613 return NT_STATUS_ACCOUNT_DISABLED;
3616 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3617 if (aname == NULL) {
3618 return NT_STATUS_ACCOUNT_DISABLED;
3621 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3622 SEC_CHAN_DOMAIN, aname,
3623 tdo_attrs, mem_ctx, &tdo_msg);
3624 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3625 return NT_STATUS_ACCOUNT_DISABLED;
3627 if (!NT_STATUS_IS_OK(nt_status)) {
3631 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3634 if (!NT_STATUS_IS_OK(nt_status)) {
3638 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3639 if (trust_info == NULL) {
3640 return NT_STATUS_NO_MEMORY;
3643 trust_info->count = 1;
3644 trust_info->data = talloc_array(trust_info, uint32_t,
3646 if (trust_info->data == NULL) {
3647 return NT_STATUS_NO_MEMORY;
3650 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3656 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3659 if (!NT_STATUS_IS_OK(nt_status)) {
3663 prevNtHash = talloc(mem_ctx, struct samr_Password);
3664 if (prevNtHash == NULL) {
3665 return NT_STATUS_NO_MEMORY;
3668 E_md4hash("", prevNtHash->hash);
3672 if (curNtHash != NULL) {
3673 *r->out.new_owf_password = *curNtHash;
3674 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3676 if (prevNtHash != NULL) {
3677 *r->out.old_owf_password = *prevNtHash;
3678 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3681 if (trust_info != NULL) {
3682 *r->out.trust_info = trust_info;
3685 return NT_STATUS_OK;
3691 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3692 struct netr_Unused47 *r)
3694 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3698 struct netr_dnsupdate_RODC_state {
3699 struct dcesrv_call_state *dce_call;
3700 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3701 struct dnsupdate_RODC *r2;
3705 called when the forwarded RODC dns update request is finished
3707 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3709 struct netr_dnsupdate_RODC_state *st =
3710 tevent_req_callback_data(subreq,
3711 struct netr_dnsupdate_RODC_state);
3714 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3715 TALLOC_FREE(subreq);
3716 if (!NT_STATUS_IS_OK(status)) {
3717 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3718 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3721 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3723 status = dcesrv_reply(st->dce_call);
3724 if (!NT_STATUS_IS_OK(status)) {
3725 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3730 netr_DsrUpdateReadOnlyServerDnsRecords
3732 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3733 TALLOC_CTX *mem_ctx,
3734 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3736 struct netlogon_creds_CredentialState *creds;
3738 struct dcerpc_binding_handle *binding_handle;
3739 struct netr_dnsupdate_RODC_state *st;
3740 struct tevent_req *subreq;
3742 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3744 r->in.computer_name,
3746 r->out.return_authenticator,
3748 NT_STATUS_NOT_OK_RETURN(nt_status);
3750 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3751 return NT_STATUS_ACCESS_DENIED;
3754 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3755 NT_STATUS_HAVE_NO_MEMORY(st);
3757 st->dce_call = dce_call;
3759 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3760 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3762 st->r2->in.dom_sid = creds->sid;
3763 st->r2->in.site_name = r->in.site_name;
3764 st->r2->in.dns_ttl = r->in.dns_ttl;
3765 st->r2->in.dns_names = r->in.dns_names;
3766 st->r2->out.dns_names = r->out.dns_names;
3768 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3769 "dnsupdate", &ndr_table_irpc);
3770 if (binding_handle == NULL) {
3771 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3772 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3773 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3776 /* forward the call */
3777 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3778 binding_handle, st->r2);
3779 NT_STATUS_HAVE_NO_MEMORY(subreq);
3781 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3783 /* setup the callback */
3784 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3786 return NT_STATUS_OK;
3790 /* include the generated boilerplate */
3791 #include "librpc/gen_ndr/ndr_netlogon_s.c"