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_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
253 lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
259 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
260 struct netr_ServerAuthenticate *r)
262 struct netr_ServerAuthenticate3 a;
265 * negotiate_flags is used as an [in] parameter
266 * so it need to be initialised.
268 * (I think ... = 0; seems wrong here --metze)
270 uint32_t negotiate_flags_in = 0;
271 uint32_t negotiate_flags_out = 0;
273 a.in.server_name = r->in.server_name;
274 a.in.account_name = r->in.account_name;
275 a.in.secure_channel_type = r->in.secure_channel_type;
276 a.in.computer_name = r->in.computer_name;
277 a.in.credentials = r->in.credentials;
278 a.in.negotiate_flags = &negotiate_flags_in;
280 a.out.return_credentials = r->out.return_credentials;
282 a.out.negotiate_flags = &negotiate_flags_out;
284 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
287 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
288 struct netr_ServerAuthenticate2 *r)
290 struct netr_ServerAuthenticate3 r3;
293 r3.in.server_name = r->in.server_name;
294 r3.in.account_name = r->in.account_name;
295 r3.in.secure_channel_type = r->in.secure_channel_type;
296 r3.in.computer_name = r->in.computer_name;
297 r3.in.credentials = r->in.credentials;
298 r3.out.return_credentials = r->out.return_credentials;
299 r3.in.negotiate_flags = r->in.negotiate_flags;
300 r3.out.negotiate_flags = r->out.negotiate_flags;
303 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
307 * NOTE: The following functions are nearly identical to the ones available in
308 * source3/rpc_server/srv_nelog_nt.c
309 * The reason we keep 2 copies is that they use different structures to
310 * represent the auth_info and the decrpc pipes.
314 * If schannel is required for this call test that it actually is available.
316 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
317 const char *computer_name,
318 bool integrity, bool privacy)
321 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
322 if (!privacy && !integrity) {
326 if ((!privacy && integrity) &&
327 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
331 if ((privacy || integrity) &&
332 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
337 /* test didn't pass */
338 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
341 return NT_STATUS_ACCESS_DENIED;
344 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
346 const char *computer_name,
347 struct netr_Authenticator *received_authenticator,
348 struct netr_Authenticator *return_authenticator,
349 struct netlogon_creds_CredentialState **creds_out)
352 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
353 bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
355 if (schannel_global_required) {
356 nt_status = schannel_check_required(auth_info,
359 if (!NT_STATUS_IS_OK(nt_status)) {
364 nt_status = schannel_check_creds_state(mem_ctx,
365 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
366 lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
368 received_authenticator,
369 return_authenticator,
375 Change the machine account password for the currently connected
376 client. Supplies only the NT#.
379 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
380 struct netr_ServerPasswordSet *r)
382 struct netlogon_creds_CredentialState *creds;
383 struct ldb_context *sam_ctx;
386 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
389 r->in.credential, r->out.return_authenticator,
391 NT_STATUS_NOT_OK_RETURN(nt_status);
393 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));
394 if (sam_ctx == NULL) {
395 return NT_STATUS_INVALID_SYSTEM_SERVICE;
398 netlogon_creds_des_decrypt(creds, r->in.new_password);
400 /* Using the sid for the account as the key, set the password */
401 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
403 NULL, /* Don't have plaintext */
404 NULL, r->in.new_password,
405 true, /* Password change */
411 Change the machine account password for the currently connected
412 client. Supplies new plaintext.
414 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
415 struct netr_ServerPasswordSet2 *r)
417 struct netlogon_creds_CredentialState *creds;
418 struct ldb_context *sam_ctx;
420 DATA_BLOB new_password;
422 struct samr_CryptPassword password_buf;
424 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
427 r->in.credential, r->out.return_authenticator,
429 NT_STATUS_NOT_OK_RETURN(nt_status);
431 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));
432 if (sam_ctx == NULL) {
433 return NT_STATUS_INVALID_SYSTEM_SERVICE;
436 memcpy(password_buf.data, r->in.new_password->data, 512);
437 SIVAL(password_buf.data, 512, r->in.new_password->length);
438 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
440 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
441 DEBUG(3,("samr: failed to decode password buffer\n"));
442 return NT_STATUS_WRONG_PASSWORD;
445 /* Using the sid for the account as the key, set the password */
446 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
448 &new_password, /* we have plaintext */
450 true, /* Password change */
459 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
460 struct netr_LogonUasLogon *r)
462 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
469 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
470 struct netr_LogonUasLogoff *r)
472 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
477 netr_LogonSamLogon_base
479 This version of the function allows other wrappers to say 'do not check the credentials'
481 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
483 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
484 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
486 struct auth_context *auth_context;
487 struct auth_usersupplied_info *user_info;
488 struct auth_serversupplied_info *server_info;
490 static const char zeros[16];
491 struct netr_SamBaseInfo *sam;
492 struct netr_SamInfo2 *sam2;
493 struct netr_SamInfo3 *sam3;
494 struct netr_SamInfo6 *sam6;
496 user_info = talloc(mem_ctx, struct auth_usersupplied_info);
497 NT_STATUS_HAVE_NO_MEMORY(user_info);
499 user_info->flags = 0;
500 user_info->mapped_state = false;
501 user_info->remote_host = NULL;
503 switch (r->in.logon_level) {
504 case NetlogonInteractiveInformation:
505 case NetlogonServiceInformation:
506 case NetlogonInteractiveTransitiveInformation:
507 case NetlogonServiceTransitiveInformation:
508 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
509 netlogon_creds_arcfour_crypt(creds,
510 r->in.logon->password->lmpassword.hash,
511 sizeof(r->in.logon->password->lmpassword.hash));
512 netlogon_creds_arcfour_crypt(creds,
513 r->in.logon->password->ntpassword.hash,
514 sizeof(r->in.logon->password->ntpassword.hash));
516 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
517 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
520 /* TODO: we need to deny anonymous access here */
521 nt_status = auth_context_create(mem_ctx,
522 dce_call->event_ctx, dce_call->msg_ctx,
523 dce_call->conn->dce_ctx->lp_ctx,
525 NT_STATUS_NOT_OK_RETURN(nt_status);
527 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
528 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
529 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
530 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
532 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
533 user_info->password_state = AUTH_PASSWORD_HASH;
535 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
536 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
537 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
539 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
540 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
541 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
544 case NetlogonNetworkInformation:
545 case NetlogonNetworkTransitiveInformation:
547 /* TODO: we need to deny anonymous access here */
548 nt_status = auth_context_create(mem_ctx,
549 dce_call->event_ctx, dce_call->msg_ctx,
550 dce_call->conn->dce_ctx->lp_ctx,
552 NT_STATUS_NOT_OK_RETURN(nt_status);
554 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
555 NT_STATUS_NOT_OK_RETURN(nt_status);
557 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
558 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
559 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
560 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
562 user_info->password_state = AUTH_PASSWORD_RESPONSE;
563 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
564 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
569 case NetlogonGenericInformation:
571 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
572 netlogon_creds_arcfour_crypt(creds,
573 r->in.logon->generic->data, r->in.logon->generic->length);
575 /* Using DES to verify kerberos tickets makes no sense */
576 return NT_STATUS_INVALID_PARAMETER;
579 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
581 struct server_id *kdc;
582 struct kdc_check_generic_kerberos check;
583 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
584 NT_STATUS_HAVE_NO_MEMORY(generic);
585 *r->out.authoritative = 1;
587 /* TODO: Describe and deal with these flags */
590 r->out.validation->generic = generic;
592 kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
593 if ((kdc == NULL) || (kdc[0].id == 0)) {
594 return NT_STATUS_NO_LOGON_SERVERS;
597 check.in.generic_request =
598 data_blob_const(r->in.logon->generic->data,
599 r->in.logon->generic->length);
601 status = irpc_call(dce_call->msg_ctx, kdc[0],
602 &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
604 if (!NT_STATUS_IS_OK(status)) {
607 generic->length = check.out.generic_reply.length;
608 generic->data = check.out.generic_reply.data;
612 /* Until we get an implemetnation of these other packages */
613 return NT_STATUS_INVALID_PARAMETER;
616 return NT_STATUS_INVALID_PARAMETER;
619 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
620 NT_STATUS_NOT_OK_RETURN(nt_status);
622 switch (r->in.validation_level) {
624 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
625 NT_STATUS_NOT_OK_RETURN(nt_status);
627 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
628 NT_STATUS_HAVE_NO_MEMORY(sam2);
631 /* And put into the talloc tree */
632 talloc_steal(sam2, sam);
633 r->out.validation->sam2 = sam2;
639 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
642 NT_STATUS_NOT_OK_RETURN(nt_status);
644 r->out.validation->sam3 = sam3;
650 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
653 NT_STATUS_NOT_OK_RETURN(nt_status);
655 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
656 NT_STATUS_HAVE_NO_MEMORY(sam6);
657 sam6->base = sam3->base;
659 sam6->sidcount = sam3->sidcount;
660 sam6->sids = sam3->sids;
662 sam6->dns_domainname.string = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
663 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
664 sam->account_name.string, sam6->dns_domainname.string);
665 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
666 /* And put into the talloc tree */
667 talloc_steal(sam6, sam3);
669 r->out.validation->sam6 = sam6;
676 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
677 /* It appears that level 6 is not individually encrypted */
678 if ((r->in.validation_level != 6) &&
679 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
680 /* This key is sent unencrypted without the ARCFOUR flag set */
681 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
682 netlogon_creds_arcfour_crypt(creds,
684 sizeof(sam->key.key));
688 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
689 /* It appears that level 6 is not individually encrypted */
690 if ((r->in.validation_level != 6) &&
691 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
692 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
693 netlogon_creds_arcfour_crypt(creds,
695 sizeof(sam->LMSessKey.key));
697 netlogon_creds_des_encrypt_LMKey(creds,
702 *r->out.authoritative = 1;
704 /* TODO: Describe and deal with these flags */
710 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
711 struct netr_LogonSamLogonEx *r)
714 struct netlogon_creds_CredentialState *creds;
716 nt_status = schannel_get_creds_state(mem_ctx,
717 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
718 lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
719 r->in.computer_name, &creds);
720 if (!NT_STATUS_IS_OK(nt_status)) {
724 if (!dce_call->conn->auth_state.auth_info ||
725 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
726 return NT_STATUS_ACCESS_DENIED;
728 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
732 netr_LogonSamLogonWithFlags
735 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
736 struct netr_LogonSamLogonWithFlags *r)
739 struct netlogon_creds_CredentialState *creds;
740 struct netr_LogonSamLogonEx r2;
742 struct netr_Authenticator *return_authenticator;
744 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
745 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
747 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
750 r->in.credential, return_authenticator,
752 NT_STATUS_NOT_OK_RETURN(nt_status);
756 r2.in.server_name = r->in.server_name;
757 r2.in.computer_name = r->in.computer_name;
758 r2.in.logon_level = r->in.logon_level;
759 r2.in.logon = r->in.logon;
760 r2.in.validation_level = r->in.validation_level;
761 r2.in.flags = r->in.flags;
762 r2.out.validation = r->out.validation;
763 r2.out.authoritative = r->out.authoritative;
764 r2.out.flags = r->out.flags;
766 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
768 r->out.return_authenticator = return_authenticator;
776 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
777 struct netr_LogonSamLogon *r)
779 struct netr_LogonSamLogonWithFlags r2;
785 r2.in.server_name = r->in.server_name;
786 r2.in.computer_name = r->in.computer_name;
787 r2.in.credential = r->in.credential;
788 r2.in.return_authenticator = r->in.return_authenticator;
789 r2.in.logon_level = r->in.logon_level;
790 r2.in.logon = r->in.logon;
791 r2.in.validation_level = r->in.validation_level;
792 r2.in.flags = &flags;
793 r2.out.validation = r->out.validation;
794 r2.out.authoritative = r->out.authoritative;
795 r2.out.flags = &flags;
797 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
799 r->out.return_authenticator = r2.out.return_authenticator;
808 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
809 struct netr_LogonSamLogoff *r)
811 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
819 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
820 struct netr_DatabaseDeltas *r)
822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
829 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
830 struct netr_DatabaseSync2 *r)
832 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
833 return NT_STATUS_NOT_IMPLEMENTED;
840 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
841 struct netr_DatabaseSync *r)
843 struct netr_DatabaseSync2 r2;
848 r2.in.logon_server = r->in.logon_server;
849 r2.in.computername = r->in.computername;
850 r2.in.credential = r->in.credential;
851 r2.in.database_id = r->in.database_id;
852 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
853 r2.in.sync_context = r->in.sync_context;
854 r2.out.sync_context = r->out.sync_context;
855 r2.out.delta_enum_array = r->out.delta_enum_array;
856 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
858 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
867 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
868 struct netr_AccountDeltas *r)
870 /* w2k3 returns "NOT IMPLEMENTED" for this call */
871 return NT_STATUS_NOT_IMPLEMENTED;
878 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
879 struct netr_AccountSync *r)
881 /* w2k3 returns "NOT IMPLEMENTED" for this call */
882 return NT_STATUS_NOT_IMPLEMENTED;
889 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
890 struct netr_GetDcName *r)
892 const char * const attrs[] = { NULL };
893 struct ldb_context *sam_ctx;
894 struct ldb_message **res;
895 struct ldb_dn *domain_dn;
899 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
900 dce_call->conn->dce_ctx->lp_ctx,
901 dce_call->conn->auth_state.session_info);
902 if (sam_ctx == NULL) {
903 return WERR_DS_UNAVAILABLE;
906 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
908 if (domain_dn == NULL) {
909 return WERR_DS_UNAVAILABLE;
912 ret = gendb_search_dn(sam_ctx, mem_ctx,
913 domain_dn, &res, attrs);
915 return WERR_NO_SUCH_DOMAIN;
918 /* TODO: - return real IP address
919 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
921 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
922 lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
923 W_ERROR_HAVE_NO_MEMORY(dcname);
925 *r->out.dcname = dcname;
933 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
934 struct netr_LogonControl2Ex *r)
936 return WERR_NOT_SUPPORTED;
943 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
944 struct netr_LogonControl *r)
946 struct netr_LogonControl2Ex r2;
949 if (r->in.level == 0x00000001) {
952 r2.in.logon_server = r->in.logon_server;
953 r2.in.function_code = r->in.function_code;
954 r2.in.level = r->in.level;
956 r2.out.query = r->out.query;
958 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
959 } else if (r->in.level == 0x00000002) {
960 werr = WERR_NOT_SUPPORTED;
962 werr = WERR_UNKNOWN_LEVEL;
972 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
973 struct netr_LogonControl2 *r)
975 struct netr_LogonControl2Ex r2;
980 r2.in.logon_server = r->in.logon_server;
981 r2.in.function_code = r->in.function_code;
982 r2.in.level = r->in.level;
983 r2.in.data = r->in.data;
984 r2.out.query = r->out.query;
986 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
991 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
992 struct ldb_context *sam_ctx,
993 struct netr_DomainTrustList *trusts,
994 uint32_t trust_flags);
999 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1000 struct netr_GetAnyDCName *r)
1002 struct netr_DomainTrustList *trusts;
1003 struct ldb_context *sam_ctx;
1004 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1008 *r->out.dcname = NULL;
1010 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1011 /* if the domainname parameter wasn't set assume our domain */
1012 r->in.domainname = lp_workgroup(lp_ctx);
1015 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1016 dce_call->conn->auth_state.session_info);
1017 if (sam_ctx == NULL) {
1018 return WERR_DS_UNAVAILABLE;
1021 if (strcasecmp(r->in.domainname, lp_workgroup(lp_ctx)) == 0) {
1022 /* well we asked for a DC of our own domain */
1023 if (samdb_is_pdc(sam_ctx)) {
1024 /* we are the PDC of the specified domain */
1025 return WERR_NO_SUCH_DOMAIN;
1028 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1029 lp_netbios_name(lp_ctx));
1030 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1035 /* Okay, now we have to consider the trusted domains */
1037 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1038 W_ERROR_HAVE_NO_MEMORY(trusts);
1042 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1043 NETR_TRUST_FLAG_INBOUND
1044 | NETR_TRUST_FLAG_OUTBOUND);
1045 W_ERROR_NOT_OK_RETURN(werr);
1047 for (i = 0; i < trusts->count; i++) {
1048 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1049 /* FIXME: Here we need to find a DC for the specified
1050 * trusted domain. */
1052 /* return WERR_OK; */
1053 return WERR_NO_SUCH_DOMAIN;
1057 return WERR_NO_SUCH_DOMAIN;
1064 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1065 struct netr_DatabaseRedo *r)
1067 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1072 netr_NetrEnumerateTurstedDomains
1074 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1075 struct netr_NetrEnumerateTrustedDomains *r)
1077 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1082 netr_LogonGetCapabilities
1084 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1085 struct netr_LogonGetCapabilities *r)
1087 /* we don't support AES yet */
1088 return NT_STATUS_NOT_IMPLEMENTED;
1093 netr_NETRLOGONSETSERVICEBITS
1095 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1096 struct netr_NETRLOGONSETSERVICEBITS *r)
1098 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1103 netr_LogonGetTrustRid
1105 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1106 struct netr_LogonGetTrustRid *r)
1108 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1113 netr_NETRLOGONCOMPUTESERVERDIGEST
1115 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1116 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1118 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1123 netr_NETRLOGONCOMPUTECLIENTDIGEST
1125 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1126 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1128 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1136 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1137 struct netr_DsRGetSiteName *r)
1139 struct ldb_context *sam_ctx;
1140 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1142 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1143 dce_call->conn->auth_state.session_info);
1144 if (sam_ctx == NULL) {
1145 return WERR_DS_UNAVAILABLE;
1148 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1149 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1156 fill in a netr_OneDomainInfo from a ldb search result
1158 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1159 struct loadparm_context *lp_ctx,
1160 struct ldb_context *sam_ctx,
1161 struct ldb_message *res,
1162 struct netr_OneDomainInfo *info,
1163 bool is_local, bool is_trust_list)
1167 if (is_trust_list) {
1168 /* w2k8 only fills this on trusted domains */
1169 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1170 info->trust_extension.length = 16;
1171 info->trust_extension.info->flags =
1172 NETR_TRUST_FLAG_TREEROOT |
1173 NETR_TRUST_FLAG_IN_FOREST |
1174 NETR_TRUST_FLAG_PRIMARY |
1175 NETR_TRUST_FLAG_NATIVE;
1177 info->trust_extension.info->parent_index = 0; /* should be index into array
1179 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1180 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1183 if (is_trust_list) {
1184 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1185 info->dns_forestname.string = NULL;
1187 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1188 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1189 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1190 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1194 info->domainname.string = lp_workgroup(lp_ctx);
1195 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1196 info->domain_guid = samdb_result_guid(res, "objectGUID");
1197 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1199 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1200 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1201 info->domain_guid = samdb_result_guid(res, "objectGUID");
1202 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1204 if (!is_trust_list) {
1205 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1208 return NT_STATUS_OK;
1212 netr_LogonGetDomainInfo
1213 this is called as part of the ADS domain logon procedure.
1215 It has an important role in convaying details about the client, such
1216 as Operating System, Version, Service Pack etc.
1218 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1219 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1221 struct netlogon_creds_CredentialState *creds;
1222 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1223 "securityIdentifier", "trustPartner", NULL };
1224 const char * const attrs2[] = { "dNSHostName",
1225 "msDS-SupportedEncryptionTypes", NULL };
1226 const char * const attrs3[] = { NULL };
1227 const char *temp_str, *temp_str2;
1228 const char *old_dns_hostname;
1229 struct ldb_context *sam_ctx;
1230 struct ldb_message **res0, **res1, **res2, **res3, *new_msg;
1231 struct ldb_dn *workstation_dn;
1232 struct netr_DomainInformation *domain_info;
1233 struct netr_LsaPolicyInformation *lsa_policy_info;
1234 struct netr_OsVersionInfoEx *os_version;
1235 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1236 bool update_dns_hostname = true;
1240 status = dcesrv_netr_creds_server_step_check(dce_call,
1242 r->in.computer_name,
1244 r->out.return_authenticator,
1246 if (!NT_STATUS_IS_OK(status)) {
1247 DEBUG(0,(__location__ " Bad credentials - error\n"));
1249 NT_STATUS_NOT_OK_RETURN(status);
1251 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1252 dce_call->conn->dce_ctx->lp_ctx,
1253 system_session(dce_call->conn->dce_ctx->lp_ctx));
1254 if (sam_ctx == NULL) {
1255 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1258 switch (r->in.level) {
1259 case 1: /* Domain information */
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;
1290 * Check that the DNS hostname when it should be updated
1291 * will be used only by maximum one host.
1293 ret = gendb_search(sam_ctx, mem_ctx,
1294 ldb_get_default_basedn(sam_ctx),
1295 &res0, attrs3, "(dNSHostName=%s)",
1296 r->in.query->workstation_info->dns_hostname);
1298 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1301 update_dns_hostname = false;
1306 /* Prepare the workstation DN */
1307 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1308 dom_sid_string(mem_ctx, creds->sid));
1309 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1311 /* Lookup for attributes in workstation object */
1312 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1315 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1318 /* Gets the old DNS hostname */
1319 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1322 /* Gets host informations and put them in our directory */
1323 new_msg = ldb_msg_new(mem_ctx);
1324 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1326 new_msg->dn = workstation_dn;
1328 /* Deletes old OS version values */
1329 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1330 "operatingSystemServicePack");
1331 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1332 "operatingSystemVersion");
1334 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1335 DEBUG(3,("Impossible to update samdb: %s\n",
1336 ldb_errstring(sam_ctx)));
1339 talloc_free(new_msg);
1341 new_msg = ldb_msg_new(mem_ctx);
1342 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1344 new_msg->dn = workstation_dn;
1346 /* Sets the OS name */
1347 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1349 r->in.query->workstation_info->os_name.string);
1352 * Sets informations from "os_version". On a empty structure
1353 * the values are cleared.
1355 if (r->in.query->workstation_info->os_version.os != NULL) {
1356 os_version = &r->in.query->workstation_info->os_version.os->os;
1358 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1359 "operatingSystemServicePack",
1360 os_version->CSDVersion);
1362 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1363 "operatingSystemVersion",
1364 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1365 os_version->MajorVersion,
1366 os_version->MinorVersion,
1367 os_version->BuildNumber
1373 * If the boolean "update_dns_hostname" remained true, then we
1374 * are fine to start the update.
1376 if (update_dns_hostname) {
1377 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1379 r->in.query->workstation_info->dns_hostname);
1381 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1382 "servicePrincipalName",
1383 talloc_asprintf(mem_ctx, "HOST/%s",
1384 r->in.computer_name)
1386 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1387 "servicePrincipalName",
1388 talloc_asprintf(mem_ctx, "HOST/%s",
1389 r->in.query->workstation_info->dns_hostname)
1393 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1394 DEBUG(3,("Impossible to update samdb: %s\n",
1395 ldb_errstring(sam_ctx)));
1398 talloc_free(new_msg);
1400 /* Writes back the domain information */
1402 /* We need to do two searches. The first will pull our primary
1403 domain and the second will pull any trusted domains. Our
1404 primary domain is also a "trusted" domain, so we need to
1405 put the primary domain into the lists of returned trusts as
1407 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1410 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1413 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1414 "(objectClass=trustedDomain)");
1416 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1419 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1420 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1422 ZERO_STRUCTP(domain_info);
1424 /* Informations about the local and trusted domains */
1426 status = fill_one_domain_info(mem_ctx,
1427 dce_call->conn->dce_ctx->lp_ctx,
1428 sam_ctx, res2[0], &domain_info->primary_domain,
1430 NT_STATUS_NOT_OK_RETURN(status);
1432 domain_info->trusted_domain_count = ret3 + 1;
1433 domain_info->trusted_domains = talloc_array(mem_ctx,
1434 struct netr_OneDomainInfo,
1435 domain_info->trusted_domain_count);
1436 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1438 for (i=0;i<ret3;i++) {
1439 status = fill_one_domain_info(mem_ctx,
1440 dce_call->conn->dce_ctx->lp_ctx,
1442 &domain_info->trusted_domains[i],
1444 NT_STATUS_NOT_OK_RETURN(status);
1447 status = fill_one_domain_info(mem_ctx,
1448 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1449 &domain_info->trusted_domains[i], true, true);
1450 NT_STATUS_NOT_OK_RETURN(status);
1452 /* Sets the supported encryption types */
1453 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1454 "msDS-SupportedEncryptionTypes",
1455 default_supported_enc_types);
1457 /* Other host domain informations */
1459 lsa_policy_info = talloc(mem_ctx,
1460 struct netr_LsaPolicyInformation);
1461 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1462 ZERO_STRUCTP(lsa_policy_info);
1464 domain_info->lsa_policy = *lsa_policy_info;
1466 /* The DNS hostname is only returned back when there is a chance
1468 if ((r->in.query->workstation_info->workstation_flags
1469 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1470 domain_info->dns_hostname.string = old_dns_hostname;
1472 domain_info->dns_hostname.string = NULL;
1475 domain_info->workstation_flags =
1476 r->in.query->workstation_info->workstation_flags;
1478 r->out.info->domain_info = domain_info;
1480 case 2: /* LSA policy information - not used at the moment */
1481 lsa_policy_info = talloc(mem_ctx,
1482 struct netr_LsaPolicyInformation);
1483 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1484 ZERO_STRUCTP(lsa_policy_info);
1486 r->out.info->lsa_policy_info = lsa_policy_info;
1489 return NT_STATUS_INVALID_LEVEL;
1493 return NT_STATUS_OK;
1499 netr_ServerPasswordGet
1501 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1502 struct netr_ServerPasswordGet *r)
1504 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1509 netr_NETRLOGONSENDTOSAM
1511 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1512 struct netr_NETRLOGONSENDTOSAM *r)
1514 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1519 netr_DsRGetDCNameEx2
1521 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1522 TALLOC_CTX *mem_ctx,
1523 struct netr_DsRGetDCNameEx2 *r)
1525 struct ldb_context *sam_ctx;
1526 struct netr_DsRGetDCNameInfo *info;
1527 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1528 const struct tsocket_address *remote_address;
1530 const char *server_site_name;
1532 struct netlogon_samlogon_response response;
1535 ZERO_STRUCTP(r->out.info);
1537 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1538 dce_call->conn->auth_state.session_info);
1539 if (sam_ctx == NULL) {
1540 return WERR_DS_UNAVAILABLE;
1543 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1544 if (tsocket_address_is_inet(remote_address, "ip")) {
1545 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1546 W_ERROR_HAVE_NO_MEMORY(addr);
1549 /* "server_unc" is ignored by w2k3 */
1551 /* Proof server site parameter "site_name" if it was specified */
1552 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1553 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1554 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1555 server_site_name) != 0)) {
1556 return WERR_NO_SUCH_DOMAIN;
1559 /* TODO: the flags are ignored for now */
1561 guid_str = r->in.domain_guid != NULL ?
1562 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1564 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1568 r->in.client_account,
1570 NETLOGON_NT_VERSION_5EX_WITH_IP,
1572 if (!NT_STATUS_IS_OK(status)) {
1573 return ntstatus_to_werror(status);
1576 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1577 W_ERROR_HAVE_NO_MEMORY(info);
1578 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1579 response.data.nt5_ex.pdc_dns_name);
1580 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1581 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1582 response.data.nt5_ex.sockaddr.pdc_ip);
1583 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1584 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1585 info->domain_guid = response.data.nt5_ex.domain_uuid;
1586 info->domain_name = response.data.nt5_ex.dns_domain;
1587 info->forest_name = response.data.nt5_ex.forest;
1588 info->dc_flags = response.data.nt5_ex.server_type;
1589 info->dc_site_name = response.data.nt5_ex.server_site;
1590 info->client_site_name = response.data.nt5_ex.client_site;
1592 *r->out.info = info;
1600 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1601 struct netr_DsRGetDCNameEx *r)
1603 struct netr_DsRGetDCNameEx2 r2;
1608 r2.in.server_unc = r->in.server_unc;
1609 r2.in.client_account = NULL;
1611 r2.in.domain_guid = r->in.domain_guid;
1612 r2.in.domain_name = r->in.domain_name;
1613 r2.in.site_name = r->in.site_name;
1614 r2.in.flags = r->in.flags;
1615 r2.out.info = r->out.info;
1617 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1625 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1626 struct netr_DsRGetDCName *r)
1628 struct netr_DsRGetDCNameEx2 r2;
1633 r2.in.server_unc = r->in.server_unc;
1634 r2.in.client_account = NULL;
1636 r2.in.domain_name = r->in.domain_name;
1637 r2.in.domain_guid = r->in.domain_guid;
1639 r2.in.site_name = NULL; /* should fill in from site GUID */
1640 r2.in.flags = r->in.flags;
1641 r2.out.info = r->out.info;
1643 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1648 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1650 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1651 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1653 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1658 netr_NetrEnumerateTrustedDomainsEx
1660 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1661 struct netr_NetrEnumerateTrustedDomainsEx *r)
1663 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1668 netr_DsRAddressToSitenamesExW
1670 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1671 struct netr_DsRAddressToSitenamesExW *r)
1673 struct ldb_context *sam_ctx;
1674 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1675 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1676 uint16_t sin_family;
1677 struct sockaddr_in *addr;
1679 struct sockaddr_in6 *addr6;
1680 char addr_str[INET6_ADDRSTRLEN];
1682 char addr_str[INET_ADDRSTRLEN];
1688 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1689 dce_call->conn->auth_state.session_info);
1690 if (sam_ctx == NULL) {
1691 return WERR_DS_UNAVAILABLE;
1694 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1695 W_ERROR_HAVE_NO_MEMORY(ctr);
1699 ctr->count = r->in.count;
1700 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1701 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1702 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1703 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1705 for (i=0; i<ctr->count; i++) {
1706 ctr->sitename[i].string = NULL;
1707 ctr->subnetname[i].string = NULL;
1709 if (r->in.addresses[i].size < sizeof(sin_family)) {
1712 sin_family = SVAL(r->in.addresses[i].buffer, 0);
1714 switch (sin_family) {
1716 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1719 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1720 res = inet_ntop(AF_INET, &addr->sin_addr,
1721 addr_str, sizeof(addr_str));
1725 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1728 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1729 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1730 addr_str, sizeof(addr_str));
1741 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1745 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1746 ctr->subnetname[i].string = subnet_name;
1754 netr_DsRAddressToSitenamesW
1756 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1757 struct netr_DsRAddressToSitenamesW *r)
1759 struct netr_DsRAddressToSitenamesExW r2;
1760 struct netr_DsRAddressToSitenamesWCtr *ctr;
1766 r2.in.server_name = r->in.server_name;
1767 r2.in.count = r->in.count;
1768 r2.in.addresses = r->in.addresses;
1770 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1771 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1773 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1774 W_ERROR_HAVE_NO_MEMORY(ctr);
1778 ctr->count = r->in.count;
1779 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1780 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1782 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1784 for (i=0; i<ctr->count; i++) {
1785 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1793 netr_DsrGetDcSiteCoverageW
1795 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1796 struct netr_DsrGetDcSiteCoverageW *r)
1798 struct ldb_context *sam_ctx;
1799 struct DcSitesCtr *ctr;
1800 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1802 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1803 dce_call->conn->auth_state.session_info);
1804 if (sam_ctx == NULL) {
1805 return WERR_DS_UNAVAILABLE;
1808 ctr = talloc(mem_ctx, struct DcSitesCtr);
1809 W_ERROR_HAVE_NO_MEMORY(ctr);
1813 /* For now only return our default site */
1815 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1816 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1817 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1818 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1824 #define GET_CHECK_STR(dest, mem, msg, attr) \
1827 s = samdb_result_string(msg, attr, NULL); \
1829 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1830 "without flatname\n", \
1831 ldb_dn_get_linearized(msg->dn))); \
1834 dest = talloc_strdup(mem, s); \
1835 W_ERROR_HAVE_NO_MEMORY(dest); \
1839 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1840 struct ldb_context *sam_ctx,
1841 struct netr_DomainTrustList *trusts,
1842 uint32_t trust_flags)
1844 struct ldb_dn *system_dn;
1845 struct ldb_message **dom_res = NULL;
1846 const char *trust_attrs[] = { "flatname", "trustPartner",
1847 "securityIdentifier", "trustDirection",
1848 "trustType", "trustAttributes", NULL };
1853 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1854 NETR_TRUST_FLAG_OUTBOUND))) {
1855 return WERR_INVALID_FLAGS;
1858 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1859 ldb_get_default_basedn(sam_ctx),
1860 "(&(objectClass=container)(cn=System))");
1862 return WERR_GENERAL_FAILURE;
1865 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1866 &dom_res, trust_attrs,
1867 "(objectclass=trustedDomain)");
1869 for (i = 0; i < ret; i++) {
1870 unsigned int trust_dir;
1873 trust_dir = samdb_result_uint(dom_res[i],
1874 "trustDirection", 0);
1876 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1877 flags |= NETR_TRUST_FLAG_INBOUND;
1879 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1880 flags |= NETR_TRUST_FLAG_OUTBOUND;
1883 if (!(flags & trust_flags)) {
1884 /* this trust direction was not requested */
1889 trusts->array = talloc_realloc(trusts, trusts->array,
1890 struct netr_DomainTrust,
1892 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1894 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1895 dom_res[i], "flatname");
1896 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1897 dom_res[i], "trustPartner");
1899 trusts->array[n].trust_flags = flags;
1900 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1901 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1902 /* TODO: find if we have parent in the list */
1903 trusts->array[n].parent_index = 0;
1906 trusts->array[n].trust_type =
1907 samdb_result_uint(dom_res[i],
1909 trusts->array[n].trust_attributes =
1910 samdb_result_uint(dom_res[i],
1911 "trustAttributes", 0);
1913 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1914 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1915 struct dom_sid zero_sid;
1916 ZERO_STRUCT(zero_sid);
1917 trusts->array[n].sid =
1918 dom_sid_dup(trusts, &zero_sid);
1920 trusts->array[n].sid =
1921 samdb_result_dom_sid(trusts, dom_res[i],
1922 "securityIdentifier");
1924 trusts->array[n].guid = GUID_zero();
1926 trusts->count = n + 1;
1929 talloc_free(dom_res);
1934 netr_DsrEnumerateDomainTrusts
1936 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1937 TALLOC_CTX *mem_ctx,
1938 struct netr_DsrEnumerateDomainTrusts *r)
1940 struct netr_DomainTrustList *trusts;
1941 struct ldb_context *sam_ctx;
1943 struct ldb_message **dom_res;
1944 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1945 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1946 const char *dnsdomain = lp_dnsdomain(lp_ctx);
1950 if (r->in.trust_flags & 0xFFFFFE00) {
1951 return WERR_INVALID_FLAGS;
1954 /* TODO: turn to hard check once we are sure this is 100% correct */
1955 if (!r->in.server_name) {
1956 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1957 "But received NULL!\n", dnsdomain));
1959 p = strchr(r->in.server_name, '.');
1961 DEBUG(3, ("Invalid domain! Expected name in domain "
1962 "[%s]. But received [%s]!\n",
1963 dnsdomain, r->in.server_name));
1964 p = r->in.server_name;
1968 if (strcasecmp(p, dnsdomain)) {
1969 DEBUG(3, ("Invalid domain! Expected name in domain "
1970 "[%s]. But received [%s]!\n",
1971 dnsdomain, r->in.server_name));
1975 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1976 W_ERROR_HAVE_NO_MEMORY(trusts);
1979 r->out.trusts = trusts;
1981 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1982 dce_call->conn->auth_state.session_info);
1983 if (sam_ctx == NULL) {
1984 return WERR_GENERAL_FAILURE;
1987 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1988 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1990 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1991 trusts, r->in.trust_flags);
1992 W_ERROR_NOT_OK_RETURN(werr);
1995 /* NOTE: we currently are always the root of the forest */
1996 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1997 int n = trusts->count;
1999 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2000 &dom_res, dom_attrs);
2002 return WERR_GENERAL_FAILURE;
2005 trusts->count = n + 1;
2006 trusts->array = talloc_realloc(trusts, trusts->array,
2007 struct netr_DomainTrust,
2009 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2011 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
2012 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
2013 trusts->array[n].trust_flags =
2014 NETR_TRUST_FLAG_NATIVE |
2015 NETR_TRUST_FLAG_TREEROOT |
2016 NETR_TRUST_FLAG_IN_FOREST |
2017 NETR_TRUST_FLAG_PRIMARY;
2018 /* we are always the root domain for now */
2019 trusts->array[n].parent_index = 0;
2020 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2021 trusts->array[n].trust_attributes = 0;
2022 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2025 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2027 talloc_free(dom_res);
2035 netr_DsrDeregisterDNSHostRecords
2037 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2038 struct netr_DsrDeregisterDNSHostRecords *r)
2040 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2045 netr_ServerTrustPasswordsGet
2047 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2048 struct netr_ServerTrustPasswordsGet *r)
2050 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2054 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2055 struct ldb_context *sam_ctx,
2056 struct loadparm_context *lp_ctx,
2057 struct lsa_ForestTrustInformation *info)
2059 struct lsa_ForestTrustDomainInfo *domain_info;
2060 struct lsa_ForestTrustRecord *e;
2061 struct ldb_message **dom_res;
2062 const char * const dom_attrs[] = { "objectSid", NULL };
2065 /* we need to provide 2 entries:
2066 * 1. the Root Forest name
2067 * 2. the Domain Information
2071 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2072 W_ERROR_HAVE_NO_MEMORY(info->entries);
2074 /* Forest root info */
2075 e = talloc(info, struct lsa_ForestTrustRecord);
2076 W_ERROR_HAVE_NO_MEMORY(e);
2079 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2080 e->time = 0; /* so far always 0 in trces. */
2081 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2083 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2085 info->entries[0] = e;
2088 e = talloc(info, struct lsa_ForestTrustRecord);
2089 W_ERROR_HAVE_NO_MEMORY(e);
2091 /* get our own domain info */
2092 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2094 return WERR_GENERAL_FAILURE;
2097 /* TODO: check if disabled and set flags accordingly */
2099 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2100 e->time = 0; /* so far always 0 in traces. */
2102 domain_info = &e->forest_trust_data.domain_info;
2103 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2105 domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
2106 domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
2108 info->entries[1] = e;
2110 talloc_free(dom_res);
2116 netr_DsRGetForestTrustInformation
2118 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2119 TALLOC_CTX *mem_ctx,
2120 struct netr_DsRGetForestTrustInformation *r)
2122 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2123 struct lsa_ForestTrustInformation *info, **info_ptr;
2124 struct ldb_context *sam_ctx;
2127 if (r->in.flags & 0xFFFFFFFE) {
2128 return WERR_INVALID_FLAGS;
2131 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2132 dce_call->conn->auth_state.session_info);
2133 if (sam_ctx == NULL) {
2134 return WERR_GENERAL_FAILURE;
2137 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2138 if (!samdb_is_pdc(sam_ctx)) {
2139 return WERR_NERR_NOTPRIMARY;
2142 if (r->in.trusted_domain_name == NULL) {
2143 return WERR_INVALID_FLAGS;
2146 /* TODO: establish an schannel connection with
2147 * r->in.trusted_domain_name and perform a
2148 * netr_GetForestTrustInformation call against it */
2150 /* for now return not implementd */
2151 return WERR_CALL_NOT_IMPLEMENTED;
2154 /* TODO: check r->in.server_name is our name */
2156 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2157 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2159 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2160 W_ERROR_HAVE_NO_MEMORY(info);
2162 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2163 W_ERROR_NOT_OK_RETURN(werr);
2166 r->out.forest_trust_info = info_ptr;
2173 netr_GetForestTrustInformation
2175 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2176 TALLOC_CTX *mem_ctx,
2177 struct netr_GetForestTrustInformation *r)
2179 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2180 struct netlogon_creds_CredentialState *creds;
2181 struct lsa_ForestTrustInformation *info, **info_ptr;
2182 struct ldb_context *sam_ctx;
2186 status = dcesrv_netr_creds_server_step_check(dce_call,
2188 r->in.computer_name,
2190 r->out.return_authenticator,
2192 if (!NT_STATUS_IS_OK(status)) {
2196 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2197 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2198 return NT_STATUS_NOT_IMPLEMENTED;
2201 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2202 dce_call->conn->auth_state.session_info);
2203 if (sam_ctx == NULL) {
2204 return NT_STATUS_UNSUCCESSFUL;
2207 /* TODO: check r->in.server_name is our name */
2209 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2211 return NT_STATUS_NO_MEMORY;
2213 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2215 return NT_STATUS_NO_MEMORY;
2218 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2219 if (!W_ERROR_IS_OK(werr)) {
2220 return werror_to_ntstatus(werr);
2224 r->out.forest_trust_info = info_ptr;
2226 return NT_STATUS_OK;
2231 netr_ServerGetTrustInfo
2233 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2234 struct netr_ServerGetTrustInfo *r)
2236 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2240 /* include the generated boilerplate */
2241 #include "librpc/gen_ndr/ndr_netlogon_s.c"