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(context, iface) \
49 dcesrv_interface_netlogon_bind(context, 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_connection_context *context,
61 const struct dcesrv_interface *iface)
63 return dcesrv_interface_bind_reject_connect(context, iface);
66 #define NETLOGON_SERVER_PIPE_STATE_MAGIC 0x4f555358
67 struct netlogon_server_pipe_state {
68 struct netr_Credential client_challenge;
69 struct netr_Credential server_challenge;
72 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
73 struct netr_ServerReqChallenge *r)
75 struct netlogon_server_pipe_state *pipe_state = NULL;
78 ZERO_STRUCTP(r->out.return_credentials);
80 pipe_state = dcesrv_iface_state_find_conn(dce_call,
81 NETLOGON_SERVER_PIPE_STATE_MAGIC,
82 struct netlogon_server_pipe_state);
83 TALLOC_FREE(pipe_state);
85 pipe_state = talloc_zero(dce_call,
86 struct netlogon_server_pipe_state);
87 if (pipe_state == NULL) {
88 return NT_STATUS_NO_MEMORY;
91 pipe_state->client_challenge = *r->in.credentials;
93 generate_random_buffer(pipe_state->server_challenge.data,
94 sizeof(pipe_state->server_challenge.data));
96 *r->out.return_credentials = pipe_state->server_challenge;
98 ntstatus = dcesrv_iface_state_store_conn(dce_call,
99 NETLOGON_SERVER_PIPE_STATE_MAGIC,
101 if (!NT_STATUS_IS_OK(ntstatus)) {
105 ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
106 &pipe_state->client_challenge,
107 &pipe_state->server_challenge,
108 r->in.computer_name);
109 if (!NT_STATUS_IS_OK(ntstatus)) {
110 TALLOC_FREE(pipe_state);
118 * Do the actual processing of a netr_ServerAuthenticate3 message.
119 * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
121 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
122 struct dcesrv_call_state *dce_call,
124 struct netr_ServerAuthenticate3 *r,
125 const char **trust_account_for_search,
126 const char **trust_account_in_db,
127 struct dom_sid **sid)
129 struct netlogon_server_pipe_state *pipe_state = NULL;
130 bool challenge_valid = false;
131 struct netlogon_server_pipe_state challenge;
132 struct netlogon_creds_CredentialState *creds;
133 struct ldb_context *sam_ctx;
134 struct samr_Password *curNtHash = NULL;
135 struct samr_Password *prevNtHash = NULL;
136 uint32_t user_account_control;
138 struct ldb_message **msgs;
140 const char *attrs[] = {"unicodePwd", "userAccountControl",
141 "objectSid", "samAccountName", NULL};
142 uint32_t server_flags = 0;
143 uint32_t negotiate_flags = 0;
144 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
145 bool reject_des_client = !allow_nt4_crypto;
146 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
148 ZERO_STRUCTP(r->out.return_credentials);
151 pipe_state = dcesrv_iface_state_find_conn(dce_call,
152 NETLOGON_SERVER_PIPE_STATE_MAGIC,
153 struct netlogon_server_pipe_state);
154 if (pipe_state != NULL) {
156 * If we had a challenge remembered on the connection
157 * consider this for usage. This can't be cleanup
160 * This is the default code path for typical clients
161 * which call netr_ServerReqChallenge() and
162 * netr_ServerAuthenticate3() on the same dcerpc connection.
164 challenge = *pipe_state;
166 challenge_valid = true;
172 * Fallback and try to get the challenge from
175 * If too many clients are using this code path,
176 * they may destroy their cache entries as the
177 * TDB has a fixed size limited via a lossy hash
179 * The TDB used is the schannel store, which is
180 * initialised at startup.
182 * NOTE: The challenge is deleted from the DB as soon as it is
183 * fetched, to prevent reuse.
187 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
188 &challenge.client_challenge,
189 &challenge.server_challenge,
190 r->in.computer_name);
192 if (!NT_STATUS_IS_OK(ntstatus)) {
193 ZERO_STRUCT(challenge);
195 challenge_valid = true;
199 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
200 NETLOGON_NEG_PERSISTENT_SAMREPL |
201 NETLOGON_NEG_ARCFOUR |
202 NETLOGON_NEG_PROMOTION_COUNT |
203 NETLOGON_NEG_CHANGELOG_BDC |
204 NETLOGON_NEG_FULL_SYNC_REPL |
205 NETLOGON_NEG_MULTIPLE_SIDS |
207 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
208 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
209 NETLOGON_NEG_GENERIC_PASSTHROUGH |
210 NETLOGON_NEG_CONCURRENT_RPC |
211 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
212 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
213 NETLOGON_NEG_STRONG_KEYS |
214 NETLOGON_NEG_TRANSITIVE_TRUSTS |
215 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
216 NETLOGON_NEG_PASSWORD_SET2 |
217 NETLOGON_NEG_GETDOMAININFO |
218 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
219 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
220 NETLOGON_NEG_RODC_PASSTHROUGH |
221 NETLOGON_NEG_SUPPORTS_AES |
222 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
223 NETLOGON_NEG_AUTHENTICATED_RPC;
225 negotiate_flags = *r->in.negotiate_flags & server_flags;
227 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
228 reject_des_client = false;
231 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
232 reject_des_client = false;
233 reject_md5_client = false;
236 if (reject_des_client || reject_md5_client) {
238 * Here we match Windows 2012 and return no flags.
240 *r->out.negotiate_flags = 0;
241 return NT_STATUS_DOWNGRADE_DETECTED;
245 * This talloc_free is important to prevent re-use of the
246 * challenge. We have to delay it this far due to NETApp
248 * https://bugzilla.samba.org/show_bug.cgi?id=11291
250 TALLOC_FREE(pipe_state);
253 * At this point we must also cleanup the TDB cache
254 * entry, if we fail the client needs to call
255 * netr_ServerReqChallenge again.
257 * Note: this handles a non existing record just fine,
258 * the r->in.computer_name might not be the one used
259 * in netr_ServerReqChallenge(), but we are trying to
260 * just tidy up the normal case to prevent re-use.
262 schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
263 r->in.computer_name);
266 * According to Microsoft (see bugid #6099)
267 * Windows 7 looks at the negotiate_flags
268 * returned in this structure *even if the
269 * call fails with access denied!
271 *r->out.negotiate_flags = negotiate_flags;
273 switch (r->in.secure_channel_type) {
275 case SEC_CHAN_DNS_DOMAIN:
276 case SEC_CHAN_DOMAIN:
281 return NT_STATUS_INVALID_PARAMETER;
283 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
284 r->in.secure_channel_type));
285 return NT_STATUS_INVALID_PARAMETER;
288 sam_ctx = samdb_connect(mem_ctx,
290 dce_call->conn->dce_ctx->lp_ctx,
291 system_session(dce_call->conn->dce_ctx->lp_ctx),
292 dce_call->conn->remote_address,
294 if (sam_ctx == NULL) {
295 return NT_STATUS_INVALID_SYSTEM_SERVICE;
298 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
299 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
301 struct ldb_message *tdo_msg = NULL;
302 const char * const tdo_attrs[] = {
308 char *encoded_name = NULL;
310 const char *flatname = NULL;
312 bool require_trailer = true;
313 const char *netbios = NULL;
314 const char *dns = NULL;
316 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
318 require_trailer = false;
321 encoded_name = ldb_binary_encode_string(mem_ctx,
323 if (encoded_name == NULL) {
324 return NT_STATUS_NO_MEMORY;
327 len = strlen(encoded_name);
329 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
332 if (require_trailer && encoded_name[len - 1] != trailer) {
333 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
335 encoded_name[len - 1] = '\0';
337 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
340 netbios = encoded_name;
343 nt_status = dsdb_trust_search_tdo(sam_ctx,
345 tdo_attrs, mem_ctx, &tdo_msg);
346 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
347 DEBUG(2, ("Client asked for a trusted domain secure channel, "
348 "but there's no tdo for [%s] => [%s] \n",
349 log_escape(mem_ctx, r->in.account_name),
351 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
353 if (!NT_STATUS_IS_OK(nt_status)) {
357 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
360 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
361 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
363 if (!NT_STATUS_IS_OK(nt_status)) {
367 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
368 if (flatname == NULL) {
369 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
372 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
373 if (*trust_account_for_search == NULL) {
374 return NT_STATUS_NO_MEMORY;
377 *trust_account_for_search = r->in.account_name;
380 /* pull the user attributes */
381 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
382 "(&(sAMAccountName=%s)(objectclass=user))",
383 ldb_binary_encode_string(mem_ctx,
384 *trust_account_for_search));
386 if (num_records == 0) {
387 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
388 log_escape(mem_ctx, r->in.account_name)));
389 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
392 if (num_records > 1) {
393 DEBUG(0,("Found %d records matching user [%s]\n",
395 log_escape(mem_ctx, r->in.account_name)));
396 return NT_STATUS_INTERNAL_DB_CORRUPTION;
399 *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
402 if (*trust_account_in_db == NULL) {
403 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
404 r->in.account_name));
405 return NT_STATUS_INTERNAL_DB_CORRUPTION;
408 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
410 if (user_account_control & UF_ACCOUNTDISABLE) {
411 DEBUG(1, ("Account [%s] is disabled\n",
412 log_escape(mem_ctx, r->in.account_name)));
413 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
416 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
417 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
418 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
419 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
421 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
422 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
423 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
424 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
426 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
428 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
429 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
430 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
431 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
433 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
434 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
435 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
436 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
439 /* we should never reach this */
440 return NT_STATUS_INTERNAL_ERROR;
443 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
444 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
445 dce_call->conn->dce_ctx->lp_ctx,
446 msgs[0], NULL, &curNtHash);
447 if (!NT_STATUS_IS_OK(nt_status)) {
448 return NT_STATUS_ACCESS_DENIED;
452 if (curNtHash == NULL) {
453 return NT_STATUS_ACCESS_DENIED;
456 if (!challenge_valid) {
457 DEBUG(1, ("No challenge requested by client [%s/%s], "
458 "cannot authenticate\n",
459 log_escape(mem_ctx, r->in.computer_name),
460 log_escape(mem_ctx, r->in.account_name)));
461 return NT_STATUS_ACCESS_DENIED;
464 creds = netlogon_creds_server_init(mem_ctx,
467 r->in.secure_channel_type,
468 &challenge.client_challenge,
469 &challenge.server_challenge,
472 r->out.return_credentials,
474 if (creds == NULL && prevNtHash != NULL) {
476 * We fallback to the previous password for domain trusts.
478 * Note that lpcfg_old_password_allowed_period() doesn't
481 creds = netlogon_creds_server_init(mem_ctx,
484 r->in.secure_channel_type,
485 &challenge.client_challenge,
486 &challenge.server_challenge,
489 r->out.return_credentials,
494 return NT_STATUS_ACCESS_DENIED;
496 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
497 *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
499 nt_status = schannel_save_creds_state(mem_ctx,
500 dce_call->conn->dce_ctx->lp_ctx,
502 if (!NT_STATUS_IS_OK(nt_status)) {
503 ZERO_STRUCTP(r->out.return_credentials);
507 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
514 * Log a netr_ServerAuthenticate3 request, and then invoke
515 * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
517 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
518 struct dcesrv_call_state *dce_call,
520 struct netr_ServerAuthenticate3 *r)
523 struct dom_sid *sid = NULL;
524 const char *trust_account_for_search = NULL;
525 const char *trust_account_in_db = NULL;
526 struct auth_usersupplied_info ui = {
527 .local_host = dce_call->conn->local_address,
528 .remote_host = dce_call->conn->remote_address,
530 .account_name = r->in.account_name,
531 .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
533 .service_description = "NETLOGON",
534 .auth_description = "ServerAuthenticate",
535 .netlogon_trust_account = {
536 .computer_name = r->in.computer_name,
537 .negotiate_flags = *r->in.negotiate_flags,
538 .secure_channel_type = r->in.secure_channel_type,
542 status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
545 &trust_account_for_search,
546 &trust_account_in_db,
548 ui.netlogon_trust_account.sid = sid;
549 ui.netlogon_trust_account.account_name = trust_account_in_db;
550 ui.mapped.account_name = trust_account_for_search;
551 log_authentication_event(
552 dce_call->conn->msg_ctx,
553 dce_call->conn->dce_ctx->lp_ctx,
557 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
564 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
565 struct netr_ServerAuthenticate *r)
567 struct netr_ServerAuthenticate3 a;
570 * negotiate_flags is used as an [in] parameter
571 * so it need to be initialised.
573 * (I think ... = 0; seems wrong here --metze)
575 uint32_t negotiate_flags_in = 0;
576 uint32_t negotiate_flags_out = 0;
578 a.in.server_name = r->in.server_name;
579 a.in.account_name = r->in.account_name;
580 a.in.secure_channel_type = r->in.secure_channel_type;
581 a.in.computer_name = r->in.computer_name;
582 a.in.credentials = r->in.credentials;
583 a.in.negotiate_flags = &negotiate_flags_in;
585 a.out.return_credentials = r->out.return_credentials;
587 a.out.negotiate_flags = &negotiate_flags_out;
589 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
592 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
593 struct netr_ServerAuthenticate2 *r)
595 struct netr_ServerAuthenticate3 r3;
598 r3.in.server_name = r->in.server_name;
599 r3.in.account_name = r->in.account_name;
600 r3.in.secure_channel_type = r->in.secure_channel_type;
601 r3.in.computer_name = r->in.computer_name;
602 r3.in.credentials = r->in.credentials;
603 r3.out.return_credentials = r->out.return_credentials;
604 r3.in.negotiate_flags = r->in.negotiate_flags;
605 r3.out.negotiate_flags = r->out.negotiate_flags;
608 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
612 * NOTE: The following functions are nearly identical to the ones available in
613 * source3/rpc_server/srv_nelog_nt.c
614 * The reason we keep 2 copies is that they use different structures to
615 * represent the auth_info and the decrpc pipes.
617 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
619 const char *computer_name,
620 struct netr_Authenticator *received_authenticator,
621 struct netr_Authenticator *return_authenticator,
622 struct netlogon_creds_CredentialState **creds_out)
625 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
626 bool schannel_global_required = (schannel == true);
628 if (schannel_global_required) {
629 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
631 dcesrv_call_auth_info(dce_call, &auth_type, NULL);
633 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
634 DBG_ERR("[%s] is not using schannel\n",
636 return NT_STATUS_ACCESS_DENIED;
640 nt_status = schannel_check_creds_state(mem_ctx,
641 dce_call->conn->dce_ctx->lp_ctx,
643 received_authenticator,
644 return_authenticator,
650 Change the machine account password for the currently connected
651 client. Supplies only the NT#.
654 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
655 struct netr_ServerPasswordSet *r)
657 struct netlogon_creds_CredentialState *creds;
658 struct ldb_context *sam_ctx;
659 const char * const attrs[] = { "unicodePwd", NULL };
660 struct ldb_message **res;
661 struct samr_Password *oldNtHash;
665 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
668 r->in.credential, r->out.return_authenticator,
670 NT_STATUS_NOT_OK_RETURN(nt_status);
672 sam_ctx = samdb_connect(mem_ctx,
674 dce_call->conn->dce_ctx->lp_ctx,
675 system_session(dce_call->conn->dce_ctx->lp_ctx),
676 dce_call->conn->remote_address,
678 if (sam_ctx == NULL) {
679 return NT_STATUS_INVALID_SYSTEM_SERVICE;
682 netlogon_creds_des_decrypt(creds, r->in.new_password);
684 /* fetch the old password hashes (the NT hash has to exist) */
686 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
687 "(&(objectClass=user)(objectSid=%s))",
688 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
690 return NT_STATUS_WRONG_PASSWORD;
693 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
694 dce_call->conn->dce_ctx->lp_ctx,
695 res[0], NULL, &oldNtHash);
696 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
697 return NT_STATUS_WRONG_PASSWORD;
700 /* Using the sid for the account as the key, set the password */
701 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
703 NULL, /* Don't have version */
704 NULL, /* Don't have plaintext */
705 NULL, r->in.new_password,
706 NULL, oldNtHash, /* Password change */
712 Change the machine account password for the currently connected
713 client. Supplies new plaintext.
715 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
716 struct netr_ServerPasswordSet2 *r)
718 struct netlogon_creds_CredentialState *creds;
719 struct ldb_context *sam_ctx;
720 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
721 struct ldb_message **res;
722 struct samr_Password *oldLmHash, *oldNtHash;
723 struct NL_PASSWORD_VERSION version = {};
724 const uint32_t *new_version = NULL;
726 DATA_BLOB new_password;
728 struct samr_CryptPassword password_buf;
730 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
733 r->in.credential, r->out.return_authenticator,
735 NT_STATUS_NOT_OK_RETURN(nt_status);
737 sam_ctx = samdb_connect(mem_ctx,
739 dce_call->conn->dce_ctx->lp_ctx,
740 system_session(dce_call->conn->dce_ctx->lp_ctx),
741 dce_call->conn->remote_address,
743 if (sam_ctx == NULL) {
744 return NT_STATUS_INVALID_SYSTEM_SERVICE;
747 memcpy(password_buf.data, r->in.new_password->data, 512);
748 SIVAL(password_buf.data, 512, r->in.new_password->length);
750 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
751 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
753 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
756 switch (creds->secure_channel_type) {
757 case SEC_CHAN_DOMAIN:
758 case SEC_CHAN_DNS_DOMAIN: {
759 uint32_t len = IVAL(password_buf.data, 512);
761 uint32_t ofs = 500 - len;
764 p = password_buf.data + ofs;
766 version.ReservedField = IVAL(p, 0);
767 version.PasswordVersionNumber = IVAL(p, 4);
768 version.PasswordVersionPresent = IVAL(p, 8);
770 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
771 new_version = &version.PasswordVersionNumber;
779 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
780 DEBUG(3,("samr: failed to decode password buffer\n"));
781 return NT_STATUS_WRONG_PASSWORD;
784 /* fetch the old password hashes (at least one of both has to exist) */
786 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
787 "(&(objectClass=user)(objectSid=%s))",
788 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
790 return NT_STATUS_WRONG_PASSWORD;
793 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
794 dce_call->conn->dce_ctx->lp_ctx,
795 res[0], &oldLmHash, &oldNtHash);
796 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
797 return NT_STATUS_WRONG_PASSWORD;
800 /* Using the sid for the account as the key, set the password */
801 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
804 &new_password, /* we have plaintext */
806 oldLmHash, oldNtHash, /* Password change */
815 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
816 struct netr_LogonUasLogon *r)
818 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
825 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
826 struct netr_LogonUasLogoff *r)
828 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
832 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
833 const struct netr_LogonSamLogonEx *r)
835 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
837 switch (r->in.logon_level) {
838 case NetlogonInteractiveInformation:
839 case NetlogonServiceInformation:
840 case NetlogonInteractiveTransitiveInformation:
841 case NetlogonServiceTransitiveInformation:
842 if (r->in.logon->password == NULL) {
843 return NT_STATUS_INVALID_PARAMETER;
846 switch (r->in.validation_level) {
847 case NetlogonValidationSamInfo: /* 2 */
848 case NetlogonValidationSamInfo2: /* 3 */
849 case NetlogonValidationSamInfo4: /* 6 */
852 return NT_STATUS_INVALID_INFO_CLASS;
856 case NetlogonNetworkInformation:
857 case NetlogonNetworkTransitiveInformation:
858 if (r->in.logon->network == NULL) {
859 return NT_STATUS_INVALID_PARAMETER;
862 switch (r->in.validation_level) {
863 case NetlogonValidationSamInfo: /* 2 */
864 case NetlogonValidationSamInfo2: /* 3 */
865 case NetlogonValidationSamInfo4: /* 6 */
868 return NT_STATUS_INVALID_INFO_CLASS;
873 case NetlogonGenericInformation:
874 if (r->in.logon->generic == NULL) {
875 return NT_STATUS_INVALID_PARAMETER;
878 switch (r->in.validation_level) {
879 /* TODO: case NetlogonValidationGenericInfo: 4 */
880 case NetlogonValidationGenericInfo2: /* 5 */
883 return NT_STATUS_INVALID_INFO_CLASS;
888 return NT_STATUS_INVALID_PARAMETER;
891 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
893 switch (r->in.validation_level) {
894 case NetlogonValidationSamInfo4: /* 6 */
895 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
896 return NT_STATUS_INVALID_PARAMETER;
907 struct dcesrv_netr_LogonSamLogon_base_state {
908 struct dcesrv_call_state *dce_call;
912 struct netlogon_creds_CredentialState *creds;
914 struct netr_LogonSamLogonEx r;
916 uint32_t _ignored_flags;
919 struct netr_LogonSamLogon *lsl;
920 struct netr_LogonSamLogonWithFlags *lslwf;
921 struct netr_LogonSamLogonEx *lslex;
924 struct kdc_check_generic_kerberos kr;
927 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
928 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
929 static void dcesrv_netr_LogonSamLogon_base_reply(
930 struct dcesrv_netr_LogonSamLogon_base_state *state);
933 netr_LogonSamLogon_base
935 This version of the function allows other wrappers to say 'do not check the credentials'
937 We can't do the traditional 'wrapping' format completely, as this
938 function must only run under schannel
940 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
942 struct dcesrv_call_state *dce_call = state->dce_call;
943 TALLOC_CTX *mem_ctx = state->mem_ctx;
944 struct netr_LogonSamLogonEx *r = &state->r;
945 struct netlogon_creds_CredentialState *creds = state->creds;
946 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
947 const char *workgroup = lpcfg_workgroup(lp_ctx);
948 struct auth4_context *auth_context = NULL;
949 struct auth_usersupplied_info *user_info = NULL;
951 struct tevent_req *subreq = NULL;
953 *r->out.authoritative = 1;
955 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
957 * Currently we're always the forest root ourself.
959 return NT_STATUS_NO_SUCH_USER;
962 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
964 * Currently we don't support trusts correctly yet.
966 return NT_STATUS_NO_SUCH_USER;
969 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
970 NT_STATUS_HAVE_NO_MEMORY(user_info);
972 user_info->service_description = "SamLogon";
974 netlogon_creds_decrypt_samlogon_logon(creds,
978 switch (r->in.logon_level) {
979 case NetlogonInteractiveInformation:
980 case NetlogonServiceInformation:
981 case NetlogonInteractiveTransitiveInformation:
982 case NetlogonServiceTransitiveInformation:
983 case NetlogonNetworkInformation:
984 case NetlogonNetworkTransitiveInformation:
986 nt_status = auth_context_create_for_netlogon(mem_ctx,
987 dce_call->event_ctx, dce_call->msg_ctx,
988 dce_call->conn->dce_ctx->lp_ctx,
990 NT_STATUS_NOT_OK_RETURN(nt_status);
992 user_info->remote_host = dce_call->conn->remote_address;
993 user_info->local_host = dce_call->conn->local_address;
995 user_info->netlogon_trust_account.secure_channel_type
996 = creds->secure_channel_type;
997 user_info->netlogon_trust_account.negotiate_flags
998 = creds->negotiate_flags;
1001 * These two can be unrelated when the account is
1002 * actually that of a trusted domain, so we want to
1003 * know which DC in that trusted domain contacted
1006 user_info->netlogon_trust_account.computer_name
1007 = creds->computer_name;
1008 user_info->netlogon_trust_account.account_name
1009 = creds->account_name;
1010 user_info->netlogon_trust_account.sid
1014 /* We do not need to set up the user_info in this case */
1018 switch (r->in.logon_level) {
1019 case NetlogonInteractiveInformation:
1020 case NetlogonServiceInformation:
1021 case NetlogonInteractiveTransitiveInformation:
1022 case NetlogonServiceTransitiveInformation:
1023 user_info->auth_description = "interactive";
1025 user_info->logon_parameters
1026 = r->in.logon->password->identity_info.parameter_control;
1027 user_info->client.account_name
1028 = r->in.logon->password->identity_info.account_name.string;
1029 user_info->client.domain_name
1030 = r->in.logon->password->identity_info.domain_name.string;
1031 user_info->workstation_name
1032 = r->in.logon->password->identity_info.workstation.string;
1033 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1034 user_info->password_state = AUTH_PASSWORD_HASH;
1036 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1037 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1038 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1040 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1041 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1042 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1045 = r->in.logon->password->identity_info.logon_id;
1048 case NetlogonNetworkInformation:
1049 case NetlogonNetworkTransitiveInformation:
1050 user_info->auth_description = "network";
1052 nt_status = auth_context_set_challenge(
1054 r->in.logon->network->challenge,
1055 "netr_LogonSamLogonWithFlags");
1056 NT_STATUS_NOT_OK_RETURN(nt_status);
1058 user_info->logon_parameters
1059 = r->in.logon->network->identity_info.parameter_control;
1060 user_info->client.account_name
1061 = r->in.logon->network->identity_info.account_name.string;
1062 user_info->client.domain_name
1063 = r->in.logon->network->identity_info.domain_name.string;
1064 user_info->workstation_name
1065 = r->in.logon->network->identity_info.workstation.string;
1067 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1068 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1069 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1072 = r->in.logon->network->identity_info.logon_id;
1074 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1075 user_info->client.account_name,
1076 user_info->client.domain_name,
1077 user_info->password.response.nt,
1079 NT_STATUS_NOT_OK_RETURN(nt_status);
1084 case NetlogonGenericInformation:
1086 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1088 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1091 /* Using DES to verify kerberos tickets makes no sense */
1092 return NT_STATUS_INVALID_PARAMETER;
1095 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1096 struct dcerpc_binding_handle *irpc_handle;
1097 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1098 NT_STATUS_HAVE_NO_MEMORY(generic);
1100 r->out.validation->generic = generic;
1103 = r->in.logon->generic->identity_info.logon_id;
1105 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1109 if (irpc_handle == NULL) {
1110 return NT_STATUS_NO_LOGON_SERVERS;
1113 state->kr.in.generic_request =
1114 data_blob_const(r->in.logon->generic->data,
1115 r->in.logon->generic->length);
1118 * 60 seconds should be enough
1120 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1121 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1122 state->dce_call->event_ctx,
1123 irpc_handle, &state->kr);
1124 if (subreq == NULL) {
1125 return NT_STATUS_NO_MEMORY;
1127 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1128 tevent_req_set_callback(subreq,
1129 dcesrv_netr_LogonSamLogon_base_krb5_done,
1131 return NT_STATUS_OK;
1134 /* Until we get an implemetnation of these other packages */
1135 return NT_STATUS_INVALID_PARAMETER;
1138 return NT_STATUS_INVALID_PARAMETER;
1141 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1142 auth_context, user_info);
1143 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1144 tevent_req_set_callback(subreq,
1145 dcesrv_netr_LogonSamLogon_base_auth_done,
1147 return NT_STATUS_OK;
1150 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1152 struct dcesrv_netr_LogonSamLogon_base_state *state =
1153 tevent_req_callback_data(subreq,
1154 struct dcesrv_netr_LogonSamLogon_base_state);
1155 TALLOC_CTX *mem_ctx = state->mem_ctx;
1156 struct netr_LogonSamLogonEx *r = &state->r;
1157 struct auth_user_info_dc *user_info_dc = NULL;
1158 struct netr_SamInfo2 *sam2 = NULL;
1159 struct netr_SamInfo3 *sam3 = NULL;
1160 struct netr_SamInfo6 *sam6 = NULL;
1163 nt_status = auth_check_password_recv(subreq, mem_ctx,
1165 r->out.authoritative);
1166 TALLOC_FREE(subreq);
1167 if (!NT_STATUS_IS_OK(nt_status)) {
1168 r->out.result = nt_status;
1169 dcesrv_netr_LogonSamLogon_base_reply(state);
1173 switch (r->in.validation_level) {
1175 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1178 if (!NT_STATUS_IS_OK(nt_status)) {
1179 r->out.result = nt_status;
1180 dcesrv_netr_LogonSamLogon_base_reply(state);
1184 r->out.validation->sam2 = sam2;
1188 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1191 if (!NT_STATUS_IS_OK(nt_status)) {
1192 r->out.result = nt_status;
1193 dcesrv_netr_LogonSamLogon_base_reply(state);
1197 r->out.validation->sam3 = sam3;
1201 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1204 if (!NT_STATUS_IS_OK(nt_status)) {
1205 r->out.result = nt_status;
1206 dcesrv_netr_LogonSamLogon_base_reply(state);
1210 r->out.validation->sam6 = sam6;
1214 if (!NT_STATUS_IS_OK(nt_status)) {
1215 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1216 dcesrv_netr_LogonSamLogon_base_reply(state);
1221 /* TODO: Describe and deal with these flags */
1224 r->out.result = NT_STATUS_OK;
1226 dcesrv_netr_LogonSamLogon_base_reply(state);
1229 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1231 struct dcesrv_netr_LogonSamLogon_base_state *state =
1232 tevent_req_callback_data(subreq,
1233 struct dcesrv_netr_LogonSamLogon_base_state);
1234 TALLOC_CTX *mem_ctx = state->mem_ctx;
1235 struct netr_LogonSamLogonEx *r = &state->r;
1236 struct netr_GenericInfo2 *generic = NULL;
1239 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1240 TALLOC_FREE(subreq);
1241 if (!NT_STATUS_IS_OK(status)) {
1242 r->out.result = status;
1243 dcesrv_netr_LogonSamLogon_base_reply(state);
1247 generic = r->out.validation->generic;
1248 generic->length = state->kr.out.generic_reply.length;
1249 generic->data = state->kr.out.generic_reply.data;
1251 /* TODO: Describe and deal with these flags */
1254 r->out.result = NT_STATUS_OK;
1256 dcesrv_netr_LogonSamLogon_base_reply(state);
1259 static void dcesrv_netr_LogonSamLogon_base_reply(
1260 struct dcesrv_netr_LogonSamLogon_base_state *state)
1262 struct netr_LogonSamLogonEx *r = &state->r;
1265 if (NT_STATUS_IS_OK(r->out.result)) {
1266 netlogon_creds_encrypt_samlogon_validation(state->creds,
1267 r->in.validation_level,
1271 if (state->_r.lslex != NULL) {
1272 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1273 _r->out.result = r->out.result;
1274 } else if (state->_r.lslwf != NULL) {
1275 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1276 _r->out.result = r->out.result;
1277 } else if (state->_r.lsl != NULL) {
1278 struct netr_LogonSamLogon *_r = state->_r.lsl;
1279 _r->out.result = r->out.result;
1282 status = dcesrv_reply(state->dce_call);
1283 if (!NT_STATUS_IS_OK(status)) {
1284 DBG_ERR("dcesrv_reply() failed - %s\n",
1289 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1290 struct netr_LogonSamLogonEx *r)
1292 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1293 struct dcesrv_netr_LogonSamLogon_base_state *state;
1296 *r->out.authoritative = 1;
1298 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1299 if (state == NULL) {
1300 return NT_STATUS_NO_MEMORY;
1303 state->dce_call = dce_call;
1304 state->mem_ctx = mem_ctx;
1306 state->r.in.server_name = r->in.server_name;
1307 state->r.in.computer_name = r->in.computer_name;
1308 state->r.in.logon_level = r->in.logon_level;
1309 state->r.in.logon = r->in.logon;
1310 state->r.in.validation_level = r->in.validation_level;
1311 state->r.in.flags = r->in.flags;
1312 state->r.out.validation = r->out.validation;
1313 state->r.out.authoritative = r->out.authoritative;
1314 state->r.out.flags = r->out.flags;
1316 state->_r.lslex = r;
1318 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1319 if (!NT_STATUS_IS_OK(nt_status)) {
1323 nt_status = schannel_get_creds_state(mem_ctx,
1324 dce_call->conn->dce_ctx->lp_ctx,
1325 r->in.computer_name, &state->creds);
1326 if (!NT_STATUS_IS_OK(nt_status)) {
1330 dcesrv_call_auth_info(dce_call, &auth_type, NULL);
1332 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1333 return NT_STATUS_ACCESS_DENIED;
1336 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1338 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1346 netr_LogonSamLogonWithFlags
1349 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1350 struct netr_LogonSamLogonWithFlags *r)
1352 struct dcesrv_netr_LogonSamLogon_base_state *state;
1355 *r->out.authoritative = 1;
1357 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1358 if (state == NULL) {
1359 return NT_STATUS_NO_MEMORY;
1362 state->dce_call = dce_call;
1363 state->mem_ctx = mem_ctx;
1365 state->r.in.server_name = r->in.server_name;
1366 state->r.in.computer_name = r->in.computer_name;
1367 state->r.in.logon_level = r->in.logon_level;
1368 state->r.in.logon = r->in.logon;
1369 state->r.in.validation_level = r->in.validation_level;
1370 state->r.in.flags = r->in.flags;
1371 state->r.out.validation = r->out.validation;
1372 state->r.out.authoritative = r->out.authoritative;
1373 state->r.out.flags = r->out.flags;
1375 state->_r.lslwf = r;
1377 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1378 if (!NT_STATUS_IS_OK(nt_status)) {
1382 r->out.return_authenticator = talloc_zero(mem_ctx,
1383 struct netr_Authenticator);
1384 if (r->out.return_authenticator == NULL) {
1385 return NT_STATUS_NO_MEMORY;
1388 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1390 r->in.computer_name,
1392 r->out.return_authenticator,
1394 if (!NT_STATUS_IS_OK(nt_status)) {
1398 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1400 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1410 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1411 struct netr_LogonSamLogon *r)
1413 struct dcesrv_netr_LogonSamLogon_base_state *state;
1416 *r->out.authoritative = 1;
1418 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1419 if (state == NULL) {
1420 return NT_STATUS_NO_MEMORY;
1423 state->dce_call = dce_call;
1424 state->mem_ctx = mem_ctx;
1426 state->r.in.server_name = r->in.server_name;
1427 state->r.in.computer_name = r->in.computer_name;
1428 state->r.in.logon_level = r->in.logon_level;
1429 state->r.in.logon = r->in.logon;
1430 state->r.in.validation_level = r->in.validation_level;
1431 state->r.in.flags = &state->_ignored_flags;
1432 state->r.out.validation = r->out.validation;
1433 state->r.out.authoritative = r->out.authoritative;
1434 state->r.out.flags = &state->_ignored_flags;
1438 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1439 if (!NT_STATUS_IS_OK(nt_status)) {
1443 r->out.return_authenticator = talloc_zero(mem_ctx,
1444 struct netr_Authenticator);
1445 if (r->out.return_authenticator == NULL) {
1446 return NT_STATUS_NO_MEMORY;
1449 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1451 r->in.computer_name,
1453 r->out.return_authenticator,
1455 if (!NT_STATUS_IS_OK(nt_status)) {
1459 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1461 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1472 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1473 struct netr_LogonSamLogoff *r)
1475 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1483 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1484 struct netr_DatabaseDeltas *r)
1486 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1493 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1494 struct netr_DatabaseSync2 *r)
1496 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1497 return NT_STATUS_NOT_IMPLEMENTED;
1504 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1505 struct netr_DatabaseSync *r)
1507 struct netr_DatabaseSync2 r2;
1512 r2.in.logon_server = r->in.logon_server;
1513 r2.in.computername = r->in.computername;
1514 r2.in.credential = r->in.credential;
1515 r2.in.database_id = r->in.database_id;
1516 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1517 r2.in.sync_context = r->in.sync_context;
1518 r2.out.sync_context = r->out.sync_context;
1519 r2.out.delta_enum_array = r->out.delta_enum_array;
1520 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1522 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1531 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1532 struct netr_AccountDeltas *r)
1534 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1535 return NT_STATUS_NOT_IMPLEMENTED;
1542 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1543 struct netr_AccountSync *r)
1545 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1546 return NT_STATUS_NOT_IMPLEMENTED;
1553 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1554 struct netr_GetDcName *r)
1556 struct auth_session_info *session_info =
1557 dcesrv_call_session_info(dce_call);
1558 const char * const attrs[] = { NULL };
1559 struct ldb_context *sam_ctx;
1560 struct ldb_message **res;
1561 struct ldb_dn *domain_dn;
1566 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1567 * that the domainname needs to be a valid netbios domain
1568 * name, if it is not NULL.
1570 if (r->in.domainname) {
1571 const char *dot = strchr(r->in.domainname, '.');
1572 size_t len = strlen(r->in.domainname);
1574 if (dot || len > 15) {
1575 return WERR_NERR_DCNOTFOUND;
1579 * TODO: Should we also varify that only valid
1580 * netbios name characters are used?
1584 sam_ctx = samdb_connect(mem_ctx,
1585 dce_call->event_ctx,
1586 dce_call->conn->dce_ctx->lp_ctx,
1588 dce_call->conn->remote_address,
1590 if (sam_ctx == NULL) {
1591 return WERR_DS_UNAVAILABLE;
1594 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1596 if (domain_dn == NULL) {
1597 return WERR_NO_SUCH_DOMAIN;
1600 ret = gendb_search_dn(sam_ctx, mem_ctx,
1601 domain_dn, &res, attrs);
1603 return WERR_NO_SUCH_DOMAIN;
1606 /* TODO: - return real IP address
1607 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1609 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1610 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1611 W_ERROR_HAVE_NO_MEMORY(dcname);
1613 *r->out.dcname = dcname;
1617 struct dcesrv_netr_LogonControl_base_state {
1618 struct dcesrv_call_state *dce_call;
1620 TALLOC_CTX *mem_ctx;
1622 struct netr_LogonControl2Ex r;
1625 struct netr_LogonControl *l;
1626 struct netr_LogonControl2 *l2;
1627 struct netr_LogonControl2Ex *l2ex;
1631 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1633 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1635 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1636 struct auth_session_info *session_info =
1637 dcesrv_call_session_info(state->dce_call);
1638 enum security_user_level security_level;
1639 struct dcerpc_binding_handle *irpc_handle;
1640 struct tevent_req *subreq;
1643 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1645 if (state->_r.l != NULL) {
1649 if (state->r.in.level == 0x00000002) {
1650 return WERR_NOT_SUPPORTED;
1651 } else if (state->r.in.level != 0x00000001) {
1652 return WERR_INVALID_LEVEL;
1655 switch (state->r.in.function_code) {
1656 case NETLOGON_CONTROL_QUERY:
1657 case NETLOGON_CONTROL_REPLICATE:
1658 case NETLOGON_CONTROL_SYNCHRONIZE:
1659 case NETLOGON_CONTROL_PDC_REPLICATE:
1660 case NETLOGON_CONTROL_BREAKPOINT:
1661 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1662 case NETLOGON_CONTROL_TRUNCATE_LOG:
1665 return WERR_NOT_SUPPORTED;
1669 if (state->r.in.level < 0x00000001) {
1670 return WERR_INVALID_LEVEL;
1673 if (state->r.in.level > 0x00000004) {
1674 return WERR_INVALID_LEVEL;
1677 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1678 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1679 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1681 switch (state->r.in.level) {
1683 info1 = talloc_zero(state->mem_ctx,
1684 struct netr_NETLOGON_INFO_1);
1685 if (info1 == NULL) {
1686 return WERR_NOT_ENOUGH_MEMORY;
1688 state->r.out.query->info1 = info1;
1692 info3 = talloc_zero(state->mem_ctx,
1693 struct netr_NETLOGON_INFO_3);
1694 if (info3 == NULL) {
1695 return WERR_NOT_ENOUGH_MEMORY;
1697 state->r.out.query->info3 = info3;
1701 return WERR_INVALID_PARAMETER;
1706 * Some validations are done before the access check
1707 * and some after the access check
1709 security_level = security_session_user_level(session_info, NULL);
1710 if (security_level < SECURITY_ADMINISTRATOR) {
1711 return WERR_ACCESS_DENIED;
1714 if (state->_r.l2 != NULL) {
1716 * netr_LogonControl2
1718 if (state->r.in.level == 0x00000004) {
1719 return WERR_INVALID_LEVEL;
1723 switch (state->r.in.level) {
1728 switch (state->r.in.function_code) {
1729 case NETLOGON_CONTROL_REDISCOVER:
1730 case NETLOGON_CONTROL_TC_QUERY:
1731 case NETLOGON_CONTROL_TC_VERIFY:
1734 return WERR_INVALID_PARAMETER;
1743 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1744 return WERR_INVALID_PARAMETER;
1750 return WERR_INVALID_LEVEL;
1753 switch (state->r.in.function_code) {
1754 case NETLOGON_CONTROL_REDISCOVER:
1755 case NETLOGON_CONTROL_TC_QUERY:
1756 case NETLOGON_CONTROL_TC_VERIFY:
1757 if (state->r.in.level != 2) {
1758 return WERR_INVALID_PARAMETER;
1761 if (state->r.in.data == NULL) {
1762 return WERR_INVALID_PARAMETER;
1765 if (state->r.in.data->domain == NULL) {
1766 return WERR_INVALID_PARAMETER;
1771 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1772 if (state->r.in.level != 1) {
1773 return WERR_INVALID_PARAMETER;
1776 if (state->r.in.data == NULL) {
1777 return WERR_INVALID_PARAMETER;
1780 if (state->r.in.data->domain == NULL) {
1781 return WERR_INVALID_PARAMETER;
1784 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1785 state->r.in.data->domain);
1787 struct ldb_context *sam_ctx;
1789 sam_ctx = samdb_connect(
1791 state->dce_call->event_ctx,
1793 system_session(lp_ctx),
1794 state->dce_call->conn->remote_address,
1796 if (sam_ctx == NULL) {
1797 return WERR_DS_UNAVAILABLE;
1801 * Secrets for trusted domains can only be triggered on
1804 ok = samdb_is_pdc(sam_ctx);
1805 TALLOC_FREE(sam_ctx);
1807 return WERR_INVALID_DOMAIN_ROLE;
1813 return WERR_NOT_SUPPORTED;
1816 irpc_handle = irpc_binding_handle_by_name(state,
1817 state->dce_call->msg_ctx,
1819 &ndr_table_winbind);
1820 if (irpc_handle == NULL) {
1821 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1822 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1823 return WERR_SERVICE_NOT_FOUND;
1827 * 60 seconds timeout should be enough
1829 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1831 subreq = dcerpc_winbind_LogonControl_send(state,
1832 state->dce_call->event_ctx,
1834 state->r.in.function_code,
1837 state->r.out.query);
1838 if (subreq == NULL) {
1839 return WERR_NOT_ENOUGH_MEMORY;
1841 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1842 tevent_req_set_callback(subreq,
1843 dcesrv_netr_LogonControl_base_done,
1849 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1851 struct dcesrv_netr_LogonControl_base_state *state =
1852 tevent_req_callback_data(subreq,
1853 struct dcesrv_netr_LogonControl_base_state);
1856 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1857 &state->r.out.result);
1858 TALLOC_FREE(subreq);
1859 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1860 state->r.out.result = WERR_TIMEOUT;
1861 } else if (!NT_STATUS_IS_OK(status)) {
1862 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1863 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1864 nt_errstr(status)));
1867 if (state->_r.l2ex != NULL) {
1868 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1869 r->out.result = state->r.out.result;
1870 } else if (state->_r.l2 != NULL) {
1871 struct netr_LogonControl2 *r = state->_r.l2;
1872 r->out.result = state->r.out.result;
1873 } else if (state->_r.l != NULL) {
1874 struct netr_LogonControl *r = state->_r.l;
1875 r->out.result = state->r.out.result;
1878 status = dcesrv_reply(state->dce_call);
1879 if (!NT_STATUS_IS_OK(status)) {
1880 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1887 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1888 struct netr_LogonControl *r)
1890 struct dcesrv_netr_LogonControl_base_state *state;
1893 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1894 if (state == NULL) {
1895 return WERR_NOT_ENOUGH_MEMORY;
1898 state->dce_call = dce_call;
1899 state->mem_ctx = mem_ctx;
1901 state->r.in.logon_server = r->in.logon_server;
1902 state->r.in.function_code = r->in.function_code;
1903 state->r.in.level = r->in.level;
1904 state->r.in.data = NULL;
1905 state->r.out.query = r->out.query;
1909 werr = dcesrv_netr_LogonControl_base_call(state);
1911 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1921 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1922 struct netr_LogonControl2 *r)
1924 struct dcesrv_netr_LogonControl_base_state *state;
1927 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1928 if (state == NULL) {
1929 return WERR_NOT_ENOUGH_MEMORY;
1932 state->dce_call = dce_call;
1933 state->mem_ctx = mem_ctx;
1935 state->r.in.logon_server = r->in.logon_server;
1936 state->r.in.function_code = r->in.function_code;
1937 state->r.in.level = r->in.level;
1938 state->r.in.data = r->in.data;
1939 state->r.out.query = r->out.query;
1943 werr = dcesrv_netr_LogonControl_base_call(state);
1945 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1953 netr_LogonControl2Ex
1955 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1956 struct netr_LogonControl2Ex *r)
1958 struct dcesrv_netr_LogonControl_base_state *state;
1961 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1962 if (state == NULL) {
1963 return WERR_NOT_ENOUGH_MEMORY;
1966 state->dce_call = dce_call;
1967 state->mem_ctx = mem_ctx;
1972 werr = dcesrv_netr_LogonControl_base_call(state);
1974 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1981 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1982 struct ldb_context *sam_ctx,
1983 struct netr_DomainTrustList *trusts,
1984 uint32_t trust_flags);
1989 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1990 struct netr_GetAnyDCName *r)
1992 struct auth_session_info *session_info =
1993 dcesrv_call_session_info(dce_call);
1994 struct netr_DomainTrustList *trusts;
1995 struct ldb_context *sam_ctx;
1996 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2000 *r->out.dcname = NULL;
2002 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2003 /* if the domainname parameter wasn't set assume our domain */
2004 r->in.domainname = lpcfg_workgroup(lp_ctx);
2007 sam_ctx = samdb_connect(mem_ctx,
2008 dce_call->event_ctx,
2011 dce_call->conn->remote_address,
2013 if (sam_ctx == NULL) {
2014 return WERR_DS_UNAVAILABLE;
2017 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2018 /* well we asked for a DC of our own domain */
2019 if (samdb_is_pdc(sam_ctx)) {
2020 /* we are the PDC of the specified domain */
2021 return WERR_NO_SUCH_DOMAIN;
2024 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2025 lpcfg_netbios_name(lp_ctx));
2026 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2031 /* Okay, now we have to consider the trusted domains */
2033 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2034 W_ERROR_HAVE_NO_MEMORY(trusts);
2038 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2039 NETR_TRUST_FLAG_INBOUND
2040 | NETR_TRUST_FLAG_OUTBOUND);
2041 W_ERROR_NOT_OK_RETURN(werr);
2043 for (i = 0; i < trusts->count; i++) {
2044 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2045 /* FIXME: Here we need to find a DC for the specified
2046 * trusted domain. */
2048 /* return WERR_OK; */
2049 return WERR_NO_SUCH_DOMAIN;
2053 return WERR_NO_SUCH_DOMAIN;
2060 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2061 struct netr_DatabaseRedo *r)
2063 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2068 netr_NetrEnumerateTrustedDomains
2070 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2071 struct netr_NetrEnumerateTrustedDomains *r)
2073 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2078 netr_LogonGetCapabilities
2080 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2081 struct netr_LogonGetCapabilities *r)
2083 struct netlogon_creds_CredentialState *creds;
2086 status = dcesrv_netr_creds_server_step_check(dce_call,
2088 r->in.computer_name,
2090 r->out.return_authenticator,
2092 if (!NT_STATUS_IS_OK(status)) {
2093 DEBUG(0,(__location__ " Bad credentials - error\n"));
2095 NT_STATUS_NOT_OK_RETURN(status);
2097 if (r->in.query_level != 1) {
2098 return NT_STATUS_NOT_SUPPORTED;
2101 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2103 return NT_STATUS_OK;
2108 netr_NETRLOGONSETSERVICEBITS
2110 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2111 struct netr_NETRLOGONSETSERVICEBITS *r)
2113 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2118 netr_LogonGetTrustRid
2120 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2121 struct netr_LogonGetTrustRid *r)
2123 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2128 netr_NETRLOGONCOMPUTESERVERDIGEST
2130 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2131 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2133 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2138 netr_NETRLOGONCOMPUTECLIENTDIGEST
2140 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2141 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2143 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2151 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2152 struct netr_DsRGetSiteName *r)
2154 struct auth_session_info *session_info =
2155 dcesrv_call_session_info(dce_call);
2156 struct ldb_context *sam_ctx;
2157 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2159 sam_ctx = samdb_connect(mem_ctx,
2160 dce_call->event_ctx,
2163 dce_call->conn->remote_address,
2165 if (sam_ctx == NULL) {
2166 return WERR_DS_UNAVAILABLE;
2170 * We assume to be a DC when we get called over NETLOGON. Hence we
2171 * get our site name always by using "samdb_server_site_name()"
2172 * and not "samdb_client_site_name()".
2174 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2175 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2182 fill in a netr_OneDomainInfo from our own domain/forest
2184 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2185 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2186 struct GUID domain_guid,
2187 struct netr_OneDomainInfo *info,
2192 if (is_trust_list) {
2193 struct netr_trust_extension *tei = NULL;
2195 /* w2k8 only fills this on trusted domains */
2196 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2198 return NT_STATUS_NO_MEMORY;
2200 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2203 * We're always within a native forest
2205 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2206 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2208 /* For now we assume we're always the tree root */
2209 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2210 tei->parent_index = 0;
2212 tei->trust_type = our_tdo->trust_type;
2214 * This needs to be 0 instead of our_tdo->trust_attributes
2215 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2216 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2218 tei->trust_attributes = 0;
2220 info->trust_extension.info = tei;
2221 info->trust_extension.length = 16;
2224 if (is_trust_list) {
2225 info->dns_domainname.string = our_tdo->domain_name.string;
2227 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2228 info->dns_forestname.string = NULL;
2230 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2231 our_tdo->domain_name.string);
2232 if (info->dns_domainname.string == NULL) {
2233 return NT_STATUS_NO_MEMORY;
2236 info->dns_forestname.string = info->dns_domainname.string;
2239 info->domainname.string = our_tdo->netbios_name.string;
2240 info->domain_sid = our_tdo->sid;
2241 info->domain_guid = domain_guid;
2243 return NT_STATUS_OK;
2247 fill in a netr_OneDomainInfo from a trust tdo
2249 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2250 struct GUID domain_guid,
2251 const struct lsa_TrustDomainInfoInfoEx *tdo,
2252 struct netr_OneDomainInfo *info)
2254 struct netr_trust_extension *tei = NULL;
2258 /* w2k8 only fills this on trusted domains */
2259 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2261 return NT_STATUS_NO_MEMORY;
2264 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2265 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2267 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2268 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2270 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2271 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2275 * TODO: once we support multiple domains within our forest,
2276 * we need to fill this correct (or let the caller do it
2277 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2279 tei->parent_index = 0;
2281 tei->trust_type = tdo->trust_type;
2282 tei->trust_attributes = tdo->trust_attributes;
2284 info->trust_extension.info = tei;
2285 info->trust_extension.length = 16;
2287 info->domainname.string = tdo->netbios_name.string;
2288 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2289 info->dns_domainname.string = tdo->domain_name.string;
2291 info->dns_domainname.string = NULL;
2293 info->domain_sid = tdo->sid;
2294 info->domain_guid = domain_guid;
2296 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2297 info->dns_forestname.string = NULL;
2299 return NT_STATUS_OK;
2303 netr_LogonGetDomainInfo
2304 this is called as part of the ADS domain logon procedure.
2306 It has an important role in convaying details about the client, such
2307 as Operating System, Version, Service Pack etc.
2309 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2310 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2312 struct netlogon_creds_CredentialState *creds;
2313 const char * const trusts_attrs[] = {
2314 "securityIdentifier",
2322 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2323 "msDS-SupportedEncryptionTypes", NULL };
2324 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
2325 struct ldb_context *sam_ctx;
2326 const struct GUID *our_domain_guid = NULL;
2327 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2328 struct ldb_message **res1, *new_msg;
2329 struct ldb_result *trusts_res = NULL;
2330 struct ldb_dn *workstation_dn;
2331 struct netr_DomainInformation *domain_info;
2332 struct netr_LsaPolicyInformation *lsa_policy_info;
2333 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2334 bool update_dns_hostname = true;
2338 status = dcesrv_netr_creds_server_step_check(dce_call,
2340 r->in.computer_name,
2342 r->out.return_authenticator,
2344 if (!NT_STATUS_IS_OK(status)) {
2346 char* remote = NULL;
2347 TALLOC_CTX *frame = talloc_stackframe();
2348 remote = tsocket_address_string(dce_call->conn->remote_address,
2350 local = tsocket_address_string(dce_call->conn->local_address,
2352 DBG_ERR(("Bad credentials - "
2353 "computer[%s] remote[%s] local[%s]\n"),
2354 log_escape(frame, r->in.computer_name),
2359 NT_STATUS_NOT_OK_RETURN(status);
2361 sam_ctx = samdb_connect(mem_ctx,
2362 dce_call->event_ctx,
2363 dce_call->conn->dce_ctx->lp_ctx,
2364 system_session(dce_call->conn->dce_ctx->lp_ctx),
2365 dce_call->conn->remote_address,
2367 if (sam_ctx == NULL) {
2368 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2371 switch (r->in.level) {
2372 case 1: /* Domain information */
2374 if (r->in.query->workstation_info == NULL) {
2375 return NT_STATUS_INVALID_PARAMETER;
2378 /* Prepares the workstation DN */
2379 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2380 dom_sid_string(mem_ctx, creds->sid));
2381 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2383 /* Lookup for attributes in workstation object */
2384 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2387 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2390 /* Gets the sam account name which is checked against the DNS
2391 * hostname parameter. */
2392 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2395 if (sam_account_name == NULL) {
2396 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2400 * Checks that the sam account name without a possible "$"
2401 * matches as prefix with the DNS hostname in the workstation
2404 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2405 strcspn(sam_account_name, "$"));
2406 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2407 if (r->in.query->workstation_info->dns_hostname != NULL) {
2408 prefix2 = talloc_strndup(mem_ctx,
2409 r->in.query->workstation_info->dns_hostname,
2410 strcspn(r->in.query->workstation_info->dns_hostname, "."));
2411 NT_STATUS_HAVE_NO_MEMORY(prefix2);
2413 if (strcasecmp(prefix1, prefix2) != 0) {
2414 update_dns_hostname = false;
2417 update_dns_hostname = false;
2420 /* Gets the old DNS hostname */
2421 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2426 * Updates the DNS hostname when the client wishes that the
2427 * server should handle this for him
2428 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2429 * obviously only checked when we do already have a
2431 * See MS-NRPC section 3.5.4.3.9
2433 if ((old_dns_hostname != NULL) &&
2434 (r->in.query->workstation_info->workstation_flags
2435 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2436 update_dns_hostname = false;
2439 /* Gets host information and put them into our directory */
2441 new_msg = ldb_msg_new(mem_ctx);
2442 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2444 new_msg->dn = workstation_dn;
2446 /* Sets the OS name */
2448 if (r->in.query->workstation_info->os_name.string == NULL) {
2449 return NT_STATUS_INVALID_PARAMETER;
2452 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2453 r->in.query->workstation_info->os_name.string);
2454 if (ret != LDB_SUCCESS) {
2455 return NT_STATUS_NO_MEMORY;
2459 * Sets information from "os_version". On an empty structure
2460 * the values are cleared.
2462 if (r->in.query->workstation_info->os_version.os != NULL) {
2463 struct netr_OsVersionInfoEx *os_version;
2464 const char *os_version_str;
2466 os_version = &r->in.query->workstation_info->os_version.os->os;
2468 if (os_version->CSDVersion == NULL) {
2469 return NT_STATUS_INVALID_PARAMETER;
2472 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2473 os_version->MajorVersion,
2474 os_version->MinorVersion,
2475 os_version->BuildNumber);
2476 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2478 ret = ldb_msg_add_string(new_msg,
2479 "operatingSystemServicePack",
2480 os_version->CSDVersion);
2481 if (ret != LDB_SUCCESS) {
2482 return NT_STATUS_NO_MEMORY;
2485 ret = ldb_msg_add_string(new_msg,
2486 "operatingSystemVersion",
2488 if (ret != LDB_SUCCESS) {
2489 return NT_STATUS_NO_MEMORY;
2492 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2493 "operatingSystemServicePack");
2494 if (ret != LDB_SUCCESS) {
2495 return NT_STATUS_NO_MEMORY;
2498 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2499 "operatingSystemVersion");
2500 if (ret != LDB_SUCCESS) {
2501 return NT_STATUS_NO_MEMORY;
2506 * If the boolean "update_dns_hostname" remained true, then we
2507 * are fine to start the update.
2509 if (update_dns_hostname) {
2510 ret = ldb_msg_add_string(new_msg,
2512 r->in.query->workstation_info->dns_hostname);
2513 if (ret != LDB_SUCCESS) {
2514 return NT_STATUS_NO_MEMORY;
2517 /* This manual "servicePrincipalName" generation is
2518 * still needed! Since the update in the samldb LDB
2519 * module does only work if the entries already exist
2520 * which isn't always the case. */
2521 ret = ldb_msg_add_string(new_msg,
2522 "servicePrincipalName",
2523 talloc_asprintf(new_msg, "HOST/%s",
2524 r->in.computer_name));
2525 if (ret != LDB_SUCCESS) {
2526 return NT_STATUS_NO_MEMORY;
2529 ret = ldb_msg_add_string(new_msg,
2530 "servicePrincipalName",
2531 talloc_asprintf(new_msg, "HOST/%s",
2532 r->in.query->workstation_info->dns_hostname));
2533 if (ret != LDB_SUCCESS) {
2534 return NT_STATUS_NO_MEMORY;
2538 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2539 DEBUG(3,("Impossible to update samdb: %s\n",
2540 ldb_errstring(sam_ctx)));
2543 talloc_free(new_msg);
2545 /* Writes back the domain information */
2547 our_domain_guid = samdb_domain_guid(sam_ctx);
2548 if (our_domain_guid == NULL) {
2549 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2552 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2553 if (!NT_STATUS_IS_OK(status)) {
2557 status = dsdb_trust_search_tdos(sam_ctx,
2562 if (!NT_STATUS_IS_OK(status)) {
2566 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2567 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2569 ZERO_STRUCTP(domain_info);
2571 /* Informations about the local and trusted domains */
2573 status = fill_our_one_domain_info(mem_ctx,
2576 &domain_info->primary_domain,
2578 if (!NT_STATUS_IS_OK(status)) {
2582 domain_info->trusted_domain_count = trusts_res->count + 1;
2583 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2584 struct netr_OneDomainInfo,
2585 domain_info->trusted_domain_count);
2586 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2588 for (i=0; i < trusts_res->count; i++) {
2589 struct netr_OneDomainInfo *o =
2590 &domain_info->trusted_domains[i];
2591 /* we can't know the guid of trusts outside our forest */
2592 struct GUID trust_domain_guid = GUID_zero();
2593 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2595 status = dsdb_trust_parse_tdo_info(mem_ctx,
2596 trusts_res->msgs[i],
2598 if (!NT_STATUS_IS_OK(status)) {
2602 status = fill_trust_one_domain_info(mem_ctx,
2606 if (!NT_STATUS_IS_OK(status)) {
2611 status = fill_our_one_domain_info(mem_ctx,
2614 &domain_info->trusted_domains[i],
2616 if (!NT_STATUS_IS_OK(status)) {
2620 /* Sets the supported encryption types */
2621 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2622 "msDS-SupportedEncryptionTypes",
2623 default_supported_enc_types);
2625 /* Other host domain information */
2627 lsa_policy_info = talloc(mem_ctx,
2628 struct netr_LsaPolicyInformation);
2629 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2630 ZERO_STRUCTP(lsa_policy_info);
2632 domain_info->lsa_policy = *lsa_policy_info;
2634 /* The DNS hostname is only returned back when there is a chance
2636 if ((r->in.query->workstation_info->workstation_flags
2637 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2638 domain_info->dns_hostname.string = old_dns_hostname;
2640 domain_info->dns_hostname.string = NULL;
2643 domain_info->workstation_flags =
2644 r->in.query->workstation_info->workstation_flags & (
2645 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2647 r->out.info->domain_info = domain_info;
2649 case 2: /* LSA policy information - not used at the moment */
2650 lsa_policy_info = talloc(mem_ctx,
2651 struct netr_LsaPolicyInformation);
2652 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2653 ZERO_STRUCTP(lsa_policy_info);
2655 r->out.info->lsa_policy_info = lsa_policy_info;
2658 return NT_STATUS_INVALID_LEVEL;
2662 return NT_STATUS_OK;
2667 netr_ServerPasswordGet
2669 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2670 struct netr_ServerPasswordGet *r)
2672 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2675 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2676 TALLOC_CTX *mem_ctx,
2677 struct dom_sid *user_sid,
2678 struct ldb_dn *obj_dn)
2680 const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
2681 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2682 struct ldb_dn *rodc_dn;
2684 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2685 const struct dom_sid *additional_sids[] = { NULL, NULL };
2687 struct dom_sid *object_sid;
2688 const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
2690 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2691 dom_sid_string(mem_ctx, user_sid));
2692 if (!ldb_dn_validate(rodc_dn)) goto denied;
2694 /* do the two searches we need */
2695 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2696 DSDB_SEARCH_SHOW_EXTENDED_DN);
2697 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2699 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2700 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2702 object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
2704 additional_sids[0] = object_sid;
2706 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2707 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
2708 if (!W_ERROR_IS_OK(werr)) {
2712 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2713 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
2714 if (!W_ERROR_IS_OK(werr)) {
2719 * The SID list needs to include itself as well as the tokenGroups.
2721 * TODO determine if sIDHistory is required for this check
2723 werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
2724 mem_ctx, "tokenGroups", &token_sids,
2725 additional_sids, 1);
2726 if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
2730 if (never_reveal_sids &&
2731 sid_list_match(token_sids, never_reveal_sids)) {
2736 sid_list_match(token_sids, reveal_sids)) {
2748 netr_NetrLogonSendToSam
2750 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2751 struct netr_NetrLogonSendToSam *r)
2753 struct netlogon_creds_CredentialState *creds;
2754 struct ldb_context *sam_ctx;
2756 DATA_BLOB decrypted_blob;
2757 enum ndr_err_code ndr_err;
2758 struct netr_SendToSamBase base_msg = { 0 };
2760 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2762 r->in.computer_name,
2764 r->out.return_authenticator,
2767 NT_STATUS_NOT_OK_RETURN(nt_status);
2769 switch (creds->secure_channel_type) {
2773 case SEC_CHAN_WKSTA:
2774 case SEC_CHAN_DNS_DOMAIN:
2775 case SEC_CHAN_DOMAIN:
2777 return NT_STATUS_INVALID_PARAMETER;
2779 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
2780 creds->secure_channel_type));
2781 return NT_STATUS_INVALID_PARAMETER;
2784 sam_ctx = samdb_connect(mem_ctx,
2785 dce_call->event_ctx,
2786 dce_call->conn->dce_ctx->lp_ctx,
2787 system_session(dce_call->conn->dce_ctx->lp_ctx),
2788 dce_call->conn->remote_address,
2790 if (sam_ctx == NULL) {
2791 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2794 /* Buffer is meant to be 16-bit aligned */
2795 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2796 netlogon_creds_aes_decrypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2798 netlogon_creds_arcfour_crypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2801 decrypted_blob.data = r->in.opaque_buffer;
2802 decrypted_blob.length = r->in.buffer_len;
2804 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
2805 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
2807 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2808 /* We only partially implement SendToSam */
2809 return NT_STATUS_NOT_IMPLEMENTED;
2812 /* Now 'send' to SAM */
2813 switch (base_msg.message_type) {
2814 case SendToSamResetBadPasswordCount:
2816 struct ldb_message *msg = ldb_msg_new(mem_ctx);
2817 struct ldb_dn *dn = NULL;
2821 ret = ldb_transaction_start(sam_ctx);
2822 if (ret != LDB_SUCCESS) {
2823 return NT_STATUS_INTERNAL_ERROR;
2826 ret = dsdb_find_dn_by_guid(sam_ctx,
2828 &base_msg.message.reset_bad_password.guid,
2831 if (ret != LDB_SUCCESS) {
2832 ldb_transaction_cancel(sam_ctx);
2833 return NT_STATUS_INVALID_PARAMETER;
2836 if (creds->secure_channel_type == SEC_CHAN_RODC &&
2837 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
2838 DEBUG(1, ("Client asked to reset bad password on "
2839 "an arbitrary user: %s\n",
2840 ldb_dn_get_linearized(dn)));
2841 ldb_transaction_cancel(sam_ctx);
2842 return NT_STATUS_INVALID_PARAMETER;
2847 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
2848 if (ret != LDB_SUCCESS) {
2849 ldb_transaction_cancel(sam_ctx);
2850 return NT_STATUS_INVALID_PARAMETER;
2853 ret = dsdb_replace(sam_ctx, msg, 0);
2854 if (ret != LDB_SUCCESS) {
2855 ldb_transaction_cancel(sam_ctx);
2856 return NT_STATUS_INVALID_PARAMETER;
2859 ret = ldb_transaction_commit(sam_ctx);
2860 if (ret != LDB_SUCCESS) {
2861 ldb_transaction_cancel(sam_ctx);
2862 return NT_STATUS_INTERNAL_ERROR;
2868 return NT_STATUS_NOT_IMPLEMENTED;
2871 return NT_STATUS_OK;
2874 struct dcesrv_netr_DsRGetDCName_base_state {
2875 struct dcesrv_call_state *dce_call;
2876 TALLOC_CTX *mem_ctx;
2878 struct netr_DsRGetDCNameEx2 r;
2879 const char *client_site;
2882 struct netr_DsRGetDCName *dc;
2883 struct netr_DsRGetDCNameEx *dcex;
2884 struct netr_DsRGetDCNameEx2 *dcex2;
2888 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
2890 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
2892 struct dcesrv_call_state *dce_call = state->dce_call;
2893 struct auth_session_info *session_info =
2894 dcesrv_call_session_info(dce_call);
2895 TALLOC_CTX *mem_ctx = state->mem_ctx;
2896 struct netr_DsRGetDCNameEx2 *r = &state->r;
2897 struct ldb_context *sam_ctx;
2898 struct netr_DsRGetDCNameInfo *info;
2899 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2900 const struct tsocket_address *local_address;
2901 char *local_addr = NULL;
2902 const struct tsocket_address *remote_address;
2903 char *remote_addr = NULL;
2904 const char *server_site_name;
2906 struct netlogon_samlogon_response response;
2908 const char *dc_name = NULL;
2909 const char *domain_name = NULL;
2911 bool different_domain = true;
2913 ZERO_STRUCTP(r->out.info);
2915 sam_ctx = samdb_connect(state,
2916 dce_call->event_ctx,
2919 dce_call->conn->remote_address,
2921 if (sam_ctx == NULL) {
2922 return WERR_DS_UNAVAILABLE;
2925 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2926 if (tsocket_address_is_inet(local_address, "ip")) {
2927 local_addr = tsocket_address_inet_addr_string(local_address, state);
2928 W_ERROR_HAVE_NO_MEMORY(local_addr);
2931 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2932 if (tsocket_address_is_inet(remote_address, "ip")) {
2933 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
2934 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2937 /* "server_unc" is ignored by w2k3 */
2939 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2940 return WERR_INVALID_FLAGS;
2943 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2944 r->in.flags & DS_PDC_REQUIRED &&
2945 r->in.flags & DS_KDC_REQUIRED) {
2946 return WERR_INVALID_FLAGS;
2948 if (r->in.flags & DS_IS_FLAT_NAME &&
2949 r->in.flags & DS_IS_DNS_NAME) {
2950 return WERR_INVALID_FLAGS;
2952 if (r->in.flags & DS_RETURN_DNS_NAME &&
2953 r->in.flags & DS_RETURN_FLAT_NAME) {
2954 return WERR_INVALID_FLAGS;
2956 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2957 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2958 return WERR_INVALID_FLAGS;
2961 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2963 (DS_DIRECTORY_SERVICE_REQUIRED |
2964 DS_DIRECTORY_SERVICE_PREFERRED |
2965 DS_GC_SERVER_REQUIRED |
2968 return WERR_INVALID_FLAGS;
2971 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2973 return WERR_INVALID_FLAGS;
2977 * If we send an all-zero GUID, we should ignore it as winbind actually
2978 * checks it with a DNS query. Windows also appears to ignore it.
2980 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
2981 r->in.domain_guid = NULL;
2984 /* Attempt winbind search only if we suspect the domain is incorrect */
2985 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
2986 if (r->in.flags & DS_IS_FLAT_NAME) {
2987 if (strcasecmp_m(r->in.domain_name,
2988 lpcfg_sam_name(lp_ctx)) == 0) {
2989 different_domain = false;
2991 } else if (r->in.flags & DS_IS_DNS_NAME) {
2992 if (strcasecmp_m(r->in.domain_name,
2993 lpcfg_dnsdomain(lp_ctx)) == 0) {
2994 different_domain = false;
2997 if (strcasecmp_m(r->in.domain_name,
2998 lpcfg_sam_name(lp_ctx)) == 0 ||
2999 strcasecmp_m(r->in.domain_name,
3000 lpcfg_dnsdomain(lp_ctx)) == 0) {
3001 different_domain = false;
3006 * We need to be able to handle empty domain names, where we
3007 * revert to our domain by default.
3009 different_domain = false;
3012 /* Proof server site parameter "site_name" if it was specified */
3013 server_site_name = samdb_server_site_name(sam_ctx, state);
3014 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3015 if (different_domain || (r->in.site_name != NULL &&
3016 (strcasecmp_m(r->in.site_name,
3017 server_site_name) != 0))) {
3019 struct dcerpc_binding_handle *irpc_handle = NULL;
3020 struct tevent_req *subreq = NULL;
3023 * Retrieve the client site to override the winbind response.
3025 * DO NOT use Windows fallback for client site.
3026 * In the case of multiple domains, this is plainly wrong.
3028 * Note: It's possible that the client may belong to multiple
3029 * subnets across domains. It's not clear what this would mean,
3030 * but here we only return what this domain knows.
3032 state->client_site = samdb_client_site_name(sam_ctx,
3038 irpc_handle = irpc_binding_handle_by_name(state,
3041 &ndr_table_winbind);
3042 if (irpc_handle == NULL) {
3043 DEBUG(0,("Failed to get binding_handle for "
3044 "winbind_server task\n"));
3045 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3046 return WERR_SERVICE_NOT_FOUND;
3049 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3051 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3053 subreq = dcerpc_wbint_DsGetDcName_send(state,
3054 dce_call->event_ctx,
3061 if (subreq == NULL) {
3062 return WERR_NOT_ENOUGH_MEMORY;
3065 tevent_req_set_callback(subreq,
3066 dcesrv_netr_DsRGetDCName_base_done,
3072 guid_str = r->in.domain_guid != NULL ?
3073 GUID_string(state, r->in.domain_guid) : NULL;
3075 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3079 r->in.client_account,
3080 r->in.mask, remote_addr,
3081 NETLOGON_NT_VERSION_5EX_WITH_IP,
3082 lp_ctx, &response, true);
3083 if (!NT_STATUS_IS_OK(status)) {
3084 return ntstatus_to_werror(status);
3088 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3089 * (O) flag when the returned forest name is in DNS format. This is here
3090 * always the case (see below).
3092 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3094 if (r->in.flags & DS_RETURN_DNS_NAME) {
3095 dc_name = response.data.nt5_ex.pdc_dns_name;
3096 domain_name = response.data.nt5_ex.dns_domain;
3098 * According to MS-NRPC 2.2.1.2.1 we should set the
3099 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3100 * the returned information is in DNS form.
3102 response.data.nt5_ex.server_type |=
3103 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3104 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3105 dc_name = response.data.nt5_ex.pdc_name;
3106 domain_name = response.data.nt5_ex.domain_name;
3110 * TODO: autodetect what we need to return
3111 * based on the given arguments
3113 dc_name = response.data.nt5_ex.pdc_name;
3114 domain_name = response.data.nt5_ex.domain_name;
3117 if (!dc_name || !dc_name[0]) {
3118 return WERR_NO_SUCH_DOMAIN;
3121 if (!domain_name || !domain_name[0]) {
3122 return WERR_NO_SUCH_DOMAIN;
3125 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3126 W_ERROR_HAVE_NO_MEMORY(info);
3127 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3128 dc_name[0] != '\\'? "\\\\":"",
3129 talloc_strdup(mem_ctx, dc_name));
3130 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3132 pdc_ip = local_addr;
3133 if (pdc_ip == NULL) {
3134 pdc_ip = "127.0.0.1";
3136 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3137 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3138 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3139 info->domain_guid = response.data.nt5_ex.domain_uuid;
3140 info->domain_name = domain_name;
3141 info->forest_name = response.data.nt5_ex.forest;
3142 info->dc_flags = response.data.nt5_ex.server_type;
3143 if (r->in.flags & DS_RETURN_DNS_NAME) {
3144 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3145 * returned if we are returning info->dc_unc containing a FQDN.
3146 * This attribute is called DomainControllerName in the specs,
3147 * it seems that we decide to return FQDN or netbios depending on
3148 * DS_RETURN_DNS_NAME.
3150 info->dc_flags |= DS_DNS_CONTROLLER;
3152 info->dc_site_name = response.data.nt5_ex.server_site;
3153 info->client_site_name = response.data.nt5_ex.client_site;
3155 *r->out.info = info;
3160 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3162 struct dcesrv_netr_DsRGetDCName_base_state *state =
3163 tevent_req_callback_data(subreq,
3164 struct dcesrv_netr_DsRGetDCName_base_state);
3165 struct dcesrv_call_state *dce_call = state->dce_call;
3166 NTSTATUS result, status;
3168 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3171 TALLOC_FREE(subreq);
3173 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3174 state->r.out.result = WERR_TIMEOUT;
3178 if (!NT_STATUS_IS_OK(status)) {
3179 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3181 state->r.out.result = WERR_GEN_FAILURE;
3185 if (!NT_STATUS_IS_OK(result)) {
3186 DBG_NOTICE("DC location via winbind failed - %s\n",
3188 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3192 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3193 DBG_ERR("DC location via winbind returned no results\n");
3194 state->r.out.result = WERR_GEN_FAILURE;
3198 if (state->r.out.info[0]->dc_unc == NULL) {
3199 DBG_ERR("DC location via winbind returned no DC unc\n");
3200 state->r.out.result = WERR_GEN_FAILURE;
3205 * Either the supplied site name is NULL (possibly via
3206 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3207 * the input match name.
3209 * TODO: Currently this means that requests with NETBIOS domain
3210 * names can fail because they do not return the site name.
3212 if (state->r.in.site_name == NULL ||
3213 strcasecmp_m("", state->r.in.site_name) == 0 ||
3214 (state->r.out.info[0]->dc_site_name != NULL &&
3215 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3216 state->r.in.site_name) == 0)) {
3218 state->r.out.info[0]->client_site_name =
3219 talloc_move(state->mem_ctx, &state->client_site);
3222 * Make sure to return our DC UNC with // prefix.
3223 * Winbind currently doesn't send the leading slashes
3226 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3227 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3228 const char *dc_unc = NULL;
3230 dc_unc = talloc_asprintf(state->mem_ctx,
3232 state->r.out.info[0]->dc_unc);
3233 state->r.out.info[0]->dc_unc = dc_unc;
3236 state->r.out.result = WERR_OK;
3238 state->r.out.info = NULL;
3239 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3243 if (state->_r.dcex2 != NULL) {
3244 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3245 r->out.result = state->r.out.result;
3246 } else if (state->_r.dcex != NULL) {
3247 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3248 r->out.result = state->r.out.result;
3249 } else if (state->_r.dc != NULL) {
3250 struct netr_DsRGetDCName *r = state->_r.dc;
3251 r->out.result = state->r.out.result;
3255 status = dcesrv_reply(dce_call);
3256 if (!NT_STATUS_IS_OK(status)) {
3257 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3258 nt_errstr(status)));
3263 netr_DsRGetDCNameEx2
3265 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3266 TALLOC_CTX *mem_ctx,
3267 struct netr_DsRGetDCNameEx2 *r)
3269 struct dcesrv_netr_DsRGetDCName_base_state *state;
3271 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3272 if (state == NULL) {
3273 return WERR_NOT_ENOUGH_MEMORY;
3276 state->dce_call = dce_call;
3277 state->mem_ctx = mem_ctx;
3280 state->_r.dcex2 = r;
3282 return dcesrv_netr_DsRGetDCName_base_call(state);
3288 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3289 struct netr_DsRGetDCNameEx *r)
3291 struct dcesrv_netr_DsRGetDCName_base_state *state;
3293 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3294 if (state == NULL) {
3295 return WERR_NOT_ENOUGH_MEMORY;
3298 state->dce_call = dce_call;
3299 state->mem_ctx = mem_ctx;
3301 state->r.in.server_unc = r->in.server_unc;
3302 state->r.in.client_account = NULL;
3303 state->r.in.mask = 0;
3304 state->r.in.domain_guid = r->in.domain_guid;
3305 state->r.in.domain_name = r->in.domain_name;
3306 state->r.in.site_name = r->in.site_name;
3307 state->r.in.flags = r->in.flags;
3308 state->r.out.info = r->out.info;
3312 return dcesrv_netr_DsRGetDCName_base_call(state);
3318 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3319 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3320 * insists that it be ignored.
3322 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3323 struct netr_DsRGetDCName *r)
3325 struct dcesrv_netr_DsRGetDCName_base_state *state;
3327 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3328 if (state == NULL) {
3329 return WERR_NOT_ENOUGH_MEMORY;
3332 state->dce_call = dce_call;
3333 state->mem_ctx = mem_ctx;
3335 state->r.in.server_unc = r->in.server_unc;
3336 state->r.in.client_account = NULL;
3337 state->r.in.mask = 0;
3338 state->r.in.domain_name = r->in.domain_name;
3339 state->r.in.domain_guid = r->in.domain_guid;
3341 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3342 state->r.in.flags = r->in.flags;
3343 state->r.out.info = r->out.info;
3347 return dcesrv_netr_DsRGetDCName_base_call(state);
3350 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3352 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3353 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3355 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3360 netr_NetrEnumerateTrustedDomainsEx
3362 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3363 struct netr_NetrEnumerateTrustedDomainsEx *r)
3365 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3370 netr_DsRAddressToSitenamesExW
3372 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3373 struct netr_DsRAddressToSitenamesExW *r)
3375 struct auth_session_info *session_info =
3376 dcesrv_call_session_info(dce_call);
3377 struct ldb_context *sam_ctx;
3378 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3379 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3380 sa_family_t sin_family;
3381 struct sockaddr_in *addr;
3383 struct sockaddr_in6 *addr6;
3384 char addr_str[INET6_ADDRSTRLEN];
3386 char addr_str[INET_ADDRSTRLEN];
3392 sam_ctx = samdb_connect(mem_ctx,
3393 dce_call->event_ctx,
3396 dce_call->conn->remote_address,
3398 if (sam_ctx == NULL) {
3399 return WERR_DS_UNAVAILABLE;
3402 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3403 W_ERROR_HAVE_NO_MEMORY(ctr);
3407 ctr->count = r->in.count;
3408 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3409 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3410 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3411 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3413 for (i=0; i<ctr->count; i++) {
3414 ctr->sitename[i].string = NULL;
3415 ctr->subnetname[i].string = NULL;
3417 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3420 /* The first two byte of the buffer are reserved for the
3421 * "sin_family" but for now only the first one is used. */
3422 sin_family = r->in.addresses[i].buffer[0];
3424 switch (sin_family) {
3426 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3429 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3430 res = inet_ntop(AF_INET, &addr->sin_addr,
3431 addr_str, sizeof(addr_str));
3435 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3438 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3439 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3440 addr_str, sizeof(addr_str));
3451 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3456 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3457 ctr->subnetname[i].string = subnet_name;
3465 netr_DsRAddressToSitenamesW
3467 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3468 struct netr_DsRAddressToSitenamesW *r)
3470 struct netr_DsRAddressToSitenamesExW r2;
3471 struct netr_DsRAddressToSitenamesWCtr *ctr;
3477 r2.in.server_name = r->in.server_name;
3478 r2.in.count = r->in.count;
3479 r2.in.addresses = r->in.addresses;
3481 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3482 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3484 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3485 W_ERROR_HAVE_NO_MEMORY(ctr);
3489 ctr->count = r->in.count;
3490 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3491 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3493 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3495 for (i=0; i<ctr->count; i++) {
3496 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3504 netr_DsrGetDcSiteCoverageW
3506 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3507 struct netr_DsrGetDcSiteCoverageW *r)
3509 struct auth_session_info *session_info =
3510 dcesrv_call_session_info(dce_call);
3511 struct ldb_context *sam_ctx;
3512 struct DcSitesCtr *ctr;
3513 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3515 sam_ctx = samdb_connect(mem_ctx,
3516 dce_call->event_ctx,
3519 dce_call->conn->remote_address,
3521 if (sam_ctx == NULL) {
3522 return WERR_DS_UNAVAILABLE;
3525 ctr = talloc(mem_ctx, struct DcSitesCtr);
3526 W_ERROR_HAVE_NO_MEMORY(ctr);
3530 /* For now only return our default site */
3532 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3533 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3534 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3535 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3541 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3542 struct ldb_context *sam_ctx,
3543 struct netr_DomainTrustList *trusts,
3544 uint32_t trust_flags)
3546 struct ldb_dn *system_dn;
3547 struct ldb_message **dom_res = NULL;
3548 const char *trust_attrs[] = { "flatname", "trustPartner",
3549 "securityIdentifier", "trustDirection",
3550 "trustType", "trustAttributes", NULL };
3555 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3556 NETR_TRUST_FLAG_OUTBOUND))) {
3557 return WERR_INVALID_FLAGS;
3560 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3561 ldb_get_default_basedn(sam_ctx),
3562 "(&(objectClass=container)(cn=System))");
3564 return WERR_GEN_FAILURE;
3567 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3568 &dom_res, trust_attrs,
3569 "(objectclass=trustedDomain)");
3571 for (i = 0; i < ret; i++) {
3572 unsigned int trust_dir;
3575 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3576 "trustDirection", 0);
3578 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3579 flags |= NETR_TRUST_FLAG_INBOUND;
3581 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3582 flags |= NETR_TRUST_FLAG_OUTBOUND;
3585 if (!(flags & trust_flags)) {
3586 /* this trust direction was not requested */
3591 trusts->array = talloc_realloc(trusts, trusts->array,
3592 struct netr_DomainTrust,
3594 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3596 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3597 if (!trusts->array[n].netbios_name) {
3598 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3599 "without flatname\n",
3600 ldb_dn_get_linearized(dom_res[i]->dn)));
3603 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3605 trusts->array[n].trust_flags = flags;
3606 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3607 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3608 /* TODO: find if we have parent in the list */
3609 trusts->array[n].parent_index = 0;
3612 trusts->array[n].trust_type =
3613 ldb_msg_find_attr_as_uint(dom_res[i],
3615 trusts->array[n].trust_attributes =
3616 ldb_msg_find_attr_as_uint(dom_res[i],
3617 "trustAttributes", 0);
3619 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3620 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3621 struct dom_sid zero_sid;
3622 ZERO_STRUCT(zero_sid);
3623 trusts->array[n].sid =
3624 dom_sid_dup(trusts, &zero_sid);
3626 trusts->array[n].sid =
3627 samdb_result_dom_sid(trusts, dom_res[i],
3628 "securityIdentifier");
3630 trusts->array[n].guid = GUID_zero();
3632 trusts->count = n + 1;
3635 talloc_free(dom_res);
3640 netr_DsrEnumerateDomainTrusts
3642 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3643 TALLOC_CTX *mem_ctx,
3644 struct netr_DsrEnumerateDomainTrusts *r)
3646 struct auth_session_info *session_info =
3647 dcesrv_call_session_info(dce_call);
3648 struct netr_DomainTrustList *trusts;
3649 struct ldb_context *sam_ctx;
3651 struct ldb_message **dom_res;
3652 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3653 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3654 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3658 if (r->in.trust_flags & 0xFFFFFE00) {
3659 return WERR_INVALID_FLAGS;
3662 /* TODO: turn to hard check once we are sure this is 100% correct */
3663 if (!r->in.server_name) {
3664 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3665 "But received NULL!\n", dnsdomain));
3667 p = strchr(r->in.server_name, '.');
3669 DEBUG(3, ("Invalid domain! Expected name in domain "
3670 "[%s]. But received [%s]!\n",
3671 dnsdomain, r->in.server_name));
3672 p = r->in.server_name;
3676 if (strcasecmp(p, dnsdomain)) {
3677 DEBUG(3, ("Invalid domain! Expected name in domain "
3678 "[%s]. But received [%s]!\n",
3679 dnsdomain, r->in.server_name));
3683 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3684 W_ERROR_HAVE_NO_MEMORY(trusts);
3687 r->out.trusts = trusts;
3689 sam_ctx = samdb_connect(mem_ctx,
3690 dce_call->event_ctx,
3693 dce_call->conn->remote_address,
3695 if (sam_ctx == NULL) {
3696 return WERR_GEN_FAILURE;
3699 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3700 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3702 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3703 trusts, r->in.trust_flags);
3704 W_ERROR_NOT_OK_RETURN(werr);
3707 /* NOTE: we currently are always the root of the forest */
3708 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3709 uint32_t n = trusts->count;
3711 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3712 &dom_res, dom_attrs);
3714 return WERR_GEN_FAILURE;
3717 trusts->count = n + 1;
3718 trusts->array = talloc_realloc(trusts, trusts->array,
3719 struct netr_DomainTrust,
3721 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3723 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3724 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3725 trusts->array[n].trust_flags =
3726 NETR_TRUST_FLAG_NATIVE |
3727 NETR_TRUST_FLAG_TREEROOT |
3728 NETR_TRUST_FLAG_IN_FOREST |
3729 NETR_TRUST_FLAG_PRIMARY;
3730 /* we are always the root domain for now */
3731 trusts->array[n].parent_index = 0;
3732 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3733 trusts->array[n].trust_attributes = 0;
3734 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3737 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3739 talloc_free(dom_res);
3747 netr_DsrDeregisterDNSHostRecords
3749 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3750 struct netr_DsrDeregisterDNSHostRecords *r)
3752 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3756 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3757 struct netr_ServerGetTrustInfo *r);
3760 netr_ServerTrustPasswordsGet
3762 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3763 struct netr_ServerTrustPasswordsGet *r)
3765 struct netr_ServerGetTrustInfo r2 = {};
3766 struct netr_TrustInfo *_ti = NULL;
3769 r2.in.server_name = r->in.server_name;
3770 r2.in.account_name = r->in.account_name;
3771 r2.in.secure_channel_type = r->in.secure_channel_type;
3772 r2.in.computer_name = r->in.computer_name;
3773 r2.in.credential = r->in.credential;
3775 r2.out.return_authenticator = r->out.return_authenticator;
3776 r2.out.new_owf_password = r->out.new_owf_password;
3777 r2.out.old_owf_password = r->out.old_owf_password;
3778 r2.out.trust_info = &_ti;
3780 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3782 r->out.return_authenticator = r2.out.return_authenticator;
3783 r->out.new_owf_password = r2.out.new_owf_password;
3784 r->out.old_owf_password = r2.out.old_owf_password;
3790 netr_DsRGetForestTrustInformation
3792 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3793 struct dcesrv_call_state *dce_call;
3794 TALLOC_CTX *mem_ctx;
3795 struct netr_DsRGetForestTrustInformation *r;
3798 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3800 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3801 TALLOC_CTX *mem_ctx,
3802 struct netr_DsRGetForestTrustInformation *r)
3804 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3805 struct auth_session_info *session_info =
3806 dcesrv_call_session_info(dce_call);
3807 enum security_user_level security_level;
3808 struct ldb_context *sam_ctx = NULL;
3809 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3810 struct dcerpc_binding_handle *irpc_handle = NULL;
3811 struct tevent_req *subreq = NULL;
3812 struct ldb_dn *domain_dn = NULL;
3813 struct ldb_dn *forest_dn = NULL;
3817 security_level = security_session_user_level(session_info, NULL);
3818 if (security_level < SECURITY_USER) {
3819 return WERR_ACCESS_DENIED;
3822 if (r->in.flags & 0xFFFFFFFE) {
3823 return WERR_INVALID_FLAGS;
3826 sam_ctx = samdb_connect(mem_ctx,
3827 dce_call->event_ctx,
3830 dce_call->conn->remote_address,
3832 if (sam_ctx == NULL) {
3833 return WERR_GEN_FAILURE;
3836 domain_dn = ldb_get_default_basedn(sam_ctx);
3837 if (domain_dn == NULL) {
3838 return WERR_GEN_FAILURE;
3841 forest_dn = ldb_get_root_basedn(sam_ctx);
3842 if (forest_dn == NULL) {
3843 return WERR_GEN_FAILURE;
3846 cmp = ldb_dn_compare(domain_dn, forest_dn);
3848 return WERR_NERR_ACFNOTLOADED;
3851 forest_level = dsdb_forest_functional_level(sam_ctx);
3852 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3853 return WERR_INVALID_FUNCTION;
3856 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3857 if (!samdb_is_pdc(sam_ctx)) {
3858 return WERR_NERR_NOTPRIMARY;
3861 if (r->in.trusted_domain_name == NULL) {
3862 return WERR_INVALID_FLAGS;
3866 if (r->in.trusted_domain_name == NULL) {
3870 * information about our own domain
3872 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3873 r->out.forest_trust_info);
3874 if (!NT_STATUS_IS_OK(status)) {
3875 return ntstatus_to_werror(status);
3882 * Forward the request to winbindd
3885 state = talloc_zero(mem_ctx,
3886 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3887 if (state == NULL) {
3888 return WERR_NOT_ENOUGH_MEMORY;
3890 state->dce_call = dce_call;
3891 state->mem_ctx = mem_ctx;
3894 irpc_handle = irpc_binding_handle_by_name(state,
3895 state->dce_call->msg_ctx,
3897 &ndr_table_winbind);
3898 if (irpc_handle == NULL) {
3899 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3900 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3901 return WERR_SERVICE_NOT_FOUND;
3905 * 60 seconds timeout should be enough
3907 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3909 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3910 state->dce_call->event_ctx,
3912 r->in.trusted_domain_name,
3914 r->out.forest_trust_info);
3915 if (subreq == NULL) {
3916 return WERR_NOT_ENOUGH_MEMORY;
3918 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3919 tevent_req_set_callback(subreq,
3920 dcesrv_netr_DsRGetForestTrustInformation_done,
3926 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3928 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3929 tevent_req_callback_data(subreq,
3930 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3933 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3935 &state->r->out.result);
3936 TALLOC_FREE(subreq);
3937 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3938 state->r->out.result = WERR_TIMEOUT;
3939 } else if (!NT_STATUS_IS_OK(status)) {
3940 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3941 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3942 nt_errstr(status)));
3945 status = dcesrv_reply(state->dce_call);
3946 if (!NT_STATUS_IS_OK(status)) {
3947 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3952 netr_GetForestTrustInformation
3954 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3955 TALLOC_CTX *mem_ctx,
3956 struct netr_GetForestTrustInformation *r)
3958 struct auth_session_info *session_info =
3959 dcesrv_call_session_info(dce_call);
3960 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3961 struct netlogon_creds_CredentialState *creds = NULL;
3962 struct ldb_context *sam_ctx = NULL;
3963 struct ldb_dn *domain_dn = NULL;
3964 struct ldb_dn *forest_dn = NULL;
3969 status = dcesrv_netr_creds_server_step_check(dce_call,
3971 r->in.computer_name,
3973 r->out.return_authenticator,
3975 if (!NT_STATUS_IS_OK(status)) {
3979 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3980 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3981 return NT_STATUS_NOT_IMPLEMENTED;
3984 sam_ctx = samdb_connect(mem_ctx,
3985 dce_call->event_ctx,
3988 dce_call->conn->remote_address,
3990 if (sam_ctx == NULL) {
3991 return NT_STATUS_INTERNAL_ERROR;
3994 /* TODO: check r->in.server_name is our name */
3996 domain_dn = ldb_get_default_basedn(sam_ctx);
3997 if (domain_dn == NULL) {
3998 return NT_STATUS_INTERNAL_ERROR;
4001 forest_dn = ldb_get_root_basedn(sam_ctx);
4002 if (forest_dn == NULL) {
4003 return NT_STATUS_INTERNAL_ERROR;
4006 cmp = ldb_dn_compare(domain_dn, forest_dn);
4008 return NT_STATUS_INVALID_DOMAIN_STATE;
4011 forest_level = dsdb_forest_functional_level(sam_ctx);
4012 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4013 return NT_STATUS_INVALID_DOMAIN_STATE;
4016 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4017 r->out.forest_trust_info);
4018 if (!NT_STATUS_IS_OK(status)) {
4022 return NT_STATUS_OK;
4027 netr_ServerGetTrustInfo
4029 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4030 struct netr_ServerGetTrustInfo *r)
4032 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4033 struct netlogon_creds_CredentialState *creds = NULL;
4034 struct ldb_context *sam_ctx = NULL;
4035 const char * const attrs[] = {
4038 "userAccountControl",
4041 struct ldb_message **res = NULL;
4042 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4045 const char *asid = NULL;
4047 const char *aname = NULL;
4048 struct ldb_message *tdo_msg = NULL;
4049 const char * const tdo_attrs[] = {
4050 "trustAuthIncoming",
4054 struct netr_TrustInfo *trust_info = NULL;
4056 ZERO_STRUCTP(r->out.new_owf_password);
4057 ZERO_STRUCTP(r->out.old_owf_password);
4059 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4061 r->in.computer_name,
4063 r->out.return_authenticator,
4065 if (!NT_STATUS_IS_OK(nt_status)) {
4069 /* TODO: check r->in.server_name is our name */
4071 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4072 return NT_STATUS_INVALID_PARAMETER;
4075 if (r->in.secure_channel_type != creds->secure_channel_type) {
4076 return NT_STATUS_INVALID_PARAMETER;
4079 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4080 return NT_STATUS_INVALID_PARAMETER;
4083 sam_ctx = samdb_connect(mem_ctx,
4084 dce_call->event_ctx,
4086 system_session(lp_ctx),
4087 dce_call->conn->remote_address,
4089 if (sam_ctx == NULL) {
4090 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4093 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4095 return NT_STATUS_NO_MEMORY;
4098 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4099 "(&(objectClass=user)(objectSid=%s))",
4102 return NT_STATUS_ACCOUNT_DISABLED;
4105 switch (creds->secure_channel_type) {
4106 case SEC_CHAN_DNS_DOMAIN:
4107 case SEC_CHAN_DOMAIN:
4108 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4110 if (uac & UF_ACCOUNTDISABLE) {
4111 return NT_STATUS_ACCOUNT_DISABLED;
4114 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4115 return NT_STATUS_ACCOUNT_DISABLED;
4118 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4119 if (aname == NULL) {
4120 return NT_STATUS_ACCOUNT_DISABLED;
4123 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4124 SEC_CHAN_DOMAIN, aname,
4125 tdo_attrs, mem_ctx, &tdo_msg);
4126 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4127 return NT_STATUS_ACCOUNT_DISABLED;
4129 if (!NT_STATUS_IS_OK(nt_status)) {
4133 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4136 if (!NT_STATUS_IS_OK(nt_status)) {
4140 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4141 if (trust_info == NULL) {
4142 return NT_STATUS_NO_MEMORY;
4145 trust_info->count = 1;
4146 trust_info->data = talloc_array(trust_info, uint32_t,
4148 if (trust_info->data == NULL) {
4149 return NT_STATUS_NO_MEMORY;
4152 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4158 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4161 if (!NT_STATUS_IS_OK(nt_status)) {
4165 prevNtHash = talloc(mem_ctx, struct samr_Password);
4166 if (prevNtHash == NULL) {
4167 return NT_STATUS_NO_MEMORY;
4170 E_md4hash("", prevNtHash->hash);
4174 if (curNtHash != NULL) {
4175 *r->out.new_owf_password = *curNtHash;
4176 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4178 if (prevNtHash != NULL) {
4179 *r->out.old_owf_password = *prevNtHash;
4180 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4183 if (trust_info != NULL) {
4184 *r->out.trust_info = trust_info;
4187 return NT_STATUS_OK;
4193 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4194 struct netr_Unused47 *r)
4196 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4200 struct netr_dnsupdate_RODC_state {
4201 struct dcesrv_call_state *dce_call;
4202 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4203 struct dnsupdate_RODC *r2;
4207 called when the forwarded RODC dns update request is finished
4209 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4211 struct netr_dnsupdate_RODC_state *st =
4212 tevent_req_callback_data(subreq,
4213 struct netr_dnsupdate_RODC_state);
4216 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4217 TALLOC_FREE(subreq);
4218 if (!NT_STATUS_IS_OK(status)) {
4219 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4220 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4223 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4225 status = dcesrv_reply(st->dce_call);
4226 if (!NT_STATUS_IS_OK(status)) {
4227 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4232 netr_DsrUpdateReadOnlyServerDnsRecords
4234 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4235 TALLOC_CTX *mem_ctx,
4236 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4238 struct netlogon_creds_CredentialState *creds;
4240 struct dcerpc_binding_handle *binding_handle;
4241 struct netr_dnsupdate_RODC_state *st;
4242 struct tevent_req *subreq;
4244 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4246 r->in.computer_name,
4248 r->out.return_authenticator,
4250 NT_STATUS_NOT_OK_RETURN(nt_status);
4252 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4253 return NT_STATUS_ACCESS_DENIED;
4256 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4257 NT_STATUS_HAVE_NO_MEMORY(st);
4259 st->dce_call = dce_call;
4261 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4262 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4264 st->r2->in.dom_sid = creds->sid;
4265 st->r2->in.site_name = r->in.site_name;
4266 st->r2->in.dns_ttl = r->in.dns_ttl;
4267 st->r2->in.dns_names = r->in.dns_names;
4268 st->r2->out.dns_names = r->out.dns_names;
4270 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
4271 "dnsupdate", &ndr_table_irpc);
4272 if (binding_handle == NULL) {
4273 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4274 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4275 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4278 /* forward the call */
4279 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4280 binding_handle, st->r2);
4281 NT_STATUS_HAVE_NO_MEMORY(subreq);
4283 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4285 /* setup the callback */
4286 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4288 return NT_STATUS_OK;
4292 /* include the generated boilerplate */
4293 #include "librpc/gen_ndr/ndr_netlogon_s.c"