s4-param: use "state directory" and "cache directory" options
[Samba/gebeck_regimport.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobd5a7eebb55c172b2b7599fdde92c03fa621db0e2
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 lpcfg_private_dir(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 lpcfg_private_dir(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 lpcfg_private_dir(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_DS_UNAVAILABLE;
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;
1299 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1300 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1302 return WERR_OK;
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)
1316 ZERO_STRUCTP(info);
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
1329 of parent */
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;
1337 } else {
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);
1344 if (is_local) {
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");
1349 } else {
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;
1385 int ret, ret3, i;
1386 NTSTATUS status;
1388 status = dcesrv_netr_creds_server_step_check(dce_call,
1389 mem_ctx,
1390 r->in.computer_name,
1391 r->in.credential,
1392 r->out.return_authenticator,
1393 &creds);
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,
1420 attrs2);
1421 if (ret != 1) {
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],
1428 "sAMAccountName",
1429 NULL);
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
1437 * info structure.
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;
1451 } else {
1452 update_dns_hostname = false;
1455 /* Gets the old DNS hostname */
1456 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1457 "dNSHostName",
1458 NULL);
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
1465 * "dNSHostName".
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",
1522 os_version_str);
1523 if (ret != LDB_SUCCESS) {
1524 return NT_STATUS_NO_MEMORY;
1526 } else {
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,
1546 "dNSHostname",
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
1586 well. */
1587 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1588 &res2, attrs);
1589 if (ret != 1) {
1590 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1593 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1594 "(objectClass=trustedDomain)");
1595 if (ret3 == -1) {
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,
1609 true, false);
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,
1621 sam_ctx, res3[i],
1622 &domain_info->trusted_domains[i],
1623 false, true);
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
1647 * for a change. */
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;
1651 } else {
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;
1659 break;
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;
1667 break;
1668 default:
1669 return NT_STATUS_INVALID_LEVEL;
1670 break;
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;
1708 char *addr = NULL;
1709 const char *server_site_name;
1710 char *guid_str;
1711 struct netlogon_samlogon_response response;
1712 NTSTATUS status;
1713 const char *dc_name = NULL;
1714 const char *domain_name = NULL;
1715 struct interface *ifaces;
1716 const char *pdc_ip;
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 &&
1757 r->in.flags &
1758 (DS_DIRECTORY_SERVICE_REQUIRED |
1759 DS_DIRECTORY_SERVICE_PREFERRED |
1760 DS_GC_SERVER_REQUIRED |
1761 DS_PDC_REQUIRED |
1762 DS_KDC_REQUIRED)) {
1763 return WERR_INVALID_FLAGS;
1766 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1767 r->in.site_name) {
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,
1783 r->in.domain_name,
1784 r->in.domain_name,
1785 NULL, guid_str,
1786 r->in.client_account,
1787 r->in.mask, addr,
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);
1794 if (r->in.flags & DS_RETURN_DNS_NAME) {
1795 dc_name = response.data.nt5_ex.pdc_dns_name;
1796 domain_name = response.data.nt5_ex.dns_domain;
1797 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1798 dc_name = response.data.nt5_ex.pdc_name;
1799 domain_name = response.data.nt5_ex.domain_name;
1800 } else {
1803 * TODO: autodetect what we need to return
1804 * based on the given arguments
1806 dc_name = response.data.nt5_ex.pdc_name;
1807 domain_name = response.data.nt5_ex.domain_name;
1810 if (!dc_name || !dc_name[0]) {
1811 return WERR_NO_SUCH_DOMAIN;
1814 if (!domain_name || !domain_name[0]) {
1815 return WERR_NO_SUCH_DOMAIN;
1818 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1819 W_ERROR_HAVE_NO_MEMORY(info);
1820 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1821 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1823 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1824 pdc_ip = iface_list_best_ip(ifaces, addr);
1825 if (pdc_ip == NULL) {
1826 pdc_ip = "127.0.0.1";
1828 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1829 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1830 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1831 info->domain_guid = response.data.nt5_ex.domain_uuid;
1832 info->domain_name = domain_name;
1833 info->forest_name = response.data.nt5_ex.forest;
1834 info->dc_flags = response.data.nt5_ex.server_type;
1835 info->dc_site_name = response.data.nt5_ex.server_site;
1836 info->client_site_name = response.data.nt5_ex.client_site;
1838 *r->out.info = info;
1840 return WERR_OK;
1844 netr_DsRGetDCNameEx
1846 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1847 struct netr_DsRGetDCNameEx *r)
1849 struct netr_DsRGetDCNameEx2 r2;
1850 WERROR werr;
1852 ZERO_STRUCT(r2);
1854 r2.in.server_unc = r->in.server_unc;
1855 r2.in.client_account = NULL;
1856 r2.in.mask = 0;
1857 r2.in.domain_guid = r->in.domain_guid;
1858 r2.in.domain_name = r->in.domain_name;
1859 r2.in.site_name = r->in.site_name;
1860 r2.in.flags = r->in.flags;
1861 r2.out.info = r->out.info;
1863 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1865 return werr;
1869 netr_DsRGetDCName
1871 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1872 struct netr_DsRGetDCName *r)
1874 struct netr_DsRGetDCNameEx2 r2;
1875 WERROR werr;
1877 ZERO_STRUCT(r2);
1879 r2.in.server_unc = r->in.server_unc;
1880 r2.in.client_account = NULL;
1881 r2.in.mask = 0;
1882 r2.in.domain_name = r->in.domain_name;
1883 r2.in.domain_guid = r->in.domain_guid;
1885 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1886 r2.in.flags = r->in.flags;
1887 r2.out.info = r->out.info;
1889 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1891 return werr;
1894 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1896 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1897 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1899 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1904 netr_NetrEnumerateTrustedDomainsEx
1906 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1907 struct netr_NetrEnumerateTrustedDomainsEx *r)
1909 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1914 netr_DsRAddressToSitenamesExW
1916 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1917 struct netr_DsRAddressToSitenamesExW *r)
1919 struct ldb_context *sam_ctx;
1920 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1921 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1922 sa_family_t sin_family;
1923 struct sockaddr_in *addr;
1924 #ifdef HAVE_IPV6
1925 struct sockaddr_in6 *addr6;
1926 char addr_str[INET6_ADDRSTRLEN];
1927 #else
1928 char addr_str[INET_ADDRSTRLEN];
1929 #endif
1930 char *subnet_name;
1931 const char *res;
1932 uint32_t i;
1934 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1935 dce_call->conn->auth_state.session_info, 0);
1936 if (sam_ctx == NULL) {
1937 return WERR_DS_UNAVAILABLE;
1940 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1941 W_ERROR_HAVE_NO_MEMORY(ctr);
1943 *r->out.ctr = ctr;
1945 ctr->count = r->in.count;
1946 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1947 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1948 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1949 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1951 for (i=0; i<ctr->count; i++) {
1952 ctr->sitename[i].string = NULL;
1953 ctr->subnetname[i].string = NULL;
1955 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1956 continue;
1958 /* The first two byte of the buffer are reserved for the
1959 * "sin_family" but for now only the first one is used. */
1960 sin_family = r->in.addresses[i].buffer[0];
1962 switch (sin_family) {
1963 case AF_INET:
1964 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1965 continue;
1967 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1968 res = inet_ntop(AF_INET, &addr->sin_addr,
1969 addr_str, sizeof(addr_str));
1970 break;
1971 #ifdef HAVE_IPV6
1972 case AF_INET6:
1973 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1974 continue;
1976 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1977 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1978 addr_str, sizeof(addr_str));
1979 break;
1980 #endif
1981 default:
1982 continue;
1985 if (res == NULL) {
1986 continue;
1989 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1990 mem_ctx,
1991 addr_str,
1992 &subnet_name);
1993 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1994 ctr->subnetname[i].string = subnet_name;
1997 return WERR_OK;
2002 netr_DsRAddressToSitenamesW
2004 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2005 struct netr_DsRAddressToSitenamesW *r)
2007 struct netr_DsRAddressToSitenamesExW r2;
2008 struct netr_DsRAddressToSitenamesWCtr *ctr;
2009 uint32_t i;
2010 WERROR werr;
2012 ZERO_STRUCT(r2);
2014 r2.in.server_name = r->in.server_name;
2015 r2.in.count = r->in.count;
2016 r2.in.addresses = r->in.addresses;
2018 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2019 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2021 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2022 W_ERROR_HAVE_NO_MEMORY(ctr);
2024 *r->out.ctr = ctr;
2026 ctr->count = r->in.count;
2027 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2028 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2030 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2032 for (i=0; i<ctr->count; i++) {
2033 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2036 return werr;
2041 netr_DsrGetDcSiteCoverageW
2043 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2044 struct netr_DsrGetDcSiteCoverageW *r)
2046 struct ldb_context *sam_ctx;
2047 struct DcSitesCtr *ctr;
2048 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2050 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2051 dce_call->conn->auth_state.session_info, 0);
2052 if (sam_ctx == NULL) {
2053 return WERR_DS_UNAVAILABLE;
2056 ctr = talloc(mem_ctx, struct DcSitesCtr);
2057 W_ERROR_HAVE_NO_MEMORY(ctr);
2059 *r->out.ctr = ctr;
2061 /* For now only return our default site */
2062 ctr->num_sites = 1;
2063 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2064 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2065 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2066 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2068 return WERR_OK;
2072 #define GET_CHECK_STR(dest, mem, msg, attr) \
2073 do {\
2074 const char *s; \
2075 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
2076 if (!s) { \
2077 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
2078 "without flatname\n", \
2079 ldb_dn_get_linearized(msg->dn))); \
2080 continue; \
2082 dest = talloc_strdup(mem, s); \
2083 W_ERROR_HAVE_NO_MEMORY(dest); \
2084 } while(0)
2087 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2088 struct ldb_context *sam_ctx,
2089 struct netr_DomainTrustList *trusts,
2090 uint32_t trust_flags)
2092 struct ldb_dn *system_dn;
2093 struct ldb_message **dom_res = NULL;
2094 const char *trust_attrs[] = { "flatname", "trustPartner",
2095 "securityIdentifier", "trustDirection",
2096 "trustType", "trustAttributes", NULL };
2097 uint32_t n;
2098 int i;
2099 int ret;
2101 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2102 NETR_TRUST_FLAG_OUTBOUND))) {
2103 return WERR_INVALID_FLAGS;
2106 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2107 ldb_get_default_basedn(sam_ctx),
2108 "(&(objectClass=container)(cn=System))");
2109 if (!system_dn) {
2110 return WERR_GENERAL_FAILURE;
2113 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2114 &dom_res, trust_attrs,
2115 "(objectclass=trustedDomain)");
2117 for (i = 0; i < ret; i++) {
2118 unsigned int trust_dir;
2119 uint32_t flags = 0;
2121 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2122 "trustDirection", 0);
2124 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2125 flags |= NETR_TRUST_FLAG_INBOUND;
2127 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2128 flags |= NETR_TRUST_FLAG_OUTBOUND;
2131 if (!(flags & trust_flags)) {
2132 /* this trust direction was not requested */
2133 continue;
2136 n = trusts->count;
2137 trusts->array = talloc_realloc(trusts, trusts->array,
2138 struct netr_DomainTrust,
2139 n + 1);
2140 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2142 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2143 dom_res[i], "flatname");
2144 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2145 dom_res[i], "trustPartner");
2147 trusts->array[n].trust_flags = flags;
2148 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2149 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2150 /* TODO: find if we have parent in the list */
2151 trusts->array[n].parent_index = 0;
2154 trusts->array[n].trust_type =
2155 ldb_msg_find_attr_as_uint(dom_res[i],
2156 "trustType", 0);
2157 trusts->array[n].trust_attributes =
2158 ldb_msg_find_attr_as_uint(dom_res[i],
2159 "trustAttributes", 0);
2161 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2162 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2163 struct dom_sid zero_sid;
2164 ZERO_STRUCT(zero_sid);
2165 trusts->array[n].sid =
2166 dom_sid_dup(trusts, &zero_sid);
2167 } else {
2168 trusts->array[n].sid =
2169 samdb_result_dom_sid(trusts, dom_res[i],
2170 "securityIdentifier");
2172 trusts->array[n].guid = GUID_zero();
2174 trusts->count = n + 1;
2177 talloc_free(dom_res);
2178 return WERR_OK;
2182 netr_DsrEnumerateDomainTrusts
2184 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2185 TALLOC_CTX *mem_ctx,
2186 struct netr_DsrEnumerateDomainTrusts *r)
2188 struct netr_DomainTrustList *trusts;
2189 struct ldb_context *sam_ctx;
2190 int ret;
2191 struct ldb_message **dom_res;
2192 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2193 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2194 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2195 const char *p;
2196 WERROR werr;
2198 if (r->in.trust_flags & 0xFFFFFE00) {
2199 return WERR_INVALID_FLAGS;
2202 /* TODO: turn to hard check once we are sure this is 100% correct */
2203 if (!r->in.server_name) {
2204 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2205 "But received NULL!\n", dnsdomain));
2206 } else {
2207 p = strchr(r->in.server_name, '.');
2208 if (!p) {
2209 DEBUG(3, ("Invalid domain! Expected name in domain "
2210 "[%s]. But received [%s]!\n",
2211 dnsdomain, r->in.server_name));
2212 p = r->in.server_name;
2213 } else {
2214 p++;
2216 if (strcasecmp(p, dnsdomain)) {
2217 DEBUG(3, ("Invalid domain! Expected name in domain "
2218 "[%s]. But received [%s]!\n",
2219 dnsdomain, r->in.server_name));
2223 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2224 W_ERROR_HAVE_NO_MEMORY(trusts);
2226 trusts->count = 0;
2227 r->out.trusts = trusts;
2229 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2230 dce_call->conn->auth_state.session_info, 0);
2231 if (sam_ctx == NULL) {
2232 return WERR_GENERAL_FAILURE;
2235 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2236 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2238 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2239 trusts, r->in.trust_flags);
2240 W_ERROR_NOT_OK_RETURN(werr);
2243 /* NOTE: we currently are always the root of the forest */
2244 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2245 uint32_t n = trusts->count;
2247 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2248 &dom_res, dom_attrs);
2249 if (ret != 1) {
2250 return WERR_GENERAL_FAILURE;
2253 trusts->count = n + 1;
2254 trusts->array = talloc_realloc(trusts, trusts->array,
2255 struct netr_DomainTrust,
2256 trusts->count);
2257 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2259 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2260 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2261 trusts->array[n].trust_flags =
2262 NETR_TRUST_FLAG_NATIVE |
2263 NETR_TRUST_FLAG_TREEROOT |
2264 NETR_TRUST_FLAG_IN_FOREST |
2265 NETR_TRUST_FLAG_PRIMARY;
2266 /* we are always the root domain for now */
2267 trusts->array[n].parent_index = 0;
2268 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2269 trusts->array[n].trust_attributes = 0;
2270 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2271 dom_res[0],
2272 "objectSid");
2273 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2274 "objectGUID");
2275 talloc_free(dom_res);
2278 return WERR_OK;
2283 netr_DsrDeregisterDNSHostRecords
2285 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2286 struct netr_DsrDeregisterDNSHostRecords *r)
2288 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2293 netr_ServerTrustPasswordsGet
2295 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2296 struct netr_ServerTrustPasswordsGet *r)
2298 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2302 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2303 struct ldb_context *sam_ctx,
2304 struct loadparm_context *lp_ctx,
2305 struct lsa_ForestTrustInformation *info)
2307 struct lsa_ForestTrustDomainInfo *domain_info;
2308 struct lsa_ForestTrustRecord *e;
2309 struct ldb_message **dom_res;
2310 const char * const dom_attrs[] = { "objectSid", NULL };
2311 int ret;
2313 /* we need to provide 2 entries:
2314 * 1. the Root Forest name
2315 * 2. the Domain Information
2318 info->count = 2;
2319 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2320 W_ERROR_HAVE_NO_MEMORY(info->entries);
2322 /* Forest root info */
2323 e = talloc(info, struct lsa_ForestTrustRecord);
2324 W_ERROR_HAVE_NO_MEMORY(e);
2326 e->flags = 0;
2327 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2328 e->time = 0; /* so far always 0 in trces. */
2329 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2330 mem_ctx);
2331 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2333 info->entries[0] = e;
2335 /* Domain info */
2336 e = talloc(info, struct lsa_ForestTrustRecord);
2337 W_ERROR_HAVE_NO_MEMORY(e);
2339 /* get our own domain info */
2340 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2341 if (ret != 1) {
2342 return WERR_GENERAL_FAILURE;
2345 /* TODO: check if disabled and set flags accordingly */
2346 e->flags = 0;
2347 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2348 e->time = 0; /* so far always 0 in traces. */
2350 domain_info = &e->forest_trust_data.domain_info;
2351 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2352 "objectSid");
2353 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2354 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2356 info->entries[1] = e;
2358 talloc_free(dom_res);
2360 return WERR_OK;
2364 netr_DsRGetForestTrustInformation
2366 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2367 TALLOC_CTX *mem_ctx,
2368 struct netr_DsRGetForestTrustInformation *r)
2370 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2371 struct lsa_ForestTrustInformation *info, **info_ptr;
2372 struct ldb_context *sam_ctx;
2373 WERROR werr;
2375 if (r->in.flags & 0xFFFFFFFE) {
2376 return WERR_INVALID_FLAGS;
2379 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2380 dce_call->conn->auth_state.session_info, 0);
2381 if (sam_ctx == NULL) {
2382 return WERR_GENERAL_FAILURE;
2385 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2386 if (!samdb_is_pdc(sam_ctx)) {
2387 return WERR_NERR_NOTPRIMARY;
2390 if (r->in.trusted_domain_name == NULL) {
2391 return WERR_INVALID_FLAGS;
2394 /* TODO: establish an schannel connection with
2395 * r->in.trusted_domain_name and perform a
2396 * netr_GetForestTrustInformation call against it */
2398 /* for now return not implementd */
2399 return WERR_CALL_NOT_IMPLEMENTED;
2402 /* TODO: check r->in.server_name is our name */
2404 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2405 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2407 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2408 W_ERROR_HAVE_NO_MEMORY(info);
2410 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2411 W_ERROR_NOT_OK_RETURN(werr);
2413 *info_ptr = info;
2414 r->out.forest_trust_info = info_ptr;
2416 return WERR_OK;
2421 netr_GetForestTrustInformation
2423 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2424 TALLOC_CTX *mem_ctx,
2425 struct netr_GetForestTrustInformation *r)
2427 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2428 struct netlogon_creds_CredentialState *creds;
2429 struct lsa_ForestTrustInformation *info, **info_ptr;
2430 struct ldb_context *sam_ctx;
2431 NTSTATUS status;
2432 WERROR werr;
2434 status = dcesrv_netr_creds_server_step_check(dce_call,
2435 mem_ctx,
2436 r->in.computer_name,
2437 r->in.credential,
2438 r->out.return_authenticator,
2439 &creds);
2440 if (!NT_STATUS_IS_OK(status)) {
2441 return status;
2444 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2445 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2446 return NT_STATUS_NOT_IMPLEMENTED;
2449 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2450 dce_call->conn->auth_state.session_info, 0);
2451 if (sam_ctx == NULL) {
2452 return NT_STATUS_INTERNAL_ERROR;
2455 /* TODO: check r->in.server_name is our name */
2457 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2458 if (!info_ptr) {
2459 return NT_STATUS_NO_MEMORY;
2461 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2462 if (!info) {
2463 return NT_STATUS_NO_MEMORY;
2466 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2467 if (!W_ERROR_IS_OK(werr)) {
2468 return werror_to_ntstatus(werr);
2471 *info_ptr = info;
2472 r->out.forest_trust_info = info_ptr;
2474 return NT_STATUS_OK;
2479 netr_ServerGetTrustInfo
2481 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2482 struct netr_ServerGetTrustInfo *r)
2484 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2488 netr_Unused47
2490 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2491 struct netr_Unused47 *r)
2493 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2497 struct netr_dnsupdate_RODC_state {
2498 struct dcesrv_call_state *dce_call;
2499 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2500 struct dnsupdate_RODC *r2;
2504 called when the forwarded RODC dns update request is finished
2506 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2508 struct netr_dnsupdate_RODC_state *st =
2509 tevent_req_callback_data(subreq,
2510 struct netr_dnsupdate_RODC_state);
2511 NTSTATUS status;
2513 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2514 TALLOC_FREE(subreq);
2515 if (!NT_STATUS_IS_OK(status)) {
2516 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2517 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2520 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2522 status = dcesrv_reply(st->dce_call);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2529 netr_DsrUpdateReadOnlyServerDnsRecords
2531 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2532 TALLOC_CTX *mem_ctx,
2533 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2535 struct netlogon_creds_CredentialState *creds;
2536 NTSTATUS nt_status;
2537 struct dcerpc_binding_handle *binding_handle;
2538 struct netr_dnsupdate_RODC_state *st;
2539 struct tevent_req *subreq;
2541 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2542 mem_ctx,
2543 r->in.computer_name,
2544 r->in.credential,
2545 r->out.return_authenticator,
2546 &creds);
2547 NT_STATUS_NOT_OK_RETURN(nt_status);
2549 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2550 return NT_STATUS_ACCESS_DENIED;
2553 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2554 NT_STATUS_HAVE_NO_MEMORY(st);
2556 st->dce_call = dce_call;
2557 st->r = r;
2558 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2559 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2561 st->r2->in.dom_sid = creds->sid;
2562 st->r2->in.site_name = r->in.site_name;
2563 st->r2->in.dns_ttl = r->in.dns_ttl;
2564 st->r2->in.dns_names = r->in.dns_names;
2565 st->r2->out.dns_names = r->out.dns_names;
2567 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2568 "dnsupdate", &ndr_table_irpc);
2569 if (binding_handle == NULL) {
2570 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2571 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2572 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2575 /* forward the call */
2576 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2577 binding_handle, st->r2);
2578 NT_STATUS_HAVE_NO_MEMORY(subreq);
2580 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2582 /* setup the callback */
2583 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2585 return NT_STATUS_OK;
2589 /* include the generated boilerplate */
2590 #include "librpc/gen_ndr/ndr_netlogon_s.c"