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;
95 ZERO_STRUCTP(r->out.return_credentials);
99 * According to Microsoft (see bugid #6099)
100 * Windows 7 looks at the negotiate_flags
101 * returned in this structure *even if the
102 * call fails with access denied!
104 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
105 NETLOGON_NEG_PERSISTENT_SAMREPL |
106 NETLOGON_NEG_ARCFOUR |
107 NETLOGON_NEG_PROMOTION_COUNT |
108 NETLOGON_NEG_CHANGELOG_BDC |
109 NETLOGON_NEG_FULL_SYNC_REPL |
110 NETLOGON_NEG_MULTIPLE_SIDS |
112 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
113 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
114 NETLOGON_NEG_GENERIC_PASSTHROUGH |
115 NETLOGON_NEG_CONCURRENT_RPC |
116 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
117 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
118 NETLOGON_NEG_STRONG_KEYS |
119 NETLOGON_NEG_TRANSITIVE_TRUSTS |
120 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
121 NETLOGON_NEG_PASSWORD_SET2 |
122 NETLOGON_NEG_GETDOMAININFO |
123 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
124 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
125 NETLOGON_NEG_RODC_PASSTHROUGH |
126 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
127 NETLOGON_NEG_AUTHENTICATED_RPC;
129 switch (r->in.secure_channel_type) {
131 case SEC_CHAN_DNS_DOMAIN:
132 case SEC_CHAN_DOMAIN:
137 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
138 r->in.secure_channel_type));
139 return NT_STATUS_INVALID_PARAMETER;
142 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
143 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
144 if (sam_ctx == NULL) {
145 return NT_STATUS_INVALID_SYSTEM_SERVICE;
148 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
149 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
150 const char *flatname;
151 if (!encoded_account) {
152 return NT_STATUS_NO_MEMORY;
155 /* Kill the trailing dot */
156 if (encoded_account[strlen(encoded_account)-1] == '.') {
157 encoded_account[strlen(encoded_account)-1] = '\0';
160 /* pull the user attributes */
161 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
163 "(&(trustPartner=%s)(objectclass=trustedDomain))",
166 if (num_records == 0) {
167 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
169 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
172 if (num_records > 1) {
173 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
174 return NT_STATUS_INTERNAL_DB_CORRUPTION;
177 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
179 /* No flatname for this trust - we can't proceed */
180 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
182 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
185 return NT_STATUS_NO_MEMORY;
189 account_name = r->in.account_name;
192 /* pull the user attributes */
193 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
194 "(&(sAMAccountName=%s)(objectclass=user))",
195 ldb_binary_encode_string(mem_ctx, account_name));
197 if (num_records == 0) {
198 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
199 r->in.account_name));
200 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
203 if (num_records > 1) {
204 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
205 return NT_STATUS_INTERNAL_DB_CORRUPTION;
208 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
210 if (user_account_control & UF_ACCOUNTDISABLE) {
211 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
212 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
215 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
216 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
217 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
218 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
220 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
221 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
222 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
223 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
225 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
227 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
228 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
229 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
230 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
232 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
233 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
234 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
235 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
238 /* we should never reach this */
239 return NT_STATUS_INTERNAL_ERROR;
242 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
245 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
246 if (mach_pwd == NULL) {
247 return NT_STATUS_ACCESS_DENIED;
251 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
252 return NT_STATUS_ACCESS_DENIED;
255 creds = netlogon_creds_server_init(mem_ctx,
258 r->in.secure_channel_type,
259 &pipe_state->client_challenge,
260 &pipe_state->server_challenge,
263 r->out.return_credentials,
264 *r->in.negotiate_flags);
267 return NT_STATUS_ACCESS_DENIED;
270 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
272 nt_status = schannel_save_creds_state(mem_ctx,
273 dce_call->conn->dce_ctx->lp_ctx,
279 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
280 struct netr_ServerAuthenticate *r)
282 struct netr_ServerAuthenticate3 a;
285 * negotiate_flags is used as an [in] parameter
286 * so it need to be initialised.
288 * (I think ... = 0; seems wrong here --metze)
290 uint32_t negotiate_flags_in = 0;
291 uint32_t negotiate_flags_out = 0;
293 a.in.server_name = r->in.server_name;
294 a.in.account_name = r->in.account_name;
295 a.in.secure_channel_type = r->in.secure_channel_type;
296 a.in.computer_name = r->in.computer_name;
297 a.in.credentials = r->in.credentials;
298 a.in.negotiate_flags = &negotiate_flags_in;
300 a.out.return_credentials = r->out.return_credentials;
302 a.out.negotiate_flags = &negotiate_flags_out;
304 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
307 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
308 struct netr_ServerAuthenticate2 *r)
310 struct netr_ServerAuthenticate3 r3;
313 r3.in.server_name = r->in.server_name;
314 r3.in.account_name = r->in.account_name;
315 r3.in.secure_channel_type = r->in.secure_channel_type;
316 r3.in.computer_name = r->in.computer_name;
317 r3.in.credentials = r->in.credentials;
318 r3.out.return_credentials = r->out.return_credentials;
319 r3.in.negotiate_flags = r->in.negotiate_flags;
320 r3.out.negotiate_flags = r->out.negotiate_flags;
323 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
327 * NOTE: The following functions are nearly identical to the ones available in
328 * source3/rpc_server/srv_nelog_nt.c
329 * The reason we keep 2 copies is that they use different structures to
330 * represent the auth_info and the decrpc pipes.
334 * If schannel is required for this call test that it actually is available.
336 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
337 const char *computer_name,
338 bool integrity, bool privacy)
341 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
342 if (!privacy && !integrity) {
346 if ((!privacy && integrity) &&
347 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
351 if ((privacy || integrity) &&
352 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
357 /* test didn't pass */
358 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
361 return NT_STATUS_ACCESS_DENIED;
364 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
366 const char *computer_name,
367 struct netr_Authenticator *received_authenticator,
368 struct netr_Authenticator *return_authenticator,
369 struct netlogon_creds_CredentialState **creds_out)
372 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
373 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
375 if (schannel_global_required) {
376 nt_status = schannel_check_required(auth_info,
379 if (!NT_STATUS_IS_OK(nt_status)) {
384 nt_status = schannel_check_creds_state(mem_ctx,
385 dce_call->conn->dce_ctx->lp_ctx,
387 received_authenticator,
388 return_authenticator,
394 Change the machine account password for the currently connected
395 client. Supplies only the NT#.
398 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
399 struct netr_ServerPasswordSet *r)
401 struct netlogon_creds_CredentialState *creds;
402 struct ldb_context *sam_ctx;
403 const char * const attrs[] = { "unicodePwd", NULL };
404 struct ldb_message **res;
405 struct samr_Password *oldNtHash;
409 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
412 r->in.credential, r->out.return_authenticator,
414 NT_STATUS_NOT_OK_RETURN(nt_status);
416 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);
417 if (sam_ctx == NULL) {
418 return NT_STATUS_INVALID_SYSTEM_SERVICE;
421 netlogon_creds_des_decrypt(creds, r->in.new_password);
423 /* fetch the old password hashes (the NT hash has to exist) */
425 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
426 "(&(objectClass=user)(objectSid=%s))",
427 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
429 return NT_STATUS_WRONG_PASSWORD;
432 nt_status = samdb_result_passwords(mem_ctx,
433 dce_call->conn->dce_ctx->lp_ctx,
434 res[0], NULL, &oldNtHash);
435 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
436 return NT_STATUS_WRONG_PASSWORD;
439 /* Using the sid for the account as the key, set the password */
440 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
442 NULL, /* Don't have plaintext */
443 NULL, r->in.new_password,
444 NULL, oldNtHash, /* Password change */
450 Change the machine account password for the currently connected
451 client. Supplies new plaintext.
453 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
454 struct netr_ServerPasswordSet2 *r)
456 struct netlogon_creds_CredentialState *creds;
457 struct ldb_context *sam_ctx;
458 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
459 struct ldb_message **res;
460 struct samr_Password *oldLmHash, *oldNtHash;
462 DATA_BLOB new_password;
465 struct samr_CryptPassword password_buf;
467 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
470 r->in.credential, r->out.return_authenticator,
472 NT_STATUS_NOT_OK_RETURN(nt_status);
474 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);
475 if (sam_ctx == NULL) {
476 return NT_STATUS_INVALID_SYSTEM_SERVICE;
479 memcpy(password_buf.data, r->in.new_password->data, 512);
480 SIVAL(password_buf.data, 512, r->in.new_password->length);
481 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
483 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
484 DEBUG(3,("samr: failed to decode password buffer\n"));
485 return NT_STATUS_WRONG_PASSWORD;
488 /* fetch the old password hashes (at least one of both has to exist) */
490 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
491 "(&(objectClass=user)(objectSid=%s))",
492 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
494 return NT_STATUS_WRONG_PASSWORD;
497 nt_status = samdb_result_passwords(mem_ctx,
498 dce_call->conn->dce_ctx->lp_ctx,
499 res[0], &oldLmHash, &oldNtHash);
500 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
501 return NT_STATUS_WRONG_PASSWORD;
504 /* Using the sid for the account as the key, set the password */
505 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
507 &new_password, /* we have plaintext */
509 oldLmHash, oldNtHash, /* Password change */
518 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
519 struct netr_LogonUasLogon *r)
521 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
528 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
529 struct netr_LogonUasLogoff *r)
531 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
535 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
537 switch (r->in.logon_level) {
538 case NetlogonInteractiveInformation:
539 case NetlogonServiceInformation:
540 case NetlogonInteractiveTransitiveInformation:
541 case NetlogonServiceTransitiveInformation:
542 if (r->in.logon->password == NULL) {
543 return NT_STATUS_INVALID_PARAMETER;
546 switch (r->in.validation_level) {
547 case NetlogonValidationSamInfo: /* 2 */
548 case NetlogonValidationSamInfo2: /* 3 */
549 case NetlogonValidationSamInfo4: /* 6 */
552 return NT_STATUS_INVALID_INFO_CLASS;
556 case NetlogonNetworkInformation:
557 case NetlogonNetworkTransitiveInformation:
558 if (r->in.logon->network == NULL) {
559 return NT_STATUS_INVALID_PARAMETER;
562 switch (r->in.validation_level) {
563 case NetlogonValidationSamInfo: /* 2 */
564 case NetlogonValidationSamInfo2: /* 3 */
565 case NetlogonValidationSamInfo4: /* 6 */
568 return NT_STATUS_INVALID_INFO_CLASS;
573 case NetlogonGenericInformation:
574 if (r->in.logon->generic == NULL) {
575 return NT_STATUS_INVALID_PARAMETER;
578 switch (r->in.validation_level) {
579 /* TODO: case NetlogonValidationGenericInfo: 4 */
580 case NetlogonValidationGenericInfo2: /* 5 */
583 return NT_STATUS_INVALID_INFO_CLASS;
588 return NT_STATUS_INVALID_PARAMETER;
595 netr_LogonSamLogon_base
597 This version of the function allows other wrappers to say 'do not check the credentials'
599 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
601 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
602 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
604 struct auth4_context *auth_context;
605 struct auth_usersupplied_info *user_info;
606 struct auth_user_info_dc *user_info_dc;
608 static const char zeros[16];
609 struct netr_SamBaseInfo *sam;
610 struct netr_SamInfo2 *sam2;
611 struct netr_SamInfo3 *sam3;
612 struct netr_SamInfo6 *sam6;
614 *r->out.authoritative = 1;
616 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
617 NT_STATUS_HAVE_NO_MEMORY(user_info);
619 switch (r->in.logon_level) {
620 case NetlogonInteractiveInformation:
621 case NetlogonServiceInformation:
622 case NetlogonInteractiveTransitiveInformation:
623 case NetlogonServiceTransitiveInformation:
624 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
625 netlogon_creds_arcfour_crypt(creds,
626 r->in.logon->password->lmpassword.hash,
627 sizeof(r->in.logon->password->lmpassword.hash));
628 netlogon_creds_arcfour_crypt(creds,
629 r->in.logon->password->ntpassword.hash,
630 sizeof(r->in.logon->password->ntpassword.hash));
632 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
633 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
636 /* TODO: we need to deny anonymous access here */
637 nt_status = auth_context_create(mem_ctx,
638 dce_call->event_ctx, dce_call->msg_ctx,
639 dce_call->conn->dce_ctx->lp_ctx,
641 NT_STATUS_NOT_OK_RETURN(nt_status);
643 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
644 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
645 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
646 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
648 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
649 user_info->password_state = AUTH_PASSWORD_HASH;
651 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
652 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
653 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
655 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
656 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
657 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
660 case NetlogonNetworkInformation:
661 case NetlogonNetworkTransitiveInformation:
663 /* TODO: we need to deny anonymous access here */
664 nt_status = auth_context_create(mem_ctx,
665 dce_call->event_ctx, dce_call->msg_ctx,
666 dce_call->conn->dce_ctx->lp_ctx,
668 NT_STATUS_NOT_OK_RETURN(nt_status);
670 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
671 NT_STATUS_NOT_OK_RETURN(nt_status);
673 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
674 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
675 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
676 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
678 user_info->password_state = AUTH_PASSWORD_RESPONSE;
679 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
680 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
685 case NetlogonGenericInformation:
687 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
688 netlogon_creds_arcfour_crypt(creds,
689 r->in.logon->generic->data, r->in.logon->generic->length);
691 /* Using DES to verify kerberos tickets makes no sense */
692 return NT_STATUS_INVALID_PARAMETER;
695 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
697 struct dcerpc_binding_handle *irpc_handle;
698 struct kdc_check_generic_kerberos check;
699 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
700 NT_STATUS_HAVE_NO_MEMORY(generic);
701 *r->out.authoritative = 1;
703 /* TODO: Describe and deal with these flags */
706 r->out.validation->generic = generic;
708 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
712 if (irpc_handle == NULL) {
713 return NT_STATUS_NO_LOGON_SERVERS;
716 check.in.generic_request =
717 data_blob_const(r->in.logon->generic->data,
718 r->in.logon->generic->length);
720 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
723 if (!NT_STATUS_IS_OK(status)) {
726 generic->length = check.out.generic_reply.length;
727 generic->data = check.out.generic_reply.data;
731 /* Until we get an implemetnation of these other packages */
732 return NT_STATUS_INVALID_PARAMETER;
735 return NT_STATUS_INVALID_PARAMETER;
738 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
739 /* TODO: set *r->out.authoritative = 0 on specific errors */
740 NT_STATUS_NOT_OK_RETURN(nt_status);
742 switch (r->in.validation_level) {
744 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
745 NT_STATUS_NOT_OK_RETURN(nt_status);
747 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
748 NT_STATUS_HAVE_NO_MEMORY(sam2);
751 /* And put into the talloc tree */
752 talloc_steal(sam2, sam);
753 r->out.validation->sam2 = sam2;
759 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
762 NT_STATUS_NOT_OK_RETURN(nt_status);
764 r->out.validation->sam3 = sam3;
770 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
773 NT_STATUS_NOT_OK_RETURN(nt_status);
775 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
776 NT_STATUS_HAVE_NO_MEMORY(sam6);
777 sam6->base = sam3->base;
779 sam6->sidcount = sam3->sidcount;
780 sam6->sids = sam3->sids;
782 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
783 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
784 sam->account_name.string, sam6->dns_domainname.string);
785 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
786 /* And put into the talloc tree */
787 talloc_steal(sam6, sam3);
789 r->out.validation->sam6 = sam6;
793 return NT_STATUS_INVALID_INFO_CLASS;
796 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
797 /* It appears that level 6 is not individually encrypted */
798 if ((r->in.validation_level != 6) &&
799 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
800 /* This key is sent unencrypted without the ARCFOUR flag set */
801 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
802 netlogon_creds_arcfour_crypt(creds,
804 sizeof(sam->key.key));
808 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
809 /* It appears that level 6 is not individually encrypted */
810 if ((r->in.validation_level != 6) &&
811 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
812 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
813 netlogon_creds_arcfour_crypt(creds,
815 sizeof(sam->LMSessKey.key));
817 netlogon_creds_des_encrypt_LMKey(creds,
822 /* TODO: Describe and deal with these flags */
828 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
829 struct netr_LogonSamLogonEx *r)
832 struct netlogon_creds_CredentialState *creds;
834 *r->out.authoritative = 1;
836 nt_status = dcesrv_netr_LogonSamLogon_check(r);
837 if (!NT_STATUS_IS_OK(nt_status)) {
841 nt_status = schannel_get_creds_state(mem_ctx,
842 dce_call->conn->dce_ctx->lp_ctx,
843 r->in.computer_name, &creds);
844 if (!NT_STATUS_IS_OK(nt_status)) {
848 if (!dce_call->conn->auth_state.auth_info ||
849 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
850 return NT_STATUS_ACCESS_DENIED;
852 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
856 netr_LogonSamLogonWithFlags
859 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
860 struct netr_LogonSamLogonWithFlags *r)
863 struct netlogon_creds_CredentialState *creds;
864 struct netr_LogonSamLogonEx r2;
866 struct netr_Authenticator *return_authenticator;
870 r2.in.server_name = r->in.server_name;
871 r2.in.computer_name = r->in.computer_name;
872 r2.in.logon_level = r->in.logon_level;
873 r2.in.logon = r->in.logon;
874 r2.in.validation_level = r->in.validation_level;
875 r2.in.flags = r->in.flags;
876 r2.out.validation = r->out.validation;
877 r2.out.authoritative = r->out.authoritative;
878 r2.out.flags = r->out.flags;
880 *r->out.authoritative = 1;
882 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
883 if (!NT_STATUS_IS_OK(nt_status)) {
887 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
888 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
890 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
893 r->in.credential, return_authenticator,
895 NT_STATUS_NOT_OK_RETURN(nt_status);
897 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
899 r->out.return_authenticator = return_authenticator;
907 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
908 struct netr_LogonSamLogon *r)
910 struct netr_LogonSamLogonWithFlags r2;
916 r2.in.server_name = r->in.server_name;
917 r2.in.computer_name = r->in.computer_name;
918 r2.in.credential = r->in.credential;
919 r2.in.return_authenticator = r->in.return_authenticator;
920 r2.in.logon_level = r->in.logon_level;
921 r2.in.logon = r->in.logon;
922 r2.in.validation_level = r->in.validation_level;
923 r2.in.flags = &flags;
924 r2.out.validation = r->out.validation;
925 r2.out.authoritative = r->out.authoritative;
926 r2.out.flags = &flags;
928 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
930 r->out.return_authenticator = r2.out.return_authenticator;
939 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
940 struct netr_LogonSamLogoff *r)
942 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
950 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
951 struct netr_DatabaseDeltas *r)
953 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
960 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
961 struct netr_DatabaseSync2 *r)
963 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
964 return NT_STATUS_NOT_IMPLEMENTED;
971 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
972 struct netr_DatabaseSync *r)
974 struct netr_DatabaseSync2 r2;
979 r2.in.logon_server = r->in.logon_server;
980 r2.in.computername = r->in.computername;
981 r2.in.credential = r->in.credential;
982 r2.in.database_id = r->in.database_id;
983 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
984 r2.in.sync_context = r->in.sync_context;
985 r2.out.sync_context = r->out.sync_context;
986 r2.out.delta_enum_array = r->out.delta_enum_array;
987 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
989 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
998 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
999 struct netr_AccountDeltas *r)
1001 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1002 return NT_STATUS_NOT_IMPLEMENTED;
1009 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1010 struct netr_AccountSync *r)
1012 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1013 return NT_STATUS_NOT_IMPLEMENTED;
1020 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1021 struct netr_GetDcName *r)
1023 const char * const attrs[] = { NULL };
1024 struct ldb_context *sam_ctx;
1025 struct ldb_message **res;
1026 struct ldb_dn *domain_dn;
1031 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1032 * that the domainname needs to be a valid netbios domain
1033 * name, if it is not NULL.
1035 if (r->in.domainname) {
1036 const char *dot = strchr(r->in.domainname, '.');
1037 size_t len = strlen(r->in.domainname);
1039 if (dot || len > 15) {
1040 return WERR_DCNOTFOUND;
1044 * TODO: Should we also varify that only valid
1045 * netbios name characters are used?
1049 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1050 dce_call->conn->dce_ctx->lp_ctx,
1051 dce_call->conn->auth_state.session_info, 0);
1052 if (sam_ctx == NULL) {
1053 return WERR_DS_UNAVAILABLE;
1056 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1058 if (domain_dn == NULL) {
1059 return WERR_NO_SUCH_DOMAIN;
1062 ret = gendb_search_dn(sam_ctx, mem_ctx,
1063 domain_dn, &res, attrs);
1065 return WERR_NO_SUCH_DOMAIN;
1068 /* TODO: - return real IP address
1069 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1071 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1072 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1073 W_ERROR_HAVE_NO_MEMORY(dcname);
1075 *r->out.dcname = dcname;
1081 netr_LogonControl2Ex
1083 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1084 struct netr_LogonControl2Ex *r)
1086 return WERR_NOT_SUPPORTED;
1093 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1094 struct netr_LogonControl *r)
1096 struct netr_LogonControl2Ex r2;
1099 if (r->in.level == 0x00000001) {
1102 r2.in.logon_server = r->in.logon_server;
1103 r2.in.function_code = r->in.function_code;
1104 r2.in.level = r->in.level;
1106 r2.out.query = r->out.query;
1108 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1109 } else if (r->in.level == 0x00000002) {
1110 werr = WERR_NOT_SUPPORTED;
1112 werr = WERR_UNKNOWN_LEVEL;
1122 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1123 struct netr_LogonControl2 *r)
1125 struct netr_LogonControl2Ex r2;
1130 r2.in.logon_server = r->in.logon_server;
1131 r2.in.function_code = r->in.function_code;
1132 r2.in.level = r->in.level;
1133 r2.in.data = r->in.data;
1134 r2.out.query = r->out.query;
1136 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1141 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1142 struct ldb_context *sam_ctx,
1143 struct netr_DomainTrustList *trusts,
1144 uint32_t trust_flags);
1149 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150 struct netr_GetAnyDCName *r)
1152 struct netr_DomainTrustList *trusts;
1153 struct ldb_context *sam_ctx;
1154 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1158 *r->out.dcname = NULL;
1160 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1161 /* if the domainname parameter wasn't set assume our domain */
1162 r->in.domainname = lpcfg_workgroup(lp_ctx);
1165 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1166 dce_call->conn->auth_state.session_info, 0);
1167 if (sam_ctx == NULL) {
1168 return WERR_DS_UNAVAILABLE;
1171 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1172 /* well we asked for a DC of our own domain */
1173 if (samdb_is_pdc(sam_ctx)) {
1174 /* we are the PDC of the specified domain */
1175 return WERR_NO_SUCH_DOMAIN;
1178 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1179 lpcfg_netbios_name(lp_ctx));
1180 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1185 /* Okay, now we have to consider the trusted domains */
1187 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1188 W_ERROR_HAVE_NO_MEMORY(trusts);
1192 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1193 NETR_TRUST_FLAG_INBOUND
1194 | NETR_TRUST_FLAG_OUTBOUND);
1195 W_ERROR_NOT_OK_RETURN(werr);
1197 for (i = 0; i < trusts->count; i++) {
1198 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1199 /* FIXME: Here we need to find a DC for the specified
1200 * trusted domain. */
1202 /* return WERR_OK; */
1203 return WERR_NO_SUCH_DOMAIN;
1207 return WERR_NO_SUCH_DOMAIN;
1214 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1215 struct netr_DatabaseRedo *r)
1217 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1222 netr_NetrEnumerateTrustedDomains
1224 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1225 struct netr_NetrEnumerateTrustedDomains *r)
1227 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1232 netr_LogonGetCapabilities
1234 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1235 struct netr_LogonGetCapabilities *r)
1238 /* we don't support AES yet */
1239 return NT_STATUS_NOT_IMPLEMENTED;
1244 netr_NETRLOGONSETSERVICEBITS
1246 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1247 struct netr_NETRLOGONSETSERVICEBITS *r)
1249 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1254 netr_LogonGetTrustRid
1256 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1257 struct netr_LogonGetTrustRid *r)
1259 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1264 netr_NETRLOGONCOMPUTESERVERDIGEST
1266 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1267 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1269 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1274 netr_NETRLOGONCOMPUTECLIENTDIGEST
1276 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1277 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1279 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1287 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1288 struct netr_DsRGetSiteName *r)
1290 struct ldb_context *sam_ctx;
1291 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1293 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1294 dce_call->conn->auth_state.session_info, 0);
1295 if (sam_ctx == NULL) {
1296 return WERR_DS_UNAVAILABLE;
1299 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1300 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1307 fill in a netr_OneDomainInfo from a ldb search result
1309 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1310 struct loadparm_context *lp_ctx,
1311 struct ldb_context *sam_ctx,
1312 struct ldb_message *res,
1313 struct netr_OneDomainInfo *info,
1314 bool is_local, bool is_trust_list)
1318 if (is_trust_list) {
1319 /* w2k8 only fills this on trusted domains */
1320 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1321 info->trust_extension.length = 16;
1322 info->trust_extension.info->flags =
1323 NETR_TRUST_FLAG_TREEROOT |
1324 NETR_TRUST_FLAG_IN_FOREST |
1325 NETR_TRUST_FLAG_PRIMARY |
1326 NETR_TRUST_FLAG_NATIVE;
1328 info->trust_extension.info->parent_index = 0; /* should be index into array
1330 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1331 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1334 if (is_trust_list) {
1335 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1336 info->dns_forestname.string = NULL;
1338 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1339 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1340 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1341 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1345 info->domainname.string = lpcfg_workgroup(lp_ctx);
1346 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1347 info->domain_guid = samdb_result_guid(res, "objectGUID");
1348 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1350 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1351 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1352 info->domain_guid = samdb_result_guid(res, "objectGUID");
1353 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1355 if (!is_trust_list) {
1356 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1359 return NT_STATUS_OK;
1363 netr_LogonGetDomainInfo
1364 this is called as part of the ADS domain logon procedure.
1366 It has an important role in convaying details about the client, such
1367 as Operating System, Version, Service Pack etc.
1369 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1370 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1372 struct netlogon_creds_CredentialState *creds;
1373 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1374 "securityIdentifier", "trustPartner", NULL };
1375 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1376 "msDS-SupportedEncryptionTypes", NULL };
1377 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1378 struct ldb_context *sam_ctx;
1379 struct ldb_message **res1, **res2, **res3, *new_msg;
1380 struct ldb_dn *workstation_dn;
1381 struct netr_DomainInformation *domain_info;
1382 struct netr_LsaPolicyInformation *lsa_policy_info;
1383 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1384 bool update_dns_hostname = true;
1388 status = dcesrv_netr_creds_server_step_check(dce_call,
1390 r->in.computer_name,
1392 r->out.return_authenticator,
1394 if (!NT_STATUS_IS_OK(status)) {
1395 DEBUG(0,(__location__ " Bad credentials - error\n"));
1397 NT_STATUS_NOT_OK_RETURN(status);
1399 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1400 dce_call->conn->dce_ctx->lp_ctx,
1401 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1402 if (sam_ctx == NULL) {
1403 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1406 switch (r->in.level) {
1407 case 1: /* Domain information */
1409 if (r->in.query->workstation_info == NULL) {
1410 return NT_STATUS_INVALID_PARAMETER;
1413 /* Prepares the workstation DN */
1414 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1415 dom_sid_string(mem_ctx, creds->sid));
1416 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1418 /* Lookup for attributes in workstation object */
1419 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1422 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1425 /* Gets the sam account name which is checked against the DNS
1426 * hostname parameter. */
1427 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1430 if (sam_account_name == NULL) {
1431 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1435 * Checks that the sam account name without a possible "$"
1436 * matches as prefix with the DNS hostname in the workstation
1439 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1440 strcspn(sam_account_name, "$"));
1441 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1442 if (r->in.query->workstation_info->dns_hostname != NULL) {
1443 prefix2 = talloc_strndup(mem_ctx,
1444 r->in.query->workstation_info->dns_hostname,
1445 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1446 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1448 if (strcasecmp(prefix1, prefix2) != 0) {
1449 update_dns_hostname = false;
1452 update_dns_hostname = false;
1455 /* Gets the old DNS hostname */
1456 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1461 * Updates the DNS hostname when the client wishes that the
1462 * server should handle this for him
1463 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1464 * obviously only checked when we do already have a
1466 * See MS-NRPC section 3.5.4.3.9
1468 if ((old_dns_hostname != NULL) &&
1469 (r->in.query->workstation_info->workstation_flags
1470 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1471 update_dns_hostname = false;
1474 /* Gets host information and put them into our directory */
1476 new_msg = ldb_msg_new(mem_ctx);
1477 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1479 new_msg->dn = workstation_dn;
1481 /* Sets the OS name */
1483 if (r->in.query->workstation_info->os_name.string == NULL) {
1484 return NT_STATUS_INVALID_PARAMETER;
1487 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1488 r->in.query->workstation_info->os_name.string);
1489 if (ret != LDB_SUCCESS) {
1490 return NT_STATUS_NO_MEMORY;
1494 * Sets information from "os_version". On an empty structure
1495 * the values are cleared.
1497 if (r->in.query->workstation_info->os_version.os != NULL) {
1498 struct netr_OsVersionInfoEx *os_version;
1499 const char *os_version_str;
1501 os_version = &r->in.query->workstation_info->os_version.os->os;
1503 if (os_version->CSDVersion == NULL) {
1504 return NT_STATUS_INVALID_PARAMETER;
1507 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1508 os_version->MajorVersion,
1509 os_version->MinorVersion,
1510 os_version->BuildNumber);
1511 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1513 ret = ldb_msg_add_string(new_msg,
1514 "operatingSystemServicePack",
1515 os_version->CSDVersion);
1516 if (ret != LDB_SUCCESS) {
1517 return NT_STATUS_NO_MEMORY;
1520 ret = ldb_msg_add_string(new_msg,
1521 "operatingSystemVersion",
1523 if (ret != LDB_SUCCESS) {
1524 return NT_STATUS_NO_MEMORY;
1527 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1528 "operatingSystemServicePack");
1529 if (ret != LDB_SUCCESS) {
1530 return NT_STATUS_NO_MEMORY;
1533 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1534 "operatingSystemVersion");
1535 if (ret != LDB_SUCCESS) {
1536 return NT_STATUS_NO_MEMORY;
1541 * If the boolean "update_dns_hostname" remained true, then we
1542 * are fine to start the update.
1544 if (update_dns_hostname) {
1545 ret = ldb_msg_add_string(new_msg,
1547 r->in.query->workstation_info->dns_hostname);
1548 if (ret != LDB_SUCCESS) {
1549 return NT_STATUS_NO_MEMORY;
1552 /* This manual "servicePrincipalName" generation is
1553 * still needed! Since the update in the samldb LDB
1554 * module does only work if the entries already exist
1555 * which isn't always the case. */
1556 ret = ldb_msg_add_string(new_msg,
1557 "servicePrincipalName",
1558 talloc_asprintf(new_msg, "HOST/%s",
1559 r->in.computer_name));
1560 if (ret != LDB_SUCCESS) {
1561 return NT_STATUS_NO_MEMORY;
1564 ret = ldb_msg_add_string(new_msg,
1565 "servicePrincipalName",
1566 talloc_asprintf(new_msg, "HOST/%s",
1567 r->in.query->workstation_info->dns_hostname));
1568 if (ret != LDB_SUCCESS) {
1569 return NT_STATUS_NO_MEMORY;
1573 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1574 DEBUG(3,("Impossible to update samdb: %s\n",
1575 ldb_errstring(sam_ctx)));
1578 talloc_free(new_msg);
1580 /* Writes back the domain information */
1582 /* We need to do two searches. The first will pull our primary
1583 domain and the second will pull any trusted domains. Our
1584 primary domain is also a "trusted" domain, so we need to
1585 put the primary domain into the lists of returned trusts as
1587 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1590 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1593 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1594 "(objectClass=trustedDomain)");
1596 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1599 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1600 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1602 ZERO_STRUCTP(domain_info);
1604 /* Informations about the local and trusted domains */
1606 status = fill_one_domain_info(mem_ctx,
1607 dce_call->conn->dce_ctx->lp_ctx,
1608 sam_ctx, res2[0], &domain_info->primary_domain,
1610 NT_STATUS_NOT_OK_RETURN(status);
1612 domain_info->trusted_domain_count = ret3 + 1;
1613 domain_info->trusted_domains = talloc_array(mem_ctx,
1614 struct netr_OneDomainInfo,
1615 domain_info->trusted_domain_count);
1616 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1618 for (i=0;i<ret3;i++) {
1619 status = fill_one_domain_info(mem_ctx,
1620 dce_call->conn->dce_ctx->lp_ctx,
1622 &domain_info->trusted_domains[i],
1624 NT_STATUS_NOT_OK_RETURN(status);
1627 status = fill_one_domain_info(mem_ctx,
1628 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1629 &domain_info->trusted_domains[i], true, true);
1630 NT_STATUS_NOT_OK_RETURN(status);
1632 /* Sets the supported encryption types */
1633 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1634 "msDS-SupportedEncryptionTypes",
1635 default_supported_enc_types);
1637 /* Other host domain information */
1639 lsa_policy_info = talloc(mem_ctx,
1640 struct netr_LsaPolicyInformation);
1641 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1642 ZERO_STRUCTP(lsa_policy_info);
1644 domain_info->lsa_policy = *lsa_policy_info;
1646 /* The DNS hostname is only returned back when there is a chance
1648 if ((r->in.query->workstation_info->workstation_flags
1649 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1650 domain_info->dns_hostname.string = old_dns_hostname;
1652 domain_info->dns_hostname.string = NULL;
1655 domain_info->workstation_flags =
1656 r->in.query->workstation_info->workstation_flags;
1658 r->out.info->domain_info = domain_info;
1660 case 2: /* LSA policy information - not used at the moment */
1661 lsa_policy_info = talloc(mem_ctx,
1662 struct netr_LsaPolicyInformation);
1663 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1664 ZERO_STRUCTP(lsa_policy_info);
1666 r->out.info->lsa_policy_info = lsa_policy_info;
1669 return NT_STATUS_INVALID_LEVEL;
1673 return NT_STATUS_OK;
1678 netr_ServerPasswordGet
1680 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1681 struct netr_ServerPasswordGet *r)
1683 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1688 netr_NETRLOGONSENDTOSAM
1690 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1691 struct netr_NETRLOGONSENDTOSAM *r)
1693 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1698 netr_DsRGetDCNameEx2
1700 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1701 TALLOC_CTX *mem_ctx,
1702 struct netr_DsRGetDCNameEx2 *r)
1704 struct ldb_context *sam_ctx;
1705 struct netr_DsRGetDCNameInfo *info;
1706 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1707 const struct tsocket_address *remote_address;
1709 const char *server_site_name;
1711 struct netlogon_samlogon_response response;
1713 const char *dc_name = NULL;
1714 const char *domain_name = NULL;
1715 struct interface *ifaces;
1718 ZERO_STRUCTP(r->out.info);
1720 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1721 dce_call->conn->auth_state.session_info, 0);
1722 if (sam_ctx == NULL) {
1723 return WERR_DS_UNAVAILABLE;
1726 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1727 if (tsocket_address_is_inet(remote_address, "ip")) {
1728 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1729 W_ERROR_HAVE_NO_MEMORY(addr);
1732 /* "server_unc" is ignored by w2k3 */
1734 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1735 return WERR_INVALID_FLAGS;
1738 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1739 r->in.flags & DS_PDC_REQUIRED &&
1740 r->in.flags & DS_KDC_REQUIRED) {
1741 return WERR_INVALID_FLAGS;
1743 if (r->in.flags & DS_IS_FLAT_NAME &&
1744 r->in.flags & DS_IS_DNS_NAME) {
1745 return WERR_INVALID_FLAGS;
1747 if (r->in.flags & DS_RETURN_DNS_NAME &&
1748 r->in.flags & DS_RETURN_FLAT_NAME) {
1749 return WERR_INVALID_FLAGS;
1751 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1752 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1753 return WERR_INVALID_FLAGS;
1756 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1758 (DS_DIRECTORY_SERVICE_REQUIRED |
1759 DS_DIRECTORY_SERVICE_PREFERRED |
1760 DS_GC_SERVER_REQUIRED |
1763 return WERR_INVALID_FLAGS;
1766 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1768 return WERR_INVALID_FLAGS;
1771 /* Proof server site parameter "site_name" if it was specified */
1772 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1773 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1774 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1775 server_site_name) != 0)) {
1776 return WERR_NO_SUCH_DOMAIN;
1779 guid_str = r->in.domain_guid != NULL ?
1780 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1782 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1786 r->in.client_account,
1788 NETLOGON_NT_VERSION_5EX_WITH_IP,
1789 lp_ctx, &response, true);
1790 if (!NT_STATUS_IS_OK(status)) {
1791 return ntstatus_to_werror(status);
1795 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1796 * (O) flag when the returned forest name is in DNS format. This is here
1797 * always the case (see below).
1799 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1801 if (r->in.flags & DS_RETURN_DNS_NAME) {
1802 dc_name = response.data.nt5_ex.pdc_dns_name;
1803 domain_name = response.data.nt5_ex.dns_domain;
1805 * According to MS-NRPC 2.2.1.2.1 we should set the
1806 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1807 * the returned information is in DNS form.
1809 response.data.nt5_ex.server_type |=
1810 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1811 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1812 dc_name = response.data.nt5_ex.pdc_name;
1813 domain_name = response.data.nt5_ex.domain_name;
1817 * TODO: autodetect what we need to return
1818 * based on the given arguments
1820 dc_name = response.data.nt5_ex.pdc_name;
1821 domain_name = response.data.nt5_ex.domain_name;
1824 if (!dc_name || !dc_name[0]) {
1825 return WERR_NO_SUCH_DOMAIN;
1828 if (!domain_name || !domain_name[0]) {
1829 return WERR_NO_SUCH_DOMAIN;
1832 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1833 W_ERROR_HAVE_NO_MEMORY(info);
1834 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1835 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1837 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1838 pdc_ip = iface_list_best_ip(ifaces, addr);
1839 if (pdc_ip == NULL) {
1840 pdc_ip = "127.0.0.1";
1842 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1843 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1844 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1845 info->domain_guid = response.data.nt5_ex.domain_uuid;
1846 info->domain_name = domain_name;
1847 info->forest_name = response.data.nt5_ex.forest;
1848 info->dc_flags = response.data.nt5_ex.server_type;
1849 info->dc_site_name = response.data.nt5_ex.server_site;
1850 info->client_site_name = response.data.nt5_ex.client_site;
1852 *r->out.info = info;
1860 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1861 struct netr_DsRGetDCNameEx *r)
1863 struct netr_DsRGetDCNameEx2 r2;
1868 r2.in.server_unc = r->in.server_unc;
1869 r2.in.client_account = NULL;
1871 r2.in.domain_guid = r->in.domain_guid;
1872 r2.in.domain_name = r->in.domain_name;
1873 r2.in.site_name = r->in.site_name;
1874 r2.in.flags = r->in.flags;
1875 r2.out.info = r->out.info;
1877 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1885 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1886 struct netr_DsRGetDCName *r)
1888 struct netr_DsRGetDCNameEx2 r2;
1893 r2.in.server_unc = r->in.server_unc;
1894 r2.in.client_account = NULL;
1896 r2.in.domain_name = r->in.domain_name;
1897 r2.in.domain_guid = r->in.domain_guid;
1899 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1900 r2.in.flags = r->in.flags;
1901 r2.out.info = r->out.info;
1903 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1908 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1910 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1911 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1913 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1918 netr_NetrEnumerateTrustedDomainsEx
1920 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1921 struct netr_NetrEnumerateTrustedDomainsEx *r)
1923 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1928 netr_DsRAddressToSitenamesExW
1930 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1931 struct netr_DsRAddressToSitenamesExW *r)
1933 struct ldb_context *sam_ctx;
1934 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1935 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1936 sa_family_t sin_family;
1937 struct sockaddr_in *addr;
1939 struct sockaddr_in6 *addr6;
1940 char addr_str[INET6_ADDRSTRLEN];
1942 char addr_str[INET_ADDRSTRLEN];
1948 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1949 dce_call->conn->auth_state.session_info, 0);
1950 if (sam_ctx == NULL) {
1951 return WERR_DS_UNAVAILABLE;
1954 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1955 W_ERROR_HAVE_NO_MEMORY(ctr);
1959 ctr->count = r->in.count;
1960 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1961 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1962 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1963 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1965 for (i=0; i<ctr->count; i++) {
1966 ctr->sitename[i].string = NULL;
1967 ctr->subnetname[i].string = NULL;
1969 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1972 /* The first two byte of the buffer are reserved for the
1973 * "sin_family" but for now only the first one is used. */
1974 sin_family = r->in.addresses[i].buffer[0];
1976 switch (sin_family) {
1978 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1981 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1982 res = inet_ntop(AF_INET, &addr->sin_addr,
1983 addr_str, sizeof(addr_str));
1987 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1990 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1991 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1992 addr_str, sizeof(addr_str));
2003 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2007 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2008 ctr->subnetname[i].string = subnet_name;
2016 netr_DsRAddressToSitenamesW
2018 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2019 struct netr_DsRAddressToSitenamesW *r)
2021 struct netr_DsRAddressToSitenamesExW r2;
2022 struct netr_DsRAddressToSitenamesWCtr *ctr;
2028 r2.in.server_name = r->in.server_name;
2029 r2.in.count = r->in.count;
2030 r2.in.addresses = r->in.addresses;
2032 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2033 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2035 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2036 W_ERROR_HAVE_NO_MEMORY(ctr);
2040 ctr->count = r->in.count;
2041 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2042 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2044 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2046 for (i=0; i<ctr->count; i++) {
2047 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2055 netr_DsrGetDcSiteCoverageW
2057 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2058 struct netr_DsrGetDcSiteCoverageW *r)
2060 struct ldb_context *sam_ctx;
2061 struct DcSitesCtr *ctr;
2062 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2064 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2065 dce_call->conn->auth_state.session_info, 0);
2066 if (sam_ctx == NULL) {
2067 return WERR_DS_UNAVAILABLE;
2070 ctr = talloc(mem_ctx, struct DcSitesCtr);
2071 W_ERROR_HAVE_NO_MEMORY(ctr);
2075 /* For now only return our default site */
2077 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2078 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2079 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2080 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2086 #define GET_CHECK_STR(dest, mem, msg, attr) \
2089 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
2091 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
2092 "without flatname\n", \
2093 ldb_dn_get_linearized(msg->dn))); \
2096 dest = talloc_strdup(mem, s); \
2097 W_ERROR_HAVE_NO_MEMORY(dest); \
2101 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2102 struct ldb_context *sam_ctx,
2103 struct netr_DomainTrustList *trusts,
2104 uint32_t trust_flags)
2106 struct ldb_dn *system_dn;
2107 struct ldb_message **dom_res = NULL;
2108 const char *trust_attrs[] = { "flatname", "trustPartner",
2109 "securityIdentifier", "trustDirection",
2110 "trustType", "trustAttributes", NULL };
2115 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2116 NETR_TRUST_FLAG_OUTBOUND))) {
2117 return WERR_INVALID_FLAGS;
2120 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2121 ldb_get_default_basedn(sam_ctx),
2122 "(&(objectClass=container)(cn=System))");
2124 return WERR_GENERAL_FAILURE;
2127 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2128 &dom_res, trust_attrs,
2129 "(objectclass=trustedDomain)");
2131 for (i = 0; i < ret; i++) {
2132 unsigned int trust_dir;
2135 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2136 "trustDirection", 0);
2138 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2139 flags |= NETR_TRUST_FLAG_INBOUND;
2141 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2142 flags |= NETR_TRUST_FLAG_OUTBOUND;
2145 if (!(flags & trust_flags)) {
2146 /* this trust direction was not requested */
2151 trusts->array = talloc_realloc(trusts, trusts->array,
2152 struct netr_DomainTrust,
2154 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2156 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2157 dom_res[i], "flatname");
2158 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2159 dom_res[i], "trustPartner");
2161 trusts->array[n].trust_flags = flags;
2162 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2163 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2164 /* TODO: find if we have parent in the list */
2165 trusts->array[n].parent_index = 0;
2168 trusts->array[n].trust_type =
2169 ldb_msg_find_attr_as_uint(dom_res[i],
2171 trusts->array[n].trust_attributes =
2172 ldb_msg_find_attr_as_uint(dom_res[i],
2173 "trustAttributes", 0);
2175 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2176 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2177 struct dom_sid zero_sid;
2178 ZERO_STRUCT(zero_sid);
2179 trusts->array[n].sid =
2180 dom_sid_dup(trusts, &zero_sid);
2182 trusts->array[n].sid =
2183 samdb_result_dom_sid(trusts, dom_res[i],
2184 "securityIdentifier");
2186 trusts->array[n].guid = GUID_zero();
2188 trusts->count = n + 1;
2191 talloc_free(dom_res);
2196 netr_DsrEnumerateDomainTrusts
2198 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2199 TALLOC_CTX *mem_ctx,
2200 struct netr_DsrEnumerateDomainTrusts *r)
2202 struct netr_DomainTrustList *trusts;
2203 struct ldb_context *sam_ctx;
2205 struct ldb_message **dom_res;
2206 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2207 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2208 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2212 if (r->in.trust_flags & 0xFFFFFE00) {
2213 return WERR_INVALID_FLAGS;
2216 /* TODO: turn to hard check once we are sure this is 100% correct */
2217 if (!r->in.server_name) {
2218 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2219 "But received NULL!\n", dnsdomain));
2221 p = strchr(r->in.server_name, '.');
2223 DEBUG(3, ("Invalid domain! Expected name in domain "
2224 "[%s]. But received [%s]!\n",
2225 dnsdomain, r->in.server_name));
2226 p = r->in.server_name;
2230 if (strcasecmp(p, dnsdomain)) {
2231 DEBUG(3, ("Invalid domain! Expected name in domain "
2232 "[%s]. But received [%s]!\n",
2233 dnsdomain, r->in.server_name));
2237 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2238 W_ERROR_HAVE_NO_MEMORY(trusts);
2241 r->out.trusts = trusts;
2243 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2244 dce_call->conn->auth_state.session_info, 0);
2245 if (sam_ctx == NULL) {
2246 return WERR_GENERAL_FAILURE;
2249 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2250 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2252 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2253 trusts, r->in.trust_flags);
2254 W_ERROR_NOT_OK_RETURN(werr);
2257 /* NOTE: we currently are always the root of the forest */
2258 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2259 uint32_t n = trusts->count;
2261 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2262 &dom_res, dom_attrs);
2264 return WERR_GENERAL_FAILURE;
2267 trusts->count = n + 1;
2268 trusts->array = talloc_realloc(trusts, trusts->array,
2269 struct netr_DomainTrust,
2271 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2273 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2274 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2275 trusts->array[n].trust_flags =
2276 NETR_TRUST_FLAG_NATIVE |
2277 NETR_TRUST_FLAG_TREEROOT |
2278 NETR_TRUST_FLAG_IN_FOREST |
2279 NETR_TRUST_FLAG_PRIMARY;
2280 /* we are always the root domain for now */
2281 trusts->array[n].parent_index = 0;
2282 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2283 trusts->array[n].trust_attributes = 0;
2284 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2287 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2289 talloc_free(dom_res);
2297 netr_DsrDeregisterDNSHostRecords
2299 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2300 struct netr_DsrDeregisterDNSHostRecords *r)
2302 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2307 netr_ServerTrustPasswordsGet
2309 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2310 struct netr_ServerTrustPasswordsGet *r)
2312 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2316 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2317 struct ldb_context *sam_ctx,
2318 struct loadparm_context *lp_ctx,
2319 struct lsa_ForestTrustInformation *info)
2321 struct lsa_ForestTrustDomainInfo *domain_info;
2322 struct lsa_ForestTrustRecord *e;
2323 struct ldb_message **dom_res;
2324 const char * const dom_attrs[] = { "objectSid", NULL };
2327 /* we need to provide 2 entries:
2328 * 1. the Root Forest name
2329 * 2. the Domain Information
2333 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2334 W_ERROR_HAVE_NO_MEMORY(info->entries);
2336 /* Forest root info */
2337 e = talloc(info, struct lsa_ForestTrustRecord);
2338 W_ERROR_HAVE_NO_MEMORY(e);
2341 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2342 e->time = 0; /* so far always 0 in trces. */
2343 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2345 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2347 info->entries[0] = e;
2350 e = talloc(info, struct lsa_ForestTrustRecord);
2351 W_ERROR_HAVE_NO_MEMORY(e);
2353 /* get our own domain info */
2354 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2356 return WERR_GENERAL_FAILURE;
2359 /* TODO: check if disabled and set flags accordingly */
2361 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2362 e->time = 0; /* so far always 0 in traces. */
2364 domain_info = &e->forest_trust_data.domain_info;
2365 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2367 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2368 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2370 info->entries[1] = e;
2372 talloc_free(dom_res);
2378 netr_DsRGetForestTrustInformation
2380 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2381 TALLOC_CTX *mem_ctx,
2382 struct netr_DsRGetForestTrustInformation *r)
2384 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2385 struct lsa_ForestTrustInformation *info, **info_ptr;
2386 struct ldb_context *sam_ctx;
2389 if (r->in.flags & 0xFFFFFFFE) {
2390 return WERR_INVALID_FLAGS;
2393 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2394 dce_call->conn->auth_state.session_info, 0);
2395 if (sam_ctx == NULL) {
2396 return WERR_GENERAL_FAILURE;
2399 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2400 if (!samdb_is_pdc(sam_ctx)) {
2401 return WERR_NERR_NOTPRIMARY;
2404 if (r->in.trusted_domain_name == NULL) {
2405 return WERR_INVALID_FLAGS;
2408 /* TODO: establish an schannel connection with
2409 * r->in.trusted_domain_name and perform a
2410 * netr_GetForestTrustInformation call against it */
2412 /* for now return not implementd */
2413 return WERR_CALL_NOT_IMPLEMENTED;
2416 /* TODO: check r->in.server_name is our name */
2418 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2419 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2421 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2422 W_ERROR_HAVE_NO_MEMORY(info);
2424 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2425 W_ERROR_NOT_OK_RETURN(werr);
2428 r->out.forest_trust_info = info_ptr;
2435 netr_GetForestTrustInformation
2437 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2438 TALLOC_CTX *mem_ctx,
2439 struct netr_GetForestTrustInformation *r)
2441 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2442 struct netlogon_creds_CredentialState *creds;
2443 struct lsa_ForestTrustInformation *info, **info_ptr;
2444 struct ldb_context *sam_ctx;
2448 status = dcesrv_netr_creds_server_step_check(dce_call,
2450 r->in.computer_name,
2452 r->out.return_authenticator,
2454 if (!NT_STATUS_IS_OK(status)) {
2458 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2459 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2460 return NT_STATUS_NOT_IMPLEMENTED;
2463 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2464 dce_call->conn->auth_state.session_info, 0);
2465 if (sam_ctx == NULL) {
2466 return NT_STATUS_INTERNAL_ERROR;
2469 /* TODO: check r->in.server_name is our name */
2471 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2473 return NT_STATUS_NO_MEMORY;
2475 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2477 return NT_STATUS_NO_MEMORY;
2480 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2481 if (!W_ERROR_IS_OK(werr)) {
2482 return werror_to_ntstatus(werr);
2486 r->out.forest_trust_info = info_ptr;
2488 return NT_STATUS_OK;
2493 netr_ServerGetTrustInfo
2495 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2496 struct netr_ServerGetTrustInfo *r)
2498 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2504 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2505 struct netr_Unused47 *r)
2507 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2511 struct netr_dnsupdate_RODC_state {
2512 struct dcesrv_call_state *dce_call;
2513 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2514 struct dnsupdate_RODC *r2;
2518 called when the forwarded RODC dns update request is finished
2520 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2522 struct netr_dnsupdate_RODC_state *st =
2523 tevent_req_callback_data(subreq,
2524 struct netr_dnsupdate_RODC_state);
2527 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2528 TALLOC_FREE(subreq);
2529 if (!NT_STATUS_IS_OK(status)) {
2530 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2531 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2534 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2536 status = dcesrv_reply(st->dce_call);
2537 if (!NT_STATUS_IS_OK(status)) {
2538 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2543 netr_DsrUpdateReadOnlyServerDnsRecords
2545 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2546 TALLOC_CTX *mem_ctx,
2547 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2549 struct netlogon_creds_CredentialState *creds;
2551 struct dcerpc_binding_handle *binding_handle;
2552 struct netr_dnsupdate_RODC_state *st;
2553 struct tevent_req *subreq;
2555 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2557 r->in.computer_name,
2559 r->out.return_authenticator,
2561 NT_STATUS_NOT_OK_RETURN(nt_status);
2563 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2564 return NT_STATUS_ACCESS_DENIED;
2567 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2568 NT_STATUS_HAVE_NO_MEMORY(st);
2570 st->dce_call = dce_call;
2572 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2573 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2575 st->r2->in.dom_sid = creds->sid;
2576 st->r2->in.site_name = r->in.site_name;
2577 st->r2->in.dns_ttl = r->in.dns_ttl;
2578 st->r2->in.dns_names = r->in.dns_names;
2579 st->r2->out.dns_names = r->out.dns_names;
2581 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2582 "dnsupdate", &ndr_table_irpc);
2583 if (binding_handle == NULL) {
2584 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2585 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2586 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2589 /* forward the call */
2590 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2591 binding_handle, st->r2);
2592 NT_STATUS_HAVE_NO_MEMORY(subreq);
2594 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2596 /* setup the callback */
2597 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2599 return NT_STATUS_OK;
2603 /* include the generated boilerplate */
2604 #include "librpc/gen_ndr/ndr_netlogon_s.c"