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 struct netr_SamBaseInfo *sam;
623 struct netr_SamInfo2 *sam2;
624 struct netr_SamInfo3 *sam3;
625 struct netr_SamInfo6 *sam6;
627 *r->out.authoritative = 1;
629 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
630 NT_STATUS_HAVE_NO_MEMORY(user_info);
632 netlogon_creds_decrypt_samlogon_logon(creds,
636 switch (r->in.logon_level) {
637 case NetlogonInteractiveInformation:
638 case NetlogonServiceInformation:
639 case NetlogonInteractiveTransitiveInformation:
640 case NetlogonServiceTransitiveInformation:
642 /* TODO: we need to deny anonymous access here */
643 nt_status = auth_context_create(mem_ctx,
644 dce_call->event_ctx, dce_call->msg_ctx,
645 dce_call->conn->dce_ctx->lp_ctx,
647 NT_STATUS_NOT_OK_RETURN(nt_status);
649 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
650 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
651 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
652 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
654 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
655 user_info->password_state = AUTH_PASSWORD_HASH;
657 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
658 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
659 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
661 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
662 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
663 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
666 case NetlogonNetworkInformation:
667 case NetlogonNetworkTransitiveInformation:
669 /* TODO: we need to deny anonymous access here */
670 nt_status = auth_context_create(mem_ctx,
671 dce_call->event_ctx, dce_call->msg_ctx,
672 dce_call->conn->dce_ctx->lp_ctx,
674 NT_STATUS_NOT_OK_RETURN(nt_status);
676 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
677 NT_STATUS_NOT_OK_RETURN(nt_status);
679 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
680 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
681 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
682 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
684 user_info->password_state = AUTH_PASSWORD_RESPONSE;
685 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
686 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
691 case NetlogonGenericInformation:
693 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
695 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
698 /* Using DES to verify kerberos tickets makes no sense */
699 return NT_STATUS_INVALID_PARAMETER;
702 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
704 struct dcerpc_binding_handle *irpc_handle;
705 struct kdc_check_generic_kerberos check;
706 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
707 NT_STATUS_HAVE_NO_MEMORY(generic);
708 *r->out.authoritative = 1;
710 /* TODO: Describe and deal with these flags */
713 r->out.validation->generic = generic;
715 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
719 if (irpc_handle == NULL) {
720 return NT_STATUS_NO_LOGON_SERVERS;
723 check.in.generic_request =
724 data_blob_const(r->in.logon->generic->data,
725 r->in.logon->generic->length);
727 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
730 if (!NT_STATUS_IS_OK(status)) {
733 generic->length = check.out.generic_reply.length;
734 generic->data = check.out.generic_reply.data;
738 /* Until we get an implemetnation of these other packages */
739 return NT_STATUS_INVALID_PARAMETER;
742 return NT_STATUS_INVALID_PARAMETER;
745 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
746 /* TODO: set *r->out.authoritative = 0 on specific errors */
747 NT_STATUS_NOT_OK_RETURN(nt_status);
749 switch (r->in.validation_level) {
751 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
752 NT_STATUS_NOT_OK_RETURN(nt_status);
754 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
755 NT_STATUS_HAVE_NO_MEMORY(sam2);
758 /* And put into the talloc tree */
759 talloc_steal(sam2, sam);
760 r->out.validation->sam2 = sam2;
766 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
769 NT_STATUS_NOT_OK_RETURN(nt_status);
771 r->out.validation->sam3 = sam3;
777 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
780 NT_STATUS_NOT_OK_RETURN(nt_status);
782 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
783 NT_STATUS_HAVE_NO_MEMORY(sam6);
784 sam6->base = sam3->base;
786 sam6->sidcount = sam3->sidcount;
787 sam6->sids = sam3->sids;
789 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
790 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
791 sam->account_name.string, sam6->dns_domainname.string);
792 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
793 /* And put into the talloc tree */
794 talloc_steal(sam6, sam3);
796 r->out.validation->sam6 = sam6;
800 return NT_STATUS_INVALID_INFO_CLASS;
803 netlogon_creds_encrypt_samlogon_validation(creds,
804 r->in.validation_level,
807 /* TODO: Describe and deal with these flags */
813 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
814 struct netr_LogonSamLogonEx *r)
817 struct netlogon_creds_CredentialState *creds;
819 *r->out.authoritative = 1;
821 nt_status = dcesrv_netr_LogonSamLogon_check(r);
822 if (!NT_STATUS_IS_OK(nt_status)) {
826 nt_status = schannel_get_creds_state(mem_ctx,
827 dce_call->conn->dce_ctx->lp_ctx,
828 r->in.computer_name, &creds);
829 if (!NT_STATUS_IS_OK(nt_status)) {
833 if (!dce_call->conn->auth_state.auth_info ||
834 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
835 return NT_STATUS_ACCESS_DENIED;
837 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
841 netr_LogonSamLogonWithFlags
844 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
845 struct netr_LogonSamLogonWithFlags *r)
848 struct netlogon_creds_CredentialState *creds;
849 struct netr_LogonSamLogonEx r2;
851 struct netr_Authenticator *return_authenticator;
855 r2.in.server_name = r->in.server_name;
856 r2.in.computer_name = r->in.computer_name;
857 r2.in.logon_level = r->in.logon_level;
858 r2.in.logon = r->in.logon;
859 r2.in.validation_level = r->in.validation_level;
860 r2.in.flags = r->in.flags;
861 r2.out.validation = r->out.validation;
862 r2.out.authoritative = r->out.authoritative;
863 r2.out.flags = r->out.flags;
865 *r->out.authoritative = 1;
867 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
868 if (!NT_STATUS_IS_OK(nt_status)) {
872 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
873 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
875 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
878 r->in.credential, return_authenticator,
880 NT_STATUS_NOT_OK_RETURN(nt_status);
882 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
884 r->out.return_authenticator = return_authenticator;
892 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
893 struct netr_LogonSamLogon *r)
895 struct netr_LogonSamLogonWithFlags r2;
901 r2.in.server_name = r->in.server_name;
902 r2.in.computer_name = r->in.computer_name;
903 r2.in.credential = r->in.credential;
904 r2.in.return_authenticator = r->in.return_authenticator;
905 r2.in.logon_level = r->in.logon_level;
906 r2.in.logon = r->in.logon;
907 r2.in.validation_level = r->in.validation_level;
908 r2.in.flags = &flags;
909 r2.out.validation = r->out.validation;
910 r2.out.authoritative = r->out.authoritative;
911 r2.out.flags = &flags;
913 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
915 r->out.return_authenticator = r2.out.return_authenticator;
924 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
925 struct netr_LogonSamLogoff *r)
927 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
935 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
936 struct netr_DatabaseDeltas *r)
938 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
945 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
946 struct netr_DatabaseSync2 *r)
948 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
949 return NT_STATUS_NOT_IMPLEMENTED;
956 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
957 struct netr_DatabaseSync *r)
959 struct netr_DatabaseSync2 r2;
964 r2.in.logon_server = r->in.logon_server;
965 r2.in.computername = r->in.computername;
966 r2.in.credential = r->in.credential;
967 r2.in.database_id = r->in.database_id;
968 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
969 r2.in.sync_context = r->in.sync_context;
970 r2.out.sync_context = r->out.sync_context;
971 r2.out.delta_enum_array = r->out.delta_enum_array;
972 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
974 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
983 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
984 struct netr_AccountDeltas *r)
986 /* w2k3 returns "NOT IMPLEMENTED" for this call */
987 return NT_STATUS_NOT_IMPLEMENTED;
994 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
995 struct netr_AccountSync *r)
997 /* w2k3 returns "NOT IMPLEMENTED" for this call */
998 return NT_STATUS_NOT_IMPLEMENTED;
1005 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1006 struct netr_GetDcName *r)
1008 const char * const attrs[] = { NULL };
1009 struct ldb_context *sam_ctx;
1010 struct ldb_message **res;
1011 struct ldb_dn *domain_dn;
1016 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1017 * that the domainname needs to be a valid netbios domain
1018 * name, if it is not NULL.
1020 if (r->in.domainname) {
1021 const char *dot = strchr(r->in.domainname, '.');
1022 size_t len = strlen(r->in.domainname);
1024 if (dot || len > 15) {
1025 return WERR_DCNOTFOUND;
1029 * TODO: Should we also varify that only valid
1030 * netbios name characters are used?
1034 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1035 dce_call->conn->dce_ctx->lp_ctx,
1036 dce_call->conn->auth_state.session_info, 0);
1037 if (sam_ctx == NULL) {
1038 return WERR_DS_UNAVAILABLE;
1041 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1043 if (domain_dn == NULL) {
1044 return WERR_NO_SUCH_DOMAIN;
1047 ret = gendb_search_dn(sam_ctx, mem_ctx,
1048 domain_dn, &res, attrs);
1050 return WERR_NO_SUCH_DOMAIN;
1053 /* TODO: - return real IP address
1054 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1056 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1057 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1058 W_ERROR_HAVE_NO_MEMORY(dcname);
1060 *r->out.dcname = dcname;
1066 netr_LogonControl2Ex
1068 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1069 struct netr_LogonControl2Ex *r)
1071 return WERR_NOT_SUPPORTED;
1078 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1079 struct netr_LogonControl *r)
1081 struct netr_LogonControl2Ex r2;
1084 if (r->in.level == 0x00000001) {
1087 r2.in.logon_server = r->in.logon_server;
1088 r2.in.function_code = r->in.function_code;
1089 r2.in.level = r->in.level;
1091 r2.out.query = r->out.query;
1093 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1094 } else if (r->in.level == 0x00000002) {
1095 werr = WERR_NOT_SUPPORTED;
1097 werr = WERR_UNKNOWN_LEVEL;
1107 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1108 struct netr_LogonControl2 *r)
1110 struct netr_LogonControl2Ex r2;
1115 r2.in.logon_server = r->in.logon_server;
1116 r2.in.function_code = r->in.function_code;
1117 r2.in.level = r->in.level;
1118 r2.in.data = r->in.data;
1119 r2.out.query = r->out.query;
1121 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1126 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1127 struct ldb_context *sam_ctx,
1128 struct netr_DomainTrustList *trusts,
1129 uint32_t trust_flags);
1134 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1135 struct netr_GetAnyDCName *r)
1137 struct netr_DomainTrustList *trusts;
1138 struct ldb_context *sam_ctx;
1139 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1143 *r->out.dcname = NULL;
1145 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1146 /* if the domainname parameter wasn't set assume our domain */
1147 r->in.domainname = lpcfg_workgroup(lp_ctx);
1150 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1151 dce_call->conn->auth_state.session_info, 0);
1152 if (sam_ctx == NULL) {
1153 return WERR_DS_UNAVAILABLE;
1156 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1157 /* well we asked for a DC of our own domain */
1158 if (samdb_is_pdc(sam_ctx)) {
1159 /* we are the PDC of the specified domain */
1160 return WERR_NO_SUCH_DOMAIN;
1163 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1164 lpcfg_netbios_name(lp_ctx));
1165 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1170 /* Okay, now we have to consider the trusted domains */
1172 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1173 W_ERROR_HAVE_NO_MEMORY(trusts);
1177 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1178 NETR_TRUST_FLAG_INBOUND
1179 | NETR_TRUST_FLAG_OUTBOUND);
1180 W_ERROR_NOT_OK_RETURN(werr);
1182 for (i = 0; i < trusts->count; i++) {
1183 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1184 /* FIXME: Here we need to find a DC for the specified
1185 * trusted domain. */
1187 /* return WERR_OK; */
1188 return WERR_NO_SUCH_DOMAIN;
1192 return WERR_NO_SUCH_DOMAIN;
1199 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1200 struct netr_DatabaseRedo *r)
1202 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1207 netr_NetrEnumerateTrustedDomains
1209 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1210 struct netr_NetrEnumerateTrustedDomains *r)
1212 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1217 netr_LogonGetCapabilities
1219 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1220 struct netr_LogonGetCapabilities *r)
1222 struct netlogon_creds_CredentialState *creds;
1225 status = dcesrv_netr_creds_server_step_check(dce_call,
1227 r->in.computer_name,
1229 r->out.return_authenticator,
1231 if (!NT_STATUS_IS_OK(status)) {
1232 DEBUG(0,(__location__ " Bad credentials - error\n"));
1234 NT_STATUS_NOT_OK_RETURN(status);
1236 if (r->in.query_level != 1) {
1237 return NT_STATUS_NOT_SUPPORTED;
1240 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1242 return NT_STATUS_OK;
1247 netr_NETRLOGONSETSERVICEBITS
1249 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1250 struct netr_NETRLOGONSETSERVICEBITS *r)
1252 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1257 netr_LogonGetTrustRid
1259 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1260 struct netr_LogonGetTrustRid *r)
1262 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1267 netr_NETRLOGONCOMPUTESERVERDIGEST
1269 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1270 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1272 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1277 netr_NETRLOGONCOMPUTECLIENTDIGEST
1279 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1280 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1282 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1290 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1291 struct netr_DsRGetSiteName *r)
1293 struct ldb_context *sam_ctx;
1294 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1296 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1297 dce_call->conn->auth_state.session_info, 0);
1298 if (sam_ctx == NULL) {
1299 return WERR_DS_UNAVAILABLE;
1303 * We assume to be a DC when we get called over NETLOGON. Hence we
1304 * get our site name always by using "samdb_server_site_name()"
1305 * and not "samdb_client_site_name()".
1307 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1308 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1315 fill in a netr_OneDomainInfo from a ldb search result
1317 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1318 struct loadparm_context *lp_ctx,
1319 struct ldb_context *sam_ctx,
1320 struct ldb_message *res,
1321 struct netr_OneDomainInfo *info,
1322 bool is_local, bool is_trust_list)
1326 if (is_trust_list) {
1327 /* w2k8 only fills this on trusted domains */
1328 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1329 info->trust_extension.length = 16;
1330 info->trust_extension.info->flags =
1331 NETR_TRUST_FLAG_TREEROOT |
1332 NETR_TRUST_FLAG_IN_FOREST |
1333 NETR_TRUST_FLAG_PRIMARY |
1334 NETR_TRUST_FLAG_NATIVE;
1336 info->trust_extension.info->parent_index = 0; /* should be index into array
1338 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1339 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1342 if (is_trust_list) {
1343 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1344 info->dns_forestname.string = NULL;
1346 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1347 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1348 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1349 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1353 info->domainname.string = lpcfg_workgroup(lp_ctx);
1354 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1355 info->domain_guid = samdb_result_guid(res, "objectGUID");
1356 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1358 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1359 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1360 info->domain_guid = samdb_result_guid(res, "objectGUID");
1361 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1363 if (!is_trust_list) {
1364 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1367 return NT_STATUS_OK;
1371 netr_LogonGetDomainInfo
1372 this is called as part of the ADS domain logon procedure.
1374 It has an important role in convaying details about the client, such
1375 as Operating System, Version, Service Pack etc.
1377 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1378 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1380 struct netlogon_creds_CredentialState *creds;
1381 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1382 "securityIdentifier", "trustPartner", NULL };
1383 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1384 "msDS-SupportedEncryptionTypes", NULL };
1385 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1386 struct ldb_context *sam_ctx;
1387 struct ldb_message **res1, **res2, **res3, *new_msg;
1388 struct ldb_dn *workstation_dn;
1389 struct netr_DomainInformation *domain_info;
1390 struct netr_LsaPolicyInformation *lsa_policy_info;
1391 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1392 bool update_dns_hostname = true;
1396 status = dcesrv_netr_creds_server_step_check(dce_call,
1398 r->in.computer_name,
1400 r->out.return_authenticator,
1402 if (!NT_STATUS_IS_OK(status)) {
1403 DEBUG(0,(__location__ " Bad credentials - error\n"));
1405 NT_STATUS_NOT_OK_RETURN(status);
1407 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1408 dce_call->conn->dce_ctx->lp_ctx,
1409 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1410 if (sam_ctx == NULL) {
1411 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1414 switch (r->in.level) {
1415 case 1: /* Domain information */
1417 if (r->in.query->workstation_info == NULL) {
1418 return NT_STATUS_INVALID_PARAMETER;
1421 /* Prepares the workstation DN */
1422 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1423 dom_sid_string(mem_ctx, creds->sid));
1424 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1426 /* Lookup for attributes in workstation object */
1427 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1430 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1433 /* Gets the sam account name which is checked against the DNS
1434 * hostname parameter. */
1435 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1438 if (sam_account_name == NULL) {
1439 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1443 * Checks that the sam account name without a possible "$"
1444 * matches as prefix with the DNS hostname in the workstation
1447 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1448 strcspn(sam_account_name, "$"));
1449 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1450 if (r->in.query->workstation_info->dns_hostname != NULL) {
1451 prefix2 = talloc_strndup(mem_ctx,
1452 r->in.query->workstation_info->dns_hostname,
1453 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1454 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1456 if (strcasecmp(prefix1, prefix2) != 0) {
1457 update_dns_hostname = false;
1460 update_dns_hostname = false;
1463 /* Gets the old DNS hostname */
1464 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1469 * Updates the DNS hostname when the client wishes that the
1470 * server should handle this for him
1471 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1472 * obviously only checked when we do already have a
1474 * See MS-NRPC section 3.5.4.3.9
1476 if ((old_dns_hostname != NULL) &&
1477 (r->in.query->workstation_info->workstation_flags
1478 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1479 update_dns_hostname = false;
1482 /* Gets host information and put them into our directory */
1484 new_msg = ldb_msg_new(mem_ctx);
1485 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1487 new_msg->dn = workstation_dn;
1489 /* Sets the OS name */
1491 if (r->in.query->workstation_info->os_name.string == NULL) {
1492 return NT_STATUS_INVALID_PARAMETER;
1495 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1496 r->in.query->workstation_info->os_name.string);
1497 if (ret != LDB_SUCCESS) {
1498 return NT_STATUS_NO_MEMORY;
1502 * Sets information from "os_version". On an empty structure
1503 * the values are cleared.
1505 if (r->in.query->workstation_info->os_version.os != NULL) {
1506 struct netr_OsVersionInfoEx *os_version;
1507 const char *os_version_str;
1509 os_version = &r->in.query->workstation_info->os_version.os->os;
1511 if (os_version->CSDVersion == NULL) {
1512 return NT_STATUS_INVALID_PARAMETER;
1515 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1516 os_version->MajorVersion,
1517 os_version->MinorVersion,
1518 os_version->BuildNumber);
1519 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1521 ret = ldb_msg_add_string(new_msg,
1522 "operatingSystemServicePack",
1523 os_version->CSDVersion);
1524 if (ret != LDB_SUCCESS) {
1525 return NT_STATUS_NO_MEMORY;
1528 ret = ldb_msg_add_string(new_msg,
1529 "operatingSystemVersion",
1531 if (ret != LDB_SUCCESS) {
1532 return NT_STATUS_NO_MEMORY;
1535 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1536 "operatingSystemServicePack");
1537 if (ret != LDB_SUCCESS) {
1538 return NT_STATUS_NO_MEMORY;
1541 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1542 "operatingSystemVersion");
1543 if (ret != LDB_SUCCESS) {
1544 return NT_STATUS_NO_MEMORY;
1549 * If the boolean "update_dns_hostname" remained true, then we
1550 * are fine to start the update.
1552 if (update_dns_hostname) {
1553 ret = ldb_msg_add_string(new_msg,
1555 r->in.query->workstation_info->dns_hostname);
1556 if (ret != LDB_SUCCESS) {
1557 return NT_STATUS_NO_MEMORY;
1560 /* This manual "servicePrincipalName" generation is
1561 * still needed! Since the update in the samldb LDB
1562 * module does only work if the entries already exist
1563 * which isn't always the case. */
1564 ret = ldb_msg_add_string(new_msg,
1565 "servicePrincipalName",
1566 talloc_asprintf(new_msg, "HOST/%s",
1567 r->in.computer_name));
1568 if (ret != LDB_SUCCESS) {
1569 return NT_STATUS_NO_MEMORY;
1572 ret = ldb_msg_add_string(new_msg,
1573 "servicePrincipalName",
1574 talloc_asprintf(new_msg, "HOST/%s",
1575 r->in.query->workstation_info->dns_hostname));
1576 if (ret != LDB_SUCCESS) {
1577 return NT_STATUS_NO_MEMORY;
1581 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1582 DEBUG(3,("Impossible to update samdb: %s\n",
1583 ldb_errstring(sam_ctx)));
1586 talloc_free(new_msg);
1588 /* Writes back the domain information */
1590 /* We need to do two searches. The first will pull our primary
1591 domain and the second will pull any trusted domains. Our
1592 primary domain is also a "trusted" domain, so we need to
1593 put the primary domain into the lists of returned trusts as
1595 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1598 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1601 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1602 "(objectClass=trustedDomain)");
1604 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1607 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1608 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1610 ZERO_STRUCTP(domain_info);
1612 /* Informations about the local and trusted domains */
1614 status = fill_one_domain_info(mem_ctx,
1615 dce_call->conn->dce_ctx->lp_ctx,
1616 sam_ctx, res2[0], &domain_info->primary_domain,
1618 NT_STATUS_NOT_OK_RETURN(status);
1620 domain_info->trusted_domain_count = ret3 + 1;
1621 domain_info->trusted_domains = talloc_array(mem_ctx,
1622 struct netr_OneDomainInfo,
1623 domain_info->trusted_domain_count);
1624 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1626 for (i=0;i<ret3;i++) {
1627 status = fill_one_domain_info(mem_ctx,
1628 dce_call->conn->dce_ctx->lp_ctx,
1630 &domain_info->trusted_domains[i],
1632 NT_STATUS_NOT_OK_RETURN(status);
1635 status = fill_one_domain_info(mem_ctx,
1636 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1637 &domain_info->trusted_domains[i], true, true);
1638 NT_STATUS_NOT_OK_RETURN(status);
1640 /* Sets the supported encryption types */
1641 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1642 "msDS-SupportedEncryptionTypes",
1643 default_supported_enc_types);
1645 /* Other host domain information */
1647 lsa_policy_info = talloc(mem_ctx,
1648 struct netr_LsaPolicyInformation);
1649 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1650 ZERO_STRUCTP(lsa_policy_info);
1652 domain_info->lsa_policy = *lsa_policy_info;
1654 /* The DNS hostname is only returned back when there is a chance
1656 if ((r->in.query->workstation_info->workstation_flags
1657 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1658 domain_info->dns_hostname.string = old_dns_hostname;
1660 domain_info->dns_hostname.string = NULL;
1663 domain_info->workstation_flags =
1664 r->in.query->workstation_info->workstation_flags & (
1665 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1667 r->out.info->domain_info = domain_info;
1669 case 2: /* LSA policy information - not used at the moment */
1670 lsa_policy_info = talloc(mem_ctx,
1671 struct netr_LsaPolicyInformation);
1672 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1673 ZERO_STRUCTP(lsa_policy_info);
1675 r->out.info->lsa_policy_info = lsa_policy_info;
1678 return NT_STATUS_INVALID_LEVEL;
1682 return NT_STATUS_OK;
1687 netr_ServerPasswordGet
1689 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1690 struct netr_ServerPasswordGet *r)
1692 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1697 netr_NETRLOGONSENDTOSAM
1699 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1700 struct netr_NETRLOGONSENDTOSAM *r)
1702 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1707 netr_DsRGetDCNameEx2
1709 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1710 TALLOC_CTX *mem_ctx,
1711 struct netr_DsRGetDCNameEx2 *r)
1713 struct ldb_context *sam_ctx;
1714 struct netr_DsRGetDCNameInfo *info;
1715 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1716 const struct tsocket_address *remote_address;
1718 const char *server_site_name;
1720 struct netlogon_samlogon_response response;
1722 const char *dc_name = NULL;
1723 const char *domain_name = NULL;
1724 struct interface *ifaces;
1727 ZERO_STRUCTP(r->out.info);
1729 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1730 dce_call->conn->auth_state.session_info, 0);
1731 if (sam_ctx == NULL) {
1732 return WERR_DS_UNAVAILABLE;
1735 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1736 if (tsocket_address_is_inet(remote_address, "ip")) {
1737 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1738 W_ERROR_HAVE_NO_MEMORY(addr);
1741 /* "server_unc" is ignored by w2k3 */
1743 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1744 return WERR_INVALID_FLAGS;
1747 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1748 r->in.flags & DS_PDC_REQUIRED &&
1749 r->in.flags & DS_KDC_REQUIRED) {
1750 return WERR_INVALID_FLAGS;
1752 if (r->in.flags & DS_IS_FLAT_NAME &&
1753 r->in.flags & DS_IS_DNS_NAME) {
1754 return WERR_INVALID_FLAGS;
1756 if (r->in.flags & DS_RETURN_DNS_NAME &&
1757 r->in.flags & DS_RETURN_FLAT_NAME) {
1758 return WERR_INVALID_FLAGS;
1760 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1761 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1762 return WERR_INVALID_FLAGS;
1765 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1767 (DS_DIRECTORY_SERVICE_REQUIRED |
1768 DS_DIRECTORY_SERVICE_PREFERRED |
1769 DS_GC_SERVER_REQUIRED |
1772 return WERR_INVALID_FLAGS;
1775 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1777 return WERR_INVALID_FLAGS;
1780 /* Proof server site parameter "site_name" if it was specified */
1781 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1782 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1783 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1784 server_site_name) != 0)) {
1785 return WERR_NO_SUCH_DOMAIN;
1788 guid_str = r->in.domain_guid != NULL ?
1789 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1791 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1795 r->in.client_account,
1797 NETLOGON_NT_VERSION_5EX_WITH_IP,
1798 lp_ctx, &response, true);
1799 if (!NT_STATUS_IS_OK(status)) {
1800 return ntstatus_to_werror(status);
1804 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1805 * (O) flag when the returned forest name is in DNS format. This is here
1806 * always the case (see below).
1808 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1810 if (r->in.flags & DS_RETURN_DNS_NAME) {
1811 dc_name = response.data.nt5_ex.pdc_dns_name;
1812 domain_name = response.data.nt5_ex.dns_domain;
1814 * According to MS-NRPC 2.2.1.2.1 we should set the
1815 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1816 * the returned information is in DNS form.
1818 response.data.nt5_ex.server_type |=
1819 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1820 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1821 dc_name = response.data.nt5_ex.pdc_name;
1822 domain_name = response.data.nt5_ex.domain_name;
1826 * TODO: autodetect what we need to return
1827 * based on the given arguments
1829 dc_name = response.data.nt5_ex.pdc_name;
1830 domain_name = response.data.nt5_ex.domain_name;
1833 if (!dc_name || !dc_name[0]) {
1834 return WERR_NO_SUCH_DOMAIN;
1837 if (!domain_name || !domain_name[0]) {
1838 return WERR_NO_SUCH_DOMAIN;
1841 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1842 W_ERROR_HAVE_NO_MEMORY(info);
1843 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1844 dc_name[0] == '\\'? "\\\\":"",
1845 talloc_strdup(mem_ctx, dc_name));
1846 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1848 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1849 pdc_ip = iface_list_best_ip(ifaces, addr);
1850 if (pdc_ip == NULL) {
1851 pdc_ip = "127.0.0.1";
1853 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1854 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1855 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1856 info->domain_guid = response.data.nt5_ex.domain_uuid;
1857 info->domain_name = domain_name;
1858 info->forest_name = response.data.nt5_ex.forest;
1859 info->dc_flags = response.data.nt5_ex.server_type;
1860 if (r->in.flags & DS_RETURN_DNS_NAME) {
1861 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
1862 * returned if we are returning info->dc_unc containing a FQDN.
1863 * This attribute is called DomainControllerName in the specs,
1864 * it seems that we decide to return FQDN or netbios depending on
1865 * DS_RETURN_DNS_NAME.
1867 info->dc_flags |= DS_DNS_CONTROLLER;
1869 info->dc_site_name = response.data.nt5_ex.server_site;
1870 info->client_site_name = response.data.nt5_ex.client_site;
1872 *r->out.info = info;
1880 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1881 struct netr_DsRGetDCNameEx *r)
1883 struct netr_DsRGetDCNameEx2 r2;
1888 r2.in.server_unc = r->in.server_unc;
1889 r2.in.client_account = NULL;
1891 r2.in.domain_guid = r->in.domain_guid;
1892 r2.in.domain_name = r->in.domain_name;
1893 r2.in.site_name = r->in.site_name;
1894 r2.in.flags = r->in.flags;
1895 r2.out.info = r->out.info;
1897 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1905 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1906 struct netr_DsRGetDCName *r)
1908 struct netr_DsRGetDCNameEx2 r2;
1913 r2.in.server_unc = r->in.server_unc;
1914 r2.in.client_account = NULL;
1916 r2.in.domain_name = r->in.domain_name;
1917 r2.in.domain_guid = r->in.domain_guid;
1919 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1920 r2.in.flags = r->in.flags;
1921 r2.out.info = r->out.info;
1923 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1928 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1930 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1931 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1933 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1938 netr_NetrEnumerateTrustedDomainsEx
1940 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1941 struct netr_NetrEnumerateTrustedDomainsEx *r)
1943 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1948 netr_DsRAddressToSitenamesExW
1950 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1951 struct netr_DsRAddressToSitenamesExW *r)
1953 struct ldb_context *sam_ctx;
1954 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1955 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1956 sa_family_t sin_family;
1957 struct sockaddr_in *addr;
1959 struct sockaddr_in6 *addr6;
1960 char addr_str[INET6_ADDRSTRLEN];
1962 char addr_str[INET_ADDRSTRLEN];
1968 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1969 dce_call->conn->auth_state.session_info, 0);
1970 if (sam_ctx == NULL) {
1971 return WERR_DS_UNAVAILABLE;
1974 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1975 W_ERROR_HAVE_NO_MEMORY(ctr);
1979 ctr->count = r->in.count;
1980 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1981 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1982 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1983 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1985 for (i=0; i<ctr->count; i++) {
1986 ctr->sitename[i].string = NULL;
1987 ctr->subnetname[i].string = NULL;
1989 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1992 /* The first two byte of the buffer are reserved for the
1993 * "sin_family" but for now only the first one is used. */
1994 sin_family = r->in.addresses[i].buffer[0];
1996 switch (sin_family) {
1998 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2001 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2002 res = inet_ntop(AF_INET, &addr->sin_addr,
2003 addr_str, sizeof(addr_str));
2007 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2010 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2011 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2012 addr_str, sizeof(addr_str));
2023 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2027 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2028 ctr->subnetname[i].string = subnet_name;
2036 netr_DsRAddressToSitenamesW
2038 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2039 struct netr_DsRAddressToSitenamesW *r)
2041 struct netr_DsRAddressToSitenamesExW r2;
2042 struct netr_DsRAddressToSitenamesWCtr *ctr;
2048 r2.in.server_name = r->in.server_name;
2049 r2.in.count = r->in.count;
2050 r2.in.addresses = r->in.addresses;
2052 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2053 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2055 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2056 W_ERROR_HAVE_NO_MEMORY(ctr);
2060 ctr->count = r->in.count;
2061 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2062 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2064 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2066 for (i=0; i<ctr->count; i++) {
2067 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2075 netr_DsrGetDcSiteCoverageW
2077 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2078 struct netr_DsrGetDcSiteCoverageW *r)
2080 struct ldb_context *sam_ctx;
2081 struct DcSitesCtr *ctr;
2082 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2084 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2085 dce_call->conn->auth_state.session_info, 0);
2086 if (sam_ctx == NULL) {
2087 return WERR_DS_UNAVAILABLE;
2090 ctr = talloc(mem_ctx, struct DcSitesCtr);
2091 W_ERROR_HAVE_NO_MEMORY(ctr);
2095 /* For now only return our default site */
2097 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2098 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2099 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2100 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2106 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2107 struct ldb_context *sam_ctx,
2108 struct netr_DomainTrustList *trusts,
2109 uint32_t trust_flags)
2111 struct ldb_dn *system_dn;
2112 struct ldb_message **dom_res = NULL;
2113 const char *trust_attrs[] = { "flatname", "trustPartner",
2114 "securityIdentifier", "trustDirection",
2115 "trustType", "trustAttributes", NULL };
2120 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2121 NETR_TRUST_FLAG_OUTBOUND))) {
2122 return WERR_INVALID_FLAGS;
2125 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2126 ldb_get_default_basedn(sam_ctx),
2127 "(&(objectClass=container)(cn=System))");
2129 return WERR_GENERAL_FAILURE;
2132 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2133 &dom_res, trust_attrs,
2134 "(objectclass=trustedDomain)");
2136 for (i = 0; i < ret; i++) {
2137 unsigned int trust_dir;
2140 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2141 "trustDirection", 0);
2143 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2144 flags |= NETR_TRUST_FLAG_INBOUND;
2146 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2147 flags |= NETR_TRUST_FLAG_OUTBOUND;
2150 if (!(flags & trust_flags)) {
2151 /* this trust direction was not requested */
2156 trusts->array = talloc_realloc(trusts, trusts->array,
2157 struct netr_DomainTrust,
2159 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2161 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2162 if (!trusts->array[n].netbios_name) {
2163 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2164 "without flatname\n",
2165 ldb_dn_get_linearized(dom_res[i]->dn)));
2168 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2170 trusts->array[n].trust_flags = flags;
2171 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2172 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2173 /* TODO: find if we have parent in the list */
2174 trusts->array[n].parent_index = 0;
2177 trusts->array[n].trust_type =
2178 ldb_msg_find_attr_as_uint(dom_res[i],
2180 trusts->array[n].trust_attributes =
2181 ldb_msg_find_attr_as_uint(dom_res[i],
2182 "trustAttributes", 0);
2184 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2185 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2186 struct dom_sid zero_sid;
2187 ZERO_STRUCT(zero_sid);
2188 trusts->array[n].sid =
2189 dom_sid_dup(trusts, &zero_sid);
2191 trusts->array[n].sid =
2192 samdb_result_dom_sid(trusts, dom_res[i],
2193 "securityIdentifier");
2195 trusts->array[n].guid = GUID_zero();
2197 trusts->count = n + 1;
2200 talloc_free(dom_res);
2205 netr_DsrEnumerateDomainTrusts
2207 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2208 TALLOC_CTX *mem_ctx,
2209 struct netr_DsrEnumerateDomainTrusts *r)
2211 struct netr_DomainTrustList *trusts;
2212 struct ldb_context *sam_ctx;
2214 struct ldb_message **dom_res;
2215 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2216 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2217 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2221 if (r->in.trust_flags & 0xFFFFFE00) {
2222 return WERR_INVALID_FLAGS;
2225 /* TODO: turn to hard check once we are sure this is 100% correct */
2226 if (!r->in.server_name) {
2227 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2228 "But received NULL!\n", dnsdomain));
2230 p = strchr(r->in.server_name, '.');
2232 DEBUG(3, ("Invalid domain! Expected name in domain "
2233 "[%s]. But received [%s]!\n",
2234 dnsdomain, r->in.server_name));
2235 p = r->in.server_name;
2239 if (strcasecmp(p, dnsdomain)) {
2240 DEBUG(3, ("Invalid domain! Expected name in domain "
2241 "[%s]. But received [%s]!\n",
2242 dnsdomain, r->in.server_name));
2246 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2247 W_ERROR_HAVE_NO_MEMORY(trusts);
2250 r->out.trusts = trusts;
2252 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2253 dce_call->conn->auth_state.session_info, 0);
2254 if (sam_ctx == NULL) {
2255 return WERR_GENERAL_FAILURE;
2258 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2259 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2261 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2262 trusts, r->in.trust_flags);
2263 W_ERROR_NOT_OK_RETURN(werr);
2266 /* NOTE: we currently are always the root of the forest */
2267 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2268 uint32_t n = trusts->count;
2270 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2271 &dom_res, dom_attrs);
2273 return WERR_GENERAL_FAILURE;
2276 trusts->count = n + 1;
2277 trusts->array = talloc_realloc(trusts, trusts->array,
2278 struct netr_DomainTrust,
2280 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2282 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2283 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2284 trusts->array[n].trust_flags =
2285 NETR_TRUST_FLAG_NATIVE |
2286 NETR_TRUST_FLAG_TREEROOT |
2287 NETR_TRUST_FLAG_IN_FOREST |
2288 NETR_TRUST_FLAG_PRIMARY;
2289 /* we are always the root domain for now */
2290 trusts->array[n].parent_index = 0;
2291 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2292 trusts->array[n].trust_attributes = 0;
2293 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2296 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2298 talloc_free(dom_res);
2306 netr_DsrDeregisterDNSHostRecords
2308 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2309 struct netr_DsrDeregisterDNSHostRecords *r)
2311 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2316 netr_ServerTrustPasswordsGet
2318 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2319 struct netr_ServerTrustPasswordsGet *r)
2321 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2325 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2326 struct ldb_context *sam_ctx,
2327 struct loadparm_context *lp_ctx,
2328 struct lsa_ForestTrustInformation *info)
2330 struct lsa_ForestTrustDomainInfo *domain_info;
2331 struct lsa_ForestTrustRecord *e;
2332 struct ldb_message **dom_res;
2333 const char * const dom_attrs[] = { "objectSid", NULL };
2336 /* we need to provide 2 entries:
2337 * 1. the Root Forest name
2338 * 2. the Domain Information
2342 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2343 W_ERROR_HAVE_NO_MEMORY(info->entries);
2345 /* Forest root info */
2346 e = talloc(info, struct lsa_ForestTrustRecord);
2347 W_ERROR_HAVE_NO_MEMORY(e);
2350 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2351 e->time = 0; /* so far always 0 in trces. */
2352 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2354 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2356 info->entries[0] = e;
2359 e = talloc(info, struct lsa_ForestTrustRecord);
2360 W_ERROR_HAVE_NO_MEMORY(e);
2362 /* get our own domain info */
2363 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2365 return WERR_GENERAL_FAILURE;
2368 /* TODO: check if disabled and set flags accordingly */
2370 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2371 e->time = 0; /* so far always 0 in traces. */
2373 domain_info = &e->forest_trust_data.domain_info;
2374 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2376 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2377 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2379 info->entries[1] = e;
2381 talloc_free(dom_res);
2387 netr_DsRGetForestTrustInformation
2389 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2390 TALLOC_CTX *mem_ctx,
2391 struct netr_DsRGetForestTrustInformation *r)
2393 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2394 struct lsa_ForestTrustInformation *info, **info_ptr;
2395 struct ldb_context *sam_ctx;
2398 if (r->in.flags & 0xFFFFFFFE) {
2399 return WERR_INVALID_FLAGS;
2402 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2403 dce_call->conn->auth_state.session_info, 0);
2404 if (sam_ctx == NULL) {
2405 return WERR_GENERAL_FAILURE;
2408 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2409 if (!samdb_is_pdc(sam_ctx)) {
2410 return WERR_NERR_NOTPRIMARY;
2413 if (r->in.trusted_domain_name == NULL) {
2414 return WERR_INVALID_FLAGS;
2417 /* TODO: establish an schannel connection with
2418 * r->in.trusted_domain_name and perform a
2419 * netr_GetForestTrustInformation call against it */
2421 /* for now return not implementd */
2422 return WERR_CALL_NOT_IMPLEMENTED;
2425 /* TODO: check r->in.server_name is our name */
2427 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2428 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2430 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2431 W_ERROR_HAVE_NO_MEMORY(info);
2433 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2434 W_ERROR_NOT_OK_RETURN(werr);
2437 r->out.forest_trust_info = info_ptr;
2444 netr_GetForestTrustInformation
2446 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2447 TALLOC_CTX *mem_ctx,
2448 struct netr_GetForestTrustInformation *r)
2450 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2451 struct netlogon_creds_CredentialState *creds;
2452 struct lsa_ForestTrustInformation *info, **info_ptr;
2453 struct ldb_context *sam_ctx;
2457 status = dcesrv_netr_creds_server_step_check(dce_call,
2459 r->in.computer_name,
2461 r->out.return_authenticator,
2463 if (!NT_STATUS_IS_OK(status)) {
2467 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2468 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2469 return NT_STATUS_NOT_IMPLEMENTED;
2472 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2473 dce_call->conn->auth_state.session_info, 0);
2474 if (sam_ctx == NULL) {
2475 return NT_STATUS_INTERNAL_ERROR;
2478 /* TODO: check r->in.server_name is our name */
2480 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2482 return NT_STATUS_NO_MEMORY;
2484 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2486 return NT_STATUS_NO_MEMORY;
2489 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2490 if (!W_ERROR_IS_OK(werr)) {
2491 return werror_to_ntstatus(werr);
2495 r->out.forest_trust_info = info_ptr;
2497 return NT_STATUS_OK;
2502 netr_ServerGetTrustInfo
2504 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2505 struct netr_ServerGetTrustInfo *r)
2507 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2513 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2514 struct netr_Unused47 *r)
2516 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2520 struct netr_dnsupdate_RODC_state {
2521 struct dcesrv_call_state *dce_call;
2522 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2523 struct dnsupdate_RODC *r2;
2527 called when the forwarded RODC dns update request is finished
2529 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2531 struct netr_dnsupdate_RODC_state *st =
2532 tevent_req_callback_data(subreq,
2533 struct netr_dnsupdate_RODC_state);
2536 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2537 TALLOC_FREE(subreq);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2540 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2543 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2545 status = dcesrv_reply(st->dce_call);
2546 if (!NT_STATUS_IS_OK(status)) {
2547 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2552 netr_DsrUpdateReadOnlyServerDnsRecords
2554 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2555 TALLOC_CTX *mem_ctx,
2556 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2558 struct netlogon_creds_CredentialState *creds;
2560 struct dcerpc_binding_handle *binding_handle;
2561 struct netr_dnsupdate_RODC_state *st;
2562 struct tevent_req *subreq;
2564 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2566 r->in.computer_name,
2568 r->out.return_authenticator,
2570 NT_STATUS_NOT_OK_RETURN(nt_status);
2572 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2573 return NT_STATUS_ACCESS_DENIED;
2576 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2577 NT_STATUS_HAVE_NO_MEMORY(st);
2579 st->dce_call = dce_call;
2581 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2582 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2584 st->r2->in.dom_sid = creds->sid;
2585 st->r2->in.site_name = r->in.site_name;
2586 st->r2->in.dns_ttl = r->in.dns_ttl;
2587 st->r2->in.dns_names = r->in.dns_names;
2588 st->r2->out.dns_names = r->out.dns_names;
2590 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2591 "dnsupdate", &ndr_table_irpc);
2592 if (binding_handle == NULL) {
2593 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2594 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2595 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2598 /* forward the call */
2599 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2600 binding_handle, st->r2);
2601 NT_STATUS_HAVE_NO_MEMORY(subreq);
2603 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2605 /* setup the callback */
2606 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2608 return NT_STATUS_OK;
2612 /* include the generated boilerplate */
2613 #include "librpc/gen_ndr/ndr_netlogon_s.c"