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 completly, as this function must only run under schannel
842 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
843 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
845 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
846 const char *workgroup = lpcfg_workgroup(lp_ctx);
847 struct auth4_context *auth_context = NULL;
848 struct auth_usersupplied_info *user_info = NULL;
849 struct auth_user_info_dc *user_info_dc = NULL;
851 struct netr_SamInfo2 *sam2 = NULL;
852 struct netr_SamInfo3 *sam3 = NULL;
853 struct netr_SamInfo6 *sam6 = NULL;
855 *r->out.authoritative = 1;
857 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
858 NT_STATUS_HAVE_NO_MEMORY(user_info);
860 netlogon_creds_decrypt_samlogon_logon(creds,
864 switch (r->in.logon_level) {
865 case NetlogonInteractiveInformation:
866 case NetlogonServiceInformation:
867 case NetlogonInteractiveTransitiveInformation:
868 case NetlogonServiceTransitiveInformation:
870 /* TODO: we need to deny anonymous access here */
871 nt_status = auth_context_create(mem_ctx,
872 dce_call->event_ctx, dce_call->msg_ctx,
873 dce_call->conn->dce_ctx->lp_ctx,
875 NT_STATUS_NOT_OK_RETURN(nt_status);
877 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
878 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
879 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
880 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
882 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
883 user_info->password_state = AUTH_PASSWORD_HASH;
885 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
886 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
887 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
889 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
890 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
891 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
894 case NetlogonNetworkInformation:
895 case NetlogonNetworkTransitiveInformation:
897 /* TODO: we need to deny anonymous access here */
898 nt_status = auth_context_create(mem_ctx,
899 dce_call->event_ctx, dce_call->msg_ctx,
900 dce_call->conn->dce_ctx->lp_ctx,
902 NT_STATUS_NOT_OK_RETURN(nt_status);
904 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
905 NT_STATUS_NOT_OK_RETURN(nt_status);
907 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
908 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
909 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
910 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
912 user_info->password_state = AUTH_PASSWORD_RESPONSE;
913 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
914 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
916 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
917 user_info->client.account_name,
918 user_info->client.domain_name,
919 user_info->password.response.nt,
921 NT_STATUS_NOT_OK_RETURN(nt_status);
926 case NetlogonGenericInformation:
928 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
930 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
933 /* Using DES to verify kerberos tickets makes no sense */
934 return NT_STATUS_INVALID_PARAMETER;
937 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
939 struct dcerpc_binding_handle *irpc_handle;
940 struct kdc_check_generic_kerberos check;
941 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
942 NT_STATUS_HAVE_NO_MEMORY(generic);
943 *r->out.authoritative = 1;
945 /* TODO: Describe and deal with these flags */
948 r->out.validation->generic = generic;
950 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
954 if (irpc_handle == NULL) {
955 return NT_STATUS_NO_LOGON_SERVERS;
958 check.in.generic_request =
959 data_blob_const(r->in.logon->generic->data,
960 r->in.logon->generic->length);
963 * TODO: make this async and avoid
964 * dcerpc_binding_handle_set_sync_ev()
966 dcerpc_binding_handle_set_sync_ev(irpc_handle,
967 dce_call->event_ctx);
968 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
971 if (!NT_STATUS_IS_OK(status)) {
974 generic->length = check.out.generic_reply.length;
975 generic->data = check.out.generic_reply.data;
979 /* Until we get an implemetnation of these other packages */
980 return NT_STATUS_INVALID_PARAMETER;
983 return NT_STATUS_INVALID_PARAMETER;
986 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
987 /* TODO: set *r->out.authoritative = 0 on specific errors */
988 NT_STATUS_NOT_OK_RETURN(nt_status);
990 switch (r->in.validation_level) {
992 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
995 NT_STATUS_NOT_OK_RETURN(nt_status);
997 r->out.validation->sam2 = sam2;
1001 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1004 NT_STATUS_NOT_OK_RETURN(nt_status);
1006 r->out.validation->sam3 = sam3;
1010 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1011 return NT_STATUS_INVALID_PARAMETER;
1014 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1017 NT_STATUS_NOT_OK_RETURN(nt_status);
1019 r->out.validation->sam6 = sam6;
1023 return NT_STATUS_INVALID_INFO_CLASS;
1026 netlogon_creds_encrypt_samlogon_validation(creds,
1027 r->in.validation_level,
1030 /* TODO: Describe and deal with these flags */
1033 return NT_STATUS_OK;
1036 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1037 struct netr_LogonSamLogonEx *r)
1040 struct netlogon_creds_CredentialState *creds;
1042 *r->out.authoritative = 1;
1044 nt_status = dcesrv_netr_LogonSamLogon_check(r);
1045 if (!NT_STATUS_IS_OK(nt_status)) {
1049 nt_status = schannel_get_creds_state(mem_ctx,
1050 dce_call->conn->dce_ctx->lp_ctx,
1051 r->in.computer_name, &creds);
1052 if (!NT_STATUS_IS_OK(nt_status)) {
1056 if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1057 return NT_STATUS_ACCESS_DENIED;
1059 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1063 netr_LogonSamLogonWithFlags
1066 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1067 struct netr_LogonSamLogonWithFlags *r)
1070 struct netlogon_creds_CredentialState *creds;
1071 struct netr_LogonSamLogonEx r2;
1073 struct netr_Authenticator *return_authenticator;
1077 r2.in.server_name = r->in.server_name;
1078 r2.in.computer_name = r->in.computer_name;
1079 r2.in.logon_level = r->in.logon_level;
1080 r2.in.logon = r->in.logon;
1081 r2.in.validation_level = r->in.validation_level;
1082 r2.in.flags = r->in.flags;
1083 r2.out.validation = r->out.validation;
1084 r2.out.authoritative = r->out.authoritative;
1085 r2.out.flags = r->out.flags;
1087 *r->out.authoritative = 1;
1089 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1090 if (!NT_STATUS_IS_OK(nt_status)) {
1094 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1095 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1097 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1099 r->in.computer_name,
1100 r->in.credential, return_authenticator,
1102 NT_STATUS_NOT_OK_RETURN(nt_status);
1104 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1106 r->out.return_authenticator = return_authenticator;
1114 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1115 struct netr_LogonSamLogon *r)
1117 struct netr_LogonSamLogonWithFlags r2;
1123 r2.in.server_name = r->in.server_name;
1124 r2.in.computer_name = r->in.computer_name;
1125 r2.in.credential = r->in.credential;
1126 r2.in.return_authenticator = r->in.return_authenticator;
1127 r2.in.logon_level = r->in.logon_level;
1128 r2.in.logon = r->in.logon;
1129 r2.in.validation_level = r->in.validation_level;
1130 r2.in.flags = &flags;
1131 r2.out.validation = r->out.validation;
1132 r2.out.authoritative = r->out.authoritative;
1133 r2.out.flags = &flags;
1135 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1137 r->out.return_authenticator = r2.out.return_authenticator;
1146 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1147 struct netr_LogonSamLogoff *r)
1149 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1157 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1158 struct netr_DatabaseDeltas *r)
1160 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1167 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1168 struct netr_DatabaseSync2 *r)
1170 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1171 return NT_STATUS_NOT_IMPLEMENTED;
1178 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1179 struct netr_DatabaseSync *r)
1181 struct netr_DatabaseSync2 r2;
1186 r2.in.logon_server = r->in.logon_server;
1187 r2.in.computername = r->in.computername;
1188 r2.in.credential = r->in.credential;
1189 r2.in.database_id = r->in.database_id;
1190 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1191 r2.in.sync_context = r->in.sync_context;
1192 r2.out.sync_context = r->out.sync_context;
1193 r2.out.delta_enum_array = r->out.delta_enum_array;
1194 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1196 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1205 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1206 struct netr_AccountDeltas *r)
1208 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1209 return NT_STATUS_NOT_IMPLEMENTED;
1216 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1217 struct netr_AccountSync *r)
1219 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1220 return NT_STATUS_NOT_IMPLEMENTED;
1227 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1228 struct netr_GetDcName *r)
1230 const char * const attrs[] = { NULL };
1231 struct ldb_context *sam_ctx;
1232 struct ldb_message **res;
1233 struct ldb_dn *domain_dn;
1238 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1239 * that the domainname needs to be a valid netbios domain
1240 * name, if it is not NULL.
1242 if (r->in.domainname) {
1243 const char *dot = strchr(r->in.domainname, '.');
1244 size_t len = strlen(r->in.domainname);
1246 if (dot || len > 15) {
1247 return WERR_NERR_DCNOTFOUND;
1251 * TODO: Should we also varify that only valid
1252 * netbios name characters are used?
1256 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1257 dce_call->conn->dce_ctx->lp_ctx,
1258 dce_call->conn->auth_state.session_info, 0);
1259 if (sam_ctx == NULL) {
1260 return WERR_DS_UNAVAILABLE;
1263 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1265 if (domain_dn == NULL) {
1266 return WERR_NO_SUCH_DOMAIN;
1269 ret = gendb_search_dn(sam_ctx, mem_ctx,
1270 domain_dn, &res, attrs);
1272 return WERR_NO_SUCH_DOMAIN;
1275 /* TODO: - return real IP address
1276 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1278 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1279 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1280 W_ERROR_HAVE_NO_MEMORY(dcname);
1282 *r->out.dcname = dcname;
1286 struct dcesrv_netr_LogonControl_base_state {
1287 struct dcesrv_call_state *dce_call;
1289 TALLOC_CTX *mem_ctx;
1291 struct netr_LogonControl2Ex r;
1294 struct netr_LogonControl *l;
1295 struct netr_LogonControl2 *l2;
1296 struct netr_LogonControl2Ex *l2ex;
1300 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1302 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1304 struct dcesrv_connection *conn = state->dce_call->conn;
1305 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1306 struct auth_session_info *session_info = conn->auth_state.session_info;
1307 enum security_user_level security_level;
1308 struct dcerpc_binding_handle *irpc_handle;
1309 struct tevent_req *subreq;
1312 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1314 if (state->_r.l != NULL) {
1318 if (state->r.in.level == 0x00000002) {
1319 return WERR_NOT_SUPPORTED;
1320 } else if (state->r.in.level != 0x00000001) {
1321 return WERR_INVALID_LEVEL;
1324 switch (state->r.in.function_code) {
1325 case NETLOGON_CONTROL_QUERY:
1326 case NETLOGON_CONTROL_REPLICATE:
1327 case NETLOGON_CONTROL_SYNCHRONIZE:
1328 case NETLOGON_CONTROL_PDC_REPLICATE:
1329 case NETLOGON_CONTROL_BREAKPOINT:
1330 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1331 case NETLOGON_CONTROL_TRUNCATE_LOG:
1334 return WERR_NOT_SUPPORTED;
1338 if (state->r.in.level < 0x00000001) {
1339 return WERR_INVALID_LEVEL;
1342 if (state->r.in.level > 0x00000004) {
1343 return WERR_INVALID_LEVEL;
1346 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1347 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1348 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1350 switch (state->r.in.level) {
1352 info1 = talloc_zero(state->mem_ctx,
1353 struct netr_NETLOGON_INFO_1);
1354 if (info1 == NULL) {
1355 return WERR_NOT_ENOUGH_MEMORY;
1357 state->r.out.query->info1 = info1;
1361 info3 = talloc_zero(state->mem_ctx,
1362 struct netr_NETLOGON_INFO_3);
1363 if (info3 == NULL) {
1364 return WERR_NOT_ENOUGH_MEMORY;
1366 state->r.out.query->info3 = info3;
1370 return WERR_INVALID_PARAMETER;
1375 * Some validations are done before the access check
1376 * and some after the access check
1378 security_level = security_session_user_level(session_info, NULL);
1379 if (security_level < SECURITY_ADMINISTRATOR) {
1380 return WERR_ACCESS_DENIED;
1383 if (state->_r.l2 != NULL) {
1385 * netr_LogonControl2
1387 if (state->r.in.level == 0x00000004) {
1388 return WERR_INVALID_LEVEL;
1392 switch (state->r.in.level) {
1397 switch (state->r.in.function_code) {
1398 case NETLOGON_CONTROL_REDISCOVER:
1399 case NETLOGON_CONTROL_TC_QUERY:
1400 case NETLOGON_CONTROL_TC_VERIFY:
1403 return WERR_INVALID_PARAMETER;
1412 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1413 return WERR_INVALID_PARAMETER;
1419 return WERR_INVALID_LEVEL;
1422 switch (state->r.in.function_code) {
1423 case NETLOGON_CONTROL_REDISCOVER:
1424 case NETLOGON_CONTROL_TC_QUERY:
1425 case NETLOGON_CONTROL_TC_VERIFY:
1426 if (state->r.in.level != 2) {
1427 return WERR_INVALID_PARAMETER;
1430 if (state->r.in.data == NULL) {
1431 return WERR_INVALID_PARAMETER;
1434 if (state->r.in.data->domain == NULL) {
1435 return WERR_INVALID_PARAMETER;
1440 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1441 if (state->r.in.level != 1) {
1442 return WERR_INVALID_PARAMETER;
1445 if (state->r.in.data == NULL) {
1446 return WERR_INVALID_PARAMETER;
1449 if (state->r.in.data->domain == NULL) {
1450 return WERR_INVALID_PARAMETER;
1453 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1454 state->r.in.data->domain);
1456 struct ldb_context *sam_ctx;
1458 sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1459 lp_ctx, system_session(lp_ctx), 0);
1460 if (sam_ctx == NULL) {
1461 return WERR_DS_UNAVAILABLE;
1465 * Secrets for trusted domains can only be triggered on
1468 ok = samdb_is_pdc(sam_ctx);
1469 TALLOC_FREE(sam_ctx);
1471 return WERR_INVALID_DOMAIN_ROLE;
1477 return WERR_NOT_SUPPORTED;
1480 irpc_handle = irpc_binding_handle_by_name(state,
1481 state->dce_call->msg_ctx,
1483 &ndr_table_winbind);
1484 if (irpc_handle == NULL) {
1485 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1486 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1487 return WERR_SERVICE_NOT_FOUND;
1491 * 60 seconds timeout should be enough
1493 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1495 subreq = dcerpc_winbind_LogonControl_send(state,
1496 state->dce_call->event_ctx,
1498 state->r.in.function_code,
1501 state->r.out.query);
1502 if (subreq == NULL) {
1503 return WERR_NOT_ENOUGH_MEMORY;
1505 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1506 tevent_req_set_callback(subreq,
1507 dcesrv_netr_LogonControl_base_done,
1513 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1515 struct dcesrv_netr_LogonControl_base_state *state =
1516 tevent_req_callback_data(subreq,
1517 struct dcesrv_netr_LogonControl_base_state);
1520 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1521 &state->r.out.result);
1522 TALLOC_FREE(subreq);
1523 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1524 state->r.out.result = WERR_TIMEOUT;
1525 } else if (!NT_STATUS_IS_OK(status)) {
1526 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1527 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1528 nt_errstr(status)));
1531 if (state->_r.l2ex != NULL) {
1532 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1533 r->out.result = state->r.out.result;
1534 } else if (state->_r.l2 != NULL) {
1535 struct netr_LogonControl2 *r = state->_r.l2;
1536 r->out.result = state->r.out.result;
1537 } else if (state->_r.l != NULL) {
1538 struct netr_LogonControl *r = state->_r.l;
1539 r->out.result = state->r.out.result;
1542 status = dcesrv_reply(state->dce_call);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1551 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1552 struct netr_LogonControl *r)
1554 struct dcesrv_netr_LogonControl_base_state *state;
1557 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1558 if (state == NULL) {
1559 return WERR_NOT_ENOUGH_MEMORY;
1562 state->dce_call = dce_call;
1563 state->mem_ctx = mem_ctx;
1565 state->r.in.logon_server = r->in.logon_server;
1566 state->r.in.function_code = r->in.function_code;
1567 state->r.in.level = r->in.level;
1568 state->r.in.data = NULL;
1569 state->r.out.query = r->out.query;
1573 werr = dcesrv_netr_LogonControl_base_call(state);
1575 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1585 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1586 struct netr_LogonControl2 *r)
1588 struct dcesrv_netr_LogonControl_base_state *state;
1591 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1592 if (state == NULL) {
1593 return WERR_NOT_ENOUGH_MEMORY;
1596 state->dce_call = dce_call;
1597 state->mem_ctx = mem_ctx;
1599 state->r.in.logon_server = r->in.logon_server;
1600 state->r.in.function_code = r->in.function_code;
1601 state->r.in.level = r->in.level;
1602 state->r.in.data = r->in.data;
1603 state->r.out.query = r->out.query;
1607 werr = dcesrv_netr_LogonControl_base_call(state);
1609 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1617 netr_LogonControl2Ex
1619 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1620 struct netr_LogonControl2Ex *r)
1622 struct dcesrv_netr_LogonControl_base_state *state;
1625 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1626 if (state == NULL) {
1627 return WERR_NOT_ENOUGH_MEMORY;
1630 state->dce_call = dce_call;
1631 state->mem_ctx = mem_ctx;
1636 werr = dcesrv_netr_LogonControl_base_call(state);
1638 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1645 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1646 struct ldb_context *sam_ctx,
1647 struct netr_DomainTrustList *trusts,
1648 uint32_t trust_flags);
1653 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1654 struct netr_GetAnyDCName *r)
1656 struct netr_DomainTrustList *trusts;
1657 struct ldb_context *sam_ctx;
1658 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1662 *r->out.dcname = NULL;
1664 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1665 /* if the domainname parameter wasn't set assume our domain */
1666 r->in.domainname = lpcfg_workgroup(lp_ctx);
1669 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1670 dce_call->conn->auth_state.session_info, 0);
1671 if (sam_ctx == NULL) {
1672 return WERR_DS_UNAVAILABLE;
1675 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1676 /* well we asked for a DC of our own domain */
1677 if (samdb_is_pdc(sam_ctx)) {
1678 /* we are the PDC of the specified domain */
1679 return WERR_NO_SUCH_DOMAIN;
1682 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1683 lpcfg_netbios_name(lp_ctx));
1684 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1689 /* Okay, now we have to consider the trusted domains */
1691 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1692 W_ERROR_HAVE_NO_MEMORY(trusts);
1696 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1697 NETR_TRUST_FLAG_INBOUND
1698 | NETR_TRUST_FLAG_OUTBOUND);
1699 W_ERROR_NOT_OK_RETURN(werr);
1701 for (i = 0; i < trusts->count; i++) {
1702 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1703 /* FIXME: Here we need to find a DC for the specified
1704 * trusted domain. */
1706 /* return WERR_OK; */
1707 return WERR_NO_SUCH_DOMAIN;
1711 return WERR_NO_SUCH_DOMAIN;
1718 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1719 struct netr_DatabaseRedo *r)
1721 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1726 netr_NetrEnumerateTrustedDomains
1728 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1729 struct netr_NetrEnumerateTrustedDomains *r)
1731 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1736 netr_LogonGetCapabilities
1738 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1739 struct netr_LogonGetCapabilities *r)
1741 struct netlogon_creds_CredentialState *creds;
1744 status = dcesrv_netr_creds_server_step_check(dce_call,
1746 r->in.computer_name,
1748 r->out.return_authenticator,
1750 if (!NT_STATUS_IS_OK(status)) {
1751 DEBUG(0,(__location__ " Bad credentials - error\n"));
1753 NT_STATUS_NOT_OK_RETURN(status);
1755 if (r->in.query_level != 1) {
1756 return NT_STATUS_NOT_SUPPORTED;
1759 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1761 return NT_STATUS_OK;
1766 netr_NETRLOGONSETSERVICEBITS
1768 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1769 struct netr_NETRLOGONSETSERVICEBITS *r)
1771 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1776 netr_LogonGetTrustRid
1778 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1779 struct netr_LogonGetTrustRid *r)
1781 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1786 netr_NETRLOGONCOMPUTESERVERDIGEST
1788 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1789 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1791 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1796 netr_NETRLOGONCOMPUTECLIENTDIGEST
1798 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1799 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1801 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1809 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1810 struct netr_DsRGetSiteName *r)
1812 struct ldb_context *sam_ctx;
1813 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1815 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1816 dce_call->conn->auth_state.session_info, 0);
1817 if (sam_ctx == NULL) {
1818 return WERR_DS_UNAVAILABLE;
1822 * We assume to be a DC when we get called over NETLOGON. Hence we
1823 * get our site name always by using "samdb_server_site_name()"
1824 * and not "samdb_client_site_name()".
1826 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1827 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1834 fill in a netr_OneDomainInfo from a ldb search result
1836 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1837 struct loadparm_context *lp_ctx,
1838 struct ldb_context *sam_ctx,
1839 struct ldb_message *res,
1840 struct netr_OneDomainInfo *info,
1841 bool is_local, bool is_trust_list)
1845 if (is_trust_list) {
1846 /* w2k8 only fills this on trusted domains */
1847 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1848 info->trust_extension.length = 16;
1849 info->trust_extension.info->flags =
1850 NETR_TRUST_FLAG_TREEROOT |
1851 NETR_TRUST_FLAG_IN_FOREST |
1852 NETR_TRUST_FLAG_PRIMARY |
1853 NETR_TRUST_FLAG_NATIVE;
1855 info->trust_extension.info->parent_index = 0; /* should be index into array
1857 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1858 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1861 if (is_trust_list) {
1862 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1863 info->dns_forestname.string = NULL;
1865 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1866 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1867 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1868 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1872 info->domainname.string = lpcfg_workgroup(lp_ctx);
1873 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1874 info->domain_guid = samdb_result_guid(res, "objectGUID");
1875 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1877 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1878 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1879 info->domain_guid = samdb_result_guid(res, "objectGUID");
1880 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1882 if (!is_trust_list) {
1883 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1886 return NT_STATUS_OK;
1890 netr_LogonGetDomainInfo
1891 this is called as part of the ADS domain logon procedure.
1893 It has an important role in convaying details about the client, such
1894 as Operating System, Version, Service Pack etc.
1896 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1897 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1899 struct netlogon_creds_CredentialState *creds;
1900 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1901 "securityIdentifier", "trustPartner", NULL };
1902 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1903 "msDS-SupportedEncryptionTypes", NULL };
1904 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1905 struct ldb_context *sam_ctx;
1906 struct ldb_message **res1, **res2, **res3, *new_msg;
1907 struct ldb_dn *workstation_dn;
1908 struct netr_DomainInformation *domain_info;
1909 struct netr_LsaPolicyInformation *lsa_policy_info;
1910 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1911 bool update_dns_hostname = true;
1915 status = dcesrv_netr_creds_server_step_check(dce_call,
1917 r->in.computer_name,
1919 r->out.return_authenticator,
1921 if (!NT_STATUS_IS_OK(status)) {
1922 DEBUG(0,(__location__ " Bad credentials - error\n"));
1924 NT_STATUS_NOT_OK_RETURN(status);
1926 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1927 dce_call->conn->dce_ctx->lp_ctx,
1928 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1929 if (sam_ctx == NULL) {
1930 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1933 switch (r->in.level) {
1934 case 1: /* Domain information */
1936 if (r->in.query->workstation_info == NULL) {
1937 return NT_STATUS_INVALID_PARAMETER;
1940 /* Prepares the workstation DN */
1941 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1942 dom_sid_string(mem_ctx, creds->sid));
1943 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1945 /* Lookup for attributes in workstation object */
1946 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1949 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1952 /* Gets the sam account name which is checked against the DNS
1953 * hostname parameter. */
1954 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1957 if (sam_account_name == NULL) {
1958 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1962 * Checks that the sam account name without a possible "$"
1963 * matches as prefix with the DNS hostname in the workstation
1966 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1967 strcspn(sam_account_name, "$"));
1968 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1969 if (r->in.query->workstation_info->dns_hostname != NULL) {
1970 prefix2 = talloc_strndup(mem_ctx,
1971 r->in.query->workstation_info->dns_hostname,
1972 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1973 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1975 if (strcasecmp(prefix1, prefix2) != 0) {
1976 update_dns_hostname = false;
1979 update_dns_hostname = false;
1982 /* Gets the old DNS hostname */
1983 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1988 * Updates the DNS hostname when the client wishes that the
1989 * server should handle this for him
1990 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1991 * obviously only checked when we do already have a
1993 * See MS-NRPC section 3.5.4.3.9
1995 if ((old_dns_hostname != NULL) &&
1996 (r->in.query->workstation_info->workstation_flags
1997 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1998 update_dns_hostname = false;
2001 /* Gets host information and put them into our directory */
2003 new_msg = ldb_msg_new(mem_ctx);
2004 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2006 new_msg->dn = workstation_dn;
2008 /* Sets the OS name */
2010 if (r->in.query->workstation_info->os_name.string == NULL) {
2011 return NT_STATUS_INVALID_PARAMETER;
2014 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2015 r->in.query->workstation_info->os_name.string);
2016 if (ret != LDB_SUCCESS) {
2017 return NT_STATUS_NO_MEMORY;
2021 * Sets information from "os_version". On an empty structure
2022 * the values are cleared.
2024 if (r->in.query->workstation_info->os_version.os != NULL) {
2025 struct netr_OsVersionInfoEx *os_version;
2026 const char *os_version_str;
2028 os_version = &r->in.query->workstation_info->os_version.os->os;
2030 if (os_version->CSDVersion == NULL) {
2031 return NT_STATUS_INVALID_PARAMETER;
2034 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2035 os_version->MajorVersion,
2036 os_version->MinorVersion,
2037 os_version->BuildNumber);
2038 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2040 ret = ldb_msg_add_string(new_msg,
2041 "operatingSystemServicePack",
2042 os_version->CSDVersion);
2043 if (ret != LDB_SUCCESS) {
2044 return NT_STATUS_NO_MEMORY;
2047 ret = ldb_msg_add_string(new_msg,
2048 "operatingSystemVersion",
2050 if (ret != LDB_SUCCESS) {
2051 return NT_STATUS_NO_MEMORY;
2054 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2055 "operatingSystemServicePack");
2056 if (ret != LDB_SUCCESS) {
2057 return NT_STATUS_NO_MEMORY;
2060 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2061 "operatingSystemVersion");
2062 if (ret != LDB_SUCCESS) {
2063 return NT_STATUS_NO_MEMORY;
2068 * If the boolean "update_dns_hostname" remained true, then we
2069 * are fine to start the update.
2071 if (update_dns_hostname) {
2072 ret = ldb_msg_add_string(new_msg,
2074 r->in.query->workstation_info->dns_hostname);
2075 if (ret != LDB_SUCCESS) {
2076 return NT_STATUS_NO_MEMORY;
2079 /* This manual "servicePrincipalName" generation is
2080 * still needed! Since the update in the samldb LDB
2081 * module does only work if the entries already exist
2082 * which isn't always the case. */
2083 ret = ldb_msg_add_string(new_msg,
2084 "servicePrincipalName",
2085 talloc_asprintf(new_msg, "HOST/%s",
2086 r->in.computer_name));
2087 if (ret != LDB_SUCCESS) {
2088 return NT_STATUS_NO_MEMORY;
2091 ret = ldb_msg_add_string(new_msg,
2092 "servicePrincipalName",
2093 talloc_asprintf(new_msg, "HOST/%s",
2094 r->in.query->workstation_info->dns_hostname));
2095 if (ret != LDB_SUCCESS) {
2096 return NT_STATUS_NO_MEMORY;
2100 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2101 DEBUG(3,("Impossible to update samdb: %s\n",
2102 ldb_errstring(sam_ctx)));
2105 talloc_free(new_msg);
2107 /* Writes back the domain information */
2109 /* We need to do two searches. The first will pull our primary
2110 domain and the second will pull any trusted domains. Our
2111 primary domain is also a "trusted" domain, so we need to
2112 put the primary domain into the lists of returned trusts as
2114 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2117 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2120 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2121 "(objectClass=trustedDomain)");
2123 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2126 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2127 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2129 ZERO_STRUCTP(domain_info);
2131 /* Informations about the local and trusted domains */
2133 status = fill_one_domain_info(mem_ctx,
2134 dce_call->conn->dce_ctx->lp_ctx,
2135 sam_ctx, res2[0], &domain_info->primary_domain,
2137 NT_STATUS_NOT_OK_RETURN(status);
2139 domain_info->trusted_domain_count = ret3 + 1;
2140 domain_info->trusted_domains = talloc_array(mem_ctx,
2141 struct netr_OneDomainInfo,
2142 domain_info->trusted_domain_count);
2143 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2145 for (i=0;i<ret3;i++) {
2146 status = fill_one_domain_info(mem_ctx,
2147 dce_call->conn->dce_ctx->lp_ctx,
2149 &domain_info->trusted_domains[i],
2151 NT_STATUS_NOT_OK_RETURN(status);
2154 status = fill_one_domain_info(mem_ctx,
2155 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2156 &domain_info->trusted_domains[i], true, true);
2157 NT_STATUS_NOT_OK_RETURN(status);
2159 /* Sets the supported encryption types */
2160 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2161 "msDS-SupportedEncryptionTypes",
2162 default_supported_enc_types);
2164 /* Other host domain information */
2166 lsa_policy_info = talloc(mem_ctx,
2167 struct netr_LsaPolicyInformation);
2168 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2169 ZERO_STRUCTP(lsa_policy_info);
2171 domain_info->lsa_policy = *lsa_policy_info;
2173 /* The DNS hostname is only returned back when there is a chance
2175 if ((r->in.query->workstation_info->workstation_flags
2176 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2177 domain_info->dns_hostname.string = old_dns_hostname;
2179 domain_info->dns_hostname.string = NULL;
2182 domain_info->workstation_flags =
2183 r->in.query->workstation_info->workstation_flags & (
2184 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2186 r->out.info->domain_info = domain_info;
2188 case 2: /* LSA policy information - not used at the moment */
2189 lsa_policy_info = talloc(mem_ctx,
2190 struct netr_LsaPolicyInformation);
2191 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2192 ZERO_STRUCTP(lsa_policy_info);
2194 r->out.info->lsa_policy_info = lsa_policy_info;
2197 return NT_STATUS_INVALID_LEVEL;
2201 return NT_STATUS_OK;
2206 netr_ServerPasswordGet
2208 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2209 struct netr_ServerPasswordGet *r)
2211 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2216 netr_NETRLOGONSENDTOSAM
2218 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2219 struct netr_NETRLOGONSENDTOSAM *r)
2221 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2226 netr_DsRGetDCNameEx2
2228 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2229 TALLOC_CTX *mem_ctx,
2230 struct netr_DsRGetDCNameEx2 *r)
2232 struct ldb_context *sam_ctx;
2233 struct netr_DsRGetDCNameInfo *info;
2234 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2235 const struct tsocket_address *local_address;
2236 char *local_addr = NULL;
2237 const struct tsocket_address *remote_address;
2238 char *remote_addr = NULL;
2239 const char *server_site_name;
2241 struct netlogon_samlogon_response response;
2243 const char *dc_name = NULL;
2244 const char *domain_name = NULL;
2247 ZERO_STRUCTP(r->out.info);
2249 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2250 dce_call->conn->auth_state.session_info, 0);
2251 if (sam_ctx == NULL) {
2252 return WERR_DS_UNAVAILABLE;
2255 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2256 if (tsocket_address_is_inet(local_address, "ip")) {
2257 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2258 W_ERROR_HAVE_NO_MEMORY(local_addr);
2261 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2262 if (tsocket_address_is_inet(remote_address, "ip")) {
2263 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2264 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2267 /* "server_unc" is ignored by w2k3 */
2269 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2270 return WERR_INVALID_FLAGS;
2273 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2274 r->in.flags & DS_PDC_REQUIRED &&
2275 r->in.flags & DS_KDC_REQUIRED) {
2276 return WERR_INVALID_FLAGS;
2278 if (r->in.flags & DS_IS_FLAT_NAME &&
2279 r->in.flags & DS_IS_DNS_NAME) {
2280 return WERR_INVALID_FLAGS;
2282 if (r->in.flags & DS_RETURN_DNS_NAME &&
2283 r->in.flags & DS_RETURN_FLAT_NAME) {
2284 return WERR_INVALID_FLAGS;
2286 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2287 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2288 return WERR_INVALID_FLAGS;
2291 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2293 (DS_DIRECTORY_SERVICE_REQUIRED |
2294 DS_DIRECTORY_SERVICE_PREFERRED |
2295 DS_GC_SERVER_REQUIRED |
2298 return WERR_INVALID_FLAGS;
2301 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2303 return WERR_INVALID_FLAGS;
2306 /* Proof server site parameter "site_name" if it was specified */
2307 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2308 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2309 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2310 server_site_name) != 0)) {
2311 return WERR_NO_SUCH_DOMAIN;
2314 guid_str = r->in.domain_guid != NULL ?
2315 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2317 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2321 r->in.client_account,
2322 r->in.mask, remote_addr,
2323 NETLOGON_NT_VERSION_5EX_WITH_IP,
2324 lp_ctx, &response, true);
2325 if (!NT_STATUS_IS_OK(status)) {
2326 return ntstatus_to_werror(status);
2330 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2331 * (O) flag when the returned forest name is in DNS format. This is here
2332 * always the case (see below).
2334 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2336 if (r->in.flags & DS_RETURN_DNS_NAME) {
2337 dc_name = response.data.nt5_ex.pdc_dns_name;
2338 domain_name = response.data.nt5_ex.dns_domain;
2340 * According to MS-NRPC 2.2.1.2.1 we should set the
2341 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2342 * the returned information is in DNS form.
2344 response.data.nt5_ex.server_type |=
2345 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2346 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2347 dc_name = response.data.nt5_ex.pdc_name;
2348 domain_name = response.data.nt5_ex.domain_name;
2352 * TODO: autodetect what we need to return
2353 * based on the given arguments
2355 dc_name = response.data.nt5_ex.pdc_name;
2356 domain_name = response.data.nt5_ex.domain_name;
2359 if (!dc_name || !dc_name[0]) {
2360 return WERR_NO_SUCH_DOMAIN;
2363 if (!domain_name || !domain_name[0]) {
2364 return WERR_NO_SUCH_DOMAIN;
2367 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2368 W_ERROR_HAVE_NO_MEMORY(info);
2369 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2370 dc_name[0] != '\\'? "\\\\":"",
2371 talloc_strdup(mem_ctx, dc_name));
2372 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2374 pdc_ip = local_addr;
2375 if (pdc_ip == NULL) {
2376 pdc_ip = "127.0.0.1";
2378 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2379 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2380 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2381 info->domain_guid = response.data.nt5_ex.domain_uuid;
2382 info->domain_name = domain_name;
2383 info->forest_name = response.data.nt5_ex.forest;
2384 info->dc_flags = response.data.nt5_ex.server_type;
2385 if (r->in.flags & DS_RETURN_DNS_NAME) {
2386 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2387 * returned if we are returning info->dc_unc containing a FQDN.
2388 * This attribute is called DomainControllerName in the specs,
2389 * it seems that we decide to return FQDN or netbios depending on
2390 * DS_RETURN_DNS_NAME.
2392 info->dc_flags |= DS_DNS_CONTROLLER;
2394 info->dc_site_name = response.data.nt5_ex.server_site;
2395 info->client_site_name = response.data.nt5_ex.client_site;
2397 *r->out.info = info;
2405 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2406 struct netr_DsRGetDCNameEx *r)
2408 struct netr_DsRGetDCNameEx2 r2;
2413 r2.in.server_unc = r->in.server_unc;
2414 r2.in.client_account = NULL;
2416 r2.in.domain_guid = r->in.domain_guid;
2417 r2.in.domain_name = r->in.domain_name;
2418 r2.in.site_name = r->in.site_name;
2419 r2.in.flags = r->in.flags;
2420 r2.out.info = r->out.info;
2422 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2430 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2431 struct netr_DsRGetDCName *r)
2433 struct netr_DsRGetDCNameEx2 r2;
2438 r2.in.server_unc = r->in.server_unc;
2439 r2.in.client_account = NULL;
2441 r2.in.domain_name = r->in.domain_name;
2442 r2.in.domain_guid = r->in.domain_guid;
2444 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2445 r2.in.flags = r->in.flags;
2446 r2.out.info = r->out.info;
2448 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2453 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2455 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2456 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2458 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2463 netr_NetrEnumerateTrustedDomainsEx
2465 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2466 struct netr_NetrEnumerateTrustedDomainsEx *r)
2468 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2473 netr_DsRAddressToSitenamesExW
2475 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2476 struct netr_DsRAddressToSitenamesExW *r)
2478 struct ldb_context *sam_ctx;
2479 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2480 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2481 sa_family_t sin_family;
2482 struct sockaddr_in *addr;
2484 struct sockaddr_in6 *addr6;
2485 char addr_str[INET6_ADDRSTRLEN];
2487 char addr_str[INET_ADDRSTRLEN];
2493 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2494 dce_call->conn->auth_state.session_info, 0);
2495 if (sam_ctx == NULL) {
2496 return WERR_DS_UNAVAILABLE;
2499 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2500 W_ERROR_HAVE_NO_MEMORY(ctr);
2504 ctr->count = r->in.count;
2505 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2506 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2507 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2508 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2510 for (i=0; i<ctr->count; i++) {
2511 ctr->sitename[i].string = NULL;
2512 ctr->subnetname[i].string = NULL;
2514 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2517 /* The first two byte of the buffer are reserved for the
2518 * "sin_family" but for now only the first one is used. */
2519 sin_family = r->in.addresses[i].buffer[0];
2521 switch (sin_family) {
2523 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2526 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2527 res = inet_ntop(AF_INET, &addr->sin_addr,
2528 addr_str, sizeof(addr_str));
2532 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2535 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2536 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2537 addr_str, sizeof(addr_str));
2548 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2552 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2553 ctr->subnetname[i].string = subnet_name;
2561 netr_DsRAddressToSitenamesW
2563 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2564 struct netr_DsRAddressToSitenamesW *r)
2566 struct netr_DsRAddressToSitenamesExW r2;
2567 struct netr_DsRAddressToSitenamesWCtr *ctr;
2573 r2.in.server_name = r->in.server_name;
2574 r2.in.count = r->in.count;
2575 r2.in.addresses = r->in.addresses;
2577 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2578 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2580 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2581 W_ERROR_HAVE_NO_MEMORY(ctr);
2585 ctr->count = r->in.count;
2586 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2587 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2589 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2591 for (i=0; i<ctr->count; i++) {
2592 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2600 netr_DsrGetDcSiteCoverageW
2602 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2603 struct netr_DsrGetDcSiteCoverageW *r)
2605 struct ldb_context *sam_ctx;
2606 struct DcSitesCtr *ctr;
2607 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2609 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2610 dce_call->conn->auth_state.session_info, 0);
2611 if (sam_ctx == NULL) {
2612 return WERR_DS_UNAVAILABLE;
2615 ctr = talloc(mem_ctx, struct DcSitesCtr);
2616 W_ERROR_HAVE_NO_MEMORY(ctr);
2620 /* For now only return our default site */
2622 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2623 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2624 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2625 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2631 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2632 struct ldb_context *sam_ctx,
2633 struct netr_DomainTrustList *trusts,
2634 uint32_t trust_flags)
2636 struct ldb_dn *system_dn;
2637 struct ldb_message **dom_res = NULL;
2638 const char *trust_attrs[] = { "flatname", "trustPartner",
2639 "securityIdentifier", "trustDirection",
2640 "trustType", "trustAttributes", NULL };
2645 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2646 NETR_TRUST_FLAG_OUTBOUND))) {
2647 return WERR_INVALID_FLAGS;
2650 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2651 ldb_get_default_basedn(sam_ctx),
2652 "(&(objectClass=container)(cn=System))");
2654 return WERR_GEN_FAILURE;
2657 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2658 &dom_res, trust_attrs,
2659 "(objectclass=trustedDomain)");
2661 for (i = 0; i < ret; i++) {
2662 unsigned int trust_dir;
2665 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2666 "trustDirection", 0);
2668 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2669 flags |= NETR_TRUST_FLAG_INBOUND;
2671 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2672 flags |= NETR_TRUST_FLAG_OUTBOUND;
2675 if (!(flags & trust_flags)) {
2676 /* this trust direction was not requested */
2681 trusts->array = talloc_realloc(trusts, trusts->array,
2682 struct netr_DomainTrust,
2684 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2686 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2687 if (!trusts->array[n].netbios_name) {
2688 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2689 "without flatname\n",
2690 ldb_dn_get_linearized(dom_res[i]->dn)));
2693 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2695 trusts->array[n].trust_flags = flags;
2696 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2697 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2698 /* TODO: find if we have parent in the list */
2699 trusts->array[n].parent_index = 0;
2702 trusts->array[n].trust_type =
2703 ldb_msg_find_attr_as_uint(dom_res[i],
2705 trusts->array[n].trust_attributes =
2706 ldb_msg_find_attr_as_uint(dom_res[i],
2707 "trustAttributes", 0);
2709 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2710 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2711 struct dom_sid zero_sid;
2712 ZERO_STRUCT(zero_sid);
2713 trusts->array[n].sid =
2714 dom_sid_dup(trusts, &zero_sid);
2716 trusts->array[n].sid =
2717 samdb_result_dom_sid(trusts, dom_res[i],
2718 "securityIdentifier");
2720 trusts->array[n].guid = GUID_zero();
2722 trusts->count = n + 1;
2725 talloc_free(dom_res);
2730 netr_DsrEnumerateDomainTrusts
2732 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2733 TALLOC_CTX *mem_ctx,
2734 struct netr_DsrEnumerateDomainTrusts *r)
2736 struct netr_DomainTrustList *trusts;
2737 struct ldb_context *sam_ctx;
2739 struct ldb_message **dom_res;
2740 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2741 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2742 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2746 if (r->in.trust_flags & 0xFFFFFE00) {
2747 return WERR_INVALID_FLAGS;
2750 /* TODO: turn to hard check once we are sure this is 100% correct */
2751 if (!r->in.server_name) {
2752 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2753 "But received NULL!\n", dnsdomain));
2755 p = strchr(r->in.server_name, '.');
2757 DEBUG(3, ("Invalid domain! Expected name in domain "
2758 "[%s]. But received [%s]!\n",
2759 dnsdomain, r->in.server_name));
2760 p = r->in.server_name;
2764 if (strcasecmp(p, dnsdomain)) {
2765 DEBUG(3, ("Invalid domain! Expected name in domain "
2766 "[%s]. But received [%s]!\n",
2767 dnsdomain, r->in.server_name));
2771 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2772 W_ERROR_HAVE_NO_MEMORY(trusts);
2775 r->out.trusts = trusts;
2777 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2778 dce_call->conn->auth_state.session_info, 0);
2779 if (sam_ctx == NULL) {
2780 return WERR_GEN_FAILURE;
2783 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2784 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2786 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2787 trusts, r->in.trust_flags);
2788 W_ERROR_NOT_OK_RETURN(werr);
2791 /* NOTE: we currently are always the root of the forest */
2792 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2793 uint32_t n = trusts->count;
2795 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2796 &dom_res, dom_attrs);
2798 return WERR_GEN_FAILURE;
2801 trusts->count = n + 1;
2802 trusts->array = talloc_realloc(trusts, trusts->array,
2803 struct netr_DomainTrust,
2805 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2807 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2808 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2809 trusts->array[n].trust_flags =
2810 NETR_TRUST_FLAG_NATIVE |
2811 NETR_TRUST_FLAG_TREEROOT |
2812 NETR_TRUST_FLAG_IN_FOREST |
2813 NETR_TRUST_FLAG_PRIMARY;
2814 /* we are always the root domain for now */
2815 trusts->array[n].parent_index = 0;
2816 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2817 trusts->array[n].trust_attributes = 0;
2818 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2821 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2823 talloc_free(dom_res);
2831 netr_DsrDeregisterDNSHostRecords
2833 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2834 struct netr_DsrDeregisterDNSHostRecords *r)
2836 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2840 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2841 struct netr_ServerGetTrustInfo *r);
2844 netr_ServerTrustPasswordsGet
2846 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2847 struct netr_ServerTrustPasswordsGet *r)
2849 struct netr_ServerGetTrustInfo r2 = {};
2850 struct netr_TrustInfo *_ti = NULL;
2853 r2.in.server_name = r->in.server_name;
2854 r2.in.account_name = r->in.account_name;
2855 r2.in.secure_channel_type = r->in.secure_channel_type;
2856 r2.in.computer_name = r->in.computer_name;
2857 r2.in.credential = r->in.credential;
2859 r2.out.return_authenticator = r->out.return_authenticator;
2860 r2.out.new_owf_password = r->out.new_owf_password;
2861 r2.out.old_owf_password = r->out.old_owf_password;
2862 r2.out.trust_info = &_ti;
2864 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
2866 r->out.return_authenticator = r2.out.return_authenticator;
2867 r->out.new_owf_password = r2.out.new_owf_password;
2868 r->out.old_owf_password = r2.out.old_owf_password;
2874 netr_DsRGetForestTrustInformation
2876 struct dcesrv_netr_DsRGetForestTrustInformation_state {
2877 struct dcesrv_call_state *dce_call;
2878 TALLOC_CTX *mem_ctx;
2879 struct netr_DsRGetForestTrustInformation *r;
2882 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
2884 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2885 TALLOC_CTX *mem_ctx,
2886 struct netr_DsRGetForestTrustInformation *r)
2888 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2889 struct dcesrv_connection *conn = dce_call->conn;
2890 struct auth_session_info *session_info = conn->auth_state.session_info;
2891 enum security_user_level security_level;
2892 struct ldb_context *sam_ctx = NULL;
2893 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
2894 struct dcerpc_binding_handle *irpc_handle = NULL;
2895 struct tevent_req *subreq = NULL;
2896 struct ldb_dn *domain_dn = NULL;
2897 struct ldb_dn *forest_dn = NULL;
2901 security_level = security_session_user_level(session_info, NULL);
2902 if (security_level < SECURITY_USER) {
2903 return WERR_ACCESS_DENIED;
2906 if (r->in.flags & 0xFFFFFFFE) {
2907 return WERR_INVALID_FLAGS;
2910 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2911 dce_call->conn->auth_state.session_info, 0);
2912 if (sam_ctx == NULL) {
2913 return WERR_GEN_FAILURE;
2916 domain_dn = ldb_get_default_basedn(sam_ctx);
2917 if (domain_dn == NULL) {
2918 return WERR_GEN_FAILURE;
2921 forest_dn = ldb_get_root_basedn(sam_ctx);
2922 if (forest_dn == NULL) {
2923 return WERR_GEN_FAILURE;
2926 cmp = ldb_dn_compare(domain_dn, forest_dn);
2928 return WERR_NERR_ACFNOTLOADED;
2931 forest_level = dsdb_forest_functional_level(sam_ctx);
2932 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
2933 return WERR_INVALID_FUNCTION;
2936 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2937 if (!samdb_is_pdc(sam_ctx)) {
2938 return WERR_NERR_NOTPRIMARY;
2941 if (r->in.trusted_domain_name == NULL) {
2942 return WERR_INVALID_FLAGS;
2946 if (r->in.trusted_domain_name == NULL) {
2950 * information about our own domain
2952 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
2953 r->out.forest_trust_info);
2954 if (!NT_STATUS_IS_OK(status)) {
2955 return ntstatus_to_werror(status);
2962 * Forward the request to winbindd
2965 state = talloc_zero(mem_ctx,
2966 struct dcesrv_netr_DsRGetForestTrustInformation_state);
2967 if (state == NULL) {
2968 return WERR_NOT_ENOUGH_MEMORY;
2970 state->dce_call = dce_call;
2971 state->mem_ctx = mem_ctx;
2974 irpc_handle = irpc_binding_handle_by_name(state,
2975 state->dce_call->msg_ctx,
2977 &ndr_table_winbind);
2978 if (irpc_handle == NULL) {
2979 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2980 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2981 return WERR_SERVICE_NOT_FOUND;
2985 * 60 seconds timeout should be enough
2987 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2989 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
2990 state->dce_call->event_ctx,
2992 r->in.trusted_domain_name,
2994 r->out.forest_trust_info);
2995 if (subreq == NULL) {
2996 return WERR_NOT_ENOUGH_MEMORY;
2998 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2999 tevent_req_set_callback(subreq,
3000 dcesrv_netr_DsRGetForestTrustInformation_done,
3006 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3008 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3009 tevent_req_callback_data(subreq,
3010 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3013 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3015 &state->r->out.result);
3016 TALLOC_FREE(subreq);
3017 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3018 state->r->out.result = WERR_TIMEOUT;
3019 } else if (!NT_STATUS_IS_OK(status)) {
3020 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3021 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3022 nt_errstr(status)));
3025 status = dcesrv_reply(state->dce_call);
3026 if (!NT_STATUS_IS_OK(status)) {
3027 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3032 netr_GetForestTrustInformation
3034 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3035 TALLOC_CTX *mem_ctx,
3036 struct netr_GetForestTrustInformation *r)
3038 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3039 struct netlogon_creds_CredentialState *creds = NULL;
3040 struct ldb_context *sam_ctx = NULL;
3041 struct ldb_dn *domain_dn = NULL;
3042 struct ldb_dn *forest_dn = NULL;
3047 status = dcesrv_netr_creds_server_step_check(dce_call,
3049 r->in.computer_name,
3051 r->out.return_authenticator,
3053 if (!NT_STATUS_IS_OK(status)) {
3057 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3058 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3059 return NT_STATUS_NOT_IMPLEMENTED;
3062 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3063 dce_call->conn->auth_state.session_info, 0);
3064 if (sam_ctx == NULL) {
3065 return NT_STATUS_INTERNAL_ERROR;
3068 /* TODO: check r->in.server_name is our name */
3070 domain_dn = ldb_get_default_basedn(sam_ctx);
3071 if (domain_dn == NULL) {
3072 return NT_STATUS_INTERNAL_ERROR;
3075 forest_dn = ldb_get_root_basedn(sam_ctx);
3076 if (forest_dn == NULL) {
3077 return NT_STATUS_INTERNAL_ERROR;
3080 cmp = ldb_dn_compare(domain_dn, forest_dn);
3082 return NT_STATUS_INVALID_DOMAIN_STATE;
3085 forest_level = dsdb_forest_functional_level(sam_ctx);
3086 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3087 return NT_STATUS_INVALID_DOMAIN_STATE;
3090 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3091 r->out.forest_trust_info);
3092 if (!NT_STATUS_IS_OK(status)) {
3096 return NT_STATUS_OK;
3101 netr_ServerGetTrustInfo
3103 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3104 struct netr_ServerGetTrustInfo *r)
3106 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3107 struct netlogon_creds_CredentialState *creds = NULL;
3108 struct ldb_context *sam_ctx = NULL;
3109 const char * const attrs[] = {
3112 "userAccountControl",
3115 struct ldb_message **res = NULL;
3116 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3119 const char *asid = NULL;
3121 const char *aname = NULL;
3122 struct ldb_message *tdo_msg = NULL;
3123 const char * const tdo_attrs[] = {
3124 "trustAuthIncoming",
3128 struct netr_TrustInfo *trust_info = NULL;
3130 ZERO_STRUCTP(r->out.new_owf_password);
3131 ZERO_STRUCTP(r->out.old_owf_password);
3133 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3135 r->in.computer_name,
3137 r->out.return_authenticator,
3139 if (!NT_STATUS_IS_OK(nt_status)) {
3143 /* TODO: check r->in.server_name is our name */
3145 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3146 return NT_STATUS_INVALID_PARAMETER;
3149 if (r->in.secure_channel_type != creds->secure_channel_type) {
3150 return NT_STATUS_INVALID_PARAMETER;
3153 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3154 return NT_STATUS_INVALID_PARAMETER;
3157 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3158 lp_ctx, system_session(lp_ctx), 0);
3159 if (sam_ctx == NULL) {
3160 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3163 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3165 return NT_STATUS_NO_MEMORY;
3168 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3169 "(&(objectClass=user)(objectSid=%s))",
3172 return NT_STATUS_ACCOUNT_DISABLED;
3175 switch (creds->secure_channel_type) {
3176 case SEC_CHAN_DNS_DOMAIN:
3177 case SEC_CHAN_DOMAIN:
3178 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3180 if (uac & UF_ACCOUNTDISABLE) {
3181 return NT_STATUS_ACCOUNT_DISABLED;
3184 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3185 return NT_STATUS_ACCOUNT_DISABLED;
3188 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3189 if (aname == NULL) {
3190 return NT_STATUS_ACCOUNT_DISABLED;
3193 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3194 SEC_CHAN_DOMAIN, aname,
3195 tdo_attrs, mem_ctx, &tdo_msg);
3196 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3197 return NT_STATUS_ACCOUNT_DISABLED;
3199 if (!NT_STATUS_IS_OK(nt_status)) {
3203 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3206 if (!NT_STATUS_IS_OK(nt_status)) {
3210 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3211 if (trust_info == NULL) {
3212 return NT_STATUS_NO_MEMORY;
3215 trust_info->count = 1;
3216 trust_info->data = talloc_array(trust_info, uint32_t,
3218 if (trust_info->data == NULL) {
3219 return NT_STATUS_NO_MEMORY;
3222 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3228 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3231 if (!NT_STATUS_IS_OK(nt_status)) {
3235 prevNtHash = talloc(mem_ctx, struct samr_Password);
3236 if (prevNtHash == NULL) {
3237 return NT_STATUS_NO_MEMORY;
3240 E_md4hash("", prevNtHash->hash);
3244 if (curNtHash != NULL) {
3245 *r->out.new_owf_password = *curNtHash;
3246 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3248 if (prevNtHash != NULL) {
3249 *r->out.old_owf_password = *prevNtHash;
3250 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3253 if (trust_info != NULL) {
3254 *r->out.trust_info = trust_info;
3257 return NT_STATUS_OK;
3263 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3264 struct netr_Unused47 *r)
3266 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3270 struct netr_dnsupdate_RODC_state {
3271 struct dcesrv_call_state *dce_call;
3272 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3273 struct dnsupdate_RODC *r2;
3277 called when the forwarded RODC dns update request is finished
3279 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3281 struct netr_dnsupdate_RODC_state *st =
3282 tevent_req_callback_data(subreq,
3283 struct netr_dnsupdate_RODC_state);
3286 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3287 TALLOC_FREE(subreq);
3288 if (!NT_STATUS_IS_OK(status)) {
3289 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3290 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3293 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3295 status = dcesrv_reply(st->dce_call);
3296 if (!NT_STATUS_IS_OK(status)) {
3297 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3302 netr_DsrUpdateReadOnlyServerDnsRecords
3304 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3305 TALLOC_CTX *mem_ctx,
3306 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3308 struct netlogon_creds_CredentialState *creds;
3310 struct dcerpc_binding_handle *binding_handle;
3311 struct netr_dnsupdate_RODC_state *st;
3312 struct tevent_req *subreq;
3314 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3316 r->in.computer_name,
3318 r->out.return_authenticator,
3320 NT_STATUS_NOT_OK_RETURN(nt_status);
3322 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3323 return NT_STATUS_ACCESS_DENIED;
3326 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3327 NT_STATUS_HAVE_NO_MEMORY(st);
3329 st->dce_call = dce_call;
3331 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3332 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3334 st->r2->in.dom_sid = creds->sid;
3335 st->r2->in.site_name = r->in.site_name;
3336 st->r2->in.dns_ttl = r->in.dns_ttl;
3337 st->r2->in.dns_names = r->in.dns_names;
3338 st->r2->out.dns_names = r->out.dns_names;
3340 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3341 "dnsupdate", &ndr_table_irpc);
3342 if (binding_handle == NULL) {
3343 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3344 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3345 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3348 /* forward the call */
3349 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3350 binding_handle, st->r2);
3351 NT_STATUS_HAVE_NO_MEMORY(subreq);
3353 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3355 /* setup the callback */
3356 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3358 return NT_STATUS_OK;
3362 /* include the generated boilerplate */
3363 #include "librpc/gen_ndr/ndr_netlogon_s.c"