VERSION: Bump version number up to 3.6.18.
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob8cd8257c240dca867cecbd9601f071ec16b4e2c8
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"
41 struct netlogon_server_pipe_state {
42 struct netr_Credential client_challenge;
43 struct netr_Credential server_challenge;
46 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
47 struct netr_ServerReqChallenge *r)
49 struct netlogon_server_pipe_state *pipe_state =
50 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
52 ZERO_STRUCTP(r->out.return_credentials);
54 /* destroyed on pipe shutdown */
56 if (pipe_state) {
57 talloc_free(pipe_state);
58 dce_call->context->private_data = NULL;
61 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
62 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
64 pipe_state->client_challenge = *r->in.credentials;
66 generate_random_buffer(pipe_state->server_challenge.data,
67 sizeof(pipe_state->server_challenge.data));
69 *r->out.return_credentials = pipe_state->server_challenge;
71 dce_call->context->private_data = pipe_state;
73 return NT_STATUS_OK;
76 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
77 struct netr_ServerAuthenticate3 *r)
79 struct netlogon_server_pipe_state *pipe_state =
80 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
81 struct netlogon_creds_CredentialState *creds;
82 struct ldb_context *sam_ctx;
83 struct samr_Password *mach_pwd;
84 uint32_t user_account_control;
85 int num_records;
86 struct ldb_message **msgs;
87 NTSTATUS nt_status;
88 const char *attrs[] = {"unicodePwd", "userAccountControl",
89 "objectSid", NULL};
91 const char *trust_dom_attrs[] = {"flatname", NULL};
92 const char *account_name;
94 ZERO_STRUCTP(r->out.return_credentials);
95 *r->out.rid = 0;
98 * According to Microsoft (see bugid #6099)
99 * Windows 7 looks at the negotiate_flags
100 * returned in this structure *even if the
101 * call fails with access denied!
103 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
104 NETLOGON_NEG_PERSISTENT_SAMREPL |
105 NETLOGON_NEG_ARCFOUR |
106 NETLOGON_NEG_PROMOTION_COUNT |
107 NETLOGON_NEG_CHANGELOG_BDC |
108 NETLOGON_NEG_FULL_SYNC_REPL |
109 NETLOGON_NEG_MULTIPLE_SIDS |
110 NETLOGON_NEG_REDO |
111 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
112 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
113 NETLOGON_NEG_GENERIC_PASSTHROUGH |
114 NETLOGON_NEG_CONCURRENT_RPC |
115 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
116 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
117 NETLOGON_NEG_STRONG_KEYS |
118 NETLOGON_NEG_TRANSITIVE_TRUSTS |
119 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
120 NETLOGON_NEG_PASSWORD_SET2 |
121 NETLOGON_NEG_GETDOMAININFO |
122 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
123 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
124 NETLOGON_NEG_RODC_PASSTHROUGH |
125 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
126 NETLOGON_NEG_AUTHENTICATED_RPC;
128 switch (r->in.secure_channel_type) {
129 case SEC_CHAN_WKSTA:
130 case SEC_CHAN_DNS_DOMAIN:
131 case SEC_CHAN_DOMAIN:
132 case SEC_CHAN_BDC:
133 case SEC_CHAN_RODC:
134 break;
135 default:
136 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
137 r->in.secure_channel_type));
138 return NT_STATUS_INVALID_PARAMETER;
141 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
142 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
143 if (sam_ctx == NULL) {
144 return NT_STATUS_INVALID_SYSTEM_SERVICE;
147 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
148 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
149 const char *flatname;
150 if (!encoded_account) {
151 return NT_STATUS_NO_MEMORY;
154 /* Kill the trailing dot */
155 if (encoded_account[strlen(encoded_account)-1] == '.') {
156 encoded_account[strlen(encoded_account)-1] = '\0';
159 /* pull the user attributes */
160 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
161 trust_dom_attrs,
162 "(&(trustPartner=%s)(objectclass=trustedDomain))",
163 encoded_account);
165 if (num_records == 0) {
166 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
167 encoded_account));
168 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
171 if (num_records > 1) {
172 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
173 return NT_STATUS_INTERNAL_DB_CORRUPTION;
176 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
177 if (!flatname) {
178 /* No flatname for this trust - we can't proceed */
179 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
181 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
183 if (!account_name) {
184 return NT_STATUS_NO_MEMORY;
187 } else {
188 account_name = r->in.account_name;
191 /* pull the user attributes */
192 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
193 "(&(sAMAccountName=%s)(objectclass=user))",
194 ldb_binary_encode_string(mem_ctx, account_name));
196 if (num_records == 0) {
197 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
198 r->in.account_name));
199 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
202 if (num_records > 1) {
203 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
204 return NT_STATUS_INTERNAL_DB_CORRUPTION;
207 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
209 if (user_account_control & UF_ACCOUNTDISABLE) {
210 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
211 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
214 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
215 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
216 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
217 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
219 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
220 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
221 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
222 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
224 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
226 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
227 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
228 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
229 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
231 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
232 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
233 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
234 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
236 } else {
237 /* we should never reach this */
238 return NT_STATUS_INTERNAL_ERROR;
241 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
242 "objectSid", 0);
244 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
245 if (mach_pwd == NULL) {
246 return NT_STATUS_ACCESS_DENIED;
249 if (!pipe_state) {
250 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
251 return NT_STATUS_ACCESS_DENIED;
254 creds = netlogon_creds_server_init(mem_ctx,
255 r->in.account_name,
256 r->in.computer_name,
257 r->in.secure_channel_type,
258 &pipe_state->client_challenge,
259 &pipe_state->server_challenge,
260 mach_pwd,
261 r->in.credentials,
262 r->out.return_credentials,
263 *r->in.negotiate_flags);
265 if (!creds) {
266 return NT_STATUS_ACCESS_DENIED;
269 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
271 nt_status = schannel_save_creds_state(mem_ctx,
272 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
273 creds);
275 return nt_status;
278 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
279 struct netr_ServerAuthenticate *r)
281 struct netr_ServerAuthenticate3 a;
282 uint32_t rid;
283 /* TODO:
284 * negotiate_flags is used as an [in] parameter
285 * so it need to be initialised.
287 * (I think ... = 0; seems wrong here --metze)
289 uint32_t negotiate_flags_in = 0;
290 uint32_t negotiate_flags_out = 0;
292 a.in.server_name = r->in.server_name;
293 a.in.account_name = r->in.account_name;
294 a.in.secure_channel_type = r->in.secure_channel_type;
295 a.in.computer_name = r->in.computer_name;
296 a.in.credentials = r->in.credentials;
297 a.in.negotiate_flags = &negotiate_flags_in;
299 a.out.return_credentials = r->out.return_credentials;
300 a.out.rid = &rid;
301 a.out.negotiate_flags = &negotiate_flags_out;
303 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
306 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
307 struct netr_ServerAuthenticate2 *r)
309 struct netr_ServerAuthenticate3 r3;
310 uint32_t rid = 0;
312 r3.in.server_name = r->in.server_name;
313 r3.in.account_name = r->in.account_name;
314 r3.in.secure_channel_type = r->in.secure_channel_type;
315 r3.in.computer_name = r->in.computer_name;
316 r3.in.credentials = r->in.credentials;
317 r3.out.return_credentials = r->out.return_credentials;
318 r3.in.negotiate_flags = r->in.negotiate_flags;
319 r3.out.negotiate_flags = r->out.negotiate_flags;
320 r3.out.rid = &rid;
322 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
326 * NOTE: The following functions are nearly identical to the ones available in
327 * source3/rpc_server/srv_nelog_nt.c
328 * The reason we keep 2 copies is that they use different structures to
329 * represent the auth_info and the decrpc pipes.
333 * If schannel is required for this call test that it actually is available.
335 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
336 const char *computer_name,
337 bool integrity, bool privacy)
340 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
341 if (!privacy && !integrity) {
342 return NT_STATUS_OK;
345 if ((!privacy && integrity) &&
346 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
347 return NT_STATUS_OK;
350 if ((privacy || integrity) &&
351 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
352 return NT_STATUS_OK;
356 /* test didn't pass */
357 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
358 computer_name));
360 return NT_STATUS_ACCESS_DENIED;
363 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
364 TALLOC_CTX *mem_ctx,
365 const char *computer_name,
366 struct netr_Authenticator *received_authenticator,
367 struct netr_Authenticator *return_authenticator,
368 struct netlogon_creds_CredentialState **creds_out)
370 NTSTATUS nt_status;
371 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
372 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
374 if (schannel_global_required) {
375 nt_status = schannel_check_required(auth_info,
376 computer_name,
377 true, false);
378 if (!NT_STATUS_IS_OK(nt_status)) {
379 return nt_status;
383 nt_status = schannel_check_creds_state(mem_ctx,
384 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
385 computer_name,
386 received_authenticator,
387 return_authenticator,
388 creds_out);
389 return nt_status;
393 Change the machine account password for the currently connected
394 client. Supplies only the NT#.
397 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
398 struct netr_ServerPasswordSet *r)
400 struct netlogon_creds_CredentialState *creds;
401 struct ldb_context *sam_ctx;
402 const char * const attrs[] = { "unicodePwd", NULL };
403 struct ldb_message **res;
404 struct samr_Password *oldNtHash;
405 NTSTATUS nt_status;
406 int ret;
408 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
409 mem_ctx,
410 r->in.computer_name,
411 r->in.credential, r->out.return_authenticator,
412 &creds);
413 NT_STATUS_NOT_OK_RETURN(nt_status);
415 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);
416 if (sam_ctx == NULL) {
417 return NT_STATUS_INVALID_SYSTEM_SERVICE;
420 netlogon_creds_des_decrypt(creds, r->in.new_password);
422 /* fetch the old password hashes (the NT hash has to exist) */
424 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
425 "(&(objectClass=user)(objectSid=%s))",
426 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
427 if (ret != 1) {
428 return NT_STATUS_WRONG_PASSWORD;
431 nt_status = samdb_result_passwords(mem_ctx,
432 dce_call->conn->dce_ctx->lp_ctx,
433 res[0], NULL, &oldNtHash);
434 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
435 return NT_STATUS_WRONG_PASSWORD;
438 /* Using the sid for the account as the key, set the password */
439 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
440 creds->sid,
441 NULL, /* Don't have plaintext */
442 NULL, r->in.new_password,
443 NULL, oldNtHash, /* Password change */
444 NULL, NULL);
445 return nt_status;
449 Change the machine account password for the currently connected
450 client. Supplies new plaintext.
452 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
453 struct netr_ServerPasswordSet2 *r)
455 struct netlogon_creds_CredentialState *creds;
456 struct ldb_context *sam_ctx;
457 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
458 struct ldb_message **res;
459 struct samr_Password *oldLmHash, *oldNtHash;
460 NTSTATUS nt_status;
461 DATA_BLOB new_password;
462 int ret;
464 struct samr_CryptPassword password_buf;
466 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
467 mem_ctx,
468 r->in.computer_name,
469 r->in.credential, r->out.return_authenticator,
470 &creds);
471 NT_STATUS_NOT_OK_RETURN(nt_status);
473 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);
474 if (sam_ctx == NULL) {
475 return NT_STATUS_INVALID_SYSTEM_SERVICE;
478 memcpy(password_buf.data, r->in.new_password->data, 512);
479 SIVAL(password_buf.data, 512, r->in.new_password->length);
480 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
482 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
483 DEBUG(3,("samr: failed to decode password buffer\n"));
484 return NT_STATUS_WRONG_PASSWORD;
487 /* fetch the old password hashes (at least one of both has to exist) */
489 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
490 "(&(objectClass=user)(objectSid=%s))",
491 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
492 if (ret != 1) {
493 return NT_STATUS_WRONG_PASSWORD;
496 nt_status = samdb_result_passwords(mem_ctx,
497 dce_call->conn->dce_ctx->lp_ctx,
498 res[0], &oldLmHash, &oldNtHash);
499 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
500 return NT_STATUS_WRONG_PASSWORD;
503 /* Using the sid for the account as the key, set the password */
504 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
505 creds->sid,
506 &new_password, /* we have plaintext */
507 NULL, NULL,
508 oldLmHash, oldNtHash, /* Password change */
509 NULL, NULL);
510 return nt_status;
515 netr_LogonUasLogon
517 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
518 struct netr_LogonUasLogon *r)
520 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
525 netr_LogonUasLogoff
527 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
528 struct netr_LogonUasLogoff *r)
530 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
534 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
536 switch (r->in.logon_level) {
537 case NetlogonInteractiveInformation:
538 case NetlogonServiceInformation:
539 case NetlogonInteractiveTransitiveInformation:
540 case NetlogonServiceTransitiveInformation:
541 if (r->in.logon->password == NULL) {
542 return NT_STATUS_INVALID_PARAMETER;
545 switch (r->in.validation_level) {
546 case NetlogonValidationSamInfo: /* 2 */
547 case NetlogonValidationSamInfo2: /* 3 */
548 case NetlogonValidationSamInfo4: /* 6 */
549 break;
550 default:
551 return NT_STATUS_INVALID_INFO_CLASS;
554 break;
555 case NetlogonNetworkInformation:
556 case NetlogonNetworkTransitiveInformation:
557 if (r->in.logon->network == NULL) {
558 return NT_STATUS_INVALID_PARAMETER;
561 switch (r->in.validation_level) {
562 case NetlogonValidationSamInfo: /* 2 */
563 case NetlogonValidationSamInfo2: /* 3 */
564 case NetlogonValidationSamInfo4: /* 6 */
565 break;
566 default:
567 return NT_STATUS_INVALID_INFO_CLASS;
570 break;
572 case NetlogonGenericInformation:
573 if (r->in.logon->generic == NULL) {
574 return NT_STATUS_INVALID_PARAMETER;
577 switch (r->in.validation_level) {
578 /* TODO: case NetlogonValidationGenericInfo: 4 */
579 case NetlogonValidationGenericInfo2: /* 5 */
580 break;
581 default:
582 return NT_STATUS_INVALID_INFO_CLASS;
585 break;
586 default:
587 return NT_STATUS_INVALID_PARAMETER;
590 return NT_STATUS_OK;
594 netr_LogonSamLogon_base
596 This version of the function allows other wrappers to say 'do not check the credentials'
598 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
600 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
601 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
603 struct auth_context *auth_context;
604 struct auth_usersupplied_info *user_info;
605 struct auth_user_info_dc *user_info_dc;
606 NTSTATUS nt_status;
607 static const char zeros[16];
608 struct netr_SamBaseInfo *sam;
609 struct netr_SamInfo2 *sam2;
610 struct netr_SamInfo3 *sam3;
611 struct netr_SamInfo6 *sam6;
613 *r->out.authoritative = 1;
615 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
616 NT_STATUS_HAVE_NO_MEMORY(user_info);
618 switch (r->in.logon_level) {
619 case NetlogonInteractiveInformation:
620 case NetlogonServiceInformation:
621 case NetlogonInteractiveTransitiveInformation:
622 case NetlogonServiceTransitiveInformation:
623 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
624 netlogon_creds_arcfour_crypt(creds,
625 r->in.logon->password->lmpassword.hash,
626 sizeof(r->in.logon->password->lmpassword.hash));
627 netlogon_creds_arcfour_crypt(creds,
628 r->in.logon->password->ntpassword.hash,
629 sizeof(r->in.logon->password->ntpassword.hash));
630 } else {
631 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
632 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
635 /* TODO: we need to deny anonymous access here */
636 nt_status = auth_context_create(mem_ctx,
637 dce_call->event_ctx, dce_call->msg_ctx,
638 dce_call->conn->dce_ctx->lp_ctx,
639 &auth_context);
640 NT_STATUS_NOT_OK_RETURN(nt_status);
642 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
643 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
644 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
645 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
647 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
648 user_info->password_state = AUTH_PASSWORD_HASH;
650 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
651 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
652 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
654 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
655 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
656 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
658 break;
659 case NetlogonNetworkInformation:
660 case NetlogonNetworkTransitiveInformation:
662 /* TODO: we need to deny anonymous access here */
663 nt_status = auth_context_create(mem_ctx,
664 dce_call->event_ctx, dce_call->msg_ctx,
665 dce_call->conn->dce_ctx->lp_ctx,
666 &auth_context);
667 NT_STATUS_NOT_OK_RETURN(nt_status);
669 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
670 NT_STATUS_NOT_OK_RETURN(nt_status);
672 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
673 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
674 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
675 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
677 user_info->password_state = AUTH_PASSWORD_RESPONSE;
678 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
679 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
681 break;
684 case NetlogonGenericInformation:
686 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
687 netlogon_creds_arcfour_crypt(creds,
688 r->in.logon->generic->data, r->in.logon->generic->length);
689 } else {
690 /* Using DES to verify kerberos tickets makes no sense */
691 return NT_STATUS_INVALID_PARAMETER;
694 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
695 NTSTATUS status;
696 struct dcerpc_binding_handle *irpc_handle;
697 struct kdc_check_generic_kerberos check;
698 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
699 NT_STATUS_HAVE_NO_MEMORY(generic);
700 *r->out.authoritative = 1;
702 /* TODO: Describe and deal with these flags */
703 *r->out.flags = 0;
705 r->out.validation->generic = generic;
707 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
708 dce_call->msg_ctx,
709 "kdc_server",
710 &ndr_table_irpc);
711 if (irpc_handle == NULL) {
712 return NT_STATUS_NO_LOGON_SERVERS;
715 check.in.generic_request =
716 data_blob_const(r->in.logon->generic->data,
717 r->in.logon->generic->length);
719 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
720 mem_ctx,
721 &check);
722 if (!NT_STATUS_IS_OK(status)) {
723 return status;
725 generic->length = check.out.generic_reply.length;
726 generic->data = check.out.generic_reply.data;
727 return NT_STATUS_OK;
730 /* Until we get an implemetnation of these other packages */
731 return NT_STATUS_INVALID_PARAMETER;
733 default:
734 return NT_STATUS_INVALID_PARAMETER;
737 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
738 /* TODO: set *r->out.authoritative = 0 on specific errors */
739 NT_STATUS_NOT_OK_RETURN(nt_status);
741 switch (r->in.validation_level) {
742 case 2:
743 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
744 NT_STATUS_NOT_OK_RETURN(nt_status);
746 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
747 NT_STATUS_HAVE_NO_MEMORY(sam2);
748 sam2->base = *sam;
750 /* And put into the talloc tree */
751 talloc_steal(sam2, sam);
752 r->out.validation->sam2 = sam2;
754 sam = &sam2->base;
755 break;
757 case 3:
758 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
759 user_info_dc,
760 &sam3);
761 NT_STATUS_NOT_OK_RETURN(nt_status);
763 r->out.validation->sam3 = sam3;
765 sam = &sam3->base;
766 break;
768 case 6:
769 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
770 user_info_dc,
771 &sam3);
772 NT_STATUS_NOT_OK_RETURN(nt_status);
774 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
775 NT_STATUS_HAVE_NO_MEMORY(sam6);
776 sam6->base = sam3->base;
777 sam = &sam6->base;
778 sam6->sidcount = sam3->sidcount;
779 sam6->sids = sam3->sids;
781 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
782 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
783 sam->account_name.string, sam6->dns_domainname.string);
784 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
785 /* And put into the talloc tree */
786 talloc_steal(sam6, sam3);
788 r->out.validation->sam6 = sam6;
789 break;
791 default:
792 return NT_STATUS_INVALID_INFO_CLASS;
795 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
796 /* It appears that level 6 is not individually encrypted */
797 if ((r->in.validation_level != 6) &&
798 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
799 /* This key is sent unencrypted without the ARCFOUR flag set */
800 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
801 netlogon_creds_arcfour_crypt(creds,
802 sam->key.key,
803 sizeof(sam->key.key));
807 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
808 /* It appears that level 6 is not individually encrypted */
809 if ((r->in.validation_level != 6) &&
810 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
811 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
812 netlogon_creds_arcfour_crypt(creds,
813 sam->LMSessKey.key,
814 sizeof(sam->LMSessKey.key));
815 } else {
816 netlogon_creds_des_encrypt_LMKey(creds,
817 &sam->LMSessKey);
821 /* TODO: Describe and deal with these flags */
822 *r->out.flags = 0;
824 return NT_STATUS_OK;
827 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
828 struct netr_LogonSamLogonEx *r)
830 NTSTATUS nt_status;
831 struct netlogon_creds_CredentialState *creds;
833 *r->out.authoritative = 1;
835 nt_status = dcesrv_netr_LogonSamLogon_check(r);
836 if (!NT_STATUS_IS_OK(nt_status)) {
837 return nt_status;
840 nt_status = schannel_get_creds_state(mem_ctx,
841 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
842 r->in.computer_name, &creds);
843 if (!NT_STATUS_IS_OK(nt_status)) {
844 return nt_status;
847 if (!dce_call->conn->auth_state.auth_info ||
848 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
849 return NT_STATUS_ACCESS_DENIED;
851 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
855 netr_LogonSamLogonWithFlags
858 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
859 struct netr_LogonSamLogonWithFlags *r)
861 NTSTATUS nt_status;
862 struct netlogon_creds_CredentialState *creds;
863 struct netr_LogonSamLogonEx r2;
865 struct netr_Authenticator *return_authenticator;
867 ZERO_STRUCT(r2);
869 r2.in.server_name = r->in.server_name;
870 r2.in.computer_name = r->in.computer_name;
871 r2.in.logon_level = r->in.logon_level;
872 r2.in.logon = r->in.logon;
873 r2.in.validation_level = r->in.validation_level;
874 r2.in.flags = r->in.flags;
875 r2.out.validation = r->out.validation;
876 r2.out.authoritative = r->out.authoritative;
877 r2.out.flags = r->out.flags;
879 *r->out.authoritative = 1;
881 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
882 if (!NT_STATUS_IS_OK(nt_status)) {
883 return nt_status;
886 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
887 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
889 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
890 mem_ctx,
891 r->in.computer_name,
892 r->in.credential, return_authenticator,
893 &creds);
894 NT_STATUS_NOT_OK_RETURN(nt_status);
896 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
898 r->out.return_authenticator = return_authenticator;
900 return nt_status;
904 netr_LogonSamLogon
906 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
907 struct netr_LogonSamLogon *r)
909 struct netr_LogonSamLogonWithFlags r2;
910 uint32_t flags = 0;
911 NTSTATUS status;
913 ZERO_STRUCT(r2);
915 r2.in.server_name = r->in.server_name;
916 r2.in.computer_name = r->in.computer_name;
917 r2.in.credential = r->in.credential;
918 r2.in.return_authenticator = r->in.return_authenticator;
919 r2.in.logon_level = r->in.logon_level;
920 r2.in.logon = r->in.logon;
921 r2.in.validation_level = r->in.validation_level;
922 r2.in.flags = &flags;
923 r2.out.validation = r->out.validation;
924 r2.out.authoritative = r->out.authoritative;
925 r2.out.flags = &flags;
927 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
929 r->out.return_authenticator = r2.out.return_authenticator;
931 return status;
936 netr_LogonSamLogoff
938 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
939 struct netr_LogonSamLogoff *r)
941 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
947 netr_DatabaseDeltas
949 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
950 struct netr_DatabaseDeltas *r)
952 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
957 netr_DatabaseSync2
959 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
960 struct netr_DatabaseSync2 *r)
962 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
963 return NT_STATUS_NOT_IMPLEMENTED;
968 netr_DatabaseSync
970 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
971 struct netr_DatabaseSync *r)
973 struct netr_DatabaseSync2 r2;
974 NTSTATUS status;
976 ZERO_STRUCT(r2);
978 r2.in.logon_server = r->in.logon_server;
979 r2.in.computername = r->in.computername;
980 r2.in.credential = r->in.credential;
981 r2.in.database_id = r->in.database_id;
982 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
983 r2.in.sync_context = r->in.sync_context;
984 r2.out.sync_context = r->out.sync_context;
985 r2.out.delta_enum_array = r->out.delta_enum_array;
986 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
988 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
990 return status;
995 netr_AccountDeltas
997 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
998 struct netr_AccountDeltas *r)
1000 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1001 return NT_STATUS_NOT_IMPLEMENTED;
1006 netr_AccountSync
1008 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1009 struct netr_AccountSync *r)
1011 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1012 return NT_STATUS_NOT_IMPLEMENTED;
1017 netr_GetDcName
1019 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1020 struct netr_GetDcName *r)
1022 const char * const attrs[] = { NULL };
1023 struct ldb_context *sam_ctx;
1024 struct ldb_message **res;
1025 struct ldb_dn *domain_dn;
1026 int ret;
1027 const char *dcname;
1030 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1031 * that the domainname needs to be a valid netbios domain
1032 * name, if it is not NULL.
1034 if (r->in.domainname) {
1035 const char *dot = strchr(r->in.domainname, '.');
1036 size_t len = strlen(r->in.domainname);
1038 if (dot || len > 15) {
1039 return WERR_DCNOTFOUND;
1043 * TODO: Should we also varify that only valid
1044 * netbios name characters are used?
1048 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1049 dce_call->conn->dce_ctx->lp_ctx,
1050 dce_call->conn->auth_state.session_info, 0);
1051 if (sam_ctx == NULL) {
1052 return WERR_DS_UNAVAILABLE;
1055 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1056 r->in.domainname);
1057 if (domain_dn == NULL) {
1058 return WERR_DS_UNAVAILABLE;
1061 ret = gendb_search_dn(sam_ctx, mem_ctx,
1062 domain_dn, &res, attrs);
1063 if (ret != 1) {
1064 return WERR_NO_SUCH_DOMAIN;
1067 /* TODO: - return real IP address
1068 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1070 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1071 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1072 W_ERROR_HAVE_NO_MEMORY(dcname);
1074 *r->out.dcname = dcname;
1075 return WERR_OK;
1080 netr_LogonControl2Ex
1082 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1083 struct netr_LogonControl2Ex *r)
1085 return WERR_NOT_SUPPORTED;
1090 netr_LogonControl
1092 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1093 struct netr_LogonControl *r)
1095 struct netr_LogonControl2Ex r2;
1096 WERROR werr;
1098 if (r->in.level == 0x00000001) {
1099 ZERO_STRUCT(r2);
1101 r2.in.logon_server = r->in.logon_server;
1102 r2.in.function_code = r->in.function_code;
1103 r2.in.level = r->in.level;
1104 r2.in.data = NULL;
1105 r2.out.query = r->out.query;
1107 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1108 } else if (r->in.level == 0x00000002) {
1109 werr = WERR_NOT_SUPPORTED;
1110 } else {
1111 werr = WERR_UNKNOWN_LEVEL;
1114 return werr;
1119 netr_LogonControl2
1121 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1122 struct netr_LogonControl2 *r)
1124 struct netr_LogonControl2Ex r2;
1125 WERROR werr;
1127 ZERO_STRUCT(r2);
1129 r2.in.logon_server = r->in.logon_server;
1130 r2.in.function_code = r->in.function_code;
1131 r2.in.level = r->in.level;
1132 r2.in.data = r->in.data;
1133 r2.out.query = r->out.query;
1135 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1137 return werr;
1140 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1141 struct ldb_context *sam_ctx,
1142 struct netr_DomainTrustList *trusts,
1143 uint32_t trust_flags);
1146 netr_GetAnyDCName
1148 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1149 struct netr_GetAnyDCName *r)
1151 struct netr_DomainTrustList *trusts;
1152 struct ldb_context *sam_ctx;
1153 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1154 uint32_t i;
1155 WERROR werr;
1157 *r->out.dcname = NULL;
1159 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1160 /* if the domainname parameter wasn't set assume our domain */
1161 r->in.domainname = lpcfg_workgroup(lp_ctx);
1164 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1165 dce_call->conn->auth_state.session_info, 0);
1166 if (sam_ctx == NULL) {
1167 return WERR_DS_UNAVAILABLE;
1170 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1171 /* well we asked for a DC of our own domain */
1172 if (samdb_is_pdc(sam_ctx)) {
1173 /* we are the PDC of the specified domain */
1174 return WERR_NO_SUCH_DOMAIN;
1177 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1178 lpcfg_netbios_name(lp_ctx));
1179 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1181 return WERR_OK;
1184 /* Okay, now we have to consider the trusted domains */
1186 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1187 W_ERROR_HAVE_NO_MEMORY(trusts);
1189 trusts->count = 0;
1191 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1192 NETR_TRUST_FLAG_INBOUND
1193 | NETR_TRUST_FLAG_OUTBOUND);
1194 W_ERROR_NOT_OK_RETURN(werr);
1196 for (i = 0; i < trusts->count; i++) {
1197 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1198 /* FIXME: Here we need to find a DC for the specified
1199 * trusted domain. */
1201 /* return WERR_OK; */
1202 return WERR_NO_SUCH_DOMAIN;
1206 return WERR_NO_SUCH_DOMAIN;
1211 netr_DatabaseRedo
1213 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1214 struct netr_DatabaseRedo *r)
1216 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1221 netr_NetrEnumerateTrustedDomains
1223 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1224 struct netr_NetrEnumerateTrustedDomains *r)
1226 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1231 netr_LogonGetCapabilities
1233 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1234 struct netr_LogonGetCapabilities *r)
1236 /* we don't support AES yet */
1237 return NT_STATUS_NOT_IMPLEMENTED;
1242 netr_NETRLOGONSETSERVICEBITS
1244 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1245 struct netr_NETRLOGONSETSERVICEBITS *r)
1247 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1252 netr_LogonGetTrustRid
1254 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1255 struct netr_LogonGetTrustRid *r)
1257 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1262 netr_NETRLOGONCOMPUTESERVERDIGEST
1264 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1265 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1267 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1272 netr_NETRLOGONCOMPUTECLIENTDIGEST
1274 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1275 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1277 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1283 netr_DsRGetSiteName
1285 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1286 struct netr_DsRGetSiteName *r)
1288 struct ldb_context *sam_ctx;
1289 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1291 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1292 dce_call->conn->auth_state.session_info, 0);
1293 if (sam_ctx == NULL) {
1294 return WERR_DS_UNAVAILABLE;
1297 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1298 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1300 return WERR_OK;
1305 fill in a netr_OneDomainInfo from a ldb search result
1307 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1308 struct loadparm_context *lp_ctx,
1309 struct ldb_context *sam_ctx,
1310 struct ldb_message *res,
1311 struct netr_OneDomainInfo *info,
1312 bool is_local, bool is_trust_list)
1314 ZERO_STRUCTP(info);
1316 if (is_trust_list) {
1317 /* w2k8 only fills this on trusted domains */
1318 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1319 info->trust_extension.length = 16;
1320 info->trust_extension.info->flags =
1321 NETR_TRUST_FLAG_TREEROOT |
1322 NETR_TRUST_FLAG_IN_FOREST |
1323 NETR_TRUST_FLAG_PRIMARY |
1324 NETR_TRUST_FLAG_NATIVE;
1326 info->trust_extension.info->parent_index = 0; /* should be index into array
1327 of parent */
1328 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1329 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1332 if (is_trust_list) {
1333 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1334 info->dns_forestname.string = NULL;
1335 } else {
1336 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1337 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1338 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1339 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1342 if (is_local) {
1343 info->domainname.string = lpcfg_workgroup(lp_ctx);
1344 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1345 info->domain_guid = samdb_result_guid(res, "objectGUID");
1346 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1347 } else {
1348 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1349 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1350 info->domain_guid = samdb_result_guid(res, "objectGUID");
1351 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1353 if (!is_trust_list) {
1354 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1357 return NT_STATUS_OK;
1361 netr_LogonGetDomainInfo
1362 this is called as part of the ADS domain logon procedure.
1364 It has an important role in convaying details about the client, such
1365 as Operating System, Version, Service Pack etc.
1367 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1368 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1370 struct netlogon_creds_CredentialState *creds;
1371 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1372 "securityIdentifier", "trustPartner", NULL };
1373 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1374 "msDS-SupportedEncryptionTypes", NULL };
1375 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1376 struct ldb_context *sam_ctx;
1377 struct ldb_message **res1, **res2, **res3, *new_msg;
1378 struct ldb_dn *workstation_dn;
1379 struct netr_DomainInformation *domain_info;
1380 struct netr_LsaPolicyInformation *lsa_policy_info;
1381 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1382 bool update_dns_hostname = true;
1383 int ret, ret3, i;
1384 NTSTATUS status;
1386 status = dcesrv_netr_creds_server_step_check(dce_call,
1387 mem_ctx,
1388 r->in.computer_name,
1389 r->in.credential,
1390 r->out.return_authenticator,
1391 &creds);
1392 if (!NT_STATUS_IS_OK(status)) {
1393 DEBUG(0,(__location__ " Bad credentials - error\n"));
1395 NT_STATUS_NOT_OK_RETURN(status);
1397 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1398 dce_call->conn->dce_ctx->lp_ctx,
1399 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1400 if (sam_ctx == NULL) {
1401 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1404 switch (r->in.level) {
1405 case 1: /* Domain information */
1407 if (r->in.query->workstation_info == NULL) {
1408 return NT_STATUS_INVALID_PARAMETER;
1411 /* Prepares the workstation DN */
1412 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1413 dom_sid_string(mem_ctx, creds->sid));
1414 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1416 /* Lookup for attributes in workstation object */
1417 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1418 attrs2);
1419 if (ret != 1) {
1420 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1423 /* Gets the sam account name which is checked against the DNS
1424 * hostname parameter. */
1425 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1426 "sAMAccountName",
1427 NULL);
1428 if (sam_account_name == NULL) {
1429 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1433 * Checks that the sam account name without a possible "$"
1434 * matches as prefix with the DNS hostname in the workstation
1435 * info structure.
1437 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1438 strcspn(sam_account_name, "$"));
1439 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1440 if (r->in.query->workstation_info->dns_hostname != NULL) {
1441 prefix2 = talloc_strndup(mem_ctx,
1442 r->in.query->workstation_info->dns_hostname,
1443 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1444 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1446 if (strcasecmp(prefix1, prefix2) != 0) {
1447 update_dns_hostname = false;
1449 } else {
1450 update_dns_hostname = false;
1453 /* Gets the old DNS hostname */
1454 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1455 "dNSHostName",
1456 NULL);
1459 * Updates the DNS hostname when the client wishes that the
1460 * server should handle this for him
1461 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1462 * obviously only checked when we do already have a
1463 * "dNSHostName".
1464 * See MS-NRPC section 3.5.4.3.9
1466 if ((old_dns_hostname != NULL) &&
1467 (r->in.query->workstation_info->workstation_flags
1468 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1469 update_dns_hostname = false;
1472 /* Gets host information and put them into our directory */
1474 new_msg = ldb_msg_new(mem_ctx);
1475 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1477 new_msg->dn = workstation_dn;
1479 /* Sets the OS name */
1481 if (r->in.query->workstation_info->os_name.string == NULL) {
1482 return NT_STATUS_INVALID_PARAMETER;
1485 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1486 r->in.query->workstation_info->os_name.string);
1487 if (ret != LDB_SUCCESS) {
1488 return NT_STATUS_NO_MEMORY;
1492 * Sets information from "os_version". On an empty structure
1493 * the values are cleared.
1495 if (r->in.query->workstation_info->os_version.os != NULL) {
1496 struct netr_OsVersionInfoEx *os_version;
1497 const char *os_version_str;
1499 os_version = &r->in.query->workstation_info->os_version.os->os;
1501 if (os_version->CSDVersion == NULL) {
1502 return NT_STATUS_INVALID_PARAMETER;
1505 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1506 os_version->MajorVersion,
1507 os_version->MinorVersion,
1508 os_version->BuildNumber);
1509 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1511 ret = ldb_msg_add_string(new_msg,
1512 "operatingSystemServicePack",
1513 os_version->CSDVersion);
1514 if (ret != LDB_SUCCESS) {
1515 return NT_STATUS_NO_MEMORY;
1518 ret = ldb_msg_add_string(new_msg,
1519 "operatingSystemVersion",
1520 os_version_str);
1521 if (ret != LDB_SUCCESS) {
1522 return NT_STATUS_NO_MEMORY;
1524 } else {
1525 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1526 "operatingSystemServicePack");
1527 if (ret != LDB_SUCCESS) {
1528 return NT_STATUS_NO_MEMORY;
1531 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1532 "operatingSystemVersion");
1533 if (ret != LDB_SUCCESS) {
1534 return NT_STATUS_NO_MEMORY;
1539 * If the boolean "update_dns_hostname" remained true, then we
1540 * are fine to start the update.
1542 if (update_dns_hostname) {
1543 ret = ldb_msg_add_string(new_msg,
1544 "dNSHostname",
1545 r->in.query->workstation_info->dns_hostname);
1546 if (ret != LDB_SUCCESS) {
1547 return NT_STATUS_NO_MEMORY;
1550 /* This manual "servicePrincipalName" generation is
1551 * still needed! Since the update in the samldb LDB
1552 * module does only work if the entries already exist
1553 * which isn't always the case. */
1554 ret = ldb_msg_add_string(new_msg,
1555 "servicePrincipalName",
1556 talloc_asprintf(new_msg, "HOST/%s",
1557 r->in.computer_name));
1558 if (ret != LDB_SUCCESS) {
1559 return NT_STATUS_NO_MEMORY;
1562 ret = ldb_msg_add_string(new_msg,
1563 "servicePrincipalName",
1564 talloc_asprintf(new_msg, "HOST/%s",
1565 r->in.query->workstation_info->dns_hostname));
1566 if (ret != LDB_SUCCESS) {
1567 return NT_STATUS_NO_MEMORY;
1571 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1572 DEBUG(3,("Impossible to update samdb: %s\n",
1573 ldb_errstring(sam_ctx)));
1576 talloc_free(new_msg);
1578 /* Writes back the domain information */
1580 /* We need to do two searches. The first will pull our primary
1581 domain and the second will pull any trusted domains. Our
1582 primary domain is also a "trusted" domain, so we need to
1583 put the primary domain into the lists of returned trusts as
1584 well. */
1585 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1586 &res2, attrs);
1587 if (ret != 1) {
1588 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1591 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1592 "(objectClass=trustedDomain)");
1593 if (ret3 == -1) {
1594 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1597 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1598 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1600 ZERO_STRUCTP(domain_info);
1602 /* Informations about the local and trusted domains */
1604 status = fill_one_domain_info(mem_ctx,
1605 dce_call->conn->dce_ctx->lp_ctx,
1606 sam_ctx, res2[0], &domain_info->primary_domain,
1607 true, false);
1608 NT_STATUS_NOT_OK_RETURN(status);
1610 domain_info->trusted_domain_count = ret3 + 1;
1611 domain_info->trusted_domains = talloc_array(mem_ctx,
1612 struct netr_OneDomainInfo,
1613 domain_info->trusted_domain_count);
1614 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1616 for (i=0;i<ret3;i++) {
1617 status = fill_one_domain_info(mem_ctx,
1618 dce_call->conn->dce_ctx->lp_ctx,
1619 sam_ctx, res3[i],
1620 &domain_info->trusted_domains[i],
1621 false, true);
1622 NT_STATUS_NOT_OK_RETURN(status);
1625 status = fill_one_domain_info(mem_ctx,
1626 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1627 &domain_info->trusted_domains[i], true, true);
1628 NT_STATUS_NOT_OK_RETURN(status);
1630 /* Sets the supported encryption types */
1631 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1632 "msDS-SupportedEncryptionTypes",
1633 default_supported_enc_types);
1635 /* Other host domain information */
1637 lsa_policy_info = talloc(mem_ctx,
1638 struct netr_LsaPolicyInformation);
1639 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1640 ZERO_STRUCTP(lsa_policy_info);
1642 domain_info->lsa_policy = *lsa_policy_info;
1644 /* The DNS hostname is only returned back when there is a chance
1645 * for a change. */
1646 if ((r->in.query->workstation_info->workstation_flags
1647 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1648 domain_info->dns_hostname.string = old_dns_hostname;
1649 } else {
1650 domain_info->dns_hostname.string = NULL;
1653 domain_info->workstation_flags =
1654 r->in.query->workstation_info->workstation_flags;
1656 r->out.info->domain_info = domain_info;
1657 break;
1658 case 2: /* LSA policy information - not used at the moment */
1659 lsa_policy_info = talloc(mem_ctx,
1660 struct netr_LsaPolicyInformation);
1661 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1662 ZERO_STRUCTP(lsa_policy_info);
1664 r->out.info->lsa_policy_info = lsa_policy_info;
1665 break;
1666 default:
1667 return NT_STATUS_INVALID_LEVEL;
1668 break;
1671 return NT_STATUS_OK;
1676 netr_ServerPasswordGet
1678 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1679 struct netr_ServerPasswordGet *r)
1681 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1686 netr_NETRLOGONSENDTOSAM
1688 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1689 struct netr_NETRLOGONSENDTOSAM *r)
1691 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1696 netr_DsRGetDCNameEx2
1698 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1699 TALLOC_CTX *mem_ctx,
1700 struct netr_DsRGetDCNameEx2 *r)
1702 struct ldb_context *sam_ctx;
1703 struct netr_DsRGetDCNameInfo *info;
1704 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1705 const struct tsocket_address *remote_address;
1706 char *addr = NULL;
1707 const char *server_site_name;
1708 char *guid_str;
1709 struct netlogon_samlogon_response response;
1710 NTSTATUS status;
1711 const char *dc_name = NULL;
1712 const char *domain_name = NULL;
1714 ZERO_STRUCTP(r->out.info);
1716 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1717 dce_call->conn->auth_state.session_info, 0);
1718 if (sam_ctx == NULL) {
1719 return WERR_DS_UNAVAILABLE;
1722 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1723 if (tsocket_address_is_inet(remote_address, "ip")) {
1724 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1725 W_ERROR_HAVE_NO_MEMORY(addr);
1728 /* "server_unc" is ignored by w2k3 */
1730 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1731 return WERR_INVALID_FLAGS;
1734 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1735 r->in.flags & DS_PDC_REQUIRED &&
1736 r->in.flags & DS_KDC_REQUIRED) {
1737 return WERR_INVALID_FLAGS;
1739 if (r->in.flags & DS_IS_FLAT_NAME &&
1740 r->in.flags & DS_IS_DNS_NAME) {
1741 return WERR_INVALID_FLAGS;
1743 if (r->in.flags & DS_RETURN_DNS_NAME &&
1744 r->in.flags & DS_RETURN_FLAT_NAME) {
1745 return WERR_INVALID_FLAGS;
1747 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1748 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1749 return WERR_INVALID_FLAGS;
1752 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1753 r->in.flags &
1754 (DS_DIRECTORY_SERVICE_REQUIRED |
1755 DS_DIRECTORY_SERVICE_PREFERRED |
1756 DS_GC_SERVER_REQUIRED |
1757 DS_PDC_REQUIRED |
1758 DS_KDC_REQUIRED)) {
1759 return WERR_INVALID_FLAGS;
1762 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1763 r->in.site_name) {
1764 return WERR_INVALID_FLAGS;
1767 /* Proof server site parameter "site_name" if it was specified */
1768 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1769 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1770 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1771 server_site_name) != 0)) {
1772 return WERR_NO_SUCH_DOMAIN;
1775 guid_str = r->in.domain_guid != NULL ?
1776 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1778 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1779 r->in.domain_name,
1780 r->in.domain_name,
1781 NULL, guid_str,
1782 r->in.client_account,
1783 r->in.mask, addr,
1784 NETLOGON_NT_VERSION_5EX_WITH_IP,
1785 lp_ctx, &response, true);
1786 if (!NT_STATUS_IS_OK(status)) {
1787 return ntstatus_to_werror(status);
1790 if (r->in.flags & DS_RETURN_DNS_NAME) {
1791 dc_name = response.data.nt5_ex.pdc_dns_name;
1792 domain_name = response.data.nt5_ex.dns_domain;
1793 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1794 dc_name = response.data.nt5_ex.pdc_name;
1795 domain_name = response.data.nt5_ex.domain_name;
1796 } else {
1799 * TODO: autodetect what we need to return
1800 * based on the given arguments
1802 dc_name = response.data.nt5_ex.pdc_name;
1803 domain_name = response.data.nt5_ex.domain_name;
1806 if (!dc_name || !dc_name[0]) {
1807 return WERR_NO_SUCH_DOMAIN;
1810 if (!domain_name || !domain_name[0]) {
1811 return WERR_NO_SUCH_DOMAIN;
1814 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1815 W_ERROR_HAVE_NO_MEMORY(info);
1816 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1817 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1818 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1819 response.data.nt5_ex.sockaddr.pdc_ip);
1820 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1821 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1822 info->domain_guid = response.data.nt5_ex.domain_uuid;
1823 info->domain_name = domain_name;
1824 info->forest_name = response.data.nt5_ex.forest;
1825 info->dc_flags = response.data.nt5_ex.server_type;
1826 info->dc_site_name = response.data.nt5_ex.server_site;
1827 info->client_site_name = response.data.nt5_ex.client_site;
1829 *r->out.info = info;
1831 return WERR_OK;
1835 netr_DsRGetDCNameEx
1837 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1838 struct netr_DsRGetDCNameEx *r)
1840 struct netr_DsRGetDCNameEx2 r2;
1841 WERROR werr;
1843 ZERO_STRUCT(r2);
1845 r2.in.server_unc = r->in.server_unc;
1846 r2.in.client_account = NULL;
1847 r2.in.mask = 0;
1848 r2.in.domain_guid = r->in.domain_guid;
1849 r2.in.domain_name = r->in.domain_name;
1850 r2.in.site_name = r->in.site_name;
1851 r2.in.flags = r->in.flags;
1852 r2.out.info = r->out.info;
1854 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1856 return werr;
1860 netr_DsRGetDCName
1862 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1863 struct netr_DsRGetDCName *r)
1865 struct netr_DsRGetDCNameEx2 r2;
1866 WERROR werr;
1868 ZERO_STRUCT(r2);
1870 r2.in.server_unc = r->in.server_unc;
1871 r2.in.client_account = NULL;
1872 r2.in.mask = 0;
1873 r2.in.domain_name = r->in.domain_name;
1874 r2.in.domain_guid = r->in.domain_guid;
1876 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1877 r2.in.flags = r->in.flags;
1878 r2.out.info = r->out.info;
1880 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1882 return werr;
1885 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1887 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1888 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1890 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1895 netr_NetrEnumerateTrustedDomainsEx
1897 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1898 struct netr_NetrEnumerateTrustedDomainsEx *r)
1900 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1905 netr_DsRAddressToSitenamesExW
1907 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1908 struct netr_DsRAddressToSitenamesExW *r)
1910 struct ldb_context *sam_ctx;
1911 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1912 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1913 sa_family_t sin_family;
1914 struct sockaddr_in *addr;
1915 #ifdef HAVE_IPV6
1916 struct sockaddr_in6 *addr6;
1917 char addr_str[INET6_ADDRSTRLEN];
1918 #else
1919 char addr_str[INET_ADDRSTRLEN];
1920 #endif
1921 char *subnet_name;
1922 const char *res;
1923 uint32_t i;
1925 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1926 dce_call->conn->auth_state.session_info, 0);
1927 if (sam_ctx == NULL) {
1928 return WERR_DS_UNAVAILABLE;
1931 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1932 W_ERROR_HAVE_NO_MEMORY(ctr);
1934 *r->out.ctr = ctr;
1936 ctr->count = r->in.count;
1937 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1938 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1939 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1940 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1942 for (i=0; i<ctr->count; i++) {
1943 ctr->sitename[i].string = NULL;
1944 ctr->subnetname[i].string = NULL;
1946 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1947 continue;
1949 /* The first two byte of the buffer are reserved for the
1950 * "sin_family" but for now only the first one is used. */
1951 sin_family = r->in.addresses[i].buffer[0];
1953 switch (sin_family) {
1954 case AF_INET:
1955 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1956 continue;
1958 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1959 res = inet_ntop(AF_INET, &addr->sin_addr,
1960 addr_str, sizeof(addr_str));
1961 break;
1962 #ifdef HAVE_IPV6
1963 case AF_INET6:
1964 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1965 continue;
1967 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1968 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1969 addr_str, sizeof(addr_str));
1970 break;
1971 #endif
1972 default:
1973 continue;
1976 if (res == NULL) {
1977 continue;
1980 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1981 mem_ctx,
1982 addr_str,
1983 &subnet_name);
1984 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1985 ctr->subnetname[i].string = subnet_name;
1988 return WERR_OK;
1993 netr_DsRAddressToSitenamesW
1995 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1996 struct netr_DsRAddressToSitenamesW *r)
1998 struct netr_DsRAddressToSitenamesExW r2;
1999 struct netr_DsRAddressToSitenamesWCtr *ctr;
2000 uint32_t i;
2001 WERROR werr;
2003 ZERO_STRUCT(r2);
2005 r2.in.server_name = r->in.server_name;
2006 r2.in.count = r->in.count;
2007 r2.in.addresses = r->in.addresses;
2009 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2010 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2012 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2013 W_ERROR_HAVE_NO_MEMORY(ctr);
2015 *r->out.ctr = ctr;
2017 ctr->count = r->in.count;
2018 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2019 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2021 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2023 for (i=0; i<ctr->count; i++) {
2024 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2027 return werr;
2032 netr_DsrGetDcSiteCoverageW
2034 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2035 struct netr_DsrGetDcSiteCoverageW *r)
2037 struct ldb_context *sam_ctx;
2038 struct DcSitesCtr *ctr;
2039 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2041 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2042 dce_call->conn->auth_state.session_info, 0);
2043 if (sam_ctx == NULL) {
2044 return WERR_DS_UNAVAILABLE;
2047 ctr = talloc(mem_ctx, struct DcSitesCtr);
2048 W_ERROR_HAVE_NO_MEMORY(ctr);
2050 *r->out.ctr = ctr;
2052 /* For now only return our default site */
2053 ctr->num_sites = 1;
2054 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2055 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2056 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2057 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2059 return WERR_OK;
2063 #define GET_CHECK_STR(dest, mem, msg, attr) \
2064 do {\
2065 const char *s; \
2066 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
2067 if (!s) { \
2068 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
2069 "without flatname\n", \
2070 ldb_dn_get_linearized(msg->dn))); \
2071 continue; \
2073 dest = talloc_strdup(mem, s); \
2074 W_ERROR_HAVE_NO_MEMORY(dest); \
2075 } while(0)
2078 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2079 struct ldb_context *sam_ctx,
2080 struct netr_DomainTrustList *trusts,
2081 uint32_t trust_flags)
2083 struct ldb_dn *system_dn;
2084 struct ldb_message **dom_res = NULL;
2085 const char *trust_attrs[] = { "flatname", "trustPartner",
2086 "securityIdentifier", "trustDirection",
2087 "trustType", "trustAttributes", NULL };
2088 uint32_t n;
2089 int i;
2090 int ret;
2092 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2093 NETR_TRUST_FLAG_OUTBOUND))) {
2094 return WERR_INVALID_FLAGS;
2097 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2098 ldb_get_default_basedn(sam_ctx),
2099 "(&(objectClass=container)(cn=System))");
2100 if (!system_dn) {
2101 return WERR_GENERAL_FAILURE;
2104 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2105 &dom_res, trust_attrs,
2106 "(objectclass=trustedDomain)");
2108 for (i = 0; i < ret; i++) {
2109 unsigned int trust_dir;
2110 uint32_t flags = 0;
2112 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2113 "trustDirection", 0);
2115 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2116 flags |= NETR_TRUST_FLAG_INBOUND;
2118 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2119 flags |= NETR_TRUST_FLAG_OUTBOUND;
2122 if (!(flags & trust_flags)) {
2123 /* this trust direction was not requested */
2124 continue;
2127 n = trusts->count;
2128 trusts->array = talloc_realloc(trusts, trusts->array,
2129 struct netr_DomainTrust,
2130 n + 1);
2131 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2133 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2134 dom_res[i], "flatname");
2135 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2136 dom_res[i], "trustPartner");
2138 trusts->array[n].trust_flags = flags;
2139 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2140 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2141 /* TODO: find if we have parent in the list */
2142 trusts->array[n].parent_index = 0;
2145 trusts->array[n].trust_type =
2146 ldb_msg_find_attr_as_uint(dom_res[i],
2147 "trustType", 0);
2148 trusts->array[n].trust_attributes =
2149 ldb_msg_find_attr_as_uint(dom_res[i],
2150 "trustAttributes", 0);
2152 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2153 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2154 struct dom_sid zero_sid;
2155 ZERO_STRUCT(zero_sid);
2156 trusts->array[n].sid =
2157 dom_sid_dup(trusts, &zero_sid);
2158 } else {
2159 trusts->array[n].sid =
2160 samdb_result_dom_sid(trusts, dom_res[i],
2161 "securityIdentifier");
2163 trusts->array[n].guid = GUID_zero();
2165 trusts->count = n + 1;
2168 talloc_free(dom_res);
2169 return WERR_OK;
2173 netr_DsrEnumerateDomainTrusts
2175 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2176 TALLOC_CTX *mem_ctx,
2177 struct netr_DsrEnumerateDomainTrusts *r)
2179 struct netr_DomainTrustList *trusts;
2180 struct ldb_context *sam_ctx;
2181 int ret;
2182 struct ldb_message **dom_res;
2183 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2184 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2185 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2186 const char *p;
2187 WERROR werr;
2189 if (r->in.trust_flags & 0xFFFFFE00) {
2190 return WERR_INVALID_FLAGS;
2193 /* TODO: turn to hard check once we are sure this is 100% correct */
2194 if (!r->in.server_name) {
2195 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2196 "But received NULL!\n", dnsdomain));
2197 } else {
2198 p = strchr(r->in.server_name, '.');
2199 if (!p) {
2200 DEBUG(3, ("Invalid domain! Expected name in domain "
2201 "[%s]. But received [%s]!\n",
2202 dnsdomain, r->in.server_name));
2203 p = r->in.server_name;
2204 } else {
2205 p++;
2207 if (strcasecmp(p, dnsdomain)) {
2208 DEBUG(3, ("Invalid domain! Expected name in domain "
2209 "[%s]. But received [%s]!\n",
2210 dnsdomain, r->in.server_name));
2214 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2215 W_ERROR_HAVE_NO_MEMORY(trusts);
2217 trusts->count = 0;
2218 r->out.trusts = trusts;
2220 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2221 dce_call->conn->auth_state.session_info, 0);
2222 if (sam_ctx == NULL) {
2223 return WERR_GENERAL_FAILURE;
2226 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2227 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2229 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2230 trusts, r->in.trust_flags);
2231 W_ERROR_NOT_OK_RETURN(werr);
2234 /* NOTE: we currently are always the root of the forest */
2235 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2236 uint32_t n = trusts->count;
2238 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2239 &dom_res, dom_attrs);
2240 if (ret != 1) {
2241 return WERR_GENERAL_FAILURE;
2244 trusts->count = n + 1;
2245 trusts->array = talloc_realloc(trusts, trusts->array,
2246 struct netr_DomainTrust,
2247 trusts->count);
2248 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2250 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2251 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2252 trusts->array[n].trust_flags =
2253 NETR_TRUST_FLAG_NATIVE |
2254 NETR_TRUST_FLAG_TREEROOT |
2255 NETR_TRUST_FLAG_IN_FOREST |
2256 NETR_TRUST_FLAG_PRIMARY;
2257 /* we are always the root domain for now */
2258 trusts->array[n].parent_index = 0;
2259 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2260 trusts->array[n].trust_attributes = 0;
2261 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2262 dom_res[0],
2263 "objectSid");
2264 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2265 "objectGUID");
2266 talloc_free(dom_res);
2269 return WERR_OK;
2274 netr_DsrDeregisterDNSHostRecords
2276 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2277 struct netr_DsrDeregisterDNSHostRecords *r)
2279 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2284 netr_ServerTrustPasswordsGet
2286 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2287 struct netr_ServerTrustPasswordsGet *r)
2289 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2293 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2294 struct ldb_context *sam_ctx,
2295 struct loadparm_context *lp_ctx,
2296 struct lsa_ForestTrustInformation *info)
2298 struct lsa_ForestTrustDomainInfo *domain_info;
2299 struct lsa_ForestTrustRecord *e;
2300 struct ldb_message **dom_res;
2301 const char * const dom_attrs[] = { "objectSid", NULL };
2302 int ret;
2304 /* we need to provide 2 entries:
2305 * 1. the Root Forest name
2306 * 2. the Domain Information
2309 info->count = 2;
2310 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2311 W_ERROR_HAVE_NO_MEMORY(info->entries);
2313 /* Forest root info */
2314 e = talloc(info, struct lsa_ForestTrustRecord);
2315 W_ERROR_HAVE_NO_MEMORY(e);
2317 e->flags = 0;
2318 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2319 e->time = 0; /* so far always 0 in trces. */
2320 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2321 mem_ctx);
2322 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2324 info->entries[0] = e;
2326 /* Domain info */
2327 e = talloc(info, struct lsa_ForestTrustRecord);
2328 W_ERROR_HAVE_NO_MEMORY(e);
2330 /* get our own domain info */
2331 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2332 if (ret != 1) {
2333 return WERR_GENERAL_FAILURE;
2336 /* TODO: check if disabled and set flags accordingly */
2337 e->flags = 0;
2338 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2339 e->time = 0; /* so far always 0 in traces. */
2341 domain_info = &e->forest_trust_data.domain_info;
2342 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2343 "objectSid");
2344 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2345 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2347 info->entries[1] = e;
2349 talloc_free(dom_res);
2351 return WERR_OK;
2355 netr_DsRGetForestTrustInformation
2357 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2358 TALLOC_CTX *mem_ctx,
2359 struct netr_DsRGetForestTrustInformation *r)
2361 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2362 struct lsa_ForestTrustInformation *info, **info_ptr;
2363 struct ldb_context *sam_ctx;
2364 WERROR werr;
2366 if (r->in.flags & 0xFFFFFFFE) {
2367 return WERR_INVALID_FLAGS;
2370 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2371 dce_call->conn->auth_state.session_info, 0);
2372 if (sam_ctx == NULL) {
2373 return WERR_GENERAL_FAILURE;
2376 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2377 if (!samdb_is_pdc(sam_ctx)) {
2378 return WERR_NERR_NOTPRIMARY;
2381 if (r->in.trusted_domain_name == NULL) {
2382 return WERR_INVALID_FLAGS;
2385 /* TODO: establish an schannel connection with
2386 * r->in.trusted_domain_name and perform a
2387 * netr_GetForestTrustInformation call against it */
2389 /* for now return not implementd */
2390 return WERR_CALL_NOT_IMPLEMENTED;
2393 /* TODO: check r->in.server_name is our name */
2395 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2396 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2398 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2399 W_ERROR_HAVE_NO_MEMORY(info);
2401 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2402 W_ERROR_NOT_OK_RETURN(werr);
2404 *info_ptr = info;
2405 r->out.forest_trust_info = info_ptr;
2407 return WERR_OK;
2412 netr_GetForestTrustInformation
2414 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2415 TALLOC_CTX *mem_ctx,
2416 struct netr_GetForestTrustInformation *r)
2418 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2419 struct netlogon_creds_CredentialState *creds;
2420 struct lsa_ForestTrustInformation *info, **info_ptr;
2421 struct ldb_context *sam_ctx;
2422 NTSTATUS status;
2423 WERROR werr;
2425 status = dcesrv_netr_creds_server_step_check(dce_call,
2426 mem_ctx,
2427 r->in.computer_name,
2428 r->in.credential,
2429 r->out.return_authenticator,
2430 &creds);
2431 if (!NT_STATUS_IS_OK(status)) {
2432 return status;
2435 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2436 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2437 return NT_STATUS_NOT_IMPLEMENTED;
2440 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2441 dce_call->conn->auth_state.session_info, 0);
2442 if (sam_ctx == NULL) {
2443 return NT_STATUS_UNSUCCESSFUL;
2446 /* TODO: check r->in.server_name is our name */
2448 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2449 if (!info_ptr) {
2450 return NT_STATUS_NO_MEMORY;
2452 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2453 if (!info) {
2454 return NT_STATUS_NO_MEMORY;
2457 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2458 if (!W_ERROR_IS_OK(werr)) {
2459 return werror_to_ntstatus(werr);
2462 *info_ptr = info;
2463 r->out.forest_trust_info = info_ptr;
2465 return NT_STATUS_OK;
2470 netr_ServerGetTrustInfo
2472 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2473 struct netr_ServerGetTrustInfo *r)
2475 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2479 netr_Unused47
2481 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2482 struct netr_Unused47 *r)
2484 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2488 struct netr_dnsupdate_RODC_state {
2489 struct dcesrv_call_state *dce_call;
2490 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2491 struct dnsupdate_RODC *r2;
2495 called when the forwarded RODC dns update request is finished
2497 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2499 struct netr_dnsupdate_RODC_state *st =
2500 tevent_req_callback_data(subreq,
2501 struct netr_dnsupdate_RODC_state);
2502 NTSTATUS status;
2504 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2505 TALLOC_FREE(subreq);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2508 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2511 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2513 status = dcesrv_reply(st->dce_call);
2514 if (!NT_STATUS_IS_OK(status)) {
2515 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2520 netr_DsrUpdateReadOnlyServerDnsRecords
2522 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2523 TALLOC_CTX *mem_ctx,
2524 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2526 struct netlogon_creds_CredentialState *creds;
2527 NTSTATUS nt_status;
2528 struct dcerpc_binding_handle *binding_handle;
2529 struct netr_dnsupdate_RODC_state *st;
2530 struct tevent_req *subreq;
2532 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2533 mem_ctx,
2534 r->in.computer_name,
2535 r->in.credential,
2536 r->out.return_authenticator,
2537 &creds);
2538 NT_STATUS_NOT_OK_RETURN(nt_status);
2540 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2541 return NT_STATUS_ACCESS_DENIED;
2544 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2545 NT_STATUS_HAVE_NO_MEMORY(st);
2547 st->dce_call = dce_call;
2548 st->r = r;
2549 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2550 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2552 st->r2->in.dom_sid = creds->sid;
2553 st->r2->in.site_name = r->in.site_name;
2554 st->r2->in.dns_ttl = r->in.dns_ttl;
2555 st->r2->in.dns_names = r->in.dns_names;
2556 st->r2->out.dns_names = r->out.dns_names;
2558 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2559 "dnsupdate", &ndr_table_irpc);
2560 if (binding_handle == NULL) {
2561 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2562 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2563 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2566 /* forward the call */
2567 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2568 binding_handle, st->r2);
2569 NT_STATUS_HAVE_NO_MEMORY(subreq);
2571 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2573 /* setup the callback */
2574 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2576 return NT_STATUS_OK;
2580 /* include the generated boilerplate */
2581 #include "librpc/gen_ndr/ndr_netlogon_s.c"