s4-rpc_server: use netlogon_creds_encrypt_samlogon().
[Samba/gebeck_regimport.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobd463e85af15b571b44d1e3ca4a84770d29d95d6c
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);
491 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
492 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
493 } else {
494 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
497 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
498 DEBUG(3,("samr: failed to decode password buffer\n"));
499 return NT_STATUS_WRONG_PASSWORD;
502 /* fetch the old password hashes (at least one of both has to exist) */
504 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
505 "(&(objectClass=user)(objectSid=%s))",
506 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
507 if (ret != 1) {
508 return NT_STATUS_WRONG_PASSWORD;
511 nt_status = samdb_result_passwords(mem_ctx,
512 dce_call->conn->dce_ctx->lp_ctx,
513 res[0], &oldLmHash, &oldNtHash);
514 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
515 return NT_STATUS_WRONG_PASSWORD;
518 /* Using the sid for the account as the key, set the password */
519 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
520 creds->sid,
521 &new_password, /* we have plaintext */
522 NULL, NULL,
523 oldLmHash, oldNtHash, /* Password change */
524 NULL, NULL);
525 return nt_status;
530 netr_LogonUasLogon
532 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
533 struct netr_LogonUasLogon *r)
535 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
540 netr_LogonUasLogoff
542 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
543 struct netr_LogonUasLogoff *r)
545 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
549 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
551 switch (r->in.logon_level) {
552 case NetlogonInteractiveInformation:
553 case NetlogonServiceInformation:
554 case NetlogonInteractiveTransitiveInformation:
555 case NetlogonServiceTransitiveInformation:
556 if (r->in.logon->password == NULL) {
557 return NT_STATUS_INVALID_PARAMETER;
560 switch (r->in.validation_level) {
561 case NetlogonValidationSamInfo: /* 2 */
562 case NetlogonValidationSamInfo2: /* 3 */
563 case NetlogonValidationSamInfo4: /* 6 */
564 break;
565 default:
566 return NT_STATUS_INVALID_INFO_CLASS;
569 break;
570 case NetlogonNetworkInformation:
571 case NetlogonNetworkTransitiveInformation:
572 if (r->in.logon->network == NULL) {
573 return NT_STATUS_INVALID_PARAMETER;
576 switch (r->in.validation_level) {
577 case NetlogonValidationSamInfo: /* 2 */
578 case NetlogonValidationSamInfo2: /* 3 */
579 case NetlogonValidationSamInfo4: /* 6 */
580 break;
581 default:
582 return NT_STATUS_INVALID_INFO_CLASS;
585 break;
587 case NetlogonGenericInformation:
588 if (r->in.logon->generic == NULL) {
589 return NT_STATUS_INVALID_PARAMETER;
592 switch (r->in.validation_level) {
593 /* TODO: case NetlogonValidationGenericInfo: 4 */
594 case NetlogonValidationGenericInfo2: /* 5 */
595 break;
596 default:
597 return NT_STATUS_INVALID_INFO_CLASS;
600 break;
601 default:
602 return NT_STATUS_INVALID_PARAMETER;
605 return NT_STATUS_OK;
609 netr_LogonSamLogon_base
611 This version of the function allows other wrappers to say 'do not check the credentials'
613 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
615 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
616 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
618 struct auth4_context *auth_context;
619 struct auth_usersupplied_info *user_info;
620 struct auth_user_info_dc *user_info_dc;
621 NTSTATUS nt_status;
622 struct netr_SamBaseInfo *sam;
623 struct netr_SamInfo2 *sam2;
624 struct netr_SamInfo3 *sam3;
625 struct netr_SamInfo6 *sam6;
627 *r->out.authoritative = 1;
629 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
630 NT_STATUS_HAVE_NO_MEMORY(user_info);
632 switch (r->in.logon_level) {
633 case NetlogonInteractiveInformation:
634 case NetlogonServiceInformation:
635 case NetlogonInteractiveTransitiveInformation:
636 case NetlogonServiceTransitiveInformation:
637 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
638 netlogon_creds_aes_decrypt(creds,
639 r->in.logon->password->lmpassword.hash,
640 sizeof(r->in.logon->password->lmpassword.hash));
641 netlogon_creds_aes_decrypt(creds,
642 r->in.logon->password->ntpassword.hash,
643 sizeof(r->in.logon->password->ntpassword.hash));
644 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
645 netlogon_creds_arcfour_crypt(creds,
646 r->in.logon->password->lmpassword.hash,
647 sizeof(r->in.logon->password->lmpassword.hash));
648 netlogon_creds_arcfour_crypt(creds,
649 r->in.logon->password->ntpassword.hash,
650 sizeof(r->in.logon->password->ntpassword.hash));
651 } else {
652 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
653 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
656 /* TODO: we need to deny anonymous access here */
657 nt_status = auth_context_create(mem_ctx,
658 dce_call->event_ctx, dce_call->msg_ctx,
659 dce_call->conn->dce_ctx->lp_ctx,
660 &auth_context);
661 NT_STATUS_NOT_OK_RETURN(nt_status);
663 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
664 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
665 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
666 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
668 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
669 user_info->password_state = AUTH_PASSWORD_HASH;
671 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
672 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
673 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
675 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
676 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
677 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
679 break;
680 case NetlogonNetworkInformation:
681 case NetlogonNetworkTransitiveInformation:
683 /* TODO: we need to deny anonymous access here */
684 nt_status = auth_context_create(mem_ctx,
685 dce_call->event_ctx, dce_call->msg_ctx,
686 dce_call->conn->dce_ctx->lp_ctx,
687 &auth_context);
688 NT_STATUS_NOT_OK_RETURN(nt_status);
690 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
691 NT_STATUS_NOT_OK_RETURN(nt_status);
693 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
694 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
695 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
696 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
698 user_info->password_state = AUTH_PASSWORD_RESPONSE;
699 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
700 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
702 break;
705 case NetlogonGenericInformation:
707 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
708 netlogon_creds_aes_decrypt(creds,
709 r->in.logon->generic->data, r->in.logon->generic->length);
710 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
711 netlogon_creds_arcfour_crypt(creds,
712 r->in.logon->generic->data, r->in.logon->generic->length);
713 } else {
714 /* Using DES to verify kerberos tickets makes no sense */
715 return NT_STATUS_INVALID_PARAMETER;
718 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
719 NTSTATUS status;
720 struct dcerpc_binding_handle *irpc_handle;
721 struct kdc_check_generic_kerberos check;
722 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
723 NT_STATUS_HAVE_NO_MEMORY(generic);
724 *r->out.authoritative = 1;
726 /* TODO: Describe and deal with these flags */
727 *r->out.flags = 0;
729 r->out.validation->generic = generic;
731 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
732 dce_call->msg_ctx,
733 "kdc_server",
734 &ndr_table_irpc);
735 if (irpc_handle == NULL) {
736 return NT_STATUS_NO_LOGON_SERVERS;
739 check.in.generic_request =
740 data_blob_const(r->in.logon->generic->data,
741 r->in.logon->generic->length);
743 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
744 mem_ctx,
745 &check);
746 if (!NT_STATUS_IS_OK(status)) {
747 return status;
749 generic->length = check.out.generic_reply.length;
750 generic->data = check.out.generic_reply.data;
751 return NT_STATUS_OK;
754 /* Until we get an implemetnation of these other packages */
755 return NT_STATUS_INVALID_PARAMETER;
757 default:
758 return NT_STATUS_INVALID_PARAMETER;
761 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
762 /* TODO: set *r->out.authoritative = 0 on specific errors */
763 NT_STATUS_NOT_OK_RETURN(nt_status);
765 switch (r->in.validation_level) {
766 case 2:
767 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
768 NT_STATUS_NOT_OK_RETURN(nt_status);
770 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
771 NT_STATUS_HAVE_NO_MEMORY(sam2);
772 sam2->base = *sam;
774 /* And put into the talloc tree */
775 talloc_steal(sam2, sam);
776 r->out.validation->sam2 = sam2;
778 sam = &sam2->base;
779 break;
781 case 3:
782 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
783 user_info_dc,
784 &sam3);
785 NT_STATUS_NOT_OK_RETURN(nt_status);
787 r->out.validation->sam3 = sam3;
789 sam = &sam3->base;
790 break;
792 case 6:
793 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
794 user_info_dc,
795 &sam3);
796 NT_STATUS_NOT_OK_RETURN(nt_status);
798 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
799 NT_STATUS_HAVE_NO_MEMORY(sam6);
800 sam6->base = sam3->base;
801 sam = &sam6->base;
802 sam6->sidcount = sam3->sidcount;
803 sam6->sids = sam3->sids;
805 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
806 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
807 sam->account_name.string, sam6->dns_domainname.string);
808 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
809 /* And put into the talloc tree */
810 talloc_steal(sam6, sam3);
812 r->out.validation->sam6 = sam6;
813 break;
815 default:
816 return NT_STATUS_INVALID_INFO_CLASS;
819 netlogon_creds_encrypt_samlogon_validation(creds,
820 r->in.validation_level,
821 r->out.validation);
823 /* TODO: Describe and deal with these flags */
824 *r->out.flags = 0;
826 return NT_STATUS_OK;
829 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
830 struct netr_LogonSamLogonEx *r)
832 NTSTATUS nt_status;
833 struct netlogon_creds_CredentialState *creds;
835 *r->out.authoritative = 1;
837 nt_status = dcesrv_netr_LogonSamLogon_check(r);
838 if (!NT_STATUS_IS_OK(nt_status)) {
839 return nt_status;
842 nt_status = schannel_get_creds_state(mem_ctx,
843 dce_call->conn->dce_ctx->lp_ctx,
844 r->in.computer_name, &creds);
845 if (!NT_STATUS_IS_OK(nt_status)) {
846 return nt_status;
849 if (!dce_call->conn->auth_state.auth_info ||
850 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
851 return NT_STATUS_ACCESS_DENIED;
853 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
857 netr_LogonSamLogonWithFlags
860 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
861 struct netr_LogonSamLogonWithFlags *r)
863 NTSTATUS nt_status;
864 struct netlogon_creds_CredentialState *creds;
865 struct netr_LogonSamLogonEx r2;
867 struct netr_Authenticator *return_authenticator;
869 ZERO_STRUCT(r2);
871 r2.in.server_name = r->in.server_name;
872 r2.in.computer_name = r->in.computer_name;
873 r2.in.logon_level = r->in.logon_level;
874 r2.in.logon = r->in.logon;
875 r2.in.validation_level = r->in.validation_level;
876 r2.in.flags = r->in.flags;
877 r2.out.validation = r->out.validation;
878 r2.out.authoritative = r->out.authoritative;
879 r2.out.flags = r->out.flags;
881 *r->out.authoritative = 1;
883 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
884 if (!NT_STATUS_IS_OK(nt_status)) {
885 return nt_status;
888 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
889 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
891 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
892 mem_ctx,
893 r->in.computer_name,
894 r->in.credential, return_authenticator,
895 &creds);
896 NT_STATUS_NOT_OK_RETURN(nt_status);
898 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
900 r->out.return_authenticator = return_authenticator;
902 return nt_status;
906 netr_LogonSamLogon
908 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
909 struct netr_LogonSamLogon *r)
911 struct netr_LogonSamLogonWithFlags r2;
912 uint32_t flags = 0;
913 NTSTATUS status;
915 ZERO_STRUCT(r2);
917 r2.in.server_name = r->in.server_name;
918 r2.in.computer_name = r->in.computer_name;
919 r2.in.credential = r->in.credential;
920 r2.in.return_authenticator = r->in.return_authenticator;
921 r2.in.logon_level = r->in.logon_level;
922 r2.in.logon = r->in.logon;
923 r2.in.validation_level = r->in.validation_level;
924 r2.in.flags = &flags;
925 r2.out.validation = r->out.validation;
926 r2.out.authoritative = r->out.authoritative;
927 r2.out.flags = &flags;
929 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
931 r->out.return_authenticator = r2.out.return_authenticator;
933 return status;
938 netr_LogonSamLogoff
940 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
941 struct netr_LogonSamLogoff *r)
943 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
949 netr_DatabaseDeltas
951 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
952 struct netr_DatabaseDeltas *r)
954 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
959 netr_DatabaseSync2
961 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
962 struct netr_DatabaseSync2 *r)
964 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
965 return NT_STATUS_NOT_IMPLEMENTED;
970 netr_DatabaseSync
972 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
973 struct netr_DatabaseSync *r)
975 struct netr_DatabaseSync2 r2;
976 NTSTATUS status;
978 ZERO_STRUCT(r2);
980 r2.in.logon_server = r->in.logon_server;
981 r2.in.computername = r->in.computername;
982 r2.in.credential = r->in.credential;
983 r2.in.database_id = r->in.database_id;
984 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
985 r2.in.sync_context = r->in.sync_context;
986 r2.out.sync_context = r->out.sync_context;
987 r2.out.delta_enum_array = r->out.delta_enum_array;
988 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
990 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
992 return status;
997 netr_AccountDeltas
999 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1000 struct netr_AccountDeltas *r)
1002 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1003 return NT_STATUS_NOT_IMPLEMENTED;
1008 netr_AccountSync
1010 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1011 struct netr_AccountSync *r)
1013 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1014 return NT_STATUS_NOT_IMPLEMENTED;
1019 netr_GetDcName
1021 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1022 struct netr_GetDcName *r)
1024 const char * const attrs[] = { NULL };
1025 struct ldb_context *sam_ctx;
1026 struct ldb_message **res;
1027 struct ldb_dn *domain_dn;
1028 int ret;
1029 const char *dcname;
1032 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1033 * that the domainname needs to be a valid netbios domain
1034 * name, if it is not NULL.
1036 if (r->in.domainname) {
1037 const char *dot = strchr(r->in.domainname, '.');
1038 size_t len = strlen(r->in.domainname);
1040 if (dot || len > 15) {
1041 return WERR_DCNOTFOUND;
1045 * TODO: Should we also varify that only valid
1046 * netbios name characters are used?
1050 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1051 dce_call->conn->dce_ctx->lp_ctx,
1052 dce_call->conn->auth_state.session_info, 0);
1053 if (sam_ctx == NULL) {
1054 return WERR_DS_UNAVAILABLE;
1057 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1058 r->in.domainname);
1059 if (domain_dn == NULL) {
1060 return WERR_NO_SUCH_DOMAIN;
1063 ret = gendb_search_dn(sam_ctx, mem_ctx,
1064 domain_dn, &res, attrs);
1065 if (ret != 1) {
1066 return WERR_NO_SUCH_DOMAIN;
1069 /* TODO: - return real IP address
1070 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1072 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1073 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1074 W_ERROR_HAVE_NO_MEMORY(dcname);
1076 *r->out.dcname = dcname;
1077 return WERR_OK;
1082 netr_LogonControl2Ex
1084 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1085 struct netr_LogonControl2Ex *r)
1087 return WERR_NOT_SUPPORTED;
1092 netr_LogonControl
1094 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1095 struct netr_LogonControl *r)
1097 struct netr_LogonControl2Ex r2;
1098 WERROR werr;
1100 if (r->in.level == 0x00000001) {
1101 ZERO_STRUCT(r2);
1103 r2.in.logon_server = r->in.logon_server;
1104 r2.in.function_code = r->in.function_code;
1105 r2.in.level = r->in.level;
1106 r2.in.data = NULL;
1107 r2.out.query = r->out.query;
1109 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1110 } else if (r->in.level == 0x00000002) {
1111 werr = WERR_NOT_SUPPORTED;
1112 } else {
1113 werr = WERR_UNKNOWN_LEVEL;
1116 return werr;
1121 netr_LogonControl2
1123 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1124 struct netr_LogonControl2 *r)
1126 struct netr_LogonControl2Ex r2;
1127 WERROR werr;
1129 ZERO_STRUCT(r2);
1131 r2.in.logon_server = r->in.logon_server;
1132 r2.in.function_code = r->in.function_code;
1133 r2.in.level = r->in.level;
1134 r2.in.data = r->in.data;
1135 r2.out.query = r->out.query;
1137 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1139 return werr;
1142 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1143 struct ldb_context *sam_ctx,
1144 struct netr_DomainTrustList *trusts,
1145 uint32_t trust_flags);
1148 netr_GetAnyDCName
1150 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1151 struct netr_GetAnyDCName *r)
1153 struct netr_DomainTrustList *trusts;
1154 struct ldb_context *sam_ctx;
1155 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1156 uint32_t i;
1157 WERROR werr;
1159 *r->out.dcname = NULL;
1161 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1162 /* if the domainname parameter wasn't set assume our domain */
1163 r->in.domainname = lpcfg_workgroup(lp_ctx);
1166 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1167 dce_call->conn->auth_state.session_info, 0);
1168 if (sam_ctx == NULL) {
1169 return WERR_DS_UNAVAILABLE;
1172 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1173 /* well we asked for a DC of our own domain */
1174 if (samdb_is_pdc(sam_ctx)) {
1175 /* we are the PDC of the specified domain */
1176 return WERR_NO_SUCH_DOMAIN;
1179 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1180 lpcfg_netbios_name(lp_ctx));
1181 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1183 return WERR_OK;
1186 /* Okay, now we have to consider the trusted domains */
1188 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1189 W_ERROR_HAVE_NO_MEMORY(trusts);
1191 trusts->count = 0;
1193 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1194 NETR_TRUST_FLAG_INBOUND
1195 | NETR_TRUST_FLAG_OUTBOUND);
1196 W_ERROR_NOT_OK_RETURN(werr);
1198 for (i = 0; i < trusts->count; i++) {
1199 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1200 /* FIXME: Here we need to find a DC for the specified
1201 * trusted domain. */
1203 /* return WERR_OK; */
1204 return WERR_NO_SUCH_DOMAIN;
1208 return WERR_NO_SUCH_DOMAIN;
1213 netr_DatabaseRedo
1215 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1216 struct netr_DatabaseRedo *r)
1218 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1223 netr_NetrEnumerateTrustedDomains
1225 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1226 struct netr_NetrEnumerateTrustedDomains *r)
1228 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1233 netr_LogonGetCapabilities
1235 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1236 struct netr_LogonGetCapabilities *r)
1238 struct netlogon_creds_CredentialState *creds;
1239 NTSTATUS status;
1241 status = dcesrv_netr_creds_server_step_check(dce_call,
1242 mem_ctx,
1243 r->in.computer_name,
1244 r->in.credential,
1245 r->out.return_authenticator,
1246 &creds);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 DEBUG(0,(__location__ " Bad credentials - error\n"));
1250 NT_STATUS_NOT_OK_RETURN(status);
1252 if (r->in.query_level != 1) {
1253 return NT_STATUS_NOT_SUPPORTED;
1256 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1258 return NT_STATUS_OK;
1263 netr_NETRLOGONSETSERVICEBITS
1265 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1266 struct netr_NETRLOGONSETSERVICEBITS *r)
1268 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1273 netr_LogonGetTrustRid
1275 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1276 struct netr_LogonGetTrustRid *r)
1278 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1283 netr_NETRLOGONCOMPUTESERVERDIGEST
1285 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1286 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1288 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1293 netr_NETRLOGONCOMPUTECLIENTDIGEST
1295 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1296 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1298 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1304 netr_DsRGetSiteName
1306 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1307 struct netr_DsRGetSiteName *r)
1309 struct ldb_context *sam_ctx;
1310 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1312 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1313 dce_call->conn->auth_state.session_info, 0);
1314 if (sam_ctx == NULL) {
1315 return WERR_DS_UNAVAILABLE;
1319 * We assume to be a DC when we get called over NETLOGON. Hence we
1320 * get our site name always by using "samdb_server_site_name()"
1321 * and not "samdb_client_site_name()".
1323 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1324 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1326 return WERR_OK;
1331 fill in a netr_OneDomainInfo from a ldb search result
1333 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1334 struct loadparm_context *lp_ctx,
1335 struct ldb_context *sam_ctx,
1336 struct ldb_message *res,
1337 struct netr_OneDomainInfo *info,
1338 bool is_local, bool is_trust_list)
1340 ZERO_STRUCTP(info);
1342 if (is_trust_list) {
1343 /* w2k8 only fills this on trusted domains */
1344 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1345 info->trust_extension.length = 16;
1346 info->trust_extension.info->flags =
1347 NETR_TRUST_FLAG_TREEROOT |
1348 NETR_TRUST_FLAG_IN_FOREST |
1349 NETR_TRUST_FLAG_PRIMARY |
1350 NETR_TRUST_FLAG_NATIVE;
1352 info->trust_extension.info->parent_index = 0; /* should be index into array
1353 of parent */
1354 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1355 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1358 if (is_trust_list) {
1359 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1360 info->dns_forestname.string = NULL;
1361 } else {
1362 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1363 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1364 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1365 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1368 if (is_local) {
1369 info->domainname.string = lpcfg_workgroup(lp_ctx);
1370 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1371 info->domain_guid = samdb_result_guid(res, "objectGUID");
1372 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1373 } else {
1374 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1375 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1376 info->domain_guid = samdb_result_guid(res, "objectGUID");
1377 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1379 if (!is_trust_list) {
1380 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1383 return NT_STATUS_OK;
1387 netr_LogonGetDomainInfo
1388 this is called as part of the ADS domain logon procedure.
1390 It has an important role in convaying details about the client, such
1391 as Operating System, Version, Service Pack etc.
1393 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1394 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1396 struct netlogon_creds_CredentialState *creds;
1397 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1398 "securityIdentifier", "trustPartner", NULL };
1399 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1400 "msDS-SupportedEncryptionTypes", NULL };
1401 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1402 struct ldb_context *sam_ctx;
1403 struct ldb_message **res1, **res2, **res3, *new_msg;
1404 struct ldb_dn *workstation_dn;
1405 struct netr_DomainInformation *domain_info;
1406 struct netr_LsaPolicyInformation *lsa_policy_info;
1407 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1408 bool update_dns_hostname = true;
1409 int ret, ret3, i;
1410 NTSTATUS status;
1412 status = dcesrv_netr_creds_server_step_check(dce_call,
1413 mem_ctx,
1414 r->in.computer_name,
1415 r->in.credential,
1416 r->out.return_authenticator,
1417 &creds);
1418 if (!NT_STATUS_IS_OK(status)) {
1419 DEBUG(0,(__location__ " Bad credentials - error\n"));
1421 NT_STATUS_NOT_OK_RETURN(status);
1423 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1424 dce_call->conn->dce_ctx->lp_ctx,
1425 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1426 if (sam_ctx == NULL) {
1427 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1430 switch (r->in.level) {
1431 case 1: /* Domain information */
1433 if (r->in.query->workstation_info == NULL) {
1434 return NT_STATUS_INVALID_PARAMETER;
1437 /* Prepares the workstation DN */
1438 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1439 dom_sid_string(mem_ctx, creds->sid));
1440 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1442 /* Lookup for attributes in workstation object */
1443 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1444 attrs2);
1445 if (ret != 1) {
1446 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1449 /* Gets the sam account name which is checked against the DNS
1450 * hostname parameter. */
1451 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1452 "sAMAccountName",
1453 NULL);
1454 if (sam_account_name == NULL) {
1455 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1459 * Checks that the sam account name without a possible "$"
1460 * matches as prefix with the DNS hostname in the workstation
1461 * info structure.
1463 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1464 strcspn(sam_account_name, "$"));
1465 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1466 if (r->in.query->workstation_info->dns_hostname != NULL) {
1467 prefix2 = talloc_strndup(mem_ctx,
1468 r->in.query->workstation_info->dns_hostname,
1469 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1470 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1472 if (strcasecmp(prefix1, prefix2) != 0) {
1473 update_dns_hostname = false;
1475 } else {
1476 update_dns_hostname = false;
1479 /* Gets the old DNS hostname */
1480 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1481 "dNSHostName",
1482 NULL);
1485 * Updates the DNS hostname when the client wishes that the
1486 * server should handle this for him
1487 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1488 * obviously only checked when we do already have a
1489 * "dNSHostName".
1490 * See MS-NRPC section 3.5.4.3.9
1492 if ((old_dns_hostname != NULL) &&
1493 (r->in.query->workstation_info->workstation_flags
1494 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1495 update_dns_hostname = false;
1498 /* Gets host information and put them into our directory */
1500 new_msg = ldb_msg_new(mem_ctx);
1501 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1503 new_msg->dn = workstation_dn;
1505 /* Sets the OS name */
1507 if (r->in.query->workstation_info->os_name.string == NULL) {
1508 return NT_STATUS_INVALID_PARAMETER;
1511 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1512 r->in.query->workstation_info->os_name.string);
1513 if (ret != LDB_SUCCESS) {
1514 return NT_STATUS_NO_MEMORY;
1518 * Sets information from "os_version". On an empty structure
1519 * the values are cleared.
1521 if (r->in.query->workstation_info->os_version.os != NULL) {
1522 struct netr_OsVersionInfoEx *os_version;
1523 const char *os_version_str;
1525 os_version = &r->in.query->workstation_info->os_version.os->os;
1527 if (os_version->CSDVersion == NULL) {
1528 return NT_STATUS_INVALID_PARAMETER;
1531 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1532 os_version->MajorVersion,
1533 os_version->MinorVersion,
1534 os_version->BuildNumber);
1535 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1537 ret = ldb_msg_add_string(new_msg,
1538 "operatingSystemServicePack",
1539 os_version->CSDVersion);
1540 if (ret != LDB_SUCCESS) {
1541 return NT_STATUS_NO_MEMORY;
1544 ret = ldb_msg_add_string(new_msg,
1545 "operatingSystemVersion",
1546 os_version_str);
1547 if (ret != LDB_SUCCESS) {
1548 return NT_STATUS_NO_MEMORY;
1550 } else {
1551 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1552 "operatingSystemServicePack");
1553 if (ret != LDB_SUCCESS) {
1554 return NT_STATUS_NO_MEMORY;
1557 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1558 "operatingSystemVersion");
1559 if (ret != LDB_SUCCESS) {
1560 return NT_STATUS_NO_MEMORY;
1565 * If the boolean "update_dns_hostname" remained true, then we
1566 * are fine to start the update.
1568 if (update_dns_hostname) {
1569 ret = ldb_msg_add_string(new_msg,
1570 "dNSHostname",
1571 r->in.query->workstation_info->dns_hostname);
1572 if (ret != LDB_SUCCESS) {
1573 return NT_STATUS_NO_MEMORY;
1576 /* This manual "servicePrincipalName" generation is
1577 * still needed! Since the update in the samldb LDB
1578 * module does only work if the entries already exist
1579 * which isn't always the case. */
1580 ret = ldb_msg_add_string(new_msg,
1581 "servicePrincipalName",
1582 talloc_asprintf(new_msg, "HOST/%s",
1583 r->in.computer_name));
1584 if (ret != LDB_SUCCESS) {
1585 return NT_STATUS_NO_MEMORY;
1588 ret = ldb_msg_add_string(new_msg,
1589 "servicePrincipalName",
1590 talloc_asprintf(new_msg, "HOST/%s",
1591 r->in.query->workstation_info->dns_hostname));
1592 if (ret != LDB_SUCCESS) {
1593 return NT_STATUS_NO_MEMORY;
1597 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1598 DEBUG(3,("Impossible to update samdb: %s\n",
1599 ldb_errstring(sam_ctx)));
1602 talloc_free(new_msg);
1604 /* Writes back the domain information */
1606 /* We need to do two searches. The first will pull our primary
1607 domain and the second will pull any trusted domains. Our
1608 primary domain is also a "trusted" domain, so we need to
1609 put the primary domain into the lists of returned trusts as
1610 well. */
1611 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1612 &res2, attrs);
1613 if (ret != 1) {
1614 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1617 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1618 "(objectClass=trustedDomain)");
1619 if (ret3 == -1) {
1620 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1623 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1624 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1626 ZERO_STRUCTP(domain_info);
1628 /* Informations about the local and trusted domains */
1630 status = fill_one_domain_info(mem_ctx,
1631 dce_call->conn->dce_ctx->lp_ctx,
1632 sam_ctx, res2[0], &domain_info->primary_domain,
1633 true, false);
1634 NT_STATUS_NOT_OK_RETURN(status);
1636 domain_info->trusted_domain_count = ret3 + 1;
1637 domain_info->trusted_domains = talloc_array(mem_ctx,
1638 struct netr_OneDomainInfo,
1639 domain_info->trusted_domain_count);
1640 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1642 for (i=0;i<ret3;i++) {
1643 status = fill_one_domain_info(mem_ctx,
1644 dce_call->conn->dce_ctx->lp_ctx,
1645 sam_ctx, res3[i],
1646 &domain_info->trusted_domains[i],
1647 false, true);
1648 NT_STATUS_NOT_OK_RETURN(status);
1651 status = fill_one_domain_info(mem_ctx,
1652 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1653 &domain_info->trusted_domains[i], true, true);
1654 NT_STATUS_NOT_OK_RETURN(status);
1656 /* Sets the supported encryption types */
1657 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1658 "msDS-SupportedEncryptionTypes",
1659 default_supported_enc_types);
1661 /* Other host domain information */
1663 lsa_policy_info = talloc(mem_ctx,
1664 struct netr_LsaPolicyInformation);
1665 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1666 ZERO_STRUCTP(lsa_policy_info);
1668 domain_info->lsa_policy = *lsa_policy_info;
1670 /* The DNS hostname is only returned back when there is a chance
1671 * for a change. */
1672 if ((r->in.query->workstation_info->workstation_flags
1673 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1674 domain_info->dns_hostname.string = old_dns_hostname;
1675 } else {
1676 domain_info->dns_hostname.string = NULL;
1679 domain_info->workstation_flags =
1680 r->in.query->workstation_info->workstation_flags & (
1681 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1683 r->out.info->domain_info = domain_info;
1684 break;
1685 case 2: /* LSA policy information - not used at the moment */
1686 lsa_policy_info = talloc(mem_ctx,
1687 struct netr_LsaPolicyInformation);
1688 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1689 ZERO_STRUCTP(lsa_policy_info);
1691 r->out.info->lsa_policy_info = lsa_policy_info;
1692 break;
1693 default:
1694 return NT_STATUS_INVALID_LEVEL;
1695 break;
1698 return NT_STATUS_OK;
1703 netr_ServerPasswordGet
1705 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1706 struct netr_ServerPasswordGet *r)
1708 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1713 netr_NETRLOGONSENDTOSAM
1715 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1716 struct netr_NETRLOGONSENDTOSAM *r)
1718 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1723 netr_DsRGetDCNameEx2
1725 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1726 TALLOC_CTX *mem_ctx,
1727 struct netr_DsRGetDCNameEx2 *r)
1729 struct ldb_context *sam_ctx;
1730 struct netr_DsRGetDCNameInfo *info;
1731 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1732 const struct tsocket_address *remote_address;
1733 char *addr = NULL;
1734 const char *server_site_name;
1735 char *guid_str;
1736 struct netlogon_samlogon_response response;
1737 NTSTATUS status;
1738 const char *dc_name = NULL;
1739 const char *domain_name = NULL;
1740 struct interface *ifaces;
1741 const char *pdc_ip;
1743 ZERO_STRUCTP(r->out.info);
1745 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1746 dce_call->conn->auth_state.session_info, 0);
1747 if (sam_ctx == NULL) {
1748 return WERR_DS_UNAVAILABLE;
1751 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1752 if (tsocket_address_is_inet(remote_address, "ip")) {
1753 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1754 W_ERROR_HAVE_NO_MEMORY(addr);
1757 /* "server_unc" is ignored by w2k3 */
1759 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1760 return WERR_INVALID_FLAGS;
1763 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1764 r->in.flags & DS_PDC_REQUIRED &&
1765 r->in.flags & DS_KDC_REQUIRED) {
1766 return WERR_INVALID_FLAGS;
1768 if (r->in.flags & DS_IS_FLAT_NAME &&
1769 r->in.flags & DS_IS_DNS_NAME) {
1770 return WERR_INVALID_FLAGS;
1772 if (r->in.flags & DS_RETURN_DNS_NAME &&
1773 r->in.flags & DS_RETURN_FLAT_NAME) {
1774 return WERR_INVALID_FLAGS;
1776 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1777 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1778 return WERR_INVALID_FLAGS;
1781 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1782 r->in.flags &
1783 (DS_DIRECTORY_SERVICE_REQUIRED |
1784 DS_DIRECTORY_SERVICE_PREFERRED |
1785 DS_GC_SERVER_REQUIRED |
1786 DS_PDC_REQUIRED |
1787 DS_KDC_REQUIRED)) {
1788 return WERR_INVALID_FLAGS;
1791 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1792 r->in.site_name) {
1793 return WERR_INVALID_FLAGS;
1796 /* Proof server site parameter "site_name" if it was specified */
1797 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1798 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1799 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1800 server_site_name) != 0)) {
1801 return WERR_NO_SUCH_DOMAIN;
1804 guid_str = r->in.domain_guid != NULL ?
1805 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1807 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1808 r->in.domain_name,
1809 r->in.domain_name,
1810 NULL, guid_str,
1811 r->in.client_account,
1812 r->in.mask, addr,
1813 NETLOGON_NT_VERSION_5EX_WITH_IP,
1814 lp_ctx, &response, true);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 return ntstatus_to_werror(status);
1820 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1821 * (O) flag when the returned forest name is in DNS format. This is here
1822 * always the case (see below).
1824 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1826 if (r->in.flags & DS_RETURN_DNS_NAME) {
1827 dc_name = response.data.nt5_ex.pdc_dns_name;
1828 domain_name = response.data.nt5_ex.dns_domain;
1830 * According to MS-NRPC 2.2.1.2.1 we should set the
1831 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1832 * the returned information is in DNS form.
1834 response.data.nt5_ex.server_type |=
1835 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1836 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1837 dc_name = response.data.nt5_ex.pdc_name;
1838 domain_name = response.data.nt5_ex.domain_name;
1839 } else {
1842 * TODO: autodetect what we need to return
1843 * based on the given arguments
1845 dc_name = response.data.nt5_ex.pdc_name;
1846 domain_name = response.data.nt5_ex.domain_name;
1849 if (!dc_name || !dc_name[0]) {
1850 return WERR_NO_SUCH_DOMAIN;
1853 if (!domain_name || !domain_name[0]) {
1854 return WERR_NO_SUCH_DOMAIN;
1857 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1858 W_ERROR_HAVE_NO_MEMORY(info);
1859 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1860 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1862 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1863 pdc_ip = iface_list_best_ip(ifaces, addr);
1864 if (pdc_ip == NULL) {
1865 pdc_ip = "127.0.0.1";
1867 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1868 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1869 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1870 info->domain_guid = response.data.nt5_ex.domain_uuid;
1871 info->domain_name = domain_name;
1872 info->forest_name = response.data.nt5_ex.forest;
1873 info->dc_flags = response.data.nt5_ex.server_type;
1874 info->dc_site_name = response.data.nt5_ex.server_site;
1875 info->client_site_name = response.data.nt5_ex.client_site;
1877 *r->out.info = info;
1879 return WERR_OK;
1883 netr_DsRGetDCNameEx
1885 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1886 struct netr_DsRGetDCNameEx *r)
1888 struct netr_DsRGetDCNameEx2 r2;
1889 WERROR werr;
1891 ZERO_STRUCT(r2);
1893 r2.in.server_unc = r->in.server_unc;
1894 r2.in.client_account = NULL;
1895 r2.in.mask = 0;
1896 r2.in.domain_guid = r->in.domain_guid;
1897 r2.in.domain_name = r->in.domain_name;
1898 r2.in.site_name = r->in.site_name;
1899 r2.in.flags = r->in.flags;
1900 r2.out.info = r->out.info;
1902 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1904 return werr;
1908 netr_DsRGetDCName
1910 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1911 struct netr_DsRGetDCName *r)
1913 struct netr_DsRGetDCNameEx2 r2;
1914 WERROR werr;
1916 ZERO_STRUCT(r2);
1918 r2.in.server_unc = r->in.server_unc;
1919 r2.in.client_account = NULL;
1920 r2.in.mask = 0;
1921 r2.in.domain_name = r->in.domain_name;
1922 r2.in.domain_guid = r->in.domain_guid;
1924 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1925 r2.in.flags = r->in.flags;
1926 r2.out.info = r->out.info;
1928 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1930 return werr;
1933 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1935 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1936 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1938 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1943 netr_NetrEnumerateTrustedDomainsEx
1945 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1946 struct netr_NetrEnumerateTrustedDomainsEx *r)
1948 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1953 netr_DsRAddressToSitenamesExW
1955 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1956 struct netr_DsRAddressToSitenamesExW *r)
1958 struct ldb_context *sam_ctx;
1959 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1960 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1961 sa_family_t sin_family;
1962 struct sockaddr_in *addr;
1963 #ifdef HAVE_IPV6
1964 struct sockaddr_in6 *addr6;
1965 char addr_str[INET6_ADDRSTRLEN];
1966 #else
1967 char addr_str[INET_ADDRSTRLEN];
1968 #endif
1969 char *subnet_name;
1970 const char *res;
1971 uint32_t i;
1973 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1974 dce_call->conn->auth_state.session_info, 0);
1975 if (sam_ctx == NULL) {
1976 return WERR_DS_UNAVAILABLE;
1979 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1980 W_ERROR_HAVE_NO_MEMORY(ctr);
1982 *r->out.ctr = ctr;
1984 ctr->count = r->in.count;
1985 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1986 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1987 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1988 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1990 for (i=0; i<ctr->count; i++) {
1991 ctr->sitename[i].string = NULL;
1992 ctr->subnetname[i].string = NULL;
1994 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1995 continue;
1997 /* The first two byte of the buffer are reserved for the
1998 * "sin_family" but for now only the first one is used. */
1999 sin_family = r->in.addresses[i].buffer[0];
2001 switch (sin_family) {
2002 case AF_INET:
2003 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2004 continue;
2006 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2007 res = inet_ntop(AF_INET, &addr->sin_addr,
2008 addr_str, sizeof(addr_str));
2009 break;
2010 #ifdef HAVE_IPV6
2011 case AF_INET6:
2012 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2013 continue;
2015 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2016 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2017 addr_str, sizeof(addr_str));
2018 break;
2019 #endif
2020 default:
2021 continue;
2024 if (res == NULL) {
2025 continue;
2028 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2029 mem_ctx,
2030 addr_str,
2031 &subnet_name);
2032 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2033 ctr->subnetname[i].string = subnet_name;
2036 return WERR_OK;
2041 netr_DsRAddressToSitenamesW
2043 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2044 struct netr_DsRAddressToSitenamesW *r)
2046 struct netr_DsRAddressToSitenamesExW r2;
2047 struct netr_DsRAddressToSitenamesWCtr *ctr;
2048 uint32_t i;
2049 WERROR werr;
2051 ZERO_STRUCT(r2);
2053 r2.in.server_name = r->in.server_name;
2054 r2.in.count = r->in.count;
2055 r2.in.addresses = r->in.addresses;
2057 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2058 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2060 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2061 W_ERROR_HAVE_NO_MEMORY(ctr);
2063 *r->out.ctr = ctr;
2065 ctr->count = r->in.count;
2066 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2067 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2069 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2071 for (i=0; i<ctr->count; i++) {
2072 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2075 return werr;
2080 netr_DsrGetDcSiteCoverageW
2082 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2083 struct netr_DsrGetDcSiteCoverageW *r)
2085 struct ldb_context *sam_ctx;
2086 struct DcSitesCtr *ctr;
2087 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2089 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2090 dce_call->conn->auth_state.session_info, 0);
2091 if (sam_ctx == NULL) {
2092 return WERR_DS_UNAVAILABLE;
2095 ctr = talloc(mem_ctx, struct DcSitesCtr);
2096 W_ERROR_HAVE_NO_MEMORY(ctr);
2098 *r->out.ctr = ctr;
2100 /* For now only return our default site */
2101 ctr->num_sites = 1;
2102 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2103 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2104 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2105 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2107 return WERR_OK;
2111 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2112 struct ldb_context *sam_ctx,
2113 struct netr_DomainTrustList *trusts,
2114 uint32_t trust_flags)
2116 struct ldb_dn *system_dn;
2117 struct ldb_message **dom_res = NULL;
2118 const char *trust_attrs[] = { "flatname", "trustPartner",
2119 "securityIdentifier", "trustDirection",
2120 "trustType", "trustAttributes", NULL };
2121 uint32_t n;
2122 int i;
2123 int ret;
2125 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2126 NETR_TRUST_FLAG_OUTBOUND))) {
2127 return WERR_INVALID_FLAGS;
2130 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2131 ldb_get_default_basedn(sam_ctx),
2132 "(&(objectClass=container)(cn=System))");
2133 if (!system_dn) {
2134 return WERR_GENERAL_FAILURE;
2137 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2138 &dom_res, trust_attrs,
2139 "(objectclass=trustedDomain)");
2141 for (i = 0; i < ret; i++) {
2142 unsigned int trust_dir;
2143 uint32_t flags = 0;
2145 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2146 "trustDirection", 0);
2148 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2149 flags |= NETR_TRUST_FLAG_INBOUND;
2151 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2152 flags |= NETR_TRUST_FLAG_OUTBOUND;
2155 if (!(flags & trust_flags)) {
2156 /* this trust direction was not requested */
2157 continue;
2160 n = trusts->count;
2161 trusts->array = talloc_realloc(trusts, trusts->array,
2162 struct netr_DomainTrust,
2163 n + 1);
2164 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2166 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2167 if (!trusts->array[n].netbios_name) {
2168 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2169 "without flatname\n",
2170 ldb_dn_get_linearized(dom_res[i]->dn)));
2173 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2175 trusts->array[n].trust_flags = flags;
2176 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2177 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2178 /* TODO: find if we have parent in the list */
2179 trusts->array[n].parent_index = 0;
2182 trusts->array[n].trust_type =
2183 ldb_msg_find_attr_as_uint(dom_res[i],
2184 "trustType", 0);
2185 trusts->array[n].trust_attributes =
2186 ldb_msg_find_attr_as_uint(dom_res[i],
2187 "trustAttributes", 0);
2189 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2190 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2191 struct dom_sid zero_sid;
2192 ZERO_STRUCT(zero_sid);
2193 trusts->array[n].sid =
2194 dom_sid_dup(trusts, &zero_sid);
2195 } else {
2196 trusts->array[n].sid =
2197 samdb_result_dom_sid(trusts, dom_res[i],
2198 "securityIdentifier");
2200 trusts->array[n].guid = GUID_zero();
2202 trusts->count = n + 1;
2205 talloc_free(dom_res);
2206 return WERR_OK;
2210 netr_DsrEnumerateDomainTrusts
2212 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2213 TALLOC_CTX *mem_ctx,
2214 struct netr_DsrEnumerateDomainTrusts *r)
2216 struct netr_DomainTrustList *trusts;
2217 struct ldb_context *sam_ctx;
2218 int ret;
2219 struct ldb_message **dom_res;
2220 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2221 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2222 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2223 const char *p;
2224 WERROR werr;
2226 if (r->in.trust_flags & 0xFFFFFE00) {
2227 return WERR_INVALID_FLAGS;
2230 /* TODO: turn to hard check once we are sure this is 100% correct */
2231 if (!r->in.server_name) {
2232 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2233 "But received NULL!\n", dnsdomain));
2234 } else {
2235 p = strchr(r->in.server_name, '.');
2236 if (!p) {
2237 DEBUG(3, ("Invalid domain! Expected name in domain "
2238 "[%s]. But received [%s]!\n",
2239 dnsdomain, r->in.server_name));
2240 p = r->in.server_name;
2241 } else {
2242 p++;
2244 if (strcasecmp(p, dnsdomain)) {
2245 DEBUG(3, ("Invalid domain! Expected name in domain "
2246 "[%s]. But received [%s]!\n",
2247 dnsdomain, r->in.server_name));
2251 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2252 W_ERROR_HAVE_NO_MEMORY(trusts);
2254 trusts->count = 0;
2255 r->out.trusts = trusts;
2257 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2258 dce_call->conn->auth_state.session_info, 0);
2259 if (sam_ctx == NULL) {
2260 return WERR_GENERAL_FAILURE;
2263 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2264 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2266 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2267 trusts, r->in.trust_flags);
2268 W_ERROR_NOT_OK_RETURN(werr);
2271 /* NOTE: we currently are always the root of the forest */
2272 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2273 uint32_t n = trusts->count;
2275 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2276 &dom_res, dom_attrs);
2277 if (ret != 1) {
2278 return WERR_GENERAL_FAILURE;
2281 trusts->count = n + 1;
2282 trusts->array = talloc_realloc(trusts, trusts->array,
2283 struct netr_DomainTrust,
2284 trusts->count);
2285 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2287 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2288 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2289 trusts->array[n].trust_flags =
2290 NETR_TRUST_FLAG_NATIVE |
2291 NETR_TRUST_FLAG_TREEROOT |
2292 NETR_TRUST_FLAG_IN_FOREST |
2293 NETR_TRUST_FLAG_PRIMARY;
2294 /* we are always the root domain for now */
2295 trusts->array[n].parent_index = 0;
2296 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2297 trusts->array[n].trust_attributes = 0;
2298 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2299 dom_res[0],
2300 "objectSid");
2301 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2302 "objectGUID");
2303 talloc_free(dom_res);
2306 return WERR_OK;
2311 netr_DsrDeregisterDNSHostRecords
2313 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2314 struct netr_DsrDeregisterDNSHostRecords *r)
2316 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2321 netr_ServerTrustPasswordsGet
2323 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2324 struct netr_ServerTrustPasswordsGet *r)
2326 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2330 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2331 struct ldb_context *sam_ctx,
2332 struct loadparm_context *lp_ctx,
2333 struct lsa_ForestTrustInformation *info)
2335 struct lsa_ForestTrustDomainInfo *domain_info;
2336 struct lsa_ForestTrustRecord *e;
2337 struct ldb_message **dom_res;
2338 const char * const dom_attrs[] = { "objectSid", NULL };
2339 int ret;
2341 /* we need to provide 2 entries:
2342 * 1. the Root Forest name
2343 * 2. the Domain Information
2346 info->count = 2;
2347 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2348 W_ERROR_HAVE_NO_MEMORY(info->entries);
2350 /* Forest root info */
2351 e = talloc(info, struct lsa_ForestTrustRecord);
2352 W_ERROR_HAVE_NO_MEMORY(e);
2354 e->flags = 0;
2355 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2356 e->time = 0; /* so far always 0 in trces. */
2357 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2358 mem_ctx);
2359 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2361 info->entries[0] = e;
2363 /* Domain info */
2364 e = talloc(info, struct lsa_ForestTrustRecord);
2365 W_ERROR_HAVE_NO_MEMORY(e);
2367 /* get our own domain info */
2368 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2369 if (ret != 1) {
2370 return WERR_GENERAL_FAILURE;
2373 /* TODO: check if disabled and set flags accordingly */
2374 e->flags = 0;
2375 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2376 e->time = 0; /* so far always 0 in traces. */
2378 domain_info = &e->forest_trust_data.domain_info;
2379 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2380 "objectSid");
2381 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2382 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2384 info->entries[1] = e;
2386 talloc_free(dom_res);
2388 return WERR_OK;
2392 netr_DsRGetForestTrustInformation
2394 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2395 TALLOC_CTX *mem_ctx,
2396 struct netr_DsRGetForestTrustInformation *r)
2398 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2399 struct lsa_ForestTrustInformation *info, **info_ptr;
2400 struct ldb_context *sam_ctx;
2401 WERROR werr;
2403 if (r->in.flags & 0xFFFFFFFE) {
2404 return WERR_INVALID_FLAGS;
2407 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2408 dce_call->conn->auth_state.session_info, 0);
2409 if (sam_ctx == NULL) {
2410 return WERR_GENERAL_FAILURE;
2413 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2414 if (!samdb_is_pdc(sam_ctx)) {
2415 return WERR_NERR_NOTPRIMARY;
2418 if (r->in.trusted_domain_name == NULL) {
2419 return WERR_INVALID_FLAGS;
2422 /* TODO: establish an schannel connection with
2423 * r->in.trusted_domain_name and perform a
2424 * netr_GetForestTrustInformation call against it */
2426 /* for now return not implementd */
2427 return WERR_CALL_NOT_IMPLEMENTED;
2430 /* TODO: check r->in.server_name is our name */
2432 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2433 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2435 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2436 W_ERROR_HAVE_NO_MEMORY(info);
2438 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2439 W_ERROR_NOT_OK_RETURN(werr);
2441 *info_ptr = info;
2442 r->out.forest_trust_info = info_ptr;
2444 return WERR_OK;
2449 netr_GetForestTrustInformation
2451 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2452 TALLOC_CTX *mem_ctx,
2453 struct netr_GetForestTrustInformation *r)
2455 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2456 struct netlogon_creds_CredentialState *creds;
2457 struct lsa_ForestTrustInformation *info, **info_ptr;
2458 struct ldb_context *sam_ctx;
2459 NTSTATUS status;
2460 WERROR werr;
2462 status = dcesrv_netr_creds_server_step_check(dce_call,
2463 mem_ctx,
2464 r->in.computer_name,
2465 r->in.credential,
2466 r->out.return_authenticator,
2467 &creds);
2468 if (!NT_STATUS_IS_OK(status)) {
2469 return status;
2472 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2473 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2474 return NT_STATUS_NOT_IMPLEMENTED;
2477 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2478 dce_call->conn->auth_state.session_info, 0);
2479 if (sam_ctx == NULL) {
2480 return NT_STATUS_INTERNAL_ERROR;
2483 /* TODO: check r->in.server_name is our name */
2485 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2486 if (!info_ptr) {
2487 return NT_STATUS_NO_MEMORY;
2489 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2490 if (!info) {
2491 return NT_STATUS_NO_MEMORY;
2494 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2495 if (!W_ERROR_IS_OK(werr)) {
2496 return werror_to_ntstatus(werr);
2499 *info_ptr = info;
2500 r->out.forest_trust_info = info_ptr;
2502 return NT_STATUS_OK;
2507 netr_ServerGetTrustInfo
2509 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2510 struct netr_ServerGetTrustInfo *r)
2512 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2516 netr_Unused47
2518 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2519 struct netr_Unused47 *r)
2521 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2525 struct netr_dnsupdate_RODC_state {
2526 struct dcesrv_call_state *dce_call;
2527 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2528 struct dnsupdate_RODC *r2;
2532 called when the forwarded RODC dns update request is finished
2534 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2536 struct netr_dnsupdate_RODC_state *st =
2537 tevent_req_callback_data(subreq,
2538 struct netr_dnsupdate_RODC_state);
2539 NTSTATUS status;
2541 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2542 TALLOC_FREE(subreq);
2543 if (!NT_STATUS_IS_OK(status)) {
2544 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2545 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2548 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2550 status = dcesrv_reply(st->dce_call);
2551 if (!NT_STATUS_IS_OK(status)) {
2552 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2557 netr_DsrUpdateReadOnlyServerDnsRecords
2559 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2560 TALLOC_CTX *mem_ctx,
2561 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2563 struct netlogon_creds_CredentialState *creds;
2564 NTSTATUS nt_status;
2565 struct dcerpc_binding_handle *binding_handle;
2566 struct netr_dnsupdate_RODC_state *st;
2567 struct tevent_req *subreq;
2569 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2570 mem_ctx,
2571 r->in.computer_name,
2572 r->in.credential,
2573 r->out.return_authenticator,
2574 &creds);
2575 NT_STATUS_NOT_OK_RETURN(nt_status);
2577 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2578 return NT_STATUS_ACCESS_DENIED;
2581 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2582 NT_STATUS_HAVE_NO_MEMORY(st);
2584 st->dce_call = dce_call;
2585 st->r = r;
2586 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2587 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2589 st->r2->in.dom_sid = creds->sid;
2590 st->r2->in.site_name = r->in.site_name;
2591 st->r2->in.dns_ttl = r->in.dns_ttl;
2592 st->r2->in.dns_names = r->in.dns_names;
2593 st->r2->out.dns_names = r->out.dns_names;
2595 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2596 "dnsupdate", &ndr_table_irpc);
2597 if (binding_handle == NULL) {
2598 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2599 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2600 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2603 /* forward the call */
2604 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2605 binding_handle, st->r2);
2606 NT_STATUS_HAVE_NO_MEMORY(subreq);
2608 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2610 /* setup the callback */
2611 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2613 return NT_STATUS_OK;
2617 /* include the generated boilerplate */
2618 #include "librpc/gen_ndr/ndr_netlogon_s.c"