2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "cldap_server/cldap_server.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
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 negotiate_flags = 0;
96 ZERO_STRUCTP(r->out.return_credentials);
99 negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
100 NETLOGON_NEG_PERSISTENT_SAMREPL |
101 NETLOGON_NEG_ARCFOUR |
102 NETLOGON_NEG_PROMOTION_COUNT |
103 NETLOGON_NEG_CHANGELOG_BDC |
104 NETLOGON_NEG_FULL_SYNC_REPL |
105 NETLOGON_NEG_MULTIPLE_SIDS |
107 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
108 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
109 NETLOGON_NEG_GENERIC_PASSTHROUGH |
110 NETLOGON_NEG_CONCURRENT_RPC |
111 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
112 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
113 NETLOGON_NEG_TRANSITIVE_TRUSTS |
114 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
115 NETLOGON_NEG_PASSWORD_SET2 |
116 NETLOGON_NEG_GETDOMAININFO |
117 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
118 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
119 NETLOGON_NEG_RODC_PASSTHROUGH |
120 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
121 NETLOGON_NEG_AUTHENTICATED_RPC;
123 if (*r->in.negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
124 negotiate_flags |= NETLOGON_NEG_STRONG_KEYS;
127 if (*r->in.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
128 negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
132 * According to Microsoft (see bugid #6099)
133 * Windows 7 looks at the negotiate_flags
134 * returned in this structure *even if the
135 * call fails with access denied!
137 *r->out.negotiate_flags = negotiate_flags;
139 switch (r->in.secure_channel_type) {
141 case SEC_CHAN_DNS_DOMAIN:
142 case SEC_CHAN_DOMAIN:
147 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
148 r->in.secure_channel_type));
149 return NT_STATUS_INVALID_PARAMETER;
152 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
153 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
154 if (sam_ctx == NULL) {
155 return NT_STATUS_INVALID_SYSTEM_SERVICE;
158 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
159 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
160 const char *flatname;
161 if (!encoded_account) {
162 return NT_STATUS_NO_MEMORY;
165 /* Kill the trailing dot */
166 if (encoded_account[strlen(encoded_account)-1] == '.') {
167 encoded_account[strlen(encoded_account)-1] = '\0';
170 /* pull the user attributes */
171 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
173 "(&(trustPartner=%s)(objectclass=trustedDomain))",
176 if (num_records == 0) {
177 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
179 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
182 if (num_records > 1) {
183 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
184 return NT_STATUS_INTERNAL_DB_CORRUPTION;
187 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
189 /* No flatname for this trust - we can't proceed */
190 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
192 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
195 return NT_STATUS_NO_MEMORY;
199 account_name = r->in.account_name;
202 /* pull the user attributes */
203 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
204 "(&(sAMAccountName=%s)(objectclass=user))",
205 ldb_binary_encode_string(mem_ctx, account_name));
207 if (num_records == 0) {
208 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
209 r->in.account_name));
210 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
213 if (num_records > 1) {
214 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
215 return NT_STATUS_INTERNAL_DB_CORRUPTION;
218 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
220 if (user_account_control & UF_ACCOUNTDISABLE) {
221 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
222 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
225 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
226 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
227 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
228 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
230 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
231 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
232 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
233 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
235 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
237 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
238 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
239 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
240 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
242 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
243 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
244 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
245 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
248 /* we should never reach this */
249 return NT_STATUS_INTERNAL_ERROR;
252 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
255 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
256 if (mach_pwd == NULL) {
257 return NT_STATUS_ACCESS_DENIED;
261 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
262 return NT_STATUS_ACCESS_DENIED;
265 creds = netlogon_creds_server_init(mem_ctx,
268 r->in.secure_channel_type,
269 &pipe_state->client_challenge,
270 &pipe_state->server_challenge,
273 r->out.return_credentials,
276 return NT_STATUS_ACCESS_DENIED;
279 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
281 nt_status = schannel_save_creds_state(mem_ctx,
282 dce_call->conn->dce_ctx->lp_ctx,
288 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
289 struct netr_ServerAuthenticate *r)
291 struct netr_ServerAuthenticate3 a;
294 * negotiate_flags is used as an [in] parameter
295 * so it need to be initialised.
297 * (I think ... = 0; seems wrong here --metze)
299 uint32_t negotiate_flags_in = 0;
300 uint32_t negotiate_flags_out = 0;
302 a.in.server_name = r->in.server_name;
303 a.in.account_name = r->in.account_name;
304 a.in.secure_channel_type = r->in.secure_channel_type;
305 a.in.computer_name = r->in.computer_name;
306 a.in.credentials = r->in.credentials;
307 a.in.negotiate_flags = &negotiate_flags_in;
309 a.out.return_credentials = r->out.return_credentials;
311 a.out.negotiate_flags = &negotiate_flags_out;
313 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
316 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
317 struct netr_ServerAuthenticate2 *r)
319 struct netr_ServerAuthenticate3 r3;
322 r3.in.server_name = r->in.server_name;
323 r3.in.account_name = r->in.account_name;
324 r3.in.secure_channel_type = r->in.secure_channel_type;
325 r3.in.computer_name = r->in.computer_name;
326 r3.in.credentials = r->in.credentials;
327 r3.out.return_credentials = r->out.return_credentials;
328 r3.in.negotiate_flags = r->in.negotiate_flags;
329 r3.out.negotiate_flags = r->out.negotiate_flags;
332 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
336 * NOTE: The following functions are nearly identical to the ones available in
337 * source3/rpc_server/srv_nelog_nt.c
338 * The reason we keep 2 copies is that they use different structures to
339 * represent the auth_info and the decrpc pipes.
343 * If schannel is required for this call test that it actually is available.
345 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
346 const char *computer_name,
347 bool integrity, bool privacy)
350 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
351 if (!privacy && !integrity) {
355 if ((!privacy && integrity) &&
356 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
360 if ((privacy || integrity) &&
361 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
366 /* test didn't pass */
367 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
370 return NT_STATUS_ACCESS_DENIED;
373 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
375 const char *computer_name,
376 struct netr_Authenticator *received_authenticator,
377 struct netr_Authenticator *return_authenticator,
378 struct netlogon_creds_CredentialState **creds_out)
381 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
382 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
384 if (schannel_global_required) {
385 nt_status = schannel_check_required(auth_info,
388 if (!NT_STATUS_IS_OK(nt_status)) {
393 nt_status = schannel_check_creds_state(mem_ctx,
394 dce_call->conn->dce_ctx->lp_ctx,
396 received_authenticator,
397 return_authenticator,
403 Change the machine account password for the currently connected
404 client. Supplies only the NT#.
407 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
408 struct netr_ServerPasswordSet *r)
410 struct netlogon_creds_CredentialState *creds;
411 struct ldb_context *sam_ctx;
412 const char * const attrs[] = { "unicodePwd", NULL };
413 struct ldb_message **res;
414 struct samr_Password *oldNtHash;
418 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
421 r->in.credential, r->out.return_authenticator,
423 NT_STATUS_NOT_OK_RETURN(nt_status);
425 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);
426 if (sam_ctx == NULL) {
427 return NT_STATUS_INVALID_SYSTEM_SERVICE;
430 netlogon_creds_des_decrypt(creds, r->in.new_password);
432 /* fetch the old password hashes (the NT hash has to exist) */
434 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
435 "(&(objectClass=user)(objectSid=%s))",
436 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
438 return NT_STATUS_WRONG_PASSWORD;
441 nt_status = samdb_result_passwords(mem_ctx,
442 dce_call->conn->dce_ctx->lp_ctx,
443 res[0], NULL, &oldNtHash);
444 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
445 return NT_STATUS_WRONG_PASSWORD;
448 /* Using the sid for the account as the key, set the password */
449 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
451 NULL, /* Don't have plaintext */
452 NULL, r->in.new_password,
453 NULL, oldNtHash, /* Password change */
459 Change the machine account password for the currently connected
460 client. Supplies new plaintext.
462 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
463 struct netr_ServerPasswordSet2 *r)
465 struct netlogon_creds_CredentialState *creds;
466 struct ldb_context *sam_ctx;
467 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
468 struct ldb_message **res;
469 struct samr_Password *oldLmHash, *oldNtHash;
471 DATA_BLOB new_password;
474 struct samr_CryptPassword password_buf;
476 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
479 r->in.credential, r->out.return_authenticator,
481 NT_STATUS_NOT_OK_RETURN(nt_status);
483 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);
484 if (sam_ctx == NULL) {
485 return NT_STATUS_INVALID_SYSTEM_SERVICE;
488 memcpy(password_buf.data, r->in.new_password->data, 512);
489 SIVAL(password_buf.data, 512, r->in.new_password->length);
491 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
492 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
494 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
497 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
498 DEBUG(3,("samr: failed to decode password buffer\n"));
499 return NT_STATUS_WRONG_PASSWORD;
502 /* fetch the old password hashes (at least one of both has to exist) */
504 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
505 "(&(objectClass=user)(objectSid=%s))",
506 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
508 return NT_STATUS_WRONG_PASSWORD;
511 nt_status = samdb_result_passwords(mem_ctx,
512 dce_call->conn->dce_ctx->lp_ctx,
513 res[0], &oldLmHash, &oldNtHash);
514 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
515 return NT_STATUS_WRONG_PASSWORD;
518 /* Using the sid for the account as the key, set the password */
519 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
521 &new_password, /* we have plaintext */
523 oldLmHash, oldNtHash, /* Password change */
532 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
533 struct netr_LogonUasLogon *r)
535 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
542 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
543 struct netr_LogonUasLogoff *r)
545 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
549 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
551 switch (r->in.logon_level) {
552 case NetlogonInteractiveInformation:
553 case NetlogonServiceInformation:
554 case NetlogonInteractiveTransitiveInformation:
555 case NetlogonServiceTransitiveInformation:
556 if (r->in.logon->password == NULL) {
557 return NT_STATUS_INVALID_PARAMETER;
560 switch (r->in.validation_level) {
561 case NetlogonValidationSamInfo: /* 2 */
562 case NetlogonValidationSamInfo2: /* 3 */
563 case NetlogonValidationSamInfo4: /* 6 */
566 return NT_STATUS_INVALID_INFO_CLASS;
570 case NetlogonNetworkInformation:
571 case NetlogonNetworkTransitiveInformation:
572 if (r->in.logon->network == NULL) {
573 return NT_STATUS_INVALID_PARAMETER;
576 switch (r->in.validation_level) {
577 case NetlogonValidationSamInfo: /* 2 */
578 case NetlogonValidationSamInfo2: /* 3 */
579 case NetlogonValidationSamInfo4: /* 6 */
582 return NT_STATUS_INVALID_INFO_CLASS;
587 case NetlogonGenericInformation:
588 if (r->in.logon->generic == NULL) {
589 return NT_STATUS_INVALID_PARAMETER;
592 switch (r->in.validation_level) {
593 /* TODO: case NetlogonValidationGenericInfo: 4 */
594 case NetlogonValidationGenericInfo2: /* 5 */
597 return NT_STATUS_INVALID_INFO_CLASS;
602 return NT_STATUS_INVALID_PARAMETER;
609 netr_LogonSamLogon_base
611 This version of the function allows other wrappers to say 'do not check the credentials'
613 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
615 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
616 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
618 struct auth4_context *auth_context;
619 struct auth_usersupplied_info *user_info;
620 struct auth_user_info_dc *user_info_dc;
622 static const char zeros[16];
623 struct netr_SamBaseInfo *sam;
624 struct netr_SamInfo2 *sam2;
625 struct netr_SamInfo3 *sam3;
626 struct netr_SamInfo6 *sam6;
628 *r->out.authoritative = 1;
630 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
631 NT_STATUS_HAVE_NO_MEMORY(user_info);
633 switch (r->in.logon_level) {
634 case NetlogonInteractiveInformation:
635 case NetlogonServiceInformation:
636 case NetlogonInteractiveTransitiveInformation:
637 case NetlogonServiceTransitiveInformation:
638 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
639 netlogon_creds_aes_decrypt(creds,
640 r->in.logon->password->lmpassword.hash,
641 sizeof(r->in.logon->password->lmpassword.hash));
642 netlogon_creds_aes_decrypt(creds,
643 r->in.logon->password->ntpassword.hash,
644 sizeof(r->in.logon->password->ntpassword.hash));
645 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
646 netlogon_creds_arcfour_crypt(creds,
647 r->in.logon->password->lmpassword.hash,
648 sizeof(r->in.logon->password->lmpassword.hash));
649 netlogon_creds_arcfour_crypt(creds,
650 r->in.logon->password->ntpassword.hash,
651 sizeof(r->in.logon->password->ntpassword.hash));
653 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
654 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
657 /* TODO: we need to deny anonymous access here */
658 nt_status = auth_context_create(mem_ctx,
659 dce_call->event_ctx, dce_call->msg_ctx,
660 dce_call->conn->dce_ctx->lp_ctx,
662 NT_STATUS_NOT_OK_RETURN(nt_status);
664 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
665 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
666 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
667 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
669 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
670 user_info->password_state = AUTH_PASSWORD_HASH;
672 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
673 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
674 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
676 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
677 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
678 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
681 case NetlogonNetworkInformation:
682 case NetlogonNetworkTransitiveInformation:
684 /* TODO: we need to deny anonymous access here */
685 nt_status = auth_context_create(mem_ctx,
686 dce_call->event_ctx, dce_call->msg_ctx,
687 dce_call->conn->dce_ctx->lp_ctx,
689 NT_STATUS_NOT_OK_RETURN(nt_status);
691 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
692 NT_STATUS_NOT_OK_RETURN(nt_status);
694 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
695 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
696 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
697 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
699 user_info->password_state = AUTH_PASSWORD_RESPONSE;
700 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
701 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
706 case NetlogonGenericInformation:
708 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
709 netlogon_creds_aes_decrypt(creds,
710 r->in.logon->generic->data, r->in.logon->generic->length);
711 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
712 netlogon_creds_arcfour_crypt(creds,
713 r->in.logon->generic->data, r->in.logon->generic->length);
715 /* Using DES to verify kerberos tickets makes no sense */
716 return NT_STATUS_INVALID_PARAMETER;
719 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
721 struct dcerpc_binding_handle *irpc_handle;
722 struct kdc_check_generic_kerberos check;
723 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
724 NT_STATUS_HAVE_NO_MEMORY(generic);
725 *r->out.authoritative = 1;
727 /* TODO: Describe and deal with these flags */
730 r->out.validation->generic = generic;
732 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
736 if (irpc_handle == NULL) {
737 return NT_STATUS_NO_LOGON_SERVERS;
740 check.in.generic_request =
741 data_blob_const(r->in.logon->generic->data,
742 r->in.logon->generic->length);
744 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
747 if (!NT_STATUS_IS_OK(status)) {
750 generic->length = check.out.generic_reply.length;
751 generic->data = check.out.generic_reply.data;
755 /* Until we get an implemetnation of these other packages */
756 return NT_STATUS_INVALID_PARAMETER;
759 return NT_STATUS_INVALID_PARAMETER;
762 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
763 /* TODO: set *r->out.authoritative = 0 on specific errors */
764 NT_STATUS_NOT_OK_RETURN(nt_status);
766 switch (r->in.validation_level) {
768 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
769 NT_STATUS_NOT_OK_RETURN(nt_status);
771 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
772 NT_STATUS_HAVE_NO_MEMORY(sam2);
775 /* And put into the talloc tree */
776 talloc_steal(sam2, sam);
777 r->out.validation->sam2 = sam2;
783 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
786 NT_STATUS_NOT_OK_RETURN(nt_status);
788 r->out.validation->sam3 = sam3;
794 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
797 NT_STATUS_NOT_OK_RETURN(nt_status);
799 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
800 NT_STATUS_HAVE_NO_MEMORY(sam6);
801 sam6->base = sam3->base;
803 sam6->sidcount = sam3->sidcount;
804 sam6->sids = sam3->sids;
806 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
807 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
808 sam->account_name.string, sam6->dns_domainname.string);
809 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
810 /* And put into the talloc tree */
811 talloc_steal(sam6, sam3);
813 r->out.validation->sam6 = sam6;
817 return NT_STATUS_INVALID_INFO_CLASS;
820 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
821 /* It appears that level 6 is not individually encrypted */
822 if ((r->in.validation_level != 6) &&
823 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
824 /* This key is sent unencrypted without the ARCFOUR or AES flag set */
825 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
826 netlogon_creds_aes_encrypt(creds,
828 sizeof(sam->key.key));
829 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
830 netlogon_creds_arcfour_crypt(creds,
832 sizeof(sam->key.key));
836 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
837 /* It appears that level 6 is not individually encrypted */
838 if ((r->in.validation_level != 6) &&
839 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
840 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
841 netlogon_creds_aes_encrypt(creds,
843 sizeof(sam->LMSessKey.key));
844 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
845 netlogon_creds_arcfour_crypt(creds,
847 sizeof(sam->LMSessKey.key));
849 netlogon_creds_des_encrypt_LMKey(creds,
854 /* TODO: Describe and deal with these flags */
860 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
861 struct netr_LogonSamLogonEx *r)
864 struct netlogon_creds_CredentialState *creds;
866 *r->out.authoritative = 1;
868 nt_status = dcesrv_netr_LogonSamLogon_check(r);
869 if (!NT_STATUS_IS_OK(nt_status)) {
873 nt_status = schannel_get_creds_state(mem_ctx,
874 dce_call->conn->dce_ctx->lp_ctx,
875 r->in.computer_name, &creds);
876 if (!NT_STATUS_IS_OK(nt_status)) {
880 if (!dce_call->conn->auth_state.auth_info ||
881 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
882 return NT_STATUS_ACCESS_DENIED;
884 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
888 netr_LogonSamLogonWithFlags
891 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
892 struct netr_LogonSamLogonWithFlags *r)
895 struct netlogon_creds_CredentialState *creds;
896 struct netr_LogonSamLogonEx r2;
898 struct netr_Authenticator *return_authenticator;
902 r2.in.server_name = r->in.server_name;
903 r2.in.computer_name = r->in.computer_name;
904 r2.in.logon_level = r->in.logon_level;
905 r2.in.logon = r->in.logon;
906 r2.in.validation_level = r->in.validation_level;
907 r2.in.flags = r->in.flags;
908 r2.out.validation = r->out.validation;
909 r2.out.authoritative = r->out.authoritative;
910 r2.out.flags = r->out.flags;
912 *r->out.authoritative = 1;
914 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
915 if (!NT_STATUS_IS_OK(nt_status)) {
919 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
920 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
922 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
925 r->in.credential, return_authenticator,
927 NT_STATUS_NOT_OK_RETURN(nt_status);
929 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
931 r->out.return_authenticator = return_authenticator;
939 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
940 struct netr_LogonSamLogon *r)
942 struct netr_LogonSamLogonWithFlags r2;
948 r2.in.server_name = r->in.server_name;
949 r2.in.computer_name = r->in.computer_name;
950 r2.in.credential = r->in.credential;
951 r2.in.return_authenticator = r->in.return_authenticator;
952 r2.in.logon_level = r->in.logon_level;
953 r2.in.logon = r->in.logon;
954 r2.in.validation_level = r->in.validation_level;
955 r2.in.flags = &flags;
956 r2.out.validation = r->out.validation;
957 r2.out.authoritative = r->out.authoritative;
958 r2.out.flags = &flags;
960 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
962 r->out.return_authenticator = r2.out.return_authenticator;
971 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
972 struct netr_LogonSamLogoff *r)
974 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
982 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
983 struct netr_DatabaseDeltas *r)
985 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
992 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
993 struct netr_DatabaseSync2 *r)
995 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
996 return NT_STATUS_NOT_IMPLEMENTED;
1003 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1004 struct netr_DatabaseSync *r)
1006 struct netr_DatabaseSync2 r2;
1011 r2.in.logon_server = r->in.logon_server;
1012 r2.in.computername = r->in.computername;
1013 r2.in.credential = r->in.credential;
1014 r2.in.database_id = r->in.database_id;
1015 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1016 r2.in.sync_context = r->in.sync_context;
1017 r2.out.sync_context = r->out.sync_context;
1018 r2.out.delta_enum_array = r->out.delta_enum_array;
1019 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1021 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1030 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1031 struct netr_AccountDeltas *r)
1033 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1034 return NT_STATUS_NOT_IMPLEMENTED;
1041 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1042 struct netr_AccountSync *r)
1044 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1045 return NT_STATUS_NOT_IMPLEMENTED;
1052 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1053 struct netr_GetDcName *r)
1055 const char * const attrs[] = { NULL };
1056 struct ldb_context *sam_ctx;
1057 struct ldb_message **res;
1058 struct ldb_dn *domain_dn;
1063 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1064 * that the domainname needs to be a valid netbios domain
1065 * name, if it is not NULL.
1067 if (r->in.domainname) {
1068 const char *dot = strchr(r->in.domainname, '.');
1069 size_t len = strlen(r->in.domainname);
1071 if (dot || len > 15) {
1072 return WERR_DCNOTFOUND;
1076 * TODO: Should we also varify that only valid
1077 * netbios name characters are used?
1081 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1082 dce_call->conn->dce_ctx->lp_ctx,
1083 dce_call->conn->auth_state.session_info, 0);
1084 if (sam_ctx == NULL) {
1085 return WERR_DS_UNAVAILABLE;
1088 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1090 if (domain_dn == NULL) {
1091 return WERR_NO_SUCH_DOMAIN;
1094 ret = gendb_search_dn(sam_ctx, mem_ctx,
1095 domain_dn, &res, attrs);
1097 return WERR_NO_SUCH_DOMAIN;
1100 /* TODO: - return real IP address
1101 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1103 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1104 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1105 W_ERROR_HAVE_NO_MEMORY(dcname);
1107 *r->out.dcname = dcname;
1113 netr_LogonControl2Ex
1115 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1116 struct netr_LogonControl2Ex *r)
1118 return WERR_NOT_SUPPORTED;
1125 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1126 struct netr_LogonControl *r)
1128 struct netr_LogonControl2Ex r2;
1131 if (r->in.level == 0x00000001) {
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;
1138 r2.out.query = r->out.query;
1140 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1141 } else if (r->in.level == 0x00000002) {
1142 werr = WERR_NOT_SUPPORTED;
1144 werr = WERR_UNKNOWN_LEVEL;
1154 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1155 struct netr_LogonControl2 *r)
1157 struct netr_LogonControl2Ex r2;
1162 r2.in.logon_server = r->in.logon_server;
1163 r2.in.function_code = r->in.function_code;
1164 r2.in.level = r->in.level;
1165 r2.in.data = r->in.data;
1166 r2.out.query = r->out.query;
1168 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1173 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1174 struct ldb_context *sam_ctx,
1175 struct netr_DomainTrustList *trusts,
1176 uint32_t trust_flags);
1181 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1182 struct netr_GetAnyDCName *r)
1184 struct netr_DomainTrustList *trusts;
1185 struct ldb_context *sam_ctx;
1186 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1190 *r->out.dcname = NULL;
1192 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1193 /* if the domainname parameter wasn't set assume our domain */
1194 r->in.domainname = lpcfg_workgroup(lp_ctx);
1197 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1198 dce_call->conn->auth_state.session_info, 0);
1199 if (sam_ctx == NULL) {
1200 return WERR_DS_UNAVAILABLE;
1203 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1204 /* well we asked for a DC of our own domain */
1205 if (samdb_is_pdc(sam_ctx)) {
1206 /* we are the PDC of the specified domain */
1207 return WERR_NO_SUCH_DOMAIN;
1210 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1211 lpcfg_netbios_name(lp_ctx));
1212 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1217 /* Okay, now we have to consider the trusted domains */
1219 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1220 W_ERROR_HAVE_NO_MEMORY(trusts);
1224 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1225 NETR_TRUST_FLAG_INBOUND
1226 | NETR_TRUST_FLAG_OUTBOUND);
1227 W_ERROR_NOT_OK_RETURN(werr);
1229 for (i = 0; i < trusts->count; i++) {
1230 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1231 /* FIXME: Here we need to find a DC for the specified
1232 * trusted domain. */
1234 /* return WERR_OK; */
1235 return WERR_NO_SUCH_DOMAIN;
1239 return WERR_NO_SUCH_DOMAIN;
1246 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1247 struct netr_DatabaseRedo *r)
1249 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1254 netr_NetrEnumerateTrustedDomains
1256 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1257 struct netr_NetrEnumerateTrustedDomains *r)
1259 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1264 netr_LogonGetCapabilities
1266 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1267 struct netr_LogonGetCapabilities *r)
1269 struct netlogon_creds_CredentialState *creds;
1272 status = dcesrv_netr_creds_server_step_check(dce_call,
1274 r->in.computer_name,
1276 r->out.return_authenticator,
1278 if (!NT_STATUS_IS_OK(status)) {
1279 DEBUG(0,(__location__ " Bad credentials - error\n"));
1281 NT_STATUS_NOT_OK_RETURN(status);
1283 if (r->in.query_level != 1) {
1284 return NT_STATUS_NOT_SUPPORTED;
1287 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1289 return NT_STATUS_OK;
1294 netr_NETRLOGONSETSERVICEBITS
1296 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1297 struct netr_NETRLOGONSETSERVICEBITS *r)
1299 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1304 netr_LogonGetTrustRid
1306 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1307 struct netr_LogonGetTrustRid *r)
1309 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1314 netr_NETRLOGONCOMPUTESERVERDIGEST
1316 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1317 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1319 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1324 netr_NETRLOGONCOMPUTECLIENTDIGEST
1326 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1327 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1329 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1337 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1338 struct netr_DsRGetSiteName *r)
1340 struct ldb_context *sam_ctx;
1341 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1343 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1344 dce_call->conn->auth_state.session_info, 0);
1345 if (sam_ctx == NULL) {
1346 return WERR_DS_UNAVAILABLE;
1350 * We assume to be a DC when we get called over NETLOGON. Hence we
1351 * get our site name always by using "samdb_server_site_name()"
1352 * and not "samdb_client_site_name()".
1354 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1355 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1362 fill in a netr_OneDomainInfo from a ldb search result
1364 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1365 struct loadparm_context *lp_ctx,
1366 struct ldb_context *sam_ctx,
1367 struct ldb_message *res,
1368 struct netr_OneDomainInfo *info,
1369 bool is_local, bool is_trust_list)
1373 if (is_trust_list) {
1374 /* w2k8 only fills this on trusted domains */
1375 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1376 info->trust_extension.length = 16;
1377 info->trust_extension.info->flags =
1378 NETR_TRUST_FLAG_TREEROOT |
1379 NETR_TRUST_FLAG_IN_FOREST |
1380 NETR_TRUST_FLAG_PRIMARY |
1381 NETR_TRUST_FLAG_NATIVE;
1383 info->trust_extension.info->parent_index = 0; /* should be index into array
1385 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1386 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1389 if (is_trust_list) {
1390 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1391 info->dns_forestname.string = NULL;
1393 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1394 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1395 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1396 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1400 info->domainname.string = lpcfg_workgroup(lp_ctx);
1401 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1402 info->domain_guid = samdb_result_guid(res, "objectGUID");
1403 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1405 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1406 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1407 info->domain_guid = samdb_result_guid(res, "objectGUID");
1408 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1410 if (!is_trust_list) {
1411 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1414 return NT_STATUS_OK;
1418 netr_LogonGetDomainInfo
1419 this is called as part of the ADS domain logon procedure.
1421 It has an important role in convaying details about the client, such
1422 as Operating System, Version, Service Pack etc.
1424 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1425 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1427 struct netlogon_creds_CredentialState *creds;
1428 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1429 "securityIdentifier", "trustPartner", NULL };
1430 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1431 "msDS-SupportedEncryptionTypes", NULL };
1432 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1433 struct ldb_context *sam_ctx;
1434 struct ldb_message **res1, **res2, **res3, *new_msg;
1435 struct ldb_dn *workstation_dn;
1436 struct netr_DomainInformation *domain_info;
1437 struct netr_LsaPolicyInformation *lsa_policy_info;
1438 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1439 bool update_dns_hostname = true;
1443 status = dcesrv_netr_creds_server_step_check(dce_call,
1445 r->in.computer_name,
1447 r->out.return_authenticator,
1449 if (!NT_STATUS_IS_OK(status)) {
1450 DEBUG(0,(__location__ " Bad credentials - error\n"));
1452 NT_STATUS_NOT_OK_RETURN(status);
1454 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1455 dce_call->conn->dce_ctx->lp_ctx,
1456 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1457 if (sam_ctx == NULL) {
1458 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1461 switch (r->in.level) {
1462 case 1: /* Domain information */
1464 if (r->in.query->workstation_info == NULL) {
1465 return NT_STATUS_INVALID_PARAMETER;
1468 /* Prepares the workstation DN */
1469 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1470 dom_sid_string(mem_ctx, creds->sid));
1471 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1473 /* Lookup for attributes in workstation object */
1474 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1477 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1480 /* Gets the sam account name which is checked against the DNS
1481 * hostname parameter. */
1482 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1485 if (sam_account_name == NULL) {
1486 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1490 * Checks that the sam account name without a possible "$"
1491 * matches as prefix with the DNS hostname in the workstation
1494 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1495 strcspn(sam_account_name, "$"));
1496 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1497 if (r->in.query->workstation_info->dns_hostname != NULL) {
1498 prefix2 = talloc_strndup(mem_ctx,
1499 r->in.query->workstation_info->dns_hostname,
1500 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1501 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1503 if (strcasecmp(prefix1, prefix2) != 0) {
1504 update_dns_hostname = false;
1507 update_dns_hostname = false;
1510 /* Gets the old DNS hostname */
1511 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1516 * Updates the DNS hostname when the client wishes that the
1517 * server should handle this for him
1518 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1519 * obviously only checked when we do already have a
1521 * See MS-NRPC section 3.5.4.3.9
1523 if ((old_dns_hostname != NULL) &&
1524 (r->in.query->workstation_info->workstation_flags
1525 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1526 update_dns_hostname = false;
1529 /* Gets host information and put them into our directory */
1531 new_msg = ldb_msg_new(mem_ctx);
1532 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1534 new_msg->dn = workstation_dn;
1536 /* Sets the OS name */
1538 if (r->in.query->workstation_info->os_name.string == NULL) {
1539 return NT_STATUS_INVALID_PARAMETER;
1542 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1543 r->in.query->workstation_info->os_name.string);
1544 if (ret != LDB_SUCCESS) {
1545 return NT_STATUS_NO_MEMORY;
1549 * Sets information from "os_version". On an empty structure
1550 * the values are cleared.
1552 if (r->in.query->workstation_info->os_version.os != NULL) {
1553 struct netr_OsVersionInfoEx *os_version;
1554 const char *os_version_str;
1556 os_version = &r->in.query->workstation_info->os_version.os->os;
1558 if (os_version->CSDVersion == NULL) {
1559 return NT_STATUS_INVALID_PARAMETER;
1562 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1563 os_version->MajorVersion,
1564 os_version->MinorVersion,
1565 os_version->BuildNumber);
1566 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1568 ret = ldb_msg_add_string(new_msg,
1569 "operatingSystemServicePack",
1570 os_version->CSDVersion);
1571 if (ret != LDB_SUCCESS) {
1572 return NT_STATUS_NO_MEMORY;
1575 ret = ldb_msg_add_string(new_msg,
1576 "operatingSystemVersion",
1578 if (ret != LDB_SUCCESS) {
1579 return NT_STATUS_NO_MEMORY;
1582 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1583 "operatingSystemServicePack");
1584 if (ret != LDB_SUCCESS) {
1585 return NT_STATUS_NO_MEMORY;
1588 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1589 "operatingSystemVersion");
1590 if (ret != LDB_SUCCESS) {
1591 return NT_STATUS_NO_MEMORY;
1596 * If the boolean "update_dns_hostname" remained true, then we
1597 * are fine to start the update.
1599 if (update_dns_hostname) {
1600 ret = ldb_msg_add_string(new_msg,
1602 r->in.query->workstation_info->dns_hostname);
1603 if (ret != LDB_SUCCESS) {
1604 return NT_STATUS_NO_MEMORY;
1607 /* This manual "servicePrincipalName" generation is
1608 * still needed! Since the update in the samldb LDB
1609 * module does only work if the entries already exist
1610 * which isn't always the case. */
1611 ret = ldb_msg_add_string(new_msg,
1612 "servicePrincipalName",
1613 talloc_asprintf(new_msg, "HOST/%s",
1614 r->in.computer_name));
1615 if (ret != LDB_SUCCESS) {
1616 return NT_STATUS_NO_MEMORY;
1619 ret = ldb_msg_add_string(new_msg,
1620 "servicePrincipalName",
1621 talloc_asprintf(new_msg, "HOST/%s",
1622 r->in.query->workstation_info->dns_hostname));
1623 if (ret != LDB_SUCCESS) {
1624 return NT_STATUS_NO_MEMORY;
1628 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1629 DEBUG(3,("Impossible to update samdb: %s\n",
1630 ldb_errstring(sam_ctx)));
1633 talloc_free(new_msg);
1635 /* Writes back the domain information */
1637 /* We need to do two searches. The first will pull our primary
1638 domain and the second will pull any trusted domains. Our
1639 primary domain is also a "trusted" domain, so we need to
1640 put the primary domain into the lists of returned trusts as
1642 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1645 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1648 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1649 "(objectClass=trustedDomain)");
1651 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1654 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1655 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1657 ZERO_STRUCTP(domain_info);
1659 /* Informations about the local and trusted domains */
1661 status = fill_one_domain_info(mem_ctx,
1662 dce_call->conn->dce_ctx->lp_ctx,
1663 sam_ctx, res2[0], &domain_info->primary_domain,
1665 NT_STATUS_NOT_OK_RETURN(status);
1667 domain_info->trusted_domain_count = ret3 + 1;
1668 domain_info->trusted_domains = talloc_array(mem_ctx,
1669 struct netr_OneDomainInfo,
1670 domain_info->trusted_domain_count);
1671 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1673 for (i=0;i<ret3;i++) {
1674 status = fill_one_domain_info(mem_ctx,
1675 dce_call->conn->dce_ctx->lp_ctx,
1677 &domain_info->trusted_domains[i],
1679 NT_STATUS_NOT_OK_RETURN(status);
1682 status = fill_one_domain_info(mem_ctx,
1683 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1684 &domain_info->trusted_domains[i], true, true);
1685 NT_STATUS_NOT_OK_RETURN(status);
1687 /* Sets the supported encryption types */
1688 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1689 "msDS-SupportedEncryptionTypes",
1690 default_supported_enc_types);
1692 /* Other host domain information */
1694 lsa_policy_info = talloc(mem_ctx,
1695 struct netr_LsaPolicyInformation);
1696 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1697 ZERO_STRUCTP(lsa_policy_info);
1699 domain_info->lsa_policy = *lsa_policy_info;
1701 /* The DNS hostname is only returned back when there is a chance
1703 if ((r->in.query->workstation_info->workstation_flags
1704 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1705 domain_info->dns_hostname.string = old_dns_hostname;
1707 domain_info->dns_hostname.string = NULL;
1710 domain_info->workstation_flags =
1711 r->in.query->workstation_info->workstation_flags & (
1712 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1714 r->out.info->domain_info = domain_info;
1716 case 2: /* LSA policy information - not used at the moment */
1717 lsa_policy_info = talloc(mem_ctx,
1718 struct netr_LsaPolicyInformation);
1719 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1720 ZERO_STRUCTP(lsa_policy_info);
1722 r->out.info->lsa_policy_info = lsa_policy_info;
1725 return NT_STATUS_INVALID_LEVEL;
1729 return NT_STATUS_OK;
1734 netr_ServerPasswordGet
1736 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1737 struct netr_ServerPasswordGet *r)
1739 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1744 netr_NETRLOGONSENDTOSAM
1746 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1747 struct netr_NETRLOGONSENDTOSAM *r)
1749 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1754 netr_DsRGetDCNameEx2
1756 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1757 TALLOC_CTX *mem_ctx,
1758 struct netr_DsRGetDCNameEx2 *r)
1760 struct ldb_context *sam_ctx;
1761 struct netr_DsRGetDCNameInfo *info;
1762 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1763 const struct tsocket_address *remote_address;
1765 const char *server_site_name;
1767 struct netlogon_samlogon_response response;
1769 const char *dc_name = NULL;
1770 const char *domain_name = NULL;
1771 struct interface *ifaces;
1774 ZERO_STRUCTP(r->out.info);
1776 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1777 dce_call->conn->auth_state.session_info, 0);
1778 if (sam_ctx == NULL) {
1779 return WERR_DS_UNAVAILABLE;
1782 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1783 if (tsocket_address_is_inet(remote_address, "ip")) {
1784 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1785 W_ERROR_HAVE_NO_MEMORY(addr);
1788 /* "server_unc" is ignored by w2k3 */
1790 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1791 return WERR_INVALID_FLAGS;
1794 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1795 r->in.flags & DS_PDC_REQUIRED &&
1796 r->in.flags & DS_KDC_REQUIRED) {
1797 return WERR_INVALID_FLAGS;
1799 if (r->in.flags & DS_IS_FLAT_NAME &&
1800 r->in.flags & DS_IS_DNS_NAME) {
1801 return WERR_INVALID_FLAGS;
1803 if (r->in.flags & DS_RETURN_DNS_NAME &&
1804 r->in.flags & DS_RETURN_FLAT_NAME) {
1805 return WERR_INVALID_FLAGS;
1807 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1808 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1809 return WERR_INVALID_FLAGS;
1812 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1814 (DS_DIRECTORY_SERVICE_REQUIRED |
1815 DS_DIRECTORY_SERVICE_PREFERRED |
1816 DS_GC_SERVER_REQUIRED |
1819 return WERR_INVALID_FLAGS;
1822 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1824 return WERR_INVALID_FLAGS;
1827 /* Proof server site parameter "site_name" if it was specified */
1828 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1829 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1830 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1831 server_site_name) != 0)) {
1832 return WERR_NO_SUCH_DOMAIN;
1835 guid_str = r->in.domain_guid != NULL ?
1836 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1838 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1842 r->in.client_account,
1844 NETLOGON_NT_VERSION_5EX_WITH_IP,
1845 lp_ctx, &response, true);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 return ntstatus_to_werror(status);
1851 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1852 * (O) flag when the returned forest name is in DNS format. This is here
1853 * always the case (see below).
1855 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1857 if (r->in.flags & DS_RETURN_DNS_NAME) {
1858 dc_name = response.data.nt5_ex.pdc_dns_name;
1859 domain_name = response.data.nt5_ex.dns_domain;
1861 * According to MS-NRPC 2.2.1.2.1 we should set the
1862 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1863 * the returned information is in DNS form.
1865 response.data.nt5_ex.server_type |=
1866 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1867 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1868 dc_name = response.data.nt5_ex.pdc_name;
1869 domain_name = response.data.nt5_ex.domain_name;
1873 * TODO: autodetect what we need to return
1874 * based on the given arguments
1876 dc_name = response.data.nt5_ex.pdc_name;
1877 domain_name = response.data.nt5_ex.domain_name;
1880 if (!dc_name || !dc_name[0]) {
1881 return WERR_NO_SUCH_DOMAIN;
1884 if (!domain_name || !domain_name[0]) {
1885 return WERR_NO_SUCH_DOMAIN;
1888 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1889 W_ERROR_HAVE_NO_MEMORY(info);
1890 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1891 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1893 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1894 pdc_ip = iface_list_best_ip(ifaces, addr);
1895 if (pdc_ip == NULL) {
1896 pdc_ip = "127.0.0.1";
1898 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1899 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1900 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1901 info->domain_guid = response.data.nt5_ex.domain_uuid;
1902 info->domain_name = domain_name;
1903 info->forest_name = response.data.nt5_ex.forest;
1904 info->dc_flags = response.data.nt5_ex.server_type;
1905 info->dc_site_name = response.data.nt5_ex.server_site;
1906 info->client_site_name = response.data.nt5_ex.client_site;
1908 *r->out.info = info;
1916 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1917 struct netr_DsRGetDCNameEx *r)
1919 struct netr_DsRGetDCNameEx2 r2;
1924 r2.in.server_unc = r->in.server_unc;
1925 r2.in.client_account = NULL;
1927 r2.in.domain_guid = r->in.domain_guid;
1928 r2.in.domain_name = r->in.domain_name;
1929 r2.in.site_name = r->in.site_name;
1930 r2.in.flags = r->in.flags;
1931 r2.out.info = r->out.info;
1933 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1941 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1942 struct netr_DsRGetDCName *r)
1944 struct netr_DsRGetDCNameEx2 r2;
1949 r2.in.server_unc = r->in.server_unc;
1950 r2.in.client_account = NULL;
1952 r2.in.domain_name = r->in.domain_name;
1953 r2.in.domain_guid = r->in.domain_guid;
1955 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1956 r2.in.flags = r->in.flags;
1957 r2.out.info = r->out.info;
1959 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1964 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1966 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1967 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1969 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1974 netr_NetrEnumerateTrustedDomainsEx
1976 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1977 struct netr_NetrEnumerateTrustedDomainsEx *r)
1979 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1984 netr_DsRAddressToSitenamesExW
1986 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1987 struct netr_DsRAddressToSitenamesExW *r)
1989 struct ldb_context *sam_ctx;
1990 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1991 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1992 sa_family_t sin_family;
1993 struct sockaddr_in *addr;
1995 struct sockaddr_in6 *addr6;
1996 char addr_str[INET6_ADDRSTRLEN];
1998 char addr_str[INET_ADDRSTRLEN];
2004 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2005 dce_call->conn->auth_state.session_info, 0);
2006 if (sam_ctx == NULL) {
2007 return WERR_DS_UNAVAILABLE;
2010 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2011 W_ERROR_HAVE_NO_MEMORY(ctr);
2015 ctr->count = r->in.count;
2016 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2017 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2018 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2019 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2021 for (i=0; i<ctr->count; i++) {
2022 ctr->sitename[i].string = NULL;
2023 ctr->subnetname[i].string = NULL;
2025 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2028 /* The first two byte of the buffer are reserved for the
2029 * "sin_family" but for now only the first one is used. */
2030 sin_family = r->in.addresses[i].buffer[0];
2032 switch (sin_family) {
2034 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2037 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2038 res = inet_ntop(AF_INET, &addr->sin_addr,
2039 addr_str, sizeof(addr_str));
2043 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2046 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2047 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2048 addr_str, sizeof(addr_str));
2059 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2063 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2064 ctr->subnetname[i].string = subnet_name;
2072 netr_DsRAddressToSitenamesW
2074 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2075 struct netr_DsRAddressToSitenamesW *r)
2077 struct netr_DsRAddressToSitenamesExW r2;
2078 struct netr_DsRAddressToSitenamesWCtr *ctr;
2084 r2.in.server_name = r->in.server_name;
2085 r2.in.count = r->in.count;
2086 r2.in.addresses = r->in.addresses;
2088 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2089 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2091 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2092 W_ERROR_HAVE_NO_MEMORY(ctr);
2096 ctr->count = r->in.count;
2097 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2098 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2100 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2102 for (i=0; i<ctr->count; i++) {
2103 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2111 netr_DsrGetDcSiteCoverageW
2113 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2114 struct netr_DsrGetDcSiteCoverageW *r)
2116 struct ldb_context *sam_ctx;
2117 struct DcSitesCtr *ctr;
2118 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2120 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2121 dce_call->conn->auth_state.session_info, 0);
2122 if (sam_ctx == NULL) {
2123 return WERR_DS_UNAVAILABLE;
2126 ctr = talloc(mem_ctx, struct DcSitesCtr);
2127 W_ERROR_HAVE_NO_MEMORY(ctr);
2131 /* For now only return our default site */
2133 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2134 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2135 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2136 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2142 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2143 struct ldb_context *sam_ctx,
2144 struct netr_DomainTrustList *trusts,
2145 uint32_t trust_flags)
2147 struct ldb_dn *system_dn;
2148 struct ldb_message **dom_res = NULL;
2149 const char *trust_attrs[] = { "flatname", "trustPartner",
2150 "securityIdentifier", "trustDirection",
2151 "trustType", "trustAttributes", NULL };
2156 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2157 NETR_TRUST_FLAG_OUTBOUND))) {
2158 return WERR_INVALID_FLAGS;
2161 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2162 ldb_get_default_basedn(sam_ctx),
2163 "(&(objectClass=container)(cn=System))");
2165 return WERR_GENERAL_FAILURE;
2168 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2169 &dom_res, trust_attrs,
2170 "(objectclass=trustedDomain)");
2172 for (i = 0; i < ret; i++) {
2173 unsigned int trust_dir;
2176 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2177 "trustDirection", 0);
2179 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2180 flags |= NETR_TRUST_FLAG_INBOUND;
2182 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2183 flags |= NETR_TRUST_FLAG_OUTBOUND;
2186 if (!(flags & trust_flags)) {
2187 /* this trust direction was not requested */
2192 trusts->array = talloc_realloc(trusts, trusts->array,
2193 struct netr_DomainTrust,
2195 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2197 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2198 if (!trusts->array[n].netbios_name) {
2199 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2200 "without flatname\n",
2201 ldb_dn_get_linearized(dom_res[i]->dn)));
2204 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2206 trusts->array[n].trust_flags = flags;
2207 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2208 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2209 /* TODO: find if we have parent in the list */
2210 trusts->array[n].parent_index = 0;
2213 trusts->array[n].trust_type =
2214 ldb_msg_find_attr_as_uint(dom_res[i],
2216 trusts->array[n].trust_attributes =
2217 ldb_msg_find_attr_as_uint(dom_res[i],
2218 "trustAttributes", 0);
2220 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2221 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2222 struct dom_sid zero_sid;
2223 ZERO_STRUCT(zero_sid);
2224 trusts->array[n].sid =
2225 dom_sid_dup(trusts, &zero_sid);
2227 trusts->array[n].sid =
2228 samdb_result_dom_sid(trusts, dom_res[i],
2229 "securityIdentifier");
2231 trusts->array[n].guid = GUID_zero();
2233 trusts->count = n + 1;
2236 talloc_free(dom_res);
2241 netr_DsrEnumerateDomainTrusts
2243 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2244 TALLOC_CTX *mem_ctx,
2245 struct netr_DsrEnumerateDomainTrusts *r)
2247 struct netr_DomainTrustList *trusts;
2248 struct ldb_context *sam_ctx;
2250 struct ldb_message **dom_res;
2251 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2252 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2253 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2257 if (r->in.trust_flags & 0xFFFFFE00) {
2258 return WERR_INVALID_FLAGS;
2261 /* TODO: turn to hard check once we are sure this is 100% correct */
2262 if (!r->in.server_name) {
2263 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2264 "But received NULL!\n", dnsdomain));
2266 p = strchr(r->in.server_name, '.');
2268 DEBUG(3, ("Invalid domain! Expected name in domain "
2269 "[%s]. But received [%s]!\n",
2270 dnsdomain, r->in.server_name));
2271 p = r->in.server_name;
2275 if (strcasecmp(p, dnsdomain)) {
2276 DEBUG(3, ("Invalid domain! Expected name in domain "
2277 "[%s]. But received [%s]!\n",
2278 dnsdomain, r->in.server_name));
2282 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2283 W_ERROR_HAVE_NO_MEMORY(trusts);
2286 r->out.trusts = trusts;
2288 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2289 dce_call->conn->auth_state.session_info, 0);
2290 if (sam_ctx == NULL) {
2291 return WERR_GENERAL_FAILURE;
2294 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2295 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2297 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2298 trusts, r->in.trust_flags);
2299 W_ERROR_NOT_OK_RETURN(werr);
2302 /* NOTE: we currently are always the root of the forest */
2303 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2304 uint32_t n = trusts->count;
2306 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2307 &dom_res, dom_attrs);
2309 return WERR_GENERAL_FAILURE;
2312 trusts->count = n + 1;
2313 trusts->array = talloc_realloc(trusts, trusts->array,
2314 struct netr_DomainTrust,
2316 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2318 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2319 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2320 trusts->array[n].trust_flags =
2321 NETR_TRUST_FLAG_NATIVE |
2322 NETR_TRUST_FLAG_TREEROOT |
2323 NETR_TRUST_FLAG_IN_FOREST |
2324 NETR_TRUST_FLAG_PRIMARY;
2325 /* we are always the root domain for now */
2326 trusts->array[n].parent_index = 0;
2327 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2328 trusts->array[n].trust_attributes = 0;
2329 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2332 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2334 talloc_free(dom_res);
2342 netr_DsrDeregisterDNSHostRecords
2344 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2345 struct netr_DsrDeregisterDNSHostRecords *r)
2347 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2352 netr_ServerTrustPasswordsGet
2354 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2355 struct netr_ServerTrustPasswordsGet *r)
2357 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2361 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2362 struct ldb_context *sam_ctx,
2363 struct loadparm_context *lp_ctx,
2364 struct lsa_ForestTrustInformation *info)
2366 struct lsa_ForestTrustDomainInfo *domain_info;
2367 struct lsa_ForestTrustRecord *e;
2368 struct ldb_message **dom_res;
2369 const char * const dom_attrs[] = { "objectSid", NULL };
2372 /* we need to provide 2 entries:
2373 * 1. the Root Forest name
2374 * 2. the Domain Information
2378 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2379 W_ERROR_HAVE_NO_MEMORY(info->entries);
2381 /* Forest root info */
2382 e = talloc(info, struct lsa_ForestTrustRecord);
2383 W_ERROR_HAVE_NO_MEMORY(e);
2386 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2387 e->time = 0; /* so far always 0 in trces. */
2388 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2390 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2392 info->entries[0] = e;
2395 e = talloc(info, struct lsa_ForestTrustRecord);
2396 W_ERROR_HAVE_NO_MEMORY(e);
2398 /* get our own domain info */
2399 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2401 return WERR_GENERAL_FAILURE;
2404 /* TODO: check if disabled and set flags accordingly */
2406 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2407 e->time = 0; /* so far always 0 in traces. */
2409 domain_info = &e->forest_trust_data.domain_info;
2410 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2412 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2413 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2415 info->entries[1] = e;
2417 talloc_free(dom_res);
2423 netr_DsRGetForestTrustInformation
2425 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2426 TALLOC_CTX *mem_ctx,
2427 struct netr_DsRGetForestTrustInformation *r)
2429 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2430 struct lsa_ForestTrustInformation *info, **info_ptr;
2431 struct ldb_context *sam_ctx;
2434 if (r->in.flags & 0xFFFFFFFE) {
2435 return WERR_INVALID_FLAGS;
2438 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2439 dce_call->conn->auth_state.session_info, 0);
2440 if (sam_ctx == NULL) {
2441 return WERR_GENERAL_FAILURE;
2444 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2445 if (!samdb_is_pdc(sam_ctx)) {
2446 return WERR_NERR_NOTPRIMARY;
2449 if (r->in.trusted_domain_name == NULL) {
2450 return WERR_INVALID_FLAGS;
2453 /* TODO: establish an schannel connection with
2454 * r->in.trusted_domain_name and perform a
2455 * netr_GetForestTrustInformation call against it */
2457 /* for now return not implementd */
2458 return WERR_CALL_NOT_IMPLEMENTED;
2461 /* TODO: check r->in.server_name is our name */
2463 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2464 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2466 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2467 W_ERROR_HAVE_NO_MEMORY(info);
2469 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2470 W_ERROR_NOT_OK_RETURN(werr);
2473 r->out.forest_trust_info = info_ptr;
2480 netr_GetForestTrustInformation
2482 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2483 TALLOC_CTX *mem_ctx,
2484 struct netr_GetForestTrustInformation *r)
2486 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2487 struct netlogon_creds_CredentialState *creds;
2488 struct lsa_ForestTrustInformation *info, **info_ptr;
2489 struct ldb_context *sam_ctx;
2493 status = dcesrv_netr_creds_server_step_check(dce_call,
2495 r->in.computer_name,
2497 r->out.return_authenticator,
2499 if (!NT_STATUS_IS_OK(status)) {
2503 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2504 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2505 return NT_STATUS_NOT_IMPLEMENTED;
2508 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2509 dce_call->conn->auth_state.session_info, 0);
2510 if (sam_ctx == NULL) {
2511 return NT_STATUS_INTERNAL_ERROR;
2514 /* TODO: check r->in.server_name is our name */
2516 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2518 return NT_STATUS_NO_MEMORY;
2520 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2522 return NT_STATUS_NO_MEMORY;
2525 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2526 if (!W_ERROR_IS_OK(werr)) {
2527 return werror_to_ntstatus(werr);
2531 r->out.forest_trust_info = info_ptr;
2533 return NT_STATUS_OK;
2538 netr_ServerGetTrustInfo
2540 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2541 struct netr_ServerGetTrustInfo *r)
2543 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2549 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2550 struct netr_Unused47 *r)
2552 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2556 struct netr_dnsupdate_RODC_state {
2557 struct dcesrv_call_state *dce_call;
2558 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2559 struct dnsupdate_RODC *r2;
2563 called when the forwarded RODC dns update request is finished
2565 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2567 struct netr_dnsupdate_RODC_state *st =
2568 tevent_req_callback_data(subreq,
2569 struct netr_dnsupdate_RODC_state);
2572 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2573 TALLOC_FREE(subreq);
2574 if (!NT_STATUS_IS_OK(status)) {
2575 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2576 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2579 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2581 status = dcesrv_reply(st->dce_call);
2582 if (!NT_STATUS_IS_OK(status)) {
2583 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2588 netr_DsrUpdateReadOnlyServerDnsRecords
2590 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2591 TALLOC_CTX *mem_ctx,
2592 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2594 struct netlogon_creds_CredentialState *creds;
2596 struct dcerpc_binding_handle *binding_handle;
2597 struct netr_dnsupdate_RODC_state *st;
2598 struct tevent_req *subreq;
2600 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2602 r->in.computer_name,
2604 r->out.return_authenticator,
2606 NT_STATUS_NOT_OK_RETURN(nt_status);
2608 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2609 return NT_STATUS_ACCESS_DENIED;
2612 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2613 NT_STATUS_HAVE_NO_MEMORY(st);
2615 st->dce_call = dce_call;
2617 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2618 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2620 st->r2->in.dom_sid = creds->sid;
2621 st->r2->in.site_name = r->in.site_name;
2622 st->r2->in.dns_ttl = r->in.dns_ttl;
2623 st->r2->in.dns_names = r->in.dns_names;
2624 st->r2->out.dns_names = r->out.dns_names;
2626 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2627 "dnsupdate", &ndr_table_irpc);
2628 if (binding_handle == NULL) {
2629 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2630 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2631 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2634 /* forward the call */
2635 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2636 binding_handle, st->r2);
2637 NT_STATUS_HAVE_NO_MEMORY(subreq);
2639 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2641 /* setup the callback */
2642 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2644 return NT_STATUS_OK;
2648 /* include the generated boilerplate */
2649 #include "librpc/gen_ndr/ndr_netlogon_s.c"