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"
36 struct netlogon_server_pipe_state {
37 struct netr_Credential client_challenge;
38 struct netr_Credential server_challenge;
41 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
42 struct netr_ServerReqChallenge *r)
44 struct netlogon_server_pipe_state *pipe_state =
45 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
47 ZERO_STRUCTP(r->out.return_credentials);
49 /* destroyed on pipe shutdown */
52 talloc_free(pipe_state);
53 dce_call->context->private_data = NULL;
56 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
57 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
59 pipe_state->client_challenge = *r->in.credentials;
61 generate_random_buffer(pipe_state->server_challenge.data,
62 sizeof(pipe_state->server_challenge.data));
64 *r->out.return_credentials = pipe_state->server_challenge;
66 dce_call->context->private_data = pipe_state;
71 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
72 struct netr_ServerAuthenticate3 *r)
74 struct netlogon_server_pipe_state *pipe_state =
75 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
76 struct netlogon_creds_CredentialState *creds;
77 struct ldb_context *sam_ctx;
78 struct samr_Password *mach_pwd;
79 uint32_t user_account_control;
81 struct ldb_message **msgs;
83 const char *attrs[] = {"unicodePwd", "userAccountControl",
86 const char *trust_dom_attrs[] = {"flatname", NULL};
87 const char *account_name;
89 ZERO_STRUCTP(r->out.return_credentials);
93 * According to Microsoft (see bugid #6099)
94 * Windows 7 looks at the negotiate_flags
95 * returned in this structure *even if the
96 * call fails with access denied!
98 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
99 NETLOGON_NEG_PERSISTENT_SAMREPL |
100 NETLOGON_NEG_ARCFOUR |
101 NETLOGON_NEG_PROMOTION_COUNT |
102 NETLOGON_NEG_CHANGELOG_BDC |
103 NETLOGON_NEG_FULL_SYNC_REPL |
104 NETLOGON_NEG_MULTIPLE_SIDS |
106 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
107 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
108 NETLOGON_NEG_GENERIC_PASSTHROUGH |
109 NETLOGON_NEG_CONCURRENT_RPC |
110 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
111 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
112 NETLOGON_NEG_STRONG_KEYS |
113 NETLOGON_NEG_TRANSITIVE_TRUSTS |
114 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
115 NETLOGON_NEG_PASSWORD_SET2 |
116 NETLOGON_NEG_GETDOMAININFO |
117 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
118 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
119 NETLOGON_NEG_RODC_PASSTHROUGH |
120 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
121 NETLOGON_NEG_AUTHENTICATED_RPC;
124 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
125 return NT_STATUS_ACCESS_DENIED;
128 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
129 system_session(dce_call->conn->dce_ctx->lp_ctx));
130 if (sam_ctx == NULL) {
131 return NT_STATUS_INVALID_SYSTEM_SERVICE;
134 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
135 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
136 const char *flatname;
137 if (!encoded_account) {
138 return NT_STATUS_NO_MEMORY;
141 /* Kill the trailing dot */
142 if (encoded_account[strlen(encoded_account)-1] == '.') {
143 encoded_account[strlen(encoded_account)-1] = '\0';
146 /* pull the user attributes */
147 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
149 "(&(trustPartner=%s)(objectclass=trustedDomain))",
152 if (num_records == 0) {
153 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
155 return NT_STATUS_ACCESS_DENIED;
158 if (num_records > 1) {
159 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
160 return NT_STATUS_INTERNAL_DB_CORRUPTION;
163 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
165 /* No flatname for this trust - we can't proceed */
166 return NT_STATUS_ACCESS_DENIED;
168 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
171 return NT_STATUS_NO_MEMORY;
175 account_name = r->in.account_name;
178 /* pull the user attributes */
179 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
180 "(&(sAMAccountName=%s)(objectclass=user))",
181 ldb_binary_encode_string(mem_ctx, account_name));
183 if (num_records == 0) {
184 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
185 r->in.account_name));
186 return NT_STATUS_ACCESS_DENIED;
189 if (num_records > 1) {
190 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
191 return NT_STATUS_INTERNAL_DB_CORRUPTION;
194 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
196 if (user_account_control & UF_ACCOUNTDISABLE) {
197 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
198 return NT_STATUS_ACCESS_DENIED;
201 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
202 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
203 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
204 return NT_STATUS_ACCESS_DENIED;
206 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
207 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
208 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
209 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
211 return NT_STATUS_ACCESS_DENIED;
213 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
214 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
215 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
216 return NT_STATUS_ACCESS_DENIED;
219 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
220 r->in.secure_channel_type));
221 return NT_STATUS_ACCESS_DENIED;
224 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
227 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
228 if (mach_pwd == NULL) {
229 return NT_STATUS_ACCESS_DENIED;
232 creds = netlogon_creds_server_init(mem_ctx,
235 r->in.secure_channel_type,
236 &pipe_state->client_challenge,
237 &pipe_state->server_challenge,
240 r->out.return_credentials,
241 *r->in.negotiate_flags);
244 return NT_STATUS_ACCESS_DENIED;
247 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
249 nt_status = schannel_save_creds_state(mem_ctx,
250 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
251 lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
257 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
258 struct netr_ServerAuthenticate *r)
260 struct netr_ServerAuthenticate3 a;
263 * negotiate_flags is used as an [in] parameter
264 * so it need to be initialised.
266 * (I think ... = 0; seems wrong here --metze)
268 uint32_t negotiate_flags_in = 0;
269 uint32_t negotiate_flags_out = 0;
271 a.in.server_name = r->in.server_name;
272 a.in.account_name = r->in.account_name;
273 a.in.secure_channel_type = r->in.secure_channel_type;
274 a.in.computer_name = r->in.computer_name;
275 a.in.credentials = r->in.credentials;
276 a.in.negotiate_flags = &negotiate_flags_in;
278 a.out.return_credentials = r->out.return_credentials;
280 a.out.negotiate_flags = &negotiate_flags_out;
282 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
285 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
286 struct netr_ServerAuthenticate2 *r)
288 struct netr_ServerAuthenticate3 r3;
291 r3.in.server_name = r->in.server_name;
292 r3.in.account_name = r->in.account_name;
293 r3.in.secure_channel_type = r->in.secure_channel_type;
294 r3.in.computer_name = r->in.computer_name;
295 r3.in.credentials = r->in.credentials;
296 r3.out.return_credentials = r->out.return_credentials;
297 r3.in.negotiate_flags = r->in.negotiate_flags;
298 r3.out.negotiate_flags = r->out.negotiate_flags;
301 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
305 * NOTE: The following functions are nearly identical to the ones available in
306 * source3/rpc_server/srv_nelog_nt.c
307 * The reason we keep 2 copies is that they use different structures to
308 * represent the auth_info and the decrpc pipes.
312 * If schannel is required for this call test that it actually is available.
314 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
315 const char *computer_name,
316 bool integrity, bool privacy)
319 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
320 if (!privacy && !integrity) {
324 if ((!privacy && integrity) &&
325 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
329 if ((privacy || integrity) &&
330 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
335 /* test didn't pass */
336 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
339 return NT_STATUS_ACCESS_DENIED;
342 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
344 const char *computer_name,
345 struct netr_Authenticator *received_authenticator,
346 struct netr_Authenticator *return_authenticator,
347 struct netlogon_creds_CredentialState **creds_out)
350 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
351 bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
353 if (schannel_global_required) {
354 nt_status = schannel_check_required(auth_info,
357 if (!NT_STATUS_IS_OK(nt_status)) {
362 nt_status = schannel_check_creds_state(mem_ctx,
363 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_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 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
621 NT_STATUS_NOT_OK_RETURN(nt_status);
623 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
624 /* It appears that level 6 is not individually encrypted */
625 if ((r->in.validation_level != 6) &&
626 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
627 /* This key is sent unencrypted without the ARCFOUR flag set */
628 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
629 netlogon_creds_arcfour_crypt(creds,
631 sizeof(sam->key.key));
635 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
636 /* It appears that level 6 is not individually encrypted */
637 if ((r->in.validation_level != 6) &&
638 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
639 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
640 netlogon_creds_arcfour_crypt(creds,
642 sizeof(sam->LMSessKey.key));
644 netlogon_creds_des_encrypt_LMKey(creds,
649 switch (r->in.validation_level) {
651 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
652 NT_STATUS_HAVE_NO_MEMORY(sam2);
654 r->out.validation->sam2 = sam2;
658 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
659 NT_STATUS_HAVE_NO_MEMORY(sam3);
661 r->out.validation->sam3 = sam3;
665 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
666 NT_STATUS_HAVE_NO_MEMORY(sam6);
668 sam6->forest.string = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
669 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
670 sam->account_name.string, sam6->forest.string);
671 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
672 r->out.validation->sam6 = sam6;
679 *r->out.authoritative = 1;
681 /* TODO: Describe and deal with these flags */
687 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
688 struct netr_LogonSamLogonEx *r)
691 struct netlogon_creds_CredentialState *creds;
693 nt_status = schannel_get_creds_state(mem_ctx,
694 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
695 lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
696 r->in.computer_name, &creds);
697 if (!NT_STATUS_IS_OK(nt_status)) {
701 if (!dce_call->conn->auth_state.auth_info ||
702 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
703 return NT_STATUS_ACCESS_DENIED;
705 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
709 netr_LogonSamLogonWithFlags
712 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
713 struct netr_LogonSamLogonWithFlags *r)
716 struct netlogon_creds_CredentialState *creds;
717 struct netr_LogonSamLogonEx r2;
719 struct netr_Authenticator *return_authenticator;
721 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
722 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
724 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
727 r->in.credential, return_authenticator,
729 NT_STATUS_NOT_OK_RETURN(nt_status);
733 r2.in.server_name = r->in.server_name;
734 r2.in.computer_name = r->in.computer_name;
735 r2.in.logon_level = r->in.logon_level;
736 r2.in.logon = r->in.logon;
737 r2.in.validation_level = r->in.validation_level;
738 r2.in.flags = r->in.flags;
739 r2.out.validation = r->out.validation;
740 r2.out.authoritative = r->out.authoritative;
741 r2.out.flags = r->out.flags;
743 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
745 r->out.return_authenticator = return_authenticator;
753 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
754 struct netr_LogonSamLogon *r)
756 struct netr_LogonSamLogonWithFlags r2;
762 r2.in.server_name = r->in.server_name;
763 r2.in.computer_name = r->in.computer_name;
764 r2.in.credential = r->in.credential;
765 r2.in.return_authenticator = r->in.return_authenticator;
766 r2.in.logon_level = r->in.logon_level;
767 r2.in.logon = r->in.logon;
768 r2.in.validation_level = r->in.validation_level;
769 r2.in.flags = &flags;
770 r2.out.validation = r->out.validation;
771 r2.out.authoritative = r->out.authoritative;
772 r2.out.flags = &flags;
774 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
776 r->out.return_authenticator = r2.out.return_authenticator;
785 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
786 struct netr_LogonSamLogoff *r)
788 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
796 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
797 struct netr_DatabaseDeltas *r)
799 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
806 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
807 struct netr_DatabaseSync2 *r)
809 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
810 return NT_STATUS_NOT_IMPLEMENTED;
817 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
818 struct netr_DatabaseSync *r)
820 struct netr_DatabaseSync2 r2;
825 r2.in.logon_server = r->in.logon_server;
826 r2.in.computername = r->in.computername;
827 r2.in.credential = r->in.credential;
828 r2.in.database_id = r->in.database_id;
829 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
830 r2.in.sync_context = r->in.sync_context;
831 r2.out.sync_context = r->out.sync_context;
832 r2.out.delta_enum_array = r->out.delta_enum_array;
833 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
835 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
844 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
845 struct netr_AccountDeltas *r)
847 /* w2k3 returns "NOT IMPLEMENTED" for this call */
848 return NT_STATUS_NOT_IMPLEMENTED;
855 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
856 struct netr_AccountSync *r)
858 /* w2k3 returns "NOT IMPLEMENTED" for this call */
859 return NT_STATUS_NOT_IMPLEMENTED;
866 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
867 struct netr_GetDcName *r)
869 const char * const attrs[] = { NULL };
870 struct ldb_context *sam_ctx;
871 struct ldb_message **res;
872 struct ldb_dn *domain_dn;
876 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
877 dce_call->conn->dce_ctx->lp_ctx,
878 dce_call->conn->auth_state.session_info);
879 if (sam_ctx == NULL) {
880 return WERR_DS_UNAVAILABLE;
883 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
885 if (domain_dn == NULL) {
886 return WERR_DS_UNAVAILABLE;
889 ret = gendb_search_dn(sam_ctx, mem_ctx,
890 domain_dn, &res, attrs);
892 return WERR_NO_SUCH_DOMAIN;
895 /* TODO: - return real IP address
896 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
898 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
899 lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
900 W_ERROR_HAVE_NO_MEMORY(dcname);
902 *r->out.dcname = dcname;
910 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
911 struct netr_LogonControl2Ex *r)
913 return WERR_NOT_SUPPORTED;
920 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
921 struct netr_LogonControl *r)
923 struct netr_LogonControl2Ex r2;
926 if (r->in.level == 0x00000001) {
929 r2.in.logon_server = r->in.logon_server;
930 r2.in.function_code = r->in.function_code;
931 r2.in.level = r->in.level;
933 r2.out.query = r->out.query;
935 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
936 } else if (r->in.level == 0x00000002) {
937 werr = WERR_NOT_SUPPORTED;
939 werr = WERR_UNKNOWN_LEVEL;
949 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
950 struct netr_LogonControl2 *r)
952 struct netr_LogonControl2Ex r2;
957 r2.in.logon_server = r->in.logon_server;
958 r2.in.function_code = r->in.function_code;
959 r2.in.level = r->in.level;
960 r2.in.data = r->in.data;
961 r2.out.query = r->out.query;
963 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
972 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
973 struct netr_GetAnyDCName *r)
975 struct netr_GetDcName r2;
980 r2.in.logon_server = r->in.logon_server;
981 r2.in.domainname = r->in.domainname;
982 r2.out.dcname = r->out.dcname;
984 werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
993 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
994 struct netr_DatabaseRedo *r)
996 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1001 netr_NetrEnumerateTurstedDomains
1003 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1004 struct netr_NetrEnumerateTrustedDomains *r)
1006 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1011 netr_LogonGetCapabilities
1013 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1014 struct netr_LogonGetCapabilities *r)
1016 /* we don't support AES yet */
1017 return NT_STATUS_NOT_IMPLEMENTED;
1022 netr_NETRLOGONSETSERVICEBITS
1024 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1025 struct netr_NETRLOGONSETSERVICEBITS *r)
1027 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1032 netr_LogonGetTrustRid
1034 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1035 struct netr_LogonGetTrustRid *r)
1037 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1042 netr_NETRLOGONCOMPUTESERVERDIGEST
1044 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1045 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1047 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1052 netr_NETRLOGONCOMPUTECLIENTDIGEST
1054 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1055 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1057 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1065 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1066 struct netr_DsRGetSiteName *r)
1068 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1073 fill in a netr_OneDomainInfo from a ldb search result
1075 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1076 struct loadparm_context *lp_ctx,
1077 struct ldb_context *sam_ctx,
1078 struct ldb_message *res,
1079 struct netr_OneDomainInfo *info,
1080 bool is_local, bool is_trust_list)
1084 if (is_trust_list) {
1085 /* w2k8 only fills this on trusted domains */
1086 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1087 info->trust_extension.length = 16;
1088 info->trust_extension.info->flags =
1089 NETR_TRUST_FLAG_TREEROOT |
1090 NETR_TRUST_FLAG_IN_FOREST |
1091 NETR_TRUST_FLAG_PRIMARY |
1092 NETR_TRUST_FLAG_NATIVE;
1094 info->trust_extension.info->parent_index = 0; /* should be index into array
1096 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1097 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1100 if (is_trust_list) {
1101 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1102 info->dns_forestname.string = NULL;
1105 /* TODO: we need a common function for pulling the forest */
1106 info->dns_forestname.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
1107 if (!info->dns_forestname.string) {
1108 return NT_STATUS_NO_SUCH_DOMAIN;
1110 p = strchr(info->dns_forestname.string, '/');
1114 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1119 info->domainname.string = lp_sam_name(lp_ctx);
1120 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1121 info->domain_guid = samdb_result_guid(res, "objectGUID");
1122 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1124 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1125 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1126 info->domain_guid = samdb_result_guid(res, "objectGUID");
1127 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1129 if (!is_trust_list) {
1130 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1133 return NT_STATUS_OK;
1137 netr_LogonGetDomainInfo
1138 this is called as part of the ADS domain logon procedure.
1140 It has an important role in convaying details about the client, such
1141 as Operating System, Version, Service Pack etc.
1143 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1144 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1146 struct netlogon_creds_CredentialState *creds;
1147 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1148 "securityIdentifier", "trustPartner", NULL };
1149 const char * const attrs2[] = { "dNSHostName",
1150 "msDS-SupportedEncryptionTypes", NULL };
1151 const char * const attrs3[] = { NULL };
1152 const char *temp_str, *temp_str2;
1153 const char *old_dns_hostname;
1154 struct ldb_context *sam_ctx;
1155 struct ldb_message **res0, **res1, **res2, **res3, *new_msg;
1156 struct ldb_dn *workstation_dn;
1157 struct netr_DomainInformation *domain_info;
1158 struct netr_LsaPolicyInformation *lsa_policy_info;
1159 struct netr_OsVersionInfoEx *os_version;
1160 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1161 bool update_dns_hostname = true;
1165 status = dcesrv_netr_creds_server_step_check(dce_call,
1167 r->in.computer_name,
1169 r->out.return_authenticator,
1171 if (!NT_STATUS_IS_OK(status)) {
1172 DEBUG(0,(__location__ " Bad credentials - error\n"));
1174 NT_STATUS_NOT_OK_RETURN(status);
1176 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1177 dce_call->conn->dce_ctx->lp_ctx,
1178 system_session(dce_call->conn->dce_ctx->lp_ctx));
1179 if (sam_ctx == NULL) {
1180 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1183 switch (r->in.level) {
1184 case 1: /* Domain information */
1187 * Updates the DNS hostname when the client wishes that the
1188 * server should handle this for him
1189 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1190 * See MS-NRPC section 3.5.4.3.9
1192 if ((r->in.query->workstation_info->workstation_flags
1193 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1194 update_dns_hostname = false;
1198 * Checks that the computer name parameter without possible "$"
1199 * matches as prefix with the DNS hostname in the workstation
1202 temp_str = talloc_strndup(mem_ctx,
1203 r->in.computer_name,
1204 strcspn(r->in.computer_name, "$"));
1205 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1206 temp_str2 = talloc_strndup(mem_ctx,
1207 r->in.query->workstation_info->dns_hostname,
1208 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1209 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1210 if (strcasecmp(temp_str, temp_str2) != 0) {
1211 update_dns_hostname = false;
1215 * Check that the DNS hostname when it should be updated
1216 * will be used only by maximum one host.
1218 ret = gendb_search(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1219 &res0, attrs3, "(dNSHostName=%s)",
1220 r->in.query->workstation_info->dns_hostname);
1222 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1225 update_dns_hostname = false;
1230 /* Prepare the workstation DN */
1231 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1232 dom_sid_string(mem_ctx, creds->sid));
1233 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1235 /* Lookup for attributes in workstation object */
1236 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1239 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1242 /* Gets the old DNS hostname */
1243 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1246 /* Gets host informations and put them in our directory */
1247 new_msg = ldb_msg_new(mem_ctx);
1248 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1250 new_msg->dn = workstation_dn;
1252 /* Deletes old OS version values */
1253 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1254 "operatingSystemServicePack");
1255 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1256 "operatingSystemVersion");
1258 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1259 DEBUG(3,("Impossible to update samdb: %s\n",
1260 ldb_errstring(sam_ctx)));
1263 talloc_free(new_msg);
1265 new_msg = ldb_msg_new(mem_ctx);
1266 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1268 new_msg->dn = workstation_dn;
1270 /* Sets the OS name */
1271 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1273 r->in.query->workstation_info->os_name.string);
1276 * Sets informations from "os_version". On a empty structure
1277 * the values are cleared.
1279 if (r->in.query->workstation_info->os_version.os != NULL) {
1280 os_version = &r->in.query->workstation_info->os_version.os->os;
1282 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1283 "operatingSystemServicePack",
1284 os_version->CSDVersion);
1286 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1287 "operatingSystemVersion",
1288 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1289 os_version->MajorVersion,
1290 os_version->MinorVersion,
1291 os_version->BuildNumber
1297 * If the boolean "update_dns_hostname" remained true, then we
1298 * are fine to start the update.
1300 if (update_dns_hostname) {
1301 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1303 r->in.query->workstation_info->dns_hostname);
1305 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1306 "servicePrincipalName",
1307 talloc_asprintf(mem_ctx, "HOST/%s",
1308 r->in.computer_name)
1310 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1311 "servicePrincipalName",
1312 talloc_asprintf(mem_ctx, "HOST/%s",
1313 r->in.query->workstation_info->dns_hostname)
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 /* Writes back the domain information */
1326 /* We need to do two searches. The first will pull our primary
1327 domain and the second will pull any trusted domains. Our
1328 primary domain is also a "trusted" domain, so we need to
1329 put the primary domain into the lists of returned trusts as
1331 ret = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1334 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1337 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1338 "(objectClass=trustedDomain)");
1340 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1343 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1344 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1346 ZERO_STRUCTP(domain_info);
1348 /* Informations about the local and trusted domains */
1350 status = fill_one_domain_info(mem_ctx,
1351 dce_call->conn->dce_ctx->lp_ctx,
1352 sam_ctx, res2[0], &domain_info->primary_domain,
1354 NT_STATUS_NOT_OK_RETURN(status);
1356 domain_info->trusted_domain_count = ret3 + 1;
1357 domain_info->trusted_domains = talloc_array(mem_ctx,
1358 struct netr_OneDomainInfo,
1359 domain_info->trusted_domain_count);
1360 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1362 for (i=0;i<ret3;i++) {
1363 status = fill_one_domain_info(mem_ctx,
1364 dce_call->conn->dce_ctx->lp_ctx,
1366 &domain_info->trusted_domains[i],
1368 NT_STATUS_NOT_OK_RETURN(status);
1371 status = fill_one_domain_info(mem_ctx,
1372 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1373 &domain_info->trusted_domains[i], true, true);
1374 NT_STATUS_NOT_OK_RETURN(status);
1376 /* Sets the supported encryption types */
1377 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1378 "msDS-SupportedEncryptionTypes",
1379 default_supported_enc_types);
1381 /* Other host domain informations */
1383 lsa_policy_info = talloc(mem_ctx,
1384 struct netr_LsaPolicyInformation);
1385 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1386 ZERO_STRUCTP(lsa_policy_info);
1388 domain_info->lsa_policy = *lsa_policy_info;
1390 /* The DNS hostname is only returned back when there is a chance
1392 if ((r->in.query->workstation_info->workstation_flags
1393 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1394 domain_info->dns_hostname.string = old_dns_hostname;
1396 domain_info->dns_hostname.string = NULL;
1399 domain_info->workstation_flags =
1400 r->in.query->workstation_info->workstation_flags;
1402 r->out.info->domain_info = domain_info;
1404 case 2: /* LSA policy information - not used at the moment */
1405 lsa_policy_info = talloc(mem_ctx,
1406 struct netr_LsaPolicyInformation);
1407 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1408 ZERO_STRUCTP(lsa_policy_info);
1410 r->out.info->lsa_policy_info = lsa_policy_info;
1413 return NT_STATUS_INVALID_LEVEL;
1417 return NT_STATUS_OK;
1423 netr_ServerPasswordGet
1425 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1426 struct netr_ServerPasswordGet *r)
1428 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1433 netr_NETRLOGONSENDTOSAM
1435 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1436 struct netr_NETRLOGONSENDTOSAM *r)
1438 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1443 netr_DsRAddressToSitenamesW
1445 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1446 struct netr_DsRAddressToSitenamesW *r)
1448 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1453 netr_DsRGetDCNameEx2
1455 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1456 TALLOC_CTX *mem_ctx,
1457 struct netr_DsRGetDCNameEx2 *r)
1459 const char * const attrs[] = { "objectGUID", NULL };
1460 struct ldb_context *sam_ctx;
1461 struct ldb_message **res;
1462 struct ldb_dn *domain_dn;
1464 struct netr_DsRGetDCNameInfo *info;
1465 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1467 ZERO_STRUCTP(r->out.info);
1469 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1470 dce_call->conn->auth_state.session_info);
1471 if (sam_ctx == NULL) {
1472 return WERR_DS_UNAVAILABLE;
1475 /* Windows 7 sends the domain name in the form the user typed, so we
1476 * have to cope with both the short and long form here */
1477 if (r->in.domain_name != NULL &&
1478 !lp_is_my_domain_or_realm(lp_ctx, r->in.domain_name)) {
1479 return WERR_NO_SUCH_DOMAIN;
1482 domain_dn = ldb_get_default_basedn(sam_ctx);
1483 if (domain_dn == NULL) {
1484 return WERR_DS_UNAVAILABLE;
1487 ret = gendb_search_dn(sam_ctx, mem_ctx,
1488 domain_dn, &res, attrs);
1490 return WERR_GENERAL_FAILURE;
1493 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1494 W_ERROR_HAVE_NO_MEMORY(info);
1496 /* TODO: - return real IP address
1497 * - check all r->in.* parameters
1498 * (server_unc is ignored by w2k3!)
1500 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1501 lp_netbios_name(lp_ctx),
1502 lp_dnsdomain(lp_ctx));
1503 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1505 info->dc_address = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1506 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1508 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1509 info->domain_guid = samdb_result_guid(res[0], "objectGUID");
1510 info->domain_name = lp_dnsdomain(lp_ctx);
1511 info->forest_name = lp_dnsdomain(lp_ctx);
1512 info->dc_flags = DS_DNS_FOREST_ROOT |
1515 DS_SERVER_WRITABLE |
1517 DS_SERVER_TIMESERV |
1524 info->dc_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1525 W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1527 /* FIXME: Hardcoded site name */
1528 info->client_site_name = talloc_strdup(mem_ctx,
1529 "Default-First-Site-Name");
1530 W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1532 *r->out.info = info;
1540 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1541 struct netr_DsRGetDCNameEx *r)
1543 struct netr_DsRGetDCNameEx2 r2;
1548 r2.in.server_unc = r->in.server_unc;
1549 r2.in.client_account = NULL;
1551 r2.in.domain_guid = r->in.domain_guid;
1552 r2.in.domain_name = r->in.domain_name;
1553 r2.in.site_name = r->in.site_name;
1554 r2.in.flags = r->in.flags;
1555 r2.out.info = r->out.info;
1557 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1565 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1566 struct netr_DsRGetDCName *r)
1568 struct netr_DsRGetDCNameEx2 r2;
1573 r2.in.server_unc = r->in.server_unc;
1574 r2.in.client_account = NULL;
1576 r2.in.domain_name = r->in.domain_name;
1577 r2.in.domain_guid = r->in.domain_guid;
1579 r2.in.site_name = NULL; /* should fill in from site GUID */
1580 r2.in.flags = r->in.flags;
1581 r2.out.info = r->out.info;
1583 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1588 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1590 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1591 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1593 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1598 netr_NetrEnumerateTrustedDomainsEx
1600 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1601 struct netr_NetrEnumerateTrustedDomainsEx *r)
1603 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1608 netr_DsRAddressToSitenamesExW
1610 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1611 struct netr_DsRAddressToSitenamesExW *r)
1613 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1616 /* we should map the provided IPs to site names, once we have
1619 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1620 W_ERROR_HAVE_NO_MEMORY(ctr);
1624 ctr->count = r->in.count;
1625 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1626 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1627 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1628 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1630 for (i=0; i<ctr->count; i++) {
1631 /* FIXME: Hardcoded site name */
1632 ctr->sitename[i].string = "Default-First-Site-Name";
1633 ctr->subnetname[i].string = NULL;
1641 netr_DsrGetDcSiteCoverageW
1643 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1644 struct netr_DsrGetDcSiteCoverageW *r)
1646 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1650 #define GET_CHECK_STR(dest, mem, msg, attr) \
1653 s = samdb_result_string(msg, attr, NULL); \
1655 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1656 "without flatname\n", \
1657 ldb_dn_get_linearized(msg->dn))); \
1660 dest = talloc_strdup(mem, s); \
1661 W_ERROR_HAVE_NO_MEMORY(dest); \
1665 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1666 struct ldb_context *sam_ctx,
1667 struct netr_DomainTrustList *trusts,
1668 uint32_t trust_flags)
1670 struct ldb_dn *system_dn;
1671 struct ldb_message **dom_res = NULL;
1672 const char *trust_attrs[] = { "flatname", "trustPartner",
1673 "securityIdentifier", "trustDirection",
1674 "trustType", "trustAttributes", NULL };
1678 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1679 NETR_TRUST_FLAG_OUTBOUND))) {
1680 return WERR_INVALID_FLAGS;
1683 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1684 ldb_get_default_basedn(sam_ctx),
1685 "(&(objectClass=container)(cn=System))");
1687 return WERR_GENERAL_FAILURE;
1690 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1691 &dom_res, trust_attrs,
1692 "(objectclass=trustedDomain)");
1694 for (i = 0; i < ret; i++) {
1695 unsigned int trust_dir;
1698 trust_dir = samdb_result_uint(dom_res[i],
1699 "trustDirection", 0);
1701 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1702 flags |= NETR_TRUST_FLAG_INBOUND;
1704 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1705 flags |= NETR_TRUST_FLAG_OUTBOUND;
1708 if (!(flags & trust_flags)) {
1709 /* this trust direction was not requested */
1714 trusts->array = talloc_realloc(trusts, trusts->array,
1715 struct netr_DomainTrust,
1717 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1719 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1720 dom_res[i], "flatname");
1721 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1722 dom_res[i], "trustPartner");
1724 trusts->array[n].trust_flags = flags;
1725 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1726 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1727 /* TODO: find if we have parent in the list */
1728 trusts->array[n].parent_index = 0;
1731 trusts->array[n].trust_type =
1732 samdb_result_uint(dom_res[i],
1734 trusts->array[n].trust_attributes =
1735 samdb_result_uint(dom_res[i],
1736 "trustAttributes", 0);
1738 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1739 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1740 struct dom_sid zero_sid;
1741 ZERO_STRUCT(zero_sid);
1742 trusts->array[n].sid =
1743 dom_sid_dup(trusts, &zero_sid);
1745 trusts->array[n].sid =
1746 samdb_result_dom_sid(trusts, dom_res[i],
1747 "securityIdentifier");
1749 trusts->array[n].guid = GUID_zero();
1751 trusts->count = n + 1;
1754 talloc_free(dom_res);
1759 netr_DsrEnumerateDomainTrusts
1761 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1762 TALLOC_CTX *mem_ctx,
1763 struct netr_DsrEnumerateDomainTrusts *r)
1765 struct netr_DomainTrustList *trusts;
1766 struct ldb_context *sam_ctx;
1768 struct ldb_message **dom_res;
1769 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1770 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1771 const char *dnsdomain = lp_dnsdomain(lp_ctx);
1775 if (r->in.trust_flags & 0xFFFFFE00) {
1776 return WERR_INVALID_FLAGS;
1779 /* TODO: turn to hard check once we are sure this is 100% correct */
1780 if (!r->in.server_name) {
1781 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1782 "But received NULL!\n", dnsdomain));
1784 p = strchr(r->in.server_name, '.');
1786 DEBUG(3, ("Invalid domain! Expected name in domain "
1787 "[%s]. But received [%s]!\n",
1788 dnsdomain, r->in.server_name));
1789 p = r->in.server_name;
1793 if (strcasecmp(p, dnsdomain)) {
1794 DEBUG(3, ("Invalid domain! Expected name in domain "
1795 "[%s]. But received [%s]!\n",
1796 dnsdomain, r->in.server_name));
1800 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1801 W_ERROR_HAVE_NO_MEMORY(trusts);
1804 r->out.trusts = trusts;
1806 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1807 dce_call->conn->auth_state.session_info);
1808 if (sam_ctx == NULL) {
1809 return WERR_GENERAL_FAILURE;
1812 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1813 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1815 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1816 trusts, r->in.trust_flags);
1817 W_ERROR_NOT_OK_RETURN(werr);
1820 /* NOTE: we currently are always the root of the forest */
1821 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1822 int n = trusts->count;
1824 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1825 &dom_res, dom_attrs);
1827 return WERR_GENERAL_FAILURE;
1830 trusts->count = n + 1;
1831 trusts->array = talloc_realloc(trusts, trusts->array,
1832 struct netr_DomainTrust,
1834 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1836 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1837 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1838 trusts->array[n].trust_flags =
1839 NETR_TRUST_FLAG_NATIVE |
1840 NETR_TRUST_FLAG_TREEROOT |
1841 NETR_TRUST_FLAG_IN_FOREST |
1842 NETR_TRUST_FLAG_PRIMARY;
1843 /* we are always the root domain for now */
1844 trusts->array[n].parent_index = 0;
1845 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1846 trusts->array[n].trust_attributes = 0;
1847 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
1850 trusts->array[n].guid = samdb_result_guid(dom_res[0],
1852 talloc_free(dom_res);
1860 netr_DsrDeregisterDNSHostRecords
1862 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1863 struct netr_DsrDeregisterDNSHostRecords *r)
1865 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1870 netr_ServerTrustPasswordsGet
1872 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1873 struct netr_ServerTrustPasswordsGet *r)
1875 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1879 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
1880 struct ldb_context *sam_ctx,
1881 struct loadparm_context *lp_ctx,
1882 struct lsa_ForestTrustInformation *info)
1884 struct lsa_ForestTrustDomainInfo *domain_info;
1885 struct lsa_ForestTrustRecord *e;
1886 struct ldb_message **dom_res;
1887 const char * const dom_attrs[] = { "objectSid", NULL };
1890 /* we need to provide 2 entries:
1891 * 1. the Root Forest name
1892 * 2. the Domain Information
1896 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
1897 W_ERROR_HAVE_NO_MEMORY(info->entries);
1899 /* Forest root info */
1900 e = talloc(info, struct lsa_ForestTrustRecord);
1901 W_ERROR_HAVE_NO_MEMORY(e);
1904 e->level = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
1905 e->time = 0; /* so far always 0 in trces. */
1906 e->forest_trust_data.top_level_name.string = lp_dnsdomain(lp_ctx);
1908 info->entries[0] = e;
1911 e = talloc(info, struct lsa_ForestTrustRecord);
1912 W_ERROR_HAVE_NO_MEMORY(e);
1914 /* get our own domain info */
1915 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
1917 return WERR_GENERAL_FAILURE;
1920 /* TODO: check if disabled and set flags accordingly */
1922 e->level = LSA_FOREST_TRUST_DOMAIN_INFO;
1923 e->time = 0; /* so far always 0 in traces. */
1925 domain_info = &e->forest_trust_data.domain_info;
1926 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
1928 domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
1929 domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
1931 info->entries[1] = e;
1933 talloc_free(dom_res);
1939 netr_DsRGetForestTrustInformation
1941 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
1942 TALLOC_CTX *mem_ctx,
1943 struct netr_DsRGetForestTrustInformation *r)
1945 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1946 struct lsa_ForestTrustInformation *info, **info_ptr;
1947 struct ldb_context *sam_ctx;
1950 if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
1951 return WERR_CALL_NOT_IMPLEMENTED;
1954 if (r->in.flags & 0xFFFFFFFE) {
1955 return WERR_INVALID_FLAGS;
1958 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1959 dce_call->conn->auth_state.session_info);
1960 if (sam_ctx == NULL) {
1961 return WERR_GENERAL_FAILURE;
1964 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
1965 if (!samdb_is_pdc(sam_ctx)) {
1966 return WERR_NERR_NOTPRIMARY;
1969 if (r->in.trusted_domain_name == NULL) {
1970 return WERR_INVALID_FLAGS;
1973 /* TODO: establish an schannel connection with
1974 * r->in.trusted_domain_name and perform a
1975 * netr_GetForestTrustInformation call against it */
1977 /* for now return not implementd */
1978 return WERR_CALL_NOT_IMPLEMENTED;
1981 /* TODO: check r->in.server_name is our name */
1983 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
1984 W_ERROR_HAVE_NO_MEMORY(info_ptr);
1986 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
1987 W_ERROR_HAVE_NO_MEMORY(info);
1989 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
1990 W_ERROR_NOT_OK_RETURN(werr);
1993 r->out.forest_trust_info = info_ptr;
2000 netr_GetForestTrustInformation
2002 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2003 TALLOC_CTX *mem_ctx,
2004 struct netr_GetForestTrustInformation *r)
2006 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2007 struct netlogon_creds_CredentialState *creds;
2008 struct lsa_ForestTrustInformation *info, **info_ptr;
2009 struct ldb_context *sam_ctx;
2013 if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
2014 return NT_STATUS_NOT_IMPLEMENTED;
2017 status = dcesrv_netr_creds_server_step_check(dce_call,
2019 r->in.computer_name,
2021 r->out.return_authenticator,
2023 if (!NT_STATUS_IS_OK(status)) {
2027 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2028 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2029 return NT_STATUS_NOT_IMPLEMENTED;
2032 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2033 dce_call->conn->auth_state.session_info);
2034 if (sam_ctx == NULL) {
2035 return NT_STATUS_UNSUCCESSFUL;
2038 /* TODO: check r->in.server_name is our name */
2040 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2042 return NT_STATUS_NO_MEMORY;
2044 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2046 return NT_STATUS_NO_MEMORY;
2049 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2050 if (!W_ERROR_IS_OK(werr)) {
2051 return werror_to_ntstatus(werr);
2055 r->out.forest_trust_info = info_ptr;
2057 return NT_STATUS_OK;
2062 netr_ServerGetTrustInfo
2064 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2065 struct netr_ServerGetTrustInfo *r)
2067 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2071 /* include the generated boilerplate */
2072 #include "librpc/gen_ndr/ndr_netlogon_s.c"