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-2010
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_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "cldap_server/cldap_server.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
40 #include "lib/socket/netif.h"
42 struct netlogon_server_pipe_state {
43 struct netr_Credential client_challenge;
44 struct netr_Credential server_challenge;
47 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
48 struct netr_ServerReqChallenge *r)
50 struct netlogon_server_pipe_state *pipe_state =
51 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
53 ZERO_STRUCTP(r->out.return_credentials);
55 /* destroyed on pipe shutdown */
58 talloc_free(pipe_state);
59 dce_call->context->private_data = NULL;
62 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
63 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
65 pipe_state->client_challenge = *r->in.credentials;
67 generate_random_buffer(pipe_state->server_challenge.data,
68 sizeof(pipe_state->server_challenge.data));
70 *r->out.return_credentials = pipe_state->server_challenge;
72 dce_call->context->private_data = pipe_state;
77 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
78 struct netr_ServerAuthenticate3 *r)
80 struct netlogon_server_pipe_state *pipe_state =
81 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
82 struct netlogon_creds_CredentialState *creds;
83 struct ldb_context *sam_ctx;
84 struct samr_Password *mach_pwd;
85 uint32_t user_account_control;
87 struct ldb_message **msgs;
89 const char *attrs[] = {"unicodePwd", "userAccountControl",
92 const char *trust_dom_attrs[] = {"flatname", NULL};
93 const char *account_name;
94 uint32_t negotiate_flags = 0;
96 ZERO_STRUCTP(r->out.return_credentials);
99 negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
100 NETLOGON_NEG_PERSISTENT_SAMREPL |
101 NETLOGON_NEG_ARCFOUR |
102 NETLOGON_NEG_PROMOTION_COUNT |
103 NETLOGON_NEG_CHANGELOG_BDC |
104 NETLOGON_NEG_FULL_SYNC_REPL |
105 NETLOGON_NEG_MULTIPLE_SIDS |
107 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
108 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
109 NETLOGON_NEG_GENERIC_PASSTHROUGH |
110 NETLOGON_NEG_CONCURRENT_RPC |
111 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
112 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
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;
123 if (*r->in.negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
124 negotiate_flags |= NETLOGON_NEG_STRONG_KEYS;
128 * According to Microsoft (see bugid #6099)
129 * Windows 7 looks at the negotiate_flags
130 * returned in this structure *even if the
131 * call fails with access denied!
133 *r->out.negotiate_flags = negotiate_flags;
135 switch (r->in.secure_channel_type) {
137 case SEC_CHAN_DNS_DOMAIN:
138 case SEC_CHAN_DOMAIN:
143 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
144 r->in.secure_channel_type));
145 return NT_STATUS_INVALID_PARAMETER;
148 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
149 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
150 if (sam_ctx == NULL) {
151 return NT_STATUS_INVALID_SYSTEM_SERVICE;
154 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
155 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
156 const char *flatname;
157 if (!encoded_account) {
158 return NT_STATUS_NO_MEMORY;
161 /* Kill the trailing dot */
162 if (encoded_account[strlen(encoded_account)-1] == '.') {
163 encoded_account[strlen(encoded_account)-1] = '\0';
166 /* pull the user attributes */
167 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
169 "(&(trustPartner=%s)(objectclass=trustedDomain))",
172 if (num_records == 0) {
173 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
175 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
178 if (num_records > 1) {
179 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
180 return NT_STATUS_INTERNAL_DB_CORRUPTION;
183 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
185 /* No flatname for this trust - we can't proceed */
186 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
188 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
191 return NT_STATUS_NO_MEMORY;
195 account_name = r->in.account_name;
198 /* pull the user attributes */
199 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
200 "(&(sAMAccountName=%s)(objectclass=user))",
201 ldb_binary_encode_string(mem_ctx, account_name));
203 if (num_records == 0) {
204 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
205 r->in.account_name));
206 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
209 if (num_records > 1) {
210 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
211 return NT_STATUS_INTERNAL_DB_CORRUPTION;
214 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
216 if (user_account_control & UF_ACCOUNTDISABLE) {
217 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
218 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
221 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
222 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
223 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
224 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
226 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
227 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
228 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
229 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
231 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
233 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
234 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
235 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
236 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
238 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
239 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
240 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
241 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
244 /* we should never reach this */
245 return NT_STATUS_INTERNAL_ERROR;
248 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
251 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
252 if (mach_pwd == NULL) {
253 return NT_STATUS_ACCESS_DENIED;
257 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
258 return NT_STATUS_ACCESS_DENIED;
261 creds = netlogon_creds_server_init(mem_ctx,
264 r->in.secure_channel_type,
265 &pipe_state->client_challenge,
266 &pipe_state->server_challenge,
269 r->out.return_credentials,
272 return NT_STATUS_ACCESS_DENIED;
275 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
277 nt_status = schannel_save_creds_state(mem_ctx,
278 dce_call->conn->dce_ctx->lp_ctx,
284 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
285 struct netr_ServerAuthenticate *r)
287 struct netr_ServerAuthenticate3 a;
290 * negotiate_flags is used as an [in] parameter
291 * so it need to be initialised.
293 * (I think ... = 0; seems wrong here --metze)
295 uint32_t negotiate_flags_in = 0;
296 uint32_t negotiate_flags_out = 0;
298 a.in.server_name = r->in.server_name;
299 a.in.account_name = r->in.account_name;
300 a.in.secure_channel_type = r->in.secure_channel_type;
301 a.in.computer_name = r->in.computer_name;
302 a.in.credentials = r->in.credentials;
303 a.in.negotiate_flags = &negotiate_flags_in;
305 a.out.return_credentials = r->out.return_credentials;
307 a.out.negotiate_flags = &negotiate_flags_out;
309 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
312 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
313 struct netr_ServerAuthenticate2 *r)
315 struct netr_ServerAuthenticate3 r3;
318 r3.in.server_name = r->in.server_name;
319 r3.in.account_name = r->in.account_name;
320 r3.in.secure_channel_type = r->in.secure_channel_type;
321 r3.in.computer_name = r->in.computer_name;
322 r3.in.credentials = r->in.credentials;
323 r3.out.return_credentials = r->out.return_credentials;
324 r3.in.negotiate_flags = r->in.negotiate_flags;
325 r3.out.negotiate_flags = r->out.negotiate_flags;
328 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
332 * NOTE: The following functions are nearly identical to the ones available in
333 * source3/rpc_server/srv_nelog_nt.c
334 * The reason we keep 2 copies is that they use different structures to
335 * represent the auth_info and the decrpc pipes.
339 * If schannel is required for this call test that it actually is available.
341 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
342 const char *computer_name,
343 bool integrity, bool privacy)
346 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
347 if (!privacy && !integrity) {
351 if ((!privacy && integrity) &&
352 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
356 if ((privacy || integrity) &&
357 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
362 /* test didn't pass */
363 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
366 return NT_STATUS_ACCESS_DENIED;
369 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
371 const char *computer_name,
372 struct netr_Authenticator *received_authenticator,
373 struct netr_Authenticator *return_authenticator,
374 struct netlogon_creds_CredentialState **creds_out)
377 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
378 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
380 if (schannel_global_required) {
381 nt_status = schannel_check_required(auth_info,
384 if (!NT_STATUS_IS_OK(nt_status)) {
389 nt_status = schannel_check_creds_state(mem_ctx,
390 dce_call->conn->dce_ctx->lp_ctx,
392 received_authenticator,
393 return_authenticator,
399 Change the machine account password for the currently connected
400 client. Supplies only the NT#.
403 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
404 struct netr_ServerPasswordSet *r)
406 struct netlogon_creds_CredentialState *creds;
407 struct ldb_context *sam_ctx;
408 const char * const attrs[] = { "unicodePwd", NULL };
409 struct ldb_message **res;
410 struct samr_Password *oldNtHash;
414 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
417 r->in.credential, r->out.return_authenticator,
419 NT_STATUS_NOT_OK_RETURN(nt_status);
421 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), 0);
422 if (sam_ctx == NULL) {
423 return NT_STATUS_INVALID_SYSTEM_SERVICE;
426 netlogon_creds_des_decrypt(creds, r->in.new_password);
428 /* fetch the old password hashes (the NT hash has to exist) */
430 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
431 "(&(objectClass=user)(objectSid=%s))",
432 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
434 return NT_STATUS_WRONG_PASSWORD;
437 nt_status = samdb_result_passwords(mem_ctx,
438 dce_call->conn->dce_ctx->lp_ctx,
439 res[0], NULL, &oldNtHash);
440 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
441 return NT_STATUS_WRONG_PASSWORD;
444 /* Using the sid for the account as the key, set the password */
445 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
447 NULL, /* Don't have plaintext */
448 NULL, r->in.new_password,
449 NULL, oldNtHash, /* Password change */
455 Change the machine account password for the currently connected
456 client. Supplies new plaintext.
458 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
459 struct netr_ServerPasswordSet2 *r)
461 struct netlogon_creds_CredentialState *creds;
462 struct ldb_context *sam_ctx;
463 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
464 struct ldb_message **res;
465 struct samr_Password *oldLmHash, *oldNtHash;
467 DATA_BLOB new_password;
470 struct samr_CryptPassword password_buf;
472 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
475 r->in.credential, r->out.return_authenticator,
477 NT_STATUS_NOT_OK_RETURN(nt_status);
479 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), 0);
480 if (sam_ctx == NULL) {
481 return NT_STATUS_INVALID_SYSTEM_SERVICE;
484 memcpy(password_buf.data, r->in.new_password->data, 512);
485 SIVAL(password_buf.data, 512, r->in.new_password->length);
486 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
488 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
489 DEBUG(3,("samr: failed to decode password buffer\n"));
490 return NT_STATUS_WRONG_PASSWORD;
493 /* fetch the old password hashes (at least one of both has to exist) */
495 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
496 "(&(objectClass=user)(objectSid=%s))",
497 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
499 return NT_STATUS_WRONG_PASSWORD;
502 nt_status = samdb_result_passwords(mem_ctx,
503 dce_call->conn->dce_ctx->lp_ctx,
504 res[0], &oldLmHash, &oldNtHash);
505 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
506 return NT_STATUS_WRONG_PASSWORD;
509 /* Using the sid for the account as the key, set the password */
510 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
512 &new_password, /* we have plaintext */
514 oldLmHash, oldNtHash, /* Password change */
523 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
524 struct netr_LogonUasLogon *r)
526 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
533 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
534 struct netr_LogonUasLogoff *r)
536 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
540 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
542 switch (r->in.logon_level) {
543 case NetlogonInteractiveInformation:
544 case NetlogonServiceInformation:
545 case NetlogonInteractiveTransitiveInformation:
546 case NetlogonServiceTransitiveInformation:
547 if (r->in.logon->password == NULL) {
548 return NT_STATUS_INVALID_PARAMETER;
551 switch (r->in.validation_level) {
552 case NetlogonValidationSamInfo: /* 2 */
553 case NetlogonValidationSamInfo2: /* 3 */
554 case NetlogonValidationSamInfo4: /* 6 */
557 return NT_STATUS_INVALID_INFO_CLASS;
561 case NetlogonNetworkInformation:
562 case NetlogonNetworkTransitiveInformation:
563 if (r->in.logon->network == NULL) {
564 return NT_STATUS_INVALID_PARAMETER;
567 switch (r->in.validation_level) {
568 case NetlogonValidationSamInfo: /* 2 */
569 case NetlogonValidationSamInfo2: /* 3 */
570 case NetlogonValidationSamInfo4: /* 6 */
573 return NT_STATUS_INVALID_INFO_CLASS;
578 case NetlogonGenericInformation:
579 if (r->in.logon->generic == NULL) {
580 return NT_STATUS_INVALID_PARAMETER;
583 switch (r->in.validation_level) {
584 /* TODO: case NetlogonValidationGenericInfo: 4 */
585 case NetlogonValidationGenericInfo2: /* 5 */
588 return NT_STATUS_INVALID_INFO_CLASS;
593 return NT_STATUS_INVALID_PARAMETER;
600 netr_LogonSamLogon_base
602 This version of the function allows other wrappers to say 'do not check the credentials'
604 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
606 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
607 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
609 struct auth4_context *auth_context;
610 struct auth_usersupplied_info *user_info;
611 struct auth_user_info_dc *user_info_dc;
613 static const char zeros[16];
614 struct netr_SamBaseInfo *sam;
615 struct netr_SamInfo2 *sam2;
616 struct netr_SamInfo3 *sam3;
617 struct netr_SamInfo6 *sam6;
619 *r->out.authoritative = 1;
621 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
622 NT_STATUS_HAVE_NO_MEMORY(user_info);
624 switch (r->in.logon_level) {
625 case NetlogonInteractiveInformation:
626 case NetlogonServiceInformation:
627 case NetlogonInteractiveTransitiveInformation:
628 case NetlogonServiceTransitiveInformation:
629 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
630 netlogon_creds_arcfour_crypt(creds,
631 r->in.logon->password->lmpassword.hash,
632 sizeof(r->in.logon->password->lmpassword.hash));
633 netlogon_creds_arcfour_crypt(creds,
634 r->in.logon->password->ntpassword.hash,
635 sizeof(r->in.logon->password->ntpassword.hash));
637 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
638 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
641 /* TODO: we need to deny anonymous access here */
642 nt_status = auth_context_create(mem_ctx,
643 dce_call->event_ctx, dce_call->msg_ctx,
644 dce_call->conn->dce_ctx->lp_ctx,
646 NT_STATUS_NOT_OK_RETURN(nt_status);
648 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
649 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
650 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
651 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
653 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
654 user_info->password_state = AUTH_PASSWORD_HASH;
656 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
657 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
658 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
660 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
661 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
662 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
665 case NetlogonNetworkInformation:
666 case NetlogonNetworkTransitiveInformation:
668 /* TODO: we need to deny anonymous access here */
669 nt_status = auth_context_create(mem_ctx,
670 dce_call->event_ctx, dce_call->msg_ctx,
671 dce_call->conn->dce_ctx->lp_ctx,
673 NT_STATUS_NOT_OK_RETURN(nt_status);
675 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
676 NT_STATUS_NOT_OK_RETURN(nt_status);
678 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
679 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
680 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
681 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
683 user_info->password_state = AUTH_PASSWORD_RESPONSE;
684 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
685 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
690 case NetlogonGenericInformation:
692 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
693 netlogon_creds_arcfour_crypt(creds,
694 r->in.logon->generic->data, r->in.logon->generic->length);
696 /* Using DES to verify kerberos tickets makes no sense */
697 return NT_STATUS_INVALID_PARAMETER;
700 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
702 struct dcerpc_binding_handle *irpc_handle;
703 struct kdc_check_generic_kerberos check;
704 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
705 NT_STATUS_HAVE_NO_MEMORY(generic);
706 *r->out.authoritative = 1;
708 /* TODO: Describe and deal with these flags */
711 r->out.validation->generic = generic;
713 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
717 if (irpc_handle == NULL) {
718 return NT_STATUS_NO_LOGON_SERVERS;
721 check.in.generic_request =
722 data_blob_const(r->in.logon->generic->data,
723 r->in.logon->generic->length);
725 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
728 if (!NT_STATUS_IS_OK(status)) {
731 generic->length = check.out.generic_reply.length;
732 generic->data = check.out.generic_reply.data;
736 /* Until we get an implemetnation of these other packages */
737 return NT_STATUS_INVALID_PARAMETER;
740 return NT_STATUS_INVALID_PARAMETER;
743 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
744 /* TODO: set *r->out.authoritative = 0 on specific errors */
745 NT_STATUS_NOT_OK_RETURN(nt_status);
747 switch (r->in.validation_level) {
749 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
750 NT_STATUS_NOT_OK_RETURN(nt_status);
752 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
753 NT_STATUS_HAVE_NO_MEMORY(sam2);
756 /* And put into the talloc tree */
757 talloc_steal(sam2, sam);
758 r->out.validation->sam2 = sam2;
764 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
767 NT_STATUS_NOT_OK_RETURN(nt_status);
769 r->out.validation->sam3 = sam3;
775 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
778 NT_STATUS_NOT_OK_RETURN(nt_status);
780 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
781 NT_STATUS_HAVE_NO_MEMORY(sam6);
782 sam6->base = sam3->base;
784 sam6->sidcount = sam3->sidcount;
785 sam6->sids = sam3->sids;
787 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
788 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
789 sam->account_name.string, sam6->dns_domainname.string);
790 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
791 /* And put into the talloc tree */
792 talloc_steal(sam6, sam3);
794 r->out.validation->sam6 = sam6;
798 return NT_STATUS_INVALID_INFO_CLASS;
801 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
802 /* It appears that level 6 is not individually encrypted */
803 if ((r->in.validation_level != 6) &&
804 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
805 /* This key is sent unencrypted without the ARCFOUR flag set */
806 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
807 netlogon_creds_arcfour_crypt(creds,
809 sizeof(sam->key.key));
813 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
814 /* It appears that level 6 is not individually encrypted */
815 if ((r->in.validation_level != 6) &&
816 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
817 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
818 netlogon_creds_arcfour_crypt(creds,
820 sizeof(sam->LMSessKey.key));
822 netlogon_creds_des_encrypt_LMKey(creds,
827 /* TODO: Describe and deal with these flags */
833 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
834 struct netr_LogonSamLogonEx *r)
837 struct netlogon_creds_CredentialState *creds;
839 *r->out.authoritative = 1;
841 nt_status = dcesrv_netr_LogonSamLogon_check(r);
842 if (!NT_STATUS_IS_OK(nt_status)) {
846 nt_status = schannel_get_creds_state(mem_ctx,
847 dce_call->conn->dce_ctx->lp_ctx,
848 r->in.computer_name, &creds);
849 if (!NT_STATUS_IS_OK(nt_status)) {
853 if (!dce_call->conn->auth_state.auth_info ||
854 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
855 return NT_STATUS_ACCESS_DENIED;
857 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
861 netr_LogonSamLogonWithFlags
864 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
865 struct netr_LogonSamLogonWithFlags *r)
868 struct netlogon_creds_CredentialState *creds;
869 struct netr_LogonSamLogonEx r2;
871 struct netr_Authenticator *return_authenticator;
875 r2.in.server_name = r->in.server_name;
876 r2.in.computer_name = r->in.computer_name;
877 r2.in.logon_level = r->in.logon_level;
878 r2.in.logon = r->in.logon;
879 r2.in.validation_level = r->in.validation_level;
880 r2.in.flags = r->in.flags;
881 r2.out.validation = r->out.validation;
882 r2.out.authoritative = r->out.authoritative;
883 r2.out.flags = r->out.flags;
885 *r->out.authoritative = 1;
887 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
888 if (!NT_STATUS_IS_OK(nt_status)) {
892 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
893 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
895 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
898 r->in.credential, return_authenticator,
900 NT_STATUS_NOT_OK_RETURN(nt_status);
902 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
904 r->out.return_authenticator = return_authenticator;
912 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
913 struct netr_LogonSamLogon *r)
915 struct netr_LogonSamLogonWithFlags r2;
921 r2.in.server_name = r->in.server_name;
922 r2.in.computer_name = r->in.computer_name;
923 r2.in.credential = r->in.credential;
924 r2.in.return_authenticator = r->in.return_authenticator;
925 r2.in.logon_level = r->in.logon_level;
926 r2.in.logon = r->in.logon;
927 r2.in.validation_level = r->in.validation_level;
928 r2.in.flags = &flags;
929 r2.out.validation = r->out.validation;
930 r2.out.authoritative = r->out.authoritative;
931 r2.out.flags = &flags;
933 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
935 r->out.return_authenticator = r2.out.return_authenticator;
944 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
945 struct netr_LogonSamLogoff *r)
947 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
955 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
956 struct netr_DatabaseDeltas *r)
958 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
965 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
966 struct netr_DatabaseSync2 *r)
968 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
969 return NT_STATUS_NOT_IMPLEMENTED;
976 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
977 struct netr_DatabaseSync *r)
979 struct netr_DatabaseSync2 r2;
984 r2.in.logon_server = r->in.logon_server;
985 r2.in.computername = r->in.computername;
986 r2.in.credential = r->in.credential;
987 r2.in.database_id = r->in.database_id;
988 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
989 r2.in.sync_context = r->in.sync_context;
990 r2.out.sync_context = r->out.sync_context;
991 r2.out.delta_enum_array = r->out.delta_enum_array;
992 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
994 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1003 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1004 struct netr_AccountDeltas *r)
1006 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1007 return NT_STATUS_NOT_IMPLEMENTED;
1014 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1015 struct netr_AccountSync *r)
1017 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1018 return NT_STATUS_NOT_IMPLEMENTED;
1025 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1026 struct netr_GetDcName *r)
1028 const char * const attrs[] = { NULL };
1029 struct ldb_context *sam_ctx;
1030 struct ldb_message **res;
1031 struct ldb_dn *domain_dn;
1036 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1037 * that the domainname needs to be a valid netbios domain
1038 * name, if it is not NULL.
1040 if (r->in.domainname) {
1041 const char *dot = strchr(r->in.domainname, '.');
1042 size_t len = strlen(r->in.domainname);
1044 if (dot || len > 15) {
1045 return WERR_DCNOTFOUND;
1049 * TODO: Should we also varify that only valid
1050 * netbios name characters are used?
1054 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1055 dce_call->conn->dce_ctx->lp_ctx,
1056 dce_call->conn->auth_state.session_info, 0);
1057 if (sam_ctx == NULL) {
1058 return WERR_DS_UNAVAILABLE;
1061 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1063 if (domain_dn == NULL) {
1064 return WERR_NO_SUCH_DOMAIN;
1067 ret = gendb_search_dn(sam_ctx, mem_ctx,
1068 domain_dn, &res, attrs);
1070 return WERR_NO_SUCH_DOMAIN;
1073 /* TODO: - return real IP address
1074 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1076 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1077 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1078 W_ERROR_HAVE_NO_MEMORY(dcname);
1080 *r->out.dcname = dcname;
1086 netr_LogonControl2Ex
1088 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1089 struct netr_LogonControl2Ex *r)
1091 return WERR_NOT_SUPPORTED;
1098 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1099 struct netr_LogonControl *r)
1101 struct netr_LogonControl2Ex r2;
1104 if (r->in.level == 0x00000001) {
1107 r2.in.logon_server = r->in.logon_server;
1108 r2.in.function_code = r->in.function_code;
1109 r2.in.level = r->in.level;
1111 r2.out.query = r->out.query;
1113 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1114 } else if (r->in.level == 0x00000002) {
1115 werr = WERR_NOT_SUPPORTED;
1117 werr = WERR_UNKNOWN_LEVEL;
1127 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1128 struct netr_LogonControl2 *r)
1130 struct netr_LogonControl2Ex r2;
1135 r2.in.logon_server = r->in.logon_server;
1136 r2.in.function_code = r->in.function_code;
1137 r2.in.level = r->in.level;
1138 r2.in.data = r->in.data;
1139 r2.out.query = r->out.query;
1141 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1146 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1147 struct ldb_context *sam_ctx,
1148 struct netr_DomainTrustList *trusts,
1149 uint32_t trust_flags);
1154 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1155 struct netr_GetAnyDCName *r)
1157 struct netr_DomainTrustList *trusts;
1158 struct ldb_context *sam_ctx;
1159 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1163 *r->out.dcname = NULL;
1165 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1166 /* if the domainname parameter wasn't set assume our domain */
1167 r->in.domainname = lpcfg_workgroup(lp_ctx);
1170 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1171 dce_call->conn->auth_state.session_info, 0);
1172 if (sam_ctx == NULL) {
1173 return WERR_DS_UNAVAILABLE;
1176 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1177 /* well we asked for a DC of our own domain */
1178 if (samdb_is_pdc(sam_ctx)) {
1179 /* we are the PDC of the specified domain */
1180 return WERR_NO_SUCH_DOMAIN;
1183 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1184 lpcfg_netbios_name(lp_ctx));
1185 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1190 /* Okay, now we have to consider the trusted domains */
1192 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1193 W_ERROR_HAVE_NO_MEMORY(trusts);
1197 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1198 NETR_TRUST_FLAG_INBOUND
1199 | NETR_TRUST_FLAG_OUTBOUND);
1200 W_ERROR_NOT_OK_RETURN(werr);
1202 for (i = 0; i < trusts->count; i++) {
1203 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1204 /* FIXME: Here we need to find a DC for the specified
1205 * trusted domain. */
1207 /* return WERR_OK; */
1208 return WERR_NO_SUCH_DOMAIN;
1212 return WERR_NO_SUCH_DOMAIN;
1219 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1220 struct netr_DatabaseRedo *r)
1222 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1227 netr_NetrEnumerateTrustedDomains
1229 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1230 struct netr_NetrEnumerateTrustedDomains *r)
1232 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1237 netr_LogonGetCapabilities
1239 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1240 struct netr_LogonGetCapabilities *r)
1242 struct netlogon_creds_CredentialState *creds;
1245 status = dcesrv_netr_creds_server_step_check(dce_call,
1247 r->in.computer_name,
1249 r->out.return_authenticator,
1251 if (!NT_STATUS_IS_OK(status)) {
1252 DEBUG(0,(__location__ " Bad credentials - error\n"));
1254 NT_STATUS_NOT_OK_RETURN(status);
1256 if (r->in.query_level != 1) {
1257 return NT_STATUS_NOT_SUPPORTED;
1260 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1262 return NT_STATUS_OK;
1267 netr_NETRLOGONSETSERVICEBITS
1269 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1270 struct netr_NETRLOGONSETSERVICEBITS *r)
1272 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1277 netr_LogonGetTrustRid
1279 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1280 struct netr_LogonGetTrustRid *r)
1282 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1287 netr_NETRLOGONCOMPUTESERVERDIGEST
1289 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1290 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1292 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1297 netr_NETRLOGONCOMPUTECLIENTDIGEST
1299 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1300 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1302 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1310 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1311 struct netr_DsRGetSiteName *r)
1313 struct ldb_context *sam_ctx;
1314 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1316 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1317 dce_call->conn->auth_state.session_info, 0);
1318 if (sam_ctx == NULL) {
1319 return WERR_DS_UNAVAILABLE;
1323 * We assume to be a DC when we get called over NETLOGON. Hence we
1324 * get our site name always by using "samdb_server_site_name()"
1325 * and not "samdb_client_site_name()".
1327 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1328 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1335 fill in a netr_OneDomainInfo from a ldb search result
1337 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1338 struct loadparm_context *lp_ctx,
1339 struct ldb_context *sam_ctx,
1340 struct ldb_message *res,
1341 struct netr_OneDomainInfo *info,
1342 bool is_local, bool is_trust_list)
1346 if (is_trust_list) {
1347 /* w2k8 only fills this on trusted domains */
1348 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1349 info->trust_extension.length = 16;
1350 info->trust_extension.info->flags =
1351 NETR_TRUST_FLAG_TREEROOT |
1352 NETR_TRUST_FLAG_IN_FOREST |
1353 NETR_TRUST_FLAG_PRIMARY |
1354 NETR_TRUST_FLAG_NATIVE;
1356 info->trust_extension.info->parent_index = 0; /* should be index into array
1358 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1359 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1362 if (is_trust_list) {
1363 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1364 info->dns_forestname.string = NULL;
1366 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1367 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1368 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1369 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1373 info->domainname.string = lpcfg_workgroup(lp_ctx);
1374 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1375 info->domain_guid = samdb_result_guid(res, "objectGUID");
1376 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1378 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1379 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1380 info->domain_guid = samdb_result_guid(res, "objectGUID");
1381 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1383 if (!is_trust_list) {
1384 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1387 return NT_STATUS_OK;
1391 netr_LogonGetDomainInfo
1392 this is called as part of the ADS domain logon procedure.
1394 It has an important role in convaying details about the client, such
1395 as Operating System, Version, Service Pack etc.
1397 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1398 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1400 struct netlogon_creds_CredentialState *creds;
1401 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1402 "securityIdentifier", "trustPartner", NULL };
1403 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1404 "msDS-SupportedEncryptionTypes", NULL };
1405 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1406 struct ldb_context *sam_ctx;
1407 struct ldb_message **res1, **res2, **res3, *new_msg;
1408 struct ldb_dn *workstation_dn;
1409 struct netr_DomainInformation *domain_info;
1410 struct netr_LsaPolicyInformation *lsa_policy_info;
1411 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1412 bool update_dns_hostname = true;
1416 status = dcesrv_netr_creds_server_step_check(dce_call,
1418 r->in.computer_name,
1420 r->out.return_authenticator,
1422 if (!NT_STATUS_IS_OK(status)) {
1423 DEBUG(0,(__location__ " Bad credentials - error\n"));
1425 NT_STATUS_NOT_OK_RETURN(status);
1427 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1428 dce_call->conn->dce_ctx->lp_ctx,
1429 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1430 if (sam_ctx == NULL) {
1431 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1434 switch (r->in.level) {
1435 case 1: /* Domain information */
1437 if (r->in.query->workstation_info == NULL) {
1438 return NT_STATUS_INVALID_PARAMETER;
1441 /* Prepares the workstation DN */
1442 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1443 dom_sid_string(mem_ctx, creds->sid));
1444 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1446 /* Lookup for attributes in workstation object */
1447 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1450 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1453 /* Gets the sam account name which is checked against the DNS
1454 * hostname parameter. */
1455 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1458 if (sam_account_name == NULL) {
1459 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1463 * Checks that the sam account name without a possible "$"
1464 * matches as prefix with the DNS hostname in the workstation
1467 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1468 strcspn(sam_account_name, "$"));
1469 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1470 if (r->in.query->workstation_info->dns_hostname != NULL) {
1471 prefix2 = talloc_strndup(mem_ctx,
1472 r->in.query->workstation_info->dns_hostname,
1473 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1474 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1476 if (strcasecmp(prefix1, prefix2) != 0) {
1477 update_dns_hostname = false;
1480 update_dns_hostname = false;
1483 /* Gets the old DNS hostname */
1484 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1489 * Updates the DNS hostname when the client wishes that the
1490 * server should handle this for him
1491 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1492 * obviously only checked when we do already have a
1494 * See MS-NRPC section 3.5.4.3.9
1496 if ((old_dns_hostname != NULL) &&
1497 (r->in.query->workstation_info->workstation_flags
1498 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1499 update_dns_hostname = false;
1502 /* Gets host information and put them into our directory */
1504 new_msg = ldb_msg_new(mem_ctx);
1505 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1507 new_msg->dn = workstation_dn;
1509 /* Sets the OS name */
1511 if (r->in.query->workstation_info->os_name.string == NULL) {
1512 return NT_STATUS_INVALID_PARAMETER;
1515 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1516 r->in.query->workstation_info->os_name.string);
1517 if (ret != LDB_SUCCESS) {
1518 return NT_STATUS_NO_MEMORY;
1522 * Sets information from "os_version". On an empty structure
1523 * the values are cleared.
1525 if (r->in.query->workstation_info->os_version.os != NULL) {
1526 struct netr_OsVersionInfoEx *os_version;
1527 const char *os_version_str;
1529 os_version = &r->in.query->workstation_info->os_version.os->os;
1531 if (os_version->CSDVersion == NULL) {
1532 return NT_STATUS_INVALID_PARAMETER;
1535 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1536 os_version->MajorVersion,
1537 os_version->MinorVersion,
1538 os_version->BuildNumber);
1539 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1541 ret = ldb_msg_add_string(new_msg,
1542 "operatingSystemServicePack",
1543 os_version->CSDVersion);
1544 if (ret != LDB_SUCCESS) {
1545 return NT_STATUS_NO_MEMORY;
1548 ret = ldb_msg_add_string(new_msg,
1549 "operatingSystemVersion",
1551 if (ret != LDB_SUCCESS) {
1552 return NT_STATUS_NO_MEMORY;
1555 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1556 "operatingSystemServicePack");
1557 if (ret != LDB_SUCCESS) {
1558 return NT_STATUS_NO_MEMORY;
1561 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1562 "operatingSystemVersion");
1563 if (ret != LDB_SUCCESS) {
1564 return NT_STATUS_NO_MEMORY;
1569 * If the boolean "update_dns_hostname" remained true, then we
1570 * are fine to start the update.
1572 if (update_dns_hostname) {
1573 ret = ldb_msg_add_string(new_msg,
1575 r->in.query->workstation_info->dns_hostname);
1576 if (ret != LDB_SUCCESS) {
1577 return NT_STATUS_NO_MEMORY;
1580 /* This manual "servicePrincipalName" generation is
1581 * still needed! Since the update in the samldb LDB
1582 * module does only work if the entries already exist
1583 * which isn't always the case. */
1584 ret = ldb_msg_add_string(new_msg,
1585 "servicePrincipalName",
1586 talloc_asprintf(new_msg, "HOST/%s",
1587 r->in.computer_name));
1588 if (ret != LDB_SUCCESS) {
1589 return NT_STATUS_NO_MEMORY;
1592 ret = ldb_msg_add_string(new_msg,
1593 "servicePrincipalName",
1594 talloc_asprintf(new_msg, "HOST/%s",
1595 r->in.query->workstation_info->dns_hostname));
1596 if (ret != LDB_SUCCESS) {
1597 return NT_STATUS_NO_MEMORY;
1601 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1602 DEBUG(3,("Impossible to update samdb: %s\n",
1603 ldb_errstring(sam_ctx)));
1606 talloc_free(new_msg);
1608 /* Writes back the domain information */
1610 /* We need to do two searches. The first will pull our primary
1611 domain and the second will pull any trusted domains. Our
1612 primary domain is also a "trusted" domain, so we need to
1613 put the primary domain into the lists of returned trusts as
1615 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1618 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1621 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1622 "(objectClass=trustedDomain)");
1624 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1627 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1628 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1630 ZERO_STRUCTP(domain_info);
1632 /* Informations about the local and trusted domains */
1634 status = fill_one_domain_info(mem_ctx,
1635 dce_call->conn->dce_ctx->lp_ctx,
1636 sam_ctx, res2[0], &domain_info->primary_domain,
1638 NT_STATUS_NOT_OK_RETURN(status);
1640 domain_info->trusted_domain_count = ret3 + 1;
1641 domain_info->trusted_domains = talloc_array(mem_ctx,
1642 struct netr_OneDomainInfo,
1643 domain_info->trusted_domain_count);
1644 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1646 for (i=0;i<ret3;i++) {
1647 status = fill_one_domain_info(mem_ctx,
1648 dce_call->conn->dce_ctx->lp_ctx,
1650 &domain_info->trusted_domains[i],
1652 NT_STATUS_NOT_OK_RETURN(status);
1655 status = fill_one_domain_info(mem_ctx,
1656 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1657 &domain_info->trusted_domains[i], true, true);
1658 NT_STATUS_NOT_OK_RETURN(status);
1660 /* Sets the supported encryption types */
1661 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1662 "msDS-SupportedEncryptionTypes",
1663 default_supported_enc_types);
1665 /* Other host domain information */
1667 lsa_policy_info = talloc(mem_ctx,
1668 struct netr_LsaPolicyInformation);
1669 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1670 ZERO_STRUCTP(lsa_policy_info);
1672 domain_info->lsa_policy = *lsa_policy_info;
1674 /* The DNS hostname is only returned back when there is a chance
1676 if ((r->in.query->workstation_info->workstation_flags
1677 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1678 domain_info->dns_hostname.string = old_dns_hostname;
1680 domain_info->dns_hostname.string = NULL;
1683 domain_info->workstation_flags =
1684 r->in.query->workstation_info->workstation_flags;
1686 r->out.info->domain_info = domain_info;
1688 case 2: /* LSA policy information - not used at the moment */
1689 lsa_policy_info = talloc(mem_ctx,
1690 struct netr_LsaPolicyInformation);
1691 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1692 ZERO_STRUCTP(lsa_policy_info);
1694 r->out.info->lsa_policy_info = lsa_policy_info;
1697 return NT_STATUS_INVALID_LEVEL;
1701 return NT_STATUS_OK;
1706 netr_ServerPasswordGet
1708 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1709 struct netr_ServerPasswordGet *r)
1711 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1716 netr_NETRLOGONSENDTOSAM
1718 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1719 struct netr_NETRLOGONSENDTOSAM *r)
1721 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1726 netr_DsRGetDCNameEx2
1728 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1729 TALLOC_CTX *mem_ctx,
1730 struct netr_DsRGetDCNameEx2 *r)
1732 struct ldb_context *sam_ctx;
1733 struct netr_DsRGetDCNameInfo *info;
1734 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1735 const struct tsocket_address *remote_address;
1737 const char *server_site_name;
1739 struct netlogon_samlogon_response response;
1741 const char *dc_name = NULL;
1742 const char *domain_name = NULL;
1743 struct interface *ifaces;
1746 ZERO_STRUCTP(r->out.info);
1748 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1749 dce_call->conn->auth_state.session_info, 0);
1750 if (sam_ctx == NULL) {
1751 return WERR_DS_UNAVAILABLE;
1754 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1755 if (tsocket_address_is_inet(remote_address, "ip")) {
1756 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1757 W_ERROR_HAVE_NO_MEMORY(addr);
1760 /* "server_unc" is ignored by w2k3 */
1762 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1763 return WERR_INVALID_FLAGS;
1766 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1767 r->in.flags & DS_PDC_REQUIRED &&
1768 r->in.flags & DS_KDC_REQUIRED) {
1769 return WERR_INVALID_FLAGS;
1771 if (r->in.flags & DS_IS_FLAT_NAME &&
1772 r->in.flags & DS_IS_DNS_NAME) {
1773 return WERR_INVALID_FLAGS;
1775 if (r->in.flags & DS_RETURN_DNS_NAME &&
1776 r->in.flags & DS_RETURN_FLAT_NAME) {
1777 return WERR_INVALID_FLAGS;
1779 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1780 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1781 return WERR_INVALID_FLAGS;
1784 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1786 (DS_DIRECTORY_SERVICE_REQUIRED |
1787 DS_DIRECTORY_SERVICE_PREFERRED |
1788 DS_GC_SERVER_REQUIRED |
1791 return WERR_INVALID_FLAGS;
1794 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1796 return WERR_INVALID_FLAGS;
1799 /* Proof server site parameter "site_name" if it was specified */
1800 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1801 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1802 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1803 server_site_name) != 0)) {
1804 return WERR_NO_SUCH_DOMAIN;
1807 guid_str = r->in.domain_guid != NULL ?
1808 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1810 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1814 r->in.client_account,
1816 NETLOGON_NT_VERSION_5EX_WITH_IP,
1817 lp_ctx, &response, true);
1818 if (!NT_STATUS_IS_OK(status)) {
1819 return ntstatus_to_werror(status);
1823 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1824 * (O) flag when the returned forest name is in DNS format. This is here
1825 * always the case (see below).
1827 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1829 if (r->in.flags & DS_RETURN_DNS_NAME) {
1830 dc_name = response.data.nt5_ex.pdc_dns_name;
1831 domain_name = response.data.nt5_ex.dns_domain;
1833 * According to MS-NRPC 2.2.1.2.1 we should set the
1834 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1835 * the returned information is in DNS form.
1837 response.data.nt5_ex.server_type |=
1838 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1839 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1840 dc_name = response.data.nt5_ex.pdc_name;
1841 domain_name = response.data.nt5_ex.domain_name;
1845 * TODO: autodetect what we need to return
1846 * based on the given arguments
1848 dc_name = response.data.nt5_ex.pdc_name;
1849 domain_name = response.data.nt5_ex.domain_name;
1852 if (!dc_name || !dc_name[0]) {
1853 return WERR_NO_SUCH_DOMAIN;
1856 if (!domain_name || !domain_name[0]) {
1857 return WERR_NO_SUCH_DOMAIN;
1860 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1861 W_ERROR_HAVE_NO_MEMORY(info);
1862 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1863 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1865 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1866 pdc_ip = iface_list_best_ip(ifaces, addr);
1867 if (pdc_ip == NULL) {
1868 pdc_ip = "127.0.0.1";
1870 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1871 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1872 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1873 info->domain_guid = response.data.nt5_ex.domain_uuid;
1874 info->domain_name = domain_name;
1875 info->forest_name = response.data.nt5_ex.forest;
1876 info->dc_flags = response.data.nt5_ex.server_type;
1877 info->dc_site_name = response.data.nt5_ex.server_site;
1878 info->client_site_name = response.data.nt5_ex.client_site;
1880 *r->out.info = info;
1888 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1889 struct netr_DsRGetDCNameEx *r)
1891 struct netr_DsRGetDCNameEx2 r2;
1896 r2.in.server_unc = r->in.server_unc;
1897 r2.in.client_account = NULL;
1899 r2.in.domain_guid = r->in.domain_guid;
1900 r2.in.domain_name = r->in.domain_name;
1901 r2.in.site_name = r->in.site_name;
1902 r2.in.flags = r->in.flags;
1903 r2.out.info = r->out.info;
1905 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1913 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1914 struct netr_DsRGetDCName *r)
1916 struct netr_DsRGetDCNameEx2 r2;
1921 r2.in.server_unc = r->in.server_unc;
1922 r2.in.client_account = NULL;
1924 r2.in.domain_name = r->in.domain_name;
1925 r2.in.domain_guid = r->in.domain_guid;
1927 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1928 r2.in.flags = r->in.flags;
1929 r2.out.info = r->out.info;
1931 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1936 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1938 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1939 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1941 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1946 netr_NetrEnumerateTrustedDomainsEx
1948 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1949 struct netr_NetrEnumerateTrustedDomainsEx *r)
1951 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1956 netr_DsRAddressToSitenamesExW
1958 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1959 struct netr_DsRAddressToSitenamesExW *r)
1961 struct ldb_context *sam_ctx;
1962 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1963 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1964 sa_family_t sin_family;
1965 struct sockaddr_in *addr;
1967 struct sockaddr_in6 *addr6;
1968 char addr_str[INET6_ADDRSTRLEN];
1970 char addr_str[INET_ADDRSTRLEN];
1976 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1977 dce_call->conn->auth_state.session_info, 0);
1978 if (sam_ctx == NULL) {
1979 return WERR_DS_UNAVAILABLE;
1982 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1983 W_ERROR_HAVE_NO_MEMORY(ctr);
1987 ctr->count = r->in.count;
1988 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1989 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1990 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1991 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1993 for (i=0; i<ctr->count; i++) {
1994 ctr->sitename[i].string = NULL;
1995 ctr->subnetname[i].string = NULL;
1997 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2000 /* The first two byte of the buffer are reserved for the
2001 * "sin_family" but for now only the first one is used. */
2002 sin_family = r->in.addresses[i].buffer[0];
2004 switch (sin_family) {
2006 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2009 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2010 res = inet_ntop(AF_INET, &addr->sin_addr,
2011 addr_str, sizeof(addr_str));
2015 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2018 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2019 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2020 addr_str, sizeof(addr_str));
2031 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2035 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2036 ctr->subnetname[i].string = subnet_name;
2044 netr_DsRAddressToSitenamesW
2046 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2047 struct netr_DsRAddressToSitenamesW *r)
2049 struct netr_DsRAddressToSitenamesExW r2;
2050 struct netr_DsRAddressToSitenamesWCtr *ctr;
2056 r2.in.server_name = r->in.server_name;
2057 r2.in.count = r->in.count;
2058 r2.in.addresses = r->in.addresses;
2060 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2061 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2063 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2064 W_ERROR_HAVE_NO_MEMORY(ctr);
2068 ctr->count = r->in.count;
2069 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2070 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2072 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2074 for (i=0; i<ctr->count; i++) {
2075 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2083 netr_DsrGetDcSiteCoverageW
2085 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2086 struct netr_DsrGetDcSiteCoverageW *r)
2088 struct ldb_context *sam_ctx;
2089 struct DcSitesCtr *ctr;
2090 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2092 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2093 dce_call->conn->auth_state.session_info, 0);
2094 if (sam_ctx == NULL) {
2095 return WERR_DS_UNAVAILABLE;
2098 ctr = talloc(mem_ctx, struct DcSitesCtr);
2099 W_ERROR_HAVE_NO_MEMORY(ctr);
2103 /* For now only return our default site */
2105 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2106 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2107 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2108 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2114 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2115 struct ldb_context *sam_ctx,
2116 struct netr_DomainTrustList *trusts,
2117 uint32_t trust_flags)
2119 struct ldb_dn *system_dn;
2120 struct ldb_message **dom_res = NULL;
2121 const char *trust_attrs[] = { "flatname", "trustPartner",
2122 "securityIdentifier", "trustDirection",
2123 "trustType", "trustAttributes", NULL };
2128 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2129 NETR_TRUST_FLAG_OUTBOUND))) {
2130 return WERR_INVALID_FLAGS;
2133 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2134 ldb_get_default_basedn(sam_ctx),
2135 "(&(objectClass=container)(cn=System))");
2137 return WERR_GENERAL_FAILURE;
2140 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2141 &dom_res, trust_attrs,
2142 "(objectclass=trustedDomain)");
2144 for (i = 0; i < ret; i++) {
2145 unsigned int trust_dir;
2148 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2149 "trustDirection", 0);
2151 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2152 flags |= NETR_TRUST_FLAG_INBOUND;
2154 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2155 flags |= NETR_TRUST_FLAG_OUTBOUND;
2158 if (!(flags & trust_flags)) {
2159 /* this trust direction was not requested */
2164 trusts->array = talloc_realloc(trusts, trusts->array,
2165 struct netr_DomainTrust,
2167 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2169 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2170 if (!trusts->array[n].netbios_name) {
2171 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2172 "without flatname\n",
2173 ldb_dn_get_linearized(dom_res[i]->dn)));
2176 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2178 trusts->array[n].trust_flags = flags;
2179 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2180 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2181 /* TODO: find if we have parent in the list */
2182 trusts->array[n].parent_index = 0;
2185 trusts->array[n].trust_type =
2186 ldb_msg_find_attr_as_uint(dom_res[i],
2188 trusts->array[n].trust_attributes =
2189 ldb_msg_find_attr_as_uint(dom_res[i],
2190 "trustAttributes", 0);
2192 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2193 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2194 struct dom_sid zero_sid;
2195 ZERO_STRUCT(zero_sid);
2196 trusts->array[n].sid =
2197 dom_sid_dup(trusts, &zero_sid);
2199 trusts->array[n].sid =
2200 samdb_result_dom_sid(trusts, dom_res[i],
2201 "securityIdentifier");
2203 trusts->array[n].guid = GUID_zero();
2205 trusts->count = n + 1;
2208 talloc_free(dom_res);
2213 netr_DsrEnumerateDomainTrusts
2215 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2216 TALLOC_CTX *mem_ctx,
2217 struct netr_DsrEnumerateDomainTrusts *r)
2219 struct netr_DomainTrustList *trusts;
2220 struct ldb_context *sam_ctx;
2222 struct ldb_message **dom_res;
2223 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2224 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2225 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2229 if (r->in.trust_flags & 0xFFFFFE00) {
2230 return WERR_INVALID_FLAGS;
2233 /* TODO: turn to hard check once we are sure this is 100% correct */
2234 if (!r->in.server_name) {
2235 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2236 "But received NULL!\n", dnsdomain));
2238 p = strchr(r->in.server_name, '.');
2240 DEBUG(3, ("Invalid domain! Expected name in domain "
2241 "[%s]. But received [%s]!\n",
2242 dnsdomain, r->in.server_name));
2243 p = r->in.server_name;
2247 if (strcasecmp(p, dnsdomain)) {
2248 DEBUG(3, ("Invalid domain! Expected name in domain "
2249 "[%s]. But received [%s]!\n",
2250 dnsdomain, r->in.server_name));
2254 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2255 W_ERROR_HAVE_NO_MEMORY(trusts);
2258 r->out.trusts = trusts;
2260 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2261 dce_call->conn->auth_state.session_info, 0);
2262 if (sam_ctx == NULL) {
2263 return WERR_GENERAL_FAILURE;
2266 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2267 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2269 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2270 trusts, r->in.trust_flags);
2271 W_ERROR_NOT_OK_RETURN(werr);
2274 /* NOTE: we currently are always the root of the forest */
2275 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2276 uint32_t n = trusts->count;
2278 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2279 &dom_res, dom_attrs);
2281 return WERR_GENERAL_FAILURE;
2284 trusts->count = n + 1;
2285 trusts->array = talloc_realloc(trusts, trusts->array,
2286 struct netr_DomainTrust,
2288 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2290 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2291 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2292 trusts->array[n].trust_flags =
2293 NETR_TRUST_FLAG_NATIVE |
2294 NETR_TRUST_FLAG_TREEROOT |
2295 NETR_TRUST_FLAG_IN_FOREST |
2296 NETR_TRUST_FLAG_PRIMARY;
2297 /* we are always the root domain for now */
2298 trusts->array[n].parent_index = 0;
2299 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2300 trusts->array[n].trust_attributes = 0;
2301 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2304 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2306 talloc_free(dom_res);
2314 netr_DsrDeregisterDNSHostRecords
2316 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2317 struct netr_DsrDeregisterDNSHostRecords *r)
2319 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2324 netr_ServerTrustPasswordsGet
2326 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2327 struct netr_ServerTrustPasswordsGet *r)
2329 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2333 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2334 struct ldb_context *sam_ctx,
2335 struct loadparm_context *lp_ctx,
2336 struct lsa_ForestTrustInformation *info)
2338 struct lsa_ForestTrustDomainInfo *domain_info;
2339 struct lsa_ForestTrustRecord *e;
2340 struct ldb_message **dom_res;
2341 const char * const dom_attrs[] = { "objectSid", NULL };
2344 /* we need to provide 2 entries:
2345 * 1. the Root Forest name
2346 * 2. the Domain Information
2350 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2351 W_ERROR_HAVE_NO_MEMORY(info->entries);
2353 /* Forest root info */
2354 e = talloc(info, struct lsa_ForestTrustRecord);
2355 W_ERROR_HAVE_NO_MEMORY(e);
2358 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2359 e->time = 0; /* so far always 0 in trces. */
2360 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2362 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2364 info->entries[0] = e;
2367 e = talloc(info, struct lsa_ForestTrustRecord);
2368 W_ERROR_HAVE_NO_MEMORY(e);
2370 /* get our own domain info */
2371 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2373 return WERR_GENERAL_FAILURE;
2376 /* TODO: check if disabled and set flags accordingly */
2378 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2379 e->time = 0; /* so far always 0 in traces. */
2381 domain_info = &e->forest_trust_data.domain_info;
2382 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2384 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2385 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2387 info->entries[1] = e;
2389 talloc_free(dom_res);
2395 netr_DsRGetForestTrustInformation
2397 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2398 TALLOC_CTX *mem_ctx,
2399 struct netr_DsRGetForestTrustInformation *r)
2401 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2402 struct lsa_ForestTrustInformation *info, **info_ptr;
2403 struct ldb_context *sam_ctx;
2406 if (r->in.flags & 0xFFFFFFFE) {
2407 return WERR_INVALID_FLAGS;
2410 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2411 dce_call->conn->auth_state.session_info, 0);
2412 if (sam_ctx == NULL) {
2413 return WERR_GENERAL_FAILURE;
2416 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2417 if (!samdb_is_pdc(sam_ctx)) {
2418 return WERR_NERR_NOTPRIMARY;
2421 if (r->in.trusted_domain_name == NULL) {
2422 return WERR_INVALID_FLAGS;
2425 /* TODO: establish an schannel connection with
2426 * r->in.trusted_domain_name and perform a
2427 * netr_GetForestTrustInformation call against it */
2429 /* for now return not implementd */
2430 return WERR_CALL_NOT_IMPLEMENTED;
2433 /* TODO: check r->in.server_name is our name */
2435 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2436 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2438 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2439 W_ERROR_HAVE_NO_MEMORY(info);
2441 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2442 W_ERROR_NOT_OK_RETURN(werr);
2445 r->out.forest_trust_info = info_ptr;
2452 netr_GetForestTrustInformation
2454 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2455 TALLOC_CTX *mem_ctx,
2456 struct netr_GetForestTrustInformation *r)
2458 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2459 struct netlogon_creds_CredentialState *creds;
2460 struct lsa_ForestTrustInformation *info, **info_ptr;
2461 struct ldb_context *sam_ctx;
2465 status = dcesrv_netr_creds_server_step_check(dce_call,
2467 r->in.computer_name,
2469 r->out.return_authenticator,
2471 if (!NT_STATUS_IS_OK(status)) {
2475 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2476 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2477 return NT_STATUS_NOT_IMPLEMENTED;
2480 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2481 dce_call->conn->auth_state.session_info, 0);
2482 if (sam_ctx == NULL) {
2483 return NT_STATUS_INTERNAL_ERROR;
2486 /* TODO: check r->in.server_name is our name */
2488 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2490 return NT_STATUS_NO_MEMORY;
2492 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2494 return NT_STATUS_NO_MEMORY;
2497 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2498 if (!W_ERROR_IS_OK(werr)) {
2499 return werror_to_ntstatus(werr);
2503 r->out.forest_trust_info = info_ptr;
2505 return NT_STATUS_OK;
2510 netr_ServerGetTrustInfo
2512 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2513 struct netr_ServerGetTrustInfo *r)
2515 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2521 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2522 struct netr_Unused47 *r)
2524 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2528 struct netr_dnsupdate_RODC_state {
2529 struct dcesrv_call_state *dce_call;
2530 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2531 struct dnsupdate_RODC *r2;
2535 called when the forwarded RODC dns update request is finished
2537 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2539 struct netr_dnsupdate_RODC_state *st =
2540 tevent_req_callback_data(subreq,
2541 struct netr_dnsupdate_RODC_state);
2544 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2545 TALLOC_FREE(subreq);
2546 if (!NT_STATUS_IS_OK(status)) {
2547 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2548 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2551 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2553 status = dcesrv_reply(st->dce_call);
2554 if (!NT_STATUS_IS_OK(status)) {
2555 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2560 netr_DsrUpdateReadOnlyServerDnsRecords
2562 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2563 TALLOC_CTX *mem_ctx,
2564 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2566 struct netlogon_creds_CredentialState *creds;
2568 struct dcerpc_binding_handle *binding_handle;
2569 struct netr_dnsupdate_RODC_state *st;
2570 struct tevent_req *subreq;
2572 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2574 r->in.computer_name,
2576 r->out.return_authenticator,
2578 NT_STATUS_NOT_OK_RETURN(nt_status);
2580 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2581 return NT_STATUS_ACCESS_DENIED;
2584 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2585 NT_STATUS_HAVE_NO_MEMORY(st);
2587 st->dce_call = dce_call;
2589 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2590 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2592 st->r2->in.dom_sid = creds->sid;
2593 st->r2->in.site_name = r->in.site_name;
2594 st->r2->in.dns_ttl = r->in.dns_ttl;
2595 st->r2->in.dns_names = r->in.dns_names;
2596 st->r2->out.dns_names = r->out.dns_names;
2598 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2599 "dnsupdate", &ndr_table_irpc);
2600 if (binding_handle == NULL) {
2601 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2602 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2603 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2606 /* forward the call */
2607 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2608 binding_handle, st->r2);
2609 NT_STATUS_HAVE_NO_MEMORY(subreq);
2611 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2613 /* setup the callback */
2614 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2616 return NT_STATUS_OK;
2620 /* include the generated boilerplate */
2621 #include "librpc/gen_ndr/ndr_netlogon_s.c"