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"
46 #define DCESRV_INTERFACE_NETLOGON_BIND(call, iface) \
47 dcesrv_interface_netlogon_bind(call, iface)
50 * This #define allows the netlogon interface to accept invalid
51 * association groups, because association groups are to coordinate
52 * handles, and handles are not used in NETLOGON. This in turn avoids
53 * the need to coordinate these across multiple possible NETLOGON
56 #define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
58 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_call_state *dce_call,
59 const struct dcesrv_interface *iface)
61 return dcesrv_interface_bind_reject_connect(dce_call, iface);
64 struct netlogon_server_pipe_state {
65 struct netr_Credential client_challenge;
66 struct netr_Credential server_challenge;
69 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
70 struct netr_ServerReqChallenge *r)
72 struct netlogon_server_pipe_state *pipe_state =
73 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
76 ZERO_STRUCTP(r->out.return_credentials);
79 talloc_free(pipe_state);
80 dce_call->context->private_data = NULL;
83 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
84 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
86 pipe_state->client_challenge = *r->in.credentials;
88 generate_random_buffer(pipe_state->server_challenge.data,
89 sizeof(pipe_state->server_challenge.data));
91 *r->out.return_credentials = pipe_state->server_challenge;
93 dce_call->context->private_data = pipe_state;
95 ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
96 &pipe_state->client_challenge,
97 &pipe_state->server_challenge,
99 if (!NT_STATUS_IS_OK(ntstatus)) {
106 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
107 struct netr_ServerAuthenticate3 *r)
109 struct netlogon_server_pipe_state *pipe_state =
110 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
111 bool challenge_valid = false;
112 struct netlogon_server_pipe_state challenge;
113 struct netlogon_creds_CredentialState *creds;
114 struct ldb_context *sam_ctx;
115 struct samr_Password *curNtHash = NULL;
116 struct samr_Password *prevNtHash = NULL;
117 uint32_t user_account_control;
119 struct ldb_message **msgs;
121 const char *attrs[] = {"unicodePwd", "userAccountControl",
123 const char *account_name;
124 uint32_t server_flags = 0;
125 uint32_t negotiate_flags = 0;
126 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
127 bool reject_des_client = !allow_nt4_crypto;
128 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
129 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
130 bool reject_none_rpc = (schannel == true);
132 ZERO_STRUCTP(r->out.return_credentials);
135 if (pipe_state != NULL) {
136 dce_call->context->private_data = NULL;
139 * If we had a challenge remembered on the connection
140 * consider this for usage. This can't be cleanup
143 * This is the default code path for typical clients
144 * which call netr_ServerReqChallenge() and
145 * netr_ServerAuthenticate3() on the same dcerpc connection.
147 challenge = *pipe_state;
149 challenge_valid = true;
155 * Fallback and try to get the challenge from
158 * If too many clients are using this code path,
159 * they may destroy their cache entries as the
160 * TDB has a fixed size limited via a lossy hash
162 * The TDB used is the schannel store, which is
163 * initialised at startup.
165 * NOTE: The challenge is deleted from the DB as soon as it is
166 * fetched, to prevent reuse.
170 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
171 &challenge.client_challenge,
172 &challenge.server_challenge,
173 r->in.computer_name);
175 if (!NT_STATUS_IS_OK(ntstatus)) {
176 ZERO_STRUCT(challenge);
178 challenge_valid = true;
182 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
183 NETLOGON_NEG_PERSISTENT_SAMREPL |
184 NETLOGON_NEG_ARCFOUR |
185 NETLOGON_NEG_PROMOTION_COUNT |
186 NETLOGON_NEG_CHANGELOG_BDC |
187 NETLOGON_NEG_FULL_SYNC_REPL |
188 NETLOGON_NEG_MULTIPLE_SIDS |
190 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
191 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
192 NETLOGON_NEG_GENERIC_PASSTHROUGH |
193 NETLOGON_NEG_CONCURRENT_RPC |
194 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
195 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
196 NETLOGON_NEG_STRONG_KEYS |
197 NETLOGON_NEG_TRANSITIVE_TRUSTS |
198 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
199 NETLOGON_NEG_PASSWORD_SET2 |
200 NETLOGON_NEG_GETDOMAININFO |
201 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
202 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
203 NETLOGON_NEG_RODC_PASSTHROUGH |
204 NETLOGON_NEG_SUPPORTS_AES |
205 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
206 NETLOGON_NEG_AUTHENTICATED_RPC;
208 negotiate_flags = *r->in.negotiate_flags & server_flags;
210 if (negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
211 reject_none_rpc = false;
214 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
215 reject_des_client = false;
218 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
219 reject_des_client = false;
220 reject_md5_client = false;
223 if (reject_des_client || reject_md5_client) {
225 * Here we match Windows 2012 and return no flags.
227 *r->out.negotiate_flags = 0;
228 return NT_STATUS_DOWNGRADE_DETECTED;
232 * This talloc_free is important to prevent re-use of the
233 * challenge. We have to delay it this far due to NETApp
235 * https://bugzilla.samba.org/show_bug.cgi?id=11291
237 TALLOC_FREE(pipe_state);
240 * At this point we must also cleanup the TDB cache
241 * entry, if we fail the client needs to call
242 * netr_ServerReqChallenge again.
244 * Note: this handles a non existing record just fine,
245 * the r->in.computer_name might not be the one used
246 * in netr_ServerReqChallenge(), but we are trying to
247 * just tidy up the normal case to prevent re-use.
249 schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
250 r->in.computer_name);
253 * According to Microsoft (see bugid #6099)
254 * Windows 7 looks at the negotiate_flags
255 * returned in this structure *even if the
256 * call fails with access denied!
258 *r->out.negotiate_flags = negotiate_flags;
260 if (reject_none_rpc) {
261 /* schannel must be used, but client did not offer it. */
262 DEBUG(0,("%s: schannel required but client failed "
263 "to offer it. Client was %s\n",
264 __func__, r->in.account_name));
265 return NT_STATUS_ACCESS_DENIED;
268 switch (r->in.secure_channel_type) {
270 case SEC_CHAN_DNS_DOMAIN:
271 case SEC_CHAN_DOMAIN:
276 return NT_STATUS_INVALID_PARAMETER;
278 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
279 r->in.secure_channel_type));
280 return NT_STATUS_INVALID_PARAMETER;
283 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
284 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
285 if (sam_ctx == NULL) {
286 return NT_STATUS_INVALID_SYSTEM_SERVICE;
289 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
290 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
292 struct ldb_message *tdo_msg = NULL;
293 const char * const tdo_attrs[] = {
299 char *encoded_name = NULL;
301 const char *flatname = NULL;
303 bool require_trailer = true;
304 const char *netbios = NULL;
305 const char *dns = NULL;
307 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
309 require_trailer = false;
312 encoded_name = ldb_binary_encode_string(mem_ctx,
314 if (encoded_name == NULL) {
315 return NT_STATUS_NO_MEMORY;
318 len = strlen(encoded_name);
320 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
323 if (require_trailer && encoded_name[len - 1] != trailer) {
324 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
326 encoded_name[len - 1] = '\0';
328 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
331 netbios = encoded_name;
334 nt_status = dsdb_trust_search_tdo(sam_ctx,
336 tdo_attrs, mem_ctx, &tdo_msg);
337 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
338 DEBUG(2, ("Client asked for a trusted domain secure channel, "
339 "but there's no tdo for [%s] => [%s] \n",
340 r->in.account_name, encoded_name));
341 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
343 if (!NT_STATUS_IS_OK(nt_status)) {
347 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
350 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
351 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
353 if (!NT_STATUS_IS_OK(nt_status)) {
357 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
358 if (flatname == NULL) {
359 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
362 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
363 if (account_name == NULL) {
364 return NT_STATUS_NO_MEMORY;
367 account_name = r->in.account_name;
370 /* pull the user attributes */
371 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
372 "(&(sAMAccountName=%s)(objectclass=user))",
373 ldb_binary_encode_string(mem_ctx, account_name));
375 if (num_records == 0) {
376 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
377 r->in.account_name));
378 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
381 if (num_records > 1) {
382 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
383 return NT_STATUS_INTERNAL_DB_CORRUPTION;
386 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
388 if (user_account_control & UF_ACCOUNTDISABLE) {
389 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
390 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
393 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
394 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
395 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
396 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
398 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
399 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
400 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
401 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
403 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
405 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
406 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
407 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
408 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
410 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
411 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
412 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
413 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
416 /* we should never reach this */
417 return NT_STATUS_INTERNAL_ERROR;
420 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
421 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
422 dce_call->conn->dce_ctx->lp_ctx,
423 msgs[0], NULL, &curNtHash);
424 if (!NT_STATUS_IS_OK(nt_status)) {
425 return NT_STATUS_ACCESS_DENIED;
429 if (curNtHash == NULL) {
430 return NT_STATUS_ACCESS_DENIED;
433 if (!challenge_valid) {
434 DEBUG(1, ("No challenge requested by client [%s/%s], "
435 "cannot authenticate\n",
437 r->in.account_name));
438 return NT_STATUS_ACCESS_DENIED;
441 creds = netlogon_creds_server_init(mem_ctx,
444 r->in.secure_channel_type,
445 &challenge.client_challenge,
446 &challenge.server_challenge,
449 r->out.return_credentials,
451 if (creds == NULL && prevNtHash != NULL) {
453 * We fallback to the previous password for domain trusts.
455 * Note that lpcfg_old_password_allowed_period() doesn't
458 creds = netlogon_creds_server_init(mem_ctx,
461 r->in.secure_channel_type,
462 &challenge.client_challenge,
463 &challenge.server_challenge,
466 r->out.return_credentials,
470 return NT_STATUS_ACCESS_DENIED;
473 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
475 nt_status = schannel_save_creds_state(mem_ctx,
476 dce_call->conn->dce_ctx->lp_ctx,
478 if (!NT_STATUS_IS_OK(nt_status)) {
479 ZERO_STRUCTP(r->out.return_credentials);
483 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
489 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
490 struct netr_ServerAuthenticate *r)
492 struct netr_ServerAuthenticate3 a;
495 * negotiate_flags is used as an [in] parameter
496 * so it need to be initialised.
498 * (I think ... = 0; seems wrong here --metze)
500 uint32_t negotiate_flags_in = 0;
501 uint32_t negotiate_flags_out = 0;
503 a.in.server_name = r->in.server_name;
504 a.in.account_name = r->in.account_name;
505 a.in.secure_channel_type = r->in.secure_channel_type;
506 a.in.computer_name = r->in.computer_name;
507 a.in.credentials = r->in.credentials;
508 a.in.negotiate_flags = &negotiate_flags_in;
510 a.out.return_credentials = r->out.return_credentials;
512 a.out.negotiate_flags = &negotiate_flags_out;
514 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
517 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
518 struct netr_ServerAuthenticate2 *r)
520 struct netr_ServerAuthenticate3 r3;
523 r3.in.server_name = r->in.server_name;
524 r3.in.account_name = r->in.account_name;
525 r3.in.secure_channel_type = r->in.secure_channel_type;
526 r3.in.computer_name = r->in.computer_name;
527 r3.in.credentials = r->in.credentials;
528 r3.out.return_credentials = r->out.return_credentials;
529 r3.in.negotiate_flags = r->in.negotiate_flags;
530 r3.out.negotiate_flags = r->out.negotiate_flags;
533 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
537 * NOTE: The following functions are nearly identical to the ones available in
538 * source3/rpc_server/srv_nelog_nt.c
539 * The reason we keep 2 copies is that they use different structures to
540 * represent the auth_info and the decrpc pipes.
544 * If schannel is required for this call test that it actually is available.
546 static NTSTATUS schannel_check_required(const struct dcesrv_auth *auth_info,
547 const char *computer_name,
548 bool integrity, bool privacy)
551 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
552 if (!privacy && !integrity) {
556 if ((!privacy && integrity) &&
557 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
561 if ((privacy || integrity) &&
562 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
567 /* test didn't pass */
568 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
571 return NT_STATUS_ACCESS_DENIED;
574 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
576 const char *computer_name,
577 struct netr_Authenticator *received_authenticator,
578 struct netr_Authenticator *return_authenticator,
579 struct netlogon_creds_CredentialState **creds_out)
582 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
583 bool schannel_global_required = (schannel == true);
585 if (schannel_global_required) {
586 nt_status = schannel_check_required(&dce_call->conn->auth_state,
589 if (!NT_STATUS_IS_OK(nt_status)) {
594 nt_status = schannel_check_creds_state(mem_ctx,
595 dce_call->conn->dce_ctx->lp_ctx,
597 received_authenticator,
598 return_authenticator,
604 Change the machine account password for the currently connected
605 client. Supplies only the NT#.
608 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
609 struct netr_ServerPasswordSet *r)
611 struct netlogon_creds_CredentialState *creds;
612 struct ldb_context *sam_ctx;
613 const char * const attrs[] = { "unicodePwd", NULL };
614 struct ldb_message **res;
615 struct samr_Password *oldNtHash;
619 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
622 r->in.credential, r->out.return_authenticator,
624 NT_STATUS_NOT_OK_RETURN(nt_status);
626 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);
627 if (sam_ctx == NULL) {
628 return NT_STATUS_INVALID_SYSTEM_SERVICE;
631 netlogon_creds_des_decrypt(creds, r->in.new_password);
633 /* fetch the old password hashes (the NT hash has to exist) */
635 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
636 "(&(objectClass=user)(objectSid=%s))",
637 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
639 return NT_STATUS_WRONG_PASSWORD;
642 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
643 dce_call->conn->dce_ctx->lp_ctx,
644 res[0], NULL, &oldNtHash);
645 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
646 return NT_STATUS_WRONG_PASSWORD;
649 /* Using the sid for the account as the key, set the password */
650 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
652 NULL, /* Don't have version */
653 NULL, /* Don't have plaintext */
654 NULL, r->in.new_password,
655 NULL, oldNtHash, /* Password change */
661 Change the machine account password for the currently connected
662 client. Supplies new plaintext.
664 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
665 struct netr_ServerPasswordSet2 *r)
667 struct netlogon_creds_CredentialState *creds;
668 struct ldb_context *sam_ctx;
669 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
670 struct ldb_message **res;
671 struct samr_Password *oldLmHash, *oldNtHash;
672 struct NL_PASSWORD_VERSION version = {};
673 const uint32_t *new_version = NULL;
675 DATA_BLOB new_password;
677 struct samr_CryptPassword password_buf;
679 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
682 r->in.credential, r->out.return_authenticator,
684 NT_STATUS_NOT_OK_RETURN(nt_status);
686 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);
687 if (sam_ctx == NULL) {
688 return NT_STATUS_INVALID_SYSTEM_SERVICE;
691 memcpy(password_buf.data, r->in.new_password->data, 512);
692 SIVAL(password_buf.data, 512, r->in.new_password->length);
694 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
695 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
697 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
700 switch (creds->secure_channel_type) {
701 case SEC_CHAN_DOMAIN:
702 case SEC_CHAN_DNS_DOMAIN: {
703 uint32_t len = IVAL(password_buf.data, 512);
705 uint32_t ofs = 500 - len;
708 p = password_buf.data + ofs;
710 version.ReservedField = IVAL(p, 0);
711 version.PasswordVersionNumber = IVAL(p, 4);
712 version.PasswordVersionPresent = IVAL(p, 8);
714 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
715 new_version = &version.PasswordVersionNumber;
723 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
724 DEBUG(3,("samr: failed to decode password buffer\n"));
725 return NT_STATUS_WRONG_PASSWORD;
728 /* fetch the old password hashes (at least one of both has to exist) */
730 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
731 "(&(objectClass=user)(objectSid=%s))",
732 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
734 return NT_STATUS_WRONG_PASSWORD;
737 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
738 dce_call->conn->dce_ctx->lp_ctx,
739 res[0], &oldLmHash, &oldNtHash);
740 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
741 return NT_STATUS_WRONG_PASSWORD;
744 /* Using the sid for the account as the key, set the password */
745 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
748 &new_password, /* we have plaintext */
750 oldLmHash, oldNtHash, /* Password change */
759 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
760 struct netr_LogonUasLogon *r)
762 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
769 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
770 struct netr_LogonUasLogoff *r)
772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
776 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
778 switch (r->in.logon_level) {
779 case NetlogonInteractiveInformation:
780 case NetlogonServiceInformation:
781 case NetlogonInteractiveTransitiveInformation:
782 case NetlogonServiceTransitiveInformation:
783 if (r->in.logon->password == NULL) {
784 return NT_STATUS_INVALID_PARAMETER;
787 switch (r->in.validation_level) {
788 case NetlogonValidationSamInfo: /* 2 */
789 case NetlogonValidationSamInfo2: /* 3 */
790 case NetlogonValidationSamInfo4: /* 6 */
793 return NT_STATUS_INVALID_INFO_CLASS;
797 case NetlogonNetworkInformation:
798 case NetlogonNetworkTransitiveInformation:
799 if (r->in.logon->network == NULL) {
800 return NT_STATUS_INVALID_PARAMETER;
803 switch (r->in.validation_level) {
804 case NetlogonValidationSamInfo: /* 2 */
805 case NetlogonValidationSamInfo2: /* 3 */
806 case NetlogonValidationSamInfo4: /* 6 */
809 return NT_STATUS_INVALID_INFO_CLASS;
814 case NetlogonGenericInformation:
815 if (r->in.logon->generic == NULL) {
816 return NT_STATUS_INVALID_PARAMETER;
819 switch (r->in.validation_level) {
820 /* TODO: case NetlogonValidationGenericInfo: 4 */
821 case NetlogonValidationGenericInfo2: /* 5 */
824 return NT_STATUS_INVALID_INFO_CLASS;
829 return NT_STATUS_INVALID_PARAMETER;
836 netr_LogonSamLogon_base
838 This version of the function allows other wrappers to say 'do not check the credentials'
840 We can't do the traditional 'wrapping' format completely, as this
841 function must only run under schannel
843 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
844 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
846 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
847 const char *workgroup = lpcfg_workgroup(lp_ctx);
848 struct auth4_context *auth_context = NULL;
849 struct auth_usersupplied_info *user_info = NULL;
850 struct auth_user_info_dc *user_info_dc = NULL;
852 struct netr_SamInfo2 *sam2 = NULL;
853 struct netr_SamInfo3 *sam3 = NULL;
854 struct netr_SamInfo6 *sam6 = NULL;
856 *r->out.authoritative = 1;
858 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
859 NT_STATUS_HAVE_NO_MEMORY(user_info);
861 user_info->service_description = "SamLogon";
863 netlogon_creds_decrypt_samlogon_logon(creds,
867 switch (r->in.logon_level) {
868 case NetlogonInteractiveInformation:
869 case NetlogonServiceInformation:
870 case NetlogonInteractiveTransitiveInformation:
871 case NetlogonServiceTransitiveInformation:
872 case NetlogonNetworkInformation:
873 case NetlogonNetworkTransitiveInformation:
875 nt_status = auth_context_create_for_netlogon(mem_ctx,
876 dce_call->event_ctx, dce_call->msg_ctx,
877 dce_call->conn->dce_ctx->lp_ctx,
879 NT_STATUS_NOT_OK_RETURN(nt_status);
881 user_info->remote_host = dce_call->conn->remote_address;
882 user_info->local_host = dce_call->conn->local_address;
884 user_info->netlogon_trust_account.secure_channel_type
885 = creds->secure_channel_type;
886 user_info->netlogon_trust_account.negotiate_flags
887 = creds->negotiate_flags;
890 * These two can be unrelated when the account is
891 * actually that of a trusted domain, so we want to
892 * know which DC in that trusted domain contacted
895 user_info->netlogon_trust_account.computer_name
896 = creds->computer_name;
897 user_info->netlogon_trust_account.account_name
898 = creds->account_name;
899 user_info->netlogon_trust_account.sid
903 /* We do not need to set up the user_info in this case */
907 switch (r->in.logon_level) {
908 case NetlogonInteractiveInformation:
909 case NetlogonServiceInformation:
910 case NetlogonInteractiveTransitiveInformation:
911 case NetlogonServiceTransitiveInformation:
912 user_info->auth_description = "interactive";
914 user_info->logon_parameters
915 = r->in.logon->password->identity_info.parameter_control;
916 user_info->client.account_name
917 = r->in.logon->password->identity_info.account_name.string;
918 user_info->client.domain_name
919 = r->in.logon->password->identity_info.domain_name.string;
920 user_info->workstation_name
921 = r->in.logon->password->identity_info.workstation.string;
922 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
923 user_info->password_state = AUTH_PASSWORD_HASH;
925 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
926 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
927 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
929 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
930 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
931 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
934 case NetlogonNetworkInformation:
935 case NetlogonNetworkTransitiveInformation:
936 user_info->auth_description = "network";
938 nt_status = auth_context_set_challenge(
940 r->in.logon->network->challenge,
941 "netr_LogonSamLogonWithFlags");
942 NT_STATUS_NOT_OK_RETURN(nt_status);
944 user_info->logon_parameters
945 = r->in.logon->network->identity_info.parameter_control;
946 user_info->client.account_name
947 = r->in.logon->network->identity_info.account_name.string;
948 user_info->client.domain_name
949 = r->in.logon->network->identity_info.domain_name.string;
950 user_info->workstation_name
951 = r->in.logon->network->identity_info.workstation.string;
953 user_info->password_state = AUTH_PASSWORD_RESPONSE;
954 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
955 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
957 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
958 user_info->client.account_name,
959 user_info->client.domain_name,
960 user_info->password.response.nt,
962 NT_STATUS_NOT_OK_RETURN(nt_status);
967 case NetlogonGenericInformation:
969 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
971 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
974 /* Using DES to verify kerberos tickets makes no sense */
975 return NT_STATUS_INVALID_PARAMETER;
978 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
980 struct dcerpc_binding_handle *irpc_handle;
981 struct kdc_check_generic_kerberos check;
982 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
983 NT_STATUS_HAVE_NO_MEMORY(generic);
984 *r->out.authoritative = 1;
986 /* TODO: Describe and deal with these flags */
989 r->out.validation->generic = generic;
991 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
995 if (irpc_handle == NULL) {
996 return NT_STATUS_NO_LOGON_SERVERS;
999 check.in.generic_request =
1000 data_blob_const(r->in.logon->generic->data,
1001 r->in.logon->generic->length);
1004 * TODO: make this async and avoid
1005 * dcerpc_binding_handle_set_sync_ev()
1007 dcerpc_binding_handle_set_sync_ev(irpc_handle,
1008 dce_call->event_ctx);
1009 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
1012 if (!NT_STATUS_IS_OK(status)) {
1015 generic->length = check.out.generic_reply.length;
1016 generic->data = check.out.generic_reply.data;
1017 return NT_STATUS_OK;
1020 /* Until we get an implemetnation of these other packages */
1021 return NT_STATUS_INVALID_PARAMETER;
1024 return NT_STATUS_INVALID_PARAMETER;
1027 nt_status = auth_check_password(auth_context, mem_ctx, user_info,
1028 &user_info_dc, r->out.authoritative);
1029 NT_STATUS_NOT_OK_RETURN(nt_status);
1031 switch (r->in.validation_level) {
1033 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1036 NT_STATUS_NOT_OK_RETURN(nt_status);
1038 r->out.validation->sam2 = sam2;
1042 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1045 NT_STATUS_NOT_OK_RETURN(nt_status);
1047 r->out.validation->sam3 = sam3;
1051 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1052 return NT_STATUS_INVALID_PARAMETER;
1055 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1058 NT_STATUS_NOT_OK_RETURN(nt_status);
1060 r->out.validation->sam6 = sam6;
1064 return NT_STATUS_INVALID_INFO_CLASS;
1067 netlogon_creds_encrypt_samlogon_validation(creds,
1068 r->in.validation_level,
1071 /* TODO: Describe and deal with these flags */
1074 return NT_STATUS_OK;
1077 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1078 struct netr_LogonSamLogonEx *r)
1081 struct netlogon_creds_CredentialState *creds;
1083 *r->out.authoritative = 1;
1085 nt_status = dcesrv_netr_LogonSamLogon_check(r);
1086 if (!NT_STATUS_IS_OK(nt_status)) {
1090 nt_status = schannel_get_creds_state(mem_ctx,
1091 dce_call->conn->dce_ctx->lp_ctx,
1092 r->in.computer_name, &creds);
1093 if (!NT_STATUS_IS_OK(nt_status)) {
1097 if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1098 return NT_STATUS_ACCESS_DENIED;
1100 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1104 netr_LogonSamLogonWithFlags
1107 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1108 struct netr_LogonSamLogonWithFlags *r)
1111 struct netlogon_creds_CredentialState *creds;
1112 struct netr_LogonSamLogonEx r2;
1114 struct netr_Authenticator *return_authenticator;
1118 r2.in.server_name = r->in.server_name;
1119 r2.in.computer_name = r->in.computer_name;
1120 r2.in.logon_level = r->in.logon_level;
1121 r2.in.logon = r->in.logon;
1122 r2.in.validation_level = r->in.validation_level;
1123 r2.in.flags = r->in.flags;
1124 r2.out.validation = r->out.validation;
1125 r2.out.authoritative = r->out.authoritative;
1126 r2.out.flags = r->out.flags;
1128 *r->out.authoritative = 1;
1130 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1131 if (!NT_STATUS_IS_OK(nt_status)) {
1135 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1136 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1138 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1140 r->in.computer_name,
1141 r->in.credential, return_authenticator,
1143 NT_STATUS_NOT_OK_RETURN(nt_status);
1145 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1147 r->out.return_authenticator = return_authenticator;
1155 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1156 struct netr_LogonSamLogon *r)
1158 struct netr_LogonSamLogonWithFlags r2;
1164 r2.in.server_name = r->in.server_name;
1165 r2.in.computer_name = r->in.computer_name;
1166 r2.in.credential = r->in.credential;
1167 r2.in.return_authenticator = r->in.return_authenticator;
1168 r2.in.logon_level = r->in.logon_level;
1169 r2.in.logon = r->in.logon;
1170 r2.in.validation_level = r->in.validation_level;
1171 r2.in.flags = &flags;
1172 r2.out.validation = r->out.validation;
1173 r2.out.authoritative = r->out.authoritative;
1174 r2.out.flags = &flags;
1176 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1178 r->out.return_authenticator = r2.out.return_authenticator;
1187 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1188 struct netr_LogonSamLogoff *r)
1190 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1198 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1199 struct netr_DatabaseDeltas *r)
1201 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1208 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1209 struct netr_DatabaseSync2 *r)
1211 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1212 return NT_STATUS_NOT_IMPLEMENTED;
1219 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1220 struct netr_DatabaseSync *r)
1222 struct netr_DatabaseSync2 r2;
1227 r2.in.logon_server = r->in.logon_server;
1228 r2.in.computername = r->in.computername;
1229 r2.in.credential = r->in.credential;
1230 r2.in.database_id = r->in.database_id;
1231 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1232 r2.in.sync_context = r->in.sync_context;
1233 r2.out.sync_context = r->out.sync_context;
1234 r2.out.delta_enum_array = r->out.delta_enum_array;
1235 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1237 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1246 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1247 struct netr_AccountDeltas *r)
1249 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1250 return NT_STATUS_NOT_IMPLEMENTED;
1257 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1258 struct netr_AccountSync *r)
1260 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1261 return NT_STATUS_NOT_IMPLEMENTED;
1268 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1269 struct netr_GetDcName *r)
1271 const char * const attrs[] = { NULL };
1272 struct ldb_context *sam_ctx;
1273 struct ldb_message **res;
1274 struct ldb_dn *domain_dn;
1279 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1280 * that the domainname needs to be a valid netbios domain
1281 * name, if it is not NULL.
1283 if (r->in.domainname) {
1284 const char *dot = strchr(r->in.domainname, '.');
1285 size_t len = strlen(r->in.domainname);
1287 if (dot || len > 15) {
1288 return WERR_NERR_DCNOTFOUND;
1292 * TODO: Should we also varify that only valid
1293 * netbios name characters are used?
1297 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1298 dce_call->conn->dce_ctx->lp_ctx,
1299 dce_call->conn->auth_state.session_info, 0);
1300 if (sam_ctx == NULL) {
1301 return WERR_DS_UNAVAILABLE;
1304 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1306 if (domain_dn == NULL) {
1307 return WERR_NO_SUCH_DOMAIN;
1310 ret = gendb_search_dn(sam_ctx, mem_ctx,
1311 domain_dn, &res, attrs);
1313 return WERR_NO_SUCH_DOMAIN;
1316 /* TODO: - return real IP address
1317 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1319 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1320 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1321 W_ERROR_HAVE_NO_MEMORY(dcname);
1323 *r->out.dcname = dcname;
1327 struct dcesrv_netr_LogonControl_base_state {
1328 struct dcesrv_call_state *dce_call;
1330 TALLOC_CTX *mem_ctx;
1332 struct netr_LogonControl2Ex r;
1335 struct netr_LogonControl *l;
1336 struct netr_LogonControl2 *l2;
1337 struct netr_LogonControl2Ex *l2ex;
1341 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1343 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1345 struct dcesrv_connection *conn = state->dce_call->conn;
1346 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1347 struct auth_session_info *session_info = conn->auth_state.session_info;
1348 enum security_user_level security_level;
1349 struct dcerpc_binding_handle *irpc_handle;
1350 struct tevent_req *subreq;
1353 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1355 if (state->_r.l != NULL) {
1359 if (state->r.in.level == 0x00000002) {
1360 return WERR_NOT_SUPPORTED;
1361 } else if (state->r.in.level != 0x00000001) {
1362 return WERR_INVALID_LEVEL;
1365 switch (state->r.in.function_code) {
1366 case NETLOGON_CONTROL_QUERY:
1367 case NETLOGON_CONTROL_REPLICATE:
1368 case NETLOGON_CONTROL_SYNCHRONIZE:
1369 case NETLOGON_CONTROL_PDC_REPLICATE:
1370 case NETLOGON_CONTROL_BREAKPOINT:
1371 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1372 case NETLOGON_CONTROL_TRUNCATE_LOG:
1375 return WERR_NOT_SUPPORTED;
1379 if (state->r.in.level < 0x00000001) {
1380 return WERR_INVALID_LEVEL;
1383 if (state->r.in.level > 0x00000004) {
1384 return WERR_INVALID_LEVEL;
1387 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1388 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1389 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1391 switch (state->r.in.level) {
1393 info1 = talloc_zero(state->mem_ctx,
1394 struct netr_NETLOGON_INFO_1);
1395 if (info1 == NULL) {
1396 return WERR_NOT_ENOUGH_MEMORY;
1398 state->r.out.query->info1 = info1;
1402 info3 = talloc_zero(state->mem_ctx,
1403 struct netr_NETLOGON_INFO_3);
1404 if (info3 == NULL) {
1405 return WERR_NOT_ENOUGH_MEMORY;
1407 state->r.out.query->info3 = info3;
1411 return WERR_INVALID_PARAMETER;
1416 * Some validations are done before the access check
1417 * and some after the access check
1419 security_level = security_session_user_level(session_info, NULL);
1420 if (security_level < SECURITY_ADMINISTRATOR) {
1421 return WERR_ACCESS_DENIED;
1424 if (state->_r.l2 != NULL) {
1426 * netr_LogonControl2
1428 if (state->r.in.level == 0x00000004) {
1429 return WERR_INVALID_LEVEL;
1433 switch (state->r.in.level) {
1438 switch (state->r.in.function_code) {
1439 case NETLOGON_CONTROL_REDISCOVER:
1440 case NETLOGON_CONTROL_TC_QUERY:
1441 case NETLOGON_CONTROL_TC_VERIFY:
1444 return WERR_INVALID_PARAMETER;
1453 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1454 return WERR_INVALID_PARAMETER;
1460 return WERR_INVALID_LEVEL;
1463 switch (state->r.in.function_code) {
1464 case NETLOGON_CONTROL_REDISCOVER:
1465 case NETLOGON_CONTROL_TC_QUERY:
1466 case NETLOGON_CONTROL_TC_VERIFY:
1467 if (state->r.in.level != 2) {
1468 return WERR_INVALID_PARAMETER;
1471 if (state->r.in.data == NULL) {
1472 return WERR_INVALID_PARAMETER;
1475 if (state->r.in.data->domain == NULL) {
1476 return WERR_INVALID_PARAMETER;
1481 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1482 if (state->r.in.level != 1) {
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;
1494 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1495 state->r.in.data->domain);
1497 struct ldb_context *sam_ctx;
1499 sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1500 lp_ctx, system_session(lp_ctx), 0);
1501 if (sam_ctx == NULL) {
1502 return WERR_DS_UNAVAILABLE;
1506 * Secrets for trusted domains can only be triggered on
1509 ok = samdb_is_pdc(sam_ctx);
1510 TALLOC_FREE(sam_ctx);
1512 return WERR_INVALID_DOMAIN_ROLE;
1518 return WERR_NOT_SUPPORTED;
1521 irpc_handle = irpc_binding_handle_by_name(state,
1522 state->dce_call->msg_ctx,
1524 &ndr_table_winbind);
1525 if (irpc_handle == NULL) {
1526 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1527 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1528 return WERR_SERVICE_NOT_FOUND;
1532 * 60 seconds timeout should be enough
1534 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1536 subreq = dcerpc_winbind_LogonControl_send(state,
1537 state->dce_call->event_ctx,
1539 state->r.in.function_code,
1542 state->r.out.query);
1543 if (subreq == NULL) {
1544 return WERR_NOT_ENOUGH_MEMORY;
1546 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1547 tevent_req_set_callback(subreq,
1548 dcesrv_netr_LogonControl_base_done,
1554 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1556 struct dcesrv_netr_LogonControl_base_state *state =
1557 tevent_req_callback_data(subreq,
1558 struct dcesrv_netr_LogonControl_base_state);
1561 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1562 &state->r.out.result);
1563 TALLOC_FREE(subreq);
1564 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1565 state->r.out.result = WERR_TIMEOUT;
1566 } else if (!NT_STATUS_IS_OK(status)) {
1567 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1568 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1569 nt_errstr(status)));
1572 if (state->_r.l2ex != NULL) {
1573 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1574 r->out.result = state->r.out.result;
1575 } else if (state->_r.l2 != NULL) {
1576 struct netr_LogonControl2 *r = state->_r.l2;
1577 r->out.result = state->r.out.result;
1578 } else if (state->_r.l != NULL) {
1579 struct netr_LogonControl *r = state->_r.l;
1580 r->out.result = state->r.out.result;
1583 status = dcesrv_reply(state->dce_call);
1584 if (!NT_STATUS_IS_OK(status)) {
1585 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1592 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1593 struct netr_LogonControl *r)
1595 struct dcesrv_netr_LogonControl_base_state *state;
1598 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1599 if (state == NULL) {
1600 return WERR_NOT_ENOUGH_MEMORY;
1603 state->dce_call = dce_call;
1604 state->mem_ctx = mem_ctx;
1606 state->r.in.logon_server = r->in.logon_server;
1607 state->r.in.function_code = r->in.function_code;
1608 state->r.in.level = r->in.level;
1609 state->r.in.data = NULL;
1610 state->r.out.query = r->out.query;
1614 werr = dcesrv_netr_LogonControl_base_call(state);
1616 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1626 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1627 struct netr_LogonControl2 *r)
1629 struct dcesrv_netr_LogonControl_base_state *state;
1632 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1633 if (state == NULL) {
1634 return WERR_NOT_ENOUGH_MEMORY;
1637 state->dce_call = dce_call;
1638 state->mem_ctx = mem_ctx;
1640 state->r.in.logon_server = r->in.logon_server;
1641 state->r.in.function_code = r->in.function_code;
1642 state->r.in.level = r->in.level;
1643 state->r.in.data = r->in.data;
1644 state->r.out.query = r->out.query;
1648 werr = dcesrv_netr_LogonControl_base_call(state);
1650 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1658 netr_LogonControl2Ex
1660 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1661 struct netr_LogonControl2Ex *r)
1663 struct dcesrv_netr_LogonControl_base_state *state;
1666 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1667 if (state == NULL) {
1668 return WERR_NOT_ENOUGH_MEMORY;
1671 state->dce_call = dce_call;
1672 state->mem_ctx = mem_ctx;
1677 werr = dcesrv_netr_LogonControl_base_call(state);
1679 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1686 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1687 struct ldb_context *sam_ctx,
1688 struct netr_DomainTrustList *trusts,
1689 uint32_t trust_flags);
1694 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1695 struct netr_GetAnyDCName *r)
1697 struct netr_DomainTrustList *trusts;
1698 struct ldb_context *sam_ctx;
1699 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1703 *r->out.dcname = NULL;
1705 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1706 /* if the domainname parameter wasn't set assume our domain */
1707 r->in.domainname = lpcfg_workgroup(lp_ctx);
1710 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1711 dce_call->conn->auth_state.session_info, 0);
1712 if (sam_ctx == NULL) {
1713 return WERR_DS_UNAVAILABLE;
1716 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1717 /* well we asked for a DC of our own domain */
1718 if (samdb_is_pdc(sam_ctx)) {
1719 /* we are the PDC of the specified domain */
1720 return WERR_NO_SUCH_DOMAIN;
1723 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1724 lpcfg_netbios_name(lp_ctx));
1725 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1730 /* Okay, now we have to consider the trusted domains */
1732 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1733 W_ERROR_HAVE_NO_MEMORY(trusts);
1737 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1738 NETR_TRUST_FLAG_INBOUND
1739 | NETR_TRUST_FLAG_OUTBOUND);
1740 W_ERROR_NOT_OK_RETURN(werr);
1742 for (i = 0; i < trusts->count; i++) {
1743 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1744 /* FIXME: Here we need to find a DC for the specified
1745 * trusted domain. */
1747 /* return WERR_OK; */
1748 return WERR_NO_SUCH_DOMAIN;
1752 return WERR_NO_SUCH_DOMAIN;
1759 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1760 struct netr_DatabaseRedo *r)
1762 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1767 netr_NetrEnumerateTrustedDomains
1769 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1770 struct netr_NetrEnumerateTrustedDomains *r)
1772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1777 netr_LogonGetCapabilities
1779 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1780 struct netr_LogonGetCapabilities *r)
1782 struct netlogon_creds_CredentialState *creds;
1785 status = dcesrv_netr_creds_server_step_check(dce_call,
1787 r->in.computer_name,
1789 r->out.return_authenticator,
1791 if (!NT_STATUS_IS_OK(status)) {
1792 DEBUG(0,(__location__ " Bad credentials - error\n"));
1794 NT_STATUS_NOT_OK_RETURN(status);
1796 if (r->in.query_level != 1) {
1797 return NT_STATUS_NOT_SUPPORTED;
1800 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1802 return NT_STATUS_OK;
1807 netr_NETRLOGONSETSERVICEBITS
1809 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1810 struct netr_NETRLOGONSETSERVICEBITS *r)
1812 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1817 netr_LogonGetTrustRid
1819 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1820 struct netr_LogonGetTrustRid *r)
1822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1827 netr_NETRLOGONCOMPUTESERVERDIGEST
1829 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1830 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1837 netr_NETRLOGONCOMPUTECLIENTDIGEST
1839 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1840 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1850 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1851 struct netr_DsRGetSiteName *r)
1853 struct ldb_context *sam_ctx;
1854 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1856 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1857 dce_call->conn->auth_state.session_info, 0);
1858 if (sam_ctx == NULL) {
1859 return WERR_DS_UNAVAILABLE;
1863 * We assume to be a DC when we get called over NETLOGON. Hence we
1864 * get our site name always by using "samdb_server_site_name()"
1865 * and not "samdb_client_site_name()".
1867 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1868 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1875 fill in a netr_OneDomainInfo from a ldb search result
1877 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1878 struct loadparm_context *lp_ctx,
1879 struct ldb_context *sam_ctx,
1880 struct ldb_message *res,
1881 struct netr_OneDomainInfo *info,
1882 bool is_local, bool is_trust_list)
1886 if (is_trust_list) {
1887 /* w2k8 only fills this on trusted domains */
1888 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1889 info->trust_extension.length = 16;
1890 info->trust_extension.info->flags =
1891 NETR_TRUST_FLAG_TREEROOT |
1892 NETR_TRUST_FLAG_IN_FOREST |
1893 NETR_TRUST_FLAG_PRIMARY |
1894 NETR_TRUST_FLAG_NATIVE;
1896 info->trust_extension.info->parent_index = 0; /* should be index into array
1898 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1899 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1902 if (is_trust_list) {
1903 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1904 info->dns_forestname.string = NULL;
1906 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1907 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1908 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1909 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1913 info->domainname.string = lpcfg_workgroup(lp_ctx);
1914 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1915 info->domain_guid = samdb_result_guid(res, "objectGUID");
1916 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1918 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1919 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1920 info->domain_guid = samdb_result_guid(res, "objectGUID");
1921 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1923 if (!is_trust_list) {
1924 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1927 return NT_STATUS_OK;
1931 netr_LogonGetDomainInfo
1932 this is called as part of the ADS domain logon procedure.
1934 It has an important role in convaying details about the client, such
1935 as Operating System, Version, Service Pack etc.
1937 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1938 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1940 struct netlogon_creds_CredentialState *creds;
1941 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1942 "securityIdentifier", "trustPartner", NULL };
1943 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1944 "msDS-SupportedEncryptionTypes", NULL };
1945 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1946 struct ldb_context *sam_ctx;
1947 struct ldb_message **res1, **res2, **res3, *new_msg;
1948 struct ldb_dn *workstation_dn;
1949 struct netr_DomainInformation *domain_info;
1950 struct netr_LsaPolicyInformation *lsa_policy_info;
1951 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1952 bool update_dns_hostname = true;
1956 status = dcesrv_netr_creds_server_step_check(dce_call,
1958 r->in.computer_name,
1960 r->out.return_authenticator,
1962 if (!NT_STATUS_IS_OK(status)) {
1963 DEBUG(0,(__location__ " Bad credentials - error\n"));
1965 NT_STATUS_NOT_OK_RETURN(status);
1967 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1968 dce_call->conn->dce_ctx->lp_ctx,
1969 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1970 if (sam_ctx == NULL) {
1971 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1974 switch (r->in.level) {
1975 case 1: /* Domain information */
1977 if (r->in.query->workstation_info == NULL) {
1978 return NT_STATUS_INVALID_PARAMETER;
1981 /* Prepares the workstation DN */
1982 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1983 dom_sid_string(mem_ctx, creds->sid));
1984 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1986 /* Lookup for attributes in workstation object */
1987 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1990 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1993 /* Gets the sam account name which is checked against the DNS
1994 * hostname parameter. */
1995 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1998 if (sam_account_name == NULL) {
1999 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2003 * Checks that the sam account name without a possible "$"
2004 * matches as prefix with the DNS hostname in the workstation
2007 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2008 strcspn(sam_account_name, "$"));
2009 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2010 if (r->in.query->workstation_info->dns_hostname != NULL) {
2011 prefix2 = talloc_strndup(mem_ctx,
2012 r->in.query->workstation_info->dns_hostname,
2013 strcspn(r->in.query->workstation_info->dns_hostname, "."));
2014 NT_STATUS_HAVE_NO_MEMORY(prefix2);
2016 if (strcasecmp(prefix1, prefix2) != 0) {
2017 update_dns_hostname = false;
2020 update_dns_hostname = false;
2023 /* Gets the old DNS hostname */
2024 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2029 * Updates the DNS hostname when the client wishes that the
2030 * server should handle this for him
2031 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2032 * obviously only checked when we do already have a
2034 * See MS-NRPC section 3.5.4.3.9
2036 if ((old_dns_hostname != NULL) &&
2037 (r->in.query->workstation_info->workstation_flags
2038 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2039 update_dns_hostname = false;
2042 /* Gets host information and put them into our directory */
2044 new_msg = ldb_msg_new(mem_ctx);
2045 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2047 new_msg->dn = workstation_dn;
2049 /* Sets the OS name */
2051 if (r->in.query->workstation_info->os_name.string == NULL) {
2052 return NT_STATUS_INVALID_PARAMETER;
2055 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2056 r->in.query->workstation_info->os_name.string);
2057 if (ret != LDB_SUCCESS) {
2058 return NT_STATUS_NO_MEMORY;
2062 * Sets information from "os_version". On an empty structure
2063 * the values are cleared.
2065 if (r->in.query->workstation_info->os_version.os != NULL) {
2066 struct netr_OsVersionInfoEx *os_version;
2067 const char *os_version_str;
2069 os_version = &r->in.query->workstation_info->os_version.os->os;
2071 if (os_version->CSDVersion == NULL) {
2072 return NT_STATUS_INVALID_PARAMETER;
2075 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2076 os_version->MajorVersion,
2077 os_version->MinorVersion,
2078 os_version->BuildNumber);
2079 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2081 ret = ldb_msg_add_string(new_msg,
2082 "operatingSystemServicePack",
2083 os_version->CSDVersion);
2084 if (ret != LDB_SUCCESS) {
2085 return NT_STATUS_NO_MEMORY;
2088 ret = ldb_msg_add_string(new_msg,
2089 "operatingSystemVersion",
2091 if (ret != LDB_SUCCESS) {
2092 return NT_STATUS_NO_MEMORY;
2095 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2096 "operatingSystemServicePack");
2097 if (ret != LDB_SUCCESS) {
2098 return NT_STATUS_NO_MEMORY;
2101 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2102 "operatingSystemVersion");
2103 if (ret != LDB_SUCCESS) {
2104 return NT_STATUS_NO_MEMORY;
2109 * If the boolean "update_dns_hostname" remained true, then we
2110 * are fine to start the update.
2112 if (update_dns_hostname) {
2113 ret = ldb_msg_add_string(new_msg,
2115 r->in.query->workstation_info->dns_hostname);
2116 if (ret != LDB_SUCCESS) {
2117 return NT_STATUS_NO_MEMORY;
2120 /* This manual "servicePrincipalName" generation is
2121 * still needed! Since the update in the samldb LDB
2122 * module does only work if the entries already exist
2123 * which isn't always the case. */
2124 ret = ldb_msg_add_string(new_msg,
2125 "servicePrincipalName",
2126 talloc_asprintf(new_msg, "HOST/%s",
2127 r->in.computer_name));
2128 if (ret != LDB_SUCCESS) {
2129 return NT_STATUS_NO_MEMORY;
2132 ret = ldb_msg_add_string(new_msg,
2133 "servicePrincipalName",
2134 talloc_asprintf(new_msg, "HOST/%s",
2135 r->in.query->workstation_info->dns_hostname));
2136 if (ret != LDB_SUCCESS) {
2137 return NT_STATUS_NO_MEMORY;
2141 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2142 DEBUG(3,("Impossible to update samdb: %s\n",
2143 ldb_errstring(sam_ctx)));
2146 talloc_free(new_msg);
2148 /* Writes back the domain information */
2150 /* We need to do two searches. The first will pull our primary
2151 domain and the second will pull any trusted domains. Our
2152 primary domain is also a "trusted" domain, so we need to
2153 put the primary domain into the lists of returned trusts as
2155 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2158 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2161 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2162 "(objectClass=trustedDomain)");
2164 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2167 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2168 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2170 ZERO_STRUCTP(domain_info);
2172 /* Informations about the local and trusted domains */
2174 status = fill_one_domain_info(mem_ctx,
2175 dce_call->conn->dce_ctx->lp_ctx,
2176 sam_ctx, res2[0], &domain_info->primary_domain,
2178 NT_STATUS_NOT_OK_RETURN(status);
2180 domain_info->trusted_domain_count = ret3 + 1;
2181 domain_info->trusted_domains = talloc_array(mem_ctx,
2182 struct netr_OneDomainInfo,
2183 domain_info->trusted_domain_count);
2184 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2186 for (i=0;i<ret3;i++) {
2187 status = fill_one_domain_info(mem_ctx,
2188 dce_call->conn->dce_ctx->lp_ctx,
2190 &domain_info->trusted_domains[i],
2192 NT_STATUS_NOT_OK_RETURN(status);
2195 status = fill_one_domain_info(mem_ctx,
2196 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2197 &domain_info->trusted_domains[i], true, true);
2198 NT_STATUS_NOT_OK_RETURN(status);
2200 /* Sets the supported encryption types */
2201 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2202 "msDS-SupportedEncryptionTypes",
2203 default_supported_enc_types);
2205 /* Other host domain information */
2207 lsa_policy_info = talloc(mem_ctx,
2208 struct netr_LsaPolicyInformation);
2209 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2210 ZERO_STRUCTP(lsa_policy_info);
2212 domain_info->lsa_policy = *lsa_policy_info;
2214 /* The DNS hostname is only returned back when there is a chance
2216 if ((r->in.query->workstation_info->workstation_flags
2217 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2218 domain_info->dns_hostname.string = old_dns_hostname;
2220 domain_info->dns_hostname.string = NULL;
2223 domain_info->workstation_flags =
2224 r->in.query->workstation_info->workstation_flags & (
2225 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2227 r->out.info->domain_info = domain_info;
2229 case 2: /* LSA policy information - not used at the moment */
2230 lsa_policy_info = talloc(mem_ctx,
2231 struct netr_LsaPolicyInformation);
2232 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2233 ZERO_STRUCTP(lsa_policy_info);
2235 r->out.info->lsa_policy_info = lsa_policy_info;
2238 return NT_STATUS_INVALID_LEVEL;
2242 return NT_STATUS_OK;
2247 netr_ServerPasswordGet
2249 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2250 struct netr_ServerPasswordGet *r)
2252 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2257 netr_NETRLOGONSENDTOSAM
2259 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2260 struct netr_NETRLOGONSENDTOSAM *r)
2262 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2267 netr_DsRGetDCNameEx2
2269 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2270 TALLOC_CTX *mem_ctx,
2271 struct netr_DsRGetDCNameEx2 *r)
2273 struct ldb_context *sam_ctx;
2274 struct netr_DsRGetDCNameInfo *info;
2275 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2276 const struct tsocket_address *local_address;
2277 char *local_addr = NULL;
2278 const struct tsocket_address *remote_address;
2279 char *remote_addr = NULL;
2280 const char *server_site_name;
2282 struct netlogon_samlogon_response response;
2284 const char *dc_name = NULL;
2285 const char *domain_name = NULL;
2288 ZERO_STRUCTP(r->out.info);
2290 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2291 dce_call->conn->auth_state.session_info, 0);
2292 if (sam_ctx == NULL) {
2293 return WERR_DS_UNAVAILABLE;
2296 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2297 if (tsocket_address_is_inet(local_address, "ip")) {
2298 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2299 W_ERROR_HAVE_NO_MEMORY(local_addr);
2302 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2303 if (tsocket_address_is_inet(remote_address, "ip")) {
2304 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2305 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2308 /* "server_unc" is ignored by w2k3 */
2310 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2311 return WERR_INVALID_FLAGS;
2314 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2315 r->in.flags & DS_PDC_REQUIRED &&
2316 r->in.flags & DS_KDC_REQUIRED) {
2317 return WERR_INVALID_FLAGS;
2319 if (r->in.flags & DS_IS_FLAT_NAME &&
2320 r->in.flags & DS_IS_DNS_NAME) {
2321 return WERR_INVALID_FLAGS;
2323 if (r->in.flags & DS_RETURN_DNS_NAME &&
2324 r->in.flags & DS_RETURN_FLAT_NAME) {
2325 return WERR_INVALID_FLAGS;
2327 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2328 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2329 return WERR_INVALID_FLAGS;
2332 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2334 (DS_DIRECTORY_SERVICE_REQUIRED |
2335 DS_DIRECTORY_SERVICE_PREFERRED |
2336 DS_GC_SERVER_REQUIRED |
2339 return WERR_INVALID_FLAGS;
2342 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2344 return WERR_INVALID_FLAGS;
2347 /* Proof server site parameter "site_name" if it was specified */
2348 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2349 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2350 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2351 server_site_name) != 0)) {
2352 return WERR_NO_SUCH_DOMAIN;
2355 guid_str = r->in.domain_guid != NULL ?
2356 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2358 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2362 r->in.client_account,
2363 r->in.mask, remote_addr,
2364 NETLOGON_NT_VERSION_5EX_WITH_IP,
2365 lp_ctx, &response, true);
2366 if (!NT_STATUS_IS_OK(status)) {
2367 return ntstatus_to_werror(status);
2371 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2372 * (O) flag when the returned forest name is in DNS format. This is here
2373 * always the case (see below).
2375 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2377 if (r->in.flags & DS_RETURN_DNS_NAME) {
2378 dc_name = response.data.nt5_ex.pdc_dns_name;
2379 domain_name = response.data.nt5_ex.dns_domain;
2381 * According to MS-NRPC 2.2.1.2.1 we should set the
2382 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2383 * the returned information is in DNS form.
2385 response.data.nt5_ex.server_type |=
2386 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2387 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2388 dc_name = response.data.nt5_ex.pdc_name;
2389 domain_name = response.data.nt5_ex.domain_name;
2393 * TODO: autodetect what we need to return
2394 * based on the given arguments
2396 dc_name = response.data.nt5_ex.pdc_name;
2397 domain_name = response.data.nt5_ex.domain_name;
2400 if (!dc_name || !dc_name[0]) {
2401 return WERR_NO_SUCH_DOMAIN;
2404 if (!domain_name || !domain_name[0]) {
2405 return WERR_NO_SUCH_DOMAIN;
2408 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2409 W_ERROR_HAVE_NO_MEMORY(info);
2410 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2411 dc_name[0] != '\\'? "\\\\":"",
2412 talloc_strdup(mem_ctx, dc_name));
2413 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2415 pdc_ip = local_addr;
2416 if (pdc_ip == NULL) {
2417 pdc_ip = "127.0.0.1";
2419 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2420 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2421 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2422 info->domain_guid = response.data.nt5_ex.domain_uuid;
2423 info->domain_name = domain_name;
2424 info->forest_name = response.data.nt5_ex.forest;
2425 info->dc_flags = response.data.nt5_ex.server_type;
2426 if (r->in.flags & DS_RETURN_DNS_NAME) {
2427 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2428 * returned if we are returning info->dc_unc containing a FQDN.
2429 * This attribute is called DomainControllerName in the specs,
2430 * it seems that we decide to return FQDN or netbios depending on
2431 * DS_RETURN_DNS_NAME.
2433 info->dc_flags |= DS_DNS_CONTROLLER;
2435 info->dc_site_name = response.data.nt5_ex.server_site;
2436 info->client_site_name = response.data.nt5_ex.client_site;
2438 *r->out.info = info;
2446 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2447 struct netr_DsRGetDCNameEx *r)
2449 struct netr_DsRGetDCNameEx2 r2;
2454 r2.in.server_unc = r->in.server_unc;
2455 r2.in.client_account = NULL;
2457 r2.in.domain_guid = r->in.domain_guid;
2458 r2.in.domain_name = r->in.domain_name;
2459 r2.in.site_name = r->in.site_name;
2460 r2.in.flags = r->in.flags;
2461 r2.out.info = r->out.info;
2463 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2471 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2472 struct netr_DsRGetDCName *r)
2474 struct netr_DsRGetDCNameEx2 r2;
2479 r2.in.server_unc = r->in.server_unc;
2480 r2.in.client_account = NULL;
2482 r2.in.domain_name = r->in.domain_name;
2483 r2.in.domain_guid = r->in.domain_guid;
2485 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2486 r2.in.flags = r->in.flags;
2487 r2.out.info = r->out.info;
2489 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2494 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2496 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2497 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2499 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2504 netr_NetrEnumerateTrustedDomainsEx
2506 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2507 struct netr_NetrEnumerateTrustedDomainsEx *r)
2509 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2514 netr_DsRAddressToSitenamesExW
2516 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2517 struct netr_DsRAddressToSitenamesExW *r)
2519 struct ldb_context *sam_ctx;
2520 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2521 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2522 sa_family_t sin_family;
2523 struct sockaddr_in *addr;
2525 struct sockaddr_in6 *addr6;
2526 char addr_str[INET6_ADDRSTRLEN];
2528 char addr_str[INET_ADDRSTRLEN];
2534 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2535 dce_call->conn->auth_state.session_info, 0);
2536 if (sam_ctx == NULL) {
2537 return WERR_DS_UNAVAILABLE;
2540 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2541 W_ERROR_HAVE_NO_MEMORY(ctr);
2545 ctr->count = r->in.count;
2546 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2547 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2548 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2549 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2551 for (i=0; i<ctr->count; i++) {
2552 ctr->sitename[i].string = NULL;
2553 ctr->subnetname[i].string = NULL;
2555 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2558 /* The first two byte of the buffer are reserved for the
2559 * "sin_family" but for now only the first one is used. */
2560 sin_family = r->in.addresses[i].buffer[0];
2562 switch (sin_family) {
2564 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2567 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2568 res = inet_ntop(AF_INET, &addr->sin_addr,
2569 addr_str, sizeof(addr_str));
2573 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2576 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2577 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2578 addr_str, sizeof(addr_str));
2589 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2593 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2594 ctr->subnetname[i].string = subnet_name;
2602 netr_DsRAddressToSitenamesW
2604 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2605 struct netr_DsRAddressToSitenamesW *r)
2607 struct netr_DsRAddressToSitenamesExW r2;
2608 struct netr_DsRAddressToSitenamesWCtr *ctr;
2614 r2.in.server_name = r->in.server_name;
2615 r2.in.count = r->in.count;
2616 r2.in.addresses = r->in.addresses;
2618 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2619 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2621 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2622 W_ERROR_HAVE_NO_MEMORY(ctr);
2626 ctr->count = r->in.count;
2627 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2628 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2630 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2632 for (i=0; i<ctr->count; i++) {
2633 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2641 netr_DsrGetDcSiteCoverageW
2643 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2644 struct netr_DsrGetDcSiteCoverageW *r)
2646 struct ldb_context *sam_ctx;
2647 struct DcSitesCtr *ctr;
2648 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2650 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2651 dce_call->conn->auth_state.session_info, 0);
2652 if (sam_ctx == NULL) {
2653 return WERR_DS_UNAVAILABLE;
2656 ctr = talloc(mem_ctx, struct DcSitesCtr);
2657 W_ERROR_HAVE_NO_MEMORY(ctr);
2661 /* For now only return our default site */
2663 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2664 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2665 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2666 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2672 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2673 struct ldb_context *sam_ctx,
2674 struct netr_DomainTrustList *trusts,
2675 uint32_t trust_flags)
2677 struct ldb_dn *system_dn;
2678 struct ldb_message **dom_res = NULL;
2679 const char *trust_attrs[] = { "flatname", "trustPartner",
2680 "securityIdentifier", "trustDirection",
2681 "trustType", "trustAttributes", NULL };
2686 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2687 NETR_TRUST_FLAG_OUTBOUND))) {
2688 return WERR_INVALID_FLAGS;
2691 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2692 ldb_get_default_basedn(sam_ctx),
2693 "(&(objectClass=container)(cn=System))");
2695 return WERR_GEN_FAILURE;
2698 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2699 &dom_res, trust_attrs,
2700 "(objectclass=trustedDomain)");
2702 for (i = 0; i < ret; i++) {
2703 unsigned int trust_dir;
2706 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2707 "trustDirection", 0);
2709 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2710 flags |= NETR_TRUST_FLAG_INBOUND;
2712 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2713 flags |= NETR_TRUST_FLAG_OUTBOUND;
2716 if (!(flags & trust_flags)) {
2717 /* this trust direction was not requested */
2722 trusts->array = talloc_realloc(trusts, trusts->array,
2723 struct netr_DomainTrust,
2725 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2727 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2728 if (!trusts->array[n].netbios_name) {
2729 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2730 "without flatname\n",
2731 ldb_dn_get_linearized(dom_res[i]->dn)));
2734 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2736 trusts->array[n].trust_flags = flags;
2737 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2738 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2739 /* TODO: find if we have parent in the list */
2740 trusts->array[n].parent_index = 0;
2743 trusts->array[n].trust_type =
2744 ldb_msg_find_attr_as_uint(dom_res[i],
2746 trusts->array[n].trust_attributes =
2747 ldb_msg_find_attr_as_uint(dom_res[i],
2748 "trustAttributes", 0);
2750 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2751 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2752 struct dom_sid zero_sid;
2753 ZERO_STRUCT(zero_sid);
2754 trusts->array[n].sid =
2755 dom_sid_dup(trusts, &zero_sid);
2757 trusts->array[n].sid =
2758 samdb_result_dom_sid(trusts, dom_res[i],
2759 "securityIdentifier");
2761 trusts->array[n].guid = GUID_zero();
2763 trusts->count = n + 1;
2766 talloc_free(dom_res);
2771 netr_DsrEnumerateDomainTrusts
2773 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2774 TALLOC_CTX *mem_ctx,
2775 struct netr_DsrEnumerateDomainTrusts *r)
2777 struct netr_DomainTrustList *trusts;
2778 struct ldb_context *sam_ctx;
2780 struct ldb_message **dom_res;
2781 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2782 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2783 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2787 if (r->in.trust_flags & 0xFFFFFE00) {
2788 return WERR_INVALID_FLAGS;
2791 /* TODO: turn to hard check once we are sure this is 100% correct */
2792 if (!r->in.server_name) {
2793 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2794 "But received NULL!\n", dnsdomain));
2796 p = strchr(r->in.server_name, '.');
2798 DEBUG(3, ("Invalid domain! Expected name in domain "
2799 "[%s]. But received [%s]!\n",
2800 dnsdomain, r->in.server_name));
2801 p = r->in.server_name;
2805 if (strcasecmp(p, dnsdomain)) {
2806 DEBUG(3, ("Invalid domain! Expected name in domain "
2807 "[%s]. But received [%s]!\n",
2808 dnsdomain, r->in.server_name));
2812 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2813 W_ERROR_HAVE_NO_MEMORY(trusts);
2816 r->out.trusts = trusts;
2818 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2819 dce_call->conn->auth_state.session_info, 0);
2820 if (sam_ctx == NULL) {
2821 return WERR_GEN_FAILURE;
2824 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2825 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2827 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2828 trusts, r->in.trust_flags);
2829 W_ERROR_NOT_OK_RETURN(werr);
2832 /* NOTE: we currently are always the root of the forest */
2833 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2834 uint32_t n = trusts->count;
2836 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2837 &dom_res, dom_attrs);
2839 return WERR_GEN_FAILURE;
2842 trusts->count = n + 1;
2843 trusts->array = talloc_realloc(trusts, trusts->array,
2844 struct netr_DomainTrust,
2846 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2848 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2849 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2850 trusts->array[n].trust_flags =
2851 NETR_TRUST_FLAG_NATIVE |
2852 NETR_TRUST_FLAG_TREEROOT |
2853 NETR_TRUST_FLAG_IN_FOREST |
2854 NETR_TRUST_FLAG_PRIMARY;
2855 /* we are always the root domain for now */
2856 trusts->array[n].parent_index = 0;
2857 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2858 trusts->array[n].trust_attributes = 0;
2859 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2862 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2864 talloc_free(dom_res);
2872 netr_DsrDeregisterDNSHostRecords
2874 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2875 struct netr_DsrDeregisterDNSHostRecords *r)
2877 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2881 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2882 struct netr_ServerGetTrustInfo *r);
2885 netr_ServerTrustPasswordsGet
2887 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2888 struct netr_ServerTrustPasswordsGet *r)
2890 struct netr_ServerGetTrustInfo r2 = {};
2891 struct netr_TrustInfo *_ti = NULL;
2894 r2.in.server_name = r->in.server_name;
2895 r2.in.account_name = r->in.account_name;
2896 r2.in.secure_channel_type = r->in.secure_channel_type;
2897 r2.in.computer_name = r->in.computer_name;
2898 r2.in.credential = r->in.credential;
2900 r2.out.return_authenticator = r->out.return_authenticator;
2901 r2.out.new_owf_password = r->out.new_owf_password;
2902 r2.out.old_owf_password = r->out.old_owf_password;
2903 r2.out.trust_info = &_ti;
2905 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
2907 r->out.return_authenticator = r2.out.return_authenticator;
2908 r->out.new_owf_password = r2.out.new_owf_password;
2909 r->out.old_owf_password = r2.out.old_owf_password;
2915 netr_DsRGetForestTrustInformation
2917 struct dcesrv_netr_DsRGetForestTrustInformation_state {
2918 struct dcesrv_call_state *dce_call;
2919 TALLOC_CTX *mem_ctx;
2920 struct netr_DsRGetForestTrustInformation *r;
2923 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
2925 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2926 TALLOC_CTX *mem_ctx,
2927 struct netr_DsRGetForestTrustInformation *r)
2929 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2930 struct dcesrv_connection *conn = dce_call->conn;
2931 struct auth_session_info *session_info = conn->auth_state.session_info;
2932 enum security_user_level security_level;
2933 struct ldb_context *sam_ctx = NULL;
2934 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
2935 struct dcerpc_binding_handle *irpc_handle = NULL;
2936 struct tevent_req *subreq = NULL;
2937 struct ldb_dn *domain_dn = NULL;
2938 struct ldb_dn *forest_dn = NULL;
2942 security_level = security_session_user_level(session_info, NULL);
2943 if (security_level < SECURITY_USER) {
2944 return WERR_ACCESS_DENIED;
2947 if (r->in.flags & 0xFFFFFFFE) {
2948 return WERR_INVALID_FLAGS;
2951 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2952 dce_call->conn->auth_state.session_info, 0);
2953 if (sam_ctx == NULL) {
2954 return WERR_GEN_FAILURE;
2957 domain_dn = ldb_get_default_basedn(sam_ctx);
2958 if (domain_dn == NULL) {
2959 return WERR_GEN_FAILURE;
2962 forest_dn = ldb_get_root_basedn(sam_ctx);
2963 if (forest_dn == NULL) {
2964 return WERR_GEN_FAILURE;
2967 cmp = ldb_dn_compare(domain_dn, forest_dn);
2969 return WERR_NERR_ACFNOTLOADED;
2972 forest_level = dsdb_forest_functional_level(sam_ctx);
2973 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
2974 return WERR_INVALID_FUNCTION;
2977 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2978 if (!samdb_is_pdc(sam_ctx)) {
2979 return WERR_NERR_NOTPRIMARY;
2982 if (r->in.trusted_domain_name == NULL) {
2983 return WERR_INVALID_FLAGS;
2987 if (r->in.trusted_domain_name == NULL) {
2991 * information about our own domain
2993 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
2994 r->out.forest_trust_info);
2995 if (!NT_STATUS_IS_OK(status)) {
2996 return ntstatus_to_werror(status);
3003 * Forward the request to winbindd
3006 state = talloc_zero(mem_ctx,
3007 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3008 if (state == NULL) {
3009 return WERR_NOT_ENOUGH_MEMORY;
3011 state->dce_call = dce_call;
3012 state->mem_ctx = mem_ctx;
3015 irpc_handle = irpc_binding_handle_by_name(state,
3016 state->dce_call->msg_ctx,
3018 &ndr_table_winbind);
3019 if (irpc_handle == NULL) {
3020 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3021 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3022 return WERR_SERVICE_NOT_FOUND;
3026 * 60 seconds timeout should be enough
3028 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3030 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3031 state->dce_call->event_ctx,
3033 r->in.trusted_domain_name,
3035 r->out.forest_trust_info);
3036 if (subreq == NULL) {
3037 return WERR_NOT_ENOUGH_MEMORY;
3039 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3040 tevent_req_set_callback(subreq,
3041 dcesrv_netr_DsRGetForestTrustInformation_done,
3047 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3049 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3050 tevent_req_callback_data(subreq,
3051 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3054 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3056 &state->r->out.result);
3057 TALLOC_FREE(subreq);
3058 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3059 state->r->out.result = WERR_TIMEOUT;
3060 } else if (!NT_STATUS_IS_OK(status)) {
3061 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3062 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3063 nt_errstr(status)));
3066 status = dcesrv_reply(state->dce_call);
3067 if (!NT_STATUS_IS_OK(status)) {
3068 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3073 netr_GetForestTrustInformation
3075 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3076 TALLOC_CTX *mem_ctx,
3077 struct netr_GetForestTrustInformation *r)
3079 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3080 struct netlogon_creds_CredentialState *creds = NULL;
3081 struct ldb_context *sam_ctx = NULL;
3082 struct ldb_dn *domain_dn = NULL;
3083 struct ldb_dn *forest_dn = NULL;
3088 status = dcesrv_netr_creds_server_step_check(dce_call,
3090 r->in.computer_name,
3092 r->out.return_authenticator,
3094 if (!NT_STATUS_IS_OK(status)) {
3098 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3099 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3100 return NT_STATUS_NOT_IMPLEMENTED;
3103 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3104 dce_call->conn->auth_state.session_info, 0);
3105 if (sam_ctx == NULL) {
3106 return NT_STATUS_INTERNAL_ERROR;
3109 /* TODO: check r->in.server_name is our name */
3111 domain_dn = ldb_get_default_basedn(sam_ctx);
3112 if (domain_dn == NULL) {
3113 return NT_STATUS_INTERNAL_ERROR;
3116 forest_dn = ldb_get_root_basedn(sam_ctx);
3117 if (forest_dn == NULL) {
3118 return NT_STATUS_INTERNAL_ERROR;
3121 cmp = ldb_dn_compare(domain_dn, forest_dn);
3123 return NT_STATUS_INVALID_DOMAIN_STATE;
3126 forest_level = dsdb_forest_functional_level(sam_ctx);
3127 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3128 return NT_STATUS_INVALID_DOMAIN_STATE;
3131 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3132 r->out.forest_trust_info);
3133 if (!NT_STATUS_IS_OK(status)) {
3137 return NT_STATUS_OK;
3142 netr_ServerGetTrustInfo
3144 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3145 struct netr_ServerGetTrustInfo *r)
3147 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3148 struct netlogon_creds_CredentialState *creds = NULL;
3149 struct ldb_context *sam_ctx = NULL;
3150 const char * const attrs[] = {
3153 "userAccountControl",
3156 struct ldb_message **res = NULL;
3157 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3160 const char *asid = NULL;
3162 const char *aname = NULL;
3163 struct ldb_message *tdo_msg = NULL;
3164 const char * const tdo_attrs[] = {
3165 "trustAuthIncoming",
3169 struct netr_TrustInfo *trust_info = NULL;
3171 ZERO_STRUCTP(r->out.new_owf_password);
3172 ZERO_STRUCTP(r->out.old_owf_password);
3174 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3176 r->in.computer_name,
3178 r->out.return_authenticator,
3180 if (!NT_STATUS_IS_OK(nt_status)) {
3184 /* TODO: check r->in.server_name is our name */
3186 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3187 return NT_STATUS_INVALID_PARAMETER;
3190 if (r->in.secure_channel_type != creds->secure_channel_type) {
3191 return NT_STATUS_INVALID_PARAMETER;
3194 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3195 return NT_STATUS_INVALID_PARAMETER;
3198 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3199 lp_ctx, system_session(lp_ctx), 0);
3200 if (sam_ctx == NULL) {
3201 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3204 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3206 return NT_STATUS_NO_MEMORY;
3209 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3210 "(&(objectClass=user)(objectSid=%s))",
3213 return NT_STATUS_ACCOUNT_DISABLED;
3216 switch (creds->secure_channel_type) {
3217 case SEC_CHAN_DNS_DOMAIN:
3218 case SEC_CHAN_DOMAIN:
3219 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3221 if (uac & UF_ACCOUNTDISABLE) {
3222 return NT_STATUS_ACCOUNT_DISABLED;
3225 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3226 return NT_STATUS_ACCOUNT_DISABLED;
3229 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3230 if (aname == NULL) {
3231 return NT_STATUS_ACCOUNT_DISABLED;
3234 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3235 SEC_CHAN_DOMAIN, aname,
3236 tdo_attrs, mem_ctx, &tdo_msg);
3237 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3238 return NT_STATUS_ACCOUNT_DISABLED;
3240 if (!NT_STATUS_IS_OK(nt_status)) {
3244 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3247 if (!NT_STATUS_IS_OK(nt_status)) {
3251 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3252 if (trust_info == NULL) {
3253 return NT_STATUS_NO_MEMORY;
3256 trust_info->count = 1;
3257 trust_info->data = talloc_array(trust_info, uint32_t,
3259 if (trust_info->data == NULL) {
3260 return NT_STATUS_NO_MEMORY;
3263 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3269 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3272 if (!NT_STATUS_IS_OK(nt_status)) {
3276 prevNtHash = talloc(mem_ctx, struct samr_Password);
3277 if (prevNtHash == NULL) {
3278 return NT_STATUS_NO_MEMORY;
3281 E_md4hash("", prevNtHash->hash);
3285 if (curNtHash != NULL) {
3286 *r->out.new_owf_password = *curNtHash;
3287 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3289 if (prevNtHash != NULL) {
3290 *r->out.old_owf_password = *prevNtHash;
3291 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3294 if (trust_info != NULL) {
3295 *r->out.trust_info = trust_info;
3298 return NT_STATUS_OK;
3304 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3305 struct netr_Unused47 *r)
3307 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3311 struct netr_dnsupdate_RODC_state {
3312 struct dcesrv_call_state *dce_call;
3313 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3314 struct dnsupdate_RODC *r2;
3318 called when the forwarded RODC dns update request is finished
3320 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3322 struct netr_dnsupdate_RODC_state *st =
3323 tevent_req_callback_data(subreq,
3324 struct netr_dnsupdate_RODC_state);
3327 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3328 TALLOC_FREE(subreq);
3329 if (!NT_STATUS_IS_OK(status)) {
3330 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3331 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3334 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3336 status = dcesrv_reply(st->dce_call);
3337 if (!NT_STATUS_IS_OK(status)) {
3338 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3343 netr_DsrUpdateReadOnlyServerDnsRecords
3345 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3346 TALLOC_CTX *mem_ctx,
3347 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3349 struct netlogon_creds_CredentialState *creds;
3351 struct dcerpc_binding_handle *binding_handle;
3352 struct netr_dnsupdate_RODC_state *st;
3353 struct tevent_req *subreq;
3355 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3357 r->in.computer_name,
3359 r->out.return_authenticator,
3361 NT_STATUS_NOT_OK_RETURN(nt_status);
3363 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3364 return NT_STATUS_ACCESS_DENIED;
3367 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3368 NT_STATUS_HAVE_NO_MEMORY(st);
3370 st->dce_call = dce_call;
3372 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3373 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3375 st->r2->in.dom_sid = creds->sid;
3376 st->r2->in.site_name = r->in.site_name;
3377 st->r2->in.dns_ttl = r->in.dns_ttl;
3378 st->r2->in.dns_names = r->in.dns_names;
3379 st->r2->out.dns_names = r->out.dns_names;
3381 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3382 "dnsupdate", &ndr_table_irpc);
3383 if (binding_handle == NULL) {
3384 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3385 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3386 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3389 /* forward the call */
3390 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3391 binding_handle, st->r2);
3392 NT_STATUS_HAVE_NO_MEMORY(subreq);
3394 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3396 /* setup the callback */
3397 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3399 return NT_STATUS_OK;
3403 /* include the generated boilerplate */
3404 #include "librpc/gen_ndr/ndr_netlogon_s.c"