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 netlogon_creds_decrypt_samlogon_logon(creds,
865 switch (r->in.logon_level) {
866 case NetlogonInteractiveInformation:
867 case NetlogonServiceInformation:
868 case NetlogonInteractiveTransitiveInformation:
869 case NetlogonServiceTransitiveInformation:
871 /* TODO: we need to deny anonymous access here */
872 nt_status = auth_context_create(mem_ctx,
873 dce_call->event_ctx, dce_call->msg_ctx,
874 dce_call->conn->dce_ctx->lp_ctx,
876 NT_STATUS_NOT_OK_RETURN(nt_status);
878 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
879 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
880 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
881 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
883 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
884 user_info->password_state = AUTH_PASSWORD_HASH;
886 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
887 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
888 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
890 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
891 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
892 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
895 case NetlogonNetworkInformation:
896 case NetlogonNetworkTransitiveInformation:
898 /* TODO: we need to deny anonymous access here */
899 nt_status = auth_context_create(mem_ctx,
900 dce_call->event_ctx, dce_call->msg_ctx,
901 dce_call->conn->dce_ctx->lp_ctx,
903 NT_STATUS_NOT_OK_RETURN(nt_status);
905 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
906 NT_STATUS_NOT_OK_RETURN(nt_status);
908 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
909 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
910 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
911 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
913 user_info->password_state = AUTH_PASSWORD_RESPONSE;
914 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
915 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
917 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
918 user_info->client.account_name,
919 user_info->client.domain_name,
920 user_info->password.response.nt,
922 NT_STATUS_NOT_OK_RETURN(nt_status);
927 case NetlogonGenericInformation:
929 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
931 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
934 /* Using DES to verify kerberos tickets makes no sense */
935 return NT_STATUS_INVALID_PARAMETER;
938 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
940 struct dcerpc_binding_handle *irpc_handle;
941 struct kdc_check_generic_kerberos check;
942 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
943 NT_STATUS_HAVE_NO_MEMORY(generic);
944 *r->out.authoritative = 1;
946 /* TODO: Describe and deal with these flags */
949 r->out.validation->generic = generic;
951 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
955 if (irpc_handle == NULL) {
956 return NT_STATUS_NO_LOGON_SERVERS;
959 check.in.generic_request =
960 data_blob_const(r->in.logon->generic->data,
961 r->in.logon->generic->length);
964 * TODO: make this async and avoid
965 * dcerpc_binding_handle_set_sync_ev()
967 dcerpc_binding_handle_set_sync_ev(irpc_handle,
968 dce_call->event_ctx);
969 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
972 if (!NT_STATUS_IS_OK(status)) {
975 generic->length = check.out.generic_reply.length;
976 generic->data = check.out.generic_reply.data;
980 /* Until we get an implemetnation of these other packages */
981 return NT_STATUS_INVALID_PARAMETER;
984 return NT_STATUS_INVALID_PARAMETER;
987 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
988 /* TODO: set *r->out.authoritative = 0 on specific errors */
989 NT_STATUS_NOT_OK_RETURN(nt_status);
991 switch (r->in.validation_level) {
993 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
996 NT_STATUS_NOT_OK_RETURN(nt_status);
998 r->out.validation->sam2 = sam2;
1002 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1005 NT_STATUS_NOT_OK_RETURN(nt_status);
1007 r->out.validation->sam3 = sam3;
1011 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1012 return NT_STATUS_INVALID_PARAMETER;
1015 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1018 NT_STATUS_NOT_OK_RETURN(nt_status);
1020 r->out.validation->sam6 = sam6;
1024 return NT_STATUS_INVALID_INFO_CLASS;
1027 netlogon_creds_encrypt_samlogon_validation(creds,
1028 r->in.validation_level,
1031 /* TODO: Describe and deal with these flags */
1034 return NT_STATUS_OK;
1037 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1038 struct netr_LogonSamLogonEx *r)
1041 struct netlogon_creds_CredentialState *creds;
1043 *r->out.authoritative = 1;
1045 nt_status = dcesrv_netr_LogonSamLogon_check(r);
1046 if (!NT_STATUS_IS_OK(nt_status)) {
1050 nt_status = schannel_get_creds_state(mem_ctx,
1051 dce_call->conn->dce_ctx->lp_ctx,
1052 r->in.computer_name, &creds);
1053 if (!NT_STATUS_IS_OK(nt_status)) {
1057 if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1058 return NT_STATUS_ACCESS_DENIED;
1060 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1064 netr_LogonSamLogonWithFlags
1067 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1068 struct netr_LogonSamLogonWithFlags *r)
1071 struct netlogon_creds_CredentialState *creds;
1072 struct netr_LogonSamLogonEx r2;
1074 struct netr_Authenticator *return_authenticator;
1078 r2.in.server_name = r->in.server_name;
1079 r2.in.computer_name = r->in.computer_name;
1080 r2.in.logon_level = r->in.logon_level;
1081 r2.in.logon = r->in.logon;
1082 r2.in.validation_level = r->in.validation_level;
1083 r2.in.flags = r->in.flags;
1084 r2.out.validation = r->out.validation;
1085 r2.out.authoritative = r->out.authoritative;
1086 r2.out.flags = r->out.flags;
1088 *r->out.authoritative = 1;
1090 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1091 if (!NT_STATUS_IS_OK(nt_status)) {
1095 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1096 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1098 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1100 r->in.computer_name,
1101 r->in.credential, return_authenticator,
1103 NT_STATUS_NOT_OK_RETURN(nt_status);
1105 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1107 r->out.return_authenticator = return_authenticator;
1115 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1116 struct netr_LogonSamLogon *r)
1118 struct netr_LogonSamLogonWithFlags r2;
1124 r2.in.server_name = r->in.server_name;
1125 r2.in.computer_name = r->in.computer_name;
1126 r2.in.credential = r->in.credential;
1127 r2.in.return_authenticator = r->in.return_authenticator;
1128 r2.in.logon_level = r->in.logon_level;
1129 r2.in.logon = r->in.logon;
1130 r2.in.validation_level = r->in.validation_level;
1131 r2.in.flags = &flags;
1132 r2.out.validation = r->out.validation;
1133 r2.out.authoritative = r->out.authoritative;
1134 r2.out.flags = &flags;
1136 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1138 r->out.return_authenticator = r2.out.return_authenticator;
1147 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1148 struct netr_LogonSamLogoff *r)
1150 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1158 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1159 struct netr_DatabaseDeltas *r)
1161 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1168 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1169 struct netr_DatabaseSync2 *r)
1171 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1172 return NT_STATUS_NOT_IMPLEMENTED;
1179 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1180 struct netr_DatabaseSync *r)
1182 struct netr_DatabaseSync2 r2;
1187 r2.in.logon_server = r->in.logon_server;
1188 r2.in.computername = r->in.computername;
1189 r2.in.credential = r->in.credential;
1190 r2.in.database_id = r->in.database_id;
1191 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1192 r2.in.sync_context = r->in.sync_context;
1193 r2.out.sync_context = r->out.sync_context;
1194 r2.out.delta_enum_array = r->out.delta_enum_array;
1195 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1197 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1206 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1207 struct netr_AccountDeltas *r)
1209 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1210 return NT_STATUS_NOT_IMPLEMENTED;
1217 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1218 struct netr_AccountSync *r)
1220 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1221 return NT_STATUS_NOT_IMPLEMENTED;
1228 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1229 struct netr_GetDcName *r)
1231 const char * const attrs[] = { NULL };
1232 struct ldb_context *sam_ctx;
1233 struct ldb_message **res;
1234 struct ldb_dn *domain_dn;
1239 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1240 * that the domainname needs to be a valid netbios domain
1241 * name, if it is not NULL.
1243 if (r->in.domainname) {
1244 const char *dot = strchr(r->in.domainname, '.');
1245 size_t len = strlen(r->in.domainname);
1247 if (dot || len > 15) {
1248 return WERR_NERR_DCNOTFOUND;
1252 * TODO: Should we also varify that only valid
1253 * netbios name characters are used?
1257 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1258 dce_call->conn->dce_ctx->lp_ctx,
1259 dce_call->conn->auth_state.session_info, 0);
1260 if (sam_ctx == NULL) {
1261 return WERR_DS_UNAVAILABLE;
1264 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1266 if (domain_dn == NULL) {
1267 return WERR_NO_SUCH_DOMAIN;
1270 ret = gendb_search_dn(sam_ctx, mem_ctx,
1271 domain_dn, &res, attrs);
1273 return WERR_NO_SUCH_DOMAIN;
1276 /* TODO: - return real IP address
1277 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1279 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1280 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1281 W_ERROR_HAVE_NO_MEMORY(dcname);
1283 *r->out.dcname = dcname;
1287 struct dcesrv_netr_LogonControl_base_state {
1288 struct dcesrv_call_state *dce_call;
1290 TALLOC_CTX *mem_ctx;
1292 struct netr_LogonControl2Ex r;
1295 struct netr_LogonControl *l;
1296 struct netr_LogonControl2 *l2;
1297 struct netr_LogonControl2Ex *l2ex;
1301 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1303 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1305 struct dcesrv_connection *conn = state->dce_call->conn;
1306 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1307 struct auth_session_info *session_info = conn->auth_state.session_info;
1308 enum security_user_level security_level;
1309 struct dcerpc_binding_handle *irpc_handle;
1310 struct tevent_req *subreq;
1313 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1315 if (state->_r.l != NULL) {
1319 if (state->r.in.level == 0x00000002) {
1320 return WERR_NOT_SUPPORTED;
1321 } else if (state->r.in.level != 0x00000001) {
1322 return WERR_INVALID_LEVEL;
1325 switch (state->r.in.function_code) {
1326 case NETLOGON_CONTROL_QUERY:
1327 case NETLOGON_CONTROL_REPLICATE:
1328 case NETLOGON_CONTROL_SYNCHRONIZE:
1329 case NETLOGON_CONTROL_PDC_REPLICATE:
1330 case NETLOGON_CONTROL_BREAKPOINT:
1331 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1332 case NETLOGON_CONTROL_TRUNCATE_LOG:
1335 return WERR_NOT_SUPPORTED;
1339 if (state->r.in.level < 0x00000001) {
1340 return WERR_INVALID_LEVEL;
1343 if (state->r.in.level > 0x00000004) {
1344 return WERR_INVALID_LEVEL;
1347 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1348 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1349 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1351 switch (state->r.in.level) {
1353 info1 = talloc_zero(state->mem_ctx,
1354 struct netr_NETLOGON_INFO_1);
1355 if (info1 == NULL) {
1356 return WERR_NOT_ENOUGH_MEMORY;
1358 state->r.out.query->info1 = info1;
1362 info3 = talloc_zero(state->mem_ctx,
1363 struct netr_NETLOGON_INFO_3);
1364 if (info3 == NULL) {
1365 return WERR_NOT_ENOUGH_MEMORY;
1367 state->r.out.query->info3 = info3;
1371 return WERR_INVALID_PARAMETER;
1376 * Some validations are done before the access check
1377 * and some after the access check
1379 security_level = security_session_user_level(session_info, NULL);
1380 if (security_level < SECURITY_ADMINISTRATOR) {
1381 return WERR_ACCESS_DENIED;
1384 if (state->_r.l2 != NULL) {
1386 * netr_LogonControl2
1388 if (state->r.in.level == 0x00000004) {
1389 return WERR_INVALID_LEVEL;
1393 switch (state->r.in.level) {
1398 switch (state->r.in.function_code) {
1399 case NETLOGON_CONTROL_REDISCOVER:
1400 case NETLOGON_CONTROL_TC_QUERY:
1401 case NETLOGON_CONTROL_TC_VERIFY:
1404 return WERR_INVALID_PARAMETER;
1413 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1414 return WERR_INVALID_PARAMETER;
1420 return WERR_INVALID_LEVEL;
1423 switch (state->r.in.function_code) {
1424 case NETLOGON_CONTROL_REDISCOVER:
1425 case NETLOGON_CONTROL_TC_QUERY:
1426 case NETLOGON_CONTROL_TC_VERIFY:
1427 if (state->r.in.level != 2) {
1428 return WERR_INVALID_PARAMETER;
1431 if (state->r.in.data == NULL) {
1432 return WERR_INVALID_PARAMETER;
1435 if (state->r.in.data->domain == NULL) {
1436 return WERR_INVALID_PARAMETER;
1441 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1442 if (state->r.in.level != 1) {
1443 return WERR_INVALID_PARAMETER;
1446 if (state->r.in.data == NULL) {
1447 return WERR_INVALID_PARAMETER;
1450 if (state->r.in.data->domain == NULL) {
1451 return WERR_INVALID_PARAMETER;
1454 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1455 state->r.in.data->domain);
1457 struct ldb_context *sam_ctx;
1459 sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1460 lp_ctx, system_session(lp_ctx), 0);
1461 if (sam_ctx == NULL) {
1462 return WERR_DS_UNAVAILABLE;
1466 * Secrets for trusted domains can only be triggered on
1469 ok = samdb_is_pdc(sam_ctx);
1470 TALLOC_FREE(sam_ctx);
1472 return WERR_INVALID_DOMAIN_ROLE;
1478 return WERR_NOT_SUPPORTED;
1481 irpc_handle = irpc_binding_handle_by_name(state,
1482 state->dce_call->msg_ctx,
1484 &ndr_table_winbind);
1485 if (irpc_handle == NULL) {
1486 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1487 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1488 return WERR_SERVICE_NOT_FOUND;
1492 * 60 seconds timeout should be enough
1494 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1496 subreq = dcerpc_winbind_LogonControl_send(state,
1497 state->dce_call->event_ctx,
1499 state->r.in.function_code,
1502 state->r.out.query);
1503 if (subreq == NULL) {
1504 return WERR_NOT_ENOUGH_MEMORY;
1506 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1507 tevent_req_set_callback(subreq,
1508 dcesrv_netr_LogonControl_base_done,
1514 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1516 struct dcesrv_netr_LogonControl_base_state *state =
1517 tevent_req_callback_data(subreq,
1518 struct dcesrv_netr_LogonControl_base_state);
1521 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1522 &state->r.out.result);
1523 TALLOC_FREE(subreq);
1524 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1525 state->r.out.result = WERR_TIMEOUT;
1526 } else if (!NT_STATUS_IS_OK(status)) {
1527 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1528 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1529 nt_errstr(status)));
1532 if (state->_r.l2ex != NULL) {
1533 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1534 r->out.result = state->r.out.result;
1535 } else if (state->_r.l2 != NULL) {
1536 struct netr_LogonControl2 *r = state->_r.l2;
1537 r->out.result = state->r.out.result;
1538 } else if (state->_r.l != NULL) {
1539 struct netr_LogonControl *r = state->_r.l;
1540 r->out.result = state->r.out.result;
1543 status = dcesrv_reply(state->dce_call);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1552 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1553 struct netr_LogonControl *r)
1555 struct dcesrv_netr_LogonControl_base_state *state;
1558 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1559 if (state == NULL) {
1560 return WERR_NOT_ENOUGH_MEMORY;
1563 state->dce_call = dce_call;
1564 state->mem_ctx = mem_ctx;
1566 state->r.in.logon_server = r->in.logon_server;
1567 state->r.in.function_code = r->in.function_code;
1568 state->r.in.level = r->in.level;
1569 state->r.in.data = NULL;
1570 state->r.out.query = r->out.query;
1574 werr = dcesrv_netr_LogonControl_base_call(state);
1576 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1586 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1587 struct netr_LogonControl2 *r)
1589 struct dcesrv_netr_LogonControl_base_state *state;
1592 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1593 if (state == NULL) {
1594 return WERR_NOT_ENOUGH_MEMORY;
1597 state->dce_call = dce_call;
1598 state->mem_ctx = mem_ctx;
1600 state->r.in.logon_server = r->in.logon_server;
1601 state->r.in.function_code = r->in.function_code;
1602 state->r.in.level = r->in.level;
1603 state->r.in.data = r->in.data;
1604 state->r.out.query = r->out.query;
1608 werr = dcesrv_netr_LogonControl_base_call(state);
1610 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1618 netr_LogonControl2Ex
1620 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1621 struct netr_LogonControl2Ex *r)
1623 struct dcesrv_netr_LogonControl_base_state *state;
1626 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1627 if (state == NULL) {
1628 return WERR_NOT_ENOUGH_MEMORY;
1631 state->dce_call = dce_call;
1632 state->mem_ctx = mem_ctx;
1637 werr = dcesrv_netr_LogonControl_base_call(state);
1639 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1646 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1647 struct ldb_context *sam_ctx,
1648 struct netr_DomainTrustList *trusts,
1649 uint32_t trust_flags);
1654 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1655 struct netr_GetAnyDCName *r)
1657 struct netr_DomainTrustList *trusts;
1658 struct ldb_context *sam_ctx;
1659 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1663 *r->out.dcname = NULL;
1665 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1666 /* if the domainname parameter wasn't set assume our domain */
1667 r->in.domainname = lpcfg_workgroup(lp_ctx);
1670 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1671 dce_call->conn->auth_state.session_info, 0);
1672 if (sam_ctx == NULL) {
1673 return WERR_DS_UNAVAILABLE;
1676 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1677 /* well we asked for a DC of our own domain */
1678 if (samdb_is_pdc(sam_ctx)) {
1679 /* we are the PDC of the specified domain */
1680 return WERR_NO_SUCH_DOMAIN;
1683 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1684 lpcfg_netbios_name(lp_ctx));
1685 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1690 /* Okay, now we have to consider the trusted domains */
1692 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1693 W_ERROR_HAVE_NO_MEMORY(trusts);
1697 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1698 NETR_TRUST_FLAG_INBOUND
1699 | NETR_TRUST_FLAG_OUTBOUND);
1700 W_ERROR_NOT_OK_RETURN(werr);
1702 for (i = 0; i < trusts->count; i++) {
1703 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1704 /* FIXME: Here we need to find a DC for the specified
1705 * trusted domain. */
1707 /* return WERR_OK; */
1708 return WERR_NO_SUCH_DOMAIN;
1712 return WERR_NO_SUCH_DOMAIN;
1719 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1720 struct netr_DatabaseRedo *r)
1722 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1727 netr_NetrEnumerateTrustedDomains
1729 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1730 struct netr_NetrEnumerateTrustedDomains *r)
1732 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1737 netr_LogonGetCapabilities
1739 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1740 struct netr_LogonGetCapabilities *r)
1742 struct netlogon_creds_CredentialState *creds;
1745 status = dcesrv_netr_creds_server_step_check(dce_call,
1747 r->in.computer_name,
1749 r->out.return_authenticator,
1751 if (!NT_STATUS_IS_OK(status)) {
1752 DEBUG(0,(__location__ " Bad credentials - error\n"));
1754 NT_STATUS_NOT_OK_RETURN(status);
1756 if (r->in.query_level != 1) {
1757 return NT_STATUS_NOT_SUPPORTED;
1760 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1762 return NT_STATUS_OK;
1767 netr_NETRLOGONSETSERVICEBITS
1769 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1770 struct netr_NETRLOGONSETSERVICEBITS *r)
1772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1777 netr_LogonGetTrustRid
1779 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1780 struct netr_LogonGetTrustRid *r)
1782 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1787 netr_NETRLOGONCOMPUTESERVERDIGEST
1789 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1790 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1792 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1797 netr_NETRLOGONCOMPUTECLIENTDIGEST
1799 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1800 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1810 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1811 struct netr_DsRGetSiteName *r)
1813 struct ldb_context *sam_ctx;
1814 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1816 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1817 dce_call->conn->auth_state.session_info, 0);
1818 if (sam_ctx == NULL) {
1819 return WERR_DS_UNAVAILABLE;
1823 * We assume to be a DC when we get called over NETLOGON. Hence we
1824 * get our site name always by using "samdb_server_site_name()"
1825 * and not "samdb_client_site_name()".
1827 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1828 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1835 fill in a netr_OneDomainInfo from a ldb search result
1837 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1838 struct loadparm_context *lp_ctx,
1839 struct ldb_context *sam_ctx,
1840 struct ldb_message *res,
1841 struct netr_OneDomainInfo *info,
1842 bool is_local, bool is_trust_list)
1846 if (is_trust_list) {
1847 /* w2k8 only fills this on trusted domains */
1848 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1849 info->trust_extension.length = 16;
1850 info->trust_extension.info->flags =
1851 NETR_TRUST_FLAG_TREEROOT |
1852 NETR_TRUST_FLAG_IN_FOREST |
1853 NETR_TRUST_FLAG_PRIMARY |
1854 NETR_TRUST_FLAG_NATIVE;
1856 info->trust_extension.info->parent_index = 0; /* should be index into array
1858 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1859 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1862 if (is_trust_list) {
1863 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1864 info->dns_forestname.string = NULL;
1866 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1867 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1868 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1869 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1873 info->domainname.string = lpcfg_workgroup(lp_ctx);
1874 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1875 info->domain_guid = samdb_result_guid(res, "objectGUID");
1876 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1878 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1879 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1880 info->domain_guid = samdb_result_guid(res, "objectGUID");
1881 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1883 if (!is_trust_list) {
1884 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1887 return NT_STATUS_OK;
1891 netr_LogonGetDomainInfo
1892 this is called as part of the ADS domain logon procedure.
1894 It has an important role in convaying details about the client, such
1895 as Operating System, Version, Service Pack etc.
1897 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1898 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1900 struct netlogon_creds_CredentialState *creds;
1901 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1902 "securityIdentifier", "trustPartner", NULL };
1903 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1904 "msDS-SupportedEncryptionTypes", NULL };
1905 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1906 struct ldb_context *sam_ctx;
1907 struct ldb_message **res1, **res2, **res3, *new_msg;
1908 struct ldb_dn *workstation_dn;
1909 struct netr_DomainInformation *domain_info;
1910 struct netr_LsaPolicyInformation *lsa_policy_info;
1911 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1912 bool update_dns_hostname = true;
1916 status = dcesrv_netr_creds_server_step_check(dce_call,
1918 r->in.computer_name,
1920 r->out.return_authenticator,
1922 if (!NT_STATUS_IS_OK(status)) {
1923 DEBUG(0,(__location__ " Bad credentials - error\n"));
1925 NT_STATUS_NOT_OK_RETURN(status);
1927 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1928 dce_call->conn->dce_ctx->lp_ctx,
1929 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1930 if (sam_ctx == NULL) {
1931 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1934 switch (r->in.level) {
1935 case 1: /* Domain information */
1937 if (r->in.query->workstation_info == NULL) {
1938 return NT_STATUS_INVALID_PARAMETER;
1941 /* Prepares the workstation DN */
1942 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1943 dom_sid_string(mem_ctx, creds->sid));
1944 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1946 /* Lookup for attributes in workstation object */
1947 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1950 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1953 /* Gets the sam account name which is checked against the DNS
1954 * hostname parameter. */
1955 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1958 if (sam_account_name == NULL) {
1959 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1963 * Checks that the sam account name without a possible "$"
1964 * matches as prefix with the DNS hostname in the workstation
1967 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1968 strcspn(sam_account_name, "$"));
1969 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1970 if (r->in.query->workstation_info->dns_hostname != NULL) {
1971 prefix2 = talloc_strndup(mem_ctx,
1972 r->in.query->workstation_info->dns_hostname,
1973 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1974 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1976 if (strcasecmp(prefix1, prefix2) != 0) {
1977 update_dns_hostname = false;
1980 update_dns_hostname = false;
1983 /* Gets the old DNS hostname */
1984 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1989 * Updates the DNS hostname when the client wishes that the
1990 * server should handle this for him
1991 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1992 * obviously only checked when we do already have a
1994 * See MS-NRPC section 3.5.4.3.9
1996 if ((old_dns_hostname != NULL) &&
1997 (r->in.query->workstation_info->workstation_flags
1998 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1999 update_dns_hostname = false;
2002 /* Gets host information and put them into our directory */
2004 new_msg = ldb_msg_new(mem_ctx);
2005 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2007 new_msg->dn = workstation_dn;
2009 /* Sets the OS name */
2011 if (r->in.query->workstation_info->os_name.string == NULL) {
2012 return NT_STATUS_INVALID_PARAMETER;
2015 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2016 r->in.query->workstation_info->os_name.string);
2017 if (ret != LDB_SUCCESS) {
2018 return NT_STATUS_NO_MEMORY;
2022 * Sets information from "os_version". On an empty structure
2023 * the values are cleared.
2025 if (r->in.query->workstation_info->os_version.os != NULL) {
2026 struct netr_OsVersionInfoEx *os_version;
2027 const char *os_version_str;
2029 os_version = &r->in.query->workstation_info->os_version.os->os;
2031 if (os_version->CSDVersion == NULL) {
2032 return NT_STATUS_INVALID_PARAMETER;
2035 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2036 os_version->MajorVersion,
2037 os_version->MinorVersion,
2038 os_version->BuildNumber);
2039 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2041 ret = ldb_msg_add_string(new_msg,
2042 "operatingSystemServicePack",
2043 os_version->CSDVersion);
2044 if (ret != LDB_SUCCESS) {
2045 return NT_STATUS_NO_MEMORY;
2048 ret = ldb_msg_add_string(new_msg,
2049 "operatingSystemVersion",
2051 if (ret != LDB_SUCCESS) {
2052 return NT_STATUS_NO_MEMORY;
2055 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2056 "operatingSystemServicePack");
2057 if (ret != LDB_SUCCESS) {
2058 return NT_STATUS_NO_MEMORY;
2061 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2062 "operatingSystemVersion");
2063 if (ret != LDB_SUCCESS) {
2064 return NT_STATUS_NO_MEMORY;
2069 * If the boolean "update_dns_hostname" remained true, then we
2070 * are fine to start the update.
2072 if (update_dns_hostname) {
2073 ret = ldb_msg_add_string(new_msg,
2075 r->in.query->workstation_info->dns_hostname);
2076 if (ret != LDB_SUCCESS) {
2077 return NT_STATUS_NO_MEMORY;
2080 /* This manual "servicePrincipalName" generation is
2081 * still needed! Since the update in the samldb LDB
2082 * module does only work if the entries already exist
2083 * which isn't always the case. */
2084 ret = ldb_msg_add_string(new_msg,
2085 "servicePrincipalName",
2086 talloc_asprintf(new_msg, "HOST/%s",
2087 r->in.computer_name));
2088 if (ret != LDB_SUCCESS) {
2089 return NT_STATUS_NO_MEMORY;
2092 ret = ldb_msg_add_string(new_msg,
2093 "servicePrincipalName",
2094 talloc_asprintf(new_msg, "HOST/%s",
2095 r->in.query->workstation_info->dns_hostname));
2096 if (ret != LDB_SUCCESS) {
2097 return NT_STATUS_NO_MEMORY;
2101 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2102 DEBUG(3,("Impossible to update samdb: %s\n",
2103 ldb_errstring(sam_ctx)));
2106 talloc_free(new_msg);
2108 /* Writes back the domain information */
2110 /* We need to do two searches. The first will pull our primary
2111 domain and the second will pull any trusted domains. Our
2112 primary domain is also a "trusted" domain, so we need to
2113 put the primary domain into the lists of returned trusts as
2115 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2118 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2121 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2122 "(objectClass=trustedDomain)");
2124 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2127 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2128 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2130 ZERO_STRUCTP(domain_info);
2132 /* Informations about the local and trusted domains */
2134 status = fill_one_domain_info(mem_ctx,
2135 dce_call->conn->dce_ctx->lp_ctx,
2136 sam_ctx, res2[0], &domain_info->primary_domain,
2138 NT_STATUS_NOT_OK_RETURN(status);
2140 domain_info->trusted_domain_count = ret3 + 1;
2141 domain_info->trusted_domains = talloc_array(mem_ctx,
2142 struct netr_OneDomainInfo,
2143 domain_info->trusted_domain_count);
2144 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2146 for (i=0;i<ret3;i++) {
2147 status = fill_one_domain_info(mem_ctx,
2148 dce_call->conn->dce_ctx->lp_ctx,
2150 &domain_info->trusted_domains[i],
2152 NT_STATUS_NOT_OK_RETURN(status);
2155 status = fill_one_domain_info(mem_ctx,
2156 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2157 &domain_info->trusted_domains[i], true, true);
2158 NT_STATUS_NOT_OK_RETURN(status);
2160 /* Sets the supported encryption types */
2161 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2162 "msDS-SupportedEncryptionTypes",
2163 default_supported_enc_types);
2165 /* Other host domain information */
2167 lsa_policy_info = talloc(mem_ctx,
2168 struct netr_LsaPolicyInformation);
2169 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2170 ZERO_STRUCTP(lsa_policy_info);
2172 domain_info->lsa_policy = *lsa_policy_info;
2174 /* The DNS hostname is only returned back when there is a chance
2176 if ((r->in.query->workstation_info->workstation_flags
2177 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2178 domain_info->dns_hostname.string = old_dns_hostname;
2180 domain_info->dns_hostname.string = NULL;
2183 domain_info->workstation_flags =
2184 r->in.query->workstation_info->workstation_flags & (
2185 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2187 r->out.info->domain_info = domain_info;
2189 case 2: /* LSA policy information - not used at the moment */
2190 lsa_policy_info = talloc(mem_ctx,
2191 struct netr_LsaPolicyInformation);
2192 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2193 ZERO_STRUCTP(lsa_policy_info);
2195 r->out.info->lsa_policy_info = lsa_policy_info;
2198 return NT_STATUS_INVALID_LEVEL;
2202 return NT_STATUS_OK;
2207 netr_ServerPasswordGet
2209 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2210 struct netr_ServerPasswordGet *r)
2212 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2217 netr_NETRLOGONSENDTOSAM
2219 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2220 struct netr_NETRLOGONSENDTOSAM *r)
2222 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2227 netr_DsRGetDCNameEx2
2229 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2230 TALLOC_CTX *mem_ctx,
2231 struct netr_DsRGetDCNameEx2 *r)
2233 struct ldb_context *sam_ctx;
2234 struct netr_DsRGetDCNameInfo *info;
2235 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2236 const struct tsocket_address *local_address;
2237 char *local_addr = NULL;
2238 const struct tsocket_address *remote_address;
2239 char *remote_addr = NULL;
2240 const char *server_site_name;
2242 struct netlogon_samlogon_response response;
2244 const char *dc_name = NULL;
2245 const char *domain_name = NULL;
2248 ZERO_STRUCTP(r->out.info);
2250 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2251 dce_call->conn->auth_state.session_info, 0);
2252 if (sam_ctx == NULL) {
2253 return WERR_DS_UNAVAILABLE;
2256 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2257 if (tsocket_address_is_inet(local_address, "ip")) {
2258 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2259 W_ERROR_HAVE_NO_MEMORY(local_addr);
2262 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2263 if (tsocket_address_is_inet(remote_address, "ip")) {
2264 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2265 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2268 /* "server_unc" is ignored by w2k3 */
2270 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2271 return WERR_INVALID_FLAGS;
2274 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2275 r->in.flags & DS_PDC_REQUIRED &&
2276 r->in.flags & DS_KDC_REQUIRED) {
2277 return WERR_INVALID_FLAGS;
2279 if (r->in.flags & DS_IS_FLAT_NAME &&
2280 r->in.flags & DS_IS_DNS_NAME) {
2281 return WERR_INVALID_FLAGS;
2283 if (r->in.flags & DS_RETURN_DNS_NAME &&
2284 r->in.flags & DS_RETURN_FLAT_NAME) {
2285 return WERR_INVALID_FLAGS;
2287 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2288 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2289 return WERR_INVALID_FLAGS;
2292 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2294 (DS_DIRECTORY_SERVICE_REQUIRED |
2295 DS_DIRECTORY_SERVICE_PREFERRED |
2296 DS_GC_SERVER_REQUIRED |
2299 return WERR_INVALID_FLAGS;
2302 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2304 return WERR_INVALID_FLAGS;
2307 /* Proof server site parameter "site_name" if it was specified */
2308 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2309 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2310 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2311 server_site_name) != 0)) {
2312 return WERR_NO_SUCH_DOMAIN;
2315 guid_str = r->in.domain_guid != NULL ?
2316 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2318 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2322 r->in.client_account,
2323 r->in.mask, remote_addr,
2324 NETLOGON_NT_VERSION_5EX_WITH_IP,
2325 lp_ctx, &response, true);
2326 if (!NT_STATUS_IS_OK(status)) {
2327 return ntstatus_to_werror(status);
2331 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2332 * (O) flag when the returned forest name is in DNS format. This is here
2333 * always the case (see below).
2335 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2337 if (r->in.flags & DS_RETURN_DNS_NAME) {
2338 dc_name = response.data.nt5_ex.pdc_dns_name;
2339 domain_name = response.data.nt5_ex.dns_domain;
2341 * According to MS-NRPC 2.2.1.2.1 we should set the
2342 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2343 * the returned information is in DNS form.
2345 response.data.nt5_ex.server_type |=
2346 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2347 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2348 dc_name = response.data.nt5_ex.pdc_name;
2349 domain_name = response.data.nt5_ex.domain_name;
2353 * TODO: autodetect what we need to return
2354 * based on the given arguments
2356 dc_name = response.data.nt5_ex.pdc_name;
2357 domain_name = response.data.nt5_ex.domain_name;
2360 if (!dc_name || !dc_name[0]) {
2361 return WERR_NO_SUCH_DOMAIN;
2364 if (!domain_name || !domain_name[0]) {
2365 return WERR_NO_SUCH_DOMAIN;
2368 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2369 W_ERROR_HAVE_NO_MEMORY(info);
2370 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2371 dc_name[0] != '\\'? "\\\\":"",
2372 talloc_strdup(mem_ctx, dc_name));
2373 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2375 pdc_ip = local_addr;
2376 if (pdc_ip == NULL) {
2377 pdc_ip = "127.0.0.1";
2379 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2380 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2381 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2382 info->domain_guid = response.data.nt5_ex.domain_uuid;
2383 info->domain_name = domain_name;
2384 info->forest_name = response.data.nt5_ex.forest;
2385 info->dc_flags = response.data.nt5_ex.server_type;
2386 if (r->in.flags & DS_RETURN_DNS_NAME) {
2387 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2388 * returned if we are returning info->dc_unc containing a FQDN.
2389 * This attribute is called DomainControllerName in the specs,
2390 * it seems that we decide to return FQDN or netbios depending on
2391 * DS_RETURN_DNS_NAME.
2393 info->dc_flags |= DS_DNS_CONTROLLER;
2395 info->dc_site_name = response.data.nt5_ex.server_site;
2396 info->client_site_name = response.data.nt5_ex.client_site;
2398 *r->out.info = info;
2406 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2407 struct netr_DsRGetDCNameEx *r)
2409 struct netr_DsRGetDCNameEx2 r2;
2414 r2.in.server_unc = r->in.server_unc;
2415 r2.in.client_account = NULL;
2417 r2.in.domain_guid = r->in.domain_guid;
2418 r2.in.domain_name = r->in.domain_name;
2419 r2.in.site_name = r->in.site_name;
2420 r2.in.flags = r->in.flags;
2421 r2.out.info = r->out.info;
2423 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2431 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2432 struct netr_DsRGetDCName *r)
2434 struct netr_DsRGetDCNameEx2 r2;
2439 r2.in.server_unc = r->in.server_unc;
2440 r2.in.client_account = NULL;
2442 r2.in.domain_name = r->in.domain_name;
2443 r2.in.domain_guid = r->in.domain_guid;
2445 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2446 r2.in.flags = r->in.flags;
2447 r2.out.info = r->out.info;
2449 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2454 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2456 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2457 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2459 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2464 netr_NetrEnumerateTrustedDomainsEx
2466 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2467 struct netr_NetrEnumerateTrustedDomainsEx *r)
2469 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2474 netr_DsRAddressToSitenamesExW
2476 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2477 struct netr_DsRAddressToSitenamesExW *r)
2479 struct ldb_context *sam_ctx;
2480 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2481 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2482 sa_family_t sin_family;
2483 struct sockaddr_in *addr;
2485 struct sockaddr_in6 *addr6;
2486 char addr_str[INET6_ADDRSTRLEN];
2488 char addr_str[INET_ADDRSTRLEN];
2494 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2495 dce_call->conn->auth_state.session_info, 0);
2496 if (sam_ctx == NULL) {
2497 return WERR_DS_UNAVAILABLE;
2500 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2501 W_ERROR_HAVE_NO_MEMORY(ctr);
2505 ctr->count = r->in.count;
2506 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2507 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2508 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2509 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2511 for (i=0; i<ctr->count; i++) {
2512 ctr->sitename[i].string = NULL;
2513 ctr->subnetname[i].string = NULL;
2515 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2518 /* The first two byte of the buffer are reserved for the
2519 * "sin_family" but for now only the first one is used. */
2520 sin_family = r->in.addresses[i].buffer[0];
2522 switch (sin_family) {
2524 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2527 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2528 res = inet_ntop(AF_INET, &addr->sin_addr,
2529 addr_str, sizeof(addr_str));
2533 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2536 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2537 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2538 addr_str, sizeof(addr_str));
2549 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2553 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2554 ctr->subnetname[i].string = subnet_name;
2562 netr_DsRAddressToSitenamesW
2564 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2565 struct netr_DsRAddressToSitenamesW *r)
2567 struct netr_DsRAddressToSitenamesExW r2;
2568 struct netr_DsRAddressToSitenamesWCtr *ctr;
2574 r2.in.server_name = r->in.server_name;
2575 r2.in.count = r->in.count;
2576 r2.in.addresses = r->in.addresses;
2578 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2579 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2581 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2582 W_ERROR_HAVE_NO_MEMORY(ctr);
2586 ctr->count = r->in.count;
2587 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2588 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2590 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2592 for (i=0; i<ctr->count; i++) {
2593 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2601 netr_DsrGetDcSiteCoverageW
2603 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2604 struct netr_DsrGetDcSiteCoverageW *r)
2606 struct ldb_context *sam_ctx;
2607 struct DcSitesCtr *ctr;
2608 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2610 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2611 dce_call->conn->auth_state.session_info, 0);
2612 if (sam_ctx == NULL) {
2613 return WERR_DS_UNAVAILABLE;
2616 ctr = talloc(mem_ctx, struct DcSitesCtr);
2617 W_ERROR_HAVE_NO_MEMORY(ctr);
2621 /* For now only return our default site */
2623 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2624 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2625 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2626 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2632 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2633 struct ldb_context *sam_ctx,
2634 struct netr_DomainTrustList *trusts,
2635 uint32_t trust_flags)
2637 struct ldb_dn *system_dn;
2638 struct ldb_message **dom_res = NULL;
2639 const char *trust_attrs[] = { "flatname", "trustPartner",
2640 "securityIdentifier", "trustDirection",
2641 "trustType", "trustAttributes", NULL };
2646 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2647 NETR_TRUST_FLAG_OUTBOUND))) {
2648 return WERR_INVALID_FLAGS;
2651 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2652 ldb_get_default_basedn(sam_ctx),
2653 "(&(objectClass=container)(cn=System))");
2655 return WERR_GEN_FAILURE;
2658 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2659 &dom_res, trust_attrs,
2660 "(objectclass=trustedDomain)");
2662 for (i = 0; i < ret; i++) {
2663 unsigned int trust_dir;
2666 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2667 "trustDirection", 0);
2669 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2670 flags |= NETR_TRUST_FLAG_INBOUND;
2672 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2673 flags |= NETR_TRUST_FLAG_OUTBOUND;
2676 if (!(flags & trust_flags)) {
2677 /* this trust direction was not requested */
2682 trusts->array = talloc_realloc(trusts, trusts->array,
2683 struct netr_DomainTrust,
2685 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2687 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2688 if (!trusts->array[n].netbios_name) {
2689 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2690 "without flatname\n",
2691 ldb_dn_get_linearized(dom_res[i]->dn)));
2694 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2696 trusts->array[n].trust_flags = flags;
2697 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2698 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2699 /* TODO: find if we have parent in the list */
2700 trusts->array[n].parent_index = 0;
2703 trusts->array[n].trust_type =
2704 ldb_msg_find_attr_as_uint(dom_res[i],
2706 trusts->array[n].trust_attributes =
2707 ldb_msg_find_attr_as_uint(dom_res[i],
2708 "trustAttributes", 0);
2710 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2711 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2712 struct dom_sid zero_sid;
2713 ZERO_STRUCT(zero_sid);
2714 trusts->array[n].sid =
2715 dom_sid_dup(trusts, &zero_sid);
2717 trusts->array[n].sid =
2718 samdb_result_dom_sid(trusts, dom_res[i],
2719 "securityIdentifier");
2721 trusts->array[n].guid = GUID_zero();
2723 trusts->count = n + 1;
2726 talloc_free(dom_res);
2731 netr_DsrEnumerateDomainTrusts
2733 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2734 TALLOC_CTX *mem_ctx,
2735 struct netr_DsrEnumerateDomainTrusts *r)
2737 struct netr_DomainTrustList *trusts;
2738 struct ldb_context *sam_ctx;
2740 struct ldb_message **dom_res;
2741 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2742 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2743 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2747 if (r->in.trust_flags & 0xFFFFFE00) {
2748 return WERR_INVALID_FLAGS;
2751 /* TODO: turn to hard check once we are sure this is 100% correct */
2752 if (!r->in.server_name) {
2753 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2754 "But received NULL!\n", dnsdomain));
2756 p = strchr(r->in.server_name, '.');
2758 DEBUG(3, ("Invalid domain! Expected name in domain "
2759 "[%s]. But received [%s]!\n",
2760 dnsdomain, r->in.server_name));
2761 p = r->in.server_name;
2765 if (strcasecmp(p, dnsdomain)) {
2766 DEBUG(3, ("Invalid domain! Expected name in domain "
2767 "[%s]. But received [%s]!\n",
2768 dnsdomain, r->in.server_name));
2772 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2773 W_ERROR_HAVE_NO_MEMORY(trusts);
2776 r->out.trusts = trusts;
2778 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2779 dce_call->conn->auth_state.session_info, 0);
2780 if (sam_ctx == NULL) {
2781 return WERR_GEN_FAILURE;
2784 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2785 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2787 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2788 trusts, r->in.trust_flags);
2789 W_ERROR_NOT_OK_RETURN(werr);
2792 /* NOTE: we currently are always the root of the forest */
2793 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2794 uint32_t n = trusts->count;
2796 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2797 &dom_res, dom_attrs);
2799 return WERR_GEN_FAILURE;
2802 trusts->count = n + 1;
2803 trusts->array = talloc_realloc(trusts, trusts->array,
2804 struct netr_DomainTrust,
2806 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2808 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2809 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2810 trusts->array[n].trust_flags =
2811 NETR_TRUST_FLAG_NATIVE |
2812 NETR_TRUST_FLAG_TREEROOT |
2813 NETR_TRUST_FLAG_IN_FOREST |
2814 NETR_TRUST_FLAG_PRIMARY;
2815 /* we are always the root domain for now */
2816 trusts->array[n].parent_index = 0;
2817 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2818 trusts->array[n].trust_attributes = 0;
2819 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2822 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2824 talloc_free(dom_res);
2832 netr_DsrDeregisterDNSHostRecords
2834 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2835 struct netr_DsrDeregisterDNSHostRecords *r)
2837 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2841 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2842 struct netr_ServerGetTrustInfo *r);
2845 netr_ServerTrustPasswordsGet
2847 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2848 struct netr_ServerTrustPasswordsGet *r)
2850 struct netr_ServerGetTrustInfo r2 = {};
2851 struct netr_TrustInfo *_ti = NULL;
2854 r2.in.server_name = r->in.server_name;
2855 r2.in.account_name = r->in.account_name;
2856 r2.in.secure_channel_type = r->in.secure_channel_type;
2857 r2.in.computer_name = r->in.computer_name;
2858 r2.in.credential = r->in.credential;
2860 r2.out.return_authenticator = r->out.return_authenticator;
2861 r2.out.new_owf_password = r->out.new_owf_password;
2862 r2.out.old_owf_password = r->out.old_owf_password;
2863 r2.out.trust_info = &_ti;
2865 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
2867 r->out.return_authenticator = r2.out.return_authenticator;
2868 r->out.new_owf_password = r2.out.new_owf_password;
2869 r->out.old_owf_password = r2.out.old_owf_password;
2875 netr_DsRGetForestTrustInformation
2877 struct dcesrv_netr_DsRGetForestTrustInformation_state {
2878 struct dcesrv_call_state *dce_call;
2879 TALLOC_CTX *mem_ctx;
2880 struct netr_DsRGetForestTrustInformation *r;
2883 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
2885 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2886 TALLOC_CTX *mem_ctx,
2887 struct netr_DsRGetForestTrustInformation *r)
2889 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2890 struct dcesrv_connection *conn = dce_call->conn;
2891 struct auth_session_info *session_info = conn->auth_state.session_info;
2892 enum security_user_level security_level;
2893 struct ldb_context *sam_ctx = NULL;
2894 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
2895 struct dcerpc_binding_handle *irpc_handle = NULL;
2896 struct tevent_req *subreq = NULL;
2897 struct ldb_dn *domain_dn = NULL;
2898 struct ldb_dn *forest_dn = NULL;
2902 security_level = security_session_user_level(session_info, NULL);
2903 if (security_level < SECURITY_USER) {
2904 return WERR_ACCESS_DENIED;
2907 if (r->in.flags & 0xFFFFFFFE) {
2908 return WERR_INVALID_FLAGS;
2911 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2912 dce_call->conn->auth_state.session_info, 0);
2913 if (sam_ctx == NULL) {
2914 return WERR_GEN_FAILURE;
2917 domain_dn = ldb_get_default_basedn(sam_ctx);
2918 if (domain_dn == NULL) {
2919 return WERR_GEN_FAILURE;
2922 forest_dn = ldb_get_root_basedn(sam_ctx);
2923 if (forest_dn == NULL) {
2924 return WERR_GEN_FAILURE;
2927 cmp = ldb_dn_compare(domain_dn, forest_dn);
2929 return WERR_NERR_ACFNOTLOADED;
2932 forest_level = dsdb_forest_functional_level(sam_ctx);
2933 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
2934 return WERR_INVALID_FUNCTION;
2937 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2938 if (!samdb_is_pdc(sam_ctx)) {
2939 return WERR_NERR_NOTPRIMARY;
2942 if (r->in.trusted_domain_name == NULL) {
2943 return WERR_INVALID_FLAGS;
2947 if (r->in.trusted_domain_name == NULL) {
2951 * information about our own domain
2953 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
2954 r->out.forest_trust_info);
2955 if (!NT_STATUS_IS_OK(status)) {
2956 return ntstatus_to_werror(status);
2963 * Forward the request to winbindd
2966 state = talloc_zero(mem_ctx,
2967 struct dcesrv_netr_DsRGetForestTrustInformation_state);
2968 if (state == NULL) {
2969 return WERR_NOT_ENOUGH_MEMORY;
2971 state->dce_call = dce_call;
2972 state->mem_ctx = mem_ctx;
2975 irpc_handle = irpc_binding_handle_by_name(state,
2976 state->dce_call->msg_ctx,
2978 &ndr_table_winbind);
2979 if (irpc_handle == NULL) {
2980 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2981 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2982 return WERR_SERVICE_NOT_FOUND;
2986 * 60 seconds timeout should be enough
2988 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2990 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
2991 state->dce_call->event_ctx,
2993 r->in.trusted_domain_name,
2995 r->out.forest_trust_info);
2996 if (subreq == NULL) {
2997 return WERR_NOT_ENOUGH_MEMORY;
2999 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3000 tevent_req_set_callback(subreq,
3001 dcesrv_netr_DsRGetForestTrustInformation_done,
3007 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3009 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3010 tevent_req_callback_data(subreq,
3011 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3014 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3016 &state->r->out.result);
3017 TALLOC_FREE(subreq);
3018 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3019 state->r->out.result = WERR_TIMEOUT;
3020 } else if (!NT_STATUS_IS_OK(status)) {
3021 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3022 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3023 nt_errstr(status)));
3026 status = dcesrv_reply(state->dce_call);
3027 if (!NT_STATUS_IS_OK(status)) {
3028 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3033 netr_GetForestTrustInformation
3035 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3036 TALLOC_CTX *mem_ctx,
3037 struct netr_GetForestTrustInformation *r)
3039 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3040 struct netlogon_creds_CredentialState *creds = NULL;
3041 struct ldb_context *sam_ctx = NULL;
3042 struct ldb_dn *domain_dn = NULL;
3043 struct ldb_dn *forest_dn = NULL;
3048 status = dcesrv_netr_creds_server_step_check(dce_call,
3050 r->in.computer_name,
3052 r->out.return_authenticator,
3054 if (!NT_STATUS_IS_OK(status)) {
3058 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3059 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3060 return NT_STATUS_NOT_IMPLEMENTED;
3063 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3064 dce_call->conn->auth_state.session_info, 0);
3065 if (sam_ctx == NULL) {
3066 return NT_STATUS_INTERNAL_ERROR;
3069 /* TODO: check r->in.server_name is our name */
3071 domain_dn = ldb_get_default_basedn(sam_ctx);
3072 if (domain_dn == NULL) {
3073 return NT_STATUS_INTERNAL_ERROR;
3076 forest_dn = ldb_get_root_basedn(sam_ctx);
3077 if (forest_dn == NULL) {
3078 return NT_STATUS_INTERNAL_ERROR;
3081 cmp = ldb_dn_compare(domain_dn, forest_dn);
3083 return NT_STATUS_INVALID_DOMAIN_STATE;
3086 forest_level = dsdb_forest_functional_level(sam_ctx);
3087 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3088 return NT_STATUS_INVALID_DOMAIN_STATE;
3091 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3092 r->out.forest_trust_info);
3093 if (!NT_STATUS_IS_OK(status)) {
3097 return NT_STATUS_OK;
3102 netr_ServerGetTrustInfo
3104 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3105 struct netr_ServerGetTrustInfo *r)
3107 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3108 struct netlogon_creds_CredentialState *creds = NULL;
3109 struct ldb_context *sam_ctx = NULL;
3110 const char * const attrs[] = {
3113 "userAccountControl",
3116 struct ldb_message **res = NULL;
3117 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3120 const char *asid = NULL;
3122 const char *aname = NULL;
3123 struct ldb_message *tdo_msg = NULL;
3124 const char * const tdo_attrs[] = {
3125 "trustAuthIncoming",
3129 struct netr_TrustInfo *trust_info = NULL;
3131 ZERO_STRUCTP(r->out.new_owf_password);
3132 ZERO_STRUCTP(r->out.old_owf_password);
3134 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3136 r->in.computer_name,
3138 r->out.return_authenticator,
3140 if (!NT_STATUS_IS_OK(nt_status)) {
3144 /* TODO: check r->in.server_name is our name */
3146 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3147 return NT_STATUS_INVALID_PARAMETER;
3150 if (r->in.secure_channel_type != creds->secure_channel_type) {
3151 return NT_STATUS_INVALID_PARAMETER;
3154 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3155 return NT_STATUS_INVALID_PARAMETER;
3158 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3159 lp_ctx, system_session(lp_ctx), 0);
3160 if (sam_ctx == NULL) {
3161 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3164 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3166 return NT_STATUS_NO_MEMORY;
3169 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3170 "(&(objectClass=user)(objectSid=%s))",
3173 return NT_STATUS_ACCOUNT_DISABLED;
3176 switch (creds->secure_channel_type) {
3177 case SEC_CHAN_DNS_DOMAIN:
3178 case SEC_CHAN_DOMAIN:
3179 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3181 if (uac & UF_ACCOUNTDISABLE) {
3182 return NT_STATUS_ACCOUNT_DISABLED;
3185 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3186 return NT_STATUS_ACCOUNT_DISABLED;
3189 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3190 if (aname == NULL) {
3191 return NT_STATUS_ACCOUNT_DISABLED;
3194 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3195 SEC_CHAN_DOMAIN, aname,
3196 tdo_attrs, mem_ctx, &tdo_msg);
3197 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3198 return NT_STATUS_ACCOUNT_DISABLED;
3200 if (!NT_STATUS_IS_OK(nt_status)) {
3204 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3207 if (!NT_STATUS_IS_OK(nt_status)) {
3211 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3212 if (trust_info == NULL) {
3213 return NT_STATUS_NO_MEMORY;
3216 trust_info->count = 1;
3217 trust_info->data = talloc_array(trust_info, uint32_t,
3219 if (trust_info->data == NULL) {
3220 return NT_STATUS_NO_MEMORY;
3223 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3229 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3232 if (!NT_STATUS_IS_OK(nt_status)) {
3236 prevNtHash = talloc(mem_ctx, struct samr_Password);
3237 if (prevNtHash == NULL) {
3238 return NT_STATUS_NO_MEMORY;
3241 E_md4hash("", prevNtHash->hash);
3245 if (curNtHash != NULL) {
3246 *r->out.new_owf_password = *curNtHash;
3247 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3249 if (prevNtHash != NULL) {
3250 *r->out.old_owf_password = *prevNtHash;
3251 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3254 if (trust_info != NULL) {
3255 *r->out.trust_info = trust_info;
3258 return NT_STATUS_OK;
3264 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3265 struct netr_Unused47 *r)
3267 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3271 struct netr_dnsupdate_RODC_state {
3272 struct dcesrv_call_state *dce_call;
3273 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3274 struct dnsupdate_RODC *r2;
3278 called when the forwarded RODC dns update request is finished
3280 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3282 struct netr_dnsupdate_RODC_state *st =
3283 tevent_req_callback_data(subreq,
3284 struct netr_dnsupdate_RODC_state);
3287 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3288 TALLOC_FREE(subreq);
3289 if (!NT_STATUS_IS_OK(status)) {
3290 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3291 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3294 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3296 status = dcesrv_reply(st->dce_call);
3297 if (!NT_STATUS_IS_OK(status)) {
3298 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3303 netr_DsrUpdateReadOnlyServerDnsRecords
3305 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3306 TALLOC_CTX *mem_ctx,
3307 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3309 struct netlogon_creds_CredentialState *creds;
3311 struct dcerpc_binding_handle *binding_handle;
3312 struct netr_dnsupdate_RODC_state *st;
3313 struct tevent_req *subreq;
3315 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3317 r->in.computer_name,
3319 r->out.return_authenticator,
3321 NT_STATUS_NOT_OK_RETURN(nt_status);
3323 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3324 return NT_STATUS_ACCESS_DENIED;
3327 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3328 NT_STATUS_HAVE_NO_MEMORY(st);
3330 st->dce_call = dce_call;
3332 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3333 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3335 st->r2->in.dom_sid = creds->sid;
3336 st->r2->in.site_name = r->in.site_name;
3337 st->r2->in.dns_ttl = r->in.dns_ttl;
3338 st->r2->in.dns_names = r->in.dns_names;
3339 st->r2->out.dns_names = r->out.dns_names;
3341 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3342 "dnsupdate", &ndr_table_irpc);
3343 if (binding_handle == NULL) {
3344 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3345 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3346 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3349 /* forward the call */
3350 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3351 binding_handle, st->r2);
3352 NT_STATUS_HAVE_NO_MEMORY(subreq);
3354 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3356 /* setup the callback */
3357 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3359 return NT_STATUS_OK;
3363 /* include the generated boilerplate */
3364 #include "librpc/gen_ndr/ndr_netlogon_s.c"