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 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
274 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
275 if (mach_pwd == NULL) {
276 return NT_STATUS_ACCESS_DENIED;
280 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
281 return NT_STATUS_ACCESS_DENIED;
284 creds = netlogon_creds_server_init(mem_ctx,
287 r->in.secure_channel_type,
288 &pipe_state->client_challenge,
289 &pipe_state->server_challenge,
292 r->out.return_credentials,
295 return NT_STATUS_ACCESS_DENIED;
298 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
300 nt_status = schannel_save_creds_state(mem_ctx,
301 dce_call->conn->dce_ctx->lp_ctx,
307 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
308 struct netr_ServerAuthenticate *r)
310 struct netr_ServerAuthenticate3 a;
313 * negotiate_flags is used as an [in] parameter
314 * so it need to be initialised.
316 * (I think ... = 0; seems wrong here --metze)
318 uint32_t negotiate_flags_in = 0;
319 uint32_t negotiate_flags_out = 0;
321 a.in.server_name = r->in.server_name;
322 a.in.account_name = r->in.account_name;
323 a.in.secure_channel_type = r->in.secure_channel_type;
324 a.in.computer_name = r->in.computer_name;
325 a.in.credentials = r->in.credentials;
326 a.in.negotiate_flags = &negotiate_flags_in;
328 a.out.return_credentials = r->out.return_credentials;
330 a.out.negotiate_flags = &negotiate_flags_out;
332 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
335 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
336 struct netr_ServerAuthenticate2 *r)
338 struct netr_ServerAuthenticate3 r3;
341 r3.in.server_name = r->in.server_name;
342 r3.in.account_name = r->in.account_name;
343 r3.in.secure_channel_type = r->in.secure_channel_type;
344 r3.in.computer_name = r->in.computer_name;
345 r3.in.credentials = r->in.credentials;
346 r3.out.return_credentials = r->out.return_credentials;
347 r3.in.negotiate_flags = r->in.negotiate_flags;
348 r3.out.negotiate_flags = r->out.negotiate_flags;
351 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
355 * NOTE: The following functions are nearly identical to the ones available in
356 * source3/rpc_server/srv_nelog_nt.c
357 * The reason we keep 2 copies is that they use different structures to
358 * represent the auth_info and the decrpc pipes.
362 * If schannel is required for this call test that it actually is available.
364 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
365 const char *computer_name,
366 bool integrity, bool privacy)
369 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
370 if (!privacy && !integrity) {
374 if ((!privacy && integrity) &&
375 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
379 if ((privacy || integrity) &&
380 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
385 /* test didn't pass */
386 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
389 return NT_STATUS_ACCESS_DENIED;
392 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
394 const char *computer_name,
395 struct netr_Authenticator *received_authenticator,
396 struct netr_Authenticator *return_authenticator,
397 struct netlogon_creds_CredentialState **creds_out)
400 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
401 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
403 if (schannel_global_required) {
404 nt_status = schannel_check_required(auth_info,
407 if (!NT_STATUS_IS_OK(nt_status)) {
412 nt_status = schannel_check_creds_state(mem_ctx,
413 dce_call->conn->dce_ctx->lp_ctx,
415 received_authenticator,
416 return_authenticator,
422 Change the machine account password for the currently connected
423 client. Supplies only the NT#.
426 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
427 struct netr_ServerPasswordSet *r)
429 struct netlogon_creds_CredentialState *creds;
430 struct ldb_context *sam_ctx;
431 const char * const attrs[] = { "unicodePwd", NULL };
432 struct ldb_message **res;
433 struct samr_Password *oldNtHash;
437 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
440 r->in.credential, r->out.return_authenticator,
442 NT_STATUS_NOT_OK_RETURN(nt_status);
444 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);
445 if (sam_ctx == NULL) {
446 return NT_STATUS_INVALID_SYSTEM_SERVICE;
449 netlogon_creds_des_decrypt(creds, r->in.new_password);
451 /* fetch the old password hashes (the NT hash has to exist) */
453 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
454 "(&(objectClass=user)(objectSid=%s))",
455 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
457 return NT_STATUS_WRONG_PASSWORD;
460 nt_status = samdb_result_passwords(mem_ctx,
461 dce_call->conn->dce_ctx->lp_ctx,
462 res[0], NULL, &oldNtHash);
463 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
464 return NT_STATUS_WRONG_PASSWORD;
467 /* Using the sid for the account as the key, set the password */
468 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
470 NULL, /* Don't have plaintext */
471 NULL, r->in.new_password,
472 NULL, oldNtHash, /* Password change */
478 Change the machine account password for the currently connected
479 client. Supplies new plaintext.
481 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
482 struct netr_ServerPasswordSet2 *r)
484 struct netlogon_creds_CredentialState *creds;
485 struct ldb_context *sam_ctx;
486 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
487 struct ldb_message **res;
488 struct samr_Password *oldLmHash, *oldNtHash;
490 DATA_BLOB new_password;
493 struct samr_CryptPassword password_buf;
495 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
498 r->in.credential, r->out.return_authenticator,
500 NT_STATUS_NOT_OK_RETURN(nt_status);
502 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);
503 if (sam_ctx == NULL) {
504 return NT_STATUS_INVALID_SYSTEM_SERVICE;
507 memcpy(password_buf.data, r->in.new_password->data, 512);
508 SIVAL(password_buf.data, 512, r->in.new_password->length);
510 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
511 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
513 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
516 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
517 DEBUG(3,("samr: failed to decode password buffer\n"));
518 return NT_STATUS_WRONG_PASSWORD;
521 /* fetch the old password hashes (at least one of both has to exist) */
523 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
524 "(&(objectClass=user)(objectSid=%s))",
525 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
527 return NT_STATUS_WRONG_PASSWORD;
530 nt_status = samdb_result_passwords(mem_ctx,
531 dce_call->conn->dce_ctx->lp_ctx,
532 res[0], &oldLmHash, &oldNtHash);
533 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
534 return NT_STATUS_WRONG_PASSWORD;
537 /* Using the sid for the account as the key, set the password */
538 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
540 &new_password, /* we have plaintext */
542 oldLmHash, oldNtHash, /* Password change */
551 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
552 struct netr_LogonUasLogon *r)
554 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
561 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
562 struct netr_LogonUasLogoff *r)
564 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
568 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
570 switch (r->in.logon_level) {
571 case NetlogonInteractiveInformation:
572 case NetlogonServiceInformation:
573 case NetlogonInteractiveTransitiveInformation:
574 case NetlogonServiceTransitiveInformation:
575 if (r->in.logon->password == NULL) {
576 return NT_STATUS_INVALID_PARAMETER;
579 switch (r->in.validation_level) {
580 case NetlogonValidationSamInfo: /* 2 */
581 case NetlogonValidationSamInfo2: /* 3 */
582 case NetlogonValidationSamInfo4: /* 6 */
585 return NT_STATUS_INVALID_INFO_CLASS;
589 case NetlogonNetworkInformation:
590 case NetlogonNetworkTransitiveInformation:
591 if (r->in.logon->network == NULL) {
592 return NT_STATUS_INVALID_PARAMETER;
595 switch (r->in.validation_level) {
596 case NetlogonValidationSamInfo: /* 2 */
597 case NetlogonValidationSamInfo2: /* 3 */
598 case NetlogonValidationSamInfo4: /* 6 */
601 return NT_STATUS_INVALID_INFO_CLASS;
606 case NetlogonGenericInformation:
607 if (r->in.logon->generic == NULL) {
608 return NT_STATUS_INVALID_PARAMETER;
611 switch (r->in.validation_level) {
612 /* TODO: case NetlogonValidationGenericInfo: 4 */
613 case NetlogonValidationGenericInfo2: /* 5 */
616 return NT_STATUS_INVALID_INFO_CLASS;
621 return NT_STATUS_INVALID_PARAMETER;
628 netr_LogonSamLogon_base
630 This version of the function allows other wrappers to say 'do not check the credentials'
632 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
634 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
635 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
637 struct auth4_context *auth_context;
638 struct auth_usersupplied_info *user_info;
639 struct auth_user_info_dc *user_info_dc;
641 struct netr_SamBaseInfo *sam;
642 struct netr_SamInfo2 *sam2;
643 struct netr_SamInfo3 *sam3;
644 struct netr_SamInfo6 *sam6;
646 *r->out.authoritative = 1;
648 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
649 NT_STATUS_HAVE_NO_MEMORY(user_info);
651 netlogon_creds_decrypt_samlogon_logon(creds,
655 switch (r->in.logon_level) {
656 case NetlogonInteractiveInformation:
657 case NetlogonServiceInformation:
658 case NetlogonInteractiveTransitiveInformation:
659 case NetlogonServiceTransitiveInformation:
661 /* TODO: we need to deny anonymous access here */
662 nt_status = auth_context_create(mem_ctx,
663 dce_call->event_ctx, dce_call->msg_ctx,
664 dce_call->conn->dce_ctx->lp_ctx,
666 NT_STATUS_NOT_OK_RETURN(nt_status);
668 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
669 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
670 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
671 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
673 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
674 user_info->password_state = AUTH_PASSWORD_HASH;
676 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
677 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
678 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
680 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
681 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
682 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
685 case NetlogonNetworkInformation:
686 case NetlogonNetworkTransitiveInformation:
688 /* TODO: we need to deny anonymous access here */
689 nt_status = auth_context_create(mem_ctx,
690 dce_call->event_ctx, dce_call->msg_ctx,
691 dce_call->conn->dce_ctx->lp_ctx,
693 NT_STATUS_NOT_OK_RETURN(nt_status);
695 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
696 NT_STATUS_NOT_OK_RETURN(nt_status);
698 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
699 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
700 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
701 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
703 user_info->password_state = AUTH_PASSWORD_RESPONSE;
704 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
705 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
710 case NetlogonGenericInformation:
712 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
714 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
717 /* Using DES to verify kerberos tickets makes no sense */
718 return NT_STATUS_INVALID_PARAMETER;
721 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
723 struct dcerpc_binding_handle *irpc_handle;
724 struct kdc_check_generic_kerberos check;
725 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
726 NT_STATUS_HAVE_NO_MEMORY(generic);
727 *r->out.authoritative = 1;
729 /* TODO: Describe and deal with these flags */
732 r->out.validation->generic = generic;
734 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
738 if (irpc_handle == NULL) {
739 return NT_STATUS_NO_LOGON_SERVERS;
742 check.in.generic_request =
743 data_blob_const(r->in.logon->generic->data,
744 r->in.logon->generic->length);
746 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
749 if (!NT_STATUS_IS_OK(status)) {
752 generic->length = check.out.generic_reply.length;
753 generic->data = check.out.generic_reply.data;
757 /* Until we get an implemetnation of these other packages */
758 return NT_STATUS_INVALID_PARAMETER;
761 return NT_STATUS_INVALID_PARAMETER;
764 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
765 /* TODO: set *r->out.authoritative = 0 on specific errors */
766 NT_STATUS_NOT_OK_RETURN(nt_status);
768 switch (r->in.validation_level) {
770 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
771 NT_STATUS_NOT_OK_RETURN(nt_status);
773 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
774 NT_STATUS_HAVE_NO_MEMORY(sam2);
777 /* And put into the talloc tree */
778 talloc_steal(sam2, sam);
779 r->out.validation->sam2 = sam2;
785 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
788 NT_STATUS_NOT_OK_RETURN(nt_status);
790 r->out.validation->sam3 = sam3;
796 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
799 NT_STATUS_NOT_OK_RETURN(nt_status);
801 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
802 NT_STATUS_HAVE_NO_MEMORY(sam6);
803 sam6->base = sam3->base;
805 sam6->sidcount = sam3->sidcount;
806 sam6->sids = sam3->sids;
808 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
809 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
810 sam->account_name.string, sam6->dns_domainname.string);
811 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
812 /* And put into the talloc tree */
813 talloc_steal(sam6, sam3);
815 r->out.validation->sam6 = sam6;
819 return NT_STATUS_INVALID_INFO_CLASS;
822 netlogon_creds_encrypt_samlogon_validation(creds,
823 r->in.validation_level,
826 /* TODO: Describe and deal with these flags */
832 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
833 struct netr_LogonSamLogonEx *r)
836 struct netlogon_creds_CredentialState *creds;
838 *r->out.authoritative = 1;
840 nt_status = dcesrv_netr_LogonSamLogon_check(r);
841 if (!NT_STATUS_IS_OK(nt_status)) {
845 nt_status = schannel_get_creds_state(mem_ctx,
846 dce_call->conn->dce_ctx->lp_ctx,
847 r->in.computer_name, &creds);
848 if (!NT_STATUS_IS_OK(nt_status)) {
852 if (!dce_call->conn->auth_state.auth_info ||
853 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
854 return NT_STATUS_ACCESS_DENIED;
856 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
860 netr_LogonSamLogonWithFlags
863 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
864 struct netr_LogonSamLogonWithFlags *r)
867 struct netlogon_creds_CredentialState *creds;
868 struct netr_LogonSamLogonEx r2;
870 struct netr_Authenticator *return_authenticator;
874 r2.in.server_name = r->in.server_name;
875 r2.in.computer_name = r->in.computer_name;
876 r2.in.logon_level = r->in.logon_level;
877 r2.in.logon = r->in.logon;
878 r2.in.validation_level = r->in.validation_level;
879 r2.in.flags = r->in.flags;
880 r2.out.validation = r->out.validation;
881 r2.out.authoritative = r->out.authoritative;
882 r2.out.flags = r->out.flags;
884 *r->out.authoritative = 1;
886 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
887 if (!NT_STATUS_IS_OK(nt_status)) {
891 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
892 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
894 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
897 r->in.credential, return_authenticator,
899 NT_STATUS_NOT_OK_RETURN(nt_status);
901 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
903 r->out.return_authenticator = return_authenticator;
911 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
912 struct netr_LogonSamLogon *r)
914 struct netr_LogonSamLogonWithFlags r2;
920 r2.in.server_name = r->in.server_name;
921 r2.in.computer_name = r->in.computer_name;
922 r2.in.credential = r->in.credential;
923 r2.in.return_authenticator = r->in.return_authenticator;
924 r2.in.logon_level = r->in.logon_level;
925 r2.in.logon = r->in.logon;
926 r2.in.validation_level = r->in.validation_level;
927 r2.in.flags = &flags;
928 r2.out.validation = r->out.validation;
929 r2.out.authoritative = r->out.authoritative;
930 r2.out.flags = &flags;
932 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
934 r->out.return_authenticator = r2.out.return_authenticator;
943 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
944 struct netr_LogonSamLogoff *r)
946 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
954 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
955 struct netr_DatabaseDeltas *r)
957 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
964 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
965 struct netr_DatabaseSync2 *r)
967 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
968 return NT_STATUS_NOT_IMPLEMENTED;
975 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
976 struct netr_DatabaseSync *r)
978 struct netr_DatabaseSync2 r2;
983 r2.in.logon_server = r->in.logon_server;
984 r2.in.computername = r->in.computername;
985 r2.in.credential = r->in.credential;
986 r2.in.database_id = r->in.database_id;
987 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
988 r2.in.sync_context = r->in.sync_context;
989 r2.out.sync_context = r->out.sync_context;
990 r2.out.delta_enum_array = r->out.delta_enum_array;
991 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
993 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1002 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1003 struct netr_AccountDeltas *r)
1005 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1006 return NT_STATUS_NOT_IMPLEMENTED;
1013 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1014 struct netr_AccountSync *r)
1016 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1017 return NT_STATUS_NOT_IMPLEMENTED;
1024 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1025 struct netr_GetDcName *r)
1027 const char * const attrs[] = { NULL };
1028 struct ldb_context *sam_ctx;
1029 struct ldb_message **res;
1030 struct ldb_dn *domain_dn;
1035 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1036 * that the domainname needs to be a valid netbios domain
1037 * name, if it is not NULL.
1039 if (r->in.domainname) {
1040 const char *dot = strchr(r->in.domainname, '.');
1041 size_t len = strlen(r->in.domainname);
1043 if (dot || len > 15) {
1044 return WERR_DCNOTFOUND;
1048 * TODO: Should we also varify that only valid
1049 * netbios name characters are used?
1053 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1054 dce_call->conn->dce_ctx->lp_ctx,
1055 dce_call->conn->auth_state.session_info, 0);
1056 if (sam_ctx == NULL) {
1057 return WERR_DS_UNAVAILABLE;
1060 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1062 if (domain_dn == NULL) {
1063 return WERR_NO_SUCH_DOMAIN;
1066 ret = gendb_search_dn(sam_ctx, mem_ctx,
1067 domain_dn, &res, attrs);
1069 return WERR_NO_SUCH_DOMAIN;
1072 /* TODO: - return real IP address
1073 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1075 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1076 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1077 W_ERROR_HAVE_NO_MEMORY(dcname);
1079 *r->out.dcname = dcname;
1085 netr_LogonControl2Ex
1087 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1088 struct netr_LogonControl2Ex *r)
1090 return WERR_NOT_SUPPORTED;
1097 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1098 struct netr_LogonControl *r)
1100 struct netr_LogonControl2Ex r2;
1103 if (r->in.level == 0x00000001) {
1106 r2.in.logon_server = r->in.logon_server;
1107 r2.in.function_code = r->in.function_code;
1108 r2.in.level = r->in.level;
1110 r2.out.query = r->out.query;
1112 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1113 } else if (r->in.level == 0x00000002) {
1114 werr = WERR_NOT_SUPPORTED;
1116 werr = WERR_UNKNOWN_LEVEL;
1126 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1127 struct netr_LogonControl2 *r)
1129 struct netr_LogonControl2Ex r2;
1134 r2.in.logon_server = r->in.logon_server;
1135 r2.in.function_code = r->in.function_code;
1136 r2.in.level = r->in.level;
1137 r2.in.data = r->in.data;
1138 r2.out.query = r->out.query;
1140 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1145 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1146 struct ldb_context *sam_ctx,
1147 struct netr_DomainTrustList *trusts,
1148 uint32_t trust_flags);
1153 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1154 struct netr_GetAnyDCName *r)
1156 struct netr_DomainTrustList *trusts;
1157 struct ldb_context *sam_ctx;
1158 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1162 *r->out.dcname = NULL;
1164 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1165 /* if the domainname parameter wasn't set assume our domain */
1166 r->in.domainname = lpcfg_workgroup(lp_ctx);
1169 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1170 dce_call->conn->auth_state.session_info, 0);
1171 if (sam_ctx == NULL) {
1172 return WERR_DS_UNAVAILABLE;
1175 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1176 /* well we asked for a DC of our own domain */
1177 if (samdb_is_pdc(sam_ctx)) {
1178 /* we are the PDC of the specified domain */
1179 return WERR_NO_SUCH_DOMAIN;
1182 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1183 lpcfg_netbios_name(lp_ctx));
1184 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1189 /* Okay, now we have to consider the trusted domains */
1191 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1192 W_ERROR_HAVE_NO_MEMORY(trusts);
1196 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1197 NETR_TRUST_FLAG_INBOUND
1198 | NETR_TRUST_FLAG_OUTBOUND);
1199 W_ERROR_NOT_OK_RETURN(werr);
1201 for (i = 0; i < trusts->count; i++) {
1202 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1203 /* FIXME: Here we need to find a DC for the specified
1204 * trusted domain. */
1206 /* return WERR_OK; */
1207 return WERR_NO_SUCH_DOMAIN;
1211 return WERR_NO_SUCH_DOMAIN;
1218 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1219 struct netr_DatabaseRedo *r)
1221 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1226 netr_NetrEnumerateTrustedDomains
1228 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1229 struct netr_NetrEnumerateTrustedDomains *r)
1231 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1236 netr_LogonGetCapabilities
1238 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1239 struct netr_LogonGetCapabilities *r)
1241 struct netlogon_creds_CredentialState *creds;
1244 status = dcesrv_netr_creds_server_step_check(dce_call,
1246 r->in.computer_name,
1248 r->out.return_authenticator,
1250 if (!NT_STATUS_IS_OK(status)) {
1251 DEBUG(0,(__location__ " Bad credentials - error\n"));
1253 NT_STATUS_NOT_OK_RETURN(status);
1255 if (r->in.query_level != 1) {
1256 return NT_STATUS_NOT_SUPPORTED;
1259 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1261 return NT_STATUS_OK;
1266 netr_NETRLOGONSETSERVICEBITS
1268 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1269 struct netr_NETRLOGONSETSERVICEBITS *r)
1271 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1276 netr_LogonGetTrustRid
1278 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1279 struct netr_LogonGetTrustRid *r)
1281 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1286 netr_NETRLOGONCOMPUTESERVERDIGEST
1288 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1289 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1291 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1296 netr_NETRLOGONCOMPUTECLIENTDIGEST
1298 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1299 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1301 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1309 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1310 struct netr_DsRGetSiteName *r)
1312 struct ldb_context *sam_ctx;
1313 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1315 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1316 dce_call->conn->auth_state.session_info, 0);
1317 if (sam_ctx == NULL) {
1318 return WERR_DS_UNAVAILABLE;
1322 * We assume to be a DC when we get called over NETLOGON. Hence we
1323 * get our site name always by using "samdb_server_site_name()"
1324 * and not "samdb_client_site_name()".
1326 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1327 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1334 fill in a netr_OneDomainInfo from a ldb search result
1336 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1337 struct loadparm_context *lp_ctx,
1338 struct ldb_context *sam_ctx,
1339 struct ldb_message *res,
1340 struct netr_OneDomainInfo *info,
1341 bool is_local, bool is_trust_list)
1345 if (is_trust_list) {
1346 /* w2k8 only fills this on trusted domains */
1347 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1348 info->trust_extension.length = 16;
1349 info->trust_extension.info->flags =
1350 NETR_TRUST_FLAG_TREEROOT |
1351 NETR_TRUST_FLAG_IN_FOREST |
1352 NETR_TRUST_FLAG_PRIMARY |
1353 NETR_TRUST_FLAG_NATIVE;
1355 info->trust_extension.info->parent_index = 0; /* should be index into array
1357 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1358 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1361 if (is_trust_list) {
1362 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1363 info->dns_forestname.string = NULL;
1365 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1366 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1367 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1368 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1372 info->domainname.string = lpcfg_workgroup(lp_ctx);
1373 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1374 info->domain_guid = samdb_result_guid(res, "objectGUID");
1375 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1377 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1378 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1379 info->domain_guid = samdb_result_guid(res, "objectGUID");
1380 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1382 if (!is_trust_list) {
1383 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1386 return NT_STATUS_OK;
1390 netr_LogonGetDomainInfo
1391 this is called as part of the ADS domain logon procedure.
1393 It has an important role in convaying details about the client, such
1394 as Operating System, Version, Service Pack etc.
1396 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1397 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1399 struct netlogon_creds_CredentialState *creds;
1400 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1401 "securityIdentifier", "trustPartner", NULL };
1402 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1403 "msDS-SupportedEncryptionTypes", NULL };
1404 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1405 struct ldb_context *sam_ctx;
1406 struct ldb_message **res1, **res2, **res3, *new_msg;
1407 struct ldb_dn *workstation_dn;
1408 struct netr_DomainInformation *domain_info;
1409 struct netr_LsaPolicyInformation *lsa_policy_info;
1410 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1411 bool update_dns_hostname = true;
1415 status = dcesrv_netr_creds_server_step_check(dce_call,
1417 r->in.computer_name,
1419 r->out.return_authenticator,
1421 if (!NT_STATUS_IS_OK(status)) {
1422 DEBUG(0,(__location__ " Bad credentials - error\n"));
1424 NT_STATUS_NOT_OK_RETURN(status);
1426 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1427 dce_call->conn->dce_ctx->lp_ctx,
1428 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1429 if (sam_ctx == NULL) {
1430 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1433 switch (r->in.level) {
1434 case 1: /* Domain information */
1436 if (r->in.query->workstation_info == NULL) {
1437 return NT_STATUS_INVALID_PARAMETER;
1440 /* Prepares the workstation DN */
1441 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1442 dom_sid_string(mem_ctx, creds->sid));
1443 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1445 /* Lookup for attributes in workstation object */
1446 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1449 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1452 /* Gets the sam account name which is checked against the DNS
1453 * hostname parameter. */
1454 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1457 if (sam_account_name == NULL) {
1458 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1462 * Checks that the sam account name without a possible "$"
1463 * matches as prefix with the DNS hostname in the workstation
1466 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1467 strcspn(sam_account_name, "$"));
1468 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1469 if (r->in.query->workstation_info->dns_hostname != NULL) {
1470 prefix2 = talloc_strndup(mem_ctx,
1471 r->in.query->workstation_info->dns_hostname,
1472 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1473 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1475 if (strcasecmp(prefix1, prefix2) != 0) {
1476 update_dns_hostname = false;
1479 update_dns_hostname = false;
1482 /* Gets the old DNS hostname */
1483 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1488 * Updates the DNS hostname when the client wishes that the
1489 * server should handle this for him
1490 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1491 * obviously only checked when we do already have a
1493 * See MS-NRPC section 3.5.4.3.9
1495 if ((old_dns_hostname != NULL) &&
1496 (r->in.query->workstation_info->workstation_flags
1497 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1498 update_dns_hostname = false;
1501 /* Gets host information and put them into our directory */
1503 new_msg = ldb_msg_new(mem_ctx);
1504 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1506 new_msg->dn = workstation_dn;
1508 /* Sets the OS name */
1510 if (r->in.query->workstation_info->os_name.string == NULL) {
1511 return NT_STATUS_INVALID_PARAMETER;
1514 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1515 r->in.query->workstation_info->os_name.string);
1516 if (ret != LDB_SUCCESS) {
1517 return NT_STATUS_NO_MEMORY;
1521 * Sets information from "os_version". On an empty structure
1522 * the values are cleared.
1524 if (r->in.query->workstation_info->os_version.os != NULL) {
1525 struct netr_OsVersionInfoEx *os_version;
1526 const char *os_version_str;
1528 os_version = &r->in.query->workstation_info->os_version.os->os;
1530 if (os_version->CSDVersion == NULL) {
1531 return NT_STATUS_INVALID_PARAMETER;
1534 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1535 os_version->MajorVersion,
1536 os_version->MinorVersion,
1537 os_version->BuildNumber);
1538 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1540 ret = ldb_msg_add_string(new_msg,
1541 "operatingSystemServicePack",
1542 os_version->CSDVersion);
1543 if (ret != LDB_SUCCESS) {
1544 return NT_STATUS_NO_MEMORY;
1547 ret = ldb_msg_add_string(new_msg,
1548 "operatingSystemVersion",
1550 if (ret != LDB_SUCCESS) {
1551 return NT_STATUS_NO_MEMORY;
1554 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1555 "operatingSystemServicePack");
1556 if (ret != LDB_SUCCESS) {
1557 return NT_STATUS_NO_MEMORY;
1560 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1561 "operatingSystemVersion");
1562 if (ret != LDB_SUCCESS) {
1563 return NT_STATUS_NO_MEMORY;
1568 * If the boolean "update_dns_hostname" remained true, then we
1569 * are fine to start the update.
1571 if (update_dns_hostname) {
1572 ret = ldb_msg_add_string(new_msg,
1574 r->in.query->workstation_info->dns_hostname);
1575 if (ret != LDB_SUCCESS) {
1576 return NT_STATUS_NO_MEMORY;
1579 /* This manual "servicePrincipalName" generation is
1580 * still needed! Since the update in the samldb LDB
1581 * module does only work if the entries already exist
1582 * which isn't always the case. */
1583 ret = ldb_msg_add_string(new_msg,
1584 "servicePrincipalName",
1585 talloc_asprintf(new_msg, "HOST/%s",
1586 r->in.computer_name));
1587 if (ret != LDB_SUCCESS) {
1588 return NT_STATUS_NO_MEMORY;
1591 ret = ldb_msg_add_string(new_msg,
1592 "servicePrincipalName",
1593 talloc_asprintf(new_msg, "HOST/%s",
1594 r->in.query->workstation_info->dns_hostname));
1595 if (ret != LDB_SUCCESS) {
1596 return NT_STATUS_NO_MEMORY;
1600 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1601 DEBUG(3,("Impossible to update samdb: %s\n",
1602 ldb_errstring(sam_ctx)));
1605 talloc_free(new_msg);
1607 /* Writes back the domain information */
1609 /* We need to do two searches. The first will pull our primary
1610 domain and the second will pull any trusted domains. Our
1611 primary domain is also a "trusted" domain, so we need to
1612 put the primary domain into the lists of returned trusts as
1614 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1617 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1620 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1621 "(objectClass=trustedDomain)");
1623 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1626 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1627 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1629 ZERO_STRUCTP(domain_info);
1631 /* Informations about the local and trusted domains */
1633 status = fill_one_domain_info(mem_ctx,
1634 dce_call->conn->dce_ctx->lp_ctx,
1635 sam_ctx, res2[0], &domain_info->primary_domain,
1637 NT_STATUS_NOT_OK_RETURN(status);
1639 domain_info->trusted_domain_count = ret3 + 1;
1640 domain_info->trusted_domains = talloc_array(mem_ctx,
1641 struct netr_OneDomainInfo,
1642 domain_info->trusted_domain_count);
1643 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1645 for (i=0;i<ret3;i++) {
1646 status = fill_one_domain_info(mem_ctx,
1647 dce_call->conn->dce_ctx->lp_ctx,
1649 &domain_info->trusted_domains[i],
1651 NT_STATUS_NOT_OK_RETURN(status);
1654 status = fill_one_domain_info(mem_ctx,
1655 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1656 &domain_info->trusted_domains[i], true, true);
1657 NT_STATUS_NOT_OK_RETURN(status);
1659 /* Sets the supported encryption types */
1660 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1661 "msDS-SupportedEncryptionTypes",
1662 default_supported_enc_types);
1664 /* Other host domain information */
1666 lsa_policy_info = talloc(mem_ctx,
1667 struct netr_LsaPolicyInformation);
1668 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1669 ZERO_STRUCTP(lsa_policy_info);
1671 domain_info->lsa_policy = *lsa_policy_info;
1673 /* The DNS hostname is only returned back when there is a chance
1675 if ((r->in.query->workstation_info->workstation_flags
1676 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1677 domain_info->dns_hostname.string = old_dns_hostname;
1679 domain_info->dns_hostname.string = NULL;
1682 domain_info->workstation_flags =
1683 r->in.query->workstation_info->workstation_flags & (
1684 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1686 r->out.info->domain_info = domain_info;
1688 case 2: /* LSA policy information - not used at the moment */
1689 lsa_policy_info = talloc(mem_ctx,
1690 struct netr_LsaPolicyInformation);
1691 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1692 ZERO_STRUCTP(lsa_policy_info);
1694 r->out.info->lsa_policy_info = lsa_policy_info;
1697 return NT_STATUS_INVALID_LEVEL;
1701 return NT_STATUS_OK;
1706 netr_ServerPasswordGet
1708 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1709 struct netr_ServerPasswordGet *r)
1711 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1716 netr_NETRLOGONSENDTOSAM
1718 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1719 struct netr_NETRLOGONSENDTOSAM *r)
1721 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1726 netr_DsRGetDCNameEx2
1728 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1729 TALLOC_CTX *mem_ctx,
1730 struct netr_DsRGetDCNameEx2 *r)
1732 struct ldb_context *sam_ctx;
1733 struct netr_DsRGetDCNameInfo *info;
1734 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1735 const struct tsocket_address *remote_address;
1737 const char *server_site_name;
1739 struct netlogon_samlogon_response response;
1741 const char *dc_name = NULL;
1742 const char *domain_name = NULL;
1743 struct interface *ifaces;
1746 ZERO_STRUCTP(r->out.info);
1748 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1749 dce_call->conn->auth_state.session_info, 0);
1750 if (sam_ctx == NULL) {
1751 return WERR_DS_UNAVAILABLE;
1754 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1755 if (tsocket_address_is_inet(remote_address, "ip")) {
1756 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1757 W_ERROR_HAVE_NO_MEMORY(addr);
1760 /* "server_unc" is ignored by w2k3 */
1762 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1763 return WERR_INVALID_FLAGS;
1766 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1767 r->in.flags & DS_PDC_REQUIRED &&
1768 r->in.flags & DS_KDC_REQUIRED) {
1769 return WERR_INVALID_FLAGS;
1771 if (r->in.flags & DS_IS_FLAT_NAME &&
1772 r->in.flags & DS_IS_DNS_NAME) {
1773 return WERR_INVALID_FLAGS;
1775 if (r->in.flags & DS_RETURN_DNS_NAME &&
1776 r->in.flags & DS_RETURN_FLAT_NAME) {
1777 return WERR_INVALID_FLAGS;
1779 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1780 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1781 return WERR_INVALID_FLAGS;
1784 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1786 (DS_DIRECTORY_SERVICE_REQUIRED |
1787 DS_DIRECTORY_SERVICE_PREFERRED |
1788 DS_GC_SERVER_REQUIRED |
1791 return WERR_INVALID_FLAGS;
1794 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1796 return WERR_INVALID_FLAGS;
1799 /* Proof server site parameter "site_name" if it was specified */
1800 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1801 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1802 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1803 server_site_name) != 0)) {
1804 return WERR_NO_SUCH_DOMAIN;
1807 guid_str = r->in.domain_guid != NULL ?
1808 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1810 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1814 r->in.client_account,
1816 NETLOGON_NT_VERSION_5EX_WITH_IP,
1817 lp_ctx, &response, true);
1818 if (!NT_STATUS_IS_OK(status)) {
1819 return ntstatus_to_werror(status);
1823 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1824 * (O) flag when the returned forest name is in DNS format. This is here
1825 * always the case (see below).
1827 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1829 if (r->in.flags & DS_RETURN_DNS_NAME) {
1830 dc_name = response.data.nt5_ex.pdc_dns_name;
1831 domain_name = response.data.nt5_ex.dns_domain;
1833 * According to MS-NRPC 2.2.1.2.1 we should set the
1834 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1835 * the returned information is in DNS form.
1837 response.data.nt5_ex.server_type |=
1838 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1839 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1840 dc_name = response.data.nt5_ex.pdc_name;
1841 domain_name = response.data.nt5_ex.domain_name;
1845 * TODO: autodetect what we need to return
1846 * based on the given arguments
1848 dc_name = response.data.nt5_ex.pdc_name;
1849 domain_name = response.data.nt5_ex.domain_name;
1852 if (!dc_name || !dc_name[0]) {
1853 return WERR_NO_SUCH_DOMAIN;
1856 if (!domain_name || !domain_name[0]) {
1857 return WERR_NO_SUCH_DOMAIN;
1860 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1861 W_ERROR_HAVE_NO_MEMORY(info);
1862 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1863 dc_name[0] == '\\'? "\\\\":"",
1864 talloc_strdup(mem_ctx, dc_name));
1865 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1867 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1868 pdc_ip = iface_list_best_ip(ifaces, addr);
1869 if (pdc_ip == NULL) {
1870 pdc_ip = "127.0.0.1";
1872 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1873 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1874 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1875 info->domain_guid = response.data.nt5_ex.domain_uuid;
1876 info->domain_name = domain_name;
1877 info->forest_name = response.data.nt5_ex.forest;
1878 info->dc_flags = response.data.nt5_ex.server_type;
1879 if (r->in.flags & DS_RETURN_DNS_NAME) {
1880 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
1881 * returned if we are returning info->dc_unc containing a FQDN.
1882 * This attribute is called DomainControllerName in the specs,
1883 * it seems that we decide to return FQDN or netbios depending on
1884 * DS_RETURN_DNS_NAME.
1886 info->dc_flags |= DS_DNS_CONTROLLER;
1888 info->dc_site_name = response.data.nt5_ex.server_site;
1889 info->client_site_name = response.data.nt5_ex.client_site;
1891 *r->out.info = info;
1899 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1900 struct netr_DsRGetDCNameEx *r)
1902 struct netr_DsRGetDCNameEx2 r2;
1907 r2.in.server_unc = r->in.server_unc;
1908 r2.in.client_account = NULL;
1910 r2.in.domain_guid = r->in.domain_guid;
1911 r2.in.domain_name = r->in.domain_name;
1912 r2.in.site_name = r->in.site_name;
1913 r2.in.flags = r->in.flags;
1914 r2.out.info = r->out.info;
1916 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1924 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1925 struct netr_DsRGetDCName *r)
1927 struct netr_DsRGetDCNameEx2 r2;
1932 r2.in.server_unc = r->in.server_unc;
1933 r2.in.client_account = NULL;
1935 r2.in.domain_name = r->in.domain_name;
1936 r2.in.domain_guid = r->in.domain_guid;
1938 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1939 r2.in.flags = r->in.flags;
1940 r2.out.info = r->out.info;
1942 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1947 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1949 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1950 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1952 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1957 netr_NetrEnumerateTrustedDomainsEx
1959 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1960 struct netr_NetrEnumerateTrustedDomainsEx *r)
1962 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1967 netr_DsRAddressToSitenamesExW
1969 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1970 struct netr_DsRAddressToSitenamesExW *r)
1972 struct ldb_context *sam_ctx;
1973 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1974 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1975 sa_family_t sin_family;
1976 struct sockaddr_in *addr;
1978 struct sockaddr_in6 *addr6;
1979 char addr_str[INET6_ADDRSTRLEN];
1981 char addr_str[INET_ADDRSTRLEN];
1987 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1988 dce_call->conn->auth_state.session_info, 0);
1989 if (sam_ctx == NULL) {
1990 return WERR_DS_UNAVAILABLE;
1993 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1994 W_ERROR_HAVE_NO_MEMORY(ctr);
1998 ctr->count = r->in.count;
1999 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2000 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2001 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2002 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2004 for (i=0; i<ctr->count; i++) {
2005 ctr->sitename[i].string = NULL;
2006 ctr->subnetname[i].string = NULL;
2008 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2011 /* The first two byte of the buffer are reserved for the
2012 * "sin_family" but for now only the first one is used. */
2013 sin_family = r->in.addresses[i].buffer[0];
2015 switch (sin_family) {
2017 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2020 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2021 res = inet_ntop(AF_INET, &addr->sin_addr,
2022 addr_str, sizeof(addr_str));
2026 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2029 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2030 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2031 addr_str, sizeof(addr_str));
2042 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2046 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2047 ctr->subnetname[i].string = subnet_name;
2055 netr_DsRAddressToSitenamesW
2057 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2058 struct netr_DsRAddressToSitenamesW *r)
2060 struct netr_DsRAddressToSitenamesExW r2;
2061 struct netr_DsRAddressToSitenamesWCtr *ctr;
2067 r2.in.server_name = r->in.server_name;
2068 r2.in.count = r->in.count;
2069 r2.in.addresses = r->in.addresses;
2071 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2072 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2074 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2075 W_ERROR_HAVE_NO_MEMORY(ctr);
2079 ctr->count = r->in.count;
2080 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2081 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2083 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2085 for (i=0; i<ctr->count; i++) {
2086 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2094 netr_DsrGetDcSiteCoverageW
2096 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2097 struct netr_DsrGetDcSiteCoverageW *r)
2099 struct ldb_context *sam_ctx;
2100 struct DcSitesCtr *ctr;
2101 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2103 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2104 dce_call->conn->auth_state.session_info, 0);
2105 if (sam_ctx == NULL) {
2106 return WERR_DS_UNAVAILABLE;
2109 ctr = talloc(mem_ctx, struct DcSitesCtr);
2110 W_ERROR_HAVE_NO_MEMORY(ctr);
2114 /* For now only return our default site */
2116 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2117 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2118 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2119 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2125 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2126 struct ldb_context *sam_ctx,
2127 struct netr_DomainTrustList *trusts,
2128 uint32_t trust_flags)
2130 struct ldb_dn *system_dn;
2131 struct ldb_message **dom_res = NULL;
2132 const char *trust_attrs[] = { "flatname", "trustPartner",
2133 "securityIdentifier", "trustDirection",
2134 "trustType", "trustAttributes", NULL };
2139 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2140 NETR_TRUST_FLAG_OUTBOUND))) {
2141 return WERR_INVALID_FLAGS;
2144 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2145 ldb_get_default_basedn(sam_ctx),
2146 "(&(objectClass=container)(cn=System))");
2148 return WERR_GENERAL_FAILURE;
2151 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2152 &dom_res, trust_attrs,
2153 "(objectclass=trustedDomain)");
2155 for (i = 0; i < ret; i++) {
2156 unsigned int trust_dir;
2159 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2160 "trustDirection", 0);
2162 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2163 flags |= NETR_TRUST_FLAG_INBOUND;
2165 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2166 flags |= NETR_TRUST_FLAG_OUTBOUND;
2169 if (!(flags & trust_flags)) {
2170 /* this trust direction was not requested */
2175 trusts->array = talloc_realloc(trusts, trusts->array,
2176 struct netr_DomainTrust,
2178 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2180 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2181 if (!trusts->array[n].netbios_name) {
2182 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2183 "without flatname\n",
2184 ldb_dn_get_linearized(dom_res[i]->dn)));
2187 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2189 trusts->array[n].trust_flags = flags;
2190 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2191 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2192 /* TODO: find if we have parent in the list */
2193 trusts->array[n].parent_index = 0;
2196 trusts->array[n].trust_type =
2197 ldb_msg_find_attr_as_uint(dom_res[i],
2199 trusts->array[n].trust_attributes =
2200 ldb_msg_find_attr_as_uint(dom_res[i],
2201 "trustAttributes", 0);
2203 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2204 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2205 struct dom_sid zero_sid;
2206 ZERO_STRUCT(zero_sid);
2207 trusts->array[n].sid =
2208 dom_sid_dup(trusts, &zero_sid);
2210 trusts->array[n].sid =
2211 samdb_result_dom_sid(trusts, dom_res[i],
2212 "securityIdentifier");
2214 trusts->array[n].guid = GUID_zero();
2216 trusts->count = n + 1;
2219 talloc_free(dom_res);
2224 netr_DsrEnumerateDomainTrusts
2226 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2227 TALLOC_CTX *mem_ctx,
2228 struct netr_DsrEnumerateDomainTrusts *r)
2230 struct netr_DomainTrustList *trusts;
2231 struct ldb_context *sam_ctx;
2233 struct ldb_message **dom_res;
2234 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2235 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2236 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2240 if (r->in.trust_flags & 0xFFFFFE00) {
2241 return WERR_INVALID_FLAGS;
2244 /* TODO: turn to hard check once we are sure this is 100% correct */
2245 if (!r->in.server_name) {
2246 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2247 "But received NULL!\n", dnsdomain));
2249 p = strchr(r->in.server_name, '.');
2251 DEBUG(3, ("Invalid domain! Expected name in domain "
2252 "[%s]. But received [%s]!\n",
2253 dnsdomain, r->in.server_name));
2254 p = r->in.server_name;
2258 if (strcasecmp(p, dnsdomain)) {
2259 DEBUG(3, ("Invalid domain! Expected name in domain "
2260 "[%s]. But received [%s]!\n",
2261 dnsdomain, r->in.server_name));
2265 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2266 W_ERROR_HAVE_NO_MEMORY(trusts);
2269 r->out.trusts = trusts;
2271 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2272 dce_call->conn->auth_state.session_info, 0);
2273 if (sam_ctx == NULL) {
2274 return WERR_GENERAL_FAILURE;
2277 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2278 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2280 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2281 trusts, r->in.trust_flags);
2282 W_ERROR_NOT_OK_RETURN(werr);
2285 /* NOTE: we currently are always the root of the forest */
2286 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2287 uint32_t n = trusts->count;
2289 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2290 &dom_res, dom_attrs);
2292 return WERR_GENERAL_FAILURE;
2295 trusts->count = n + 1;
2296 trusts->array = talloc_realloc(trusts, trusts->array,
2297 struct netr_DomainTrust,
2299 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2301 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2302 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2303 trusts->array[n].trust_flags =
2304 NETR_TRUST_FLAG_NATIVE |
2305 NETR_TRUST_FLAG_TREEROOT |
2306 NETR_TRUST_FLAG_IN_FOREST |
2307 NETR_TRUST_FLAG_PRIMARY;
2308 /* we are always the root domain for now */
2309 trusts->array[n].parent_index = 0;
2310 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2311 trusts->array[n].trust_attributes = 0;
2312 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2315 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2317 talloc_free(dom_res);
2325 netr_DsrDeregisterDNSHostRecords
2327 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2328 struct netr_DsrDeregisterDNSHostRecords *r)
2330 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2335 netr_ServerTrustPasswordsGet
2337 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2338 struct netr_ServerTrustPasswordsGet *r)
2340 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2344 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2345 struct ldb_context *sam_ctx,
2346 struct loadparm_context *lp_ctx,
2347 struct lsa_ForestTrustInformation *info)
2349 struct lsa_ForestTrustDomainInfo *domain_info;
2350 struct lsa_ForestTrustRecord *e;
2351 struct ldb_message **dom_res;
2352 const char * const dom_attrs[] = { "objectSid", NULL };
2355 /* we need to provide 2 entries:
2356 * 1. the Root Forest name
2357 * 2. the Domain Information
2361 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2362 W_ERROR_HAVE_NO_MEMORY(info->entries);
2364 /* Forest root info */
2365 e = talloc(info, struct lsa_ForestTrustRecord);
2366 W_ERROR_HAVE_NO_MEMORY(e);
2369 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2370 e->time = 0; /* so far always 0 in trces. */
2371 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2373 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2375 info->entries[0] = e;
2378 e = talloc(info, struct lsa_ForestTrustRecord);
2379 W_ERROR_HAVE_NO_MEMORY(e);
2381 /* get our own domain info */
2382 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2384 return WERR_GENERAL_FAILURE;
2387 /* TODO: check if disabled and set flags accordingly */
2389 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2390 e->time = 0; /* so far always 0 in traces. */
2392 domain_info = &e->forest_trust_data.domain_info;
2393 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2395 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2396 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2398 info->entries[1] = e;
2400 talloc_free(dom_res);
2406 netr_DsRGetForestTrustInformation
2408 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2409 TALLOC_CTX *mem_ctx,
2410 struct netr_DsRGetForestTrustInformation *r)
2412 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2413 struct lsa_ForestTrustInformation *info, **info_ptr;
2414 struct ldb_context *sam_ctx;
2417 if (r->in.flags & 0xFFFFFFFE) {
2418 return WERR_INVALID_FLAGS;
2421 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2422 dce_call->conn->auth_state.session_info, 0);
2423 if (sam_ctx == NULL) {
2424 return WERR_GENERAL_FAILURE;
2427 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2428 if (!samdb_is_pdc(sam_ctx)) {
2429 return WERR_NERR_NOTPRIMARY;
2432 if (r->in.trusted_domain_name == NULL) {
2433 return WERR_INVALID_FLAGS;
2436 /* TODO: establish an schannel connection with
2437 * r->in.trusted_domain_name and perform a
2438 * netr_GetForestTrustInformation call against it */
2440 /* for now return not implementd */
2441 return WERR_CALL_NOT_IMPLEMENTED;
2444 /* TODO: check r->in.server_name is our name */
2446 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2447 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2449 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2450 W_ERROR_HAVE_NO_MEMORY(info);
2452 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2453 W_ERROR_NOT_OK_RETURN(werr);
2456 r->out.forest_trust_info = info_ptr;
2463 netr_GetForestTrustInformation
2465 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2466 TALLOC_CTX *mem_ctx,
2467 struct netr_GetForestTrustInformation *r)
2469 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2470 struct netlogon_creds_CredentialState *creds;
2471 struct lsa_ForestTrustInformation *info, **info_ptr;
2472 struct ldb_context *sam_ctx;
2476 status = dcesrv_netr_creds_server_step_check(dce_call,
2478 r->in.computer_name,
2480 r->out.return_authenticator,
2482 if (!NT_STATUS_IS_OK(status)) {
2486 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2487 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2488 return NT_STATUS_NOT_IMPLEMENTED;
2491 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2492 dce_call->conn->auth_state.session_info, 0);
2493 if (sam_ctx == NULL) {
2494 return NT_STATUS_INTERNAL_ERROR;
2497 /* TODO: check r->in.server_name is our name */
2499 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2501 return NT_STATUS_NO_MEMORY;
2503 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2505 return NT_STATUS_NO_MEMORY;
2508 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2509 if (!W_ERROR_IS_OK(werr)) {
2510 return werror_to_ntstatus(werr);
2514 r->out.forest_trust_info = info_ptr;
2516 return NT_STATUS_OK;
2521 netr_ServerGetTrustInfo
2523 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2524 struct netr_ServerGetTrustInfo *r)
2526 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2532 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2533 struct netr_Unused47 *r)
2535 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2539 struct netr_dnsupdate_RODC_state {
2540 struct dcesrv_call_state *dce_call;
2541 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2542 struct dnsupdate_RODC *r2;
2546 called when the forwarded RODC dns update request is finished
2548 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2550 struct netr_dnsupdate_RODC_state *st =
2551 tevent_req_callback_data(subreq,
2552 struct netr_dnsupdate_RODC_state);
2555 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2556 TALLOC_FREE(subreq);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2559 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2562 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2564 status = dcesrv_reply(st->dce_call);
2565 if (!NT_STATUS_IS_OK(status)) {
2566 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2571 netr_DsrUpdateReadOnlyServerDnsRecords
2573 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2574 TALLOC_CTX *mem_ctx,
2575 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2577 struct netlogon_creds_CredentialState *creds;
2579 struct dcerpc_binding_handle *binding_handle;
2580 struct netr_dnsupdate_RODC_state *st;
2581 struct tevent_req *subreq;
2583 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2585 r->in.computer_name,
2587 r->out.return_authenticator,
2589 NT_STATUS_NOT_OK_RETURN(nt_status);
2591 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2592 return NT_STATUS_ACCESS_DENIED;
2595 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2596 NT_STATUS_HAVE_NO_MEMORY(st);
2598 st->dce_call = dce_call;
2600 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2601 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2603 st->r2->in.dom_sid = creds->sid;
2604 st->r2->in.site_name = r->in.site_name;
2605 st->r2->in.dns_ttl = r->in.dns_ttl;
2606 st->r2->in.dns_names = r->in.dns_names;
2607 st->r2->out.dns_names = r->out.dns_names;
2609 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2610 "dnsupdate", &ndr_table_irpc);
2611 if (binding_handle == NULL) {
2612 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2613 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2614 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2617 /* forward the call */
2618 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2619 binding_handle, st->r2);
2620 NT_STATUS_HAVE_NO_MEMORY(subreq);
2622 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2624 /* setup the callback */
2625 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2627 return NT_STATUS_OK;
2631 /* include the generated boilerplate */
2632 #include "librpc/gen_ndr/ndr_netlogon_s.c"