s4:netlogon: correctly calculate the negotiate_flags
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob8cba3e39069f53c3475b05b737c94e9bfb5c310d
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 "dsdb/samdb/ldb_modules/util.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;
94 uint32_t server_flags = 0;
95 uint32_t negotiate_flags = 0;
97 ZERO_STRUCTP(r->out.return_credentials);
98 *r->out.rid = 0;
100 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
101 NETLOGON_NEG_PERSISTENT_SAMREPL |
102 NETLOGON_NEG_ARCFOUR |
103 NETLOGON_NEG_PROMOTION_COUNT |
104 NETLOGON_NEG_CHANGELOG_BDC |
105 NETLOGON_NEG_FULL_SYNC_REPL |
106 NETLOGON_NEG_MULTIPLE_SIDS |
107 NETLOGON_NEG_REDO |
108 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
109 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
110 NETLOGON_NEG_GENERIC_PASSTHROUGH |
111 NETLOGON_NEG_CONCURRENT_RPC |
112 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
113 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
114 NETLOGON_NEG_STRONG_KEYS |
115 NETLOGON_NEG_TRANSITIVE_TRUSTS |
116 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
117 NETLOGON_NEG_PASSWORD_SET2 |
118 NETLOGON_NEG_GETDOMAININFO |
119 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
120 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
121 NETLOGON_NEG_RODC_PASSTHROUGH |
122 NETLOGON_NEG_SUPPORTS_AES |
123 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
124 NETLOGON_NEG_AUTHENTICATED_RPC;
126 negotiate_flags = *r->in.negotiate_flags & server_flags;
129 * According to Microsoft (see bugid #6099)
130 * Windows 7 looks at the negotiate_flags
131 * returned in this structure *even if the
132 * call fails with access denied!
134 *r->out.negotiate_flags = negotiate_flags;
136 switch (r->in.secure_channel_type) {
137 case SEC_CHAN_WKSTA:
138 case SEC_CHAN_DNS_DOMAIN:
139 case SEC_CHAN_DOMAIN:
140 case SEC_CHAN_BDC:
141 case SEC_CHAN_RODC:
142 break;
143 default:
144 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
145 r->in.secure_channel_type));
146 return NT_STATUS_INVALID_PARAMETER;
149 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
150 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
151 if (sam_ctx == NULL) {
152 return NT_STATUS_INVALID_SYSTEM_SERVICE;
155 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
156 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
157 const char *flatname;
158 if (!encoded_account) {
159 return NT_STATUS_NO_MEMORY;
162 /* Kill the trailing dot */
163 if (encoded_account[strlen(encoded_account)-1] == '.') {
164 encoded_account[strlen(encoded_account)-1] = '\0';
167 /* pull the user attributes */
168 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
169 trust_dom_attrs,
170 "(&(trustPartner=%s)(objectclass=trustedDomain))",
171 encoded_account);
173 if (num_records == 0) {
174 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
175 encoded_account));
176 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
179 if (num_records > 1) {
180 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
181 return NT_STATUS_INTERNAL_DB_CORRUPTION;
184 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
185 if (!flatname) {
186 /* No flatname for this trust - we can't proceed */
187 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
189 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
191 if (!account_name) {
192 return NT_STATUS_NO_MEMORY;
195 } else {
196 account_name = r->in.account_name;
199 /* pull the user attributes */
200 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
201 "(&(sAMAccountName=%s)(objectclass=user))",
202 ldb_binary_encode_string(mem_ctx, account_name));
204 if (num_records == 0) {
205 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
206 r->in.account_name));
207 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
210 if (num_records > 1) {
211 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
212 return NT_STATUS_INTERNAL_DB_CORRUPTION;
215 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
217 if (user_account_control & UF_ACCOUNTDISABLE) {
218 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
219 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
222 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
223 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
224 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) 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_DOMAIN ||
228 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
229 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
230 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
232 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
234 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
235 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
236 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
237 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
239 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
240 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
241 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
242 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
244 } else {
245 /* we should never reach this */
246 return NT_STATUS_INTERNAL_ERROR;
249 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
250 "objectSid", 0);
252 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
253 if (mach_pwd == NULL) {
254 return NT_STATUS_ACCESS_DENIED;
257 if (!pipe_state) {
258 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
259 return NT_STATUS_ACCESS_DENIED;
262 creds = netlogon_creds_server_init(mem_ctx,
263 r->in.account_name,
264 r->in.computer_name,
265 r->in.secure_channel_type,
266 &pipe_state->client_challenge,
267 &pipe_state->server_challenge,
268 mach_pwd,
269 r->in.credentials,
270 r->out.return_credentials,
271 negotiate_flags);
272 if (!creds) {
273 return NT_STATUS_ACCESS_DENIED;
276 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
278 nt_status = schannel_save_creds_state(mem_ctx,
279 dce_call->conn->dce_ctx->lp_ctx,
280 creds);
282 return nt_status;
285 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
286 struct netr_ServerAuthenticate *r)
288 struct netr_ServerAuthenticate3 a;
289 uint32_t rid;
290 /* TODO:
291 * negotiate_flags is used as an [in] parameter
292 * so it need to be initialised.
294 * (I think ... = 0; seems wrong here --metze)
296 uint32_t negotiate_flags_in = 0;
297 uint32_t negotiate_flags_out = 0;
299 a.in.server_name = r->in.server_name;
300 a.in.account_name = r->in.account_name;
301 a.in.secure_channel_type = r->in.secure_channel_type;
302 a.in.computer_name = r->in.computer_name;
303 a.in.credentials = r->in.credentials;
304 a.in.negotiate_flags = &negotiate_flags_in;
306 a.out.return_credentials = r->out.return_credentials;
307 a.out.rid = &rid;
308 a.out.negotiate_flags = &negotiate_flags_out;
310 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
313 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
314 struct netr_ServerAuthenticate2 *r)
316 struct netr_ServerAuthenticate3 r3;
317 uint32_t rid = 0;
319 r3.in.server_name = r->in.server_name;
320 r3.in.account_name = r->in.account_name;
321 r3.in.secure_channel_type = r->in.secure_channel_type;
322 r3.in.computer_name = r->in.computer_name;
323 r3.in.credentials = r->in.credentials;
324 r3.out.return_credentials = r->out.return_credentials;
325 r3.in.negotiate_flags = r->in.negotiate_flags;
326 r3.out.negotiate_flags = r->out.negotiate_flags;
327 r3.out.rid = &rid;
329 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
333 * NOTE: The following functions are nearly identical to the ones available in
334 * source3/rpc_server/srv_nelog_nt.c
335 * The reason we keep 2 copies is that they use different structures to
336 * represent the auth_info and the decrpc pipes.
340 * If schannel is required for this call test that it actually is available.
342 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
343 const char *computer_name,
344 bool integrity, bool privacy)
347 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
348 if (!privacy && !integrity) {
349 return NT_STATUS_OK;
352 if ((!privacy && integrity) &&
353 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
354 return NT_STATUS_OK;
357 if ((privacy || integrity) &&
358 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
359 return NT_STATUS_OK;
363 /* test didn't pass */
364 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
365 computer_name));
367 return NT_STATUS_ACCESS_DENIED;
370 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
371 TALLOC_CTX *mem_ctx,
372 const char *computer_name,
373 struct netr_Authenticator *received_authenticator,
374 struct netr_Authenticator *return_authenticator,
375 struct netlogon_creds_CredentialState **creds_out)
377 NTSTATUS nt_status;
378 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
379 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
381 if (schannel_global_required) {
382 nt_status = schannel_check_required(auth_info,
383 computer_name,
384 true, false);
385 if (!NT_STATUS_IS_OK(nt_status)) {
386 return nt_status;
390 nt_status = schannel_check_creds_state(mem_ctx,
391 dce_call->conn->dce_ctx->lp_ctx,
392 computer_name,
393 received_authenticator,
394 return_authenticator,
395 creds_out);
396 return nt_status;
400 Change the machine account password for the currently connected
401 client. Supplies only the NT#.
404 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
405 struct netr_ServerPasswordSet *r)
407 struct netlogon_creds_CredentialState *creds;
408 struct ldb_context *sam_ctx;
409 const char * const attrs[] = { "unicodePwd", NULL };
410 struct ldb_message **res;
411 struct samr_Password *oldNtHash;
412 NTSTATUS nt_status;
413 int ret;
415 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
416 mem_ctx,
417 r->in.computer_name,
418 r->in.credential, r->out.return_authenticator,
419 &creds);
420 NT_STATUS_NOT_OK_RETURN(nt_status);
422 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);
423 if (sam_ctx == NULL) {
424 return NT_STATUS_INVALID_SYSTEM_SERVICE;
427 netlogon_creds_des_decrypt(creds, r->in.new_password);
429 /* fetch the old password hashes (the NT hash has to exist) */
431 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
432 "(&(objectClass=user)(objectSid=%s))",
433 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
434 if (ret != 1) {
435 return NT_STATUS_WRONG_PASSWORD;
438 nt_status = samdb_result_passwords(mem_ctx,
439 dce_call->conn->dce_ctx->lp_ctx,
440 res[0], NULL, &oldNtHash);
441 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
442 return NT_STATUS_WRONG_PASSWORD;
445 /* Using the sid for the account as the key, set the password */
446 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
447 creds->sid,
448 NULL, /* Don't have plaintext */
449 NULL, r->in.new_password,
450 NULL, oldNtHash, /* Password change */
451 NULL, NULL);
452 return nt_status;
456 Change the machine account password for the currently connected
457 client. Supplies new plaintext.
459 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
460 struct netr_ServerPasswordSet2 *r)
462 struct netlogon_creds_CredentialState *creds;
463 struct ldb_context *sam_ctx;
464 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
465 struct ldb_message **res;
466 struct samr_Password *oldLmHash, *oldNtHash;
467 NTSTATUS nt_status;
468 DATA_BLOB new_password;
469 int ret;
471 struct samr_CryptPassword password_buf;
473 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
474 mem_ctx,
475 r->in.computer_name,
476 r->in.credential, r->out.return_authenticator,
477 &creds);
478 NT_STATUS_NOT_OK_RETURN(nt_status);
480 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);
481 if (sam_ctx == NULL) {
482 return NT_STATUS_INVALID_SYSTEM_SERVICE;
485 memcpy(password_buf.data, r->in.new_password->data, 512);
486 SIVAL(password_buf.data, 512, r->in.new_password->length);
488 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
489 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
490 } else {
491 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
494 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
495 DEBUG(3,("samr: failed to decode password buffer\n"));
496 return NT_STATUS_WRONG_PASSWORD;
499 /* fetch the old password hashes (at least one of both has to exist) */
501 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
502 "(&(objectClass=user)(objectSid=%s))",
503 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
504 if (ret != 1) {
505 return NT_STATUS_WRONG_PASSWORD;
508 nt_status = samdb_result_passwords(mem_ctx,
509 dce_call->conn->dce_ctx->lp_ctx,
510 res[0], &oldLmHash, &oldNtHash);
511 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
512 return NT_STATUS_WRONG_PASSWORD;
515 /* Using the sid for the account as the key, set the password */
516 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
517 creds->sid,
518 &new_password, /* we have plaintext */
519 NULL, NULL,
520 oldLmHash, oldNtHash, /* Password change */
521 NULL, NULL);
522 return nt_status;
527 netr_LogonUasLogon
529 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
530 struct netr_LogonUasLogon *r)
532 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
537 netr_LogonUasLogoff
539 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
540 struct netr_LogonUasLogoff *r)
542 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
546 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
548 switch (r->in.logon_level) {
549 case NetlogonInteractiveInformation:
550 case NetlogonServiceInformation:
551 case NetlogonInteractiveTransitiveInformation:
552 case NetlogonServiceTransitiveInformation:
553 if (r->in.logon->password == NULL) {
554 return NT_STATUS_INVALID_PARAMETER;
557 switch (r->in.validation_level) {
558 case NetlogonValidationSamInfo: /* 2 */
559 case NetlogonValidationSamInfo2: /* 3 */
560 case NetlogonValidationSamInfo4: /* 6 */
561 break;
562 default:
563 return NT_STATUS_INVALID_INFO_CLASS;
566 break;
567 case NetlogonNetworkInformation:
568 case NetlogonNetworkTransitiveInformation:
569 if (r->in.logon->network == NULL) {
570 return NT_STATUS_INVALID_PARAMETER;
573 switch (r->in.validation_level) {
574 case NetlogonValidationSamInfo: /* 2 */
575 case NetlogonValidationSamInfo2: /* 3 */
576 case NetlogonValidationSamInfo4: /* 6 */
577 break;
578 default:
579 return NT_STATUS_INVALID_INFO_CLASS;
582 break;
584 case NetlogonGenericInformation:
585 if (r->in.logon->generic == NULL) {
586 return NT_STATUS_INVALID_PARAMETER;
589 switch (r->in.validation_level) {
590 /* TODO: case NetlogonValidationGenericInfo: 4 */
591 case NetlogonValidationGenericInfo2: /* 5 */
592 break;
593 default:
594 return NT_STATUS_INVALID_INFO_CLASS;
597 break;
598 default:
599 return NT_STATUS_INVALID_PARAMETER;
602 return NT_STATUS_OK;
606 netr_LogonSamLogon_base
608 This version of the function allows other wrappers to say 'do not check the credentials'
610 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
612 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
613 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
615 struct auth4_context *auth_context;
616 struct auth_usersupplied_info *user_info;
617 struct auth_user_info_dc *user_info_dc;
618 NTSTATUS nt_status;
619 struct netr_SamBaseInfo *sam;
620 struct netr_SamInfo2 *sam2;
621 struct netr_SamInfo3 *sam3;
622 struct netr_SamInfo6 *sam6;
624 *r->out.authoritative = 1;
626 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
627 NT_STATUS_HAVE_NO_MEMORY(user_info);
629 netlogon_creds_decrypt_samlogon_logon(creds,
630 r->in.logon_level,
631 r->in.logon);
633 switch (r->in.logon_level) {
634 case NetlogonInteractiveInformation:
635 case NetlogonServiceInformation:
636 case NetlogonInteractiveTransitiveInformation:
637 case NetlogonServiceTransitiveInformation:
639 /* TODO: we need to deny anonymous access here */
640 nt_status = auth_context_create(mem_ctx,
641 dce_call->event_ctx, dce_call->msg_ctx,
642 dce_call->conn->dce_ctx->lp_ctx,
643 &auth_context);
644 NT_STATUS_NOT_OK_RETURN(nt_status);
646 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
647 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
648 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
649 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
651 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
652 user_info->password_state = AUTH_PASSWORD_HASH;
654 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
655 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
656 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
658 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
659 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
660 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
662 break;
663 case NetlogonNetworkInformation:
664 case NetlogonNetworkTransitiveInformation:
666 /* TODO: we need to deny anonymous access here */
667 nt_status = auth_context_create(mem_ctx,
668 dce_call->event_ctx, dce_call->msg_ctx,
669 dce_call->conn->dce_ctx->lp_ctx,
670 &auth_context);
671 NT_STATUS_NOT_OK_RETURN(nt_status);
673 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
674 NT_STATUS_NOT_OK_RETURN(nt_status);
676 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
677 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
678 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
679 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
681 user_info->password_state = AUTH_PASSWORD_RESPONSE;
682 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
683 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
685 break;
688 case NetlogonGenericInformation:
690 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
691 /* OK */
692 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
693 /* OK */
694 } else {
695 /* Using DES to verify kerberos tickets makes no sense */
696 return NT_STATUS_INVALID_PARAMETER;
699 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
700 NTSTATUS status;
701 struct dcerpc_binding_handle *irpc_handle;
702 struct kdc_check_generic_kerberos check;
703 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
704 NT_STATUS_HAVE_NO_MEMORY(generic);
705 *r->out.authoritative = 1;
707 /* TODO: Describe and deal with these flags */
708 *r->out.flags = 0;
710 r->out.validation->generic = generic;
712 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
713 dce_call->msg_ctx,
714 "kdc_server",
715 &ndr_table_irpc);
716 if (irpc_handle == NULL) {
717 return NT_STATUS_NO_LOGON_SERVERS;
720 check.in.generic_request =
721 data_blob_const(r->in.logon->generic->data,
722 r->in.logon->generic->length);
724 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
725 mem_ctx,
726 &check);
727 if (!NT_STATUS_IS_OK(status)) {
728 return status;
730 generic->length = check.out.generic_reply.length;
731 generic->data = check.out.generic_reply.data;
732 return NT_STATUS_OK;
735 /* Until we get an implemetnation of these other packages */
736 return NT_STATUS_INVALID_PARAMETER;
738 default:
739 return NT_STATUS_INVALID_PARAMETER;
742 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
743 /* TODO: set *r->out.authoritative = 0 on specific errors */
744 NT_STATUS_NOT_OK_RETURN(nt_status);
746 switch (r->in.validation_level) {
747 case 2:
748 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
749 NT_STATUS_NOT_OK_RETURN(nt_status);
751 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
752 NT_STATUS_HAVE_NO_MEMORY(sam2);
753 sam2->base = *sam;
755 /* And put into the talloc tree */
756 talloc_steal(sam2, sam);
757 r->out.validation->sam2 = sam2;
759 sam = &sam2->base;
760 break;
762 case 3:
763 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
764 user_info_dc,
765 &sam3);
766 NT_STATUS_NOT_OK_RETURN(nt_status);
768 r->out.validation->sam3 = sam3;
770 sam = &sam3->base;
771 break;
773 case 6:
774 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
775 user_info_dc,
776 &sam3);
777 NT_STATUS_NOT_OK_RETURN(nt_status);
779 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
780 NT_STATUS_HAVE_NO_MEMORY(sam6);
781 sam6->base = sam3->base;
782 sam = &sam6->base;
783 sam6->sidcount = sam3->sidcount;
784 sam6->sids = sam3->sids;
786 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
787 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
788 sam->account_name.string, sam6->dns_domainname.string);
789 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
790 /* And put into the talloc tree */
791 talloc_steal(sam6, sam3);
793 r->out.validation->sam6 = sam6;
794 break;
796 default:
797 return NT_STATUS_INVALID_INFO_CLASS;
800 netlogon_creds_encrypt_samlogon_validation(creds,
801 r->in.validation_level,
802 r->out.validation);
804 /* TODO: Describe and deal with these flags */
805 *r->out.flags = 0;
807 return NT_STATUS_OK;
810 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
811 struct netr_LogonSamLogonEx *r)
813 NTSTATUS nt_status;
814 struct netlogon_creds_CredentialState *creds;
816 *r->out.authoritative = 1;
818 nt_status = dcesrv_netr_LogonSamLogon_check(r);
819 if (!NT_STATUS_IS_OK(nt_status)) {
820 return nt_status;
823 nt_status = schannel_get_creds_state(mem_ctx,
824 dce_call->conn->dce_ctx->lp_ctx,
825 r->in.computer_name, &creds);
826 if (!NT_STATUS_IS_OK(nt_status)) {
827 return nt_status;
830 if (!dce_call->conn->auth_state.auth_info ||
831 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
832 return NT_STATUS_ACCESS_DENIED;
834 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
838 netr_LogonSamLogonWithFlags
841 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
842 struct netr_LogonSamLogonWithFlags *r)
844 NTSTATUS nt_status;
845 struct netlogon_creds_CredentialState *creds;
846 struct netr_LogonSamLogonEx r2;
848 struct netr_Authenticator *return_authenticator;
850 ZERO_STRUCT(r2);
852 r2.in.server_name = r->in.server_name;
853 r2.in.computer_name = r->in.computer_name;
854 r2.in.logon_level = r->in.logon_level;
855 r2.in.logon = r->in.logon;
856 r2.in.validation_level = r->in.validation_level;
857 r2.in.flags = r->in.flags;
858 r2.out.validation = r->out.validation;
859 r2.out.authoritative = r->out.authoritative;
860 r2.out.flags = r->out.flags;
862 *r->out.authoritative = 1;
864 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
865 if (!NT_STATUS_IS_OK(nt_status)) {
866 return nt_status;
869 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
870 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
872 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
873 mem_ctx,
874 r->in.computer_name,
875 r->in.credential, return_authenticator,
876 &creds);
877 NT_STATUS_NOT_OK_RETURN(nt_status);
879 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
881 r->out.return_authenticator = return_authenticator;
883 return nt_status;
887 netr_LogonSamLogon
889 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
890 struct netr_LogonSamLogon *r)
892 struct netr_LogonSamLogonWithFlags r2;
893 uint32_t flags = 0;
894 NTSTATUS status;
896 ZERO_STRUCT(r2);
898 r2.in.server_name = r->in.server_name;
899 r2.in.computer_name = r->in.computer_name;
900 r2.in.credential = r->in.credential;
901 r2.in.return_authenticator = r->in.return_authenticator;
902 r2.in.logon_level = r->in.logon_level;
903 r2.in.logon = r->in.logon;
904 r2.in.validation_level = r->in.validation_level;
905 r2.in.flags = &flags;
906 r2.out.validation = r->out.validation;
907 r2.out.authoritative = r->out.authoritative;
908 r2.out.flags = &flags;
910 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
912 r->out.return_authenticator = r2.out.return_authenticator;
914 return status;
919 netr_LogonSamLogoff
921 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
922 struct netr_LogonSamLogoff *r)
924 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
930 netr_DatabaseDeltas
932 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
933 struct netr_DatabaseDeltas *r)
935 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
940 netr_DatabaseSync2
942 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
943 struct netr_DatabaseSync2 *r)
945 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
946 return NT_STATUS_NOT_IMPLEMENTED;
951 netr_DatabaseSync
953 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
954 struct netr_DatabaseSync *r)
956 struct netr_DatabaseSync2 r2;
957 NTSTATUS status;
959 ZERO_STRUCT(r2);
961 r2.in.logon_server = r->in.logon_server;
962 r2.in.computername = r->in.computername;
963 r2.in.credential = r->in.credential;
964 r2.in.database_id = r->in.database_id;
965 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
966 r2.in.sync_context = r->in.sync_context;
967 r2.out.sync_context = r->out.sync_context;
968 r2.out.delta_enum_array = r->out.delta_enum_array;
969 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
971 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
973 return status;
978 netr_AccountDeltas
980 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
981 struct netr_AccountDeltas *r)
983 /* w2k3 returns "NOT IMPLEMENTED" for this call */
984 return NT_STATUS_NOT_IMPLEMENTED;
989 netr_AccountSync
991 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
992 struct netr_AccountSync *r)
994 /* w2k3 returns "NOT IMPLEMENTED" for this call */
995 return NT_STATUS_NOT_IMPLEMENTED;
1000 netr_GetDcName
1002 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1003 struct netr_GetDcName *r)
1005 const char * const attrs[] = { NULL };
1006 struct ldb_context *sam_ctx;
1007 struct ldb_message **res;
1008 struct ldb_dn *domain_dn;
1009 int ret;
1010 const char *dcname;
1013 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1014 * that the domainname needs to be a valid netbios domain
1015 * name, if it is not NULL.
1017 if (r->in.domainname) {
1018 const char *dot = strchr(r->in.domainname, '.');
1019 size_t len = strlen(r->in.domainname);
1021 if (dot || len > 15) {
1022 return WERR_DCNOTFOUND;
1026 * TODO: Should we also varify that only valid
1027 * netbios name characters are used?
1031 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1032 dce_call->conn->dce_ctx->lp_ctx,
1033 dce_call->conn->auth_state.session_info, 0);
1034 if (sam_ctx == NULL) {
1035 return WERR_DS_UNAVAILABLE;
1038 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1039 r->in.domainname);
1040 if (domain_dn == NULL) {
1041 return WERR_NO_SUCH_DOMAIN;
1044 ret = gendb_search_dn(sam_ctx, mem_ctx,
1045 domain_dn, &res, attrs);
1046 if (ret != 1) {
1047 return WERR_NO_SUCH_DOMAIN;
1050 /* TODO: - return real IP address
1051 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1053 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1054 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1055 W_ERROR_HAVE_NO_MEMORY(dcname);
1057 *r->out.dcname = dcname;
1058 return WERR_OK;
1063 netr_LogonControl2Ex
1065 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1066 struct netr_LogonControl2Ex *r)
1068 return WERR_NOT_SUPPORTED;
1073 netr_LogonControl
1075 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1076 struct netr_LogonControl *r)
1078 struct netr_LogonControl2Ex r2;
1079 WERROR werr;
1081 if (r->in.level == 0x00000001) {
1082 ZERO_STRUCT(r2);
1084 r2.in.logon_server = r->in.logon_server;
1085 r2.in.function_code = r->in.function_code;
1086 r2.in.level = r->in.level;
1087 r2.in.data = NULL;
1088 r2.out.query = r->out.query;
1090 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1091 } else if (r->in.level == 0x00000002) {
1092 werr = WERR_NOT_SUPPORTED;
1093 } else {
1094 werr = WERR_UNKNOWN_LEVEL;
1097 return werr;
1102 netr_LogonControl2
1104 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1105 struct netr_LogonControl2 *r)
1107 struct netr_LogonControl2Ex r2;
1108 WERROR werr;
1110 ZERO_STRUCT(r2);
1112 r2.in.logon_server = r->in.logon_server;
1113 r2.in.function_code = r->in.function_code;
1114 r2.in.level = r->in.level;
1115 r2.in.data = r->in.data;
1116 r2.out.query = r->out.query;
1118 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1120 return werr;
1123 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1124 struct ldb_context *sam_ctx,
1125 struct netr_DomainTrustList *trusts,
1126 uint32_t trust_flags);
1129 netr_GetAnyDCName
1131 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1132 struct netr_GetAnyDCName *r)
1134 struct netr_DomainTrustList *trusts;
1135 struct ldb_context *sam_ctx;
1136 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1137 uint32_t i;
1138 WERROR werr;
1140 *r->out.dcname = NULL;
1142 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1143 /* if the domainname parameter wasn't set assume our domain */
1144 r->in.domainname = lpcfg_workgroup(lp_ctx);
1147 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1148 dce_call->conn->auth_state.session_info, 0);
1149 if (sam_ctx == NULL) {
1150 return WERR_DS_UNAVAILABLE;
1153 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1154 /* well we asked for a DC of our own domain */
1155 if (samdb_is_pdc(sam_ctx)) {
1156 /* we are the PDC of the specified domain */
1157 return WERR_NO_SUCH_DOMAIN;
1160 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1161 lpcfg_netbios_name(lp_ctx));
1162 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1164 return WERR_OK;
1167 /* Okay, now we have to consider the trusted domains */
1169 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1170 W_ERROR_HAVE_NO_MEMORY(trusts);
1172 trusts->count = 0;
1174 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1175 NETR_TRUST_FLAG_INBOUND
1176 | NETR_TRUST_FLAG_OUTBOUND);
1177 W_ERROR_NOT_OK_RETURN(werr);
1179 for (i = 0; i < trusts->count; i++) {
1180 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1181 /* FIXME: Here we need to find a DC for the specified
1182 * trusted domain. */
1184 /* return WERR_OK; */
1185 return WERR_NO_SUCH_DOMAIN;
1189 return WERR_NO_SUCH_DOMAIN;
1194 netr_DatabaseRedo
1196 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1197 struct netr_DatabaseRedo *r)
1199 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1204 netr_NetrEnumerateTrustedDomains
1206 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1207 struct netr_NetrEnumerateTrustedDomains *r)
1209 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1214 netr_LogonGetCapabilities
1216 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1217 struct netr_LogonGetCapabilities *r)
1219 struct netlogon_creds_CredentialState *creds;
1220 NTSTATUS status;
1222 status = dcesrv_netr_creds_server_step_check(dce_call,
1223 mem_ctx,
1224 r->in.computer_name,
1225 r->in.credential,
1226 r->out.return_authenticator,
1227 &creds);
1228 if (!NT_STATUS_IS_OK(status)) {
1229 DEBUG(0,(__location__ " Bad credentials - error\n"));
1231 NT_STATUS_NOT_OK_RETURN(status);
1233 if (r->in.query_level != 1) {
1234 return NT_STATUS_NOT_SUPPORTED;
1237 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1239 return NT_STATUS_OK;
1244 netr_NETRLOGONSETSERVICEBITS
1246 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1247 struct netr_NETRLOGONSETSERVICEBITS *r)
1249 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1254 netr_LogonGetTrustRid
1256 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1257 struct netr_LogonGetTrustRid *r)
1259 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1264 netr_NETRLOGONCOMPUTESERVERDIGEST
1266 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1267 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1269 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1274 netr_NETRLOGONCOMPUTECLIENTDIGEST
1276 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1277 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1279 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1285 netr_DsRGetSiteName
1287 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1288 struct netr_DsRGetSiteName *r)
1290 struct ldb_context *sam_ctx;
1291 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1293 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1294 dce_call->conn->auth_state.session_info, 0);
1295 if (sam_ctx == NULL) {
1296 return WERR_DS_UNAVAILABLE;
1300 * We assume to be a DC when we get called over NETLOGON. Hence we
1301 * get our site name always by using "samdb_server_site_name()"
1302 * and not "samdb_client_site_name()".
1304 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1305 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1307 return WERR_OK;
1312 fill in a netr_OneDomainInfo from a ldb search result
1314 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1315 struct loadparm_context *lp_ctx,
1316 struct ldb_context *sam_ctx,
1317 struct ldb_message *res,
1318 struct netr_OneDomainInfo *info,
1319 bool is_local, bool is_trust_list)
1321 ZERO_STRUCTP(info);
1323 if (is_trust_list) {
1324 /* w2k8 only fills this on trusted domains */
1325 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1326 info->trust_extension.length = 16;
1327 info->trust_extension.info->flags =
1328 NETR_TRUST_FLAG_TREEROOT |
1329 NETR_TRUST_FLAG_IN_FOREST |
1330 NETR_TRUST_FLAG_PRIMARY |
1331 NETR_TRUST_FLAG_NATIVE;
1333 info->trust_extension.info->parent_index = 0; /* should be index into array
1334 of parent */
1335 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1336 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1339 if (is_trust_list) {
1340 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1341 info->dns_forestname.string = NULL;
1342 } else {
1343 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1344 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1345 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1346 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1349 if (is_local) {
1350 info->domainname.string = lpcfg_workgroup(lp_ctx);
1351 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1352 info->domain_guid = samdb_result_guid(res, "objectGUID");
1353 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1354 } else {
1355 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1356 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1357 info->domain_guid = samdb_result_guid(res, "objectGUID");
1358 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1360 if (!is_trust_list) {
1361 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1364 return NT_STATUS_OK;
1368 netr_LogonGetDomainInfo
1369 this is called as part of the ADS domain logon procedure.
1371 It has an important role in convaying details about the client, such
1372 as Operating System, Version, Service Pack etc.
1374 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1375 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1377 struct netlogon_creds_CredentialState *creds;
1378 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1379 "securityIdentifier", "trustPartner", NULL };
1380 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1381 "msDS-SupportedEncryptionTypes", NULL };
1382 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1383 struct ldb_context *sam_ctx;
1384 struct ldb_message **res1, **res2, **res3, *new_msg;
1385 struct ldb_dn *workstation_dn;
1386 struct netr_DomainInformation *domain_info;
1387 struct netr_LsaPolicyInformation *lsa_policy_info;
1388 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1389 bool update_dns_hostname = true;
1390 int ret, ret3, i;
1391 NTSTATUS status;
1393 status = dcesrv_netr_creds_server_step_check(dce_call,
1394 mem_ctx,
1395 r->in.computer_name,
1396 r->in.credential,
1397 r->out.return_authenticator,
1398 &creds);
1399 if (!NT_STATUS_IS_OK(status)) {
1400 DEBUG(0,(__location__ " Bad credentials - error\n"));
1402 NT_STATUS_NOT_OK_RETURN(status);
1404 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1405 dce_call->conn->dce_ctx->lp_ctx,
1406 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1407 if (sam_ctx == NULL) {
1408 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1411 switch (r->in.level) {
1412 case 1: /* Domain information */
1414 if (r->in.query->workstation_info == NULL) {
1415 return NT_STATUS_INVALID_PARAMETER;
1418 /* Prepares the workstation DN */
1419 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1420 dom_sid_string(mem_ctx, creds->sid));
1421 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1423 /* Lookup for attributes in workstation object */
1424 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1425 attrs2);
1426 if (ret != 1) {
1427 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1430 /* Gets the sam account name which is checked against the DNS
1431 * hostname parameter. */
1432 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1433 "sAMAccountName",
1434 NULL);
1435 if (sam_account_name == NULL) {
1436 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1440 * Checks that the sam account name without a possible "$"
1441 * matches as prefix with the DNS hostname in the workstation
1442 * info structure.
1444 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1445 strcspn(sam_account_name, "$"));
1446 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1447 if (r->in.query->workstation_info->dns_hostname != NULL) {
1448 prefix2 = talloc_strndup(mem_ctx,
1449 r->in.query->workstation_info->dns_hostname,
1450 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1451 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1453 if (strcasecmp(prefix1, prefix2) != 0) {
1454 update_dns_hostname = false;
1456 } else {
1457 update_dns_hostname = false;
1460 /* Gets the old DNS hostname */
1461 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1462 "dNSHostName",
1463 NULL);
1466 * Updates the DNS hostname when the client wishes that the
1467 * server should handle this for him
1468 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1469 * obviously only checked when we do already have a
1470 * "dNSHostName".
1471 * See MS-NRPC section 3.5.4.3.9
1473 if ((old_dns_hostname != NULL) &&
1474 (r->in.query->workstation_info->workstation_flags
1475 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1476 update_dns_hostname = false;
1479 /* Gets host information and put them into our directory */
1481 new_msg = ldb_msg_new(mem_ctx);
1482 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1484 new_msg->dn = workstation_dn;
1486 /* Sets the OS name */
1488 if (r->in.query->workstation_info->os_name.string == NULL) {
1489 return NT_STATUS_INVALID_PARAMETER;
1492 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1493 r->in.query->workstation_info->os_name.string);
1494 if (ret != LDB_SUCCESS) {
1495 return NT_STATUS_NO_MEMORY;
1499 * Sets information from "os_version". On an empty structure
1500 * the values are cleared.
1502 if (r->in.query->workstation_info->os_version.os != NULL) {
1503 struct netr_OsVersionInfoEx *os_version;
1504 const char *os_version_str;
1506 os_version = &r->in.query->workstation_info->os_version.os->os;
1508 if (os_version->CSDVersion == NULL) {
1509 return NT_STATUS_INVALID_PARAMETER;
1512 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1513 os_version->MajorVersion,
1514 os_version->MinorVersion,
1515 os_version->BuildNumber);
1516 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1518 ret = ldb_msg_add_string(new_msg,
1519 "operatingSystemServicePack",
1520 os_version->CSDVersion);
1521 if (ret != LDB_SUCCESS) {
1522 return NT_STATUS_NO_MEMORY;
1525 ret = ldb_msg_add_string(new_msg,
1526 "operatingSystemVersion",
1527 os_version_str);
1528 if (ret != LDB_SUCCESS) {
1529 return NT_STATUS_NO_MEMORY;
1531 } else {
1532 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1533 "operatingSystemServicePack");
1534 if (ret != LDB_SUCCESS) {
1535 return NT_STATUS_NO_MEMORY;
1538 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1539 "operatingSystemVersion");
1540 if (ret != LDB_SUCCESS) {
1541 return NT_STATUS_NO_MEMORY;
1546 * If the boolean "update_dns_hostname" remained true, then we
1547 * are fine to start the update.
1549 if (update_dns_hostname) {
1550 ret = ldb_msg_add_string(new_msg,
1551 "dNSHostname",
1552 r->in.query->workstation_info->dns_hostname);
1553 if (ret != LDB_SUCCESS) {
1554 return NT_STATUS_NO_MEMORY;
1557 /* This manual "servicePrincipalName" generation is
1558 * still needed! Since the update in the samldb LDB
1559 * module does only work if the entries already exist
1560 * which isn't always the case. */
1561 ret = ldb_msg_add_string(new_msg,
1562 "servicePrincipalName",
1563 talloc_asprintf(new_msg, "HOST/%s",
1564 r->in.computer_name));
1565 if (ret != LDB_SUCCESS) {
1566 return NT_STATUS_NO_MEMORY;
1569 ret = ldb_msg_add_string(new_msg,
1570 "servicePrincipalName",
1571 talloc_asprintf(new_msg, "HOST/%s",
1572 r->in.query->workstation_info->dns_hostname));
1573 if (ret != LDB_SUCCESS) {
1574 return NT_STATUS_NO_MEMORY;
1578 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1579 DEBUG(3,("Impossible to update samdb: %s\n",
1580 ldb_errstring(sam_ctx)));
1583 talloc_free(new_msg);
1585 /* Writes back the domain information */
1587 /* We need to do two searches. The first will pull our primary
1588 domain and the second will pull any trusted domains. Our
1589 primary domain is also a "trusted" domain, so we need to
1590 put the primary domain into the lists of returned trusts as
1591 well. */
1592 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1593 &res2, attrs);
1594 if (ret != 1) {
1595 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1598 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1599 "(objectClass=trustedDomain)");
1600 if (ret3 == -1) {
1601 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1604 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1605 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1607 ZERO_STRUCTP(domain_info);
1609 /* Informations about the local and trusted domains */
1611 status = fill_one_domain_info(mem_ctx,
1612 dce_call->conn->dce_ctx->lp_ctx,
1613 sam_ctx, res2[0], &domain_info->primary_domain,
1614 true, false);
1615 NT_STATUS_NOT_OK_RETURN(status);
1617 domain_info->trusted_domain_count = ret3 + 1;
1618 domain_info->trusted_domains = talloc_array(mem_ctx,
1619 struct netr_OneDomainInfo,
1620 domain_info->trusted_domain_count);
1621 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1623 for (i=0;i<ret3;i++) {
1624 status = fill_one_domain_info(mem_ctx,
1625 dce_call->conn->dce_ctx->lp_ctx,
1626 sam_ctx, res3[i],
1627 &domain_info->trusted_domains[i],
1628 false, true);
1629 NT_STATUS_NOT_OK_RETURN(status);
1632 status = fill_one_domain_info(mem_ctx,
1633 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1634 &domain_info->trusted_domains[i], true, true);
1635 NT_STATUS_NOT_OK_RETURN(status);
1637 /* Sets the supported encryption types */
1638 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1639 "msDS-SupportedEncryptionTypes",
1640 default_supported_enc_types);
1642 /* Other host domain information */
1644 lsa_policy_info = talloc(mem_ctx,
1645 struct netr_LsaPolicyInformation);
1646 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1647 ZERO_STRUCTP(lsa_policy_info);
1649 domain_info->lsa_policy = *lsa_policy_info;
1651 /* The DNS hostname is only returned back when there is a chance
1652 * for a change. */
1653 if ((r->in.query->workstation_info->workstation_flags
1654 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1655 domain_info->dns_hostname.string = old_dns_hostname;
1656 } else {
1657 domain_info->dns_hostname.string = NULL;
1660 domain_info->workstation_flags =
1661 r->in.query->workstation_info->workstation_flags & (
1662 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1664 r->out.info->domain_info = domain_info;
1665 break;
1666 case 2: /* LSA policy information - not used at the moment */
1667 lsa_policy_info = talloc(mem_ctx,
1668 struct netr_LsaPolicyInformation);
1669 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1670 ZERO_STRUCTP(lsa_policy_info);
1672 r->out.info->lsa_policy_info = lsa_policy_info;
1673 break;
1674 default:
1675 return NT_STATUS_INVALID_LEVEL;
1676 break;
1679 return NT_STATUS_OK;
1684 netr_ServerPasswordGet
1686 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1687 struct netr_ServerPasswordGet *r)
1689 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1694 netr_NETRLOGONSENDTOSAM
1696 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1697 struct netr_NETRLOGONSENDTOSAM *r)
1699 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1704 netr_DsRGetDCNameEx2
1706 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1707 TALLOC_CTX *mem_ctx,
1708 struct netr_DsRGetDCNameEx2 *r)
1710 struct ldb_context *sam_ctx;
1711 struct netr_DsRGetDCNameInfo *info;
1712 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1713 const struct tsocket_address *remote_address;
1714 char *addr = NULL;
1715 const char *server_site_name;
1716 char *guid_str;
1717 struct netlogon_samlogon_response response;
1718 NTSTATUS status;
1719 const char *dc_name = NULL;
1720 const char *domain_name = NULL;
1721 struct interface *ifaces;
1722 const char *pdc_ip;
1724 ZERO_STRUCTP(r->out.info);
1726 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1727 dce_call->conn->auth_state.session_info, 0);
1728 if (sam_ctx == NULL) {
1729 return WERR_DS_UNAVAILABLE;
1732 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1733 if (tsocket_address_is_inet(remote_address, "ip")) {
1734 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1735 W_ERROR_HAVE_NO_MEMORY(addr);
1738 /* "server_unc" is ignored by w2k3 */
1740 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1741 return WERR_INVALID_FLAGS;
1744 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1745 r->in.flags & DS_PDC_REQUIRED &&
1746 r->in.flags & DS_KDC_REQUIRED) {
1747 return WERR_INVALID_FLAGS;
1749 if (r->in.flags & DS_IS_FLAT_NAME &&
1750 r->in.flags & DS_IS_DNS_NAME) {
1751 return WERR_INVALID_FLAGS;
1753 if (r->in.flags & DS_RETURN_DNS_NAME &&
1754 r->in.flags & DS_RETURN_FLAT_NAME) {
1755 return WERR_INVALID_FLAGS;
1757 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1758 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1759 return WERR_INVALID_FLAGS;
1762 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1763 r->in.flags &
1764 (DS_DIRECTORY_SERVICE_REQUIRED |
1765 DS_DIRECTORY_SERVICE_PREFERRED |
1766 DS_GC_SERVER_REQUIRED |
1767 DS_PDC_REQUIRED |
1768 DS_KDC_REQUIRED)) {
1769 return WERR_INVALID_FLAGS;
1772 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1773 r->in.site_name) {
1774 return WERR_INVALID_FLAGS;
1777 /* Proof server site parameter "site_name" if it was specified */
1778 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1779 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1780 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1781 server_site_name) != 0)) {
1782 return WERR_NO_SUCH_DOMAIN;
1785 guid_str = r->in.domain_guid != NULL ?
1786 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1788 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1789 r->in.domain_name,
1790 r->in.domain_name,
1791 NULL, guid_str,
1792 r->in.client_account,
1793 r->in.mask, addr,
1794 NETLOGON_NT_VERSION_5EX_WITH_IP,
1795 lp_ctx, &response, true);
1796 if (!NT_STATUS_IS_OK(status)) {
1797 return ntstatus_to_werror(status);
1801 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1802 * (O) flag when the returned forest name is in DNS format. This is here
1803 * always the case (see below).
1805 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1807 if (r->in.flags & DS_RETURN_DNS_NAME) {
1808 dc_name = response.data.nt5_ex.pdc_dns_name;
1809 domain_name = response.data.nt5_ex.dns_domain;
1811 * According to MS-NRPC 2.2.1.2.1 we should set the
1812 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1813 * the returned information is in DNS form.
1815 response.data.nt5_ex.server_type |=
1816 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1817 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1818 dc_name = response.data.nt5_ex.pdc_name;
1819 domain_name = response.data.nt5_ex.domain_name;
1820 } else {
1823 * TODO: autodetect what we need to return
1824 * based on the given arguments
1826 dc_name = response.data.nt5_ex.pdc_name;
1827 domain_name = response.data.nt5_ex.domain_name;
1830 if (!dc_name || !dc_name[0]) {
1831 return WERR_NO_SUCH_DOMAIN;
1834 if (!domain_name || !domain_name[0]) {
1835 return WERR_NO_SUCH_DOMAIN;
1838 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1839 W_ERROR_HAVE_NO_MEMORY(info);
1840 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1841 dc_name[0] == '\\'? "\\\\":"",
1842 talloc_strdup(mem_ctx, dc_name));
1843 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1845 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1846 pdc_ip = iface_list_best_ip(ifaces, addr);
1847 if (pdc_ip == NULL) {
1848 pdc_ip = "127.0.0.1";
1850 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1851 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1852 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1853 info->domain_guid = response.data.nt5_ex.domain_uuid;
1854 info->domain_name = domain_name;
1855 info->forest_name = response.data.nt5_ex.forest;
1856 info->dc_flags = response.data.nt5_ex.server_type;
1857 if (r->in.flags & DS_RETURN_DNS_NAME) {
1858 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
1859 * returned if we are returning info->dc_unc containing a FQDN.
1860 * This attribute is called DomainControllerName in the specs,
1861 * it seems that we decide to return FQDN or netbios depending on
1862 * DS_RETURN_DNS_NAME.
1864 info->dc_flags |= DS_DNS_CONTROLLER;
1866 info->dc_site_name = response.data.nt5_ex.server_site;
1867 info->client_site_name = response.data.nt5_ex.client_site;
1869 *r->out.info = info;
1871 return WERR_OK;
1875 netr_DsRGetDCNameEx
1877 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1878 struct netr_DsRGetDCNameEx *r)
1880 struct netr_DsRGetDCNameEx2 r2;
1881 WERROR werr;
1883 ZERO_STRUCT(r2);
1885 r2.in.server_unc = r->in.server_unc;
1886 r2.in.client_account = NULL;
1887 r2.in.mask = 0;
1888 r2.in.domain_guid = r->in.domain_guid;
1889 r2.in.domain_name = r->in.domain_name;
1890 r2.in.site_name = r->in.site_name;
1891 r2.in.flags = r->in.flags;
1892 r2.out.info = r->out.info;
1894 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1896 return werr;
1900 netr_DsRGetDCName
1902 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1903 struct netr_DsRGetDCName *r)
1905 struct netr_DsRGetDCNameEx2 r2;
1906 WERROR werr;
1908 ZERO_STRUCT(r2);
1910 r2.in.server_unc = r->in.server_unc;
1911 r2.in.client_account = NULL;
1912 r2.in.mask = 0;
1913 r2.in.domain_name = r->in.domain_name;
1914 r2.in.domain_guid = r->in.domain_guid;
1916 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1917 r2.in.flags = r->in.flags;
1918 r2.out.info = r->out.info;
1920 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1922 return werr;
1925 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1927 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1928 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1930 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1935 netr_NetrEnumerateTrustedDomainsEx
1937 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1938 struct netr_NetrEnumerateTrustedDomainsEx *r)
1940 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1945 netr_DsRAddressToSitenamesExW
1947 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1948 struct netr_DsRAddressToSitenamesExW *r)
1950 struct ldb_context *sam_ctx;
1951 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1952 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1953 sa_family_t sin_family;
1954 struct sockaddr_in *addr;
1955 #ifdef HAVE_IPV6
1956 struct sockaddr_in6 *addr6;
1957 char addr_str[INET6_ADDRSTRLEN];
1958 #else
1959 char addr_str[INET_ADDRSTRLEN];
1960 #endif
1961 char *subnet_name;
1962 const char *res;
1963 uint32_t i;
1965 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1966 dce_call->conn->auth_state.session_info, 0);
1967 if (sam_ctx == NULL) {
1968 return WERR_DS_UNAVAILABLE;
1971 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1972 W_ERROR_HAVE_NO_MEMORY(ctr);
1974 *r->out.ctr = ctr;
1976 ctr->count = r->in.count;
1977 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1978 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1979 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1980 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1982 for (i=0; i<ctr->count; i++) {
1983 ctr->sitename[i].string = NULL;
1984 ctr->subnetname[i].string = NULL;
1986 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1987 continue;
1989 /* The first two byte of the buffer are reserved for the
1990 * "sin_family" but for now only the first one is used. */
1991 sin_family = r->in.addresses[i].buffer[0];
1993 switch (sin_family) {
1994 case AF_INET:
1995 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1996 continue;
1998 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1999 res = inet_ntop(AF_INET, &addr->sin_addr,
2000 addr_str, sizeof(addr_str));
2001 break;
2002 #ifdef HAVE_IPV6
2003 case AF_INET6:
2004 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2005 continue;
2007 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2008 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2009 addr_str, sizeof(addr_str));
2010 break;
2011 #endif
2012 default:
2013 continue;
2016 if (res == NULL) {
2017 continue;
2020 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2021 mem_ctx,
2022 addr_str,
2023 &subnet_name);
2024 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2025 ctr->subnetname[i].string = subnet_name;
2028 return WERR_OK;
2033 netr_DsRAddressToSitenamesW
2035 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2036 struct netr_DsRAddressToSitenamesW *r)
2038 struct netr_DsRAddressToSitenamesExW r2;
2039 struct netr_DsRAddressToSitenamesWCtr *ctr;
2040 uint32_t i;
2041 WERROR werr;
2043 ZERO_STRUCT(r2);
2045 r2.in.server_name = r->in.server_name;
2046 r2.in.count = r->in.count;
2047 r2.in.addresses = r->in.addresses;
2049 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2050 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2052 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2053 W_ERROR_HAVE_NO_MEMORY(ctr);
2055 *r->out.ctr = ctr;
2057 ctr->count = r->in.count;
2058 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2059 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2061 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2063 for (i=0; i<ctr->count; i++) {
2064 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2067 return werr;
2072 netr_DsrGetDcSiteCoverageW
2074 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2075 struct netr_DsrGetDcSiteCoverageW *r)
2077 struct ldb_context *sam_ctx;
2078 struct DcSitesCtr *ctr;
2079 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2081 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2082 dce_call->conn->auth_state.session_info, 0);
2083 if (sam_ctx == NULL) {
2084 return WERR_DS_UNAVAILABLE;
2087 ctr = talloc(mem_ctx, struct DcSitesCtr);
2088 W_ERROR_HAVE_NO_MEMORY(ctr);
2090 *r->out.ctr = ctr;
2092 /* For now only return our default site */
2093 ctr->num_sites = 1;
2094 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2095 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2096 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2097 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2099 return WERR_OK;
2103 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2104 struct ldb_context *sam_ctx,
2105 struct netr_DomainTrustList *trusts,
2106 uint32_t trust_flags)
2108 struct ldb_dn *system_dn;
2109 struct ldb_message **dom_res = NULL;
2110 const char *trust_attrs[] = { "flatname", "trustPartner",
2111 "securityIdentifier", "trustDirection",
2112 "trustType", "trustAttributes", NULL };
2113 uint32_t n;
2114 int i;
2115 int ret;
2117 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2118 NETR_TRUST_FLAG_OUTBOUND))) {
2119 return WERR_INVALID_FLAGS;
2122 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2123 ldb_get_default_basedn(sam_ctx),
2124 "(&(objectClass=container)(cn=System))");
2125 if (!system_dn) {
2126 return WERR_GENERAL_FAILURE;
2129 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2130 &dom_res, trust_attrs,
2131 "(objectclass=trustedDomain)");
2133 for (i = 0; i < ret; i++) {
2134 unsigned int trust_dir;
2135 uint32_t flags = 0;
2137 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2138 "trustDirection", 0);
2140 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2141 flags |= NETR_TRUST_FLAG_INBOUND;
2143 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2144 flags |= NETR_TRUST_FLAG_OUTBOUND;
2147 if (!(flags & trust_flags)) {
2148 /* this trust direction was not requested */
2149 continue;
2152 n = trusts->count;
2153 trusts->array = talloc_realloc(trusts, trusts->array,
2154 struct netr_DomainTrust,
2155 n + 1);
2156 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2158 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2159 if (!trusts->array[n].netbios_name) {
2160 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2161 "without flatname\n",
2162 ldb_dn_get_linearized(dom_res[i]->dn)));
2165 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2167 trusts->array[n].trust_flags = flags;
2168 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2169 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2170 /* TODO: find if we have parent in the list */
2171 trusts->array[n].parent_index = 0;
2174 trusts->array[n].trust_type =
2175 ldb_msg_find_attr_as_uint(dom_res[i],
2176 "trustType", 0);
2177 trusts->array[n].trust_attributes =
2178 ldb_msg_find_attr_as_uint(dom_res[i],
2179 "trustAttributes", 0);
2181 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2182 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2183 struct dom_sid zero_sid;
2184 ZERO_STRUCT(zero_sid);
2185 trusts->array[n].sid =
2186 dom_sid_dup(trusts, &zero_sid);
2187 } else {
2188 trusts->array[n].sid =
2189 samdb_result_dom_sid(trusts, dom_res[i],
2190 "securityIdentifier");
2192 trusts->array[n].guid = GUID_zero();
2194 trusts->count = n + 1;
2197 talloc_free(dom_res);
2198 return WERR_OK;
2202 netr_DsrEnumerateDomainTrusts
2204 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2205 TALLOC_CTX *mem_ctx,
2206 struct netr_DsrEnumerateDomainTrusts *r)
2208 struct netr_DomainTrustList *trusts;
2209 struct ldb_context *sam_ctx;
2210 int ret;
2211 struct ldb_message **dom_res;
2212 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2213 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2214 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2215 const char *p;
2216 WERROR werr;
2218 if (r->in.trust_flags & 0xFFFFFE00) {
2219 return WERR_INVALID_FLAGS;
2222 /* TODO: turn to hard check once we are sure this is 100% correct */
2223 if (!r->in.server_name) {
2224 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2225 "But received NULL!\n", dnsdomain));
2226 } else {
2227 p = strchr(r->in.server_name, '.');
2228 if (!p) {
2229 DEBUG(3, ("Invalid domain! Expected name in domain "
2230 "[%s]. But received [%s]!\n",
2231 dnsdomain, r->in.server_name));
2232 p = r->in.server_name;
2233 } else {
2234 p++;
2236 if (strcasecmp(p, dnsdomain)) {
2237 DEBUG(3, ("Invalid domain! Expected name in domain "
2238 "[%s]. But received [%s]!\n",
2239 dnsdomain, r->in.server_name));
2243 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2244 W_ERROR_HAVE_NO_MEMORY(trusts);
2246 trusts->count = 0;
2247 r->out.trusts = trusts;
2249 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2250 dce_call->conn->auth_state.session_info, 0);
2251 if (sam_ctx == NULL) {
2252 return WERR_GENERAL_FAILURE;
2255 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2256 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2258 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2259 trusts, r->in.trust_flags);
2260 W_ERROR_NOT_OK_RETURN(werr);
2263 /* NOTE: we currently are always the root of the forest */
2264 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2265 uint32_t n = trusts->count;
2267 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2268 &dom_res, dom_attrs);
2269 if (ret != 1) {
2270 return WERR_GENERAL_FAILURE;
2273 trusts->count = n + 1;
2274 trusts->array = talloc_realloc(trusts, trusts->array,
2275 struct netr_DomainTrust,
2276 trusts->count);
2277 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2279 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2280 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2281 trusts->array[n].trust_flags =
2282 NETR_TRUST_FLAG_NATIVE |
2283 NETR_TRUST_FLAG_TREEROOT |
2284 NETR_TRUST_FLAG_IN_FOREST |
2285 NETR_TRUST_FLAG_PRIMARY;
2286 /* we are always the root domain for now */
2287 trusts->array[n].parent_index = 0;
2288 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2289 trusts->array[n].trust_attributes = 0;
2290 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2291 dom_res[0],
2292 "objectSid");
2293 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2294 "objectGUID");
2295 talloc_free(dom_res);
2298 return WERR_OK;
2303 netr_DsrDeregisterDNSHostRecords
2305 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2306 struct netr_DsrDeregisterDNSHostRecords *r)
2308 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2313 netr_ServerTrustPasswordsGet
2315 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2316 struct netr_ServerTrustPasswordsGet *r)
2318 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2322 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2323 struct ldb_context *sam_ctx,
2324 struct loadparm_context *lp_ctx,
2325 struct lsa_ForestTrustInformation *info)
2327 struct lsa_ForestTrustDomainInfo *domain_info;
2328 struct lsa_ForestTrustRecord *e;
2329 struct ldb_message **dom_res;
2330 const char * const dom_attrs[] = { "objectSid", NULL };
2331 int ret;
2333 /* we need to provide 2 entries:
2334 * 1. the Root Forest name
2335 * 2. the Domain Information
2338 info->count = 2;
2339 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2340 W_ERROR_HAVE_NO_MEMORY(info->entries);
2342 /* Forest root info */
2343 e = talloc(info, struct lsa_ForestTrustRecord);
2344 W_ERROR_HAVE_NO_MEMORY(e);
2346 e->flags = 0;
2347 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2348 e->time = 0; /* so far always 0 in trces. */
2349 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2350 mem_ctx);
2351 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2353 info->entries[0] = e;
2355 /* Domain info */
2356 e = talloc(info, struct lsa_ForestTrustRecord);
2357 W_ERROR_HAVE_NO_MEMORY(e);
2359 /* get our own domain info */
2360 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2361 if (ret != 1) {
2362 return WERR_GENERAL_FAILURE;
2365 /* TODO: check if disabled and set flags accordingly */
2366 e->flags = 0;
2367 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2368 e->time = 0; /* so far always 0 in traces. */
2370 domain_info = &e->forest_trust_data.domain_info;
2371 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2372 "objectSid");
2373 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2374 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2376 info->entries[1] = e;
2378 talloc_free(dom_res);
2380 return WERR_OK;
2384 netr_DsRGetForestTrustInformation
2386 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2387 TALLOC_CTX *mem_ctx,
2388 struct netr_DsRGetForestTrustInformation *r)
2390 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2391 struct lsa_ForestTrustInformation *info, **info_ptr;
2392 struct ldb_context *sam_ctx;
2393 WERROR werr;
2395 if (r->in.flags & 0xFFFFFFFE) {
2396 return WERR_INVALID_FLAGS;
2399 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2400 dce_call->conn->auth_state.session_info, 0);
2401 if (sam_ctx == NULL) {
2402 return WERR_GENERAL_FAILURE;
2405 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2406 if (!samdb_is_pdc(sam_ctx)) {
2407 return WERR_NERR_NOTPRIMARY;
2410 if (r->in.trusted_domain_name == NULL) {
2411 return WERR_INVALID_FLAGS;
2414 /* TODO: establish an schannel connection with
2415 * r->in.trusted_domain_name and perform a
2416 * netr_GetForestTrustInformation call against it */
2418 /* for now return not implementd */
2419 return WERR_CALL_NOT_IMPLEMENTED;
2422 /* TODO: check r->in.server_name is our name */
2424 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2425 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2427 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2428 W_ERROR_HAVE_NO_MEMORY(info);
2430 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2431 W_ERROR_NOT_OK_RETURN(werr);
2433 *info_ptr = info;
2434 r->out.forest_trust_info = info_ptr;
2436 return WERR_OK;
2441 netr_GetForestTrustInformation
2443 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2444 TALLOC_CTX *mem_ctx,
2445 struct netr_GetForestTrustInformation *r)
2447 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2448 struct netlogon_creds_CredentialState *creds;
2449 struct lsa_ForestTrustInformation *info, **info_ptr;
2450 struct ldb_context *sam_ctx;
2451 NTSTATUS status;
2452 WERROR werr;
2454 status = dcesrv_netr_creds_server_step_check(dce_call,
2455 mem_ctx,
2456 r->in.computer_name,
2457 r->in.credential,
2458 r->out.return_authenticator,
2459 &creds);
2460 if (!NT_STATUS_IS_OK(status)) {
2461 return status;
2464 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2465 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2466 return NT_STATUS_NOT_IMPLEMENTED;
2469 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2470 dce_call->conn->auth_state.session_info, 0);
2471 if (sam_ctx == NULL) {
2472 return NT_STATUS_INTERNAL_ERROR;
2475 /* TODO: check r->in.server_name is our name */
2477 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2478 if (!info_ptr) {
2479 return NT_STATUS_NO_MEMORY;
2481 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2482 if (!info) {
2483 return NT_STATUS_NO_MEMORY;
2486 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2487 if (!W_ERROR_IS_OK(werr)) {
2488 return werror_to_ntstatus(werr);
2491 *info_ptr = info;
2492 r->out.forest_trust_info = info_ptr;
2494 return NT_STATUS_OK;
2499 netr_ServerGetTrustInfo
2501 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2502 struct netr_ServerGetTrustInfo *r)
2504 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2508 netr_Unused47
2510 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2511 struct netr_Unused47 *r)
2513 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2517 struct netr_dnsupdate_RODC_state {
2518 struct dcesrv_call_state *dce_call;
2519 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2520 struct dnsupdate_RODC *r2;
2524 called when the forwarded RODC dns update request is finished
2526 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2528 struct netr_dnsupdate_RODC_state *st =
2529 tevent_req_callback_data(subreq,
2530 struct netr_dnsupdate_RODC_state);
2531 NTSTATUS status;
2533 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2534 TALLOC_FREE(subreq);
2535 if (!NT_STATUS_IS_OK(status)) {
2536 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2537 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2540 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2542 status = dcesrv_reply(st->dce_call);
2543 if (!NT_STATUS_IS_OK(status)) {
2544 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2549 netr_DsrUpdateReadOnlyServerDnsRecords
2551 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2552 TALLOC_CTX *mem_ctx,
2553 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2555 struct netlogon_creds_CredentialState *creds;
2556 NTSTATUS nt_status;
2557 struct dcerpc_binding_handle *binding_handle;
2558 struct netr_dnsupdate_RODC_state *st;
2559 struct tevent_req *subreq;
2561 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2562 mem_ctx,
2563 r->in.computer_name,
2564 r->in.credential,
2565 r->out.return_authenticator,
2566 &creds);
2567 NT_STATUS_NOT_OK_RETURN(nt_status);
2569 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2570 return NT_STATUS_ACCESS_DENIED;
2573 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2574 NT_STATUS_HAVE_NO_MEMORY(st);
2576 st->dce_call = dce_call;
2577 st->r = r;
2578 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2579 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2581 st->r2->in.dom_sid = creds->sid;
2582 st->r2->in.site_name = r->in.site_name;
2583 st->r2->in.dns_ttl = r->in.dns_ttl;
2584 st->r2->in.dns_names = r->in.dns_names;
2585 st->r2->out.dns_names = r->out.dns_names;
2587 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2588 "dnsupdate", &ndr_table_irpc);
2589 if (binding_handle == NULL) {
2590 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2591 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2592 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2595 /* forward the call */
2596 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2597 binding_handle, st->r2);
2598 NT_STATUS_HAVE_NO_MEMORY(subreq);
2600 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2602 /* setup the callback */
2603 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2605 return NT_STATUS_OK;
2609 /* include the generated boilerplate */
2610 #include "librpc/gen_ndr/ndr_netlogon_s.c"