s4-rpc_server: support AES encryption in interactive and generic samlogon.
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob3eaf0d4e1df2279df2169789b7d56e2cb54bc7f4
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 static const char zeros[16];
623 struct netr_SamBaseInfo *sam;
624 struct netr_SamInfo2 *sam2;
625 struct netr_SamInfo3 *sam3;
626 struct netr_SamInfo6 *sam6;
628 *r->out.authoritative = 1;
630 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
631 NT_STATUS_HAVE_NO_MEMORY(user_info);
633 switch (r->in.logon_level) {
634 case NetlogonInteractiveInformation:
635 case NetlogonServiceInformation:
636 case NetlogonInteractiveTransitiveInformation:
637 case NetlogonServiceTransitiveInformation:
638 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
639 netlogon_creds_aes_decrypt(creds,
640 r->in.logon->password->lmpassword.hash,
641 sizeof(r->in.logon->password->lmpassword.hash));
642 netlogon_creds_aes_decrypt(creds,
643 r->in.logon->password->ntpassword.hash,
644 sizeof(r->in.logon->password->ntpassword.hash));
645 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
646 netlogon_creds_arcfour_crypt(creds,
647 r->in.logon->password->lmpassword.hash,
648 sizeof(r->in.logon->password->lmpassword.hash));
649 netlogon_creds_arcfour_crypt(creds,
650 r->in.logon->password->ntpassword.hash,
651 sizeof(r->in.logon->password->ntpassword.hash));
652 } else {
653 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
654 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
657 /* TODO: we need to deny anonymous access here */
658 nt_status = auth_context_create(mem_ctx,
659 dce_call->event_ctx, dce_call->msg_ctx,
660 dce_call->conn->dce_ctx->lp_ctx,
661 &auth_context);
662 NT_STATUS_NOT_OK_RETURN(nt_status);
664 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
665 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
666 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
667 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
669 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
670 user_info->password_state = AUTH_PASSWORD_HASH;
672 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
673 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
674 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
676 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
677 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
678 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
680 break;
681 case NetlogonNetworkInformation:
682 case NetlogonNetworkTransitiveInformation:
684 /* TODO: we need to deny anonymous access here */
685 nt_status = auth_context_create(mem_ctx,
686 dce_call->event_ctx, dce_call->msg_ctx,
687 dce_call->conn->dce_ctx->lp_ctx,
688 &auth_context);
689 NT_STATUS_NOT_OK_RETURN(nt_status);
691 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
692 NT_STATUS_NOT_OK_RETURN(nt_status);
694 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
695 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
696 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
697 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
699 user_info->password_state = AUTH_PASSWORD_RESPONSE;
700 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
701 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
703 break;
706 case NetlogonGenericInformation:
708 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
709 netlogon_creds_aes_decrypt(creds,
710 r->in.logon->generic->data, r->in.logon->generic->length);
711 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
712 netlogon_creds_arcfour_crypt(creds,
713 r->in.logon->generic->data, r->in.logon->generic->length);
714 } else {
715 /* Using DES to verify kerberos tickets makes no sense */
716 return NT_STATUS_INVALID_PARAMETER;
719 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
720 NTSTATUS status;
721 struct dcerpc_binding_handle *irpc_handle;
722 struct kdc_check_generic_kerberos check;
723 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
724 NT_STATUS_HAVE_NO_MEMORY(generic);
725 *r->out.authoritative = 1;
727 /* TODO: Describe and deal with these flags */
728 *r->out.flags = 0;
730 r->out.validation->generic = generic;
732 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
733 dce_call->msg_ctx,
734 "kdc_server",
735 &ndr_table_irpc);
736 if (irpc_handle == NULL) {
737 return NT_STATUS_NO_LOGON_SERVERS;
740 check.in.generic_request =
741 data_blob_const(r->in.logon->generic->data,
742 r->in.logon->generic->length);
744 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
745 mem_ctx,
746 &check);
747 if (!NT_STATUS_IS_OK(status)) {
748 return status;
750 generic->length = check.out.generic_reply.length;
751 generic->data = check.out.generic_reply.data;
752 return NT_STATUS_OK;
755 /* Until we get an implemetnation of these other packages */
756 return NT_STATUS_INVALID_PARAMETER;
758 default:
759 return NT_STATUS_INVALID_PARAMETER;
762 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
763 /* TODO: set *r->out.authoritative = 0 on specific errors */
764 NT_STATUS_NOT_OK_RETURN(nt_status);
766 switch (r->in.validation_level) {
767 case 2:
768 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
769 NT_STATUS_NOT_OK_RETURN(nt_status);
771 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
772 NT_STATUS_HAVE_NO_MEMORY(sam2);
773 sam2->base = *sam;
775 /* And put into the talloc tree */
776 talloc_steal(sam2, sam);
777 r->out.validation->sam2 = sam2;
779 sam = &sam2->base;
780 break;
782 case 3:
783 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
784 user_info_dc,
785 &sam3);
786 NT_STATUS_NOT_OK_RETURN(nt_status);
788 r->out.validation->sam3 = sam3;
790 sam = &sam3->base;
791 break;
793 case 6:
794 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
795 user_info_dc,
796 &sam3);
797 NT_STATUS_NOT_OK_RETURN(nt_status);
799 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
800 NT_STATUS_HAVE_NO_MEMORY(sam6);
801 sam6->base = sam3->base;
802 sam = &sam6->base;
803 sam6->sidcount = sam3->sidcount;
804 sam6->sids = sam3->sids;
806 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
807 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
808 sam->account_name.string, sam6->dns_domainname.string);
809 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
810 /* And put into the talloc tree */
811 talloc_steal(sam6, sam3);
813 r->out.validation->sam6 = sam6;
814 break;
816 default:
817 return NT_STATUS_INVALID_INFO_CLASS;
820 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
821 /* It appears that level 6 is not individually encrypted */
822 if ((r->in.validation_level != 6) &&
823 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
824 /* This key is sent unencrypted without the ARCFOUR or AES flag set */
825 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
826 netlogon_creds_aes_encrypt(creds,
827 sam->key.key,
828 sizeof(sam->key.key));
829 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
830 netlogon_creds_arcfour_crypt(creds,
831 sam->key.key,
832 sizeof(sam->key.key));
836 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
837 /* It appears that level 6 is not individually encrypted */
838 if ((r->in.validation_level != 6) &&
839 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
840 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
841 netlogon_creds_aes_encrypt(creds,
842 sam->LMSessKey.key,
843 sizeof(sam->LMSessKey.key));
844 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
845 netlogon_creds_arcfour_crypt(creds,
846 sam->LMSessKey.key,
847 sizeof(sam->LMSessKey.key));
848 } else {
849 netlogon_creds_des_encrypt_LMKey(creds,
850 &sam->LMSessKey);
854 /* TODO: Describe and deal with these flags */
855 *r->out.flags = 0;
857 return NT_STATUS_OK;
860 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
861 struct netr_LogonSamLogonEx *r)
863 NTSTATUS nt_status;
864 struct netlogon_creds_CredentialState *creds;
866 *r->out.authoritative = 1;
868 nt_status = dcesrv_netr_LogonSamLogon_check(r);
869 if (!NT_STATUS_IS_OK(nt_status)) {
870 return nt_status;
873 nt_status = schannel_get_creds_state(mem_ctx,
874 dce_call->conn->dce_ctx->lp_ctx,
875 r->in.computer_name, &creds);
876 if (!NT_STATUS_IS_OK(nt_status)) {
877 return nt_status;
880 if (!dce_call->conn->auth_state.auth_info ||
881 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
882 return NT_STATUS_ACCESS_DENIED;
884 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
888 netr_LogonSamLogonWithFlags
891 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
892 struct netr_LogonSamLogonWithFlags *r)
894 NTSTATUS nt_status;
895 struct netlogon_creds_CredentialState *creds;
896 struct netr_LogonSamLogonEx r2;
898 struct netr_Authenticator *return_authenticator;
900 ZERO_STRUCT(r2);
902 r2.in.server_name = r->in.server_name;
903 r2.in.computer_name = r->in.computer_name;
904 r2.in.logon_level = r->in.logon_level;
905 r2.in.logon = r->in.logon;
906 r2.in.validation_level = r->in.validation_level;
907 r2.in.flags = r->in.flags;
908 r2.out.validation = r->out.validation;
909 r2.out.authoritative = r->out.authoritative;
910 r2.out.flags = r->out.flags;
912 *r->out.authoritative = 1;
914 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
915 if (!NT_STATUS_IS_OK(nt_status)) {
916 return nt_status;
919 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
920 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
922 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
923 mem_ctx,
924 r->in.computer_name,
925 r->in.credential, return_authenticator,
926 &creds);
927 NT_STATUS_NOT_OK_RETURN(nt_status);
929 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
931 r->out.return_authenticator = return_authenticator;
933 return nt_status;
937 netr_LogonSamLogon
939 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
940 struct netr_LogonSamLogon *r)
942 struct netr_LogonSamLogonWithFlags r2;
943 uint32_t flags = 0;
944 NTSTATUS status;
946 ZERO_STRUCT(r2);
948 r2.in.server_name = r->in.server_name;
949 r2.in.computer_name = r->in.computer_name;
950 r2.in.credential = r->in.credential;
951 r2.in.return_authenticator = r->in.return_authenticator;
952 r2.in.logon_level = r->in.logon_level;
953 r2.in.logon = r->in.logon;
954 r2.in.validation_level = r->in.validation_level;
955 r2.in.flags = &flags;
956 r2.out.validation = r->out.validation;
957 r2.out.authoritative = r->out.authoritative;
958 r2.out.flags = &flags;
960 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
962 r->out.return_authenticator = r2.out.return_authenticator;
964 return status;
969 netr_LogonSamLogoff
971 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
972 struct netr_LogonSamLogoff *r)
974 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
980 netr_DatabaseDeltas
982 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
983 struct netr_DatabaseDeltas *r)
985 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
990 netr_DatabaseSync2
992 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
993 struct netr_DatabaseSync2 *r)
995 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
996 return NT_STATUS_NOT_IMPLEMENTED;
1001 netr_DatabaseSync
1003 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1004 struct netr_DatabaseSync *r)
1006 struct netr_DatabaseSync2 r2;
1007 NTSTATUS status;
1009 ZERO_STRUCT(r2);
1011 r2.in.logon_server = r->in.logon_server;
1012 r2.in.computername = r->in.computername;
1013 r2.in.credential = r->in.credential;
1014 r2.in.database_id = r->in.database_id;
1015 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1016 r2.in.sync_context = r->in.sync_context;
1017 r2.out.sync_context = r->out.sync_context;
1018 r2.out.delta_enum_array = r->out.delta_enum_array;
1019 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1021 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1023 return status;
1028 netr_AccountDeltas
1030 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1031 struct netr_AccountDeltas *r)
1033 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1034 return NT_STATUS_NOT_IMPLEMENTED;
1039 netr_AccountSync
1041 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1042 struct netr_AccountSync *r)
1044 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1045 return NT_STATUS_NOT_IMPLEMENTED;
1050 netr_GetDcName
1052 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1053 struct netr_GetDcName *r)
1055 const char * const attrs[] = { NULL };
1056 struct ldb_context *sam_ctx;
1057 struct ldb_message **res;
1058 struct ldb_dn *domain_dn;
1059 int ret;
1060 const char *dcname;
1063 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1064 * that the domainname needs to be a valid netbios domain
1065 * name, if it is not NULL.
1067 if (r->in.domainname) {
1068 const char *dot = strchr(r->in.domainname, '.');
1069 size_t len = strlen(r->in.domainname);
1071 if (dot || len > 15) {
1072 return WERR_DCNOTFOUND;
1076 * TODO: Should we also varify that only valid
1077 * netbios name characters are used?
1081 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1082 dce_call->conn->dce_ctx->lp_ctx,
1083 dce_call->conn->auth_state.session_info, 0);
1084 if (sam_ctx == NULL) {
1085 return WERR_DS_UNAVAILABLE;
1088 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1089 r->in.domainname);
1090 if (domain_dn == NULL) {
1091 return WERR_NO_SUCH_DOMAIN;
1094 ret = gendb_search_dn(sam_ctx, mem_ctx,
1095 domain_dn, &res, attrs);
1096 if (ret != 1) {
1097 return WERR_NO_SUCH_DOMAIN;
1100 /* TODO: - return real IP address
1101 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1103 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1104 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1105 W_ERROR_HAVE_NO_MEMORY(dcname);
1107 *r->out.dcname = dcname;
1108 return WERR_OK;
1113 netr_LogonControl2Ex
1115 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1116 struct netr_LogonControl2Ex *r)
1118 return WERR_NOT_SUPPORTED;
1123 netr_LogonControl
1125 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1126 struct netr_LogonControl *r)
1128 struct netr_LogonControl2Ex r2;
1129 WERROR werr;
1131 if (r->in.level == 0x00000001) {
1132 ZERO_STRUCT(r2);
1134 r2.in.logon_server = r->in.logon_server;
1135 r2.in.function_code = r->in.function_code;
1136 r2.in.level = r->in.level;
1137 r2.in.data = NULL;
1138 r2.out.query = r->out.query;
1140 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1141 } else if (r->in.level == 0x00000002) {
1142 werr = WERR_NOT_SUPPORTED;
1143 } else {
1144 werr = WERR_UNKNOWN_LEVEL;
1147 return werr;
1152 netr_LogonControl2
1154 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1155 struct netr_LogonControl2 *r)
1157 struct netr_LogonControl2Ex r2;
1158 WERROR werr;
1160 ZERO_STRUCT(r2);
1162 r2.in.logon_server = r->in.logon_server;
1163 r2.in.function_code = r->in.function_code;
1164 r2.in.level = r->in.level;
1165 r2.in.data = r->in.data;
1166 r2.out.query = r->out.query;
1168 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1170 return werr;
1173 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1174 struct ldb_context *sam_ctx,
1175 struct netr_DomainTrustList *trusts,
1176 uint32_t trust_flags);
1179 netr_GetAnyDCName
1181 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1182 struct netr_GetAnyDCName *r)
1184 struct netr_DomainTrustList *trusts;
1185 struct ldb_context *sam_ctx;
1186 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1187 uint32_t i;
1188 WERROR werr;
1190 *r->out.dcname = NULL;
1192 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1193 /* if the domainname parameter wasn't set assume our domain */
1194 r->in.domainname = lpcfg_workgroup(lp_ctx);
1197 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1198 dce_call->conn->auth_state.session_info, 0);
1199 if (sam_ctx == NULL) {
1200 return WERR_DS_UNAVAILABLE;
1203 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1204 /* well we asked for a DC of our own domain */
1205 if (samdb_is_pdc(sam_ctx)) {
1206 /* we are the PDC of the specified domain */
1207 return WERR_NO_SUCH_DOMAIN;
1210 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1211 lpcfg_netbios_name(lp_ctx));
1212 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1214 return WERR_OK;
1217 /* Okay, now we have to consider the trusted domains */
1219 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1220 W_ERROR_HAVE_NO_MEMORY(trusts);
1222 trusts->count = 0;
1224 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1225 NETR_TRUST_FLAG_INBOUND
1226 | NETR_TRUST_FLAG_OUTBOUND);
1227 W_ERROR_NOT_OK_RETURN(werr);
1229 for (i = 0; i < trusts->count; i++) {
1230 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1231 /* FIXME: Here we need to find a DC for the specified
1232 * trusted domain. */
1234 /* return WERR_OK; */
1235 return WERR_NO_SUCH_DOMAIN;
1239 return WERR_NO_SUCH_DOMAIN;
1244 netr_DatabaseRedo
1246 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1247 struct netr_DatabaseRedo *r)
1249 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1254 netr_NetrEnumerateTrustedDomains
1256 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1257 struct netr_NetrEnumerateTrustedDomains *r)
1259 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1264 netr_LogonGetCapabilities
1266 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1267 struct netr_LogonGetCapabilities *r)
1269 struct netlogon_creds_CredentialState *creds;
1270 NTSTATUS status;
1272 status = dcesrv_netr_creds_server_step_check(dce_call,
1273 mem_ctx,
1274 r->in.computer_name,
1275 r->in.credential,
1276 r->out.return_authenticator,
1277 &creds);
1278 if (!NT_STATUS_IS_OK(status)) {
1279 DEBUG(0,(__location__ " Bad credentials - error\n"));
1281 NT_STATUS_NOT_OK_RETURN(status);
1283 if (r->in.query_level != 1) {
1284 return NT_STATUS_NOT_SUPPORTED;
1287 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1289 return NT_STATUS_OK;
1294 netr_NETRLOGONSETSERVICEBITS
1296 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1297 struct netr_NETRLOGONSETSERVICEBITS *r)
1299 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1304 netr_LogonGetTrustRid
1306 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1307 struct netr_LogonGetTrustRid *r)
1309 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1314 netr_NETRLOGONCOMPUTESERVERDIGEST
1316 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1317 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1319 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1324 netr_NETRLOGONCOMPUTECLIENTDIGEST
1326 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1327 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1329 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1335 netr_DsRGetSiteName
1337 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1338 struct netr_DsRGetSiteName *r)
1340 struct ldb_context *sam_ctx;
1341 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1343 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1344 dce_call->conn->auth_state.session_info, 0);
1345 if (sam_ctx == NULL) {
1346 return WERR_DS_UNAVAILABLE;
1350 * We assume to be a DC when we get called over NETLOGON. Hence we
1351 * get our site name always by using "samdb_server_site_name()"
1352 * and not "samdb_client_site_name()".
1354 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1355 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1357 return WERR_OK;
1362 fill in a netr_OneDomainInfo from a ldb search result
1364 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1365 struct loadparm_context *lp_ctx,
1366 struct ldb_context *sam_ctx,
1367 struct ldb_message *res,
1368 struct netr_OneDomainInfo *info,
1369 bool is_local, bool is_trust_list)
1371 ZERO_STRUCTP(info);
1373 if (is_trust_list) {
1374 /* w2k8 only fills this on trusted domains */
1375 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1376 info->trust_extension.length = 16;
1377 info->trust_extension.info->flags =
1378 NETR_TRUST_FLAG_TREEROOT |
1379 NETR_TRUST_FLAG_IN_FOREST |
1380 NETR_TRUST_FLAG_PRIMARY |
1381 NETR_TRUST_FLAG_NATIVE;
1383 info->trust_extension.info->parent_index = 0; /* should be index into array
1384 of parent */
1385 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1386 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1389 if (is_trust_list) {
1390 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1391 info->dns_forestname.string = NULL;
1392 } else {
1393 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1394 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1395 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1396 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1399 if (is_local) {
1400 info->domainname.string = lpcfg_workgroup(lp_ctx);
1401 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1402 info->domain_guid = samdb_result_guid(res, "objectGUID");
1403 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1404 } else {
1405 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1406 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1407 info->domain_guid = samdb_result_guid(res, "objectGUID");
1408 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1410 if (!is_trust_list) {
1411 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1414 return NT_STATUS_OK;
1418 netr_LogonGetDomainInfo
1419 this is called as part of the ADS domain logon procedure.
1421 It has an important role in convaying details about the client, such
1422 as Operating System, Version, Service Pack etc.
1424 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1425 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1427 struct netlogon_creds_CredentialState *creds;
1428 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1429 "securityIdentifier", "trustPartner", NULL };
1430 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1431 "msDS-SupportedEncryptionTypes", NULL };
1432 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1433 struct ldb_context *sam_ctx;
1434 struct ldb_message **res1, **res2, **res3, *new_msg;
1435 struct ldb_dn *workstation_dn;
1436 struct netr_DomainInformation *domain_info;
1437 struct netr_LsaPolicyInformation *lsa_policy_info;
1438 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1439 bool update_dns_hostname = true;
1440 int ret, ret3, i;
1441 NTSTATUS status;
1443 status = dcesrv_netr_creds_server_step_check(dce_call,
1444 mem_ctx,
1445 r->in.computer_name,
1446 r->in.credential,
1447 r->out.return_authenticator,
1448 &creds);
1449 if (!NT_STATUS_IS_OK(status)) {
1450 DEBUG(0,(__location__ " Bad credentials - error\n"));
1452 NT_STATUS_NOT_OK_RETURN(status);
1454 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1455 dce_call->conn->dce_ctx->lp_ctx,
1456 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1457 if (sam_ctx == NULL) {
1458 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1461 switch (r->in.level) {
1462 case 1: /* Domain information */
1464 if (r->in.query->workstation_info == NULL) {
1465 return NT_STATUS_INVALID_PARAMETER;
1468 /* Prepares the workstation DN */
1469 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1470 dom_sid_string(mem_ctx, creds->sid));
1471 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1473 /* Lookup for attributes in workstation object */
1474 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1475 attrs2);
1476 if (ret != 1) {
1477 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1480 /* Gets the sam account name which is checked against the DNS
1481 * hostname parameter. */
1482 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1483 "sAMAccountName",
1484 NULL);
1485 if (sam_account_name == NULL) {
1486 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1490 * Checks that the sam account name without a possible "$"
1491 * matches as prefix with the DNS hostname in the workstation
1492 * info structure.
1494 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1495 strcspn(sam_account_name, "$"));
1496 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1497 if (r->in.query->workstation_info->dns_hostname != NULL) {
1498 prefix2 = talloc_strndup(mem_ctx,
1499 r->in.query->workstation_info->dns_hostname,
1500 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1501 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1503 if (strcasecmp(prefix1, prefix2) != 0) {
1504 update_dns_hostname = false;
1506 } else {
1507 update_dns_hostname = false;
1510 /* Gets the old DNS hostname */
1511 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1512 "dNSHostName",
1513 NULL);
1516 * Updates the DNS hostname when the client wishes that the
1517 * server should handle this for him
1518 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1519 * obviously only checked when we do already have a
1520 * "dNSHostName".
1521 * See MS-NRPC section 3.5.4.3.9
1523 if ((old_dns_hostname != NULL) &&
1524 (r->in.query->workstation_info->workstation_flags
1525 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1526 update_dns_hostname = false;
1529 /* Gets host information and put them into our directory */
1531 new_msg = ldb_msg_new(mem_ctx);
1532 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1534 new_msg->dn = workstation_dn;
1536 /* Sets the OS name */
1538 if (r->in.query->workstation_info->os_name.string == NULL) {
1539 return NT_STATUS_INVALID_PARAMETER;
1542 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1543 r->in.query->workstation_info->os_name.string);
1544 if (ret != LDB_SUCCESS) {
1545 return NT_STATUS_NO_MEMORY;
1549 * Sets information from "os_version". On an empty structure
1550 * the values are cleared.
1552 if (r->in.query->workstation_info->os_version.os != NULL) {
1553 struct netr_OsVersionInfoEx *os_version;
1554 const char *os_version_str;
1556 os_version = &r->in.query->workstation_info->os_version.os->os;
1558 if (os_version->CSDVersion == NULL) {
1559 return NT_STATUS_INVALID_PARAMETER;
1562 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1563 os_version->MajorVersion,
1564 os_version->MinorVersion,
1565 os_version->BuildNumber);
1566 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1568 ret = ldb_msg_add_string(new_msg,
1569 "operatingSystemServicePack",
1570 os_version->CSDVersion);
1571 if (ret != LDB_SUCCESS) {
1572 return NT_STATUS_NO_MEMORY;
1575 ret = ldb_msg_add_string(new_msg,
1576 "operatingSystemVersion",
1577 os_version_str);
1578 if (ret != LDB_SUCCESS) {
1579 return NT_STATUS_NO_MEMORY;
1581 } else {
1582 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1583 "operatingSystemServicePack");
1584 if (ret != LDB_SUCCESS) {
1585 return NT_STATUS_NO_MEMORY;
1588 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1589 "operatingSystemVersion");
1590 if (ret != LDB_SUCCESS) {
1591 return NT_STATUS_NO_MEMORY;
1596 * If the boolean "update_dns_hostname" remained true, then we
1597 * are fine to start the update.
1599 if (update_dns_hostname) {
1600 ret = ldb_msg_add_string(new_msg,
1601 "dNSHostname",
1602 r->in.query->workstation_info->dns_hostname);
1603 if (ret != LDB_SUCCESS) {
1604 return NT_STATUS_NO_MEMORY;
1607 /* This manual "servicePrincipalName" generation is
1608 * still needed! Since the update in the samldb LDB
1609 * module does only work if the entries already exist
1610 * which isn't always the case. */
1611 ret = ldb_msg_add_string(new_msg,
1612 "servicePrincipalName",
1613 talloc_asprintf(new_msg, "HOST/%s",
1614 r->in.computer_name));
1615 if (ret != LDB_SUCCESS) {
1616 return NT_STATUS_NO_MEMORY;
1619 ret = ldb_msg_add_string(new_msg,
1620 "servicePrincipalName",
1621 talloc_asprintf(new_msg, "HOST/%s",
1622 r->in.query->workstation_info->dns_hostname));
1623 if (ret != LDB_SUCCESS) {
1624 return NT_STATUS_NO_MEMORY;
1628 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1629 DEBUG(3,("Impossible to update samdb: %s\n",
1630 ldb_errstring(sam_ctx)));
1633 talloc_free(new_msg);
1635 /* Writes back the domain information */
1637 /* We need to do two searches. The first will pull our primary
1638 domain and the second will pull any trusted domains. Our
1639 primary domain is also a "trusted" domain, so we need to
1640 put the primary domain into the lists of returned trusts as
1641 well. */
1642 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1643 &res2, attrs);
1644 if (ret != 1) {
1645 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1648 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1649 "(objectClass=trustedDomain)");
1650 if (ret3 == -1) {
1651 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1654 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1655 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1657 ZERO_STRUCTP(domain_info);
1659 /* Informations about the local and trusted domains */
1661 status = fill_one_domain_info(mem_ctx,
1662 dce_call->conn->dce_ctx->lp_ctx,
1663 sam_ctx, res2[0], &domain_info->primary_domain,
1664 true, false);
1665 NT_STATUS_NOT_OK_RETURN(status);
1667 domain_info->trusted_domain_count = ret3 + 1;
1668 domain_info->trusted_domains = talloc_array(mem_ctx,
1669 struct netr_OneDomainInfo,
1670 domain_info->trusted_domain_count);
1671 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1673 for (i=0;i<ret3;i++) {
1674 status = fill_one_domain_info(mem_ctx,
1675 dce_call->conn->dce_ctx->lp_ctx,
1676 sam_ctx, res3[i],
1677 &domain_info->trusted_domains[i],
1678 false, true);
1679 NT_STATUS_NOT_OK_RETURN(status);
1682 status = fill_one_domain_info(mem_ctx,
1683 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1684 &domain_info->trusted_domains[i], true, true);
1685 NT_STATUS_NOT_OK_RETURN(status);
1687 /* Sets the supported encryption types */
1688 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1689 "msDS-SupportedEncryptionTypes",
1690 default_supported_enc_types);
1692 /* Other host domain information */
1694 lsa_policy_info = talloc(mem_ctx,
1695 struct netr_LsaPolicyInformation);
1696 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1697 ZERO_STRUCTP(lsa_policy_info);
1699 domain_info->lsa_policy = *lsa_policy_info;
1701 /* The DNS hostname is only returned back when there is a chance
1702 * for a change. */
1703 if ((r->in.query->workstation_info->workstation_flags
1704 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1705 domain_info->dns_hostname.string = old_dns_hostname;
1706 } else {
1707 domain_info->dns_hostname.string = NULL;
1710 domain_info->workstation_flags =
1711 r->in.query->workstation_info->workstation_flags & (
1712 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1714 r->out.info->domain_info = domain_info;
1715 break;
1716 case 2: /* LSA policy information - not used at the moment */
1717 lsa_policy_info = talloc(mem_ctx,
1718 struct netr_LsaPolicyInformation);
1719 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1720 ZERO_STRUCTP(lsa_policy_info);
1722 r->out.info->lsa_policy_info = lsa_policy_info;
1723 break;
1724 default:
1725 return NT_STATUS_INVALID_LEVEL;
1726 break;
1729 return NT_STATUS_OK;
1734 netr_ServerPasswordGet
1736 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1737 struct netr_ServerPasswordGet *r)
1739 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1744 netr_NETRLOGONSENDTOSAM
1746 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1747 struct netr_NETRLOGONSENDTOSAM *r)
1749 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1754 netr_DsRGetDCNameEx2
1756 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1757 TALLOC_CTX *mem_ctx,
1758 struct netr_DsRGetDCNameEx2 *r)
1760 struct ldb_context *sam_ctx;
1761 struct netr_DsRGetDCNameInfo *info;
1762 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1763 const struct tsocket_address *remote_address;
1764 char *addr = NULL;
1765 const char *server_site_name;
1766 char *guid_str;
1767 struct netlogon_samlogon_response response;
1768 NTSTATUS status;
1769 const char *dc_name = NULL;
1770 const char *domain_name = NULL;
1771 struct interface *ifaces;
1772 const char *pdc_ip;
1774 ZERO_STRUCTP(r->out.info);
1776 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1777 dce_call->conn->auth_state.session_info, 0);
1778 if (sam_ctx == NULL) {
1779 return WERR_DS_UNAVAILABLE;
1782 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1783 if (tsocket_address_is_inet(remote_address, "ip")) {
1784 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1785 W_ERROR_HAVE_NO_MEMORY(addr);
1788 /* "server_unc" is ignored by w2k3 */
1790 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1791 return WERR_INVALID_FLAGS;
1794 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1795 r->in.flags & DS_PDC_REQUIRED &&
1796 r->in.flags & DS_KDC_REQUIRED) {
1797 return WERR_INVALID_FLAGS;
1799 if (r->in.flags & DS_IS_FLAT_NAME &&
1800 r->in.flags & DS_IS_DNS_NAME) {
1801 return WERR_INVALID_FLAGS;
1803 if (r->in.flags & DS_RETURN_DNS_NAME &&
1804 r->in.flags & DS_RETURN_FLAT_NAME) {
1805 return WERR_INVALID_FLAGS;
1807 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1808 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1809 return WERR_INVALID_FLAGS;
1812 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1813 r->in.flags &
1814 (DS_DIRECTORY_SERVICE_REQUIRED |
1815 DS_DIRECTORY_SERVICE_PREFERRED |
1816 DS_GC_SERVER_REQUIRED |
1817 DS_PDC_REQUIRED |
1818 DS_KDC_REQUIRED)) {
1819 return WERR_INVALID_FLAGS;
1822 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1823 r->in.site_name) {
1824 return WERR_INVALID_FLAGS;
1827 /* Proof server site parameter "site_name" if it was specified */
1828 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1829 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1830 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1831 server_site_name) != 0)) {
1832 return WERR_NO_SUCH_DOMAIN;
1835 guid_str = r->in.domain_guid != NULL ?
1836 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1838 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1839 r->in.domain_name,
1840 r->in.domain_name,
1841 NULL, guid_str,
1842 r->in.client_account,
1843 r->in.mask, addr,
1844 NETLOGON_NT_VERSION_5EX_WITH_IP,
1845 lp_ctx, &response, true);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 return ntstatus_to_werror(status);
1851 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1852 * (O) flag when the returned forest name is in DNS format. This is here
1853 * always the case (see below).
1855 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1857 if (r->in.flags & DS_RETURN_DNS_NAME) {
1858 dc_name = response.data.nt5_ex.pdc_dns_name;
1859 domain_name = response.data.nt5_ex.dns_domain;
1861 * According to MS-NRPC 2.2.1.2.1 we should set the
1862 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1863 * the returned information is in DNS form.
1865 response.data.nt5_ex.server_type |=
1866 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1867 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1868 dc_name = response.data.nt5_ex.pdc_name;
1869 domain_name = response.data.nt5_ex.domain_name;
1870 } else {
1873 * TODO: autodetect what we need to return
1874 * based on the given arguments
1876 dc_name = response.data.nt5_ex.pdc_name;
1877 domain_name = response.data.nt5_ex.domain_name;
1880 if (!dc_name || !dc_name[0]) {
1881 return WERR_NO_SUCH_DOMAIN;
1884 if (!domain_name || !domain_name[0]) {
1885 return WERR_NO_SUCH_DOMAIN;
1888 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1889 W_ERROR_HAVE_NO_MEMORY(info);
1890 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1891 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1893 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1894 pdc_ip = iface_list_best_ip(ifaces, addr);
1895 if (pdc_ip == NULL) {
1896 pdc_ip = "127.0.0.1";
1898 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1899 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1900 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1901 info->domain_guid = response.data.nt5_ex.domain_uuid;
1902 info->domain_name = domain_name;
1903 info->forest_name = response.data.nt5_ex.forest;
1904 info->dc_flags = response.data.nt5_ex.server_type;
1905 info->dc_site_name = response.data.nt5_ex.server_site;
1906 info->client_site_name = response.data.nt5_ex.client_site;
1908 *r->out.info = info;
1910 return WERR_OK;
1914 netr_DsRGetDCNameEx
1916 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1917 struct netr_DsRGetDCNameEx *r)
1919 struct netr_DsRGetDCNameEx2 r2;
1920 WERROR werr;
1922 ZERO_STRUCT(r2);
1924 r2.in.server_unc = r->in.server_unc;
1925 r2.in.client_account = NULL;
1926 r2.in.mask = 0;
1927 r2.in.domain_guid = r->in.domain_guid;
1928 r2.in.domain_name = r->in.domain_name;
1929 r2.in.site_name = r->in.site_name;
1930 r2.in.flags = r->in.flags;
1931 r2.out.info = r->out.info;
1933 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1935 return werr;
1939 netr_DsRGetDCName
1941 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1942 struct netr_DsRGetDCName *r)
1944 struct netr_DsRGetDCNameEx2 r2;
1945 WERROR werr;
1947 ZERO_STRUCT(r2);
1949 r2.in.server_unc = r->in.server_unc;
1950 r2.in.client_account = NULL;
1951 r2.in.mask = 0;
1952 r2.in.domain_name = r->in.domain_name;
1953 r2.in.domain_guid = r->in.domain_guid;
1955 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1956 r2.in.flags = r->in.flags;
1957 r2.out.info = r->out.info;
1959 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1961 return werr;
1964 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1966 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1967 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1969 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1974 netr_NetrEnumerateTrustedDomainsEx
1976 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1977 struct netr_NetrEnumerateTrustedDomainsEx *r)
1979 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1984 netr_DsRAddressToSitenamesExW
1986 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1987 struct netr_DsRAddressToSitenamesExW *r)
1989 struct ldb_context *sam_ctx;
1990 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1991 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1992 sa_family_t sin_family;
1993 struct sockaddr_in *addr;
1994 #ifdef HAVE_IPV6
1995 struct sockaddr_in6 *addr6;
1996 char addr_str[INET6_ADDRSTRLEN];
1997 #else
1998 char addr_str[INET_ADDRSTRLEN];
1999 #endif
2000 char *subnet_name;
2001 const char *res;
2002 uint32_t i;
2004 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2005 dce_call->conn->auth_state.session_info, 0);
2006 if (sam_ctx == NULL) {
2007 return WERR_DS_UNAVAILABLE;
2010 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2011 W_ERROR_HAVE_NO_MEMORY(ctr);
2013 *r->out.ctr = ctr;
2015 ctr->count = r->in.count;
2016 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2017 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2018 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2019 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2021 for (i=0; i<ctr->count; i++) {
2022 ctr->sitename[i].string = NULL;
2023 ctr->subnetname[i].string = NULL;
2025 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2026 continue;
2028 /* The first two byte of the buffer are reserved for the
2029 * "sin_family" but for now only the first one is used. */
2030 sin_family = r->in.addresses[i].buffer[0];
2032 switch (sin_family) {
2033 case AF_INET:
2034 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2035 continue;
2037 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2038 res = inet_ntop(AF_INET, &addr->sin_addr,
2039 addr_str, sizeof(addr_str));
2040 break;
2041 #ifdef HAVE_IPV6
2042 case AF_INET6:
2043 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2044 continue;
2046 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2047 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2048 addr_str, sizeof(addr_str));
2049 break;
2050 #endif
2051 default:
2052 continue;
2055 if (res == NULL) {
2056 continue;
2059 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2060 mem_ctx,
2061 addr_str,
2062 &subnet_name);
2063 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2064 ctr->subnetname[i].string = subnet_name;
2067 return WERR_OK;
2072 netr_DsRAddressToSitenamesW
2074 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2075 struct netr_DsRAddressToSitenamesW *r)
2077 struct netr_DsRAddressToSitenamesExW r2;
2078 struct netr_DsRAddressToSitenamesWCtr *ctr;
2079 uint32_t i;
2080 WERROR werr;
2082 ZERO_STRUCT(r2);
2084 r2.in.server_name = r->in.server_name;
2085 r2.in.count = r->in.count;
2086 r2.in.addresses = r->in.addresses;
2088 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2089 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2091 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2092 W_ERROR_HAVE_NO_MEMORY(ctr);
2094 *r->out.ctr = ctr;
2096 ctr->count = r->in.count;
2097 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2098 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2100 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2102 for (i=0; i<ctr->count; i++) {
2103 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2106 return werr;
2111 netr_DsrGetDcSiteCoverageW
2113 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2114 struct netr_DsrGetDcSiteCoverageW *r)
2116 struct ldb_context *sam_ctx;
2117 struct DcSitesCtr *ctr;
2118 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2120 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2121 dce_call->conn->auth_state.session_info, 0);
2122 if (sam_ctx == NULL) {
2123 return WERR_DS_UNAVAILABLE;
2126 ctr = talloc(mem_ctx, struct DcSitesCtr);
2127 W_ERROR_HAVE_NO_MEMORY(ctr);
2129 *r->out.ctr = ctr;
2131 /* For now only return our default site */
2132 ctr->num_sites = 1;
2133 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2134 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2135 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2136 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2138 return WERR_OK;
2142 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2143 struct ldb_context *sam_ctx,
2144 struct netr_DomainTrustList *trusts,
2145 uint32_t trust_flags)
2147 struct ldb_dn *system_dn;
2148 struct ldb_message **dom_res = NULL;
2149 const char *trust_attrs[] = { "flatname", "trustPartner",
2150 "securityIdentifier", "trustDirection",
2151 "trustType", "trustAttributes", NULL };
2152 uint32_t n;
2153 int i;
2154 int ret;
2156 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2157 NETR_TRUST_FLAG_OUTBOUND))) {
2158 return WERR_INVALID_FLAGS;
2161 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2162 ldb_get_default_basedn(sam_ctx),
2163 "(&(objectClass=container)(cn=System))");
2164 if (!system_dn) {
2165 return WERR_GENERAL_FAILURE;
2168 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2169 &dom_res, trust_attrs,
2170 "(objectclass=trustedDomain)");
2172 for (i = 0; i < ret; i++) {
2173 unsigned int trust_dir;
2174 uint32_t flags = 0;
2176 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2177 "trustDirection", 0);
2179 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2180 flags |= NETR_TRUST_FLAG_INBOUND;
2182 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2183 flags |= NETR_TRUST_FLAG_OUTBOUND;
2186 if (!(flags & trust_flags)) {
2187 /* this trust direction was not requested */
2188 continue;
2191 n = trusts->count;
2192 trusts->array = talloc_realloc(trusts, trusts->array,
2193 struct netr_DomainTrust,
2194 n + 1);
2195 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2197 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2198 if (!trusts->array[n].netbios_name) {
2199 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2200 "without flatname\n",
2201 ldb_dn_get_linearized(dom_res[i]->dn)));
2204 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2206 trusts->array[n].trust_flags = flags;
2207 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2208 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2209 /* TODO: find if we have parent in the list */
2210 trusts->array[n].parent_index = 0;
2213 trusts->array[n].trust_type =
2214 ldb_msg_find_attr_as_uint(dom_res[i],
2215 "trustType", 0);
2216 trusts->array[n].trust_attributes =
2217 ldb_msg_find_attr_as_uint(dom_res[i],
2218 "trustAttributes", 0);
2220 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2221 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2222 struct dom_sid zero_sid;
2223 ZERO_STRUCT(zero_sid);
2224 trusts->array[n].sid =
2225 dom_sid_dup(trusts, &zero_sid);
2226 } else {
2227 trusts->array[n].sid =
2228 samdb_result_dom_sid(trusts, dom_res[i],
2229 "securityIdentifier");
2231 trusts->array[n].guid = GUID_zero();
2233 trusts->count = n + 1;
2236 talloc_free(dom_res);
2237 return WERR_OK;
2241 netr_DsrEnumerateDomainTrusts
2243 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2244 TALLOC_CTX *mem_ctx,
2245 struct netr_DsrEnumerateDomainTrusts *r)
2247 struct netr_DomainTrustList *trusts;
2248 struct ldb_context *sam_ctx;
2249 int ret;
2250 struct ldb_message **dom_res;
2251 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2252 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2253 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2254 const char *p;
2255 WERROR werr;
2257 if (r->in.trust_flags & 0xFFFFFE00) {
2258 return WERR_INVALID_FLAGS;
2261 /* TODO: turn to hard check once we are sure this is 100% correct */
2262 if (!r->in.server_name) {
2263 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2264 "But received NULL!\n", dnsdomain));
2265 } else {
2266 p = strchr(r->in.server_name, '.');
2267 if (!p) {
2268 DEBUG(3, ("Invalid domain! Expected name in domain "
2269 "[%s]. But received [%s]!\n",
2270 dnsdomain, r->in.server_name));
2271 p = r->in.server_name;
2272 } else {
2273 p++;
2275 if (strcasecmp(p, dnsdomain)) {
2276 DEBUG(3, ("Invalid domain! Expected name in domain "
2277 "[%s]. But received [%s]!\n",
2278 dnsdomain, r->in.server_name));
2282 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2283 W_ERROR_HAVE_NO_MEMORY(trusts);
2285 trusts->count = 0;
2286 r->out.trusts = trusts;
2288 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2289 dce_call->conn->auth_state.session_info, 0);
2290 if (sam_ctx == NULL) {
2291 return WERR_GENERAL_FAILURE;
2294 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2295 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2297 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2298 trusts, r->in.trust_flags);
2299 W_ERROR_NOT_OK_RETURN(werr);
2302 /* NOTE: we currently are always the root of the forest */
2303 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2304 uint32_t n = trusts->count;
2306 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2307 &dom_res, dom_attrs);
2308 if (ret != 1) {
2309 return WERR_GENERAL_FAILURE;
2312 trusts->count = n + 1;
2313 trusts->array = talloc_realloc(trusts, trusts->array,
2314 struct netr_DomainTrust,
2315 trusts->count);
2316 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2318 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2319 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2320 trusts->array[n].trust_flags =
2321 NETR_TRUST_FLAG_NATIVE |
2322 NETR_TRUST_FLAG_TREEROOT |
2323 NETR_TRUST_FLAG_IN_FOREST |
2324 NETR_TRUST_FLAG_PRIMARY;
2325 /* we are always the root domain for now */
2326 trusts->array[n].parent_index = 0;
2327 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2328 trusts->array[n].trust_attributes = 0;
2329 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2330 dom_res[0],
2331 "objectSid");
2332 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2333 "objectGUID");
2334 talloc_free(dom_res);
2337 return WERR_OK;
2342 netr_DsrDeregisterDNSHostRecords
2344 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2345 struct netr_DsrDeregisterDNSHostRecords *r)
2347 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2352 netr_ServerTrustPasswordsGet
2354 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2355 struct netr_ServerTrustPasswordsGet *r)
2357 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2361 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2362 struct ldb_context *sam_ctx,
2363 struct loadparm_context *lp_ctx,
2364 struct lsa_ForestTrustInformation *info)
2366 struct lsa_ForestTrustDomainInfo *domain_info;
2367 struct lsa_ForestTrustRecord *e;
2368 struct ldb_message **dom_res;
2369 const char * const dom_attrs[] = { "objectSid", NULL };
2370 int ret;
2372 /* we need to provide 2 entries:
2373 * 1. the Root Forest name
2374 * 2. the Domain Information
2377 info->count = 2;
2378 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2379 W_ERROR_HAVE_NO_MEMORY(info->entries);
2381 /* Forest root info */
2382 e = talloc(info, struct lsa_ForestTrustRecord);
2383 W_ERROR_HAVE_NO_MEMORY(e);
2385 e->flags = 0;
2386 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2387 e->time = 0; /* so far always 0 in trces. */
2388 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2389 mem_ctx);
2390 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2392 info->entries[0] = e;
2394 /* Domain info */
2395 e = talloc(info, struct lsa_ForestTrustRecord);
2396 W_ERROR_HAVE_NO_MEMORY(e);
2398 /* get our own domain info */
2399 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2400 if (ret != 1) {
2401 return WERR_GENERAL_FAILURE;
2404 /* TODO: check if disabled and set flags accordingly */
2405 e->flags = 0;
2406 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2407 e->time = 0; /* so far always 0 in traces. */
2409 domain_info = &e->forest_trust_data.domain_info;
2410 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2411 "objectSid");
2412 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2413 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2415 info->entries[1] = e;
2417 talloc_free(dom_res);
2419 return WERR_OK;
2423 netr_DsRGetForestTrustInformation
2425 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2426 TALLOC_CTX *mem_ctx,
2427 struct netr_DsRGetForestTrustInformation *r)
2429 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2430 struct lsa_ForestTrustInformation *info, **info_ptr;
2431 struct ldb_context *sam_ctx;
2432 WERROR werr;
2434 if (r->in.flags & 0xFFFFFFFE) {
2435 return WERR_INVALID_FLAGS;
2438 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2439 dce_call->conn->auth_state.session_info, 0);
2440 if (sam_ctx == NULL) {
2441 return WERR_GENERAL_FAILURE;
2444 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2445 if (!samdb_is_pdc(sam_ctx)) {
2446 return WERR_NERR_NOTPRIMARY;
2449 if (r->in.trusted_domain_name == NULL) {
2450 return WERR_INVALID_FLAGS;
2453 /* TODO: establish an schannel connection with
2454 * r->in.trusted_domain_name and perform a
2455 * netr_GetForestTrustInformation call against it */
2457 /* for now return not implementd */
2458 return WERR_CALL_NOT_IMPLEMENTED;
2461 /* TODO: check r->in.server_name is our name */
2463 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2464 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2466 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2467 W_ERROR_HAVE_NO_MEMORY(info);
2469 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2470 W_ERROR_NOT_OK_RETURN(werr);
2472 *info_ptr = info;
2473 r->out.forest_trust_info = info_ptr;
2475 return WERR_OK;
2480 netr_GetForestTrustInformation
2482 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2483 TALLOC_CTX *mem_ctx,
2484 struct netr_GetForestTrustInformation *r)
2486 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2487 struct netlogon_creds_CredentialState *creds;
2488 struct lsa_ForestTrustInformation *info, **info_ptr;
2489 struct ldb_context *sam_ctx;
2490 NTSTATUS status;
2491 WERROR werr;
2493 status = dcesrv_netr_creds_server_step_check(dce_call,
2494 mem_ctx,
2495 r->in.computer_name,
2496 r->in.credential,
2497 r->out.return_authenticator,
2498 &creds);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 return status;
2503 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2504 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2505 return NT_STATUS_NOT_IMPLEMENTED;
2508 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2509 dce_call->conn->auth_state.session_info, 0);
2510 if (sam_ctx == NULL) {
2511 return NT_STATUS_INTERNAL_ERROR;
2514 /* TODO: check r->in.server_name is our name */
2516 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2517 if (!info_ptr) {
2518 return NT_STATUS_NO_MEMORY;
2520 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2521 if (!info) {
2522 return NT_STATUS_NO_MEMORY;
2525 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2526 if (!W_ERROR_IS_OK(werr)) {
2527 return werror_to_ntstatus(werr);
2530 *info_ptr = info;
2531 r->out.forest_trust_info = info_ptr;
2533 return NT_STATUS_OK;
2538 netr_ServerGetTrustInfo
2540 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2541 struct netr_ServerGetTrustInfo *r)
2543 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2547 netr_Unused47
2549 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2550 struct netr_Unused47 *r)
2552 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2556 struct netr_dnsupdate_RODC_state {
2557 struct dcesrv_call_state *dce_call;
2558 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2559 struct dnsupdate_RODC *r2;
2563 called when the forwarded RODC dns update request is finished
2565 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2567 struct netr_dnsupdate_RODC_state *st =
2568 tevent_req_callback_data(subreq,
2569 struct netr_dnsupdate_RODC_state);
2570 NTSTATUS status;
2572 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2573 TALLOC_FREE(subreq);
2574 if (!NT_STATUS_IS_OK(status)) {
2575 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2576 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2579 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2581 status = dcesrv_reply(st->dce_call);
2582 if (!NT_STATUS_IS_OK(status)) {
2583 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2588 netr_DsrUpdateReadOnlyServerDnsRecords
2590 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2591 TALLOC_CTX *mem_ctx,
2592 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2594 struct netlogon_creds_CredentialState *creds;
2595 NTSTATUS nt_status;
2596 struct dcerpc_binding_handle *binding_handle;
2597 struct netr_dnsupdate_RODC_state *st;
2598 struct tevent_req *subreq;
2600 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2601 mem_ctx,
2602 r->in.computer_name,
2603 r->in.credential,
2604 r->out.return_authenticator,
2605 &creds);
2606 NT_STATUS_NOT_OK_RETURN(nt_status);
2608 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2609 return NT_STATUS_ACCESS_DENIED;
2612 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2613 NT_STATUS_HAVE_NO_MEMORY(st);
2615 st->dce_call = dce_call;
2616 st->r = r;
2617 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2618 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2620 st->r2->in.dom_sid = creds->sid;
2621 st->r2->in.site_name = r->in.site_name;
2622 st->r2->in.dns_ttl = r->in.dns_ttl;
2623 st->r2->in.dns_names = r->in.dns_names;
2624 st->r2->out.dns_names = r->out.dns_names;
2626 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2627 "dnsupdate", &ndr_table_irpc);
2628 if (binding_handle == NULL) {
2629 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2630 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2631 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2634 /* forward the call */
2635 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2636 binding_handle, st->r2);
2637 NT_STATUS_HAVE_NO_MEMORY(subreq);
2639 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2641 /* setup the callback */
2642 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2644 return NT_STATUS_OK;
2648 /* include the generated boilerplate */
2649 #include "librpc/gen_ndr/ndr_netlogon_s.c"