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 *temp_str;
1152 const char *old_dns_hostname;
1153 struct ldb_context *sam_ctx;
1154 struct ldb_message **res1, **res2, **res3, *new_msg;
1155 struct ldb_dn *workstation_dn;
1156 struct netr_DomainInformation *domain_info;
1157 struct netr_LsaPolicyInformation *lsa_policy_info;
1158 struct netr_OsVersionInfoEx *os_version;
1159 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1160 int ret1, ret2, ret3, i;
1163 status = dcesrv_netr_creds_server_step_check(dce_call,
1165 r->in.computer_name,
1167 r->out.return_authenticator,
1169 if (!NT_STATUS_IS_OK(status)) {
1170 DEBUG(0,(__location__ " Bad credentials - error\n"));
1172 NT_STATUS_NOT_OK_RETURN(status);
1174 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1175 dce_call->conn->dce_ctx->lp_ctx,
1176 system_session(dce_call->conn->dce_ctx->lp_ctx));
1177 if (sam_ctx == NULL) {
1178 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1181 switch (r->in.level) {
1182 case 1: /* Domain information */
1184 /* TODO: check NTSTATUS results - and fail also on SAMDB
1185 * errors (needs some testing against Windows Server 2008) */
1188 * Check that the computer name parameter matches as prefix with
1189 * the DNS hostname in the workstation info structure.
1191 temp_str = strndup(r->in.query->workstation_info->dns_hostname,
1192 strcspn(r->in.query->workstation_info->dns_hostname,
1194 if (strcasecmp(r->in.computer_name, temp_str) != 0)
1195 return NT_STATUS_INVALID_PARAMETER;
1197 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1198 dom_sid_string(mem_ctx, creds->sid));
1199 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1201 /* Lookup for attributes in workstation object */
1202 ret1 = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1205 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1208 /* Gets the old DNS hostname */
1209 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1212 /* Gets host informations and put them in our directory */
1213 new_msg = ldb_msg_new(mem_ctx);
1214 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1216 new_msg->dn = workstation_dn;
1218 /* Deletes old OS version values */
1219 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1220 "operatingSystemServicePack");
1221 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1222 "operatingSystemVersion");
1224 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1225 DEBUG(3,("Impossible to update samdb: %s\n",
1226 ldb_errstring(sam_ctx)));
1229 talloc_free(new_msg);
1231 new_msg = ldb_msg_new(mem_ctx);
1232 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1234 new_msg->dn = workstation_dn;
1236 /* Sets the OS name */
1237 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1239 r->in.query->workstation_info->os_name.string);
1242 * Sets informations from "os_version". On a empty structure
1243 * the values are cleared.
1245 if (r->in.query->workstation_info->os_version.os != NULL) {
1246 os_version = &r->in.query->workstation_info->os_version.os->os;
1248 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1249 "operatingSystemServicePack",
1250 os_version->CSDVersion);
1252 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1253 "operatingSystemVersion",
1254 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1255 os_version->MajorVersion,
1256 os_version->MinorVersion,
1257 os_version->BuildNumber
1263 * Updates the "dNSHostname" and the "servicePrincipalName"s
1264 * since the client wishes that the server should handle this
1265 * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1266 * See MS-NRPC section 3.5.4.3.9
1268 if ((r->in.query->workstation_info->workstation_flags
1269 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
1270 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1272 r->in.query->workstation_info->dns_hostname);
1274 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1275 "servicePrincipalName",
1276 talloc_asprintf(mem_ctx, "HOST/%s",
1277 r->in.computer_name)
1279 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1280 "servicePrincipalName",
1281 talloc_asprintf(mem_ctx, "HOST/%s",
1282 r->in.query->workstation_info->dns_hostname)
1286 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1287 DEBUG(3,("Impossible to update samdb: %s\n",
1288 ldb_errstring(sam_ctx)));
1291 talloc_free(new_msg);
1293 /* Writes back the domain information */
1295 /* We need to do two searches. The first will pull our primary
1296 domain and the second will pull any trusted domains. Our
1297 primary domain is also a "trusted" domain, so we need to
1298 put the primary domain into the lists of returned trusts as
1300 ret2 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1303 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1306 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1307 "(objectClass=trustedDomain)");
1309 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1312 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1313 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1315 ZERO_STRUCTP(domain_info);
1317 /* Informations about the local and trusted domains */
1319 status = fill_one_domain_info(mem_ctx,
1320 dce_call->conn->dce_ctx->lp_ctx,
1321 sam_ctx, res2[0], &domain_info->primary_domain,
1323 NT_STATUS_NOT_OK_RETURN(status);
1325 domain_info->trusted_domain_count = ret3 + 1;
1326 domain_info->trusted_domains = talloc_array(mem_ctx,
1327 struct netr_OneDomainInfo,
1328 domain_info->trusted_domain_count);
1329 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1331 for (i=0;i<ret3;i++) {
1332 status = fill_one_domain_info(mem_ctx,
1333 dce_call->conn->dce_ctx->lp_ctx,
1335 &domain_info->trusted_domains[i],
1337 NT_STATUS_NOT_OK_RETURN(status);
1340 status = fill_one_domain_info(mem_ctx,
1341 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1342 &domain_info->trusted_domains[i], true, true);
1343 NT_STATUS_NOT_OK_RETURN(status);
1345 /* Sets the supported encryption types */
1346 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1347 "msDS-SupportedEncryptionTypes",
1348 default_supported_enc_types);
1350 /* Other host domain informations */
1352 lsa_policy_info = talloc(mem_ctx,
1353 struct netr_LsaPolicyInformation);
1354 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1355 ZERO_STRUCTP(lsa_policy_info);
1357 domain_info->lsa_policy = *lsa_policy_info;
1359 domain_info->dns_hostname.string = old_dns_hostname;
1360 domain_info->workstation_flags =
1361 r->in.query->workstation_info->workstation_flags;
1363 r->out.info->domain_info = domain_info;
1365 case 2: /* LSA policy information - not used at the moment */
1366 lsa_policy_info = talloc(mem_ctx,
1367 struct netr_LsaPolicyInformation);
1368 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1369 ZERO_STRUCTP(lsa_policy_info);
1371 r->out.info->lsa_policy_info = lsa_policy_info;
1374 return NT_STATUS_INVALID_LEVEL;
1378 return NT_STATUS_OK;
1384 netr_ServerPasswordGet
1386 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1387 struct netr_ServerPasswordGet *r)
1389 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1394 netr_NETRLOGONSENDTOSAM
1396 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1397 struct netr_NETRLOGONSENDTOSAM *r)
1399 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1404 netr_DsRAddressToSitenamesW
1406 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1407 struct netr_DsRAddressToSitenamesW *r)
1409 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1414 netr_DsRGetDCNameEx2
1416 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1417 TALLOC_CTX *mem_ctx,
1418 struct netr_DsRGetDCNameEx2 *r)
1420 const char * const attrs[] = { "objectGUID", NULL };
1421 struct ldb_context *sam_ctx;
1422 struct ldb_message **res;
1423 struct ldb_dn *domain_dn;
1425 struct netr_DsRGetDCNameInfo *info;
1426 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1428 ZERO_STRUCTP(r->out.info);
1430 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1431 dce_call->conn->auth_state.session_info);
1432 if (sam_ctx == NULL) {
1433 return WERR_DS_UNAVAILABLE;
1436 /* Windows 7 sends the domain name in the form the user typed, so we
1437 * have to cope with both the short and long form here */
1438 if (r->in.domain_name != NULL &&
1439 !lp_is_my_domain_or_realm(lp_ctx, r->in.domain_name)) {
1440 return WERR_NO_SUCH_DOMAIN;
1443 domain_dn = ldb_get_default_basedn(sam_ctx);
1444 if (domain_dn == NULL) {
1445 return WERR_DS_UNAVAILABLE;
1448 ret = gendb_search_dn(sam_ctx, mem_ctx,
1449 domain_dn, &res, attrs);
1451 return WERR_GENERAL_FAILURE;
1454 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1455 W_ERROR_HAVE_NO_MEMORY(info);
1457 /* TODO: - return real IP address
1458 * - check all r->in.* parameters
1459 * (server_unc is ignored by w2k3!)
1461 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1462 lp_netbios_name(lp_ctx),
1463 lp_dnsdomain(lp_ctx));
1464 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1466 info->dc_address = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1467 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1469 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1470 info->domain_guid = samdb_result_guid(res[0], "objectGUID");
1471 info->domain_name = lp_dnsdomain(lp_ctx);
1472 info->forest_name = lp_dnsdomain(lp_ctx);
1473 info->dc_flags = DS_DNS_FOREST_ROOT |
1476 DS_SERVER_WRITABLE |
1478 DS_SERVER_TIMESERV |
1485 info->dc_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1486 W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1488 /* FIXME: Hardcoded site name */
1489 info->client_site_name = talloc_strdup(mem_ctx,
1490 "Default-First-Site-Name");
1491 W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1493 *r->out.info = info;
1501 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1502 struct netr_DsRGetDCNameEx *r)
1504 struct netr_DsRGetDCNameEx2 r2;
1509 r2.in.server_unc = r->in.server_unc;
1510 r2.in.client_account = NULL;
1512 r2.in.domain_guid = r->in.domain_guid;
1513 r2.in.domain_name = r->in.domain_name;
1514 r2.in.site_name = r->in.site_name;
1515 r2.in.flags = r->in.flags;
1516 r2.out.info = r->out.info;
1518 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1526 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1527 struct netr_DsRGetDCName *r)
1529 struct netr_DsRGetDCNameEx2 r2;
1534 r2.in.server_unc = r->in.server_unc;
1535 r2.in.client_account = NULL;
1537 r2.in.domain_name = r->in.domain_name;
1538 r2.in.domain_guid = r->in.domain_guid;
1540 r2.in.site_name = NULL; /* should fill in from site GUID */
1541 r2.in.flags = r->in.flags;
1542 r2.out.info = r->out.info;
1544 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1549 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1551 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1552 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1554 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1559 netr_NetrEnumerateTrustedDomainsEx
1561 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1562 struct netr_NetrEnumerateTrustedDomainsEx *r)
1564 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1569 netr_DsRAddressToSitenamesExW
1571 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1572 struct netr_DsRAddressToSitenamesExW *r)
1574 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1577 /* we should map the provided IPs to site names, once we have
1580 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1581 W_ERROR_HAVE_NO_MEMORY(ctr);
1585 ctr->count = r->in.count;
1586 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1587 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1588 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1589 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1591 for (i=0; i<ctr->count; i++) {
1592 /* FIXME: Hardcoded site name */
1593 ctr->sitename[i].string = "Default-First-Site-Name";
1594 ctr->subnetname[i].string = NULL;
1602 netr_DsrGetDcSiteCoverageW
1604 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1605 struct netr_DsrGetDcSiteCoverageW *r)
1607 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1611 #define GET_CHECK_STR(dest, mem, msg, attr) \
1614 s = samdb_result_string(msg, attr, NULL); \
1616 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1617 "without flatname\n", \
1618 ldb_dn_get_linearized(msg->dn))); \
1621 dest = talloc_strdup(mem, s); \
1622 W_ERROR_HAVE_NO_MEMORY(dest); \
1626 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1627 struct ldb_context *sam_ctx,
1628 struct netr_DomainTrustList *trusts,
1629 uint32_t trust_flags)
1631 struct ldb_dn *system_dn;
1632 struct ldb_message **dom_res = NULL;
1633 const char *trust_attrs[] = { "flatname", "trustPartner",
1634 "securityIdentifier", "trustDirection",
1635 "trustType", "trustAttributes", NULL };
1639 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1640 NETR_TRUST_FLAG_OUTBOUND))) {
1641 return WERR_INVALID_FLAGS;
1644 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1645 ldb_get_default_basedn(sam_ctx),
1646 "(&(objectClass=container)(cn=System))");
1648 return WERR_GENERAL_FAILURE;
1651 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1652 &dom_res, trust_attrs,
1653 "(objectclass=trustedDomain)");
1655 for (i = 0; i < ret; i++) {
1656 unsigned int trust_dir;
1659 trust_dir = samdb_result_uint(dom_res[i],
1660 "trustDirection", 0);
1662 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1663 flags |= NETR_TRUST_FLAG_INBOUND;
1665 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1666 flags |= NETR_TRUST_FLAG_OUTBOUND;
1669 if (!(flags & trust_flags)) {
1670 /* this trust direction was not requested */
1675 trusts->array = talloc_realloc(trusts, trusts->array,
1676 struct netr_DomainTrust,
1678 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1680 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1681 dom_res[i], "flatname");
1682 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1683 dom_res[i], "trustPartner");
1685 trusts->array[n].trust_flags = flags;
1686 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1687 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1688 /* TODO: find if we have parent in the list */
1689 trusts->array[n].parent_index = 0;
1692 trusts->array[n].trust_type =
1693 samdb_result_uint(dom_res[i],
1695 trusts->array[n].trust_attributes =
1696 samdb_result_uint(dom_res[i],
1697 "trustAttributes", 0);
1699 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1700 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1701 struct dom_sid zero_sid;
1702 ZERO_STRUCT(zero_sid);
1703 trusts->array[n].sid =
1704 dom_sid_dup(trusts, &zero_sid);
1706 trusts->array[n].sid =
1707 samdb_result_dom_sid(trusts, dom_res[i],
1708 "securityIdentifier");
1710 trusts->array[n].guid = GUID_zero();
1712 trusts->count = n + 1;
1715 talloc_free(dom_res);
1720 netr_DsrEnumerateDomainTrusts
1722 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1723 TALLOC_CTX *mem_ctx,
1724 struct netr_DsrEnumerateDomainTrusts *r)
1726 struct netr_DomainTrustList *trusts;
1727 struct ldb_context *sam_ctx;
1729 struct ldb_message **dom_res;
1730 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1731 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1732 const char *dnsdomain = lp_dnsdomain(lp_ctx);
1736 if (r->in.trust_flags & 0xFFFFFE00) {
1737 return WERR_INVALID_FLAGS;
1740 /* TODO: turn to hard check once we are sure this is 100% correct */
1741 if (!r->in.server_name) {
1742 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1743 "But received NULL!\n", dnsdomain));
1745 p = strchr(r->in.server_name, '.');
1747 DEBUG(3, ("Invalid domain! Expected name in domain "
1748 "[%s]. But received [%s]!\n",
1749 dnsdomain, r->in.server_name));
1750 p = r->in.server_name;
1754 if (strcasecmp(p, dnsdomain)) {
1755 DEBUG(3, ("Invalid domain! Expected name in domain "
1756 "[%s]. But received [%s]!\n",
1757 dnsdomain, r->in.server_name));
1761 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1762 W_ERROR_HAVE_NO_MEMORY(trusts);
1765 r->out.trusts = trusts;
1767 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1768 dce_call->conn->auth_state.session_info);
1769 if (sam_ctx == NULL) {
1770 return WERR_GENERAL_FAILURE;
1773 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1774 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1776 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1777 trusts, r->in.trust_flags);
1778 W_ERROR_NOT_OK_RETURN(werr);
1781 /* NOTE: we currently are always the root of the forest */
1782 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1783 int n = trusts->count;
1785 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1786 &dom_res, dom_attrs);
1788 return WERR_GENERAL_FAILURE;
1791 trusts->count = n + 1;
1792 trusts->array = talloc_realloc(trusts, trusts->array,
1793 struct netr_DomainTrust,
1795 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1797 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1798 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1799 trusts->array[n].trust_flags =
1800 NETR_TRUST_FLAG_NATIVE |
1801 NETR_TRUST_FLAG_TREEROOT |
1802 NETR_TRUST_FLAG_IN_FOREST |
1803 NETR_TRUST_FLAG_PRIMARY;
1804 /* we are always the root domain for now */
1805 trusts->array[n].parent_index = 0;
1806 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1807 trusts->array[n].trust_attributes = 0;
1808 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
1811 trusts->array[n].guid = samdb_result_guid(dom_res[0],
1813 talloc_free(dom_res);
1821 netr_DsrDeregisterDNSHostRecords
1823 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1824 struct netr_DsrDeregisterDNSHostRecords *r)
1826 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1831 netr_ServerTrustPasswordsGet
1833 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1834 struct netr_ServerTrustPasswordsGet *r)
1836 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1840 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
1841 struct ldb_context *sam_ctx,
1842 struct loadparm_context *lp_ctx,
1843 struct lsa_ForestTrustInformation *info)
1845 struct lsa_ForestTrustDomainInfo *domain_info;
1846 struct lsa_ForestTrustRecord *e;
1847 struct ldb_message **dom_res;
1848 const char * const dom_attrs[] = { "objectSid", NULL };
1851 /* we need to provide 2 entries:
1852 * 1. the Root Forest name
1853 * 2. the Domain Information
1857 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
1858 W_ERROR_HAVE_NO_MEMORY(info->entries);
1860 /* Forest root info */
1861 e = talloc(info, struct lsa_ForestTrustRecord);
1862 W_ERROR_HAVE_NO_MEMORY(e);
1865 e->level = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
1866 e->time = 0; /* so far always 0 in trces. */
1867 e->forest_trust_data.top_level_name.string = lp_dnsdomain(lp_ctx);
1869 info->entries[0] = e;
1872 e = talloc(info, struct lsa_ForestTrustRecord);
1873 W_ERROR_HAVE_NO_MEMORY(e);
1875 /* get our own domain info */
1876 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
1878 return WERR_GENERAL_FAILURE;
1881 /* TODO: check if disabled and set flags accordingly */
1883 e->level = LSA_FOREST_TRUST_DOMAIN_INFO;
1884 e->time = 0; /* so far always 0 in traces. */
1886 domain_info = &e->forest_trust_data.domain_info;
1887 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
1889 domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
1890 domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
1892 info->entries[1] = e;
1894 talloc_free(dom_res);
1900 netr_DsRGetForestTrustInformation
1902 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
1903 TALLOC_CTX *mem_ctx,
1904 struct netr_DsRGetForestTrustInformation *r)
1906 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1907 struct lsa_ForestTrustInformation *info, **info_ptr;
1908 struct ldb_context *sam_ctx;
1911 if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
1912 return WERR_CALL_NOT_IMPLEMENTED;
1915 if (r->in.flags & 0xFFFFFFFE) {
1916 return WERR_INVALID_FLAGS;
1919 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1920 dce_call->conn->auth_state.session_info);
1921 if (sam_ctx == NULL) {
1922 return WERR_GENERAL_FAILURE;
1925 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
1926 if (!samdb_is_pdc(sam_ctx)) {
1927 return WERR_NERR_NOTPRIMARY;
1930 if (r->in.trusted_domain_name == NULL) {
1931 return WERR_INVALID_FLAGS;
1934 /* TODO: establish an schannel connection with
1935 * r->in.trusted_domain_name and perform a
1936 * netr_GetForestTrustInformation call against it */
1938 /* for now return not implementd */
1939 return WERR_CALL_NOT_IMPLEMENTED;
1942 /* TODO: check r->in.server_name is our name */
1944 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
1945 W_ERROR_HAVE_NO_MEMORY(info_ptr);
1947 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
1948 W_ERROR_HAVE_NO_MEMORY(info);
1950 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
1951 W_ERROR_NOT_OK_RETURN(werr);
1954 r->out.forest_trust_info = info_ptr;
1961 netr_GetForestTrustInformation
1963 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
1964 TALLOC_CTX *mem_ctx,
1965 struct netr_GetForestTrustInformation *r)
1967 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1968 struct netlogon_creds_CredentialState *creds;
1969 struct lsa_ForestTrustInformation *info, **info_ptr;
1970 struct ldb_context *sam_ctx;
1974 if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
1975 return NT_STATUS_NOT_IMPLEMENTED;
1978 status = dcesrv_netr_creds_server_step_check(dce_call,
1980 r->in.computer_name,
1982 r->out.return_authenticator,
1984 if (!NT_STATUS_IS_OK(status)) {
1988 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
1989 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
1990 return NT_STATUS_NOT_IMPLEMENTED;
1993 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1994 dce_call->conn->auth_state.session_info);
1995 if (sam_ctx == NULL) {
1996 return NT_STATUS_UNSUCCESSFUL;
1999 /* TODO: check r->in.server_name is our name */
2001 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2003 return NT_STATUS_NO_MEMORY;
2005 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2007 return NT_STATUS_NO_MEMORY;
2010 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2011 if (!W_ERROR_IS_OK(werr)) {
2012 return werror_to_ntstatus(werr);
2016 r->out.forest_trust_info = info_ptr;
2018 return NT_STATUS_OK;
2023 netr_ServerGetTrustInfo
2025 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2026 struct netr_ServerGetTrustInfo *r)
2028 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2032 /* include the generated boilerplate */
2033 #include "librpc/gen_ndr/ndr_netlogon_s.c"