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);
534 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
536 switch (r->in.logon_level) {
537 case NetlogonInteractiveInformation:
538 case NetlogonServiceInformation:
539 case NetlogonInteractiveTransitiveInformation:
540 case NetlogonServiceTransitiveInformation:
541 if (r->in.logon->password == NULL) {
542 return NT_STATUS_INVALID_PARAMETER;
545 switch (r->in.validation_level) {
546 case NetlogonValidationSamInfo: /* 2 */
547 case NetlogonValidationSamInfo2: /* 3 */
548 case NetlogonValidationSamInfo4: /* 6 */
551 return NT_STATUS_INVALID_INFO_CLASS;
555 case NetlogonNetworkInformation:
556 case NetlogonNetworkTransitiveInformation:
557 if (r->in.logon->network == NULL) {
558 return NT_STATUS_INVALID_PARAMETER;
561 switch (r->in.validation_level) {
562 case NetlogonValidationSamInfo: /* 2 */
563 case NetlogonValidationSamInfo2: /* 3 */
564 case NetlogonValidationSamInfo4: /* 6 */
567 return NT_STATUS_INVALID_INFO_CLASS;
572 case NetlogonGenericInformation:
573 if (r->in.logon->generic == NULL) {
574 return NT_STATUS_INVALID_PARAMETER;
577 switch (r->in.validation_level) {
578 /* TODO: case NetlogonValidationGenericInfo: 4 */
579 case NetlogonValidationGenericInfo2: /* 5 */
582 return NT_STATUS_INVALID_INFO_CLASS;
587 return NT_STATUS_INVALID_PARAMETER;
594 netr_LogonSamLogon_base
596 This version of the function allows other wrappers to say 'do not check the credentials'
598 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
600 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
601 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
603 struct auth_context *auth_context;
604 struct auth_usersupplied_info *user_info;
605 struct auth_user_info_dc *user_info_dc;
607 static const char zeros[16];
608 struct netr_SamBaseInfo *sam;
609 struct netr_SamInfo2 *sam2;
610 struct netr_SamInfo3 *sam3;
611 struct netr_SamInfo6 *sam6;
613 *r->out.authoritative = 1;
615 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
616 NT_STATUS_HAVE_NO_MEMORY(user_info);
618 switch (r->in.logon_level) {
619 case NetlogonInteractiveInformation:
620 case NetlogonServiceInformation:
621 case NetlogonInteractiveTransitiveInformation:
622 case NetlogonServiceTransitiveInformation:
623 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
624 netlogon_creds_arcfour_crypt(creds,
625 r->in.logon->password->lmpassword.hash,
626 sizeof(r->in.logon->password->lmpassword.hash));
627 netlogon_creds_arcfour_crypt(creds,
628 r->in.logon->password->ntpassword.hash,
629 sizeof(r->in.logon->password->ntpassword.hash));
631 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
632 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
635 /* TODO: we need to deny anonymous access here */
636 nt_status = auth_context_create(mem_ctx,
637 dce_call->event_ctx, dce_call->msg_ctx,
638 dce_call->conn->dce_ctx->lp_ctx,
640 NT_STATUS_NOT_OK_RETURN(nt_status);
642 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
643 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
644 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
645 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
647 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
648 user_info->password_state = AUTH_PASSWORD_HASH;
650 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
651 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
652 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
654 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
655 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
656 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
659 case NetlogonNetworkInformation:
660 case NetlogonNetworkTransitiveInformation:
662 /* TODO: we need to deny anonymous access here */
663 nt_status = auth_context_create(mem_ctx,
664 dce_call->event_ctx, dce_call->msg_ctx,
665 dce_call->conn->dce_ctx->lp_ctx,
667 NT_STATUS_NOT_OK_RETURN(nt_status);
669 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
670 NT_STATUS_NOT_OK_RETURN(nt_status);
672 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
673 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
674 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
675 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
677 user_info->password_state = AUTH_PASSWORD_RESPONSE;
678 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
679 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
684 case NetlogonGenericInformation:
686 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
687 netlogon_creds_arcfour_crypt(creds,
688 r->in.logon->generic->data, r->in.logon->generic->length);
690 /* Using DES to verify kerberos tickets makes no sense */
691 return NT_STATUS_INVALID_PARAMETER;
694 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
696 struct dcerpc_binding_handle *irpc_handle;
697 struct kdc_check_generic_kerberos check;
698 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
699 NT_STATUS_HAVE_NO_MEMORY(generic);
700 *r->out.authoritative = 1;
702 /* TODO: Describe and deal with these flags */
705 r->out.validation->generic = generic;
707 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
711 if (irpc_handle == NULL) {
712 return NT_STATUS_NO_LOGON_SERVERS;
715 check.in.generic_request =
716 data_blob_const(r->in.logon->generic->data,
717 r->in.logon->generic->length);
719 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
722 if (!NT_STATUS_IS_OK(status)) {
725 generic->length = check.out.generic_reply.length;
726 generic->data = check.out.generic_reply.data;
730 /* Until we get an implemetnation of these other packages */
731 return NT_STATUS_INVALID_PARAMETER;
734 return NT_STATUS_INVALID_PARAMETER;
737 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
738 /* TODO: set *r->out.authoritative = 0 on specific errors */
739 NT_STATUS_NOT_OK_RETURN(nt_status);
741 switch (r->in.validation_level) {
743 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
744 NT_STATUS_NOT_OK_RETURN(nt_status);
746 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
747 NT_STATUS_HAVE_NO_MEMORY(sam2);
750 /* And put into the talloc tree */
751 talloc_steal(sam2, sam);
752 r->out.validation->sam2 = sam2;
758 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
761 NT_STATUS_NOT_OK_RETURN(nt_status);
763 r->out.validation->sam3 = sam3;
769 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
772 NT_STATUS_NOT_OK_RETURN(nt_status);
774 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
775 NT_STATUS_HAVE_NO_MEMORY(sam6);
776 sam6->base = sam3->base;
778 sam6->sidcount = sam3->sidcount;
779 sam6->sids = sam3->sids;
781 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
782 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
783 sam->account_name.string, sam6->dns_domainname.string);
784 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
785 /* And put into the talloc tree */
786 talloc_steal(sam6, sam3);
788 r->out.validation->sam6 = sam6;
792 return NT_STATUS_INVALID_INFO_CLASS;
795 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
796 /* It appears that level 6 is not individually encrypted */
797 if ((r->in.validation_level != 6) &&
798 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
799 /* This key is sent unencrypted without the ARCFOUR flag set */
800 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
801 netlogon_creds_arcfour_crypt(creds,
803 sizeof(sam->key.key));
807 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
808 /* It appears that level 6 is not individually encrypted */
809 if ((r->in.validation_level != 6) &&
810 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
811 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
812 netlogon_creds_arcfour_crypt(creds,
814 sizeof(sam->LMSessKey.key));
816 netlogon_creds_des_encrypt_LMKey(creds,
821 /* TODO: Describe and deal with these flags */
827 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
828 struct netr_LogonSamLogonEx *r)
831 struct netlogon_creds_CredentialState *creds;
833 *r->out.authoritative = 1;
835 nt_status = dcesrv_netr_LogonSamLogon_check(r);
836 if (!NT_STATUS_IS_OK(nt_status)) {
840 nt_status = schannel_get_creds_state(mem_ctx,
841 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
842 r->in.computer_name, &creds);
843 if (!NT_STATUS_IS_OK(nt_status)) {
847 if (!dce_call->conn->auth_state.auth_info ||
848 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
849 return NT_STATUS_ACCESS_DENIED;
851 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
855 netr_LogonSamLogonWithFlags
858 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
859 struct netr_LogonSamLogonWithFlags *r)
862 struct netlogon_creds_CredentialState *creds;
863 struct netr_LogonSamLogonEx r2;
865 struct netr_Authenticator *return_authenticator;
869 r2.in.server_name = r->in.server_name;
870 r2.in.computer_name = r->in.computer_name;
871 r2.in.logon_level = r->in.logon_level;
872 r2.in.logon = r->in.logon;
873 r2.in.validation_level = r->in.validation_level;
874 r2.in.flags = r->in.flags;
875 r2.out.validation = r->out.validation;
876 r2.out.authoritative = r->out.authoritative;
877 r2.out.flags = r->out.flags;
879 *r->out.authoritative = 1;
881 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
882 if (!NT_STATUS_IS_OK(nt_status)) {
886 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
887 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
889 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
892 r->in.credential, return_authenticator,
894 NT_STATUS_NOT_OK_RETURN(nt_status);
896 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
898 r->out.return_authenticator = return_authenticator;
906 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
907 struct netr_LogonSamLogon *r)
909 struct netr_LogonSamLogonWithFlags r2;
915 r2.in.server_name = r->in.server_name;
916 r2.in.computer_name = r->in.computer_name;
917 r2.in.credential = r->in.credential;
918 r2.in.return_authenticator = r->in.return_authenticator;
919 r2.in.logon_level = r->in.logon_level;
920 r2.in.logon = r->in.logon;
921 r2.in.validation_level = r->in.validation_level;
922 r2.in.flags = &flags;
923 r2.out.validation = r->out.validation;
924 r2.out.authoritative = r->out.authoritative;
925 r2.out.flags = &flags;
927 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
929 r->out.return_authenticator = r2.out.return_authenticator;
938 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
939 struct netr_LogonSamLogoff *r)
941 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
949 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
950 struct netr_DatabaseDeltas *r)
952 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
959 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
960 struct netr_DatabaseSync2 *r)
962 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
963 return NT_STATUS_NOT_IMPLEMENTED;
970 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
971 struct netr_DatabaseSync *r)
973 struct netr_DatabaseSync2 r2;
978 r2.in.logon_server = r->in.logon_server;
979 r2.in.computername = r->in.computername;
980 r2.in.credential = r->in.credential;
981 r2.in.database_id = r->in.database_id;
982 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
983 r2.in.sync_context = r->in.sync_context;
984 r2.out.sync_context = r->out.sync_context;
985 r2.out.delta_enum_array = r->out.delta_enum_array;
986 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
988 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
997 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
998 struct netr_AccountDeltas *r)
1000 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1001 return NT_STATUS_NOT_IMPLEMENTED;
1008 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1009 struct netr_AccountSync *r)
1011 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1012 return NT_STATUS_NOT_IMPLEMENTED;
1019 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1020 struct netr_GetDcName *r)
1022 const char * const attrs[] = { NULL };
1023 struct ldb_context *sam_ctx;
1024 struct ldb_message **res;
1025 struct ldb_dn *domain_dn;
1030 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1031 * that the domainname needs to be a valid netbios domain
1032 * name, if it is not NULL.
1034 if (r->in.domainname) {
1035 const char *dot = strchr(r->in.domainname, '.');
1036 size_t len = strlen(r->in.domainname);
1038 if (dot || len > 15) {
1039 return WERR_DCNOTFOUND;
1043 * TODO: Should we also varify that only valid
1044 * netbios name characters are used?
1048 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1049 dce_call->conn->dce_ctx->lp_ctx,
1050 dce_call->conn->auth_state.session_info, 0);
1051 if (sam_ctx == NULL) {
1052 return WERR_DS_UNAVAILABLE;
1055 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1057 if (domain_dn == NULL) {
1058 return WERR_DS_UNAVAILABLE;
1061 ret = gendb_search_dn(sam_ctx, mem_ctx,
1062 domain_dn, &res, attrs);
1064 return WERR_NO_SUCH_DOMAIN;
1067 /* TODO: - return real IP address
1068 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1070 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1071 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1072 W_ERROR_HAVE_NO_MEMORY(dcname);
1074 *r->out.dcname = dcname;
1080 netr_LogonControl2Ex
1082 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1083 struct netr_LogonControl2Ex *r)
1085 return WERR_NOT_SUPPORTED;
1092 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1093 struct netr_LogonControl *r)
1095 struct netr_LogonControl2Ex r2;
1098 if (r->in.level == 0x00000001) {
1101 r2.in.logon_server = r->in.logon_server;
1102 r2.in.function_code = r->in.function_code;
1103 r2.in.level = r->in.level;
1105 r2.out.query = r->out.query;
1107 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1108 } else if (r->in.level == 0x00000002) {
1109 werr = WERR_NOT_SUPPORTED;
1111 werr = WERR_UNKNOWN_LEVEL;
1121 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1122 struct netr_LogonControl2 *r)
1124 struct netr_LogonControl2Ex r2;
1129 r2.in.logon_server = r->in.logon_server;
1130 r2.in.function_code = r->in.function_code;
1131 r2.in.level = r->in.level;
1132 r2.in.data = r->in.data;
1133 r2.out.query = r->out.query;
1135 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1140 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1141 struct ldb_context *sam_ctx,
1142 struct netr_DomainTrustList *trusts,
1143 uint32_t trust_flags);
1148 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1149 struct netr_GetAnyDCName *r)
1151 struct netr_DomainTrustList *trusts;
1152 struct ldb_context *sam_ctx;
1153 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1157 *r->out.dcname = NULL;
1159 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1160 /* if the domainname parameter wasn't set assume our domain */
1161 r->in.domainname = lpcfg_workgroup(lp_ctx);
1164 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1165 dce_call->conn->auth_state.session_info, 0);
1166 if (sam_ctx == NULL) {
1167 return WERR_DS_UNAVAILABLE;
1170 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1171 /* well we asked for a DC of our own domain */
1172 if (samdb_is_pdc(sam_ctx)) {
1173 /* we are the PDC of the specified domain */
1174 return WERR_NO_SUCH_DOMAIN;
1177 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1178 lpcfg_netbios_name(lp_ctx));
1179 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1184 /* Okay, now we have to consider the trusted domains */
1186 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1187 W_ERROR_HAVE_NO_MEMORY(trusts);
1191 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1192 NETR_TRUST_FLAG_INBOUND
1193 | NETR_TRUST_FLAG_OUTBOUND);
1194 W_ERROR_NOT_OK_RETURN(werr);
1196 for (i = 0; i < trusts->count; i++) {
1197 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1198 /* FIXME: Here we need to find a DC for the specified
1199 * trusted domain. */
1201 /* return WERR_OK; */
1202 return WERR_NO_SUCH_DOMAIN;
1206 return WERR_NO_SUCH_DOMAIN;
1213 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1214 struct netr_DatabaseRedo *r)
1216 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1221 netr_NetrEnumerateTrustedDomains
1223 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1224 struct netr_NetrEnumerateTrustedDomains *r)
1226 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1231 netr_LogonGetCapabilities
1233 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1234 struct netr_LogonGetCapabilities *r)
1236 /* we don't support AES yet */
1237 return NT_STATUS_NOT_IMPLEMENTED;
1242 netr_NETRLOGONSETSERVICEBITS
1244 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1245 struct netr_NETRLOGONSETSERVICEBITS *r)
1247 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1252 netr_LogonGetTrustRid
1254 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1255 struct netr_LogonGetTrustRid *r)
1257 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1262 netr_NETRLOGONCOMPUTESERVERDIGEST
1264 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1265 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1267 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1272 netr_NETRLOGONCOMPUTECLIENTDIGEST
1274 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1275 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1277 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1285 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1286 struct netr_DsRGetSiteName *r)
1288 struct ldb_context *sam_ctx;
1289 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1291 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1292 dce_call->conn->auth_state.session_info, 0);
1293 if (sam_ctx == NULL) {
1294 return WERR_DS_UNAVAILABLE;
1297 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1298 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1305 fill in a netr_OneDomainInfo from a ldb search result
1307 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1308 struct loadparm_context *lp_ctx,
1309 struct ldb_context *sam_ctx,
1310 struct ldb_message *res,
1311 struct netr_OneDomainInfo *info,
1312 bool is_local, bool is_trust_list)
1316 if (is_trust_list) {
1317 /* w2k8 only fills this on trusted domains */
1318 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1319 info->trust_extension.length = 16;
1320 info->trust_extension.info->flags =
1321 NETR_TRUST_FLAG_TREEROOT |
1322 NETR_TRUST_FLAG_IN_FOREST |
1323 NETR_TRUST_FLAG_PRIMARY |
1324 NETR_TRUST_FLAG_NATIVE;
1326 info->trust_extension.info->parent_index = 0; /* should be index into array
1328 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1329 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1332 if (is_trust_list) {
1333 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1334 info->dns_forestname.string = NULL;
1336 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1337 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1338 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1339 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1343 info->domainname.string = lpcfg_workgroup(lp_ctx);
1344 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1345 info->domain_guid = samdb_result_guid(res, "objectGUID");
1346 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1348 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1349 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1350 info->domain_guid = samdb_result_guid(res, "objectGUID");
1351 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1353 if (!is_trust_list) {
1354 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1357 return NT_STATUS_OK;
1361 netr_LogonGetDomainInfo
1362 this is called as part of the ADS domain logon procedure.
1364 It has an important role in convaying details about the client, such
1365 as Operating System, Version, Service Pack etc.
1367 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1368 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1370 struct netlogon_creds_CredentialState *creds;
1371 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1372 "securityIdentifier", "trustPartner", NULL };
1373 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1374 "msDS-SupportedEncryptionTypes", NULL };
1375 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1376 struct ldb_context *sam_ctx;
1377 struct ldb_message **res1, **res2, **res3, *new_msg;
1378 struct ldb_dn *workstation_dn;
1379 struct netr_DomainInformation *domain_info;
1380 struct netr_LsaPolicyInformation *lsa_policy_info;
1381 struct netr_OsVersionInfoEx *os_version;
1382 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1383 bool update_dns_hostname = true;
1387 status = dcesrv_netr_creds_server_step_check(dce_call,
1389 r->in.computer_name,
1391 r->out.return_authenticator,
1393 if (!NT_STATUS_IS_OK(status)) {
1394 DEBUG(0,(__location__ " Bad credentials - error\n"));
1396 NT_STATUS_NOT_OK_RETURN(status);
1398 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1399 dce_call->conn->dce_ctx->lp_ctx,
1400 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1401 if (sam_ctx == NULL) {
1402 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1405 switch (r->in.level) {
1406 case 1: /* Domain information */
1408 if (r->in.query->workstation_info == NULL) {
1409 return NT_STATUS_INVALID_PARAMETER;
1412 /* Prepares the workstation DN */
1413 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1414 dom_sid_string(mem_ctx, creds->sid));
1415 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1417 /* Lookup for attributes in workstation object */
1418 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1421 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1424 /* Gets the sam account name which is checked against the DNS
1425 * hostname parameter. */
1426 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1429 if (sam_account_name == NULL) {
1430 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1434 * Checks that the sam account name without a possible "$"
1435 * matches as prefix with the DNS hostname in the workstation
1438 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1439 strcspn(sam_account_name, "$"));
1440 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1441 if (r->in.query->workstation_info->dns_hostname != NULL) {
1442 prefix2 = talloc_strndup(mem_ctx,
1443 r->in.query->workstation_info->dns_hostname,
1444 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1445 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1447 if (strcasecmp(prefix1, prefix2) != 0) {
1448 update_dns_hostname = false;
1451 update_dns_hostname = false;
1454 /* Gets the old DNS hostname */
1455 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1460 * Updates the DNS hostname when the client wishes that the
1461 * server should handle this for him
1462 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1463 * obviously only checked when we do already have a
1465 * See MS-NRPC section 3.5.4.3.9
1467 if ((old_dns_hostname != NULL) &&
1468 (r->in.query->workstation_info->workstation_flags
1469 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1470 update_dns_hostname = false;
1473 /* Gets host informations and put them into our directory */
1475 new_msg = ldb_msg_new(mem_ctx);
1476 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1478 new_msg->dn = workstation_dn;
1480 /* Sets the OS name */
1481 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1483 r->in.query->workstation_info->os_name.string);
1484 if (ret != LDB_SUCCESS) {
1485 return NT_STATUS_NO_MEMORY;
1489 * Sets informations from "os_version". On an empty structure
1490 * the values are cleared.
1492 if (r->in.query->workstation_info->os_version.os != NULL) {
1493 os_version = &r->in.query->workstation_info->os_version.os->os;
1495 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1496 "operatingSystemServicePack",
1497 os_version->CSDVersion);
1498 if (ret != LDB_SUCCESS) {
1499 return NT_STATUS_NO_MEMORY;
1502 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1503 "operatingSystemVersion",
1504 talloc_asprintf(mem_ctx,
1506 os_version->MajorVersion,
1507 os_version->MinorVersion,
1508 os_version->BuildNumber));
1509 if (ret != LDB_SUCCESS) {
1510 return NT_STATUS_NO_MEMORY;
1513 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1514 "operatingSystemServicePack");
1515 if (ret != LDB_SUCCESS) {
1516 return NT_STATUS_NO_MEMORY;
1519 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1520 "operatingSystemVersion");
1521 if (ret != LDB_SUCCESS) {
1522 return NT_STATUS_NO_MEMORY;
1527 * If the boolean "update_dns_hostname" remained true, then we
1528 * are fine to start the update.
1530 if (update_dns_hostname) {
1531 ret = samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1533 r->in.query->workstation_info->dns_hostname);
1534 if (ret != LDB_SUCCESS) {
1535 return NT_STATUS_NO_MEMORY;
1538 /* This manual "servicePrincipalName" generation is
1539 * still needed! Since the update in the samldb LDB
1540 * module does only work if the entries already exist
1541 * which isn't always the case. */
1542 ret = ldb_msg_add_string(new_msg,
1543 "servicePrincipalName",
1544 talloc_asprintf(new_msg, "HOST/%s",
1545 r->in.computer_name));
1546 if (ret != LDB_SUCCESS) {
1547 return NT_STATUS_NO_MEMORY;
1550 ret = ldb_msg_add_string(new_msg,
1551 "servicePrincipalName",
1552 talloc_asprintf(new_msg, "HOST/%s",
1553 r->in.query->workstation_info->dns_hostname));
1554 if (ret != LDB_SUCCESS) {
1555 return NT_STATUS_NO_MEMORY;
1559 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1560 DEBUG(3,("Impossible to update samdb: %s\n",
1561 ldb_errstring(sam_ctx)));
1564 talloc_free(new_msg);
1566 /* Writes back the domain information */
1568 /* We need to do two searches. The first will pull our primary
1569 domain and the second will pull any trusted domains. Our
1570 primary domain is also a "trusted" domain, so we need to
1571 put the primary domain into the lists of returned trusts as
1573 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1576 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1579 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1580 "(objectClass=trustedDomain)");
1582 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1585 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1586 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1588 ZERO_STRUCTP(domain_info);
1590 /* Informations about the local and trusted domains */
1592 status = fill_one_domain_info(mem_ctx,
1593 dce_call->conn->dce_ctx->lp_ctx,
1594 sam_ctx, res2[0], &domain_info->primary_domain,
1596 NT_STATUS_NOT_OK_RETURN(status);
1598 domain_info->trusted_domain_count = ret3 + 1;
1599 domain_info->trusted_domains = talloc_array(mem_ctx,
1600 struct netr_OneDomainInfo,
1601 domain_info->trusted_domain_count);
1602 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1604 for (i=0;i<ret3;i++) {
1605 status = fill_one_domain_info(mem_ctx,
1606 dce_call->conn->dce_ctx->lp_ctx,
1608 &domain_info->trusted_domains[i],
1610 NT_STATUS_NOT_OK_RETURN(status);
1613 status = fill_one_domain_info(mem_ctx,
1614 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1615 &domain_info->trusted_domains[i], true, true);
1616 NT_STATUS_NOT_OK_RETURN(status);
1618 /* Sets the supported encryption types */
1619 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1620 "msDS-SupportedEncryptionTypes",
1621 default_supported_enc_types);
1623 /* Other host domain informations */
1625 lsa_policy_info = talloc(mem_ctx,
1626 struct netr_LsaPolicyInformation);
1627 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1628 ZERO_STRUCTP(lsa_policy_info);
1630 domain_info->lsa_policy = *lsa_policy_info;
1632 /* The DNS hostname is only returned back when there is a chance
1634 if ((r->in.query->workstation_info->workstation_flags
1635 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1636 domain_info->dns_hostname.string = old_dns_hostname;
1638 domain_info->dns_hostname.string = NULL;
1641 domain_info->workstation_flags =
1642 r->in.query->workstation_info->workstation_flags;
1644 r->out.info->domain_info = domain_info;
1646 case 2: /* LSA policy information - not used at the moment */
1647 lsa_policy_info = talloc(mem_ctx,
1648 struct netr_LsaPolicyInformation);
1649 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1650 ZERO_STRUCTP(lsa_policy_info);
1652 r->out.info->lsa_policy_info = lsa_policy_info;
1655 return NT_STATUS_INVALID_LEVEL;
1659 return NT_STATUS_OK;
1664 netr_ServerPasswordGet
1666 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1667 struct netr_ServerPasswordGet *r)
1669 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1674 netr_NETRLOGONSENDTOSAM
1676 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1677 struct netr_NETRLOGONSENDTOSAM *r)
1679 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1684 netr_DsRGetDCNameEx2
1686 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1687 TALLOC_CTX *mem_ctx,
1688 struct netr_DsRGetDCNameEx2 *r)
1690 struct ldb_context *sam_ctx;
1691 struct netr_DsRGetDCNameInfo *info;
1692 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1693 const struct tsocket_address *remote_address;
1695 const char *server_site_name;
1697 struct netlogon_samlogon_response response;
1699 const char *dc_name = NULL;
1700 const char *domain_name = NULL;
1702 ZERO_STRUCTP(r->out.info);
1704 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1705 dce_call->conn->auth_state.session_info, 0);
1706 if (sam_ctx == NULL) {
1707 return WERR_DS_UNAVAILABLE;
1710 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1711 if (tsocket_address_is_inet(remote_address, "ip")) {
1712 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1713 W_ERROR_HAVE_NO_MEMORY(addr);
1716 /* "server_unc" is ignored by w2k3 */
1718 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1719 return WERR_INVALID_FLAGS;
1722 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1723 r->in.flags & DS_PDC_REQUIRED &&
1724 r->in.flags & DS_KDC_REQUIRED) {
1725 return WERR_INVALID_FLAGS;
1727 if (r->in.flags & DS_IS_FLAT_NAME &&
1728 r->in.flags & DS_IS_DNS_NAME) {
1729 return WERR_INVALID_FLAGS;
1731 if (r->in.flags & DS_RETURN_DNS_NAME &&
1732 r->in.flags & DS_RETURN_FLAT_NAME) {
1733 return WERR_INVALID_FLAGS;
1735 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1736 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1737 return WERR_INVALID_FLAGS;
1740 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1742 (DS_DIRECTORY_SERVICE_REQUIRED |
1743 DS_DIRECTORY_SERVICE_PREFERRED |
1744 DS_GC_SERVER_REQUIRED |
1747 return WERR_INVALID_FLAGS;
1750 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1752 return WERR_INVALID_FLAGS;
1755 /* Proof server site parameter "site_name" if it was specified */
1756 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1757 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1758 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1759 server_site_name) != 0)) {
1760 return WERR_NO_SUCH_DOMAIN;
1763 guid_str = r->in.domain_guid != NULL ?
1764 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1766 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1770 r->in.client_account,
1772 NETLOGON_NT_VERSION_5EX_WITH_IP,
1773 lp_ctx, &response, true);
1774 if (!NT_STATUS_IS_OK(status)) {
1775 return ntstatus_to_werror(status);
1778 if (r->in.flags & DS_RETURN_DNS_NAME) {
1779 dc_name = response.data.nt5_ex.pdc_dns_name;
1780 domain_name = response.data.nt5_ex.dns_domain;
1781 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1782 dc_name = response.data.nt5_ex.pdc_name;
1783 domain_name = response.data.nt5_ex.domain_name;
1787 * TODO: autodetect what we need to return
1788 * based on the given arguments
1790 dc_name = response.data.nt5_ex.pdc_name;
1791 domain_name = response.data.nt5_ex.domain_name;
1794 if (!dc_name || !dc_name[0]) {
1795 return WERR_NO_SUCH_DOMAIN;
1798 if (!domain_name || !domain_name[0]) {
1799 return WERR_NO_SUCH_DOMAIN;
1802 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1803 W_ERROR_HAVE_NO_MEMORY(info);
1804 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1805 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1806 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1807 response.data.nt5_ex.sockaddr.pdc_ip);
1808 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1809 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1810 info->domain_guid = response.data.nt5_ex.domain_uuid;
1811 info->domain_name = domain_name;
1812 info->forest_name = response.data.nt5_ex.forest;
1813 info->dc_flags = response.data.nt5_ex.server_type;
1814 info->dc_site_name = response.data.nt5_ex.server_site;
1815 info->client_site_name = response.data.nt5_ex.client_site;
1817 *r->out.info = info;
1825 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1826 struct netr_DsRGetDCNameEx *r)
1828 struct netr_DsRGetDCNameEx2 r2;
1833 r2.in.server_unc = r->in.server_unc;
1834 r2.in.client_account = NULL;
1836 r2.in.domain_guid = r->in.domain_guid;
1837 r2.in.domain_name = r->in.domain_name;
1838 r2.in.site_name = r->in.site_name;
1839 r2.in.flags = r->in.flags;
1840 r2.out.info = r->out.info;
1842 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1850 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1851 struct netr_DsRGetDCName *r)
1853 struct netr_DsRGetDCNameEx2 r2;
1858 r2.in.server_unc = r->in.server_unc;
1859 r2.in.client_account = NULL;
1861 r2.in.domain_name = r->in.domain_name;
1862 r2.in.domain_guid = r->in.domain_guid;
1864 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1865 r2.in.flags = r->in.flags;
1866 r2.out.info = r->out.info;
1868 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1873 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1875 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1876 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1878 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1883 netr_NetrEnumerateTrustedDomainsEx
1885 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1886 struct netr_NetrEnumerateTrustedDomainsEx *r)
1888 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1893 netr_DsRAddressToSitenamesExW
1895 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1896 struct netr_DsRAddressToSitenamesExW *r)
1898 struct ldb_context *sam_ctx;
1899 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1900 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1901 sa_family_t sin_family;
1902 struct sockaddr_in *addr;
1904 struct sockaddr_in6 *addr6;
1905 char addr_str[INET6_ADDRSTRLEN];
1907 char addr_str[INET_ADDRSTRLEN];
1913 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1914 dce_call->conn->auth_state.session_info, 0);
1915 if (sam_ctx == NULL) {
1916 return WERR_DS_UNAVAILABLE;
1919 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1920 W_ERROR_HAVE_NO_MEMORY(ctr);
1924 ctr->count = r->in.count;
1925 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1926 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1927 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1928 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1930 for (i=0; i<ctr->count; i++) {
1931 ctr->sitename[i].string = NULL;
1932 ctr->subnetname[i].string = NULL;
1934 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1937 /* The first two byte of the buffer are reserved for the
1938 * "sin_family" but for now only the first one is used. */
1939 sin_family = r->in.addresses[i].buffer[0];
1941 switch (sin_family) {
1943 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1946 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1947 res = inet_ntop(AF_INET, &addr->sin_addr,
1948 addr_str, sizeof(addr_str));
1952 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1955 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1956 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1957 addr_str, sizeof(addr_str));
1968 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1972 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1973 ctr->subnetname[i].string = subnet_name;
1981 netr_DsRAddressToSitenamesW
1983 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1984 struct netr_DsRAddressToSitenamesW *r)
1986 struct netr_DsRAddressToSitenamesExW r2;
1987 struct netr_DsRAddressToSitenamesWCtr *ctr;
1993 r2.in.server_name = r->in.server_name;
1994 r2.in.count = r->in.count;
1995 r2.in.addresses = r->in.addresses;
1997 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1998 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2000 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2001 W_ERROR_HAVE_NO_MEMORY(ctr);
2005 ctr->count = r->in.count;
2006 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2007 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2009 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2011 for (i=0; i<ctr->count; i++) {
2012 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2020 netr_DsrGetDcSiteCoverageW
2022 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2023 struct netr_DsrGetDcSiteCoverageW *r)
2025 struct ldb_context *sam_ctx;
2026 struct DcSitesCtr *ctr;
2027 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2029 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2030 dce_call->conn->auth_state.session_info, 0);
2031 if (sam_ctx == NULL) {
2032 return WERR_DS_UNAVAILABLE;
2035 ctr = talloc(mem_ctx, struct DcSitesCtr);
2036 W_ERROR_HAVE_NO_MEMORY(ctr);
2040 /* For now only return our default site */
2042 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2043 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2044 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2045 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2051 #define GET_CHECK_STR(dest, mem, msg, attr) \
2054 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
2056 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
2057 "without flatname\n", \
2058 ldb_dn_get_linearized(msg->dn))); \
2061 dest = talloc_strdup(mem, s); \
2062 W_ERROR_HAVE_NO_MEMORY(dest); \
2066 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2067 struct ldb_context *sam_ctx,
2068 struct netr_DomainTrustList *trusts,
2069 uint32_t trust_flags)
2071 struct ldb_dn *system_dn;
2072 struct ldb_message **dom_res = NULL;
2073 const char *trust_attrs[] = { "flatname", "trustPartner",
2074 "securityIdentifier", "trustDirection",
2075 "trustType", "trustAttributes", NULL };
2080 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2081 NETR_TRUST_FLAG_OUTBOUND))) {
2082 return WERR_INVALID_FLAGS;
2085 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2086 ldb_get_default_basedn(sam_ctx),
2087 "(&(objectClass=container)(cn=System))");
2089 return WERR_GENERAL_FAILURE;
2092 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2093 &dom_res, trust_attrs,
2094 "(objectclass=trustedDomain)");
2096 for (i = 0; i < ret; i++) {
2097 unsigned int trust_dir;
2100 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2101 "trustDirection", 0);
2103 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2104 flags |= NETR_TRUST_FLAG_INBOUND;
2106 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2107 flags |= NETR_TRUST_FLAG_OUTBOUND;
2110 if (!(flags & trust_flags)) {
2111 /* this trust direction was not requested */
2116 trusts->array = talloc_realloc(trusts, trusts->array,
2117 struct netr_DomainTrust,
2119 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2121 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2122 dom_res[i], "flatname");
2123 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2124 dom_res[i], "trustPartner");
2126 trusts->array[n].trust_flags = flags;
2127 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2128 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2129 /* TODO: find if we have parent in the list */
2130 trusts->array[n].parent_index = 0;
2133 trusts->array[n].trust_type =
2134 ldb_msg_find_attr_as_uint(dom_res[i],
2136 trusts->array[n].trust_attributes =
2137 ldb_msg_find_attr_as_uint(dom_res[i],
2138 "trustAttributes", 0);
2140 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2141 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2142 struct dom_sid zero_sid;
2143 ZERO_STRUCT(zero_sid);
2144 trusts->array[n].sid =
2145 dom_sid_dup(trusts, &zero_sid);
2147 trusts->array[n].sid =
2148 samdb_result_dom_sid(trusts, dom_res[i],
2149 "securityIdentifier");
2151 trusts->array[n].guid = GUID_zero();
2153 trusts->count = n + 1;
2156 talloc_free(dom_res);
2161 netr_DsrEnumerateDomainTrusts
2163 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2164 TALLOC_CTX *mem_ctx,
2165 struct netr_DsrEnumerateDomainTrusts *r)
2167 struct netr_DomainTrustList *trusts;
2168 struct ldb_context *sam_ctx;
2170 struct ldb_message **dom_res;
2171 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2172 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2173 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2177 if (r->in.trust_flags & 0xFFFFFE00) {
2178 return WERR_INVALID_FLAGS;
2181 /* TODO: turn to hard check once we are sure this is 100% correct */
2182 if (!r->in.server_name) {
2183 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2184 "But received NULL!\n", dnsdomain));
2186 p = strchr(r->in.server_name, '.');
2188 DEBUG(3, ("Invalid domain! Expected name in domain "
2189 "[%s]. But received [%s]!\n",
2190 dnsdomain, r->in.server_name));
2191 p = r->in.server_name;
2195 if (strcasecmp(p, dnsdomain)) {
2196 DEBUG(3, ("Invalid domain! Expected name in domain "
2197 "[%s]. But received [%s]!\n",
2198 dnsdomain, r->in.server_name));
2202 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2203 W_ERROR_HAVE_NO_MEMORY(trusts);
2206 r->out.trusts = trusts;
2208 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2209 dce_call->conn->auth_state.session_info, 0);
2210 if (sam_ctx == NULL) {
2211 return WERR_GENERAL_FAILURE;
2214 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2215 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2217 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2218 trusts, r->in.trust_flags);
2219 W_ERROR_NOT_OK_RETURN(werr);
2222 /* NOTE: we currently are always the root of the forest */
2223 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2224 uint32_t n = trusts->count;
2226 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2227 &dom_res, dom_attrs);
2229 return WERR_GENERAL_FAILURE;
2232 trusts->count = n + 1;
2233 trusts->array = talloc_realloc(trusts, trusts->array,
2234 struct netr_DomainTrust,
2236 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2238 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2239 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2240 trusts->array[n].trust_flags =
2241 NETR_TRUST_FLAG_NATIVE |
2242 NETR_TRUST_FLAG_TREEROOT |
2243 NETR_TRUST_FLAG_IN_FOREST |
2244 NETR_TRUST_FLAG_PRIMARY;
2245 /* we are always the root domain for now */
2246 trusts->array[n].parent_index = 0;
2247 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2248 trusts->array[n].trust_attributes = 0;
2249 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2252 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2254 talloc_free(dom_res);
2262 netr_DsrDeregisterDNSHostRecords
2264 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2265 struct netr_DsrDeregisterDNSHostRecords *r)
2267 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2272 netr_ServerTrustPasswordsGet
2274 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2275 struct netr_ServerTrustPasswordsGet *r)
2277 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2281 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2282 struct ldb_context *sam_ctx,
2283 struct loadparm_context *lp_ctx,
2284 struct lsa_ForestTrustInformation *info)
2286 struct lsa_ForestTrustDomainInfo *domain_info;
2287 struct lsa_ForestTrustRecord *e;
2288 struct ldb_message **dom_res;
2289 const char * const dom_attrs[] = { "objectSid", NULL };
2292 /* we need to provide 2 entries:
2293 * 1. the Root Forest name
2294 * 2. the Domain Information
2298 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2299 W_ERROR_HAVE_NO_MEMORY(info->entries);
2301 /* Forest root info */
2302 e = talloc(info, struct lsa_ForestTrustRecord);
2303 W_ERROR_HAVE_NO_MEMORY(e);
2306 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2307 e->time = 0; /* so far always 0 in trces. */
2308 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2310 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2312 info->entries[0] = e;
2315 e = talloc(info, struct lsa_ForestTrustRecord);
2316 W_ERROR_HAVE_NO_MEMORY(e);
2318 /* get our own domain info */
2319 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2321 return WERR_GENERAL_FAILURE;
2324 /* TODO: check if disabled and set flags accordingly */
2326 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2327 e->time = 0; /* so far always 0 in traces. */
2329 domain_info = &e->forest_trust_data.domain_info;
2330 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2332 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2333 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2335 info->entries[1] = e;
2337 talloc_free(dom_res);
2343 netr_DsRGetForestTrustInformation
2345 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2346 TALLOC_CTX *mem_ctx,
2347 struct netr_DsRGetForestTrustInformation *r)
2349 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2350 struct lsa_ForestTrustInformation *info, **info_ptr;
2351 struct ldb_context *sam_ctx;
2354 if (r->in.flags & 0xFFFFFFFE) {
2355 return WERR_INVALID_FLAGS;
2358 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2359 dce_call->conn->auth_state.session_info, 0);
2360 if (sam_ctx == NULL) {
2361 return WERR_GENERAL_FAILURE;
2364 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2365 if (!samdb_is_pdc(sam_ctx)) {
2366 return WERR_NERR_NOTPRIMARY;
2369 if (r->in.trusted_domain_name == NULL) {
2370 return WERR_INVALID_FLAGS;
2373 /* TODO: establish an schannel connection with
2374 * r->in.trusted_domain_name and perform a
2375 * netr_GetForestTrustInformation call against it */
2377 /* for now return not implementd */
2378 return WERR_CALL_NOT_IMPLEMENTED;
2381 /* TODO: check r->in.server_name is our name */
2383 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2384 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2386 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2387 W_ERROR_HAVE_NO_MEMORY(info);
2389 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2390 W_ERROR_NOT_OK_RETURN(werr);
2393 r->out.forest_trust_info = info_ptr;
2400 netr_GetForestTrustInformation
2402 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2403 TALLOC_CTX *mem_ctx,
2404 struct netr_GetForestTrustInformation *r)
2406 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2407 struct netlogon_creds_CredentialState *creds;
2408 struct lsa_ForestTrustInformation *info, **info_ptr;
2409 struct ldb_context *sam_ctx;
2413 status = dcesrv_netr_creds_server_step_check(dce_call,
2415 r->in.computer_name,
2417 r->out.return_authenticator,
2419 if (!NT_STATUS_IS_OK(status)) {
2423 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2424 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2425 return NT_STATUS_NOT_IMPLEMENTED;
2428 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2429 dce_call->conn->auth_state.session_info, 0);
2430 if (sam_ctx == NULL) {
2431 return NT_STATUS_UNSUCCESSFUL;
2434 /* TODO: check r->in.server_name is our name */
2436 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2438 return NT_STATUS_NO_MEMORY;
2440 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2442 return NT_STATUS_NO_MEMORY;
2445 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2446 if (!W_ERROR_IS_OK(werr)) {
2447 return werror_to_ntstatus(werr);
2451 r->out.forest_trust_info = info_ptr;
2453 return NT_STATUS_OK;
2458 netr_ServerGetTrustInfo
2460 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2461 struct netr_ServerGetTrustInfo *r)
2463 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2469 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2470 struct netr_Unused47 *r)
2472 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2476 struct netr_dnsupdate_RODC_state {
2477 struct dcesrv_call_state *dce_call;
2478 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2479 struct dnsupdate_RODC *r2;
2483 called when the forwarded RODC dns update request is finished
2485 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2487 struct netr_dnsupdate_RODC_state *st =
2488 tevent_req_callback_data(subreq,
2489 struct netr_dnsupdate_RODC_state);
2492 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2493 TALLOC_FREE(subreq);
2494 if (!NT_STATUS_IS_OK(status)) {
2495 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2496 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2499 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2501 status = dcesrv_reply(st->dce_call);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2508 netr_DsrUpdateReadOnlyServerDnsRecords
2510 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2511 TALLOC_CTX *mem_ctx,
2512 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2514 struct netlogon_creds_CredentialState *creds;
2516 struct dcerpc_binding_handle *binding_handle;
2517 struct netr_dnsupdate_RODC_state *st;
2518 struct tevent_req *subreq;
2520 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2522 r->in.computer_name,
2524 r->out.return_authenticator,
2526 NT_STATUS_NOT_OK_RETURN(nt_status);
2528 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2529 return NT_STATUS_ACCESS_DENIED;
2532 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2533 NT_STATUS_HAVE_NO_MEMORY(st);
2535 st->dce_call = dce_call;
2537 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2538 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2540 st->r2->in.dom_sid = creds->sid;
2541 st->r2->in.site_name = r->in.site_name;
2542 st->r2->in.dns_ttl = r->in.dns_ttl;
2543 st->r2->in.dns_names = r->in.dns_names;
2544 st->r2->out.dns_names = r->out.dns_names;
2546 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2547 "dnsupdate", &ndr_table_irpc);
2548 if (binding_handle == NULL) {
2549 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2550 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2551 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2554 /* forward the call */
2555 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2556 binding_handle, st->r2);
2557 NT_STATUS_HAVE_NO_MEMORY(subreq);
2559 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2561 /* setup the callback */
2562 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2564 return NT_STATUS_OK;
2568 /* include the generated boilerplate */
2569 #include "librpc/gen_ndr/ndr_netlogon_s.c"