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_SamInfo2 *sam2 = NULL;
845 struct netr_SamInfo3 *sam3 = NULL;
846 struct netr_SamInfo6 *sam6 = NULL;
848 *r->out.authoritative = 1;
850 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
851 NT_STATUS_HAVE_NO_MEMORY(user_info);
853 netlogon_creds_decrypt_samlogon_logon(creds,
857 switch (r->in.logon_level) {
858 case NetlogonInteractiveInformation:
859 case NetlogonServiceInformation:
860 case NetlogonInteractiveTransitiveInformation:
861 case NetlogonServiceTransitiveInformation:
863 /* TODO: we need to deny anonymous access here */
864 nt_status = auth_context_create(mem_ctx,
865 dce_call->event_ctx, dce_call->msg_ctx,
866 dce_call->conn->dce_ctx->lp_ctx,
868 NT_STATUS_NOT_OK_RETURN(nt_status);
870 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
871 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
872 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
873 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
875 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
876 user_info->password_state = AUTH_PASSWORD_HASH;
878 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
879 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
880 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
882 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
883 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
884 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
887 case NetlogonNetworkInformation:
888 case NetlogonNetworkTransitiveInformation:
890 /* TODO: we need to deny anonymous access here */
891 nt_status = auth_context_create(mem_ctx,
892 dce_call->event_ctx, dce_call->msg_ctx,
893 dce_call->conn->dce_ctx->lp_ctx,
895 NT_STATUS_NOT_OK_RETURN(nt_status);
897 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
898 NT_STATUS_NOT_OK_RETURN(nt_status);
900 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
901 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
902 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
903 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
905 user_info->password_state = AUTH_PASSWORD_RESPONSE;
906 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
907 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
909 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
910 user_info->client.account_name,
911 user_info->client.domain_name,
912 user_info->password.response.nt,
914 NT_STATUS_NOT_OK_RETURN(nt_status);
919 case NetlogonGenericInformation:
921 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
923 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
926 /* Using DES to verify kerberos tickets makes no sense */
927 return NT_STATUS_INVALID_PARAMETER;
930 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
932 struct dcerpc_binding_handle *irpc_handle;
933 struct kdc_check_generic_kerberos check;
934 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
935 NT_STATUS_HAVE_NO_MEMORY(generic);
936 *r->out.authoritative = 1;
938 /* TODO: Describe and deal with these flags */
941 r->out.validation->generic = generic;
943 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
947 if (irpc_handle == NULL) {
948 return NT_STATUS_NO_LOGON_SERVERS;
951 check.in.generic_request =
952 data_blob_const(r->in.logon->generic->data,
953 r->in.logon->generic->length);
956 * TODO: make this async and avoid
957 * dcerpc_binding_handle_set_sync_ev()
959 dcerpc_binding_handle_set_sync_ev(irpc_handle,
960 dce_call->event_ctx);
961 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
964 if (!NT_STATUS_IS_OK(status)) {
967 generic->length = check.out.generic_reply.length;
968 generic->data = check.out.generic_reply.data;
972 /* Until we get an implemetnation of these other packages */
973 return NT_STATUS_INVALID_PARAMETER;
976 return NT_STATUS_INVALID_PARAMETER;
979 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
980 /* TODO: set *r->out.authoritative = 0 on specific errors */
981 NT_STATUS_NOT_OK_RETURN(nt_status);
983 switch (r->in.validation_level) {
985 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
988 NT_STATUS_NOT_OK_RETURN(nt_status);
990 r->out.validation->sam2 = sam2;
994 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
997 NT_STATUS_NOT_OK_RETURN(nt_status);
999 r->out.validation->sam3 = sam3;
1003 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
1004 return NT_STATUS_INVALID_PARAMETER;
1007 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1010 NT_STATUS_NOT_OK_RETURN(nt_status);
1012 r->out.validation->sam6 = sam6;
1016 return NT_STATUS_INVALID_INFO_CLASS;
1019 netlogon_creds_encrypt_samlogon_validation(creds,
1020 r->in.validation_level,
1023 /* TODO: Describe and deal with these flags */
1026 return NT_STATUS_OK;
1029 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1030 struct netr_LogonSamLogonEx *r)
1033 struct netlogon_creds_CredentialState *creds;
1035 *r->out.authoritative = 1;
1037 nt_status = dcesrv_netr_LogonSamLogon_check(r);
1038 if (!NT_STATUS_IS_OK(nt_status)) {
1042 nt_status = schannel_get_creds_state(mem_ctx,
1043 dce_call->conn->dce_ctx->lp_ctx,
1044 r->in.computer_name, &creds);
1045 if (!NT_STATUS_IS_OK(nt_status)) {
1049 if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1050 return NT_STATUS_ACCESS_DENIED;
1052 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1056 netr_LogonSamLogonWithFlags
1059 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1060 struct netr_LogonSamLogonWithFlags *r)
1063 struct netlogon_creds_CredentialState *creds;
1064 struct netr_LogonSamLogonEx r2;
1066 struct netr_Authenticator *return_authenticator;
1070 r2.in.server_name = r->in.server_name;
1071 r2.in.computer_name = r->in.computer_name;
1072 r2.in.logon_level = r->in.logon_level;
1073 r2.in.logon = r->in.logon;
1074 r2.in.validation_level = r->in.validation_level;
1075 r2.in.flags = r->in.flags;
1076 r2.out.validation = r->out.validation;
1077 r2.out.authoritative = r->out.authoritative;
1078 r2.out.flags = r->out.flags;
1080 *r->out.authoritative = 1;
1082 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1083 if (!NT_STATUS_IS_OK(nt_status)) {
1087 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1088 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1090 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1092 r->in.computer_name,
1093 r->in.credential, return_authenticator,
1095 NT_STATUS_NOT_OK_RETURN(nt_status);
1097 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1099 r->out.return_authenticator = return_authenticator;
1107 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1108 struct netr_LogonSamLogon *r)
1110 struct netr_LogonSamLogonWithFlags r2;
1116 r2.in.server_name = r->in.server_name;
1117 r2.in.computer_name = r->in.computer_name;
1118 r2.in.credential = r->in.credential;
1119 r2.in.return_authenticator = r->in.return_authenticator;
1120 r2.in.logon_level = r->in.logon_level;
1121 r2.in.logon = r->in.logon;
1122 r2.in.validation_level = r->in.validation_level;
1123 r2.in.flags = &flags;
1124 r2.out.validation = r->out.validation;
1125 r2.out.authoritative = r->out.authoritative;
1126 r2.out.flags = &flags;
1128 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1130 r->out.return_authenticator = r2.out.return_authenticator;
1139 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1140 struct netr_LogonSamLogoff *r)
1142 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1150 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1151 struct netr_DatabaseDeltas *r)
1153 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1160 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1161 struct netr_DatabaseSync2 *r)
1163 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1164 return NT_STATUS_NOT_IMPLEMENTED;
1171 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1172 struct netr_DatabaseSync *r)
1174 struct netr_DatabaseSync2 r2;
1179 r2.in.logon_server = r->in.logon_server;
1180 r2.in.computername = r->in.computername;
1181 r2.in.credential = r->in.credential;
1182 r2.in.database_id = r->in.database_id;
1183 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1184 r2.in.sync_context = r->in.sync_context;
1185 r2.out.sync_context = r->out.sync_context;
1186 r2.out.delta_enum_array = r->out.delta_enum_array;
1187 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1189 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1198 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1199 struct netr_AccountDeltas *r)
1201 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1202 return NT_STATUS_NOT_IMPLEMENTED;
1209 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1210 struct netr_AccountSync *r)
1212 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1213 return NT_STATUS_NOT_IMPLEMENTED;
1220 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1221 struct netr_GetDcName *r)
1223 const char * const attrs[] = { NULL };
1224 struct ldb_context *sam_ctx;
1225 struct ldb_message **res;
1226 struct ldb_dn *domain_dn;
1231 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1232 * that the domainname needs to be a valid netbios domain
1233 * name, if it is not NULL.
1235 if (r->in.domainname) {
1236 const char *dot = strchr(r->in.domainname, '.');
1237 size_t len = strlen(r->in.domainname);
1239 if (dot || len > 15) {
1240 return WERR_DCNOTFOUND;
1244 * TODO: Should we also varify that only valid
1245 * netbios name characters are used?
1249 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1250 dce_call->conn->dce_ctx->lp_ctx,
1251 dce_call->conn->auth_state.session_info, 0);
1252 if (sam_ctx == NULL) {
1253 return WERR_DS_UNAVAILABLE;
1256 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1258 if (domain_dn == NULL) {
1259 return WERR_NO_SUCH_DOMAIN;
1262 ret = gendb_search_dn(sam_ctx, mem_ctx,
1263 domain_dn, &res, attrs);
1265 return WERR_NO_SUCH_DOMAIN;
1268 /* TODO: - return real IP address
1269 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1271 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1272 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1273 W_ERROR_HAVE_NO_MEMORY(dcname);
1275 *r->out.dcname = dcname;
1279 struct dcesrv_netr_LogonControl_base_state {
1280 struct dcesrv_call_state *dce_call;
1282 TALLOC_CTX *mem_ctx;
1284 struct netr_LogonControl2Ex r;
1287 struct netr_LogonControl *l;
1288 struct netr_LogonControl2 *l2;
1289 struct netr_LogonControl2Ex *l2ex;
1293 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1295 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1297 struct dcesrv_connection *conn = state->dce_call->conn;
1298 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1299 struct auth_session_info *session_info = conn->auth_state.session_info;
1300 enum security_user_level security_level;
1301 struct dcerpc_binding_handle *irpc_handle;
1302 struct tevent_req *subreq;
1305 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1307 if (state->_r.l != NULL) {
1311 if (state->r.in.level == 0x00000002) {
1312 return WERR_NOT_SUPPORTED;
1313 } else if (state->r.in.level != 0x00000001) {
1314 return WERR_INVALID_LEVEL;
1317 switch (state->r.in.function_code) {
1318 case NETLOGON_CONTROL_QUERY:
1319 case NETLOGON_CONTROL_REPLICATE:
1320 case NETLOGON_CONTROL_SYNCHRONIZE:
1321 case NETLOGON_CONTROL_PDC_REPLICATE:
1322 case NETLOGON_CONTROL_BREAKPOINT:
1323 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1324 case NETLOGON_CONTROL_TRUNCATE_LOG:
1327 return WERR_NOT_SUPPORTED;
1331 if (state->r.in.level < 0x00000001) {
1332 return WERR_INVALID_LEVEL;
1335 if (state->r.in.level > 0x00000004) {
1336 return WERR_INVALID_LEVEL;
1339 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1340 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1341 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1343 switch (state->r.in.level) {
1345 info1 = talloc_zero(state->mem_ctx,
1346 struct netr_NETLOGON_INFO_1);
1347 if (info1 == NULL) {
1350 state->r.out.query->info1 = info1;
1354 info3 = talloc_zero(state->mem_ctx,
1355 struct netr_NETLOGON_INFO_3);
1356 if (info3 == NULL) {
1359 state->r.out.query->info3 = info3;
1363 return WERR_INVALID_PARAMETER;
1368 * Some validations are done before the access check
1369 * and some after the access check
1371 security_level = security_session_user_level(session_info, NULL);
1372 if (security_level < SECURITY_ADMINISTRATOR) {
1373 return WERR_ACCESS_DENIED;
1376 if (state->_r.l2 != NULL) {
1378 * netr_LogonControl2
1380 if (state->r.in.level == 0x00000004) {
1381 return WERR_INVALID_LEVEL;
1385 switch (state->r.in.level) {
1390 switch (state->r.in.function_code) {
1391 case NETLOGON_CONTROL_REDISCOVER:
1392 case NETLOGON_CONTROL_TC_QUERY:
1393 case NETLOGON_CONTROL_TC_VERIFY:
1396 return WERR_INVALID_PARAMETER;
1405 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1406 return WERR_INVALID_PARAMETER;
1412 return WERR_INVALID_LEVEL;
1415 switch (state->r.in.function_code) {
1416 case NETLOGON_CONTROL_REDISCOVER:
1417 case NETLOGON_CONTROL_TC_QUERY:
1418 case NETLOGON_CONTROL_TC_VERIFY:
1419 if (state->r.in.level != 2) {
1420 return WERR_INVALID_PARAMETER;
1423 if (state->r.in.data == NULL) {
1424 return WERR_INVALID_PARAMETER;
1427 if (state->r.in.data->domain == NULL) {
1428 return WERR_INVALID_PARAMETER;
1433 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1434 if (state->r.in.level != 1) {
1435 return WERR_INVALID_PARAMETER;
1438 if (state->r.in.data == NULL) {
1439 return WERR_INVALID_PARAMETER;
1442 if (state->r.in.data->domain == NULL) {
1443 return WERR_INVALID_PARAMETER;
1446 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1447 state->r.in.data->domain);
1449 struct ldb_context *sam_ctx;
1451 sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1452 lp_ctx, system_session(lp_ctx), 0);
1453 if (sam_ctx == NULL) {
1454 return WERR_DS_UNAVAILABLE;
1458 * Secrets for trusted domains can only be triggered on
1461 ok = samdb_is_pdc(sam_ctx);
1462 TALLOC_FREE(sam_ctx);
1464 return WERR_INVALID_DOMAIN_ROLE;
1470 return WERR_NOT_SUPPORTED;
1473 irpc_handle = irpc_binding_handle_by_name(state,
1474 state->dce_call->msg_ctx,
1476 &ndr_table_winbind);
1477 if (irpc_handle == NULL) {
1478 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1479 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1480 return WERR_SERVICE_NOT_FOUND;
1484 * 60 seconds timeout should be enough
1486 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1488 subreq = dcerpc_winbind_LogonControl_send(state,
1489 state->dce_call->event_ctx,
1491 state->r.in.function_code,
1494 state->r.out.query);
1495 if (subreq == NULL) {
1498 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1499 tevent_req_set_callback(subreq,
1500 dcesrv_netr_LogonControl_base_done,
1506 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1508 struct dcesrv_netr_LogonControl_base_state *state =
1509 tevent_req_callback_data(subreq,
1510 struct dcesrv_netr_LogonControl_base_state);
1513 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1514 &state->r.out.result);
1515 TALLOC_FREE(subreq);
1516 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1517 state->r.out.result = WERR_TIMEOUT;
1518 } else if (!NT_STATUS_IS_OK(status)) {
1519 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1520 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1521 nt_errstr(status)));
1524 if (state->_r.l2ex != NULL) {
1525 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1526 r->out.result = state->r.out.result;
1527 } else if (state->_r.l2 != NULL) {
1528 struct netr_LogonControl2 *r = state->_r.l2;
1529 r->out.result = state->r.out.result;
1530 } else if (state->_r.l != NULL) {
1531 struct netr_LogonControl *r = state->_r.l;
1532 r->out.result = state->r.out.result;
1535 status = dcesrv_reply(state->dce_call);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1544 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1545 struct netr_LogonControl *r)
1547 struct dcesrv_netr_LogonControl_base_state *state;
1550 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1551 if (state == NULL) {
1555 state->dce_call = dce_call;
1556 state->mem_ctx = mem_ctx;
1558 state->r.in.logon_server = r->in.logon_server;
1559 state->r.in.function_code = r->in.function_code;
1560 state->r.in.level = r->in.level;
1561 state->r.in.data = NULL;
1562 state->r.out.query = r->out.query;
1566 werr = dcesrv_netr_LogonControl_base_call(state);
1568 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1578 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1579 struct netr_LogonControl2 *r)
1581 struct dcesrv_netr_LogonControl_base_state *state;
1584 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1585 if (state == NULL) {
1589 state->dce_call = dce_call;
1590 state->mem_ctx = mem_ctx;
1592 state->r.in.logon_server = r->in.logon_server;
1593 state->r.in.function_code = r->in.function_code;
1594 state->r.in.level = r->in.level;
1595 state->r.in.data = r->in.data;
1596 state->r.out.query = r->out.query;
1600 werr = dcesrv_netr_LogonControl_base_call(state);
1602 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1610 netr_LogonControl2Ex
1612 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1613 struct netr_LogonControl2Ex *r)
1615 struct dcesrv_netr_LogonControl_base_state *state;
1618 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1619 if (state == NULL) {
1623 state->dce_call = dce_call;
1624 state->mem_ctx = mem_ctx;
1629 werr = dcesrv_netr_LogonControl_base_call(state);
1631 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1638 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1639 struct ldb_context *sam_ctx,
1640 struct netr_DomainTrustList *trusts,
1641 uint32_t trust_flags);
1646 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1647 struct netr_GetAnyDCName *r)
1649 struct netr_DomainTrustList *trusts;
1650 struct ldb_context *sam_ctx;
1651 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1655 *r->out.dcname = NULL;
1657 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1658 /* if the domainname parameter wasn't set assume our domain */
1659 r->in.domainname = lpcfg_workgroup(lp_ctx);
1662 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1663 dce_call->conn->auth_state.session_info, 0);
1664 if (sam_ctx == NULL) {
1665 return WERR_DS_UNAVAILABLE;
1668 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1669 /* well we asked for a DC of our own domain */
1670 if (samdb_is_pdc(sam_ctx)) {
1671 /* we are the PDC of the specified domain */
1672 return WERR_NO_SUCH_DOMAIN;
1675 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1676 lpcfg_netbios_name(lp_ctx));
1677 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1682 /* Okay, now we have to consider the trusted domains */
1684 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1685 W_ERROR_HAVE_NO_MEMORY(trusts);
1689 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1690 NETR_TRUST_FLAG_INBOUND
1691 | NETR_TRUST_FLAG_OUTBOUND);
1692 W_ERROR_NOT_OK_RETURN(werr);
1694 for (i = 0; i < trusts->count; i++) {
1695 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1696 /* FIXME: Here we need to find a DC for the specified
1697 * trusted domain. */
1699 /* return WERR_OK; */
1700 return WERR_NO_SUCH_DOMAIN;
1704 return WERR_NO_SUCH_DOMAIN;
1711 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1712 struct netr_DatabaseRedo *r)
1714 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1719 netr_NetrEnumerateTrustedDomains
1721 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1722 struct netr_NetrEnumerateTrustedDomains *r)
1724 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1729 netr_LogonGetCapabilities
1731 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1732 struct netr_LogonGetCapabilities *r)
1734 struct netlogon_creds_CredentialState *creds;
1737 status = dcesrv_netr_creds_server_step_check(dce_call,
1739 r->in.computer_name,
1741 r->out.return_authenticator,
1743 if (!NT_STATUS_IS_OK(status)) {
1744 DEBUG(0,(__location__ " Bad credentials - error\n"));
1746 NT_STATUS_NOT_OK_RETURN(status);
1748 if (r->in.query_level != 1) {
1749 return NT_STATUS_NOT_SUPPORTED;
1752 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1754 return NT_STATUS_OK;
1759 netr_NETRLOGONSETSERVICEBITS
1761 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1762 struct netr_NETRLOGONSETSERVICEBITS *r)
1764 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1769 netr_LogonGetTrustRid
1771 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1772 struct netr_LogonGetTrustRid *r)
1774 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1779 netr_NETRLOGONCOMPUTESERVERDIGEST
1781 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1782 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1784 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1789 netr_NETRLOGONCOMPUTECLIENTDIGEST
1791 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1792 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1794 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1802 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1803 struct netr_DsRGetSiteName *r)
1805 struct ldb_context *sam_ctx;
1806 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1808 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1809 dce_call->conn->auth_state.session_info, 0);
1810 if (sam_ctx == NULL) {
1811 return WERR_DS_UNAVAILABLE;
1815 * We assume to be a DC when we get called over NETLOGON. Hence we
1816 * get our site name always by using "samdb_server_site_name()"
1817 * and not "samdb_client_site_name()".
1819 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1820 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1827 fill in a netr_OneDomainInfo from a ldb search result
1829 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1830 struct loadparm_context *lp_ctx,
1831 struct ldb_context *sam_ctx,
1832 struct ldb_message *res,
1833 struct netr_OneDomainInfo *info,
1834 bool is_local, bool is_trust_list)
1838 if (is_trust_list) {
1839 /* w2k8 only fills this on trusted domains */
1840 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1841 info->trust_extension.length = 16;
1842 info->trust_extension.info->flags =
1843 NETR_TRUST_FLAG_TREEROOT |
1844 NETR_TRUST_FLAG_IN_FOREST |
1845 NETR_TRUST_FLAG_PRIMARY |
1846 NETR_TRUST_FLAG_NATIVE;
1848 info->trust_extension.info->parent_index = 0; /* should be index into array
1850 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1851 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1854 if (is_trust_list) {
1855 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1856 info->dns_forestname.string = NULL;
1858 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1859 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1860 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1861 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1865 info->domainname.string = lpcfg_workgroup(lp_ctx);
1866 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1867 info->domain_guid = samdb_result_guid(res, "objectGUID");
1868 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1870 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1871 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1872 info->domain_guid = samdb_result_guid(res, "objectGUID");
1873 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1875 if (!is_trust_list) {
1876 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1879 return NT_STATUS_OK;
1883 netr_LogonGetDomainInfo
1884 this is called as part of the ADS domain logon procedure.
1886 It has an important role in convaying details about the client, such
1887 as Operating System, Version, Service Pack etc.
1889 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1890 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1892 struct netlogon_creds_CredentialState *creds;
1893 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1894 "securityIdentifier", "trustPartner", NULL };
1895 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1896 "msDS-SupportedEncryptionTypes", NULL };
1897 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1898 struct ldb_context *sam_ctx;
1899 struct ldb_message **res1, **res2, **res3, *new_msg;
1900 struct ldb_dn *workstation_dn;
1901 struct netr_DomainInformation *domain_info;
1902 struct netr_LsaPolicyInformation *lsa_policy_info;
1903 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1904 bool update_dns_hostname = true;
1908 status = dcesrv_netr_creds_server_step_check(dce_call,
1910 r->in.computer_name,
1912 r->out.return_authenticator,
1914 if (!NT_STATUS_IS_OK(status)) {
1915 DEBUG(0,(__location__ " Bad credentials - error\n"));
1917 NT_STATUS_NOT_OK_RETURN(status);
1919 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1920 dce_call->conn->dce_ctx->lp_ctx,
1921 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1922 if (sam_ctx == NULL) {
1923 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1926 switch (r->in.level) {
1927 case 1: /* Domain information */
1929 if (r->in.query->workstation_info == NULL) {
1930 return NT_STATUS_INVALID_PARAMETER;
1933 /* Prepares the workstation DN */
1934 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1935 dom_sid_string(mem_ctx, creds->sid));
1936 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1938 /* Lookup for attributes in workstation object */
1939 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1942 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1945 /* Gets the sam account name which is checked against the DNS
1946 * hostname parameter. */
1947 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1950 if (sam_account_name == NULL) {
1951 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1955 * Checks that the sam account name without a possible "$"
1956 * matches as prefix with the DNS hostname in the workstation
1959 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1960 strcspn(sam_account_name, "$"));
1961 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1962 if (r->in.query->workstation_info->dns_hostname != NULL) {
1963 prefix2 = talloc_strndup(mem_ctx,
1964 r->in.query->workstation_info->dns_hostname,
1965 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1966 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1968 if (strcasecmp(prefix1, prefix2) != 0) {
1969 update_dns_hostname = false;
1972 update_dns_hostname = false;
1975 /* Gets the old DNS hostname */
1976 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1981 * Updates the DNS hostname when the client wishes that the
1982 * server should handle this for him
1983 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1984 * obviously only checked when we do already have a
1986 * See MS-NRPC section 3.5.4.3.9
1988 if ((old_dns_hostname != NULL) &&
1989 (r->in.query->workstation_info->workstation_flags
1990 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1991 update_dns_hostname = false;
1994 /* Gets host information and put them into our directory */
1996 new_msg = ldb_msg_new(mem_ctx);
1997 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1999 new_msg->dn = workstation_dn;
2001 /* Sets the OS name */
2003 if (r->in.query->workstation_info->os_name.string == NULL) {
2004 return NT_STATUS_INVALID_PARAMETER;
2007 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2008 r->in.query->workstation_info->os_name.string);
2009 if (ret != LDB_SUCCESS) {
2010 return NT_STATUS_NO_MEMORY;
2014 * Sets information from "os_version". On an empty structure
2015 * the values are cleared.
2017 if (r->in.query->workstation_info->os_version.os != NULL) {
2018 struct netr_OsVersionInfoEx *os_version;
2019 const char *os_version_str;
2021 os_version = &r->in.query->workstation_info->os_version.os->os;
2023 if (os_version->CSDVersion == NULL) {
2024 return NT_STATUS_INVALID_PARAMETER;
2027 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2028 os_version->MajorVersion,
2029 os_version->MinorVersion,
2030 os_version->BuildNumber);
2031 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2033 ret = ldb_msg_add_string(new_msg,
2034 "operatingSystemServicePack",
2035 os_version->CSDVersion);
2036 if (ret != LDB_SUCCESS) {
2037 return NT_STATUS_NO_MEMORY;
2040 ret = ldb_msg_add_string(new_msg,
2041 "operatingSystemVersion",
2043 if (ret != LDB_SUCCESS) {
2044 return NT_STATUS_NO_MEMORY;
2047 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2048 "operatingSystemServicePack");
2049 if (ret != LDB_SUCCESS) {
2050 return NT_STATUS_NO_MEMORY;
2053 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2054 "operatingSystemVersion");
2055 if (ret != LDB_SUCCESS) {
2056 return NT_STATUS_NO_MEMORY;
2061 * If the boolean "update_dns_hostname" remained true, then we
2062 * are fine to start the update.
2064 if (update_dns_hostname) {
2065 ret = ldb_msg_add_string(new_msg,
2067 r->in.query->workstation_info->dns_hostname);
2068 if (ret != LDB_SUCCESS) {
2069 return NT_STATUS_NO_MEMORY;
2072 /* This manual "servicePrincipalName" generation is
2073 * still needed! Since the update in the samldb LDB
2074 * module does only work if the entries already exist
2075 * which isn't always the case. */
2076 ret = ldb_msg_add_string(new_msg,
2077 "servicePrincipalName",
2078 talloc_asprintf(new_msg, "HOST/%s",
2079 r->in.computer_name));
2080 if (ret != LDB_SUCCESS) {
2081 return NT_STATUS_NO_MEMORY;
2084 ret = ldb_msg_add_string(new_msg,
2085 "servicePrincipalName",
2086 talloc_asprintf(new_msg, "HOST/%s",
2087 r->in.query->workstation_info->dns_hostname));
2088 if (ret != LDB_SUCCESS) {
2089 return NT_STATUS_NO_MEMORY;
2093 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2094 DEBUG(3,("Impossible to update samdb: %s\n",
2095 ldb_errstring(sam_ctx)));
2098 talloc_free(new_msg);
2100 /* Writes back the domain information */
2102 /* We need to do two searches. The first will pull our primary
2103 domain and the second will pull any trusted domains. Our
2104 primary domain is also a "trusted" domain, so we need to
2105 put the primary domain into the lists of returned trusts as
2107 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2110 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2113 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2114 "(objectClass=trustedDomain)");
2116 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2119 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2120 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2122 ZERO_STRUCTP(domain_info);
2124 /* Informations about the local and trusted domains */
2126 status = fill_one_domain_info(mem_ctx,
2127 dce_call->conn->dce_ctx->lp_ctx,
2128 sam_ctx, res2[0], &domain_info->primary_domain,
2130 NT_STATUS_NOT_OK_RETURN(status);
2132 domain_info->trusted_domain_count = ret3 + 1;
2133 domain_info->trusted_domains = talloc_array(mem_ctx,
2134 struct netr_OneDomainInfo,
2135 domain_info->trusted_domain_count);
2136 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2138 for (i=0;i<ret3;i++) {
2139 status = fill_one_domain_info(mem_ctx,
2140 dce_call->conn->dce_ctx->lp_ctx,
2142 &domain_info->trusted_domains[i],
2144 NT_STATUS_NOT_OK_RETURN(status);
2147 status = fill_one_domain_info(mem_ctx,
2148 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2149 &domain_info->trusted_domains[i], true, true);
2150 NT_STATUS_NOT_OK_RETURN(status);
2152 /* Sets the supported encryption types */
2153 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2154 "msDS-SupportedEncryptionTypes",
2155 default_supported_enc_types);
2157 /* Other host domain information */
2159 lsa_policy_info = talloc(mem_ctx,
2160 struct netr_LsaPolicyInformation);
2161 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2162 ZERO_STRUCTP(lsa_policy_info);
2164 domain_info->lsa_policy = *lsa_policy_info;
2166 /* The DNS hostname is only returned back when there is a chance
2168 if ((r->in.query->workstation_info->workstation_flags
2169 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2170 domain_info->dns_hostname.string = old_dns_hostname;
2172 domain_info->dns_hostname.string = NULL;
2175 domain_info->workstation_flags =
2176 r->in.query->workstation_info->workstation_flags & (
2177 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2179 r->out.info->domain_info = domain_info;
2181 case 2: /* LSA policy information - not used at the moment */
2182 lsa_policy_info = talloc(mem_ctx,
2183 struct netr_LsaPolicyInformation);
2184 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2185 ZERO_STRUCTP(lsa_policy_info);
2187 r->out.info->lsa_policy_info = lsa_policy_info;
2190 return NT_STATUS_INVALID_LEVEL;
2194 return NT_STATUS_OK;
2199 netr_ServerPasswordGet
2201 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2202 struct netr_ServerPasswordGet *r)
2204 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2209 netr_NETRLOGONSENDTOSAM
2211 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2212 struct netr_NETRLOGONSENDTOSAM *r)
2214 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2219 netr_DsRGetDCNameEx2
2221 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2222 TALLOC_CTX *mem_ctx,
2223 struct netr_DsRGetDCNameEx2 *r)
2225 struct ldb_context *sam_ctx;
2226 struct netr_DsRGetDCNameInfo *info;
2227 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2228 const struct tsocket_address *local_address;
2229 char *local_addr = NULL;
2230 const struct tsocket_address *remote_address;
2231 char *remote_addr = NULL;
2232 const char *server_site_name;
2234 struct netlogon_samlogon_response response;
2236 const char *dc_name = NULL;
2237 const char *domain_name = NULL;
2240 ZERO_STRUCTP(r->out.info);
2242 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2243 dce_call->conn->auth_state.session_info, 0);
2244 if (sam_ctx == NULL) {
2245 return WERR_DS_UNAVAILABLE;
2248 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2249 if (tsocket_address_is_inet(local_address, "ip")) {
2250 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2251 W_ERROR_HAVE_NO_MEMORY(local_addr);
2254 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2255 if (tsocket_address_is_inet(remote_address, "ip")) {
2256 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2257 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2260 /* "server_unc" is ignored by w2k3 */
2262 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2263 return WERR_INVALID_FLAGS;
2266 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2267 r->in.flags & DS_PDC_REQUIRED &&
2268 r->in.flags & DS_KDC_REQUIRED) {
2269 return WERR_INVALID_FLAGS;
2271 if (r->in.flags & DS_IS_FLAT_NAME &&
2272 r->in.flags & DS_IS_DNS_NAME) {
2273 return WERR_INVALID_FLAGS;
2275 if (r->in.flags & DS_RETURN_DNS_NAME &&
2276 r->in.flags & DS_RETURN_FLAT_NAME) {
2277 return WERR_INVALID_FLAGS;
2279 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2280 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2281 return WERR_INVALID_FLAGS;
2284 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2286 (DS_DIRECTORY_SERVICE_REQUIRED |
2287 DS_DIRECTORY_SERVICE_PREFERRED |
2288 DS_GC_SERVER_REQUIRED |
2291 return WERR_INVALID_FLAGS;
2294 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2296 return WERR_INVALID_FLAGS;
2299 /* Proof server site parameter "site_name" if it was specified */
2300 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2301 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2302 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2303 server_site_name) != 0)) {
2304 return WERR_NO_SUCH_DOMAIN;
2307 guid_str = r->in.domain_guid != NULL ?
2308 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2310 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2314 r->in.client_account,
2315 r->in.mask, remote_addr,
2316 NETLOGON_NT_VERSION_5EX_WITH_IP,
2317 lp_ctx, &response, true);
2318 if (!NT_STATUS_IS_OK(status)) {
2319 return ntstatus_to_werror(status);
2323 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2324 * (O) flag when the returned forest name is in DNS format. This is here
2325 * always the case (see below).
2327 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2329 if (r->in.flags & DS_RETURN_DNS_NAME) {
2330 dc_name = response.data.nt5_ex.pdc_dns_name;
2331 domain_name = response.data.nt5_ex.dns_domain;
2333 * According to MS-NRPC 2.2.1.2.1 we should set the
2334 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2335 * the returned information is in DNS form.
2337 response.data.nt5_ex.server_type |=
2338 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2339 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2340 dc_name = response.data.nt5_ex.pdc_name;
2341 domain_name = response.data.nt5_ex.domain_name;
2345 * TODO: autodetect what we need to return
2346 * based on the given arguments
2348 dc_name = response.data.nt5_ex.pdc_name;
2349 domain_name = response.data.nt5_ex.domain_name;
2352 if (!dc_name || !dc_name[0]) {
2353 return WERR_NO_SUCH_DOMAIN;
2356 if (!domain_name || !domain_name[0]) {
2357 return WERR_NO_SUCH_DOMAIN;
2360 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2361 W_ERROR_HAVE_NO_MEMORY(info);
2362 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2363 dc_name[0] != '\\'? "\\\\":"",
2364 talloc_strdup(mem_ctx, dc_name));
2365 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2367 pdc_ip = local_addr;
2368 if (pdc_ip == NULL) {
2369 pdc_ip = "127.0.0.1";
2371 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2372 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2373 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2374 info->domain_guid = response.data.nt5_ex.domain_uuid;
2375 info->domain_name = domain_name;
2376 info->forest_name = response.data.nt5_ex.forest;
2377 info->dc_flags = response.data.nt5_ex.server_type;
2378 if (r->in.flags & DS_RETURN_DNS_NAME) {
2379 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2380 * returned if we are returning info->dc_unc containing a FQDN.
2381 * This attribute is called DomainControllerName in the specs,
2382 * it seems that we decide to return FQDN or netbios depending on
2383 * DS_RETURN_DNS_NAME.
2385 info->dc_flags |= DS_DNS_CONTROLLER;
2387 info->dc_site_name = response.data.nt5_ex.server_site;
2388 info->client_site_name = response.data.nt5_ex.client_site;
2390 *r->out.info = info;
2398 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2399 struct netr_DsRGetDCNameEx *r)
2401 struct netr_DsRGetDCNameEx2 r2;
2406 r2.in.server_unc = r->in.server_unc;
2407 r2.in.client_account = NULL;
2409 r2.in.domain_guid = r->in.domain_guid;
2410 r2.in.domain_name = r->in.domain_name;
2411 r2.in.site_name = r->in.site_name;
2412 r2.in.flags = r->in.flags;
2413 r2.out.info = r->out.info;
2415 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2423 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2424 struct netr_DsRGetDCName *r)
2426 struct netr_DsRGetDCNameEx2 r2;
2431 r2.in.server_unc = r->in.server_unc;
2432 r2.in.client_account = NULL;
2434 r2.in.domain_name = r->in.domain_name;
2435 r2.in.domain_guid = r->in.domain_guid;
2437 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2438 r2.in.flags = r->in.flags;
2439 r2.out.info = r->out.info;
2441 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2446 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2448 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2449 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2451 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2456 netr_NetrEnumerateTrustedDomainsEx
2458 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2459 struct netr_NetrEnumerateTrustedDomainsEx *r)
2461 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2466 netr_DsRAddressToSitenamesExW
2468 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2469 struct netr_DsRAddressToSitenamesExW *r)
2471 struct ldb_context *sam_ctx;
2472 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2473 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2474 sa_family_t sin_family;
2475 struct sockaddr_in *addr;
2477 struct sockaddr_in6 *addr6;
2478 char addr_str[INET6_ADDRSTRLEN];
2480 char addr_str[INET_ADDRSTRLEN];
2486 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2487 dce_call->conn->auth_state.session_info, 0);
2488 if (sam_ctx == NULL) {
2489 return WERR_DS_UNAVAILABLE;
2492 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2493 W_ERROR_HAVE_NO_MEMORY(ctr);
2497 ctr->count = r->in.count;
2498 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2499 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2500 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2501 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2503 for (i=0; i<ctr->count; i++) {
2504 ctr->sitename[i].string = NULL;
2505 ctr->subnetname[i].string = NULL;
2507 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2510 /* The first two byte of the buffer are reserved for the
2511 * "sin_family" but for now only the first one is used. */
2512 sin_family = r->in.addresses[i].buffer[0];
2514 switch (sin_family) {
2516 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2519 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2520 res = inet_ntop(AF_INET, &addr->sin_addr,
2521 addr_str, sizeof(addr_str));
2525 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2528 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2529 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2530 addr_str, sizeof(addr_str));
2541 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2545 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2546 ctr->subnetname[i].string = subnet_name;
2554 netr_DsRAddressToSitenamesW
2556 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2557 struct netr_DsRAddressToSitenamesW *r)
2559 struct netr_DsRAddressToSitenamesExW r2;
2560 struct netr_DsRAddressToSitenamesWCtr *ctr;
2566 r2.in.server_name = r->in.server_name;
2567 r2.in.count = r->in.count;
2568 r2.in.addresses = r->in.addresses;
2570 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2571 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2573 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2574 W_ERROR_HAVE_NO_MEMORY(ctr);
2578 ctr->count = r->in.count;
2579 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2580 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2582 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2584 for (i=0; i<ctr->count; i++) {
2585 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2593 netr_DsrGetDcSiteCoverageW
2595 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2596 struct netr_DsrGetDcSiteCoverageW *r)
2598 struct ldb_context *sam_ctx;
2599 struct DcSitesCtr *ctr;
2600 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2602 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2603 dce_call->conn->auth_state.session_info, 0);
2604 if (sam_ctx == NULL) {
2605 return WERR_DS_UNAVAILABLE;
2608 ctr = talloc(mem_ctx, struct DcSitesCtr);
2609 W_ERROR_HAVE_NO_MEMORY(ctr);
2613 /* For now only return our default site */
2615 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2616 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2617 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2618 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2624 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2625 struct ldb_context *sam_ctx,
2626 struct netr_DomainTrustList *trusts,
2627 uint32_t trust_flags)
2629 struct ldb_dn *system_dn;
2630 struct ldb_message **dom_res = NULL;
2631 const char *trust_attrs[] = { "flatname", "trustPartner",
2632 "securityIdentifier", "trustDirection",
2633 "trustType", "trustAttributes", NULL };
2638 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2639 NETR_TRUST_FLAG_OUTBOUND))) {
2640 return WERR_INVALID_FLAGS;
2643 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2644 ldb_get_default_basedn(sam_ctx),
2645 "(&(objectClass=container)(cn=System))");
2647 return WERR_GENERAL_FAILURE;
2650 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2651 &dom_res, trust_attrs,
2652 "(objectclass=trustedDomain)");
2654 for (i = 0; i < ret; i++) {
2655 unsigned int trust_dir;
2658 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2659 "trustDirection", 0);
2661 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2662 flags |= NETR_TRUST_FLAG_INBOUND;
2664 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2665 flags |= NETR_TRUST_FLAG_OUTBOUND;
2668 if (!(flags & trust_flags)) {
2669 /* this trust direction was not requested */
2674 trusts->array = talloc_realloc(trusts, trusts->array,
2675 struct netr_DomainTrust,
2677 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2679 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2680 if (!trusts->array[n].netbios_name) {
2681 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2682 "without flatname\n",
2683 ldb_dn_get_linearized(dom_res[i]->dn)));
2686 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2688 trusts->array[n].trust_flags = flags;
2689 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2690 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2691 /* TODO: find if we have parent in the list */
2692 trusts->array[n].parent_index = 0;
2695 trusts->array[n].trust_type =
2696 ldb_msg_find_attr_as_uint(dom_res[i],
2698 trusts->array[n].trust_attributes =
2699 ldb_msg_find_attr_as_uint(dom_res[i],
2700 "trustAttributes", 0);
2702 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2703 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2704 struct dom_sid zero_sid;
2705 ZERO_STRUCT(zero_sid);
2706 trusts->array[n].sid =
2707 dom_sid_dup(trusts, &zero_sid);
2709 trusts->array[n].sid =
2710 samdb_result_dom_sid(trusts, dom_res[i],
2711 "securityIdentifier");
2713 trusts->array[n].guid = GUID_zero();
2715 trusts->count = n + 1;
2718 talloc_free(dom_res);
2723 netr_DsrEnumerateDomainTrusts
2725 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2726 TALLOC_CTX *mem_ctx,
2727 struct netr_DsrEnumerateDomainTrusts *r)
2729 struct netr_DomainTrustList *trusts;
2730 struct ldb_context *sam_ctx;
2732 struct ldb_message **dom_res;
2733 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2734 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2735 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2739 if (r->in.trust_flags & 0xFFFFFE00) {
2740 return WERR_INVALID_FLAGS;
2743 /* TODO: turn to hard check once we are sure this is 100% correct */
2744 if (!r->in.server_name) {
2745 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2746 "But received NULL!\n", dnsdomain));
2748 p = strchr(r->in.server_name, '.');
2750 DEBUG(3, ("Invalid domain! Expected name in domain "
2751 "[%s]. But received [%s]!\n",
2752 dnsdomain, r->in.server_name));
2753 p = r->in.server_name;
2757 if (strcasecmp(p, dnsdomain)) {
2758 DEBUG(3, ("Invalid domain! Expected name in domain "
2759 "[%s]. But received [%s]!\n",
2760 dnsdomain, r->in.server_name));
2764 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2765 W_ERROR_HAVE_NO_MEMORY(trusts);
2768 r->out.trusts = trusts;
2770 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2771 dce_call->conn->auth_state.session_info, 0);
2772 if (sam_ctx == NULL) {
2773 return WERR_GENERAL_FAILURE;
2776 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2777 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2779 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2780 trusts, r->in.trust_flags);
2781 W_ERROR_NOT_OK_RETURN(werr);
2784 /* NOTE: we currently are always the root of the forest */
2785 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2786 uint32_t n = trusts->count;
2788 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2789 &dom_res, dom_attrs);
2791 return WERR_GENERAL_FAILURE;
2794 trusts->count = n + 1;
2795 trusts->array = talloc_realloc(trusts, trusts->array,
2796 struct netr_DomainTrust,
2798 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2800 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2801 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2802 trusts->array[n].trust_flags =
2803 NETR_TRUST_FLAG_NATIVE |
2804 NETR_TRUST_FLAG_TREEROOT |
2805 NETR_TRUST_FLAG_IN_FOREST |
2806 NETR_TRUST_FLAG_PRIMARY;
2807 /* we are always the root domain for now */
2808 trusts->array[n].parent_index = 0;
2809 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2810 trusts->array[n].trust_attributes = 0;
2811 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2814 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2816 talloc_free(dom_res);
2824 netr_DsrDeregisterDNSHostRecords
2826 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2827 struct netr_DsrDeregisterDNSHostRecords *r)
2829 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2833 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2834 struct netr_ServerGetTrustInfo *r);
2837 netr_ServerTrustPasswordsGet
2839 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2840 struct netr_ServerTrustPasswordsGet *r)
2842 struct netr_ServerGetTrustInfo r2 = {};
2843 struct netr_TrustInfo *_ti = NULL;
2846 r2.in.server_name = r->in.server_name;
2847 r2.in.account_name = r->in.account_name;
2848 r2.in.secure_channel_type = r->in.secure_channel_type;
2849 r2.in.computer_name = r->in.computer_name;
2850 r2.in.credential = r->in.credential;
2852 r2.out.return_authenticator = r->out.return_authenticator;
2853 r2.out.new_owf_password = r->out.new_owf_password;
2854 r2.out.old_owf_password = r->out.old_owf_password;
2855 r2.out.trust_info = &_ti;
2857 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
2859 r->out.return_authenticator = r2.out.return_authenticator;
2860 r->out.new_owf_password = r2.out.new_owf_password;
2861 r->out.old_owf_password = r2.out.old_owf_password;
2867 netr_DsRGetForestTrustInformation
2869 struct dcesrv_netr_DsRGetForestTrustInformation_state {
2870 struct dcesrv_call_state *dce_call;
2871 TALLOC_CTX *mem_ctx;
2872 struct netr_DsRGetForestTrustInformation *r;
2875 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
2877 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2878 TALLOC_CTX *mem_ctx,
2879 struct netr_DsRGetForestTrustInformation *r)
2881 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2882 struct dcesrv_connection *conn = dce_call->conn;
2883 struct auth_session_info *session_info = conn->auth_state.session_info;
2884 enum security_user_level security_level;
2885 struct ldb_context *sam_ctx = NULL;
2886 struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
2887 struct dcerpc_binding_handle *irpc_handle = NULL;
2888 struct tevent_req *subreq = NULL;
2889 struct ldb_dn *domain_dn = NULL;
2890 struct ldb_dn *forest_dn = NULL;
2894 security_level = security_session_user_level(session_info, NULL);
2895 if (security_level < SECURITY_USER) {
2896 return WERR_ACCESS_DENIED;
2899 if (r->in.flags & 0xFFFFFFFE) {
2900 return WERR_INVALID_FLAGS;
2903 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2904 dce_call->conn->auth_state.session_info, 0);
2905 if (sam_ctx == NULL) {
2906 return WERR_GENERAL_FAILURE;
2909 domain_dn = ldb_get_default_basedn(sam_ctx);
2910 if (domain_dn == NULL) {
2911 return WERR_GENERAL_FAILURE;
2914 forest_dn = ldb_get_root_basedn(sam_ctx);
2915 if (forest_dn == NULL) {
2916 return WERR_GENERAL_FAILURE;
2919 cmp = ldb_dn_compare(domain_dn, forest_dn);
2921 return WERR_NERR_ACFNOTLOADED;
2924 forest_level = dsdb_forest_functional_level(sam_ctx);
2925 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
2926 return WERR_INVALID_FUNCTION;
2929 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2930 if (!samdb_is_pdc(sam_ctx)) {
2931 return WERR_NERR_NOTPRIMARY;
2934 if (r->in.trusted_domain_name == NULL) {
2935 return WERR_INVALID_FLAGS;
2939 if (r->in.trusted_domain_name == NULL) {
2943 * information about our own domain
2945 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
2946 r->out.forest_trust_info);
2947 if (!NT_STATUS_IS_OK(status)) {
2948 return ntstatus_to_werror(status);
2955 * Forward the request to winbindd
2958 state = talloc_zero(mem_ctx,
2959 struct dcesrv_netr_DsRGetForestTrustInformation_state);
2960 if (state == NULL) {
2963 state->dce_call = dce_call;
2964 state->mem_ctx = mem_ctx;
2967 irpc_handle = irpc_binding_handle_by_name(state,
2968 state->dce_call->msg_ctx,
2970 &ndr_table_winbind);
2971 if (irpc_handle == NULL) {
2972 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
2973 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2974 return WERR_SERVICE_NOT_FOUND;
2978 * 60 seconds timeout should be enough
2980 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
2982 subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
2983 state->dce_call->event_ctx,
2985 r->in.trusted_domain_name,
2987 r->out.forest_trust_info);
2988 if (subreq == NULL) {
2991 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2992 tevent_req_set_callback(subreq,
2993 dcesrv_netr_DsRGetForestTrustInformation_done,
2999 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3001 struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3002 tevent_req_callback_data(subreq,
3003 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3006 status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3008 &state->r->out.result);
3009 TALLOC_FREE(subreq);
3010 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3011 state->r->out.result = WERR_TIMEOUT;
3012 } else if (!NT_STATUS_IS_OK(status)) {
3013 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3014 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3015 nt_errstr(status)));
3018 status = dcesrv_reply(state->dce_call);
3019 if (!NT_STATUS_IS_OK(status)) {
3020 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3025 netr_GetForestTrustInformation
3027 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3028 TALLOC_CTX *mem_ctx,
3029 struct netr_GetForestTrustInformation *r)
3031 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3032 struct netlogon_creds_CredentialState *creds = NULL;
3033 struct ldb_context *sam_ctx = NULL;
3034 struct ldb_dn *domain_dn = NULL;
3035 struct ldb_dn *forest_dn = NULL;
3040 status = dcesrv_netr_creds_server_step_check(dce_call,
3042 r->in.computer_name,
3044 r->out.return_authenticator,
3046 if (!NT_STATUS_IS_OK(status)) {
3050 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3051 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3052 return NT_STATUS_NOT_IMPLEMENTED;
3055 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3056 dce_call->conn->auth_state.session_info, 0);
3057 if (sam_ctx == NULL) {
3058 return NT_STATUS_INTERNAL_ERROR;
3061 /* TODO: check r->in.server_name is our name */
3063 domain_dn = ldb_get_default_basedn(sam_ctx);
3064 if (domain_dn == NULL) {
3065 return NT_STATUS_INTERNAL_ERROR;
3068 forest_dn = ldb_get_root_basedn(sam_ctx);
3069 if (forest_dn == NULL) {
3070 return NT_STATUS_INTERNAL_ERROR;
3073 cmp = ldb_dn_compare(domain_dn, forest_dn);
3075 return NT_STATUS_INVALID_DOMAIN_STATE;
3078 forest_level = dsdb_forest_functional_level(sam_ctx);
3079 if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3080 return NT_STATUS_INVALID_DOMAIN_STATE;
3083 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3084 r->out.forest_trust_info);
3085 if (!NT_STATUS_IS_OK(status)) {
3089 return NT_STATUS_OK;
3094 netr_ServerGetTrustInfo
3096 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3097 struct netr_ServerGetTrustInfo *r)
3099 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3100 struct netlogon_creds_CredentialState *creds = NULL;
3101 struct ldb_context *sam_ctx = NULL;
3102 const char * const attrs[] = {
3105 "userAccountControl",
3108 struct ldb_message **res = NULL;
3109 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3112 const char *asid = NULL;
3114 const char *aname = NULL;
3115 struct ldb_message *tdo_msg = NULL;
3116 const char * const tdo_attrs[] = {
3117 "trustAuthIncoming",
3121 struct netr_TrustInfo *trust_info = NULL;
3123 ZERO_STRUCTP(r->out.new_owf_password);
3124 ZERO_STRUCTP(r->out.old_owf_password);
3126 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3128 r->in.computer_name,
3130 r->out.return_authenticator,
3132 if (!NT_STATUS_IS_OK(nt_status)) {
3136 /* TODO: check r->in.server_name is our name */
3138 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3139 return NT_STATUS_INVALID_PARAMETER;
3142 if (r->in.secure_channel_type != creds->secure_channel_type) {
3143 return NT_STATUS_INVALID_PARAMETER;
3146 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3147 return NT_STATUS_INVALID_PARAMETER;
3150 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3151 lp_ctx, system_session(lp_ctx), 0);
3152 if (sam_ctx == NULL) {
3153 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3156 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3158 return NT_STATUS_NO_MEMORY;
3161 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3162 "(&(objectClass=user)(objectSid=%s))",
3165 return NT_STATUS_ACCOUNT_DISABLED;
3168 switch (creds->secure_channel_type) {
3169 case SEC_CHAN_DNS_DOMAIN:
3170 case SEC_CHAN_DOMAIN:
3171 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3173 if (uac & UF_ACCOUNTDISABLE) {
3174 return NT_STATUS_ACCOUNT_DISABLED;
3177 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3178 return NT_STATUS_ACCOUNT_DISABLED;
3181 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3182 if (aname == NULL) {
3183 return NT_STATUS_ACCOUNT_DISABLED;
3186 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3187 SEC_CHAN_DOMAIN, aname,
3188 tdo_attrs, mem_ctx, &tdo_msg);
3189 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3190 return NT_STATUS_ACCOUNT_DISABLED;
3192 if (!NT_STATUS_IS_OK(nt_status)) {
3196 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3199 if (!NT_STATUS_IS_OK(nt_status)) {
3203 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3204 if (trust_info == NULL) {
3205 return NT_STATUS_NO_MEMORY;
3208 trust_info->count = 1;
3209 trust_info->data = talloc_array(trust_info, uint32_t,
3211 if (trust_info->data == NULL) {
3212 return NT_STATUS_NO_MEMORY;
3215 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3221 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3224 if (!NT_STATUS_IS_OK(nt_status)) {
3228 prevNtHash = talloc(mem_ctx, struct samr_Password);
3229 if (prevNtHash == NULL) {
3230 return NT_STATUS_NO_MEMORY;
3233 E_md4hash("", prevNtHash->hash);
3237 if (curNtHash != NULL) {
3238 *r->out.new_owf_password = *curNtHash;
3239 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3241 if (prevNtHash != NULL) {
3242 *r->out.old_owf_password = *prevNtHash;
3243 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3246 if (trust_info != NULL) {
3247 *r->out.trust_info = trust_info;
3250 return NT_STATUS_OK;
3256 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3257 struct netr_Unused47 *r)
3259 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3263 struct netr_dnsupdate_RODC_state {
3264 struct dcesrv_call_state *dce_call;
3265 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3266 struct dnsupdate_RODC *r2;
3270 called when the forwarded RODC dns update request is finished
3272 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3274 struct netr_dnsupdate_RODC_state *st =
3275 tevent_req_callback_data(subreq,
3276 struct netr_dnsupdate_RODC_state);
3279 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3280 TALLOC_FREE(subreq);
3281 if (!NT_STATUS_IS_OK(status)) {
3282 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3283 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3286 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3288 status = dcesrv_reply(st->dce_call);
3289 if (!NT_STATUS_IS_OK(status)) {
3290 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3295 netr_DsrUpdateReadOnlyServerDnsRecords
3297 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3298 TALLOC_CTX *mem_ctx,
3299 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3301 struct netlogon_creds_CredentialState *creds;
3303 struct dcerpc_binding_handle *binding_handle;
3304 struct netr_dnsupdate_RODC_state *st;
3305 struct tevent_req *subreq;
3307 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3309 r->in.computer_name,
3311 r->out.return_authenticator,
3313 NT_STATUS_NOT_OK_RETURN(nt_status);
3315 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3316 return NT_STATUS_ACCESS_DENIED;
3319 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3320 NT_STATUS_HAVE_NO_MEMORY(st);
3322 st->dce_call = dce_call;
3324 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3325 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3327 st->r2->in.dom_sid = creds->sid;
3328 st->r2->in.site_name = r->in.site_name;
3329 st->r2->in.dns_ttl = r->in.dns_ttl;
3330 st->r2->in.dns_names = r->in.dns_names;
3331 st->r2->out.dns_names = r->out.dns_names;
3333 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3334 "dnsupdate", &ndr_table_irpc);
3335 if (binding_handle == NULL) {
3336 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3337 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3338 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3341 /* forward the call */
3342 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3343 binding_handle, st->r2);
3344 NT_STATUS_HAVE_NO_MEMORY(subreq);
3346 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3348 /* setup the callback */
3349 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3351 return NT_STATUS_OK;
3355 /* include the generated boilerplate */
3356 #include "librpc/gen_ndr/ndr_netlogon_s.c"