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(mem_ctx, struct auth_usersupplied_info);
495 NT_STATUS_HAVE_NO_MEMORY(user_info);
497 user_info->flags = 0;
498 user_info->mapped_state = false;
499 user_info->remote_host = NULL;
501 switch (r->in.logon_level) {
502 case NetlogonInteractiveInformation:
503 case NetlogonServiceInformation:
504 case NetlogonInteractiveTransitiveInformation:
505 case NetlogonServiceTransitiveInformation:
506 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
507 netlogon_creds_arcfour_crypt(creds,
508 r->in.logon->password->lmpassword.hash,
509 sizeof(r->in.logon->password->lmpassword.hash));
510 netlogon_creds_arcfour_crypt(creds,
511 r->in.logon->password->ntpassword.hash,
512 sizeof(r->in.logon->password->ntpassword.hash));
514 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
515 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
518 /* TODO: we need to deny anonymous access here */
519 nt_status = auth_context_create(mem_ctx,
520 dce_call->event_ctx, dce_call->msg_ctx,
521 dce_call->conn->dce_ctx->lp_ctx,
523 NT_STATUS_NOT_OK_RETURN(nt_status);
525 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
526 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
527 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
528 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
530 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
531 user_info->password_state = AUTH_PASSWORD_HASH;
533 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
534 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
535 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
537 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
538 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
539 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
542 case NetlogonNetworkInformation:
543 case NetlogonNetworkTransitiveInformation:
545 /* TODO: we need to deny anonymous access here */
546 nt_status = auth_context_create(mem_ctx,
547 dce_call->event_ctx, dce_call->msg_ctx,
548 dce_call->conn->dce_ctx->lp_ctx,
550 NT_STATUS_NOT_OK_RETURN(nt_status);
552 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
553 NT_STATUS_NOT_OK_RETURN(nt_status);
555 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
556 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
557 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
558 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
560 user_info->password_state = AUTH_PASSWORD_RESPONSE;
561 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
562 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
567 case NetlogonGenericInformation:
569 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
570 netlogon_creds_arcfour_crypt(creds,
571 r->in.logon->generic->data, r->in.logon->generic->length);
573 /* Using DES to verify kerberos tickets makes no sense */
574 return NT_STATUS_INVALID_PARAMETER;
577 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
579 struct server_id *kdc;
580 struct kdc_check_generic_kerberos check;
581 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
582 NT_STATUS_HAVE_NO_MEMORY(generic);
583 *r->out.authoritative = 1;
585 /* TODO: Describe and deal with these flags */
588 r->out.validation->generic = generic;
590 kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
591 if ((kdc == NULL) || (kdc[0].id == 0)) {
592 return NT_STATUS_NO_LOGON_SERVERS;
595 check.in.generic_request =
596 data_blob_const(r->in.logon->generic->data,
597 r->in.logon->generic->length);
599 status = irpc_call(dce_call->msg_ctx, kdc[0],
600 &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
602 if (!NT_STATUS_IS_OK(status)) {
605 generic->length = check.out.generic_reply.length;
606 generic->data = check.out.generic_reply.data;
610 /* Until we get an implemetnation of these other packages */
611 return NT_STATUS_INVALID_PARAMETER;
614 return NT_STATUS_INVALID_PARAMETER;
617 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
618 NT_STATUS_NOT_OK_RETURN(nt_status);
620 switch (r->in.validation_level) {
622 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
623 NT_STATUS_NOT_OK_RETURN(nt_status);
625 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
626 NT_STATUS_HAVE_NO_MEMORY(sam2);
629 /* And put into the talloc tree */
630 talloc_steal(sam2, sam);
631 r->out.validation->sam2 = sam2;
637 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
640 NT_STATUS_NOT_OK_RETURN(nt_status);
642 r->out.validation->sam3 = sam3;
648 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
651 NT_STATUS_NOT_OK_RETURN(nt_status);
653 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
654 NT_STATUS_HAVE_NO_MEMORY(sam6);
655 sam6->base = sam3->base;
657 sam6->sidcount = sam3->sidcount;
658 sam6->sids = sam3->sids;
660 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
661 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
662 sam->account_name.string, sam6->dns_domainname.string);
663 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
664 /* And put into the talloc tree */
665 talloc_steal(sam6, sam3);
667 r->out.validation->sam6 = sam6;
674 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
675 /* It appears that level 6 is not individually encrypted */
676 if ((r->in.validation_level != 6) &&
677 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
678 /* This key is sent unencrypted without the ARCFOUR flag set */
679 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
680 netlogon_creds_arcfour_crypt(creds,
682 sizeof(sam->key.key));
686 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
687 /* It appears that level 6 is not individually encrypted */
688 if ((r->in.validation_level != 6) &&
689 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
690 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
691 netlogon_creds_arcfour_crypt(creds,
693 sizeof(sam->LMSessKey.key));
695 netlogon_creds_des_encrypt_LMKey(creds,
700 *r->out.authoritative = 1;
702 /* TODO: Describe and deal with these flags */
708 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
709 struct netr_LogonSamLogonEx *r)
712 struct netlogon_creds_CredentialState *creds;
714 nt_status = schannel_get_creds_state(mem_ctx,
715 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
716 r->in.computer_name, &creds);
717 if (!NT_STATUS_IS_OK(nt_status)) {
721 if (!dce_call->conn->auth_state.auth_info ||
722 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
723 return NT_STATUS_ACCESS_DENIED;
725 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
729 netr_LogonSamLogonWithFlags
732 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
733 struct netr_LogonSamLogonWithFlags *r)
736 struct netlogon_creds_CredentialState *creds;
737 struct netr_LogonSamLogonEx r2;
739 struct netr_Authenticator *return_authenticator;
741 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
742 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
744 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
747 r->in.credential, return_authenticator,
749 NT_STATUS_NOT_OK_RETURN(nt_status);
753 r2.in.server_name = r->in.server_name;
754 r2.in.computer_name = r->in.computer_name;
755 r2.in.logon_level = r->in.logon_level;
756 r2.in.logon = r->in.logon;
757 r2.in.validation_level = r->in.validation_level;
758 r2.in.flags = r->in.flags;
759 r2.out.validation = r->out.validation;
760 r2.out.authoritative = r->out.authoritative;
761 r2.out.flags = r->out.flags;
763 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
765 r->out.return_authenticator = return_authenticator;
773 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
774 struct netr_LogonSamLogon *r)
776 struct netr_LogonSamLogonWithFlags r2;
782 r2.in.server_name = r->in.server_name;
783 r2.in.computer_name = r->in.computer_name;
784 r2.in.credential = r->in.credential;
785 r2.in.return_authenticator = r->in.return_authenticator;
786 r2.in.logon_level = r->in.logon_level;
787 r2.in.logon = r->in.logon;
788 r2.in.validation_level = r->in.validation_level;
789 r2.in.flags = &flags;
790 r2.out.validation = r->out.validation;
791 r2.out.authoritative = r->out.authoritative;
792 r2.out.flags = &flags;
794 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
796 r->out.return_authenticator = r2.out.return_authenticator;
805 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
806 struct netr_LogonSamLogoff *r)
808 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
816 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
817 struct netr_DatabaseDeltas *r)
819 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
826 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
827 struct netr_DatabaseSync2 *r)
829 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
830 return NT_STATUS_NOT_IMPLEMENTED;
837 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
838 struct netr_DatabaseSync *r)
840 struct netr_DatabaseSync2 r2;
845 r2.in.logon_server = r->in.logon_server;
846 r2.in.computername = r->in.computername;
847 r2.in.credential = r->in.credential;
848 r2.in.database_id = r->in.database_id;
849 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
850 r2.in.sync_context = r->in.sync_context;
851 r2.out.sync_context = r->out.sync_context;
852 r2.out.delta_enum_array = r->out.delta_enum_array;
853 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
855 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
864 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
865 struct netr_AccountDeltas *r)
867 /* w2k3 returns "NOT IMPLEMENTED" for this call */
868 return NT_STATUS_NOT_IMPLEMENTED;
875 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
876 struct netr_AccountSync *r)
878 /* w2k3 returns "NOT IMPLEMENTED" for this call */
879 return NT_STATUS_NOT_IMPLEMENTED;
886 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
887 struct netr_GetDcName *r)
889 const char * const attrs[] = { NULL };
890 struct ldb_context *sam_ctx;
891 struct ldb_message **res;
892 struct ldb_dn *domain_dn;
896 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
897 dce_call->conn->dce_ctx->lp_ctx,
898 dce_call->conn->auth_state.session_info);
899 if (sam_ctx == NULL) {
900 return WERR_DS_UNAVAILABLE;
903 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
905 if (domain_dn == NULL) {
906 return WERR_DS_UNAVAILABLE;
909 ret = gendb_search_dn(sam_ctx, mem_ctx,
910 domain_dn, &res, attrs);
912 return WERR_NO_SUCH_DOMAIN;
915 /* TODO: - return real IP address
916 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
918 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
919 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
920 W_ERROR_HAVE_NO_MEMORY(dcname);
922 *r->out.dcname = dcname;
930 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
931 struct netr_LogonControl2Ex *r)
933 return WERR_NOT_SUPPORTED;
940 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
941 struct netr_LogonControl *r)
943 struct netr_LogonControl2Ex r2;
946 if (r->in.level == 0x00000001) {
949 r2.in.logon_server = r->in.logon_server;
950 r2.in.function_code = r->in.function_code;
951 r2.in.level = r->in.level;
953 r2.out.query = r->out.query;
955 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
956 } else if (r->in.level == 0x00000002) {
957 werr = WERR_NOT_SUPPORTED;
959 werr = WERR_UNKNOWN_LEVEL;
969 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
970 struct netr_LogonControl2 *r)
972 struct netr_LogonControl2Ex r2;
977 r2.in.logon_server = r->in.logon_server;
978 r2.in.function_code = r->in.function_code;
979 r2.in.level = r->in.level;
980 r2.in.data = r->in.data;
981 r2.out.query = r->out.query;
983 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
988 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
989 struct ldb_context *sam_ctx,
990 struct netr_DomainTrustList *trusts,
991 uint32_t trust_flags);
996 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
997 struct netr_GetAnyDCName *r)
999 struct netr_DomainTrustList *trusts;
1000 struct ldb_context *sam_ctx;
1001 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1005 *r->out.dcname = NULL;
1007 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1008 /* if the domainname parameter wasn't set assume our domain */
1009 r->in.domainname = lpcfg_workgroup(lp_ctx);
1012 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1013 dce_call->conn->auth_state.session_info);
1014 if (sam_ctx == NULL) {
1015 return WERR_DS_UNAVAILABLE;
1018 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1019 /* well we asked for a DC of our own domain */
1020 if (samdb_is_pdc(sam_ctx)) {
1021 /* we are the PDC of the specified domain */
1022 return WERR_NO_SUCH_DOMAIN;
1025 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1026 lpcfg_netbios_name(lp_ctx));
1027 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1032 /* Okay, now we have to consider the trusted domains */
1034 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1035 W_ERROR_HAVE_NO_MEMORY(trusts);
1039 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1040 NETR_TRUST_FLAG_INBOUND
1041 | NETR_TRUST_FLAG_OUTBOUND);
1042 W_ERROR_NOT_OK_RETURN(werr);
1044 for (i = 0; i < trusts->count; i++) {
1045 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1046 /* FIXME: Here we need to find a DC for the specified
1047 * trusted domain. */
1049 /* return WERR_OK; */
1050 return WERR_NO_SUCH_DOMAIN;
1054 return WERR_NO_SUCH_DOMAIN;
1061 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1062 struct netr_DatabaseRedo *r)
1064 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1069 netr_NetrEnumerateTrustedDomains
1071 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1072 struct netr_NetrEnumerateTrustedDomains *r)
1074 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1079 netr_LogonGetCapabilities
1081 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1082 struct netr_LogonGetCapabilities *r)
1084 /* we don't support AES yet */
1085 return NT_STATUS_NOT_IMPLEMENTED;
1090 netr_NETRLOGONSETSERVICEBITS
1092 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1093 struct netr_NETRLOGONSETSERVICEBITS *r)
1095 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1100 netr_LogonGetTrustRid
1102 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1103 struct netr_LogonGetTrustRid *r)
1105 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1110 netr_NETRLOGONCOMPUTESERVERDIGEST
1112 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1113 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1115 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1120 netr_NETRLOGONCOMPUTECLIENTDIGEST
1122 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1123 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1125 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1133 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1134 struct netr_DsRGetSiteName *r)
1136 struct ldb_context *sam_ctx;
1137 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1139 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1140 dce_call->conn->auth_state.session_info);
1141 if (sam_ctx == NULL) {
1142 return WERR_DS_UNAVAILABLE;
1145 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1146 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1153 fill in a netr_OneDomainInfo from a ldb search result
1155 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1156 struct loadparm_context *lp_ctx,
1157 struct ldb_context *sam_ctx,
1158 struct ldb_message *res,
1159 struct netr_OneDomainInfo *info,
1160 bool is_local, bool is_trust_list)
1164 if (is_trust_list) {
1165 /* w2k8 only fills this on trusted domains */
1166 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1167 info->trust_extension.length = 16;
1168 info->trust_extension.info->flags =
1169 NETR_TRUST_FLAG_TREEROOT |
1170 NETR_TRUST_FLAG_IN_FOREST |
1171 NETR_TRUST_FLAG_PRIMARY |
1172 NETR_TRUST_FLAG_NATIVE;
1174 info->trust_extension.info->parent_index = 0; /* should be index into array
1176 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1177 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1180 if (is_trust_list) {
1181 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1182 info->dns_forestname.string = NULL;
1184 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1185 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1186 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1187 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1191 info->domainname.string = lpcfg_workgroup(lp_ctx);
1192 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1193 info->domain_guid = samdb_result_guid(res, "objectGUID");
1194 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1196 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1197 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1198 info->domain_guid = samdb_result_guid(res, "objectGUID");
1199 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1201 if (!is_trust_list) {
1202 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1205 return NT_STATUS_OK;
1209 netr_LogonGetDomainInfo
1210 this is called as part of the ADS domain logon procedure.
1212 It has an important role in convaying details about the client, such
1213 as Operating System, Version, Service Pack etc.
1215 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1216 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1218 struct netlogon_creds_CredentialState *creds;
1219 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1220 "securityIdentifier", "trustPartner", NULL };
1221 const char * const attrs2[] = { "dNSHostName",
1222 "msDS-SupportedEncryptionTypes", NULL };
1223 const char *temp_str, *temp_str2;
1224 const char *old_dns_hostname;
1225 struct ldb_context *sam_ctx;
1226 struct ldb_message **res1, **res2, **res3, *new_msg;
1227 struct ldb_dn *workstation_dn;
1228 struct netr_DomainInformation *domain_info;
1229 struct netr_LsaPolicyInformation *lsa_policy_info;
1230 struct netr_OsVersionInfoEx *os_version;
1231 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1232 bool update_dns_hostname = true;
1236 status = dcesrv_netr_creds_server_step_check(dce_call,
1238 r->in.computer_name,
1240 r->out.return_authenticator,
1242 if (!NT_STATUS_IS_OK(status)) {
1243 DEBUG(0,(__location__ " Bad credentials - error\n"));
1245 NT_STATUS_NOT_OK_RETURN(status);
1247 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1248 dce_call->conn->dce_ctx->lp_ctx,
1249 system_session(dce_call->conn->dce_ctx->lp_ctx));
1250 if (sam_ctx == NULL) {
1251 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1254 switch (r->in.level) {
1255 case 1: /* Domain information */
1257 if (r->in.query->workstation_info == NULL) {
1258 return NT_STATUS_INVALID_PARAMETER;
1262 * Checks that the computer name parameter without possible "$"
1263 * matches as prefix with the DNS hostname in the workstation
1266 temp_str = talloc_strndup(mem_ctx,
1267 r->in.computer_name,
1268 strcspn(r->in.computer_name, "$"));
1269 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1270 temp_str2 = talloc_strndup(mem_ctx,
1271 r->in.query->workstation_info->dns_hostname,
1272 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1273 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1274 if (strcasecmp(temp_str, temp_str2) != 0) {
1275 update_dns_hostname = false;
1278 /* Prepare the workstation DN */
1279 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1280 dom_sid_string(mem_ctx, creds->sid));
1281 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1283 /* Lookup for attributes in workstation object */
1284 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1287 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1290 /* Gets the old DNS hostname */
1291 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1295 * Updates the DNS hostname when the client wishes that the
1296 * server should handle this for him
1297 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1298 * obviously only checked when we do already have a
1300 * See MS-NRPC section 3.5.4.3.9
1302 if ((old_dns_hostname != NULL) &&
1303 (r->in.query->workstation_info->workstation_flags
1304 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1305 update_dns_hostname = false;
1308 /* Gets host informations and put them into our directory */
1310 new_msg = ldb_msg_new(mem_ctx);
1311 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1313 new_msg->dn = workstation_dn;
1315 /* Sets the OS name */
1316 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1318 r->in.query->workstation_info->os_name.string);
1321 * Sets informations from "os_version". On an empty structure
1322 * the values are cleared.
1324 if (r->in.query->workstation_info->os_version.os != NULL) {
1325 os_version = &r->in.query->workstation_info->os_version.os->os;
1327 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1328 "operatingSystemServicePack",
1329 os_version->CSDVersion);
1331 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1332 "operatingSystemVersion",
1333 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1334 os_version->MajorVersion,
1335 os_version->MinorVersion,
1336 os_version->BuildNumber
1340 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1341 "operatingSystemServicePack");
1343 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1344 "operatingSystemVersion");
1348 * If the boolean "update_dns_hostname" remained true, then we
1349 * are fine to start the update.
1351 if (update_dns_hostname) {
1352 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1354 r->in.query->workstation_info->dns_hostname);
1356 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1357 "servicePrincipalName",
1358 talloc_asprintf(mem_ctx, "HOST/%s",
1359 r->in.computer_name)
1361 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1362 "servicePrincipalName",
1363 talloc_asprintf(mem_ctx, "HOST/%s",
1364 r->in.query->workstation_info->dns_hostname)
1368 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1369 DEBUG(3,("Impossible to update samdb: %s\n",
1370 ldb_errstring(sam_ctx)));
1373 talloc_free(new_msg);
1375 /* Writes back the domain information */
1377 /* We need to do two searches. The first will pull our primary
1378 domain and the second will pull any trusted domains. Our
1379 primary domain is also a "trusted" domain, so we need to
1380 put the primary domain into the lists of returned trusts as
1382 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1385 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1388 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1389 "(objectClass=trustedDomain)");
1391 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1394 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1395 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1397 ZERO_STRUCTP(domain_info);
1399 /* Informations about the local and trusted domains */
1401 status = fill_one_domain_info(mem_ctx,
1402 dce_call->conn->dce_ctx->lp_ctx,
1403 sam_ctx, res2[0], &domain_info->primary_domain,
1405 NT_STATUS_NOT_OK_RETURN(status);
1407 domain_info->trusted_domain_count = ret3 + 1;
1408 domain_info->trusted_domains = talloc_array(mem_ctx,
1409 struct netr_OneDomainInfo,
1410 domain_info->trusted_domain_count);
1411 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1413 for (i=0;i<ret3;i++) {
1414 status = fill_one_domain_info(mem_ctx,
1415 dce_call->conn->dce_ctx->lp_ctx,
1417 &domain_info->trusted_domains[i],
1419 NT_STATUS_NOT_OK_RETURN(status);
1422 status = fill_one_domain_info(mem_ctx,
1423 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1424 &domain_info->trusted_domains[i], true, true);
1425 NT_STATUS_NOT_OK_RETURN(status);
1427 /* Sets the supported encryption types */
1428 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1429 "msDS-SupportedEncryptionTypes",
1430 default_supported_enc_types);
1432 /* Other host domain informations */
1434 lsa_policy_info = talloc(mem_ctx,
1435 struct netr_LsaPolicyInformation);
1436 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1437 ZERO_STRUCTP(lsa_policy_info);
1439 domain_info->lsa_policy = *lsa_policy_info;
1441 /* The DNS hostname is only returned back when there is a chance
1443 if ((r->in.query->workstation_info->workstation_flags
1444 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1445 domain_info->dns_hostname.string = old_dns_hostname;
1447 domain_info->dns_hostname.string = NULL;
1450 domain_info->workstation_flags =
1451 r->in.query->workstation_info->workstation_flags;
1453 r->out.info->domain_info = domain_info;
1455 case 2: /* LSA policy information - not used at the moment */
1456 lsa_policy_info = talloc(mem_ctx,
1457 struct netr_LsaPolicyInformation);
1458 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1459 ZERO_STRUCTP(lsa_policy_info);
1461 r->out.info->lsa_policy_info = lsa_policy_info;
1464 return NT_STATUS_INVALID_LEVEL;
1468 return NT_STATUS_OK;
1474 netr_ServerPasswordGet
1476 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1477 struct netr_ServerPasswordGet *r)
1479 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1484 netr_NETRLOGONSENDTOSAM
1486 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1487 struct netr_NETRLOGONSENDTOSAM *r)
1489 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1494 netr_DsRGetDCNameEx2
1496 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1497 TALLOC_CTX *mem_ctx,
1498 struct netr_DsRGetDCNameEx2 *r)
1500 struct ldb_context *sam_ctx;
1501 struct netr_DsRGetDCNameInfo *info;
1502 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1503 const struct tsocket_address *remote_address;
1505 const char *server_site_name;
1507 struct netlogon_samlogon_response response;
1510 ZERO_STRUCTP(r->out.info);
1512 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1513 dce_call->conn->auth_state.session_info);
1514 if (sam_ctx == NULL) {
1515 return WERR_DS_UNAVAILABLE;
1518 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1519 if (tsocket_address_is_inet(remote_address, "ip")) {
1520 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1521 W_ERROR_HAVE_NO_MEMORY(addr);
1524 /* "server_unc" is ignored by w2k3 */
1526 /* Proof server site parameter "site_name" if it was specified */
1527 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1528 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1529 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1530 server_site_name) != 0)) {
1531 return WERR_NO_SUCH_DOMAIN;
1534 /* TODO: the flags are ignored for now */
1536 guid_str = r->in.domain_guid != NULL ?
1537 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1539 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1543 r->in.client_account,
1545 NETLOGON_NT_VERSION_5EX_WITH_IP,
1546 lp_ctx, &response, true);
1547 if (!NT_STATUS_IS_OK(status)) {
1548 return ntstatus_to_werror(status);
1551 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1552 W_ERROR_HAVE_NO_MEMORY(info);
1553 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1554 response.data.nt5_ex.pdc_dns_name);
1555 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1556 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1557 response.data.nt5_ex.sockaddr.pdc_ip);
1558 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1559 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1560 info->domain_guid = response.data.nt5_ex.domain_uuid;
1561 info->domain_name = response.data.nt5_ex.dns_domain;
1562 info->forest_name = response.data.nt5_ex.forest;
1563 info->dc_flags = response.data.nt5_ex.server_type;
1564 info->dc_site_name = response.data.nt5_ex.server_site;
1565 info->client_site_name = response.data.nt5_ex.client_site;
1567 *r->out.info = info;
1575 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1576 struct netr_DsRGetDCNameEx *r)
1578 struct netr_DsRGetDCNameEx2 r2;
1583 r2.in.server_unc = r->in.server_unc;
1584 r2.in.client_account = NULL;
1586 r2.in.domain_guid = r->in.domain_guid;
1587 r2.in.domain_name = r->in.domain_name;
1588 r2.in.site_name = r->in.site_name;
1589 r2.in.flags = r->in.flags;
1590 r2.out.info = r->out.info;
1592 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1600 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1601 struct netr_DsRGetDCName *r)
1603 struct netr_DsRGetDCNameEx2 r2;
1608 r2.in.server_unc = r->in.server_unc;
1609 r2.in.client_account = NULL;
1611 r2.in.domain_name = r->in.domain_name;
1612 r2.in.domain_guid = r->in.domain_guid;
1614 r2.in.site_name = NULL; /* should fill in from site GUID */
1615 r2.in.flags = r->in.flags;
1616 r2.out.info = r->out.info;
1618 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1623 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1625 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1626 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1628 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1633 netr_NetrEnumerateTrustedDomainsEx
1635 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1636 struct netr_NetrEnumerateTrustedDomainsEx *r)
1638 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1643 netr_DsRAddressToSitenamesExW
1645 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1646 struct netr_DsRAddressToSitenamesExW *r)
1648 struct ldb_context *sam_ctx;
1649 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1650 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1651 sa_family_t sin_family;
1652 struct sockaddr_in *addr;
1654 struct sockaddr_in6 *addr6;
1655 char addr_str[INET6_ADDRSTRLEN];
1657 char addr_str[INET_ADDRSTRLEN];
1663 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1664 dce_call->conn->auth_state.session_info);
1665 if (sam_ctx == NULL) {
1666 return WERR_DS_UNAVAILABLE;
1669 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1670 W_ERROR_HAVE_NO_MEMORY(ctr);
1674 ctr->count = r->in.count;
1675 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1676 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1677 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1678 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1680 for (i=0; i<ctr->count; i++) {
1681 ctr->sitename[i].string = NULL;
1682 ctr->subnetname[i].string = NULL;
1684 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1687 /* The first two byte of the buffer are reserved for the
1688 * "sin_family" but for now only the first one is used. */
1689 sin_family = r->in.addresses[i].buffer[0];
1691 switch (sin_family) {
1693 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1696 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1697 res = inet_ntop(AF_INET, &addr->sin_addr,
1698 addr_str, sizeof(addr_str));
1702 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1705 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1706 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1707 addr_str, sizeof(addr_str));
1718 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1722 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1723 ctr->subnetname[i].string = subnet_name;
1731 netr_DsRAddressToSitenamesW
1733 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1734 struct netr_DsRAddressToSitenamesW *r)
1736 struct netr_DsRAddressToSitenamesExW r2;
1737 struct netr_DsRAddressToSitenamesWCtr *ctr;
1743 r2.in.server_name = r->in.server_name;
1744 r2.in.count = r->in.count;
1745 r2.in.addresses = r->in.addresses;
1747 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1748 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1750 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1751 W_ERROR_HAVE_NO_MEMORY(ctr);
1755 ctr->count = r->in.count;
1756 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1757 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1759 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1761 for (i=0; i<ctr->count; i++) {
1762 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1770 netr_DsrGetDcSiteCoverageW
1772 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1773 struct netr_DsrGetDcSiteCoverageW *r)
1775 struct ldb_context *sam_ctx;
1776 struct DcSitesCtr *ctr;
1777 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1779 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1780 dce_call->conn->auth_state.session_info);
1781 if (sam_ctx == NULL) {
1782 return WERR_DS_UNAVAILABLE;
1785 ctr = talloc(mem_ctx, struct DcSitesCtr);
1786 W_ERROR_HAVE_NO_MEMORY(ctr);
1790 /* For now only return our default site */
1792 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1793 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1794 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1795 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1801 #define GET_CHECK_STR(dest, mem, msg, attr) \
1804 s = samdb_result_string(msg, attr, NULL); \
1806 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1807 "without flatname\n", \
1808 ldb_dn_get_linearized(msg->dn))); \
1811 dest = talloc_strdup(mem, s); \
1812 W_ERROR_HAVE_NO_MEMORY(dest); \
1816 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1817 struct ldb_context *sam_ctx,
1818 struct netr_DomainTrustList *trusts,
1819 uint32_t trust_flags)
1821 struct ldb_dn *system_dn;
1822 struct ldb_message **dom_res = NULL;
1823 const char *trust_attrs[] = { "flatname", "trustPartner",
1824 "securityIdentifier", "trustDirection",
1825 "trustType", "trustAttributes", NULL };
1830 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1831 NETR_TRUST_FLAG_OUTBOUND))) {
1832 return WERR_INVALID_FLAGS;
1835 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1836 ldb_get_default_basedn(sam_ctx),
1837 "(&(objectClass=container)(cn=System))");
1839 return WERR_GENERAL_FAILURE;
1842 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1843 &dom_res, trust_attrs,
1844 "(objectclass=trustedDomain)");
1846 for (i = 0; i < ret; i++) {
1847 unsigned int trust_dir;
1850 trust_dir = samdb_result_uint(dom_res[i],
1851 "trustDirection", 0);
1853 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1854 flags |= NETR_TRUST_FLAG_INBOUND;
1856 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1857 flags |= NETR_TRUST_FLAG_OUTBOUND;
1860 if (!(flags & trust_flags)) {
1861 /* this trust direction was not requested */
1866 trusts->array = talloc_realloc(trusts, trusts->array,
1867 struct netr_DomainTrust,
1869 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1871 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1872 dom_res[i], "flatname");
1873 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1874 dom_res[i], "trustPartner");
1876 trusts->array[n].trust_flags = flags;
1877 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1878 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1879 /* TODO: find if we have parent in the list */
1880 trusts->array[n].parent_index = 0;
1883 trusts->array[n].trust_type =
1884 samdb_result_uint(dom_res[i],
1886 trusts->array[n].trust_attributes =
1887 samdb_result_uint(dom_res[i],
1888 "trustAttributes", 0);
1890 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1891 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1892 struct dom_sid zero_sid;
1893 ZERO_STRUCT(zero_sid);
1894 trusts->array[n].sid =
1895 dom_sid_dup(trusts, &zero_sid);
1897 trusts->array[n].sid =
1898 samdb_result_dom_sid(trusts, dom_res[i],
1899 "securityIdentifier");
1901 trusts->array[n].guid = GUID_zero();
1903 trusts->count = n + 1;
1906 talloc_free(dom_res);
1911 netr_DsrEnumerateDomainTrusts
1913 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1914 TALLOC_CTX *mem_ctx,
1915 struct netr_DsrEnumerateDomainTrusts *r)
1917 struct netr_DomainTrustList *trusts;
1918 struct ldb_context *sam_ctx;
1920 struct ldb_message **dom_res;
1921 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1922 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1923 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
1927 if (r->in.trust_flags & 0xFFFFFE00) {
1928 return WERR_INVALID_FLAGS;
1931 /* TODO: turn to hard check once we are sure this is 100% correct */
1932 if (!r->in.server_name) {
1933 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1934 "But received NULL!\n", dnsdomain));
1936 p = strchr(r->in.server_name, '.');
1938 DEBUG(3, ("Invalid domain! Expected name in domain "
1939 "[%s]. But received [%s]!\n",
1940 dnsdomain, r->in.server_name));
1941 p = r->in.server_name;
1945 if (strcasecmp(p, dnsdomain)) {
1946 DEBUG(3, ("Invalid domain! Expected name in domain "
1947 "[%s]. But received [%s]!\n",
1948 dnsdomain, r->in.server_name));
1952 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1953 W_ERROR_HAVE_NO_MEMORY(trusts);
1956 r->out.trusts = trusts;
1958 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1959 dce_call->conn->auth_state.session_info);
1960 if (sam_ctx == NULL) {
1961 return WERR_GENERAL_FAILURE;
1964 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1965 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1967 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1968 trusts, r->in.trust_flags);
1969 W_ERROR_NOT_OK_RETURN(werr);
1972 /* NOTE: we currently are always the root of the forest */
1973 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1974 uint32_t n = trusts->count;
1976 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1977 &dom_res, dom_attrs);
1979 return WERR_GENERAL_FAILURE;
1982 trusts->count = n + 1;
1983 trusts->array = talloc_realloc(trusts, trusts->array,
1984 struct netr_DomainTrust,
1986 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1988 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
1989 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
1990 trusts->array[n].trust_flags =
1991 NETR_TRUST_FLAG_NATIVE |
1992 NETR_TRUST_FLAG_TREEROOT |
1993 NETR_TRUST_FLAG_IN_FOREST |
1994 NETR_TRUST_FLAG_PRIMARY;
1995 /* we are always the root domain for now */
1996 trusts->array[n].parent_index = 0;
1997 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1998 trusts->array[n].trust_attributes = 0;
1999 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2002 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2004 talloc_free(dom_res);
2012 netr_DsrDeregisterDNSHostRecords
2014 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2015 struct netr_DsrDeregisterDNSHostRecords *r)
2017 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2022 netr_ServerTrustPasswordsGet
2024 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2025 struct netr_ServerTrustPasswordsGet *r)
2027 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2031 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2032 struct ldb_context *sam_ctx,
2033 struct loadparm_context *lp_ctx,
2034 struct lsa_ForestTrustInformation *info)
2036 struct lsa_ForestTrustDomainInfo *domain_info;
2037 struct lsa_ForestTrustRecord *e;
2038 struct ldb_message **dom_res;
2039 const char * const dom_attrs[] = { "objectSid", NULL };
2042 /* we need to provide 2 entries:
2043 * 1. the Root Forest name
2044 * 2. the Domain Information
2048 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2049 W_ERROR_HAVE_NO_MEMORY(info->entries);
2051 /* Forest root info */
2052 e = talloc(info, struct lsa_ForestTrustRecord);
2053 W_ERROR_HAVE_NO_MEMORY(e);
2056 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2057 e->time = 0; /* so far always 0 in trces. */
2058 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2060 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2062 info->entries[0] = e;
2065 e = talloc(info, struct lsa_ForestTrustRecord);
2066 W_ERROR_HAVE_NO_MEMORY(e);
2068 /* get our own domain info */
2069 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2071 return WERR_GENERAL_FAILURE;
2074 /* TODO: check if disabled and set flags accordingly */
2076 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2077 e->time = 0; /* so far always 0 in traces. */
2079 domain_info = &e->forest_trust_data.domain_info;
2080 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2082 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2083 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2085 info->entries[1] = e;
2087 talloc_free(dom_res);
2093 netr_DsRGetForestTrustInformation
2095 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2096 TALLOC_CTX *mem_ctx,
2097 struct netr_DsRGetForestTrustInformation *r)
2099 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2100 struct lsa_ForestTrustInformation *info, **info_ptr;
2101 struct ldb_context *sam_ctx;
2104 if (r->in.flags & 0xFFFFFFFE) {
2105 return WERR_INVALID_FLAGS;
2108 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2109 dce_call->conn->auth_state.session_info);
2110 if (sam_ctx == NULL) {
2111 return WERR_GENERAL_FAILURE;
2114 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2115 if (!samdb_is_pdc(sam_ctx)) {
2116 return WERR_NERR_NOTPRIMARY;
2119 if (r->in.trusted_domain_name == NULL) {
2120 return WERR_INVALID_FLAGS;
2123 /* TODO: establish an schannel connection with
2124 * r->in.trusted_domain_name and perform a
2125 * netr_GetForestTrustInformation call against it */
2127 /* for now return not implementd */
2128 return WERR_CALL_NOT_IMPLEMENTED;
2131 /* TODO: check r->in.server_name is our name */
2133 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2134 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2136 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2137 W_ERROR_HAVE_NO_MEMORY(info);
2139 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2140 W_ERROR_NOT_OK_RETURN(werr);
2143 r->out.forest_trust_info = info_ptr;
2150 netr_GetForestTrustInformation
2152 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2153 TALLOC_CTX *mem_ctx,
2154 struct netr_GetForestTrustInformation *r)
2156 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2157 struct netlogon_creds_CredentialState *creds;
2158 struct lsa_ForestTrustInformation *info, **info_ptr;
2159 struct ldb_context *sam_ctx;
2163 status = dcesrv_netr_creds_server_step_check(dce_call,
2165 r->in.computer_name,
2167 r->out.return_authenticator,
2169 if (!NT_STATUS_IS_OK(status)) {
2173 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2174 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2175 return NT_STATUS_NOT_IMPLEMENTED;
2178 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2179 dce_call->conn->auth_state.session_info);
2180 if (sam_ctx == NULL) {
2181 return NT_STATUS_UNSUCCESSFUL;
2184 /* TODO: check r->in.server_name is our name */
2186 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2188 return NT_STATUS_NO_MEMORY;
2190 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2192 return NT_STATUS_NO_MEMORY;
2195 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2196 if (!W_ERROR_IS_OK(werr)) {
2197 return werror_to_ntstatus(werr);
2201 r->out.forest_trust_info = info_ptr;
2203 return NT_STATUS_OK;
2208 netr_ServerGetTrustInfo
2210 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2211 struct netr_ServerGetTrustInfo *r)
2213 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2217 /* include the generated boilerplate */
2218 #include "librpc/gen_ndr/ndr_netlogon_s.c"