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_irpc.h"
41 #include "lib/socket/netif.h"
43 static struct memcache *global_challenge_table;
45 struct netlogon_server_pipe_state {
46 struct netr_Credential client_challenge;
47 struct netr_Credential server_challenge;
50 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
51 struct netr_ServerReqChallenge *r)
53 struct netlogon_server_pipe_state *pipe_state =
54 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
57 ZERO_STRUCTP(r->out.return_credentials);
59 if (global_challenge_table == NULL) {
61 * We maintain a global challenge table
62 * with a fixed size (8k)
64 * This is required for the strange clients
65 * which use different connections for
66 * netr_ServerReqChallenge() and netr_ServerAuthenticate3()
69 global_challenge_table = memcache_init(talloc_autofree_context(),
71 if (global_challenge_table == NULL) {
72 return NT_STATUS_NO_MEMORY;
76 /* destroyed on pipe shutdown */
79 talloc_free(pipe_state);
80 dce_call->context->private_data = NULL;
83 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
84 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
86 pipe_state->client_challenge = *r->in.credentials;
88 generate_random_buffer(pipe_state->server_challenge.data,
89 sizeof(pipe_state->server_challenge.data));
91 *r->out.return_credentials = pipe_state->server_challenge;
93 dce_call->context->private_data = pipe_state;
95 key = data_blob_string_const(r->in.computer_name);
96 val = data_blob_const(pipe_state, sizeof(*pipe_state));
98 memcache_add(global_challenge_table, SINGLETON_CACHE, key, val);
103 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
104 struct netr_ServerAuthenticate3 *r)
106 struct netlogon_server_pipe_state *pipe_state =
107 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
108 DATA_BLOB challenge_key;
109 bool challenge_valid = false;
110 struct netlogon_server_pipe_state challenge;
111 struct netlogon_creds_CredentialState *creds;
112 struct ldb_context *sam_ctx;
113 struct samr_Password *mach_pwd;
114 uint32_t user_account_control;
116 struct ldb_message **msgs;
118 const char *attrs[] = {"unicodePwd", "userAccountControl",
121 const char *trust_dom_attrs[] = {"flatname", NULL};
122 const char *account_name;
123 uint32_t server_flags = 0;
124 uint32_t negotiate_flags = 0;
125 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
126 bool reject_des_client = !allow_nt4_crypto;
127 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
129 ZERO_STRUCTP(r->out.return_credentials);
132 challenge_key = data_blob_string_const(r->in.computer_name);
133 if (pipe_state != NULL) {
134 dce_call->context->private_data = NULL;
137 * If we had a challenge remembered on the connection
138 * consider this for usage. This can't be cleanup
141 * This is the default code path for typical clients
142 * which call netr_ServerReqChallenge() and
143 * netr_ServerAuthenticate3() on the same dcerpc connection.
145 challenge = *pipe_state;
146 TALLOC_FREE(pipe_state);
147 challenge_valid = true;
153 * Fallback and try to get the challenge from
156 * If too many clients are using this code path,
157 * they may destroy their cache entries as the
158 * global_challenge_table memcache has a fixed size.
160 * Note: this handles global_challenge_table == NULL fine
162 ok = memcache_lookup(global_challenge_table, SINGLETON_CACHE,
163 challenge_key, &val);
164 if (ok && val.length == sizeof(challenge)) {
165 memcpy(&challenge, val.data, sizeof(challenge));
166 challenge_valid = true;
168 ZERO_STRUCT(challenge);
173 * At this point we can cleanup the cache entry,
174 * if we fail the client needs to call netr_ServerReqChallenge
177 * Note: this handles global_challenge_table == NULL
178 * and also a non existing record just fine.
180 memcache_delete(global_challenge_table,
181 SINGLETON_CACHE, challenge_key);
183 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
184 NETLOGON_NEG_PERSISTENT_SAMREPL |
185 NETLOGON_NEG_ARCFOUR |
186 NETLOGON_NEG_PROMOTION_COUNT |
187 NETLOGON_NEG_CHANGELOG_BDC |
188 NETLOGON_NEG_FULL_SYNC_REPL |
189 NETLOGON_NEG_MULTIPLE_SIDS |
191 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
192 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
193 NETLOGON_NEG_GENERIC_PASSTHROUGH |
194 NETLOGON_NEG_CONCURRENT_RPC |
195 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
196 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
197 NETLOGON_NEG_STRONG_KEYS |
198 NETLOGON_NEG_TRANSITIVE_TRUSTS |
199 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
200 NETLOGON_NEG_PASSWORD_SET2 |
201 NETLOGON_NEG_GETDOMAININFO |
202 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
203 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
204 NETLOGON_NEG_RODC_PASSTHROUGH |
205 NETLOGON_NEG_SUPPORTS_AES |
206 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
207 NETLOGON_NEG_AUTHENTICATED_RPC;
209 negotiate_flags = *r->in.negotiate_flags & server_flags;
211 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
212 reject_des_client = false;
215 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
216 reject_des_client = false;
217 reject_md5_client = false;
220 if (reject_des_client || reject_md5_client) {
222 * Here we match Windows 2012 and return no flags.
224 *r->out.negotiate_flags = 0;
225 return NT_STATUS_DOWNGRADE_DETECTED;
229 * According to Microsoft (see bugid #6099)
230 * Windows 7 looks at the negotiate_flags
231 * returned in this structure *even if the
232 * call fails with access denied!
234 *r->out.negotiate_flags = negotiate_flags;
236 switch (r->in.secure_channel_type) {
238 case SEC_CHAN_DNS_DOMAIN:
239 case SEC_CHAN_DOMAIN:
244 return NT_STATUS_INVALID_PARAMETER;
246 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
247 r->in.secure_channel_type));
248 return NT_STATUS_INVALID_PARAMETER;
251 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
252 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
253 if (sam_ctx == NULL) {
254 return NT_STATUS_INVALID_SYSTEM_SERVICE;
257 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
258 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
259 const char *flatname;
260 if (!encoded_account) {
261 return NT_STATUS_NO_MEMORY;
264 /* Kill the trailing dot */
265 if (encoded_account[strlen(encoded_account)-1] == '.') {
266 encoded_account[strlen(encoded_account)-1] = '\0';
269 /* pull the user attributes */
270 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
272 "(&(trustPartner=%s)(objectclass=trustedDomain))",
275 if (num_records == 0) {
276 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
278 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
281 if (num_records > 1) {
282 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
283 return NT_STATUS_INTERNAL_DB_CORRUPTION;
286 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
288 /* No flatname for this trust - we can't proceed */
289 DEBUG(3,("Couldn't find flatname for trust [%s] in samdb.\n",
291 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
293 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
296 return NT_STATUS_NO_MEMORY;
300 account_name = r->in.account_name;
303 /* pull the user attributes */
304 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
305 "(&(sAMAccountName=%s)(objectclass=user))",
306 ldb_binary_encode_string(mem_ctx, account_name));
308 if (num_records == 0) {
309 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
310 r->in.account_name));
311 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
314 if (num_records > 1) {
315 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
316 return NT_STATUS_INTERNAL_DB_CORRUPTION;
319 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
321 if (user_account_control & UF_ACCOUNTDISABLE) {
322 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
323 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
326 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
327 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
328 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
329 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
331 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
332 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
333 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
334 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
336 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
338 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
339 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
340 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
341 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
343 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
344 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
345 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
346 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
349 /* we should never reach this */
350 return NT_STATUS_INTERNAL_ERROR;
353 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
354 if (mach_pwd == NULL) {
355 return NT_STATUS_ACCESS_DENIED;
358 if (!challenge_valid) {
359 DEBUG(1, ("No challenge requested by client [%s/%s], "
360 "cannot authenticate\n",
362 r->in.account_name));
363 return NT_STATUS_ACCESS_DENIED;
366 creds = netlogon_creds_server_init(mem_ctx,
369 r->in.secure_channel_type,
370 &challenge.client_challenge,
371 &challenge.server_challenge,
374 r->out.return_credentials,
377 return NT_STATUS_ACCESS_DENIED;
380 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
382 nt_status = schannel_save_creds_state(mem_ctx,
383 dce_call->conn->dce_ctx->lp_ctx,
385 if (!NT_STATUS_IS_OK(nt_status)) {
386 ZERO_STRUCTP(r->out.return_credentials);
390 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
396 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
397 struct netr_ServerAuthenticate *r)
399 struct netr_ServerAuthenticate3 a;
402 * negotiate_flags is used as an [in] parameter
403 * so it need to be initialised.
405 * (I think ... = 0; seems wrong here --metze)
407 uint32_t negotiate_flags_in = 0;
408 uint32_t negotiate_flags_out = 0;
410 a.in.server_name = r->in.server_name;
411 a.in.account_name = r->in.account_name;
412 a.in.secure_channel_type = r->in.secure_channel_type;
413 a.in.computer_name = r->in.computer_name;
414 a.in.credentials = r->in.credentials;
415 a.in.negotiate_flags = &negotiate_flags_in;
417 a.out.return_credentials = r->out.return_credentials;
419 a.out.negotiate_flags = &negotiate_flags_out;
421 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
424 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
425 struct netr_ServerAuthenticate2 *r)
427 struct netr_ServerAuthenticate3 r3;
430 r3.in.server_name = r->in.server_name;
431 r3.in.account_name = r->in.account_name;
432 r3.in.secure_channel_type = r->in.secure_channel_type;
433 r3.in.computer_name = r->in.computer_name;
434 r3.in.credentials = r->in.credentials;
435 r3.out.return_credentials = r->out.return_credentials;
436 r3.in.negotiate_flags = r->in.negotiate_flags;
437 r3.out.negotiate_flags = r->out.negotiate_flags;
440 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
444 * NOTE: The following functions are nearly identical to the ones available in
445 * source3/rpc_server/srv_nelog_nt.c
446 * The reason we keep 2 copies is that they use different structures to
447 * represent the auth_info and the decrpc pipes.
451 * If schannel is required for this call test that it actually is available.
453 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
454 const char *computer_name,
455 bool integrity, bool privacy)
458 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
459 if (!privacy && !integrity) {
463 if ((!privacy && integrity) &&
464 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
468 if ((privacy || integrity) &&
469 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
474 /* test didn't pass */
475 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
478 return NT_STATUS_ACCESS_DENIED;
481 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
483 const char *computer_name,
484 struct netr_Authenticator *received_authenticator,
485 struct netr_Authenticator *return_authenticator,
486 struct netlogon_creds_CredentialState **creds_out)
489 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
490 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
492 if (schannel_global_required) {
493 nt_status = schannel_check_required(auth_info,
496 if (!NT_STATUS_IS_OK(nt_status)) {
501 nt_status = schannel_check_creds_state(mem_ctx,
502 dce_call->conn->dce_ctx->lp_ctx,
504 received_authenticator,
505 return_authenticator,
511 Change the machine account password for the currently connected
512 client. Supplies only the NT#.
515 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
516 struct netr_ServerPasswordSet *r)
518 struct netlogon_creds_CredentialState *creds;
519 struct ldb_context *sam_ctx;
520 const char * const attrs[] = { "unicodePwd", NULL };
521 struct ldb_message **res;
522 struct samr_Password *oldNtHash;
526 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
529 r->in.credential, r->out.return_authenticator,
531 NT_STATUS_NOT_OK_RETURN(nt_status);
533 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);
534 if (sam_ctx == NULL) {
535 return NT_STATUS_INVALID_SYSTEM_SERVICE;
538 netlogon_creds_des_decrypt(creds, r->in.new_password);
540 /* fetch the old password hashes (the NT hash has to exist) */
542 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
543 "(&(objectClass=user)(objectSid=%s))",
544 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
546 return NT_STATUS_WRONG_PASSWORD;
549 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
550 dce_call->conn->dce_ctx->lp_ctx,
551 res[0], NULL, &oldNtHash);
552 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
553 return NT_STATUS_WRONG_PASSWORD;
556 /* Using the sid for the account as the key, set the password */
557 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
559 NULL, /* Don't have plaintext */
560 NULL, r->in.new_password,
561 NULL, oldNtHash, /* Password change */
567 Change the machine account password for the currently connected
568 client. Supplies new plaintext.
570 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
571 struct netr_ServerPasswordSet2 *r)
573 struct netlogon_creds_CredentialState *creds;
574 struct ldb_context *sam_ctx;
575 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
576 struct ldb_message **res;
577 struct samr_Password *oldLmHash, *oldNtHash;
579 DATA_BLOB new_password;
582 struct samr_CryptPassword password_buf;
584 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
587 r->in.credential, r->out.return_authenticator,
589 NT_STATUS_NOT_OK_RETURN(nt_status);
591 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);
592 if (sam_ctx == NULL) {
593 return NT_STATUS_INVALID_SYSTEM_SERVICE;
596 memcpy(password_buf.data, r->in.new_password->data, 512);
597 SIVAL(password_buf.data, 512, r->in.new_password->length);
599 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
600 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
602 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
605 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
606 DEBUG(3,("samr: failed to decode password buffer\n"));
607 return NT_STATUS_WRONG_PASSWORD;
610 /* fetch the old password hashes (at least one of both has to exist) */
612 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
613 "(&(objectClass=user)(objectSid=%s))",
614 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
616 return NT_STATUS_WRONG_PASSWORD;
619 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
620 dce_call->conn->dce_ctx->lp_ctx,
621 res[0], &oldLmHash, &oldNtHash);
622 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
623 return NT_STATUS_WRONG_PASSWORD;
626 /* Using the sid for the account as the key, set the password */
627 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
629 &new_password, /* we have plaintext */
631 oldLmHash, oldNtHash, /* Password change */
640 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
641 struct netr_LogonUasLogon *r)
643 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
650 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
651 struct netr_LogonUasLogoff *r)
653 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
657 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
659 switch (r->in.logon_level) {
660 case NetlogonInteractiveInformation:
661 case NetlogonServiceInformation:
662 case NetlogonInteractiveTransitiveInformation:
663 case NetlogonServiceTransitiveInformation:
664 if (r->in.logon->password == NULL) {
665 return NT_STATUS_INVALID_PARAMETER;
668 switch (r->in.validation_level) {
669 case NetlogonValidationSamInfo: /* 2 */
670 case NetlogonValidationSamInfo2: /* 3 */
671 case NetlogonValidationSamInfo4: /* 6 */
674 return NT_STATUS_INVALID_INFO_CLASS;
678 case NetlogonNetworkInformation:
679 case NetlogonNetworkTransitiveInformation:
680 if (r->in.logon->network == NULL) {
681 return NT_STATUS_INVALID_PARAMETER;
684 switch (r->in.validation_level) {
685 case NetlogonValidationSamInfo: /* 2 */
686 case NetlogonValidationSamInfo2: /* 3 */
687 case NetlogonValidationSamInfo4: /* 6 */
690 return NT_STATUS_INVALID_INFO_CLASS;
695 case NetlogonGenericInformation:
696 if (r->in.logon->generic == NULL) {
697 return NT_STATUS_INVALID_PARAMETER;
700 switch (r->in.validation_level) {
701 /* TODO: case NetlogonValidationGenericInfo: 4 */
702 case NetlogonValidationGenericInfo2: /* 5 */
705 return NT_STATUS_INVALID_INFO_CLASS;
710 return NT_STATUS_INVALID_PARAMETER;
717 netr_LogonSamLogon_base
719 This version of the function allows other wrappers to say 'do not check the credentials'
721 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
723 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
724 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
726 struct auth4_context *auth_context;
727 struct auth_usersupplied_info *user_info;
728 struct auth_user_info_dc *user_info_dc;
730 struct netr_SamBaseInfo *sam;
731 struct netr_SamInfo2 *sam2;
732 struct netr_SamInfo3 *sam3;
733 struct netr_SamInfo6 *sam6;
735 *r->out.authoritative = 1;
737 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
738 NT_STATUS_HAVE_NO_MEMORY(user_info);
740 netlogon_creds_decrypt_samlogon_logon(creds,
744 switch (r->in.logon_level) {
745 case NetlogonInteractiveInformation:
746 case NetlogonServiceInformation:
747 case NetlogonInteractiveTransitiveInformation:
748 case NetlogonServiceTransitiveInformation:
750 /* TODO: we need to deny anonymous access here */
751 nt_status = auth_context_create(mem_ctx,
752 dce_call->event_ctx, dce_call->msg_ctx,
753 dce_call->conn->dce_ctx->lp_ctx,
755 NT_STATUS_NOT_OK_RETURN(nt_status);
757 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
758 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
759 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
760 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
762 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
763 user_info->password_state = AUTH_PASSWORD_HASH;
765 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
766 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
767 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
769 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
770 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
771 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
774 case NetlogonNetworkInformation:
775 case NetlogonNetworkTransitiveInformation:
777 /* TODO: we need to deny anonymous access here */
778 nt_status = auth_context_create(mem_ctx,
779 dce_call->event_ctx, dce_call->msg_ctx,
780 dce_call->conn->dce_ctx->lp_ctx,
782 NT_STATUS_NOT_OK_RETURN(nt_status);
784 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
785 NT_STATUS_NOT_OK_RETURN(nt_status);
787 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
788 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
789 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
790 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
792 user_info->password_state = AUTH_PASSWORD_RESPONSE;
793 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
794 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
799 case NetlogonGenericInformation:
801 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
803 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
806 /* Using DES to verify kerberos tickets makes no sense */
807 return NT_STATUS_INVALID_PARAMETER;
810 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
812 struct dcerpc_binding_handle *irpc_handle;
813 struct kdc_check_generic_kerberos check;
814 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
815 NT_STATUS_HAVE_NO_MEMORY(generic);
816 *r->out.authoritative = 1;
818 /* TODO: Describe and deal with these flags */
821 r->out.validation->generic = generic;
823 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
827 if (irpc_handle == NULL) {
828 return NT_STATUS_NO_LOGON_SERVERS;
831 check.in.generic_request =
832 data_blob_const(r->in.logon->generic->data,
833 r->in.logon->generic->length);
836 * TODO: make this async and avoid
837 * dcerpc_binding_handle_set_sync_ev()
839 dcerpc_binding_handle_set_sync_ev(irpc_handle,
840 dce_call->event_ctx);
841 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
844 if (!NT_STATUS_IS_OK(status)) {
847 generic->length = check.out.generic_reply.length;
848 generic->data = check.out.generic_reply.data;
852 /* Until we get an implemetnation of these other packages */
853 return NT_STATUS_INVALID_PARAMETER;
856 return NT_STATUS_INVALID_PARAMETER;
859 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
860 /* TODO: set *r->out.authoritative = 0 on specific errors */
861 NT_STATUS_NOT_OK_RETURN(nt_status);
863 switch (r->in.validation_level) {
865 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
866 NT_STATUS_NOT_OK_RETURN(nt_status);
868 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
869 NT_STATUS_HAVE_NO_MEMORY(sam2);
872 /* And put into the talloc tree */
873 talloc_steal(sam2, sam);
874 r->out.validation->sam2 = sam2;
880 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
883 NT_STATUS_NOT_OK_RETURN(nt_status);
885 r->out.validation->sam3 = sam3;
891 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
894 NT_STATUS_NOT_OK_RETURN(nt_status);
896 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
897 NT_STATUS_HAVE_NO_MEMORY(sam6);
898 sam6->base = sam3->base;
900 sam6->sidcount = sam3->sidcount;
901 sam6->sids = sam3->sids;
903 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
904 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
905 sam->account_name.string, sam6->dns_domainname.string);
906 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
907 /* And put into the talloc tree */
908 talloc_steal(sam6, sam3);
910 r->out.validation->sam6 = sam6;
914 return NT_STATUS_INVALID_INFO_CLASS;
917 netlogon_creds_encrypt_samlogon_validation(creds,
918 r->in.validation_level,
921 /* TODO: Describe and deal with these flags */
927 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
928 struct netr_LogonSamLogonEx *r)
931 struct netlogon_creds_CredentialState *creds;
933 *r->out.authoritative = 1;
935 nt_status = dcesrv_netr_LogonSamLogon_check(r);
936 if (!NT_STATUS_IS_OK(nt_status)) {
940 nt_status = schannel_get_creds_state(mem_ctx,
941 dce_call->conn->dce_ctx->lp_ctx,
942 r->in.computer_name, &creds);
943 if (!NT_STATUS_IS_OK(nt_status)) {
947 if (!dce_call->conn->auth_state.auth_info ||
948 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
949 return NT_STATUS_ACCESS_DENIED;
951 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
955 netr_LogonSamLogonWithFlags
958 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
959 struct netr_LogonSamLogonWithFlags *r)
962 struct netlogon_creds_CredentialState *creds;
963 struct netr_LogonSamLogonEx r2;
965 struct netr_Authenticator *return_authenticator;
969 r2.in.server_name = r->in.server_name;
970 r2.in.computer_name = r->in.computer_name;
971 r2.in.logon_level = r->in.logon_level;
972 r2.in.logon = r->in.logon;
973 r2.in.validation_level = r->in.validation_level;
974 r2.in.flags = r->in.flags;
975 r2.out.validation = r->out.validation;
976 r2.out.authoritative = r->out.authoritative;
977 r2.out.flags = r->out.flags;
979 *r->out.authoritative = 1;
981 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
982 if (!NT_STATUS_IS_OK(nt_status)) {
986 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
987 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
989 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
992 r->in.credential, return_authenticator,
994 NT_STATUS_NOT_OK_RETURN(nt_status);
996 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
998 r->out.return_authenticator = return_authenticator;
1006 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1007 struct netr_LogonSamLogon *r)
1009 struct netr_LogonSamLogonWithFlags r2;
1015 r2.in.server_name = r->in.server_name;
1016 r2.in.computer_name = r->in.computer_name;
1017 r2.in.credential = r->in.credential;
1018 r2.in.return_authenticator = r->in.return_authenticator;
1019 r2.in.logon_level = r->in.logon_level;
1020 r2.in.logon = r->in.logon;
1021 r2.in.validation_level = r->in.validation_level;
1022 r2.in.flags = &flags;
1023 r2.out.validation = r->out.validation;
1024 r2.out.authoritative = r->out.authoritative;
1025 r2.out.flags = &flags;
1027 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1029 r->out.return_authenticator = r2.out.return_authenticator;
1038 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1039 struct netr_LogonSamLogoff *r)
1041 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1049 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1050 struct netr_DatabaseDeltas *r)
1052 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1059 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1060 struct netr_DatabaseSync2 *r)
1062 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1063 return NT_STATUS_NOT_IMPLEMENTED;
1070 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1071 struct netr_DatabaseSync *r)
1073 struct netr_DatabaseSync2 r2;
1078 r2.in.logon_server = r->in.logon_server;
1079 r2.in.computername = r->in.computername;
1080 r2.in.credential = r->in.credential;
1081 r2.in.database_id = r->in.database_id;
1082 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1083 r2.in.sync_context = r->in.sync_context;
1084 r2.out.sync_context = r->out.sync_context;
1085 r2.out.delta_enum_array = r->out.delta_enum_array;
1086 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1088 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1097 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1098 struct netr_AccountDeltas *r)
1100 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1101 return NT_STATUS_NOT_IMPLEMENTED;
1108 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1109 struct netr_AccountSync *r)
1111 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1112 return NT_STATUS_NOT_IMPLEMENTED;
1119 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1120 struct netr_GetDcName *r)
1122 const char * const attrs[] = { NULL };
1123 struct ldb_context *sam_ctx;
1124 struct ldb_message **res;
1125 struct ldb_dn *domain_dn;
1130 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1131 * that the domainname needs to be a valid netbios domain
1132 * name, if it is not NULL.
1134 if (r->in.domainname) {
1135 const char *dot = strchr(r->in.domainname, '.');
1136 size_t len = strlen(r->in.domainname);
1138 if (dot || len > 15) {
1139 return WERR_DCNOTFOUND;
1143 * TODO: Should we also varify that only valid
1144 * netbios name characters are used?
1148 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1149 dce_call->conn->dce_ctx->lp_ctx,
1150 dce_call->conn->auth_state.session_info, 0);
1151 if (sam_ctx == NULL) {
1152 return WERR_DS_UNAVAILABLE;
1155 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1157 if (domain_dn == NULL) {
1158 return WERR_NO_SUCH_DOMAIN;
1161 ret = gendb_search_dn(sam_ctx, mem_ctx,
1162 domain_dn, &res, attrs);
1164 return WERR_NO_SUCH_DOMAIN;
1167 /* TODO: - return real IP address
1168 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1170 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1171 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1172 W_ERROR_HAVE_NO_MEMORY(dcname);
1174 *r->out.dcname = dcname;
1180 netr_LogonControl2Ex
1182 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1183 struct netr_LogonControl2Ex *r)
1185 return WERR_NOT_SUPPORTED;
1192 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1193 struct netr_LogonControl *r)
1195 struct netr_LogonControl2Ex r2;
1198 if (r->in.level == 0x00000001) {
1201 r2.in.logon_server = r->in.logon_server;
1202 r2.in.function_code = r->in.function_code;
1203 r2.in.level = r->in.level;
1205 r2.out.query = r->out.query;
1207 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1208 } else if (r->in.level == 0x00000002) {
1209 werr = WERR_NOT_SUPPORTED;
1211 werr = WERR_UNKNOWN_LEVEL;
1221 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1222 struct netr_LogonControl2 *r)
1224 struct netr_LogonControl2Ex r2;
1229 r2.in.logon_server = r->in.logon_server;
1230 r2.in.function_code = r->in.function_code;
1231 r2.in.level = r->in.level;
1232 r2.in.data = r->in.data;
1233 r2.out.query = r->out.query;
1235 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1240 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1241 struct ldb_context *sam_ctx,
1242 struct netr_DomainTrustList *trusts,
1243 uint32_t trust_flags);
1248 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1249 struct netr_GetAnyDCName *r)
1251 struct netr_DomainTrustList *trusts;
1252 struct ldb_context *sam_ctx;
1253 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1257 *r->out.dcname = NULL;
1259 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1260 /* if the domainname parameter wasn't set assume our domain */
1261 r->in.domainname = lpcfg_workgroup(lp_ctx);
1264 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1265 dce_call->conn->auth_state.session_info, 0);
1266 if (sam_ctx == NULL) {
1267 return WERR_DS_UNAVAILABLE;
1270 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1271 /* well we asked for a DC of our own domain */
1272 if (samdb_is_pdc(sam_ctx)) {
1273 /* we are the PDC of the specified domain */
1274 return WERR_NO_SUCH_DOMAIN;
1277 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1278 lpcfg_netbios_name(lp_ctx));
1279 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1284 /* Okay, now we have to consider the trusted domains */
1286 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1287 W_ERROR_HAVE_NO_MEMORY(trusts);
1291 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1292 NETR_TRUST_FLAG_INBOUND
1293 | NETR_TRUST_FLAG_OUTBOUND);
1294 W_ERROR_NOT_OK_RETURN(werr);
1296 for (i = 0; i < trusts->count; i++) {
1297 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1298 /* FIXME: Here we need to find a DC for the specified
1299 * trusted domain. */
1301 /* return WERR_OK; */
1302 return WERR_NO_SUCH_DOMAIN;
1306 return WERR_NO_SUCH_DOMAIN;
1313 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1314 struct netr_DatabaseRedo *r)
1316 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1321 netr_NetrEnumerateTrustedDomains
1323 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1324 struct netr_NetrEnumerateTrustedDomains *r)
1326 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1331 netr_LogonGetCapabilities
1333 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1334 struct netr_LogonGetCapabilities *r)
1336 struct netlogon_creds_CredentialState *creds;
1339 status = dcesrv_netr_creds_server_step_check(dce_call,
1341 r->in.computer_name,
1343 r->out.return_authenticator,
1345 if (!NT_STATUS_IS_OK(status)) {
1346 DEBUG(0,(__location__ " Bad credentials - error\n"));
1348 NT_STATUS_NOT_OK_RETURN(status);
1350 if (r->in.query_level != 1) {
1351 return NT_STATUS_NOT_SUPPORTED;
1354 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1356 return NT_STATUS_OK;
1361 netr_NETRLOGONSETSERVICEBITS
1363 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1364 struct netr_NETRLOGONSETSERVICEBITS *r)
1366 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1371 netr_LogonGetTrustRid
1373 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1374 struct netr_LogonGetTrustRid *r)
1376 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1381 netr_NETRLOGONCOMPUTESERVERDIGEST
1383 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1384 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1386 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1391 netr_NETRLOGONCOMPUTECLIENTDIGEST
1393 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1394 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1396 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1404 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1405 struct netr_DsRGetSiteName *r)
1407 struct ldb_context *sam_ctx;
1408 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1410 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1411 dce_call->conn->auth_state.session_info, 0);
1412 if (sam_ctx == NULL) {
1413 return WERR_DS_UNAVAILABLE;
1417 * We assume to be a DC when we get called over NETLOGON. Hence we
1418 * get our site name always by using "samdb_server_site_name()"
1419 * and not "samdb_client_site_name()".
1421 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1422 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1429 fill in a netr_OneDomainInfo from a ldb search result
1431 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1432 struct loadparm_context *lp_ctx,
1433 struct ldb_context *sam_ctx,
1434 struct ldb_message *res,
1435 struct netr_OneDomainInfo *info,
1436 bool is_local, bool is_trust_list)
1440 if (is_trust_list) {
1441 /* w2k8 only fills this on trusted domains */
1442 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1443 info->trust_extension.length = 16;
1444 info->trust_extension.info->flags =
1445 NETR_TRUST_FLAG_TREEROOT |
1446 NETR_TRUST_FLAG_IN_FOREST |
1447 NETR_TRUST_FLAG_PRIMARY |
1448 NETR_TRUST_FLAG_NATIVE;
1450 info->trust_extension.info->parent_index = 0; /* should be index into array
1452 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1453 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1456 if (is_trust_list) {
1457 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1458 info->dns_forestname.string = NULL;
1460 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1461 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1462 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1463 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1467 info->domainname.string = lpcfg_workgroup(lp_ctx);
1468 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1469 info->domain_guid = samdb_result_guid(res, "objectGUID");
1470 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1472 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1473 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1474 info->domain_guid = samdb_result_guid(res, "objectGUID");
1475 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1477 if (!is_trust_list) {
1478 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1481 return NT_STATUS_OK;
1485 netr_LogonGetDomainInfo
1486 this is called as part of the ADS domain logon procedure.
1488 It has an important role in convaying details about the client, such
1489 as Operating System, Version, Service Pack etc.
1491 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1492 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1494 struct netlogon_creds_CredentialState *creds;
1495 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1496 "securityIdentifier", "trustPartner", NULL };
1497 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1498 "msDS-SupportedEncryptionTypes", NULL };
1499 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1500 struct ldb_context *sam_ctx;
1501 struct ldb_message **res1, **res2, **res3, *new_msg;
1502 struct ldb_dn *workstation_dn;
1503 struct netr_DomainInformation *domain_info;
1504 struct netr_LsaPolicyInformation *lsa_policy_info;
1505 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1506 bool update_dns_hostname = true;
1510 status = dcesrv_netr_creds_server_step_check(dce_call,
1512 r->in.computer_name,
1514 r->out.return_authenticator,
1516 if (!NT_STATUS_IS_OK(status)) {
1517 DEBUG(0,(__location__ " Bad credentials - error\n"));
1519 NT_STATUS_NOT_OK_RETURN(status);
1521 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1522 dce_call->conn->dce_ctx->lp_ctx,
1523 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1524 if (sam_ctx == NULL) {
1525 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1528 switch (r->in.level) {
1529 case 1: /* Domain information */
1531 if (r->in.query->workstation_info == NULL) {
1532 return NT_STATUS_INVALID_PARAMETER;
1535 /* Prepares the workstation DN */
1536 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1537 dom_sid_string(mem_ctx, creds->sid));
1538 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1540 /* Lookup for attributes in workstation object */
1541 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1544 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1547 /* Gets the sam account name which is checked against the DNS
1548 * hostname parameter. */
1549 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1552 if (sam_account_name == NULL) {
1553 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1557 * Checks that the sam account name without a possible "$"
1558 * matches as prefix with the DNS hostname in the workstation
1561 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1562 strcspn(sam_account_name, "$"));
1563 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1564 if (r->in.query->workstation_info->dns_hostname != NULL) {
1565 prefix2 = talloc_strndup(mem_ctx,
1566 r->in.query->workstation_info->dns_hostname,
1567 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1568 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1570 if (strcasecmp(prefix1, prefix2) != 0) {
1571 update_dns_hostname = false;
1574 update_dns_hostname = false;
1577 /* Gets the old DNS hostname */
1578 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1583 * Updates the DNS hostname when the client wishes that the
1584 * server should handle this for him
1585 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1586 * obviously only checked when we do already have a
1588 * See MS-NRPC section 3.5.4.3.9
1590 if ((old_dns_hostname != NULL) &&
1591 (r->in.query->workstation_info->workstation_flags
1592 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1593 update_dns_hostname = false;
1596 /* Gets host information and put them into our directory */
1598 new_msg = ldb_msg_new(mem_ctx);
1599 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1601 new_msg->dn = workstation_dn;
1603 /* Sets the OS name */
1605 if (r->in.query->workstation_info->os_name.string == NULL) {
1606 return NT_STATUS_INVALID_PARAMETER;
1609 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1610 r->in.query->workstation_info->os_name.string);
1611 if (ret != LDB_SUCCESS) {
1612 return NT_STATUS_NO_MEMORY;
1616 * Sets information from "os_version". On an empty structure
1617 * the values are cleared.
1619 if (r->in.query->workstation_info->os_version.os != NULL) {
1620 struct netr_OsVersionInfoEx *os_version;
1621 const char *os_version_str;
1623 os_version = &r->in.query->workstation_info->os_version.os->os;
1625 if (os_version->CSDVersion == NULL) {
1626 return NT_STATUS_INVALID_PARAMETER;
1629 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1630 os_version->MajorVersion,
1631 os_version->MinorVersion,
1632 os_version->BuildNumber);
1633 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1635 ret = ldb_msg_add_string(new_msg,
1636 "operatingSystemServicePack",
1637 os_version->CSDVersion);
1638 if (ret != LDB_SUCCESS) {
1639 return NT_STATUS_NO_MEMORY;
1642 ret = ldb_msg_add_string(new_msg,
1643 "operatingSystemVersion",
1645 if (ret != LDB_SUCCESS) {
1646 return NT_STATUS_NO_MEMORY;
1649 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1650 "operatingSystemServicePack");
1651 if (ret != LDB_SUCCESS) {
1652 return NT_STATUS_NO_MEMORY;
1655 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1656 "operatingSystemVersion");
1657 if (ret != LDB_SUCCESS) {
1658 return NT_STATUS_NO_MEMORY;
1663 * If the boolean "update_dns_hostname" remained true, then we
1664 * are fine to start the update.
1666 if (update_dns_hostname) {
1667 ret = ldb_msg_add_string(new_msg,
1669 r->in.query->workstation_info->dns_hostname);
1670 if (ret != LDB_SUCCESS) {
1671 return NT_STATUS_NO_MEMORY;
1674 /* This manual "servicePrincipalName" generation is
1675 * still needed! Since the update in the samldb LDB
1676 * module does only work if the entries already exist
1677 * which isn't always the case. */
1678 ret = ldb_msg_add_string(new_msg,
1679 "servicePrincipalName",
1680 talloc_asprintf(new_msg, "HOST/%s",
1681 r->in.computer_name));
1682 if (ret != LDB_SUCCESS) {
1683 return NT_STATUS_NO_MEMORY;
1686 ret = ldb_msg_add_string(new_msg,
1687 "servicePrincipalName",
1688 talloc_asprintf(new_msg, "HOST/%s",
1689 r->in.query->workstation_info->dns_hostname));
1690 if (ret != LDB_SUCCESS) {
1691 return NT_STATUS_NO_MEMORY;
1695 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1696 DEBUG(3,("Impossible to update samdb: %s\n",
1697 ldb_errstring(sam_ctx)));
1700 talloc_free(new_msg);
1702 /* Writes back the domain information */
1704 /* We need to do two searches. The first will pull our primary
1705 domain and the second will pull any trusted domains. Our
1706 primary domain is also a "trusted" domain, so we need to
1707 put the primary domain into the lists of returned trusts as
1709 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1712 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1715 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1716 "(objectClass=trustedDomain)");
1718 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1721 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1722 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1724 ZERO_STRUCTP(domain_info);
1726 /* Informations about the local and trusted domains */
1728 status = fill_one_domain_info(mem_ctx,
1729 dce_call->conn->dce_ctx->lp_ctx,
1730 sam_ctx, res2[0], &domain_info->primary_domain,
1732 NT_STATUS_NOT_OK_RETURN(status);
1734 domain_info->trusted_domain_count = ret3 + 1;
1735 domain_info->trusted_domains = talloc_array(mem_ctx,
1736 struct netr_OneDomainInfo,
1737 domain_info->trusted_domain_count);
1738 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1740 for (i=0;i<ret3;i++) {
1741 status = fill_one_domain_info(mem_ctx,
1742 dce_call->conn->dce_ctx->lp_ctx,
1744 &domain_info->trusted_domains[i],
1746 NT_STATUS_NOT_OK_RETURN(status);
1749 status = fill_one_domain_info(mem_ctx,
1750 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1751 &domain_info->trusted_domains[i], true, true);
1752 NT_STATUS_NOT_OK_RETURN(status);
1754 /* Sets the supported encryption types */
1755 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1756 "msDS-SupportedEncryptionTypes",
1757 default_supported_enc_types);
1759 /* Other host domain information */
1761 lsa_policy_info = talloc(mem_ctx,
1762 struct netr_LsaPolicyInformation);
1763 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1764 ZERO_STRUCTP(lsa_policy_info);
1766 domain_info->lsa_policy = *lsa_policy_info;
1768 /* The DNS hostname is only returned back when there is a chance
1770 if ((r->in.query->workstation_info->workstation_flags
1771 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1772 domain_info->dns_hostname.string = old_dns_hostname;
1774 domain_info->dns_hostname.string = NULL;
1777 domain_info->workstation_flags =
1778 r->in.query->workstation_info->workstation_flags & (
1779 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1781 r->out.info->domain_info = domain_info;
1783 case 2: /* LSA policy information - not used at the moment */
1784 lsa_policy_info = talloc(mem_ctx,
1785 struct netr_LsaPolicyInformation);
1786 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1787 ZERO_STRUCTP(lsa_policy_info);
1789 r->out.info->lsa_policy_info = lsa_policy_info;
1792 return NT_STATUS_INVALID_LEVEL;
1796 return NT_STATUS_OK;
1801 netr_ServerPasswordGet
1803 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1804 struct netr_ServerPasswordGet *r)
1806 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1811 netr_NETRLOGONSENDTOSAM
1813 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1814 struct netr_NETRLOGONSENDTOSAM *r)
1816 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1821 netr_DsRGetDCNameEx2
1823 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1824 TALLOC_CTX *mem_ctx,
1825 struct netr_DsRGetDCNameEx2 *r)
1827 struct ldb_context *sam_ctx;
1828 struct netr_DsRGetDCNameInfo *info;
1829 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1830 const struct tsocket_address *remote_address;
1832 const char *server_site_name;
1834 struct netlogon_samlogon_response response;
1836 const char *dc_name = NULL;
1837 const char *domain_name = NULL;
1838 struct interface *ifaces;
1841 ZERO_STRUCTP(r->out.info);
1843 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1844 dce_call->conn->auth_state.session_info, 0);
1845 if (sam_ctx == NULL) {
1846 return WERR_DS_UNAVAILABLE;
1849 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1850 if (tsocket_address_is_inet(remote_address, "ip")) {
1851 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1852 W_ERROR_HAVE_NO_MEMORY(addr);
1855 /* "server_unc" is ignored by w2k3 */
1857 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1858 return WERR_INVALID_FLAGS;
1861 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1862 r->in.flags & DS_PDC_REQUIRED &&
1863 r->in.flags & DS_KDC_REQUIRED) {
1864 return WERR_INVALID_FLAGS;
1866 if (r->in.flags & DS_IS_FLAT_NAME &&
1867 r->in.flags & DS_IS_DNS_NAME) {
1868 return WERR_INVALID_FLAGS;
1870 if (r->in.flags & DS_RETURN_DNS_NAME &&
1871 r->in.flags & DS_RETURN_FLAT_NAME) {
1872 return WERR_INVALID_FLAGS;
1874 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1875 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1876 return WERR_INVALID_FLAGS;
1879 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1881 (DS_DIRECTORY_SERVICE_REQUIRED |
1882 DS_DIRECTORY_SERVICE_PREFERRED |
1883 DS_GC_SERVER_REQUIRED |
1886 return WERR_INVALID_FLAGS;
1889 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1891 return WERR_INVALID_FLAGS;
1894 /* Proof server site parameter "site_name" if it was specified */
1895 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1896 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1897 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1898 server_site_name) != 0)) {
1899 return WERR_NO_SUCH_DOMAIN;
1902 guid_str = r->in.domain_guid != NULL ?
1903 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1905 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1909 r->in.client_account,
1911 NETLOGON_NT_VERSION_5EX_WITH_IP,
1912 lp_ctx, &response, true);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 return ntstatus_to_werror(status);
1918 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1919 * (O) flag when the returned forest name is in DNS format. This is here
1920 * always the case (see below).
1922 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1924 if (r->in.flags & DS_RETURN_DNS_NAME) {
1925 dc_name = response.data.nt5_ex.pdc_dns_name;
1926 domain_name = response.data.nt5_ex.dns_domain;
1928 * According to MS-NRPC 2.2.1.2.1 we should set the
1929 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1930 * the returned information is in DNS form.
1932 response.data.nt5_ex.server_type |=
1933 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1934 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1935 dc_name = response.data.nt5_ex.pdc_name;
1936 domain_name = response.data.nt5_ex.domain_name;
1940 * TODO: autodetect what we need to return
1941 * based on the given arguments
1943 dc_name = response.data.nt5_ex.pdc_name;
1944 domain_name = response.data.nt5_ex.domain_name;
1947 if (!dc_name || !dc_name[0]) {
1948 return WERR_NO_SUCH_DOMAIN;
1951 if (!domain_name || !domain_name[0]) {
1952 return WERR_NO_SUCH_DOMAIN;
1955 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1956 W_ERROR_HAVE_NO_MEMORY(info);
1957 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1958 dc_name[0] == '\\'? "\\\\":"",
1959 talloc_strdup(mem_ctx, dc_name));
1960 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1962 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1963 pdc_ip = iface_list_best_ip(ifaces, addr);
1964 if (pdc_ip == NULL) {
1965 pdc_ip = "127.0.0.1";
1967 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1968 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1969 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1970 info->domain_guid = response.data.nt5_ex.domain_uuid;
1971 info->domain_name = domain_name;
1972 info->forest_name = response.data.nt5_ex.forest;
1973 info->dc_flags = response.data.nt5_ex.server_type;
1974 if (r->in.flags & DS_RETURN_DNS_NAME) {
1975 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
1976 * returned if we are returning info->dc_unc containing a FQDN.
1977 * This attribute is called DomainControllerName in the specs,
1978 * it seems that we decide to return FQDN or netbios depending on
1979 * DS_RETURN_DNS_NAME.
1981 info->dc_flags |= DS_DNS_CONTROLLER;
1983 info->dc_site_name = response.data.nt5_ex.server_site;
1984 info->client_site_name = response.data.nt5_ex.client_site;
1986 *r->out.info = info;
1994 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1995 struct netr_DsRGetDCNameEx *r)
1997 struct netr_DsRGetDCNameEx2 r2;
2002 r2.in.server_unc = r->in.server_unc;
2003 r2.in.client_account = NULL;
2005 r2.in.domain_guid = r->in.domain_guid;
2006 r2.in.domain_name = r->in.domain_name;
2007 r2.in.site_name = r->in.site_name;
2008 r2.in.flags = r->in.flags;
2009 r2.out.info = r->out.info;
2011 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2019 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2020 struct netr_DsRGetDCName *r)
2022 struct netr_DsRGetDCNameEx2 r2;
2027 r2.in.server_unc = r->in.server_unc;
2028 r2.in.client_account = NULL;
2030 r2.in.domain_name = r->in.domain_name;
2031 r2.in.domain_guid = r->in.domain_guid;
2033 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2034 r2.in.flags = r->in.flags;
2035 r2.out.info = r->out.info;
2037 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2042 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2044 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2045 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2047 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2052 netr_NetrEnumerateTrustedDomainsEx
2054 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2055 struct netr_NetrEnumerateTrustedDomainsEx *r)
2057 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2062 netr_DsRAddressToSitenamesExW
2064 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2065 struct netr_DsRAddressToSitenamesExW *r)
2067 struct ldb_context *sam_ctx;
2068 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2069 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2070 sa_family_t sin_family;
2071 struct sockaddr_in *addr;
2073 struct sockaddr_in6 *addr6;
2074 char addr_str[INET6_ADDRSTRLEN];
2076 char addr_str[INET_ADDRSTRLEN];
2082 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2083 dce_call->conn->auth_state.session_info, 0);
2084 if (sam_ctx == NULL) {
2085 return WERR_DS_UNAVAILABLE;
2088 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2089 W_ERROR_HAVE_NO_MEMORY(ctr);
2093 ctr->count = r->in.count;
2094 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2095 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2096 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2097 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2099 for (i=0; i<ctr->count; i++) {
2100 ctr->sitename[i].string = NULL;
2101 ctr->subnetname[i].string = NULL;
2103 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2106 /* The first two byte of the buffer are reserved for the
2107 * "sin_family" but for now only the first one is used. */
2108 sin_family = r->in.addresses[i].buffer[0];
2110 switch (sin_family) {
2112 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2115 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2116 res = inet_ntop(AF_INET, &addr->sin_addr,
2117 addr_str, sizeof(addr_str));
2121 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2124 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2125 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2126 addr_str, sizeof(addr_str));
2137 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2141 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2142 ctr->subnetname[i].string = subnet_name;
2150 netr_DsRAddressToSitenamesW
2152 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2153 struct netr_DsRAddressToSitenamesW *r)
2155 struct netr_DsRAddressToSitenamesExW r2;
2156 struct netr_DsRAddressToSitenamesWCtr *ctr;
2162 r2.in.server_name = r->in.server_name;
2163 r2.in.count = r->in.count;
2164 r2.in.addresses = r->in.addresses;
2166 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2167 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2169 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2170 W_ERROR_HAVE_NO_MEMORY(ctr);
2174 ctr->count = r->in.count;
2175 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2176 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2178 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2180 for (i=0; i<ctr->count; i++) {
2181 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2189 netr_DsrGetDcSiteCoverageW
2191 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2192 struct netr_DsrGetDcSiteCoverageW *r)
2194 struct ldb_context *sam_ctx;
2195 struct DcSitesCtr *ctr;
2196 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2198 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2199 dce_call->conn->auth_state.session_info, 0);
2200 if (sam_ctx == NULL) {
2201 return WERR_DS_UNAVAILABLE;
2204 ctr = talloc(mem_ctx, struct DcSitesCtr);
2205 W_ERROR_HAVE_NO_MEMORY(ctr);
2209 /* For now only return our default site */
2211 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2212 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2213 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2214 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2220 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2221 struct ldb_context *sam_ctx,
2222 struct netr_DomainTrustList *trusts,
2223 uint32_t trust_flags)
2225 struct ldb_dn *system_dn;
2226 struct ldb_message **dom_res = NULL;
2227 const char *trust_attrs[] = { "flatname", "trustPartner",
2228 "securityIdentifier", "trustDirection",
2229 "trustType", "trustAttributes", NULL };
2234 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2235 NETR_TRUST_FLAG_OUTBOUND))) {
2236 return WERR_INVALID_FLAGS;
2239 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2240 ldb_get_default_basedn(sam_ctx),
2241 "(&(objectClass=container)(cn=System))");
2243 return WERR_GENERAL_FAILURE;
2246 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2247 &dom_res, trust_attrs,
2248 "(objectclass=trustedDomain)");
2250 for (i = 0; i < ret; i++) {
2251 unsigned int trust_dir;
2254 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2255 "trustDirection", 0);
2257 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2258 flags |= NETR_TRUST_FLAG_INBOUND;
2260 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2261 flags |= NETR_TRUST_FLAG_OUTBOUND;
2264 if (!(flags & trust_flags)) {
2265 /* this trust direction was not requested */
2270 trusts->array = talloc_realloc(trusts, trusts->array,
2271 struct netr_DomainTrust,
2273 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2275 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2276 if (!trusts->array[n].netbios_name) {
2277 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2278 "without flatname\n",
2279 ldb_dn_get_linearized(dom_res[i]->dn)));
2282 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2284 trusts->array[n].trust_flags = flags;
2285 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2286 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2287 /* TODO: find if we have parent in the list */
2288 trusts->array[n].parent_index = 0;
2291 trusts->array[n].trust_type =
2292 ldb_msg_find_attr_as_uint(dom_res[i],
2294 trusts->array[n].trust_attributes =
2295 ldb_msg_find_attr_as_uint(dom_res[i],
2296 "trustAttributes", 0);
2298 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2299 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2300 struct dom_sid zero_sid;
2301 ZERO_STRUCT(zero_sid);
2302 trusts->array[n].sid =
2303 dom_sid_dup(trusts, &zero_sid);
2305 trusts->array[n].sid =
2306 samdb_result_dom_sid(trusts, dom_res[i],
2307 "securityIdentifier");
2309 trusts->array[n].guid = GUID_zero();
2311 trusts->count = n + 1;
2314 talloc_free(dom_res);
2319 netr_DsrEnumerateDomainTrusts
2321 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2322 TALLOC_CTX *mem_ctx,
2323 struct netr_DsrEnumerateDomainTrusts *r)
2325 struct netr_DomainTrustList *trusts;
2326 struct ldb_context *sam_ctx;
2328 struct ldb_message **dom_res;
2329 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2330 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2331 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2335 if (r->in.trust_flags & 0xFFFFFE00) {
2336 return WERR_INVALID_FLAGS;
2339 /* TODO: turn to hard check once we are sure this is 100% correct */
2340 if (!r->in.server_name) {
2341 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2342 "But received NULL!\n", dnsdomain));
2344 p = strchr(r->in.server_name, '.');
2346 DEBUG(3, ("Invalid domain! Expected name in domain "
2347 "[%s]. But received [%s]!\n",
2348 dnsdomain, r->in.server_name));
2349 p = r->in.server_name;
2353 if (strcasecmp(p, dnsdomain)) {
2354 DEBUG(3, ("Invalid domain! Expected name in domain "
2355 "[%s]. But received [%s]!\n",
2356 dnsdomain, r->in.server_name));
2360 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2361 W_ERROR_HAVE_NO_MEMORY(trusts);
2364 r->out.trusts = trusts;
2366 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2367 dce_call->conn->auth_state.session_info, 0);
2368 if (sam_ctx == NULL) {
2369 return WERR_GENERAL_FAILURE;
2372 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2373 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2375 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2376 trusts, r->in.trust_flags);
2377 W_ERROR_NOT_OK_RETURN(werr);
2380 /* NOTE: we currently are always the root of the forest */
2381 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2382 uint32_t n = trusts->count;
2384 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2385 &dom_res, dom_attrs);
2387 return WERR_GENERAL_FAILURE;
2390 trusts->count = n + 1;
2391 trusts->array = talloc_realloc(trusts, trusts->array,
2392 struct netr_DomainTrust,
2394 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2396 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2397 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2398 trusts->array[n].trust_flags =
2399 NETR_TRUST_FLAG_NATIVE |
2400 NETR_TRUST_FLAG_TREEROOT |
2401 NETR_TRUST_FLAG_IN_FOREST |
2402 NETR_TRUST_FLAG_PRIMARY;
2403 /* we are always the root domain for now */
2404 trusts->array[n].parent_index = 0;
2405 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2406 trusts->array[n].trust_attributes = 0;
2407 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2410 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2412 talloc_free(dom_res);
2420 netr_DsrDeregisterDNSHostRecords
2422 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2423 struct netr_DsrDeregisterDNSHostRecords *r)
2425 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2430 netr_ServerTrustPasswordsGet
2432 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2433 struct netr_ServerTrustPasswordsGet *r)
2435 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2439 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2440 struct ldb_context *sam_ctx,
2441 struct loadparm_context *lp_ctx,
2442 struct lsa_ForestTrustInformation *info)
2444 struct lsa_ForestTrustDomainInfo *domain_info;
2445 struct lsa_ForestTrustRecord *e;
2446 struct ldb_message **dom_res;
2447 const char * const dom_attrs[] = { "objectSid", NULL };
2450 /* we need to provide 2 entries:
2451 * 1. the Root Forest name
2452 * 2. the Domain Information
2456 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2457 W_ERROR_HAVE_NO_MEMORY(info->entries);
2459 /* Forest root info */
2460 e = talloc(info, struct lsa_ForestTrustRecord);
2461 W_ERROR_HAVE_NO_MEMORY(e);
2464 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2465 e->time = 0; /* so far always 0 in trces. */
2466 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2468 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2470 info->entries[0] = e;
2473 e = talloc(info, struct lsa_ForestTrustRecord);
2474 W_ERROR_HAVE_NO_MEMORY(e);
2476 /* get our own domain info */
2477 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2479 return WERR_GENERAL_FAILURE;
2482 /* TODO: check if disabled and set flags accordingly */
2484 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2485 e->time = 0; /* so far always 0 in traces. */
2487 domain_info = &e->forest_trust_data.domain_info;
2488 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2490 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2491 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2493 info->entries[1] = e;
2495 talloc_free(dom_res);
2501 netr_DsRGetForestTrustInformation
2503 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2504 TALLOC_CTX *mem_ctx,
2505 struct netr_DsRGetForestTrustInformation *r)
2507 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2508 struct lsa_ForestTrustInformation *info, **info_ptr;
2509 struct ldb_context *sam_ctx;
2512 if (r->in.flags & 0xFFFFFFFE) {
2513 return WERR_INVALID_FLAGS;
2516 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2517 dce_call->conn->auth_state.session_info, 0);
2518 if (sam_ctx == NULL) {
2519 return WERR_GENERAL_FAILURE;
2522 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2523 if (!samdb_is_pdc(sam_ctx)) {
2524 return WERR_NERR_NOTPRIMARY;
2527 if (r->in.trusted_domain_name == NULL) {
2528 return WERR_INVALID_FLAGS;
2531 /* TODO: establish an schannel connection with
2532 * r->in.trusted_domain_name and perform a
2533 * netr_GetForestTrustInformation call against it */
2535 /* for now return not implementd */
2536 return WERR_CALL_NOT_IMPLEMENTED;
2539 /* TODO: check r->in.server_name is our name */
2541 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2542 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2544 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2545 W_ERROR_HAVE_NO_MEMORY(info);
2547 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2548 W_ERROR_NOT_OK_RETURN(werr);
2551 r->out.forest_trust_info = info_ptr;
2558 netr_GetForestTrustInformation
2560 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2561 TALLOC_CTX *mem_ctx,
2562 struct netr_GetForestTrustInformation *r)
2564 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2565 struct netlogon_creds_CredentialState *creds;
2566 struct lsa_ForestTrustInformation *info, **info_ptr;
2567 struct ldb_context *sam_ctx;
2571 status = dcesrv_netr_creds_server_step_check(dce_call,
2573 r->in.computer_name,
2575 r->out.return_authenticator,
2577 if (!NT_STATUS_IS_OK(status)) {
2581 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2582 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2583 return NT_STATUS_NOT_IMPLEMENTED;
2586 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2587 dce_call->conn->auth_state.session_info, 0);
2588 if (sam_ctx == NULL) {
2589 return NT_STATUS_INTERNAL_ERROR;
2592 /* TODO: check r->in.server_name is our name */
2594 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2596 return NT_STATUS_NO_MEMORY;
2598 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2600 return NT_STATUS_NO_MEMORY;
2603 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2604 if (!W_ERROR_IS_OK(werr)) {
2605 return werror_to_ntstatus(werr);
2609 r->out.forest_trust_info = info_ptr;
2611 return NT_STATUS_OK;
2616 netr_ServerGetTrustInfo
2618 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2619 struct netr_ServerGetTrustInfo *r)
2621 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2627 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2628 struct netr_Unused47 *r)
2630 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2634 struct netr_dnsupdate_RODC_state {
2635 struct dcesrv_call_state *dce_call;
2636 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2637 struct dnsupdate_RODC *r2;
2641 called when the forwarded RODC dns update request is finished
2643 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2645 struct netr_dnsupdate_RODC_state *st =
2646 tevent_req_callback_data(subreq,
2647 struct netr_dnsupdate_RODC_state);
2650 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2651 TALLOC_FREE(subreq);
2652 if (!NT_STATUS_IS_OK(status)) {
2653 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2654 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2657 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2659 status = dcesrv_reply(st->dce_call);
2660 if (!NT_STATUS_IS_OK(status)) {
2661 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2666 netr_DsrUpdateReadOnlyServerDnsRecords
2668 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2669 TALLOC_CTX *mem_ctx,
2670 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2672 struct netlogon_creds_CredentialState *creds;
2674 struct dcerpc_binding_handle *binding_handle;
2675 struct netr_dnsupdate_RODC_state *st;
2676 struct tevent_req *subreq;
2678 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2680 r->in.computer_name,
2682 r->out.return_authenticator,
2684 NT_STATUS_NOT_OK_RETURN(nt_status);
2686 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2687 return NT_STATUS_ACCESS_DENIED;
2690 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2691 NT_STATUS_HAVE_NO_MEMORY(st);
2693 st->dce_call = dce_call;
2695 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2696 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2698 st->r2->in.dom_sid = creds->sid;
2699 st->r2->in.site_name = r->in.site_name;
2700 st->r2->in.dns_ttl = r->in.dns_ttl;
2701 st->r2->in.dns_names = r->in.dns_names;
2702 st->r2->out.dns_names = r->out.dns_names;
2704 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2705 "dnsupdate", &ndr_table_irpc);
2706 if (binding_handle == NULL) {
2707 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2708 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2709 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2712 /* forward the call */
2713 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2714 binding_handle, st->r2);
2715 NT_STATUS_HAVE_NO_MEMORY(subreq);
2717 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2719 /* setup the callback */
2720 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2722 return NT_STATUS_OK;
2726 /* include the generated boilerplate */
2727 #include "librpc/gen_ndr/ndr_netlogon_s.c"