s3:smb2_sesssetup: add support for SMB 2.24/3.00 signing
[Samba/gebeck_regimport.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob1cbd9583c7a68d828ee54d76997f9cd64ba9ce1d
1 /*
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/>.
24 #include "includes.h"
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 */
57 if (pipe_state) {
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;
74 return NT_STATUS_OK;
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;
86 int num_records;
87 struct ldb_message **msgs;
88 NTSTATUS nt_status;
89 const char *attrs[] = {"unicodePwd", "userAccountControl",
90 "objectSid", NULL};
92 const char *trust_dom_attrs[] = {"flatname", NULL};
93 const char *account_name;
95 ZERO_STRUCTP(r->out.return_credentials);
96 *r->out.rid = 0;
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 |
111 NETLOGON_NEG_REDO |
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) {
130 case SEC_CHAN_WKSTA:
131 case SEC_CHAN_DNS_DOMAIN:
132 case SEC_CHAN_DOMAIN:
133 case SEC_CHAN_BDC:
134 case SEC_CHAN_RODC:
135 break;
136 default:
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,
162 trust_dom_attrs,
163 "(&(trustPartner=%s)(objectclass=trustedDomain))",
164 encoded_account);
166 if (num_records == 0) {
167 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
168 encoded_account));
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);
178 if (!flatname) {
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);
184 if (!account_name) {
185 return NT_STATUS_NO_MEMORY;
188 } else {
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;
237 } else {
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],
243 "objectSid", 0);
245 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
246 if (mach_pwd == NULL) {
247 return NT_STATUS_ACCESS_DENIED;
250 if (!pipe_state) {
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,
256 r->in.account_name,
257 r->in.computer_name,
258 r->in.secure_channel_type,
259 &pipe_state->client_challenge,
260 &pipe_state->server_challenge,
261 mach_pwd,
262 r->in.credentials,
263 r->out.return_credentials,
264 *r->in.negotiate_flags);
266 if (!creds) {
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,
274 creds);
276 return nt_status;
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;
283 uint32_t rid;
284 /* TODO:
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;
301 a.out.rid = &rid;
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;
311 uint32_t rid = 0;
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;
321 r3.out.rid = &rid;
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) {
343 return NT_STATUS_OK;
346 if ((!privacy && integrity) &&
347 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
348 return NT_STATUS_OK;
351 if ((privacy || integrity) &&
352 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
353 return NT_STATUS_OK;
357 /* test didn't pass */
358 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
359 computer_name));
361 return NT_STATUS_ACCESS_DENIED;
364 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
365 TALLOC_CTX *mem_ctx,
366 const char *computer_name,
367 struct netr_Authenticator *received_authenticator,
368 struct netr_Authenticator *return_authenticator,
369 struct netlogon_creds_CredentialState **creds_out)
371 NTSTATUS nt_status;
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,
377 computer_name,
378 true, false);
379 if (!NT_STATUS_IS_OK(nt_status)) {
380 return nt_status;
384 nt_status = schannel_check_creds_state(mem_ctx,
385 dce_call->conn->dce_ctx->lp_ctx,
386 computer_name,
387 received_authenticator,
388 return_authenticator,
389 creds_out);
390 return nt_status;
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;
406 NTSTATUS nt_status;
407 int ret;
409 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
410 mem_ctx,
411 r->in.computer_name,
412 r->in.credential, r->out.return_authenticator,
413 &creds);
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));
428 if (ret != 1) {
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,
441 creds->sid,
442 NULL, /* Don't have plaintext */
443 NULL, r->in.new_password,
444 NULL, oldNtHash, /* Password change */
445 NULL, NULL);
446 return nt_status;
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;
461 NTSTATUS nt_status;
462 DATA_BLOB new_password;
463 int ret;
465 struct samr_CryptPassword password_buf;
467 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
468 mem_ctx,
469 r->in.computer_name,
470 r->in.credential, r->out.return_authenticator,
471 &creds);
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));
493 if (ret != 1) {
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,
506 creds->sid,
507 &new_password, /* we have plaintext */
508 NULL, NULL,
509 oldLmHash, oldNtHash, /* Password change */
510 NULL, NULL);
511 return nt_status;
516 netr_LogonUasLogon
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);
526 netr_LogonUasLogoff
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 */
550 break;
551 default:
552 return NT_STATUS_INVALID_INFO_CLASS;
555 break;
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 */
566 break;
567 default:
568 return NT_STATUS_INVALID_INFO_CLASS;
571 break;
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 */
581 break;
582 default:
583 return NT_STATUS_INVALID_INFO_CLASS;
586 break;
587 default:
588 return NT_STATUS_INVALID_PARAMETER;
591 return NT_STATUS_OK;
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;
607 NTSTATUS nt_status;
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));
631 } else {
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,
640 &auth_context);
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;
659 break;
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,
667 &auth_context);
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);
682 break;
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);
690 } else {
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) {
696 NTSTATUS status;
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 */
704 *r->out.flags = 0;
706 r->out.validation->generic = generic;
708 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
709 dce_call->msg_ctx,
710 "kdc_server",
711 &ndr_table_irpc);
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,
721 mem_ctx,
722 &check);
723 if (!NT_STATUS_IS_OK(status)) {
724 return status;
726 generic->length = check.out.generic_reply.length;
727 generic->data = check.out.generic_reply.data;
728 return NT_STATUS_OK;
731 /* Until we get an implemetnation of these other packages */
732 return NT_STATUS_INVALID_PARAMETER;
734 default:
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) {
743 case 2:
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);
749 sam2->base = *sam;
751 /* And put into the talloc tree */
752 talloc_steal(sam2, sam);
753 r->out.validation->sam2 = sam2;
755 sam = &sam2->base;
756 break;
758 case 3:
759 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
760 user_info_dc,
761 &sam3);
762 NT_STATUS_NOT_OK_RETURN(nt_status);
764 r->out.validation->sam3 = sam3;
766 sam = &sam3->base;
767 break;
769 case 6:
770 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
771 user_info_dc,
772 &sam3);
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;
778 sam = &sam6->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;
790 break;
792 default:
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,
803 sam->key.key,
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,
814 sam->LMSessKey.key,
815 sizeof(sam->LMSessKey.key));
816 } else {
817 netlogon_creds_des_encrypt_LMKey(creds,
818 &sam->LMSessKey);
822 /* TODO: Describe and deal with these flags */
823 *r->out.flags = 0;
825 return NT_STATUS_OK;
828 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
829 struct netr_LogonSamLogonEx *r)
831 NTSTATUS nt_status;
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)) {
838 return 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)) {
845 return 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)
862 NTSTATUS nt_status;
863 struct netlogon_creds_CredentialState *creds;
864 struct netr_LogonSamLogonEx r2;
866 struct netr_Authenticator *return_authenticator;
868 ZERO_STRUCT(r2);
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)) {
884 return 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,
891 mem_ctx,
892 r->in.computer_name,
893 r->in.credential, return_authenticator,
894 &creds);
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;
901 return nt_status;
905 netr_LogonSamLogon
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;
911 uint32_t flags = 0;
912 NTSTATUS status;
914 ZERO_STRUCT(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;
932 return status;
937 netr_LogonSamLogoff
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);
948 netr_DatabaseDeltas
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);
958 netr_DatabaseSync2
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;
969 netr_DatabaseSync
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;
975 NTSTATUS status;
977 ZERO_STRUCT(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);
991 return status;
996 netr_AccountDeltas
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;
1007 netr_AccountSync
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;
1018 netr_GetDcName
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;
1027 int ret;
1028 const char *dcname;
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,
1057 r->in.domainname);
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);
1064 if (ret != 1) {
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;
1076 return WERR_OK;
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;
1091 netr_LogonControl
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;
1097 WERROR werr;
1099 if (r->in.level == 0x00000001) {
1100 ZERO_STRUCT(r2);
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;
1105 r2.in.data = NULL;
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;
1111 } else {
1112 werr = WERR_UNKNOWN_LEVEL;
1115 return werr;
1120 netr_LogonControl2
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;
1126 WERROR werr;
1128 ZERO_STRUCT(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);
1138 return werr;
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);
1147 netr_GetAnyDCName
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;
1155 uint32_t i;
1156 WERROR werr;
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);
1182 return WERR_OK;
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);
1190 trusts->count = 0;
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;
1212 netr_DatabaseRedo
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);
1285 netr_DsRGetSiteName
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;
1300 * We assume to be a DC when we get called over NETLOGON. Hence we
1301 * get our site name always by using "samdb_server_site_name()"
1302 * and not "samdb_client_site_name()".
1304 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1305 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1307 return WERR_OK;
1312 fill in a netr_OneDomainInfo from a ldb search result
1314 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1315 struct loadparm_context *lp_ctx,
1316 struct ldb_context *sam_ctx,
1317 struct ldb_message *res,
1318 struct netr_OneDomainInfo *info,
1319 bool is_local, bool is_trust_list)
1321 ZERO_STRUCTP(info);
1323 if (is_trust_list) {
1324 /* w2k8 only fills this on trusted domains */
1325 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1326 info->trust_extension.length = 16;
1327 info->trust_extension.info->flags =
1328 NETR_TRUST_FLAG_TREEROOT |
1329 NETR_TRUST_FLAG_IN_FOREST |
1330 NETR_TRUST_FLAG_PRIMARY |
1331 NETR_TRUST_FLAG_NATIVE;
1333 info->trust_extension.info->parent_index = 0; /* should be index into array
1334 of parent */
1335 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1336 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1339 if (is_trust_list) {
1340 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1341 info->dns_forestname.string = NULL;
1342 } else {
1343 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1344 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1345 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1346 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1349 if (is_local) {
1350 info->domainname.string = lpcfg_workgroup(lp_ctx);
1351 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1352 info->domain_guid = samdb_result_guid(res, "objectGUID");
1353 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1354 } else {
1355 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1356 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1357 info->domain_guid = samdb_result_guid(res, "objectGUID");
1358 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1360 if (!is_trust_list) {
1361 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1364 return NT_STATUS_OK;
1368 netr_LogonGetDomainInfo
1369 this is called as part of the ADS domain logon procedure.
1371 It has an important role in convaying details about the client, such
1372 as Operating System, Version, Service Pack etc.
1374 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1375 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1377 struct netlogon_creds_CredentialState *creds;
1378 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1379 "securityIdentifier", "trustPartner", NULL };
1380 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1381 "msDS-SupportedEncryptionTypes", NULL };
1382 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1383 struct ldb_context *sam_ctx;
1384 struct ldb_message **res1, **res2, **res3, *new_msg;
1385 struct ldb_dn *workstation_dn;
1386 struct netr_DomainInformation *domain_info;
1387 struct netr_LsaPolicyInformation *lsa_policy_info;
1388 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1389 bool update_dns_hostname = true;
1390 int ret, ret3, i;
1391 NTSTATUS status;
1393 status = dcesrv_netr_creds_server_step_check(dce_call,
1394 mem_ctx,
1395 r->in.computer_name,
1396 r->in.credential,
1397 r->out.return_authenticator,
1398 &creds);
1399 if (!NT_STATUS_IS_OK(status)) {
1400 DEBUG(0,(__location__ " Bad credentials - error\n"));
1402 NT_STATUS_NOT_OK_RETURN(status);
1404 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1405 dce_call->conn->dce_ctx->lp_ctx,
1406 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1407 if (sam_ctx == NULL) {
1408 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1411 switch (r->in.level) {
1412 case 1: /* Domain information */
1414 if (r->in.query->workstation_info == NULL) {
1415 return NT_STATUS_INVALID_PARAMETER;
1418 /* Prepares the workstation DN */
1419 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1420 dom_sid_string(mem_ctx, creds->sid));
1421 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1423 /* Lookup for attributes in workstation object */
1424 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1425 attrs2);
1426 if (ret != 1) {
1427 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1430 /* Gets the sam account name which is checked against the DNS
1431 * hostname parameter. */
1432 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1433 "sAMAccountName",
1434 NULL);
1435 if (sam_account_name == NULL) {
1436 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1440 * Checks that the sam account name without a possible "$"
1441 * matches as prefix with the DNS hostname in the workstation
1442 * info structure.
1444 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1445 strcspn(sam_account_name, "$"));
1446 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1447 if (r->in.query->workstation_info->dns_hostname != NULL) {
1448 prefix2 = talloc_strndup(mem_ctx,
1449 r->in.query->workstation_info->dns_hostname,
1450 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1451 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1453 if (strcasecmp(prefix1, prefix2) != 0) {
1454 update_dns_hostname = false;
1456 } else {
1457 update_dns_hostname = false;
1460 /* Gets the old DNS hostname */
1461 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1462 "dNSHostName",
1463 NULL);
1466 * Updates the DNS hostname when the client wishes that the
1467 * server should handle this for him
1468 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1469 * obviously only checked when we do already have a
1470 * "dNSHostName".
1471 * See MS-NRPC section 3.5.4.3.9
1473 if ((old_dns_hostname != NULL) &&
1474 (r->in.query->workstation_info->workstation_flags
1475 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1476 update_dns_hostname = false;
1479 /* Gets host information and put them into our directory */
1481 new_msg = ldb_msg_new(mem_ctx);
1482 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1484 new_msg->dn = workstation_dn;
1486 /* Sets the OS name */
1488 if (r->in.query->workstation_info->os_name.string == NULL) {
1489 return NT_STATUS_INVALID_PARAMETER;
1492 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1493 r->in.query->workstation_info->os_name.string);
1494 if (ret != LDB_SUCCESS) {
1495 return NT_STATUS_NO_MEMORY;
1499 * Sets information from "os_version". On an empty structure
1500 * the values are cleared.
1502 if (r->in.query->workstation_info->os_version.os != NULL) {
1503 struct netr_OsVersionInfoEx *os_version;
1504 const char *os_version_str;
1506 os_version = &r->in.query->workstation_info->os_version.os->os;
1508 if (os_version->CSDVersion == NULL) {
1509 return NT_STATUS_INVALID_PARAMETER;
1512 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1513 os_version->MajorVersion,
1514 os_version->MinorVersion,
1515 os_version->BuildNumber);
1516 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1518 ret = ldb_msg_add_string(new_msg,
1519 "operatingSystemServicePack",
1520 os_version->CSDVersion);
1521 if (ret != LDB_SUCCESS) {
1522 return NT_STATUS_NO_MEMORY;
1525 ret = ldb_msg_add_string(new_msg,
1526 "operatingSystemVersion",
1527 os_version_str);
1528 if (ret != LDB_SUCCESS) {
1529 return NT_STATUS_NO_MEMORY;
1531 } else {
1532 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1533 "operatingSystemServicePack");
1534 if (ret != LDB_SUCCESS) {
1535 return NT_STATUS_NO_MEMORY;
1538 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1539 "operatingSystemVersion");
1540 if (ret != LDB_SUCCESS) {
1541 return NT_STATUS_NO_MEMORY;
1546 * If the boolean "update_dns_hostname" remained true, then we
1547 * are fine to start the update.
1549 if (update_dns_hostname) {
1550 ret = ldb_msg_add_string(new_msg,
1551 "dNSHostname",
1552 r->in.query->workstation_info->dns_hostname);
1553 if (ret != LDB_SUCCESS) {
1554 return NT_STATUS_NO_MEMORY;
1557 /* This manual "servicePrincipalName" generation is
1558 * still needed! Since the update in the samldb LDB
1559 * module does only work if the entries already exist
1560 * which isn't always the case. */
1561 ret = ldb_msg_add_string(new_msg,
1562 "servicePrincipalName",
1563 talloc_asprintf(new_msg, "HOST/%s",
1564 r->in.computer_name));
1565 if (ret != LDB_SUCCESS) {
1566 return NT_STATUS_NO_MEMORY;
1569 ret = ldb_msg_add_string(new_msg,
1570 "servicePrincipalName",
1571 talloc_asprintf(new_msg, "HOST/%s",
1572 r->in.query->workstation_info->dns_hostname));
1573 if (ret != LDB_SUCCESS) {
1574 return NT_STATUS_NO_MEMORY;
1578 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1579 DEBUG(3,("Impossible to update samdb: %s\n",
1580 ldb_errstring(sam_ctx)));
1583 talloc_free(new_msg);
1585 /* Writes back the domain information */
1587 /* We need to do two searches. The first will pull our primary
1588 domain and the second will pull any trusted domains. Our
1589 primary domain is also a "trusted" domain, so we need to
1590 put the primary domain into the lists of returned trusts as
1591 well. */
1592 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1593 &res2, attrs);
1594 if (ret != 1) {
1595 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1598 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1599 "(objectClass=trustedDomain)");
1600 if (ret3 == -1) {
1601 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1604 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1605 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1607 ZERO_STRUCTP(domain_info);
1609 /* Informations about the local and trusted domains */
1611 status = fill_one_domain_info(mem_ctx,
1612 dce_call->conn->dce_ctx->lp_ctx,
1613 sam_ctx, res2[0], &domain_info->primary_domain,
1614 true, false);
1615 NT_STATUS_NOT_OK_RETURN(status);
1617 domain_info->trusted_domain_count = ret3 + 1;
1618 domain_info->trusted_domains = talloc_array(mem_ctx,
1619 struct netr_OneDomainInfo,
1620 domain_info->trusted_domain_count);
1621 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1623 for (i=0;i<ret3;i++) {
1624 status = fill_one_domain_info(mem_ctx,
1625 dce_call->conn->dce_ctx->lp_ctx,
1626 sam_ctx, res3[i],
1627 &domain_info->trusted_domains[i],
1628 false, true);
1629 NT_STATUS_NOT_OK_RETURN(status);
1632 status = fill_one_domain_info(mem_ctx,
1633 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1634 &domain_info->trusted_domains[i], true, true);
1635 NT_STATUS_NOT_OK_RETURN(status);
1637 /* Sets the supported encryption types */
1638 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1639 "msDS-SupportedEncryptionTypes",
1640 default_supported_enc_types);
1642 /* Other host domain information */
1644 lsa_policy_info = talloc(mem_ctx,
1645 struct netr_LsaPolicyInformation);
1646 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1647 ZERO_STRUCTP(lsa_policy_info);
1649 domain_info->lsa_policy = *lsa_policy_info;
1651 /* The DNS hostname is only returned back when there is a chance
1652 * for a change. */
1653 if ((r->in.query->workstation_info->workstation_flags
1654 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1655 domain_info->dns_hostname.string = old_dns_hostname;
1656 } else {
1657 domain_info->dns_hostname.string = NULL;
1660 domain_info->workstation_flags =
1661 r->in.query->workstation_info->workstation_flags;
1663 r->out.info->domain_info = domain_info;
1664 break;
1665 case 2: /* LSA policy information - not used at the moment */
1666 lsa_policy_info = talloc(mem_ctx,
1667 struct netr_LsaPolicyInformation);
1668 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1669 ZERO_STRUCTP(lsa_policy_info);
1671 r->out.info->lsa_policy_info = lsa_policy_info;
1672 break;
1673 default:
1674 return NT_STATUS_INVALID_LEVEL;
1675 break;
1678 return NT_STATUS_OK;
1683 netr_ServerPasswordGet
1685 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1686 struct netr_ServerPasswordGet *r)
1688 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1693 netr_NETRLOGONSENDTOSAM
1695 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1696 struct netr_NETRLOGONSENDTOSAM *r)
1698 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1703 netr_DsRGetDCNameEx2
1705 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1706 TALLOC_CTX *mem_ctx,
1707 struct netr_DsRGetDCNameEx2 *r)
1709 struct ldb_context *sam_ctx;
1710 struct netr_DsRGetDCNameInfo *info;
1711 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1712 const struct tsocket_address *remote_address;
1713 char *addr = NULL;
1714 const char *server_site_name;
1715 char *guid_str;
1716 struct netlogon_samlogon_response response;
1717 NTSTATUS status;
1718 const char *dc_name = NULL;
1719 const char *domain_name = NULL;
1720 struct interface *ifaces;
1721 const char *pdc_ip;
1723 ZERO_STRUCTP(r->out.info);
1725 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1726 dce_call->conn->auth_state.session_info, 0);
1727 if (sam_ctx == NULL) {
1728 return WERR_DS_UNAVAILABLE;
1731 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1732 if (tsocket_address_is_inet(remote_address, "ip")) {
1733 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1734 W_ERROR_HAVE_NO_MEMORY(addr);
1737 /* "server_unc" is ignored by w2k3 */
1739 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1740 return WERR_INVALID_FLAGS;
1743 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1744 r->in.flags & DS_PDC_REQUIRED &&
1745 r->in.flags & DS_KDC_REQUIRED) {
1746 return WERR_INVALID_FLAGS;
1748 if (r->in.flags & DS_IS_FLAT_NAME &&
1749 r->in.flags & DS_IS_DNS_NAME) {
1750 return WERR_INVALID_FLAGS;
1752 if (r->in.flags & DS_RETURN_DNS_NAME &&
1753 r->in.flags & DS_RETURN_FLAT_NAME) {
1754 return WERR_INVALID_FLAGS;
1756 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1757 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1758 return WERR_INVALID_FLAGS;
1761 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1762 r->in.flags &
1763 (DS_DIRECTORY_SERVICE_REQUIRED |
1764 DS_DIRECTORY_SERVICE_PREFERRED |
1765 DS_GC_SERVER_REQUIRED |
1766 DS_PDC_REQUIRED |
1767 DS_KDC_REQUIRED)) {
1768 return WERR_INVALID_FLAGS;
1771 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1772 r->in.site_name) {
1773 return WERR_INVALID_FLAGS;
1776 /* Proof server site parameter "site_name" if it was specified */
1777 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1778 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1779 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1780 server_site_name) != 0)) {
1781 return WERR_NO_SUCH_DOMAIN;
1784 guid_str = r->in.domain_guid != NULL ?
1785 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1787 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1788 r->in.domain_name,
1789 r->in.domain_name,
1790 NULL, guid_str,
1791 r->in.client_account,
1792 r->in.mask, addr,
1793 NETLOGON_NT_VERSION_5EX_WITH_IP,
1794 lp_ctx, &response, true);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 return ntstatus_to_werror(status);
1800 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1801 * (O) flag when the returned forest name is in DNS format. This is here
1802 * always the case (see below).
1804 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1806 if (r->in.flags & DS_RETURN_DNS_NAME) {
1807 dc_name = response.data.nt5_ex.pdc_dns_name;
1808 domain_name = response.data.nt5_ex.dns_domain;
1810 * According to MS-NRPC 2.2.1.2.1 we should set the
1811 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1812 * the returned information is in DNS form.
1814 response.data.nt5_ex.server_type |=
1815 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1816 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1817 dc_name = response.data.nt5_ex.pdc_name;
1818 domain_name = response.data.nt5_ex.domain_name;
1819 } else {
1822 * TODO: autodetect what we need to return
1823 * based on the given arguments
1825 dc_name = response.data.nt5_ex.pdc_name;
1826 domain_name = response.data.nt5_ex.domain_name;
1829 if (!dc_name || !dc_name[0]) {
1830 return WERR_NO_SUCH_DOMAIN;
1833 if (!domain_name || !domain_name[0]) {
1834 return WERR_NO_SUCH_DOMAIN;
1837 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1838 W_ERROR_HAVE_NO_MEMORY(info);
1839 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1840 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1842 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1843 pdc_ip = iface_list_best_ip(ifaces, addr);
1844 if (pdc_ip == NULL) {
1845 pdc_ip = "127.0.0.1";
1847 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1848 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1849 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1850 info->domain_guid = response.data.nt5_ex.domain_uuid;
1851 info->domain_name = domain_name;
1852 info->forest_name = response.data.nt5_ex.forest;
1853 info->dc_flags = response.data.nt5_ex.server_type;
1854 info->dc_site_name = response.data.nt5_ex.server_site;
1855 info->client_site_name = response.data.nt5_ex.client_site;
1857 *r->out.info = info;
1859 return WERR_OK;
1863 netr_DsRGetDCNameEx
1865 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1866 struct netr_DsRGetDCNameEx *r)
1868 struct netr_DsRGetDCNameEx2 r2;
1869 WERROR werr;
1871 ZERO_STRUCT(r2);
1873 r2.in.server_unc = r->in.server_unc;
1874 r2.in.client_account = NULL;
1875 r2.in.mask = 0;
1876 r2.in.domain_guid = r->in.domain_guid;
1877 r2.in.domain_name = r->in.domain_name;
1878 r2.in.site_name = r->in.site_name;
1879 r2.in.flags = r->in.flags;
1880 r2.out.info = r->out.info;
1882 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1884 return werr;
1888 netr_DsRGetDCName
1890 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1891 struct netr_DsRGetDCName *r)
1893 struct netr_DsRGetDCNameEx2 r2;
1894 WERROR werr;
1896 ZERO_STRUCT(r2);
1898 r2.in.server_unc = r->in.server_unc;
1899 r2.in.client_account = NULL;
1900 r2.in.mask = 0;
1901 r2.in.domain_name = r->in.domain_name;
1902 r2.in.domain_guid = r->in.domain_guid;
1904 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1905 r2.in.flags = r->in.flags;
1906 r2.out.info = r->out.info;
1908 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1910 return werr;
1913 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1915 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1916 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1918 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1923 netr_NetrEnumerateTrustedDomainsEx
1925 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1926 struct netr_NetrEnumerateTrustedDomainsEx *r)
1928 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1933 netr_DsRAddressToSitenamesExW
1935 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1936 struct netr_DsRAddressToSitenamesExW *r)
1938 struct ldb_context *sam_ctx;
1939 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1940 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1941 sa_family_t sin_family;
1942 struct sockaddr_in *addr;
1943 #ifdef HAVE_IPV6
1944 struct sockaddr_in6 *addr6;
1945 char addr_str[INET6_ADDRSTRLEN];
1946 #else
1947 char addr_str[INET_ADDRSTRLEN];
1948 #endif
1949 char *subnet_name;
1950 const char *res;
1951 uint32_t i;
1953 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1954 dce_call->conn->auth_state.session_info, 0);
1955 if (sam_ctx == NULL) {
1956 return WERR_DS_UNAVAILABLE;
1959 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1960 W_ERROR_HAVE_NO_MEMORY(ctr);
1962 *r->out.ctr = ctr;
1964 ctr->count = r->in.count;
1965 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1966 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1967 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1968 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1970 for (i=0; i<ctr->count; i++) {
1971 ctr->sitename[i].string = NULL;
1972 ctr->subnetname[i].string = NULL;
1974 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1975 continue;
1977 /* The first two byte of the buffer are reserved for the
1978 * "sin_family" but for now only the first one is used. */
1979 sin_family = r->in.addresses[i].buffer[0];
1981 switch (sin_family) {
1982 case AF_INET:
1983 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1984 continue;
1986 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1987 res = inet_ntop(AF_INET, &addr->sin_addr,
1988 addr_str, sizeof(addr_str));
1989 break;
1990 #ifdef HAVE_IPV6
1991 case AF_INET6:
1992 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1993 continue;
1995 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1996 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1997 addr_str, sizeof(addr_str));
1998 break;
1999 #endif
2000 default:
2001 continue;
2004 if (res == NULL) {
2005 continue;
2008 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2009 mem_ctx,
2010 addr_str,
2011 &subnet_name);
2012 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2013 ctr->subnetname[i].string = subnet_name;
2016 return WERR_OK;
2021 netr_DsRAddressToSitenamesW
2023 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2024 struct netr_DsRAddressToSitenamesW *r)
2026 struct netr_DsRAddressToSitenamesExW r2;
2027 struct netr_DsRAddressToSitenamesWCtr *ctr;
2028 uint32_t i;
2029 WERROR werr;
2031 ZERO_STRUCT(r2);
2033 r2.in.server_name = r->in.server_name;
2034 r2.in.count = r->in.count;
2035 r2.in.addresses = r->in.addresses;
2037 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2038 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2040 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2041 W_ERROR_HAVE_NO_MEMORY(ctr);
2043 *r->out.ctr = ctr;
2045 ctr->count = r->in.count;
2046 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2047 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2049 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2051 for (i=0; i<ctr->count; i++) {
2052 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2055 return werr;
2060 netr_DsrGetDcSiteCoverageW
2062 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2063 struct netr_DsrGetDcSiteCoverageW *r)
2065 struct ldb_context *sam_ctx;
2066 struct DcSitesCtr *ctr;
2067 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2069 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2070 dce_call->conn->auth_state.session_info, 0);
2071 if (sam_ctx == NULL) {
2072 return WERR_DS_UNAVAILABLE;
2075 ctr = talloc(mem_ctx, struct DcSitesCtr);
2076 W_ERROR_HAVE_NO_MEMORY(ctr);
2078 *r->out.ctr = ctr;
2080 /* For now only return our default site */
2081 ctr->num_sites = 1;
2082 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2083 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2084 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2085 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2087 return WERR_OK;
2091 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2092 struct ldb_context *sam_ctx,
2093 struct netr_DomainTrustList *trusts,
2094 uint32_t trust_flags)
2096 struct ldb_dn *system_dn;
2097 struct ldb_message **dom_res = NULL;
2098 const char *trust_attrs[] = { "flatname", "trustPartner",
2099 "securityIdentifier", "trustDirection",
2100 "trustType", "trustAttributes", NULL };
2101 uint32_t n;
2102 int i;
2103 int ret;
2105 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2106 NETR_TRUST_FLAG_OUTBOUND))) {
2107 return WERR_INVALID_FLAGS;
2110 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2111 ldb_get_default_basedn(sam_ctx),
2112 "(&(objectClass=container)(cn=System))");
2113 if (!system_dn) {
2114 return WERR_GENERAL_FAILURE;
2117 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2118 &dom_res, trust_attrs,
2119 "(objectclass=trustedDomain)");
2121 for (i = 0; i < ret; i++) {
2122 unsigned int trust_dir;
2123 uint32_t flags = 0;
2125 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2126 "trustDirection", 0);
2128 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2129 flags |= NETR_TRUST_FLAG_INBOUND;
2131 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2132 flags |= NETR_TRUST_FLAG_OUTBOUND;
2135 if (!(flags & trust_flags)) {
2136 /* this trust direction was not requested */
2137 continue;
2140 n = trusts->count;
2141 trusts->array = talloc_realloc(trusts, trusts->array,
2142 struct netr_DomainTrust,
2143 n + 1);
2144 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2146 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2147 if (!trusts->array[n].netbios_name) {
2148 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2149 "without flatname\n",
2150 ldb_dn_get_linearized(dom_res[i]->dn)));
2153 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2155 trusts->array[n].trust_flags = flags;
2156 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2157 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2158 /* TODO: find if we have parent in the list */
2159 trusts->array[n].parent_index = 0;
2162 trusts->array[n].trust_type =
2163 ldb_msg_find_attr_as_uint(dom_res[i],
2164 "trustType", 0);
2165 trusts->array[n].trust_attributes =
2166 ldb_msg_find_attr_as_uint(dom_res[i],
2167 "trustAttributes", 0);
2169 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2170 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2171 struct dom_sid zero_sid;
2172 ZERO_STRUCT(zero_sid);
2173 trusts->array[n].sid =
2174 dom_sid_dup(trusts, &zero_sid);
2175 } else {
2176 trusts->array[n].sid =
2177 samdb_result_dom_sid(trusts, dom_res[i],
2178 "securityIdentifier");
2180 trusts->array[n].guid = GUID_zero();
2182 trusts->count = n + 1;
2185 talloc_free(dom_res);
2186 return WERR_OK;
2190 netr_DsrEnumerateDomainTrusts
2192 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2193 TALLOC_CTX *mem_ctx,
2194 struct netr_DsrEnumerateDomainTrusts *r)
2196 struct netr_DomainTrustList *trusts;
2197 struct ldb_context *sam_ctx;
2198 int ret;
2199 struct ldb_message **dom_res;
2200 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2201 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2202 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2203 const char *p;
2204 WERROR werr;
2206 if (r->in.trust_flags & 0xFFFFFE00) {
2207 return WERR_INVALID_FLAGS;
2210 /* TODO: turn to hard check once we are sure this is 100% correct */
2211 if (!r->in.server_name) {
2212 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2213 "But received NULL!\n", dnsdomain));
2214 } else {
2215 p = strchr(r->in.server_name, '.');
2216 if (!p) {
2217 DEBUG(3, ("Invalid domain! Expected name in domain "
2218 "[%s]. But received [%s]!\n",
2219 dnsdomain, r->in.server_name));
2220 p = r->in.server_name;
2221 } else {
2222 p++;
2224 if (strcasecmp(p, dnsdomain)) {
2225 DEBUG(3, ("Invalid domain! Expected name in domain "
2226 "[%s]. But received [%s]!\n",
2227 dnsdomain, r->in.server_name));
2231 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2232 W_ERROR_HAVE_NO_MEMORY(trusts);
2234 trusts->count = 0;
2235 r->out.trusts = trusts;
2237 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2238 dce_call->conn->auth_state.session_info, 0);
2239 if (sam_ctx == NULL) {
2240 return WERR_GENERAL_FAILURE;
2243 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2244 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2246 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2247 trusts, r->in.trust_flags);
2248 W_ERROR_NOT_OK_RETURN(werr);
2251 /* NOTE: we currently are always the root of the forest */
2252 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2253 uint32_t n = trusts->count;
2255 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2256 &dom_res, dom_attrs);
2257 if (ret != 1) {
2258 return WERR_GENERAL_FAILURE;
2261 trusts->count = n + 1;
2262 trusts->array = talloc_realloc(trusts, trusts->array,
2263 struct netr_DomainTrust,
2264 trusts->count);
2265 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2267 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2268 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2269 trusts->array[n].trust_flags =
2270 NETR_TRUST_FLAG_NATIVE |
2271 NETR_TRUST_FLAG_TREEROOT |
2272 NETR_TRUST_FLAG_IN_FOREST |
2273 NETR_TRUST_FLAG_PRIMARY;
2274 /* we are always the root domain for now */
2275 trusts->array[n].parent_index = 0;
2276 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2277 trusts->array[n].trust_attributes = 0;
2278 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2279 dom_res[0],
2280 "objectSid");
2281 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2282 "objectGUID");
2283 talloc_free(dom_res);
2286 return WERR_OK;
2291 netr_DsrDeregisterDNSHostRecords
2293 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2294 struct netr_DsrDeregisterDNSHostRecords *r)
2296 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2301 netr_ServerTrustPasswordsGet
2303 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2304 struct netr_ServerTrustPasswordsGet *r)
2306 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2310 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2311 struct ldb_context *sam_ctx,
2312 struct loadparm_context *lp_ctx,
2313 struct lsa_ForestTrustInformation *info)
2315 struct lsa_ForestTrustDomainInfo *domain_info;
2316 struct lsa_ForestTrustRecord *e;
2317 struct ldb_message **dom_res;
2318 const char * const dom_attrs[] = { "objectSid", NULL };
2319 int ret;
2321 /* we need to provide 2 entries:
2322 * 1. the Root Forest name
2323 * 2. the Domain Information
2326 info->count = 2;
2327 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2328 W_ERROR_HAVE_NO_MEMORY(info->entries);
2330 /* Forest root info */
2331 e = talloc(info, struct lsa_ForestTrustRecord);
2332 W_ERROR_HAVE_NO_MEMORY(e);
2334 e->flags = 0;
2335 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2336 e->time = 0; /* so far always 0 in trces. */
2337 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2338 mem_ctx);
2339 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2341 info->entries[0] = e;
2343 /* Domain info */
2344 e = talloc(info, struct lsa_ForestTrustRecord);
2345 W_ERROR_HAVE_NO_MEMORY(e);
2347 /* get our own domain info */
2348 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2349 if (ret != 1) {
2350 return WERR_GENERAL_FAILURE;
2353 /* TODO: check if disabled and set flags accordingly */
2354 e->flags = 0;
2355 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2356 e->time = 0; /* so far always 0 in traces. */
2358 domain_info = &e->forest_trust_data.domain_info;
2359 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2360 "objectSid");
2361 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2362 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2364 info->entries[1] = e;
2366 talloc_free(dom_res);
2368 return WERR_OK;
2372 netr_DsRGetForestTrustInformation
2374 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2375 TALLOC_CTX *mem_ctx,
2376 struct netr_DsRGetForestTrustInformation *r)
2378 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2379 struct lsa_ForestTrustInformation *info, **info_ptr;
2380 struct ldb_context *sam_ctx;
2381 WERROR werr;
2383 if (r->in.flags & 0xFFFFFFFE) {
2384 return WERR_INVALID_FLAGS;
2387 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2388 dce_call->conn->auth_state.session_info, 0);
2389 if (sam_ctx == NULL) {
2390 return WERR_GENERAL_FAILURE;
2393 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2394 if (!samdb_is_pdc(sam_ctx)) {
2395 return WERR_NERR_NOTPRIMARY;
2398 if (r->in.trusted_domain_name == NULL) {
2399 return WERR_INVALID_FLAGS;
2402 /* TODO: establish an schannel connection with
2403 * r->in.trusted_domain_name and perform a
2404 * netr_GetForestTrustInformation call against it */
2406 /* for now return not implementd */
2407 return WERR_CALL_NOT_IMPLEMENTED;
2410 /* TODO: check r->in.server_name is our name */
2412 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2413 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2415 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2416 W_ERROR_HAVE_NO_MEMORY(info);
2418 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2419 W_ERROR_NOT_OK_RETURN(werr);
2421 *info_ptr = info;
2422 r->out.forest_trust_info = info_ptr;
2424 return WERR_OK;
2429 netr_GetForestTrustInformation
2431 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2432 TALLOC_CTX *mem_ctx,
2433 struct netr_GetForestTrustInformation *r)
2435 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2436 struct netlogon_creds_CredentialState *creds;
2437 struct lsa_ForestTrustInformation *info, **info_ptr;
2438 struct ldb_context *sam_ctx;
2439 NTSTATUS status;
2440 WERROR werr;
2442 status = dcesrv_netr_creds_server_step_check(dce_call,
2443 mem_ctx,
2444 r->in.computer_name,
2445 r->in.credential,
2446 r->out.return_authenticator,
2447 &creds);
2448 if (!NT_STATUS_IS_OK(status)) {
2449 return status;
2452 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2453 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2454 return NT_STATUS_NOT_IMPLEMENTED;
2457 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2458 dce_call->conn->auth_state.session_info, 0);
2459 if (sam_ctx == NULL) {
2460 return NT_STATUS_INTERNAL_ERROR;
2463 /* TODO: check r->in.server_name is our name */
2465 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2466 if (!info_ptr) {
2467 return NT_STATUS_NO_MEMORY;
2469 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2470 if (!info) {
2471 return NT_STATUS_NO_MEMORY;
2474 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2475 if (!W_ERROR_IS_OK(werr)) {
2476 return werror_to_ntstatus(werr);
2479 *info_ptr = info;
2480 r->out.forest_trust_info = info_ptr;
2482 return NT_STATUS_OK;
2487 netr_ServerGetTrustInfo
2489 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2490 struct netr_ServerGetTrustInfo *r)
2492 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2496 netr_Unused47
2498 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2499 struct netr_Unused47 *r)
2501 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2505 struct netr_dnsupdate_RODC_state {
2506 struct dcesrv_call_state *dce_call;
2507 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2508 struct dnsupdate_RODC *r2;
2512 called when the forwarded RODC dns update request is finished
2514 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2516 struct netr_dnsupdate_RODC_state *st =
2517 tevent_req_callback_data(subreq,
2518 struct netr_dnsupdate_RODC_state);
2519 NTSTATUS status;
2521 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2522 TALLOC_FREE(subreq);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2525 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2528 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2530 status = dcesrv_reply(st->dce_call);
2531 if (!NT_STATUS_IS_OK(status)) {
2532 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2537 netr_DsrUpdateReadOnlyServerDnsRecords
2539 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2540 TALLOC_CTX *mem_ctx,
2541 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2543 struct netlogon_creds_CredentialState *creds;
2544 NTSTATUS nt_status;
2545 struct dcerpc_binding_handle *binding_handle;
2546 struct netr_dnsupdate_RODC_state *st;
2547 struct tevent_req *subreq;
2549 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2550 mem_ctx,
2551 r->in.computer_name,
2552 r->in.credential,
2553 r->out.return_authenticator,
2554 &creds);
2555 NT_STATUS_NOT_OK_RETURN(nt_status);
2557 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2558 return NT_STATUS_ACCESS_DENIED;
2561 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2562 NT_STATUS_HAVE_NO_MEMORY(st);
2564 st->dce_call = dce_call;
2565 st->r = r;
2566 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2567 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2569 st->r2->in.dom_sid = creds->sid;
2570 st->r2->in.site_name = r->in.site_name;
2571 st->r2->in.dns_ttl = r->in.dns_ttl;
2572 st->r2->in.dns_names = r->in.dns_names;
2573 st->r2->out.dns_names = r->out.dns_names;
2575 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2576 "dnsupdate", &ndr_table_irpc);
2577 if (binding_handle == NULL) {
2578 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2579 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2580 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2583 /* forward the call */
2584 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2585 binding_handle, st->r2);
2586 NT_STATUS_HAVE_NO_MEMORY(subreq);
2588 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2590 /* setup the callback */
2591 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2593 return NT_STATUS_OK;
2597 /* include the generated boilerplate */
2598 #include "librpc/gen_ndr/ndr_netlogon_s.c"