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));
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));
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));
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;
943 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
944 dce_call->conn->dce_ctx->lp_ctx,
945 dce_call->conn->auth_state.session_info);
946 if (sam_ctx == NULL) {
947 return WERR_DS_UNAVAILABLE;
950 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
952 if (domain_dn == NULL) {
953 return WERR_DS_UNAVAILABLE;
956 ret = gendb_search_dn(sam_ctx, mem_ctx,
957 domain_dn, &res, attrs);
959 return WERR_NO_SUCH_DOMAIN;
962 /* TODO: - return real IP address
963 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
965 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
966 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
967 W_ERROR_HAVE_NO_MEMORY(dcname);
969 *r->out.dcname = dcname;
977 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
978 struct netr_LogonControl2Ex *r)
980 return WERR_NOT_SUPPORTED;
987 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
988 struct netr_LogonControl *r)
990 struct netr_LogonControl2Ex r2;
993 if (r->in.level == 0x00000001) {
996 r2.in.logon_server = r->in.logon_server;
997 r2.in.function_code = r->in.function_code;
998 r2.in.level = r->in.level;
1000 r2.out.query = r->out.query;
1002 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1003 } else if (r->in.level == 0x00000002) {
1004 werr = WERR_NOT_SUPPORTED;
1006 werr = WERR_UNKNOWN_LEVEL;
1016 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1017 struct netr_LogonControl2 *r)
1019 struct netr_LogonControl2Ex r2;
1024 r2.in.logon_server = r->in.logon_server;
1025 r2.in.function_code = r->in.function_code;
1026 r2.in.level = r->in.level;
1027 r2.in.data = r->in.data;
1028 r2.out.query = r->out.query;
1030 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1035 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1036 struct ldb_context *sam_ctx,
1037 struct netr_DomainTrustList *trusts,
1038 uint32_t trust_flags);
1043 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1044 struct netr_GetAnyDCName *r)
1046 struct netr_DomainTrustList *trusts;
1047 struct ldb_context *sam_ctx;
1048 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1052 *r->out.dcname = NULL;
1054 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1055 /* if the domainname parameter wasn't set assume our domain */
1056 r->in.domainname = lpcfg_workgroup(lp_ctx);
1059 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1060 dce_call->conn->auth_state.session_info);
1061 if (sam_ctx == NULL) {
1062 return WERR_DS_UNAVAILABLE;
1065 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1066 /* well we asked for a DC of our own domain */
1067 if (samdb_is_pdc(sam_ctx)) {
1068 /* we are the PDC of the specified domain */
1069 return WERR_NO_SUCH_DOMAIN;
1072 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1073 lpcfg_netbios_name(lp_ctx));
1074 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1079 /* Okay, now we have to consider the trusted domains */
1081 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1082 W_ERROR_HAVE_NO_MEMORY(trusts);
1086 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1087 NETR_TRUST_FLAG_INBOUND
1088 | NETR_TRUST_FLAG_OUTBOUND);
1089 W_ERROR_NOT_OK_RETURN(werr);
1091 for (i = 0; i < trusts->count; i++) {
1092 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1093 /* FIXME: Here we need to find a DC for the specified
1094 * trusted domain. */
1096 /* return WERR_OK; */
1097 return WERR_NO_SUCH_DOMAIN;
1101 return WERR_NO_SUCH_DOMAIN;
1108 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1109 struct netr_DatabaseRedo *r)
1111 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1116 netr_NetrEnumerateTrustedDomains
1118 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1119 struct netr_NetrEnumerateTrustedDomains *r)
1121 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1126 netr_LogonGetCapabilities
1128 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1129 struct netr_LogonGetCapabilities *r)
1131 /* we don't support AES yet */
1132 return NT_STATUS_NOT_IMPLEMENTED;
1137 netr_NETRLOGONSETSERVICEBITS
1139 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1140 struct netr_NETRLOGONSETSERVICEBITS *r)
1142 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1147 netr_LogonGetTrustRid
1149 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150 struct netr_LogonGetTrustRid *r)
1152 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1157 netr_NETRLOGONCOMPUTESERVERDIGEST
1159 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1160 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1162 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1167 netr_NETRLOGONCOMPUTECLIENTDIGEST
1169 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1170 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1172 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1180 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1181 struct netr_DsRGetSiteName *r)
1183 struct ldb_context *sam_ctx;
1184 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1186 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1187 dce_call->conn->auth_state.session_info);
1188 if (sam_ctx == NULL) {
1189 return WERR_DS_UNAVAILABLE;
1192 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1193 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1200 fill in a netr_OneDomainInfo from a ldb search result
1202 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1203 struct loadparm_context *lp_ctx,
1204 struct ldb_context *sam_ctx,
1205 struct ldb_message *res,
1206 struct netr_OneDomainInfo *info,
1207 bool is_local, bool is_trust_list)
1211 if (is_trust_list) {
1212 /* w2k8 only fills this on trusted domains */
1213 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1214 info->trust_extension.length = 16;
1215 info->trust_extension.info->flags =
1216 NETR_TRUST_FLAG_TREEROOT |
1217 NETR_TRUST_FLAG_IN_FOREST |
1218 NETR_TRUST_FLAG_PRIMARY |
1219 NETR_TRUST_FLAG_NATIVE;
1221 info->trust_extension.info->parent_index = 0; /* should be index into array
1223 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1224 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1227 if (is_trust_list) {
1228 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1229 info->dns_forestname.string = NULL;
1231 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1232 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1233 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1234 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1238 info->domainname.string = lpcfg_workgroup(lp_ctx);
1239 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1240 info->domain_guid = samdb_result_guid(res, "objectGUID");
1241 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1243 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1244 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1245 info->domain_guid = samdb_result_guid(res, "objectGUID");
1246 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1248 if (!is_trust_list) {
1249 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1252 return NT_STATUS_OK;
1256 netr_LogonGetDomainInfo
1257 this is called as part of the ADS domain logon procedure.
1259 It has an important role in convaying details about the client, such
1260 as Operating System, Version, Service Pack etc.
1262 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1263 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1265 struct netlogon_creds_CredentialState *creds;
1266 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1267 "securityIdentifier", "trustPartner", NULL };
1268 const char * const attrs2[] = { "dNSHostName",
1269 "msDS-SupportedEncryptionTypes", NULL };
1270 const char *temp_str, *temp_str2;
1271 const char *old_dns_hostname;
1272 struct ldb_context *sam_ctx;
1273 struct ldb_message **res1, **res2, **res3, *new_msg;
1274 struct ldb_dn *workstation_dn;
1275 struct netr_DomainInformation *domain_info;
1276 struct netr_LsaPolicyInformation *lsa_policy_info;
1277 struct netr_OsVersionInfoEx *os_version;
1278 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1279 bool update_dns_hostname = true;
1283 status = dcesrv_netr_creds_server_step_check(dce_call,
1285 r->in.computer_name,
1287 r->out.return_authenticator,
1289 if (!NT_STATUS_IS_OK(status)) {
1290 DEBUG(0,(__location__ " Bad credentials - error\n"));
1292 NT_STATUS_NOT_OK_RETURN(status);
1294 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1295 dce_call->conn->dce_ctx->lp_ctx,
1296 system_session(dce_call->conn->dce_ctx->lp_ctx));
1297 if (sam_ctx == NULL) {
1298 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1301 switch (r->in.level) {
1302 case 1: /* Domain information */
1304 if (r->in.query->workstation_info == NULL) {
1305 return NT_STATUS_INVALID_PARAMETER;
1309 * Checks that the computer name parameter without possible "$"
1310 * matches as prefix with the DNS hostname in the workstation
1313 temp_str = talloc_strndup(mem_ctx,
1314 r->in.computer_name,
1315 strcspn(r->in.computer_name, "$"));
1316 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1317 temp_str2 = talloc_strndup(mem_ctx,
1318 r->in.query->workstation_info->dns_hostname,
1319 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1320 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1321 if (strcasecmp(temp_str, temp_str2) != 0) {
1322 update_dns_hostname = false;
1325 /* Prepare the workstation DN */
1326 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1327 dom_sid_string(mem_ctx, creds->sid));
1328 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1330 /* Lookup for attributes in workstation object */
1331 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1334 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1337 /* Gets the old DNS hostname */
1338 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1342 * Updates the DNS hostname when the client wishes that the
1343 * server should handle this for him
1344 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1345 * obviously only checked when we do already have a
1347 * See MS-NRPC section 3.5.4.3.9
1349 if ((old_dns_hostname != NULL) &&
1350 (r->in.query->workstation_info->workstation_flags
1351 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1352 update_dns_hostname = false;
1355 /* Gets host informations and put them into our directory */
1357 new_msg = ldb_msg_new(mem_ctx);
1358 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1360 new_msg->dn = workstation_dn;
1362 /* Sets the OS name */
1363 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1365 r->in.query->workstation_info->os_name.string);
1368 * Sets informations from "os_version". On an empty structure
1369 * the values are cleared.
1371 if (r->in.query->workstation_info->os_version.os != NULL) {
1372 os_version = &r->in.query->workstation_info->os_version.os->os;
1374 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1375 "operatingSystemServicePack",
1376 os_version->CSDVersion);
1378 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1379 "operatingSystemVersion",
1380 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1381 os_version->MajorVersion,
1382 os_version->MinorVersion,
1383 os_version->BuildNumber
1387 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1388 "operatingSystemServicePack");
1390 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1391 "operatingSystemVersion");
1395 * If the boolean "update_dns_hostname" remained true, then we
1396 * are fine to start the update.
1398 if (update_dns_hostname) {
1399 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1401 r->in.query->workstation_info->dns_hostname);
1403 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1404 "servicePrincipalName",
1405 talloc_asprintf(mem_ctx, "HOST/%s",
1406 r->in.computer_name)
1408 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1409 "servicePrincipalName",
1410 talloc_asprintf(mem_ctx, "HOST/%s",
1411 r->in.query->workstation_info->dns_hostname)
1415 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1416 DEBUG(3,("Impossible to update samdb: %s\n",
1417 ldb_errstring(sam_ctx)));
1420 talloc_free(new_msg);
1422 /* Writes back the domain information */
1424 /* We need to do two searches. The first will pull our primary
1425 domain and the second will pull any trusted domains. Our
1426 primary domain is also a "trusted" domain, so we need to
1427 put the primary domain into the lists of returned trusts as
1429 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1432 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1435 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1436 "(objectClass=trustedDomain)");
1438 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1441 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1442 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1444 ZERO_STRUCTP(domain_info);
1446 /* Informations about the local and trusted domains */
1448 status = fill_one_domain_info(mem_ctx,
1449 dce_call->conn->dce_ctx->lp_ctx,
1450 sam_ctx, res2[0], &domain_info->primary_domain,
1452 NT_STATUS_NOT_OK_RETURN(status);
1454 domain_info->trusted_domain_count = ret3 + 1;
1455 domain_info->trusted_domains = talloc_array(mem_ctx,
1456 struct netr_OneDomainInfo,
1457 domain_info->trusted_domain_count);
1458 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1460 for (i=0;i<ret3;i++) {
1461 status = fill_one_domain_info(mem_ctx,
1462 dce_call->conn->dce_ctx->lp_ctx,
1464 &domain_info->trusted_domains[i],
1466 NT_STATUS_NOT_OK_RETURN(status);
1469 status = fill_one_domain_info(mem_ctx,
1470 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1471 &domain_info->trusted_domains[i], true, true);
1472 NT_STATUS_NOT_OK_RETURN(status);
1474 /* Sets the supported encryption types */
1475 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1476 "msDS-SupportedEncryptionTypes",
1477 default_supported_enc_types);
1479 /* Other host domain informations */
1481 lsa_policy_info = talloc(mem_ctx,
1482 struct netr_LsaPolicyInformation);
1483 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1484 ZERO_STRUCTP(lsa_policy_info);
1486 domain_info->lsa_policy = *lsa_policy_info;
1488 /* The DNS hostname is only returned back when there is a chance
1490 if ((r->in.query->workstation_info->workstation_flags
1491 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1492 domain_info->dns_hostname.string = old_dns_hostname;
1494 domain_info->dns_hostname.string = NULL;
1497 domain_info->workstation_flags =
1498 r->in.query->workstation_info->workstation_flags;
1500 r->out.info->domain_info = domain_info;
1502 case 2: /* LSA policy information - not used at the moment */
1503 lsa_policy_info = talloc(mem_ctx,
1504 struct netr_LsaPolicyInformation);
1505 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1506 ZERO_STRUCTP(lsa_policy_info);
1508 r->out.info->lsa_policy_info = lsa_policy_info;
1511 return NT_STATUS_INVALID_LEVEL;
1515 return NT_STATUS_OK;
1521 netr_ServerPasswordGet
1523 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1524 struct netr_ServerPasswordGet *r)
1526 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1531 netr_NETRLOGONSENDTOSAM
1533 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1534 struct netr_NETRLOGONSENDTOSAM *r)
1536 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1541 netr_DsRGetDCNameEx2
1543 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1544 TALLOC_CTX *mem_ctx,
1545 struct netr_DsRGetDCNameEx2 *r)
1547 struct ldb_context *sam_ctx;
1548 struct netr_DsRGetDCNameInfo *info;
1549 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1550 const struct tsocket_address *remote_address;
1552 const char *server_site_name;
1554 struct netlogon_samlogon_response response;
1557 ZERO_STRUCTP(r->out.info);
1559 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1560 dce_call->conn->auth_state.session_info);
1561 if (sam_ctx == NULL) {
1562 return WERR_DS_UNAVAILABLE;
1565 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1566 if (tsocket_address_is_inet(remote_address, "ip")) {
1567 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1568 W_ERROR_HAVE_NO_MEMORY(addr);
1571 /* "server_unc" is ignored by w2k3 */
1573 /* Proof server site parameter "site_name" if it was specified */
1574 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1575 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1576 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1577 server_site_name) != 0)) {
1578 return WERR_NO_SUCH_DOMAIN;
1581 /* TODO: the flags are ignored for now */
1583 guid_str = r->in.domain_guid != NULL ?
1584 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1586 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1590 r->in.client_account,
1592 NETLOGON_NT_VERSION_5EX_WITH_IP,
1593 lp_ctx, &response, true);
1594 if (!NT_STATUS_IS_OK(status)) {
1595 return ntstatus_to_werror(status);
1598 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1599 W_ERROR_HAVE_NO_MEMORY(info);
1600 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1601 response.data.nt5_ex.pdc_dns_name);
1602 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1603 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1604 response.data.nt5_ex.sockaddr.pdc_ip);
1605 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1606 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1607 info->domain_guid = response.data.nt5_ex.domain_uuid;
1608 info->domain_name = response.data.nt5_ex.dns_domain;
1609 info->forest_name = response.data.nt5_ex.forest;
1610 info->dc_flags = response.data.nt5_ex.server_type;
1611 info->dc_site_name = response.data.nt5_ex.server_site;
1612 info->client_site_name = response.data.nt5_ex.client_site;
1614 *r->out.info = info;
1622 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1623 struct netr_DsRGetDCNameEx *r)
1625 struct netr_DsRGetDCNameEx2 r2;
1630 r2.in.server_unc = r->in.server_unc;
1631 r2.in.client_account = NULL;
1633 r2.in.domain_guid = r->in.domain_guid;
1634 r2.in.domain_name = r->in.domain_name;
1635 r2.in.site_name = r->in.site_name;
1636 r2.in.flags = r->in.flags;
1637 r2.out.info = r->out.info;
1639 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1647 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1648 struct netr_DsRGetDCName *r)
1650 struct netr_DsRGetDCNameEx2 r2;
1655 r2.in.server_unc = r->in.server_unc;
1656 r2.in.client_account = NULL;
1658 r2.in.domain_name = r->in.domain_name;
1659 r2.in.domain_guid = r->in.domain_guid;
1661 r2.in.site_name = NULL; /* should fill in from site GUID */
1662 r2.in.flags = r->in.flags;
1663 r2.out.info = r->out.info;
1665 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1670 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1672 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1673 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1675 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1680 netr_NetrEnumerateTrustedDomainsEx
1682 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1683 struct netr_NetrEnumerateTrustedDomainsEx *r)
1685 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1690 netr_DsRAddressToSitenamesExW
1692 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1693 struct netr_DsRAddressToSitenamesExW *r)
1695 struct ldb_context *sam_ctx;
1696 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1697 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1698 sa_family_t sin_family;
1699 struct sockaddr_in *addr;
1701 struct sockaddr_in6 *addr6;
1702 char addr_str[INET6_ADDRSTRLEN];
1704 char addr_str[INET_ADDRSTRLEN];
1710 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1711 dce_call->conn->auth_state.session_info);
1712 if (sam_ctx == NULL) {
1713 return WERR_DS_UNAVAILABLE;
1716 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1717 W_ERROR_HAVE_NO_MEMORY(ctr);
1721 ctr->count = r->in.count;
1722 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1723 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1724 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1725 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1727 for (i=0; i<ctr->count; i++) {
1728 ctr->sitename[i].string = NULL;
1729 ctr->subnetname[i].string = NULL;
1731 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1734 /* The first two byte of the buffer are reserved for the
1735 * "sin_family" but for now only the first one is used. */
1736 sin_family = r->in.addresses[i].buffer[0];
1738 switch (sin_family) {
1740 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1743 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1744 res = inet_ntop(AF_INET, &addr->sin_addr,
1745 addr_str, sizeof(addr_str));
1749 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1752 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1753 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1754 addr_str, sizeof(addr_str));
1765 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1769 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1770 ctr->subnetname[i].string = subnet_name;
1778 netr_DsRAddressToSitenamesW
1780 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1781 struct netr_DsRAddressToSitenamesW *r)
1783 struct netr_DsRAddressToSitenamesExW r2;
1784 struct netr_DsRAddressToSitenamesWCtr *ctr;
1790 r2.in.server_name = r->in.server_name;
1791 r2.in.count = r->in.count;
1792 r2.in.addresses = r->in.addresses;
1794 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1795 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1797 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1798 W_ERROR_HAVE_NO_MEMORY(ctr);
1802 ctr->count = r->in.count;
1803 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1804 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1806 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1808 for (i=0; i<ctr->count; i++) {
1809 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1817 netr_DsrGetDcSiteCoverageW
1819 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1820 struct netr_DsrGetDcSiteCoverageW *r)
1822 struct ldb_context *sam_ctx;
1823 struct DcSitesCtr *ctr;
1824 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1826 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1827 dce_call->conn->auth_state.session_info);
1828 if (sam_ctx == NULL) {
1829 return WERR_DS_UNAVAILABLE;
1832 ctr = talloc(mem_ctx, struct DcSitesCtr);
1833 W_ERROR_HAVE_NO_MEMORY(ctr);
1837 /* For now only return our default site */
1839 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1840 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1841 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1842 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1848 #define GET_CHECK_STR(dest, mem, msg, attr) \
1851 s = samdb_result_string(msg, attr, NULL); \
1853 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1854 "without flatname\n", \
1855 ldb_dn_get_linearized(msg->dn))); \
1858 dest = talloc_strdup(mem, s); \
1859 W_ERROR_HAVE_NO_MEMORY(dest); \
1863 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1864 struct ldb_context *sam_ctx,
1865 struct netr_DomainTrustList *trusts,
1866 uint32_t trust_flags)
1868 struct ldb_dn *system_dn;
1869 struct ldb_message **dom_res = NULL;
1870 const char *trust_attrs[] = { "flatname", "trustPartner",
1871 "securityIdentifier", "trustDirection",
1872 "trustType", "trustAttributes", NULL };
1877 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1878 NETR_TRUST_FLAG_OUTBOUND))) {
1879 return WERR_INVALID_FLAGS;
1882 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1883 ldb_get_default_basedn(sam_ctx),
1884 "(&(objectClass=container)(cn=System))");
1886 return WERR_GENERAL_FAILURE;
1889 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1890 &dom_res, trust_attrs,
1891 "(objectclass=trustedDomain)");
1893 for (i = 0; i < ret; i++) {
1894 unsigned int trust_dir;
1897 trust_dir = samdb_result_uint(dom_res[i],
1898 "trustDirection", 0);
1900 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1901 flags |= NETR_TRUST_FLAG_INBOUND;
1903 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1904 flags |= NETR_TRUST_FLAG_OUTBOUND;
1907 if (!(flags & trust_flags)) {
1908 /* this trust direction was not requested */
1913 trusts->array = talloc_realloc(trusts, trusts->array,
1914 struct netr_DomainTrust,
1916 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1918 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1919 dom_res[i], "flatname");
1920 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1921 dom_res[i], "trustPartner");
1923 trusts->array[n].trust_flags = flags;
1924 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1925 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1926 /* TODO: find if we have parent in the list */
1927 trusts->array[n].parent_index = 0;
1930 trusts->array[n].trust_type =
1931 samdb_result_uint(dom_res[i],
1933 trusts->array[n].trust_attributes =
1934 samdb_result_uint(dom_res[i],
1935 "trustAttributes", 0);
1937 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1938 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1939 struct dom_sid zero_sid;
1940 ZERO_STRUCT(zero_sid);
1941 trusts->array[n].sid =
1942 dom_sid_dup(trusts, &zero_sid);
1944 trusts->array[n].sid =
1945 samdb_result_dom_sid(trusts, dom_res[i],
1946 "securityIdentifier");
1948 trusts->array[n].guid = GUID_zero();
1950 trusts->count = n + 1;
1953 talloc_free(dom_res);
1958 netr_DsrEnumerateDomainTrusts
1960 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1961 TALLOC_CTX *mem_ctx,
1962 struct netr_DsrEnumerateDomainTrusts *r)
1964 struct netr_DomainTrustList *trusts;
1965 struct ldb_context *sam_ctx;
1967 struct ldb_message **dom_res;
1968 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1969 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1970 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
1974 if (r->in.trust_flags & 0xFFFFFE00) {
1975 return WERR_INVALID_FLAGS;
1978 /* TODO: turn to hard check once we are sure this is 100% correct */
1979 if (!r->in.server_name) {
1980 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1981 "But received NULL!\n", dnsdomain));
1983 p = strchr(r->in.server_name, '.');
1985 DEBUG(3, ("Invalid domain! Expected name in domain "
1986 "[%s]. But received [%s]!\n",
1987 dnsdomain, r->in.server_name));
1988 p = r->in.server_name;
1992 if (strcasecmp(p, dnsdomain)) {
1993 DEBUG(3, ("Invalid domain! Expected name in domain "
1994 "[%s]. But received [%s]!\n",
1995 dnsdomain, r->in.server_name));
1999 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2000 W_ERROR_HAVE_NO_MEMORY(trusts);
2003 r->out.trusts = trusts;
2005 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2006 dce_call->conn->auth_state.session_info);
2007 if (sam_ctx == NULL) {
2008 return WERR_GENERAL_FAILURE;
2011 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2012 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2014 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2015 trusts, r->in.trust_flags);
2016 W_ERROR_NOT_OK_RETURN(werr);
2019 /* NOTE: we currently are always the root of the forest */
2020 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2021 uint32_t n = trusts->count;
2023 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2024 &dom_res, dom_attrs);
2026 return WERR_GENERAL_FAILURE;
2029 trusts->count = n + 1;
2030 trusts->array = talloc_realloc(trusts, trusts->array,
2031 struct netr_DomainTrust,
2033 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2035 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2036 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2037 trusts->array[n].trust_flags =
2038 NETR_TRUST_FLAG_NATIVE |
2039 NETR_TRUST_FLAG_TREEROOT |
2040 NETR_TRUST_FLAG_IN_FOREST |
2041 NETR_TRUST_FLAG_PRIMARY;
2042 /* we are always the root domain for now */
2043 trusts->array[n].parent_index = 0;
2044 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2045 trusts->array[n].trust_attributes = 0;
2046 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2049 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2051 talloc_free(dom_res);
2059 netr_DsrDeregisterDNSHostRecords
2061 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2062 struct netr_DsrDeregisterDNSHostRecords *r)
2064 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2069 netr_ServerTrustPasswordsGet
2071 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2072 struct netr_ServerTrustPasswordsGet *r)
2074 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2078 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2079 struct ldb_context *sam_ctx,
2080 struct loadparm_context *lp_ctx,
2081 struct lsa_ForestTrustInformation *info)
2083 struct lsa_ForestTrustDomainInfo *domain_info;
2084 struct lsa_ForestTrustRecord *e;
2085 struct ldb_message **dom_res;
2086 const char * const dom_attrs[] = { "objectSid", NULL };
2089 /* we need to provide 2 entries:
2090 * 1. the Root Forest name
2091 * 2. the Domain Information
2095 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2096 W_ERROR_HAVE_NO_MEMORY(info->entries);
2098 /* Forest root info */
2099 e = talloc(info, struct lsa_ForestTrustRecord);
2100 W_ERROR_HAVE_NO_MEMORY(e);
2103 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2104 e->time = 0; /* so far always 0 in trces. */
2105 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2107 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2109 info->entries[0] = e;
2112 e = talloc(info, struct lsa_ForestTrustRecord);
2113 W_ERROR_HAVE_NO_MEMORY(e);
2115 /* get our own domain info */
2116 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2118 return WERR_GENERAL_FAILURE;
2121 /* TODO: check if disabled and set flags accordingly */
2123 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2124 e->time = 0; /* so far always 0 in traces. */
2126 domain_info = &e->forest_trust_data.domain_info;
2127 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2129 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2130 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2132 info->entries[1] = e;
2134 talloc_free(dom_res);
2140 netr_DsRGetForestTrustInformation
2142 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2143 TALLOC_CTX *mem_ctx,
2144 struct netr_DsRGetForestTrustInformation *r)
2146 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2147 struct lsa_ForestTrustInformation *info, **info_ptr;
2148 struct ldb_context *sam_ctx;
2151 if (r->in.flags & 0xFFFFFFFE) {
2152 return WERR_INVALID_FLAGS;
2155 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2156 dce_call->conn->auth_state.session_info);
2157 if (sam_ctx == NULL) {
2158 return WERR_GENERAL_FAILURE;
2161 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2162 if (!samdb_is_pdc(sam_ctx)) {
2163 return WERR_NERR_NOTPRIMARY;
2166 if (r->in.trusted_domain_name == NULL) {
2167 return WERR_INVALID_FLAGS;
2170 /* TODO: establish an schannel connection with
2171 * r->in.trusted_domain_name and perform a
2172 * netr_GetForestTrustInformation call against it */
2174 /* for now return not implementd */
2175 return WERR_CALL_NOT_IMPLEMENTED;
2178 /* TODO: check r->in.server_name is our name */
2180 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2181 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2183 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2184 W_ERROR_HAVE_NO_MEMORY(info);
2186 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2187 W_ERROR_NOT_OK_RETURN(werr);
2190 r->out.forest_trust_info = info_ptr;
2197 netr_GetForestTrustInformation
2199 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2200 TALLOC_CTX *mem_ctx,
2201 struct netr_GetForestTrustInformation *r)
2203 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2204 struct netlogon_creds_CredentialState *creds;
2205 struct lsa_ForestTrustInformation *info, **info_ptr;
2206 struct ldb_context *sam_ctx;
2210 status = dcesrv_netr_creds_server_step_check(dce_call,
2212 r->in.computer_name,
2214 r->out.return_authenticator,
2216 if (!NT_STATUS_IS_OK(status)) {
2220 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2221 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2222 return NT_STATUS_NOT_IMPLEMENTED;
2225 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2226 dce_call->conn->auth_state.session_info);
2227 if (sam_ctx == NULL) {
2228 return NT_STATUS_UNSUCCESSFUL;
2231 /* TODO: check r->in.server_name is our name */
2233 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2235 return NT_STATUS_NO_MEMORY;
2237 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2239 return NT_STATUS_NO_MEMORY;
2242 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2243 if (!W_ERROR_IS_OK(werr)) {
2244 return werror_to_ntstatus(werr);
2248 r->out.forest_trust_info = info_ptr;
2250 return NT_STATUS_OK;
2255 netr_ServerGetTrustInfo
2257 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2258 struct netr_ServerGetTrustInfo *r)
2260 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2266 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2267 struct netr_Unused47 *r)
2269 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2273 struct netr_dnsupdate_RODC_state {
2274 struct dcesrv_call_state *dce_call;
2275 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2276 struct dnsupdate_RODC *r2;
2280 called when the forwarded RODC dns update request is finished
2282 static void netr_dnsupdate_RODC_callback(struct tevent_req *req)
2284 struct netr_dnsupdate_RODC_state *st =
2285 tevent_req_callback_data(req,
2286 struct netr_dnsupdate_RODC_state);
2289 status = dcerpc_binding_handle_call_recv(req);
2291 if (!NT_STATUS_IS_OK(status)) {
2292 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2293 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2296 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2298 status = dcesrv_reply(st->dce_call);
2299 if (!NT_STATUS_IS_OK(status)) {
2300 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2305 netr_DsrUpdateReadOnlyServerDnsRecords
2307 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2308 TALLOC_CTX *mem_ctx,
2309 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2311 struct netlogon_creds_CredentialState *creds;
2313 struct dcerpc_binding_handle *binding_handle;
2314 struct netr_dnsupdate_RODC_state *st;
2315 struct tevent_req *req;
2317 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2319 r->in.computer_name,
2321 r->out.return_authenticator,
2323 NT_STATUS_NOT_OK_RETURN(nt_status);
2325 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2326 return NT_STATUS_ACCESS_DENIED;
2329 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2330 NT_STATUS_HAVE_NO_MEMORY(st);
2332 st->dce_call = dce_call;
2334 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2335 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2337 st->r2->in.dom_sid = creds->sid;
2338 st->r2->in.site_name = r->in.site_name;
2339 st->r2->in.dns_ttl = r->in.dns_ttl;
2340 st->r2->in.dns_names = r->in.dns_names;
2341 st->r2->out.dns_names = r->out.dns_names;
2343 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2344 "dnsupdate", &ndr_table_irpc);
2345 if (binding_handle == NULL) {
2346 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2347 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2348 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2351 /* forward the call */
2352 req = dcerpc_binding_handle_call_send(st, dce_call->event_ctx,
2354 NULL, &ndr_table_irpc,
2357 NT_STATUS_HAVE_NO_MEMORY(req);
2359 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2361 /* setup the callback */
2362 tevent_req_set_callback(req, netr_dnsupdate_RODC_callback, st);
2364 return NT_STATUS_OK;
2368 /* include the generated boilerplate */
2369 #include "librpc/gen_ndr/ndr_netlogon_s.c"