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),
563 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
564 struct netr_ServerAuthenticate *r)
566 struct netr_ServerAuthenticate3 a;
569 * negotiate_flags is used as an [in] parameter
570 * so it need to be initialised.
572 * (I think ... = 0; seems wrong here --metze)
574 uint32_t negotiate_flags_in = 0;
575 uint32_t negotiate_flags_out = 0;
577 a.in.server_name = r->in.server_name;
578 a.in.account_name = r->in.account_name;
579 a.in.secure_channel_type = r->in.secure_channel_type;
580 a.in.computer_name = r->in.computer_name;
581 a.in.credentials = r->in.credentials;
582 a.in.negotiate_flags = &negotiate_flags_in;
584 a.out.return_credentials = r->out.return_credentials;
586 a.out.negotiate_flags = &negotiate_flags_out;
588 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
591 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
592 struct netr_ServerAuthenticate2 *r)
594 struct netr_ServerAuthenticate3 r3;
597 r3.in.server_name = r->in.server_name;
598 r3.in.account_name = r->in.account_name;
599 r3.in.secure_channel_type = r->in.secure_channel_type;
600 r3.in.computer_name = r->in.computer_name;
601 r3.in.credentials = r->in.credentials;
602 r3.out.return_credentials = r->out.return_credentials;
603 r3.in.negotiate_flags = r->in.negotiate_flags;
604 r3.out.negotiate_flags = r->out.negotiate_flags;
607 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
611 * NOTE: The following functions are nearly identical to the ones available in
612 * source3/rpc_server/srv_nelog_nt.c
613 * The reason we keep 2 copies is that they use different structures to
614 * represent the auth_info and the decrpc pipes.
616 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
618 const char *computer_name,
619 struct netr_Authenticator *received_authenticator,
620 struct netr_Authenticator *return_authenticator,
621 struct netlogon_creds_CredentialState **creds_out)
624 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
625 bool schannel_global_required = (schannel == true);
627 if (schannel_global_required) {
628 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
630 dcesrv_call_auth_info(dce_call, &auth_type, NULL);
632 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
633 DBG_ERR("[%s] is not using schannel\n",
635 return NT_STATUS_ACCESS_DENIED;
639 nt_status = schannel_check_creds_state(mem_ctx,
640 dce_call->conn->dce_ctx->lp_ctx,
642 received_authenticator,
643 return_authenticator,
649 Change the machine account password for the currently connected
650 client. Supplies only the NT#.
653 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
654 struct netr_ServerPasswordSet *r)
656 struct netlogon_creds_CredentialState *creds;
657 struct ldb_context *sam_ctx;
658 const char * const attrs[] = { "unicodePwd", NULL };
659 struct ldb_message **res;
660 struct samr_Password *oldNtHash;
664 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
667 r->in.credential, r->out.return_authenticator,
669 NT_STATUS_NOT_OK_RETURN(nt_status);
671 sam_ctx = samdb_connect(mem_ctx,
673 dce_call->conn->dce_ctx->lp_ctx,
674 system_session(dce_call->conn->dce_ctx->lp_ctx),
675 dce_call->conn->remote_address,
677 if (sam_ctx == NULL) {
678 return NT_STATUS_INVALID_SYSTEM_SERVICE;
681 netlogon_creds_des_decrypt(creds, r->in.new_password);
683 /* fetch the old password hashes (the NT hash has to exist) */
685 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
686 "(&(objectClass=user)(objectSid=%s))",
687 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
689 return NT_STATUS_WRONG_PASSWORD;
692 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
693 dce_call->conn->dce_ctx->lp_ctx,
694 res[0], NULL, &oldNtHash);
695 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
696 return NT_STATUS_WRONG_PASSWORD;
699 /* Using the sid for the account as the key, set the password */
700 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
702 NULL, /* Don't have version */
703 NULL, /* Don't have plaintext */
704 NULL, r->in.new_password,
705 NULL, oldNtHash, /* Password change */
711 Change the machine account password for the currently connected
712 client. Supplies new plaintext.
714 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
715 struct netr_ServerPasswordSet2 *r)
717 struct netlogon_creds_CredentialState *creds;
718 struct ldb_context *sam_ctx;
719 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
720 struct ldb_message **res;
721 struct samr_Password *oldLmHash, *oldNtHash;
722 struct NL_PASSWORD_VERSION version = {};
723 const uint32_t *new_version = NULL;
725 DATA_BLOB new_password;
727 struct samr_CryptPassword password_buf;
729 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
732 r->in.credential, r->out.return_authenticator,
734 NT_STATUS_NOT_OK_RETURN(nt_status);
736 sam_ctx = samdb_connect(mem_ctx,
738 dce_call->conn->dce_ctx->lp_ctx,
739 system_session(dce_call->conn->dce_ctx->lp_ctx),
740 dce_call->conn->remote_address,
742 if (sam_ctx == NULL) {
743 return NT_STATUS_INVALID_SYSTEM_SERVICE;
746 memcpy(password_buf.data, r->in.new_password->data, 512);
747 SIVAL(password_buf.data, 512, r->in.new_password->length);
749 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
750 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
752 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
755 switch (creds->secure_channel_type) {
756 case SEC_CHAN_DOMAIN:
757 case SEC_CHAN_DNS_DOMAIN: {
758 uint32_t len = IVAL(password_buf.data, 512);
760 uint32_t ofs = 500 - len;
763 p = password_buf.data + ofs;
765 version.ReservedField = IVAL(p, 0);
766 version.PasswordVersionNumber = IVAL(p, 4);
767 version.PasswordVersionPresent = IVAL(p, 8);
769 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
770 new_version = &version.PasswordVersionNumber;
778 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
779 DEBUG(3,("samr: failed to decode password buffer\n"));
780 return NT_STATUS_WRONG_PASSWORD;
783 /* fetch the old password hashes (at least one of both has to exist) */
785 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
786 "(&(objectClass=user)(objectSid=%s))",
787 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
789 return NT_STATUS_WRONG_PASSWORD;
792 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
793 dce_call->conn->dce_ctx->lp_ctx,
794 res[0], &oldLmHash, &oldNtHash);
795 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
796 return NT_STATUS_WRONG_PASSWORD;
799 /* Using the sid for the account as the key, set the password */
800 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
803 &new_password, /* we have plaintext */
805 oldLmHash, oldNtHash, /* Password change */
814 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
815 struct netr_LogonUasLogon *r)
817 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
824 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
825 struct netr_LogonUasLogoff *r)
827 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
831 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
832 const struct netr_LogonSamLogonEx *r)
834 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
836 switch (r->in.logon_level) {
837 case NetlogonInteractiveInformation:
838 case NetlogonServiceInformation:
839 case NetlogonInteractiveTransitiveInformation:
840 case NetlogonServiceTransitiveInformation:
841 if (r->in.logon->password == NULL) {
842 return NT_STATUS_INVALID_PARAMETER;
845 switch (r->in.validation_level) {
846 case NetlogonValidationSamInfo: /* 2 */
847 case NetlogonValidationSamInfo2: /* 3 */
848 case NetlogonValidationSamInfo4: /* 6 */
851 return NT_STATUS_INVALID_INFO_CLASS;
855 case NetlogonNetworkInformation:
856 case NetlogonNetworkTransitiveInformation:
857 if (r->in.logon->network == NULL) {
858 return NT_STATUS_INVALID_PARAMETER;
861 switch (r->in.validation_level) {
862 case NetlogonValidationSamInfo: /* 2 */
863 case NetlogonValidationSamInfo2: /* 3 */
864 case NetlogonValidationSamInfo4: /* 6 */
867 return NT_STATUS_INVALID_INFO_CLASS;
872 case NetlogonGenericInformation:
873 if (r->in.logon->generic == NULL) {
874 return NT_STATUS_INVALID_PARAMETER;
877 switch (r->in.validation_level) {
878 /* TODO: case NetlogonValidationGenericInfo: 4 */
879 case NetlogonValidationGenericInfo2: /* 5 */
882 return NT_STATUS_INVALID_INFO_CLASS;
887 return NT_STATUS_INVALID_PARAMETER;
890 dcesrv_call_auth_info(dce_call, NULL, &auth_level);
892 switch (r->in.validation_level) {
893 case NetlogonValidationSamInfo4: /* 6 */
894 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
895 return NT_STATUS_INVALID_PARAMETER;
906 struct dcesrv_netr_LogonSamLogon_base_state {
907 struct dcesrv_call_state *dce_call;
911 struct netlogon_creds_CredentialState *creds;
913 struct netr_LogonSamLogonEx r;
915 uint32_t _ignored_flags;
918 struct netr_LogonSamLogon *lsl;
919 struct netr_LogonSamLogonWithFlags *lslwf;
920 struct netr_LogonSamLogonEx *lslex;
923 struct kdc_check_generic_kerberos kr;
926 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
927 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
928 static void dcesrv_netr_LogonSamLogon_base_reply(
929 struct dcesrv_netr_LogonSamLogon_base_state *state);
932 netr_LogonSamLogon_base
934 This version of the function allows other wrappers to say 'do not check the credentials'
936 We can't do the traditional 'wrapping' format completely, as this
937 function must only run under schannel
939 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
941 struct dcesrv_call_state *dce_call = state->dce_call;
942 TALLOC_CTX *mem_ctx = state->mem_ctx;
943 struct netr_LogonSamLogonEx *r = &state->r;
944 struct netlogon_creds_CredentialState *creds = state->creds;
945 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
946 const char *workgroup = lpcfg_workgroup(lp_ctx);
947 struct auth4_context *auth_context = NULL;
948 struct auth_usersupplied_info *user_info = NULL;
950 struct tevent_req *subreq = NULL;
952 *r->out.authoritative = 1;
954 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
956 * Currently we're always the forest root ourself.
958 return NT_STATUS_NO_SUCH_USER;
961 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
963 * Currently we don't support trusts correctly yet.
965 return NT_STATUS_NO_SUCH_USER;
968 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
969 NT_STATUS_HAVE_NO_MEMORY(user_info);
971 user_info->service_description = "SamLogon";
973 netlogon_creds_decrypt_samlogon_logon(creds,
977 switch (r->in.logon_level) {
978 case NetlogonInteractiveInformation:
979 case NetlogonServiceInformation:
980 case NetlogonInteractiveTransitiveInformation:
981 case NetlogonServiceTransitiveInformation:
982 case NetlogonNetworkInformation:
983 case NetlogonNetworkTransitiveInformation:
985 nt_status = auth_context_create_for_netlogon(mem_ctx,
986 dce_call->event_ctx, dce_call->msg_ctx,
987 dce_call->conn->dce_ctx->lp_ctx,
989 NT_STATUS_NOT_OK_RETURN(nt_status);
991 user_info->remote_host = dce_call->conn->remote_address;
992 user_info->local_host = dce_call->conn->local_address;
994 user_info->netlogon_trust_account.secure_channel_type
995 = creds->secure_channel_type;
996 user_info->netlogon_trust_account.negotiate_flags
997 = creds->negotiate_flags;
1000 * These two can be unrelated when the account is
1001 * actually that of a trusted domain, so we want to
1002 * know which DC in that trusted domain contacted
1005 user_info->netlogon_trust_account.computer_name
1006 = creds->computer_name;
1007 user_info->netlogon_trust_account.account_name
1008 = creds->account_name;
1009 user_info->netlogon_trust_account.sid
1013 /* We do not need to set up the user_info in this case */
1017 switch (r->in.logon_level) {
1018 case NetlogonInteractiveInformation:
1019 case NetlogonServiceInformation:
1020 case NetlogonInteractiveTransitiveInformation:
1021 case NetlogonServiceTransitiveInformation:
1022 user_info->auth_description = "interactive";
1024 user_info->logon_parameters
1025 = r->in.logon->password->identity_info.parameter_control;
1026 user_info->client.account_name
1027 = r->in.logon->password->identity_info.account_name.string;
1028 user_info->client.domain_name
1029 = r->in.logon->password->identity_info.domain_name.string;
1030 user_info->workstation_name
1031 = r->in.logon->password->identity_info.workstation.string;
1032 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1033 user_info->password_state = AUTH_PASSWORD_HASH;
1035 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1036 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1037 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1039 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1040 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1041 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1044 = r->in.logon->password->identity_info.logon_id;
1047 case NetlogonNetworkInformation:
1048 case NetlogonNetworkTransitiveInformation:
1049 user_info->auth_description = "network";
1051 nt_status = auth_context_set_challenge(
1053 r->in.logon->network->challenge,
1054 "netr_LogonSamLogonWithFlags");
1055 NT_STATUS_NOT_OK_RETURN(nt_status);
1057 user_info->logon_parameters
1058 = r->in.logon->network->identity_info.parameter_control;
1059 user_info->client.account_name
1060 = r->in.logon->network->identity_info.account_name.string;
1061 user_info->client.domain_name
1062 = r->in.logon->network->identity_info.domain_name.string;
1063 user_info->workstation_name
1064 = r->in.logon->network->identity_info.workstation.string;
1066 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1067 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1068 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1071 = r->in.logon->network->identity_info.logon_id;
1073 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1074 user_info->client.account_name,
1075 user_info->client.domain_name,
1076 user_info->password.response.nt,
1078 NT_STATUS_NOT_OK_RETURN(nt_status);
1083 case NetlogonGenericInformation:
1085 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1087 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1090 /* Using DES to verify kerberos tickets makes no sense */
1091 return NT_STATUS_INVALID_PARAMETER;
1094 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1095 struct dcerpc_binding_handle *irpc_handle;
1096 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1097 NT_STATUS_HAVE_NO_MEMORY(generic);
1099 r->out.validation->generic = generic;
1102 = r->in.logon->generic->identity_info.logon_id;
1104 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1108 if (irpc_handle == NULL) {
1109 return NT_STATUS_NO_LOGON_SERVERS;
1112 state->kr.in.generic_request =
1113 data_blob_const(r->in.logon->generic->data,
1114 r->in.logon->generic->length);
1117 * 60 seconds should be enough
1119 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1120 subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1121 state->dce_call->event_ctx,
1122 irpc_handle, &state->kr);
1123 if (subreq == NULL) {
1124 return NT_STATUS_NO_MEMORY;
1126 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1127 tevent_req_set_callback(subreq,
1128 dcesrv_netr_LogonSamLogon_base_krb5_done,
1130 return NT_STATUS_OK;
1133 /* Until we get an implemetnation of these other packages */
1134 return NT_STATUS_INVALID_PARAMETER;
1137 return NT_STATUS_INVALID_PARAMETER;
1140 subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1141 auth_context, user_info);
1142 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1143 tevent_req_set_callback(subreq,
1144 dcesrv_netr_LogonSamLogon_base_auth_done,
1146 return NT_STATUS_OK;
1149 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1151 struct dcesrv_netr_LogonSamLogon_base_state *state =
1152 tevent_req_callback_data(subreq,
1153 struct dcesrv_netr_LogonSamLogon_base_state);
1154 TALLOC_CTX *mem_ctx = state->mem_ctx;
1155 struct netr_LogonSamLogonEx *r = &state->r;
1156 struct auth_user_info_dc *user_info_dc = NULL;
1157 struct netr_SamInfo2 *sam2 = NULL;
1158 struct netr_SamInfo3 *sam3 = NULL;
1159 struct netr_SamInfo6 *sam6 = NULL;
1162 nt_status = auth_check_password_recv(subreq, mem_ctx,
1164 r->out.authoritative);
1165 TALLOC_FREE(subreq);
1166 if (!NT_STATUS_IS_OK(nt_status)) {
1167 r->out.result = nt_status;
1168 dcesrv_netr_LogonSamLogon_base_reply(state);
1172 switch (r->in.validation_level) {
1174 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1177 if (!NT_STATUS_IS_OK(nt_status)) {
1178 r->out.result = nt_status;
1179 dcesrv_netr_LogonSamLogon_base_reply(state);
1183 r->out.validation->sam2 = sam2;
1187 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1190 if (!NT_STATUS_IS_OK(nt_status)) {
1191 r->out.result = nt_status;
1192 dcesrv_netr_LogonSamLogon_base_reply(state);
1196 r->out.validation->sam3 = sam3;
1200 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1203 if (!NT_STATUS_IS_OK(nt_status)) {
1204 r->out.result = nt_status;
1205 dcesrv_netr_LogonSamLogon_base_reply(state);
1209 r->out.validation->sam6 = sam6;
1213 if (!NT_STATUS_IS_OK(nt_status)) {
1214 r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1215 dcesrv_netr_LogonSamLogon_base_reply(state);
1220 /* TODO: Describe and deal with these flags */
1223 r->out.result = NT_STATUS_OK;
1225 dcesrv_netr_LogonSamLogon_base_reply(state);
1228 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1230 struct dcesrv_netr_LogonSamLogon_base_state *state =
1231 tevent_req_callback_data(subreq,
1232 struct dcesrv_netr_LogonSamLogon_base_state);
1233 TALLOC_CTX *mem_ctx = state->mem_ctx;
1234 struct netr_LogonSamLogonEx *r = &state->r;
1235 struct netr_GenericInfo2 *generic = NULL;
1238 status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1239 TALLOC_FREE(subreq);
1240 if (!NT_STATUS_IS_OK(status)) {
1241 r->out.result = status;
1242 dcesrv_netr_LogonSamLogon_base_reply(state);
1246 generic = r->out.validation->generic;
1247 generic->length = state->kr.out.generic_reply.length;
1248 generic->data = state->kr.out.generic_reply.data;
1250 /* TODO: Describe and deal with these flags */
1253 r->out.result = NT_STATUS_OK;
1255 dcesrv_netr_LogonSamLogon_base_reply(state);
1258 static void dcesrv_netr_LogonSamLogon_base_reply(
1259 struct dcesrv_netr_LogonSamLogon_base_state *state)
1261 struct netr_LogonSamLogonEx *r = &state->r;
1264 if (NT_STATUS_IS_OK(r->out.result)) {
1265 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
1266 r->in.validation_level,
1268 if (!NT_STATUS_IS_OK(status)) {
1269 DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
1275 if (state->_r.lslex != NULL) {
1276 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1277 _r->out.result = r->out.result;
1278 } else if (state->_r.lslwf != NULL) {
1279 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1280 _r->out.result = r->out.result;
1281 } else if (state->_r.lsl != NULL) {
1282 struct netr_LogonSamLogon *_r = state->_r.lsl;
1283 _r->out.result = r->out.result;
1286 status = dcesrv_reply(state->dce_call);
1287 if (!NT_STATUS_IS_OK(status)) {
1288 DBG_ERR("dcesrv_reply() failed - %s\n",
1293 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1294 struct netr_LogonSamLogonEx *r)
1296 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
1297 struct dcesrv_netr_LogonSamLogon_base_state *state;
1300 *r->out.authoritative = 1;
1302 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1303 if (state == NULL) {
1304 return NT_STATUS_NO_MEMORY;
1307 state->dce_call = dce_call;
1308 state->mem_ctx = mem_ctx;
1310 state->r.in.server_name = r->in.server_name;
1311 state->r.in.computer_name = r->in.computer_name;
1312 state->r.in.logon_level = r->in.logon_level;
1313 state->r.in.logon = r->in.logon;
1314 state->r.in.validation_level = r->in.validation_level;
1315 state->r.in.flags = r->in.flags;
1316 state->r.out.validation = r->out.validation;
1317 state->r.out.authoritative = r->out.authoritative;
1318 state->r.out.flags = r->out.flags;
1320 state->_r.lslex = r;
1322 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1323 if (!NT_STATUS_IS_OK(nt_status)) {
1327 nt_status = schannel_get_creds_state(mem_ctx,
1328 dce_call->conn->dce_ctx->lp_ctx,
1329 r->in.computer_name, &state->creds);
1330 if (!NT_STATUS_IS_OK(nt_status)) {
1334 dcesrv_call_auth_info(dce_call, &auth_type, NULL);
1336 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1337 return NT_STATUS_ACCESS_DENIED;
1340 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1342 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1350 netr_LogonSamLogonWithFlags
1353 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1354 struct netr_LogonSamLogonWithFlags *r)
1356 struct dcesrv_netr_LogonSamLogon_base_state *state;
1359 *r->out.authoritative = 1;
1361 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1362 if (state == NULL) {
1363 return NT_STATUS_NO_MEMORY;
1366 state->dce_call = dce_call;
1367 state->mem_ctx = mem_ctx;
1369 state->r.in.server_name = r->in.server_name;
1370 state->r.in.computer_name = r->in.computer_name;
1371 state->r.in.logon_level = r->in.logon_level;
1372 state->r.in.logon = r->in.logon;
1373 state->r.in.validation_level = r->in.validation_level;
1374 state->r.in.flags = r->in.flags;
1375 state->r.out.validation = r->out.validation;
1376 state->r.out.authoritative = r->out.authoritative;
1377 state->r.out.flags = r->out.flags;
1379 state->_r.lslwf = r;
1381 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1382 if (!NT_STATUS_IS_OK(nt_status)) {
1386 r->out.return_authenticator = talloc_zero(mem_ctx,
1387 struct netr_Authenticator);
1388 if (r->out.return_authenticator == NULL) {
1389 return NT_STATUS_NO_MEMORY;
1392 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1394 r->in.computer_name,
1396 r->out.return_authenticator,
1398 if (!NT_STATUS_IS_OK(nt_status)) {
1402 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1404 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1414 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1415 struct netr_LogonSamLogon *r)
1417 struct dcesrv_netr_LogonSamLogon_base_state *state;
1420 *r->out.authoritative = 1;
1422 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1423 if (state == NULL) {
1424 return NT_STATUS_NO_MEMORY;
1427 state->dce_call = dce_call;
1428 state->mem_ctx = mem_ctx;
1430 state->r.in.server_name = r->in.server_name;
1431 state->r.in.computer_name = r->in.computer_name;
1432 state->r.in.logon_level = r->in.logon_level;
1433 state->r.in.logon = r->in.logon;
1434 state->r.in.validation_level = r->in.validation_level;
1435 state->r.in.flags = &state->_ignored_flags;
1436 state->r.out.validation = r->out.validation;
1437 state->r.out.authoritative = r->out.authoritative;
1438 state->r.out.flags = &state->_ignored_flags;
1442 nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1443 if (!NT_STATUS_IS_OK(nt_status)) {
1447 r->out.return_authenticator = talloc_zero(mem_ctx,
1448 struct netr_Authenticator);
1449 if (r->out.return_authenticator == NULL) {
1450 return NT_STATUS_NO_MEMORY;
1453 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1455 r->in.computer_name,
1457 r->out.return_authenticator,
1459 if (!NT_STATUS_IS_OK(nt_status)) {
1463 nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1465 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1476 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1477 struct netr_LogonSamLogoff *r)
1479 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1487 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1488 struct netr_DatabaseDeltas *r)
1490 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1497 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1498 struct netr_DatabaseSync2 *r)
1500 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1501 return NT_STATUS_NOT_IMPLEMENTED;
1508 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1509 struct netr_DatabaseSync *r)
1511 struct netr_DatabaseSync2 r2;
1516 r2.in.logon_server = r->in.logon_server;
1517 r2.in.computername = r->in.computername;
1518 r2.in.credential = r->in.credential;
1519 r2.in.database_id = r->in.database_id;
1520 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1521 r2.in.sync_context = r->in.sync_context;
1522 r2.out.sync_context = r->out.sync_context;
1523 r2.out.delta_enum_array = r->out.delta_enum_array;
1524 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1526 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1535 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1536 struct netr_AccountDeltas *r)
1538 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1539 return NT_STATUS_NOT_IMPLEMENTED;
1546 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1547 struct netr_AccountSync *r)
1549 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1550 return NT_STATUS_NOT_IMPLEMENTED;
1557 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1558 struct netr_GetDcName *r)
1560 struct auth_session_info *session_info =
1561 dcesrv_call_session_info(dce_call);
1562 const char * const attrs[] = { NULL };
1563 struct ldb_context *sam_ctx;
1564 struct ldb_message **res;
1565 struct ldb_dn *domain_dn;
1570 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1571 * that the domainname needs to be a valid netbios domain
1572 * name, if it is not NULL.
1574 if (r->in.domainname) {
1575 const char *dot = strchr(r->in.domainname, '.');
1576 size_t len = strlen(r->in.domainname);
1578 if (dot || len > 15) {
1579 return WERR_NERR_DCNOTFOUND;
1583 * TODO: Should we also varify that only valid
1584 * netbios name characters are used?
1588 sam_ctx = samdb_connect(mem_ctx,
1589 dce_call->event_ctx,
1590 dce_call->conn->dce_ctx->lp_ctx,
1592 dce_call->conn->remote_address,
1594 if (sam_ctx == NULL) {
1595 return WERR_DS_UNAVAILABLE;
1598 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1600 if (domain_dn == NULL) {
1601 return WERR_NO_SUCH_DOMAIN;
1604 ret = gendb_search_dn(sam_ctx, mem_ctx,
1605 domain_dn, &res, attrs);
1607 return WERR_NO_SUCH_DOMAIN;
1610 /* TODO: - return real IP address
1611 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1613 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1614 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1615 W_ERROR_HAVE_NO_MEMORY(dcname);
1617 *r->out.dcname = dcname;
1621 struct dcesrv_netr_LogonControl_base_state {
1622 struct dcesrv_call_state *dce_call;
1624 TALLOC_CTX *mem_ctx;
1626 struct netr_LogonControl2Ex r;
1629 struct netr_LogonControl *l;
1630 struct netr_LogonControl2 *l2;
1631 struct netr_LogonControl2Ex *l2ex;
1635 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1637 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1639 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1640 struct auth_session_info *session_info =
1641 dcesrv_call_session_info(state->dce_call);
1642 enum security_user_level security_level;
1643 struct dcerpc_binding_handle *irpc_handle;
1644 struct tevent_req *subreq;
1647 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1649 if (state->_r.l != NULL) {
1653 if (state->r.in.level == 0x00000002) {
1654 return WERR_NOT_SUPPORTED;
1655 } else if (state->r.in.level != 0x00000001) {
1656 return WERR_INVALID_LEVEL;
1659 switch (state->r.in.function_code) {
1660 case NETLOGON_CONTROL_QUERY:
1661 case NETLOGON_CONTROL_REPLICATE:
1662 case NETLOGON_CONTROL_SYNCHRONIZE:
1663 case NETLOGON_CONTROL_PDC_REPLICATE:
1664 case NETLOGON_CONTROL_BREAKPOINT:
1665 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1666 case NETLOGON_CONTROL_TRUNCATE_LOG:
1669 return WERR_NOT_SUPPORTED;
1673 if (state->r.in.level < 0x00000001) {
1674 return WERR_INVALID_LEVEL;
1677 if (state->r.in.level > 0x00000004) {
1678 return WERR_INVALID_LEVEL;
1681 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1682 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1683 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1685 switch (state->r.in.level) {
1687 info1 = talloc_zero(state->mem_ctx,
1688 struct netr_NETLOGON_INFO_1);
1689 if (info1 == NULL) {
1690 return WERR_NOT_ENOUGH_MEMORY;
1692 state->r.out.query->info1 = info1;
1696 info3 = talloc_zero(state->mem_ctx,
1697 struct netr_NETLOGON_INFO_3);
1698 if (info3 == NULL) {
1699 return WERR_NOT_ENOUGH_MEMORY;
1701 state->r.out.query->info3 = info3;
1705 return WERR_INVALID_PARAMETER;
1710 * Some validations are done before the access check
1711 * and some after the access check
1713 security_level = security_session_user_level(session_info, NULL);
1714 if (security_level < SECURITY_ADMINISTRATOR) {
1715 return WERR_ACCESS_DENIED;
1718 if (state->_r.l2 != NULL) {
1720 * netr_LogonControl2
1722 if (state->r.in.level == 0x00000004) {
1723 return WERR_INVALID_LEVEL;
1727 switch (state->r.in.level) {
1732 switch (state->r.in.function_code) {
1733 case NETLOGON_CONTROL_REDISCOVER:
1734 case NETLOGON_CONTROL_TC_QUERY:
1735 case NETLOGON_CONTROL_TC_VERIFY:
1738 return WERR_INVALID_PARAMETER;
1747 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1748 return WERR_INVALID_PARAMETER;
1754 return WERR_INVALID_LEVEL;
1757 switch (state->r.in.function_code) {
1758 case NETLOGON_CONTROL_REDISCOVER:
1759 case NETLOGON_CONTROL_TC_QUERY:
1760 case NETLOGON_CONTROL_TC_VERIFY:
1761 if (state->r.in.level != 2) {
1762 return WERR_INVALID_PARAMETER;
1765 if (state->r.in.data == NULL) {
1766 return WERR_INVALID_PARAMETER;
1769 if (state->r.in.data->domain == NULL) {
1770 return WERR_INVALID_PARAMETER;
1775 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1776 if (state->r.in.level != 1) {
1777 return WERR_INVALID_PARAMETER;
1780 if (state->r.in.data == NULL) {
1781 return WERR_INVALID_PARAMETER;
1784 if (state->r.in.data->domain == NULL) {
1785 return WERR_INVALID_PARAMETER;
1788 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1789 state->r.in.data->domain);
1791 struct ldb_context *sam_ctx;
1793 sam_ctx = samdb_connect(
1795 state->dce_call->event_ctx,
1797 system_session(lp_ctx),
1798 state->dce_call->conn->remote_address,
1800 if (sam_ctx == NULL) {
1801 return WERR_DS_UNAVAILABLE;
1805 * Secrets for trusted domains can only be triggered on
1808 ok = samdb_is_pdc(sam_ctx);
1809 TALLOC_FREE(sam_ctx);
1811 return WERR_INVALID_DOMAIN_ROLE;
1817 return WERR_NOT_SUPPORTED;
1820 irpc_handle = irpc_binding_handle_by_name(state,
1821 state->dce_call->msg_ctx,
1823 &ndr_table_winbind);
1824 if (irpc_handle == NULL) {
1825 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1826 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1827 return WERR_SERVICE_NOT_FOUND;
1831 * 60 seconds timeout should be enough
1833 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1835 subreq = dcerpc_winbind_LogonControl_send(state,
1836 state->dce_call->event_ctx,
1838 state->r.in.function_code,
1841 state->r.out.query);
1842 if (subreq == NULL) {
1843 return WERR_NOT_ENOUGH_MEMORY;
1845 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1846 tevent_req_set_callback(subreq,
1847 dcesrv_netr_LogonControl_base_done,
1853 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1855 struct dcesrv_netr_LogonControl_base_state *state =
1856 tevent_req_callback_data(subreq,
1857 struct dcesrv_netr_LogonControl_base_state);
1860 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1861 &state->r.out.result);
1862 TALLOC_FREE(subreq);
1863 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1864 state->r.out.result = WERR_TIMEOUT;
1865 } else if (!NT_STATUS_IS_OK(status)) {
1866 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1867 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1868 nt_errstr(status)));
1871 if (state->_r.l2ex != NULL) {
1872 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1873 r->out.result = state->r.out.result;
1874 } else if (state->_r.l2 != NULL) {
1875 struct netr_LogonControl2 *r = state->_r.l2;
1876 r->out.result = state->r.out.result;
1877 } else if (state->_r.l != NULL) {
1878 struct netr_LogonControl *r = state->_r.l;
1879 r->out.result = state->r.out.result;
1882 status = dcesrv_reply(state->dce_call);
1883 if (!NT_STATUS_IS_OK(status)) {
1884 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1891 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1892 struct netr_LogonControl *r)
1894 struct dcesrv_netr_LogonControl_base_state *state;
1897 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1898 if (state == NULL) {
1899 return WERR_NOT_ENOUGH_MEMORY;
1902 state->dce_call = dce_call;
1903 state->mem_ctx = mem_ctx;
1905 state->r.in.logon_server = r->in.logon_server;
1906 state->r.in.function_code = r->in.function_code;
1907 state->r.in.level = r->in.level;
1908 state->r.in.data = NULL;
1909 state->r.out.query = r->out.query;
1913 werr = dcesrv_netr_LogonControl_base_call(state);
1915 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1925 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1926 struct netr_LogonControl2 *r)
1928 struct dcesrv_netr_LogonControl_base_state *state;
1931 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1932 if (state == NULL) {
1933 return WERR_NOT_ENOUGH_MEMORY;
1936 state->dce_call = dce_call;
1937 state->mem_ctx = mem_ctx;
1939 state->r.in.logon_server = r->in.logon_server;
1940 state->r.in.function_code = r->in.function_code;
1941 state->r.in.level = r->in.level;
1942 state->r.in.data = r->in.data;
1943 state->r.out.query = r->out.query;
1947 werr = dcesrv_netr_LogonControl_base_call(state);
1949 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1957 netr_LogonControl2Ex
1959 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1960 struct netr_LogonControl2Ex *r)
1962 struct dcesrv_netr_LogonControl_base_state *state;
1965 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1966 if (state == NULL) {
1967 return WERR_NOT_ENOUGH_MEMORY;
1970 state->dce_call = dce_call;
1971 state->mem_ctx = mem_ctx;
1976 werr = dcesrv_netr_LogonControl_base_call(state);
1978 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1985 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1986 struct ldb_context *sam_ctx,
1987 struct netr_DomainTrustList *trusts,
1988 uint32_t trust_flags);
1993 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1994 struct netr_GetAnyDCName *r)
1996 struct auth_session_info *session_info =
1997 dcesrv_call_session_info(dce_call);
1998 struct netr_DomainTrustList *trusts;
1999 struct ldb_context *sam_ctx;
2000 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2004 *r->out.dcname = NULL;
2006 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2007 /* if the domainname parameter wasn't set assume our domain */
2008 r->in.domainname = lpcfg_workgroup(lp_ctx);
2011 sam_ctx = samdb_connect(mem_ctx,
2012 dce_call->event_ctx,
2015 dce_call->conn->remote_address,
2017 if (sam_ctx == NULL) {
2018 return WERR_DS_UNAVAILABLE;
2021 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2022 /* well we asked for a DC of our own domain */
2023 if (samdb_is_pdc(sam_ctx)) {
2024 /* we are the PDC of the specified domain */
2025 return WERR_NO_SUCH_DOMAIN;
2028 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2029 lpcfg_netbios_name(lp_ctx));
2030 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2035 /* Okay, now we have to consider the trusted domains */
2037 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2038 W_ERROR_HAVE_NO_MEMORY(trusts);
2042 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2043 NETR_TRUST_FLAG_INBOUND
2044 | NETR_TRUST_FLAG_OUTBOUND);
2045 W_ERROR_NOT_OK_RETURN(werr);
2047 for (i = 0; i < trusts->count; i++) {
2048 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2049 /* FIXME: Here we need to find a DC for the specified
2050 * trusted domain. */
2052 /* return WERR_OK; */
2053 return WERR_NO_SUCH_DOMAIN;
2057 return WERR_NO_SUCH_DOMAIN;
2064 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2065 struct netr_DatabaseRedo *r)
2067 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2072 netr_NetrEnumerateTrustedDomains
2074 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2075 struct netr_NetrEnumerateTrustedDomains *r)
2077 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2082 netr_LogonGetCapabilities
2084 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2085 struct netr_LogonGetCapabilities *r)
2087 struct netlogon_creds_CredentialState *creds;
2090 status = dcesrv_netr_creds_server_step_check(dce_call,
2092 r->in.computer_name,
2094 r->out.return_authenticator,
2096 if (!NT_STATUS_IS_OK(status)) {
2097 DEBUG(0,(__location__ " Bad credentials - error\n"));
2099 NT_STATUS_NOT_OK_RETURN(status);
2101 if (r->in.query_level != 1) {
2102 return NT_STATUS_NOT_SUPPORTED;
2105 r->out.capabilities->server_capabilities = creds->negotiate_flags;
2107 return NT_STATUS_OK;
2112 netr_NETRLOGONSETSERVICEBITS
2114 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2115 struct netr_NETRLOGONSETSERVICEBITS *r)
2117 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2122 netr_LogonGetTrustRid
2124 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2125 struct netr_LogonGetTrustRid *r)
2127 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2132 netr_NETRLOGONCOMPUTESERVERDIGEST
2134 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2135 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2137 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2142 netr_NETRLOGONCOMPUTECLIENTDIGEST
2144 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2145 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2147 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2155 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2156 struct netr_DsRGetSiteName *r)
2158 struct auth_session_info *session_info =
2159 dcesrv_call_session_info(dce_call);
2160 struct ldb_context *sam_ctx;
2161 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2163 sam_ctx = samdb_connect(mem_ctx,
2164 dce_call->event_ctx,
2167 dce_call->conn->remote_address,
2169 if (sam_ctx == NULL) {
2170 return WERR_DS_UNAVAILABLE;
2174 * We assume to be a DC when we get called over NETLOGON. Hence we
2175 * get our site name always by using "samdb_server_site_name()"
2176 * and not "samdb_client_site_name()".
2178 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2179 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2186 fill in a netr_OneDomainInfo from our own domain/forest
2188 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2189 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2190 struct GUID domain_guid,
2191 struct netr_OneDomainInfo *info,
2196 if (is_trust_list) {
2197 struct netr_trust_extension *tei = NULL;
2199 /* w2k8 only fills this on trusted domains */
2200 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2202 return NT_STATUS_NO_MEMORY;
2204 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2207 * We're always within a native forest
2209 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2210 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2212 /* For now we assume we're always the tree root */
2213 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2214 tei->parent_index = 0;
2216 tei->trust_type = our_tdo->trust_type;
2218 * This needs to be 0 instead of our_tdo->trust_attributes
2219 * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2220 * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2222 tei->trust_attributes = 0;
2224 info->trust_extension.info = tei;
2225 info->trust_extension.length = 16;
2228 if (is_trust_list) {
2229 info->dns_domainname.string = our_tdo->domain_name.string;
2231 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2232 info->dns_forestname.string = NULL;
2234 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2235 our_tdo->domain_name.string);
2236 if (info->dns_domainname.string == NULL) {
2237 return NT_STATUS_NO_MEMORY;
2240 info->dns_forestname.string = info->dns_domainname.string;
2243 info->domainname.string = our_tdo->netbios_name.string;
2244 info->domain_sid = our_tdo->sid;
2245 info->domain_guid = domain_guid;
2247 return NT_STATUS_OK;
2251 fill in a netr_OneDomainInfo from a trust tdo
2253 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2254 struct GUID domain_guid,
2255 const struct lsa_TrustDomainInfoInfoEx *tdo,
2256 struct netr_OneDomainInfo *info)
2258 struct netr_trust_extension *tei = NULL;
2262 /* w2k8 only fills this on trusted domains */
2263 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2265 return NT_STATUS_NO_MEMORY;
2268 if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2269 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2271 if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2272 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2274 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2275 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2279 * TODO: once we support multiple domains within our forest,
2280 * we need to fill this correct (or let the caller do it
2281 * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2283 tei->parent_index = 0;
2285 tei->trust_type = tdo->trust_type;
2286 tei->trust_attributes = tdo->trust_attributes;
2288 info->trust_extension.info = tei;
2289 info->trust_extension.length = 16;
2291 info->domainname.string = tdo->netbios_name.string;
2292 if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2293 info->dns_domainname.string = tdo->domain_name.string;
2295 info->dns_domainname.string = NULL;
2297 info->domain_sid = tdo->sid;
2298 info->domain_guid = domain_guid;
2300 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2301 info->dns_forestname.string = NULL;
2303 return NT_STATUS_OK;
2307 netr_LogonGetDomainInfo
2308 this is called as part of the ADS domain logon procedure.
2310 It has an important role in convaying details about the client, such
2311 as Operating System, Version, Service Pack etc.
2313 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2314 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2316 struct netlogon_creds_CredentialState *creds;
2317 const char * const trusts_attrs[] = {
2318 "securityIdentifier",
2326 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2327 "msDS-SupportedEncryptionTypes", NULL };
2328 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
2329 struct ldb_context *sam_ctx;
2330 const struct GUID *our_domain_guid = NULL;
2331 struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2332 struct ldb_message **res1, *new_msg;
2333 struct ldb_result *trusts_res = NULL;
2334 struct ldb_dn *workstation_dn;
2335 struct netr_DomainInformation *domain_info;
2336 struct netr_LsaPolicyInformation *lsa_policy_info;
2337 uint32_t default_supported_enc_types = 0xFFFFFFFF;
2338 bool update_dns_hostname = true;
2342 status = dcesrv_netr_creds_server_step_check(dce_call,
2344 r->in.computer_name,
2346 r->out.return_authenticator,
2348 if (!NT_STATUS_IS_OK(status)) {
2350 char* remote = NULL;
2351 TALLOC_CTX *frame = talloc_stackframe();
2352 remote = tsocket_address_string(dce_call->conn->remote_address,
2354 local = tsocket_address_string(dce_call->conn->local_address,
2356 DBG_ERR(("Bad credentials - "
2357 "computer[%s] remote[%s] local[%s]\n"),
2358 log_escape(frame, r->in.computer_name),
2363 NT_STATUS_NOT_OK_RETURN(status);
2365 sam_ctx = samdb_connect(mem_ctx,
2366 dce_call->event_ctx,
2367 dce_call->conn->dce_ctx->lp_ctx,
2368 system_session(dce_call->conn->dce_ctx->lp_ctx),
2369 dce_call->conn->remote_address,
2371 if (sam_ctx == NULL) {
2372 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2375 switch (r->in.level) {
2376 case 1: /* Domain information */
2378 if (r->in.query->workstation_info == NULL) {
2379 return NT_STATUS_INVALID_PARAMETER;
2382 /* Prepares the workstation DN */
2383 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2384 dom_sid_string(mem_ctx, creds->sid));
2385 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2387 /* Lookup for attributes in workstation object */
2388 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2391 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2394 /* Gets the sam account name which is checked against the DNS
2395 * hostname parameter. */
2396 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2399 if (sam_account_name == NULL) {
2400 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2404 * Checks that the sam account name without a possible "$"
2405 * matches as prefix with the DNS hostname in the workstation
2408 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2409 strcspn(sam_account_name, "$"));
2410 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2411 if (r->in.query->workstation_info->dns_hostname != NULL) {
2412 prefix2 = talloc_strndup(mem_ctx,
2413 r->in.query->workstation_info->dns_hostname,
2414 strcspn(r->in.query->workstation_info->dns_hostname, "."));
2415 NT_STATUS_HAVE_NO_MEMORY(prefix2);
2417 if (strcasecmp(prefix1, prefix2) != 0) {
2418 update_dns_hostname = false;
2421 update_dns_hostname = false;
2424 /* Gets the old DNS hostname */
2425 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2430 * Updates the DNS hostname when the client wishes that the
2431 * server should handle this for him
2432 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2433 * obviously only checked when we do already have a
2435 * See MS-NRPC section 3.5.4.3.9
2437 if ((old_dns_hostname != NULL) &&
2438 (r->in.query->workstation_info->workstation_flags
2439 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2440 update_dns_hostname = false;
2443 /* Gets host information and put them into our directory */
2445 new_msg = ldb_msg_new(mem_ctx);
2446 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2448 new_msg->dn = workstation_dn;
2450 /* Sets the OS name */
2452 if (r->in.query->workstation_info->os_name.string == NULL) {
2453 return NT_STATUS_INVALID_PARAMETER;
2456 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2457 r->in.query->workstation_info->os_name.string);
2458 if (ret != LDB_SUCCESS) {
2459 return NT_STATUS_NO_MEMORY;
2463 * Sets information from "os_version". On an empty structure
2464 * the values are cleared.
2466 if (r->in.query->workstation_info->os_version.os != NULL) {
2467 struct netr_OsVersionInfoEx *os_version;
2468 const char *os_version_str;
2470 os_version = &r->in.query->workstation_info->os_version.os->os;
2472 if (os_version->CSDVersion == NULL) {
2473 return NT_STATUS_INVALID_PARAMETER;
2476 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2477 os_version->MajorVersion,
2478 os_version->MinorVersion,
2479 os_version->BuildNumber);
2480 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2482 ret = ldb_msg_add_string(new_msg,
2483 "operatingSystemServicePack",
2484 os_version->CSDVersion);
2485 if (ret != LDB_SUCCESS) {
2486 return NT_STATUS_NO_MEMORY;
2489 ret = ldb_msg_add_string(new_msg,
2490 "operatingSystemVersion",
2492 if (ret != LDB_SUCCESS) {
2493 return NT_STATUS_NO_MEMORY;
2496 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2497 "operatingSystemServicePack");
2498 if (ret != LDB_SUCCESS) {
2499 return NT_STATUS_NO_MEMORY;
2502 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2503 "operatingSystemVersion");
2504 if (ret != LDB_SUCCESS) {
2505 return NT_STATUS_NO_MEMORY;
2510 * If the boolean "update_dns_hostname" remained true, then we
2511 * are fine to start the update.
2513 if (update_dns_hostname) {
2514 ret = ldb_msg_add_string(new_msg,
2516 r->in.query->workstation_info->dns_hostname);
2517 if (ret != LDB_SUCCESS) {
2518 return NT_STATUS_NO_MEMORY;
2521 /* This manual "servicePrincipalName" generation is
2522 * still needed! Since the update in the samldb LDB
2523 * module does only work if the entries already exist
2524 * which isn't always the case. */
2525 ret = ldb_msg_add_string(new_msg,
2526 "servicePrincipalName",
2527 talloc_asprintf(new_msg, "HOST/%s",
2528 r->in.computer_name));
2529 if (ret != LDB_SUCCESS) {
2530 return NT_STATUS_NO_MEMORY;
2533 ret = ldb_msg_add_string(new_msg,
2534 "servicePrincipalName",
2535 talloc_asprintf(new_msg, "HOST/%s",
2536 r->in.query->workstation_info->dns_hostname));
2537 if (ret != LDB_SUCCESS) {
2538 return NT_STATUS_NO_MEMORY;
2542 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2543 DEBUG(3,("Impossible to update samdb: %s\n",
2544 ldb_errstring(sam_ctx)));
2547 talloc_free(new_msg);
2549 /* Writes back the domain information */
2551 our_domain_guid = samdb_domain_guid(sam_ctx);
2552 if (our_domain_guid == NULL) {
2553 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2556 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2557 if (!NT_STATUS_IS_OK(status)) {
2561 status = dsdb_trust_search_tdos(sam_ctx,
2566 if (!NT_STATUS_IS_OK(status)) {
2570 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2571 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2573 ZERO_STRUCTP(domain_info);
2575 /* Informations about the local and trusted domains */
2577 status = fill_our_one_domain_info(mem_ctx,
2580 &domain_info->primary_domain,
2582 if (!NT_STATUS_IS_OK(status)) {
2586 domain_info->trusted_domain_count = trusts_res->count + 1;
2587 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2588 struct netr_OneDomainInfo,
2589 domain_info->trusted_domain_count);
2590 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2592 for (i=0; i < trusts_res->count; i++) {
2593 struct netr_OneDomainInfo *o =
2594 &domain_info->trusted_domains[i];
2595 /* we can't know the guid of trusts outside our forest */
2596 struct GUID trust_domain_guid = GUID_zero();
2597 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2599 status = dsdb_trust_parse_tdo_info(mem_ctx,
2600 trusts_res->msgs[i],
2602 if (!NT_STATUS_IS_OK(status)) {
2606 status = fill_trust_one_domain_info(mem_ctx,
2610 if (!NT_STATUS_IS_OK(status)) {
2615 status = fill_our_one_domain_info(mem_ctx,
2618 &domain_info->trusted_domains[i],
2620 if (!NT_STATUS_IS_OK(status)) {
2624 /* Sets the supported encryption types */
2625 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2626 "msDS-SupportedEncryptionTypes",
2627 default_supported_enc_types);
2629 /* Other host domain information */
2631 lsa_policy_info = talloc(mem_ctx,
2632 struct netr_LsaPolicyInformation);
2633 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2634 ZERO_STRUCTP(lsa_policy_info);
2636 domain_info->lsa_policy = *lsa_policy_info;
2638 /* The DNS hostname is only returned back when there is a chance
2640 if ((r->in.query->workstation_info->workstation_flags
2641 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2642 domain_info->dns_hostname.string = old_dns_hostname;
2644 domain_info->dns_hostname.string = NULL;
2647 domain_info->workstation_flags =
2648 r->in.query->workstation_info->workstation_flags & (
2649 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2651 r->out.info->domain_info = domain_info;
2653 case 2: /* LSA policy information - not used at the moment */
2654 lsa_policy_info = talloc(mem_ctx,
2655 struct netr_LsaPolicyInformation);
2656 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2657 ZERO_STRUCTP(lsa_policy_info);
2659 r->out.info->lsa_policy_info = lsa_policy_info;
2662 return NT_STATUS_INVALID_LEVEL;
2666 return NT_STATUS_OK;
2671 netr_ServerPasswordGet
2673 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2674 struct netr_ServerPasswordGet *r)
2676 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2679 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2680 TALLOC_CTX *mem_ctx,
2681 struct dom_sid *user_sid,
2682 struct ldb_dn *obj_dn)
2684 const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
2685 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2686 struct ldb_dn *rodc_dn;
2688 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2689 const struct dom_sid *additional_sids[] = { NULL, NULL };
2691 struct dom_sid *object_sid;
2692 const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
2694 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2695 dom_sid_string(mem_ctx, user_sid));
2696 if (!ldb_dn_validate(rodc_dn)) goto denied;
2698 /* do the two searches we need */
2699 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2700 DSDB_SEARCH_SHOW_EXTENDED_DN);
2701 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2703 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2704 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2706 object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
2708 additional_sids[0] = object_sid;
2710 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2711 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
2712 if (!W_ERROR_IS_OK(werr)) {
2716 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2717 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
2718 if (!W_ERROR_IS_OK(werr)) {
2723 * The SID list needs to include itself as well as the tokenGroups.
2725 * TODO determine if sIDHistory is required for this check
2727 werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
2728 mem_ctx, "tokenGroups", &token_sids,
2729 additional_sids, 1);
2730 if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
2734 if (never_reveal_sids &&
2735 sid_list_match(token_sids, never_reveal_sids)) {
2740 sid_list_match(token_sids, reveal_sids)) {
2752 netr_NetrLogonSendToSam
2754 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2755 struct netr_NetrLogonSendToSam *r)
2757 struct netlogon_creds_CredentialState *creds;
2758 struct ldb_context *sam_ctx;
2760 DATA_BLOB decrypted_blob;
2761 enum ndr_err_code ndr_err;
2762 struct netr_SendToSamBase base_msg = { 0 };
2764 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2766 r->in.computer_name,
2768 r->out.return_authenticator,
2771 NT_STATUS_NOT_OK_RETURN(nt_status);
2773 switch (creds->secure_channel_type) {
2777 case SEC_CHAN_WKSTA:
2778 case SEC_CHAN_DNS_DOMAIN:
2779 case SEC_CHAN_DOMAIN:
2781 return NT_STATUS_INVALID_PARAMETER;
2783 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
2784 creds->secure_channel_type));
2785 return NT_STATUS_INVALID_PARAMETER;
2788 sam_ctx = samdb_connect(mem_ctx,
2789 dce_call->event_ctx,
2790 dce_call->conn->dce_ctx->lp_ctx,
2791 system_session(dce_call->conn->dce_ctx->lp_ctx),
2792 dce_call->conn->remote_address,
2794 if (sam_ctx == NULL) {
2795 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2798 /* Buffer is meant to be 16-bit aligned */
2799 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2800 netlogon_creds_aes_decrypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2802 netlogon_creds_arcfour_crypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2805 decrypted_blob.data = r->in.opaque_buffer;
2806 decrypted_blob.length = r->in.buffer_len;
2808 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
2809 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
2811 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2812 /* We only partially implement SendToSam */
2813 return NT_STATUS_NOT_IMPLEMENTED;
2816 /* Now 'send' to SAM */
2817 switch (base_msg.message_type) {
2818 case SendToSamResetBadPasswordCount:
2820 struct ldb_message *msg = ldb_msg_new(mem_ctx);
2821 struct ldb_dn *dn = NULL;
2825 ret = ldb_transaction_start(sam_ctx);
2826 if (ret != LDB_SUCCESS) {
2827 return NT_STATUS_INTERNAL_ERROR;
2830 ret = dsdb_find_dn_by_guid(sam_ctx,
2832 &base_msg.message.reset_bad_password.guid,
2835 if (ret != LDB_SUCCESS) {
2836 ldb_transaction_cancel(sam_ctx);
2837 return NT_STATUS_INVALID_PARAMETER;
2840 if (creds->secure_channel_type == SEC_CHAN_RODC &&
2841 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
2842 DEBUG(1, ("Client asked to reset bad password on "
2843 "an arbitrary user: %s\n",
2844 ldb_dn_get_linearized(dn)));
2845 ldb_transaction_cancel(sam_ctx);
2846 return NT_STATUS_INVALID_PARAMETER;
2851 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
2852 if (ret != LDB_SUCCESS) {
2853 ldb_transaction_cancel(sam_ctx);
2854 return NT_STATUS_INVALID_PARAMETER;
2857 ret = dsdb_replace(sam_ctx, msg, 0);
2858 if (ret != LDB_SUCCESS) {
2859 ldb_transaction_cancel(sam_ctx);
2860 return NT_STATUS_INVALID_PARAMETER;
2863 ret = ldb_transaction_commit(sam_ctx);
2864 if (ret != LDB_SUCCESS) {
2865 ldb_transaction_cancel(sam_ctx);
2866 return NT_STATUS_INTERNAL_ERROR;
2872 return NT_STATUS_NOT_IMPLEMENTED;
2875 return NT_STATUS_OK;
2878 struct dcesrv_netr_DsRGetDCName_base_state {
2879 struct dcesrv_call_state *dce_call;
2880 TALLOC_CTX *mem_ctx;
2882 struct netr_DsRGetDCNameEx2 r;
2883 const char *client_site;
2886 struct netr_DsRGetDCName *dc;
2887 struct netr_DsRGetDCNameEx *dcex;
2888 struct netr_DsRGetDCNameEx2 *dcex2;
2892 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
2894 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
2896 struct dcesrv_call_state *dce_call = state->dce_call;
2897 struct auth_session_info *session_info =
2898 dcesrv_call_session_info(dce_call);
2899 TALLOC_CTX *mem_ctx = state->mem_ctx;
2900 struct netr_DsRGetDCNameEx2 *r = &state->r;
2901 struct ldb_context *sam_ctx;
2902 struct netr_DsRGetDCNameInfo *info;
2903 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2904 const struct tsocket_address *local_address;
2905 char *local_addr = NULL;
2906 const struct tsocket_address *remote_address;
2907 char *remote_addr = NULL;
2908 const char *server_site_name;
2910 struct netlogon_samlogon_response response;
2912 const char *dc_name = NULL;
2913 const char *domain_name = NULL;
2915 bool different_domain = true;
2917 ZERO_STRUCTP(r->out.info);
2919 sam_ctx = samdb_connect(state,
2920 dce_call->event_ctx,
2923 dce_call->conn->remote_address,
2925 if (sam_ctx == NULL) {
2926 return WERR_DS_UNAVAILABLE;
2929 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2930 if (tsocket_address_is_inet(local_address, "ip")) {
2931 local_addr = tsocket_address_inet_addr_string(local_address, state);
2932 W_ERROR_HAVE_NO_MEMORY(local_addr);
2935 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2936 if (tsocket_address_is_inet(remote_address, "ip")) {
2937 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
2938 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2941 /* "server_unc" is ignored by w2k3 */
2943 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2944 return WERR_INVALID_FLAGS;
2947 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2948 r->in.flags & DS_PDC_REQUIRED &&
2949 r->in.flags & DS_KDC_REQUIRED) {
2950 return WERR_INVALID_FLAGS;
2952 if (r->in.flags & DS_IS_FLAT_NAME &&
2953 r->in.flags & DS_IS_DNS_NAME) {
2954 return WERR_INVALID_FLAGS;
2956 if (r->in.flags & DS_RETURN_DNS_NAME &&
2957 r->in.flags & DS_RETURN_FLAT_NAME) {
2958 return WERR_INVALID_FLAGS;
2960 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2961 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2962 return WERR_INVALID_FLAGS;
2965 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2967 (DS_DIRECTORY_SERVICE_REQUIRED |
2968 DS_DIRECTORY_SERVICE_PREFERRED |
2969 DS_GC_SERVER_REQUIRED |
2972 return WERR_INVALID_FLAGS;
2975 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2977 return WERR_INVALID_FLAGS;
2981 * If we send an all-zero GUID, we should ignore it as winbind actually
2982 * checks it with a DNS query. Windows also appears to ignore it.
2984 if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
2985 r->in.domain_guid = NULL;
2988 /* Attempt winbind search only if we suspect the domain is incorrect */
2989 if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
2990 if (r->in.flags & DS_IS_FLAT_NAME) {
2991 if (strcasecmp_m(r->in.domain_name,
2992 lpcfg_sam_name(lp_ctx)) == 0) {
2993 different_domain = false;
2995 } else if (r->in.flags & DS_IS_DNS_NAME) {
2996 if (strcasecmp_m(r->in.domain_name,
2997 lpcfg_dnsdomain(lp_ctx)) == 0) {
2998 different_domain = false;
3001 if (strcasecmp_m(r->in.domain_name,
3002 lpcfg_sam_name(lp_ctx)) == 0 ||
3003 strcasecmp_m(r->in.domain_name,
3004 lpcfg_dnsdomain(lp_ctx)) == 0) {
3005 different_domain = false;
3010 * We need to be able to handle empty domain names, where we
3011 * revert to our domain by default.
3013 different_domain = false;
3016 /* Proof server site parameter "site_name" if it was specified */
3017 server_site_name = samdb_server_site_name(sam_ctx, state);
3018 W_ERROR_HAVE_NO_MEMORY(server_site_name);
3019 if (different_domain || (r->in.site_name != NULL &&
3020 (strcasecmp_m(r->in.site_name,
3021 server_site_name) != 0))) {
3023 struct dcerpc_binding_handle *irpc_handle = NULL;
3024 struct tevent_req *subreq = NULL;
3027 * Retrieve the client site to override the winbind response.
3029 * DO NOT use Windows fallback for client site.
3030 * In the case of multiple domains, this is plainly wrong.
3032 * Note: It's possible that the client may belong to multiple
3033 * subnets across domains. It's not clear what this would mean,
3034 * but here we only return what this domain knows.
3036 state->client_site = samdb_client_site_name(sam_ctx,
3042 irpc_handle = irpc_binding_handle_by_name(state,
3045 &ndr_table_winbind);
3046 if (irpc_handle == NULL) {
3047 DEBUG(0,("Failed to get binding_handle for "
3048 "winbind_server task\n"));
3049 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3050 return WERR_SERVICE_NOT_FOUND;
3053 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3055 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3057 subreq = dcerpc_wbint_DsGetDcName_send(state,
3058 dce_call->event_ctx,
3065 if (subreq == NULL) {
3066 return WERR_NOT_ENOUGH_MEMORY;
3069 tevent_req_set_callback(subreq,
3070 dcesrv_netr_DsRGetDCName_base_done,
3076 guid_str = r->in.domain_guid != NULL ?
3077 GUID_string(state, r->in.domain_guid) : NULL;
3079 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3083 r->in.client_account,
3084 r->in.mask, remote_addr,
3085 NETLOGON_NT_VERSION_5EX_WITH_IP,
3086 lp_ctx, &response, true);
3087 if (!NT_STATUS_IS_OK(status)) {
3088 return ntstatus_to_werror(status);
3092 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3093 * (O) flag when the returned forest name is in DNS format. This is here
3094 * always the case (see below).
3096 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3098 if (r->in.flags & DS_RETURN_DNS_NAME) {
3099 dc_name = response.data.nt5_ex.pdc_dns_name;
3100 domain_name = response.data.nt5_ex.dns_domain;
3102 * According to MS-NRPC 2.2.1.2.1 we should set the
3103 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3104 * the returned information is in DNS form.
3106 response.data.nt5_ex.server_type |=
3107 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3108 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3109 dc_name = response.data.nt5_ex.pdc_name;
3110 domain_name = response.data.nt5_ex.domain_name;
3114 * TODO: autodetect what we need to return
3115 * based on the given arguments
3117 dc_name = response.data.nt5_ex.pdc_name;
3118 domain_name = response.data.nt5_ex.domain_name;
3121 if (!dc_name || !dc_name[0]) {
3122 return WERR_NO_SUCH_DOMAIN;
3125 if (!domain_name || !domain_name[0]) {
3126 return WERR_NO_SUCH_DOMAIN;
3129 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3130 W_ERROR_HAVE_NO_MEMORY(info);
3131 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3132 dc_name[0] != '\\'? "\\\\":"",
3133 talloc_strdup(mem_ctx, dc_name));
3134 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3136 pdc_ip = local_addr;
3137 if (pdc_ip == NULL) {
3138 pdc_ip = "127.0.0.1";
3140 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3141 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3142 info->dc_address_type = DS_ADDRESS_TYPE_INET;
3143 info->domain_guid = response.data.nt5_ex.domain_uuid;
3144 info->domain_name = domain_name;
3145 info->forest_name = response.data.nt5_ex.forest;
3146 info->dc_flags = response.data.nt5_ex.server_type;
3147 if (r->in.flags & DS_RETURN_DNS_NAME) {
3148 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3149 * returned if we are returning info->dc_unc containing a FQDN.
3150 * This attribute is called DomainControllerName in the specs,
3151 * it seems that we decide to return FQDN or netbios depending on
3152 * DS_RETURN_DNS_NAME.
3154 info->dc_flags |= DS_DNS_CONTROLLER;
3156 info->dc_site_name = response.data.nt5_ex.server_site;
3157 info->client_site_name = response.data.nt5_ex.client_site;
3159 *r->out.info = info;
3164 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3166 struct dcesrv_netr_DsRGetDCName_base_state *state =
3167 tevent_req_callback_data(subreq,
3168 struct dcesrv_netr_DsRGetDCName_base_state);
3169 struct dcesrv_call_state *dce_call = state->dce_call;
3170 NTSTATUS result, status;
3172 status = dcerpc_wbint_DsGetDcName_recv(subreq,
3175 TALLOC_FREE(subreq);
3177 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3178 state->r.out.result = WERR_TIMEOUT;
3182 if (!NT_STATUS_IS_OK(status)) {
3183 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3185 state->r.out.result = WERR_GEN_FAILURE;
3189 if (!NT_STATUS_IS_OK(result)) {
3190 DBG_NOTICE("DC location via winbind failed - %s\n",
3192 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3196 if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3197 DBG_ERR("DC location via winbind returned no results\n");
3198 state->r.out.result = WERR_GEN_FAILURE;
3202 if (state->r.out.info[0]->dc_unc == NULL) {
3203 DBG_ERR("DC location via winbind returned no DC unc\n");
3204 state->r.out.result = WERR_GEN_FAILURE;
3209 * Either the supplied site name is NULL (possibly via
3210 * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3211 * the input match name.
3213 * TODO: Currently this means that requests with NETBIOS domain
3214 * names can fail because they do not return the site name.
3216 if (state->r.in.site_name == NULL ||
3217 strcasecmp_m("", state->r.in.site_name) == 0 ||
3218 (state->r.out.info[0]->dc_site_name != NULL &&
3219 strcasecmp_m(state->r.out.info[0]->dc_site_name,
3220 state->r.in.site_name) == 0)) {
3222 state->r.out.info[0]->client_site_name =
3223 talloc_move(state->mem_ctx, &state->client_site);
3226 * Make sure to return our DC UNC with // prefix.
3227 * Winbind currently doesn't send the leading slashes
3230 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3231 strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3232 const char *dc_unc = NULL;
3234 dc_unc = talloc_asprintf(state->mem_ctx,
3236 state->r.out.info[0]->dc_unc);
3237 state->r.out.info[0]->dc_unc = dc_unc;
3240 state->r.out.result = WERR_OK;
3242 state->r.out.info = NULL;
3243 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3247 if (state->_r.dcex2 != NULL) {
3248 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3249 r->out.result = state->r.out.result;
3250 } else if (state->_r.dcex != NULL) {
3251 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3252 r->out.result = state->r.out.result;
3253 } else if (state->_r.dc != NULL) {
3254 struct netr_DsRGetDCName *r = state->_r.dc;
3255 r->out.result = state->r.out.result;
3259 status = dcesrv_reply(dce_call);
3260 if (!NT_STATUS_IS_OK(status)) {
3261 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3262 nt_errstr(status)));
3267 netr_DsRGetDCNameEx2
3269 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3270 TALLOC_CTX *mem_ctx,
3271 struct netr_DsRGetDCNameEx2 *r)
3273 struct dcesrv_netr_DsRGetDCName_base_state *state;
3275 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3276 if (state == NULL) {
3277 return WERR_NOT_ENOUGH_MEMORY;
3280 state->dce_call = dce_call;
3281 state->mem_ctx = mem_ctx;
3284 state->_r.dcex2 = r;
3286 return dcesrv_netr_DsRGetDCName_base_call(state);
3292 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3293 struct netr_DsRGetDCNameEx *r)
3295 struct dcesrv_netr_DsRGetDCName_base_state *state;
3297 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3298 if (state == NULL) {
3299 return WERR_NOT_ENOUGH_MEMORY;
3302 state->dce_call = dce_call;
3303 state->mem_ctx = mem_ctx;
3305 state->r.in.server_unc = r->in.server_unc;
3306 state->r.in.client_account = NULL;
3307 state->r.in.mask = 0;
3308 state->r.in.domain_guid = r->in.domain_guid;
3309 state->r.in.domain_name = r->in.domain_name;
3310 state->r.in.site_name = r->in.site_name;
3311 state->r.in.flags = r->in.flags;
3312 state->r.out.info = r->out.info;
3316 return dcesrv_netr_DsRGetDCName_base_call(state);
3322 * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3323 * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3324 * insists that it be ignored.
3326 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3327 struct netr_DsRGetDCName *r)
3329 struct dcesrv_netr_DsRGetDCName_base_state *state;
3331 state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3332 if (state == NULL) {
3333 return WERR_NOT_ENOUGH_MEMORY;
3336 state->dce_call = dce_call;
3337 state->mem_ctx = mem_ctx;
3339 state->r.in.server_unc = r->in.server_unc;
3340 state->r.in.client_account = NULL;
3341 state->r.in.mask = 0;
3342 state->r.in.domain_name = r->in.domain_name;
3343 state->r.in.domain_guid = r->in.domain_guid;
3345 state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3346 state->r.in.flags = r->in.flags;
3347 state->r.out.info = r->out.info;
3351 return dcesrv_netr_DsRGetDCName_base_call(state);
3354 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3356 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3357 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3359 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3364 netr_NetrEnumerateTrustedDomainsEx
3366 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3367 struct netr_NetrEnumerateTrustedDomainsEx *r)
3369 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3374 netr_DsRAddressToSitenamesExW
3376 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3377 struct netr_DsRAddressToSitenamesExW *r)
3379 struct auth_session_info *session_info =
3380 dcesrv_call_session_info(dce_call);
3381 struct ldb_context *sam_ctx;
3382 struct netr_DsRAddressToSitenamesExWCtr *ctr;
3383 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3384 sa_family_t sin_family;
3385 struct sockaddr_in *addr;
3387 struct sockaddr_in6 *addr6;
3388 char addr_str[INET6_ADDRSTRLEN];
3390 char addr_str[INET_ADDRSTRLEN];
3396 sam_ctx = samdb_connect(mem_ctx,
3397 dce_call->event_ctx,
3400 dce_call->conn->remote_address,
3402 if (sam_ctx == NULL) {
3403 return WERR_DS_UNAVAILABLE;
3406 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3407 W_ERROR_HAVE_NO_MEMORY(ctr);
3411 ctr->count = r->in.count;
3412 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3413 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3414 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3415 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3417 for (i=0; i<ctr->count; i++) {
3418 ctr->sitename[i].string = NULL;
3419 ctr->subnetname[i].string = NULL;
3421 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3424 /* The first two byte of the buffer are reserved for the
3425 * "sin_family" but for now only the first one is used. */
3426 sin_family = r->in.addresses[i].buffer[0];
3428 switch (sin_family) {
3430 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3433 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3434 res = inet_ntop(AF_INET, &addr->sin_addr,
3435 addr_str, sizeof(addr_str));
3439 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3442 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3443 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3444 addr_str, sizeof(addr_str));
3455 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
3460 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3461 ctr->subnetname[i].string = subnet_name;
3469 netr_DsRAddressToSitenamesW
3471 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3472 struct netr_DsRAddressToSitenamesW *r)
3474 struct netr_DsRAddressToSitenamesExW r2;
3475 struct netr_DsRAddressToSitenamesWCtr *ctr;
3481 r2.in.server_name = r->in.server_name;
3482 r2.in.count = r->in.count;
3483 r2.in.addresses = r->in.addresses;
3485 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3486 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3488 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3489 W_ERROR_HAVE_NO_MEMORY(ctr);
3493 ctr->count = r->in.count;
3494 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3495 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3497 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3499 for (i=0; i<ctr->count; i++) {
3500 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
3508 netr_DsrGetDcSiteCoverageW
3510 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3511 struct netr_DsrGetDcSiteCoverageW *r)
3513 struct auth_session_info *session_info =
3514 dcesrv_call_session_info(dce_call);
3515 struct ldb_context *sam_ctx;
3516 struct DcSitesCtr *ctr;
3517 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3519 sam_ctx = samdb_connect(mem_ctx,
3520 dce_call->event_ctx,
3523 dce_call->conn->remote_address,
3525 if (sam_ctx == NULL) {
3526 return WERR_DS_UNAVAILABLE;
3529 ctr = talloc(mem_ctx, struct DcSitesCtr);
3530 W_ERROR_HAVE_NO_MEMORY(ctr);
3534 /* For now only return our default site */
3536 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3537 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3538 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3539 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3545 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3546 struct ldb_context *sam_ctx,
3547 struct netr_DomainTrustList *trusts,
3548 uint32_t trust_flags)
3550 struct ldb_dn *system_dn;
3551 struct ldb_message **dom_res = NULL;
3552 const char *trust_attrs[] = { "flatname", "trustPartner",
3553 "securityIdentifier", "trustDirection",
3554 "trustType", "trustAttributes", NULL };
3559 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3560 NETR_TRUST_FLAG_OUTBOUND))) {
3561 return WERR_INVALID_FLAGS;
3564 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3565 ldb_get_default_basedn(sam_ctx),
3566 "(&(objectClass=container)(cn=System))");
3568 return WERR_GEN_FAILURE;
3571 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3572 &dom_res, trust_attrs,
3573 "(objectclass=trustedDomain)");
3575 for (i = 0; i < ret; i++) {
3576 unsigned int trust_dir;
3579 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3580 "trustDirection", 0);
3582 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3583 flags |= NETR_TRUST_FLAG_INBOUND;
3585 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3586 flags |= NETR_TRUST_FLAG_OUTBOUND;
3589 if (!(flags & trust_flags)) {
3590 /* this trust direction was not requested */
3595 trusts->array = talloc_realloc(trusts, trusts->array,
3596 struct netr_DomainTrust,
3598 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3600 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3601 if (!trusts->array[n].netbios_name) {
3602 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3603 "without flatname\n",
3604 ldb_dn_get_linearized(dom_res[i]->dn)));
3607 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3609 trusts->array[n].trust_flags = flags;
3610 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3611 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3612 /* TODO: find if we have parent in the list */
3613 trusts->array[n].parent_index = 0;
3616 trusts->array[n].trust_type =
3617 ldb_msg_find_attr_as_uint(dom_res[i],
3619 trusts->array[n].trust_attributes =
3620 ldb_msg_find_attr_as_uint(dom_res[i],
3621 "trustAttributes", 0);
3623 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3624 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3625 struct dom_sid zero_sid;
3626 ZERO_STRUCT(zero_sid);
3627 trusts->array[n].sid =
3628 dom_sid_dup(trusts, &zero_sid);
3630 trusts->array[n].sid =
3631 samdb_result_dom_sid(trusts, dom_res[i],
3632 "securityIdentifier");
3634 trusts->array[n].guid = GUID_zero();
3636 trusts->count = n + 1;
3639 talloc_free(dom_res);
3644 netr_DsrEnumerateDomainTrusts
3646 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3647 TALLOC_CTX *mem_ctx,
3648 struct netr_DsrEnumerateDomainTrusts *r)
3650 struct auth_session_info *session_info =
3651 dcesrv_call_session_info(dce_call);
3652 struct netr_DomainTrustList *trusts;
3653 struct ldb_context *sam_ctx;
3655 struct ldb_message **dom_res;
3656 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3657 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3658 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3662 if (r->in.trust_flags & 0xFFFFFE00) {
3663 return WERR_INVALID_FLAGS;
3666 /* TODO: turn to hard check once we are sure this is 100% correct */
3667 if (!r->in.server_name) {
3668 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3669 "But received NULL!\n", dnsdomain));
3671 p = strchr(r->in.server_name, '.');
3673 DEBUG(3, ("Invalid domain! Expected name in domain "
3674 "[%s]. But received [%s]!\n",
3675 dnsdomain, r->in.server_name));
3676 p = r->in.server_name;
3680 if (strcasecmp(p, dnsdomain)) {
3681 DEBUG(3, ("Invalid domain! Expected name in domain "
3682 "[%s]. But received [%s]!\n",
3683 dnsdomain, r->in.server_name));
3687 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3688 W_ERROR_HAVE_NO_MEMORY(trusts);
3691 r->out.trusts = trusts;
3693 sam_ctx = samdb_connect(mem_ctx,
3694 dce_call->event_ctx,
3697 dce_call->conn->remote_address,
3699 if (sam_ctx == NULL) {
3700 return WERR_GEN_FAILURE;
3703 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3704 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3706 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3707 trusts, r->in.trust_flags);
3708 W_ERROR_NOT_OK_RETURN(werr);
3711 /* NOTE: we currently are always the root of the forest */
3712 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3713 uint32_t n = trusts->count;
3715 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3716 &dom_res, dom_attrs);
3718 return WERR_GEN_FAILURE;
3721 trusts->count = n + 1;
3722 trusts->array = talloc_realloc(trusts, trusts->array,
3723 struct netr_DomainTrust,
3725 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3727 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3728 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3729 trusts->array[n].trust_flags =
3730 NETR_TRUST_FLAG_NATIVE |
3731 NETR_TRUST_FLAG_TREEROOT |
3732 NETR_TRUST_FLAG_IN_FOREST |
3733 NETR_TRUST_FLAG_PRIMARY;
3734 /* we are always the root domain for now */
3735 trusts->array[n].parent_index = 0;
3736 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3737 trusts->array[n].trust_attributes = 0;
3738 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3741 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3743 talloc_free(dom_res);
3751 netr_DsrDeregisterDNSHostRecords
3753 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3754 struct netr_DsrDeregisterDNSHostRecords *r)
3756 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3760 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3761 struct netr_ServerGetTrustInfo *r);
3764 netr_ServerTrustPasswordsGet
3766 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3767 struct netr_ServerTrustPasswordsGet *r)
3769 struct netr_ServerGetTrustInfo r2 = {};
3770 struct netr_TrustInfo *_ti = NULL;
3773 r2.in.server_name = r->in.server_name;
3774 r2.in.account_name = r->in.account_name;
3775 r2.in.secure_channel_type = r->in.secure_channel_type;
3776 r2.in.computer_name = r->in.computer_name;
3777 r2.in.credential = r->in.credential;
3779 r2.out.return_authenticator = r->out.return_authenticator;
3780 r2.out.new_owf_password = r->out.new_owf_password;
3781 r2.out.old_owf_password = r->out.old_owf_password;
3782 r2.out.trust_info = &_ti;
3784 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3786 r->out.return_authenticator = r2.out.return_authenticator;
3787 r->out.new_owf_password = r2.out.new_owf_password;
3788 r->out.old_owf_password = r2.out.old_owf_password;
3794 netr_DsRGetForestTrustInformation
3796 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3797 struct dcesrv_call_state *dce_call;
3798 TALLOC_CTX *mem_ctx;
3799 struct netr_DsRGetForestTrustInformation *r;
3802 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3804 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3805 TALLOC_CTX *mem_ctx,
3806 struct netr_DsRGetForestTrustInformation *r)
3808 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3809 struct auth_session_info *session_info =
3810 dcesrv_call_session_info(dce_call);
3811 enum security_user_level security_level;
3812 struct ldb_context *sam_ctx = NULL;
3813 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3814 struct dcerpc_binding_handle *irpc_handle = NULL;
3815 struct tevent_req *subreq = NULL;
3816 struct ldb_dn *domain_dn = NULL;
3817 struct ldb_dn *forest_dn = NULL;
3821 security_level = security_session_user_level(session_info, NULL);
3822 if (security_level < SECURITY_USER) {
3823 return WERR_ACCESS_DENIED;
3826 if (r->in.flags & 0xFFFFFFFE) {
3827 return WERR_INVALID_FLAGS;
3830 sam_ctx = samdb_connect(mem_ctx,
3831 dce_call->event_ctx,
3834 dce_call->conn->remote_address,
3836 if (sam_ctx == NULL) {
3837 return WERR_GEN_FAILURE;
3840 domain_dn = ldb_get_default_basedn(sam_ctx);
3841 if (domain_dn == NULL) {
3842 return WERR_GEN_FAILURE;
3845 forest_dn = ldb_get_root_basedn(sam_ctx);
3846 if (forest_dn == NULL) {
3847 return WERR_GEN_FAILURE;
3850 cmp = ldb_dn_compare(domain_dn, forest_dn);
3852 return WERR_NERR_ACFNOTLOADED;
3855 forest_level = dsdb_forest_functional_level(sam_ctx);
3856 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3857 return WERR_INVALID_FUNCTION;
3860 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3861 if (!samdb_is_pdc(sam_ctx)) {
3862 return WERR_NERR_NOTPRIMARY;
3865 if (r->in.trusted_domain_name == NULL) {
3866 return WERR_INVALID_FLAGS;
3870 if (r->in.trusted_domain_name == NULL) {
3874 * information about our own domain
3876 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3877 r->out.forest_trust_info);
3878 if (!NT_STATUS_IS_OK(status)) {
3879 return ntstatus_to_werror(status);
3886 * Forward the request to winbindd
3889 state = talloc_zero(mem_ctx,
3890 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3891 if (state == NULL) {
3892 return WERR_NOT_ENOUGH_MEMORY;
3894 state->dce_call = dce_call;
3895 state->mem_ctx = mem_ctx;
3898 irpc_handle = irpc_binding_handle_by_name(state,
3899 state->dce_call->msg_ctx,
3901 &ndr_table_winbind);
3902 if (irpc_handle == NULL) {
3903 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3904 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3905 return WERR_SERVICE_NOT_FOUND;
3909 * 60 seconds timeout should be enough
3911 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3913 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3914 state->dce_call->event_ctx,
3916 r->in.trusted_domain_name,
3918 r->out.forest_trust_info);
3919 if (subreq == NULL) {
3920 return WERR_NOT_ENOUGH_MEMORY;
3922 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3923 tevent_req_set_callback(subreq,
3924 dcesrv_netr_DsRGetForestTrustInformation_done,
3930 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3932 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3933 tevent_req_callback_data(subreq,
3934 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3937 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3939 &state->r->out.result);
3940 TALLOC_FREE(subreq);
3941 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3942 state->r->out.result = WERR_TIMEOUT;
3943 } else if (!NT_STATUS_IS_OK(status)) {
3944 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3945 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3946 nt_errstr(status)));
3949 status = dcesrv_reply(state->dce_call);
3950 if (!NT_STATUS_IS_OK(status)) {
3951 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3956 netr_GetForestTrustInformation
3958 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3959 TALLOC_CTX *mem_ctx,
3960 struct netr_GetForestTrustInformation *r)
3962 struct auth_session_info *session_info =
3963 dcesrv_call_session_info(dce_call);
3964 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3965 struct netlogon_creds_CredentialState *creds = NULL;
3966 struct ldb_context *sam_ctx = NULL;
3967 struct ldb_dn *domain_dn = NULL;
3968 struct ldb_dn *forest_dn = NULL;
3973 status = dcesrv_netr_creds_server_step_check(dce_call,
3975 r->in.computer_name,
3977 r->out.return_authenticator,
3979 if (!NT_STATUS_IS_OK(status)) {
3983 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3984 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3985 return NT_STATUS_NOT_IMPLEMENTED;
3988 sam_ctx = samdb_connect(mem_ctx,
3989 dce_call->event_ctx,
3992 dce_call->conn->remote_address,
3994 if (sam_ctx == NULL) {
3995 return NT_STATUS_INTERNAL_ERROR;
3998 /* TODO: check r->in.server_name is our name */
4000 domain_dn = ldb_get_default_basedn(sam_ctx);
4001 if (domain_dn == NULL) {
4002 return NT_STATUS_INTERNAL_ERROR;
4005 forest_dn = ldb_get_root_basedn(sam_ctx);
4006 if (forest_dn == NULL) {
4007 return NT_STATUS_INTERNAL_ERROR;
4010 cmp = ldb_dn_compare(domain_dn, forest_dn);
4012 return NT_STATUS_INVALID_DOMAIN_STATE;
4015 forest_level = dsdb_forest_functional_level(sam_ctx);
4016 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4017 return NT_STATUS_INVALID_DOMAIN_STATE;
4020 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4021 r->out.forest_trust_info);
4022 if (!NT_STATUS_IS_OK(status)) {
4026 return NT_STATUS_OK;
4031 netr_ServerGetTrustInfo
4033 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4034 struct netr_ServerGetTrustInfo *r)
4036 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4037 struct netlogon_creds_CredentialState *creds = NULL;
4038 struct ldb_context *sam_ctx = NULL;
4039 const char * const attrs[] = {
4042 "userAccountControl",
4045 struct ldb_message **res = NULL;
4046 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4049 const char *asid = NULL;
4051 const char *aname = NULL;
4052 struct ldb_message *tdo_msg = NULL;
4053 const char * const tdo_attrs[] = {
4054 "trustAuthIncoming",
4058 struct netr_TrustInfo *trust_info = NULL;
4060 ZERO_STRUCTP(r->out.new_owf_password);
4061 ZERO_STRUCTP(r->out.old_owf_password);
4063 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4065 r->in.computer_name,
4067 r->out.return_authenticator,
4069 if (!NT_STATUS_IS_OK(nt_status)) {
4073 /* TODO: check r->in.server_name is our name */
4075 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4076 return NT_STATUS_INVALID_PARAMETER;
4079 if (r->in.secure_channel_type != creds->secure_channel_type) {
4080 return NT_STATUS_INVALID_PARAMETER;
4083 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4084 return NT_STATUS_INVALID_PARAMETER;
4087 sam_ctx = samdb_connect(mem_ctx,
4088 dce_call->event_ctx,
4090 system_session(lp_ctx),
4091 dce_call->conn->remote_address,
4093 if (sam_ctx == NULL) {
4094 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4097 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4099 return NT_STATUS_NO_MEMORY;
4102 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4103 "(&(objectClass=user)(objectSid=%s))",
4106 return NT_STATUS_ACCOUNT_DISABLED;
4109 switch (creds->secure_channel_type) {
4110 case SEC_CHAN_DNS_DOMAIN:
4111 case SEC_CHAN_DOMAIN:
4112 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4114 if (uac & UF_ACCOUNTDISABLE) {
4115 return NT_STATUS_ACCOUNT_DISABLED;
4118 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4119 return NT_STATUS_ACCOUNT_DISABLED;
4122 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4123 if (aname == NULL) {
4124 return NT_STATUS_ACCOUNT_DISABLED;
4127 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4128 SEC_CHAN_DOMAIN, aname,
4129 tdo_attrs, mem_ctx, &tdo_msg);
4130 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4131 return NT_STATUS_ACCOUNT_DISABLED;
4133 if (!NT_STATUS_IS_OK(nt_status)) {
4137 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4140 if (!NT_STATUS_IS_OK(nt_status)) {
4144 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4145 if (trust_info == NULL) {
4146 return NT_STATUS_NO_MEMORY;
4149 trust_info->count = 1;
4150 trust_info->data = talloc_array(trust_info, uint32_t,
4152 if (trust_info->data == NULL) {
4153 return NT_STATUS_NO_MEMORY;
4156 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4162 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4165 if (!NT_STATUS_IS_OK(nt_status)) {
4169 prevNtHash = talloc(mem_ctx, struct samr_Password);
4170 if (prevNtHash == NULL) {
4171 return NT_STATUS_NO_MEMORY;
4174 E_md4hash("", prevNtHash->hash);
4178 if (curNtHash != NULL) {
4179 *r->out.new_owf_password = *curNtHash;
4180 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4182 if (prevNtHash != NULL) {
4183 *r->out.old_owf_password = *prevNtHash;
4184 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4187 if (trust_info != NULL) {
4188 *r->out.trust_info = trust_info;
4191 return NT_STATUS_OK;
4197 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4198 struct netr_Unused47 *r)
4200 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4204 struct netr_dnsupdate_RODC_state {
4205 struct dcesrv_call_state *dce_call;
4206 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4207 struct dnsupdate_RODC *r2;
4211 called when the forwarded RODC dns update request is finished
4213 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4215 struct netr_dnsupdate_RODC_state *st =
4216 tevent_req_callback_data(subreq,
4217 struct netr_dnsupdate_RODC_state);
4220 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4221 TALLOC_FREE(subreq);
4222 if (!NT_STATUS_IS_OK(status)) {
4223 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4224 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4227 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4229 status = dcesrv_reply(st->dce_call);
4230 if (!NT_STATUS_IS_OK(status)) {
4231 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4236 netr_DsrUpdateReadOnlyServerDnsRecords
4238 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4239 TALLOC_CTX *mem_ctx,
4240 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4242 struct netlogon_creds_CredentialState *creds;
4244 struct dcerpc_binding_handle *binding_handle;
4245 struct netr_dnsupdate_RODC_state *st;
4246 struct tevent_req *subreq;
4248 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4250 r->in.computer_name,
4252 r->out.return_authenticator,
4254 NT_STATUS_NOT_OK_RETURN(nt_status);
4256 if (creds->secure_channel_type != SEC_CHAN_RODC) {
4257 return NT_STATUS_ACCESS_DENIED;
4260 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4261 NT_STATUS_HAVE_NO_MEMORY(st);
4263 st->dce_call = dce_call;
4265 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4266 NT_STATUS_HAVE_NO_MEMORY(st->r2);
4268 st->r2->in.dom_sid = creds->sid;
4269 st->r2->in.site_name = r->in.site_name;
4270 st->r2->in.dns_ttl = r->in.dns_ttl;
4271 st->r2->in.dns_names = r->in.dns_names;
4272 st->r2->out.dns_names = r->out.dns_names;
4274 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
4275 "dnsupdate", &ndr_table_irpc);
4276 if (binding_handle == NULL) {
4277 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4278 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4279 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4282 /* forward the call */
4283 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4284 binding_handle, st->r2);
4285 NT_STATUS_HAVE_NO_MEMORY(subreq);
4287 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4289 /* setup the callback */
4290 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4292 return NT_STATUS_OK;
4296 /* include the generated boilerplate */
4297 #include "librpc/gen_ndr/ndr_netlogon_s.c"