s4:rpc_server/netlogon: add support for AES based netlogon schannel
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob309601e9da60f5699a60690f789165872d580ed9
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;
1690 r->out.info->domain_info = domain_info;
1691 break;
1692 case 2: /* LSA policy information - not used at the moment */
1693 lsa_policy_info = talloc(mem_ctx,
1694 struct netr_LsaPolicyInformation);
1695 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1696 ZERO_STRUCTP(lsa_policy_info);
1698 r->out.info->lsa_policy_info = lsa_policy_info;
1699 break;
1700 default:
1701 return NT_STATUS_INVALID_LEVEL;
1702 break;
1705 return NT_STATUS_OK;
1710 netr_ServerPasswordGet
1712 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1713 struct netr_ServerPasswordGet *r)
1715 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1720 netr_NETRLOGONSENDTOSAM
1722 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1723 struct netr_NETRLOGONSENDTOSAM *r)
1725 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1730 netr_DsRGetDCNameEx2
1732 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1733 TALLOC_CTX *mem_ctx,
1734 struct netr_DsRGetDCNameEx2 *r)
1736 struct ldb_context *sam_ctx;
1737 struct netr_DsRGetDCNameInfo *info;
1738 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1739 const struct tsocket_address *remote_address;
1740 char *addr = NULL;
1741 const char *server_site_name;
1742 char *guid_str;
1743 struct netlogon_samlogon_response response;
1744 NTSTATUS status;
1745 const char *dc_name = NULL;
1746 const char *domain_name = NULL;
1747 struct interface *ifaces;
1748 const char *pdc_ip;
1750 ZERO_STRUCTP(r->out.info);
1752 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1753 dce_call->conn->auth_state.session_info, 0);
1754 if (sam_ctx == NULL) {
1755 return WERR_DS_UNAVAILABLE;
1758 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1759 if (tsocket_address_is_inet(remote_address, "ip")) {
1760 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1761 W_ERROR_HAVE_NO_MEMORY(addr);
1764 /* "server_unc" is ignored by w2k3 */
1766 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1767 return WERR_INVALID_FLAGS;
1770 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1771 r->in.flags & DS_PDC_REQUIRED &&
1772 r->in.flags & DS_KDC_REQUIRED) {
1773 return WERR_INVALID_FLAGS;
1775 if (r->in.flags & DS_IS_FLAT_NAME &&
1776 r->in.flags & DS_IS_DNS_NAME) {
1777 return WERR_INVALID_FLAGS;
1779 if (r->in.flags & DS_RETURN_DNS_NAME &&
1780 r->in.flags & DS_RETURN_FLAT_NAME) {
1781 return WERR_INVALID_FLAGS;
1783 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1784 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1785 return WERR_INVALID_FLAGS;
1788 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1789 r->in.flags &
1790 (DS_DIRECTORY_SERVICE_REQUIRED |
1791 DS_DIRECTORY_SERVICE_PREFERRED |
1792 DS_GC_SERVER_REQUIRED |
1793 DS_PDC_REQUIRED |
1794 DS_KDC_REQUIRED)) {
1795 return WERR_INVALID_FLAGS;
1798 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1799 r->in.site_name) {
1800 return WERR_INVALID_FLAGS;
1803 /* Proof server site parameter "site_name" if it was specified */
1804 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1805 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1806 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1807 server_site_name) != 0)) {
1808 return WERR_NO_SUCH_DOMAIN;
1811 guid_str = r->in.domain_guid != NULL ?
1812 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1814 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1815 r->in.domain_name,
1816 r->in.domain_name,
1817 NULL, guid_str,
1818 r->in.client_account,
1819 r->in.mask, addr,
1820 NETLOGON_NT_VERSION_5EX_WITH_IP,
1821 lp_ctx, &response, true);
1822 if (!NT_STATUS_IS_OK(status)) {
1823 return ntstatus_to_werror(status);
1827 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1828 * (O) flag when the returned forest name is in DNS format. This is here
1829 * always the case (see below).
1831 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1833 if (r->in.flags & DS_RETURN_DNS_NAME) {
1834 dc_name = response.data.nt5_ex.pdc_dns_name;
1835 domain_name = response.data.nt5_ex.dns_domain;
1837 * According to MS-NRPC 2.2.1.2.1 we should set the
1838 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1839 * the returned information is in DNS form.
1841 response.data.nt5_ex.server_type |=
1842 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1843 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1844 dc_name = response.data.nt5_ex.pdc_name;
1845 domain_name = response.data.nt5_ex.domain_name;
1846 } else {
1849 * TODO: autodetect what we need to return
1850 * based on the given arguments
1852 dc_name = response.data.nt5_ex.pdc_name;
1853 domain_name = response.data.nt5_ex.domain_name;
1856 if (!dc_name || !dc_name[0]) {
1857 return WERR_NO_SUCH_DOMAIN;
1860 if (!domain_name || !domain_name[0]) {
1861 return WERR_NO_SUCH_DOMAIN;
1864 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1865 W_ERROR_HAVE_NO_MEMORY(info);
1866 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1867 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1869 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1870 pdc_ip = iface_list_best_ip(ifaces, addr);
1871 if (pdc_ip == NULL) {
1872 pdc_ip = "127.0.0.1";
1874 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1875 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1876 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1877 info->domain_guid = response.data.nt5_ex.domain_uuid;
1878 info->domain_name = domain_name;
1879 info->forest_name = response.data.nt5_ex.forest;
1880 info->dc_flags = response.data.nt5_ex.server_type;
1881 info->dc_site_name = response.data.nt5_ex.server_site;
1882 info->client_site_name = response.data.nt5_ex.client_site;
1884 *r->out.info = info;
1886 return WERR_OK;
1890 netr_DsRGetDCNameEx
1892 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1893 struct netr_DsRGetDCNameEx *r)
1895 struct netr_DsRGetDCNameEx2 r2;
1896 WERROR werr;
1898 ZERO_STRUCT(r2);
1900 r2.in.server_unc = r->in.server_unc;
1901 r2.in.client_account = NULL;
1902 r2.in.mask = 0;
1903 r2.in.domain_guid = r->in.domain_guid;
1904 r2.in.domain_name = r->in.domain_name;
1905 r2.in.site_name = r->in.site_name;
1906 r2.in.flags = r->in.flags;
1907 r2.out.info = r->out.info;
1909 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1911 return werr;
1915 netr_DsRGetDCName
1917 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1918 struct netr_DsRGetDCName *r)
1920 struct netr_DsRGetDCNameEx2 r2;
1921 WERROR werr;
1923 ZERO_STRUCT(r2);
1925 r2.in.server_unc = r->in.server_unc;
1926 r2.in.client_account = NULL;
1927 r2.in.mask = 0;
1928 r2.in.domain_name = r->in.domain_name;
1929 r2.in.domain_guid = r->in.domain_guid;
1931 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1932 r2.in.flags = r->in.flags;
1933 r2.out.info = r->out.info;
1935 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1937 return werr;
1940 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1942 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1943 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1945 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1950 netr_NetrEnumerateTrustedDomainsEx
1952 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1953 struct netr_NetrEnumerateTrustedDomainsEx *r)
1955 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1960 netr_DsRAddressToSitenamesExW
1962 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1963 struct netr_DsRAddressToSitenamesExW *r)
1965 struct ldb_context *sam_ctx;
1966 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1967 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1968 sa_family_t sin_family;
1969 struct sockaddr_in *addr;
1970 #ifdef HAVE_IPV6
1971 struct sockaddr_in6 *addr6;
1972 char addr_str[INET6_ADDRSTRLEN];
1973 #else
1974 char addr_str[INET_ADDRSTRLEN];
1975 #endif
1976 char *subnet_name;
1977 const char *res;
1978 uint32_t i;
1980 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1981 dce_call->conn->auth_state.session_info, 0);
1982 if (sam_ctx == NULL) {
1983 return WERR_DS_UNAVAILABLE;
1986 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1987 W_ERROR_HAVE_NO_MEMORY(ctr);
1989 *r->out.ctr = ctr;
1991 ctr->count = r->in.count;
1992 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1993 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1994 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1995 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1997 for (i=0; i<ctr->count; i++) {
1998 ctr->sitename[i].string = NULL;
1999 ctr->subnetname[i].string = NULL;
2001 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2002 continue;
2004 /* The first two byte of the buffer are reserved for the
2005 * "sin_family" but for now only the first one is used. */
2006 sin_family = r->in.addresses[i].buffer[0];
2008 switch (sin_family) {
2009 case AF_INET:
2010 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2011 continue;
2013 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2014 res = inet_ntop(AF_INET, &addr->sin_addr,
2015 addr_str, sizeof(addr_str));
2016 break;
2017 #ifdef HAVE_IPV6
2018 case AF_INET6:
2019 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2020 continue;
2022 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2023 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2024 addr_str, sizeof(addr_str));
2025 break;
2026 #endif
2027 default:
2028 continue;
2031 if (res == NULL) {
2032 continue;
2035 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2036 mem_ctx,
2037 addr_str,
2038 &subnet_name);
2039 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2040 ctr->subnetname[i].string = subnet_name;
2043 return WERR_OK;
2048 netr_DsRAddressToSitenamesW
2050 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2051 struct netr_DsRAddressToSitenamesW *r)
2053 struct netr_DsRAddressToSitenamesExW r2;
2054 struct netr_DsRAddressToSitenamesWCtr *ctr;
2055 uint32_t i;
2056 WERROR werr;
2058 ZERO_STRUCT(r2);
2060 r2.in.server_name = r->in.server_name;
2061 r2.in.count = r->in.count;
2062 r2.in.addresses = r->in.addresses;
2064 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2065 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2067 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2068 W_ERROR_HAVE_NO_MEMORY(ctr);
2070 *r->out.ctr = ctr;
2072 ctr->count = r->in.count;
2073 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2074 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2076 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2078 for (i=0; i<ctr->count; i++) {
2079 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2082 return werr;
2087 netr_DsrGetDcSiteCoverageW
2089 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2090 struct netr_DsrGetDcSiteCoverageW *r)
2092 struct ldb_context *sam_ctx;
2093 struct DcSitesCtr *ctr;
2094 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2096 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2097 dce_call->conn->auth_state.session_info, 0);
2098 if (sam_ctx == NULL) {
2099 return WERR_DS_UNAVAILABLE;
2102 ctr = talloc(mem_ctx, struct DcSitesCtr);
2103 W_ERROR_HAVE_NO_MEMORY(ctr);
2105 *r->out.ctr = ctr;
2107 /* For now only return our default site */
2108 ctr->num_sites = 1;
2109 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2110 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2111 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2112 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2114 return WERR_OK;
2118 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2119 struct ldb_context *sam_ctx,
2120 struct netr_DomainTrustList *trusts,
2121 uint32_t trust_flags)
2123 struct ldb_dn *system_dn;
2124 struct ldb_message **dom_res = NULL;
2125 const char *trust_attrs[] = { "flatname", "trustPartner",
2126 "securityIdentifier", "trustDirection",
2127 "trustType", "trustAttributes", NULL };
2128 uint32_t n;
2129 int i;
2130 int ret;
2132 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2133 NETR_TRUST_FLAG_OUTBOUND))) {
2134 return WERR_INVALID_FLAGS;
2137 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2138 ldb_get_default_basedn(sam_ctx),
2139 "(&(objectClass=container)(cn=System))");
2140 if (!system_dn) {
2141 return WERR_GENERAL_FAILURE;
2144 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2145 &dom_res, trust_attrs,
2146 "(objectclass=trustedDomain)");
2148 for (i = 0; i < ret; i++) {
2149 unsigned int trust_dir;
2150 uint32_t flags = 0;
2152 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2153 "trustDirection", 0);
2155 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2156 flags |= NETR_TRUST_FLAG_INBOUND;
2158 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2159 flags |= NETR_TRUST_FLAG_OUTBOUND;
2162 if (!(flags & trust_flags)) {
2163 /* this trust direction was not requested */
2164 continue;
2167 n = trusts->count;
2168 trusts->array = talloc_realloc(trusts, trusts->array,
2169 struct netr_DomainTrust,
2170 n + 1);
2171 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2173 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2174 if (!trusts->array[n].netbios_name) {
2175 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2176 "without flatname\n",
2177 ldb_dn_get_linearized(dom_res[i]->dn)));
2180 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2182 trusts->array[n].trust_flags = flags;
2183 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2184 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2185 /* TODO: find if we have parent in the list */
2186 trusts->array[n].parent_index = 0;
2189 trusts->array[n].trust_type =
2190 ldb_msg_find_attr_as_uint(dom_res[i],
2191 "trustType", 0);
2192 trusts->array[n].trust_attributes =
2193 ldb_msg_find_attr_as_uint(dom_res[i],
2194 "trustAttributes", 0);
2196 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2197 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2198 struct dom_sid zero_sid;
2199 ZERO_STRUCT(zero_sid);
2200 trusts->array[n].sid =
2201 dom_sid_dup(trusts, &zero_sid);
2202 } else {
2203 trusts->array[n].sid =
2204 samdb_result_dom_sid(trusts, dom_res[i],
2205 "securityIdentifier");
2207 trusts->array[n].guid = GUID_zero();
2209 trusts->count = n + 1;
2212 talloc_free(dom_res);
2213 return WERR_OK;
2217 netr_DsrEnumerateDomainTrusts
2219 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2220 TALLOC_CTX *mem_ctx,
2221 struct netr_DsrEnumerateDomainTrusts *r)
2223 struct netr_DomainTrustList *trusts;
2224 struct ldb_context *sam_ctx;
2225 int ret;
2226 struct ldb_message **dom_res;
2227 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2228 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2229 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2230 const char *p;
2231 WERROR werr;
2233 if (r->in.trust_flags & 0xFFFFFE00) {
2234 return WERR_INVALID_FLAGS;
2237 /* TODO: turn to hard check once we are sure this is 100% correct */
2238 if (!r->in.server_name) {
2239 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2240 "But received NULL!\n", dnsdomain));
2241 } else {
2242 p = strchr(r->in.server_name, '.');
2243 if (!p) {
2244 DEBUG(3, ("Invalid domain! Expected name in domain "
2245 "[%s]. But received [%s]!\n",
2246 dnsdomain, r->in.server_name));
2247 p = r->in.server_name;
2248 } else {
2249 p++;
2251 if (strcasecmp(p, dnsdomain)) {
2252 DEBUG(3, ("Invalid domain! Expected name in domain "
2253 "[%s]. But received [%s]!\n",
2254 dnsdomain, r->in.server_name));
2258 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2259 W_ERROR_HAVE_NO_MEMORY(trusts);
2261 trusts->count = 0;
2262 r->out.trusts = trusts;
2264 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2265 dce_call->conn->auth_state.session_info, 0);
2266 if (sam_ctx == NULL) {
2267 return WERR_GENERAL_FAILURE;
2270 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2271 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2273 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2274 trusts, r->in.trust_flags);
2275 W_ERROR_NOT_OK_RETURN(werr);
2278 /* NOTE: we currently are always the root of the forest */
2279 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2280 uint32_t n = trusts->count;
2282 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2283 &dom_res, dom_attrs);
2284 if (ret != 1) {
2285 return WERR_GENERAL_FAILURE;
2288 trusts->count = n + 1;
2289 trusts->array = talloc_realloc(trusts, trusts->array,
2290 struct netr_DomainTrust,
2291 trusts->count);
2292 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2294 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2295 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2296 trusts->array[n].trust_flags =
2297 NETR_TRUST_FLAG_NATIVE |
2298 NETR_TRUST_FLAG_TREEROOT |
2299 NETR_TRUST_FLAG_IN_FOREST |
2300 NETR_TRUST_FLAG_PRIMARY;
2301 /* we are always the root domain for now */
2302 trusts->array[n].parent_index = 0;
2303 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2304 trusts->array[n].trust_attributes = 0;
2305 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2306 dom_res[0],
2307 "objectSid");
2308 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2309 "objectGUID");
2310 talloc_free(dom_res);
2313 return WERR_OK;
2318 netr_DsrDeregisterDNSHostRecords
2320 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2321 struct netr_DsrDeregisterDNSHostRecords *r)
2323 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2328 netr_ServerTrustPasswordsGet
2330 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2331 struct netr_ServerTrustPasswordsGet *r)
2333 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2337 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2338 struct ldb_context *sam_ctx,
2339 struct loadparm_context *lp_ctx,
2340 struct lsa_ForestTrustInformation *info)
2342 struct lsa_ForestTrustDomainInfo *domain_info;
2343 struct lsa_ForestTrustRecord *e;
2344 struct ldb_message **dom_res;
2345 const char * const dom_attrs[] = { "objectSid", NULL };
2346 int ret;
2348 /* we need to provide 2 entries:
2349 * 1. the Root Forest name
2350 * 2. the Domain Information
2353 info->count = 2;
2354 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2355 W_ERROR_HAVE_NO_MEMORY(info->entries);
2357 /* Forest root info */
2358 e = talloc(info, struct lsa_ForestTrustRecord);
2359 W_ERROR_HAVE_NO_MEMORY(e);
2361 e->flags = 0;
2362 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2363 e->time = 0; /* so far always 0 in trces. */
2364 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2365 mem_ctx);
2366 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2368 info->entries[0] = e;
2370 /* Domain info */
2371 e = talloc(info, struct lsa_ForestTrustRecord);
2372 W_ERROR_HAVE_NO_MEMORY(e);
2374 /* get our own domain info */
2375 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2376 if (ret != 1) {
2377 return WERR_GENERAL_FAILURE;
2380 /* TODO: check if disabled and set flags accordingly */
2381 e->flags = 0;
2382 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2383 e->time = 0; /* so far always 0 in traces. */
2385 domain_info = &e->forest_trust_data.domain_info;
2386 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2387 "objectSid");
2388 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2389 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2391 info->entries[1] = e;
2393 talloc_free(dom_res);
2395 return WERR_OK;
2399 netr_DsRGetForestTrustInformation
2401 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2402 TALLOC_CTX *mem_ctx,
2403 struct netr_DsRGetForestTrustInformation *r)
2405 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2406 struct lsa_ForestTrustInformation *info, **info_ptr;
2407 struct ldb_context *sam_ctx;
2408 WERROR werr;
2410 if (r->in.flags & 0xFFFFFFFE) {
2411 return WERR_INVALID_FLAGS;
2414 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2415 dce_call->conn->auth_state.session_info, 0);
2416 if (sam_ctx == NULL) {
2417 return WERR_GENERAL_FAILURE;
2420 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2421 if (!samdb_is_pdc(sam_ctx)) {
2422 return WERR_NERR_NOTPRIMARY;
2425 if (r->in.trusted_domain_name == NULL) {
2426 return WERR_INVALID_FLAGS;
2429 /* TODO: establish an schannel connection with
2430 * r->in.trusted_domain_name and perform a
2431 * netr_GetForestTrustInformation call against it */
2433 /* for now return not implementd */
2434 return WERR_CALL_NOT_IMPLEMENTED;
2437 /* TODO: check r->in.server_name is our name */
2439 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2440 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2442 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2443 W_ERROR_HAVE_NO_MEMORY(info);
2445 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2446 W_ERROR_NOT_OK_RETURN(werr);
2448 *info_ptr = info;
2449 r->out.forest_trust_info = info_ptr;
2451 return WERR_OK;
2456 netr_GetForestTrustInformation
2458 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2459 TALLOC_CTX *mem_ctx,
2460 struct netr_GetForestTrustInformation *r)
2462 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2463 struct netlogon_creds_CredentialState *creds;
2464 struct lsa_ForestTrustInformation *info, **info_ptr;
2465 struct ldb_context *sam_ctx;
2466 NTSTATUS status;
2467 WERROR werr;
2469 status = dcesrv_netr_creds_server_step_check(dce_call,
2470 mem_ctx,
2471 r->in.computer_name,
2472 r->in.credential,
2473 r->out.return_authenticator,
2474 &creds);
2475 if (!NT_STATUS_IS_OK(status)) {
2476 return status;
2479 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2480 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2481 return NT_STATUS_NOT_IMPLEMENTED;
2484 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2485 dce_call->conn->auth_state.session_info, 0);
2486 if (sam_ctx == NULL) {
2487 return NT_STATUS_INTERNAL_ERROR;
2490 /* TODO: check r->in.server_name is our name */
2492 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2493 if (!info_ptr) {
2494 return NT_STATUS_NO_MEMORY;
2496 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2497 if (!info) {
2498 return NT_STATUS_NO_MEMORY;
2501 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2502 if (!W_ERROR_IS_OK(werr)) {
2503 return werror_to_ntstatus(werr);
2506 *info_ptr = info;
2507 r->out.forest_trust_info = info_ptr;
2509 return NT_STATUS_OK;
2514 netr_ServerGetTrustInfo
2516 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2517 struct netr_ServerGetTrustInfo *r)
2519 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2523 netr_Unused47
2525 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2526 struct netr_Unused47 *r)
2528 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2532 struct netr_dnsupdate_RODC_state {
2533 struct dcesrv_call_state *dce_call;
2534 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2535 struct dnsupdate_RODC *r2;
2539 called when the forwarded RODC dns update request is finished
2541 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2543 struct netr_dnsupdate_RODC_state *st =
2544 tevent_req_callback_data(subreq,
2545 struct netr_dnsupdate_RODC_state);
2546 NTSTATUS status;
2548 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2549 TALLOC_FREE(subreq);
2550 if (!NT_STATUS_IS_OK(status)) {
2551 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2552 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2555 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2557 status = dcesrv_reply(st->dce_call);
2558 if (!NT_STATUS_IS_OK(status)) {
2559 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2564 netr_DsrUpdateReadOnlyServerDnsRecords
2566 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2567 TALLOC_CTX *mem_ctx,
2568 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2570 struct netlogon_creds_CredentialState *creds;
2571 NTSTATUS nt_status;
2572 struct dcerpc_binding_handle *binding_handle;
2573 struct netr_dnsupdate_RODC_state *st;
2574 struct tevent_req *subreq;
2576 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2577 mem_ctx,
2578 r->in.computer_name,
2579 r->in.credential,
2580 r->out.return_authenticator,
2581 &creds);
2582 NT_STATUS_NOT_OK_RETURN(nt_status);
2584 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2585 return NT_STATUS_ACCESS_DENIED;
2588 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2589 NT_STATUS_HAVE_NO_MEMORY(st);
2591 st->dce_call = dce_call;
2592 st->r = r;
2593 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2594 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2596 st->r2->in.dom_sid = creds->sid;
2597 st->r2->in.site_name = r->in.site_name;
2598 st->r2->in.dns_ttl = r->in.dns_ttl;
2599 st->r2->in.dns_names = r->in.dns_names;
2600 st->r2->out.dns_names = r->out.dns_names;
2602 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2603 "dnsupdate", &ndr_table_irpc);
2604 if (binding_handle == NULL) {
2605 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2606 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2607 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2610 /* forward the call */
2611 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2612 binding_handle, st->r2);
2613 NT_STATUS_HAVE_NO_MEMORY(subreq);
2615 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2617 /* setup the callback */
2618 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2620 return NT_STATUS_OK;
2624 /* include the generated boilerplate */
2625 #include "librpc/gen_ndr/ndr_netlogon_s.c"