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 "dsdb/samdb/ldb_modules/util.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
40 #include "lib/socket/netif.h"
42 struct netlogon_server_pipe_state {
43 struct netr_Credential client_challenge;
44 struct netr_Credential server_challenge;
47 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
48 struct netr_ServerReqChallenge *r)
50 struct netlogon_server_pipe_state *pipe_state =
51 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
53 ZERO_STRUCTP(r->out.return_credentials);
55 /* destroyed on pipe shutdown */
58 talloc_free(pipe_state);
59 dce_call->context->private_data = NULL;
62 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
63 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
65 pipe_state->client_challenge = *r->in.credentials;
67 generate_random_buffer(pipe_state->server_challenge.data,
68 sizeof(pipe_state->server_challenge.data));
70 *r->out.return_credentials = pipe_state->server_challenge;
72 dce_call->context->private_data = pipe_state;
77 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
78 struct netr_ServerAuthenticate3 *r)
80 struct netlogon_server_pipe_state *pipe_state =
81 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
82 struct netlogon_creds_CredentialState *creds;
83 struct ldb_context *sam_ctx;
84 struct samr_Password *mach_pwd;
85 uint32_t user_account_control;
87 struct ldb_message **msgs;
89 const char *attrs[] = {"unicodePwd", "userAccountControl",
92 const char *trust_dom_attrs[] = {"flatname", NULL};
93 const char *account_name;
94 uint32_t server_flags = 0;
95 uint32_t negotiate_flags = 0;
96 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
97 bool reject_des_client = !allow_nt4_crypto;
98 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
100 ZERO_STRUCTP(r->out.return_credentials);
103 server_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_SUPPORTS_AES |
126 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
127 NETLOGON_NEG_AUTHENTICATED_RPC;
129 negotiate_flags = *r->in.negotiate_flags & server_flags;
131 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
132 reject_des_client = false;
135 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
136 reject_des_client = false;
137 reject_md5_client = false;
140 if (reject_des_client || reject_md5_client) {
142 * Here we match Windows 2012 and return no flags.
144 *r->out.negotiate_flags = 0;
145 return NT_STATUS_DOWNGRADE_DETECTED;
149 * According to Microsoft (see bugid #6099)
150 * Windows 7 looks at the negotiate_flags
151 * returned in this structure *even if the
152 * call fails with access denied!
154 *r->out.negotiate_flags = negotiate_flags;
156 switch (r->in.secure_channel_type) {
158 case SEC_CHAN_DNS_DOMAIN:
159 case SEC_CHAN_DOMAIN:
164 return NT_STATUS_INVALID_PARAMETER;
166 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
167 r->in.secure_channel_type));
168 return NT_STATUS_INVALID_PARAMETER;
171 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
172 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
173 if (sam_ctx == NULL) {
174 return NT_STATUS_INVALID_SYSTEM_SERVICE;
177 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
178 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
179 const char *flatname;
180 if (!encoded_account) {
181 return NT_STATUS_NO_MEMORY;
184 /* Kill the trailing dot */
185 if (encoded_account[strlen(encoded_account)-1] == '.') {
186 encoded_account[strlen(encoded_account)-1] = '\0';
189 /* pull the user attributes */
190 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
192 "(&(trustPartner=%s)(objectclass=trustedDomain))",
195 if (num_records == 0) {
196 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
198 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
201 if (num_records > 1) {
202 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
203 return NT_STATUS_INTERNAL_DB_CORRUPTION;
206 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
208 /* No flatname for this trust - we can't proceed */
209 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
211 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
214 return NT_STATUS_NO_MEMORY;
218 account_name = r->in.account_name;
221 /* pull the user attributes */
222 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
223 "(&(sAMAccountName=%s)(objectclass=user))",
224 ldb_binary_encode_string(mem_ctx, account_name));
226 if (num_records == 0) {
227 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
228 r->in.account_name));
229 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
232 if (num_records > 1) {
233 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
234 return NT_STATUS_INTERNAL_DB_CORRUPTION;
237 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
239 if (user_account_control & UF_ACCOUNTDISABLE) {
240 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
241 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
244 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
245 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
246 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
247 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
249 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
250 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
251 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
252 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
254 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
256 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
257 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
258 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
259 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
261 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
262 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
263 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
264 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
267 /* we should never reach this */
268 return NT_STATUS_INTERNAL_ERROR;
271 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
272 if (mach_pwd == NULL) {
273 return NT_STATUS_ACCESS_DENIED;
277 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
278 return NT_STATUS_ACCESS_DENIED;
281 creds = netlogon_creds_server_init(mem_ctx,
284 r->in.secure_channel_type,
285 &pipe_state->client_challenge,
286 &pipe_state->server_challenge,
289 r->out.return_credentials,
292 return NT_STATUS_ACCESS_DENIED;
295 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
297 nt_status = schannel_save_creds_state(mem_ctx,
298 dce_call->conn->dce_ctx->lp_ctx,
300 if (!NT_STATUS_IS_OK(nt_status)) {
301 ZERO_STRUCTP(r->out.return_credentials);
305 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
311 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
312 struct netr_ServerAuthenticate *r)
314 struct netr_ServerAuthenticate3 a;
317 * negotiate_flags is used as an [in] parameter
318 * so it need to be initialised.
320 * (I think ... = 0; seems wrong here --metze)
322 uint32_t negotiate_flags_in = 0;
323 uint32_t negotiate_flags_out = 0;
325 a.in.server_name = r->in.server_name;
326 a.in.account_name = r->in.account_name;
327 a.in.secure_channel_type = r->in.secure_channel_type;
328 a.in.computer_name = r->in.computer_name;
329 a.in.credentials = r->in.credentials;
330 a.in.negotiate_flags = &negotiate_flags_in;
332 a.out.return_credentials = r->out.return_credentials;
334 a.out.negotiate_flags = &negotiate_flags_out;
336 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
339 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
340 struct netr_ServerAuthenticate2 *r)
342 struct netr_ServerAuthenticate3 r3;
345 r3.in.server_name = r->in.server_name;
346 r3.in.account_name = r->in.account_name;
347 r3.in.secure_channel_type = r->in.secure_channel_type;
348 r3.in.computer_name = r->in.computer_name;
349 r3.in.credentials = r->in.credentials;
350 r3.out.return_credentials = r->out.return_credentials;
351 r3.in.negotiate_flags = r->in.negotiate_flags;
352 r3.out.negotiate_flags = r->out.negotiate_flags;
355 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
359 * NOTE: The following functions are nearly identical to the ones available in
360 * source3/rpc_server/srv_nelog_nt.c
361 * The reason we keep 2 copies is that they use different structures to
362 * represent the auth_info and the decrpc pipes.
366 * If schannel is required for this call test that it actually is available.
368 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
369 const char *computer_name,
370 bool integrity, bool privacy)
373 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
374 if (!privacy && !integrity) {
378 if ((!privacy && integrity) &&
379 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
383 if ((privacy || integrity) &&
384 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
389 /* test didn't pass */
390 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
393 return NT_STATUS_ACCESS_DENIED;
396 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
398 const char *computer_name,
399 struct netr_Authenticator *received_authenticator,
400 struct netr_Authenticator *return_authenticator,
401 struct netlogon_creds_CredentialState **creds_out)
404 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
405 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
407 if (schannel_global_required) {
408 nt_status = schannel_check_required(auth_info,
411 if (!NT_STATUS_IS_OK(nt_status)) {
416 nt_status = schannel_check_creds_state(mem_ctx,
417 dce_call->conn->dce_ctx->lp_ctx,
419 received_authenticator,
420 return_authenticator,
426 Change the machine account password for the currently connected
427 client. Supplies only the NT#.
430 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
431 struct netr_ServerPasswordSet *r)
433 struct netlogon_creds_CredentialState *creds;
434 struct ldb_context *sam_ctx;
435 const char * const attrs[] = { "unicodePwd", NULL };
436 struct ldb_message **res;
437 struct samr_Password *oldNtHash;
441 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
444 r->in.credential, r->out.return_authenticator,
446 NT_STATUS_NOT_OK_RETURN(nt_status);
448 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);
449 if (sam_ctx == NULL) {
450 return NT_STATUS_INVALID_SYSTEM_SERVICE;
453 netlogon_creds_des_decrypt(creds, r->in.new_password);
455 /* fetch the old password hashes (the NT hash has to exist) */
457 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
458 "(&(objectClass=user)(objectSid=%s))",
459 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
461 return NT_STATUS_WRONG_PASSWORD;
464 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
465 dce_call->conn->dce_ctx->lp_ctx,
466 res[0], NULL, &oldNtHash);
467 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
468 return NT_STATUS_WRONG_PASSWORD;
471 /* Using the sid for the account as the key, set the password */
472 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
474 NULL, /* Don't have plaintext */
475 NULL, r->in.new_password,
476 NULL, oldNtHash, /* Password change */
482 Change the machine account password for the currently connected
483 client. Supplies new plaintext.
485 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
486 struct netr_ServerPasswordSet2 *r)
488 struct netlogon_creds_CredentialState *creds;
489 struct ldb_context *sam_ctx;
490 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
491 struct ldb_message **res;
492 struct samr_Password *oldLmHash, *oldNtHash;
494 DATA_BLOB new_password;
497 struct samr_CryptPassword password_buf;
499 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
502 r->in.credential, r->out.return_authenticator,
504 NT_STATUS_NOT_OK_RETURN(nt_status);
506 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);
507 if (sam_ctx == NULL) {
508 return NT_STATUS_INVALID_SYSTEM_SERVICE;
511 memcpy(password_buf.data, r->in.new_password->data, 512);
512 SIVAL(password_buf.data, 512, r->in.new_password->length);
514 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
515 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
517 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
520 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
521 DEBUG(3,("samr: failed to decode password buffer\n"));
522 return NT_STATUS_WRONG_PASSWORD;
525 /* fetch the old password hashes (at least one of both has to exist) */
527 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
528 "(&(objectClass=user)(objectSid=%s))",
529 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
531 return NT_STATUS_WRONG_PASSWORD;
534 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
535 dce_call->conn->dce_ctx->lp_ctx,
536 res[0], &oldLmHash, &oldNtHash);
537 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
538 return NT_STATUS_WRONG_PASSWORD;
541 /* Using the sid for the account as the key, set the password */
542 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
544 &new_password, /* we have plaintext */
546 oldLmHash, oldNtHash, /* Password change */
555 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
556 struct netr_LogonUasLogon *r)
558 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
565 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
566 struct netr_LogonUasLogoff *r)
568 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
572 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
574 switch (r->in.logon_level) {
575 case NetlogonInteractiveInformation:
576 case NetlogonServiceInformation:
577 case NetlogonInteractiveTransitiveInformation:
578 case NetlogonServiceTransitiveInformation:
579 if (r->in.logon->password == NULL) {
580 return NT_STATUS_INVALID_PARAMETER;
583 switch (r->in.validation_level) {
584 case NetlogonValidationSamInfo: /* 2 */
585 case NetlogonValidationSamInfo2: /* 3 */
586 case NetlogonValidationSamInfo4: /* 6 */
589 return NT_STATUS_INVALID_INFO_CLASS;
593 case NetlogonNetworkInformation:
594 case NetlogonNetworkTransitiveInformation:
595 if (r->in.logon->network == NULL) {
596 return NT_STATUS_INVALID_PARAMETER;
599 switch (r->in.validation_level) {
600 case NetlogonValidationSamInfo: /* 2 */
601 case NetlogonValidationSamInfo2: /* 3 */
602 case NetlogonValidationSamInfo4: /* 6 */
605 return NT_STATUS_INVALID_INFO_CLASS;
610 case NetlogonGenericInformation:
611 if (r->in.logon->generic == NULL) {
612 return NT_STATUS_INVALID_PARAMETER;
615 switch (r->in.validation_level) {
616 /* TODO: case NetlogonValidationGenericInfo: 4 */
617 case NetlogonValidationGenericInfo2: /* 5 */
620 return NT_STATUS_INVALID_INFO_CLASS;
625 return NT_STATUS_INVALID_PARAMETER;
632 netr_LogonSamLogon_base
634 This version of the function allows other wrappers to say 'do not check the credentials'
636 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
638 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
639 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
641 struct auth4_context *auth_context;
642 struct auth_usersupplied_info *user_info;
643 struct auth_user_info_dc *user_info_dc;
645 struct netr_SamBaseInfo *sam;
646 struct netr_SamInfo2 *sam2;
647 struct netr_SamInfo3 *sam3;
648 struct netr_SamInfo6 *sam6;
650 *r->out.authoritative = 1;
652 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
653 NT_STATUS_HAVE_NO_MEMORY(user_info);
655 netlogon_creds_decrypt_samlogon_logon(creds,
659 switch (r->in.logon_level) {
660 case NetlogonInteractiveInformation:
661 case NetlogonServiceInformation:
662 case NetlogonInteractiveTransitiveInformation:
663 case NetlogonServiceTransitiveInformation:
665 /* TODO: we need to deny anonymous access here */
666 nt_status = auth_context_create(mem_ctx,
667 dce_call->event_ctx, dce_call->msg_ctx,
668 dce_call->conn->dce_ctx->lp_ctx,
670 NT_STATUS_NOT_OK_RETURN(nt_status);
672 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
673 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
674 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
675 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
677 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
678 user_info->password_state = AUTH_PASSWORD_HASH;
680 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
681 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
682 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
684 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
685 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
686 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
689 case NetlogonNetworkInformation:
690 case NetlogonNetworkTransitiveInformation:
692 /* TODO: we need to deny anonymous access here */
693 nt_status = auth_context_create(mem_ctx,
694 dce_call->event_ctx, dce_call->msg_ctx,
695 dce_call->conn->dce_ctx->lp_ctx,
697 NT_STATUS_NOT_OK_RETURN(nt_status);
699 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
700 NT_STATUS_NOT_OK_RETURN(nt_status);
702 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
703 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
704 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
705 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
707 user_info->password_state = AUTH_PASSWORD_RESPONSE;
708 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
709 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
714 case NetlogonGenericInformation:
716 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
718 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
721 /* Using DES to verify kerberos tickets makes no sense */
722 return NT_STATUS_INVALID_PARAMETER;
725 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
727 struct dcerpc_binding_handle *irpc_handle;
728 struct kdc_check_generic_kerberos check;
729 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
730 NT_STATUS_HAVE_NO_MEMORY(generic);
731 *r->out.authoritative = 1;
733 /* TODO: Describe and deal with these flags */
736 r->out.validation->generic = generic;
738 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
742 if (irpc_handle == NULL) {
743 return NT_STATUS_NO_LOGON_SERVERS;
746 check.in.generic_request =
747 data_blob_const(r->in.logon->generic->data,
748 r->in.logon->generic->length);
751 * TODO: make this async and avoid
752 * dcerpc_binding_handle_set_sync_ev()
754 dcerpc_binding_handle_set_sync_ev(irpc_handle,
755 dce_call->event_ctx);
756 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
759 if (!NT_STATUS_IS_OK(status)) {
762 generic->length = check.out.generic_reply.length;
763 generic->data = check.out.generic_reply.data;
767 /* Until we get an implemetnation of these other packages */
768 return NT_STATUS_INVALID_PARAMETER;
771 return NT_STATUS_INVALID_PARAMETER;
774 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
775 /* TODO: set *r->out.authoritative = 0 on specific errors */
776 NT_STATUS_NOT_OK_RETURN(nt_status);
778 switch (r->in.validation_level) {
780 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
781 NT_STATUS_NOT_OK_RETURN(nt_status);
783 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
784 NT_STATUS_HAVE_NO_MEMORY(sam2);
787 /* And put into the talloc tree */
788 talloc_steal(sam2, sam);
789 r->out.validation->sam2 = sam2;
795 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
798 NT_STATUS_NOT_OK_RETURN(nt_status);
800 r->out.validation->sam3 = sam3;
806 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
809 NT_STATUS_NOT_OK_RETURN(nt_status);
811 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
812 NT_STATUS_HAVE_NO_MEMORY(sam6);
813 sam6->base = sam3->base;
815 sam6->sidcount = sam3->sidcount;
816 sam6->sids = sam3->sids;
818 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
819 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
820 sam->account_name.string, sam6->dns_domainname.string);
821 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
822 /* And put into the talloc tree */
823 talloc_steal(sam6, sam3);
825 r->out.validation->sam6 = sam6;
829 return NT_STATUS_INVALID_INFO_CLASS;
832 netlogon_creds_encrypt_samlogon_validation(creds,
833 r->in.validation_level,
836 /* TODO: Describe and deal with these flags */
842 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
843 struct netr_LogonSamLogonEx *r)
846 struct netlogon_creds_CredentialState *creds;
848 *r->out.authoritative = 1;
850 nt_status = dcesrv_netr_LogonSamLogon_check(r);
851 if (!NT_STATUS_IS_OK(nt_status)) {
855 nt_status = schannel_get_creds_state(mem_ctx,
856 dce_call->conn->dce_ctx->lp_ctx,
857 r->in.computer_name, &creds);
858 if (!NT_STATUS_IS_OK(nt_status)) {
862 if (!dce_call->conn->auth_state.auth_info ||
863 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
864 return NT_STATUS_ACCESS_DENIED;
866 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
870 netr_LogonSamLogonWithFlags
873 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
874 struct netr_LogonSamLogonWithFlags *r)
877 struct netlogon_creds_CredentialState *creds;
878 struct netr_LogonSamLogonEx r2;
880 struct netr_Authenticator *return_authenticator;
884 r2.in.server_name = r->in.server_name;
885 r2.in.computer_name = r->in.computer_name;
886 r2.in.logon_level = r->in.logon_level;
887 r2.in.logon = r->in.logon;
888 r2.in.validation_level = r->in.validation_level;
889 r2.in.flags = r->in.flags;
890 r2.out.validation = r->out.validation;
891 r2.out.authoritative = r->out.authoritative;
892 r2.out.flags = r->out.flags;
894 *r->out.authoritative = 1;
896 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
897 if (!NT_STATUS_IS_OK(nt_status)) {
901 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
902 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
904 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
907 r->in.credential, return_authenticator,
909 NT_STATUS_NOT_OK_RETURN(nt_status);
911 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
913 r->out.return_authenticator = return_authenticator;
921 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
922 struct netr_LogonSamLogon *r)
924 struct netr_LogonSamLogonWithFlags r2;
930 r2.in.server_name = r->in.server_name;
931 r2.in.computer_name = r->in.computer_name;
932 r2.in.credential = r->in.credential;
933 r2.in.return_authenticator = r->in.return_authenticator;
934 r2.in.logon_level = r->in.logon_level;
935 r2.in.logon = r->in.logon;
936 r2.in.validation_level = r->in.validation_level;
937 r2.in.flags = &flags;
938 r2.out.validation = r->out.validation;
939 r2.out.authoritative = r->out.authoritative;
940 r2.out.flags = &flags;
942 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
944 r->out.return_authenticator = r2.out.return_authenticator;
953 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
954 struct netr_LogonSamLogoff *r)
956 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
964 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
965 struct netr_DatabaseDeltas *r)
967 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
974 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
975 struct netr_DatabaseSync2 *r)
977 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
978 return NT_STATUS_NOT_IMPLEMENTED;
985 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
986 struct netr_DatabaseSync *r)
988 struct netr_DatabaseSync2 r2;
993 r2.in.logon_server = r->in.logon_server;
994 r2.in.computername = r->in.computername;
995 r2.in.credential = r->in.credential;
996 r2.in.database_id = r->in.database_id;
997 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
998 r2.in.sync_context = r->in.sync_context;
999 r2.out.sync_context = r->out.sync_context;
1000 r2.out.delta_enum_array = r->out.delta_enum_array;
1001 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1003 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1012 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1013 struct netr_AccountDeltas *r)
1015 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1016 return NT_STATUS_NOT_IMPLEMENTED;
1023 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1024 struct netr_AccountSync *r)
1026 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1027 return NT_STATUS_NOT_IMPLEMENTED;
1034 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1035 struct netr_GetDcName *r)
1037 const char * const attrs[] = { NULL };
1038 struct ldb_context *sam_ctx;
1039 struct ldb_message **res;
1040 struct ldb_dn *domain_dn;
1045 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1046 * that the domainname needs to be a valid netbios domain
1047 * name, if it is not NULL.
1049 if (r->in.domainname) {
1050 const char *dot = strchr(r->in.domainname, '.');
1051 size_t len = strlen(r->in.domainname);
1053 if (dot || len > 15) {
1054 return WERR_DCNOTFOUND;
1058 * TODO: Should we also varify that only valid
1059 * netbios name characters are used?
1063 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1064 dce_call->conn->dce_ctx->lp_ctx,
1065 dce_call->conn->auth_state.session_info, 0);
1066 if (sam_ctx == NULL) {
1067 return WERR_DS_UNAVAILABLE;
1070 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1072 if (domain_dn == NULL) {
1073 return WERR_NO_SUCH_DOMAIN;
1076 ret = gendb_search_dn(sam_ctx, mem_ctx,
1077 domain_dn, &res, attrs);
1079 return WERR_NO_SUCH_DOMAIN;
1082 /* TODO: - return real IP address
1083 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1085 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1086 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1087 W_ERROR_HAVE_NO_MEMORY(dcname);
1089 *r->out.dcname = dcname;
1095 netr_LogonControl2Ex
1097 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1098 struct netr_LogonControl2Ex *r)
1100 return WERR_NOT_SUPPORTED;
1107 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1108 struct netr_LogonControl *r)
1110 struct netr_LogonControl2Ex r2;
1113 if (r->in.level == 0x00000001) {
1116 r2.in.logon_server = r->in.logon_server;
1117 r2.in.function_code = r->in.function_code;
1118 r2.in.level = r->in.level;
1120 r2.out.query = r->out.query;
1122 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1123 } else if (r->in.level == 0x00000002) {
1124 werr = WERR_NOT_SUPPORTED;
1126 werr = WERR_UNKNOWN_LEVEL;
1136 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1137 struct netr_LogonControl2 *r)
1139 struct netr_LogonControl2Ex r2;
1144 r2.in.logon_server = r->in.logon_server;
1145 r2.in.function_code = r->in.function_code;
1146 r2.in.level = r->in.level;
1147 r2.in.data = r->in.data;
1148 r2.out.query = r->out.query;
1150 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1155 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1156 struct ldb_context *sam_ctx,
1157 struct netr_DomainTrustList *trusts,
1158 uint32_t trust_flags);
1163 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1164 struct netr_GetAnyDCName *r)
1166 struct netr_DomainTrustList *trusts;
1167 struct ldb_context *sam_ctx;
1168 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1172 *r->out.dcname = NULL;
1174 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1175 /* if the domainname parameter wasn't set assume our domain */
1176 r->in.domainname = lpcfg_workgroup(lp_ctx);
1179 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1180 dce_call->conn->auth_state.session_info, 0);
1181 if (sam_ctx == NULL) {
1182 return WERR_DS_UNAVAILABLE;
1185 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1186 /* well we asked for a DC of our own domain */
1187 if (samdb_is_pdc(sam_ctx)) {
1188 /* we are the PDC of the specified domain */
1189 return WERR_NO_SUCH_DOMAIN;
1192 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1193 lpcfg_netbios_name(lp_ctx));
1194 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1199 /* Okay, now we have to consider the trusted domains */
1201 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1202 W_ERROR_HAVE_NO_MEMORY(trusts);
1206 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1207 NETR_TRUST_FLAG_INBOUND
1208 | NETR_TRUST_FLAG_OUTBOUND);
1209 W_ERROR_NOT_OK_RETURN(werr);
1211 for (i = 0; i < trusts->count; i++) {
1212 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1213 /* FIXME: Here we need to find a DC for the specified
1214 * trusted domain. */
1216 /* return WERR_OK; */
1217 return WERR_NO_SUCH_DOMAIN;
1221 return WERR_NO_SUCH_DOMAIN;
1228 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1229 struct netr_DatabaseRedo *r)
1231 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1236 netr_NetrEnumerateTrustedDomains
1238 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1239 struct netr_NetrEnumerateTrustedDomains *r)
1241 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1246 netr_LogonGetCapabilities
1248 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1249 struct netr_LogonGetCapabilities *r)
1251 struct netlogon_creds_CredentialState *creds;
1254 status = dcesrv_netr_creds_server_step_check(dce_call,
1256 r->in.computer_name,
1258 r->out.return_authenticator,
1260 if (!NT_STATUS_IS_OK(status)) {
1261 DEBUG(0,(__location__ " Bad credentials - error\n"));
1263 NT_STATUS_NOT_OK_RETURN(status);
1265 if (r->in.query_level != 1) {
1266 return NT_STATUS_NOT_SUPPORTED;
1269 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1271 return NT_STATUS_OK;
1276 netr_NETRLOGONSETSERVICEBITS
1278 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1279 struct netr_NETRLOGONSETSERVICEBITS *r)
1281 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1286 netr_LogonGetTrustRid
1288 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1289 struct netr_LogonGetTrustRid *r)
1291 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1296 netr_NETRLOGONCOMPUTESERVERDIGEST
1298 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1299 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1301 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1306 netr_NETRLOGONCOMPUTECLIENTDIGEST
1308 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1309 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1311 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1319 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1320 struct netr_DsRGetSiteName *r)
1322 struct ldb_context *sam_ctx;
1323 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1325 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1326 dce_call->conn->auth_state.session_info, 0);
1327 if (sam_ctx == NULL) {
1328 return WERR_DS_UNAVAILABLE;
1332 * We assume to be a DC when we get called over NETLOGON. Hence we
1333 * get our site name always by using "samdb_server_site_name()"
1334 * and not "samdb_client_site_name()".
1336 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1337 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1344 fill in a netr_OneDomainInfo from a ldb search result
1346 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1347 struct loadparm_context *lp_ctx,
1348 struct ldb_context *sam_ctx,
1349 struct ldb_message *res,
1350 struct netr_OneDomainInfo *info,
1351 bool is_local, bool is_trust_list)
1355 if (is_trust_list) {
1356 /* w2k8 only fills this on trusted domains */
1357 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1358 info->trust_extension.length = 16;
1359 info->trust_extension.info->flags =
1360 NETR_TRUST_FLAG_TREEROOT |
1361 NETR_TRUST_FLAG_IN_FOREST |
1362 NETR_TRUST_FLAG_PRIMARY |
1363 NETR_TRUST_FLAG_NATIVE;
1365 info->trust_extension.info->parent_index = 0; /* should be index into array
1367 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1368 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1371 if (is_trust_list) {
1372 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1373 info->dns_forestname.string = NULL;
1375 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1376 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1377 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1378 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1382 info->domainname.string = lpcfg_workgroup(lp_ctx);
1383 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1384 info->domain_guid = samdb_result_guid(res, "objectGUID");
1385 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1387 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1388 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1389 info->domain_guid = samdb_result_guid(res, "objectGUID");
1390 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1392 if (!is_trust_list) {
1393 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1396 return NT_STATUS_OK;
1400 netr_LogonGetDomainInfo
1401 this is called as part of the ADS domain logon procedure.
1403 It has an important role in convaying details about the client, such
1404 as Operating System, Version, Service Pack etc.
1406 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1407 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1409 struct netlogon_creds_CredentialState *creds;
1410 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1411 "securityIdentifier", "trustPartner", NULL };
1412 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1413 "msDS-SupportedEncryptionTypes", NULL };
1414 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1415 struct ldb_context *sam_ctx;
1416 struct ldb_message **res1, **res2, **res3, *new_msg;
1417 struct ldb_dn *workstation_dn;
1418 struct netr_DomainInformation *domain_info;
1419 struct netr_LsaPolicyInformation *lsa_policy_info;
1420 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1421 bool update_dns_hostname = true;
1425 status = dcesrv_netr_creds_server_step_check(dce_call,
1427 r->in.computer_name,
1429 r->out.return_authenticator,
1431 if (!NT_STATUS_IS_OK(status)) {
1432 DEBUG(0,(__location__ " Bad credentials - error\n"));
1434 NT_STATUS_NOT_OK_RETURN(status);
1436 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1437 dce_call->conn->dce_ctx->lp_ctx,
1438 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1439 if (sam_ctx == NULL) {
1440 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1443 switch (r->in.level) {
1444 case 1: /* Domain information */
1446 if (r->in.query->workstation_info == NULL) {
1447 return NT_STATUS_INVALID_PARAMETER;
1450 /* Prepares the workstation DN */
1451 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1452 dom_sid_string(mem_ctx, creds->sid));
1453 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1455 /* Lookup for attributes in workstation object */
1456 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1459 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1462 /* Gets the sam account name which is checked against the DNS
1463 * hostname parameter. */
1464 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1467 if (sam_account_name == NULL) {
1468 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1472 * Checks that the sam account name without a possible "$"
1473 * matches as prefix with the DNS hostname in the workstation
1476 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1477 strcspn(sam_account_name, "$"));
1478 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1479 if (r->in.query->workstation_info->dns_hostname != NULL) {
1480 prefix2 = talloc_strndup(mem_ctx,
1481 r->in.query->workstation_info->dns_hostname,
1482 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1483 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1485 if (strcasecmp(prefix1, prefix2) != 0) {
1486 update_dns_hostname = false;
1489 update_dns_hostname = false;
1492 /* Gets the old DNS hostname */
1493 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1498 * Updates the DNS hostname when the client wishes that the
1499 * server should handle this for him
1500 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1501 * obviously only checked when we do already have a
1503 * See MS-NRPC section 3.5.4.3.9
1505 if ((old_dns_hostname != NULL) &&
1506 (r->in.query->workstation_info->workstation_flags
1507 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1508 update_dns_hostname = false;
1511 /* Gets host information and put them into our directory */
1513 new_msg = ldb_msg_new(mem_ctx);
1514 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1516 new_msg->dn = workstation_dn;
1518 /* Sets the OS name */
1520 if (r->in.query->workstation_info->os_name.string == NULL) {
1521 return NT_STATUS_INVALID_PARAMETER;
1524 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1525 r->in.query->workstation_info->os_name.string);
1526 if (ret != LDB_SUCCESS) {
1527 return NT_STATUS_NO_MEMORY;
1531 * Sets information from "os_version". On an empty structure
1532 * the values are cleared.
1534 if (r->in.query->workstation_info->os_version.os != NULL) {
1535 struct netr_OsVersionInfoEx *os_version;
1536 const char *os_version_str;
1538 os_version = &r->in.query->workstation_info->os_version.os->os;
1540 if (os_version->CSDVersion == NULL) {
1541 return NT_STATUS_INVALID_PARAMETER;
1544 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1545 os_version->MajorVersion,
1546 os_version->MinorVersion,
1547 os_version->BuildNumber);
1548 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1550 ret = ldb_msg_add_string(new_msg,
1551 "operatingSystemServicePack",
1552 os_version->CSDVersion);
1553 if (ret != LDB_SUCCESS) {
1554 return NT_STATUS_NO_MEMORY;
1557 ret = ldb_msg_add_string(new_msg,
1558 "operatingSystemVersion",
1560 if (ret != LDB_SUCCESS) {
1561 return NT_STATUS_NO_MEMORY;
1564 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1565 "operatingSystemServicePack");
1566 if (ret != LDB_SUCCESS) {
1567 return NT_STATUS_NO_MEMORY;
1570 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1571 "operatingSystemVersion");
1572 if (ret != LDB_SUCCESS) {
1573 return NT_STATUS_NO_MEMORY;
1578 * If the boolean "update_dns_hostname" remained true, then we
1579 * are fine to start the update.
1581 if (update_dns_hostname) {
1582 ret = ldb_msg_add_string(new_msg,
1584 r->in.query->workstation_info->dns_hostname);
1585 if (ret != LDB_SUCCESS) {
1586 return NT_STATUS_NO_MEMORY;
1589 /* This manual "servicePrincipalName" generation is
1590 * still needed! Since the update in the samldb LDB
1591 * module does only work if the entries already exist
1592 * which isn't always the case. */
1593 ret = ldb_msg_add_string(new_msg,
1594 "servicePrincipalName",
1595 talloc_asprintf(new_msg, "HOST/%s",
1596 r->in.computer_name));
1597 if (ret != LDB_SUCCESS) {
1598 return NT_STATUS_NO_MEMORY;
1601 ret = ldb_msg_add_string(new_msg,
1602 "servicePrincipalName",
1603 talloc_asprintf(new_msg, "HOST/%s",
1604 r->in.query->workstation_info->dns_hostname));
1605 if (ret != LDB_SUCCESS) {
1606 return NT_STATUS_NO_MEMORY;
1610 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1611 DEBUG(3,("Impossible to update samdb: %s\n",
1612 ldb_errstring(sam_ctx)));
1615 talloc_free(new_msg);
1617 /* Writes back the domain information */
1619 /* We need to do two searches. The first will pull our primary
1620 domain and the second will pull any trusted domains. Our
1621 primary domain is also a "trusted" domain, so we need to
1622 put the primary domain into the lists of returned trusts as
1624 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1627 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1630 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1631 "(objectClass=trustedDomain)");
1633 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1636 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1637 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1639 ZERO_STRUCTP(domain_info);
1641 /* Informations about the local and trusted domains */
1643 status = fill_one_domain_info(mem_ctx,
1644 dce_call->conn->dce_ctx->lp_ctx,
1645 sam_ctx, res2[0], &domain_info->primary_domain,
1647 NT_STATUS_NOT_OK_RETURN(status);
1649 domain_info->trusted_domain_count = ret3 + 1;
1650 domain_info->trusted_domains = talloc_array(mem_ctx,
1651 struct netr_OneDomainInfo,
1652 domain_info->trusted_domain_count);
1653 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1655 for (i=0;i<ret3;i++) {
1656 status = fill_one_domain_info(mem_ctx,
1657 dce_call->conn->dce_ctx->lp_ctx,
1659 &domain_info->trusted_domains[i],
1661 NT_STATUS_NOT_OK_RETURN(status);
1664 status = fill_one_domain_info(mem_ctx,
1665 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1666 &domain_info->trusted_domains[i], true, true);
1667 NT_STATUS_NOT_OK_RETURN(status);
1669 /* Sets the supported encryption types */
1670 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1671 "msDS-SupportedEncryptionTypes",
1672 default_supported_enc_types);
1674 /* Other host domain information */
1676 lsa_policy_info = talloc(mem_ctx,
1677 struct netr_LsaPolicyInformation);
1678 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1679 ZERO_STRUCTP(lsa_policy_info);
1681 domain_info->lsa_policy = *lsa_policy_info;
1683 /* The DNS hostname is only returned back when there is a chance
1685 if ((r->in.query->workstation_info->workstation_flags
1686 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1687 domain_info->dns_hostname.string = old_dns_hostname;
1689 domain_info->dns_hostname.string = NULL;
1692 domain_info->workstation_flags =
1693 r->in.query->workstation_info->workstation_flags & (
1694 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1696 r->out.info->domain_info = domain_info;
1698 case 2: /* LSA policy information - not used at the moment */
1699 lsa_policy_info = talloc(mem_ctx,
1700 struct netr_LsaPolicyInformation);
1701 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1702 ZERO_STRUCTP(lsa_policy_info);
1704 r->out.info->lsa_policy_info = lsa_policy_info;
1707 return NT_STATUS_INVALID_LEVEL;
1711 return NT_STATUS_OK;
1716 netr_ServerPasswordGet
1718 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1719 struct netr_ServerPasswordGet *r)
1721 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1726 netr_NETRLOGONSENDTOSAM
1728 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1729 struct netr_NETRLOGONSENDTOSAM *r)
1731 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1736 netr_DsRGetDCNameEx2
1738 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1739 TALLOC_CTX *mem_ctx,
1740 struct netr_DsRGetDCNameEx2 *r)
1742 struct ldb_context *sam_ctx;
1743 struct netr_DsRGetDCNameInfo *info;
1744 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1745 const struct tsocket_address *remote_address;
1747 const char *server_site_name;
1749 struct netlogon_samlogon_response response;
1751 const char *dc_name = NULL;
1752 const char *domain_name = NULL;
1753 struct interface *ifaces;
1756 ZERO_STRUCTP(r->out.info);
1758 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1759 dce_call->conn->auth_state.session_info, 0);
1760 if (sam_ctx == NULL) {
1761 return WERR_DS_UNAVAILABLE;
1764 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1765 if (tsocket_address_is_inet(remote_address, "ip")) {
1766 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1767 W_ERROR_HAVE_NO_MEMORY(addr);
1770 /* "server_unc" is ignored by w2k3 */
1772 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1773 return WERR_INVALID_FLAGS;
1776 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1777 r->in.flags & DS_PDC_REQUIRED &&
1778 r->in.flags & DS_KDC_REQUIRED) {
1779 return WERR_INVALID_FLAGS;
1781 if (r->in.flags & DS_IS_FLAT_NAME &&
1782 r->in.flags & DS_IS_DNS_NAME) {
1783 return WERR_INVALID_FLAGS;
1785 if (r->in.flags & DS_RETURN_DNS_NAME &&
1786 r->in.flags & DS_RETURN_FLAT_NAME) {
1787 return WERR_INVALID_FLAGS;
1789 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1790 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1791 return WERR_INVALID_FLAGS;
1794 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1796 (DS_DIRECTORY_SERVICE_REQUIRED |
1797 DS_DIRECTORY_SERVICE_PREFERRED |
1798 DS_GC_SERVER_REQUIRED |
1801 return WERR_INVALID_FLAGS;
1804 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1806 return WERR_INVALID_FLAGS;
1809 /* Proof server site parameter "site_name" if it was specified */
1810 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1811 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1812 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1813 server_site_name) != 0)) {
1814 return WERR_NO_SUCH_DOMAIN;
1817 guid_str = r->in.domain_guid != NULL ?
1818 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1820 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1824 r->in.client_account,
1826 NETLOGON_NT_VERSION_5EX_WITH_IP,
1827 lp_ctx, &response, true);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 return ntstatus_to_werror(status);
1833 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1834 * (O) flag when the returned forest name is in DNS format. This is here
1835 * always the case (see below).
1837 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1839 if (r->in.flags & DS_RETURN_DNS_NAME) {
1840 dc_name = response.data.nt5_ex.pdc_dns_name;
1841 domain_name = response.data.nt5_ex.dns_domain;
1843 * According to MS-NRPC 2.2.1.2.1 we should set the
1844 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1845 * the returned information is in DNS form.
1847 response.data.nt5_ex.server_type |=
1848 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1849 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1850 dc_name = response.data.nt5_ex.pdc_name;
1851 domain_name = response.data.nt5_ex.domain_name;
1855 * TODO: autodetect what we need to return
1856 * based on the given arguments
1858 dc_name = response.data.nt5_ex.pdc_name;
1859 domain_name = response.data.nt5_ex.domain_name;
1862 if (!dc_name || !dc_name[0]) {
1863 return WERR_NO_SUCH_DOMAIN;
1866 if (!domain_name || !domain_name[0]) {
1867 return WERR_NO_SUCH_DOMAIN;
1870 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1871 W_ERROR_HAVE_NO_MEMORY(info);
1872 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1873 dc_name[0] == '\\'? "\\\\":"",
1874 talloc_strdup(mem_ctx, dc_name));
1875 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1877 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1878 pdc_ip = iface_list_best_ip(ifaces, addr);
1879 if (pdc_ip == NULL) {
1880 pdc_ip = "127.0.0.1";
1882 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1883 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1884 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1885 info->domain_guid = response.data.nt5_ex.domain_uuid;
1886 info->domain_name = domain_name;
1887 info->forest_name = response.data.nt5_ex.forest;
1888 info->dc_flags = response.data.nt5_ex.server_type;
1889 if (r->in.flags & DS_RETURN_DNS_NAME) {
1890 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
1891 * returned if we are returning info->dc_unc containing a FQDN.
1892 * This attribute is called DomainControllerName in the specs,
1893 * it seems that we decide to return FQDN or netbios depending on
1894 * DS_RETURN_DNS_NAME.
1896 info->dc_flags |= DS_DNS_CONTROLLER;
1898 info->dc_site_name = response.data.nt5_ex.server_site;
1899 info->client_site_name = response.data.nt5_ex.client_site;
1901 *r->out.info = info;
1909 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1910 struct netr_DsRGetDCNameEx *r)
1912 struct netr_DsRGetDCNameEx2 r2;
1917 r2.in.server_unc = r->in.server_unc;
1918 r2.in.client_account = NULL;
1920 r2.in.domain_guid = r->in.domain_guid;
1921 r2.in.domain_name = r->in.domain_name;
1922 r2.in.site_name = r->in.site_name;
1923 r2.in.flags = r->in.flags;
1924 r2.out.info = r->out.info;
1926 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1934 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1935 struct netr_DsRGetDCName *r)
1937 struct netr_DsRGetDCNameEx2 r2;
1942 r2.in.server_unc = r->in.server_unc;
1943 r2.in.client_account = NULL;
1945 r2.in.domain_name = r->in.domain_name;
1946 r2.in.domain_guid = r->in.domain_guid;
1948 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1949 r2.in.flags = r->in.flags;
1950 r2.out.info = r->out.info;
1952 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1957 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1959 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1960 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1962 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1967 netr_NetrEnumerateTrustedDomainsEx
1969 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1970 struct netr_NetrEnumerateTrustedDomainsEx *r)
1972 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1977 netr_DsRAddressToSitenamesExW
1979 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1980 struct netr_DsRAddressToSitenamesExW *r)
1982 struct ldb_context *sam_ctx;
1983 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1984 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1985 sa_family_t sin_family;
1986 struct sockaddr_in *addr;
1988 struct sockaddr_in6 *addr6;
1989 char addr_str[INET6_ADDRSTRLEN];
1991 char addr_str[INET_ADDRSTRLEN];
1997 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1998 dce_call->conn->auth_state.session_info, 0);
1999 if (sam_ctx == NULL) {
2000 return WERR_DS_UNAVAILABLE;
2003 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2004 W_ERROR_HAVE_NO_MEMORY(ctr);
2008 ctr->count = r->in.count;
2009 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2010 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2011 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2012 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2014 for (i=0; i<ctr->count; i++) {
2015 ctr->sitename[i].string = NULL;
2016 ctr->subnetname[i].string = NULL;
2018 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2021 /* The first two byte of the buffer are reserved for the
2022 * "sin_family" but for now only the first one is used. */
2023 sin_family = r->in.addresses[i].buffer[0];
2025 switch (sin_family) {
2027 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2030 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2031 res = inet_ntop(AF_INET, &addr->sin_addr,
2032 addr_str, sizeof(addr_str));
2036 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2039 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2040 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2041 addr_str, sizeof(addr_str));
2052 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2056 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2057 ctr->subnetname[i].string = subnet_name;
2065 netr_DsRAddressToSitenamesW
2067 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2068 struct netr_DsRAddressToSitenamesW *r)
2070 struct netr_DsRAddressToSitenamesExW r2;
2071 struct netr_DsRAddressToSitenamesWCtr *ctr;
2077 r2.in.server_name = r->in.server_name;
2078 r2.in.count = r->in.count;
2079 r2.in.addresses = r->in.addresses;
2081 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2082 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2084 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2085 W_ERROR_HAVE_NO_MEMORY(ctr);
2089 ctr->count = r->in.count;
2090 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2091 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2093 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2095 for (i=0; i<ctr->count; i++) {
2096 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2104 netr_DsrGetDcSiteCoverageW
2106 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2107 struct netr_DsrGetDcSiteCoverageW *r)
2109 struct ldb_context *sam_ctx;
2110 struct DcSitesCtr *ctr;
2111 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2113 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2114 dce_call->conn->auth_state.session_info, 0);
2115 if (sam_ctx == NULL) {
2116 return WERR_DS_UNAVAILABLE;
2119 ctr = talloc(mem_ctx, struct DcSitesCtr);
2120 W_ERROR_HAVE_NO_MEMORY(ctr);
2124 /* For now only return our default site */
2126 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2127 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2128 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2129 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2135 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2136 struct ldb_context *sam_ctx,
2137 struct netr_DomainTrustList *trusts,
2138 uint32_t trust_flags)
2140 struct ldb_dn *system_dn;
2141 struct ldb_message **dom_res = NULL;
2142 const char *trust_attrs[] = { "flatname", "trustPartner",
2143 "securityIdentifier", "trustDirection",
2144 "trustType", "trustAttributes", NULL };
2149 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2150 NETR_TRUST_FLAG_OUTBOUND))) {
2151 return WERR_INVALID_FLAGS;
2154 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2155 ldb_get_default_basedn(sam_ctx),
2156 "(&(objectClass=container)(cn=System))");
2158 return WERR_GENERAL_FAILURE;
2161 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2162 &dom_res, trust_attrs,
2163 "(objectclass=trustedDomain)");
2165 for (i = 0; i < ret; i++) {
2166 unsigned int trust_dir;
2169 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2170 "trustDirection", 0);
2172 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2173 flags |= NETR_TRUST_FLAG_INBOUND;
2175 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2176 flags |= NETR_TRUST_FLAG_OUTBOUND;
2179 if (!(flags & trust_flags)) {
2180 /* this trust direction was not requested */
2185 trusts->array = talloc_realloc(trusts, trusts->array,
2186 struct netr_DomainTrust,
2188 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2190 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2191 if (!trusts->array[n].netbios_name) {
2192 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2193 "without flatname\n",
2194 ldb_dn_get_linearized(dom_res[i]->dn)));
2197 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2199 trusts->array[n].trust_flags = flags;
2200 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2201 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2202 /* TODO: find if we have parent in the list */
2203 trusts->array[n].parent_index = 0;
2206 trusts->array[n].trust_type =
2207 ldb_msg_find_attr_as_uint(dom_res[i],
2209 trusts->array[n].trust_attributes =
2210 ldb_msg_find_attr_as_uint(dom_res[i],
2211 "trustAttributes", 0);
2213 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2214 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2215 struct dom_sid zero_sid;
2216 ZERO_STRUCT(zero_sid);
2217 trusts->array[n].sid =
2218 dom_sid_dup(trusts, &zero_sid);
2220 trusts->array[n].sid =
2221 samdb_result_dom_sid(trusts, dom_res[i],
2222 "securityIdentifier");
2224 trusts->array[n].guid = GUID_zero();
2226 trusts->count = n + 1;
2229 talloc_free(dom_res);
2234 netr_DsrEnumerateDomainTrusts
2236 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2237 TALLOC_CTX *mem_ctx,
2238 struct netr_DsrEnumerateDomainTrusts *r)
2240 struct netr_DomainTrustList *trusts;
2241 struct ldb_context *sam_ctx;
2243 struct ldb_message **dom_res;
2244 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2245 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2246 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2250 if (r->in.trust_flags & 0xFFFFFE00) {
2251 return WERR_INVALID_FLAGS;
2254 /* TODO: turn to hard check once we are sure this is 100% correct */
2255 if (!r->in.server_name) {
2256 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2257 "But received NULL!\n", dnsdomain));
2259 p = strchr(r->in.server_name, '.');
2261 DEBUG(3, ("Invalid domain! Expected name in domain "
2262 "[%s]. But received [%s]!\n",
2263 dnsdomain, r->in.server_name));
2264 p = r->in.server_name;
2268 if (strcasecmp(p, dnsdomain)) {
2269 DEBUG(3, ("Invalid domain! Expected name in domain "
2270 "[%s]. But received [%s]!\n",
2271 dnsdomain, r->in.server_name));
2275 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2276 W_ERROR_HAVE_NO_MEMORY(trusts);
2279 r->out.trusts = trusts;
2281 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2282 dce_call->conn->auth_state.session_info, 0);
2283 if (sam_ctx == NULL) {
2284 return WERR_GENERAL_FAILURE;
2287 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2288 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2290 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2291 trusts, r->in.trust_flags);
2292 W_ERROR_NOT_OK_RETURN(werr);
2295 /* NOTE: we currently are always the root of the forest */
2296 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2297 uint32_t n = trusts->count;
2299 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2300 &dom_res, dom_attrs);
2302 return WERR_GENERAL_FAILURE;
2305 trusts->count = n + 1;
2306 trusts->array = talloc_realloc(trusts, trusts->array,
2307 struct netr_DomainTrust,
2309 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2311 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2312 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2313 trusts->array[n].trust_flags =
2314 NETR_TRUST_FLAG_NATIVE |
2315 NETR_TRUST_FLAG_TREEROOT |
2316 NETR_TRUST_FLAG_IN_FOREST |
2317 NETR_TRUST_FLAG_PRIMARY;
2318 /* we are always the root domain for now */
2319 trusts->array[n].parent_index = 0;
2320 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2321 trusts->array[n].trust_attributes = 0;
2322 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2325 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2327 talloc_free(dom_res);
2335 netr_DsrDeregisterDNSHostRecords
2337 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2338 struct netr_DsrDeregisterDNSHostRecords *r)
2340 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2345 netr_ServerTrustPasswordsGet
2347 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2348 struct netr_ServerTrustPasswordsGet *r)
2350 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2354 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2355 struct ldb_context *sam_ctx,
2356 struct loadparm_context *lp_ctx,
2357 struct lsa_ForestTrustInformation *info)
2359 struct lsa_ForestTrustDomainInfo *domain_info;
2360 struct lsa_ForestTrustRecord *e;
2361 struct ldb_message **dom_res;
2362 const char * const dom_attrs[] = { "objectSid", NULL };
2365 /* we need to provide 2 entries:
2366 * 1. the Root Forest name
2367 * 2. the Domain Information
2371 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2372 W_ERROR_HAVE_NO_MEMORY(info->entries);
2374 /* Forest root info */
2375 e = talloc(info, struct lsa_ForestTrustRecord);
2376 W_ERROR_HAVE_NO_MEMORY(e);
2379 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2380 e->time = 0; /* so far always 0 in trces. */
2381 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2383 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2385 info->entries[0] = e;
2388 e = talloc(info, struct lsa_ForestTrustRecord);
2389 W_ERROR_HAVE_NO_MEMORY(e);
2391 /* get our own domain info */
2392 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2394 return WERR_GENERAL_FAILURE;
2397 /* TODO: check if disabled and set flags accordingly */
2399 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2400 e->time = 0; /* so far always 0 in traces. */
2402 domain_info = &e->forest_trust_data.domain_info;
2403 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2405 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2406 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2408 info->entries[1] = e;
2410 talloc_free(dom_res);
2416 netr_DsRGetForestTrustInformation
2418 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2419 TALLOC_CTX *mem_ctx,
2420 struct netr_DsRGetForestTrustInformation *r)
2422 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2423 struct lsa_ForestTrustInformation *info, **info_ptr;
2424 struct ldb_context *sam_ctx;
2427 if (r->in.flags & 0xFFFFFFFE) {
2428 return WERR_INVALID_FLAGS;
2431 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2432 dce_call->conn->auth_state.session_info, 0);
2433 if (sam_ctx == NULL) {
2434 return WERR_GENERAL_FAILURE;
2437 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2438 if (!samdb_is_pdc(sam_ctx)) {
2439 return WERR_NERR_NOTPRIMARY;
2442 if (r->in.trusted_domain_name == NULL) {
2443 return WERR_INVALID_FLAGS;
2446 /* TODO: establish an schannel connection with
2447 * r->in.trusted_domain_name and perform a
2448 * netr_GetForestTrustInformation call against it */
2450 /* for now return not implementd */
2451 return WERR_CALL_NOT_IMPLEMENTED;
2454 /* TODO: check r->in.server_name is our name */
2456 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2457 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2459 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2460 W_ERROR_HAVE_NO_MEMORY(info);
2462 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2463 W_ERROR_NOT_OK_RETURN(werr);
2466 r->out.forest_trust_info = info_ptr;
2473 netr_GetForestTrustInformation
2475 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2476 TALLOC_CTX *mem_ctx,
2477 struct netr_GetForestTrustInformation *r)
2479 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2480 struct netlogon_creds_CredentialState *creds;
2481 struct lsa_ForestTrustInformation *info, **info_ptr;
2482 struct ldb_context *sam_ctx;
2486 status = dcesrv_netr_creds_server_step_check(dce_call,
2488 r->in.computer_name,
2490 r->out.return_authenticator,
2492 if (!NT_STATUS_IS_OK(status)) {
2496 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2497 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2498 return NT_STATUS_NOT_IMPLEMENTED;
2501 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2502 dce_call->conn->auth_state.session_info, 0);
2503 if (sam_ctx == NULL) {
2504 return NT_STATUS_INTERNAL_ERROR;
2507 /* TODO: check r->in.server_name is our name */
2509 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2511 return NT_STATUS_NO_MEMORY;
2513 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2515 return NT_STATUS_NO_MEMORY;
2518 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2519 if (!W_ERROR_IS_OK(werr)) {
2520 return werror_to_ntstatus(werr);
2524 r->out.forest_trust_info = info_ptr;
2526 return NT_STATUS_OK;
2531 netr_ServerGetTrustInfo
2533 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2534 struct netr_ServerGetTrustInfo *r)
2536 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2542 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2543 struct netr_Unused47 *r)
2545 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2549 struct netr_dnsupdate_RODC_state {
2550 struct dcesrv_call_state *dce_call;
2551 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2552 struct dnsupdate_RODC *r2;
2556 called when the forwarded RODC dns update request is finished
2558 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2560 struct netr_dnsupdate_RODC_state *st =
2561 tevent_req_callback_data(subreq,
2562 struct netr_dnsupdate_RODC_state);
2565 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2566 TALLOC_FREE(subreq);
2567 if (!NT_STATUS_IS_OK(status)) {
2568 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2569 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2572 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2574 status = dcesrv_reply(st->dce_call);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2581 netr_DsrUpdateReadOnlyServerDnsRecords
2583 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2584 TALLOC_CTX *mem_ctx,
2585 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2587 struct netlogon_creds_CredentialState *creds;
2589 struct dcerpc_binding_handle *binding_handle;
2590 struct netr_dnsupdate_RODC_state *st;
2591 struct tevent_req *subreq;
2593 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2595 r->in.computer_name,
2597 r->out.return_authenticator,
2599 NT_STATUS_NOT_OK_RETURN(nt_status);
2601 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2602 return NT_STATUS_ACCESS_DENIED;
2605 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2606 NT_STATUS_HAVE_NO_MEMORY(st);
2608 st->dce_call = dce_call;
2610 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2611 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2613 st->r2->in.dom_sid = creds->sid;
2614 st->r2->in.site_name = r->in.site_name;
2615 st->r2->in.dns_ttl = r->in.dns_ttl;
2616 st->r2->in.dns_names = r->in.dns_names;
2617 st->r2->out.dns_names = r->out.dns_names;
2619 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2620 "dnsupdate", &ndr_table_irpc);
2621 if (binding_handle == NULL) {
2622 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2623 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2624 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2627 /* forward the call */
2628 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2629 binding_handle, st->r2);
2630 NT_STATUS_HAVE_NO_MEMORY(subreq);
2632 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2634 /* setup the callback */
2635 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2637 return NT_STATUS_OK;
2641 /* include the generated boilerplate */
2642 #include "librpc/gen_ndr/ndr_netlogon_s.c"