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", dc_name);
1844 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1846 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1847 pdc_ip = iface_list_best_ip(ifaces, addr);
1848 if (pdc_ip == NULL) {
1849 pdc_ip = "127.0.0.1";
1851 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1852 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1853 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1854 info->domain_guid = response.data.nt5_ex.domain_uuid;
1855 info->domain_name = domain_name;
1856 info->forest_name = response.data.nt5_ex.forest;
1857 info->dc_flags = response.data.nt5_ex.server_type;
1858 info->dc_site_name = response.data.nt5_ex.server_site;
1859 info->client_site_name = response.data.nt5_ex.client_site;
1861 *r->out.info = info;
1869 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1870 struct netr_DsRGetDCNameEx *r)
1872 struct netr_DsRGetDCNameEx2 r2;
1877 r2.in.server_unc = r->in.server_unc;
1878 r2.in.client_account = NULL;
1880 r2.in.domain_guid = r->in.domain_guid;
1881 r2.in.domain_name = r->in.domain_name;
1882 r2.in.site_name = r->in.site_name;
1883 r2.in.flags = r->in.flags;
1884 r2.out.info = r->out.info;
1886 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1894 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1895 struct netr_DsRGetDCName *r)
1897 struct netr_DsRGetDCNameEx2 r2;
1902 r2.in.server_unc = r->in.server_unc;
1903 r2.in.client_account = NULL;
1905 r2.in.domain_name = r->in.domain_name;
1906 r2.in.domain_guid = r->in.domain_guid;
1908 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1909 r2.in.flags = r->in.flags;
1910 r2.out.info = r->out.info;
1912 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1917 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1919 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1920 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1922 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1927 netr_NetrEnumerateTrustedDomainsEx
1929 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1930 struct netr_NetrEnumerateTrustedDomainsEx *r)
1932 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1937 netr_DsRAddressToSitenamesExW
1939 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1940 struct netr_DsRAddressToSitenamesExW *r)
1942 struct ldb_context *sam_ctx;
1943 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1944 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1945 sa_family_t sin_family;
1946 struct sockaddr_in *addr;
1948 struct sockaddr_in6 *addr6;
1949 char addr_str[INET6_ADDRSTRLEN];
1951 char addr_str[INET_ADDRSTRLEN];
1957 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1958 dce_call->conn->auth_state.session_info, 0);
1959 if (sam_ctx == NULL) {
1960 return WERR_DS_UNAVAILABLE;
1963 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1964 W_ERROR_HAVE_NO_MEMORY(ctr);
1968 ctr->count = r->in.count;
1969 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1970 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1971 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1972 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1974 for (i=0; i<ctr->count; i++) {
1975 ctr->sitename[i].string = NULL;
1976 ctr->subnetname[i].string = NULL;
1978 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1981 /* The first two byte of the buffer are reserved for the
1982 * "sin_family" but for now only the first one is used. */
1983 sin_family = r->in.addresses[i].buffer[0];
1985 switch (sin_family) {
1987 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1990 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1991 res = inet_ntop(AF_INET, &addr->sin_addr,
1992 addr_str, sizeof(addr_str));
1996 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1999 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2000 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2001 addr_str, sizeof(addr_str));
2012 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2016 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2017 ctr->subnetname[i].string = subnet_name;
2025 netr_DsRAddressToSitenamesW
2027 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2028 struct netr_DsRAddressToSitenamesW *r)
2030 struct netr_DsRAddressToSitenamesExW r2;
2031 struct netr_DsRAddressToSitenamesWCtr *ctr;
2037 r2.in.server_name = r->in.server_name;
2038 r2.in.count = r->in.count;
2039 r2.in.addresses = r->in.addresses;
2041 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2042 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2044 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2045 W_ERROR_HAVE_NO_MEMORY(ctr);
2049 ctr->count = r->in.count;
2050 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2051 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2053 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2055 for (i=0; i<ctr->count; i++) {
2056 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2064 netr_DsrGetDcSiteCoverageW
2066 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2067 struct netr_DsrGetDcSiteCoverageW *r)
2069 struct ldb_context *sam_ctx;
2070 struct DcSitesCtr *ctr;
2071 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2073 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2074 dce_call->conn->auth_state.session_info, 0);
2075 if (sam_ctx == NULL) {
2076 return WERR_DS_UNAVAILABLE;
2079 ctr = talloc(mem_ctx, struct DcSitesCtr);
2080 W_ERROR_HAVE_NO_MEMORY(ctr);
2084 /* For now only return our default site */
2086 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2087 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2088 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2089 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2095 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2096 struct ldb_context *sam_ctx,
2097 struct netr_DomainTrustList *trusts,
2098 uint32_t trust_flags)
2100 struct ldb_dn *system_dn;
2101 struct ldb_message **dom_res = NULL;
2102 const char *trust_attrs[] = { "flatname", "trustPartner",
2103 "securityIdentifier", "trustDirection",
2104 "trustType", "trustAttributes", NULL };
2109 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2110 NETR_TRUST_FLAG_OUTBOUND))) {
2111 return WERR_INVALID_FLAGS;
2114 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2115 ldb_get_default_basedn(sam_ctx),
2116 "(&(objectClass=container)(cn=System))");
2118 return WERR_GENERAL_FAILURE;
2121 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2122 &dom_res, trust_attrs,
2123 "(objectclass=trustedDomain)");
2125 for (i = 0; i < ret; i++) {
2126 unsigned int trust_dir;
2129 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2130 "trustDirection", 0);
2132 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2133 flags |= NETR_TRUST_FLAG_INBOUND;
2135 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2136 flags |= NETR_TRUST_FLAG_OUTBOUND;
2139 if (!(flags & trust_flags)) {
2140 /* this trust direction was not requested */
2145 trusts->array = talloc_realloc(trusts, trusts->array,
2146 struct netr_DomainTrust,
2148 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2150 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2151 if (!trusts->array[n].netbios_name) {
2152 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2153 "without flatname\n",
2154 ldb_dn_get_linearized(dom_res[i]->dn)));
2157 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2159 trusts->array[n].trust_flags = flags;
2160 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2161 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2162 /* TODO: find if we have parent in the list */
2163 trusts->array[n].parent_index = 0;
2166 trusts->array[n].trust_type =
2167 ldb_msg_find_attr_as_uint(dom_res[i],
2169 trusts->array[n].trust_attributes =
2170 ldb_msg_find_attr_as_uint(dom_res[i],
2171 "trustAttributes", 0);
2173 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2174 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2175 struct dom_sid zero_sid;
2176 ZERO_STRUCT(zero_sid);
2177 trusts->array[n].sid =
2178 dom_sid_dup(trusts, &zero_sid);
2180 trusts->array[n].sid =
2181 samdb_result_dom_sid(trusts, dom_res[i],
2182 "securityIdentifier");
2184 trusts->array[n].guid = GUID_zero();
2186 trusts->count = n + 1;
2189 talloc_free(dom_res);
2194 netr_DsrEnumerateDomainTrusts
2196 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2197 TALLOC_CTX *mem_ctx,
2198 struct netr_DsrEnumerateDomainTrusts *r)
2200 struct netr_DomainTrustList *trusts;
2201 struct ldb_context *sam_ctx;
2203 struct ldb_message **dom_res;
2204 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2205 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2206 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2210 if (r->in.trust_flags & 0xFFFFFE00) {
2211 return WERR_INVALID_FLAGS;
2214 /* TODO: turn to hard check once we are sure this is 100% correct */
2215 if (!r->in.server_name) {
2216 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2217 "But received NULL!\n", dnsdomain));
2219 p = strchr(r->in.server_name, '.');
2221 DEBUG(3, ("Invalid domain! Expected name in domain "
2222 "[%s]. But received [%s]!\n",
2223 dnsdomain, r->in.server_name));
2224 p = r->in.server_name;
2228 if (strcasecmp(p, dnsdomain)) {
2229 DEBUG(3, ("Invalid domain! Expected name in domain "
2230 "[%s]. But received [%s]!\n",
2231 dnsdomain, r->in.server_name));
2235 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2236 W_ERROR_HAVE_NO_MEMORY(trusts);
2239 r->out.trusts = trusts;
2241 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2242 dce_call->conn->auth_state.session_info, 0);
2243 if (sam_ctx == NULL) {
2244 return WERR_GENERAL_FAILURE;
2247 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2248 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2250 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2251 trusts, r->in.trust_flags);
2252 W_ERROR_NOT_OK_RETURN(werr);
2255 /* NOTE: we currently are always the root of the forest */
2256 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2257 uint32_t n = trusts->count;
2259 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2260 &dom_res, dom_attrs);
2262 return WERR_GENERAL_FAILURE;
2265 trusts->count = n + 1;
2266 trusts->array = talloc_realloc(trusts, trusts->array,
2267 struct netr_DomainTrust,
2269 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2271 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2272 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2273 trusts->array[n].trust_flags =
2274 NETR_TRUST_FLAG_NATIVE |
2275 NETR_TRUST_FLAG_TREEROOT |
2276 NETR_TRUST_FLAG_IN_FOREST |
2277 NETR_TRUST_FLAG_PRIMARY;
2278 /* we are always the root domain for now */
2279 trusts->array[n].parent_index = 0;
2280 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2281 trusts->array[n].trust_attributes = 0;
2282 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2285 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2287 talloc_free(dom_res);
2295 netr_DsrDeregisterDNSHostRecords
2297 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2298 struct netr_DsrDeregisterDNSHostRecords *r)
2300 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2305 netr_ServerTrustPasswordsGet
2307 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2308 struct netr_ServerTrustPasswordsGet *r)
2310 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2314 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2315 struct ldb_context *sam_ctx,
2316 struct loadparm_context *lp_ctx,
2317 struct lsa_ForestTrustInformation *info)
2319 struct lsa_ForestTrustDomainInfo *domain_info;
2320 struct lsa_ForestTrustRecord *e;
2321 struct ldb_message **dom_res;
2322 const char * const dom_attrs[] = { "objectSid", NULL };
2325 /* we need to provide 2 entries:
2326 * 1. the Root Forest name
2327 * 2. the Domain Information
2331 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2332 W_ERROR_HAVE_NO_MEMORY(info->entries);
2334 /* Forest root info */
2335 e = talloc(info, struct lsa_ForestTrustRecord);
2336 W_ERROR_HAVE_NO_MEMORY(e);
2339 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2340 e->time = 0; /* so far always 0 in trces. */
2341 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2343 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2345 info->entries[0] = e;
2348 e = talloc(info, struct lsa_ForestTrustRecord);
2349 W_ERROR_HAVE_NO_MEMORY(e);
2351 /* get our own domain info */
2352 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2354 return WERR_GENERAL_FAILURE;
2357 /* TODO: check if disabled and set flags accordingly */
2359 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2360 e->time = 0; /* so far always 0 in traces. */
2362 domain_info = &e->forest_trust_data.domain_info;
2363 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2365 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2366 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2368 info->entries[1] = e;
2370 talloc_free(dom_res);
2376 netr_DsRGetForestTrustInformation
2378 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2379 TALLOC_CTX *mem_ctx,
2380 struct netr_DsRGetForestTrustInformation *r)
2382 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2383 struct lsa_ForestTrustInformation *info, **info_ptr;
2384 struct ldb_context *sam_ctx;
2387 if (r->in.flags & 0xFFFFFFFE) {
2388 return WERR_INVALID_FLAGS;
2391 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2392 dce_call->conn->auth_state.session_info, 0);
2393 if (sam_ctx == NULL) {
2394 return WERR_GENERAL_FAILURE;
2397 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2398 if (!samdb_is_pdc(sam_ctx)) {
2399 return WERR_NERR_NOTPRIMARY;
2402 if (r->in.trusted_domain_name == NULL) {
2403 return WERR_INVALID_FLAGS;
2406 /* TODO: establish an schannel connection with
2407 * r->in.trusted_domain_name and perform a
2408 * netr_GetForestTrustInformation call against it */
2410 /* for now return not implementd */
2411 return WERR_CALL_NOT_IMPLEMENTED;
2414 /* TODO: check r->in.server_name is our name */
2416 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2417 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2419 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2420 W_ERROR_HAVE_NO_MEMORY(info);
2422 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2423 W_ERROR_NOT_OK_RETURN(werr);
2426 r->out.forest_trust_info = info_ptr;
2433 netr_GetForestTrustInformation
2435 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2436 TALLOC_CTX *mem_ctx,
2437 struct netr_GetForestTrustInformation *r)
2439 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2440 struct netlogon_creds_CredentialState *creds;
2441 struct lsa_ForestTrustInformation *info, **info_ptr;
2442 struct ldb_context *sam_ctx;
2446 status = dcesrv_netr_creds_server_step_check(dce_call,
2448 r->in.computer_name,
2450 r->out.return_authenticator,
2452 if (!NT_STATUS_IS_OK(status)) {
2456 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2457 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2458 return NT_STATUS_NOT_IMPLEMENTED;
2461 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2462 dce_call->conn->auth_state.session_info, 0);
2463 if (sam_ctx == NULL) {
2464 return NT_STATUS_INTERNAL_ERROR;
2467 /* TODO: check r->in.server_name is our name */
2469 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2471 return NT_STATUS_NO_MEMORY;
2473 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2475 return NT_STATUS_NO_MEMORY;
2478 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2479 if (!W_ERROR_IS_OK(werr)) {
2480 return werror_to_ntstatus(werr);
2484 r->out.forest_trust_info = info_ptr;
2486 return NT_STATUS_OK;
2491 netr_ServerGetTrustInfo
2493 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2494 struct netr_ServerGetTrustInfo *r)
2496 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2502 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2503 struct netr_Unused47 *r)
2505 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2509 struct netr_dnsupdate_RODC_state {
2510 struct dcesrv_call_state *dce_call;
2511 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2512 struct dnsupdate_RODC *r2;
2516 called when the forwarded RODC dns update request is finished
2518 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2520 struct netr_dnsupdate_RODC_state *st =
2521 tevent_req_callback_data(subreq,
2522 struct netr_dnsupdate_RODC_state);
2525 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2526 TALLOC_FREE(subreq);
2527 if (!NT_STATUS_IS_OK(status)) {
2528 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2529 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2532 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2534 status = dcesrv_reply(st->dce_call);
2535 if (!NT_STATUS_IS_OK(status)) {
2536 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2541 netr_DsrUpdateReadOnlyServerDnsRecords
2543 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2544 TALLOC_CTX *mem_ctx,
2545 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2547 struct netlogon_creds_CredentialState *creds;
2549 struct dcerpc_binding_handle *binding_handle;
2550 struct netr_dnsupdate_RODC_state *st;
2551 struct tevent_req *subreq;
2553 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2555 r->in.computer_name,
2557 r->out.return_authenticator,
2559 NT_STATUS_NOT_OK_RETURN(nt_status);
2561 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2562 return NT_STATUS_ACCESS_DENIED;
2565 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2566 NT_STATUS_HAVE_NO_MEMORY(st);
2568 st->dce_call = dce_call;
2570 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2571 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2573 st->r2->in.dom_sid = creds->sid;
2574 st->r2->in.site_name = r->in.site_name;
2575 st->r2->in.dns_ttl = r->in.dns_ttl;
2576 st->r2->in.dns_names = r->in.dns_names;
2577 st->r2->out.dns_names = r->out.dns_names;
2579 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2580 "dnsupdate", &ndr_table_irpc);
2581 if (binding_handle == NULL) {
2582 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2583 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2584 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2587 /* forward the call */
2588 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2589 binding_handle, st->r2);
2590 NT_STATUS_HAVE_NO_MEMORY(subreq);
2592 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2594 /* setup the callback */
2595 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2597 return NT_STATUS_OK;
2601 /* include the generated boilerplate */
2602 #include "librpc/gen_ndr/ndr_netlogon_s.c"