2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "cldap_server/cldap_server.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
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[] = { "sAMAccountName", "dNSHostName",
1300 "msDS-SupportedEncryptionTypes", NULL };
1301 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1302 struct ldb_context *sam_ctx;
1303 struct ldb_message **res1, **res2, **res3, *new_msg;
1304 struct ldb_dn *workstation_dn;
1305 struct netr_DomainInformation *domain_info;
1306 struct netr_LsaPolicyInformation *lsa_policy_info;
1307 struct netr_OsVersionInfoEx *os_version;
1308 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1309 bool update_dns_hostname = true;
1313 status = dcesrv_netr_creds_server_step_check(dce_call,
1315 r->in.computer_name,
1317 r->out.return_authenticator,
1319 if (!NT_STATUS_IS_OK(status)) {
1320 DEBUG(0,(__location__ " Bad credentials - error\n"));
1322 NT_STATUS_NOT_OK_RETURN(status);
1324 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1325 dce_call->conn->dce_ctx->lp_ctx,
1326 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1327 if (sam_ctx == NULL) {
1328 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1331 switch (r->in.level) {
1332 case 1: /* Domain information */
1334 if (r->in.query->workstation_info == NULL) {
1335 return NT_STATUS_INVALID_PARAMETER;
1338 /* Prepares the workstation DN */
1339 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1340 dom_sid_string(mem_ctx, creds->sid));
1341 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1343 /* Lookup for attributes in workstation object */
1344 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1347 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1350 /* Gets the sam account name which is checked against the DNS
1351 * hostname parameter. */
1352 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1355 if (sam_account_name == NULL) {
1356 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1360 * Checks that the sam account name without a possible "$"
1361 * matches as prefix with the DNS hostname in the workstation
1364 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1365 strcspn(sam_account_name, "$"));
1366 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1367 if (r->in.query->workstation_info->dns_hostname != NULL) {
1368 prefix2 = talloc_strndup(mem_ctx,
1369 r->in.query->workstation_info->dns_hostname,
1370 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1371 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1373 if (strcasecmp(prefix1, prefix2) != 0) {
1374 update_dns_hostname = false;
1377 update_dns_hostname = false;
1380 /* Gets the old DNS hostname */
1381 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1386 * Updates the DNS hostname when the client wishes that the
1387 * server should handle this for him
1388 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1389 * obviously only checked when we do already have a
1391 * See MS-NRPC section 3.5.4.3.9
1393 if ((old_dns_hostname != NULL) &&
1394 (r->in.query->workstation_info->workstation_flags
1395 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1396 update_dns_hostname = false;
1399 /* Gets host informations and put them into our directory */
1401 new_msg = ldb_msg_new(mem_ctx);
1402 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1404 new_msg->dn = workstation_dn;
1406 /* Sets the OS name */
1407 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1409 r->in.query->workstation_info->os_name.string);
1410 if (ret != LDB_SUCCESS) {
1411 return NT_STATUS_NO_MEMORY;
1415 * Sets informations from "os_version". On an empty structure
1416 * the values are cleared.
1418 if (r->in.query->workstation_info->os_version.os != NULL) {
1419 os_version = &r->in.query->workstation_info->os_version.os->os;
1421 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1422 "operatingSystemServicePack",
1423 os_version->CSDVersion);
1424 if (ret != LDB_SUCCESS) {
1425 return NT_STATUS_NO_MEMORY;
1428 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1429 "operatingSystemVersion",
1430 talloc_asprintf(mem_ctx,
1432 os_version->MajorVersion,
1433 os_version->MinorVersion,
1434 os_version->BuildNumber));
1435 if (ret != LDB_SUCCESS) {
1436 return NT_STATUS_NO_MEMORY;
1439 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1440 "operatingSystemServicePack");
1441 if (ret != LDB_SUCCESS) {
1442 return NT_STATUS_NO_MEMORY;
1445 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1446 "operatingSystemVersion");
1447 if (ret != LDB_SUCCESS) {
1448 return NT_STATUS_NO_MEMORY;
1453 * If the boolean "update_dns_hostname" remained true, then we
1454 * are fine to start the update.
1456 if (update_dns_hostname) {
1457 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1459 r->in.query->workstation_info->dns_hostname);
1460 if (ret != LDB_SUCCESS) {
1461 return NT_STATUS_NO_MEMORY;
1464 /* This manual "servicePrincipalName" generation is
1465 * still needed! Since the update in the samldb LDB
1466 * module does only work if the entries already exist
1467 * which isn't always the case. */
1468 ret = ldb_msg_add_string(new_msg,
1469 "servicePrincipalName",
1470 talloc_asprintf(new_msg, "HOST/%s",
1471 r->in.computer_name));
1472 if (ret != LDB_SUCCESS) {
1473 return NT_STATUS_NO_MEMORY;
1476 ret = ldb_msg_add_string(new_msg,
1477 "servicePrincipalName",
1478 talloc_asprintf(new_msg, "HOST/%s",
1479 r->in.query->workstation_info->dns_hostname));
1480 if (ret != LDB_SUCCESS) {
1481 return NT_STATUS_NO_MEMORY;
1485 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1486 DEBUG(3,("Impossible to update samdb: %s\n",
1487 ldb_errstring(sam_ctx)));
1490 talloc_free(new_msg);
1492 /* Writes back the domain information */
1494 /* We need to do two searches. The first will pull our primary
1495 domain and the second will pull any trusted domains. Our
1496 primary domain is also a "trusted" domain, so we need to
1497 put the primary domain into the lists of returned trusts as
1499 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1502 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1505 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1506 "(objectClass=trustedDomain)");
1508 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1511 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1512 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1514 ZERO_STRUCTP(domain_info);
1516 /* Informations about the local and trusted domains */
1518 status = fill_one_domain_info(mem_ctx,
1519 dce_call->conn->dce_ctx->lp_ctx,
1520 sam_ctx, res2[0], &domain_info->primary_domain,
1522 NT_STATUS_NOT_OK_RETURN(status);
1524 domain_info->trusted_domain_count = ret3 + 1;
1525 domain_info->trusted_domains = talloc_array(mem_ctx,
1526 struct netr_OneDomainInfo,
1527 domain_info->trusted_domain_count);
1528 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1530 for (i=0;i<ret3;i++) {
1531 status = fill_one_domain_info(mem_ctx,
1532 dce_call->conn->dce_ctx->lp_ctx,
1534 &domain_info->trusted_domains[i],
1536 NT_STATUS_NOT_OK_RETURN(status);
1539 status = fill_one_domain_info(mem_ctx,
1540 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1541 &domain_info->trusted_domains[i], true, true);
1542 NT_STATUS_NOT_OK_RETURN(status);
1544 /* Sets the supported encryption types */
1545 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1546 "msDS-SupportedEncryptionTypes",
1547 default_supported_enc_types);
1549 /* Other host domain informations */
1551 lsa_policy_info = talloc(mem_ctx,
1552 struct netr_LsaPolicyInformation);
1553 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1554 ZERO_STRUCTP(lsa_policy_info);
1556 domain_info->lsa_policy = *lsa_policy_info;
1558 /* The DNS hostname is only returned back when there is a chance
1560 if ((r->in.query->workstation_info->workstation_flags
1561 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1562 domain_info->dns_hostname.string = old_dns_hostname;
1564 domain_info->dns_hostname.string = NULL;
1567 domain_info->workstation_flags =
1568 r->in.query->workstation_info->workstation_flags;
1570 r->out.info->domain_info = domain_info;
1572 case 2: /* LSA policy information - not used at the moment */
1573 lsa_policy_info = talloc(mem_ctx,
1574 struct netr_LsaPolicyInformation);
1575 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1576 ZERO_STRUCTP(lsa_policy_info);
1578 r->out.info->lsa_policy_info = lsa_policy_info;
1581 return NT_STATUS_INVALID_LEVEL;
1585 return NT_STATUS_OK;
1590 netr_ServerPasswordGet
1592 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1593 struct netr_ServerPasswordGet *r)
1595 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1600 netr_NETRLOGONSENDTOSAM
1602 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1603 struct netr_NETRLOGONSENDTOSAM *r)
1605 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1610 netr_DsRGetDCNameEx2
1612 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1613 TALLOC_CTX *mem_ctx,
1614 struct netr_DsRGetDCNameEx2 *r)
1616 struct ldb_context *sam_ctx;
1617 struct netr_DsRGetDCNameInfo *info;
1618 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1619 const struct tsocket_address *remote_address;
1621 const char *server_site_name;
1623 struct netlogon_samlogon_response response;
1625 const char *dc_name = NULL;
1626 const char *domain_name = NULL;
1628 ZERO_STRUCTP(r->out.info);
1630 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1631 dce_call->conn->auth_state.session_info, 0);
1632 if (sam_ctx == NULL) {
1633 return WERR_DS_UNAVAILABLE;
1636 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1637 if (tsocket_address_is_inet(remote_address, "ip")) {
1638 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1639 W_ERROR_HAVE_NO_MEMORY(addr);
1642 /* "server_unc" is ignored by w2k3 */
1644 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1645 return WERR_INVALID_FLAGS;
1648 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1649 r->in.flags & DS_PDC_REQUIRED &&
1650 r->in.flags & DS_KDC_REQUIRED) {
1651 return WERR_INVALID_FLAGS;
1653 if (r->in.flags & DS_IS_FLAT_NAME &&
1654 r->in.flags & DS_IS_DNS_NAME) {
1655 return WERR_INVALID_FLAGS;
1657 if (r->in.flags & DS_RETURN_DNS_NAME &&
1658 r->in.flags & DS_RETURN_FLAT_NAME) {
1659 return WERR_INVALID_FLAGS;
1661 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1662 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1663 return WERR_INVALID_FLAGS;
1666 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1668 (DS_DIRECTORY_SERVICE_REQUIRED |
1669 DS_DIRECTORY_SERVICE_PREFERRED |
1670 DS_GC_SERVER_REQUIRED |
1673 return WERR_INVALID_FLAGS;
1676 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1678 return WERR_INVALID_FLAGS;
1681 /* Proof server site parameter "site_name" if it was specified */
1682 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1683 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1684 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1685 server_site_name) != 0)) {
1686 return WERR_NO_SUCH_DOMAIN;
1689 guid_str = r->in.domain_guid != NULL ?
1690 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1692 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1696 r->in.client_account,
1698 NETLOGON_NT_VERSION_5EX_WITH_IP,
1699 lp_ctx, &response, true);
1700 if (!NT_STATUS_IS_OK(status)) {
1701 return ntstatus_to_werror(status);
1704 if (r->in.flags & DS_RETURN_DNS_NAME) {
1705 dc_name = response.data.nt5_ex.pdc_dns_name;
1706 domain_name = response.data.nt5_ex.dns_domain;
1707 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1708 dc_name = response.data.nt5_ex.pdc_name;
1709 domain_name = response.data.nt5_ex.domain_name;
1713 * TODO: autodetect what we need to return
1714 * based on the given arguments
1716 dc_name = response.data.nt5_ex.pdc_name;
1717 domain_name = response.data.nt5_ex.domain_name;
1720 if (!dc_name || !dc_name[0]) {
1721 return WERR_NO_SUCH_DOMAIN;
1724 if (!domain_name || !domain_name[0]) {
1725 return WERR_NO_SUCH_DOMAIN;
1728 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1729 W_ERROR_HAVE_NO_MEMORY(info);
1730 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1731 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1732 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1733 response.data.nt5_ex.sockaddr.pdc_ip);
1734 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1735 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1736 info->domain_guid = response.data.nt5_ex.domain_uuid;
1737 info->domain_name = domain_name;
1738 info->forest_name = response.data.nt5_ex.forest;
1739 info->dc_flags = response.data.nt5_ex.server_type;
1740 info->dc_site_name = response.data.nt5_ex.server_site;
1741 info->client_site_name = response.data.nt5_ex.client_site;
1743 *r->out.info = info;
1751 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1752 struct netr_DsRGetDCNameEx *r)
1754 struct netr_DsRGetDCNameEx2 r2;
1759 r2.in.server_unc = r->in.server_unc;
1760 r2.in.client_account = NULL;
1762 r2.in.domain_guid = r->in.domain_guid;
1763 r2.in.domain_name = r->in.domain_name;
1764 r2.in.site_name = r->in.site_name;
1765 r2.in.flags = r->in.flags;
1766 r2.out.info = r->out.info;
1768 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1776 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1777 struct netr_DsRGetDCName *r)
1779 struct netr_DsRGetDCNameEx2 r2;
1784 r2.in.server_unc = r->in.server_unc;
1785 r2.in.client_account = NULL;
1787 r2.in.domain_name = r->in.domain_name;
1788 r2.in.domain_guid = r->in.domain_guid;
1790 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1791 r2.in.flags = r->in.flags;
1792 r2.out.info = r->out.info;
1794 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1799 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1801 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1802 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1804 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1809 netr_NetrEnumerateTrustedDomainsEx
1811 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1812 struct netr_NetrEnumerateTrustedDomainsEx *r)
1814 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1819 netr_DsRAddressToSitenamesExW
1821 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1822 struct netr_DsRAddressToSitenamesExW *r)
1824 struct ldb_context *sam_ctx;
1825 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1826 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1827 sa_family_t sin_family;
1828 struct sockaddr_in *addr;
1830 struct sockaddr_in6 *addr6;
1831 char addr_str[INET6_ADDRSTRLEN];
1833 char addr_str[INET_ADDRSTRLEN];
1839 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1840 dce_call->conn->auth_state.session_info, 0);
1841 if (sam_ctx == NULL) {
1842 return WERR_DS_UNAVAILABLE;
1845 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1846 W_ERROR_HAVE_NO_MEMORY(ctr);
1850 ctr->count = r->in.count;
1851 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1852 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1853 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1854 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1856 for (i=0; i<ctr->count; i++) {
1857 ctr->sitename[i].string = NULL;
1858 ctr->subnetname[i].string = NULL;
1860 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1863 /* The first two byte of the buffer are reserved for the
1864 * "sin_family" but for now only the first one is used. */
1865 sin_family = r->in.addresses[i].buffer[0];
1867 switch (sin_family) {
1869 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1872 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1873 res = inet_ntop(AF_INET, &addr->sin_addr,
1874 addr_str, sizeof(addr_str));
1878 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1881 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1882 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1883 addr_str, sizeof(addr_str));
1894 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1898 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1899 ctr->subnetname[i].string = subnet_name;
1907 netr_DsRAddressToSitenamesW
1909 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1910 struct netr_DsRAddressToSitenamesW *r)
1912 struct netr_DsRAddressToSitenamesExW r2;
1913 struct netr_DsRAddressToSitenamesWCtr *ctr;
1919 r2.in.server_name = r->in.server_name;
1920 r2.in.count = r->in.count;
1921 r2.in.addresses = r->in.addresses;
1923 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1924 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1926 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1927 W_ERROR_HAVE_NO_MEMORY(ctr);
1931 ctr->count = r->in.count;
1932 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1933 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1935 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1937 for (i=0; i<ctr->count; i++) {
1938 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1946 netr_DsrGetDcSiteCoverageW
1948 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1949 struct netr_DsrGetDcSiteCoverageW *r)
1951 struct ldb_context *sam_ctx;
1952 struct DcSitesCtr *ctr;
1953 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1955 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1956 dce_call->conn->auth_state.session_info, 0);
1957 if (sam_ctx == NULL) {
1958 return WERR_DS_UNAVAILABLE;
1961 ctr = talloc(mem_ctx, struct DcSitesCtr);
1962 W_ERROR_HAVE_NO_MEMORY(ctr);
1966 /* For now only return our default site */
1968 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1969 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1970 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1971 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1977 #define GET_CHECK_STR(dest, mem, msg, attr) \
1980 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
1982 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1983 "without flatname\n", \
1984 ldb_dn_get_linearized(msg->dn))); \
1987 dest = talloc_strdup(mem, s); \
1988 W_ERROR_HAVE_NO_MEMORY(dest); \
1992 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1993 struct ldb_context *sam_ctx,
1994 struct netr_DomainTrustList *trusts,
1995 uint32_t trust_flags)
1997 struct ldb_dn *system_dn;
1998 struct ldb_message **dom_res = NULL;
1999 const char *trust_attrs[] = { "flatname", "trustPartner",
2000 "securityIdentifier", "trustDirection",
2001 "trustType", "trustAttributes", NULL };
2006 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2007 NETR_TRUST_FLAG_OUTBOUND))) {
2008 return WERR_INVALID_FLAGS;
2011 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2012 ldb_get_default_basedn(sam_ctx),
2013 "(&(objectClass=container)(cn=System))");
2015 return WERR_GENERAL_FAILURE;
2018 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2019 &dom_res, trust_attrs,
2020 "(objectclass=trustedDomain)");
2022 for (i = 0; i < ret; i++) {
2023 unsigned int trust_dir;
2026 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2027 "trustDirection", 0);
2029 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2030 flags |= NETR_TRUST_FLAG_INBOUND;
2032 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2033 flags |= NETR_TRUST_FLAG_OUTBOUND;
2036 if (!(flags & trust_flags)) {
2037 /* this trust direction was not requested */
2042 trusts->array = talloc_realloc(trusts, trusts->array,
2043 struct netr_DomainTrust,
2045 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2047 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2048 dom_res[i], "flatname");
2049 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2050 dom_res[i], "trustPartner");
2052 trusts->array[n].trust_flags = flags;
2053 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2054 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2055 /* TODO: find if we have parent in the list */
2056 trusts->array[n].parent_index = 0;
2059 trusts->array[n].trust_type =
2060 ldb_msg_find_attr_as_uint(dom_res[i],
2062 trusts->array[n].trust_attributes =
2063 ldb_msg_find_attr_as_uint(dom_res[i],
2064 "trustAttributes", 0);
2066 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2067 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2068 struct dom_sid zero_sid;
2069 ZERO_STRUCT(zero_sid);
2070 trusts->array[n].sid =
2071 dom_sid_dup(trusts, &zero_sid);
2073 trusts->array[n].sid =
2074 samdb_result_dom_sid(trusts, dom_res[i],
2075 "securityIdentifier");
2077 trusts->array[n].guid = GUID_zero();
2079 trusts->count = n + 1;
2082 talloc_free(dom_res);
2087 netr_DsrEnumerateDomainTrusts
2089 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2090 TALLOC_CTX *mem_ctx,
2091 struct netr_DsrEnumerateDomainTrusts *r)
2093 struct netr_DomainTrustList *trusts;
2094 struct ldb_context *sam_ctx;
2096 struct ldb_message **dom_res;
2097 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2098 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2099 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2103 if (r->in.trust_flags & 0xFFFFFE00) {
2104 return WERR_INVALID_FLAGS;
2107 /* TODO: turn to hard check once we are sure this is 100% correct */
2108 if (!r->in.server_name) {
2109 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2110 "But received NULL!\n", dnsdomain));
2112 p = strchr(r->in.server_name, '.');
2114 DEBUG(3, ("Invalid domain! Expected name in domain "
2115 "[%s]. But received [%s]!\n",
2116 dnsdomain, r->in.server_name));
2117 p = r->in.server_name;
2121 if (strcasecmp(p, dnsdomain)) {
2122 DEBUG(3, ("Invalid domain! Expected name in domain "
2123 "[%s]. But received [%s]!\n",
2124 dnsdomain, r->in.server_name));
2128 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2129 W_ERROR_HAVE_NO_MEMORY(trusts);
2132 r->out.trusts = trusts;
2134 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2135 dce_call->conn->auth_state.session_info, 0);
2136 if (sam_ctx == NULL) {
2137 return WERR_GENERAL_FAILURE;
2140 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2141 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2143 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2144 trusts, r->in.trust_flags);
2145 W_ERROR_NOT_OK_RETURN(werr);
2148 /* NOTE: we currently are always the root of the forest */
2149 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2150 uint32_t n = trusts->count;
2152 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2153 &dom_res, dom_attrs);
2155 return WERR_GENERAL_FAILURE;
2158 trusts->count = n + 1;
2159 trusts->array = talloc_realloc(trusts, trusts->array,
2160 struct netr_DomainTrust,
2162 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2164 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2165 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2166 trusts->array[n].trust_flags =
2167 NETR_TRUST_FLAG_NATIVE |
2168 NETR_TRUST_FLAG_TREEROOT |
2169 NETR_TRUST_FLAG_IN_FOREST |
2170 NETR_TRUST_FLAG_PRIMARY;
2171 /* we are always the root domain for now */
2172 trusts->array[n].parent_index = 0;
2173 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2174 trusts->array[n].trust_attributes = 0;
2175 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2178 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2180 talloc_free(dom_res);
2188 netr_DsrDeregisterDNSHostRecords
2190 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2191 struct netr_DsrDeregisterDNSHostRecords *r)
2193 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2198 netr_ServerTrustPasswordsGet
2200 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2201 struct netr_ServerTrustPasswordsGet *r)
2203 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2207 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2208 struct ldb_context *sam_ctx,
2209 struct loadparm_context *lp_ctx,
2210 struct lsa_ForestTrustInformation *info)
2212 struct lsa_ForestTrustDomainInfo *domain_info;
2213 struct lsa_ForestTrustRecord *e;
2214 struct ldb_message **dom_res;
2215 const char * const dom_attrs[] = { "objectSid", NULL };
2218 /* we need to provide 2 entries:
2219 * 1. the Root Forest name
2220 * 2. the Domain Information
2224 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2225 W_ERROR_HAVE_NO_MEMORY(info->entries);
2227 /* Forest root info */
2228 e = talloc(info, struct lsa_ForestTrustRecord);
2229 W_ERROR_HAVE_NO_MEMORY(e);
2232 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2233 e->time = 0; /* so far always 0 in trces. */
2234 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2236 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2238 info->entries[0] = e;
2241 e = talloc(info, struct lsa_ForestTrustRecord);
2242 W_ERROR_HAVE_NO_MEMORY(e);
2244 /* get our own domain info */
2245 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2247 return WERR_GENERAL_FAILURE;
2250 /* TODO: check if disabled and set flags accordingly */
2252 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2253 e->time = 0; /* so far always 0 in traces. */
2255 domain_info = &e->forest_trust_data.domain_info;
2256 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2258 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2259 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2261 info->entries[1] = e;
2263 talloc_free(dom_res);
2269 netr_DsRGetForestTrustInformation
2271 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2272 TALLOC_CTX *mem_ctx,
2273 struct netr_DsRGetForestTrustInformation *r)
2275 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2276 struct lsa_ForestTrustInformation *info, **info_ptr;
2277 struct ldb_context *sam_ctx;
2280 if (r->in.flags & 0xFFFFFFFE) {
2281 return WERR_INVALID_FLAGS;
2284 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2285 dce_call->conn->auth_state.session_info, 0);
2286 if (sam_ctx == NULL) {
2287 return WERR_GENERAL_FAILURE;
2290 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2291 if (!samdb_is_pdc(sam_ctx)) {
2292 return WERR_NERR_NOTPRIMARY;
2295 if (r->in.trusted_domain_name == NULL) {
2296 return WERR_INVALID_FLAGS;
2299 /* TODO: establish an schannel connection with
2300 * r->in.trusted_domain_name and perform a
2301 * netr_GetForestTrustInformation call against it */
2303 /* for now return not implementd */
2304 return WERR_CALL_NOT_IMPLEMENTED;
2307 /* TODO: check r->in.server_name is our name */
2309 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2310 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2312 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2313 W_ERROR_HAVE_NO_MEMORY(info);
2315 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2316 W_ERROR_NOT_OK_RETURN(werr);
2319 r->out.forest_trust_info = info_ptr;
2326 netr_GetForestTrustInformation
2328 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2329 TALLOC_CTX *mem_ctx,
2330 struct netr_GetForestTrustInformation *r)
2332 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2333 struct netlogon_creds_CredentialState *creds;
2334 struct lsa_ForestTrustInformation *info, **info_ptr;
2335 struct ldb_context *sam_ctx;
2339 status = dcesrv_netr_creds_server_step_check(dce_call,
2341 r->in.computer_name,
2343 r->out.return_authenticator,
2345 if (!NT_STATUS_IS_OK(status)) {
2349 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2350 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2351 return NT_STATUS_NOT_IMPLEMENTED;
2354 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2355 dce_call->conn->auth_state.session_info, 0);
2356 if (sam_ctx == NULL) {
2357 return NT_STATUS_UNSUCCESSFUL;
2360 /* TODO: check r->in.server_name is our name */
2362 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2364 return NT_STATUS_NO_MEMORY;
2366 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2368 return NT_STATUS_NO_MEMORY;
2371 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2372 if (!W_ERROR_IS_OK(werr)) {
2373 return werror_to_ntstatus(werr);
2377 r->out.forest_trust_info = info_ptr;
2379 return NT_STATUS_OK;
2384 netr_ServerGetTrustInfo
2386 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2387 struct netr_ServerGetTrustInfo *r)
2389 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2395 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2396 struct netr_Unused47 *r)
2398 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2402 struct netr_dnsupdate_RODC_state {
2403 struct dcesrv_call_state *dce_call;
2404 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2405 struct dnsupdate_RODC *r2;
2409 called when the forwarded RODC dns update request is finished
2411 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2413 struct netr_dnsupdate_RODC_state *st =
2414 tevent_req_callback_data(subreq,
2415 struct netr_dnsupdate_RODC_state);
2418 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2419 TALLOC_FREE(subreq);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2422 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2425 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2427 status = dcesrv_reply(st->dce_call);
2428 if (!NT_STATUS_IS_OK(status)) {
2429 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2434 netr_DsrUpdateReadOnlyServerDnsRecords
2436 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2437 TALLOC_CTX *mem_ctx,
2438 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2440 struct netlogon_creds_CredentialState *creds;
2442 struct dcerpc_binding_handle *binding_handle;
2443 struct netr_dnsupdate_RODC_state *st;
2444 struct tevent_req *subreq;
2446 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2448 r->in.computer_name,
2450 r->out.return_authenticator,
2452 NT_STATUS_NOT_OK_RETURN(nt_status);
2454 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2455 return NT_STATUS_ACCESS_DENIED;
2458 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2459 NT_STATUS_HAVE_NO_MEMORY(st);
2461 st->dce_call = dce_call;
2463 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2464 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2466 st->r2->in.dom_sid = creds->sid;
2467 st->r2->in.site_name = r->in.site_name;
2468 st->r2->in.dns_ttl = r->in.dns_ttl;
2469 st->r2->in.dns_names = r->in.dns_names;
2470 st->r2->out.dns_names = r->out.dns_names;
2472 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2473 "dnsupdate", &ndr_table_irpc);
2474 if (binding_handle == NULL) {
2475 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2476 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2477 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2480 /* forward the call */
2481 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2482 binding_handle, st->r2);
2483 NT_STATUS_HAVE_NO_MEMORY(subreq);
2485 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2487 /* setup the callback */
2488 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2490 return NT_STATUS_OK;
2494 /* include the generated boilerplate */
2495 #include "librpc/gen_ndr/ndr_netlogon_s.c"