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 lp_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 lp_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 lp_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 = lp_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 lp_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 lp_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 = lp_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, lp_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 lp_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_NetrEnumerateTurstedDomains
1071 static WERROR 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 = lp_workgroup(lp_ctx);
1192 info->dns_domainname.string = lp_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 in our directory */
1309 new_msg = ldb_msg_new(mem_ctx);
1310 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1312 new_msg->dn = workstation_dn;
1314 /* Deletes old OS version values */
1315 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1316 "operatingSystemServicePack");
1317 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1318 "operatingSystemVersion");
1320 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1321 DEBUG(3,("Impossible to update samdb: %s\n",
1322 ldb_errstring(sam_ctx)));
1325 talloc_free(new_msg);
1327 new_msg = ldb_msg_new(mem_ctx);
1328 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1330 new_msg->dn = workstation_dn;
1332 /* Sets the OS name */
1333 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1335 r->in.query->workstation_info->os_name.string);
1338 * Sets informations from "os_version". On a empty structure
1339 * the values are cleared.
1341 if (r->in.query->workstation_info->os_version.os != NULL) {
1342 os_version = &r->in.query->workstation_info->os_version.os->os;
1344 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1345 "operatingSystemServicePack",
1346 os_version->CSDVersion);
1348 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1349 "operatingSystemVersion",
1350 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1351 os_version->MajorVersion,
1352 os_version->MinorVersion,
1353 os_version->BuildNumber
1359 * If the boolean "update_dns_hostname" remained true, then we
1360 * are fine to start the update.
1362 if (update_dns_hostname) {
1363 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1365 r->in.query->workstation_info->dns_hostname);
1367 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1368 "servicePrincipalName",
1369 talloc_asprintf(mem_ctx, "HOST/%s",
1370 r->in.computer_name)
1372 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1373 "servicePrincipalName",
1374 talloc_asprintf(mem_ctx, "HOST/%s",
1375 r->in.query->workstation_info->dns_hostname)
1379 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1380 DEBUG(3,("Impossible to update samdb: %s\n",
1381 ldb_errstring(sam_ctx)));
1384 talloc_free(new_msg);
1386 /* Writes back the domain information */
1388 /* We need to do two searches. The first will pull our primary
1389 domain and the second will pull any trusted domains. Our
1390 primary domain is also a "trusted" domain, so we need to
1391 put the primary domain into the lists of returned trusts as
1393 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1396 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1399 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1400 "(objectClass=trustedDomain)");
1402 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1405 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1406 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1408 ZERO_STRUCTP(domain_info);
1410 /* Informations about the local and trusted domains */
1412 status = fill_one_domain_info(mem_ctx,
1413 dce_call->conn->dce_ctx->lp_ctx,
1414 sam_ctx, res2[0], &domain_info->primary_domain,
1416 NT_STATUS_NOT_OK_RETURN(status);
1418 domain_info->trusted_domain_count = ret3 + 1;
1419 domain_info->trusted_domains = talloc_array(mem_ctx,
1420 struct netr_OneDomainInfo,
1421 domain_info->trusted_domain_count);
1422 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1424 for (i=0;i<ret3;i++) {
1425 status = fill_one_domain_info(mem_ctx,
1426 dce_call->conn->dce_ctx->lp_ctx,
1428 &domain_info->trusted_domains[i],
1430 NT_STATUS_NOT_OK_RETURN(status);
1433 status = fill_one_domain_info(mem_ctx,
1434 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1435 &domain_info->trusted_domains[i], true, true);
1436 NT_STATUS_NOT_OK_RETURN(status);
1438 /* Sets the supported encryption types */
1439 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1440 "msDS-SupportedEncryptionTypes",
1441 default_supported_enc_types);
1443 /* Other host domain informations */
1445 lsa_policy_info = talloc(mem_ctx,
1446 struct netr_LsaPolicyInformation);
1447 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1448 ZERO_STRUCTP(lsa_policy_info);
1450 domain_info->lsa_policy = *lsa_policy_info;
1452 /* The DNS hostname is only returned back when there is a chance
1454 if ((r->in.query->workstation_info->workstation_flags
1455 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1456 domain_info->dns_hostname.string = old_dns_hostname;
1458 domain_info->dns_hostname.string = NULL;
1461 domain_info->workstation_flags =
1462 r->in.query->workstation_info->workstation_flags;
1464 r->out.info->domain_info = domain_info;
1466 case 2: /* LSA policy information - not used at the moment */
1467 lsa_policy_info = talloc(mem_ctx,
1468 struct netr_LsaPolicyInformation);
1469 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1470 ZERO_STRUCTP(lsa_policy_info);
1472 r->out.info->lsa_policy_info = lsa_policy_info;
1475 return NT_STATUS_INVALID_LEVEL;
1479 return NT_STATUS_OK;
1485 netr_ServerPasswordGet
1487 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1488 struct netr_ServerPasswordGet *r)
1490 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1495 netr_NETRLOGONSENDTOSAM
1497 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1498 struct netr_NETRLOGONSENDTOSAM *r)
1500 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1505 netr_DsRGetDCNameEx2
1507 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1508 TALLOC_CTX *mem_ctx,
1509 struct netr_DsRGetDCNameEx2 *r)
1511 struct ldb_context *sam_ctx;
1512 struct netr_DsRGetDCNameInfo *info;
1513 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1514 const struct tsocket_address *remote_address;
1516 const char *server_site_name;
1518 struct netlogon_samlogon_response response;
1521 ZERO_STRUCTP(r->out.info);
1523 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1524 dce_call->conn->auth_state.session_info);
1525 if (sam_ctx == NULL) {
1526 return WERR_DS_UNAVAILABLE;
1529 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1530 if (tsocket_address_is_inet(remote_address, "ip")) {
1531 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1532 W_ERROR_HAVE_NO_MEMORY(addr);
1535 /* "server_unc" is ignored by w2k3 */
1537 /* Proof server site parameter "site_name" if it was specified */
1538 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1539 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1540 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1541 server_site_name) != 0)) {
1542 return WERR_NO_SUCH_DOMAIN;
1545 /* TODO: the flags are ignored for now */
1547 guid_str = r->in.domain_guid != NULL ?
1548 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1550 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1554 r->in.client_account,
1556 NETLOGON_NT_VERSION_5EX_WITH_IP,
1557 lp_ctx, &response, true);
1558 if (!NT_STATUS_IS_OK(status)) {
1559 return ntstatus_to_werror(status);
1562 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1563 W_ERROR_HAVE_NO_MEMORY(info);
1564 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1565 response.data.nt5_ex.pdc_dns_name);
1566 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1567 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1568 response.data.nt5_ex.sockaddr.pdc_ip);
1569 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1570 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1571 info->domain_guid = response.data.nt5_ex.domain_uuid;
1572 info->domain_name = response.data.nt5_ex.dns_domain;
1573 info->forest_name = response.data.nt5_ex.forest;
1574 info->dc_flags = response.data.nt5_ex.server_type;
1575 info->dc_site_name = response.data.nt5_ex.server_site;
1576 info->client_site_name = response.data.nt5_ex.client_site;
1578 *r->out.info = info;
1586 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1587 struct netr_DsRGetDCNameEx *r)
1589 struct netr_DsRGetDCNameEx2 r2;
1594 r2.in.server_unc = r->in.server_unc;
1595 r2.in.client_account = NULL;
1597 r2.in.domain_guid = r->in.domain_guid;
1598 r2.in.domain_name = r->in.domain_name;
1599 r2.in.site_name = r->in.site_name;
1600 r2.in.flags = r->in.flags;
1601 r2.out.info = r->out.info;
1603 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1611 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1612 struct netr_DsRGetDCName *r)
1614 struct netr_DsRGetDCNameEx2 r2;
1619 r2.in.server_unc = r->in.server_unc;
1620 r2.in.client_account = NULL;
1622 r2.in.domain_name = r->in.domain_name;
1623 r2.in.domain_guid = r->in.domain_guid;
1625 r2.in.site_name = NULL; /* should fill in from site GUID */
1626 r2.in.flags = r->in.flags;
1627 r2.out.info = r->out.info;
1629 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1634 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1636 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1637 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1639 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1644 netr_NetrEnumerateTrustedDomainsEx
1646 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1647 struct netr_NetrEnumerateTrustedDomainsEx *r)
1649 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1654 netr_DsRAddressToSitenamesExW
1656 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1657 struct netr_DsRAddressToSitenamesExW *r)
1659 struct ldb_context *sam_ctx;
1660 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1661 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1662 uint16_t sin_family;
1663 struct sockaddr_in *addr;
1665 struct sockaddr_in6 *addr6;
1666 char addr_str[INET6_ADDRSTRLEN];
1668 char addr_str[INET_ADDRSTRLEN];
1674 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1675 dce_call->conn->auth_state.session_info);
1676 if (sam_ctx == NULL) {
1677 return WERR_DS_UNAVAILABLE;
1680 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1681 W_ERROR_HAVE_NO_MEMORY(ctr);
1685 ctr->count = r->in.count;
1686 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1687 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1688 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1689 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1691 for (i=0; i<ctr->count; i++) {
1692 ctr->sitename[i].string = NULL;
1693 ctr->subnetname[i].string = NULL;
1695 if (r->in.addresses[i].size < sizeof(sin_family)) {
1698 sin_family = SVAL(r->in.addresses[i].buffer, 0);
1700 switch (sin_family) {
1702 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1705 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1706 res = inet_ntop(AF_INET, &addr->sin_addr,
1707 addr_str, sizeof(addr_str));
1711 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1714 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1715 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1716 addr_str, sizeof(addr_str));
1727 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1731 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1732 ctr->subnetname[i].string = subnet_name;
1740 netr_DsRAddressToSitenamesW
1742 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1743 struct netr_DsRAddressToSitenamesW *r)
1745 struct netr_DsRAddressToSitenamesExW r2;
1746 struct netr_DsRAddressToSitenamesWCtr *ctr;
1752 r2.in.server_name = r->in.server_name;
1753 r2.in.count = r->in.count;
1754 r2.in.addresses = r->in.addresses;
1756 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1757 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1759 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1760 W_ERROR_HAVE_NO_MEMORY(ctr);
1764 ctr->count = r->in.count;
1765 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1766 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1768 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1770 for (i=0; i<ctr->count; i++) {
1771 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1779 netr_DsrGetDcSiteCoverageW
1781 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1782 struct netr_DsrGetDcSiteCoverageW *r)
1784 struct ldb_context *sam_ctx;
1785 struct DcSitesCtr *ctr;
1786 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1788 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1789 dce_call->conn->auth_state.session_info);
1790 if (sam_ctx == NULL) {
1791 return WERR_DS_UNAVAILABLE;
1794 ctr = talloc(mem_ctx, struct DcSitesCtr);
1795 W_ERROR_HAVE_NO_MEMORY(ctr);
1799 /* For now only return our default site */
1801 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1802 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1803 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1804 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1810 #define GET_CHECK_STR(dest, mem, msg, attr) \
1813 s = samdb_result_string(msg, attr, NULL); \
1815 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1816 "without flatname\n", \
1817 ldb_dn_get_linearized(msg->dn))); \
1820 dest = talloc_strdup(mem, s); \
1821 W_ERROR_HAVE_NO_MEMORY(dest); \
1825 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1826 struct ldb_context *sam_ctx,
1827 struct netr_DomainTrustList *trusts,
1828 uint32_t trust_flags)
1830 struct ldb_dn *system_dn;
1831 struct ldb_message **dom_res = NULL;
1832 const char *trust_attrs[] = { "flatname", "trustPartner",
1833 "securityIdentifier", "trustDirection",
1834 "trustType", "trustAttributes", NULL };
1839 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1840 NETR_TRUST_FLAG_OUTBOUND))) {
1841 return WERR_INVALID_FLAGS;
1844 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1845 ldb_get_default_basedn(sam_ctx),
1846 "(&(objectClass=container)(cn=System))");
1848 return WERR_GENERAL_FAILURE;
1851 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1852 &dom_res, trust_attrs,
1853 "(objectclass=trustedDomain)");
1855 for (i = 0; i < ret; i++) {
1856 unsigned int trust_dir;
1859 trust_dir = samdb_result_uint(dom_res[i],
1860 "trustDirection", 0);
1862 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1863 flags |= NETR_TRUST_FLAG_INBOUND;
1865 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1866 flags |= NETR_TRUST_FLAG_OUTBOUND;
1869 if (!(flags & trust_flags)) {
1870 /* this trust direction was not requested */
1875 trusts->array = talloc_realloc(trusts, trusts->array,
1876 struct netr_DomainTrust,
1878 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1880 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1881 dom_res[i], "flatname");
1882 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1883 dom_res[i], "trustPartner");
1885 trusts->array[n].trust_flags = flags;
1886 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1887 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1888 /* TODO: find if we have parent in the list */
1889 trusts->array[n].parent_index = 0;
1892 trusts->array[n].trust_type =
1893 samdb_result_uint(dom_res[i],
1895 trusts->array[n].trust_attributes =
1896 samdb_result_uint(dom_res[i],
1897 "trustAttributes", 0);
1899 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1900 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1901 struct dom_sid zero_sid;
1902 ZERO_STRUCT(zero_sid);
1903 trusts->array[n].sid =
1904 dom_sid_dup(trusts, &zero_sid);
1906 trusts->array[n].sid =
1907 samdb_result_dom_sid(trusts, dom_res[i],
1908 "securityIdentifier");
1910 trusts->array[n].guid = GUID_zero();
1912 trusts->count = n + 1;
1915 talloc_free(dom_res);
1920 netr_DsrEnumerateDomainTrusts
1922 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1923 TALLOC_CTX *mem_ctx,
1924 struct netr_DsrEnumerateDomainTrusts *r)
1926 struct netr_DomainTrustList *trusts;
1927 struct ldb_context *sam_ctx;
1929 struct ldb_message **dom_res;
1930 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1931 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1932 const char *dnsdomain = lp_dnsdomain(lp_ctx);
1936 if (r->in.trust_flags & 0xFFFFFE00) {
1937 return WERR_INVALID_FLAGS;
1940 /* TODO: turn to hard check once we are sure this is 100% correct */
1941 if (!r->in.server_name) {
1942 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1943 "But received NULL!\n", dnsdomain));
1945 p = strchr(r->in.server_name, '.');
1947 DEBUG(3, ("Invalid domain! Expected name in domain "
1948 "[%s]. But received [%s]!\n",
1949 dnsdomain, r->in.server_name));
1950 p = r->in.server_name;
1954 if (strcasecmp(p, dnsdomain)) {
1955 DEBUG(3, ("Invalid domain! Expected name in domain "
1956 "[%s]. But received [%s]!\n",
1957 dnsdomain, r->in.server_name));
1961 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1962 W_ERROR_HAVE_NO_MEMORY(trusts);
1965 r->out.trusts = trusts;
1967 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1968 dce_call->conn->auth_state.session_info);
1969 if (sam_ctx == NULL) {
1970 return WERR_GENERAL_FAILURE;
1973 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1974 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1976 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1977 trusts, r->in.trust_flags);
1978 W_ERROR_NOT_OK_RETURN(werr);
1981 /* NOTE: we currently are always the root of the forest */
1982 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1983 int n = trusts->count;
1985 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1986 &dom_res, dom_attrs);
1988 return WERR_GENERAL_FAILURE;
1991 trusts->count = n + 1;
1992 trusts->array = talloc_realloc(trusts, trusts->array,
1993 struct netr_DomainTrust,
1995 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1997 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1998 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1999 trusts->array[n].trust_flags =
2000 NETR_TRUST_FLAG_NATIVE |
2001 NETR_TRUST_FLAG_TREEROOT |
2002 NETR_TRUST_FLAG_IN_FOREST |
2003 NETR_TRUST_FLAG_PRIMARY;
2004 /* we are always the root domain for now */
2005 trusts->array[n].parent_index = 0;
2006 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2007 trusts->array[n].trust_attributes = 0;
2008 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2011 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2013 talloc_free(dom_res);
2021 netr_DsrDeregisterDNSHostRecords
2023 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2024 struct netr_DsrDeregisterDNSHostRecords *r)
2026 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2031 netr_ServerTrustPasswordsGet
2033 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2034 struct netr_ServerTrustPasswordsGet *r)
2036 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2040 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2041 struct ldb_context *sam_ctx,
2042 struct loadparm_context *lp_ctx,
2043 struct lsa_ForestTrustInformation *info)
2045 struct lsa_ForestTrustDomainInfo *domain_info;
2046 struct lsa_ForestTrustRecord *e;
2047 struct ldb_message **dom_res;
2048 const char * const dom_attrs[] = { "objectSid", NULL };
2051 /* we need to provide 2 entries:
2052 * 1. the Root Forest name
2053 * 2. the Domain Information
2057 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2058 W_ERROR_HAVE_NO_MEMORY(info->entries);
2060 /* Forest root info */
2061 e = talloc(info, struct lsa_ForestTrustRecord);
2062 W_ERROR_HAVE_NO_MEMORY(e);
2065 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2066 e->time = 0; /* so far always 0 in trces. */
2067 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2069 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2071 info->entries[0] = e;
2074 e = talloc(info, struct lsa_ForestTrustRecord);
2075 W_ERROR_HAVE_NO_MEMORY(e);
2077 /* get our own domain info */
2078 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2080 return WERR_GENERAL_FAILURE;
2083 /* TODO: check if disabled and set flags accordingly */
2085 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2086 e->time = 0; /* so far always 0 in traces. */
2088 domain_info = &e->forest_trust_data.domain_info;
2089 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2091 domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
2092 domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
2094 info->entries[1] = e;
2096 talloc_free(dom_res);
2102 netr_DsRGetForestTrustInformation
2104 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2105 TALLOC_CTX *mem_ctx,
2106 struct netr_DsRGetForestTrustInformation *r)
2108 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2109 struct lsa_ForestTrustInformation *info, **info_ptr;
2110 struct ldb_context *sam_ctx;
2113 if (r->in.flags & 0xFFFFFFFE) {
2114 return WERR_INVALID_FLAGS;
2117 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2118 dce_call->conn->auth_state.session_info);
2119 if (sam_ctx == NULL) {
2120 return WERR_GENERAL_FAILURE;
2123 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2124 if (!samdb_is_pdc(sam_ctx)) {
2125 return WERR_NERR_NOTPRIMARY;
2128 if (r->in.trusted_domain_name == NULL) {
2129 return WERR_INVALID_FLAGS;
2132 /* TODO: establish an schannel connection with
2133 * r->in.trusted_domain_name and perform a
2134 * netr_GetForestTrustInformation call against it */
2136 /* for now return not implementd */
2137 return WERR_CALL_NOT_IMPLEMENTED;
2140 /* TODO: check r->in.server_name is our name */
2142 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2143 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2145 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2146 W_ERROR_HAVE_NO_MEMORY(info);
2148 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2149 W_ERROR_NOT_OK_RETURN(werr);
2152 r->out.forest_trust_info = info_ptr;
2159 netr_GetForestTrustInformation
2161 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2162 TALLOC_CTX *mem_ctx,
2163 struct netr_GetForestTrustInformation *r)
2165 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2166 struct netlogon_creds_CredentialState *creds;
2167 struct lsa_ForestTrustInformation *info, **info_ptr;
2168 struct ldb_context *sam_ctx;
2172 status = dcesrv_netr_creds_server_step_check(dce_call,
2174 r->in.computer_name,
2176 r->out.return_authenticator,
2178 if (!NT_STATUS_IS_OK(status)) {
2182 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2183 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2184 return NT_STATUS_NOT_IMPLEMENTED;
2187 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2188 dce_call->conn->auth_state.session_info);
2189 if (sam_ctx == NULL) {
2190 return NT_STATUS_UNSUCCESSFUL;
2193 /* TODO: check r->in.server_name is our name */
2195 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2197 return NT_STATUS_NO_MEMORY;
2199 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2201 return NT_STATUS_NO_MEMORY;
2204 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2205 if (!W_ERROR_IS_OK(werr)) {
2206 return werror_to_ntstatus(werr);
2210 r->out.forest_trust_info = info_ptr;
2212 return NT_STATUS_OK;
2217 netr_ServerGetTrustInfo
2219 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2220 struct netr_ServerGetTrustInfo *r)
2222 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2226 /* include the generated boilerplate */
2227 #include "librpc/gen_ndr/ndr_netlogon_s.c"