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_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"
41 struct netlogon_server_pipe_state {
42 struct netr_Credential client_challenge;
43 struct netr_Credential server_challenge;
46 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
47 struct netr_ServerReqChallenge *r)
49 struct netlogon_server_pipe_state *pipe_state =
50 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
52 ZERO_STRUCTP(r->out.return_credentials);
54 /* destroyed on pipe shutdown */
57 talloc_free(pipe_state);
58 dce_call->context->private_data = NULL;
61 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
62 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
64 pipe_state->client_challenge = *r->in.credentials;
66 generate_random_buffer(pipe_state->server_challenge.data,
67 sizeof(pipe_state->server_challenge.data));
69 *r->out.return_credentials = pipe_state->server_challenge;
71 dce_call->context->private_data = pipe_state;
76 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
77 struct netr_ServerAuthenticate3 *r)
79 struct netlogon_server_pipe_state *pipe_state =
80 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
81 struct netlogon_creds_CredentialState *creds;
82 struct ldb_context *sam_ctx;
83 struct samr_Password *mach_pwd;
84 uint32_t user_account_control;
86 struct ldb_message **msgs;
88 const char *attrs[] = {"unicodePwd", "userAccountControl",
91 const char *trust_dom_attrs[] = {"flatname", NULL};
92 const char *account_name;
94 ZERO_STRUCTP(r->out.return_credentials);
98 * According to Microsoft (see bugid #6099)
99 * Windows 7 looks at the negotiate_flags
100 * returned in this structure *even if the
101 * call fails with access denied!
103 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
104 NETLOGON_NEG_PERSISTENT_SAMREPL |
105 NETLOGON_NEG_ARCFOUR |
106 NETLOGON_NEG_PROMOTION_COUNT |
107 NETLOGON_NEG_CHANGELOG_BDC |
108 NETLOGON_NEG_FULL_SYNC_REPL |
109 NETLOGON_NEG_MULTIPLE_SIDS |
111 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
112 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
113 NETLOGON_NEG_GENERIC_PASSTHROUGH |
114 NETLOGON_NEG_CONCURRENT_RPC |
115 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
116 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
117 NETLOGON_NEG_STRONG_KEYS |
118 NETLOGON_NEG_TRANSITIVE_TRUSTS |
119 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
120 NETLOGON_NEG_PASSWORD_SET2 |
121 NETLOGON_NEG_GETDOMAININFO |
122 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
123 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
124 NETLOGON_NEG_RODC_PASSTHROUGH |
125 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
126 NETLOGON_NEG_AUTHENTICATED_RPC;
129 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
130 return NT_STATUS_ACCESS_DENIED;
133 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
134 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
135 if (sam_ctx == NULL) {
136 return NT_STATUS_INVALID_SYSTEM_SERVICE;
139 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
140 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
141 const char *flatname;
142 if (!encoded_account) {
143 return NT_STATUS_NO_MEMORY;
146 /* Kill the trailing dot */
147 if (encoded_account[strlen(encoded_account)-1] == '.') {
148 encoded_account[strlen(encoded_account)-1] = '\0';
151 /* pull the user attributes */
152 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
154 "(&(trustPartner=%s)(objectclass=trustedDomain))",
157 if (num_records == 0) {
158 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
160 return NT_STATUS_ACCESS_DENIED;
163 if (num_records > 1) {
164 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
165 return NT_STATUS_INTERNAL_DB_CORRUPTION;
168 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
170 /* No flatname for this trust - we can't proceed */
171 return NT_STATUS_ACCESS_DENIED;
173 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
176 return NT_STATUS_NO_MEMORY;
180 account_name = r->in.account_name;
183 /* pull the user attributes */
184 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
185 "(&(sAMAccountName=%s)(objectclass=user))",
186 ldb_binary_encode_string(mem_ctx, account_name));
188 if (num_records == 0) {
189 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
190 r->in.account_name));
191 return NT_STATUS_ACCESS_DENIED;
194 if (num_records > 1) {
195 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
196 return NT_STATUS_INTERNAL_DB_CORRUPTION;
199 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
201 if (user_account_control & UF_ACCOUNTDISABLE) {
202 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
203 return NT_STATUS_ACCESS_DENIED;
206 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
207 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
208 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
209 return NT_STATUS_ACCESS_DENIED;
211 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
212 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
213 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
214 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
216 return NT_STATUS_ACCESS_DENIED;
218 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
219 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
220 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
221 return NT_STATUS_ACCESS_DENIED;
223 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
224 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
225 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
226 return NT_STATUS_ACCESS_DENIED;
229 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
230 r->in.secure_channel_type));
231 return NT_STATUS_ACCESS_DENIED;
234 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
237 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
238 if (mach_pwd == NULL) {
239 return NT_STATUS_ACCESS_DENIED;
242 creds = netlogon_creds_server_init(mem_ctx,
245 r->in.secure_channel_type,
246 &pipe_state->client_challenge,
247 &pipe_state->server_challenge,
250 r->out.return_credentials,
251 *r->in.negotiate_flags);
254 return NT_STATUS_ACCESS_DENIED;
257 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
259 nt_status = schannel_save_creds_state(mem_ctx,
260 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
266 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
267 struct netr_ServerAuthenticate *r)
269 struct netr_ServerAuthenticate3 a;
272 * negotiate_flags is used as an [in] parameter
273 * so it need to be initialised.
275 * (I think ... = 0; seems wrong here --metze)
277 uint32_t negotiate_flags_in = 0;
278 uint32_t negotiate_flags_out = 0;
280 a.in.server_name = r->in.server_name;
281 a.in.account_name = r->in.account_name;
282 a.in.secure_channel_type = r->in.secure_channel_type;
283 a.in.computer_name = r->in.computer_name;
284 a.in.credentials = r->in.credentials;
285 a.in.negotiate_flags = &negotiate_flags_in;
287 a.out.return_credentials = r->out.return_credentials;
289 a.out.negotiate_flags = &negotiate_flags_out;
291 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
294 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
295 struct netr_ServerAuthenticate2 *r)
297 struct netr_ServerAuthenticate3 r3;
300 r3.in.server_name = r->in.server_name;
301 r3.in.account_name = r->in.account_name;
302 r3.in.secure_channel_type = r->in.secure_channel_type;
303 r3.in.computer_name = r->in.computer_name;
304 r3.in.credentials = r->in.credentials;
305 r3.out.return_credentials = r->out.return_credentials;
306 r3.in.negotiate_flags = r->in.negotiate_flags;
307 r3.out.negotiate_flags = r->out.negotiate_flags;
310 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
314 * NOTE: The following functions are nearly identical to the ones available in
315 * source3/rpc_server/srv_nelog_nt.c
316 * The reason we keep 2 copies is that they use different structures to
317 * represent the auth_info and the decrpc pipes.
321 * If schannel is required for this call test that it actually is available.
323 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
324 const char *computer_name,
325 bool integrity, bool privacy)
328 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
329 if (!privacy && !integrity) {
333 if ((!privacy && integrity) &&
334 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
338 if ((privacy || integrity) &&
339 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
344 /* test didn't pass */
345 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
348 return NT_STATUS_ACCESS_DENIED;
351 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
353 const char *computer_name,
354 struct netr_Authenticator *received_authenticator,
355 struct netr_Authenticator *return_authenticator,
356 struct netlogon_creds_CredentialState **creds_out)
359 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
360 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
362 if (schannel_global_required) {
363 nt_status = schannel_check_required(auth_info,
366 if (!NT_STATUS_IS_OK(nt_status)) {
371 nt_status = schannel_check_creds_state(mem_ctx,
372 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
374 received_authenticator,
375 return_authenticator,
381 Change the machine account password for the currently connected
382 client. Supplies only the NT#.
385 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
386 struct netr_ServerPasswordSet *r)
388 struct netlogon_creds_CredentialState *creds;
389 struct ldb_context *sam_ctx;
390 const char * const attrs[] = { "unicodePwd", NULL };
391 struct ldb_message **res;
392 struct samr_Password *oldNtHash;
396 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
399 r->in.credential, r->out.return_authenticator,
401 NT_STATUS_NOT_OK_RETURN(nt_status);
403 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);
404 if (sam_ctx == NULL) {
405 return NT_STATUS_INVALID_SYSTEM_SERVICE;
408 netlogon_creds_des_decrypt(creds, r->in.new_password);
410 /* fetch the old password hashes (the NT hash has to exist) */
412 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
413 "(&(objectClass=user)(objectSid=%s))",
414 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
416 return NT_STATUS_WRONG_PASSWORD;
419 nt_status = samdb_result_passwords(mem_ctx,
420 dce_call->conn->dce_ctx->lp_ctx,
421 res[0], NULL, &oldNtHash);
422 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
423 return NT_STATUS_WRONG_PASSWORD;
426 /* Using the sid for the account as the key, set the password */
427 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
429 NULL, /* Don't have plaintext */
430 NULL, r->in.new_password,
431 NULL, oldNtHash, /* Password change */
437 Change the machine account password for the currently connected
438 client. Supplies new plaintext.
440 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
441 struct netr_ServerPasswordSet2 *r)
443 struct netlogon_creds_CredentialState *creds;
444 struct ldb_context *sam_ctx;
445 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
446 struct ldb_message **res;
447 struct samr_Password *oldLmHash, *oldNtHash;
449 DATA_BLOB new_password;
452 struct samr_CryptPassword password_buf;
454 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
457 r->in.credential, r->out.return_authenticator,
459 NT_STATUS_NOT_OK_RETURN(nt_status);
461 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);
462 if (sam_ctx == NULL) {
463 return NT_STATUS_INVALID_SYSTEM_SERVICE;
466 memcpy(password_buf.data, r->in.new_password->data, 512);
467 SIVAL(password_buf.data, 512, r->in.new_password->length);
468 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
470 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
471 DEBUG(3,("samr: failed to decode password buffer\n"));
472 return NT_STATUS_WRONG_PASSWORD;
475 /* fetch the old password hashes (at least one of both has to exist) */
477 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
478 "(&(objectClass=user)(objectSid=%s))",
479 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
481 return NT_STATUS_WRONG_PASSWORD;
484 nt_status = samdb_result_passwords(mem_ctx,
485 dce_call->conn->dce_ctx->lp_ctx,
486 res[0], &oldLmHash, &oldNtHash);
487 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
488 return NT_STATUS_WRONG_PASSWORD;
491 /* Using the sid for the account as the key, set the password */
492 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
494 &new_password, /* we have plaintext */
496 oldLmHash, oldNtHash, /* Password change */
505 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
506 struct netr_LogonUasLogon *r)
508 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
515 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
516 struct netr_LogonUasLogoff *r)
518 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
523 netr_LogonSamLogon_base
525 This version of the function allows other wrappers to say 'do not check the credentials'
527 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
529 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
530 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
532 struct auth_context *auth_context;
533 struct auth_usersupplied_info *user_info;
534 struct auth_serversupplied_info *server_info;
536 static const char zeros[16];
537 struct netr_SamBaseInfo *sam;
538 struct netr_SamInfo2 *sam2;
539 struct netr_SamInfo3 *sam3;
540 struct netr_SamInfo6 *sam6;
542 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
543 NT_STATUS_HAVE_NO_MEMORY(user_info);
545 switch (r->in.logon_level) {
546 case NetlogonInteractiveInformation:
547 case NetlogonServiceInformation:
548 case NetlogonInteractiveTransitiveInformation:
549 case NetlogonServiceTransitiveInformation:
550 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
551 netlogon_creds_arcfour_crypt(creds,
552 r->in.logon->password->lmpassword.hash,
553 sizeof(r->in.logon->password->lmpassword.hash));
554 netlogon_creds_arcfour_crypt(creds,
555 r->in.logon->password->ntpassword.hash,
556 sizeof(r->in.logon->password->ntpassword.hash));
558 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
559 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
562 /* TODO: we need to deny anonymous access here */
563 nt_status = auth_context_create(mem_ctx,
564 dce_call->event_ctx, dce_call->msg_ctx,
565 dce_call->conn->dce_ctx->lp_ctx,
567 NT_STATUS_NOT_OK_RETURN(nt_status);
569 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
570 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
571 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
572 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
574 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
575 user_info->password_state = AUTH_PASSWORD_HASH;
577 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
578 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
579 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
581 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
582 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
583 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
586 case NetlogonNetworkInformation:
587 case NetlogonNetworkTransitiveInformation:
589 /* TODO: we need to deny anonymous access here */
590 nt_status = auth_context_create(mem_ctx,
591 dce_call->event_ctx, dce_call->msg_ctx,
592 dce_call->conn->dce_ctx->lp_ctx,
594 NT_STATUS_NOT_OK_RETURN(nt_status);
596 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
597 NT_STATUS_NOT_OK_RETURN(nt_status);
599 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
600 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
601 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
602 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
604 user_info->password_state = AUTH_PASSWORD_RESPONSE;
605 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
606 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
611 case NetlogonGenericInformation:
613 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
614 netlogon_creds_arcfour_crypt(creds,
615 r->in.logon->generic->data, r->in.logon->generic->length);
617 /* Using DES to verify kerberos tickets makes no sense */
618 return NT_STATUS_INVALID_PARAMETER;
621 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
623 struct dcerpc_binding_handle *irpc_handle;
624 struct kdc_check_generic_kerberos check;
625 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
626 NT_STATUS_HAVE_NO_MEMORY(generic);
627 *r->out.authoritative = 1;
629 /* TODO: Describe and deal with these flags */
632 r->out.validation->generic = generic;
634 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
638 if (irpc_handle == NULL) {
639 return NT_STATUS_NO_LOGON_SERVERS;
642 check.in.generic_request =
643 data_blob_const(r->in.logon->generic->data,
644 r->in.logon->generic->length);
646 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
649 if (!NT_STATUS_IS_OK(status)) {
652 generic->length = check.out.generic_reply.length;
653 generic->data = check.out.generic_reply.data;
657 /* Until we get an implemetnation of these other packages */
658 return NT_STATUS_INVALID_PARAMETER;
661 return NT_STATUS_INVALID_PARAMETER;
664 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
665 NT_STATUS_NOT_OK_RETURN(nt_status);
667 switch (r->in.validation_level) {
669 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
670 NT_STATUS_NOT_OK_RETURN(nt_status);
672 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
673 NT_STATUS_HAVE_NO_MEMORY(sam2);
676 /* And put into the talloc tree */
677 talloc_steal(sam2, sam);
678 r->out.validation->sam2 = sam2;
684 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
687 NT_STATUS_NOT_OK_RETURN(nt_status);
689 r->out.validation->sam3 = sam3;
695 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
698 NT_STATUS_NOT_OK_RETURN(nt_status);
700 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
701 NT_STATUS_HAVE_NO_MEMORY(sam6);
702 sam6->base = sam3->base;
704 sam6->sidcount = sam3->sidcount;
705 sam6->sids = sam3->sids;
707 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
708 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
709 sam->account_name.string, sam6->dns_domainname.string);
710 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
711 /* And put into the talloc tree */
712 talloc_steal(sam6, sam3);
714 r->out.validation->sam6 = sam6;
721 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
722 /* It appears that level 6 is not individually encrypted */
723 if ((r->in.validation_level != 6) &&
724 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
725 /* This key is sent unencrypted without the ARCFOUR flag set */
726 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
727 netlogon_creds_arcfour_crypt(creds,
729 sizeof(sam->key.key));
733 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
734 /* It appears that level 6 is not individually encrypted */
735 if ((r->in.validation_level != 6) &&
736 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
737 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
738 netlogon_creds_arcfour_crypt(creds,
740 sizeof(sam->LMSessKey.key));
742 netlogon_creds_des_encrypt_LMKey(creds,
747 *r->out.authoritative = 1;
749 /* TODO: Describe and deal with these flags */
755 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
756 struct netr_LogonSamLogonEx *r)
759 struct netlogon_creds_CredentialState *creds;
761 nt_status = schannel_get_creds_state(mem_ctx,
762 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
763 r->in.computer_name, &creds);
764 if (!NT_STATUS_IS_OK(nt_status)) {
768 if (!dce_call->conn->auth_state.auth_info ||
769 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
770 return NT_STATUS_ACCESS_DENIED;
772 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
776 netr_LogonSamLogonWithFlags
779 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
780 struct netr_LogonSamLogonWithFlags *r)
783 struct netlogon_creds_CredentialState *creds;
784 struct netr_LogonSamLogonEx r2;
786 struct netr_Authenticator *return_authenticator;
788 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
789 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
791 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
794 r->in.credential, return_authenticator,
796 NT_STATUS_NOT_OK_RETURN(nt_status);
800 r2.in.server_name = r->in.server_name;
801 r2.in.computer_name = r->in.computer_name;
802 r2.in.logon_level = r->in.logon_level;
803 r2.in.logon = r->in.logon;
804 r2.in.validation_level = r->in.validation_level;
805 r2.in.flags = r->in.flags;
806 r2.out.validation = r->out.validation;
807 r2.out.authoritative = r->out.authoritative;
808 r2.out.flags = r->out.flags;
810 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
812 r->out.return_authenticator = return_authenticator;
820 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
821 struct netr_LogonSamLogon *r)
823 struct netr_LogonSamLogonWithFlags r2;
829 r2.in.server_name = r->in.server_name;
830 r2.in.computer_name = r->in.computer_name;
831 r2.in.credential = r->in.credential;
832 r2.in.return_authenticator = r->in.return_authenticator;
833 r2.in.logon_level = r->in.logon_level;
834 r2.in.logon = r->in.logon;
835 r2.in.validation_level = r->in.validation_level;
836 r2.in.flags = &flags;
837 r2.out.validation = r->out.validation;
838 r2.out.authoritative = r->out.authoritative;
839 r2.out.flags = &flags;
841 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
843 r->out.return_authenticator = r2.out.return_authenticator;
852 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
853 struct netr_LogonSamLogoff *r)
855 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
863 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
864 struct netr_DatabaseDeltas *r)
866 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
873 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
874 struct netr_DatabaseSync2 *r)
876 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
877 return NT_STATUS_NOT_IMPLEMENTED;
884 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
885 struct netr_DatabaseSync *r)
887 struct netr_DatabaseSync2 r2;
892 r2.in.logon_server = r->in.logon_server;
893 r2.in.computername = r->in.computername;
894 r2.in.credential = r->in.credential;
895 r2.in.database_id = r->in.database_id;
896 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
897 r2.in.sync_context = r->in.sync_context;
898 r2.out.sync_context = r->out.sync_context;
899 r2.out.delta_enum_array = r->out.delta_enum_array;
900 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
902 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
911 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
912 struct netr_AccountDeltas *r)
914 /* w2k3 returns "NOT IMPLEMENTED" for this call */
915 return NT_STATUS_NOT_IMPLEMENTED;
922 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
923 struct netr_AccountSync *r)
925 /* w2k3 returns "NOT IMPLEMENTED" for this call */
926 return NT_STATUS_NOT_IMPLEMENTED;
933 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
934 struct netr_GetDcName *r)
936 const char * const attrs[] = { NULL };
937 struct ldb_context *sam_ctx;
938 struct ldb_message **res;
939 struct ldb_dn *domain_dn;
944 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
945 * that the domainname needs to be a valid netbios domain
946 * name, if it is not NULL.
948 if (r->in.domainname) {
949 const char *dot = strchr(r->in.domainname, '.');
950 size_t len = strlen(r->in.domainname);
952 if (dot || len > 15) {
953 return WERR_DCNOTFOUND;
957 * TODO: Should we also varify that only valid
958 * netbios name characters are used?
962 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
963 dce_call->conn->dce_ctx->lp_ctx,
964 dce_call->conn->auth_state.session_info, 0);
965 if (sam_ctx == NULL) {
966 return WERR_DS_UNAVAILABLE;
969 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
971 if (domain_dn == NULL) {
972 return WERR_DS_UNAVAILABLE;
975 ret = gendb_search_dn(sam_ctx, mem_ctx,
976 domain_dn, &res, attrs);
978 return WERR_NO_SUCH_DOMAIN;
981 /* TODO: - return real IP address
982 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
984 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
985 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
986 W_ERROR_HAVE_NO_MEMORY(dcname);
988 *r->out.dcname = dcname;
996 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
997 struct netr_LogonControl2Ex *r)
999 return WERR_NOT_SUPPORTED;
1006 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1007 struct netr_LogonControl *r)
1009 struct netr_LogonControl2Ex r2;
1012 if (r->in.level == 0x00000001) {
1015 r2.in.logon_server = r->in.logon_server;
1016 r2.in.function_code = r->in.function_code;
1017 r2.in.level = r->in.level;
1019 r2.out.query = r->out.query;
1021 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1022 } else if (r->in.level == 0x00000002) {
1023 werr = WERR_NOT_SUPPORTED;
1025 werr = WERR_UNKNOWN_LEVEL;
1035 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1036 struct netr_LogonControl2 *r)
1038 struct netr_LogonControl2Ex r2;
1043 r2.in.logon_server = r->in.logon_server;
1044 r2.in.function_code = r->in.function_code;
1045 r2.in.level = r->in.level;
1046 r2.in.data = r->in.data;
1047 r2.out.query = r->out.query;
1049 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1054 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1055 struct ldb_context *sam_ctx,
1056 struct netr_DomainTrustList *trusts,
1057 uint32_t trust_flags);
1062 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1063 struct netr_GetAnyDCName *r)
1065 struct netr_DomainTrustList *trusts;
1066 struct ldb_context *sam_ctx;
1067 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1071 *r->out.dcname = NULL;
1073 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1074 /* if the domainname parameter wasn't set assume our domain */
1075 r->in.domainname = lpcfg_workgroup(lp_ctx);
1078 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1079 dce_call->conn->auth_state.session_info, 0);
1080 if (sam_ctx == NULL) {
1081 return WERR_DS_UNAVAILABLE;
1084 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1085 /* well we asked for a DC of our own domain */
1086 if (samdb_is_pdc(sam_ctx)) {
1087 /* we are the PDC of the specified domain */
1088 return WERR_NO_SUCH_DOMAIN;
1091 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1092 lpcfg_netbios_name(lp_ctx));
1093 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1098 /* Okay, now we have to consider the trusted domains */
1100 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1101 W_ERROR_HAVE_NO_MEMORY(trusts);
1105 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1106 NETR_TRUST_FLAG_INBOUND
1107 | NETR_TRUST_FLAG_OUTBOUND);
1108 W_ERROR_NOT_OK_RETURN(werr);
1110 for (i = 0; i < trusts->count; i++) {
1111 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1112 /* FIXME: Here we need to find a DC for the specified
1113 * trusted domain. */
1115 /* return WERR_OK; */
1116 return WERR_NO_SUCH_DOMAIN;
1120 return WERR_NO_SUCH_DOMAIN;
1127 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1128 struct netr_DatabaseRedo *r)
1130 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1135 netr_NetrEnumerateTrustedDomains
1137 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1138 struct netr_NetrEnumerateTrustedDomains *r)
1140 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1145 netr_LogonGetCapabilities
1147 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1148 struct netr_LogonGetCapabilities *r)
1150 /* we don't support AES yet */
1151 return NT_STATUS_NOT_IMPLEMENTED;
1156 netr_NETRLOGONSETSERVICEBITS
1158 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1159 struct netr_NETRLOGONSETSERVICEBITS *r)
1161 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1166 netr_LogonGetTrustRid
1168 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1169 struct netr_LogonGetTrustRid *r)
1171 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1176 netr_NETRLOGONCOMPUTESERVERDIGEST
1178 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1179 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1181 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1186 netr_NETRLOGONCOMPUTECLIENTDIGEST
1188 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1189 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1191 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1199 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1200 struct netr_DsRGetSiteName *r)
1202 struct ldb_context *sam_ctx;
1203 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1205 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1206 dce_call->conn->auth_state.session_info, 0);
1207 if (sam_ctx == NULL) {
1208 return WERR_DS_UNAVAILABLE;
1211 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1212 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1219 fill in a netr_OneDomainInfo from a ldb search result
1221 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1222 struct loadparm_context *lp_ctx,
1223 struct ldb_context *sam_ctx,
1224 struct ldb_message *res,
1225 struct netr_OneDomainInfo *info,
1226 bool is_local, bool is_trust_list)
1230 if (is_trust_list) {
1231 /* w2k8 only fills this on trusted domains */
1232 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1233 info->trust_extension.length = 16;
1234 info->trust_extension.info->flags =
1235 NETR_TRUST_FLAG_TREEROOT |
1236 NETR_TRUST_FLAG_IN_FOREST |
1237 NETR_TRUST_FLAG_PRIMARY |
1238 NETR_TRUST_FLAG_NATIVE;
1240 info->trust_extension.info->parent_index = 0; /* should be index into array
1242 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1243 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1246 if (is_trust_list) {
1247 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1248 info->dns_forestname.string = NULL;
1250 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1251 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1252 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1253 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1257 info->domainname.string = lpcfg_workgroup(lp_ctx);
1258 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1259 info->domain_guid = samdb_result_guid(res, "objectGUID");
1260 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1262 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1263 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1264 info->domain_guid = samdb_result_guid(res, "objectGUID");
1265 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1267 if (!is_trust_list) {
1268 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1271 return NT_STATUS_OK;
1275 netr_LogonGetDomainInfo
1276 this is called as part of the ADS domain logon procedure.
1278 It has an important role in convaying details about the client, such
1279 as Operating System, Version, Service Pack etc.
1281 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1282 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1284 struct netlogon_creds_CredentialState *creds;
1285 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1286 "securityIdentifier", "trustPartner", NULL };
1287 const char * const attrs2[] = { "dNSHostName",
1288 "msDS-SupportedEncryptionTypes", NULL };
1289 const char *temp_str, *temp_str2;
1290 const char *old_dns_hostname;
1291 struct ldb_context *sam_ctx;
1292 struct ldb_message **res1, **res2, **res3, *new_msg;
1293 struct ldb_dn *workstation_dn;
1294 struct netr_DomainInformation *domain_info;
1295 struct netr_LsaPolicyInformation *lsa_policy_info;
1296 struct netr_OsVersionInfoEx *os_version;
1297 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1298 bool update_dns_hostname = true;
1302 status = dcesrv_netr_creds_server_step_check(dce_call,
1304 r->in.computer_name,
1306 r->out.return_authenticator,
1308 if (!NT_STATUS_IS_OK(status)) {
1309 DEBUG(0,(__location__ " Bad credentials - error\n"));
1311 NT_STATUS_NOT_OK_RETURN(status);
1313 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1314 dce_call->conn->dce_ctx->lp_ctx,
1315 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1316 if (sam_ctx == NULL) {
1317 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1320 switch (r->in.level) {
1321 case 1: /* Domain information */
1323 if (r->in.query->workstation_info == NULL) {
1324 return NT_STATUS_INVALID_PARAMETER;
1328 * Checks that the computer name parameter without possible "$"
1329 * matches as prefix with the DNS hostname in the workstation
1332 temp_str = talloc_strndup(mem_ctx,
1333 r->in.computer_name,
1334 strcspn(r->in.computer_name, "$"));
1335 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1336 temp_str2 = talloc_strndup(mem_ctx,
1337 r->in.query->workstation_info->dns_hostname,
1338 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1339 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1340 if (strcasecmp(temp_str, temp_str2) != 0) {
1341 update_dns_hostname = false;
1344 /* Prepare the workstation DN */
1345 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1346 dom_sid_string(mem_ctx, creds->sid));
1347 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1349 /* Lookup for attributes in workstation object */
1350 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1353 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1356 /* Gets the old DNS hostname */
1357 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0], "dNSHostName",
1361 * Updates the DNS hostname when the client wishes that the
1362 * server should handle this for him
1363 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1364 * obviously only checked when we do already have a
1366 * See MS-NRPC section 3.5.4.3.9
1368 if ((old_dns_hostname != NULL) &&
1369 (r->in.query->workstation_info->workstation_flags
1370 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1371 update_dns_hostname = false;
1374 /* Gets host informations and put them into our directory */
1376 new_msg = ldb_msg_new(mem_ctx);
1377 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1379 new_msg->dn = workstation_dn;
1381 /* Sets the OS name */
1382 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1384 r->in.query->workstation_info->os_name.string);
1387 * Sets informations from "os_version". On an empty structure
1388 * the values are cleared.
1390 if (r->in.query->workstation_info->os_version.os != NULL) {
1391 os_version = &r->in.query->workstation_info->os_version.os->os;
1393 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1394 "operatingSystemServicePack",
1395 os_version->CSDVersion);
1397 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1398 "operatingSystemVersion",
1399 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1400 os_version->MajorVersion,
1401 os_version->MinorVersion,
1402 os_version->BuildNumber
1406 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1407 "operatingSystemServicePack");
1409 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1410 "operatingSystemVersion");
1414 * If the boolean "update_dns_hostname" remained true, then we
1415 * are fine to start the update.
1417 if (update_dns_hostname) {
1418 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1420 r->in.query->workstation_info->dns_hostname);
1422 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1423 "servicePrincipalName",
1424 talloc_asprintf(mem_ctx, "HOST/%s",
1425 r->in.computer_name)
1427 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1428 "servicePrincipalName",
1429 talloc_asprintf(mem_ctx, "HOST/%s",
1430 r->in.query->workstation_info->dns_hostname)
1434 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1435 DEBUG(3,("Impossible to update samdb: %s\n",
1436 ldb_errstring(sam_ctx)));
1439 talloc_free(new_msg);
1441 /* Writes back the domain information */
1443 /* We need to do two searches. The first will pull our primary
1444 domain and the second will pull any trusted domains. Our
1445 primary domain is also a "trusted" domain, so we need to
1446 put the primary domain into the lists of returned trusts as
1448 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1451 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1454 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1455 "(objectClass=trustedDomain)");
1457 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1460 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1461 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1463 ZERO_STRUCTP(domain_info);
1465 /* Informations about the local and trusted domains */
1467 status = fill_one_domain_info(mem_ctx,
1468 dce_call->conn->dce_ctx->lp_ctx,
1469 sam_ctx, res2[0], &domain_info->primary_domain,
1471 NT_STATUS_NOT_OK_RETURN(status);
1473 domain_info->trusted_domain_count = ret3 + 1;
1474 domain_info->trusted_domains = talloc_array(mem_ctx,
1475 struct netr_OneDomainInfo,
1476 domain_info->trusted_domain_count);
1477 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1479 for (i=0;i<ret3;i++) {
1480 status = fill_one_domain_info(mem_ctx,
1481 dce_call->conn->dce_ctx->lp_ctx,
1483 &domain_info->trusted_domains[i],
1485 NT_STATUS_NOT_OK_RETURN(status);
1488 status = fill_one_domain_info(mem_ctx,
1489 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1490 &domain_info->trusted_domains[i], true, true);
1491 NT_STATUS_NOT_OK_RETURN(status);
1493 /* Sets the supported encryption types */
1494 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1495 "msDS-SupportedEncryptionTypes",
1496 default_supported_enc_types);
1498 /* Other host domain informations */
1500 lsa_policy_info = talloc(mem_ctx,
1501 struct netr_LsaPolicyInformation);
1502 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1503 ZERO_STRUCTP(lsa_policy_info);
1505 domain_info->lsa_policy = *lsa_policy_info;
1507 /* The DNS hostname is only returned back when there is a chance
1509 if ((r->in.query->workstation_info->workstation_flags
1510 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1511 domain_info->dns_hostname.string = old_dns_hostname;
1513 domain_info->dns_hostname.string = NULL;
1516 domain_info->workstation_flags =
1517 r->in.query->workstation_info->workstation_flags;
1519 r->out.info->domain_info = domain_info;
1521 case 2: /* LSA policy information - not used at the moment */
1522 lsa_policy_info = talloc(mem_ctx,
1523 struct netr_LsaPolicyInformation);
1524 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1525 ZERO_STRUCTP(lsa_policy_info);
1527 r->out.info->lsa_policy_info = lsa_policy_info;
1530 return NT_STATUS_INVALID_LEVEL;
1534 return NT_STATUS_OK;
1540 netr_ServerPasswordGet
1542 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1543 struct netr_ServerPasswordGet *r)
1545 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1550 netr_NETRLOGONSENDTOSAM
1552 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1553 struct netr_NETRLOGONSENDTOSAM *r)
1555 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1560 netr_DsRGetDCNameEx2
1562 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1563 TALLOC_CTX *mem_ctx,
1564 struct netr_DsRGetDCNameEx2 *r)
1566 struct ldb_context *sam_ctx;
1567 struct netr_DsRGetDCNameInfo *info;
1568 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1569 const struct tsocket_address *remote_address;
1571 const char *server_site_name;
1573 struct netlogon_samlogon_response response;
1576 ZERO_STRUCTP(r->out.info);
1578 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1579 dce_call->conn->auth_state.session_info, 0);
1580 if (sam_ctx == NULL) {
1581 return WERR_DS_UNAVAILABLE;
1584 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1585 if (tsocket_address_is_inet(remote_address, "ip")) {
1586 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1587 W_ERROR_HAVE_NO_MEMORY(addr);
1590 /* "server_unc" is ignored by w2k3 */
1592 /* Proof server site parameter "site_name" if it was specified */
1593 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1594 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1595 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1596 server_site_name) != 0)) {
1597 return WERR_NO_SUCH_DOMAIN;
1600 /* TODO: the flags are ignored for now */
1602 guid_str = r->in.domain_guid != NULL ?
1603 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1605 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1609 r->in.client_account,
1611 NETLOGON_NT_VERSION_5EX_WITH_IP,
1612 lp_ctx, &response, true);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 return ntstatus_to_werror(status);
1617 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1618 W_ERROR_HAVE_NO_MEMORY(info);
1619 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1620 response.data.nt5_ex.pdc_dns_name);
1621 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1622 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1623 response.data.nt5_ex.sockaddr.pdc_ip);
1624 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1625 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1626 info->domain_guid = response.data.nt5_ex.domain_uuid;
1627 info->domain_name = response.data.nt5_ex.dns_domain;
1628 info->forest_name = response.data.nt5_ex.forest;
1629 info->dc_flags = response.data.nt5_ex.server_type;
1630 info->dc_site_name = response.data.nt5_ex.server_site;
1631 info->client_site_name = response.data.nt5_ex.client_site;
1633 *r->out.info = info;
1641 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1642 struct netr_DsRGetDCNameEx *r)
1644 struct netr_DsRGetDCNameEx2 r2;
1649 r2.in.server_unc = r->in.server_unc;
1650 r2.in.client_account = NULL;
1652 r2.in.domain_guid = r->in.domain_guid;
1653 r2.in.domain_name = r->in.domain_name;
1654 r2.in.site_name = r->in.site_name;
1655 r2.in.flags = r->in.flags;
1656 r2.out.info = r->out.info;
1658 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1666 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1667 struct netr_DsRGetDCName *r)
1669 struct netr_DsRGetDCNameEx2 r2;
1674 r2.in.server_unc = r->in.server_unc;
1675 r2.in.client_account = NULL;
1677 r2.in.domain_name = r->in.domain_name;
1678 r2.in.domain_guid = r->in.domain_guid;
1680 r2.in.site_name = NULL; /* should fill in from site GUID */
1681 r2.in.flags = r->in.flags;
1682 r2.out.info = r->out.info;
1684 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1689 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1691 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1692 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1694 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1699 netr_NetrEnumerateTrustedDomainsEx
1701 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1702 struct netr_NetrEnumerateTrustedDomainsEx *r)
1704 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1709 netr_DsRAddressToSitenamesExW
1711 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1712 struct netr_DsRAddressToSitenamesExW *r)
1714 struct ldb_context *sam_ctx;
1715 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1716 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1717 sa_family_t sin_family;
1718 struct sockaddr_in *addr;
1720 struct sockaddr_in6 *addr6;
1721 char addr_str[INET6_ADDRSTRLEN];
1723 char addr_str[INET_ADDRSTRLEN];
1729 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1730 dce_call->conn->auth_state.session_info, 0);
1731 if (sam_ctx == NULL) {
1732 return WERR_DS_UNAVAILABLE;
1735 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1736 W_ERROR_HAVE_NO_MEMORY(ctr);
1740 ctr->count = r->in.count;
1741 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1742 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1743 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1744 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1746 for (i=0; i<ctr->count; i++) {
1747 ctr->sitename[i].string = NULL;
1748 ctr->subnetname[i].string = NULL;
1750 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1753 /* The first two byte of the buffer are reserved for the
1754 * "sin_family" but for now only the first one is used. */
1755 sin_family = r->in.addresses[i].buffer[0];
1757 switch (sin_family) {
1759 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1762 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1763 res = inet_ntop(AF_INET, &addr->sin_addr,
1764 addr_str, sizeof(addr_str));
1768 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1771 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1772 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1773 addr_str, sizeof(addr_str));
1784 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1788 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1789 ctr->subnetname[i].string = subnet_name;
1797 netr_DsRAddressToSitenamesW
1799 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1800 struct netr_DsRAddressToSitenamesW *r)
1802 struct netr_DsRAddressToSitenamesExW r2;
1803 struct netr_DsRAddressToSitenamesWCtr *ctr;
1809 r2.in.server_name = r->in.server_name;
1810 r2.in.count = r->in.count;
1811 r2.in.addresses = r->in.addresses;
1813 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1814 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1816 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1817 W_ERROR_HAVE_NO_MEMORY(ctr);
1821 ctr->count = r->in.count;
1822 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1823 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1825 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1827 for (i=0; i<ctr->count; i++) {
1828 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1836 netr_DsrGetDcSiteCoverageW
1838 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1839 struct netr_DsrGetDcSiteCoverageW *r)
1841 struct ldb_context *sam_ctx;
1842 struct DcSitesCtr *ctr;
1843 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1845 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1846 dce_call->conn->auth_state.session_info, 0);
1847 if (sam_ctx == NULL) {
1848 return WERR_DS_UNAVAILABLE;
1851 ctr = talloc(mem_ctx, struct DcSitesCtr);
1852 W_ERROR_HAVE_NO_MEMORY(ctr);
1856 /* For now only return our default site */
1858 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1859 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1860 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1861 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1867 #define GET_CHECK_STR(dest, mem, msg, attr) \
1870 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
1872 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1873 "without flatname\n", \
1874 ldb_dn_get_linearized(msg->dn))); \
1877 dest = talloc_strdup(mem, s); \
1878 W_ERROR_HAVE_NO_MEMORY(dest); \
1882 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1883 struct ldb_context *sam_ctx,
1884 struct netr_DomainTrustList *trusts,
1885 uint32_t trust_flags)
1887 struct ldb_dn *system_dn;
1888 struct ldb_message **dom_res = NULL;
1889 const char *trust_attrs[] = { "flatname", "trustPartner",
1890 "securityIdentifier", "trustDirection",
1891 "trustType", "trustAttributes", NULL };
1896 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1897 NETR_TRUST_FLAG_OUTBOUND))) {
1898 return WERR_INVALID_FLAGS;
1901 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1902 ldb_get_default_basedn(sam_ctx),
1903 "(&(objectClass=container)(cn=System))");
1905 return WERR_GENERAL_FAILURE;
1908 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1909 &dom_res, trust_attrs,
1910 "(objectclass=trustedDomain)");
1912 for (i = 0; i < ret; i++) {
1913 unsigned int trust_dir;
1916 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
1917 "trustDirection", 0);
1919 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1920 flags |= NETR_TRUST_FLAG_INBOUND;
1922 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1923 flags |= NETR_TRUST_FLAG_OUTBOUND;
1926 if (!(flags & trust_flags)) {
1927 /* this trust direction was not requested */
1932 trusts->array = talloc_realloc(trusts, trusts->array,
1933 struct netr_DomainTrust,
1935 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1937 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1938 dom_res[i], "flatname");
1939 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1940 dom_res[i], "trustPartner");
1942 trusts->array[n].trust_flags = flags;
1943 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1944 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1945 /* TODO: find if we have parent in the list */
1946 trusts->array[n].parent_index = 0;
1949 trusts->array[n].trust_type =
1950 ldb_msg_find_attr_as_uint(dom_res[i],
1952 trusts->array[n].trust_attributes =
1953 ldb_msg_find_attr_as_uint(dom_res[i],
1954 "trustAttributes", 0);
1956 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1957 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1958 struct dom_sid zero_sid;
1959 ZERO_STRUCT(zero_sid);
1960 trusts->array[n].sid =
1961 dom_sid_dup(trusts, &zero_sid);
1963 trusts->array[n].sid =
1964 samdb_result_dom_sid(trusts, dom_res[i],
1965 "securityIdentifier");
1967 trusts->array[n].guid = GUID_zero();
1969 trusts->count = n + 1;
1972 talloc_free(dom_res);
1977 netr_DsrEnumerateDomainTrusts
1979 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1980 TALLOC_CTX *mem_ctx,
1981 struct netr_DsrEnumerateDomainTrusts *r)
1983 struct netr_DomainTrustList *trusts;
1984 struct ldb_context *sam_ctx;
1986 struct ldb_message **dom_res;
1987 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1988 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1989 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
1993 if (r->in.trust_flags & 0xFFFFFE00) {
1994 return WERR_INVALID_FLAGS;
1997 /* TODO: turn to hard check once we are sure this is 100% correct */
1998 if (!r->in.server_name) {
1999 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2000 "But received NULL!\n", dnsdomain));
2002 p = strchr(r->in.server_name, '.');
2004 DEBUG(3, ("Invalid domain! Expected name in domain "
2005 "[%s]. But received [%s]!\n",
2006 dnsdomain, r->in.server_name));
2007 p = r->in.server_name;
2011 if (strcasecmp(p, dnsdomain)) {
2012 DEBUG(3, ("Invalid domain! Expected name in domain "
2013 "[%s]. But received [%s]!\n",
2014 dnsdomain, r->in.server_name));
2018 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2019 W_ERROR_HAVE_NO_MEMORY(trusts);
2022 r->out.trusts = trusts;
2024 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2025 dce_call->conn->auth_state.session_info, 0);
2026 if (sam_ctx == NULL) {
2027 return WERR_GENERAL_FAILURE;
2030 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2031 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2033 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2034 trusts, r->in.trust_flags);
2035 W_ERROR_NOT_OK_RETURN(werr);
2038 /* NOTE: we currently are always the root of the forest */
2039 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2040 uint32_t n = trusts->count;
2042 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2043 &dom_res, dom_attrs);
2045 return WERR_GENERAL_FAILURE;
2048 trusts->count = n + 1;
2049 trusts->array = talloc_realloc(trusts, trusts->array,
2050 struct netr_DomainTrust,
2052 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2054 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2055 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2056 trusts->array[n].trust_flags =
2057 NETR_TRUST_FLAG_NATIVE |
2058 NETR_TRUST_FLAG_TREEROOT |
2059 NETR_TRUST_FLAG_IN_FOREST |
2060 NETR_TRUST_FLAG_PRIMARY;
2061 /* we are always the root domain for now */
2062 trusts->array[n].parent_index = 0;
2063 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2064 trusts->array[n].trust_attributes = 0;
2065 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2068 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2070 talloc_free(dom_res);
2078 netr_DsrDeregisterDNSHostRecords
2080 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2081 struct netr_DsrDeregisterDNSHostRecords *r)
2083 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2088 netr_ServerTrustPasswordsGet
2090 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2091 struct netr_ServerTrustPasswordsGet *r)
2093 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2097 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2098 struct ldb_context *sam_ctx,
2099 struct loadparm_context *lp_ctx,
2100 struct lsa_ForestTrustInformation *info)
2102 struct lsa_ForestTrustDomainInfo *domain_info;
2103 struct lsa_ForestTrustRecord *e;
2104 struct ldb_message **dom_res;
2105 const char * const dom_attrs[] = { "objectSid", NULL };
2108 /* we need to provide 2 entries:
2109 * 1. the Root Forest name
2110 * 2. the Domain Information
2114 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2115 W_ERROR_HAVE_NO_MEMORY(info->entries);
2117 /* Forest root info */
2118 e = talloc(info, struct lsa_ForestTrustRecord);
2119 W_ERROR_HAVE_NO_MEMORY(e);
2122 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2123 e->time = 0; /* so far always 0 in trces. */
2124 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2126 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2128 info->entries[0] = e;
2131 e = talloc(info, struct lsa_ForestTrustRecord);
2132 W_ERROR_HAVE_NO_MEMORY(e);
2134 /* get our own domain info */
2135 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2137 return WERR_GENERAL_FAILURE;
2140 /* TODO: check if disabled and set flags accordingly */
2142 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2143 e->time = 0; /* so far always 0 in traces. */
2145 domain_info = &e->forest_trust_data.domain_info;
2146 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2148 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2149 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2151 info->entries[1] = e;
2153 talloc_free(dom_res);
2159 netr_DsRGetForestTrustInformation
2161 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2162 TALLOC_CTX *mem_ctx,
2163 struct netr_DsRGetForestTrustInformation *r)
2165 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2166 struct lsa_ForestTrustInformation *info, **info_ptr;
2167 struct ldb_context *sam_ctx;
2170 if (r->in.flags & 0xFFFFFFFE) {
2171 return WERR_INVALID_FLAGS;
2174 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2175 dce_call->conn->auth_state.session_info, 0);
2176 if (sam_ctx == NULL) {
2177 return WERR_GENERAL_FAILURE;
2180 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2181 if (!samdb_is_pdc(sam_ctx)) {
2182 return WERR_NERR_NOTPRIMARY;
2185 if (r->in.trusted_domain_name == NULL) {
2186 return WERR_INVALID_FLAGS;
2189 /* TODO: establish an schannel connection with
2190 * r->in.trusted_domain_name and perform a
2191 * netr_GetForestTrustInformation call against it */
2193 /* for now return not implementd */
2194 return WERR_CALL_NOT_IMPLEMENTED;
2197 /* TODO: check r->in.server_name is our name */
2199 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2200 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2202 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2203 W_ERROR_HAVE_NO_MEMORY(info);
2205 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2206 W_ERROR_NOT_OK_RETURN(werr);
2209 r->out.forest_trust_info = info_ptr;
2216 netr_GetForestTrustInformation
2218 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2219 TALLOC_CTX *mem_ctx,
2220 struct netr_GetForestTrustInformation *r)
2222 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2223 struct netlogon_creds_CredentialState *creds;
2224 struct lsa_ForestTrustInformation *info, **info_ptr;
2225 struct ldb_context *sam_ctx;
2229 status = dcesrv_netr_creds_server_step_check(dce_call,
2231 r->in.computer_name,
2233 r->out.return_authenticator,
2235 if (!NT_STATUS_IS_OK(status)) {
2239 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2240 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2241 return NT_STATUS_NOT_IMPLEMENTED;
2244 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2245 dce_call->conn->auth_state.session_info, 0);
2246 if (sam_ctx == NULL) {
2247 return NT_STATUS_UNSUCCESSFUL;
2250 /* TODO: check r->in.server_name is our name */
2252 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2254 return NT_STATUS_NO_MEMORY;
2256 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2258 return NT_STATUS_NO_MEMORY;
2261 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2262 if (!W_ERROR_IS_OK(werr)) {
2263 return werror_to_ntstatus(werr);
2267 r->out.forest_trust_info = info_ptr;
2269 return NT_STATUS_OK;
2274 netr_ServerGetTrustInfo
2276 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2277 struct netr_ServerGetTrustInfo *r)
2279 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2285 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2286 struct netr_Unused47 *r)
2288 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2292 struct netr_dnsupdate_RODC_state {
2293 struct dcesrv_call_state *dce_call;
2294 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2295 struct dnsupdate_RODC *r2;
2299 called when the forwarded RODC dns update request is finished
2301 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2303 struct netr_dnsupdate_RODC_state *st =
2304 tevent_req_callback_data(subreq,
2305 struct netr_dnsupdate_RODC_state);
2308 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2309 TALLOC_FREE(subreq);
2310 if (!NT_STATUS_IS_OK(status)) {
2311 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2312 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2315 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2317 status = dcesrv_reply(st->dce_call);
2318 if (!NT_STATUS_IS_OK(status)) {
2319 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2324 netr_DsrUpdateReadOnlyServerDnsRecords
2326 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2327 TALLOC_CTX *mem_ctx,
2328 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2330 struct netlogon_creds_CredentialState *creds;
2332 struct dcerpc_binding_handle *binding_handle;
2333 struct netr_dnsupdate_RODC_state *st;
2334 struct tevent_req *subreq;
2336 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2338 r->in.computer_name,
2340 r->out.return_authenticator,
2342 NT_STATUS_NOT_OK_RETURN(nt_status);
2344 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2345 return NT_STATUS_ACCESS_DENIED;
2348 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2349 NT_STATUS_HAVE_NO_MEMORY(st);
2351 st->dce_call = dce_call;
2353 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2354 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2356 st->r2->in.dom_sid = creds->sid;
2357 st->r2->in.site_name = r->in.site_name;
2358 st->r2->in.dns_ttl = r->in.dns_ttl;
2359 st->r2->in.dns_names = r->in.dns_names;
2360 st->r2->out.dns_names = r->out.dns_names;
2362 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2363 "dnsupdate", &ndr_table_irpc);
2364 if (binding_handle == NULL) {
2365 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2366 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2367 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2370 /* forward the call */
2371 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2372 binding_handle, st->r2);
2373 NT_STATUS_HAVE_NO_MEMORY(subreq);
2375 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2377 /* setup the callback */
2378 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2380 return NT_STATUS_OK;
2384 /* include the generated boilerplate */
2385 #include "librpc/gen_ndr/ndr_netlogon_s.c"