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
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc.h"
35 #include "cldap_server/cldap_server.h"
36 #include "lib/tsocket/tsocket.h"
38 struct netlogon_server_pipe_state {
39 struct netr_Credential client_challenge;
40 struct netr_Credential server_challenge;
43 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
44 struct netr_ServerReqChallenge *r)
46 struct netlogon_server_pipe_state *pipe_state =
47 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
49 ZERO_STRUCTP(r->out.return_credentials);
51 /* destroyed on pipe shutdown */
54 talloc_free(pipe_state);
55 dce_call->context->private_data = NULL;
58 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
59 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
61 pipe_state->client_challenge = *r->in.credentials;
63 generate_random_buffer(pipe_state->server_challenge.data,
64 sizeof(pipe_state->server_challenge.data));
66 *r->out.return_credentials = pipe_state->server_challenge;
68 dce_call->context->private_data = pipe_state;
73 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
74 struct netr_ServerAuthenticate3 *r)
76 struct netlogon_server_pipe_state *pipe_state =
77 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
78 struct netlogon_creds_CredentialState *creds;
79 struct ldb_context *sam_ctx;
80 struct samr_Password *mach_pwd;
81 uint32_t user_account_control;
83 struct ldb_message **msgs;
85 const char *attrs[] = {"unicodePwd", "userAccountControl",
88 const char *trust_dom_attrs[] = {"flatname", NULL};
89 const char *account_name;
91 ZERO_STRUCTP(r->out.return_credentials);
95 * According to Microsoft (see bugid #6099)
96 * Windows 7 looks at the negotiate_flags
97 * returned in this structure *even if the
98 * call fails with access denied!
100 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
101 NETLOGON_NEG_PERSISTENT_SAMREPL |
102 NETLOGON_NEG_ARCFOUR |
103 NETLOGON_NEG_PROMOTION_COUNT |
104 NETLOGON_NEG_CHANGELOG_BDC |
105 NETLOGON_NEG_FULL_SYNC_REPL |
106 NETLOGON_NEG_MULTIPLE_SIDS |
108 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
109 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
110 NETLOGON_NEG_GENERIC_PASSTHROUGH |
111 NETLOGON_NEG_CONCURRENT_RPC |
112 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
113 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
114 NETLOGON_NEG_STRONG_KEYS |
115 NETLOGON_NEG_TRANSITIVE_TRUSTS |
116 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
117 NETLOGON_NEG_PASSWORD_SET2 |
118 NETLOGON_NEG_GETDOMAININFO |
119 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
120 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
121 NETLOGON_NEG_RODC_PASSTHROUGH |
122 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
123 NETLOGON_NEG_AUTHENTICATED_RPC;
126 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
127 return NT_STATUS_ACCESS_DENIED;
130 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
131 system_session(dce_call->conn->dce_ctx->lp_ctx));
132 if (sam_ctx == NULL) {
133 return NT_STATUS_INVALID_SYSTEM_SERVICE;
136 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
137 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
138 const char *flatname;
139 if (!encoded_account) {
140 return NT_STATUS_NO_MEMORY;
143 /* Kill the trailing dot */
144 if (encoded_account[strlen(encoded_account)-1] == '.') {
145 encoded_account[strlen(encoded_account)-1] = '\0';
148 /* pull the user attributes */
149 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
151 "(&(trustPartner=%s)(objectclass=trustedDomain))",
154 if (num_records == 0) {
155 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
157 return NT_STATUS_ACCESS_DENIED;
160 if (num_records > 1) {
161 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
162 return NT_STATUS_INTERNAL_DB_CORRUPTION;
165 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
167 /* No flatname for this trust - we can't proceed */
168 return NT_STATUS_ACCESS_DENIED;
170 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
173 return NT_STATUS_NO_MEMORY;
177 account_name = r->in.account_name;
180 /* pull the user attributes */
181 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
182 "(&(sAMAccountName=%s)(objectclass=user))",
183 ldb_binary_encode_string(mem_ctx, account_name));
185 if (num_records == 0) {
186 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
187 r->in.account_name));
188 return NT_STATUS_ACCESS_DENIED;
191 if (num_records > 1) {
192 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
193 return NT_STATUS_INTERNAL_DB_CORRUPTION;
196 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
198 if (user_account_control & UF_ACCOUNTDISABLE) {
199 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
200 return NT_STATUS_ACCESS_DENIED;
203 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
204 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
205 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
206 return NT_STATUS_ACCESS_DENIED;
208 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
209 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
210 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
211 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
213 return NT_STATUS_ACCESS_DENIED;
215 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
216 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
217 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
218 return NT_STATUS_ACCESS_DENIED;
221 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
222 r->in.secure_channel_type));
223 return NT_STATUS_ACCESS_DENIED;
226 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
229 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
230 if (mach_pwd == NULL) {
231 return NT_STATUS_ACCESS_DENIED;
234 creds = netlogon_creds_server_init(mem_ctx,
237 r->in.secure_channel_type,
238 &pipe_state->client_challenge,
239 &pipe_state->server_challenge,
242 r->out.return_credentials,
243 *r->in.negotiate_flags);
246 return NT_STATUS_ACCESS_DENIED;
249 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
251 nt_status = schannel_save_creds_state(mem_ctx,
252 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
258 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
259 struct netr_ServerAuthenticate *r)
261 struct netr_ServerAuthenticate3 a;
264 * negotiate_flags is used as an [in] parameter
265 * so it need to be initialised.
267 * (I think ... = 0; seems wrong here --metze)
269 uint32_t negotiate_flags_in = 0;
270 uint32_t negotiate_flags_out = 0;
272 a.in.server_name = r->in.server_name;
273 a.in.account_name = r->in.account_name;
274 a.in.secure_channel_type = r->in.secure_channel_type;
275 a.in.computer_name = r->in.computer_name;
276 a.in.credentials = r->in.credentials;
277 a.in.negotiate_flags = &negotiate_flags_in;
279 a.out.return_credentials = r->out.return_credentials;
281 a.out.negotiate_flags = &negotiate_flags_out;
283 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
286 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
287 struct netr_ServerAuthenticate2 *r)
289 struct netr_ServerAuthenticate3 r3;
292 r3.in.server_name = r->in.server_name;
293 r3.in.account_name = r->in.account_name;
294 r3.in.secure_channel_type = r->in.secure_channel_type;
295 r3.in.computer_name = r->in.computer_name;
296 r3.in.credentials = r->in.credentials;
297 r3.out.return_credentials = r->out.return_credentials;
298 r3.in.negotiate_flags = r->in.negotiate_flags;
299 r3.out.negotiate_flags = r->out.negotiate_flags;
302 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
306 * NOTE: The following functions are nearly identical to the ones available in
307 * source3/rpc_server/srv_nelog_nt.c
308 * The reason we keep 2 copies is that they use different structures to
309 * represent the auth_info and the decrpc pipes.
313 * If schannel is required for this call test that it actually is available.
315 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
316 const char *computer_name,
317 bool integrity, bool privacy)
320 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
321 if (!privacy && !integrity) {
325 if ((!privacy && integrity) &&
326 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
330 if ((privacy || integrity) &&
331 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
336 /* test didn't pass */
337 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
340 return NT_STATUS_ACCESS_DENIED;
343 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
345 const char *computer_name,
346 struct netr_Authenticator *received_authenticator,
347 struct netr_Authenticator *return_authenticator,
348 struct netlogon_creds_CredentialState **creds_out)
351 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
352 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
354 if (schannel_global_required) {
355 nt_status = schannel_check_required(auth_info,
358 if (!NT_STATUS_IS_OK(nt_status)) {
363 nt_status = schannel_check_creds_state(mem_ctx,
364 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
366 received_authenticator,
367 return_authenticator,
373 Change the machine account password for the currently connected
374 client. Supplies only the NT#.
377 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
378 struct netr_ServerPasswordSet *r)
380 struct netlogon_creds_CredentialState *creds;
381 struct ldb_context *sam_ctx;
384 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
387 r->in.credential, r->out.return_authenticator,
389 NT_STATUS_NOT_OK_RETURN(nt_status);
391 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));
392 if (sam_ctx == NULL) {
393 return NT_STATUS_INVALID_SYSTEM_SERVICE;
396 netlogon_creds_des_decrypt(creds, r->in.new_password);
398 /* Using the sid for the account as the key, set the password */
399 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
401 NULL, /* Don't have plaintext */
402 NULL, r->in.new_password,
403 true, /* Password change */
409 Change the machine account password for the currently connected
410 client. Supplies new plaintext.
412 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
413 struct netr_ServerPasswordSet2 *r)
415 struct netlogon_creds_CredentialState *creds;
416 struct ldb_context *sam_ctx;
418 DATA_BLOB new_password;
420 struct samr_CryptPassword password_buf;
422 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
425 r->in.credential, r->out.return_authenticator,
427 NT_STATUS_NOT_OK_RETURN(nt_status);
429 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));
430 if (sam_ctx == NULL) {
431 return NT_STATUS_INVALID_SYSTEM_SERVICE;
434 memcpy(password_buf.data, r->in.new_password->data, 512);
435 SIVAL(password_buf.data, 512, r->in.new_password->length);
436 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
438 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
439 DEBUG(3,("samr: failed to decode password buffer\n"));
440 return NT_STATUS_WRONG_PASSWORD;
443 /* Using the sid for the account as the key, set the password */
444 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
446 &new_password, /* we have plaintext */
448 true, /* Password change */
457 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
458 struct netr_LogonUasLogon *r)
460 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
467 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
468 struct netr_LogonUasLogoff *r)
470 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
475 netr_LogonSamLogon_base
477 This version of the function allows other wrappers to say 'do not check the credentials'
479 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
481 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
482 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
484 struct auth_context *auth_context;
485 struct auth_usersupplied_info *user_info;
486 struct auth_serversupplied_info *server_info;
488 static const char zeros[16];
489 struct netr_SamBaseInfo *sam;
490 struct netr_SamInfo2 *sam2;
491 struct netr_SamInfo3 *sam3;
492 struct netr_SamInfo6 *sam6;
494 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
495 NT_STATUS_HAVE_NO_MEMORY(user_info);
497 switch (r->in.logon_level) {
498 case NetlogonInteractiveInformation:
499 case NetlogonServiceInformation:
500 case NetlogonInteractiveTransitiveInformation:
501 case NetlogonServiceTransitiveInformation:
502 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
503 netlogon_creds_arcfour_crypt(creds,
504 r->in.logon->password->lmpassword.hash,
505 sizeof(r->in.logon->password->lmpassword.hash));
506 netlogon_creds_arcfour_crypt(creds,
507 r->in.logon->password->ntpassword.hash,
508 sizeof(r->in.logon->password->ntpassword.hash));
510 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
511 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
514 /* TODO: we need to deny anonymous access here */
515 nt_status = auth_context_create(mem_ctx,
516 dce_call->event_ctx, dce_call->msg_ctx,
517 dce_call->conn->dce_ctx->lp_ctx,
519 NT_STATUS_NOT_OK_RETURN(nt_status);
521 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
522 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
523 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
524 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
526 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
527 user_info->password_state = AUTH_PASSWORD_HASH;
529 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
530 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
531 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
533 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
534 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
535 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
538 case NetlogonNetworkInformation:
539 case NetlogonNetworkTransitiveInformation:
541 /* TODO: we need to deny anonymous access here */
542 nt_status = auth_context_create(mem_ctx,
543 dce_call->event_ctx, dce_call->msg_ctx,
544 dce_call->conn->dce_ctx->lp_ctx,
546 NT_STATUS_NOT_OK_RETURN(nt_status);
548 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
549 NT_STATUS_NOT_OK_RETURN(nt_status);
551 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
552 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
553 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
554 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
556 user_info->password_state = AUTH_PASSWORD_RESPONSE;
557 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
558 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
563 case NetlogonGenericInformation:
565 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
566 netlogon_creds_arcfour_crypt(creds,
567 r->in.logon->generic->data, r->in.logon->generic->length);
569 /* Using DES to verify kerberos tickets makes no sense */
570 return NT_STATUS_INVALID_PARAMETER;
573 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
575 struct server_id *kdc;
576 struct kdc_check_generic_kerberos check;
577 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
578 NT_STATUS_HAVE_NO_MEMORY(generic);
579 *r->out.authoritative = 1;
581 /* TODO: Describe and deal with these flags */
584 r->out.validation->generic = generic;
586 kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
587 if ((kdc == NULL) || (kdc[0].id == 0)) {
588 return NT_STATUS_NO_LOGON_SERVERS;
591 check.in.generic_request =
592 data_blob_const(r->in.logon->generic->data,
593 r->in.logon->generic->length);
595 status = irpc_call(dce_call->msg_ctx, kdc[0],
596 &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
598 if (!NT_STATUS_IS_OK(status)) {
601 generic->length = check.out.generic_reply.length;
602 generic->data = check.out.generic_reply.data;
606 /* Until we get an implemetnation of these other packages */
607 return NT_STATUS_INVALID_PARAMETER;
610 return NT_STATUS_INVALID_PARAMETER;
613 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
614 NT_STATUS_NOT_OK_RETURN(nt_status);
616 switch (r->in.validation_level) {
618 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
619 NT_STATUS_NOT_OK_RETURN(nt_status);
621 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
622 NT_STATUS_HAVE_NO_MEMORY(sam2);
625 /* And put into the talloc tree */
626 talloc_steal(sam2, sam);
627 r->out.validation->sam2 = sam2;
633 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
636 NT_STATUS_NOT_OK_RETURN(nt_status);
638 r->out.validation->sam3 = sam3;
644 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
647 NT_STATUS_NOT_OK_RETURN(nt_status);
649 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
650 NT_STATUS_HAVE_NO_MEMORY(sam6);
651 sam6->base = sam3->base;
653 sam6->sidcount = sam3->sidcount;
654 sam6->sids = sam3->sids;
656 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
657 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
658 sam->account_name.string, sam6->dns_domainname.string);
659 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
660 /* And put into the talloc tree */
661 talloc_steal(sam6, sam3);
663 r->out.validation->sam6 = sam6;
670 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
671 /* It appears that level 6 is not individually encrypted */
672 if ((r->in.validation_level != 6) &&
673 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
674 /* This key is sent unencrypted without the ARCFOUR flag set */
675 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
676 netlogon_creds_arcfour_crypt(creds,
678 sizeof(sam->key.key));
682 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
683 /* It appears that level 6 is not individually encrypted */
684 if ((r->in.validation_level != 6) &&
685 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
686 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
687 netlogon_creds_arcfour_crypt(creds,
689 sizeof(sam->LMSessKey.key));
691 netlogon_creds_des_encrypt_LMKey(creds,
696 *r->out.authoritative = 1;
698 /* TODO: Describe and deal with these flags */
704 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
705 struct netr_LogonSamLogonEx *r)
708 struct netlogon_creds_CredentialState *creds;
710 nt_status = schannel_get_creds_state(mem_ctx,
711 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
712 r->in.computer_name, &creds);
713 if (!NT_STATUS_IS_OK(nt_status)) {
717 if (!dce_call->conn->auth_state.auth_info ||
718 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
719 return NT_STATUS_ACCESS_DENIED;
721 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
725 netr_LogonSamLogonWithFlags
728 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
729 struct netr_LogonSamLogonWithFlags *r)
732 struct netlogon_creds_CredentialState *creds;
733 struct netr_LogonSamLogonEx r2;
735 struct netr_Authenticator *return_authenticator;
737 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
738 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
740 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
743 r->in.credential, return_authenticator,
745 NT_STATUS_NOT_OK_RETURN(nt_status);
749 r2.in.server_name = r->in.server_name;
750 r2.in.computer_name = r->in.computer_name;
751 r2.in.logon_level = r->in.logon_level;
752 r2.in.logon = r->in.logon;
753 r2.in.validation_level = r->in.validation_level;
754 r2.in.flags = r->in.flags;
755 r2.out.validation = r->out.validation;
756 r2.out.authoritative = r->out.authoritative;
757 r2.out.flags = r->out.flags;
759 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
761 r->out.return_authenticator = return_authenticator;
769 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
770 struct netr_LogonSamLogon *r)
772 struct netr_LogonSamLogonWithFlags r2;
778 r2.in.server_name = r->in.server_name;
779 r2.in.computer_name = r->in.computer_name;
780 r2.in.credential = r->in.credential;
781 r2.in.return_authenticator = r->in.return_authenticator;
782 r2.in.logon_level = r->in.logon_level;
783 r2.in.logon = r->in.logon;
784 r2.in.validation_level = r->in.validation_level;
785 r2.in.flags = &flags;
786 r2.out.validation = r->out.validation;
787 r2.out.authoritative = r->out.authoritative;
788 r2.out.flags = &flags;
790 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
792 r->out.return_authenticator = r2.out.return_authenticator;
801 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
802 struct netr_LogonSamLogoff *r)
804 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
812 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
813 struct netr_DatabaseDeltas *r)
815 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
822 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
823 struct netr_DatabaseSync2 *r)
825 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
826 return NT_STATUS_NOT_IMPLEMENTED;
833 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
834 struct netr_DatabaseSync *r)
836 struct netr_DatabaseSync2 r2;
841 r2.in.logon_server = r->in.logon_server;
842 r2.in.computername = r->in.computername;
843 r2.in.credential = r->in.credential;
844 r2.in.database_id = r->in.database_id;
845 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
846 r2.in.sync_context = r->in.sync_context;
847 r2.out.sync_context = r->out.sync_context;
848 r2.out.delta_enum_array = r->out.delta_enum_array;
849 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
851 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
860 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
861 struct netr_AccountDeltas *r)
863 /* w2k3 returns "NOT IMPLEMENTED" for this call */
864 return NT_STATUS_NOT_IMPLEMENTED;
871 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
872 struct netr_AccountSync *r)
874 /* w2k3 returns "NOT IMPLEMENTED" for this call */
875 return NT_STATUS_NOT_IMPLEMENTED;
882 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
883 struct netr_GetDcName *r)
885 const char * const attrs[] = { NULL };
886 struct ldb_context *sam_ctx;
887 struct ldb_message **res;
888 struct ldb_dn *domain_dn;
892 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
893 dce_call->conn->dce_ctx->lp_ctx,
894 dce_call->conn->auth_state.session_info);
895 if (sam_ctx == NULL) {
896 return WERR_DS_UNAVAILABLE;
899 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
901 if (domain_dn == NULL) {
902 return WERR_DS_UNAVAILABLE;
905 ret = gendb_search_dn(sam_ctx, mem_ctx,
906 domain_dn, &res, attrs);
908 return WERR_NO_SUCH_DOMAIN;
911 /* TODO: - return real IP address
912 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
914 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
915 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
916 W_ERROR_HAVE_NO_MEMORY(dcname);
918 *r->out.dcname = dcname;
926 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
927 struct netr_LogonControl2Ex *r)
929 return WERR_NOT_SUPPORTED;
936 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
937 struct netr_LogonControl *r)
939 struct netr_LogonControl2Ex r2;
942 if (r->in.level == 0x00000001) {
945 r2.in.logon_server = r->in.logon_server;
946 r2.in.function_code = r->in.function_code;
947 r2.in.level = r->in.level;
949 r2.out.query = r->out.query;
951 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
952 } else if (r->in.level == 0x00000002) {
953 werr = WERR_NOT_SUPPORTED;
955 werr = WERR_UNKNOWN_LEVEL;
965 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
966 struct netr_LogonControl2 *r)
968 struct netr_LogonControl2Ex r2;
973 r2.in.logon_server = r->in.logon_server;
974 r2.in.function_code = r->in.function_code;
975 r2.in.level = r->in.level;
976 r2.in.data = r->in.data;
977 r2.out.query = r->out.query;
979 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
984 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
985 struct ldb_context *sam_ctx,
986 struct netr_DomainTrustList *trusts,
987 uint32_t trust_flags);
992 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
993 struct netr_GetAnyDCName *r)
995 struct netr_DomainTrustList *trusts;
996 struct ldb_context *sam_ctx;
997 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1001 *r->out.dcname = NULL;
1003 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1004 /* if the domainname parameter wasn't set assume our domain */
1005 r->in.domainname = lpcfg_workgroup(lp_ctx);
1008 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1009 dce_call->conn->auth_state.session_info);
1010 if (sam_ctx == NULL) {
1011 return WERR_DS_UNAVAILABLE;
1014 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1015 /* well we asked for a DC of our own domain */
1016 if (samdb_is_pdc(sam_ctx)) {
1017 /* we are the PDC of the specified domain */
1018 return WERR_NO_SUCH_DOMAIN;
1021 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1022 lpcfg_netbios_name(lp_ctx));
1023 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1028 /* Okay, now we have to consider the trusted domains */
1030 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1031 W_ERROR_HAVE_NO_MEMORY(trusts);
1035 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1036 NETR_TRUST_FLAG_INBOUND
1037 | NETR_TRUST_FLAG_OUTBOUND);
1038 W_ERROR_NOT_OK_RETURN(werr);
1040 for (i = 0; i < trusts->count; i++) {
1041 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1042 /* FIXME: Here we need to find a DC for the specified
1043 * trusted domain. */
1045 /* return WERR_OK; */
1046 return WERR_NO_SUCH_DOMAIN;
1050 return WERR_NO_SUCH_DOMAIN;
1057 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1058 struct netr_DatabaseRedo *r)
1060 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1065 netr_NetrEnumerateTrustedDomains
1067 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1068 struct netr_NetrEnumerateTrustedDomains *r)
1070 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1075 netr_LogonGetCapabilities
1077 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1078 struct netr_LogonGetCapabilities *r)
1080 /* we don't support AES yet */
1081 return NT_STATUS_NOT_IMPLEMENTED;
1086 netr_NETRLOGONSETSERVICEBITS
1088 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1089 struct netr_NETRLOGONSETSERVICEBITS *r)
1091 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1096 netr_LogonGetTrustRid
1098 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1099 struct netr_LogonGetTrustRid *r)
1101 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1106 netr_NETRLOGONCOMPUTESERVERDIGEST
1108 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1109 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1111 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1116 netr_NETRLOGONCOMPUTECLIENTDIGEST
1118 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1119 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1121 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1129 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1130 struct netr_DsRGetSiteName *r)
1132 struct ldb_context *sam_ctx;
1133 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1135 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1136 dce_call->conn->auth_state.session_info);
1137 if (sam_ctx == NULL) {
1138 return WERR_DS_UNAVAILABLE;
1141 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1142 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1149 fill in a netr_OneDomainInfo from a ldb search result
1151 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1152 struct loadparm_context *lp_ctx,
1153 struct ldb_context *sam_ctx,
1154 struct ldb_message *res,
1155 struct netr_OneDomainInfo *info,
1156 bool is_local, bool is_trust_list)
1160 if (is_trust_list) {
1161 /* w2k8 only fills this on trusted domains */
1162 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1163 info->trust_extension.length = 16;
1164 info->trust_extension.info->flags =
1165 NETR_TRUST_FLAG_TREEROOT |
1166 NETR_TRUST_FLAG_IN_FOREST |
1167 NETR_TRUST_FLAG_PRIMARY |
1168 NETR_TRUST_FLAG_NATIVE;
1170 info->trust_extension.info->parent_index = 0; /* should be index into array
1172 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1173 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1176 if (is_trust_list) {
1177 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1178 info->dns_forestname.string = NULL;
1180 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1181 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1182 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1183 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1187 info->domainname.string = lpcfg_workgroup(lp_ctx);
1188 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1189 info->domain_guid = samdb_result_guid(res, "objectGUID");
1190 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1192 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1193 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1194 info->domain_guid = samdb_result_guid(res, "objectGUID");
1195 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1197 if (!is_trust_list) {
1198 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1201 return NT_STATUS_OK;
1205 netr_LogonGetDomainInfo
1206 this is called as part of the ADS domain logon procedure.
1208 It has an important role in convaying details about the client, such
1209 as Operating System, Version, Service Pack etc.
1211 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1212 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1214 struct netlogon_creds_CredentialState *creds;
1215 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1216 "securityIdentifier", "trustPartner", NULL };
1217 const char * const attrs2[] = { "dNSHostName",
1218 "msDS-SupportedEncryptionTypes", NULL };
1219 const char *temp_str, *temp_str2;
1220 const char *old_dns_hostname;
1221 struct ldb_context *sam_ctx;
1222 struct ldb_message **res1, **res2, **res3, *new_msg;
1223 struct ldb_dn *workstation_dn;
1224 struct netr_DomainInformation *domain_info;
1225 struct netr_LsaPolicyInformation *lsa_policy_info;
1226 struct netr_OsVersionInfoEx *os_version;
1227 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1228 bool update_dns_hostname = true;
1232 status = dcesrv_netr_creds_server_step_check(dce_call,
1234 r->in.computer_name,
1236 r->out.return_authenticator,
1238 if (!NT_STATUS_IS_OK(status)) {
1239 DEBUG(0,(__location__ " Bad credentials - error\n"));
1241 NT_STATUS_NOT_OK_RETURN(status);
1243 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1244 dce_call->conn->dce_ctx->lp_ctx,
1245 system_session(dce_call->conn->dce_ctx->lp_ctx));
1246 if (sam_ctx == NULL) {
1247 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1250 switch (r->in.level) {
1251 case 1: /* Domain information */
1253 if (r->in.query->workstation_info == NULL) {
1254 return NT_STATUS_INVALID_PARAMETER;
1258 * Checks that the computer name parameter without possible "$"
1259 * matches as prefix with the DNS hostname in the workstation
1262 temp_str = talloc_strndup(mem_ctx,
1263 r->in.computer_name,
1264 strcspn(r->in.computer_name, "$"));
1265 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1266 temp_str2 = talloc_strndup(mem_ctx,
1267 r->in.query->workstation_info->dns_hostname,
1268 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1269 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1270 if (strcasecmp(temp_str, temp_str2) != 0) {
1271 update_dns_hostname = false;
1274 /* Prepare the workstation DN */
1275 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1276 dom_sid_string(mem_ctx, creds->sid));
1277 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1279 /* Lookup for attributes in workstation object */
1280 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1283 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1286 /* Gets the old DNS hostname */
1287 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1291 * Updates the DNS hostname when the client wishes that the
1292 * server should handle this for him
1293 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1294 * obviously only checked when we do already have a
1296 * See MS-NRPC section 3.5.4.3.9
1298 if ((old_dns_hostname != NULL) &&
1299 (r->in.query->workstation_info->workstation_flags
1300 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1301 update_dns_hostname = false;
1304 /* Gets host informations and put them into our directory */
1306 new_msg = ldb_msg_new(mem_ctx);
1307 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1309 new_msg->dn = workstation_dn;
1311 /* Sets the OS name */
1312 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1314 r->in.query->workstation_info->os_name.string);
1317 * Sets informations from "os_version". On an empty structure
1318 * the values are cleared.
1320 if (r->in.query->workstation_info->os_version.os != NULL) {
1321 os_version = &r->in.query->workstation_info->os_version.os->os;
1323 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1324 "operatingSystemServicePack",
1325 os_version->CSDVersion);
1327 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1328 "operatingSystemVersion",
1329 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1330 os_version->MajorVersion,
1331 os_version->MinorVersion,
1332 os_version->BuildNumber
1336 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1337 "operatingSystemServicePack");
1339 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1340 "operatingSystemVersion");
1344 * If the boolean "update_dns_hostname" remained true, then we
1345 * are fine to start the update.
1347 if (update_dns_hostname) {
1348 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1350 r->in.query->workstation_info->dns_hostname);
1352 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1353 "servicePrincipalName",
1354 talloc_asprintf(mem_ctx, "HOST/%s",
1355 r->in.computer_name)
1357 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1358 "servicePrincipalName",
1359 talloc_asprintf(mem_ctx, "HOST/%s",
1360 r->in.query->workstation_info->dns_hostname)
1364 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1365 DEBUG(3,("Impossible to update samdb: %s\n",
1366 ldb_errstring(sam_ctx)));
1369 talloc_free(new_msg);
1371 /* Writes back the domain information */
1373 /* We need to do two searches. The first will pull our primary
1374 domain and the second will pull any trusted domains. Our
1375 primary domain is also a "trusted" domain, so we need to
1376 put the primary domain into the lists of returned trusts as
1378 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1381 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1384 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1385 "(objectClass=trustedDomain)");
1387 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1390 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1391 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1393 ZERO_STRUCTP(domain_info);
1395 /* Informations about the local and trusted domains */
1397 status = fill_one_domain_info(mem_ctx,
1398 dce_call->conn->dce_ctx->lp_ctx,
1399 sam_ctx, res2[0], &domain_info->primary_domain,
1401 NT_STATUS_NOT_OK_RETURN(status);
1403 domain_info->trusted_domain_count = ret3 + 1;
1404 domain_info->trusted_domains = talloc_array(mem_ctx,
1405 struct netr_OneDomainInfo,
1406 domain_info->trusted_domain_count);
1407 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1409 for (i=0;i<ret3;i++) {
1410 status = fill_one_domain_info(mem_ctx,
1411 dce_call->conn->dce_ctx->lp_ctx,
1413 &domain_info->trusted_domains[i],
1415 NT_STATUS_NOT_OK_RETURN(status);
1418 status = fill_one_domain_info(mem_ctx,
1419 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1420 &domain_info->trusted_domains[i], true, true);
1421 NT_STATUS_NOT_OK_RETURN(status);
1423 /* Sets the supported encryption types */
1424 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1425 "msDS-SupportedEncryptionTypes",
1426 default_supported_enc_types);
1428 /* Other host domain informations */
1430 lsa_policy_info = talloc(mem_ctx,
1431 struct netr_LsaPolicyInformation);
1432 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1433 ZERO_STRUCTP(lsa_policy_info);
1435 domain_info->lsa_policy = *lsa_policy_info;
1437 /* The DNS hostname is only returned back when there is a chance
1439 if ((r->in.query->workstation_info->workstation_flags
1440 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1441 domain_info->dns_hostname.string = old_dns_hostname;
1443 domain_info->dns_hostname.string = NULL;
1446 domain_info->workstation_flags =
1447 r->in.query->workstation_info->workstation_flags;
1449 r->out.info->domain_info = domain_info;
1451 case 2: /* LSA policy information - not used at the moment */
1452 lsa_policy_info = talloc(mem_ctx,
1453 struct netr_LsaPolicyInformation);
1454 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1455 ZERO_STRUCTP(lsa_policy_info);
1457 r->out.info->lsa_policy_info = lsa_policy_info;
1460 return NT_STATUS_INVALID_LEVEL;
1464 return NT_STATUS_OK;
1470 netr_ServerPasswordGet
1472 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1473 struct netr_ServerPasswordGet *r)
1475 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1480 netr_NETRLOGONSENDTOSAM
1482 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1483 struct netr_NETRLOGONSENDTOSAM *r)
1485 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1490 netr_DsRGetDCNameEx2
1492 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1493 TALLOC_CTX *mem_ctx,
1494 struct netr_DsRGetDCNameEx2 *r)
1496 struct ldb_context *sam_ctx;
1497 struct netr_DsRGetDCNameInfo *info;
1498 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1499 const struct tsocket_address *remote_address;
1501 const char *server_site_name;
1503 struct netlogon_samlogon_response response;
1506 ZERO_STRUCTP(r->out.info);
1508 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1509 dce_call->conn->auth_state.session_info);
1510 if (sam_ctx == NULL) {
1511 return WERR_DS_UNAVAILABLE;
1514 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1515 if (tsocket_address_is_inet(remote_address, "ip")) {
1516 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1517 W_ERROR_HAVE_NO_MEMORY(addr);
1520 /* "server_unc" is ignored by w2k3 */
1522 /* Proof server site parameter "site_name" if it was specified */
1523 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1524 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1525 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1526 server_site_name) != 0)) {
1527 return WERR_NO_SUCH_DOMAIN;
1530 /* TODO: the flags are ignored for now */
1532 guid_str = r->in.domain_guid != NULL ?
1533 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1535 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1539 r->in.client_account,
1541 NETLOGON_NT_VERSION_5EX_WITH_IP,
1542 lp_ctx, &response, true);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 return ntstatus_to_werror(status);
1547 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1548 W_ERROR_HAVE_NO_MEMORY(info);
1549 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1550 response.data.nt5_ex.pdc_dns_name);
1551 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1552 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1553 response.data.nt5_ex.sockaddr.pdc_ip);
1554 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1555 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1556 info->domain_guid = response.data.nt5_ex.domain_uuid;
1557 info->domain_name = response.data.nt5_ex.dns_domain;
1558 info->forest_name = response.data.nt5_ex.forest;
1559 info->dc_flags = response.data.nt5_ex.server_type;
1560 info->dc_site_name = response.data.nt5_ex.server_site;
1561 info->client_site_name = response.data.nt5_ex.client_site;
1563 *r->out.info = info;
1571 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1572 struct netr_DsRGetDCNameEx *r)
1574 struct netr_DsRGetDCNameEx2 r2;
1579 r2.in.server_unc = r->in.server_unc;
1580 r2.in.client_account = NULL;
1582 r2.in.domain_guid = r->in.domain_guid;
1583 r2.in.domain_name = r->in.domain_name;
1584 r2.in.site_name = r->in.site_name;
1585 r2.in.flags = r->in.flags;
1586 r2.out.info = r->out.info;
1588 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1596 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1597 struct netr_DsRGetDCName *r)
1599 struct netr_DsRGetDCNameEx2 r2;
1604 r2.in.server_unc = r->in.server_unc;
1605 r2.in.client_account = NULL;
1607 r2.in.domain_name = r->in.domain_name;
1608 r2.in.domain_guid = r->in.domain_guid;
1610 r2.in.site_name = NULL; /* should fill in from site GUID */
1611 r2.in.flags = r->in.flags;
1612 r2.out.info = r->out.info;
1614 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1619 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1621 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1622 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1624 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1629 netr_NetrEnumerateTrustedDomainsEx
1631 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1632 struct netr_NetrEnumerateTrustedDomainsEx *r)
1634 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1639 netr_DsRAddressToSitenamesExW
1641 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1642 struct netr_DsRAddressToSitenamesExW *r)
1644 struct ldb_context *sam_ctx;
1645 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1646 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1647 sa_family_t sin_family;
1648 struct sockaddr_in *addr;
1650 struct sockaddr_in6 *addr6;
1651 char addr_str[INET6_ADDRSTRLEN];
1653 char addr_str[INET_ADDRSTRLEN];
1659 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1660 dce_call->conn->auth_state.session_info);
1661 if (sam_ctx == NULL) {
1662 return WERR_DS_UNAVAILABLE;
1665 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1666 W_ERROR_HAVE_NO_MEMORY(ctr);
1670 ctr->count = r->in.count;
1671 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1672 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1673 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1674 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1676 for (i=0; i<ctr->count; i++) {
1677 ctr->sitename[i].string = NULL;
1678 ctr->subnetname[i].string = NULL;
1680 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1683 /* The first two byte of the buffer are reserved for the
1684 * "sin_family" but for now only the first one is used. */
1685 sin_family = r->in.addresses[i].buffer[0];
1687 switch (sin_family) {
1689 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1692 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1693 res = inet_ntop(AF_INET, &addr->sin_addr,
1694 addr_str, sizeof(addr_str));
1698 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1701 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1702 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1703 addr_str, sizeof(addr_str));
1714 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1718 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1719 ctr->subnetname[i].string = subnet_name;
1727 netr_DsRAddressToSitenamesW
1729 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1730 struct netr_DsRAddressToSitenamesW *r)
1732 struct netr_DsRAddressToSitenamesExW r2;
1733 struct netr_DsRAddressToSitenamesWCtr *ctr;
1739 r2.in.server_name = r->in.server_name;
1740 r2.in.count = r->in.count;
1741 r2.in.addresses = r->in.addresses;
1743 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1744 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1746 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1747 W_ERROR_HAVE_NO_MEMORY(ctr);
1751 ctr->count = r->in.count;
1752 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1753 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1755 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1757 for (i=0; i<ctr->count; i++) {
1758 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1766 netr_DsrGetDcSiteCoverageW
1768 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1769 struct netr_DsrGetDcSiteCoverageW *r)
1771 struct ldb_context *sam_ctx;
1772 struct DcSitesCtr *ctr;
1773 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1775 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1776 dce_call->conn->auth_state.session_info);
1777 if (sam_ctx == NULL) {
1778 return WERR_DS_UNAVAILABLE;
1781 ctr = talloc(mem_ctx, struct DcSitesCtr);
1782 W_ERROR_HAVE_NO_MEMORY(ctr);
1786 /* For now only return our default site */
1788 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1789 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1790 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1791 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1797 #define GET_CHECK_STR(dest, mem, msg, attr) \
1800 s = samdb_result_string(msg, attr, NULL); \
1802 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1803 "without flatname\n", \
1804 ldb_dn_get_linearized(msg->dn))); \
1807 dest = talloc_strdup(mem, s); \
1808 W_ERROR_HAVE_NO_MEMORY(dest); \
1812 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1813 struct ldb_context *sam_ctx,
1814 struct netr_DomainTrustList *trusts,
1815 uint32_t trust_flags)
1817 struct ldb_dn *system_dn;
1818 struct ldb_message **dom_res = NULL;
1819 const char *trust_attrs[] = { "flatname", "trustPartner",
1820 "securityIdentifier", "trustDirection",
1821 "trustType", "trustAttributes", NULL };
1826 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1827 NETR_TRUST_FLAG_OUTBOUND))) {
1828 return WERR_INVALID_FLAGS;
1831 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1832 ldb_get_default_basedn(sam_ctx),
1833 "(&(objectClass=container)(cn=System))");
1835 return WERR_GENERAL_FAILURE;
1838 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1839 &dom_res, trust_attrs,
1840 "(objectclass=trustedDomain)");
1842 for (i = 0; i < ret; i++) {
1843 unsigned int trust_dir;
1846 trust_dir = samdb_result_uint(dom_res[i],
1847 "trustDirection", 0);
1849 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1850 flags |= NETR_TRUST_FLAG_INBOUND;
1852 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1853 flags |= NETR_TRUST_FLAG_OUTBOUND;
1856 if (!(flags & trust_flags)) {
1857 /* this trust direction was not requested */
1862 trusts->array = talloc_realloc(trusts, trusts->array,
1863 struct netr_DomainTrust,
1865 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1867 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1868 dom_res[i], "flatname");
1869 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1870 dom_res[i], "trustPartner");
1872 trusts->array[n].trust_flags = flags;
1873 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1874 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1875 /* TODO: find if we have parent in the list */
1876 trusts->array[n].parent_index = 0;
1879 trusts->array[n].trust_type =
1880 samdb_result_uint(dom_res[i],
1882 trusts->array[n].trust_attributes =
1883 samdb_result_uint(dom_res[i],
1884 "trustAttributes", 0);
1886 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1887 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1888 struct dom_sid zero_sid;
1889 ZERO_STRUCT(zero_sid);
1890 trusts->array[n].sid =
1891 dom_sid_dup(trusts, &zero_sid);
1893 trusts->array[n].sid =
1894 samdb_result_dom_sid(trusts, dom_res[i],
1895 "securityIdentifier");
1897 trusts->array[n].guid = GUID_zero();
1899 trusts->count = n + 1;
1902 talloc_free(dom_res);
1907 netr_DsrEnumerateDomainTrusts
1909 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1910 TALLOC_CTX *mem_ctx,
1911 struct netr_DsrEnumerateDomainTrusts *r)
1913 struct netr_DomainTrustList *trusts;
1914 struct ldb_context *sam_ctx;
1916 struct ldb_message **dom_res;
1917 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1918 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1919 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
1923 if (r->in.trust_flags & 0xFFFFFE00) {
1924 return WERR_INVALID_FLAGS;
1927 /* TODO: turn to hard check once we are sure this is 100% correct */
1928 if (!r->in.server_name) {
1929 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1930 "But received NULL!\n", dnsdomain));
1932 p = strchr(r->in.server_name, '.');
1934 DEBUG(3, ("Invalid domain! Expected name in domain "
1935 "[%s]. But received [%s]!\n",
1936 dnsdomain, r->in.server_name));
1937 p = r->in.server_name;
1941 if (strcasecmp(p, dnsdomain)) {
1942 DEBUG(3, ("Invalid domain! Expected name in domain "
1943 "[%s]. But received [%s]!\n",
1944 dnsdomain, r->in.server_name));
1948 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1949 W_ERROR_HAVE_NO_MEMORY(trusts);
1952 r->out.trusts = trusts;
1954 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1955 dce_call->conn->auth_state.session_info);
1956 if (sam_ctx == NULL) {
1957 return WERR_GENERAL_FAILURE;
1960 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1961 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1963 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1964 trusts, r->in.trust_flags);
1965 W_ERROR_NOT_OK_RETURN(werr);
1968 /* NOTE: we currently are always the root of the forest */
1969 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1970 uint32_t n = trusts->count;
1972 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1973 &dom_res, dom_attrs);
1975 return WERR_GENERAL_FAILURE;
1978 trusts->count = n + 1;
1979 trusts->array = talloc_realloc(trusts, trusts->array,
1980 struct netr_DomainTrust,
1982 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1984 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
1985 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
1986 trusts->array[n].trust_flags =
1987 NETR_TRUST_FLAG_NATIVE |
1988 NETR_TRUST_FLAG_TREEROOT |
1989 NETR_TRUST_FLAG_IN_FOREST |
1990 NETR_TRUST_FLAG_PRIMARY;
1991 /* we are always the root domain for now */
1992 trusts->array[n].parent_index = 0;
1993 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1994 trusts->array[n].trust_attributes = 0;
1995 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
1998 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2000 talloc_free(dom_res);
2008 netr_DsrDeregisterDNSHostRecords
2010 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2011 struct netr_DsrDeregisterDNSHostRecords *r)
2013 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2018 netr_ServerTrustPasswordsGet
2020 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2021 struct netr_ServerTrustPasswordsGet *r)
2023 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2027 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2028 struct ldb_context *sam_ctx,
2029 struct loadparm_context *lp_ctx,
2030 struct lsa_ForestTrustInformation *info)
2032 struct lsa_ForestTrustDomainInfo *domain_info;
2033 struct lsa_ForestTrustRecord *e;
2034 struct ldb_message **dom_res;
2035 const char * const dom_attrs[] = { "objectSid", NULL };
2038 /* we need to provide 2 entries:
2039 * 1. the Root Forest name
2040 * 2. the Domain Information
2044 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2045 W_ERROR_HAVE_NO_MEMORY(info->entries);
2047 /* Forest root info */
2048 e = talloc(info, struct lsa_ForestTrustRecord);
2049 W_ERROR_HAVE_NO_MEMORY(e);
2052 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2053 e->time = 0; /* so far always 0 in trces. */
2054 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2056 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2058 info->entries[0] = e;
2061 e = talloc(info, struct lsa_ForestTrustRecord);
2062 W_ERROR_HAVE_NO_MEMORY(e);
2064 /* get our own domain info */
2065 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2067 return WERR_GENERAL_FAILURE;
2070 /* TODO: check if disabled and set flags accordingly */
2072 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2073 e->time = 0; /* so far always 0 in traces. */
2075 domain_info = &e->forest_trust_data.domain_info;
2076 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2078 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2079 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2081 info->entries[1] = e;
2083 talloc_free(dom_res);
2089 netr_DsRGetForestTrustInformation
2091 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2092 TALLOC_CTX *mem_ctx,
2093 struct netr_DsRGetForestTrustInformation *r)
2095 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2096 struct lsa_ForestTrustInformation *info, **info_ptr;
2097 struct ldb_context *sam_ctx;
2100 if (r->in.flags & 0xFFFFFFFE) {
2101 return WERR_INVALID_FLAGS;
2104 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2105 dce_call->conn->auth_state.session_info);
2106 if (sam_ctx == NULL) {
2107 return WERR_GENERAL_FAILURE;
2110 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2111 if (!samdb_is_pdc(sam_ctx)) {
2112 return WERR_NERR_NOTPRIMARY;
2115 if (r->in.trusted_domain_name == NULL) {
2116 return WERR_INVALID_FLAGS;
2119 /* TODO: establish an schannel connection with
2120 * r->in.trusted_domain_name and perform a
2121 * netr_GetForestTrustInformation call against it */
2123 /* for now return not implementd */
2124 return WERR_CALL_NOT_IMPLEMENTED;
2127 /* TODO: check r->in.server_name is our name */
2129 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2130 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2132 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2133 W_ERROR_HAVE_NO_MEMORY(info);
2135 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2136 W_ERROR_NOT_OK_RETURN(werr);
2139 r->out.forest_trust_info = info_ptr;
2146 netr_GetForestTrustInformation
2148 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2149 TALLOC_CTX *mem_ctx,
2150 struct netr_GetForestTrustInformation *r)
2152 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2153 struct netlogon_creds_CredentialState *creds;
2154 struct lsa_ForestTrustInformation *info, **info_ptr;
2155 struct ldb_context *sam_ctx;
2159 status = dcesrv_netr_creds_server_step_check(dce_call,
2161 r->in.computer_name,
2163 r->out.return_authenticator,
2165 if (!NT_STATUS_IS_OK(status)) {
2169 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2170 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2171 return NT_STATUS_NOT_IMPLEMENTED;
2174 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2175 dce_call->conn->auth_state.session_info);
2176 if (sam_ctx == NULL) {
2177 return NT_STATUS_UNSUCCESSFUL;
2180 /* TODO: check r->in.server_name is our name */
2182 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2184 return NT_STATUS_NO_MEMORY;
2186 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2188 return NT_STATUS_NO_MEMORY;
2191 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2192 if (!W_ERROR_IS_OK(werr)) {
2193 return werror_to_ntstatus(werr);
2197 r->out.forest_trust_info = info_ptr;
2199 return NT_STATUS_OK;
2204 netr_ServerGetTrustInfo
2206 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2207 struct netr_ServerGetTrustInfo *r)
2209 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2213 /* include the generated boilerplate */
2214 #include "librpc/gen_ndr/ndr_netlogon_s.c"