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"
47 #define DCESRV_INTERFACE_NETLOGON_BIND(call, iface) \
48 dcesrv_interface_netlogon_bind(call, iface)
51 * This #define allows the netlogon interface to accept invalid
52 * association groups, because association groups are to coordinate
53 * handles, and handles are not used in NETLOGON. This in turn avoids
54 * the need to coordinate these across multiple possible NETLOGON
57 #define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
59 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_call_state *dce_call,
60 const struct dcesrv_interface *iface)
62 return dcesrv_interface_bind_reject_connect(dce_call, iface);
65 struct netlogon_server_pipe_state {
66 struct netr_Credential client_challenge;
67 struct netr_Credential server_challenge;
70 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
71 struct netr_ServerReqChallenge *r)
73 struct netlogon_server_pipe_state *pipe_state =
74 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
77 ZERO_STRUCTP(r->out.return_credentials);
80 talloc_free(pipe_state);
81 dce_call->context->private_data = NULL;
84 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
85 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
87 pipe_state->client_challenge = *r->in.credentials;
89 generate_random_buffer(pipe_state->server_challenge.data,
90 sizeof(pipe_state->server_challenge.data));
92 *r->out.return_credentials = pipe_state->server_challenge;
94 dce_call->context->private_data = pipe_state;
96 ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
97 &pipe_state->client_challenge,
98 &pipe_state->server_challenge,
100 if (!NT_STATUS_IS_OK(ntstatus)) {
107 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
108 struct netr_ServerAuthenticate3 *r)
110 struct netlogon_server_pipe_state *pipe_state =
111 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
112 bool challenge_valid = false;
113 struct netlogon_server_pipe_state challenge;
114 struct netlogon_creds_CredentialState *creds;
115 struct ldb_context *sam_ctx;
116 struct samr_Password *curNtHash = NULL;
117 struct samr_Password *prevNtHash = NULL;
118 uint32_t user_account_control;
120 struct ldb_message **msgs;
122 const char *attrs[] = {"unicodePwd", "userAccountControl",
124 const char *account_name;
125 uint32_t server_flags = 0;
126 uint32_t negotiate_flags = 0;
127 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
128 bool reject_des_client = !allow_nt4_crypto;
129 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
130 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
131 bool reject_none_rpc = (schannel == true);
133 ZERO_STRUCTP(r->out.return_credentials);
136 if (pipe_state != NULL) {
137 dce_call->context->private_data = NULL;
140 * If we had a challenge remembered on the connection
141 * consider this for usage. This can't be cleanup
144 * This is the default code path for typical clients
145 * which call netr_ServerReqChallenge() and
146 * netr_ServerAuthenticate3() on the same dcerpc connection.
148 challenge = *pipe_state;
150 challenge_valid = true;
156 * Fallback and try to get the challenge from
159 * If too many clients are using this code path,
160 * they may destroy their cache entries as the
161 * TDB has a fixed size limited via a lossy hash
163 * The TDB used is the schannel store, which is
164 * initialised at startup.
166 * NOTE: The challenge is deleted from the DB as soon as it is
167 * fetched, to prevent reuse.
171 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
172 &challenge.client_challenge,
173 &challenge.server_challenge,
174 r->in.computer_name);
176 if (!NT_STATUS_IS_OK(ntstatus)) {
177 ZERO_STRUCT(challenge);
179 challenge_valid = true;
183 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
184 NETLOGON_NEG_PERSISTENT_SAMREPL |
185 NETLOGON_NEG_ARCFOUR |
186 NETLOGON_NEG_PROMOTION_COUNT |
187 NETLOGON_NEG_CHANGELOG_BDC |
188 NETLOGON_NEG_FULL_SYNC_REPL |
189 NETLOGON_NEG_MULTIPLE_SIDS |
191 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
192 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
193 NETLOGON_NEG_GENERIC_PASSTHROUGH |
194 NETLOGON_NEG_CONCURRENT_RPC |
195 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
196 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
197 NETLOGON_NEG_STRONG_KEYS |
198 NETLOGON_NEG_TRANSITIVE_TRUSTS |
199 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
200 NETLOGON_NEG_PASSWORD_SET2 |
201 NETLOGON_NEG_GETDOMAININFO |
202 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
203 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
204 NETLOGON_NEG_RODC_PASSTHROUGH |
205 NETLOGON_NEG_SUPPORTS_AES |
206 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
207 NETLOGON_NEG_AUTHENTICATED_RPC;
209 negotiate_flags = *r->in.negotiate_flags & server_flags;
211 if (negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
212 reject_none_rpc = false;
215 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
216 reject_des_client = false;
219 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
220 reject_des_client = false;
221 reject_md5_client = false;
224 if (reject_des_client || reject_md5_client) {
226 * Here we match Windows 2012 and return no flags.
228 *r->out.negotiate_flags = 0;
229 return NT_STATUS_DOWNGRADE_DETECTED;
233 * This talloc_free is important to prevent re-use of the
234 * challenge. We have to delay it this far due to NETApp
236 * https://bugzilla.samba.org/show_bug.cgi?id=11291
238 TALLOC_FREE(pipe_state);
241 * At this point we must also cleanup the TDB cache
242 * entry, if we fail the client needs to call
243 * netr_ServerReqChallenge again.
245 * Note: this handles a non existing record just fine,
246 * the r->in.computer_name might not be the one used
247 * in netr_ServerReqChallenge(), but we are trying to
248 * just tidy up the normal case to prevent re-use.
250 schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
251 r->in.computer_name);
254 * According to Microsoft (see bugid #6099)
255 * Windows 7 looks at the negotiate_flags
256 * returned in this structure *even if the
257 * call fails with access denied!
259 *r->out.negotiate_flags = negotiate_flags;
261 if (reject_none_rpc) {
262 /* schannel must be used, but client did not offer it. */
263 DEBUG(0,("%s: schannel required but client failed "
264 "to offer it. Client was %s\n",
265 __func__, r->in.account_name));
266 return NT_STATUS_ACCESS_DENIED;
269 switch (r->in.secure_channel_type) {
271 case SEC_CHAN_DNS_DOMAIN:
272 case SEC_CHAN_DOMAIN:
277 return NT_STATUS_INVALID_PARAMETER;
279 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
280 r->in.secure_channel_type));
281 return NT_STATUS_INVALID_PARAMETER;
284 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
285 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
286 if (sam_ctx == NULL) {
287 return NT_STATUS_INVALID_SYSTEM_SERVICE;
290 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
291 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
293 struct ldb_message *tdo_msg = NULL;
294 const char * const tdo_attrs[] = {
300 char *encoded_name = NULL;
302 const char *flatname = NULL;
304 bool require_trailer = true;
305 const char *netbios = NULL;
306 const char *dns = NULL;
308 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
310 require_trailer = false;
313 encoded_name = ldb_binary_encode_string(mem_ctx,
315 if (encoded_name == NULL) {
316 return NT_STATUS_NO_MEMORY;
319 len = strlen(encoded_name);
321 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
324 if (require_trailer && encoded_name[len - 1] != trailer) {
325 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
327 encoded_name[len - 1] = '\0';
329 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
332 netbios = encoded_name;
335 nt_status = dsdb_trust_search_tdo(sam_ctx,
337 tdo_attrs, mem_ctx, &tdo_msg);
338 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
339 DEBUG(2, ("Client asked for a trusted domain secure channel, "
340 "but there's no tdo for [%s] => [%s] \n",
341 r->in.account_name, encoded_name));
342 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
344 if (!NT_STATUS_IS_OK(nt_status)) {
348 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
351 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
352 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
354 if (!NT_STATUS_IS_OK(nt_status)) {
358 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
359 if (flatname == NULL) {
360 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
363 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
364 if (account_name == NULL) {
365 return NT_STATUS_NO_MEMORY;
368 account_name = r->in.account_name;
371 /* pull the user attributes */
372 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
373 "(&(sAMAccountName=%s)(objectclass=user))",
374 ldb_binary_encode_string(mem_ctx, account_name));
376 if (num_records == 0) {
377 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
378 r->in.account_name));
379 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
382 if (num_records > 1) {
383 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
384 return NT_STATUS_INTERNAL_DB_CORRUPTION;
387 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
389 if (user_account_control & UF_ACCOUNTDISABLE) {
390 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
391 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
394 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
395 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
396 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
397 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
399 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
400 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
401 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
402 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
404 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
406 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
407 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
408 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
409 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
411 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
412 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
413 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
414 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
417 /* we should never reach this */
418 return NT_STATUS_INTERNAL_ERROR;
421 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
422 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
423 dce_call->conn->dce_ctx->lp_ctx,
424 msgs[0], NULL, &curNtHash);
425 if (!NT_STATUS_IS_OK(nt_status)) {
426 return NT_STATUS_ACCESS_DENIED;
430 if (curNtHash == NULL) {
431 return NT_STATUS_ACCESS_DENIED;
434 if (!challenge_valid) {
435 DEBUG(1, ("No challenge requested by client [%s/%s], "
436 "cannot authenticate\n",
438 r->in.account_name));
439 return NT_STATUS_ACCESS_DENIED;
442 creds = netlogon_creds_server_init(mem_ctx,
445 r->in.secure_channel_type,
446 &challenge.client_challenge,
447 &challenge.server_challenge,
450 r->out.return_credentials,
452 if (creds == NULL && prevNtHash != NULL) {
454 * We fallback to the previous password for domain trusts.
456 * Note that lpcfg_old_password_allowed_period() doesn't
459 creds = netlogon_creds_server_init(mem_ctx,
462 r->in.secure_channel_type,
463 &challenge.client_challenge,
464 &challenge.server_challenge,
467 r->out.return_credentials,
471 return NT_STATUS_ACCESS_DENIED;
474 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
476 nt_status = schannel_save_creds_state(mem_ctx,
477 dce_call->conn->dce_ctx->lp_ctx,
479 if (!NT_STATUS_IS_OK(nt_status)) {
480 ZERO_STRUCTP(r->out.return_credentials);
484 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
490 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
491 struct netr_ServerAuthenticate *r)
493 struct netr_ServerAuthenticate3 a;
496 * negotiate_flags is used as an [in] parameter
497 * so it need to be initialised.
499 * (I think ... = 0; seems wrong here --metze)
501 uint32_t negotiate_flags_in = 0;
502 uint32_t negotiate_flags_out = 0;
504 a.in.server_name = r->in.server_name;
505 a.in.account_name = r->in.account_name;
506 a.in.secure_channel_type = r->in.secure_channel_type;
507 a.in.computer_name = r->in.computer_name;
508 a.in.credentials = r->in.credentials;
509 a.in.negotiate_flags = &negotiate_flags_in;
511 a.out.return_credentials = r->out.return_credentials;
513 a.out.negotiate_flags = &negotiate_flags_out;
515 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
518 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
519 struct netr_ServerAuthenticate2 *r)
521 struct netr_ServerAuthenticate3 r3;
524 r3.in.server_name = r->in.server_name;
525 r3.in.account_name = r->in.account_name;
526 r3.in.secure_channel_type = r->in.secure_channel_type;
527 r3.in.computer_name = r->in.computer_name;
528 r3.in.credentials = r->in.credentials;
529 r3.out.return_credentials = r->out.return_credentials;
530 r3.in.negotiate_flags = r->in.negotiate_flags;
531 r3.out.negotiate_flags = r->out.negotiate_flags;
534 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
538 * NOTE: The following functions are nearly identical to the ones available in
539 * source3/rpc_server/srv_nelog_nt.c
540 * The reason we keep 2 copies is that they use different structures to
541 * represent the auth_info and the decrpc pipes.
545 * If schannel is required for this call test that it actually is available.
547 static NTSTATUS schannel_check_required(const struct dcesrv_auth *auth_info,
548 const char *computer_name,
549 bool integrity, bool privacy)
552 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
553 if (!privacy && !integrity) {
557 if ((!privacy && integrity) &&
558 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
562 if ((privacy || integrity) &&
563 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
568 /* test didn't pass */
569 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
572 return NT_STATUS_ACCESS_DENIED;
575 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
577 const char *computer_name,
578 struct netr_Authenticator *received_authenticator,
579 struct netr_Authenticator *return_authenticator,
580 struct netlogon_creds_CredentialState **creds_out)
583 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
584 bool schannel_global_required = (schannel == true);
586 if (schannel_global_required) {
587 nt_status = schannel_check_required(&dce_call->conn->auth_state,
590 if (!NT_STATUS_IS_OK(nt_status)) {
595 nt_status = schannel_check_creds_state(mem_ctx,
596 dce_call->conn->dce_ctx->lp_ctx,
598 received_authenticator,
599 return_authenticator,
605 Change the machine account password for the currently connected
606 client. Supplies only the NT#.
609 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
610 struct netr_ServerPasswordSet *r)
612 struct netlogon_creds_CredentialState *creds;
613 struct ldb_context *sam_ctx;
614 const char * const attrs[] = { "unicodePwd", NULL };
615 struct ldb_message **res;
616 struct samr_Password *oldNtHash;
620 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
623 r->in.credential, r->out.return_authenticator,
625 NT_STATUS_NOT_OK_RETURN(nt_status);
627 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
628 if (sam_ctx == NULL) {
629 return NT_STATUS_INVALID_SYSTEM_SERVICE;
632 netlogon_creds_des_decrypt(creds, r->in.new_password);
634 /* fetch the old password hashes (the NT hash has to exist) */
636 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
637 "(&(objectClass=user)(objectSid=%s))",
638 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
640 return NT_STATUS_WRONG_PASSWORD;
643 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
644 dce_call->conn->dce_ctx->lp_ctx,
645 res[0], NULL, &oldNtHash);
646 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
647 return NT_STATUS_WRONG_PASSWORD;
650 /* Using the sid for the account as the key, set the password */
651 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
653 NULL, /* Don't have version */
654 NULL, /* Don't have plaintext */
655 NULL, r->in.new_password,
656 NULL, oldNtHash, /* Password change */
662 Change the machine account password for the currently connected
663 client. Supplies new plaintext.
665 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
666 struct netr_ServerPasswordSet2 *r)
668 struct netlogon_creds_CredentialState *creds;
669 struct ldb_context *sam_ctx;
670 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
671 struct ldb_message **res;
672 struct samr_Password *oldLmHash, *oldNtHash;
673 struct NL_PASSWORD_VERSION version = {};
674 const uint32_t *new_version = NULL;
676 DATA_BLOB new_password;
678 struct samr_CryptPassword password_buf;
680 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
683 r->in.credential, r->out.return_authenticator,
685 NT_STATUS_NOT_OK_RETURN(nt_status);
687 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
688 if (sam_ctx == NULL) {
689 return NT_STATUS_INVALID_SYSTEM_SERVICE;
692 memcpy(password_buf.data, r->in.new_password->data, 512);
693 SIVAL(password_buf.data, 512, r->in.new_password->length);
695 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
696 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
698 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
701 switch (creds->secure_channel_type) {
702 case SEC_CHAN_DOMAIN:
703 case SEC_CHAN_DNS_DOMAIN: {
704 uint32_t len = IVAL(password_buf.data, 512);
706 uint32_t ofs = 500 - len;
709 p = password_buf.data + ofs;
711 version.ReservedField = IVAL(p, 0);
712 version.PasswordVersionNumber = IVAL(p, 4);
713 version.PasswordVersionPresent = IVAL(p, 8);
715 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
716 new_version = &version.PasswordVersionNumber;
724 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
725 DEBUG(3,("samr: failed to decode password buffer\n"));
726 return NT_STATUS_WRONG_PASSWORD;
729 /* fetch the old password hashes (at least one of both has to exist) */
731 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
732 "(&(objectClass=user)(objectSid=%s))",
733 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
735 return NT_STATUS_WRONG_PASSWORD;
738 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
739 dce_call->conn->dce_ctx->lp_ctx,
740 res[0], &oldLmHash, &oldNtHash);
741 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
742 return NT_STATUS_WRONG_PASSWORD;
745 /* Using the sid for the account as the key, set the password */
746 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
749 &new_password, /* we have plaintext */
751 oldLmHash, oldNtHash, /* Password change */
760 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
761 struct netr_LogonUasLogon *r)
763 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
770 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
771 struct netr_LogonUasLogoff *r)
773 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
777 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
779 switch (r->in.logon_level) {
780 case NetlogonInteractiveInformation:
781 case NetlogonServiceInformation:
782 case NetlogonInteractiveTransitiveInformation:
783 case NetlogonServiceTransitiveInformation:
784 if (r->in.logon->password == NULL) {
785 return NT_STATUS_INVALID_PARAMETER;
788 switch (r->in.validation_level) {
789 case NetlogonValidationSamInfo: /* 2 */
790 case NetlogonValidationSamInfo2: /* 3 */
791 case NetlogonValidationSamInfo4: /* 6 */
794 return NT_STATUS_INVALID_INFO_CLASS;
798 case NetlogonNetworkInformation:
799 case NetlogonNetworkTransitiveInformation:
800 if (r->in.logon->network == NULL) {
801 return NT_STATUS_INVALID_PARAMETER;
804 switch (r->in.validation_level) {
805 case NetlogonValidationSamInfo: /* 2 */
806 case NetlogonValidationSamInfo2: /* 3 */
807 case NetlogonValidationSamInfo4: /* 6 */
810 return NT_STATUS_INVALID_INFO_CLASS;
815 case NetlogonGenericInformation:
816 if (r->in.logon->generic == NULL) {
817 return NT_STATUS_INVALID_PARAMETER;
820 switch (r->in.validation_level) {
821 /* TODO: case NetlogonValidationGenericInfo: 4 */
822 case NetlogonValidationGenericInfo2: /* 5 */
825 return NT_STATUS_INVALID_INFO_CLASS;
830 return NT_STATUS_INVALID_PARAMETER;
837 netr_LogonSamLogon_base
839 This version of the function allows other wrappers to say 'do not check the credentials'
841 We can't do the traditional 'wrapping' format completely, as this
842 function must only run under schannel
844 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
845 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
847 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
848 const char *workgroup = lpcfg_workgroup(lp_ctx);
849 struct auth4_context *auth_context = NULL;
850 struct auth_usersupplied_info *user_info = NULL;
851 struct auth_user_info_dc *user_info_dc = NULL;
853 struct netr_SamInfo2 *sam2 = NULL;
854 struct netr_SamInfo3 *sam3 = NULL;
855 struct netr_SamInfo6 *sam6 = NULL;
857 *r->out.authoritative = 1;
859 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
861 * Currently we're always the forest root ourself.
863 return NT_STATUS_NO_SUCH_USER;
866 if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
868 * Currently we don't support trusts correctly yet.
870 return NT_STATUS_NO_SUCH_USER;
873 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
874 NT_STATUS_HAVE_NO_MEMORY(user_info);
876 user_info->service_description = "SamLogon";
878 netlogon_creds_decrypt_samlogon_logon(creds,
882 switch (r->in.logon_level) {
883 case NetlogonInteractiveInformation:
884 case NetlogonServiceInformation:
885 case NetlogonInteractiveTransitiveInformation:
886 case NetlogonServiceTransitiveInformation:
887 case NetlogonNetworkInformation:
888 case NetlogonNetworkTransitiveInformation:
890 nt_status = auth_context_create_for_netlogon(mem_ctx,
891 dce_call->event_ctx, dce_call->msg_ctx,
892 dce_call->conn->dce_ctx->lp_ctx,
894 NT_STATUS_NOT_OK_RETURN(nt_status);
896 user_info->remote_host = dce_call->conn->remote_address;
897 user_info->local_host = dce_call->conn->local_address;
899 user_info->netlogon_trust_account.secure_channel_type
900 = creds->secure_channel_type;
901 user_info->netlogon_trust_account.negotiate_flags
902 = creds->negotiate_flags;
905 * These two can be unrelated when the account is
906 * actually that of a trusted domain, so we want to
907 * know which DC in that trusted domain contacted
910 user_info->netlogon_trust_account.computer_name
911 = creds->computer_name;
912 user_info->netlogon_trust_account.account_name
913 = creds->account_name;
914 user_info->netlogon_trust_account.sid
918 /* We do not need to set up the user_info in this case */
922 switch (r->in.logon_level) {
923 case NetlogonInteractiveInformation:
924 case NetlogonServiceInformation:
925 case NetlogonInteractiveTransitiveInformation:
926 case NetlogonServiceTransitiveInformation:
927 user_info->auth_description = "interactive";
929 user_info->logon_parameters
930 = r->in.logon->password->identity_info.parameter_control;
931 user_info->client.account_name
932 = r->in.logon->password->identity_info.account_name.string;
933 user_info->client.domain_name
934 = r->in.logon->password->identity_info.domain_name.string;
935 user_info->workstation_name
936 = r->in.logon->password->identity_info.workstation.string;
937 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
938 user_info->password_state = AUTH_PASSWORD_HASH;
940 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
941 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
942 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
944 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
945 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
946 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
949 case NetlogonNetworkInformation:
950 case NetlogonNetworkTransitiveInformation:
951 user_info->auth_description = "network";
953 nt_status = auth_context_set_challenge(
955 r->in.logon->network->challenge,
956 "netr_LogonSamLogonWithFlags");
957 NT_STATUS_NOT_OK_RETURN(nt_status);
959 user_info->logon_parameters
960 = r->in.logon->network->identity_info.parameter_control;
961 user_info->client.account_name
962 = r->in.logon->network->identity_info.account_name.string;
963 user_info->client.domain_name
964 = r->in.logon->network->identity_info.domain_name.string;
965 user_info->workstation_name
966 = r->in.logon->network->identity_info.workstation.string;
968 user_info->password_state = AUTH_PASSWORD_RESPONSE;
969 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
970 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
972 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
973 user_info->client.account_name,
974 user_info->client.domain_name,
975 user_info->password.response.nt,
977 NT_STATUS_NOT_OK_RETURN(nt_status);
982 case NetlogonGenericInformation:
984 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
986 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
989 /* Using DES to verify kerberos tickets makes no sense */
990 return NT_STATUS_INVALID_PARAMETER;
993 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
995 struct dcerpc_binding_handle *irpc_handle;
996 struct kdc_check_generic_kerberos check;
997 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
998 NT_STATUS_HAVE_NO_MEMORY(generic);
999 *r->out.authoritative = 1;
1001 /* TODO: Describe and deal with these flags */
1004 r->out.validation->generic = generic;
1006 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1010 if (irpc_handle == NULL) {
1011 return NT_STATUS_NO_LOGON_SERVERS;
1014 check.in.generic_request =
1015 data_blob_const(r->in.logon->generic->data,
1016 r->in.logon->generic->length);
1019 * TODO: make this async and avoid
1020 * dcerpc_binding_handle_set_sync_ev()
1022 dcerpc_binding_handle_set_sync_ev(irpc_handle,
1023 dce_call->event_ctx);
1024 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
1027 if (!NT_STATUS_IS_OK(status)) {
1030 generic->length = check.out.generic_reply.length;
1031 generic->data = check.out.generic_reply.data;
1032 return NT_STATUS_OK;
1035 /* Until we get an implemetnation of these other packages */
1036 return NT_STATUS_INVALID_PARAMETER;
1039 return NT_STATUS_INVALID_PARAMETER;
1042 nt_status = auth_check_password(auth_context, mem_ctx, user_info,
1043 &user_info_dc, r->out.authoritative);
1044 NT_STATUS_NOT_OK_RETURN(nt_status);
1046 switch (r->in.validation_level) {
1048 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1051 NT_STATUS_NOT_OK_RETURN(nt_status);
1053 r->out.validation->sam2 = sam2;
1057 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1060 NT_STATUS_NOT_OK_RETURN(nt_status);
1062 r->out.validation->sam3 = sam3;
1066 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1067 return NT_STATUS_INVALID_PARAMETER;
1070 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1073 NT_STATUS_NOT_OK_RETURN(nt_status);
1075 r->out.validation->sam6 = sam6;
1079 return NT_STATUS_INVALID_INFO_CLASS;
1082 netlogon_creds_encrypt_samlogon_validation(creds,
1083 r->in.validation_level,
1086 /* TODO: Describe and deal with these flags */
1089 return NT_STATUS_OK;
1092 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1093 struct netr_LogonSamLogonEx *r)
1096 struct netlogon_creds_CredentialState *creds;
1098 *r->out.authoritative = 1;
1100 nt_status = dcesrv_netr_LogonSamLogon_check(r);
1101 if (!NT_STATUS_IS_OK(nt_status)) {
1105 nt_status = schannel_get_creds_state(mem_ctx,
1106 dce_call->conn->dce_ctx->lp_ctx,
1107 r->in.computer_name, &creds);
1108 if (!NT_STATUS_IS_OK(nt_status)) {
1112 if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1113 return NT_STATUS_ACCESS_DENIED;
1115 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1119 netr_LogonSamLogonWithFlags
1122 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1123 struct netr_LogonSamLogonWithFlags *r)
1126 struct netlogon_creds_CredentialState *creds;
1127 struct netr_LogonSamLogonEx r2;
1129 struct netr_Authenticator *return_authenticator;
1133 r2.in.server_name = r->in.server_name;
1134 r2.in.computer_name = r->in.computer_name;
1135 r2.in.logon_level = r->in.logon_level;
1136 r2.in.logon = r->in.logon;
1137 r2.in.validation_level = r->in.validation_level;
1138 r2.in.flags = r->in.flags;
1139 r2.out.validation = r->out.validation;
1140 r2.out.authoritative = r->out.authoritative;
1141 r2.out.flags = r->out.flags;
1143 *r->out.authoritative = 1;
1145 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1146 if (!NT_STATUS_IS_OK(nt_status)) {
1150 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1151 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1153 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1155 r->in.computer_name,
1156 r->in.credential, return_authenticator,
1158 NT_STATUS_NOT_OK_RETURN(nt_status);
1160 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1162 r->out.return_authenticator = return_authenticator;
1170 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1171 struct netr_LogonSamLogon *r)
1173 struct netr_LogonSamLogonWithFlags r2;
1179 r2.in.server_name = r->in.server_name;
1180 r2.in.computer_name = r->in.computer_name;
1181 r2.in.credential = r->in.credential;
1182 r2.in.return_authenticator = r->in.return_authenticator;
1183 r2.in.logon_level = r->in.logon_level;
1184 r2.in.logon = r->in.logon;
1185 r2.in.validation_level = r->in.validation_level;
1186 r2.in.flags = &flags;
1187 r2.out.validation = r->out.validation;
1188 r2.out.authoritative = r->out.authoritative;
1189 r2.out.flags = &flags;
1191 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1193 r->out.return_authenticator = r2.out.return_authenticator;
1202 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1203 struct netr_LogonSamLogoff *r)
1205 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1213 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1214 struct netr_DatabaseDeltas *r)
1216 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1223 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1224 struct netr_DatabaseSync2 *r)
1226 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1227 return NT_STATUS_NOT_IMPLEMENTED;
1234 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1235 struct netr_DatabaseSync *r)
1237 struct netr_DatabaseSync2 r2;
1242 r2.in.logon_server = r->in.logon_server;
1243 r2.in.computername = r->in.computername;
1244 r2.in.credential = r->in.credential;
1245 r2.in.database_id = r->in.database_id;
1246 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1247 r2.in.sync_context = r->in.sync_context;
1248 r2.out.sync_context = r->out.sync_context;
1249 r2.out.delta_enum_array = r->out.delta_enum_array;
1250 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1252 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1261 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1262 struct netr_AccountDeltas *r)
1264 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1265 return NT_STATUS_NOT_IMPLEMENTED;
1272 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1273 struct netr_AccountSync *r)
1275 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1276 return NT_STATUS_NOT_IMPLEMENTED;
1283 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1284 struct netr_GetDcName *r)
1286 const char * const attrs[] = { NULL };
1287 struct ldb_context *sam_ctx;
1288 struct ldb_message **res;
1289 struct ldb_dn *domain_dn;
1294 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1295 * that the domainname needs to be a valid netbios domain
1296 * name, if it is not NULL.
1298 if (r->in.domainname) {
1299 const char *dot = strchr(r->in.domainname, '.');
1300 size_t len = strlen(r->in.domainname);
1302 if (dot || len > 15) {
1303 return WERR_NERR_DCNOTFOUND;
1307 * TODO: Should we also varify that only valid
1308 * netbios name characters are used?
1312 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1313 dce_call->conn->dce_ctx->lp_ctx,
1314 dce_call->conn->auth_state.session_info, 0);
1315 if (sam_ctx == NULL) {
1316 return WERR_DS_UNAVAILABLE;
1319 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1321 if (domain_dn == NULL) {
1322 return WERR_NO_SUCH_DOMAIN;
1325 ret = gendb_search_dn(sam_ctx, mem_ctx,
1326 domain_dn, &res, attrs);
1328 return WERR_NO_SUCH_DOMAIN;
1331 /* TODO: - return real IP address
1332 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1334 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1335 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1336 W_ERROR_HAVE_NO_MEMORY(dcname);
1338 *r->out.dcname = dcname;
1342 struct dcesrv_netr_LogonControl_base_state {
1343 struct dcesrv_call_state *dce_call;
1345 TALLOC_CTX *mem_ctx;
1347 struct netr_LogonControl2Ex r;
1350 struct netr_LogonControl *l;
1351 struct netr_LogonControl2 *l2;
1352 struct netr_LogonControl2Ex *l2ex;
1356 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1358 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1360 struct dcesrv_connection *conn = state->dce_call->conn;
1361 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1362 struct auth_session_info *session_info = conn->auth_state.session_info;
1363 enum security_user_level security_level;
1364 struct dcerpc_binding_handle *irpc_handle;
1365 struct tevent_req *subreq;
1368 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1370 if (state->_r.l != NULL) {
1374 if (state->r.in.level == 0x00000002) {
1375 return WERR_NOT_SUPPORTED;
1376 } else if (state->r.in.level != 0x00000001) {
1377 return WERR_INVALID_LEVEL;
1380 switch (state->r.in.function_code) {
1381 case NETLOGON_CONTROL_QUERY:
1382 case NETLOGON_CONTROL_REPLICATE:
1383 case NETLOGON_CONTROL_SYNCHRONIZE:
1384 case NETLOGON_CONTROL_PDC_REPLICATE:
1385 case NETLOGON_CONTROL_BREAKPOINT:
1386 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1387 case NETLOGON_CONTROL_TRUNCATE_LOG:
1390 return WERR_NOT_SUPPORTED;
1394 if (state->r.in.level < 0x00000001) {
1395 return WERR_INVALID_LEVEL;
1398 if (state->r.in.level > 0x00000004) {
1399 return WERR_INVALID_LEVEL;
1402 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1403 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1404 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1406 switch (state->r.in.level) {
1408 info1 = talloc_zero(state->mem_ctx,
1409 struct netr_NETLOGON_INFO_1);
1410 if (info1 == NULL) {
1411 return WERR_NOT_ENOUGH_MEMORY;
1413 state->r.out.query->info1 = info1;
1417 info3 = talloc_zero(state->mem_ctx,
1418 struct netr_NETLOGON_INFO_3);
1419 if (info3 == NULL) {
1420 return WERR_NOT_ENOUGH_MEMORY;
1422 state->r.out.query->info3 = info3;
1426 return WERR_INVALID_PARAMETER;
1431 * Some validations are done before the access check
1432 * and some after the access check
1434 security_level = security_session_user_level(session_info, NULL);
1435 if (security_level < SECURITY_ADMINISTRATOR) {
1436 return WERR_ACCESS_DENIED;
1439 if (state->_r.l2 != NULL) {
1441 * netr_LogonControl2
1443 if (state->r.in.level == 0x00000004) {
1444 return WERR_INVALID_LEVEL;
1448 switch (state->r.in.level) {
1453 switch (state->r.in.function_code) {
1454 case NETLOGON_CONTROL_REDISCOVER:
1455 case NETLOGON_CONTROL_TC_QUERY:
1456 case NETLOGON_CONTROL_TC_VERIFY:
1459 return WERR_INVALID_PARAMETER;
1468 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1469 return WERR_INVALID_PARAMETER;
1475 return WERR_INVALID_LEVEL;
1478 switch (state->r.in.function_code) {
1479 case NETLOGON_CONTROL_REDISCOVER:
1480 case NETLOGON_CONTROL_TC_QUERY:
1481 case NETLOGON_CONTROL_TC_VERIFY:
1482 if (state->r.in.level != 2) {
1483 return WERR_INVALID_PARAMETER;
1486 if (state->r.in.data == NULL) {
1487 return WERR_INVALID_PARAMETER;
1490 if (state->r.in.data->domain == NULL) {
1491 return WERR_INVALID_PARAMETER;
1496 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1497 if (state->r.in.level != 1) {
1498 return WERR_INVALID_PARAMETER;
1501 if (state->r.in.data == NULL) {
1502 return WERR_INVALID_PARAMETER;
1505 if (state->r.in.data->domain == NULL) {
1506 return WERR_INVALID_PARAMETER;
1509 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1510 state->r.in.data->domain);
1512 struct ldb_context *sam_ctx;
1514 sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1515 lp_ctx, system_session(lp_ctx), 0);
1516 if (sam_ctx == NULL) {
1517 return WERR_DS_UNAVAILABLE;
1521 * Secrets for trusted domains can only be triggered on
1524 ok = samdb_is_pdc(sam_ctx);
1525 TALLOC_FREE(sam_ctx);
1527 return WERR_INVALID_DOMAIN_ROLE;
1533 return WERR_NOT_SUPPORTED;
1536 irpc_handle = irpc_binding_handle_by_name(state,
1537 state->dce_call->msg_ctx,
1539 &ndr_table_winbind);
1540 if (irpc_handle == NULL) {
1541 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1542 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1543 return WERR_SERVICE_NOT_FOUND;
1547 * 60 seconds timeout should be enough
1549 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1551 subreq = dcerpc_winbind_LogonControl_send(state,
1552 state->dce_call->event_ctx,
1554 state->r.in.function_code,
1557 state->r.out.query);
1558 if (subreq == NULL) {
1559 return WERR_NOT_ENOUGH_MEMORY;
1561 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1562 tevent_req_set_callback(subreq,
1563 dcesrv_netr_LogonControl_base_done,
1569 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1571 struct dcesrv_netr_LogonControl_base_state *state =
1572 tevent_req_callback_data(subreq,
1573 struct dcesrv_netr_LogonControl_base_state);
1576 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1577 &state->r.out.result);
1578 TALLOC_FREE(subreq);
1579 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1580 state->r.out.result = WERR_TIMEOUT;
1581 } else if (!NT_STATUS_IS_OK(status)) {
1582 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1583 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1584 nt_errstr(status)));
1587 if (state->_r.l2ex != NULL) {
1588 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1589 r->out.result = state->r.out.result;
1590 } else if (state->_r.l2 != NULL) {
1591 struct netr_LogonControl2 *r = state->_r.l2;
1592 r->out.result = state->r.out.result;
1593 } else if (state->_r.l != NULL) {
1594 struct netr_LogonControl *r = state->_r.l;
1595 r->out.result = state->r.out.result;
1598 status = dcesrv_reply(state->dce_call);
1599 if (!NT_STATUS_IS_OK(status)) {
1600 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1607 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1608 struct netr_LogonControl *r)
1610 struct dcesrv_netr_LogonControl_base_state *state;
1613 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1614 if (state == NULL) {
1615 return WERR_NOT_ENOUGH_MEMORY;
1618 state->dce_call = dce_call;
1619 state->mem_ctx = mem_ctx;
1621 state->r.in.logon_server = r->in.logon_server;
1622 state->r.in.function_code = r->in.function_code;
1623 state->r.in.level = r->in.level;
1624 state->r.in.data = NULL;
1625 state->r.out.query = r->out.query;
1629 werr = dcesrv_netr_LogonControl_base_call(state);
1631 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1641 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1642 struct netr_LogonControl2 *r)
1644 struct dcesrv_netr_LogonControl_base_state *state;
1647 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1648 if (state == NULL) {
1649 return WERR_NOT_ENOUGH_MEMORY;
1652 state->dce_call = dce_call;
1653 state->mem_ctx = mem_ctx;
1655 state->r.in.logon_server = r->in.logon_server;
1656 state->r.in.function_code = r->in.function_code;
1657 state->r.in.level = r->in.level;
1658 state->r.in.data = r->in.data;
1659 state->r.out.query = r->out.query;
1663 werr = dcesrv_netr_LogonControl_base_call(state);
1665 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1673 netr_LogonControl2Ex
1675 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1676 struct netr_LogonControl2Ex *r)
1678 struct dcesrv_netr_LogonControl_base_state *state;
1681 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1682 if (state == NULL) {
1683 return WERR_NOT_ENOUGH_MEMORY;
1686 state->dce_call = dce_call;
1687 state->mem_ctx = mem_ctx;
1692 werr = dcesrv_netr_LogonControl_base_call(state);
1694 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1701 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1702 struct ldb_context *sam_ctx,
1703 struct netr_DomainTrustList *trusts,
1704 uint32_t trust_flags);
1709 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1710 struct netr_GetAnyDCName *r)
1712 struct netr_DomainTrustList *trusts;
1713 struct ldb_context *sam_ctx;
1714 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1718 *r->out.dcname = NULL;
1720 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1721 /* if the domainname parameter wasn't set assume our domain */
1722 r->in.domainname = lpcfg_workgroup(lp_ctx);
1725 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1726 dce_call->conn->auth_state.session_info, 0);
1727 if (sam_ctx == NULL) {
1728 return WERR_DS_UNAVAILABLE;
1731 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1732 /* well we asked for a DC of our own domain */
1733 if (samdb_is_pdc(sam_ctx)) {
1734 /* we are the PDC of the specified domain */
1735 return WERR_NO_SUCH_DOMAIN;
1738 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1739 lpcfg_netbios_name(lp_ctx));
1740 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1745 /* Okay, now we have to consider the trusted domains */
1747 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1748 W_ERROR_HAVE_NO_MEMORY(trusts);
1752 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1753 NETR_TRUST_FLAG_INBOUND
1754 | NETR_TRUST_FLAG_OUTBOUND);
1755 W_ERROR_NOT_OK_RETURN(werr);
1757 for (i = 0; i < trusts->count; i++) {
1758 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1759 /* FIXME: Here we need to find a DC for the specified
1760 * trusted domain. */
1762 /* return WERR_OK; */
1763 return WERR_NO_SUCH_DOMAIN;
1767 return WERR_NO_SUCH_DOMAIN;
1774 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1775 struct netr_DatabaseRedo *r)
1777 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1782 netr_NetrEnumerateTrustedDomains
1784 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1785 struct netr_NetrEnumerateTrustedDomains *r)
1787 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1792 netr_LogonGetCapabilities
1794 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1795 struct netr_LogonGetCapabilities *r)
1797 struct netlogon_creds_CredentialState *creds;
1800 status = dcesrv_netr_creds_server_step_check(dce_call,
1802 r->in.computer_name,
1804 r->out.return_authenticator,
1806 if (!NT_STATUS_IS_OK(status)) {
1807 DEBUG(0,(__location__ " Bad credentials - error\n"));
1809 NT_STATUS_NOT_OK_RETURN(status);
1811 if (r->in.query_level != 1) {
1812 return NT_STATUS_NOT_SUPPORTED;
1815 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1817 return NT_STATUS_OK;
1822 netr_NETRLOGONSETSERVICEBITS
1824 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1825 struct netr_NETRLOGONSETSERVICEBITS *r)
1827 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1832 netr_LogonGetTrustRid
1834 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1835 struct netr_LogonGetTrustRid *r)
1837 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1842 netr_NETRLOGONCOMPUTESERVERDIGEST
1844 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1845 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1847 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1852 netr_NETRLOGONCOMPUTECLIENTDIGEST
1854 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1855 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1857 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1865 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1866 struct netr_DsRGetSiteName *r)
1868 struct ldb_context *sam_ctx;
1869 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1871 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1872 dce_call->conn->auth_state.session_info, 0);
1873 if (sam_ctx == NULL) {
1874 return WERR_DS_UNAVAILABLE;
1878 * We assume to be a DC when we get called over NETLOGON. Hence we
1879 * get our site name always by using "samdb_server_site_name()"
1880 * and not "samdb_client_site_name()".
1882 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1883 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1890 fill in a netr_OneDomainInfo from a ldb search result
1892 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1893 struct loadparm_context *lp_ctx,
1894 struct ldb_context *sam_ctx,
1895 struct ldb_message *res,
1896 struct netr_OneDomainInfo *info,
1897 bool is_local, bool is_trust_list)
1901 if (is_trust_list) {
1902 /* w2k8 only fills this on trusted domains */
1903 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1904 info->trust_extension.length = 16;
1905 info->trust_extension.info->flags =
1906 NETR_TRUST_FLAG_TREEROOT |
1907 NETR_TRUST_FLAG_IN_FOREST |
1908 NETR_TRUST_FLAG_PRIMARY |
1909 NETR_TRUST_FLAG_NATIVE;
1911 info->trust_extension.info->parent_index = 0; /* should be index into array
1913 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1914 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1917 if (is_trust_list) {
1918 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1919 info->dns_forestname.string = NULL;
1921 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1922 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1923 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1924 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1928 info->domainname.string = lpcfg_workgroup(lp_ctx);
1929 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1930 info->domain_guid = samdb_result_guid(res, "objectGUID");
1931 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1933 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1934 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1935 info->domain_guid = samdb_result_guid(res, "objectGUID");
1936 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1938 if (!is_trust_list) {
1939 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1942 return NT_STATUS_OK;
1946 netr_LogonGetDomainInfo
1947 this is called as part of the ADS domain logon procedure.
1949 It has an important role in convaying details about the client, such
1950 as Operating System, Version, Service Pack etc.
1952 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1953 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1955 struct netlogon_creds_CredentialState *creds;
1956 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1957 "securityIdentifier", "trustPartner", NULL };
1958 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1959 "msDS-SupportedEncryptionTypes", NULL };
1960 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1961 struct ldb_context *sam_ctx;
1962 struct ldb_message **res1, **res2, **res3, *new_msg;
1963 struct ldb_dn *workstation_dn;
1964 struct netr_DomainInformation *domain_info;
1965 struct netr_LsaPolicyInformation *lsa_policy_info;
1966 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1967 bool update_dns_hostname = true;
1971 status = dcesrv_netr_creds_server_step_check(dce_call,
1973 r->in.computer_name,
1975 r->out.return_authenticator,
1977 if (!NT_STATUS_IS_OK(status)) {
1978 DEBUG(0,(__location__ " Bad credentials - error\n"));
1980 NT_STATUS_NOT_OK_RETURN(status);
1982 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1983 dce_call->conn->dce_ctx->lp_ctx,
1984 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1985 if (sam_ctx == NULL) {
1986 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1989 switch (r->in.level) {
1990 case 1: /* Domain information */
1992 if (r->in.query->workstation_info == NULL) {
1993 return NT_STATUS_INVALID_PARAMETER;
1996 /* Prepares the workstation DN */
1997 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1998 dom_sid_string(mem_ctx, creds->sid));
1999 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2001 /* Lookup for attributes in workstation object */
2002 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2005 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2008 /* Gets the sam account name which is checked against the DNS
2009 * hostname parameter. */
2010 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2013 if (sam_account_name == NULL) {
2014 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2018 * Checks that the sam account name without a possible "$"
2019 * matches as prefix with the DNS hostname in the workstation
2022 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2023 strcspn(sam_account_name, "$"));
2024 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2025 if (r->in.query->workstation_info->dns_hostname != NULL) {
2026 prefix2 = talloc_strndup(mem_ctx,
2027 r->in.query->workstation_info->dns_hostname,
2028 strcspn(r->in.query->workstation_info->dns_hostname, "."));
2029 NT_STATUS_HAVE_NO_MEMORY(prefix2);
2031 if (strcasecmp(prefix1, prefix2) != 0) {
2032 update_dns_hostname = false;
2035 update_dns_hostname = false;
2038 /* Gets the old DNS hostname */
2039 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2044 * Updates the DNS hostname when the client wishes that the
2045 * server should handle this for him
2046 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2047 * obviously only checked when we do already have a
2049 * See MS-NRPC section 3.5.4.3.9
2051 if ((old_dns_hostname != NULL) &&
2052 (r->in.query->workstation_info->workstation_flags
2053 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2054 update_dns_hostname = false;
2057 /* Gets host information and put them into our directory */
2059 new_msg = ldb_msg_new(mem_ctx);
2060 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2062 new_msg->dn = workstation_dn;
2064 /* Sets the OS name */
2066 if (r->in.query->workstation_info->os_name.string == NULL) {
2067 return NT_STATUS_INVALID_PARAMETER;
2070 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2071 r->in.query->workstation_info->os_name.string);
2072 if (ret != LDB_SUCCESS) {
2073 return NT_STATUS_NO_MEMORY;
2077 * Sets information from "os_version". On an empty structure
2078 * the values are cleared.
2080 if (r->in.query->workstation_info->os_version.os != NULL) {
2081 struct netr_OsVersionInfoEx *os_version;
2082 const char *os_version_str;
2084 os_version = &r->in.query->workstation_info->os_version.os->os;
2086 if (os_version->CSDVersion == NULL) {
2087 return NT_STATUS_INVALID_PARAMETER;
2090 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2091 os_version->MajorVersion,
2092 os_version->MinorVersion,
2093 os_version->BuildNumber);
2094 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2096 ret = ldb_msg_add_string(new_msg,
2097 "operatingSystemServicePack",
2098 os_version->CSDVersion);
2099 if (ret != LDB_SUCCESS) {
2100 return NT_STATUS_NO_MEMORY;
2103 ret = ldb_msg_add_string(new_msg,
2104 "operatingSystemVersion",
2106 if (ret != LDB_SUCCESS) {
2107 return NT_STATUS_NO_MEMORY;
2110 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2111 "operatingSystemServicePack");
2112 if (ret != LDB_SUCCESS) {
2113 return NT_STATUS_NO_MEMORY;
2116 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2117 "operatingSystemVersion");
2118 if (ret != LDB_SUCCESS) {
2119 return NT_STATUS_NO_MEMORY;
2124 * If the boolean "update_dns_hostname" remained true, then we
2125 * are fine to start the update.
2127 if (update_dns_hostname) {
2128 ret = ldb_msg_add_string(new_msg,
2130 r->in.query->workstation_info->dns_hostname);
2131 if (ret != LDB_SUCCESS) {
2132 return NT_STATUS_NO_MEMORY;
2135 /* This manual "servicePrincipalName" generation is
2136 * still needed! Since the update in the samldb LDB
2137 * module does only work if the entries already exist
2138 * which isn't always the case. */
2139 ret = ldb_msg_add_string(new_msg,
2140 "servicePrincipalName",
2141 talloc_asprintf(new_msg, "HOST/%s",
2142 r->in.computer_name));
2143 if (ret != LDB_SUCCESS) {
2144 return NT_STATUS_NO_MEMORY;
2147 ret = ldb_msg_add_string(new_msg,
2148 "servicePrincipalName",
2149 talloc_asprintf(new_msg, "HOST/%s",
2150 r->in.query->workstation_info->dns_hostname));
2151 if (ret != LDB_SUCCESS) {
2152 return NT_STATUS_NO_MEMORY;
2156 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2157 DEBUG(3,("Impossible to update samdb: %s\n",
2158 ldb_errstring(sam_ctx)));
2161 talloc_free(new_msg);
2163 /* Writes back the domain information */
2165 /* We need to do two searches. The first will pull our primary
2166 domain and the second will pull any trusted domains. Our
2167 primary domain is also a "trusted" domain, so we need to
2168 put the primary domain into the lists of returned trusts as
2170 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2173 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2176 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2177 "(objectClass=trustedDomain)");
2179 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2182 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2183 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2185 ZERO_STRUCTP(domain_info);
2187 /* Informations about the local and trusted domains */
2189 status = fill_one_domain_info(mem_ctx,
2190 dce_call->conn->dce_ctx->lp_ctx,
2191 sam_ctx, res2[0], &domain_info->primary_domain,
2193 NT_STATUS_NOT_OK_RETURN(status);
2195 domain_info->trusted_domain_count = ret3 + 1;
2196 domain_info->trusted_domains = talloc_array(mem_ctx,
2197 struct netr_OneDomainInfo,
2198 domain_info->trusted_domain_count);
2199 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2201 for (i=0;i<ret3;i++) {
2202 status = fill_one_domain_info(mem_ctx,
2203 dce_call->conn->dce_ctx->lp_ctx,
2205 &domain_info->trusted_domains[i],
2207 NT_STATUS_NOT_OK_RETURN(status);
2210 status = fill_one_domain_info(mem_ctx,
2211 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2212 &domain_info->trusted_domains[i], true, true);
2213 NT_STATUS_NOT_OK_RETURN(status);
2215 /* Sets the supported encryption types */
2216 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2217 "msDS-SupportedEncryptionTypes",
2218 default_supported_enc_types);
2220 /* Other host domain information */
2222 lsa_policy_info = talloc(mem_ctx,
2223 struct netr_LsaPolicyInformation);
2224 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2225 ZERO_STRUCTP(lsa_policy_info);
2227 domain_info->lsa_policy = *lsa_policy_info;
2229 /* The DNS hostname is only returned back when there is a chance
2231 if ((r->in.query->workstation_info->workstation_flags
2232 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2233 domain_info->dns_hostname.string = old_dns_hostname;
2235 domain_info->dns_hostname.string = NULL;
2238 domain_info->workstation_flags =
2239 r->in.query->workstation_info->workstation_flags & (
2240 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2242 r->out.info->domain_info = domain_info;
2244 case 2: /* LSA policy information - not used at the moment */
2245 lsa_policy_info = talloc(mem_ctx,
2246 struct netr_LsaPolicyInformation);
2247 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2248 ZERO_STRUCTP(lsa_policy_info);
2250 r->out.info->lsa_policy_info = lsa_policy_info;
2253 return NT_STATUS_INVALID_LEVEL;
2257 return NT_STATUS_OK;
2262 netr_ServerPasswordGet
2264 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2265 struct netr_ServerPasswordGet *r)
2267 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2270 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2271 TALLOC_CTX *mem_ctx,
2272 struct dom_sid *user_sid,
2273 struct ldb_dn *obj_dn)
2275 const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
2276 const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2277 struct ldb_dn *rodc_dn;
2279 struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2280 const struct dom_sid *additional_sids[] = { NULL, NULL };
2282 struct dom_sid *object_sid;
2283 const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
2285 rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2286 dom_sid_string(mem_ctx, user_sid));
2287 if (!ldb_dn_validate(rodc_dn)) goto denied;
2289 /* do the two searches we need */
2290 ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2291 DSDB_SEARCH_SHOW_EXTENDED_DN);
2292 if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2294 ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2295 if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2297 object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
2299 additional_sids[0] = object_sid;
2301 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2302 mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
2303 if (!W_ERROR_IS_OK(werr)) {
2307 werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2308 mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
2309 if (!W_ERROR_IS_OK(werr)) {
2314 * The SID list needs to include itself as well as the tokenGroups.
2316 * TODO determine if sIDHistory is required for this check
2318 werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
2319 mem_ctx, "tokenGroups", &token_sids,
2320 additional_sids, 1);
2321 if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
2325 if (never_reveal_sids &&
2326 sid_list_match(token_sids, never_reveal_sids)) {
2331 sid_list_match(token_sids, reveal_sids)) {
2343 netr_NetrLogonSendToSam
2345 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2346 struct netr_NetrLogonSendToSam *r)
2348 struct netlogon_creds_CredentialState *creds;
2349 struct ldb_context *sam_ctx;
2351 DATA_BLOB decrypted_blob;
2352 enum ndr_err_code ndr_err;
2353 struct netr_SendToSamBase base_msg = { 0 };
2355 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2357 r->in.computer_name,
2359 r->out.return_authenticator,
2362 NT_STATUS_NOT_OK_RETURN(nt_status);
2364 switch (creds->secure_channel_type) {
2368 case SEC_CHAN_WKSTA:
2369 case SEC_CHAN_DNS_DOMAIN:
2370 case SEC_CHAN_DOMAIN:
2372 return NT_STATUS_INVALID_PARAMETER;
2374 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
2375 creds->secure_channel_type));
2376 return NT_STATUS_INVALID_PARAMETER;
2379 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
2380 dce_call->conn->dce_ctx->lp_ctx,
2381 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
2382 if (sam_ctx == NULL) {
2383 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2386 /* Buffer is meant to be 16-bit aligned */
2387 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2388 netlogon_creds_aes_decrypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2390 netlogon_creds_arcfour_crypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2393 decrypted_blob.data = r->in.opaque_buffer;
2394 decrypted_blob.length = r->in.buffer_len;
2396 ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
2397 (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
2399 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2400 /* We only partially implement SendToSam */
2401 return NT_STATUS_NOT_IMPLEMENTED;
2404 /* Now 'send' to SAM */
2405 switch (base_msg.message_type) {
2406 case SendToSamResetBadPasswordCount:
2408 struct ldb_message *msg = ldb_msg_new(mem_ctx);
2409 struct ldb_dn *dn = NULL;
2413 ret = ldb_transaction_start(sam_ctx);
2414 if (ret != LDB_SUCCESS) {
2415 return NT_STATUS_INTERNAL_ERROR;
2418 ret = dsdb_find_dn_by_guid(sam_ctx,
2420 &base_msg.message.reset_bad_password.guid,
2423 if (ret != LDB_SUCCESS) {
2424 ldb_transaction_cancel(sam_ctx);
2425 return NT_STATUS_INVALID_PARAMETER;
2428 if (creds->secure_channel_type == SEC_CHAN_RODC &&
2429 !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
2430 DEBUG(1, ("Client asked to reset bad password on "
2431 "an arbitrary user: %s\n",
2432 ldb_dn_get_linearized(dn)));
2433 ldb_transaction_cancel(sam_ctx);
2434 return NT_STATUS_INVALID_PARAMETER;
2439 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
2440 if (ret != LDB_SUCCESS) {
2441 ldb_transaction_cancel(sam_ctx);
2442 return NT_STATUS_INVALID_PARAMETER;
2445 ret = dsdb_replace(sam_ctx, msg, 0);
2446 if (ret != LDB_SUCCESS) {
2447 ldb_transaction_cancel(sam_ctx);
2448 return NT_STATUS_INVALID_PARAMETER;
2451 ret = ldb_transaction_commit(sam_ctx);
2452 if (ret != LDB_SUCCESS) {
2453 ldb_transaction_cancel(sam_ctx);
2454 return NT_STATUS_INTERNAL_ERROR;
2460 return NT_STATUS_NOT_IMPLEMENTED;
2463 return NT_STATUS_OK;
2468 netr_DsRGetDCNameEx2
2470 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2471 TALLOC_CTX *mem_ctx,
2472 struct netr_DsRGetDCNameEx2 *r)
2474 struct ldb_context *sam_ctx;
2475 struct netr_DsRGetDCNameInfo *info;
2476 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2477 const struct tsocket_address *local_address;
2478 char *local_addr = NULL;
2479 const struct tsocket_address *remote_address;
2480 char *remote_addr = NULL;
2481 const char *server_site_name;
2483 struct netlogon_samlogon_response response;
2485 const char *dc_name = NULL;
2486 const char *domain_name = NULL;
2489 ZERO_STRUCTP(r->out.info);
2491 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2492 dce_call->conn->auth_state.session_info, 0);
2493 if (sam_ctx == NULL) {
2494 return WERR_DS_UNAVAILABLE;
2497 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2498 if (tsocket_address_is_inet(local_address, "ip")) {
2499 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2500 W_ERROR_HAVE_NO_MEMORY(local_addr);
2503 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2504 if (tsocket_address_is_inet(remote_address, "ip")) {
2505 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2506 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2509 /* "server_unc" is ignored by w2k3 */
2511 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2512 return WERR_INVALID_FLAGS;
2515 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2516 r->in.flags & DS_PDC_REQUIRED &&
2517 r->in.flags & DS_KDC_REQUIRED) {
2518 return WERR_INVALID_FLAGS;
2520 if (r->in.flags & DS_IS_FLAT_NAME &&
2521 r->in.flags & DS_IS_DNS_NAME) {
2522 return WERR_INVALID_FLAGS;
2524 if (r->in.flags & DS_RETURN_DNS_NAME &&
2525 r->in.flags & DS_RETURN_FLAT_NAME) {
2526 return WERR_INVALID_FLAGS;
2528 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2529 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2530 return WERR_INVALID_FLAGS;
2533 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2535 (DS_DIRECTORY_SERVICE_REQUIRED |
2536 DS_DIRECTORY_SERVICE_PREFERRED |
2537 DS_GC_SERVER_REQUIRED |
2540 return WERR_INVALID_FLAGS;
2543 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2545 return WERR_INVALID_FLAGS;
2548 /* Proof server site parameter "site_name" if it was specified */
2549 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2550 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2551 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2552 server_site_name) != 0)) {
2553 return WERR_NO_SUCH_DOMAIN;
2556 guid_str = r->in.domain_guid != NULL ?
2557 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2559 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2563 r->in.client_account,
2564 r->in.mask, remote_addr,
2565 NETLOGON_NT_VERSION_5EX_WITH_IP,
2566 lp_ctx, &response, true);
2567 if (!NT_STATUS_IS_OK(status)) {
2568 return ntstatus_to_werror(status);
2572 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2573 * (O) flag when the returned forest name is in DNS format. This is here
2574 * always the case (see below).
2576 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2578 if (r->in.flags & DS_RETURN_DNS_NAME) {
2579 dc_name = response.data.nt5_ex.pdc_dns_name;
2580 domain_name = response.data.nt5_ex.dns_domain;
2582 * According to MS-NRPC 2.2.1.2.1 we should set the
2583 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2584 * the returned information is in DNS form.
2586 response.data.nt5_ex.server_type |=
2587 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2588 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2589 dc_name = response.data.nt5_ex.pdc_name;
2590 domain_name = response.data.nt5_ex.domain_name;
2594 * TODO: autodetect what we need to return
2595 * based on the given arguments
2597 dc_name = response.data.nt5_ex.pdc_name;
2598 domain_name = response.data.nt5_ex.domain_name;
2601 if (!dc_name || !dc_name[0]) {
2602 return WERR_NO_SUCH_DOMAIN;
2605 if (!domain_name || !domain_name[0]) {
2606 return WERR_NO_SUCH_DOMAIN;
2609 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2610 W_ERROR_HAVE_NO_MEMORY(info);
2611 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2612 dc_name[0] != '\\'? "\\\\":"",
2613 talloc_strdup(mem_ctx, dc_name));
2614 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2616 pdc_ip = local_addr;
2617 if (pdc_ip == NULL) {
2618 pdc_ip = "127.0.0.1";
2620 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2621 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2622 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2623 info->domain_guid = response.data.nt5_ex.domain_uuid;
2624 info->domain_name = domain_name;
2625 info->forest_name = response.data.nt5_ex.forest;
2626 info->dc_flags = response.data.nt5_ex.server_type;
2627 if (r->in.flags & DS_RETURN_DNS_NAME) {
2628 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2629 * returned if we are returning info->dc_unc containing a FQDN.
2630 * This attribute is called DomainControllerName in the specs,
2631 * it seems that we decide to return FQDN or netbios depending on
2632 * DS_RETURN_DNS_NAME.
2634 info->dc_flags |= DS_DNS_CONTROLLER;
2636 info->dc_site_name = response.data.nt5_ex.server_site;
2637 info->client_site_name = response.data.nt5_ex.client_site;
2639 *r->out.info = info;
2647 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2648 struct netr_DsRGetDCNameEx *r)
2650 struct netr_DsRGetDCNameEx2 r2;
2655 r2.in.server_unc = r->in.server_unc;
2656 r2.in.client_account = NULL;
2658 r2.in.domain_guid = r->in.domain_guid;
2659 r2.in.domain_name = r->in.domain_name;
2660 r2.in.site_name = r->in.site_name;
2661 r2.in.flags = r->in.flags;
2662 r2.out.info = r->out.info;
2664 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2672 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2673 struct netr_DsRGetDCName *r)
2675 struct netr_DsRGetDCNameEx2 r2;
2680 r2.in.server_unc = r->in.server_unc;
2681 r2.in.client_account = NULL;
2683 r2.in.domain_name = r->in.domain_name;
2684 r2.in.domain_guid = r->in.domain_guid;
2686 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2687 r2.in.flags = r->in.flags;
2688 r2.out.info = r->out.info;
2690 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2695 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2697 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2698 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2700 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2705 netr_NetrEnumerateTrustedDomainsEx
2707 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2708 struct netr_NetrEnumerateTrustedDomainsEx *r)
2710 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2715 netr_DsRAddressToSitenamesExW
2717 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2718 struct netr_DsRAddressToSitenamesExW *r)
2720 struct ldb_context *sam_ctx;
2721 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2722 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2723 sa_family_t sin_family;
2724 struct sockaddr_in *addr;
2726 struct sockaddr_in6 *addr6;
2727 char addr_str[INET6_ADDRSTRLEN];
2729 char addr_str[INET_ADDRSTRLEN];
2735 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2736 dce_call->conn->auth_state.session_info, 0);
2737 if (sam_ctx == NULL) {
2738 return WERR_DS_UNAVAILABLE;
2741 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2742 W_ERROR_HAVE_NO_MEMORY(ctr);
2746 ctr->count = r->in.count;
2747 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2748 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2749 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2750 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2752 for (i=0; i<ctr->count; i++) {
2753 ctr->sitename[i].string = NULL;
2754 ctr->subnetname[i].string = NULL;
2756 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2759 /* The first two byte of the buffer are reserved for the
2760 * "sin_family" but for now only the first one is used. */
2761 sin_family = r->in.addresses[i].buffer[0];
2763 switch (sin_family) {
2765 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2768 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2769 res = inet_ntop(AF_INET, &addr->sin_addr,
2770 addr_str, sizeof(addr_str));
2774 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2777 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2778 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2779 addr_str, sizeof(addr_str));
2790 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2794 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2795 ctr->subnetname[i].string = subnet_name;
2803 netr_DsRAddressToSitenamesW
2805 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2806 struct netr_DsRAddressToSitenamesW *r)
2808 struct netr_DsRAddressToSitenamesExW r2;
2809 struct netr_DsRAddressToSitenamesWCtr *ctr;
2815 r2.in.server_name = r->in.server_name;
2816 r2.in.count = r->in.count;
2817 r2.in.addresses = r->in.addresses;
2819 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2820 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2822 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2823 W_ERROR_HAVE_NO_MEMORY(ctr);
2827 ctr->count = r->in.count;
2828 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2829 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2831 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2833 for (i=0; i<ctr->count; i++) {
2834 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2842 netr_DsrGetDcSiteCoverageW
2844 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2845 struct netr_DsrGetDcSiteCoverageW *r)
2847 struct ldb_context *sam_ctx;
2848 struct DcSitesCtr *ctr;
2849 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2851 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2852 dce_call->conn->auth_state.session_info, 0);
2853 if (sam_ctx == NULL) {
2854 return WERR_DS_UNAVAILABLE;
2857 ctr = talloc(mem_ctx, struct DcSitesCtr);
2858 W_ERROR_HAVE_NO_MEMORY(ctr);
2862 /* For now only return our default site */
2864 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2865 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2866 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2867 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2873 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2874 struct ldb_context *sam_ctx,
2875 struct netr_DomainTrustList *trusts,
2876 uint32_t trust_flags)
2878 struct ldb_dn *system_dn;
2879 struct ldb_message **dom_res = NULL;
2880 const char *trust_attrs[] = { "flatname", "trustPartner",
2881 "securityIdentifier", "trustDirection",
2882 "trustType", "trustAttributes", NULL };
2887 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2888 NETR_TRUST_FLAG_OUTBOUND))) {
2889 return WERR_INVALID_FLAGS;
2892 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2893 ldb_get_default_basedn(sam_ctx),
2894 "(&(objectClass=container)(cn=System))");
2896 return WERR_GEN_FAILURE;
2899 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2900 &dom_res, trust_attrs,
2901 "(objectclass=trustedDomain)");
2903 for (i = 0; i < ret; i++) {
2904 unsigned int trust_dir;
2907 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2908 "trustDirection", 0);
2910 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2911 flags |= NETR_TRUST_FLAG_INBOUND;
2913 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2914 flags |= NETR_TRUST_FLAG_OUTBOUND;
2917 if (!(flags & trust_flags)) {
2918 /* this trust direction was not requested */
2923 trusts->array = talloc_realloc(trusts, trusts->array,
2924 struct netr_DomainTrust,
2926 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2928 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2929 if (!trusts->array[n].netbios_name) {
2930 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2931 "without flatname\n",
2932 ldb_dn_get_linearized(dom_res[i]->dn)));
2935 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2937 trusts->array[n].trust_flags = flags;
2938 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2939 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2940 /* TODO: find if we have parent in the list */
2941 trusts->array[n].parent_index = 0;
2944 trusts->array[n].trust_type =
2945 ldb_msg_find_attr_as_uint(dom_res[i],
2947 trusts->array[n].trust_attributes =
2948 ldb_msg_find_attr_as_uint(dom_res[i],
2949 "trustAttributes", 0);
2951 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2952 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2953 struct dom_sid zero_sid;
2954 ZERO_STRUCT(zero_sid);
2955 trusts->array[n].sid =
2956 dom_sid_dup(trusts, &zero_sid);
2958 trusts->array[n].sid =
2959 samdb_result_dom_sid(trusts, dom_res[i],
2960 "securityIdentifier");
2962 trusts->array[n].guid = GUID_zero();
2964 trusts->count = n + 1;
2967 talloc_free(dom_res);
2972 netr_DsrEnumerateDomainTrusts
2974 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2975 TALLOC_CTX *mem_ctx,
2976 struct netr_DsrEnumerateDomainTrusts *r)
2978 struct netr_DomainTrustList *trusts;
2979 struct ldb_context *sam_ctx;
2981 struct ldb_message **dom_res;
2982 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2983 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2984 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2988 if (r->in.trust_flags & 0xFFFFFE00) {
2989 return WERR_INVALID_FLAGS;
2992 /* TODO: turn to hard check once we are sure this is 100% correct */
2993 if (!r->in.server_name) {
2994 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2995 "But received NULL!\n", dnsdomain));
2997 p = strchr(r->in.server_name, '.');
2999 DEBUG(3, ("Invalid domain! Expected name in domain "
3000 "[%s]. But received [%s]!\n",
3001 dnsdomain, r->in.server_name));
3002 p = r->in.server_name;
3006 if (strcasecmp(p, dnsdomain)) {
3007 DEBUG(3, ("Invalid domain! Expected name in domain "
3008 "[%s]. But received [%s]!\n",
3009 dnsdomain, r->in.server_name));
3013 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3014 W_ERROR_HAVE_NO_MEMORY(trusts);
3017 r->out.trusts = trusts;
3019 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3020 dce_call->conn->auth_state.session_info, 0);
3021 if (sam_ctx == NULL) {
3022 return WERR_GEN_FAILURE;
3025 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3026 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3028 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3029 trusts, r->in.trust_flags);
3030 W_ERROR_NOT_OK_RETURN(werr);
3033 /* NOTE: we currently are always the root of the forest */
3034 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3035 uint32_t n = trusts->count;
3037 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3038 &dom_res, dom_attrs);
3040 return WERR_GEN_FAILURE;
3043 trusts->count = n + 1;
3044 trusts->array = talloc_realloc(trusts, trusts->array,
3045 struct netr_DomainTrust,
3047 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3049 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3050 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3051 trusts->array[n].trust_flags =
3052 NETR_TRUST_FLAG_NATIVE |
3053 NETR_TRUST_FLAG_TREEROOT |
3054 NETR_TRUST_FLAG_IN_FOREST |
3055 NETR_TRUST_FLAG_PRIMARY;
3056 /* we are always the root domain for now */
3057 trusts->array[n].parent_index = 0;
3058 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3059 trusts->array[n].trust_attributes = 0;
3060 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3063 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3065 talloc_free(dom_res);
3073 netr_DsrDeregisterDNSHostRecords
3075 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3076 struct netr_DsrDeregisterDNSHostRecords *r)
3078 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3082 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3083 struct netr_ServerGetTrustInfo *r);
3086 netr_ServerTrustPasswordsGet
3088 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3089 struct netr_ServerTrustPasswordsGet *r)
3091 struct netr_ServerGetTrustInfo r2 = {};
3092 struct netr_TrustInfo *_ti = NULL;
3095 r2.in.server_name = r->in.server_name;
3096 r2.in.account_name = r->in.account_name;
3097 r2.in.secure_channel_type = r->in.secure_channel_type;
3098 r2.in.computer_name = r->in.computer_name;
3099 r2.in.credential = r->in.credential;
3101 r2.out.return_authenticator = r->out.return_authenticator;
3102 r2.out.new_owf_password = r->out.new_owf_password;
3103 r2.out.old_owf_password = r->out.old_owf_password;
3104 r2.out.trust_info = &_ti;
3106 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3108 r->out.return_authenticator = r2.out.return_authenticator;
3109 r->out.new_owf_password = r2.out.new_owf_password;
3110 r->out.old_owf_password = r2.out.old_owf_password;
3116 netr_DsRGetForestTrustInformation
3118 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3119 struct dcesrv_call_state *dce_call;
3120 TALLOC_CTX *mem_ctx;
3121 struct netr_DsRGetForestTrustInformation *r;
3124 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3126 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3127 TALLOC_CTX *mem_ctx,
3128 struct netr_DsRGetForestTrustInformation *r)
3130 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3131 struct dcesrv_connection *conn = dce_call->conn;
3132 struct auth_session_info *session_info = conn->auth_state.session_info;
3133 enum security_user_level security_level;
3134 struct ldb_context *sam_ctx = NULL;
3135 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3136 struct dcerpc_binding_handle *irpc_handle = NULL;
3137 struct tevent_req *subreq = NULL;
3138 struct ldb_dn *domain_dn = NULL;
3139 struct ldb_dn *forest_dn = NULL;
3143 security_level = security_session_user_level(session_info, NULL);
3144 if (security_level < SECURITY_USER) {
3145 return WERR_ACCESS_DENIED;
3148 if (r->in.flags & 0xFFFFFFFE) {
3149 return WERR_INVALID_FLAGS;
3152 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3153 dce_call->conn->auth_state.session_info, 0);
3154 if (sam_ctx == NULL) {
3155 return WERR_GEN_FAILURE;
3158 domain_dn = ldb_get_default_basedn(sam_ctx);
3159 if (domain_dn == NULL) {
3160 return WERR_GEN_FAILURE;
3163 forest_dn = ldb_get_root_basedn(sam_ctx);
3164 if (forest_dn == NULL) {
3165 return WERR_GEN_FAILURE;
3168 cmp = ldb_dn_compare(domain_dn, forest_dn);
3170 return WERR_NERR_ACFNOTLOADED;
3173 forest_level = dsdb_forest_functional_level(sam_ctx);
3174 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3175 return WERR_INVALID_FUNCTION;
3178 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3179 if (!samdb_is_pdc(sam_ctx)) {
3180 return WERR_NERR_NOTPRIMARY;
3183 if (r->in.trusted_domain_name == NULL) {
3184 return WERR_INVALID_FLAGS;
3188 if (r->in.trusted_domain_name == NULL) {
3192 * information about our own domain
3194 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3195 r->out.forest_trust_info);
3196 if (!NT_STATUS_IS_OK(status)) {
3197 return ntstatus_to_werror(status);
3204 * Forward the request to winbindd
3207 state = talloc_zero(mem_ctx,
3208 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3209 if (state == NULL) {
3210 return WERR_NOT_ENOUGH_MEMORY;
3212 state->dce_call = dce_call;
3213 state->mem_ctx = mem_ctx;
3216 irpc_handle = irpc_binding_handle_by_name(state,
3217 state->dce_call->msg_ctx,
3219 &ndr_table_winbind);
3220 if (irpc_handle == NULL) {
3221 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3222 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3223 return WERR_SERVICE_NOT_FOUND;
3227 * 60 seconds timeout should be enough
3229 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3231 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3232 state->dce_call->event_ctx,
3234 r->in.trusted_domain_name,
3236 r->out.forest_trust_info);
3237 if (subreq == NULL) {
3238 return WERR_NOT_ENOUGH_MEMORY;
3240 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3241 tevent_req_set_callback(subreq,
3242 dcesrv_netr_DsRGetForestTrustInformation_done,
3248 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3250 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3251 tevent_req_callback_data(subreq,
3252 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3255 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3257 &state->r->out.result);
3258 TALLOC_FREE(subreq);
3259 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3260 state->r->out.result = WERR_TIMEOUT;
3261 } else if (!NT_STATUS_IS_OK(status)) {
3262 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3263 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3264 nt_errstr(status)));
3267 status = dcesrv_reply(state->dce_call);
3268 if (!NT_STATUS_IS_OK(status)) {
3269 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3274 netr_GetForestTrustInformation
3276 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3277 TALLOC_CTX *mem_ctx,
3278 struct netr_GetForestTrustInformation *r)
3280 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3281 struct netlogon_creds_CredentialState *creds = NULL;
3282 struct ldb_context *sam_ctx = NULL;
3283 struct ldb_dn *domain_dn = NULL;
3284 struct ldb_dn *forest_dn = NULL;
3289 status = dcesrv_netr_creds_server_step_check(dce_call,
3291 r->in.computer_name,
3293 r->out.return_authenticator,
3295 if (!NT_STATUS_IS_OK(status)) {
3299 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3300 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3301 return NT_STATUS_NOT_IMPLEMENTED;
3304 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3305 dce_call->conn->auth_state.session_info, 0);
3306 if (sam_ctx == NULL) {
3307 return NT_STATUS_INTERNAL_ERROR;
3310 /* TODO: check r->in.server_name is our name */
3312 domain_dn = ldb_get_default_basedn(sam_ctx);
3313 if (domain_dn == NULL) {
3314 return NT_STATUS_INTERNAL_ERROR;
3317 forest_dn = ldb_get_root_basedn(sam_ctx);
3318 if (forest_dn == NULL) {
3319 return NT_STATUS_INTERNAL_ERROR;
3322 cmp = ldb_dn_compare(domain_dn, forest_dn);
3324 return NT_STATUS_INVALID_DOMAIN_STATE;
3327 forest_level = dsdb_forest_functional_level(sam_ctx);
3328 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3329 return NT_STATUS_INVALID_DOMAIN_STATE;
3332 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3333 r->out.forest_trust_info);
3334 if (!NT_STATUS_IS_OK(status)) {
3338 return NT_STATUS_OK;
3343 netr_ServerGetTrustInfo
3345 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3346 struct netr_ServerGetTrustInfo *r)
3348 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3349 struct netlogon_creds_CredentialState *creds = NULL;
3350 struct ldb_context *sam_ctx = NULL;
3351 const char * const attrs[] = {
3354 "userAccountControl",
3357 struct ldb_message **res = NULL;
3358 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3361 const char *asid = NULL;
3363 const char *aname = NULL;
3364 struct ldb_message *tdo_msg = NULL;
3365 const char * const tdo_attrs[] = {
3366 "trustAuthIncoming",
3370 struct netr_TrustInfo *trust_info = NULL;
3372 ZERO_STRUCTP(r->out.new_owf_password);
3373 ZERO_STRUCTP(r->out.old_owf_password);
3375 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3377 r->in.computer_name,
3379 r->out.return_authenticator,
3381 if (!NT_STATUS_IS_OK(nt_status)) {
3385 /* TODO: check r->in.server_name is our name */
3387 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3388 return NT_STATUS_INVALID_PARAMETER;
3391 if (r->in.secure_channel_type != creds->secure_channel_type) {
3392 return NT_STATUS_INVALID_PARAMETER;
3395 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3396 return NT_STATUS_INVALID_PARAMETER;
3399 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3400 lp_ctx, system_session(lp_ctx), 0);
3401 if (sam_ctx == NULL) {
3402 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3405 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3407 return NT_STATUS_NO_MEMORY;
3410 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3411 "(&(objectClass=user)(objectSid=%s))",
3414 return NT_STATUS_ACCOUNT_DISABLED;
3417 switch (creds->secure_channel_type) {
3418 case SEC_CHAN_DNS_DOMAIN:
3419 case SEC_CHAN_DOMAIN:
3420 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3422 if (uac & UF_ACCOUNTDISABLE) {
3423 return NT_STATUS_ACCOUNT_DISABLED;
3426 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3427 return NT_STATUS_ACCOUNT_DISABLED;
3430 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3431 if (aname == NULL) {
3432 return NT_STATUS_ACCOUNT_DISABLED;
3435 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3436 SEC_CHAN_DOMAIN, aname,
3437 tdo_attrs, mem_ctx, &tdo_msg);
3438 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3439 return NT_STATUS_ACCOUNT_DISABLED;
3441 if (!NT_STATUS_IS_OK(nt_status)) {
3445 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3448 if (!NT_STATUS_IS_OK(nt_status)) {
3452 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3453 if (trust_info == NULL) {
3454 return NT_STATUS_NO_MEMORY;
3457 trust_info->count = 1;
3458 trust_info->data = talloc_array(trust_info, uint32_t,
3460 if (trust_info->data == NULL) {
3461 return NT_STATUS_NO_MEMORY;
3464 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3470 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3473 if (!NT_STATUS_IS_OK(nt_status)) {
3477 prevNtHash = talloc(mem_ctx, struct samr_Password);
3478 if (prevNtHash == NULL) {
3479 return NT_STATUS_NO_MEMORY;
3482 E_md4hash("", prevNtHash->hash);
3486 if (curNtHash != NULL) {
3487 *r->out.new_owf_password = *curNtHash;
3488 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3490 if (prevNtHash != NULL) {
3491 *r->out.old_owf_password = *prevNtHash;
3492 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3495 if (trust_info != NULL) {
3496 *r->out.trust_info = trust_info;
3499 return NT_STATUS_OK;
3505 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3506 struct netr_Unused47 *r)
3508 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3512 struct netr_dnsupdate_RODC_state {
3513 struct dcesrv_call_state *dce_call;
3514 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3515 struct dnsupdate_RODC *r2;
3519 called when the forwarded RODC dns update request is finished
3521 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3523 struct netr_dnsupdate_RODC_state *st =
3524 tevent_req_callback_data(subreq,
3525 struct netr_dnsupdate_RODC_state);
3528 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3529 TALLOC_FREE(subreq);
3530 if (!NT_STATUS_IS_OK(status)) {
3531 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3532 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3535 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3537 status = dcesrv_reply(st->dce_call);
3538 if (!NT_STATUS_IS_OK(status)) {
3539 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3544 netr_DsrUpdateReadOnlyServerDnsRecords
3546 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3547 TALLOC_CTX *mem_ctx,
3548 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3550 struct netlogon_creds_CredentialState *creds;
3552 struct dcerpc_binding_handle *binding_handle;
3553 struct netr_dnsupdate_RODC_state *st;
3554 struct tevent_req *subreq;
3556 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3558 r->in.computer_name,
3560 r->out.return_authenticator,
3562 NT_STATUS_NOT_OK_RETURN(nt_status);
3564 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3565 return NT_STATUS_ACCESS_DENIED;
3568 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3569 NT_STATUS_HAVE_NO_MEMORY(st);
3571 st->dce_call = dce_call;
3573 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3574 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3576 st->r2->in.dom_sid = creds->sid;
3577 st->r2->in.site_name = r->in.site_name;
3578 st->r2->in.dns_ttl = r->in.dns_ttl;
3579 st->r2->in.dns_names = r->in.dns_names;
3580 st->r2->out.dns_names = r->out.dns_names;
3582 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3583 "dnsupdate", &ndr_table_irpc);
3584 if (binding_handle == NULL) {
3585 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3586 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3587 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3590 /* forward the call */
3591 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3592 binding_handle, st->r2);
3593 NT_STATUS_HAVE_NO_MEMORY(subreq);
3595 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3597 /* setup the callback */
3598 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3600 return NT_STATUS_OK;
3604 /* include the generated boilerplate */
3605 #include "librpc/gen_ndr/ndr_netlogon_s.c"