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],
1374 * Updates the DNS hostname when the client wishes that the
1375 * server should handle this for him
1376 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1377 * obviously only checked when we do already have a
1379 * See MS-NRPC section 3.5.4.3.9
1381 if ((old_dns_hostname != NULL) &&
1382 (r->in.query->workstation_info->workstation_flags
1383 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1384 update_dns_hostname = false;
1387 /* Gets host informations and put them into our directory */
1389 new_msg = ldb_msg_new(mem_ctx);
1390 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1392 new_msg->dn = workstation_dn;
1394 /* Sets the OS name */
1395 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1397 r->in.query->workstation_info->os_name.string);
1398 if (ret != LDB_SUCCESS) {
1399 return NT_STATUS_NO_MEMORY;
1403 * Sets informations from "os_version". On an empty structure
1404 * the values are cleared.
1406 if (r->in.query->workstation_info->os_version.os != NULL) {
1407 os_version = &r->in.query->workstation_info->os_version.os->os;
1409 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1410 "operatingSystemServicePack",
1411 os_version->CSDVersion);
1412 if (ret != LDB_SUCCESS) {
1413 return NT_STATUS_NO_MEMORY;
1416 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1417 "operatingSystemVersion",
1418 talloc_asprintf(mem_ctx,
1420 os_version->MajorVersion,
1421 os_version->MinorVersion,
1422 os_version->BuildNumber));
1423 if (ret != LDB_SUCCESS) {
1424 return NT_STATUS_NO_MEMORY;
1427 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1428 "operatingSystemServicePack");
1429 if (ret != LDB_SUCCESS) {
1430 return NT_STATUS_NO_MEMORY;
1433 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1434 "operatingSystemVersion");
1435 if (ret != LDB_SUCCESS) {
1436 return NT_STATUS_NO_MEMORY;
1441 * If the boolean "update_dns_hostname" remained true, then we
1442 * are fine to start the update.
1444 if (update_dns_hostname) {
1445 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1447 r->in.query->workstation_info->dns_hostname);
1448 if (ret != LDB_SUCCESS) {
1449 return NT_STATUS_NO_MEMORY;
1452 /* This manual "servicePrincipalName" generation is
1453 * still needed! Since the update in the samldb LDB
1454 * module does only work if the entries already exist
1455 * which isn't always the case. */
1456 ret = ldb_msg_add_string(new_msg,
1457 "servicePrincipalName",
1458 talloc_asprintf(new_msg, "HOST/%s",
1459 r->in.computer_name));
1460 if (ret != LDB_SUCCESS) {
1461 return NT_STATUS_NO_MEMORY;
1464 ret = ldb_msg_add_string(new_msg,
1465 "servicePrincipalName",
1466 talloc_asprintf(new_msg, "HOST/%s",
1467 r->in.query->workstation_info->dns_hostname));
1468 if (ret != LDB_SUCCESS) {
1469 return NT_STATUS_NO_MEMORY;
1473 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1474 DEBUG(3,("Impossible to update samdb: %s\n",
1475 ldb_errstring(sam_ctx)));
1478 talloc_free(new_msg);
1480 /* Writes back the domain information */
1482 /* We need to do two searches. The first will pull our primary
1483 domain and the second will pull any trusted domains. Our
1484 primary domain is also a "trusted" domain, so we need to
1485 put the primary domain into the lists of returned trusts as
1487 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1490 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1493 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1494 "(objectClass=trustedDomain)");
1496 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1499 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1500 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1502 ZERO_STRUCTP(domain_info);
1504 /* Informations about the local and trusted domains */
1506 status = fill_one_domain_info(mem_ctx,
1507 dce_call->conn->dce_ctx->lp_ctx,
1508 sam_ctx, res2[0], &domain_info->primary_domain,
1510 NT_STATUS_NOT_OK_RETURN(status);
1512 domain_info->trusted_domain_count = ret3 + 1;
1513 domain_info->trusted_domains = talloc_array(mem_ctx,
1514 struct netr_OneDomainInfo,
1515 domain_info->trusted_domain_count);
1516 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1518 for (i=0;i<ret3;i++) {
1519 status = fill_one_domain_info(mem_ctx,
1520 dce_call->conn->dce_ctx->lp_ctx,
1522 &domain_info->trusted_domains[i],
1524 NT_STATUS_NOT_OK_RETURN(status);
1527 status = fill_one_domain_info(mem_ctx,
1528 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1529 &domain_info->trusted_domains[i], true, true);
1530 NT_STATUS_NOT_OK_RETURN(status);
1532 /* Sets the supported encryption types */
1533 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1534 "msDS-SupportedEncryptionTypes",
1535 default_supported_enc_types);
1537 /* Other host domain informations */
1539 lsa_policy_info = talloc(mem_ctx,
1540 struct netr_LsaPolicyInformation);
1541 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1542 ZERO_STRUCTP(lsa_policy_info);
1544 domain_info->lsa_policy = *lsa_policy_info;
1546 /* The DNS hostname is only returned back when there is a chance
1548 if ((r->in.query->workstation_info->workstation_flags
1549 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1550 domain_info->dns_hostname.string = old_dns_hostname;
1552 domain_info->dns_hostname.string = NULL;
1555 domain_info->workstation_flags =
1556 r->in.query->workstation_info->workstation_flags;
1558 r->out.info->domain_info = domain_info;
1560 case 2: /* LSA policy information - not used at the moment */
1561 lsa_policy_info = talloc(mem_ctx,
1562 struct netr_LsaPolicyInformation);
1563 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1564 ZERO_STRUCTP(lsa_policy_info);
1566 r->out.info->lsa_policy_info = lsa_policy_info;
1569 return NT_STATUS_INVALID_LEVEL;
1573 return NT_STATUS_OK;
1578 netr_ServerPasswordGet
1580 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1581 struct netr_ServerPasswordGet *r)
1583 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1588 netr_NETRLOGONSENDTOSAM
1590 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1591 struct netr_NETRLOGONSENDTOSAM *r)
1593 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1598 netr_DsRGetDCNameEx2
1600 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1601 TALLOC_CTX *mem_ctx,
1602 struct netr_DsRGetDCNameEx2 *r)
1604 struct ldb_context *sam_ctx;
1605 struct netr_DsRGetDCNameInfo *info;
1606 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1607 const struct tsocket_address *remote_address;
1609 const char *server_site_name;
1611 struct netlogon_samlogon_response response;
1613 const char *dc_name = NULL;
1614 const char *domain_name = NULL;
1616 ZERO_STRUCTP(r->out.info);
1618 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1619 dce_call->conn->auth_state.session_info, 0);
1620 if (sam_ctx == NULL) {
1621 return WERR_DS_UNAVAILABLE;
1624 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1625 if (tsocket_address_is_inet(remote_address, "ip")) {
1626 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1627 W_ERROR_HAVE_NO_MEMORY(addr);
1630 /* "server_unc" is ignored by w2k3 */
1632 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1633 return WERR_INVALID_FLAGS;
1636 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1637 r->in.flags & DS_PDC_REQUIRED &&
1638 r->in.flags & DS_KDC_REQUIRED) {
1639 return WERR_INVALID_FLAGS;
1641 if (r->in.flags & DS_IS_FLAT_NAME &&
1642 r->in.flags & DS_IS_DNS_NAME) {
1643 return WERR_INVALID_FLAGS;
1645 if (r->in.flags & DS_RETURN_DNS_NAME &&
1646 r->in.flags & DS_RETURN_FLAT_NAME) {
1647 return WERR_INVALID_FLAGS;
1649 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1650 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1651 return WERR_INVALID_FLAGS;
1654 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1656 (DS_DIRECTORY_SERVICE_REQUIRED |
1657 DS_DIRECTORY_SERVICE_PREFERRED |
1658 DS_GC_SERVER_REQUIRED |
1661 return WERR_INVALID_FLAGS;
1664 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1666 return WERR_INVALID_FLAGS;
1669 /* Proof server site parameter "site_name" if it was specified */
1670 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1671 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1672 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1673 server_site_name) != 0)) {
1674 return WERR_NO_SUCH_DOMAIN;
1677 guid_str = r->in.domain_guid != NULL ?
1678 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1680 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1684 r->in.client_account,
1686 NETLOGON_NT_VERSION_5EX_WITH_IP,
1687 lp_ctx, &response, true);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 return ntstatus_to_werror(status);
1692 if (r->in.flags & DS_RETURN_DNS_NAME) {
1693 dc_name = response.data.nt5_ex.pdc_dns_name;
1694 domain_name = response.data.nt5_ex.dns_domain;
1695 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1696 dc_name = response.data.nt5_ex.pdc_name;
1697 domain_name = response.data.nt5_ex.domain_name;
1701 * TODO: autodetect what we need to return
1702 * based on the given arguments
1704 dc_name = response.data.nt5_ex.pdc_name;
1705 domain_name = response.data.nt5_ex.domain_name;
1708 if (!dc_name || !dc_name[0]) {
1709 return WERR_NO_SUCH_DOMAIN;
1712 if (!domain_name || !domain_name[0]) {
1713 return WERR_NO_SUCH_DOMAIN;
1716 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1717 W_ERROR_HAVE_NO_MEMORY(info);
1718 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1719 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1720 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1721 response.data.nt5_ex.sockaddr.pdc_ip);
1722 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1723 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1724 info->domain_guid = response.data.nt5_ex.domain_uuid;
1725 info->domain_name = domain_name;
1726 info->forest_name = response.data.nt5_ex.forest;
1727 info->dc_flags = response.data.nt5_ex.server_type;
1728 info->dc_site_name = response.data.nt5_ex.server_site;
1729 info->client_site_name = response.data.nt5_ex.client_site;
1731 *r->out.info = info;
1739 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1740 struct netr_DsRGetDCNameEx *r)
1742 struct netr_DsRGetDCNameEx2 r2;
1747 r2.in.server_unc = r->in.server_unc;
1748 r2.in.client_account = NULL;
1750 r2.in.domain_guid = r->in.domain_guid;
1751 r2.in.domain_name = r->in.domain_name;
1752 r2.in.site_name = r->in.site_name;
1753 r2.in.flags = r->in.flags;
1754 r2.out.info = r->out.info;
1756 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1764 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1765 struct netr_DsRGetDCName *r)
1767 struct netr_DsRGetDCNameEx2 r2;
1772 r2.in.server_unc = r->in.server_unc;
1773 r2.in.client_account = NULL;
1775 r2.in.domain_name = r->in.domain_name;
1776 r2.in.domain_guid = r->in.domain_guid;
1778 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1779 r2.in.flags = r->in.flags;
1780 r2.out.info = r->out.info;
1782 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1787 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1789 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1790 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1792 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1797 netr_NetrEnumerateTrustedDomainsEx
1799 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1800 struct netr_NetrEnumerateTrustedDomainsEx *r)
1802 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1807 netr_DsRAddressToSitenamesExW
1809 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1810 struct netr_DsRAddressToSitenamesExW *r)
1812 struct ldb_context *sam_ctx;
1813 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1814 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1815 sa_family_t sin_family;
1816 struct sockaddr_in *addr;
1818 struct sockaddr_in6 *addr6;
1819 char addr_str[INET6_ADDRSTRLEN];
1821 char addr_str[INET_ADDRSTRLEN];
1827 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1828 dce_call->conn->auth_state.session_info, 0);
1829 if (sam_ctx == NULL) {
1830 return WERR_DS_UNAVAILABLE;
1833 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1834 W_ERROR_HAVE_NO_MEMORY(ctr);
1838 ctr->count = r->in.count;
1839 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1840 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1841 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1842 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1844 for (i=0; i<ctr->count; i++) {
1845 ctr->sitename[i].string = NULL;
1846 ctr->subnetname[i].string = NULL;
1848 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1851 /* The first two byte of the buffer are reserved for the
1852 * "sin_family" but for now only the first one is used. */
1853 sin_family = r->in.addresses[i].buffer[0];
1855 switch (sin_family) {
1857 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1860 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1861 res = inet_ntop(AF_INET, &addr->sin_addr,
1862 addr_str, sizeof(addr_str));
1866 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1869 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1870 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1871 addr_str, sizeof(addr_str));
1882 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1886 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1887 ctr->subnetname[i].string = subnet_name;
1895 netr_DsRAddressToSitenamesW
1897 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1898 struct netr_DsRAddressToSitenamesW *r)
1900 struct netr_DsRAddressToSitenamesExW r2;
1901 struct netr_DsRAddressToSitenamesWCtr *ctr;
1907 r2.in.server_name = r->in.server_name;
1908 r2.in.count = r->in.count;
1909 r2.in.addresses = r->in.addresses;
1911 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1912 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1914 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1915 W_ERROR_HAVE_NO_MEMORY(ctr);
1919 ctr->count = r->in.count;
1920 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1921 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1923 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1925 for (i=0; i<ctr->count; i++) {
1926 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1934 netr_DsrGetDcSiteCoverageW
1936 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1937 struct netr_DsrGetDcSiteCoverageW *r)
1939 struct ldb_context *sam_ctx;
1940 struct DcSitesCtr *ctr;
1941 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1943 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1944 dce_call->conn->auth_state.session_info, 0);
1945 if (sam_ctx == NULL) {
1946 return WERR_DS_UNAVAILABLE;
1949 ctr = talloc(mem_ctx, struct DcSitesCtr);
1950 W_ERROR_HAVE_NO_MEMORY(ctr);
1954 /* For now only return our default site */
1956 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1957 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1958 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1959 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1965 #define GET_CHECK_STR(dest, mem, msg, attr) \
1968 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
1970 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1971 "without flatname\n", \
1972 ldb_dn_get_linearized(msg->dn))); \
1975 dest = talloc_strdup(mem, s); \
1976 W_ERROR_HAVE_NO_MEMORY(dest); \
1980 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1981 struct ldb_context *sam_ctx,
1982 struct netr_DomainTrustList *trusts,
1983 uint32_t trust_flags)
1985 struct ldb_dn *system_dn;
1986 struct ldb_message **dom_res = NULL;
1987 const char *trust_attrs[] = { "flatname", "trustPartner",
1988 "securityIdentifier", "trustDirection",
1989 "trustType", "trustAttributes", NULL };
1994 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1995 NETR_TRUST_FLAG_OUTBOUND))) {
1996 return WERR_INVALID_FLAGS;
1999 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2000 ldb_get_default_basedn(sam_ctx),
2001 "(&(objectClass=container)(cn=System))");
2003 return WERR_GENERAL_FAILURE;
2006 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2007 &dom_res, trust_attrs,
2008 "(objectclass=trustedDomain)");
2010 for (i = 0; i < ret; i++) {
2011 unsigned int trust_dir;
2014 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2015 "trustDirection", 0);
2017 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2018 flags |= NETR_TRUST_FLAG_INBOUND;
2020 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2021 flags |= NETR_TRUST_FLAG_OUTBOUND;
2024 if (!(flags & trust_flags)) {
2025 /* this trust direction was not requested */
2030 trusts->array = talloc_realloc(trusts, trusts->array,
2031 struct netr_DomainTrust,
2033 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2035 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2036 dom_res[i], "flatname");
2037 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2038 dom_res[i], "trustPartner");
2040 trusts->array[n].trust_flags = flags;
2041 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2042 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2043 /* TODO: find if we have parent in the list */
2044 trusts->array[n].parent_index = 0;
2047 trusts->array[n].trust_type =
2048 ldb_msg_find_attr_as_uint(dom_res[i],
2050 trusts->array[n].trust_attributes =
2051 ldb_msg_find_attr_as_uint(dom_res[i],
2052 "trustAttributes", 0);
2054 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2055 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2056 struct dom_sid zero_sid;
2057 ZERO_STRUCT(zero_sid);
2058 trusts->array[n].sid =
2059 dom_sid_dup(trusts, &zero_sid);
2061 trusts->array[n].sid =
2062 samdb_result_dom_sid(trusts, dom_res[i],
2063 "securityIdentifier");
2065 trusts->array[n].guid = GUID_zero();
2067 trusts->count = n + 1;
2070 talloc_free(dom_res);
2075 netr_DsrEnumerateDomainTrusts
2077 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2078 TALLOC_CTX *mem_ctx,
2079 struct netr_DsrEnumerateDomainTrusts *r)
2081 struct netr_DomainTrustList *trusts;
2082 struct ldb_context *sam_ctx;
2084 struct ldb_message **dom_res;
2085 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2086 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2087 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2091 if (r->in.trust_flags & 0xFFFFFE00) {
2092 return WERR_INVALID_FLAGS;
2095 /* TODO: turn to hard check once we are sure this is 100% correct */
2096 if (!r->in.server_name) {
2097 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2098 "But received NULL!\n", dnsdomain));
2100 p = strchr(r->in.server_name, '.');
2102 DEBUG(3, ("Invalid domain! Expected name in domain "
2103 "[%s]. But received [%s]!\n",
2104 dnsdomain, r->in.server_name));
2105 p = r->in.server_name;
2109 if (strcasecmp(p, dnsdomain)) {
2110 DEBUG(3, ("Invalid domain! Expected name in domain "
2111 "[%s]. But received [%s]!\n",
2112 dnsdomain, r->in.server_name));
2116 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2117 W_ERROR_HAVE_NO_MEMORY(trusts);
2120 r->out.trusts = trusts;
2122 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2123 dce_call->conn->auth_state.session_info, 0);
2124 if (sam_ctx == NULL) {
2125 return WERR_GENERAL_FAILURE;
2128 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2129 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2131 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2132 trusts, r->in.trust_flags);
2133 W_ERROR_NOT_OK_RETURN(werr);
2136 /* NOTE: we currently are always the root of the forest */
2137 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2138 uint32_t n = trusts->count;
2140 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2141 &dom_res, dom_attrs);
2143 return WERR_GENERAL_FAILURE;
2146 trusts->count = n + 1;
2147 trusts->array = talloc_realloc(trusts, trusts->array,
2148 struct netr_DomainTrust,
2150 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2152 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2153 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2154 trusts->array[n].trust_flags =
2155 NETR_TRUST_FLAG_NATIVE |
2156 NETR_TRUST_FLAG_TREEROOT |
2157 NETR_TRUST_FLAG_IN_FOREST |
2158 NETR_TRUST_FLAG_PRIMARY;
2159 /* we are always the root domain for now */
2160 trusts->array[n].parent_index = 0;
2161 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2162 trusts->array[n].trust_attributes = 0;
2163 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2166 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2168 talloc_free(dom_res);
2176 netr_DsrDeregisterDNSHostRecords
2178 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2179 struct netr_DsrDeregisterDNSHostRecords *r)
2181 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2186 netr_ServerTrustPasswordsGet
2188 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2189 struct netr_ServerTrustPasswordsGet *r)
2191 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2195 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2196 struct ldb_context *sam_ctx,
2197 struct loadparm_context *lp_ctx,
2198 struct lsa_ForestTrustInformation *info)
2200 struct lsa_ForestTrustDomainInfo *domain_info;
2201 struct lsa_ForestTrustRecord *e;
2202 struct ldb_message **dom_res;
2203 const char * const dom_attrs[] = { "objectSid", NULL };
2206 /* we need to provide 2 entries:
2207 * 1. the Root Forest name
2208 * 2. the Domain Information
2212 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2213 W_ERROR_HAVE_NO_MEMORY(info->entries);
2215 /* Forest root info */
2216 e = talloc(info, struct lsa_ForestTrustRecord);
2217 W_ERROR_HAVE_NO_MEMORY(e);
2220 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2221 e->time = 0; /* so far always 0 in trces. */
2222 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2224 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2226 info->entries[0] = e;
2229 e = talloc(info, struct lsa_ForestTrustRecord);
2230 W_ERROR_HAVE_NO_MEMORY(e);
2232 /* get our own domain info */
2233 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2235 return WERR_GENERAL_FAILURE;
2238 /* TODO: check if disabled and set flags accordingly */
2240 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2241 e->time = 0; /* so far always 0 in traces. */
2243 domain_info = &e->forest_trust_data.domain_info;
2244 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2246 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2247 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2249 info->entries[1] = e;
2251 talloc_free(dom_res);
2257 netr_DsRGetForestTrustInformation
2259 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2260 TALLOC_CTX *mem_ctx,
2261 struct netr_DsRGetForestTrustInformation *r)
2263 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2264 struct lsa_ForestTrustInformation *info, **info_ptr;
2265 struct ldb_context *sam_ctx;
2268 if (r->in.flags & 0xFFFFFFFE) {
2269 return WERR_INVALID_FLAGS;
2272 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2273 dce_call->conn->auth_state.session_info, 0);
2274 if (sam_ctx == NULL) {
2275 return WERR_GENERAL_FAILURE;
2278 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2279 if (!samdb_is_pdc(sam_ctx)) {
2280 return WERR_NERR_NOTPRIMARY;
2283 if (r->in.trusted_domain_name == NULL) {
2284 return WERR_INVALID_FLAGS;
2287 /* TODO: establish an schannel connection with
2288 * r->in.trusted_domain_name and perform a
2289 * netr_GetForestTrustInformation call against it */
2291 /* for now return not implementd */
2292 return WERR_CALL_NOT_IMPLEMENTED;
2295 /* TODO: check r->in.server_name is our name */
2297 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2298 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2300 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2301 W_ERROR_HAVE_NO_MEMORY(info);
2303 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2304 W_ERROR_NOT_OK_RETURN(werr);
2307 r->out.forest_trust_info = info_ptr;
2314 netr_GetForestTrustInformation
2316 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2317 TALLOC_CTX *mem_ctx,
2318 struct netr_GetForestTrustInformation *r)
2320 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2321 struct netlogon_creds_CredentialState *creds;
2322 struct lsa_ForestTrustInformation *info, **info_ptr;
2323 struct ldb_context *sam_ctx;
2327 status = dcesrv_netr_creds_server_step_check(dce_call,
2329 r->in.computer_name,
2331 r->out.return_authenticator,
2333 if (!NT_STATUS_IS_OK(status)) {
2337 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2338 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2339 return NT_STATUS_NOT_IMPLEMENTED;
2342 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2343 dce_call->conn->auth_state.session_info, 0);
2344 if (sam_ctx == NULL) {
2345 return NT_STATUS_UNSUCCESSFUL;
2348 /* TODO: check r->in.server_name is our name */
2350 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2352 return NT_STATUS_NO_MEMORY;
2354 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2356 return NT_STATUS_NO_MEMORY;
2359 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2360 if (!W_ERROR_IS_OK(werr)) {
2361 return werror_to_ntstatus(werr);
2365 r->out.forest_trust_info = info_ptr;
2367 return NT_STATUS_OK;
2372 netr_ServerGetTrustInfo
2374 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2375 struct netr_ServerGetTrustInfo *r)
2377 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2383 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2384 struct netr_Unused47 *r)
2386 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2390 struct netr_dnsupdate_RODC_state {
2391 struct dcesrv_call_state *dce_call;
2392 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2393 struct dnsupdate_RODC *r2;
2397 called when the forwarded RODC dns update request is finished
2399 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2401 struct netr_dnsupdate_RODC_state *st =
2402 tevent_req_callback_data(subreq,
2403 struct netr_dnsupdate_RODC_state);
2406 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2407 TALLOC_FREE(subreq);
2408 if (!NT_STATUS_IS_OK(status)) {
2409 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2410 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2413 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2415 status = dcesrv_reply(st->dce_call);
2416 if (!NT_STATUS_IS_OK(status)) {
2417 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2422 netr_DsrUpdateReadOnlyServerDnsRecords
2424 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2425 TALLOC_CTX *mem_ctx,
2426 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2428 struct netlogon_creds_CredentialState *creds;
2430 struct dcerpc_binding_handle *binding_handle;
2431 struct netr_dnsupdate_RODC_state *st;
2432 struct tevent_req *subreq;
2434 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2436 r->in.computer_name,
2438 r->out.return_authenticator,
2440 NT_STATUS_NOT_OK_RETURN(nt_status);
2442 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2443 return NT_STATUS_ACCESS_DENIED;
2446 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2447 NT_STATUS_HAVE_NO_MEMORY(st);
2449 st->dce_call = dce_call;
2451 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2452 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2454 st->r2->in.dom_sid = creds->sid;
2455 st->r2->in.site_name = r->in.site_name;
2456 st->r2->in.dns_ttl = r->in.dns_ttl;
2457 st->r2->in.dns_names = r->in.dns_names;
2458 st->r2->out.dns_names = r->out.dns_names;
2460 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2461 "dnsupdate", &ndr_table_irpc);
2462 if (binding_handle == NULL) {
2463 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2464 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2465 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2468 /* forward the call */
2469 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2470 binding_handle, st->r2);
2471 NT_STATUS_HAVE_NO_MEMORY(subreq);
2473 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2475 /* setup the callback */
2476 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2478 return NT_STATUS_OK;
2482 /* include the generated boilerplate */
2483 #include "librpc/gen_ndr/ndr_netlogon_s.c"