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 "../lib/util/memcache.h"
31 #include "../libcli/auth/schannel.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "lib/messaging/irpc.h"
35 #include "librpc/gen_ndr/ndr_irpc_c.h"
36 #include "../libcli/ldap/ldap_ndr.h"
37 #include "dsdb/samdb/ldb_modules/util.h"
38 #include "lib/tsocket/tsocket.h"
39 #include "librpc/gen_ndr/ndr_netlogon.h"
40 #include "librpc/gen_ndr/ndr_lsa.h"
41 #include "librpc/gen_ndr/ndr_samr.h"
42 #include "librpc/gen_ndr/ndr_irpc.h"
43 #include "librpc/gen_ndr/ndr_winbind.h"
44 #include "librpc/gen_ndr/ndr_winbind_c.h"
45 #include "lib/socket/netif.h"
47 #define DCESRV_INTERFACE_NETLOGON_BIND(call, iface) \
48 dcesrv_interface_netlogon_bind(call, iface)
49 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_call_state *dce_call,
50 const struct dcesrv_interface *iface)
52 return dcesrv_interface_bind_reject_connect(dce_call, iface);
55 static struct memcache *global_challenge_table;
57 struct netlogon_server_pipe_state {
58 struct netr_Credential client_challenge;
59 struct netr_Credential server_challenge;
62 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
63 struct netr_ServerReqChallenge *r)
65 struct netlogon_server_pipe_state *pipe_state =
66 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
69 ZERO_STRUCTP(r->out.return_credentials);
71 if (global_challenge_table == NULL) {
73 * We maintain a global challenge table
74 * with a fixed size (8k)
76 * This is required for the strange clients
77 * which use different connections for
78 * netr_ServerReqChallenge() and netr_ServerAuthenticate3()
81 global_challenge_table = memcache_init(talloc_autofree_context(),
83 if (global_challenge_table == NULL) {
84 return NT_STATUS_NO_MEMORY;
88 /* destroyed on pipe shutdown */
91 talloc_free(pipe_state);
92 dce_call->context->private_data = NULL;
95 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
96 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
98 pipe_state->client_challenge = *r->in.credentials;
100 generate_random_buffer(pipe_state->server_challenge.data,
101 sizeof(pipe_state->server_challenge.data));
103 *r->out.return_credentials = pipe_state->server_challenge;
105 dce_call->context->private_data = pipe_state;
107 key = data_blob_string_const(r->in.computer_name);
108 val = data_blob_const(pipe_state, sizeof(*pipe_state));
110 memcache_add(global_challenge_table, SINGLETON_CACHE, key, val);
115 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
116 struct netr_ServerAuthenticate3 *r)
118 struct netlogon_server_pipe_state *pipe_state =
119 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
120 DATA_BLOB challenge_key;
121 bool challenge_valid = false;
122 struct netlogon_server_pipe_state challenge;
123 struct netlogon_creds_CredentialState *creds;
124 struct ldb_context *sam_ctx;
125 struct samr_Password *curNtHash = NULL;
126 struct samr_Password *prevNtHash = NULL;
127 uint32_t user_account_control;
129 struct ldb_message **msgs;
131 const char *attrs[] = {"unicodePwd", "userAccountControl",
133 const char *account_name;
134 uint32_t server_flags = 0;
135 uint32_t negotiate_flags = 0;
136 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
137 bool reject_des_client = !allow_nt4_crypto;
138 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
139 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
140 bool reject_none_rpc = (schannel == true);
142 ZERO_STRUCTP(r->out.return_credentials);
145 challenge_key = data_blob_string_const(r->in.computer_name);
146 if (pipe_state != NULL) {
147 dce_call->context->private_data = NULL;
150 * If we had a challenge remembered on the connection
151 * consider this for usage. This can't be cleanup
154 * This is the default code path for typical clients
155 * which call netr_ServerReqChallenge() and
156 * netr_ServerAuthenticate3() on the same dcerpc connection.
158 challenge = *pipe_state;
159 TALLOC_FREE(pipe_state);
160 challenge_valid = true;
166 * Fallback and try to get the challenge from
169 * If too many clients are using this code path,
170 * they may destroy their cache entries as the
171 * global_challenge_table memcache has a fixed size.
173 * Note: this handles global_challenge_table == NULL fine
175 ok = memcache_lookup(global_challenge_table, SINGLETON_CACHE,
176 challenge_key, &val);
177 if (ok && val.length == sizeof(challenge)) {
178 memcpy(&challenge, val.data, sizeof(challenge));
179 challenge_valid = true;
181 ZERO_STRUCT(challenge);
185 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
186 NETLOGON_NEG_PERSISTENT_SAMREPL |
187 NETLOGON_NEG_ARCFOUR |
188 NETLOGON_NEG_PROMOTION_COUNT |
189 NETLOGON_NEG_CHANGELOG_BDC |
190 NETLOGON_NEG_FULL_SYNC_REPL |
191 NETLOGON_NEG_MULTIPLE_SIDS |
193 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
194 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
195 NETLOGON_NEG_GENERIC_PASSTHROUGH |
196 NETLOGON_NEG_CONCURRENT_RPC |
197 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
198 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
199 NETLOGON_NEG_STRONG_KEYS |
200 NETLOGON_NEG_TRANSITIVE_TRUSTS |
201 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
202 NETLOGON_NEG_PASSWORD_SET2 |
203 NETLOGON_NEG_GETDOMAININFO |
204 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
205 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
206 NETLOGON_NEG_RODC_PASSTHROUGH |
207 NETLOGON_NEG_SUPPORTS_AES |
208 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
209 NETLOGON_NEG_AUTHENTICATED_RPC;
211 negotiate_flags = *r->in.negotiate_flags & server_flags;
213 if (negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
214 reject_none_rpc = false;
217 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
218 reject_des_client = false;
221 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
222 reject_des_client = false;
223 reject_md5_client = false;
226 if (reject_des_client || reject_md5_client) {
228 * Here we match Windows 2012 and return no flags.
230 *r->out.negotiate_flags = 0;
231 return NT_STATUS_DOWNGRADE_DETECTED;
235 * At this point we can cleanup the cache entry,
236 * if we fail the client needs to call netr_ServerReqChallenge
239 * Note: this handles global_challenge_table == NULL
240 * and also a non existing record just fine.
242 memcache_delete(global_challenge_table,
243 SINGLETON_CACHE, challenge_key);
246 * According to Microsoft (see bugid #6099)
247 * Windows 7 looks at the negotiate_flags
248 * returned in this structure *even if the
249 * call fails with access denied!
251 *r->out.negotiate_flags = negotiate_flags;
253 if (reject_none_rpc) {
254 /* schannel must be used, but client did not offer it. */
255 DEBUG(0,("%s: schannel required but client failed "
256 "to offer it. Client was %s\n",
257 __func__, r->in.account_name));
258 return NT_STATUS_ACCESS_DENIED;
261 switch (r->in.secure_channel_type) {
263 case SEC_CHAN_DNS_DOMAIN:
264 case SEC_CHAN_DOMAIN:
269 return NT_STATUS_INVALID_PARAMETER;
271 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
272 r->in.secure_channel_type));
273 return NT_STATUS_INVALID_PARAMETER;
276 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
277 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
278 if (sam_ctx == NULL) {
279 return NT_STATUS_INVALID_SYSTEM_SERVICE;
282 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
283 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
285 struct ldb_message *tdo_msg = NULL;
286 const char * const tdo_attrs[] = {
292 char *encoded_name = NULL;
294 const char *flatname = NULL;
296 bool require_trailer = true;
297 const char *netbios = NULL;
298 const char *dns = NULL;
300 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
302 require_trailer = false;
305 encoded_name = ldb_binary_encode_string(mem_ctx,
307 if (encoded_name == NULL) {
308 return NT_STATUS_NO_MEMORY;
311 len = strlen(encoded_name);
313 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
316 if (require_trailer && encoded_name[len - 1] != trailer) {
317 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
319 encoded_name[len - 1] = '\0';
321 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
324 netbios = encoded_name;
327 nt_status = dsdb_trust_search_tdo(sam_ctx,
329 tdo_attrs, mem_ctx, &tdo_msg);
330 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
331 DEBUG(2, ("Client asked for a trusted domain secure channel, "
332 "but there's no tdo for [%s] => [%s] \n",
333 r->in.account_name, encoded_name));
334 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
336 if (!NT_STATUS_IS_OK(nt_status)) {
340 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
343 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
344 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
346 if (!NT_STATUS_IS_OK(nt_status)) {
350 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
351 if (flatname == NULL) {
352 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
355 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
356 if (account_name == NULL) {
357 return NT_STATUS_NO_MEMORY;
360 account_name = r->in.account_name;
363 /* pull the user attributes */
364 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
365 "(&(sAMAccountName=%s)(objectclass=user))",
366 ldb_binary_encode_string(mem_ctx, account_name));
368 if (num_records == 0) {
369 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
370 r->in.account_name));
371 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
374 if (num_records > 1) {
375 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
376 return NT_STATUS_INTERNAL_DB_CORRUPTION;
379 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
381 if (user_account_control & UF_ACCOUNTDISABLE) {
382 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
383 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
386 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
387 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
388 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
389 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
391 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
392 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
393 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
394 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: 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_BDC) {
399 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
400 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
401 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
403 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
404 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
405 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
406 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
409 /* we should never reach this */
410 return NT_STATUS_INTERNAL_ERROR;
413 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
414 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
415 dce_call->conn->dce_ctx->lp_ctx,
416 msgs[0], NULL, &curNtHash);
417 if (!NT_STATUS_IS_OK(nt_status)) {
418 return NT_STATUS_ACCESS_DENIED;
422 if (curNtHash == NULL) {
423 return NT_STATUS_ACCESS_DENIED;
426 if (!challenge_valid) {
427 DEBUG(1, ("No challenge requested by client [%s/%s], "
428 "cannot authenticate\n",
430 r->in.account_name));
431 return NT_STATUS_ACCESS_DENIED;
434 creds = netlogon_creds_server_init(mem_ctx,
437 r->in.secure_channel_type,
438 &challenge.client_challenge,
439 &challenge.server_challenge,
442 r->out.return_credentials,
444 if (creds == NULL && prevNtHash != NULL) {
446 * We fallback to the previous password for domain trusts.
448 * Note that lpcfg_old_password_allowed_period() doesn't
451 creds = netlogon_creds_server_init(mem_ctx,
454 r->in.secure_channel_type,
455 &challenge.client_challenge,
456 &challenge.server_challenge,
459 r->out.return_credentials,
463 return NT_STATUS_ACCESS_DENIED;
466 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
468 nt_status = schannel_save_creds_state(mem_ctx,
469 dce_call->conn->dce_ctx->lp_ctx,
471 if (!NT_STATUS_IS_OK(nt_status)) {
472 ZERO_STRUCTP(r->out.return_credentials);
476 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
482 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
483 struct netr_ServerAuthenticate *r)
485 struct netr_ServerAuthenticate3 a;
488 * negotiate_flags is used as an [in] parameter
489 * so it need to be initialised.
491 * (I think ... = 0; seems wrong here --metze)
493 uint32_t negotiate_flags_in = 0;
494 uint32_t negotiate_flags_out = 0;
496 a.in.server_name = r->in.server_name;
497 a.in.account_name = r->in.account_name;
498 a.in.secure_channel_type = r->in.secure_channel_type;
499 a.in.computer_name = r->in.computer_name;
500 a.in.credentials = r->in.credentials;
501 a.in.negotiate_flags = &negotiate_flags_in;
503 a.out.return_credentials = r->out.return_credentials;
505 a.out.negotiate_flags = &negotiate_flags_out;
507 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
510 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
511 struct netr_ServerAuthenticate2 *r)
513 struct netr_ServerAuthenticate3 r3;
516 r3.in.server_name = r->in.server_name;
517 r3.in.account_name = r->in.account_name;
518 r3.in.secure_channel_type = r->in.secure_channel_type;
519 r3.in.computer_name = r->in.computer_name;
520 r3.in.credentials = r->in.credentials;
521 r3.out.return_credentials = r->out.return_credentials;
522 r3.in.negotiate_flags = r->in.negotiate_flags;
523 r3.out.negotiate_flags = r->out.negotiate_flags;
526 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
530 * NOTE: The following functions are nearly identical to the ones available in
531 * source3/rpc_server/srv_nelog_nt.c
532 * The reason we keep 2 copies is that they use different structures to
533 * represent the auth_info and the decrpc pipes.
537 * If schannel is required for this call test that it actually is available.
539 static NTSTATUS schannel_check_required(const struct dcesrv_auth *auth_info,
540 const char *computer_name,
541 bool integrity, bool privacy)
544 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
545 if (!privacy && !integrity) {
549 if ((!privacy && integrity) &&
550 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
554 if ((privacy || integrity) &&
555 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
560 /* test didn't pass */
561 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
564 return NT_STATUS_ACCESS_DENIED;
567 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
569 const char *computer_name,
570 struct netr_Authenticator *received_authenticator,
571 struct netr_Authenticator *return_authenticator,
572 struct netlogon_creds_CredentialState **creds_out)
575 int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
576 bool schannel_global_required = (schannel == true);
578 if (schannel_global_required) {
579 nt_status = schannel_check_required(&dce_call->conn->auth_state,
582 if (!NT_STATUS_IS_OK(nt_status)) {
587 nt_status = schannel_check_creds_state(mem_ctx,
588 dce_call->conn->dce_ctx->lp_ctx,
590 received_authenticator,
591 return_authenticator,
597 Change the machine account password for the currently connected
598 client. Supplies only the NT#.
601 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
602 struct netr_ServerPasswordSet *r)
604 struct netlogon_creds_CredentialState *creds;
605 struct ldb_context *sam_ctx;
606 const char * const attrs[] = { "unicodePwd", NULL };
607 struct ldb_message **res;
608 struct samr_Password *oldNtHash;
612 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
615 r->in.credential, r->out.return_authenticator,
617 NT_STATUS_NOT_OK_RETURN(nt_status);
619 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);
620 if (sam_ctx == NULL) {
621 return NT_STATUS_INVALID_SYSTEM_SERVICE;
624 netlogon_creds_des_decrypt(creds, r->in.new_password);
626 /* fetch the old password hashes (the NT hash has to exist) */
628 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
629 "(&(objectClass=user)(objectSid=%s))",
630 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
632 return NT_STATUS_WRONG_PASSWORD;
635 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
636 dce_call->conn->dce_ctx->lp_ctx,
637 res[0], NULL, &oldNtHash);
638 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
639 return NT_STATUS_WRONG_PASSWORD;
642 /* Using the sid for the account as the key, set the password */
643 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
645 NULL, /* Don't have version */
646 NULL, /* Don't have plaintext */
647 NULL, r->in.new_password,
648 NULL, oldNtHash, /* Password change */
654 Change the machine account password for the currently connected
655 client. Supplies new plaintext.
657 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
658 struct netr_ServerPasswordSet2 *r)
660 struct netlogon_creds_CredentialState *creds;
661 struct ldb_context *sam_ctx;
662 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
663 struct ldb_message **res;
664 struct samr_Password *oldLmHash, *oldNtHash;
665 struct NL_PASSWORD_VERSION version = {};
666 const uint32_t *new_version = NULL;
668 DATA_BLOB new_password;
670 struct samr_CryptPassword password_buf;
672 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
675 r->in.credential, r->out.return_authenticator,
677 NT_STATUS_NOT_OK_RETURN(nt_status);
679 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);
680 if (sam_ctx == NULL) {
681 return NT_STATUS_INVALID_SYSTEM_SERVICE;
684 memcpy(password_buf.data, r->in.new_password->data, 512);
685 SIVAL(password_buf.data, 512, r->in.new_password->length);
687 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
688 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
690 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
693 switch (creds->secure_channel_type) {
694 case SEC_CHAN_DOMAIN:
695 case SEC_CHAN_DNS_DOMAIN: {
696 uint32_t len = IVAL(password_buf.data, 512);
698 uint32_t ofs = 500 - len;
701 p = password_buf.data + ofs;
703 version.ReservedField = IVAL(p, 0);
704 version.PasswordVersionNumber = IVAL(p, 4);
705 version.PasswordVersionPresent = IVAL(p, 8);
707 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
708 new_version = &version.PasswordVersionNumber;
716 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
717 DEBUG(3,("samr: failed to decode password buffer\n"));
718 return NT_STATUS_WRONG_PASSWORD;
721 /* fetch the old password hashes (at least one of both has to exist) */
723 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
724 "(&(objectClass=user)(objectSid=%s))",
725 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
727 return NT_STATUS_WRONG_PASSWORD;
730 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
731 dce_call->conn->dce_ctx->lp_ctx,
732 res[0], &oldLmHash, &oldNtHash);
733 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
734 return NT_STATUS_WRONG_PASSWORD;
737 /* Using the sid for the account as the key, set the password */
738 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
741 &new_password, /* we have plaintext */
743 oldLmHash, oldNtHash, /* Password change */
752 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
753 struct netr_LogonUasLogon *r)
755 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
762 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
763 struct netr_LogonUasLogoff *r)
765 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
769 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
771 switch (r->in.logon_level) {
772 case NetlogonInteractiveInformation:
773 case NetlogonServiceInformation:
774 case NetlogonInteractiveTransitiveInformation:
775 case NetlogonServiceTransitiveInformation:
776 if (r->in.logon->password == NULL) {
777 return NT_STATUS_INVALID_PARAMETER;
780 switch (r->in.validation_level) {
781 case NetlogonValidationSamInfo: /* 2 */
782 case NetlogonValidationSamInfo2: /* 3 */
783 case NetlogonValidationSamInfo4: /* 6 */
786 return NT_STATUS_INVALID_INFO_CLASS;
790 case NetlogonNetworkInformation:
791 case NetlogonNetworkTransitiveInformation:
792 if (r->in.logon->network == NULL) {
793 return NT_STATUS_INVALID_PARAMETER;
796 switch (r->in.validation_level) {
797 case NetlogonValidationSamInfo: /* 2 */
798 case NetlogonValidationSamInfo2: /* 3 */
799 case NetlogonValidationSamInfo4: /* 6 */
802 return NT_STATUS_INVALID_INFO_CLASS;
807 case NetlogonGenericInformation:
808 if (r->in.logon->generic == NULL) {
809 return NT_STATUS_INVALID_PARAMETER;
812 switch (r->in.validation_level) {
813 /* TODO: case NetlogonValidationGenericInfo: 4 */
814 case NetlogonValidationGenericInfo2: /* 5 */
817 return NT_STATUS_INVALID_INFO_CLASS;
822 return NT_STATUS_INVALID_PARAMETER;
829 netr_LogonSamLogon_base
831 This version of the function allows other wrappers to say 'do not check the credentials'
833 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
835 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
836 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
838 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
839 const char *workgroup = lpcfg_workgroup(lp_ctx);
840 struct auth4_context *auth_context = NULL;
841 struct auth_usersupplied_info *user_info = NULL;
842 struct auth_user_info_dc *user_info_dc = NULL;
844 struct netr_SamBaseInfo *sam = NULL;
845 struct netr_SamInfo2 *sam2 = NULL;
846 struct netr_SamInfo3 *sam3 = NULL;
847 struct netr_SamInfo6 *sam6 = NULL;
849 *r->out.authoritative = 1;
851 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
852 NT_STATUS_HAVE_NO_MEMORY(user_info);
854 netlogon_creds_decrypt_samlogon_logon(creds,
858 switch (r->in.logon_level) {
859 case NetlogonInteractiveInformation:
860 case NetlogonServiceInformation:
861 case NetlogonInteractiveTransitiveInformation:
862 case NetlogonServiceTransitiveInformation:
864 /* TODO: we need to deny anonymous access here */
865 nt_status = auth_context_create(mem_ctx,
866 dce_call->event_ctx, dce_call->msg_ctx,
867 dce_call->conn->dce_ctx->lp_ctx,
869 NT_STATUS_NOT_OK_RETURN(nt_status);
871 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
872 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
873 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
874 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
876 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
877 user_info->password_state = AUTH_PASSWORD_HASH;
879 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
880 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
881 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
883 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
884 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
885 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
888 case NetlogonNetworkInformation:
889 case NetlogonNetworkTransitiveInformation:
891 /* TODO: we need to deny anonymous access here */
892 nt_status = auth_context_create(mem_ctx,
893 dce_call->event_ctx, dce_call->msg_ctx,
894 dce_call->conn->dce_ctx->lp_ctx,
896 NT_STATUS_NOT_OK_RETURN(nt_status);
898 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
899 NT_STATUS_NOT_OK_RETURN(nt_status);
901 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
902 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
903 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
904 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
906 user_info->password_state = AUTH_PASSWORD_RESPONSE;
907 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
908 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
910 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
911 user_info->client.account_name,
912 user_info->client.domain_name,
913 user_info->password.response.nt,
915 NT_STATUS_NOT_OK_RETURN(nt_status);
920 case NetlogonGenericInformation:
922 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
924 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
927 /* Using DES to verify kerberos tickets makes no sense */
928 return NT_STATUS_INVALID_PARAMETER;
931 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
933 struct dcerpc_binding_handle *irpc_handle;
934 struct kdc_check_generic_kerberos check;
935 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
936 NT_STATUS_HAVE_NO_MEMORY(generic);
937 *r->out.authoritative = 1;
939 /* TODO: Describe and deal with these flags */
942 r->out.validation->generic = generic;
944 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
948 if (irpc_handle == NULL) {
949 return NT_STATUS_NO_LOGON_SERVERS;
952 check.in.generic_request =
953 data_blob_const(r->in.logon->generic->data,
954 r->in.logon->generic->length);
957 * TODO: make this async and avoid
958 * dcerpc_binding_handle_set_sync_ev()
960 dcerpc_binding_handle_set_sync_ev(irpc_handle,
961 dce_call->event_ctx);
962 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
965 if (!NT_STATUS_IS_OK(status)) {
968 generic->length = check.out.generic_reply.length;
969 generic->data = check.out.generic_reply.data;
973 /* Until we get an implemetnation of these other packages */
974 return NT_STATUS_INVALID_PARAMETER;
977 return NT_STATUS_INVALID_PARAMETER;
980 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
981 /* TODO: set *r->out.authoritative = 0 on specific errors */
982 NT_STATUS_NOT_OK_RETURN(nt_status);
984 switch (r->in.validation_level) {
986 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
987 NT_STATUS_NOT_OK_RETURN(nt_status);
989 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
990 NT_STATUS_HAVE_NO_MEMORY(sam2);
993 /* And put into the talloc tree */
994 talloc_steal(sam2, sam);
995 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;
1012 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1013 return NT_STATUS_INVALID_PARAMETER;
1016 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1019 NT_STATUS_NOT_OK_RETURN(nt_status);
1021 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
1022 NT_STATUS_HAVE_NO_MEMORY(sam6);
1023 sam6->base = sam3->base;
1025 sam6->sidcount = sam3->sidcount;
1026 sam6->sids = sam3->sids;
1028 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
1029 sam6->principal_name.string = talloc_asprintf(
1030 mem_ctx, "%s@%s", sam->account_name.string,
1031 sam6->dns_domainname.string);
1032 NT_STATUS_HAVE_NO_MEMORY(sam6->principal_name.string);
1033 /* And put into the talloc tree */
1034 talloc_steal(sam6, sam3);
1036 r->out.validation->sam6 = sam6;
1040 return NT_STATUS_INVALID_INFO_CLASS;
1043 netlogon_creds_encrypt_samlogon_validation(creds,
1044 r->in.validation_level,
1047 /* TODO: Describe and deal with these flags */
1050 return NT_STATUS_OK;
1053 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1054 struct netr_LogonSamLogonEx *r)
1057 struct netlogon_creds_CredentialState *creds;
1059 *r->out.authoritative = 1;
1061 nt_status = dcesrv_netr_LogonSamLogon_check(r);
1062 if (!NT_STATUS_IS_OK(nt_status)) {
1066 nt_status = schannel_get_creds_state(mem_ctx,
1067 dce_call->conn->dce_ctx->lp_ctx,
1068 r->in.computer_name, &creds);
1069 if (!NT_STATUS_IS_OK(nt_status)) {
1073 if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1074 return NT_STATUS_ACCESS_DENIED;
1076 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1080 netr_LogonSamLogonWithFlags
1083 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1084 struct netr_LogonSamLogonWithFlags *r)
1087 struct netlogon_creds_CredentialState *creds;
1088 struct netr_LogonSamLogonEx r2;
1090 struct netr_Authenticator *return_authenticator;
1094 r2.in.server_name = r->in.server_name;
1095 r2.in.computer_name = r->in.computer_name;
1096 r2.in.logon_level = r->in.logon_level;
1097 r2.in.logon = r->in.logon;
1098 r2.in.validation_level = r->in.validation_level;
1099 r2.in.flags = r->in.flags;
1100 r2.out.validation = r->out.validation;
1101 r2.out.authoritative = r->out.authoritative;
1102 r2.out.flags = r->out.flags;
1104 *r->out.authoritative = 1;
1106 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1107 if (!NT_STATUS_IS_OK(nt_status)) {
1111 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1112 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1114 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1116 r->in.computer_name,
1117 r->in.credential, return_authenticator,
1119 NT_STATUS_NOT_OK_RETURN(nt_status);
1121 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1123 r->out.return_authenticator = return_authenticator;
1131 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1132 struct netr_LogonSamLogon *r)
1134 struct netr_LogonSamLogonWithFlags r2;
1140 r2.in.server_name = r->in.server_name;
1141 r2.in.computer_name = r->in.computer_name;
1142 r2.in.credential = r->in.credential;
1143 r2.in.return_authenticator = r->in.return_authenticator;
1144 r2.in.logon_level = r->in.logon_level;
1145 r2.in.logon = r->in.logon;
1146 r2.in.validation_level = r->in.validation_level;
1147 r2.in.flags = &flags;
1148 r2.out.validation = r->out.validation;
1149 r2.out.authoritative = r->out.authoritative;
1150 r2.out.flags = &flags;
1152 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1154 r->out.return_authenticator = r2.out.return_authenticator;
1163 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1164 struct netr_LogonSamLogoff *r)
1166 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1174 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1175 struct netr_DatabaseDeltas *r)
1177 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1184 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1185 struct netr_DatabaseSync2 *r)
1187 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1188 return NT_STATUS_NOT_IMPLEMENTED;
1195 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1196 struct netr_DatabaseSync *r)
1198 struct netr_DatabaseSync2 r2;
1203 r2.in.logon_server = r->in.logon_server;
1204 r2.in.computername = r->in.computername;
1205 r2.in.credential = r->in.credential;
1206 r2.in.database_id = r->in.database_id;
1207 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1208 r2.in.sync_context = r->in.sync_context;
1209 r2.out.sync_context = r->out.sync_context;
1210 r2.out.delta_enum_array = r->out.delta_enum_array;
1211 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1213 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1222 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1223 struct netr_AccountDeltas *r)
1225 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1226 return NT_STATUS_NOT_IMPLEMENTED;
1233 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1234 struct netr_AccountSync *r)
1236 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1237 return NT_STATUS_NOT_IMPLEMENTED;
1244 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1245 struct netr_GetDcName *r)
1247 const char * const attrs[] = { NULL };
1248 struct ldb_context *sam_ctx;
1249 struct ldb_message **res;
1250 struct ldb_dn *domain_dn;
1255 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1256 * that the domainname needs to be a valid netbios domain
1257 * name, if it is not NULL.
1259 if (r->in.domainname) {
1260 const char *dot = strchr(r->in.domainname, '.');
1261 size_t len = strlen(r->in.domainname);
1263 if (dot || len > 15) {
1264 return WERR_DCNOTFOUND;
1268 * TODO: Should we also varify that only valid
1269 * netbios name characters are used?
1273 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1274 dce_call->conn->dce_ctx->lp_ctx,
1275 dce_call->conn->auth_state.session_info, 0);
1276 if (sam_ctx == NULL) {
1277 return WERR_DS_UNAVAILABLE;
1280 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1282 if (domain_dn == NULL) {
1283 return WERR_NO_SUCH_DOMAIN;
1286 ret = gendb_search_dn(sam_ctx, mem_ctx,
1287 domain_dn, &res, attrs);
1289 return WERR_NO_SUCH_DOMAIN;
1292 /* TODO: - return real IP address
1293 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1295 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1296 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1297 W_ERROR_HAVE_NO_MEMORY(dcname);
1299 *r->out.dcname = dcname;
1303 struct dcesrv_netr_LogonControl_base_state {
1304 struct dcesrv_call_state *dce_call;
1306 TALLOC_CTX *mem_ctx;
1308 struct netr_LogonControl2Ex r;
1311 struct netr_LogonControl *l;
1312 struct netr_LogonControl2 *l2;
1313 struct netr_LogonControl2Ex *l2ex;
1317 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1319 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1321 struct dcesrv_connection *conn = state->dce_call->conn;
1322 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1323 struct auth_session_info *session_info = conn->auth_state.session_info;
1324 enum security_user_level security_level;
1325 struct dcerpc_binding_handle *irpc_handle;
1326 struct tevent_req *subreq;
1329 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1331 if (state->_r.l != NULL) {
1335 if (state->r.in.level == 0x00000002) {
1336 return WERR_NOT_SUPPORTED;
1337 } else if (state->r.in.level != 0x00000001) {
1338 return WERR_INVALID_LEVEL;
1341 switch (state->r.in.function_code) {
1342 case NETLOGON_CONTROL_QUERY:
1343 case NETLOGON_CONTROL_REPLICATE:
1344 case NETLOGON_CONTROL_SYNCHRONIZE:
1345 case NETLOGON_CONTROL_PDC_REPLICATE:
1346 case NETLOGON_CONTROL_BREAKPOINT:
1347 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1348 case NETLOGON_CONTROL_TRUNCATE_LOG:
1351 return WERR_NOT_SUPPORTED;
1355 if (state->r.in.level < 0x00000001) {
1356 return WERR_INVALID_LEVEL;
1359 if (state->r.in.level > 0x00000004) {
1360 return WERR_INVALID_LEVEL;
1363 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1364 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1365 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1367 switch (state->r.in.level) {
1369 info1 = talloc_zero(state->mem_ctx,
1370 struct netr_NETLOGON_INFO_1);
1371 if (info1 == NULL) {
1374 state->r.out.query->info1 = info1;
1378 info3 = talloc_zero(state->mem_ctx,
1379 struct netr_NETLOGON_INFO_3);
1380 if (info3 == NULL) {
1383 state->r.out.query->info3 = info3;
1387 return WERR_INVALID_PARAMETER;
1392 * Some validations are done before the access check
1393 * and some after the access check
1395 security_level = security_session_user_level(session_info, NULL);
1396 if (security_level < SECURITY_ADMINISTRATOR) {
1397 return WERR_ACCESS_DENIED;
1400 if (state->_r.l2 != NULL) {
1402 * netr_LogonControl2
1404 if (state->r.in.level == 0x00000004) {
1405 return WERR_INVALID_LEVEL;
1409 switch (state->r.in.level) {
1414 switch (state->r.in.function_code) {
1415 case NETLOGON_CONTROL_REDISCOVER:
1416 case NETLOGON_CONTROL_TC_QUERY:
1417 case NETLOGON_CONTROL_TC_VERIFY:
1420 return WERR_INVALID_PARAMETER;
1429 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1430 return WERR_INVALID_PARAMETER;
1436 return WERR_INVALID_LEVEL;
1439 switch (state->r.in.function_code) {
1440 case NETLOGON_CONTROL_REDISCOVER:
1441 case NETLOGON_CONTROL_TC_QUERY:
1442 case NETLOGON_CONTROL_TC_VERIFY:
1443 if (state->r.in.level != 2) {
1444 return WERR_INVALID_PARAMETER;
1447 if (state->r.in.data == NULL) {
1448 return WERR_INVALID_PARAMETER;
1451 if (state->r.in.data->domain == NULL) {
1452 return WERR_INVALID_PARAMETER;
1457 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1458 if (state->r.in.level != 1) {
1459 return WERR_INVALID_PARAMETER;
1462 if (state->r.in.data == NULL) {
1463 return WERR_INVALID_PARAMETER;
1466 if (state->r.in.data->domain == NULL) {
1467 return WERR_INVALID_PARAMETER;
1470 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1471 state->r.in.data->domain);
1473 struct ldb_context *sam_ctx;
1475 sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1476 lp_ctx, system_session(lp_ctx), 0);
1477 if (sam_ctx == NULL) {
1478 return WERR_DS_UNAVAILABLE;
1482 * Secrets for trusted domains can only be triggered on
1485 ok = samdb_is_pdc(sam_ctx);
1486 TALLOC_FREE(sam_ctx);
1488 return WERR_INVALID_DOMAIN_ROLE;
1494 return WERR_NOT_SUPPORTED;
1497 irpc_handle = irpc_binding_handle_by_name(state,
1498 state->dce_call->msg_ctx,
1500 &ndr_table_winbind);
1501 if (irpc_handle == NULL) {
1502 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1503 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1504 return WERR_SERVICE_NOT_FOUND;
1508 * 60 seconds timeout should be enough
1510 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1512 subreq = dcerpc_winbind_LogonControl_send(state,
1513 state->dce_call->event_ctx,
1515 state->r.in.function_code,
1518 state->r.out.query);
1519 if (subreq == NULL) {
1522 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1523 tevent_req_set_callback(subreq,
1524 dcesrv_netr_LogonControl_base_done,
1530 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1532 struct dcesrv_netr_LogonControl_base_state *state =
1533 tevent_req_callback_data(subreq,
1534 struct dcesrv_netr_LogonControl_base_state);
1537 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1538 &state->r.out.result);
1539 TALLOC_FREE(subreq);
1540 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1541 state->r.out.result = WERR_TIMEOUT;
1542 } else if (!NT_STATUS_IS_OK(status)) {
1543 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1544 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1545 nt_errstr(status)));
1548 if (state->_r.l2ex != NULL) {
1549 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1550 r->out.result = state->r.out.result;
1551 } else if (state->_r.l2 != NULL) {
1552 struct netr_LogonControl2 *r = state->_r.l2;
1553 r->out.result = state->r.out.result;
1554 } else if (state->_r.l != NULL) {
1555 struct netr_LogonControl *r = state->_r.l;
1556 r->out.result = state->r.out.result;
1559 status = dcesrv_reply(state->dce_call);
1560 if (!NT_STATUS_IS_OK(status)) {
1561 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1568 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1569 struct netr_LogonControl *r)
1571 struct dcesrv_netr_LogonControl_base_state *state;
1574 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1575 if (state == NULL) {
1579 state->dce_call = dce_call;
1580 state->mem_ctx = mem_ctx;
1582 state->r.in.logon_server = r->in.logon_server;
1583 state->r.in.function_code = r->in.function_code;
1584 state->r.in.level = r->in.level;
1585 state->r.in.data = NULL;
1586 state->r.out.query = r->out.query;
1590 werr = dcesrv_netr_LogonControl_base_call(state);
1592 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1602 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1603 struct netr_LogonControl2 *r)
1605 struct dcesrv_netr_LogonControl_base_state *state;
1608 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1609 if (state == NULL) {
1613 state->dce_call = dce_call;
1614 state->mem_ctx = mem_ctx;
1616 state->r.in.logon_server = r->in.logon_server;
1617 state->r.in.function_code = r->in.function_code;
1618 state->r.in.level = r->in.level;
1619 state->r.in.data = r->in.data;
1620 state->r.out.query = r->out.query;
1624 werr = dcesrv_netr_LogonControl_base_call(state);
1626 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1634 netr_LogonControl2Ex
1636 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1637 struct netr_LogonControl2Ex *r)
1639 struct dcesrv_netr_LogonControl_base_state *state;
1642 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1643 if (state == NULL) {
1647 state->dce_call = dce_call;
1648 state->mem_ctx = mem_ctx;
1653 werr = dcesrv_netr_LogonControl_base_call(state);
1655 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1662 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1663 struct ldb_context *sam_ctx,
1664 struct netr_DomainTrustList *trusts,
1665 uint32_t trust_flags);
1670 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1671 struct netr_GetAnyDCName *r)
1673 struct netr_DomainTrustList *trusts;
1674 struct ldb_context *sam_ctx;
1675 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1679 *r->out.dcname = NULL;
1681 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1682 /* if the domainname parameter wasn't set assume our domain */
1683 r->in.domainname = lpcfg_workgroup(lp_ctx);
1686 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1687 dce_call->conn->auth_state.session_info, 0);
1688 if (sam_ctx == NULL) {
1689 return WERR_DS_UNAVAILABLE;
1692 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1693 /* well we asked for a DC of our own domain */
1694 if (samdb_is_pdc(sam_ctx)) {
1695 /* we are the PDC of the specified domain */
1696 return WERR_NO_SUCH_DOMAIN;
1699 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1700 lpcfg_netbios_name(lp_ctx));
1701 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1706 /* Okay, now we have to consider the trusted domains */
1708 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1709 W_ERROR_HAVE_NO_MEMORY(trusts);
1713 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1714 NETR_TRUST_FLAG_INBOUND
1715 | NETR_TRUST_FLAG_OUTBOUND);
1716 W_ERROR_NOT_OK_RETURN(werr);
1718 for (i = 0; i < trusts->count; i++) {
1719 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1720 /* FIXME: Here we need to find a DC for the specified
1721 * trusted domain. */
1723 /* return WERR_OK; */
1724 return WERR_NO_SUCH_DOMAIN;
1728 return WERR_NO_SUCH_DOMAIN;
1735 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1736 struct netr_DatabaseRedo *r)
1738 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1743 netr_NetrEnumerateTrustedDomains
1745 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1746 struct netr_NetrEnumerateTrustedDomains *r)
1748 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1753 netr_LogonGetCapabilities
1755 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1756 struct netr_LogonGetCapabilities *r)
1758 struct netlogon_creds_CredentialState *creds;
1761 status = dcesrv_netr_creds_server_step_check(dce_call,
1763 r->in.computer_name,
1765 r->out.return_authenticator,
1767 if (!NT_STATUS_IS_OK(status)) {
1768 DEBUG(0,(__location__ " Bad credentials - error\n"));
1770 NT_STATUS_NOT_OK_RETURN(status);
1772 if (r->in.query_level != 1) {
1773 return NT_STATUS_NOT_SUPPORTED;
1776 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1778 return NT_STATUS_OK;
1783 netr_NETRLOGONSETSERVICEBITS
1785 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1786 struct netr_NETRLOGONSETSERVICEBITS *r)
1788 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1793 netr_LogonGetTrustRid
1795 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1796 struct netr_LogonGetTrustRid *r)
1798 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1803 netr_NETRLOGONCOMPUTESERVERDIGEST
1805 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1806 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1808 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1813 netr_NETRLOGONCOMPUTECLIENTDIGEST
1815 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1816 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1818 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1826 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1827 struct netr_DsRGetSiteName *r)
1829 struct ldb_context *sam_ctx;
1830 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1832 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1833 dce_call->conn->auth_state.session_info, 0);
1834 if (sam_ctx == NULL) {
1835 return WERR_DS_UNAVAILABLE;
1839 * We assume to be a DC when we get called over NETLOGON. Hence we
1840 * get our site name always by using "samdb_server_site_name()"
1841 * and not "samdb_client_site_name()".
1843 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1844 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1851 fill in a netr_OneDomainInfo from a ldb search result
1853 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1854 struct loadparm_context *lp_ctx,
1855 struct ldb_context *sam_ctx,
1856 struct ldb_message *res,
1857 struct netr_OneDomainInfo *info,
1858 bool is_local, bool is_trust_list)
1862 if (is_trust_list) {
1863 /* w2k8 only fills this on trusted domains */
1864 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1865 info->trust_extension.length = 16;
1866 info->trust_extension.info->flags =
1867 NETR_TRUST_FLAG_TREEROOT |
1868 NETR_TRUST_FLAG_IN_FOREST |
1869 NETR_TRUST_FLAG_PRIMARY |
1870 NETR_TRUST_FLAG_NATIVE;
1872 info->trust_extension.info->parent_index = 0; /* should be index into array
1874 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1875 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1878 if (is_trust_list) {
1879 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1880 info->dns_forestname.string = NULL;
1882 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1883 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1884 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1885 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1889 info->domainname.string = lpcfg_workgroup(lp_ctx);
1890 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1891 info->domain_guid = samdb_result_guid(res, "objectGUID");
1892 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1894 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1895 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1896 info->domain_guid = samdb_result_guid(res, "objectGUID");
1897 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1899 if (!is_trust_list) {
1900 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1903 return NT_STATUS_OK;
1907 netr_LogonGetDomainInfo
1908 this is called as part of the ADS domain logon procedure.
1910 It has an important role in convaying details about the client, such
1911 as Operating System, Version, Service Pack etc.
1913 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1914 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1916 struct netlogon_creds_CredentialState *creds;
1917 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1918 "securityIdentifier", "trustPartner", NULL };
1919 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1920 "msDS-SupportedEncryptionTypes", NULL };
1921 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1922 struct ldb_context *sam_ctx;
1923 struct ldb_message **res1, **res2, **res3, *new_msg;
1924 struct ldb_dn *workstation_dn;
1925 struct netr_DomainInformation *domain_info;
1926 struct netr_LsaPolicyInformation *lsa_policy_info;
1927 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1928 bool update_dns_hostname = true;
1932 status = dcesrv_netr_creds_server_step_check(dce_call,
1934 r->in.computer_name,
1936 r->out.return_authenticator,
1938 if (!NT_STATUS_IS_OK(status)) {
1939 DEBUG(0,(__location__ " Bad credentials - error\n"));
1941 NT_STATUS_NOT_OK_RETURN(status);
1943 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1944 dce_call->conn->dce_ctx->lp_ctx,
1945 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1946 if (sam_ctx == NULL) {
1947 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1950 switch (r->in.level) {
1951 case 1: /* Domain information */
1953 if (r->in.query->workstation_info == NULL) {
1954 return NT_STATUS_INVALID_PARAMETER;
1957 /* Prepares the workstation DN */
1958 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1959 dom_sid_string(mem_ctx, creds->sid));
1960 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1962 /* Lookup for attributes in workstation object */
1963 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1966 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1969 /* Gets the sam account name which is checked against the DNS
1970 * hostname parameter. */
1971 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1974 if (sam_account_name == NULL) {
1975 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1979 * Checks that the sam account name without a possible "$"
1980 * matches as prefix with the DNS hostname in the workstation
1983 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1984 strcspn(sam_account_name, "$"));
1985 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1986 if (r->in.query->workstation_info->dns_hostname != NULL) {
1987 prefix2 = talloc_strndup(mem_ctx,
1988 r->in.query->workstation_info->dns_hostname,
1989 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1990 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1992 if (strcasecmp(prefix1, prefix2) != 0) {
1993 update_dns_hostname = false;
1996 update_dns_hostname = false;
1999 /* Gets the old DNS hostname */
2000 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2005 * Updates the DNS hostname when the client wishes that the
2006 * server should handle this for him
2007 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2008 * obviously only checked when we do already have a
2010 * See MS-NRPC section 3.5.4.3.9
2012 if ((old_dns_hostname != NULL) &&
2013 (r->in.query->workstation_info->workstation_flags
2014 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2015 update_dns_hostname = false;
2018 /* Gets host information and put them into our directory */
2020 new_msg = ldb_msg_new(mem_ctx);
2021 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2023 new_msg->dn = workstation_dn;
2025 /* Sets the OS name */
2027 if (r->in.query->workstation_info->os_name.string == NULL) {
2028 return NT_STATUS_INVALID_PARAMETER;
2031 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2032 r->in.query->workstation_info->os_name.string);
2033 if (ret != LDB_SUCCESS) {
2034 return NT_STATUS_NO_MEMORY;
2038 * Sets information from "os_version". On an empty structure
2039 * the values are cleared.
2041 if (r->in.query->workstation_info->os_version.os != NULL) {
2042 struct netr_OsVersionInfoEx *os_version;
2043 const char *os_version_str;
2045 os_version = &r->in.query->workstation_info->os_version.os->os;
2047 if (os_version->CSDVersion == NULL) {
2048 return NT_STATUS_INVALID_PARAMETER;
2051 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2052 os_version->MajorVersion,
2053 os_version->MinorVersion,
2054 os_version->BuildNumber);
2055 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2057 ret = ldb_msg_add_string(new_msg,
2058 "operatingSystemServicePack",
2059 os_version->CSDVersion);
2060 if (ret != LDB_SUCCESS) {
2061 return NT_STATUS_NO_MEMORY;
2064 ret = ldb_msg_add_string(new_msg,
2065 "operatingSystemVersion",
2067 if (ret != LDB_SUCCESS) {
2068 return NT_STATUS_NO_MEMORY;
2071 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2072 "operatingSystemServicePack");
2073 if (ret != LDB_SUCCESS) {
2074 return NT_STATUS_NO_MEMORY;
2077 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2078 "operatingSystemVersion");
2079 if (ret != LDB_SUCCESS) {
2080 return NT_STATUS_NO_MEMORY;
2085 * If the boolean "update_dns_hostname" remained true, then we
2086 * are fine to start the update.
2088 if (update_dns_hostname) {
2089 ret = ldb_msg_add_string(new_msg,
2091 r->in.query->workstation_info->dns_hostname);
2092 if (ret != LDB_SUCCESS) {
2093 return NT_STATUS_NO_MEMORY;
2096 /* This manual "servicePrincipalName" generation is
2097 * still needed! Since the update in the samldb LDB
2098 * module does only work if the entries already exist
2099 * which isn't always the case. */
2100 ret = ldb_msg_add_string(new_msg,
2101 "servicePrincipalName",
2102 talloc_asprintf(new_msg, "HOST/%s",
2103 r->in.computer_name));
2104 if (ret != LDB_SUCCESS) {
2105 return NT_STATUS_NO_MEMORY;
2108 ret = ldb_msg_add_string(new_msg,
2109 "servicePrincipalName",
2110 talloc_asprintf(new_msg, "HOST/%s",
2111 r->in.query->workstation_info->dns_hostname));
2112 if (ret != LDB_SUCCESS) {
2113 return NT_STATUS_NO_MEMORY;
2117 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2118 DEBUG(3,("Impossible to update samdb: %s\n",
2119 ldb_errstring(sam_ctx)));
2122 talloc_free(new_msg);
2124 /* Writes back the domain information */
2126 /* We need to do two searches. The first will pull our primary
2127 domain and the second will pull any trusted domains. Our
2128 primary domain is also a "trusted" domain, so we need to
2129 put the primary domain into the lists of returned trusts as
2131 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2134 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2137 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2138 "(objectClass=trustedDomain)");
2140 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2143 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2144 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2146 ZERO_STRUCTP(domain_info);
2148 /* Informations about the local and trusted domains */
2150 status = fill_one_domain_info(mem_ctx,
2151 dce_call->conn->dce_ctx->lp_ctx,
2152 sam_ctx, res2[0], &domain_info->primary_domain,
2154 NT_STATUS_NOT_OK_RETURN(status);
2156 domain_info->trusted_domain_count = ret3 + 1;
2157 domain_info->trusted_domains = talloc_array(mem_ctx,
2158 struct netr_OneDomainInfo,
2159 domain_info->trusted_domain_count);
2160 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2162 for (i=0;i<ret3;i++) {
2163 status = fill_one_domain_info(mem_ctx,
2164 dce_call->conn->dce_ctx->lp_ctx,
2166 &domain_info->trusted_domains[i],
2168 NT_STATUS_NOT_OK_RETURN(status);
2171 status = fill_one_domain_info(mem_ctx,
2172 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2173 &domain_info->trusted_domains[i], true, true);
2174 NT_STATUS_NOT_OK_RETURN(status);
2176 /* Sets the supported encryption types */
2177 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2178 "msDS-SupportedEncryptionTypes",
2179 default_supported_enc_types);
2181 /* Other host domain information */
2183 lsa_policy_info = talloc(mem_ctx,
2184 struct netr_LsaPolicyInformation);
2185 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2186 ZERO_STRUCTP(lsa_policy_info);
2188 domain_info->lsa_policy = *lsa_policy_info;
2190 /* The DNS hostname is only returned back when there is a chance
2192 if ((r->in.query->workstation_info->workstation_flags
2193 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2194 domain_info->dns_hostname.string = old_dns_hostname;
2196 domain_info->dns_hostname.string = NULL;
2199 domain_info->workstation_flags =
2200 r->in.query->workstation_info->workstation_flags & (
2201 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2203 r->out.info->domain_info = domain_info;
2205 case 2: /* LSA policy information - not used at the moment */
2206 lsa_policy_info = talloc(mem_ctx,
2207 struct netr_LsaPolicyInformation);
2208 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2209 ZERO_STRUCTP(lsa_policy_info);
2211 r->out.info->lsa_policy_info = lsa_policy_info;
2214 return NT_STATUS_INVALID_LEVEL;
2218 return NT_STATUS_OK;
2223 netr_ServerPasswordGet
2225 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2226 struct netr_ServerPasswordGet *r)
2228 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2233 netr_NETRLOGONSENDTOSAM
2235 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2236 struct netr_NETRLOGONSENDTOSAM *r)
2238 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2243 netr_DsRGetDCNameEx2
2245 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2246 TALLOC_CTX *mem_ctx,
2247 struct netr_DsRGetDCNameEx2 *r)
2249 struct ldb_context *sam_ctx;
2250 struct netr_DsRGetDCNameInfo *info;
2251 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2252 const struct tsocket_address *local_address;
2253 char *local_addr = NULL;
2254 const struct tsocket_address *remote_address;
2255 char *remote_addr = NULL;
2256 const char *server_site_name;
2258 struct netlogon_samlogon_response response;
2260 const char *dc_name = NULL;
2261 const char *domain_name = NULL;
2264 ZERO_STRUCTP(r->out.info);
2266 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2267 dce_call->conn->auth_state.session_info, 0);
2268 if (sam_ctx == NULL) {
2269 return WERR_DS_UNAVAILABLE;
2272 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2273 if (tsocket_address_is_inet(local_address, "ip")) {
2274 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2275 W_ERROR_HAVE_NO_MEMORY(local_addr);
2278 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2279 if (tsocket_address_is_inet(remote_address, "ip")) {
2280 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2281 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2284 /* "server_unc" is ignored by w2k3 */
2286 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2287 return WERR_INVALID_FLAGS;
2290 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2291 r->in.flags & DS_PDC_REQUIRED &&
2292 r->in.flags & DS_KDC_REQUIRED) {
2293 return WERR_INVALID_FLAGS;
2295 if (r->in.flags & DS_IS_FLAT_NAME &&
2296 r->in.flags & DS_IS_DNS_NAME) {
2297 return WERR_INVALID_FLAGS;
2299 if (r->in.flags & DS_RETURN_DNS_NAME &&
2300 r->in.flags & DS_RETURN_FLAT_NAME) {
2301 return WERR_INVALID_FLAGS;
2303 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2304 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2305 return WERR_INVALID_FLAGS;
2308 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2310 (DS_DIRECTORY_SERVICE_REQUIRED |
2311 DS_DIRECTORY_SERVICE_PREFERRED |
2312 DS_GC_SERVER_REQUIRED |
2315 return WERR_INVALID_FLAGS;
2318 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2320 return WERR_INVALID_FLAGS;
2323 /* Proof server site parameter "site_name" if it was specified */
2324 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2325 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2326 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2327 server_site_name) != 0)) {
2328 return WERR_NO_SUCH_DOMAIN;
2331 guid_str = r->in.domain_guid != NULL ?
2332 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2334 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2338 r->in.client_account,
2339 r->in.mask, remote_addr,
2340 NETLOGON_NT_VERSION_5EX_WITH_IP,
2341 lp_ctx, &response, true);
2342 if (!NT_STATUS_IS_OK(status)) {
2343 return ntstatus_to_werror(status);
2347 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2348 * (O) flag when the returned forest name is in DNS format. This is here
2349 * always the case (see below).
2351 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2353 if (r->in.flags & DS_RETURN_DNS_NAME) {
2354 dc_name = response.data.nt5_ex.pdc_dns_name;
2355 domain_name = response.data.nt5_ex.dns_domain;
2357 * According to MS-NRPC 2.2.1.2.1 we should set the
2358 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2359 * the returned information is in DNS form.
2361 response.data.nt5_ex.server_type |=
2362 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2363 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2364 dc_name = response.data.nt5_ex.pdc_name;
2365 domain_name = response.data.nt5_ex.domain_name;
2369 * TODO: autodetect what we need to return
2370 * based on the given arguments
2372 dc_name = response.data.nt5_ex.pdc_name;
2373 domain_name = response.data.nt5_ex.domain_name;
2376 if (!dc_name || !dc_name[0]) {
2377 return WERR_NO_SUCH_DOMAIN;
2380 if (!domain_name || !domain_name[0]) {
2381 return WERR_NO_SUCH_DOMAIN;
2384 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2385 W_ERROR_HAVE_NO_MEMORY(info);
2386 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2387 dc_name[0] != '\\'? "\\\\":"",
2388 talloc_strdup(mem_ctx, dc_name));
2389 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2391 pdc_ip = local_addr;
2392 if (pdc_ip == NULL) {
2393 pdc_ip = "127.0.0.1";
2395 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2396 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2397 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2398 info->domain_guid = response.data.nt5_ex.domain_uuid;
2399 info->domain_name = domain_name;
2400 info->forest_name = response.data.nt5_ex.forest;
2401 info->dc_flags = response.data.nt5_ex.server_type;
2402 if (r->in.flags & DS_RETURN_DNS_NAME) {
2403 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2404 * returned if we are returning info->dc_unc containing a FQDN.
2405 * This attribute is called DomainControllerName in the specs,
2406 * it seems that we decide to return FQDN or netbios depending on
2407 * DS_RETURN_DNS_NAME.
2409 info->dc_flags |= DS_DNS_CONTROLLER;
2411 info->dc_site_name = response.data.nt5_ex.server_site;
2412 info->client_site_name = response.data.nt5_ex.client_site;
2414 *r->out.info = info;
2422 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2423 struct netr_DsRGetDCNameEx *r)
2425 struct netr_DsRGetDCNameEx2 r2;
2430 r2.in.server_unc = r->in.server_unc;
2431 r2.in.client_account = NULL;
2433 r2.in.domain_guid = r->in.domain_guid;
2434 r2.in.domain_name = r->in.domain_name;
2435 r2.in.site_name = r->in.site_name;
2436 r2.in.flags = r->in.flags;
2437 r2.out.info = r->out.info;
2439 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2447 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2448 struct netr_DsRGetDCName *r)
2450 struct netr_DsRGetDCNameEx2 r2;
2455 r2.in.server_unc = r->in.server_unc;
2456 r2.in.client_account = NULL;
2458 r2.in.domain_name = r->in.domain_name;
2459 r2.in.domain_guid = r->in.domain_guid;
2461 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2462 r2.in.flags = r->in.flags;
2463 r2.out.info = r->out.info;
2465 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2470 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2472 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2473 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2475 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2480 netr_NetrEnumerateTrustedDomainsEx
2482 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2483 struct netr_NetrEnumerateTrustedDomainsEx *r)
2485 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2490 netr_DsRAddressToSitenamesExW
2492 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2493 struct netr_DsRAddressToSitenamesExW *r)
2495 struct ldb_context *sam_ctx;
2496 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2497 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2498 sa_family_t sin_family;
2499 struct sockaddr_in *addr;
2501 struct sockaddr_in6 *addr6;
2502 char addr_str[INET6_ADDRSTRLEN];
2504 char addr_str[INET_ADDRSTRLEN];
2510 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2511 dce_call->conn->auth_state.session_info, 0);
2512 if (sam_ctx == NULL) {
2513 return WERR_DS_UNAVAILABLE;
2516 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2517 W_ERROR_HAVE_NO_MEMORY(ctr);
2521 ctr->count = r->in.count;
2522 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2523 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2524 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2525 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2527 for (i=0; i<ctr->count; i++) {
2528 ctr->sitename[i].string = NULL;
2529 ctr->subnetname[i].string = NULL;
2531 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2534 /* The first two byte of the buffer are reserved for the
2535 * "sin_family" but for now only the first one is used. */
2536 sin_family = r->in.addresses[i].buffer[0];
2538 switch (sin_family) {
2540 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2543 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2544 res = inet_ntop(AF_INET, &addr->sin_addr,
2545 addr_str, sizeof(addr_str));
2549 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2552 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2553 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2554 addr_str, sizeof(addr_str));
2565 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2569 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2570 ctr->subnetname[i].string = subnet_name;
2578 netr_DsRAddressToSitenamesW
2580 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2581 struct netr_DsRAddressToSitenamesW *r)
2583 struct netr_DsRAddressToSitenamesExW r2;
2584 struct netr_DsRAddressToSitenamesWCtr *ctr;
2590 r2.in.server_name = r->in.server_name;
2591 r2.in.count = r->in.count;
2592 r2.in.addresses = r->in.addresses;
2594 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2595 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2597 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2598 W_ERROR_HAVE_NO_MEMORY(ctr);
2602 ctr->count = r->in.count;
2603 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2604 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2606 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2608 for (i=0; i<ctr->count; i++) {
2609 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2617 netr_DsrGetDcSiteCoverageW
2619 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2620 struct netr_DsrGetDcSiteCoverageW *r)
2622 struct ldb_context *sam_ctx;
2623 struct DcSitesCtr *ctr;
2624 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2626 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2627 dce_call->conn->auth_state.session_info, 0);
2628 if (sam_ctx == NULL) {
2629 return WERR_DS_UNAVAILABLE;
2632 ctr = talloc(mem_ctx, struct DcSitesCtr);
2633 W_ERROR_HAVE_NO_MEMORY(ctr);
2637 /* For now only return our default site */
2639 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2640 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2641 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2642 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2648 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2649 struct ldb_context *sam_ctx,
2650 struct netr_DomainTrustList *trusts,
2651 uint32_t trust_flags)
2653 struct ldb_dn *system_dn;
2654 struct ldb_message **dom_res = NULL;
2655 const char *trust_attrs[] = { "flatname", "trustPartner",
2656 "securityIdentifier", "trustDirection",
2657 "trustType", "trustAttributes", NULL };
2662 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2663 NETR_TRUST_FLAG_OUTBOUND))) {
2664 return WERR_INVALID_FLAGS;
2667 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2668 ldb_get_default_basedn(sam_ctx),
2669 "(&(objectClass=container)(cn=System))");
2671 return WERR_GENERAL_FAILURE;
2674 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2675 &dom_res, trust_attrs,
2676 "(objectclass=trustedDomain)");
2678 for (i = 0; i < ret; i++) {
2679 unsigned int trust_dir;
2682 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2683 "trustDirection", 0);
2685 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2686 flags |= NETR_TRUST_FLAG_INBOUND;
2688 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2689 flags |= NETR_TRUST_FLAG_OUTBOUND;
2692 if (!(flags & trust_flags)) {
2693 /* this trust direction was not requested */
2698 trusts->array = talloc_realloc(trusts, trusts->array,
2699 struct netr_DomainTrust,
2701 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2703 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2704 if (!trusts->array[n].netbios_name) {
2705 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2706 "without flatname\n",
2707 ldb_dn_get_linearized(dom_res[i]->dn)));
2710 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2712 trusts->array[n].trust_flags = flags;
2713 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2714 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2715 /* TODO: find if we have parent in the list */
2716 trusts->array[n].parent_index = 0;
2719 trusts->array[n].trust_type =
2720 ldb_msg_find_attr_as_uint(dom_res[i],
2722 trusts->array[n].trust_attributes =
2723 ldb_msg_find_attr_as_uint(dom_res[i],
2724 "trustAttributes", 0);
2726 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2727 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2728 struct dom_sid zero_sid;
2729 ZERO_STRUCT(zero_sid);
2730 trusts->array[n].sid =
2731 dom_sid_dup(trusts, &zero_sid);
2733 trusts->array[n].sid =
2734 samdb_result_dom_sid(trusts, dom_res[i],
2735 "securityIdentifier");
2737 trusts->array[n].guid = GUID_zero();
2739 trusts->count = n + 1;
2742 talloc_free(dom_res);
2747 netr_DsrEnumerateDomainTrusts
2749 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2750 TALLOC_CTX *mem_ctx,
2751 struct netr_DsrEnumerateDomainTrusts *r)
2753 struct netr_DomainTrustList *trusts;
2754 struct ldb_context *sam_ctx;
2756 struct ldb_message **dom_res;
2757 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2758 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2759 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2763 if (r->in.trust_flags & 0xFFFFFE00) {
2764 return WERR_INVALID_FLAGS;
2767 /* TODO: turn to hard check once we are sure this is 100% correct */
2768 if (!r->in.server_name) {
2769 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2770 "But received NULL!\n", dnsdomain));
2772 p = strchr(r->in.server_name, '.');
2774 DEBUG(3, ("Invalid domain! Expected name in domain "
2775 "[%s]. But received [%s]!\n",
2776 dnsdomain, r->in.server_name));
2777 p = r->in.server_name;
2781 if (strcasecmp(p, dnsdomain)) {
2782 DEBUG(3, ("Invalid domain! Expected name in domain "
2783 "[%s]. But received [%s]!\n",
2784 dnsdomain, r->in.server_name));
2788 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2789 W_ERROR_HAVE_NO_MEMORY(trusts);
2792 r->out.trusts = trusts;
2794 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2795 dce_call->conn->auth_state.session_info, 0);
2796 if (sam_ctx == NULL) {
2797 return WERR_GENERAL_FAILURE;
2800 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2801 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2803 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2804 trusts, r->in.trust_flags);
2805 W_ERROR_NOT_OK_RETURN(werr);
2808 /* NOTE: we currently are always the root of the forest */
2809 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2810 uint32_t n = trusts->count;
2812 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2813 &dom_res, dom_attrs);
2815 return WERR_GENERAL_FAILURE;
2818 trusts->count = n + 1;
2819 trusts->array = talloc_realloc(trusts, trusts->array,
2820 struct netr_DomainTrust,
2822 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2824 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2825 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2826 trusts->array[n].trust_flags =
2827 NETR_TRUST_FLAG_NATIVE |
2828 NETR_TRUST_FLAG_TREEROOT |
2829 NETR_TRUST_FLAG_IN_FOREST |
2830 NETR_TRUST_FLAG_PRIMARY;
2831 /* we are always the root domain for now */
2832 trusts->array[n].parent_index = 0;
2833 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2834 trusts->array[n].trust_attributes = 0;
2835 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2838 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2840 talloc_free(dom_res);
2848 netr_DsrDeregisterDNSHostRecords
2850 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2851 struct netr_DsrDeregisterDNSHostRecords *r)
2853 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2857 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2858 struct netr_ServerGetTrustInfo *r);
2861 netr_ServerTrustPasswordsGet
2863 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2864 struct netr_ServerTrustPasswordsGet *r)
2866 struct netr_ServerGetTrustInfo r2 = {};
2867 struct netr_TrustInfo *_ti = NULL;
2870 r2.in.server_name = r->in.server_name;
2871 r2.in.account_name = r->in.account_name;
2872 r2.in.secure_channel_type = r->in.secure_channel_type;
2873 r2.in.computer_name = r->in.computer_name;
2874 r2.in.credential = r->in.credential;
2876 r2.out.return_authenticator = r->out.return_authenticator;
2877 r2.out.new_owf_password = r->out.new_owf_password;
2878 r2.out.old_owf_password = r->out.old_owf_password;
2879 r2.out.trust_info = &_ti;
2881 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
2883 r->out.return_authenticator = r2.out.return_authenticator;
2884 r->out.new_owf_password = r2.out.new_owf_password;
2885 r->out.old_owf_password = r2.out.old_owf_password;
2891 netr_DsRGetForestTrustInformation
2893 struct dcesrv_netr_DsRGetForestTrustInformation_state {
2894 struct dcesrv_call_state *dce_call;
2895 TALLOC_CTX *mem_ctx;
2896 struct netr_DsRGetForestTrustInformation *r;
2899 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
2901 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2902 TALLOC_CTX *mem_ctx,
2903 struct netr_DsRGetForestTrustInformation *r)
2905 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2906 struct dcesrv_connection *conn = dce_call->conn;
2907 struct auth_session_info *session_info = conn->auth_state.session_info;
2908 enum security_user_level security_level;
2909 struct ldb_context *sam_ctx = NULL;
2910 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
2911 struct dcerpc_binding_handle *irpc_handle = NULL;
2912 struct tevent_req *subreq = NULL;
2913 struct ldb_dn *domain_dn = NULL;
2914 struct ldb_dn *forest_dn = NULL;
2918 security_level = security_session_user_level(session_info, NULL);
2919 if (security_level < SECURITY_USER) {
2920 return WERR_ACCESS_DENIED;
2923 if (r->in.flags & 0xFFFFFFFE) {
2924 return WERR_INVALID_FLAGS;
2927 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2928 dce_call->conn->auth_state.session_info, 0);
2929 if (sam_ctx == NULL) {
2930 return WERR_GENERAL_FAILURE;
2933 domain_dn = ldb_get_default_basedn(sam_ctx);
2934 if (domain_dn == NULL) {
2935 return WERR_GENERAL_FAILURE;
2938 forest_dn = ldb_get_root_basedn(sam_ctx);
2939 if (forest_dn == NULL) {
2940 return WERR_GENERAL_FAILURE;
2943 cmp = ldb_dn_compare(domain_dn, forest_dn);
2945 return WERR_NERR_ACFNOTLOADED;
2948 forest_level = dsdb_forest_functional_level(sam_ctx);
2949 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
2950 return WERR_INVALID_FUNCTION;
2953 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2954 if (!samdb_is_pdc(sam_ctx)) {
2955 return WERR_NERR_NOTPRIMARY;
2958 if (r->in.trusted_domain_name == NULL) {
2959 return WERR_INVALID_FLAGS;
2963 if (r->in.trusted_domain_name == NULL) {
2967 * information about our own domain
2969 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
2970 r->out.forest_trust_info);
2971 if (!NT_STATUS_IS_OK(status)) {
2972 return ntstatus_to_werror(status);
2979 * Forward the request to winbindd
2982 state = talloc_zero(mem_ctx,
2983 struct dcesrv_netr_DsRGetForestTrustInformation_state);
2984 if (state == NULL) {
2987 state->dce_call = dce_call;
2988 state->mem_ctx = mem_ctx;
2991 irpc_handle = irpc_binding_handle_by_name(state,
2992 state->dce_call->msg_ctx,
2994 &ndr_table_winbind);
2995 if (irpc_handle == NULL) {
2996 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2997 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2998 return WERR_SERVICE_NOT_FOUND;
3002 * 60 seconds timeout should be enough
3004 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3006 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3007 state->dce_call->event_ctx,
3009 r->in.trusted_domain_name,
3011 r->out.forest_trust_info);
3012 if (subreq == NULL) {
3015 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3016 tevent_req_set_callback(subreq,
3017 dcesrv_netr_DsRGetForestTrustInformation_done,
3023 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3025 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3026 tevent_req_callback_data(subreq,
3027 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3030 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3032 &state->r->out.result);
3033 TALLOC_FREE(subreq);
3034 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3035 state->r->out.result = WERR_TIMEOUT;
3036 } else if (!NT_STATUS_IS_OK(status)) {
3037 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3038 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3039 nt_errstr(status)));
3042 status = dcesrv_reply(state->dce_call);
3043 if (!NT_STATUS_IS_OK(status)) {
3044 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3049 netr_GetForestTrustInformation
3051 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3052 TALLOC_CTX *mem_ctx,
3053 struct netr_GetForestTrustInformation *r)
3055 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3056 struct netlogon_creds_CredentialState *creds = NULL;
3057 struct ldb_context *sam_ctx = NULL;
3058 struct ldb_dn *domain_dn = NULL;
3059 struct ldb_dn *forest_dn = NULL;
3064 status = dcesrv_netr_creds_server_step_check(dce_call,
3066 r->in.computer_name,
3068 r->out.return_authenticator,
3070 if (!NT_STATUS_IS_OK(status)) {
3074 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3075 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3076 return NT_STATUS_NOT_IMPLEMENTED;
3079 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3080 dce_call->conn->auth_state.session_info, 0);
3081 if (sam_ctx == NULL) {
3082 return NT_STATUS_INTERNAL_ERROR;
3085 /* TODO: check r->in.server_name is our name */
3087 domain_dn = ldb_get_default_basedn(sam_ctx);
3088 if (domain_dn == NULL) {
3089 return NT_STATUS_INTERNAL_ERROR;
3092 forest_dn = ldb_get_root_basedn(sam_ctx);
3093 if (forest_dn == NULL) {
3094 return NT_STATUS_INTERNAL_ERROR;
3097 cmp = ldb_dn_compare(domain_dn, forest_dn);
3099 return NT_STATUS_INVALID_DOMAIN_STATE;
3102 forest_level = dsdb_forest_functional_level(sam_ctx);
3103 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3104 return NT_STATUS_INVALID_DOMAIN_STATE;
3107 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3108 r->out.forest_trust_info);
3109 if (!NT_STATUS_IS_OK(status)) {
3113 return NT_STATUS_OK;
3118 netr_ServerGetTrustInfo
3120 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3121 struct netr_ServerGetTrustInfo *r)
3123 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3124 struct netlogon_creds_CredentialState *creds = NULL;
3125 struct ldb_context *sam_ctx = NULL;
3126 const char * const attrs[] = {
3129 "userAccountControl",
3132 struct ldb_message **res = NULL;
3133 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3136 const char *asid = NULL;
3138 const char *aname = NULL;
3139 struct ldb_message *tdo_msg = NULL;
3140 const char * const tdo_attrs[] = {
3141 "trustAuthIncoming",
3145 struct netr_TrustInfo *trust_info = NULL;
3147 ZERO_STRUCTP(r->out.new_owf_password);
3148 ZERO_STRUCTP(r->out.old_owf_password);
3150 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3152 r->in.computer_name,
3154 r->out.return_authenticator,
3156 if (!NT_STATUS_IS_OK(nt_status)) {
3160 /* TODO: check r->in.server_name is our name */
3162 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3163 return NT_STATUS_INVALID_PARAMETER;
3166 if (r->in.secure_channel_type != creds->secure_channel_type) {
3167 return NT_STATUS_INVALID_PARAMETER;
3170 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3171 return NT_STATUS_INVALID_PARAMETER;
3174 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3175 lp_ctx, system_session(lp_ctx), 0);
3176 if (sam_ctx == NULL) {
3177 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3180 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3182 return NT_STATUS_NO_MEMORY;
3185 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3186 "(&(objectClass=user)(objectSid=%s))",
3189 return NT_STATUS_ACCOUNT_DISABLED;
3192 switch (creds->secure_channel_type) {
3193 case SEC_CHAN_DNS_DOMAIN:
3194 case SEC_CHAN_DOMAIN:
3195 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3197 if (uac & UF_ACCOUNTDISABLE) {
3198 return NT_STATUS_ACCOUNT_DISABLED;
3201 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3202 return NT_STATUS_ACCOUNT_DISABLED;
3205 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3206 if (aname == NULL) {
3207 return NT_STATUS_ACCOUNT_DISABLED;
3210 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3211 SEC_CHAN_DOMAIN, aname,
3212 tdo_attrs, mem_ctx, &tdo_msg);
3213 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3214 return NT_STATUS_ACCOUNT_DISABLED;
3216 if (!NT_STATUS_IS_OK(nt_status)) {
3220 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3223 if (!NT_STATUS_IS_OK(nt_status)) {
3227 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3228 if (trust_info == NULL) {
3229 return NT_STATUS_NO_MEMORY;
3232 trust_info->count = 1;
3233 trust_info->data = talloc_array(trust_info, uint32_t,
3235 if (trust_info->data == NULL) {
3236 return NT_STATUS_NO_MEMORY;
3239 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3245 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3248 if (!NT_STATUS_IS_OK(nt_status)) {
3252 prevNtHash = talloc(mem_ctx, struct samr_Password);
3253 if (prevNtHash == NULL) {
3254 return NT_STATUS_NO_MEMORY;
3257 E_md4hash("", prevNtHash->hash);
3261 if (curNtHash != NULL) {
3262 *r->out.new_owf_password = *curNtHash;
3263 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3265 if (prevNtHash != NULL) {
3266 *r->out.old_owf_password = *prevNtHash;
3267 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3270 if (trust_info != NULL) {
3271 *r->out.trust_info = trust_info;
3274 return NT_STATUS_OK;
3280 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3281 struct netr_Unused47 *r)
3283 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3287 struct netr_dnsupdate_RODC_state {
3288 struct dcesrv_call_state *dce_call;
3289 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3290 struct dnsupdate_RODC *r2;
3294 called when the forwarded RODC dns update request is finished
3296 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3298 struct netr_dnsupdate_RODC_state *st =
3299 tevent_req_callback_data(subreq,
3300 struct netr_dnsupdate_RODC_state);
3303 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3304 TALLOC_FREE(subreq);
3305 if (!NT_STATUS_IS_OK(status)) {
3306 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3307 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3310 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3312 status = dcesrv_reply(st->dce_call);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3319 netr_DsrUpdateReadOnlyServerDnsRecords
3321 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3322 TALLOC_CTX *mem_ctx,
3323 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3325 struct netlogon_creds_CredentialState *creds;
3327 struct dcerpc_binding_handle *binding_handle;
3328 struct netr_dnsupdate_RODC_state *st;
3329 struct tevent_req *subreq;
3331 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3333 r->in.computer_name,
3335 r->out.return_authenticator,
3337 NT_STATUS_NOT_OK_RETURN(nt_status);
3339 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3340 return NT_STATUS_ACCESS_DENIED;
3343 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3344 NT_STATUS_HAVE_NO_MEMORY(st);
3346 st->dce_call = dce_call;
3348 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3349 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3351 st->r2->in.dom_sid = creds->sid;
3352 st->r2->in.site_name = r->in.site_name;
3353 st->r2->in.dns_ttl = r->in.dns_ttl;
3354 st->r2->in.dns_names = r->in.dns_names;
3355 st->r2->out.dns_names = r->out.dns_names;
3357 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3358 "dnsupdate", &ndr_table_irpc);
3359 if (binding_handle == NULL) {
3360 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3361 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3362 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3365 /* forward the call */
3366 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3367 binding_handle, st->r2);
3368 NT_STATUS_HAVE_NO_MEMORY(subreq);
3370 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3372 /* setup the callback */
3373 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3375 return NT_STATUS_OK;
3379 /* include the generated boilerplate */
3380 #include "librpc/gen_ndr/ndr_netlogon_s.c"