s4:dsdb/schema: fix dsdb_schema_set_el_from_ldb_msg() (bug #9470)
[Samba/gebeck_regimport.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob633687fd9d3acb72759beeda8b99be23118fdef2
1 /*
2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "cldap_server/cldap_server.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
40 #include "lib/socket/netif.h"
42 struct netlogon_server_pipe_state {
43 struct netr_Credential client_challenge;
44 struct netr_Credential server_challenge;
47 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
48 struct netr_ServerReqChallenge *r)
50 struct netlogon_server_pipe_state *pipe_state =
51 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
53 ZERO_STRUCTP(r->out.return_credentials);
55 /* destroyed on pipe shutdown */
57 if (pipe_state) {
58 talloc_free(pipe_state);
59 dce_call->context->private_data = NULL;
62 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
63 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
65 pipe_state->client_challenge = *r->in.credentials;
67 generate_random_buffer(pipe_state->server_challenge.data,
68 sizeof(pipe_state->server_challenge.data));
70 *r->out.return_credentials = pipe_state->server_challenge;
72 dce_call->context->private_data = pipe_state;
74 return NT_STATUS_OK;
77 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
78 struct netr_ServerAuthenticate3 *r)
80 struct netlogon_server_pipe_state *pipe_state =
81 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
82 struct netlogon_creds_CredentialState *creds;
83 struct ldb_context *sam_ctx;
84 struct samr_Password *mach_pwd;
85 uint32_t user_account_control;
86 int num_records;
87 struct ldb_message **msgs;
88 NTSTATUS nt_status;
89 const char *attrs[] = {"unicodePwd", "userAccountControl",
90 "objectSid", NULL};
92 const char *trust_dom_attrs[] = {"flatname", NULL};
93 const char *account_name;
94 uint32_t negotiate_flags = 0;
96 ZERO_STRUCTP(r->out.return_credentials);
97 *r->out.rid = 0;
99 negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
100 NETLOGON_NEG_PERSISTENT_SAMREPL |
101 NETLOGON_NEG_ARCFOUR |
102 NETLOGON_NEG_PROMOTION_COUNT |
103 NETLOGON_NEG_CHANGELOG_BDC |
104 NETLOGON_NEG_FULL_SYNC_REPL |
105 NETLOGON_NEG_MULTIPLE_SIDS |
106 NETLOGON_NEG_REDO |
107 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
108 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
109 NETLOGON_NEG_GENERIC_PASSTHROUGH |
110 NETLOGON_NEG_CONCURRENT_RPC |
111 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
112 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
113 NETLOGON_NEG_TRANSITIVE_TRUSTS |
114 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
115 NETLOGON_NEG_PASSWORD_SET2 |
116 NETLOGON_NEG_GETDOMAININFO |
117 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
118 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
119 NETLOGON_NEG_RODC_PASSTHROUGH |
120 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
121 NETLOGON_NEG_AUTHENTICATED_RPC;
123 if (*r->in.negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
124 negotiate_flags |= NETLOGON_NEG_STRONG_KEYS;
127 if (*r->in.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
128 negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
132 * According to Microsoft (see bugid #6099)
133 * Windows 7 looks at the negotiate_flags
134 * returned in this structure *even if the
135 * call fails with access denied!
137 *r->out.negotiate_flags = negotiate_flags;
139 switch (r->in.secure_channel_type) {
140 case SEC_CHAN_WKSTA:
141 case SEC_CHAN_DNS_DOMAIN:
142 case SEC_CHAN_DOMAIN:
143 case SEC_CHAN_BDC:
144 case SEC_CHAN_RODC:
145 break;
146 default:
147 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
148 r->in.secure_channel_type));
149 return NT_STATUS_INVALID_PARAMETER;
152 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
153 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
154 if (sam_ctx == NULL) {
155 return NT_STATUS_INVALID_SYSTEM_SERVICE;
158 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
159 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
160 const char *flatname;
161 if (!encoded_account) {
162 return NT_STATUS_NO_MEMORY;
165 /* Kill the trailing dot */
166 if (encoded_account[strlen(encoded_account)-1] == '.') {
167 encoded_account[strlen(encoded_account)-1] = '\0';
170 /* pull the user attributes */
171 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
172 trust_dom_attrs,
173 "(&(trustPartner=%s)(objectclass=trustedDomain))",
174 encoded_account);
176 if (num_records == 0) {
177 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
178 encoded_account));
179 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
182 if (num_records > 1) {
183 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
184 return NT_STATUS_INTERNAL_DB_CORRUPTION;
187 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
188 if (!flatname) {
189 /* No flatname for this trust - we can't proceed */
190 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
192 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
194 if (!account_name) {
195 return NT_STATUS_NO_MEMORY;
198 } else {
199 account_name = r->in.account_name;
202 /* pull the user attributes */
203 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
204 "(&(sAMAccountName=%s)(objectclass=user))",
205 ldb_binary_encode_string(mem_ctx, account_name));
207 if (num_records == 0) {
208 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
209 r->in.account_name));
210 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
213 if (num_records > 1) {
214 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
215 return NT_STATUS_INTERNAL_DB_CORRUPTION;
218 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
220 if (user_account_control & UF_ACCOUNTDISABLE) {
221 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
222 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
225 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
226 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
227 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
228 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
230 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
231 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
232 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
233 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
235 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
237 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
238 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
239 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
240 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
242 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
243 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
244 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
245 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
247 } else {
248 /* we should never reach this */
249 return NT_STATUS_INTERNAL_ERROR;
252 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
253 "objectSid", 0);
255 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
256 if (mach_pwd == NULL) {
257 return NT_STATUS_ACCESS_DENIED;
260 if (!pipe_state) {
261 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
262 return NT_STATUS_ACCESS_DENIED;
265 creds = netlogon_creds_server_init(mem_ctx,
266 r->in.account_name,
267 r->in.computer_name,
268 r->in.secure_channel_type,
269 &pipe_state->client_challenge,
270 &pipe_state->server_challenge,
271 mach_pwd,
272 r->in.credentials,
273 r->out.return_credentials,
274 negotiate_flags);
275 if (!creds) {
276 return NT_STATUS_ACCESS_DENIED;
279 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
281 nt_status = schannel_save_creds_state(mem_ctx,
282 dce_call->conn->dce_ctx->lp_ctx,
283 creds);
285 return nt_status;
288 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
289 struct netr_ServerAuthenticate *r)
291 struct netr_ServerAuthenticate3 a;
292 uint32_t rid;
293 /* TODO:
294 * negotiate_flags is used as an [in] parameter
295 * so it need to be initialised.
297 * (I think ... = 0; seems wrong here --metze)
299 uint32_t negotiate_flags_in = 0;
300 uint32_t negotiate_flags_out = 0;
302 a.in.server_name = r->in.server_name;
303 a.in.account_name = r->in.account_name;
304 a.in.secure_channel_type = r->in.secure_channel_type;
305 a.in.computer_name = r->in.computer_name;
306 a.in.credentials = r->in.credentials;
307 a.in.negotiate_flags = &negotiate_flags_in;
309 a.out.return_credentials = r->out.return_credentials;
310 a.out.rid = &rid;
311 a.out.negotiate_flags = &negotiate_flags_out;
313 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
316 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
317 struct netr_ServerAuthenticate2 *r)
319 struct netr_ServerAuthenticate3 r3;
320 uint32_t rid = 0;
322 r3.in.server_name = r->in.server_name;
323 r3.in.account_name = r->in.account_name;
324 r3.in.secure_channel_type = r->in.secure_channel_type;
325 r3.in.computer_name = r->in.computer_name;
326 r3.in.credentials = r->in.credentials;
327 r3.out.return_credentials = r->out.return_credentials;
328 r3.in.negotiate_flags = r->in.negotiate_flags;
329 r3.out.negotiate_flags = r->out.negotiate_flags;
330 r3.out.rid = &rid;
332 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
336 * NOTE: The following functions are nearly identical to the ones available in
337 * source3/rpc_server/srv_nelog_nt.c
338 * The reason we keep 2 copies is that they use different structures to
339 * represent the auth_info and the decrpc pipes.
343 * If schannel is required for this call test that it actually is available.
345 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
346 const char *computer_name,
347 bool integrity, bool privacy)
350 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
351 if (!privacy && !integrity) {
352 return NT_STATUS_OK;
355 if ((!privacy && integrity) &&
356 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
357 return NT_STATUS_OK;
360 if ((privacy || integrity) &&
361 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
362 return NT_STATUS_OK;
366 /* test didn't pass */
367 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
368 computer_name));
370 return NT_STATUS_ACCESS_DENIED;
373 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
374 TALLOC_CTX *mem_ctx,
375 const char *computer_name,
376 struct netr_Authenticator *received_authenticator,
377 struct netr_Authenticator *return_authenticator,
378 struct netlogon_creds_CredentialState **creds_out)
380 NTSTATUS nt_status;
381 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
382 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
384 if (schannel_global_required) {
385 nt_status = schannel_check_required(auth_info,
386 computer_name,
387 true, false);
388 if (!NT_STATUS_IS_OK(nt_status)) {
389 return nt_status;
393 nt_status = schannel_check_creds_state(mem_ctx,
394 dce_call->conn->dce_ctx->lp_ctx,
395 computer_name,
396 received_authenticator,
397 return_authenticator,
398 creds_out);
399 return nt_status;
403 Change the machine account password for the currently connected
404 client. Supplies only the NT#.
407 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
408 struct netr_ServerPasswordSet *r)
410 struct netlogon_creds_CredentialState *creds;
411 struct ldb_context *sam_ctx;
412 const char * const attrs[] = { "unicodePwd", NULL };
413 struct ldb_message **res;
414 struct samr_Password *oldNtHash;
415 NTSTATUS nt_status;
416 int ret;
418 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
419 mem_ctx,
420 r->in.computer_name,
421 r->in.credential, r->out.return_authenticator,
422 &creds);
423 NT_STATUS_NOT_OK_RETURN(nt_status);
425 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);
426 if (sam_ctx == NULL) {
427 return NT_STATUS_INVALID_SYSTEM_SERVICE;
430 netlogon_creds_des_decrypt(creds, r->in.new_password);
432 /* fetch the old password hashes (the NT hash has to exist) */
434 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
435 "(&(objectClass=user)(objectSid=%s))",
436 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
437 if (ret != 1) {
438 return NT_STATUS_WRONG_PASSWORD;
441 nt_status = samdb_result_passwords(mem_ctx,
442 dce_call->conn->dce_ctx->lp_ctx,
443 res[0], NULL, &oldNtHash);
444 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
445 return NT_STATUS_WRONG_PASSWORD;
448 /* Using the sid for the account as the key, set the password */
449 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
450 creds->sid,
451 NULL, /* Don't have plaintext */
452 NULL, r->in.new_password,
453 NULL, oldNtHash, /* Password change */
454 NULL, NULL);
455 return nt_status;
459 Change the machine account password for the currently connected
460 client. Supplies new plaintext.
462 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
463 struct netr_ServerPasswordSet2 *r)
465 struct netlogon_creds_CredentialState *creds;
466 struct ldb_context *sam_ctx;
467 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
468 struct ldb_message **res;
469 struct samr_Password *oldLmHash, *oldNtHash;
470 NTSTATUS nt_status;
471 DATA_BLOB new_password;
472 int ret;
474 struct samr_CryptPassword password_buf;
476 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
477 mem_ctx,
478 r->in.computer_name,
479 r->in.credential, r->out.return_authenticator,
480 &creds);
481 NT_STATUS_NOT_OK_RETURN(nt_status);
483 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);
484 if (sam_ctx == NULL) {
485 return NT_STATUS_INVALID_SYSTEM_SERVICE;
488 memcpy(password_buf.data, r->in.new_password->data, 512);
489 SIVAL(password_buf.data, 512, r->in.new_password->length);
490 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
492 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
493 DEBUG(3,("samr: failed to decode password buffer\n"));
494 return NT_STATUS_WRONG_PASSWORD;
497 /* fetch the old password hashes (at least one of both has to exist) */
499 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
500 "(&(objectClass=user)(objectSid=%s))",
501 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
502 if (ret != 1) {
503 return NT_STATUS_WRONG_PASSWORD;
506 nt_status = samdb_result_passwords(mem_ctx,
507 dce_call->conn->dce_ctx->lp_ctx,
508 res[0], &oldLmHash, &oldNtHash);
509 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
510 return NT_STATUS_WRONG_PASSWORD;
513 /* Using the sid for the account as the key, set the password */
514 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
515 creds->sid,
516 &new_password, /* we have plaintext */
517 NULL, NULL,
518 oldLmHash, oldNtHash, /* Password change */
519 NULL, NULL);
520 return nt_status;
525 netr_LogonUasLogon
527 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
528 struct netr_LogonUasLogon *r)
530 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
535 netr_LogonUasLogoff
537 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
538 struct netr_LogonUasLogoff *r)
540 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
544 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
546 switch (r->in.logon_level) {
547 case NetlogonInteractiveInformation:
548 case NetlogonServiceInformation:
549 case NetlogonInteractiveTransitiveInformation:
550 case NetlogonServiceTransitiveInformation:
551 if (r->in.logon->password == NULL) {
552 return NT_STATUS_INVALID_PARAMETER;
555 switch (r->in.validation_level) {
556 case NetlogonValidationSamInfo: /* 2 */
557 case NetlogonValidationSamInfo2: /* 3 */
558 case NetlogonValidationSamInfo4: /* 6 */
559 break;
560 default:
561 return NT_STATUS_INVALID_INFO_CLASS;
564 break;
565 case NetlogonNetworkInformation:
566 case NetlogonNetworkTransitiveInformation:
567 if (r->in.logon->network == NULL) {
568 return NT_STATUS_INVALID_PARAMETER;
571 switch (r->in.validation_level) {
572 case NetlogonValidationSamInfo: /* 2 */
573 case NetlogonValidationSamInfo2: /* 3 */
574 case NetlogonValidationSamInfo4: /* 6 */
575 break;
576 default:
577 return NT_STATUS_INVALID_INFO_CLASS;
580 break;
582 case NetlogonGenericInformation:
583 if (r->in.logon->generic == NULL) {
584 return NT_STATUS_INVALID_PARAMETER;
587 switch (r->in.validation_level) {
588 /* TODO: case NetlogonValidationGenericInfo: 4 */
589 case NetlogonValidationGenericInfo2: /* 5 */
590 break;
591 default:
592 return NT_STATUS_INVALID_INFO_CLASS;
595 break;
596 default:
597 return NT_STATUS_INVALID_PARAMETER;
600 return NT_STATUS_OK;
604 netr_LogonSamLogon_base
606 This version of the function allows other wrappers to say 'do not check the credentials'
608 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
610 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
611 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
613 struct auth4_context *auth_context;
614 struct auth_usersupplied_info *user_info;
615 struct auth_user_info_dc *user_info_dc;
616 NTSTATUS nt_status;
617 static const char zeros[16];
618 struct netr_SamBaseInfo *sam;
619 struct netr_SamInfo2 *sam2;
620 struct netr_SamInfo3 *sam3;
621 struct netr_SamInfo6 *sam6;
623 *r->out.authoritative = 1;
625 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
626 NT_STATUS_HAVE_NO_MEMORY(user_info);
628 switch (r->in.logon_level) {
629 case NetlogonInteractiveInformation:
630 case NetlogonServiceInformation:
631 case NetlogonInteractiveTransitiveInformation:
632 case NetlogonServiceTransitiveInformation:
633 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
634 netlogon_creds_arcfour_crypt(creds,
635 r->in.logon->password->lmpassword.hash,
636 sizeof(r->in.logon->password->lmpassword.hash));
637 netlogon_creds_arcfour_crypt(creds,
638 r->in.logon->password->ntpassword.hash,
639 sizeof(r->in.logon->password->ntpassword.hash));
640 } else {
641 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
642 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
645 /* TODO: we need to deny anonymous access here */
646 nt_status = auth_context_create(mem_ctx,
647 dce_call->event_ctx, dce_call->msg_ctx,
648 dce_call->conn->dce_ctx->lp_ctx,
649 &auth_context);
650 NT_STATUS_NOT_OK_RETURN(nt_status);
652 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
653 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
654 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
655 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
657 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
658 user_info->password_state = AUTH_PASSWORD_HASH;
660 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
661 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
662 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
664 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
665 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
666 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
668 break;
669 case NetlogonNetworkInformation:
670 case NetlogonNetworkTransitiveInformation:
672 /* TODO: we need to deny anonymous access here */
673 nt_status = auth_context_create(mem_ctx,
674 dce_call->event_ctx, dce_call->msg_ctx,
675 dce_call->conn->dce_ctx->lp_ctx,
676 &auth_context);
677 NT_STATUS_NOT_OK_RETURN(nt_status);
679 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
680 NT_STATUS_NOT_OK_RETURN(nt_status);
682 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
683 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
684 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
685 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
687 user_info->password_state = AUTH_PASSWORD_RESPONSE;
688 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
689 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
691 break;
694 case NetlogonGenericInformation:
696 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
697 netlogon_creds_arcfour_crypt(creds,
698 r->in.logon->generic->data, r->in.logon->generic->length);
699 } else {
700 /* Using DES to verify kerberos tickets makes no sense */
701 return NT_STATUS_INVALID_PARAMETER;
704 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
705 NTSTATUS status;
706 struct dcerpc_binding_handle *irpc_handle;
707 struct kdc_check_generic_kerberos check;
708 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
709 NT_STATUS_HAVE_NO_MEMORY(generic);
710 *r->out.authoritative = 1;
712 /* TODO: Describe and deal with these flags */
713 *r->out.flags = 0;
715 r->out.validation->generic = generic;
717 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
718 dce_call->msg_ctx,
719 "kdc_server",
720 &ndr_table_irpc);
721 if (irpc_handle == NULL) {
722 return NT_STATUS_NO_LOGON_SERVERS;
725 check.in.generic_request =
726 data_blob_const(r->in.logon->generic->data,
727 r->in.logon->generic->length);
729 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
730 mem_ctx,
731 &check);
732 if (!NT_STATUS_IS_OK(status)) {
733 return status;
735 generic->length = check.out.generic_reply.length;
736 generic->data = check.out.generic_reply.data;
737 return NT_STATUS_OK;
740 /* Until we get an implemetnation of these other packages */
741 return NT_STATUS_INVALID_PARAMETER;
743 default:
744 return NT_STATUS_INVALID_PARAMETER;
747 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
748 /* TODO: set *r->out.authoritative = 0 on specific errors */
749 NT_STATUS_NOT_OK_RETURN(nt_status);
751 switch (r->in.validation_level) {
752 case 2:
753 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
754 NT_STATUS_NOT_OK_RETURN(nt_status);
756 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
757 NT_STATUS_HAVE_NO_MEMORY(sam2);
758 sam2->base = *sam;
760 /* And put into the talloc tree */
761 talloc_steal(sam2, sam);
762 r->out.validation->sam2 = sam2;
764 sam = &sam2->base;
765 break;
767 case 3:
768 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
769 user_info_dc,
770 &sam3);
771 NT_STATUS_NOT_OK_RETURN(nt_status);
773 r->out.validation->sam3 = sam3;
775 sam = &sam3->base;
776 break;
778 case 6:
779 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
780 user_info_dc,
781 &sam3);
782 NT_STATUS_NOT_OK_RETURN(nt_status);
784 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
785 NT_STATUS_HAVE_NO_MEMORY(sam6);
786 sam6->base = sam3->base;
787 sam = &sam6->base;
788 sam6->sidcount = sam3->sidcount;
789 sam6->sids = sam3->sids;
791 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
792 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
793 sam->account_name.string, sam6->dns_domainname.string);
794 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
795 /* And put into the talloc tree */
796 talloc_steal(sam6, sam3);
798 r->out.validation->sam6 = sam6;
799 break;
801 default:
802 return NT_STATUS_INVALID_INFO_CLASS;
805 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
806 /* It appears that level 6 is not individually encrypted */
807 if ((r->in.validation_level != 6) &&
808 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
809 /* This key is sent unencrypted without the ARCFOUR flag set */
810 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
811 netlogon_creds_arcfour_crypt(creds,
812 sam->key.key,
813 sizeof(sam->key.key));
817 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
818 /* It appears that level 6 is not individually encrypted */
819 if ((r->in.validation_level != 6) &&
820 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
821 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
822 netlogon_creds_arcfour_crypt(creds,
823 sam->LMSessKey.key,
824 sizeof(sam->LMSessKey.key));
825 } else {
826 netlogon_creds_des_encrypt_LMKey(creds,
827 &sam->LMSessKey);
831 /* TODO: Describe and deal with these flags */
832 *r->out.flags = 0;
834 return NT_STATUS_OK;
837 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
838 struct netr_LogonSamLogonEx *r)
840 NTSTATUS nt_status;
841 struct netlogon_creds_CredentialState *creds;
843 *r->out.authoritative = 1;
845 nt_status = dcesrv_netr_LogonSamLogon_check(r);
846 if (!NT_STATUS_IS_OK(nt_status)) {
847 return nt_status;
850 nt_status = schannel_get_creds_state(mem_ctx,
851 dce_call->conn->dce_ctx->lp_ctx,
852 r->in.computer_name, &creds);
853 if (!NT_STATUS_IS_OK(nt_status)) {
854 return nt_status;
857 if (!dce_call->conn->auth_state.auth_info ||
858 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
859 return NT_STATUS_ACCESS_DENIED;
861 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
865 netr_LogonSamLogonWithFlags
868 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
869 struct netr_LogonSamLogonWithFlags *r)
871 NTSTATUS nt_status;
872 struct netlogon_creds_CredentialState *creds;
873 struct netr_LogonSamLogonEx r2;
875 struct netr_Authenticator *return_authenticator;
877 ZERO_STRUCT(r2);
879 r2.in.server_name = r->in.server_name;
880 r2.in.computer_name = r->in.computer_name;
881 r2.in.logon_level = r->in.logon_level;
882 r2.in.logon = r->in.logon;
883 r2.in.validation_level = r->in.validation_level;
884 r2.in.flags = r->in.flags;
885 r2.out.validation = r->out.validation;
886 r2.out.authoritative = r->out.authoritative;
887 r2.out.flags = r->out.flags;
889 *r->out.authoritative = 1;
891 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
892 if (!NT_STATUS_IS_OK(nt_status)) {
893 return nt_status;
896 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
897 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
899 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
900 mem_ctx,
901 r->in.computer_name,
902 r->in.credential, return_authenticator,
903 &creds);
904 NT_STATUS_NOT_OK_RETURN(nt_status);
906 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
908 r->out.return_authenticator = return_authenticator;
910 return nt_status;
914 netr_LogonSamLogon
916 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
917 struct netr_LogonSamLogon *r)
919 struct netr_LogonSamLogonWithFlags r2;
920 uint32_t flags = 0;
921 NTSTATUS status;
923 ZERO_STRUCT(r2);
925 r2.in.server_name = r->in.server_name;
926 r2.in.computer_name = r->in.computer_name;
927 r2.in.credential = r->in.credential;
928 r2.in.return_authenticator = r->in.return_authenticator;
929 r2.in.logon_level = r->in.logon_level;
930 r2.in.logon = r->in.logon;
931 r2.in.validation_level = r->in.validation_level;
932 r2.in.flags = &flags;
933 r2.out.validation = r->out.validation;
934 r2.out.authoritative = r->out.authoritative;
935 r2.out.flags = &flags;
937 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
939 r->out.return_authenticator = r2.out.return_authenticator;
941 return status;
946 netr_LogonSamLogoff
948 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
949 struct netr_LogonSamLogoff *r)
951 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
957 netr_DatabaseDeltas
959 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
960 struct netr_DatabaseDeltas *r)
962 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
967 netr_DatabaseSync2
969 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
970 struct netr_DatabaseSync2 *r)
972 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
973 return NT_STATUS_NOT_IMPLEMENTED;
978 netr_DatabaseSync
980 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
981 struct netr_DatabaseSync *r)
983 struct netr_DatabaseSync2 r2;
984 NTSTATUS status;
986 ZERO_STRUCT(r2);
988 r2.in.logon_server = r->in.logon_server;
989 r2.in.computername = r->in.computername;
990 r2.in.credential = r->in.credential;
991 r2.in.database_id = r->in.database_id;
992 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
993 r2.in.sync_context = r->in.sync_context;
994 r2.out.sync_context = r->out.sync_context;
995 r2.out.delta_enum_array = r->out.delta_enum_array;
996 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
998 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1000 return status;
1005 netr_AccountDeltas
1007 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1008 struct netr_AccountDeltas *r)
1010 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1011 return NT_STATUS_NOT_IMPLEMENTED;
1016 netr_AccountSync
1018 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1019 struct netr_AccountSync *r)
1021 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1022 return NT_STATUS_NOT_IMPLEMENTED;
1027 netr_GetDcName
1029 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1030 struct netr_GetDcName *r)
1032 const char * const attrs[] = { NULL };
1033 struct ldb_context *sam_ctx;
1034 struct ldb_message **res;
1035 struct ldb_dn *domain_dn;
1036 int ret;
1037 const char *dcname;
1040 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1041 * that the domainname needs to be a valid netbios domain
1042 * name, if it is not NULL.
1044 if (r->in.domainname) {
1045 const char *dot = strchr(r->in.domainname, '.');
1046 size_t len = strlen(r->in.domainname);
1048 if (dot || len > 15) {
1049 return WERR_DCNOTFOUND;
1053 * TODO: Should we also varify that only valid
1054 * netbios name characters are used?
1058 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1059 dce_call->conn->dce_ctx->lp_ctx,
1060 dce_call->conn->auth_state.session_info, 0);
1061 if (sam_ctx == NULL) {
1062 return WERR_DS_UNAVAILABLE;
1065 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1066 r->in.domainname);
1067 if (domain_dn == NULL) {
1068 return WERR_NO_SUCH_DOMAIN;
1071 ret = gendb_search_dn(sam_ctx, mem_ctx,
1072 domain_dn, &res, attrs);
1073 if (ret != 1) {
1074 return WERR_NO_SUCH_DOMAIN;
1077 /* TODO: - return real IP address
1078 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1080 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1081 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1082 W_ERROR_HAVE_NO_MEMORY(dcname);
1084 *r->out.dcname = dcname;
1085 return WERR_OK;
1090 netr_LogonControl2Ex
1092 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1093 struct netr_LogonControl2Ex *r)
1095 return WERR_NOT_SUPPORTED;
1100 netr_LogonControl
1102 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1103 struct netr_LogonControl *r)
1105 struct netr_LogonControl2Ex r2;
1106 WERROR werr;
1108 if (r->in.level == 0x00000001) {
1109 ZERO_STRUCT(r2);
1111 r2.in.logon_server = r->in.logon_server;
1112 r2.in.function_code = r->in.function_code;
1113 r2.in.level = r->in.level;
1114 r2.in.data = NULL;
1115 r2.out.query = r->out.query;
1117 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1118 } else if (r->in.level == 0x00000002) {
1119 werr = WERR_NOT_SUPPORTED;
1120 } else {
1121 werr = WERR_UNKNOWN_LEVEL;
1124 return werr;
1129 netr_LogonControl2
1131 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1132 struct netr_LogonControl2 *r)
1134 struct netr_LogonControl2Ex r2;
1135 WERROR werr;
1137 ZERO_STRUCT(r2);
1139 r2.in.logon_server = r->in.logon_server;
1140 r2.in.function_code = r->in.function_code;
1141 r2.in.level = r->in.level;
1142 r2.in.data = r->in.data;
1143 r2.out.query = r->out.query;
1145 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1147 return werr;
1150 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1151 struct ldb_context *sam_ctx,
1152 struct netr_DomainTrustList *trusts,
1153 uint32_t trust_flags);
1156 netr_GetAnyDCName
1158 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1159 struct netr_GetAnyDCName *r)
1161 struct netr_DomainTrustList *trusts;
1162 struct ldb_context *sam_ctx;
1163 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1164 uint32_t i;
1165 WERROR werr;
1167 *r->out.dcname = NULL;
1169 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1170 /* if the domainname parameter wasn't set assume our domain */
1171 r->in.domainname = lpcfg_workgroup(lp_ctx);
1174 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1175 dce_call->conn->auth_state.session_info, 0);
1176 if (sam_ctx == NULL) {
1177 return WERR_DS_UNAVAILABLE;
1180 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1181 /* well we asked for a DC of our own domain */
1182 if (samdb_is_pdc(sam_ctx)) {
1183 /* we are the PDC of the specified domain */
1184 return WERR_NO_SUCH_DOMAIN;
1187 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1188 lpcfg_netbios_name(lp_ctx));
1189 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1191 return WERR_OK;
1194 /* Okay, now we have to consider the trusted domains */
1196 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1197 W_ERROR_HAVE_NO_MEMORY(trusts);
1199 trusts->count = 0;
1201 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1202 NETR_TRUST_FLAG_INBOUND
1203 | NETR_TRUST_FLAG_OUTBOUND);
1204 W_ERROR_NOT_OK_RETURN(werr);
1206 for (i = 0; i < trusts->count; i++) {
1207 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1208 /* FIXME: Here we need to find a DC for the specified
1209 * trusted domain. */
1211 /* return WERR_OK; */
1212 return WERR_NO_SUCH_DOMAIN;
1216 return WERR_NO_SUCH_DOMAIN;
1221 netr_DatabaseRedo
1223 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1224 struct netr_DatabaseRedo *r)
1226 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1231 netr_NetrEnumerateTrustedDomains
1233 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1234 struct netr_NetrEnumerateTrustedDomains *r)
1236 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1241 netr_LogonGetCapabilities
1243 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1244 struct netr_LogonGetCapabilities *r)
1246 struct netlogon_creds_CredentialState *creds;
1247 NTSTATUS status;
1249 status = dcesrv_netr_creds_server_step_check(dce_call,
1250 mem_ctx,
1251 r->in.computer_name,
1252 r->in.credential,
1253 r->out.return_authenticator,
1254 &creds);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 DEBUG(0,(__location__ " Bad credentials - error\n"));
1258 NT_STATUS_NOT_OK_RETURN(status);
1260 if (r->in.query_level != 1) {
1261 return NT_STATUS_NOT_SUPPORTED;
1264 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1266 return NT_STATUS_OK;
1271 netr_NETRLOGONSETSERVICEBITS
1273 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1274 struct netr_NETRLOGONSETSERVICEBITS *r)
1276 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1281 netr_LogonGetTrustRid
1283 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1284 struct netr_LogonGetTrustRid *r)
1286 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1291 netr_NETRLOGONCOMPUTESERVERDIGEST
1293 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1294 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1296 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1301 netr_NETRLOGONCOMPUTECLIENTDIGEST
1303 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1304 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1306 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1312 netr_DsRGetSiteName
1314 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1315 struct netr_DsRGetSiteName *r)
1317 struct ldb_context *sam_ctx;
1318 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1320 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1321 dce_call->conn->auth_state.session_info, 0);
1322 if (sam_ctx == NULL) {
1323 return WERR_DS_UNAVAILABLE;
1327 * We assume to be a DC when we get called over NETLOGON. Hence we
1328 * get our site name always by using "samdb_server_site_name()"
1329 * and not "samdb_client_site_name()".
1331 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1332 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1334 return WERR_OK;
1339 fill in a netr_OneDomainInfo from a ldb search result
1341 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1342 struct loadparm_context *lp_ctx,
1343 struct ldb_context *sam_ctx,
1344 struct ldb_message *res,
1345 struct netr_OneDomainInfo *info,
1346 bool is_local, bool is_trust_list)
1348 ZERO_STRUCTP(info);
1350 if (is_trust_list) {
1351 /* w2k8 only fills this on trusted domains */
1352 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1353 info->trust_extension.length = 16;
1354 info->trust_extension.info->flags =
1355 NETR_TRUST_FLAG_TREEROOT |
1356 NETR_TRUST_FLAG_IN_FOREST |
1357 NETR_TRUST_FLAG_PRIMARY |
1358 NETR_TRUST_FLAG_NATIVE;
1360 info->trust_extension.info->parent_index = 0; /* should be index into array
1361 of parent */
1362 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1363 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1366 if (is_trust_list) {
1367 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1368 info->dns_forestname.string = NULL;
1369 } else {
1370 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1371 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1372 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1373 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1376 if (is_local) {
1377 info->domainname.string = lpcfg_workgroup(lp_ctx);
1378 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1379 info->domain_guid = samdb_result_guid(res, "objectGUID");
1380 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1381 } else {
1382 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1383 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1384 info->domain_guid = samdb_result_guid(res, "objectGUID");
1385 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1387 if (!is_trust_list) {
1388 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1391 return NT_STATUS_OK;
1395 netr_LogonGetDomainInfo
1396 this is called as part of the ADS domain logon procedure.
1398 It has an important role in convaying details about the client, such
1399 as Operating System, Version, Service Pack etc.
1401 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1402 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1404 struct netlogon_creds_CredentialState *creds;
1405 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1406 "securityIdentifier", "trustPartner", NULL };
1407 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1408 "msDS-SupportedEncryptionTypes", NULL };
1409 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1410 struct ldb_context *sam_ctx;
1411 struct ldb_message **res1, **res2, **res3, *new_msg;
1412 struct ldb_dn *workstation_dn;
1413 struct netr_DomainInformation *domain_info;
1414 struct netr_LsaPolicyInformation *lsa_policy_info;
1415 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1416 bool update_dns_hostname = true;
1417 int ret, ret3, i;
1418 NTSTATUS status;
1420 status = dcesrv_netr_creds_server_step_check(dce_call,
1421 mem_ctx,
1422 r->in.computer_name,
1423 r->in.credential,
1424 r->out.return_authenticator,
1425 &creds);
1426 if (!NT_STATUS_IS_OK(status)) {
1427 DEBUG(0,(__location__ " Bad credentials - error\n"));
1429 NT_STATUS_NOT_OK_RETURN(status);
1431 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1432 dce_call->conn->dce_ctx->lp_ctx,
1433 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1434 if (sam_ctx == NULL) {
1435 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1438 switch (r->in.level) {
1439 case 1: /* Domain information */
1441 if (r->in.query->workstation_info == NULL) {
1442 return NT_STATUS_INVALID_PARAMETER;
1445 /* Prepares the workstation DN */
1446 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1447 dom_sid_string(mem_ctx, creds->sid));
1448 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1450 /* Lookup for attributes in workstation object */
1451 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1452 attrs2);
1453 if (ret != 1) {
1454 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1457 /* Gets the sam account name which is checked against the DNS
1458 * hostname parameter. */
1459 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1460 "sAMAccountName",
1461 NULL);
1462 if (sam_account_name == NULL) {
1463 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1467 * Checks that the sam account name without a possible "$"
1468 * matches as prefix with the DNS hostname in the workstation
1469 * info structure.
1471 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1472 strcspn(sam_account_name, "$"));
1473 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1474 if (r->in.query->workstation_info->dns_hostname != NULL) {
1475 prefix2 = talloc_strndup(mem_ctx,
1476 r->in.query->workstation_info->dns_hostname,
1477 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1478 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1480 if (strcasecmp(prefix1, prefix2) != 0) {
1481 update_dns_hostname = false;
1483 } else {
1484 update_dns_hostname = false;
1487 /* Gets the old DNS hostname */
1488 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1489 "dNSHostName",
1490 NULL);
1493 * Updates the DNS hostname when the client wishes that the
1494 * server should handle this for him
1495 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1496 * obviously only checked when we do already have a
1497 * "dNSHostName".
1498 * See MS-NRPC section 3.5.4.3.9
1500 if ((old_dns_hostname != NULL) &&
1501 (r->in.query->workstation_info->workstation_flags
1502 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1503 update_dns_hostname = false;
1506 /* Gets host information and put them into our directory */
1508 new_msg = ldb_msg_new(mem_ctx);
1509 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1511 new_msg->dn = workstation_dn;
1513 /* Sets the OS name */
1515 if (r->in.query->workstation_info->os_name.string == NULL) {
1516 return NT_STATUS_INVALID_PARAMETER;
1519 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1520 r->in.query->workstation_info->os_name.string);
1521 if (ret != LDB_SUCCESS) {
1522 return NT_STATUS_NO_MEMORY;
1526 * Sets information from "os_version". On an empty structure
1527 * the values are cleared.
1529 if (r->in.query->workstation_info->os_version.os != NULL) {
1530 struct netr_OsVersionInfoEx *os_version;
1531 const char *os_version_str;
1533 os_version = &r->in.query->workstation_info->os_version.os->os;
1535 if (os_version->CSDVersion == NULL) {
1536 return NT_STATUS_INVALID_PARAMETER;
1539 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1540 os_version->MajorVersion,
1541 os_version->MinorVersion,
1542 os_version->BuildNumber);
1543 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1545 ret = ldb_msg_add_string(new_msg,
1546 "operatingSystemServicePack",
1547 os_version->CSDVersion);
1548 if (ret != LDB_SUCCESS) {
1549 return NT_STATUS_NO_MEMORY;
1552 ret = ldb_msg_add_string(new_msg,
1553 "operatingSystemVersion",
1554 os_version_str);
1555 if (ret != LDB_SUCCESS) {
1556 return NT_STATUS_NO_MEMORY;
1558 } else {
1559 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1560 "operatingSystemServicePack");
1561 if (ret != LDB_SUCCESS) {
1562 return NT_STATUS_NO_MEMORY;
1565 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1566 "operatingSystemVersion");
1567 if (ret != LDB_SUCCESS) {
1568 return NT_STATUS_NO_MEMORY;
1573 * If the boolean "update_dns_hostname" remained true, then we
1574 * are fine to start the update.
1576 if (update_dns_hostname) {
1577 ret = ldb_msg_add_string(new_msg,
1578 "dNSHostname",
1579 r->in.query->workstation_info->dns_hostname);
1580 if (ret != LDB_SUCCESS) {
1581 return NT_STATUS_NO_MEMORY;
1584 /* This manual "servicePrincipalName" generation is
1585 * still needed! Since the update in the samldb LDB
1586 * module does only work if the entries already exist
1587 * which isn't always the case. */
1588 ret = ldb_msg_add_string(new_msg,
1589 "servicePrincipalName",
1590 talloc_asprintf(new_msg, "HOST/%s",
1591 r->in.computer_name));
1592 if (ret != LDB_SUCCESS) {
1593 return NT_STATUS_NO_MEMORY;
1596 ret = ldb_msg_add_string(new_msg,
1597 "servicePrincipalName",
1598 talloc_asprintf(new_msg, "HOST/%s",
1599 r->in.query->workstation_info->dns_hostname));
1600 if (ret != LDB_SUCCESS) {
1601 return NT_STATUS_NO_MEMORY;
1605 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1606 DEBUG(3,("Impossible to update samdb: %s\n",
1607 ldb_errstring(sam_ctx)));
1610 talloc_free(new_msg);
1612 /* Writes back the domain information */
1614 /* We need to do two searches. The first will pull our primary
1615 domain and the second will pull any trusted domains. Our
1616 primary domain is also a "trusted" domain, so we need to
1617 put the primary domain into the lists of returned trusts as
1618 well. */
1619 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1620 &res2, attrs);
1621 if (ret != 1) {
1622 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1625 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1626 "(objectClass=trustedDomain)");
1627 if (ret3 == -1) {
1628 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1631 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1632 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1634 ZERO_STRUCTP(domain_info);
1636 /* Informations about the local and trusted domains */
1638 status = fill_one_domain_info(mem_ctx,
1639 dce_call->conn->dce_ctx->lp_ctx,
1640 sam_ctx, res2[0], &domain_info->primary_domain,
1641 true, false);
1642 NT_STATUS_NOT_OK_RETURN(status);
1644 domain_info->trusted_domain_count = ret3 + 1;
1645 domain_info->trusted_domains = talloc_array(mem_ctx,
1646 struct netr_OneDomainInfo,
1647 domain_info->trusted_domain_count);
1648 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1650 for (i=0;i<ret3;i++) {
1651 status = fill_one_domain_info(mem_ctx,
1652 dce_call->conn->dce_ctx->lp_ctx,
1653 sam_ctx, res3[i],
1654 &domain_info->trusted_domains[i],
1655 false, true);
1656 NT_STATUS_NOT_OK_RETURN(status);
1659 status = fill_one_domain_info(mem_ctx,
1660 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1661 &domain_info->trusted_domains[i], true, true);
1662 NT_STATUS_NOT_OK_RETURN(status);
1664 /* Sets the supported encryption types */
1665 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1666 "msDS-SupportedEncryptionTypes",
1667 default_supported_enc_types);
1669 /* Other host domain information */
1671 lsa_policy_info = talloc(mem_ctx,
1672 struct netr_LsaPolicyInformation);
1673 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1674 ZERO_STRUCTP(lsa_policy_info);
1676 domain_info->lsa_policy = *lsa_policy_info;
1678 /* The DNS hostname is only returned back when there is a chance
1679 * for a change. */
1680 if ((r->in.query->workstation_info->workstation_flags
1681 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1682 domain_info->dns_hostname.string = old_dns_hostname;
1683 } else {
1684 domain_info->dns_hostname.string = NULL;
1687 domain_info->workstation_flags =
1688 r->in.query->workstation_info->workstation_flags & (
1689 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1691 r->out.info->domain_info = domain_info;
1692 break;
1693 case 2: /* LSA policy information - not used at the moment */
1694 lsa_policy_info = talloc(mem_ctx,
1695 struct netr_LsaPolicyInformation);
1696 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1697 ZERO_STRUCTP(lsa_policy_info);
1699 r->out.info->lsa_policy_info = lsa_policy_info;
1700 break;
1701 default:
1702 return NT_STATUS_INVALID_LEVEL;
1703 break;
1706 return NT_STATUS_OK;
1711 netr_ServerPasswordGet
1713 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1714 struct netr_ServerPasswordGet *r)
1716 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1721 netr_NETRLOGONSENDTOSAM
1723 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1724 struct netr_NETRLOGONSENDTOSAM *r)
1726 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1731 netr_DsRGetDCNameEx2
1733 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1734 TALLOC_CTX *mem_ctx,
1735 struct netr_DsRGetDCNameEx2 *r)
1737 struct ldb_context *sam_ctx;
1738 struct netr_DsRGetDCNameInfo *info;
1739 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1740 const struct tsocket_address *remote_address;
1741 char *addr = NULL;
1742 const char *server_site_name;
1743 char *guid_str;
1744 struct netlogon_samlogon_response response;
1745 NTSTATUS status;
1746 const char *dc_name = NULL;
1747 const char *domain_name = NULL;
1748 struct interface *ifaces;
1749 const char *pdc_ip;
1751 ZERO_STRUCTP(r->out.info);
1753 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1754 dce_call->conn->auth_state.session_info, 0);
1755 if (sam_ctx == NULL) {
1756 return WERR_DS_UNAVAILABLE;
1759 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1760 if (tsocket_address_is_inet(remote_address, "ip")) {
1761 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1762 W_ERROR_HAVE_NO_MEMORY(addr);
1765 /* "server_unc" is ignored by w2k3 */
1767 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1768 return WERR_INVALID_FLAGS;
1771 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1772 r->in.flags & DS_PDC_REQUIRED &&
1773 r->in.flags & DS_KDC_REQUIRED) {
1774 return WERR_INVALID_FLAGS;
1776 if (r->in.flags & DS_IS_FLAT_NAME &&
1777 r->in.flags & DS_IS_DNS_NAME) {
1778 return WERR_INVALID_FLAGS;
1780 if (r->in.flags & DS_RETURN_DNS_NAME &&
1781 r->in.flags & DS_RETURN_FLAT_NAME) {
1782 return WERR_INVALID_FLAGS;
1784 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1785 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1786 return WERR_INVALID_FLAGS;
1789 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1790 r->in.flags &
1791 (DS_DIRECTORY_SERVICE_REQUIRED |
1792 DS_DIRECTORY_SERVICE_PREFERRED |
1793 DS_GC_SERVER_REQUIRED |
1794 DS_PDC_REQUIRED |
1795 DS_KDC_REQUIRED)) {
1796 return WERR_INVALID_FLAGS;
1799 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1800 r->in.site_name) {
1801 return WERR_INVALID_FLAGS;
1804 /* Proof server site parameter "site_name" if it was specified */
1805 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1806 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1807 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1808 server_site_name) != 0)) {
1809 return WERR_NO_SUCH_DOMAIN;
1812 guid_str = r->in.domain_guid != NULL ?
1813 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1815 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1816 r->in.domain_name,
1817 r->in.domain_name,
1818 NULL, guid_str,
1819 r->in.client_account,
1820 r->in.mask, addr,
1821 NETLOGON_NT_VERSION_5EX_WITH_IP,
1822 lp_ctx, &response, true);
1823 if (!NT_STATUS_IS_OK(status)) {
1824 return ntstatus_to_werror(status);
1828 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1829 * (O) flag when the returned forest name is in DNS format. This is here
1830 * always the case (see below).
1832 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1834 if (r->in.flags & DS_RETURN_DNS_NAME) {
1835 dc_name = response.data.nt5_ex.pdc_dns_name;
1836 domain_name = response.data.nt5_ex.dns_domain;
1838 * According to MS-NRPC 2.2.1.2.1 we should set the
1839 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1840 * the returned information is in DNS form.
1842 response.data.nt5_ex.server_type |=
1843 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1844 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1845 dc_name = response.data.nt5_ex.pdc_name;
1846 domain_name = response.data.nt5_ex.domain_name;
1847 } else {
1850 * TODO: autodetect what we need to return
1851 * based on the given arguments
1853 dc_name = response.data.nt5_ex.pdc_name;
1854 domain_name = response.data.nt5_ex.domain_name;
1857 if (!dc_name || !dc_name[0]) {
1858 return WERR_NO_SUCH_DOMAIN;
1861 if (!domain_name || !domain_name[0]) {
1862 return WERR_NO_SUCH_DOMAIN;
1865 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1866 W_ERROR_HAVE_NO_MEMORY(info);
1867 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1868 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1870 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1871 pdc_ip = iface_list_best_ip(ifaces, addr);
1872 if (pdc_ip == NULL) {
1873 pdc_ip = "127.0.0.1";
1875 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1876 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1877 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1878 info->domain_guid = response.data.nt5_ex.domain_uuid;
1879 info->domain_name = domain_name;
1880 info->forest_name = response.data.nt5_ex.forest;
1881 info->dc_flags = response.data.nt5_ex.server_type;
1882 info->dc_site_name = response.data.nt5_ex.server_site;
1883 info->client_site_name = response.data.nt5_ex.client_site;
1885 *r->out.info = info;
1887 return WERR_OK;
1891 netr_DsRGetDCNameEx
1893 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1894 struct netr_DsRGetDCNameEx *r)
1896 struct netr_DsRGetDCNameEx2 r2;
1897 WERROR werr;
1899 ZERO_STRUCT(r2);
1901 r2.in.server_unc = r->in.server_unc;
1902 r2.in.client_account = NULL;
1903 r2.in.mask = 0;
1904 r2.in.domain_guid = r->in.domain_guid;
1905 r2.in.domain_name = r->in.domain_name;
1906 r2.in.site_name = r->in.site_name;
1907 r2.in.flags = r->in.flags;
1908 r2.out.info = r->out.info;
1910 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1912 return werr;
1916 netr_DsRGetDCName
1918 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1919 struct netr_DsRGetDCName *r)
1921 struct netr_DsRGetDCNameEx2 r2;
1922 WERROR werr;
1924 ZERO_STRUCT(r2);
1926 r2.in.server_unc = r->in.server_unc;
1927 r2.in.client_account = NULL;
1928 r2.in.mask = 0;
1929 r2.in.domain_name = r->in.domain_name;
1930 r2.in.domain_guid = r->in.domain_guid;
1932 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1933 r2.in.flags = r->in.flags;
1934 r2.out.info = r->out.info;
1936 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1938 return werr;
1941 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1943 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1944 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1946 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1951 netr_NetrEnumerateTrustedDomainsEx
1953 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1954 struct netr_NetrEnumerateTrustedDomainsEx *r)
1956 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1961 netr_DsRAddressToSitenamesExW
1963 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1964 struct netr_DsRAddressToSitenamesExW *r)
1966 struct ldb_context *sam_ctx;
1967 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1968 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1969 sa_family_t sin_family;
1970 struct sockaddr_in *addr;
1971 #ifdef HAVE_IPV6
1972 struct sockaddr_in6 *addr6;
1973 char addr_str[INET6_ADDRSTRLEN];
1974 #else
1975 char addr_str[INET_ADDRSTRLEN];
1976 #endif
1977 char *subnet_name;
1978 const char *res;
1979 uint32_t i;
1981 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1982 dce_call->conn->auth_state.session_info, 0);
1983 if (sam_ctx == NULL) {
1984 return WERR_DS_UNAVAILABLE;
1987 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1988 W_ERROR_HAVE_NO_MEMORY(ctr);
1990 *r->out.ctr = ctr;
1992 ctr->count = r->in.count;
1993 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1994 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1995 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1996 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1998 for (i=0; i<ctr->count; i++) {
1999 ctr->sitename[i].string = NULL;
2000 ctr->subnetname[i].string = NULL;
2002 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2003 continue;
2005 /* The first two byte of the buffer are reserved for the
2006 * "sin_family" but for now only the first one is used. */
2007 sin_family = r->in.addresses[i].buffer[0];
2009 switch (sin_family) {
2010 case AF_INET:
2011 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2012 continue;
2014 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2015 res = inet_ntop(AF_INET, &addr->sin_addr,
2016 addr_str, sizeof(addr_str));
2017 break;
2018 #ifdef HAVE_IPV6
2019 case AF_INET6:
2020 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2021 continue;
2023 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2024 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2025 addr_str, sizeof(addr_str));
2026 break;
2027 #endif
2028 default:
2029 continue;
2032 if (res == NULL) {
2033 continue;
2036 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2037 mem_ctx,
2038 addr_str,
2039 &subnet_name);
2040 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2041 ctr->subnetname[i].string = subnet_name;
2044 return WERR_OK;
2049 netr_DsRAddressToSitenamesW
2051 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2052 struct netr_DsRAddressToSitenamesW *r)
2054 struct netr_DsRAddressToSitenamesExW r2;
2055 struct netr_DsRAddressToSitenamesWCtr *ctr;
2056 uint32_t i;
2057 WERROR werr;
2059 ZERO_STRUCT(r2);
2061 r2.in.server_name = r->in.server_name;
2062 r2.in.count = r->in.count;
2063 r2.in.addresses = r->in.addresses;
2065 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2066 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2068 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2069 W_ERROR_HAVE_NO_MEMORY(ctr);
2071 *r->out.ctr = ctr;
2073 ctr->count = r->in.count;
2074 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2075 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2077 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2079 for (i=0; i<ctr->count; i++) {
2080 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2083 return werr;
2088 netr_DsrGetDcSiteCoverageW
2090 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2091 struct netr_DsrGetDcSiteCoverageW *r)
2093 struct ldb_context *sam_ctx;
2094 struct DcSitesCtr *ctr;
2095 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2097 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2098 dce_call->conn->auth_state.session_info, 0);
2099 if (sam_ctx == NULL) {
2100 return WERR_DS_UNAVAILABLE;
2103 ctr = talloc(mem_ctx, struct DcSitesCtr);
2104 W_ERROR_HAVE_NO_MEMORY(ctr);
2106 *r->out.ctr = ctr;
2108 /* For now only return our default site */
2109 ctr->num_sites = 1;
2110 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2111 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2112 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2113 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2115 return WERR_OK;
2119 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2120 struct ldb_context *sam_ctx,
2121 struct netr_DomainTrustList *trusts,
2122 uint32_t trust_flags)
2124 struct ldb_dn *system_dn;
2125 struct ldb_message **dom_res = NULL;
2126 const char *trust_attrs[] = { "flatname", "trustPartner",
2127 "securityIdentifier", "trustDirection",
2128 "trustType", "trustAttributes", NULL };
2129 uint32_t n;
2130 int i;
2131 int ret;
2133 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2134 NETR_TRUST_FLAG_OUTBOUND))) {
2135 return WERR_INVALID_FLAGS;
2138 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2139 ldb_get_default_basedn(sam_ctx),
2140 "(&(objectClass=container)(cn=System))");
2141 if (!system_dn) {
2142 return WERR_GENERAL_FAILURE;
2145 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2146 &dom_res, trust_attrs,
2147 "(objectclass=trustedDomain)");
2149 for (i = 0; i < ret; i++) {
2150 unsigned int trust_dir;
2151 uint32_t flags = 0;
2153 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2154 "trustDirection", 0);
2156 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2157 flags |= NETR_TRUST_FLAG_INBOUND;
2159 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2160 flags |= NETR_TRUST_FLAG_OUTBOUND;
2163 if (!(flags & trust_flags)) {
2164 /* this trust direction was not requested */
2165 continue;
2168 n = trusts->count;
2169 trusts->array = talloc_realloc(trusts, trusts->array,
2170 struct netr_DomainTrust,
2171 n + 1);
2172 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2174 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2175 if (!trusts->array[n].netbios_name) {
2176 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2177 "without flatname\n",
2178 ldb_dn_get_linearized(dom_res[i]->dn)));
2181 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2183 trusts->array[n].trust_flags = flags;
2184 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2185 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2186 /* TODO: find if we have parent in the list */
2187 trusts->array[n].parent_index = 0;
2190 trusts->array[n].trust_type =
2191 ldb_msg_find_attr_as_uint(dom_res[i],
2192 "trustType", 0);
2193 trusts->array[n].trust_attributes =
2194 ldb_msg_find_attr_as_uint(dom_res[i],
2195 "trustAttributes", 0);
2197 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2198 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2199 struct dom_sid zero_sid;
2200 ZERO_STRUCT(zero_sid);
2201 trusts->array[n].sid =
2202 dom_sid_dup(trusts, &zero_sid);
2203 } else {
2204 trusts->array[n].sid =
2205 samdb_result_dom_sid(trusts, dom_res[i],
2206 "securityIdentifier");
2208 trusts->array[n].guid = GUID_zero();
2210 trusts->count = n + 1;
2213 talloc_free(dom_res);
2214 return WERR_OK;
2218 netr_DsrEnumerateDomainTrusts
2220 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2221 TALLOC_CTX *mem_ctx,
2222 struct netr_DsrEnumerateDomainTrusts *r)
2224 struct netr_DomainTrustList *trusts;
2225 struct ldb_context *sam_ctx;
2226 int ret;
2227 struct ldb_message **dom_res;
2228 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2229 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2230 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2231 const char *p;
2232 WERROR werr;
2234 if (r->in.trust_flags & 0xFFFFFE00) {
2235 return WERR_INVALID_FLAGS;
2238 /* TODO: turn to hard check once we are sure this is 100% correct */
2239 if (!r->in.server_name) {
2240 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2241 "But received NULL!\n", dnsdomain));
2242 } else {
2243 p = strchr(r->in.server_name, '.');
2244 if (!p) {
2245 DEBUG(3, ("Invalid domain! Expected name in domain "
2246 "[%s]. But received [%s]!\n",
2247 dnsdomain, r->in.server_name));
2248 p = r->in.server_name;
2249 } else {
2250 p++;
2252 if (strcasecmp(p, dnsdomain)) {
2253 DEBUG(3, ("Invalid domain! Expected name in domain "
2254 "[%s]. But received [%s]!\n",
2255 dnsdomain, r->in.server_name));
2259 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2260 W_ERROR_HAVE_NO_MEMORY(trusts);
2262 trusts->count = 0;
2263 r->out.trusts = trusts;
2265 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2266 dce_call->conn->auth_state.session_info, 0);
2267 if (sam_ctx == NULL) {
2268 return WERR_GENERAL_FAILURE;
2271 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2272 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2274 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2275 trusts, r->in.trust_flags);
2276 W_ERROR_NOT_OK_RETURN(werr);
2279 /* NOTE: we currently are always the root of the forest */
2280 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2281 uint32_t n = trusts->count;
2283 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2284 &dom_res, dom_attrs);
2285 if (ret != 1) {
2286 return WERR_GENERAL_FAILURE;
2289 trusts->count = n + 1;
2290 trusts->array = talloc_realloc(trusts, trusts->array,
2291 struct netr_DomainTrust,
2292 trusts->count);
2293 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2295 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2296 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2297 trusts->array[n].trust_flags =
2298 NETR_TRUST_FLAG_NATIVE |
2299 NETR_TRUST_FLAG_TREEROOT |
2300 NETR_TRUST_FLAG_IN_FOREST |
2301 NETR_TRUST_FLAG_PRIMARY;
2302 /* we are always the root domain for now */
2303 trusts->array[n].parent_index = 0;
2304 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2305 trusts->array[n].trust_attributes = 0;
2306 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2307 dom_res[0],
2308 "objectSid");
2309 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2310 "objectGUID");
2311 talloc_free(dom_res);
2314 return WERR_OK;
2319 netr_DsrDeregisterDNSHostRecords
2321 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2322 struct netr_DsrDeregisterDNSHostRecords *r)
2324 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2329 netr_ServerTrustPasswordsGet
2331 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2332 struct netr_ServerTrustPasswordsGet *r)
2334 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2338 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2339 struct ldb_context *sam_ctx,
2340 struct loadparm_context *lp_ctx,
2341 struct lsa_ForestTrustInformation *info)
2343 struct lsa_ForestTrustDomainInfo *domain_info;
2344 struct lsa_ForestTrustRecord *e;
2345 struct ldb_message **dom_res;
2346 const char * const dom_attrs[] = { "objectSid", NULL };
2347 int ret;
2349 /* we need to provide 2 entries:
2350 * 1. the Root Forest name
2351 * 2. the Domain Information
2354 info->count = 2;
2355 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2356 W_ERROR_HAVE_NO_MEMORY(info->entries);
2358 /* Forest root info */
2359 e = talloc(info, struct lsa_ForestTrustRecord);
2360 W_ERROR_HAVE_NO_MEMORY(e);
2362 e->flags = 0;
2363 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2364 e->time = 0; /* so far always 0 in trces. */
2365 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2366 mem_ctx);
2367 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2369 info->entries[0] = e;
2371 /* Domain info */
2372 e = talloc(info, struct lsa_ForestTrustRecord);
2373 W_ERROR_HAVE_NO_MEMORY(e);
2375 /* get our own domain info */
2376 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2377 if (ret != 1) {
2378 return WERR_GENERAL_FAILURE;
2381 /* TODO: check if disabled and set flags accordingly */
2382 e->flags = 0;
2383 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2384 e->time = 0; /* so far always 0 in traces. */
2386 domain_info = &e->forest_trust_data.domain_info;
2387 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2388 "objectSid");
2389 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2390 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2392 info->entries[1] = e;
2394 talloc_free(dom_res);
2396 return WERR_OK;
2400 netr_DsRGetForestTrustInformation
2402 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2403 TALLOC_CTX *mem_ctx,
2404 struct netr_DsRGetForestTrustInformation *r)
2406 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2407 struct lsa_ForestTrustInformation *info, **info_ptr;
2408 struct ldb_context *sam_ctx;
2409 WERROR werr;
2411 if (r->in.flags & 0xFFFFFFFE) {
2412 return WERR_INVALID_FLAGS;
2415 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2416 dce_call->conn->auth_state.session_info, 0);
2417 if (sam_ctx == NULL) {
2418 return WERR_GENERAL_FAILURE;
2421 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2422 if (!samdb_is_pdc(sam_ctx)) {
2423 return WERR_NERR_NOTPRIMARY;
2426 if (r->in.trusted_domain_name == NULL) {
2427 return WERR_INVALID_FLAGS;
2430 /* TODO: establish an schannel connection with
2431 * r->in.trusted_domain_name and perform a
2432 * netr_GetForestTrustInformation call against it */
2434 /* for now return not implementd */
2435 return WERR_CALL_NOT_IMPLEMENTED;
2438 /* TODO: check r->in.server_name is our name */
2440 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2441 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2443 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2444 W_ERROR_HAVE_NO_MEMORY(info);
2446 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2447 W_ERROR_NOT_OK_RETURN(werr);
2449 *info_ptr = info;
2450 r->out.forest_trust_info = info_ptr;
2452 return WERR_OK;
2457 netr_GetForestTrustInformation
2459 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2460 TALLOC_CTX *mem_ctx,
2461 struct netr_GetForestTrustInformation *r)
2463 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2464 struct netlogon_creds_CredentialState *creds;
2465 struct lsa_ForestTrustInformation *info, **info_ptr;
2466 struct ldb_context *sam_ctx;
2467 NTSTATUS status;
2468 WERROR werr;
2470 status = dcesrv_netr_creds_server_step_check(dce_call,
2471 mem_ctx,
2472 r->in.computer_name,
2473 r->in.credential,
2474 r->out.return_authenticator,
2475 &creds);
2476 if (!NT_STATUS_IS_OK(status)) {
2477 return status;
2480 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2481 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2482 return NT_STATUS_NOT_IMPLEMENTED;
2485 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2486 dce_call->conn->auth_state.session_info, 0);
2487 if (sam_ctx == NULL) {
2488 return NT_STATUS_INTERNAL_ERROR;
2491 /* TODO: check r->in.server_name is our name */
2493 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2494 if (!info_ptr) {
2495 return NT_STATUS_NO_MEMORY;
2497 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2498 if (!info) {
2499 return NT_STATUS_NO_MEMORY;
2502 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2503 if (!W_ERROR_IS_OK(werr)) {
2504 return werror_to_ntstatus(werr);
2507 *info_ptr = info;
2508 r->out.forest_trust_info = info_ptr;
2510 return NT_STATUS_OK;
2515 netr_ServerGetTrustInfo
2517 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2518 struct netr_ServerGetTrustInfo *r)
2520 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2524 netr_Unused47
2526 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2527 struct netr_Unused47 *r)
2529 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2533 struct netr_dnsupdate_RODC_state {
2534 struct dcesrv_call_state *dce_call;
2535 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2536 struct dnsupdate_RODC *r2;
2540 called when the forwarded RODC dns update request is finished
2542 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2544 struct netr_dnsupdate_RODC_state *st =
2545 tevent_req_callback_data(subreq,
2546 struct netr_dnsupdate_RODC_state);
2547 NTSTATUS status;
2549 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2550 TALLOC_FREE(subreq);
2551 if (!NT_STATUS_IS_OK(status)) {
2552 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2553 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2556 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2558 status = dcesrv_reply(st->dce_call);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2565 netr_DsrUpdateReadOnlyServerDnsRecords
2567 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2568 TALLOC_CTX *mem_ctx,
2569 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2571 struct netlogon_creds_CredentialState *creds;
2572 NTSTATUS nt_status;
2573 struct dcerpc_binding_handle *binding_handle;
2574 struct netr_dnsupdate_RODC_state *st;
2575 struct tevent_req *subreq;
2577 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2578 mem_ctx,
2579 r->in.computer_name,
2580 r->in.credential,
2581 r->out.return_authenticator,
2582 &creds);
2583 NT_STATUS_NOT_OK_RETURN(nt_status);
2585 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2586 return NT_STATUS_ACCESS_DENIED;
2589 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2590 NT_STATUS_HAVE_NO_MEMORY(st);
2592 st->dce_call = dce_call;
2593 st->r = r;
2594 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2595 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2597 st->r2->in.dom_sid = creds->sid;
2598 st->r2->in.site_name = r->in.site_name;
2599 st->r2->in.dns_ttl = r->in.dns_ttl;
2600 st->r2->in.dns_names = r->in.dns_names;
2601 st->r2->out.dns_names = r->out.dns_names;
2603 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2604 "dnsupdate", &ndr_table_irpc);
2605 if (binding_handle == NULL) {
2606 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2607 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2608 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2611 /* forward the call */
2612 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2613 binding_handle, st->r2);
2614 NT_STATUS_HAVE_NO_MEMORY(subreq);
2616 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2618 /* setup the callback */
2619 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2621 return NT_STATUS_OK;
2625 /* include the generated boilerplate */
2626 #include "librpc/gen_ndr/ndr_netlogon_s.c"