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);
750 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
753 if (!NT_STATUS_IS_OK(status)) {
756 generic->length = check.out.generic_reply.length;
757 generic->data = check.out.generic_reply.data;
761 /* Until we get an implemetnation of these other packages */
762 return NT_STATUS_INVALID_PARAMETER;
765 return NT_STATUS_INVALID_PARAMETER;
768 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
769 /* TODO: set *r->out.authoritative = 0 on specific errors */
770 NT_STATUS_NOT_OK_RETURN(nt_status);
772 switch (r->in.validation_level) {
774 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
775 NT_STATUS_NOT_OK_RETURN(nt_status);
777 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
778 NT_STATUS_HAVE_NO_MEMORY(sam2);
781 /* And put into the talloc tree */
782 talloc_steal(sam2, sam);
783 r->out.validation->sam2 = sam2;
789 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
792 NT_STATUS_NOT_OK_RETURN(nt_status);
794 r->out.validation->sam3 = sam3;
800 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
803 NT_STATUS_NOT_OK_RETURN(nt_status);
805 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
806 NT_STATUS_HAVE_NO_MEMORY(sam6);
807 sam6->base = sam3->base;
809 sam6->sidcount = sam3->sidcount;
810 sam6->sids = sam3->sids;
812 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
813 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
814 sam->account_name.string, sam6->dns_domainname.string);
815 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
816 /* And put into the talloc tree */
817 talloc_steal(sam6, sam3);
819 r->out.validation->sam6 = sam6;
823 return NT_STATUS_INVALID_INFO_CLASS;
826 netlogon_creds_encrypt_samlogon_validation(creds,
827 r->in.validation_level,
830 /* TODO: Describe and deal with these flags */
836 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
837 struct netr_LogonSamLogonEx *r)
840 struct netlogon_creds_CredentialState *creds;
842 *r->out.authoritative = 1;
844 nt_status = dcesrv_netr_LogonSamLogon_check(r);
845 if (!NT_STATUS_IS_OK(nt_status)) {
849 nt_status = schannel_get_creds_state(mem_ctx,
850 dce_call->conn->dce_ctx->lp_ctx,
851 r->in.computer_name, &creds);
852 if (!NT_STATUS_IS_OK(nt_status)) {
856 if (!dce_call->conn->auth_state.auth_info ||
857 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
858 return NT_STATUS_ACCESS_DENIED;
860 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
864 netr_LogonSamLogonWithFlags
867 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
868 struct netr_LogonSamLogonWithFlags *r)
871 struct netlogon_creds_CredentialState *creds;
872 struct netr_LogonSamLogonEx r2;
874 struct netr_Authenticator *return_authenticator;
878 r2.in.server_name = r->in.server_name;
879 r2.in.computer_name = r->in.computer_name;
880 r2.in.logon_level = r->in.logon_level;
881 r2.in.logon = r->in.logon;
882 r2.in.validation_level = r->in.validation_level;
883 r2.in.flags = r->in.flags;
884 r2.out.validation = r->out.validation;
885 r2.out.authoritative = r->out.authoritative;
886 r2.out.flags = r->out.flags;
888 *r->out.authoritative = 1;
890 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
891 if (!NT_STATUS_IS_OK(nt_status)) {
895 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
896 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
898 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
901 r->in.credential, return_authenticator,
903 NT_STATUS_NOT_OK_RETURN(nt_status);
905 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
907 r->out.return_authenticator = return_authenticator;
915 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
916 struct netr_LogonSamLogon *r)
918 struct netr_LogonSamLogonWithFlags r2;
924 r2.in.server_name = r->in.server_name;
925 r2.in.computer_name = r->in.computer_name;
926 r2.in.credential = r->in.credential;
927 r2.in.return_authenticator = r->in.return_authenticator;
928 r2.in.logon_level = r->in.logon_level;
929 r2.in.logon = r->in.logon;
930 r2.in.validation_level = r->in.validation_level;
931 r2.in.flags = &flags;
932 r2.out.validation = r->out.validation;
933 r2.out.authoritative = r->out.authoritative;
934 r2.out.flags = &flags;
936 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
938 r->out.return_authenticator = r2.out.return_authenticator;
947 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
948 struct netr_LogonSamLogoff *r)
950 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
958 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
959 struct netr_DatabaseDeltas *r)
961 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
968 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
969 struct netr_DatabaseSync2 *r)
971 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
972 return NT_STATUS_NOT_IMPLEMENTED;
979 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
980 struct netr_DatabaseSync *r)
982 struct netr_DatabaseSync2 r2;
987 r2.in.logon_server = r->in.logon_server;
988 r2.in.computername = r->in.computername;
989 r2.in.credential = r->in.credential;
990 r2.in.database_id = r->in.database_id;
991 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
992 r2.in.sync_context = r->in.sync_context;
993 r2.out.sync_context = r->out.sync_context;
994 r2.out.delta_enum_array = r->out.delta_enum_array;
995 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
997 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1006 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1007 struct netr_AccountDeltas *r)
1009 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1010 return NT_STATUS_NOT_IMPLEMENTED;
1017 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1018 struct netr_AccountSync *r)
1020 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1021 return NT_STATUS_NOT_IMPLEMENTED;
1028 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1029 struct netr_GetDcName *r)
1031 const char * const attrs[] = { NULL };
1032 struct ldb_context *sam_ctx;
1033 struct ldb_message **res;
1034 struct ldb_dn *domain_dn;
1039 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1040 * that the domainname needs to be a valid netbios domain
1041 * name, if it is not NULL.
1043 if (r->in.domainname) {
1044 const char *dot = strchr(r->in.domainname, '.');
1045 size_t len = strlen(r->in.domainname);
1047 if (dot || len > 15) {
1048 return WERR_DCNOTFOUND;
1052 * TODO: Should we also varify that only valid
1053 * netbios name characters are used?
1057 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1058 dce_call->conn->dce_ctx->lp_ctx,
1059 dce_call->conn->auth_state.session_info, 0);
1060 if (sam_ctx == NULL) {
1061 return WERR_DS_UNAVAILABLE;
1064 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1066 if (domain_dn == NULL) {
1067 return WERR_NO_SUCH_DOMAIN;
1070 ret = gendb_search_dn(sam_ctx, mem_ctx,
1071 domain_dn, &res, attrs);
1073 return WERR_NO_SUCH_DOMAIN;
1076 /* TODO: - return real IP address
1077 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1079 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1080 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1081 W_ERROR_HAVE_NO_MEMORY(dcname);
1083 *r->out.dcname = dcname;
1089 netr_LogonControl2Ex
1091 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1092 struct netr_LogonControl2Ex *r)
1094 return WERR_NOT_SUPPORTED;
1101 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1102 struct netr_LogonControl *r)
1104 struct netr_LogonControl2Ex r2;
1107 if (r->in.level == 0x00000001) {
1110 r2.in.logon_server = r->in.logon_server;
1111 r2.in.function_code = r->in.function_code;
1112 r2.in.level = r->in.level;
1114 r2.out.query = r->out.query;
1116 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1117 } else if (r->in.level == 0x00000002) {
1118 werr = WERR_NOT_SUPPORTED;
1120 werr = WERR_UNKNOWN_LEVEL;
1130 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1131 struct netr_LogonControl2 *r)
1133 struct netr_LogonControl2Ex r2;
1138 r2.in.logon_server = r->in.logon_server;
1139 r2.in.function_code = r->in.function_code;
1140 r2.in.level = r->in.level;
1141 r2.in.data = r->in.data;
1142 r2.out.query = r->out.query;
1144 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1149 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1150 struct ldb_context *sam_ctx,
1151 struct netr_DomainTrustList *trusts,
1152 uint32_t trust_flags);
1157 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1158 struct netr_GetAnyDCName *r)
1160 struct netr_DomainTrustList *trusts;
1161 struct ldb_context *sam_ctx;
1162 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1166 *r->out.dcname = NULL;
1168 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1169 /* if the domainname parameter wasn't set assume our domain */
1170 r->in.domainname = lpcfg_workgroup(lp_ctx);
1173 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1174 dce_call->conn->auth_state.session_info, 0);
1175 if (sam_ctx == NULL) {
1176 return WERR_DS_UNAVAILABLE;
1179 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1180 /* well we asked for a DC of our own domain */
1181 if (samdb_is_pdc(sam_ctx)) {
1182 /* we are the PDC of the specified domain */
1183 return WERR_NO_SUCH_DOMAIN;
1186 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1187 lpcfg_netbios_name(lp_ctx));
1188 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1193 /* Okay, now we have to consider the trusted domains */
1195 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1196 W_ERROR_HAVE_NO_MEMORY(trusts);
1200 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1201 NETR_TRUST_FLAG_INBOUND
1202 | NETR_TRUST_FLAG_OUTBOUND);
1203 W_ERROR_NOT_OK_RETURN(werr);
1205 for (i = 0; i < trusts->count; i++) {
1206 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1207 /* FIXME: Here we need to find a DC for the specified
1208 * trusted domain. */
1210 /* return WERR_OK; */
1211 return WERR_NO_SUCH_DOMAIN;
1215 return WERR_NO_SUCH_DOMAIN;
1222 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1223 struct netr_DatabaseRedo *r)
1225 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1230 netr_NetrEnumerateTrustedDomains
1232 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1233 struct netr_NetrEnumerateTrustedDomains *r)
1235 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1240 netr_LogonGetCapabilities
1242 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1243 struct netr_LogonGetCapabilities *r)
1245 struct netlogon_creds_CredentialState *creds;
1248 status = dcesrv_netr_creds_server_step_check(dce_call,
1250 r->in.computer_name,
1252 r->out.return_authenticator,
1254 if (!NT_STATUS_IS_OK(status)) {
1255 DEBUG(0,(__location__ " Bad credentials - error\n"));
1257 NT_STATUS_NOT_OK_RETURN(status);
1259 if (r->in.query_level != 1) {
1260 return NT_STATUS_NOT_SUPPORTED;
1263 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1265 return NT_STATUS_OK;
1270 netr_NETRLOGONSETSERVICEBITS
1272 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1273 struct netr_NETRLOGONSETSERVICEBITS *r)
1275 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1280 netr_LogonGetTrustRid
1282 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1283 struct netr_LogonGetTrustRid *r)
1285 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1290 netr_NETRLOGONCOMPUTESERVERDIGEST
1292 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1293 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1295 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1300 netr_NETRLOGONCOMPUTECLIENTDIGEST
1302 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1303 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1305 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1313 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1314 struct netr_DsRGetSiteName *r)
1316 struct ldb_context *sam_ctx;
1317 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1319 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1320 dce_call->conn->auth_state.session_info, 0);
1321 if (sam_ctx == NULL) {
1322 return WERR_DS_UNAVAILABLE;
1326 * We assume to be a DC when we get called over NETLOGON. Hence we
1327 * get our site name always by using "samdb_server_site_name()"
1328 * and not "samdb_client_site_name()".
1330 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1331 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1338 fill in a netr_OneDomainInfo from a ldb search result
1340 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1341 struct loadparm_context *lp_ctx,
1342 struct ldb_context *sam_ctx,
1343 struct ldb_message *res,
1344 struct netr_OneDomainInfo *info,
1345 bool is_local, bool is_trust_list)
1349 if (is_trust_list) {
1350 /* w2k8 only fills this on trusted domains */
1351 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1352 info->trust_extension.length = 16;
1353 info->trust_extension.info->flags =
1354 NETR_TRUST_FLAG_TREEROOT |
1355 NETR_TRUST_FLAG_IN_FOREST |
1356 NETR_TRUST_FLAG_PRIMARY |
1357 NETR_TRUST_FLAG_NATIVE;
1359 info->trust_extension.info->parent_index = 0; /* should be index into array
1361 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1362 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1365 if (is_trust_list) {
1366 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1367 info->dns_forestname.string = NULL;
1369 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1370 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1371 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1372 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1376 info->domainname.string = lpcfg_workgroup(lp_ctx);
1377 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1378 info->domain_guid = samdb_result_guid(res, "objectGUID");
1379 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1381 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1382 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1383 info->domain_guid = samdb_result_guid(res, "objectGUID");
1384 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1386 if (!is_trust_list) {
1387 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1390 return NT_STATUS_OK;
1394 netr_LogonGetDomainInfo
1395 this is called as part of the ADS domain logon procedure.
1397 It has an important role in convaying details about the client, such
1398 as Operating System, Version, Service Pack etc.
1400 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1401 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1403 struct netlogon_creds_CredentialState *creds;
1404 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1405 "securityIdentifier", "trustPartner", NULL };
1406 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1407 "msDS-SupportedEncryptionTypes", NULL };
1408 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1409 struct ldb_context *sam_ctx;
1410 struct ldb_message **res1, **res2, **res3, *new_msg;
1411 struct ldb_dn *workstation_dn;
1412 struct netr_DomainInformation *domain_info;
1413 struct netr_LsaPolicyInformation *lsa_policy_info;
1414 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1415 bool update_dns_hostname = true;
1419 status = dcesrv_netr_creds_server_step_check(dce_call,
1421 r->in.computer_name,
1423 r->out.return_authenticator,
1425 if (!NT_STATUS_IS_OK(status)) {
1426 DEBUG(0,(__location__ " Bad credentials - error\n"));
1428 NT_STATUS_NOT_OK_RETURN(status);
1430 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1431 dce_call->conn->dce_ctx->lp_ctx,
1432 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1433 if (sam_ctx == NULL) {
1434 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1437 switch (r->in.level) {
1438 case 1: /* Domain information */
1440 if (r->in.query->workstation_info == NULL) {
1441 return NT_STATUS_INVALID_PARAMETER;
1444 /* Prepares the workstation DN */
1445 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1446 dom_sid_string(mem_ctx, creds->sid));
1447 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1449 /* Lookup for attributes in workstation object */
1450 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1453 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1456 /* Gets the sam account name which is checked against the DNS
1457 * hostname parameter. */
1458 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1461 if (sam_account_name == NULL) {
1462 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1466 * Checks that the sam account name without a possible "$"
1467 * matches as prefix with the DNS hostname in the workstation
1470 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1471 strcspn(sam_account_name, "$"));
1472 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1473 if (r->in.query->workstation_info->dns_hostname != NULL) {
1474 prefix2 = talloc_strndup(mem_ctx,
1475 r->in.query->workstation_info->dns_hostname,
1476 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1477 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1479 if (strcasecmp(prefix1, prefix2) != 0) {
1480 update_dns_hostname = false;
1483 update_dns_hostname = false;
1486 /* Gets the old DNS hostname */
1487 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1492 * Updates the DNS hostname when the client wishes that the
1493 * server should handle this for him
1494 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1495 * obviously only checked when we do already have a
1497 * See MS-NRPC section 3.5.4.3.9
1499 if ((old_dns_hostname != NULL) &&
1500 (r->in.query->workstation_info->workstation_flags
1501 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1502 update_dns_hostname = false;
1505 /* Gets host information and put them into our directory */
1507 new_msg = ldb_msg_new(mem_ctx);
1508 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1510 new_msg->dn = workstation_dn;
1512 /* Sets the OS name */
1514 if (r->in.query->workstation_info->os_name.string == NULL) {
1515 return NT_STATUS_INVALID_PARAMETER;
1518 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1519 r->in.query->workstation_info->os_name.string);
1520 if (ret != LDB_SUCCESS) {
1521 return NT_STATUS_NO_MEMORY;
1525 * Sets information from "os_version". On an empty structure
1526 * the values are cleared.
1528 if (r->in.query->workstation_info->os_version.os != NULL) {
1529 struct netr_OsVersionInfoEx *os_version;
1530 const char *os_version_str;
1532 os_version = &r->in.query->workstation_info->os_version.os->os;
1534 if (os_version->CSDVersion == NULL) {
1535 return NT_STATUS_INVALID_PARAMETER;
1538 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1539 os_version->MajorVersion,
1540 os_version->MinorVersion,
1541 os_version->BuildNumber);
1542 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1544 ret = ldb_msg_add_string(new_msg,
1545 "operatingSystemServicePack",
1546 os_version->CSDVersion);
1547 if (ret != LDB_SUCCESS) {
1548 return NT_STATUS_NO_MEMORY;
1551 ret = ldb_msg_add_string(new_msg,
1552 "operatingSystemVersion",
1554 if (ret != LDB_SUCCESS) {
1555 return NT_STATUS_NO_MEMORY;
1558 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1559 "operatingSystemServicePack");
1560 if (ret != LDB_SUCCESS) {
1561 return NT_STATUS_NO_MEMORY;
1564 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1565 "operatingSystemVersion");
1566 if (ret != LDB_SUCCESS) {
1567 return NT_STATUS_NO_MEMORY;
1572 * If the boolean "update_dns_hostname" remained true, then we
1573 * are fine to start the update.
1575 if (update_dns_hostname) {
1576 ret = ldb_msg_add_string(new_msg,
1578 r->in.query->workstation_info->dns_hostname);
1579 if (ret != LDB_SUCCESS) {
1580 return NT_STATUS_NO_MEMORY;
1583 /* This manual "servicePrincipalName" generation is
1584 * still needed! Since the update in the samldb LDB
1585 * module does only work if the entries already exist
1586 * which isn't always the case. */
1587 ret = ldb_msg_add_string(new_msg,
1588 "servicePrincipalName",
1589 talloc_asprintf(new_msg, "HOST/%s",
1590 r->in.computer_name));
1591 if (ret != LDB_SUCCESS) {
1592 return NT_STATUS_NO_MEMORY;
1595 ret = ldb_msg_add_string(new_msg,
1596 "servicePrincipalName",
1597 talloc_asprintf(new_msg, "HOST/%s",
1598 r->in.query->workstation_info->dns_hostname));
1599 if (ret != LDB_SUCCESS) {
1600 return NT_STATUS_NO_MEMORY;
1604 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1605 DEBUG(3,("Impossible to update samdb: %s\n",
1606 ldb_errstring(sam_ctx)));
1609 talloc_free(new_msg);
1611 /* Writes back the domain information */
1613 /* We need to do two searches. The first will pull our primary
1614 domain and the second will pull any trusted domains. Our
1615 primary domain is also a "trusted" domain, so we need to
1616 put the primary domain into the lists of returned trusts as
1618 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1621 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1624 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1625 "(objectClass=trustedDomain)");
1627 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1630 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1631 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1633 ZERO_STRUCTP(domain_info);
1635 /* Informations about the local and trusted domains */
1637 status = fill_one_domain_info(mem_ctx,
1638 dce_call->conn->dce_ctx->lp_ctx,
1639 sam_ctx, res2[0], &domain_info->primary_domain,
1641 NT_STATUS_NOT_OK_RETURN(status);
1643 domain_info->trusted_domain_count = ret3 + 1;
1644 domain_info->trusted_domains = talloc_array(mem_ctx,
1645 struct netr_OneDomainInfo,
1646 domain_info->trusted_domain_count);
1647 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1649 for (i=0;i<ret3;i++) {
1650 status = fill_one_domain_info(mem_ctx,
1651 dce_call->conn->dce_ctx->lp_ctx,
1653 &domain_info->trusted_domains[i],
1655 NT_STATUS_NOT_OK_RETURN(status);
1658 status = fill_one_domain_info(mem_ctx,
1659 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1660 &domain_info->trusted_domains[i], true, true);
1661 NT_STATUS_NOT_OK_RETURN(status);
1663 /* Sets the supported encryption types */
1664 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1665 "msDS-SupportedEncryptionTypes",
1666 default_supported_enc_types);
1668 /* Other host domain information */
1670 lsa_policy_info = talloc(mem_ctx,
1671 struct netr_LsaPolicyInformation);
1672 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1673 ZERO_STRUCTP(lsa_policy_info);
1675 domain_info->lsa_policy = *lsa_policy_info;
1677 /* The DNS hostname is only returned back when there is a chance
1679 if ((r->in.query->workstation_info->workstation_flags
1680 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1681 domain_info->dns_hostname.string = old_dns_hostname;
1683 domain_info->dns_hostname.string = NULL;
1686 domain_info->workstation_flags =
1687 r->in.query->workstation_info->workstation_flags & (
1688 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1690 r->out.info->domain_info = domain_info;
1692 case 2: /* LSA policy information - not used at the moment */
1693 lsa_policy_info = talloc(mem_ctx,
1694 struct netr_LsaPolicyInformation);
1695 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1696 ZERO_STRUCTP(lsa_policy_info);
1698 r->out.info->lsa_policy_info = lsa_policy_info;
1701 return NT_STATUS_INVALID_LEVEL;
1705 return NT_STATUS_OK;
1710 netr_ServerPasswordGet
1712 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1713 struct netr_ServerPasswordGet *r)
1715 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1720 netr_NETRLOGONSENDTOSAM
1722 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1723 struct netr_NETRLOGONSENDTOSAM *r)
1725 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1730 netr_DsRGetDCNameEx2
1732 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1733 TALLOC_CTX *mem_ctx,
1734 struct netr_DsRGetDCNameEx2 *r)
1736 struct ldb_context *sam_ctx;
1737 struct netr_DsRGetDCNameInfo *info;
1738 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1739 const struct tsocket_address *remote_address;
1741 const char *server_site_name;
1743 struct netlogon_samlogon_response response;
1745 const char *dc_name = NULL;
1746 const char *domain_name = NULL;
1747 struct interface *ifaces;
1750 ZERO_STRUCTP(r->out.info);
1752 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1753 dce_call->conn->auth_state.session_info, 0);
1754 if (sam_ctx == NULL) {
1755 return WERR_DS_UNAVAILABLE;
1758 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1759 if (tsocket_address_is_inet(remote_address, "ip")) {
1760 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1761 W_ERROR_HAVE_NO_MEMORY(addr);
1764 /* "server_unc" is ignored by w2k3 */
1766 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1767 return WERR_INVALID_FLAGS;
1770 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1771 r->in.flags & DS_PDC_REQUIRED &&
1772 r->in.flags & DS_KDC_REQUIRED) {
1773 return WERR_INVALID_FLAGS;
1775 if (r->in.flags & DS_IS_FLAT_NAME &&
1776 r->in.flags & DS_IS_DNS_NAME) {
1777 return WERR_INVALID_FLAGS;
1779 if (r->in.flags & DS_RETURN_DNS_NAME &&
1780 r->in.flags & DS_RETURN_FLAT_NAME) {
1781 return WERR_INVALID_FLAGS;
1783 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1784 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1785 return WERR_INVALID_FLAGS;
1788 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1790 (DS_DIRECTORY_SERVICE_REQUIRED |
1791 DS_DIRECTORY_SERVICE_PREFERRED |
1792 DS_GC_SERVER_REQUIRED |
1795 return WERR_INVALID_FLAGS;
1798 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1800 return WERR_INVALID_FLAGS;
1803 /* Proof server site parameter "site_name" if it was specified */
1804 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1805 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1806 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1807 server_site_name) != 0)) {
1808 return WERR_NO_SUCH_DOMAIN;
1811 guid_str = r->in.domain_guid != NULL ?
1812 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1814 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1818 r->in.client_account,
1820 NETLOGON_NT_VERSION_5EX_WITH_IP,
1821 lp_ctx, &response, true);
1822 if (!NT_STATUS_IS_OK(status)) {
1823 return ntstatus_to_werror(status);
1827 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1828 * (O) flag when the returned forest name is in DNS format. This is here
1829 * always the case (see below).
1831 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1833 if (r->in.flags & DS_RETURN_DNS_NAME) {
1834 dc_name = response.data.nt5_ex.pdc_dns_name;
1835 domain_name = response.data.nt5_ex.dns_domain;
1837 * According to MS-NRPC 2.2.1.2.1 we should set the
1838 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1839 * the returned information is in DNS form.
1841 response.data.nt5_ex.server_type |=
1842 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1843 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1844 dc_name = response.data.nt5_ex.pdc_name;
1845 domain_name = response.data.nt5_ex.domain_name;
1849 * TODO: autodetect what we need to return
1850 * based on the given arguments
1852 dc_name = response.data.nt5_ex.pdc_name;
1853 domain_name = response.data.nt5_ex.domain_name;
1856 if (!dc_name || !dc_name[0]) {
1857 return WERR_NO_SUCH_DOMAIN;
1860 if (!domain_name || !domain_name[0]) {
1861 return WERR_NO_SUCH_DOMAIN;
1864 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1865 W_ERROR_HAVE_NO_MEMORY(info);
1866 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1867 dc_name[0] == '\\'? "\\\\":"",
1868 talloc_strdup(mem_ctx, dc_name));
1869 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1871 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1872 pdc_ip = iface_list_best_ip(ifaces, addr);
1873 if (pdc_ip == NULL) {
1874 pdc_ip = "127.0.0.1";
1876 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1877 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1878 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1879 info->domain_guid = response.data.nt5_ex.domain_uuid;
1880 info->domain_name = domain_name;
1881 info->forest_name = response.data.nt5_ex.forest;
1882 info->dc_flags = response.data.nt5_ex.server_type;
1883 if (r->in.flags & DS_RETURN_DNS_NAME) {
1884 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
1885 * returned if we are returning info->dc_unc containing a FQDN.
1886 * This attribute is called DomainControllerName in the specs,
1887 * it seems that we decide to return FQDN or netbios depending on
1888 * DS_RETURN_DNS_NAME.
1890 info->dc_flags |= DS_DNS_CONTROLLER;
1892 info->dc_site_name = response.data.nt5_ex.server_site;
1893 info->client_site_name = response.data.nt5_ex.client_site;
1895 *r->out.info = info;
1903 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1904 struct netr_DsRGetDCNameEx *r)
1906 struct netr_DsRGetDCNameEx2 r2;
1911 r2.in.server_unc = r->in.server_unc;
1912 r2.in.client_account = NULL;
1914 r2.in.domain_guid = r->in.domain_guid;
1915 r2.in.domain_name = r->in.domain_name;
1916 r2.in.site_name = r->in.site_name;
1917 r2.in.flags = r->in.flags;
1918 r2.out.info = r->out.info;
1920 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1928 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1929 struct netr_DsRGetDCName *r)
1931 struct netr_DsRGetDCNameEx2 r2;
1936 r2.in.server_unc = r->in.server_unc;
1937 r2.in.client_account = NULL;
1939 r2.in.domain_name = r->in.domain_name;
1940 r2.in.domain_guid = r->in.domain_guid;
1942 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1943 r2.in.flags = r->in.flags;
1944 r2.out.info = r->out.info;
1946 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1951 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1953 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1954 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1956 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1961 netr_NetrEnumerateTrustedDomainsEx
1963 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1964 struct netr_NetrEnumerateTrustedDomainsEx *r)
1966 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1971 netr_DsRAddressToSitenamesExW
1973 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1974 struct netr_DsRAddressToSitenamesExW *r)
1976 struct ldb_context *sam_ctx;
1977 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1978 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1979 sa_family_t sin_family;
1980 struct sockaddr_in *addr;
1982 struct sockaddr_in6 *addr6;
1983 char addr_str[INET6_ADDRSTRLEN];
1985 char addr_str[INET_ADDRSTRLEN];
1991 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1992 dce_call->conn->auth_state.session_info, 0);
1993 if (sam_ctx == NULL) {
1994 return WERR_DS_UNAVAILABLE;
1997 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1998 W_ERROR_HAVE_NO_MEMORY(ctr);
2002 ctr->count = r->in.count;
2003 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2004 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2005 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2006 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2008 for (i=0; i<ctr->count; i++) {
2009 ctr->sitename[i].string = NULL;
2010 ctr->subnetname[i].string = NULL;
2012 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2015 /* The first two byte of the buffer are reserved for the
2016 * "sin_family" but for now only the first one is used. */
2017 sin_family = r->in.addresses[i].buffer[0];
2019 switch (sin_family) {
2021 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2024 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2025 res = inet_ntop(AF_INET, &addr->sin_addr,
2026 addr_str, sizeof(addr_str));
2030 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2033 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2034 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2035 addr_str, sizeof(addr_str));
2046 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2050 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2051 ctr->subnetname[i].string = subnet_name;
2059 netr_DsRAddressToSitenamesW
2061 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2062 struct netr_DsRAddressToSitenamesW *r)
2064 struct netr_DsRAddressToSitenamesExW r2;
2065 struct netr_DsRAddressToSitenamesWCtr *ctr;
2071 r2.in.server_name = r->in.server_name;
2072 r2.in.count = r->in.count;
2073 r2.in.addresses = r->in.addresses;
2075 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2076 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2078 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2079 W_ERROR_HAVE_NO_MEMORY(ctr);
2083 ctr->count = r->in.count;
2084 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2085 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2087 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2089 for (i=0; i<ctr->count; i++) {
2090 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2098 netr_DsrGetDcSiteCoverageW
2100 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2101 struct netr_DsrGetDcSiteCoverageW *r)
2103 struct ldb_context *sam_ctx;
2104 struct DcSitesCtr *ctr;
2105 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2107 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2108 dce_call->conn->auth_state.session_info, 0);
2109 if (sam_ctx == NULL) {
2110 return WERR_DS_UNAVAILABLE;
2113 ctr = talloc(mem_ctx, struct DcSitesCtr);
2114 W_ERROR_HAVE_NO_MEMORY(ctr);
2118 /* For now only return our default site */
2120 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2121 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2122 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2123 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2129 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2130 struct ldb_context *sam_ctx,
2131 struct netr_DomainTrustList *trusts,
2132 uint32_t trust_flags)
2134 struct ldb_dn *system_dn;
2135 struct ldb_message **dom_res = NULL;
2136 const char *trust_attrs[] = { "flatname", "trustPartner",
2137 "securityIdentifier", "trustDirection",
2138 "trustType", "trustAttributes", NULL };
2143 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2144 NETR_TRUST_FLAG_OUTBOUND))) {
2145 return WERR_INVALID_FLAGS;
2148 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2149 ldb_get_default_basedn(sam_ctx),
2150 "(&(objectClass=container)(cn=System))");
2152 return WERR_GENERAL_FAILURE;
2155 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2156 &dom_res, trust_attrs,
2157 "(objectclass=trustedDomain)");
2159 for (i = 0; i < ret; i++) {
2160 unsigned int trust_dir;
2163 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2164 "trustDirection", 0);
2166 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2167 flags |= NETR_TRUST_FLAG_INBOUND;
2169 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2170 flags |= NETR_TRUST_FLAG_OUTBOUND;
2173 if (!(flags & trust_flags)) {
2174 /* this trust direction was not requested */
2179 trusts->array = talloc_realloc(trusts, trusts->array,
2180 struct netr_DomainTrust,
2182 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2184 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2185 if (!trusts->array[n].netbios_name) {
2186 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2187 "without flatname\n",
2188 ldb_dn_get_linearized(dom_res[i]->dn)));
2191 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2193 trusts->array[n].trust_flags = flags;
2194 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2195 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2196 /* TODO: find if we have parent in the list */
2197 trusts->array[n].parent_index = 0;
2200 trusts->array[n].trust_type =
2201 ldb_msg_find_attr_as_uint(dom_res[i],
2203 trusts->array[n].trust_attributes =
2204 ldb_msg_find_attr_as_uint(dom_res[i],
2205 "trustAttributes", 0);
2207 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2208 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2209 struct dom_sid zero_sid;
2210 ZERO_STRUCT(zero_sid);
2211 trusts->array[n].sid =
2212 dom_sid_dup(trusts, &zero_sid);
2214 trusts->array[n].sid =
2215 samdb_result_dom_sid(trusts, dom_res[i],
2216 "securityIdentifier");
2218 trusts->array[n].guid = GUID_zero();
2220 trusts->count = n + 1;
2223 talloc_free(dom_res);
2228 netr_DsrEnumerateDomainTrusts
2230 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2231 TALLOC_CTX *mem_ctx,
2232 struct netr_DsrEnumerateDomainTrusts *r)
2234 struct netr_DomainTrustList *trusts;
2235 struct ldb_context *sam_ctx;
2237 struct ldb_message **dom_res;
2238 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2239 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2240 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2244 if (r->in.trust_flags & 0xFFFFFE00) {
2245 return WERR_INVALID_FLAGS;
2248 /* TODO: turn to hard check once we are sure this is 100% correct */
2249 if (!r->in.server_name) {
2250 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2251 "But received NULL!\n", dnsdomain));
2253 p = strchr(r->in.server_name, '.');
2255 DEBUG(3, ("Invalid domain! Expected name in domain "
2256 "[%s]. But received [%s]!\n",
2257 dnsdomain, r->in.server_name));
2258 p = r->in.server_name;
2262 if (strcasecmp(p, dnsdomain)) {
2263 DEBUG(3, ("Invalid domain! Expected name in domain "
2264 "[%s]. But received [%s]!\n",
2265 dnsdomain, r->in.server_name));
2269 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2270 W_ERROR_HAVE_NO_MEMORY(trusts);
2273 r->out.trusts = trusts;
2275 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2276 dce_call->conn->auth_state.session_info, 0);
2277 if (sam_ctx == NULL) {
2278 return WERR_GENERAL_FAILURE;
2281 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2282 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2284 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2285 trusts, r->in.trust_flags);
2286 W_ERROR_NOT_OK_RETURN(werr);
2289 /* NOTE: we currently are always the root of the forest */
2290 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2291 uint32_t n = trusts->count;
2293 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2294 &dom_res, dom_attrs);
2296 return WERR_GENERAL_FAILURE;
2299 trusts->count = n + 1;
2300 trusts->array = talloc_realloc(trusts, trusts->array,
2301 struct netr_DomainTrust,
2303 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2305 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2306 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2307 trusts->array[n].trust_flags =
2308 NETR_TRUST_FLAG_NATIVE |
2309 NETR_TRUST_FLAG_TREEROOT |
2310 NETR_TRUST_FLAG_IN_FOREST |
2311 NETR_TRUST_FLAG_PRIMARY;
2312 /* we are always the root domain for now */
2313 trusts->array[n].parent_index = 0;
2314 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2315 trusts->array[n].trust_attributes = 0;
2316 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2319 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2321 talloc_free(dom_res);
2329 netr_DsrDeregisterDNSHostRecords
2331 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2332 struct netr_DsrDeregisterDNSHostRecords *r)
2334 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2339 netr_ServerTrustPasswordsGet
2341 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2342 struct netr_ServerTrustPasswordsGet *r)
2344 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2348 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2349 struct ldb_context *sam_ctx,
2350 struct loadparm_context *lp_ctx,
2351 struct lsa_ForestTrustInformation *info)
2353 struct lsa_ForestTrustDomainInfo *domain_info;
2354 struct lsa_ForestTrustRecord *e;
2355 struct ldb_message **dom_res;
2356 const char * const dom_attrs[] = { "objectSid", NULL };
2359 /* we need to provide 2 entries:
2360 * 1. the Root Forest name
2361 * 2. the Domain Information
2365 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2366 W_ERROR_HAVE_NO_MEMORY(info->entries);
2368 /* Forest root info */
2369 e = talloc(info, struct lsa_ForestTrustRecord);
2370 W_ERROR_HAVE_NO_MEMORY(e);
2373 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2374 e->time = 0; /* so far always 0 in trces. */
2375 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2377 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2379 info->entries[0] = e;
2382 e = talloc(info, struct lsa_ForestTrustRecord);
2383 W_ERROR_HAVE_NO_MEMORY(e);
2385 /* get our own domain info */
2386 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2388 return WERR_GENERAL_FAILURE;
2391 /* TODO: check if disabled and set flags accordingly */
2393 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2394 e->time = 0; /* so far always 0 in traces. */
2396 domain_info = &e->forest_trust_data.domain_info;
2397 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2399 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2400 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2402 info->entries[1] = e;
2404 talloc_free(dom_res);
2410 netr_DsRGetForestTrustInformation
2412 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2413 TALLOC_CTX *mem_ctx,
2414 struct netr_DsRGetForestTrustInformation *r)
2416 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2417 struct lsa_ForestTrustInformation *info, **info_ptr;
2418 struct ldb_context *sam_ctx;
2421 if (r->in.flags & 0xFFFFFFFE) {
2422 return WERR_INVALID_FLAGS;
2425 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2426 dce_call->conn->auth_state.session_info, 0);
2427 if (sam_ctx == NULL) {
2428 return WERR_GENERAL_FAILURE;
2431 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2432 if (!samdb_is_pdc(sam_ctx)) {
2433 return WERR_NERR_NOTPRIMARY;
2436 if (r->in.trusted_domain_name == NULL) {
2437 return WERR_INVALID_FLAGS;
2440 /* TODO: establish an schannel connection with
2441 * r->in.trusted_domain_name and perform a
2442 * netr_GetForestTrustInformation call against it */
2444 /* for now return not implementd */
2445 return WERR_CALL_NOT_IMPLEMENTED;
2448 /* TODO: check r->in.server_name is our name */
2450 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2451 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2453 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2454 W_ERROR_HAVE_NO_MEMORY(info);
2456 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2457 W_ERROR_NOT_OK_RETURN(werr);
2460 r->out.forest_trust_info = info_ptr;
2467 netr_GetForestTrustInformation
2469 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2470 TALLOC_CTX *mem_ctx,
2471 struct netr_GetForestTrustInformation *r)
2473 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2474 struct netlogon_creds_CredentialState *creds;
2475 struct lsa_ForestTrustInformation *info, **info_ptr;
2476 struct ldb_context *sam_ctx;
2480 status = dcesrv_netr_creds_server_step_check(dce_call,
2482 r->in.computer_name,
2484 r->out.return_authenticator,
2486 if (!NT_STATUS_IS_OK(status)) {
2490 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2491 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2492 return NT_STATUS_NOT_IMPLEMENTED;
2495 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2496 dce_call->conn->auth_state.session_info, 0);
2497 if (sam_ctx == NULL) {
2498 return NT_STATUS_INTERNAL_ERROR;
2501 /* TODO: check r->in.server_name is our name */
2503 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2505 return NT_STATUS_NO_MEMORY;
2507 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2509 return NT_STATUS_NO_MEMORY;
2512 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2513 if (!W_ERROR_IS_OK(werr)) {
2514 return werror_to_ntstatus(werr);
2518 r->out.forest_trust_info = info_ptr;
2520 return NT_STATUS_OK;
2525 netr_ServerGetTrustInfo
2527 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2528 struct netr_ServerGetTrustInfo *r)
2530 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2536 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2537 struct netr_Unused47 *r)
2539 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2543 struct netr_dnsupdate_RODC_state {
2544 struct dcesrv_call_state *dce_call;
2545 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2546 struct dnsupdate_RODC *r2;
2550 called when the forwarded RODC dns update request is finished
2552 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2554 struct netr_dnsupdate_RODC_state *st =
2555 tevent_req_callback_data(subreq,
2556 struct netr_dnsupdate_RODC_state);
2559 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2560 TALLOC_FREE(subreq);
2561 if (!NT_STATUS_IS_OK(status)) {
2562 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2563 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2566 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2568 status = dcesrv_reply(st->dce_call);
2569 if (!NT_STATUS_IS_OK(status)) {
2570 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2575 netr_DsrUpdateReadOnlyServerDnsRecords
2577 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2578 TALLOC_CTX *mem_ctx,
2579 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2581 struct netlogon_creds_CredentialState *creds;
2583 struct dcerpc_binding_handle *binding_handle;
2584 struct netr_dnsupdate_RODC_state *st;
2585 struct tevent_req *subreq;
2587 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2589 r->in.computer_name,
2591 r->out.return_authenticator,
2593 NT_STATUS_NOT_OK_RETURN(nt_status);
2595 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2596 return NT_STATUS_ACCESS_DENIED;
2599 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2600 NT_STATUS_HAVE_NO_MEMORY(st);
2602 st->dce_call = dce_call;
2604 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2605 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2607 st->r2->in.dom_sid = creds->sid;
2608 st->r2->in.site_name = r->in.site_name;
2609 st->r2->in.dns_ttl = r->in.dns_ttl;
2610 st->r2->in.dns_names = r->in.dns_names;
2611 st->r2->out.dns_names = r->out.dns_names;
2613 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2614 "dnsupdate", &ndr_table_irpc);
2615 if (binding_handle == NULL) {
2616 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2617 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2618 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2621 /* forward the call */
2622 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2623 binding_handle, st->r2);
2624 NT_STATUS_HAVE_NO_MEMORY(subreq);
2626 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2628 /* setup the callback */
2629 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2631 return NT_STATUS_OK;
2635 /* include the generated boilerplate */
2636 #include "librpc/gen_ndr/ndr_netlogon_s.c"