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 * Updates the DNS hostname when the client wishes that the
1263 * server should handle this for him
1264 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1265 * See MS-NRPC section 3.5.4.3.9
1267 if ((r->in.query->workstation_info->workstation_flags
1268 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1269 update_dns_hostname = false;
1273 * Checks that the computer name parameter without possible "$"
1274 * matches as prefix with the DNS hostname in the workstation
1277 temp_str = talloc_strndup(mem_ctx,
1278 r->in.computer_name,
1279 strcspn(r->in.computer_name, "$"));
1280 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1281 temp_str2 = talloc_strndup(mem_ctx,
1282 r->in.query->workstation_info->dns_hostname,
1283 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1284 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1285 if (strcasecmp(temp_str, temp_str2) != 0) {
1286 update_dns_hostname = false;
1289 /* Prepare the workstation DN */
1290 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1291 dom_sid_string(mem_ctx, creds->sid));
1292 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1294 /* Lookup for attributes in workstation object */
1295 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1298 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1301 /* Gets the old DNS hostname */
1302 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1305 /* Gets host informations and put them in our directory */
1306 new_msg = ldb_msg_new(mem_ctx);
1307 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1309 new_msg->dn = workstation_dn;
1311 /* Deletes old OS version values */
1312 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1313 "operatingSystemServicePack");
1314 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1315 "operatingSystemVersion");
1317 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1318 DEBUG(3,("Impossible to update samdb: %s\n",
1319 ldb_errstring(sam_ctx)));
1322 talloc_free(new_msg);
1324 new_msg = ldb_msg_new(mem_ctx);
1325 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1327 new_msg->dn = workstation_dn;
1329 /* Sets the OS name */
1330 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1332 r->in.query->workstation_info->os_name.string);
1335 * Sets informations from "os_version". On a empty structure
1336 * the values are cleared.
1338 if (r->in.query->workstation_info->os_version.os != NULL) {
1339 os_version = &r->in.query->workstation_info->os_version.os->os;
1341 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1342 "operatingSystemServicePack",
1343 os_version->CSDVersion);
1345 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1346 "operatingSystemVersion",
1347 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1348 os_version->MajorVersion,
1349 os_version->MinorVersion,
1350 os_version->BuildNumber
1356 * If the boolean "update_dns_hostname" remained true, then we
1357 * are fine to start the update.
1359 if (update_dns_hostname) {
1360 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1362 r->in.query->workstation_info->dns_hostname);
1364 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1365 "servicePrincipalName",
1366 talloc_asprintf(mem_ctx, "HOST/%s",
1367 r->in.computer_name)
1369 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1370 "servicePrincipalName",
1371 talloc_asprintf(mem_ctx, "HOST/%s",
1372 r->in.query->workstation_info->dns_hostname)
1376 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1377 DEBUG(3,("Impossible to update samdb: %s\n",
1378 ldb_errstring(sam_ctx)));
1381 talloc_free(new_msg);
1383 /* Writes back the domain information */
1385 /* We need to do two searches. The first will pull our primary
1386 domain and the second will pull any trusted domains. Our
1387 primary domain is also a "trusted" domain, so we need to
1388 put the primary domain into the lists of returned trusts as
1390 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1393 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1396 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1397 "(objectClass=trustedDomain)");
1399 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1402 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1403 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1405 ZERO_STRUCTP(domain_info);
1407 /* Informations about the local and trusted domains */
1409 status = fill_one_domain_info(mem_ctx,
1410 dce_call->conn->dce_ctx->lp_ctx,
1411 sam_ctx, res2[0], &domain_info->primary_domain,
1413 NT_STATUS_NOT_OK_RETURN(status);
1415 domain_info->trusted_domain_count = ret3 + 1;
1416 domain_info->trusted_domains = talloc_array(mem_ctx,
1417 struct netr_OneDomainInfo,
1418 domain_info->trusted_domain_count);
1419 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1421 for (i=0;i<ret3;i++) {
1422 status = fill_one_domain_info(mem_ctx,
1423 dce_call->conn->dce_ctx->lp_ctx,
1425 &domain_info->trusted_domains[i],
1427 NT_STATUS_NOT_OK_RETURN(status);
1430 status = fill_one_domain_info(mem_ctx,
1431 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1432 &domain_info->trusted_domains[i], true, true);
1433 NT_STATUS_NOT_OK_RETURN(status);
1435 /* Sets the supported encryption types */
1436 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1437 "msDS-SupportedEncryptionTypes",
1438 default_supported_enc_types);
1440 /* Other host domain informations */
1442 lsa_policy_info = talloc(mem_ctx,
1443 struct netr_LsaPolicyInformation);
1444 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1445 ZERO_STRUCTP(lsa_policy_info);
1447 domain_info->lsa_policy = *lsa_policy_info;
1449 /* The DNS hostname is only returned back when there is a chance
1451 if ((r->in.query->workstation_info->workstation_flags
1452 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1453 domain_info->dns_hostname.string = old_dns_hostname;
1455 domain_info->dns_hostname.string = NULL;
1458 domain_info->workstation_flags =
1459 r->in.query->workstation_info->workstation_flags;
1461 r->out.info->domain_info = domain_info;
1463 case 2: /* LSA policy information - not used at the moment */
1464 lsa_policy_info = talloc(mem_ctx,
1465 struct netr_LsaPolicyInformation);
1466 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1467 ZERO_STRUCTP(lsa_policy_info);
1469 r->out.info->lsa_policy_info = lsa_policy_info;
1472 return NT_STATUS_INVALID_LEVEL;
1476 return NT_STATUS_OK;
1482 netr_ServerPasswordGet
1484 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1485 struct netr_ServerPasswordGet *r)
1487 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1492 netr_NETRLOGONSENDTOSAM
1494 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1495 struct netr_NETRLOGONSENDTOSAM *r)
1497 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1502 netr_DsRGetDCNameEx2
1504 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1505 TALLOC_CTX *mem_ctx,
1506 struct netr_DsRGetDCNameEx2 *r)
1508 struct ldb_context *sam_ctx;
1509 struct netr_DsRGetDCNameInfo *info;
1510 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1511 const struct tsocket_address *remote_address;
1513 const char *server_site_name;
1515 struct netlogon_samlogon_response response;
1518 ZERO_STRUCTP(r->out.info);
1520 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1521 dce_call->conn->auth_state.session_info);
1522 if (sam_ctx == NULL) {
1523 return WERR_DS_UNAVAILABLE;
1526 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1527 if (tsocket_address_is_inet(remote_address, "ip")) {
1528 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1529 W_ERROR_HAVE_NO_MEMORY(addr);
1532 /* "server_unc" is ignored by w2k3 */
1534 /* Proof server site parameter "site_name" if it was specified */
1535 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1536 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1537 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1538 server_site_name) != 0)) {
1539 return WERR_NO_SUCH_DOMAIN;
1542 /* TODO: the flags are ignored for now */
1544 guid_str = r->in.domain_guid != NULL ?
1545 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1547 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1551 r->in.client_account,
1553 NETLOGON_NT_VERSION_5EX_WITH_IP,
1554 lp_ctx, &response, true);
1555 if (!NT_STATUS_IS_OK(status)) {
1556 return ntstatus_to_werror(status);
1559 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1560 W_ERROR_HAVE_NO_MEMORY(info);
1561 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1562 response.data.nt5_ex.pdc_dns_name);
1563 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1564 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1565 response.data.nt5_ex.sockaddr.pdc_ip);
1566 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1567 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1568 info->domain_guid = response.data.nt5_ex.domain_uuid;
1569 info->domain_name = response.data.nt5_ex.dns_domain;
1570 info->forest_name = response.data.nt5_ex.forest;
1571 info->dc_flags = response.data.nt5_ex.server_type;
1572 info->dc_site_name = response.data.nt5_ex.server_site;
1573 info->client_site_name = response.data.nt5_ex.client_site;
1575 *r->out.info = info;
1583 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1584 struct netr_DsRGetDCNameEx *r)
1586 struct netr_DsRGetDCNameEx2 r2;
1591 r2.in.server_unc = r->in.server_unc;
1592 r2.in.client_account = NULL;
1594 r2.in.domain_guid = r->in.domain_guid;
1595 r2.in.domain_name = r->in.domain_name;
1596 r2.in.site_name = r->in.site_name;
1597 r2.in.flags = r->in.flags;
1598 r2.out.info = r->out.info;
1600 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1608 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1609 struct netr_DsRGetDCName *r)
1611 struct netr_DsRGetDCNameEx2 r2;
1616 r2.in.server_unc = r->in.server_unc;
1617 r2.in.client_account = NULL;
1619 r2.in.domain_name = r->in.domain_name;
1620 r2.in.domain_guid = r->in.domain_guid;
1622 r2.in.site_name = NULL; /* should fill in from site GUID */
1623 r2.in.flags = r->in.flags;
1624 r2.out.info = r->out.info;
1626 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1631 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1633 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1634 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1636 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1641 netr_NetrEnumerateTrustedDomainsEx
1643 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1644 struct netr_NetrEnumerateTrustedDomainsEx *r)
1646 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1651 netr_DsRAddressToSitenamesExW
1653 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1654 struct netr_DsRAddressToSitenamesExW *r)
1656 struct ldb_context *sam_ctx;
1657 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1658 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1659 uint16_t sin_family;
1660 struct sockaddr_in *addr;
1662 struct sockaddr_in6 *addr6;
1663 char addr_str[INET6_ADDRSTRLEN];
1665 char addr_str[INET_ADDRSTRLEN];
1671 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1672 dce_call->conn->auth_state.session_info);
1673 if (sam_ctx == NULL) {
1674 return WERR_DS_UNAVAILABLE;
1677 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1678 W_ERROR_HAVE_NO_MEMORY(ctr);
1682 ctr->count = r->in.count;
1683 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1684 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1685 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1686 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1688 for (i=0; i<ctr->count; i++) {
1689 ctr->sitename[i].string = NULL;
1690 ctr->subnetname[i].string = NULL;
1692 if (r->in.addresses[i].size < sizeof(sin_family)) {
1695 sin_family = SVAL(r->in.addresses[i].buffer, 0);
1697 switch (sin_family) {
1699 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1702 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1703 res = inet_ntop(AF_INET, &addr->sin_addr,
1704 addr_str, sizeof(addr_str));
1708 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1711 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1712 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1713 addr_str, sizeof(addr_str));
1724 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1728 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1729 ctr->subnetname[i].string = subnet_name;
1737 netr_DsRAddressToSitenamesW
1739 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1740 struct netr_DsRAddressToSitenamesW *r)
1742 struct netr_DsRAddressToSitenamesExW r2;
1743 struct netr_DsRAddressToSitenamesWCtr *ctr;
1749 r2.in.server_name = r->in.server_name;
1750 r2.in.count = r->in.count;
1751 r2.in.addresses = r->in.addresses;
1753 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1754 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1756 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1757 W_ERROR_HAVE_NO_MEMORY(ctr);
1761 ctr->count = r->in.count;
1762 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1763 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1765 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1767 for (i=0; i<ctr->count; i++) {
1768 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1776 netr_DsrGetDcSiteCoverageW
1778 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1779 struct netr_DsrGetDcSiteCoverageW *r)
1781 struct ldb_context *sam_ctx;
1782 struct DcSitesCtr *ctr;
1783 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1785 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1786 dce_call->conn->auth_state.session_info);
1787 if (sam_ctx == NULL) {
1788 return WERR_DS_UNAVAILABLE;
1791 ctr = talloc(mem_ctx, struct DcSitesCtr);
1792 W_ERROR_HAVE_NO_MEMORY(ctr);
1796 /* For now only return our default site */
1798 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1799 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1800 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1801 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1807 #define GET_CHECK_STR(dest, mem, msg, attr) \
1810 s = samdb_result_string(msg, attr, NULL); \
1812 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1813 "without flatname\n", \
1814 ldb_dn_get_linearized(msg->dn))); \
1817 dest = talloc_strdup(mem, s); \
1818 W_ERROR_HAVE_NO_MEMORY(dest); \
1822 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1823 struct ldb_context *sam_ctx,
1824 struct netr_DomainTrustList *trusts,
1825 uint32_t trust_flags)
1827 struct ldb_dn *system_dn;
1828 struct ldb_message **dom_res = NULL;
1829 const char *trust_attrs[] = { "flatname", "trustPartner",
1830 "securityIdentifier", "trustDirection",
1831 "trustType", "trustAttributes", NULL };
1836 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1837 NETR_TRUST_FLAG_OUTBOUND))) {
1838 return WERR_INVALID_FLAGS;
1841 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1842 ldb_get_default_basedn(sam_ctx),
1843 "(&(objectClass=container)(cn=System))");
1845 return WERR_GENERAL_FAILURE;
1848 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1849 &dom_res, trust_attrs,
1850 "(objectclass=trustedDomain)");
1852 for (i = 0; i < ret; i++) {
1853 unsigned int trust_dir;
1856 trust_dir = samdb_result_uint(dom_res[i],
1857 "trustDirection", 0);
1859 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1860 flags |= NETR_TRUST_FLAG_INBOUND;
1862 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1863 flags |= NETR_TRUST_FLAG_OUTBOUND;
1866 if (!(flags & trust_flags)) {
1867 /* this trust direction was not requested */
1872 trusts->array = talloc_realloc(trusts, trusts->array,
1873 struct netr_DomainTrust,
1875 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1877 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1878 dom_res[i], "flatname");
1879 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1880 dom_res[i], "trustPartner");
1882 trusts->array[n].trust_flags = flags;
1883 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1884 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1885 /* TODO: find if we have parent in the list */
1886 trusts->array[n].parent_index = 0;
1889 trusts->array[n].trust_type =
1890 samdb_result_uint(dom_res[i],
1892 trusts->array[n].trust_attributes =
1893 samdb_result_uint(dom_res[i],
1894 "trustAttributes", 0);
1896 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1897 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1898 struct dom_sid zero_sid;
1899 ZERO_STRUCT(zero_sid);
1900 trusts->array[n].sid =
1901 dom_sid_dup(trusts, &zero_sid);
1903 trusts->array[n].sid =
1904 samdb_result_dom_sid(trusts, dom_res[i],
1905 "securityIdentifier");
1907 trusts->array[n].guid = GUID_zero();
1909 trusts->count = n + 1;
1912 talloc_free(dom_res);
1917 netr_DsrEnumerateDomainTrusts
1919 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1920 TALLOC_CTX *mem_ctx,
1921 struct netr_DsrEnumerateDomainTrusts *r)
1923 struct netr_DomainTrustList *trusts;
1924 struct ldb_context *sam_ctx;
1926 struct ldb_message **dom_res;
1927 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1928 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1929 const char *dnsdomain = lp_dnsdomain(lp_ctx);
1933 if (r->in.trust_flags & 0xFFFFFE00) {
1934 return WERR_INVALID_FLAGS;
1937 /* TODO: turn to hard check once we are sure this is 100% correct */
1938 if (!r->in.server_name) {
1939 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1940 "But received NULL!\n", dnsdomain));
1942 p = strchr(r->in.server_name, '.');
1944 DEBUG(3, ("Invalid domain! Expected name in domain "
1945 "[%s]. But received [%s]!\n",
1946 dnsdomain, r->in.server_name));
1947 p = r->in.server_name;
1951 if (strcasecmp(p, dnsdomain)) {
1952 DEBUG(3, ("Invalid domain! Expected name in domain "
1953 "[%s]. But received [%s]!\n",
1954 dnsdomain, r->in.server_name));
1958 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1959 W_ERROR_HAVE_NO_MEMORY(trusts);
1962 r->out.trusts = trusts;
1964 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1965 dce_call->conn->auth_state.session_info);
1966 if (sam_ctx == NULL) {
1967 return WERR_GENERAL_FAILURE;
1970 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1971 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1973 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1974 trusts, r->in.trust_flags);
1975 W_ERROR_NOT_OK_RETURN(werr);
1978 /* NOTE: we currently are always the root of the forest */
1979 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1980 int n = trusts->count;
1982 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1983 &dom_res, dom_attrs);
1985 return WERR_GENERAL_FAILURE;
1988 trusts->count = n + 1;
1989 trusts->array = talloc_realloc(trusts, trusts->array,
1990 struct netr_DomainTrust,
1992 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1994 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1995 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1996 trusts->array[n].trust_flags =
1997 NETR_TRUST_FLAG_NATIVE |
1998 NETR_TRUST_FLAG_TREEROOT |
1999 NETR_TRUST_FLAG_IN_FOREST |
2000 NETR_TRUST_FLAG_PRIMARY;
2001 /* we are always the root domain for now */
2002 trusts->array[n].parent_index = 0;
2003 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2004 trusts->array[n].trust_attributes = 0;
2005 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2008 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2010 talloc_free(dom_res);
2018 netr_DsrDeregisterDNSHostRecords
2020 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2021 struct netr_DsrDeregisterDNSHostRecords *r)
2023 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2028 netr_ServerTrustPasswordsGet
2030 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2031 struct netr_ServerTrustPasswordsGet *r)
2033 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2037 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2038 struct ldb_context *sam_ctx,
2039 struct loadparm_context *lp_ctx,
2040 struct lsa_ForestTrustInformation *info)
2042 struct lsa_ForestTrustDomainInfo *domain_info;
2043 struct lsa_ForestTrustRecord *e;
2044 struct ldb_message **dom_res;
2045 const char * const dom_attrs[] = { "objectSid", NULL };
2048 /* we need to provide 2 entries:
2049 * 1. the Root Forest name
2050 * 2. the Domain Information
2054 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2055 W_ERROR_HAVE_NO_MEMORY(info->entries);
2057 /* Forest root info */
2058 e = talloc(info, struct lsa_ForestTrustRecord);
2059 W_ERROR_HAVE_NO_MEMORY(e);
2062 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2063 e->time = 0; /* so far always 0 in trces. */
2064 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2066 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2068 info->entries[0] = e;
2071 e = talloc(info, struct lsa_ForestTrustRecord);
2072 W_ERROR_HAVE_NO_MEMORY(e);
2074 /* get our own domain info */
2075 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2077 return WERR_GENERAL_FAILURE;
2080 /* TODO: check if disabled and set flags accordingly */
2082 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2083 e->time = 0; /* so far always 0 in traces. */
2085 domain_info = &e->forest_trust_data.domain_info;
2086 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2088 domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
2089 domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
2091 info->entries[1] = e;
2093 talloc_free(dom_res);
2099 netr_DsRGetForestTrustInformation
2101 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2102 TALLOC_CTX *mem_ctx,
2103 struct netr_DsRGetForestTrustInformation *r)
2105 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2106 struct lsa_ForestTrustInformation *info, **info_ptr;
2107 struct ldb_context *sam_ctx;
2110 if (r->in.flags & 0xFFFFFFFE) {
2111 return WERR_INVALID_FLAGS;
2114 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2115 dce_call->conn->auth_state.session_info);
2116 if (sam_ctx == NULL) {
2117 return WERR_GENERAL_FAILURE;
2120 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2121 if (!samdb_is_pdc(sam_ctx)) {
2122 return WERR_NERR_NOTPRIMARY;
2125 if (r->in.trusted_domain_name == NULL) {
2126 return WERR_INVALID_FLAGS;
2129 /* TODO: establish an schannel connection with
2130 * r->in.trusted_domain_name and perform a
2131 * netr_GetForestTrustInformation call against it */
2133 /* for now return not implementd */
2134 return WERR_CALL_NOT_IMPLEMENTED;
2137 /* TODO: check r->in.server_name is our name */
2139 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2140 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2142 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2143 W_ERROR_HAVE_NO_MEMORY(info);
2145 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2146 W_ERROR_NOT_OK_RETURN(werr);
2149 r->out.forest_trust_info = info_ptr;
2156 netr_GetForestTrustInformation
2158 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2159 TALLOC_CTX *mem_ctx,
2160 struct netr_GetForestTrustInformation *r)
2162 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2163 struct netlogon_creds_CredentialState *creds;
2164 struct lsa_ForestTrustInformation *info, **info_ptr;
2165 struct ldb_context *sam_ctx;
2169 status = dcesrv_netr_creds_server_step_check(dce_call,
2171 r->in.computer_name,
2173 r->out.return_authenticator,
2175 if (!NT_STATUS_IS_OK(status)) {
2179 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2180 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2181 return NT_STATUS_NOT_IMPLEMENTED;
2184 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2185 dce_call->conn->auth_state.session_info);
2186 if (sam_ctx == NULL) {
2187 return NT_STATUS_UNSUCCESSFUL;
2190 /* TODO: check r->in.server_name is our name */
2192 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2194 return NT_STATUS_NO_MEMORY;
2196 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2198 return NT_STATUS_NO_MEMORY;
2201 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2202 if (!W_ERROR_IS_OK(werr)) {
2203 return werror_to_ntstatus(werr);
2207 r->out.forest_trust_info = info_ptr;
2209 return NT_STATUS_OK;
2214 netr_ServerGetTrustInfo
2216 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2217 struct netr_ServerGetTrustInfo *r)
2219 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2223 /* include the generated boilerplate */
2224 #include "librpc/gen_ndr/ndr_netlogon_s.c"