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;
128 switch (r->in.secure_channel_type) {
130 case SEC_CHAN_DNS_DOMAIN:
131 case SEC_CHAN_DOMAIN:
136 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
137 r->in.secure_channel_type));
138 return NT_STATUS_INVALID_PARAMETER;
141 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
142 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
143 if (sam_ctx == NULL) {
144 return NT_STATUS_INVALID_SYSTEM_SERVICE;
147 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
148 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
149 const char *flatname;
150 if (!encoded_account) {
151 return NT_STATUS_NO_MEMORY;
154 /* Kill the trailing dot */
155 if (encoded_account[strlen(encoded_account)-1] == '.') {
156 encoded_account[strlen(encoded_account)-1] = '\0';
159 /* pull the user attributes */
160 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
162 "(&(trustPartner=%s)(objectclass=trustedDomain))",
165 if (num_records == 0) {
166 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
168 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
171 if (num_records > 1) {
172 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
173 return NT_STATUS_INTERNAL_DB_CORRUPTION;
176 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
178 /* No flatname for this trust - we can't proceed */
179 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
181 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
184 return NT_STATUS_NO_MEMORY;
188 account_name = r->in.account_name;
191 /* pull the user attributes */
192 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
193 "(&(sAMAccountName=%s)(objectclass=user))",
194 ldb_binary_encode_string(mem_ctx, account_name));
196 if (num_records == 0) {
197 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
198 r->in.account_name));
199 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
202 if (num_records > 1) {
203 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
204 return NT_STATUS_INTERNAL_DB_CORRUPTION;
207 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
209 if (user_account_control & UF_ACCOUNTDISABLE) {
210 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
211 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
214 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
215 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
216 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
217 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
219 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
220 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
221 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
222 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
224 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
226 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
227 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
228 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
229 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
231 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
232 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
233 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
234 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
237 /* we should never reach this */
238 return NT_STATUS_INTERNAL_ERROR;
241 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
244 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
245 if (mach_pwd == NULL) {
246 return NT_STATUS_ACCESS_DENIED;
250 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
251 return NT_STATUS_ACCESS_DENIED;
254 creds = netlogon_creds_server_init(mem_ctx,
257 r->in.secure_channel_type,
258 &pipe_state->client_challenge,
259 &pipe_state->server_challenge,
262 r->out.return_credentials,
263 *r->in.negotiate_flags);
266 return NT_STATUS_ACCESS_DENIED;
269 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
271 nt_status = schannel_save_creds_state(mem_ctx,
272 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
278 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
279 struct netr_ServerAuthenticate *r)
281 struct netr_ServerAuthenticate3 a;
284 * negotiate_flags is used as an [in] parameter
285 * so it need to be initialised.
287 * (I think ... = 0; seems wrong here --metze)
289 uint32_t negotiate_flags_in = 0;
290 uint32_t negotiate_flags_out = 0;
292 a.in.server_name = r->in.server_name;
293 a.in.account_name = r->in.account_name;
294 a.in.secure_channel_type = r->in.secure_channel_type;
295 a.in.computer_name = r->in.computer_name;
296 a.in.credentials = r->in.credentials;
297 a.in.negotiate_flags = &negotiate_flags_in;
299 a.out.return_credentials = r->out.return_credentials;
301 a.out.negotiate_flags = &negotiate_flags_out;
303 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
306 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
307 struct netr_ServerAuthenticate2 *r)
309 struct netr_ServerAuthenticate3 r3;
312 r3.in.server_name = r->in.server_name;
313 r3.in.account_name = r->in.account_name;
314 r3.in.secure_channel_type = r->in.secure_channel_type;
315 r3.in.computer_name = r->in.computer_name;
316 r3.in.credentials = r->in.credentials;
317 r3.out.return_credentials = r->out.return_credentials;
318 r3.in.negotiate_flags = r->in.negotiate_flags;
319 r3.out.negotiate_flags = r->out.negotiate_flags;
322 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
326 * NOTE: The following functions are nearly identical to the ones available in
327 * source3/rpc_server/srv_nelog_nt.c
328 * The reason we keep 2 copies is that they use different structures to
329 * represent the auth_info and the decrpc pipes.
333 * If schannel is required for this call test that it actually is available.
335 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
336 const char *computer_name,
337 bool integrity, bool privacy)
340 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
341 if (!privacy && !integrity) {
345 if ((!privacy && integrity) &&
346 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
350 if ((privacy || integrity) &&
351 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
356 /* test didn't pass */
357 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
360 return NT_STATUS_ACCESS_DENIED;
363 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
365 const char *computer_name,
366 struct netr_Authenticator *received_authenticator,
367 struct netr_Authenticator *return_authenticator,
368 struct netlogon_creds_CredentialState **creds_out)
371 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
372 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
374 if (schannel_global_required) {
375 nt_status = schannel_check_required(auth_info,
378 if (!NT_STATUS_IS_OK(nt_status)) {
383 nt_status = schannel_check_creds_state(mem_ctx,
384 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
386 received_authenticator,
387 return_authenticator,
393 Change the machine account password for the currently connected
394 client. Supplies only the NT#.
397 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
398 struct netr_ServerPasswordSet *r)
400 struct netlogon_creds_CredentialState *creds;
401 struct ldb_context *sam_ctx;
402 const char * const attrs[] = { "unicodePwd", NULL };
403 struct ldb_message **res;
404 struct samr_Password *oldNtHash;
408 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
411 r->in.credential, r->out.return_authenticator,
413 NT_STATUS_NOT_OK_RETURN(nt_status);
415 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);
416 if (sam_ctx == NULL) {
417 return NT_STATUS_INVALID_SYSTEM_SERVICE;
420 netlogon_creds_des_decrypt(creds, r->in.new_password);
422 /* fetch the old password hashes (the NT hash has to exist) */
424 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
425 "(&(objectClass=user)(objectSid=%s))",
426 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
428 return NT_STATUS_WRONG_PASSWORD;
431 nt_status = samdb_result_passwords(mem_ctx,
432 dce_call->conn->dce_ctx->lp_ctx,
433 res[0], NULL, &oldNtHash);
434 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
435 return NT_STATUS_WRONG_PASSWORD;
438 /* Using the sid for the account as the key, set the password */
439 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
441 NULL, /* Don't have plaintext */
442 NULL, r->in.new_password,
443 NULL, oldNtHash, /* Password change */
449 Change the machine account password for the currently connected
450 client. Supplies new plaintext.
452 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
453 struct netr_ServerPasswordSet2 *r)
455 struct netlogon_creds_CredentialState *creds;
456 struct ldb_context *sam_ctx;
457 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
458 struct ldb_message **res;
459 struct samr_Password *oldLmHash, *oldNtHash;
461 DATA_BLOB new_password;
464 struct samr_CryptPassword password_buf;
466 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
469 r->in.credential, r->out.return_authenticator,
471 NT_STATUS_NOT_OK_RETURN(nt_status);
473 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);
474 if (sam_ctx == NULL) {
475 return NT_STATUS_INVALID_SYSTEM_SERVICE;
478 memcpy(password_buf.data, r->in.new_password->data, 512);
479 SIVAL(password_buf.data, 512, r->in.new_password->length);
480 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
482 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
483 DEBUG(3,("samr: failed to decode password buffer\n"));
484 return NT_STATUS_WRONG_PASSWORD;
487 /* fetch the old password hashes (at least one of both has to exist) */
489 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
490 "(&(objectClass=user)(objectSid=%s))",
491 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
493 return NT_STATUS_WRONG_PASSWORD;
496 nt_status = samdb_result_passwords(mem_ctx,
497 dce_call->conn->dce_ctx->lp_ctx,
498 res[0], &oldLmHash, &oldNtHash);
499 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
500 return NT_STATUS_WRONG_PASSWORD;
503 /* Using the sid for the account as the key, set the password */
504 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
506 &new_password, /* we have plaintext */
508 oldLmHash, oldNtHash, /* Password change */
517 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
518 struct netr_LogonUasLogon *r)
520 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
527 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
528 struct netr_LogonUasLogoff *r)
530 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
535 netr_LogonSamLogon_base
537 This version of the function allows other wrappers to say 'do not check the credentials'
539 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
541 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
542 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
544 struct auth_context *auth_context;
545 struct auth_usersupplied_info *user_info;
546 struct auth_serversupplied_info *server_info;
548 static const char zeros[16];
549 struct netr_SamBaseInfo *sam;
550 struct netr_SamInfo2 *sam2;
551 struct netr_SamInfo3 *sam3;
552 struct netr_SamInfo6 *sam6;
554 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
555 NT_STATUS_HAVE_NO_MEMORY(user_info);
557 switch (r->in.logon_level) {
558 case NetlogonInteractiveInformation:
559 case NetlogonServiceInformation:
560 case NetlogonInteractiveTransitiveInformation:
561 case NetlogonServiceTransitiveInformation:
562 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
563 netlogon_creds_arcfour_crypt(creds,
564 r->in.logon->password->lmpassword.hash,
565 sizeof(r->in.logon->password->lmpassword.hash));
566 netlogon_creds_arcfour_crypt(creds,
567 r->in.logon->password->ntpassword.hash,
568 sizeof(r->in.logon->password->ntpassword.hash));
570 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
571 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
574 /* TODO: we need to deny anonymous access here */
575 nt_status = auth_context_create(mem_ctx,
576 dce_call->event_ctx, dce_call->msg_ctx,
577 dce_call->conn->dce_ctx->lp_ctx,
579 NT_STATUS_NOT_OK_RETURN(nt_status);
581 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
582 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
583 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
584 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
586 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
587 user_info->password_state = AUTH_PASSWORD_HASH;
589 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
590 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
591 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
593 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
594 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
595 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
598 case NetlogonNetworkInformation:
599 case NetlogonNetworkTransitiveInformation:
601 /* TODO: we need to deny anonymous access here */
602 nt_status = auth_context_create(mem_ctx,
603 dce_call->event_ctx, dce_call->msg_ctx,
604 dce_call->conn->dce_ctx->lp_ctx,
606 NT_STATUS_NOT_OK_RETURN(nt_status);
608 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
609 NT_STATUS_NOT_OK_RETURN(nt_status);
611 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
612 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
613 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
614 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
616 user_info->password_state = AUTH_PASSWORD_RESPONSE;
617 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
618 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
623 case NetlogonGenericInformation:
625 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
626 netlogon_creds_arcfour_crypt(creds,
627 r->in.logon->generic->data, r->in.logon->generic->length);
629 /* Using DES to verify kerberos tickets makes no sense */
630 return NT_STATUS_INVALID_PARAMETER;
633 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
635 struct dcerpc_binding_handle *irpc_handle;
636 struct kdc_check_generic_kerberos check;
637 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
638 NT_STATUS_HAVE_NO_MEMORY(generic);
639 *r->out.authoritative = 1;
641 /* TODO: Describe and deal with these flags */
644 r->out.validation->generic = generic;
646 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
650 if (irpc_handle == NULL) {
651 return NT_STATUS_NO_LOGON_SERVERS;
654 check.in.generic_request =
655 data_blob_const(r->in.logon->generic->data,
656 r->in.logon->generic->length);
658 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
661 if (!NT_STATUS_IS_OK(status)) {
664 generic->length = check.out.generic_reply.length;
665 generic->data = check.out.generic_reply.data;
669 /* Until we get an implemetnation of these other packages */
670 return NT_STATUS_INVALID_PARAMETER;
673 return NT_STATUS_INVALID_PARAMETER;
676 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
677 NT_STATUS_NOT_OK_RETURN(nt_status);
679 switch (r->in.validation_level) {
681 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
682 NT_STATUS_NOT_OK_RETURN(nt_status);
684 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
685 NT_STATUS_HAVE_NO_MEMORY(sam2);
688 /* And put into the talloc tree */
689 talloc_steal(sam2, sam);
690 r->out.validation->sam2 = sam2;
696 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
699 NT_STATUS_NOT_OK_RETURN(nt_status);
701 r->out.validation->sam3 = sam3;
707 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
710 NT_STATUS_NOT_OK_RETURN(nt_status);
712 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
713 NT_STATUS_HAVE_NO_MEMORY(sam6);
714 sam6->base = sam3->base;
716 sam6->sidcount = sam3->sidcount;
717 sam6->sids = sam3->sids;
719 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
720 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
721 sam->account_name.string, sam6->dns_domainname.string);
722 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
723 /* And put into the talloc tree */
724 talloc_steal(sam6, sam3);
726 r->out.validation->sam6 = sam6;
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->key.key, zeros, sizeof(sam->key.key)) != 0) {
737 /* This key is sent unencrypted without the ARCFOUR flag set */
738 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
739 netlogon_creds_arcfour_crypt(creds,
741 sizeof(sam->key.key));
745 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
746 /* It appears that level 6 is not individually encrypted */
747 if ((r->in.validation_level != 6) &&
748 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
749 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
750 netlogon_creds_arcfour_crypt(creds,
752 sizeof(sam->LMSessKey.key));
754 netlogon_creds_des_encrypt_LMKey(creds,
759 *r->out.authoritative = 1;
761 /* TODO: Describe and deal with these flags */
767 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
768 struct netr_LogonSamLogonEx *r)
771 struct netlogon_creds_CredentialState *creds;
773 nt_status = schannel_get_creds_state(mem_ctx,
774 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
775 r->in.computer_name, &creds);
776 if (!NT_STATUS_IS_OK(nt_status)) {
780 if (!dce_call->conn->auth_state.auth_info ||
781 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
782 return NT_STATUS_ACCESS_DENIED;
784 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
788 netr_LogonSamLogonWithFlags
791 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
792 struct netr_LogonSamLogonWithFlags *r)
795 struct netlogon_creds_CredentialState *creds;
796 struct netr_LogonSamLogonEx r2;
798 struct netr_Authenticator *return_authenticator;
800 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
801 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
803 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
806 r->in.credential, return_authenticator,
808 NT_STATUS_NOT_OK_RETURN(nt_status);
812 r2.in.server_name = r->in.server_name;
813 r2.in.computer_name = r->in.computer_name;
814 r2.in.logon_level = r->in.logon_level;
815 r2.in.logon = r->in.logon;
816 r2.in.validation_level = r->in.validation_level;
817 r2.in.flags = r->in.flags;
818 r2.out.validation = r->out.validation;
819 r2.out.authoritative = r->out.authoritative;
820 r2.out.flags = r->out.flags;
822 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
824 r->out.return_authenticator = return_authenticator;
832 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
833 struct netr_LogonSamLogon *r)
835 struct netr_LogonSamLogonWithFlags r2;
841 r2.in.server_name = r->in.server_name;
842 r2.in.computer_name = r->in.computer_name;
843 r2.in.credential = r->in.credential;
844 r2.in.return_authenticator = r->in.return_authenticator;
845 r2.in.logon_level = r->in.logon_level;
846 r2.in.logon = r->in.logon;
847 r2.in.validation_level = r->in.validation_level;
848 r2.in.flags = &flags;
849 r2.out.validation = r->out.validation;
850 r2.out.authoritative = r->out.authoritative;
851 r2.out.flags = &flags;
853 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
855 r->out.return_authenticator = r2.out.return_authenticator;
864 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
865 struct netr_LogonSamLogoff *r)
867 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
875 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
876 struct netr_DatabaseDeltas *r)
878 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
885 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
886 struct netr_DatabaseSync2 *r)
888 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
889 return NT_STATUS_NOT_IMPLEMENTED;
896 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
897 struct netr_DatabaseSync *r)
899 struct netr_DatabaseSync2 r2;
904 r2.in.logon_server = r->in.logon_server;
905 r2.in.computername = r->in.computername;
906 r2.in.credential = r->in.credential;
907 r2.in.database_id = r->in.database_id;
908 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
909 r2.in.sync_context = r->in.sync_context;
910 r2.out.sync_context = r->out.sync_context;
911 r2.out.delta_enum_array = r->out.delta_enum_array;
912 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
914 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
923 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
924 struct netr_AccountDeltas *r)
926 /* w2k3 returns "NOT IMPLEMENTED" for this call */
927 return NT_STATUS_NOT_IMPLEMENTED;
934 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
935 struct netr_AccountSync *r)
937 /* w2k3 returns "NOT IMPLEMENTED" for this call */
938 return NT_STATUS_NOT_IMPLEMENTED;
945 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
946 struct netr_GetDcName *r)
948 const char * const attrs[] = { NULL };
949 struct ldb_context *sam_ctx;
950 struct ldb_message **res;
951 struct ldb_dn *domain_dn;
956 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
957 * that the domainname needs to be a valid netbios domain
958 * name, if it is not NULL.
960 if (r->in.domainname) {
961 const char *dot = strchr(r->in.domainname, '.');
962 size_t len = strlen(r->in.domainname);
964 if (dot || len > 15) {
965 return WERR_DCNOTFOUND;
969 * TODO: Should we also varify that only valid
970 * netbios name characters are used?
974 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
975 dce_call->conn->dce_ctx->lp_ctx,
976 dce_call->conn->auth_state.session_info, 0);
977 if (sam_ctx == NULL) {
978 return WERR_DS_UNAVAILABLE;
981 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
983 if (domain_dn == NULL) {
984 return WERR_DS_UNAVAILABLE;
987 ret = gendb_search_dn(sam_ctx, mem_ctx,
988 domain_dn, &res, attrs);
990 return WERR_NO_SUCH_DOMAIN;
993 /* TODO: - return real IP address
994 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
996 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
997 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
998 W_ERROR_HAVE_NO_MEMORY(dcname);
1000 *r->out.dcname = dcname;
1006 netr_LogonControl2Ex
1008 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1009 struct netr_LogonControl2Ex *r)
1011 return WERR_NOT_SUPPORTED;
1018 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1019 struct netr_LogonControl *r)
1021 struct netr_LogonControl2Ex r2;
1024 if (r->in.level == 0x00000001) {
1027 r2.in.logon_server = r->in.logon_server;
1028 r2.in.function_code = r->in.function_code;
1029 r2.in.level = r->in.level;
1031 r2.out.query = r->out.query;
1033 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1034 } else if (r->in.level == 0x00000002) {
1035 werr = WERR_NOT_SUPPORTED;
1037 werr = WERR_UNKNOWN_LEVEL;
1047 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1048 struct netr_LogonControl2 *r)
1050 struct netr_LogonControl2Ex r2;
1055 r2.in.logon_server = r->in.logon_server;
1056 r2.in.function_code = r->in.function_code;
1057 r2.in.level = r->in.level;
1058 r2.in.data = r->in.data;
1059 r2.out.query = r->out.query;
1061 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1066 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1067 struct ldb_context *sam_ctx,
1068 struct netr_DomainTrustList *trusts,
1069 uint32_t trust_flags);
1074 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1075 struct netr_GetAnyDCName *r)
1077 struct netr_DomainTrustList *trusts;
1078 struct ldb_context *sam_ctx;
1079 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1083 *r->out.dcname = NULL;
1085 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1086 /* if the domainname parameter wasn't set assume our domain */
1087 r->in.domainname = lpcfg_workgroup(lp_ctx);
1090 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1091 dce_call->conn->auth_state.session_info, 0);
1092 if (sam_ctx == NULL) {
1093 return WERR_DS_UNAVAILABLE;
1096 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1097 /* well we asked for a DC of our own domain */
1098 if (samdb_is_pdc(sam_ctx)) {
1099 /* we are the PDC of the specified domain */
1100 return WERR_NO_SUCH_DOMAIN;
1103 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1104 lpcfg_netbios_name(lp_ctx));
1105 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1110 /* Okay, now we have to consider the trusted domains */
1112 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1113 W_ERROR_HAVE_NO_MEMORY(trusts);
1117 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1118 NETR_TRUST_FLAG_INBOUND
1119 | NETR_TRUST_FLAG_OUTBOUND);
1120 W_ERROR_NOT_OK_RETURN(werr);
1122 for (i = 0; i < trusts->count; i++) {
1123 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1124 /* FIXME: Here we need to find a DC for the specified
1125 * trusted domain. */
1127 /* return WERR_OK; */
1128 return WERR_NO_SUCH_DOMAIN;
1132 return WERR_NO_SUCH_DOMAIN;
1139 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1140 struct netr_DatabaseRedo *r)
1142 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1147 netr_NetrEnumerateTrustedDomains
1149 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150 struct netr_NetrEnumerateTrustedDomains *r)
1152 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1157 netr_LogonGetCapabilities
1159 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1160 struct netr_LogonGetCapabilities *r)
1162 /* we don't support AES yet */
1163 return NT_STATUS_NOT_IMPLEMENTED;
1168 netr_NETRLOGONSETSERVICEBITS
1170 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1171 struct netr_NETRLOGONSETSERVICEBITS *r)
1173 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1178 netr_LogonGetTrustRid
1180 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1181 struct netr_LogonGetTrustRid *r)
1183 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1188 netr_NETRLOGONCOMPUTESERVERDIGEST
1190 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1191 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1193 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1198 netr_NETRLOGONCOMPUTECLIENTDIGEST
1200 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1201 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1203 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1211 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1212 struct netr_DsRGetSiteName *r)
1214 struct ldb_context *sam_ctx;
1215 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1217 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1218 dce_call->conn->auth_state.session_info, 0);
1219 if (sam_ctx == NULL) {
1220 return WERR_DS_UNAVAILABLE;
1223 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1224 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1231 fill in a netr_OneDomainInfo from a ldb search result
1233 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1234 struct loadparm_context *lp_ctx,
1235 struct ldb_context *sam_ctx,
1236 struct ldb_message *res,
1237 struct netr_OneDomainInfo *info,
1238 bool is_local, bool is_trust_list)
1242 if (is_trust_list) {
1243 /* w2k8 only fills this on trusted domains */
1244 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1245 info->trust_extension.length = 16;
1246 info->trust_extension.info->flags =
1247 NETR_TRUST_FLAG_TREEROOT |
1248 NETR_TRUST_FLAG_IN_FOREST |
1249 NETR_TRUST_FLAG_PRIMARY |
1250 NETR_TRUST_FLAG_NATIVE;
1252 info->trust_extension.info->parent_index = 0; /* should be index into array
1254 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1255 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1258 if (is_trust_list) {
1259 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1260 info->dns_forestname.string = NULL;
1262 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1263 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1264 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1265 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1269 info->domainname.string = lpcfg_workgroup(lp_ctx);
1270 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1271 info->domain_guid = samdb_result_guid(res, "objectGUID");
1272 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1274 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1275 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1276 info->domain_guid = samdb_result_guid(res, "objectGUID");
1277 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1279 if (!is_trust_list) {
1280 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1283 return NT_STATUS_OK;
1287 netr_LogonGetDomainInfo
1288 this is called as part of the ADS domain logon procedure.
1290 It has an important role in convaying details about the client, such
1291 as Operating System, Version, Service Pack etc.
1293 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1294 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1296 struct netlogon_creds_CredentialState *creds;
1297 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1298 "securityIdentifier", "trustPartner", NULL };
1299 const char * const attrs2[] = { "dNSHostName",
1300 "msDS-SupportedEncryptionTypes", NULL };
1301 const char *temp_str, *temp_str2;
1302 const char *old_dns_hostname;
1303 struct ldb_context *sam_ctx;
1304 struct ldb_message **res1, **res2, **res3, *new_msg;
1305 struct ldb_dn *workstation_dn;
1306 struct netr_DomainInformation *domain_info;
1307 struct netr_LsaPolicyInformation *lsa_policy_info;
1308 struct netr_OsVersionInfoEx *os_version;
1309 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1310 bool update_dns_hostname = true;
1314 status = dcesrv_netr_creds_server_step_check(dce_call,
1316 r->in.computer_name,
1318 r->out.return_authenticator,
1320 if (!NT_STATUS_IS_OK(status)) {
1321 DEBUG(0,(__location__ " Bad credentials - error\n"));
1323 NT_STATUS_NOT_OK_RETURN(status);
1325 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1326 dce_call->conn->dce_ctx->lp_ctx,
1327 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1328 if (sam_ctx == NULL) {
1329 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1332 switch (r->in.level) {
1333 case 1: /* Domain information */
1335 if (r->in.query->workstation_info == NULL) {
1336 return NT_STATUS_INVALID_PARAMETER;
1340 * Checks that the computer name parameter without possible "$"
1341 * matches as prefix with the DNS hostname in the workstation
1344 temp_str = talloc_strndup(mem_ctx,
1345 r->in.computer_name,
1346 strcspn(r->in.computer_name, "$"));
1347 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1348 temp_str2 = talloc_strndup(mem_ctx,
1349 r->in.query->workstation_info->dns_hostname,
1350 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1351 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1352 if (strcasecmp(temp_str, temp_str2) != 0) {
1353 update_dns_hostname = false;
1356 /* Prepare the workstation DN */
1357 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1358 dom_sid_string(mem_ctx, creds->sid));
1359 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1361 /* Lookup for attributes in workstation object */
1362 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1365 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1368 /* Gets the old DNS hostname */
1369 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0], "dNSHostName",
1373 * Updates the DNS hostname when the client wishes that the
1374 * server should handle this for him
1375 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1376 * obviously only checked when we do already have a
1378 * See MS-NRPC section 3.5.4.3.9
1380 if ((old_dns_hostname != NULL) &&
1381 (r->in.query->workstation_info->workstation_flags
1382 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1383 update_dns_hostname = false;
1386 /* Gets host informations and put them into our directory */
1388 new_msg = ldb_msg_new(mem_ctx);
1389 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1391 new_msg->dn = workstation_dn;
1393 /* Sets the OS name */
1394 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1396 r->in.query->workstation_info->os_name.string);
1399 * Sets informations from "os_version". On an empty structure
1400 * the values are cleared.
1402 if (r->in.query->workstation_info->os_version.os != NULL) {
1403 os_version = &r->in.query->workstation_info->os_version.os->os;
1405 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1406 "operatingSystemServicePack",
1407 os_version->CSDVersion);
1409 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1410 "operatingSystemVersion",
1411 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1412 os_version->MajorVersion,
1413 os_version->MinorVersion,
1414 os_version->BuildNumber
1418 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1419 "operatingSystemServicePack");
1421 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1422 "operatingSystemVersion");
1426 * If the boolean "update_dns_hostname" remained true, then we
1427 * are fine to start the update.
1429 if (update_dns_hostname) {
1430 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1432 r->in.query->workstation_info->dns_hostname);
1434 /* This manual "servicePrincipalName" generation is
1435 * still needed! Since the update in the samldb LDB
1436 * module does only work if the entries already exist
1437 * which isn't always the case. */
1438 ldb_msg_add_string(new_msg, "servicePrincipalName",
1439 talloc_asprintf(new_msg, "HOST/%s",
1440 r->in.computer_name));
1441 ldb_msg_add_string(new_msg, "servicePrincipalName",
1442 talloc_asprintf(new_msg, "HOST/%s",
1443 r->in.query->workstation_info->dns_hostname));
1446 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1447 DEBUG(3,("Impossible to update samdb: %s\n",
1448 ldb_errstring(sam_ctx)));
1451 talloc_free(new_msg);
1453 /* Writes back the domain information */
1455 /* We need to do two searches. The first will pull our primary
1456 domain and the second will pull any trusted domains. Our
1457 primary domain is also a "trusted" domain, so we need to
1458 put the primary domain into the lists of returned trusts as
1460 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1463 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1466 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1467 "(objectClass=trustedDomain)");
1469 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1472 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1473 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1475 ZERO_STRUCTP(domain_info);
1477 /* Informations about the local and trusted domains */
1479 status = fill_one_domain_info(mem_ctx,
1480 dce_call->conn->dce_ctx->lp_ctx,
1481 sam_ctx, res2[0], &domain_info->primary_domain,
1483 NT_STATUS_NOT_OK_RETURN(status);
1485 domain_info->trusted_domain_count = ret3 + 1;
1486 domain_info->trusted_domains = talloc_array(mem_ctx,
1487 struct netr_OneDomainInfo,
1488 domain_info->trusted_domain_count);
1489 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1491 for (i=0;i<ret3;i++) {
1492 status = fill_one_domain_info(mem_ctx,
1493 dce_call->conn->dce_ctx->lp_ctx,
1495 &domain_info->trusted_domains[i],
1497 NT_STATUS_NOT_OK_RETURN(status);
1500 status = fill_one_domain_info(mem_ctx,
1501 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1502 &domain_info->trusted_domains[i], true, true);
1503 NT_STATUS_NOT_OK_RETURN(status);
1505 /* Sets the supported encryption types */
1506 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1507 "msDS-SupportedEncryptionTypes",
1508 default_supported_enc_types);
1510 /* Other host domain informations */
1512 lsa_policy_info = talloc(mem_ctx,
1513 struct netr_LsaPolicyInformation);
1514 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1515 ZERO_STRUCTP(lsa_policy_info);
1517 domain_info->lsa_policy = *lsa_policy_info;
1519 /* The DNS hostname is only returned back when there is a chance
1521 if ((r->in.query->workstation_info->workstation_flags
1522 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1523 domain_info->dns_hostname.string = old_dns_hostname;
1525 domain_info->dns_hostname.string = NULL;
1528 domain_info->workstation_flags =
1529 r->in.query->workstation_info->workstation_flags;
1531 r->out.info->domain_info = domain_info;
1533 case 2: /* LSA policy information - not used at the moment */
1534 lsa_policy_info = talloc(mem_ctx,
1535 struct netr_LsaPolicyInformation);
1536 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1537 ZERO_STRUCTP(lsa_policy_info);
1539 r->out.info->lsa_policy_info = lsa_policy_info;
1542 return NT_STATUS_INVALID_LEVEL;
1546 return NT_STATUS_OK;
1552 netr_ServerPasswordGet
1554 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1555 struct netr_ServerPasswordGet *r)
1557 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1562 netr_NETRLOGONSENDTOSAM
1564 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1565 struct netr_NETRLOGONSENDTOSAM *r)
1567 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1572 netr_DsRGetDCNameEx2
1574 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1575 TALLOC_CTX *mem_ctx,
1576 struct netr_DsRGetDCNameEx2 *r)
1578 struct ldb_context *sam_ctx;
1579 struct netr_DsRGetDCNameInfo *info;
1580 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1581 const struct tsocket_address *remote_address;
1583 const char *server_site_name;
1585 struct netlogon_samlogon_response response;
1587 const char *dc_name = NULL;
1588 const char *domain_name = NULL;
1590 ZERO_STRUCTP(r->out.info);
1592 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1593 dce_call->conn->auth_state.session_info, 0);
1594 if (sam_ctx == NULL) {
1595 return WERR_DS_UNAVAILABLE;
1598 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1599 if (tsocket_address_is_inet(remote_address, "ip")) {
1600 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1601 W_ERROR_HAVE_NO_MEMORY(addr);
1604 /* "server_unc" is ignored by w2k3 */
1606 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1607 return WERR_INVALID_FLAGS;
1610 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1611 r->in.flags & DS_PDC_REQUIRED &&
1612 r->in.flags & DS_KDC_REQUIRED) {
1613 return WERR_INVALID_FLAGS;
1615 if (r->in.flags & DS_IS_FLAT_NAME &&
1616 r->in.flags & DS_IS_DNS_NAME) {
1617 return WERR_INVALID_FLAGS;
1619 if (r->in.flags & DS_RETURN_DNS_NAME &&
1620 r->in.flags & DS_RETURN_FLAT_NAME) {
1621 return WERR_INVALID_FLAGS;
1623 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1624 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1625 return WERR_INVALID_FLAGS;
1628 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1630 (DS_DIRECTORY_SERVICE_REQUIRED |
1631 DS_DIRECTORY_SERVICE_PREFERRED |
1632 DS_GC_SERVER_REQUIRED |
1635 return WERR_INVALID_FLAGS;
1638 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1640 return WERR_INVALID_FLAGS;
1643 /* Proof server site parameter "site_name" if it was specified */
1644 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1645 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1646 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1647 server_site_name) != 0)) {
1648 return WERR_NO_SUCH_DOMAIN;
1651 guid_str = r->in.domain_guid != NULL ?
1652 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1654 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1658 r->in.client_account,
1660 NETLOGON_NT_VERSION_5EX_WITH_IP,
1661 lp_ctx, &response, true);
1662 if (!NT_STATUS_IS_OK(status)) {
1663 return ntstatus_to_werror(status);
1666 if (r->in.flags & DS_RETURN_DNS_NAME) {
1667 dc_name = response.data.nt5_ex.pdc_dns_name;
1668 domain_name = response.data.nt5_ex.dns_domain;
1669 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1670 dc_name = response.data.nt5_ex.pdc_name;
1671 domain_name = response.data.nt5_ex.domain_name;
1675 * TODO: autodetect what we need to return
1676 * based on the given arguments
1678 dc_name = response.data.nt5_ex.pdc_name;
1679 domain_name = response.data.nt5_ex.domain_name;
1682 if (!dc_name || !dc_name[0]) {
1683 return WERR_NO_SUCH_DOMAIN;
1686 if (!domain_name || !domain_name[0]) {
1687 return WERR_NO_SUCH_DOMAIN;
1690 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1691 W_ERROR_HAVE_NO_MEMORY(info);
1692 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1693 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1694 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1695 response.data.nt5_ex.sockaddr.pdc_ip);
1696 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1697 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1698 info->domain_guid = response.data.nt5_ex.domain_uuid;
1699 info->domain_name = domain_name;
1700 info->forest_name = response.data.nt5_ex.forest;
1701 info->dc_flags = response.data.nt5_ex.server_type;
1702 info->dc_site_name = response.data.nt5_ex.server_site;
1703 info->client_site_name = response.data.nt5_ex.client_site;
1705 *r->out.info = info;
1713 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1714 struct netr_DsRGetDCNameEx *r)
1716 struct netr_DsRGetDCNameEx2 r2;
1721 r2.in.server_unc = r->in.server_unc;
1722 r2.in.client_account = NULL;
1724 r2.in.domain_guid = r->in.domain_guid;
1725 r2.in.domain_name = r->in.domain_name;
1726 r2.in.site_name = r->in.site_name;
1727 r2.in.flags = r->in.flags;
1728 r2.out.info = r->out.info;
1730 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1738 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1739 struct netr_DsRGetDCName *r)
1741 struct netr_DsRGetDCNameEx2 r2;
1746 r2.in.server_unc = r->in.server_unc;
1747 r2.in.client_account = NULL;
1749 r2.in.domain_name = r->in.domain_name;
1750 r2.in.domain_guid = r->in.domain_guid;
1752 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1753 r2.in.flags = r->in.flags;
1754 r2.out.info = r->out.info;
1756 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1761 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1763 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1764 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1766 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1771 netr_NetrEnumerateTrustedDomainsEx
1773 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1774 struct netr_NetrEnumerateTrustedDomainsEx *r)
1776 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1781 netr_DsRAddressToSitenamesExW
1783 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1784 struct netr_DsRAddressToSitenamesExW *r)
1786 struct ldb_context *sam_ctx;
1787 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1788 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1789 sa_family_t sin_family;
1790 struct sockaddr_in *addr;
1792 struct sockaddr_in6 *addr6;
1793 char addr_str[INET6_ADDRSTRLEN];
1795 char addr_str[INET_ADDRSTRLEN];
1801 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1802 dce_call->conn->auth_state.session_info, 0);
1803 if (sam_ctx == NULL) {
1804 return WERR_DS_UNAVAILABLE;
1807 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1808 W_ERROR_HAVE_NO_MEMORY(ctr);
1812 ctr->count = r->in.count;
1813 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1814 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1815 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1816 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1818 for (i=0; i<ctr->count; i++) {
1819 ctr->sitename[i].string = NULL;
1820 ctr->subnetname[i].string = NULL;
1822 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1825 /* The first two byte of the buffer are reserved for the
1826 * "sin_family" but for now only the first one is used. */
1827 sin_family = r->in.addresses[i].buffer[0];
1829 switch (sin_family) {
1831 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1834 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1835 res = inet_ntop(AF_INET, &addr->sin_addr,
1836 addr_str, sizeof(addr_str));
1840 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1843 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1844 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1845 addr_str, sizeof(addr_str));
1856 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1860 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1861 ctr->subnetname[i].string = subnet_name;
1869 netr_DsRAddressToSitenamesW
1871 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1872 struct netr_DsRAddressToSitenamesW *r)
1874 struct netr_DsRAddressToSitenamesExW r2;
1875 struct netr_DsRAddressToSitenamesWCtr *ctr;
1881 r2.in.server_name = r->in.server_name;
1882 r2.in.count = r->in.count;
1883 r2.in.addresses = r->in.addresses;
1885 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1886 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1888 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1889 W_ERROR_HAVE_NO_MEMORY(ctr);
1893 ctr->count = r->in.count;
1894 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1895 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1897 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1899 for (i=0; i<ctr->count; i++) {
1900 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1908 netr_DsrGetDcSiteCoverageW
1910 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1911 struct netr_DsrGetDcSiteCoverageW *r)
1913 struct ldb_context *sam_ctx;
1914 struct DcSitesCtr *ctr;
1915 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1917 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1918 dce_call->conn->auth_state.session_info, 0);
1919 if (sam_ctx == NULL) {
1920 return WERR_DS_UNAVAILABLE;
1923 ctr = talloc(mem_ctx, struct DcSitesCtr);
1924 W_ERROR_HAVE_NO_MEMORY(ctr);
1928 /* For now only return our default site */
1930 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1931 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1932 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1933 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1939 #define GET_CHECK_STR(dest, mem, msg, attr) \
1942 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
1944 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1945 "without flatname\n", \
1946 ldb_dn_get_linearized(msg->dn))); \
1949 dest = talloc_strdup(mem, s); \
1950 W_ERROR_HAVE_NO_MEMORY(dest); \
1954 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1955 struct ldb_context *sam_ctx,
1956 struct netr_DomainTrustList *trusts,
1957 uint32_t trust_flags)
1959 struct ldb_dn *system_dn;
1960 struct ldb_message **dom_res = NULL;
1961 const char *trust_attrs[] = { "flatname", "trustPartner",
1962 "securityIdentifier", "trustDirection",
1963 "trustType", "trustAttributes", NULL };
1968 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1969 NETR_TRUST_FLAG_OUTBOUND))) {
1970 return WERR_INVALID_FLAGS;
1973 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1974 ldb_get_default_basedn(sam_ctx),
1975 "(&(objectClass=container)(cn=System))");
1977 return WERR_GENERAL_FAILURE;
1980 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1981 &dom_res, trust_attrs,
1982 "(objectclass=trustedDomain)");
1984 for (i = 0; i < ret; i++) {
1985 unsigned int trust_dir;
1988 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
1989 "trustDirection", 0);
1991 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1992 flags |= NETR_TRUST_FLAG_INBOUND;
1994 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1995 flags |= NETR_TRUST_FLAG_OUTBOUND;
1998 if (!(flags & trust_flags)) {
1999 /* this trust direction was not requested */
2004 trusts->array = talloc_realloc(trusts, trusts->array,
2005 struct netr_DomainTrust,
2007 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2009 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2010 dom_res[i], "flatname");
2011 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2012 dom_res[i], "trustPartner");
2014 trusts->array[n].trust_flags = flags;
2015 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2016 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2017 /* TODO: find if we have parent in the list */
2018 trusts->array[n].parent_index = 0;
2021 trusts->array[n].trust_type =
2022 ldb_msg_find_attr_as_uint(dom_res[i],
2024 trusts->array[n].trust_attributes =
2025 ldb_msg_find_attr_as_uint(dom_res[i],
2026 "trustAttributes", 0);
2028 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2029 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2030 struct dom_sid zero_sid;
2031 ZERO_STRUCT(zero_sid);
2032 trusts->array[n].sid =
2033 dom_sid_dup(trusts, &zero_sid);
2035 trusts->array[n].sid =
2036 samdb_result_dom_sid(trusts, dom_res[i],
2037 "securityIdentifier");
2039 trusts->array[n].guid = GUID_zero();
2041 trusts->count = n + 1;
2044 talloc_free(dom_res);
2049 netr_DsrEnumerateDomainTrusts
2051 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2052 TALLOC_CTX *mem_ctx,
2053 struct netr_DsrEnumerateDomainTrusts *r)
2055 struct netr_DomainTrustList *trusts;
2056 struct ldb_context *sam_ctx;
2058 struct ldb_message **dom_res;
2059 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2060 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2061 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2065 if (r->in.trust_flags & 0xFFFFFE00) {
2066 return WERR_INVALID_FLAGS;
2069 /* TODO: turn to hard check once we are sure this is 100% correct */
2070 if (!r->in.server_name) {
2071 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2072 "But received NULL!\n", dnsdomain));
2074 p = strchr(r->in.server_name, '.');
2076 DEBUG(3, ("Invalid domain! Expected name in domain "
2077 "[%s]. But received [%s]!\n",
2078 dnsdomain, r->in.server_name));
2079 p = r->in.server_name;
2083 if (strcasecmp(p, dnsdomain)) {
2084 DEBUG(3, ("Invalid domain! Expected name in domain "
2085 "[%s]. But received [%s]!\n",
2086 dnsdomain, r->in.server_name));
2090 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2091 W_ERROR_HAVE_NO_MEMORY(trusts);
2094 r->out.trusts = trusts;
2096 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2097 dce_call->conn->auth_state.session_info, 0);
2098 if (sam_ctx == NULL) {
2099 return WERR_GENERAL_FAILURE;
2102 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2103 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2105 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2106 trusts, r->in.trust_flags);
2107 W_ERROR_NOT_OK_RETURN(werr);
2110 /* NOTE: we currently are always the root of the forest */
2111 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2112 uint32_t n = trusts->count;
2114 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2115 &dom_res, dom_attrs);
2117 return WERR_GENERAL_FAILURE;
2120 trusts->count = n + 1;
2121 trusts->array = talloc_realloc(trusts, trusts->array,
2122 struct netr_DomainTrust,
2124 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2126 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2127 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2128 trusts->array[n].trust_flags =
2129 NETR_TRUST_FLAG_NATIVE |
2130 NETR_TRUST_FLAG_TREEROOT |
2131 NETR_TRUST_FLAG_IN_FOREST |
2132 NETR_TRUST_FLAG_PRIMARY;
2133 /* we are always the root domain for now */
2134 trusts->array[n].parent_index = 0;
2135 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2136 trusts->array[n].trust_attributes = 0;
2137 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2140 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2142 talloc_free(dom_res);
2150 netr_DsrDeregisterDNSHostRecords
2152 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2153 struct netr_DsrDeregisterDNSHostRecords *r)
2155 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2160 netr_ServerTrustPasswordsGet
2162 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2163 struct netr_ServerTrustPasswordsGet *r)
2165 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2169 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2170 struct ldb_context *sam_ctx,
2171 struct loadparm_context *lp_ctx,
2172 struct lsa_ForestTrustInformation *info)
2174 struct lsa_ForestTrustDomainInfo *domain_info;
2175 struct lsa_ForestTrustRecord *e;
2176 struct ldb_message **dom_res;
2177 const char * const dom_attrs[] = { "objectSid", NULL };
2180 /* we need to provide 2 entries:
2181 * 1. the Root Forest name
2182 * 2. the Domain Information
2186 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2187 W_ERROR_HAVE_NO_MEMORY(info->entries);
2189 /* Forest root info */
2190 e = talloc(info, struct lsa_ForestTrustRecord);
2191 W_ERROR_HAVE_NO_MEMORY(e);
2194 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2195 e->time = 0; /* so far always 0 in trces. */
2196 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2198 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2200 info->entries[0] = e;
2203 e = talloc(info, struct lsa_ForestTrustRecord);
2204 W_ERROR_HAVE_NO_MEMORY(e);
2206 /* get our own domain info */
2207 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2209 return WERR_GENERAL_FAILURE;
2212 /* TODO: check if disabled and set flags accordingly */
2214 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2215 e->time = 0; /* so far always 0 in traces. */
2217 domain_info = &e->forest_trust_data.domain_info;
2218 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2220 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2221 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2223 info->entries[1] = e;
2225 talloc_free(dom_res);
2231 netr_DsRGetForestTrustInformation
2233 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2234 TALLOC_CTX *mem_ctx,
2235 struct netr_DsRGetForestTrustInformation *r)
2237 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2238 struct lsa_ForestTrustInformation *info, **info_ptr;
2239 struct ldb_context *sam_ctx;
2242 if (r->in.flags & 0xFFFFFFFE) {
2243 return WERR_INVALID_FLAGS;
2246 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2247 dce_call->conn->auth_state.session_info, 0);
2248 if (sam_ctx == NULL) {
2249 return WERR_GENERAL_FAILURE;
2252 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2253 if (!samdb_is_pdc(sam_ctx)) {
2254 return WERR_NERR_NOTPRIMARY;
2257 if (r->in.trusted_domain_name == NULL) {
2258 return WERR_INVALID_FLAGS;
2261 /* TODO: establish an schannel connection with
2262 * r->in.trusted_domain_name and perform a
2263 * netr_GetForestTrustInformation call against it */
2265 /* for now return not implementd */
2266 return WERR_CALL_NOT_IMPLEMENTED;
2269 /* TODO: check r->in.server_name is our name */
2271 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2272 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2274 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2275 W_ERROR_HAVE_NO_MEMORY(info);
2277 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2278 W_ERROR_NOT_OK_RETURN(werr);
2281 r->out.forest_trust_info = info_ptr;
2288 netr_GetForestTrustInformation
2290 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2291 TALLOC_CTX *mem_ctx,
2292 struct netr_GetForestTrustInformation *r)
2294 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2295 struct netlogon_creds_CredentialState *creds;
2296 struct lsa_ForestTrustInformation *info, **info_ptr;
2297 struct ldb_context *sam_ctx;
2301 status = dcesrv_netr_creds_server_step_check(dce_call,
2303 r->in.computer_name,
2305 r->out.return_authenticator,
2307 if (!NT_STATUS_IS_OK(status)) {
2311 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2312 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2313 return NT_STATUS_NOT_IMPLEMENTED;
2316 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2317 dce_call->conn->auth_state.session_info, 0);
2318 if (sam_ctx == NULL) {
2319 return NT_STATUS_UNSUCCESSFUL;
2322 /* TODO: check r->in.server_name is our name */
2324 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2326 return NT_STATUS_NO_MEMORY;
2328 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2330 return NT_STATUS_NO_MEMORY;
2333 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2334 if (!W_ERROR_IS_OK(werr)) {
2335 return werror_to_ntstatus(werr);
2339 r->out.forest_trust_info = info_ptr;
2341 return NT_STATUS_OK;
2346 netr_ServerGetTrustInfo
2348 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2349 struct netr_ServerGetTrustInfo *r)
2351 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2357 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2358 struct netr_Unused47 *r)
2360 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2364 struct netr_dnsupdate_RODC_state {
2365 struct dcesrv_call_state *dce_call;
2366 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2367 struct dnsupdate_RODC *r2;
2371 called when the forwarded RODC dns update request is finished
2373 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2375 struct netr_dnsupdate_RODC_state *st =
2376 tevent_req_callback_data(subreq,
2377 struct netr_dnsupdate_RODC_state);
2380 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2381 TALLOC_FREE(subreq);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2384 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2387 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2389 status = dcesrv_reply(st->dce_call);
2390 if (!NT_STATUS_IS_OK(status)) {
2391 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2396 netr_DsrUpdateReadOnlyServerDnsRecords
2398 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2399 TALLOC_CTX *mem_ctx,
2400 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2402 struct netlogon_creds_CredentialState *creds;
2404 struct dcerpc_binding_handle *binding_handle;
2405 struct netr_dnsupdate_RODC_state *st;
2406 struct tevent_req *subreq;
2408 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2410 r->in.computer_name,
2412 r->out.return_authenticator,
2414 NT_STATUS_NOT_OK_RETURN(nt_status);
2416 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2417 return NT_STATUS_ACCESS_DENIED;
2420 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2421 NT_STATUS_HAVE_NO_MEMORY(st);
2423 st->dce_call = dce_call;
2425 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2426 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2428 st->r2->in.dom_sid = creds->sid;
2429 st->r2->in.site_name = r->in.site_name;
2430 st->r2->in.dns_ttl = r->in.dns_ttl;
2431 st->r2->in.dns_names = r->in.dns_names;
2432 st->r2->out.dns_names = r->out.dns_names;
2434 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2435 "dnsupdate", &ndr_table_irpc);
2436 if (binding_handle == NULL) {
2437 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2438 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2439 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2442 /* forward the call */
2443 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2444 binding_handle, st->r2);
2445 NT_STATUS_HAVE_NO_MEMORY(subreq);
2447 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2449 /* setup the callback */
2450 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2452 return NT_STATUS_OK;
2456 /* include the generated boilerplate */
2457 #include "librpc/gen_ndr/ndr_netlogon_s.c"