s4-rpc_server: support AES encryption in interactive and generic samlogon.
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobac69d3d84eab1c35d82beaaf66fb714622f8d545
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;
1713 r->out.info->domain_info = domain_info;
1714 break;
1715 case 2: /* LSA policy information - not used at the moment */
1716 lsa_policy_info = talloc(mem_ctx,
1717 struct netr_LsaPolicyInformation);
1718 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1719 ZERO_STRUCTP(lsa_policy_info);
1721 r->out.info->lsa_policy_info = lsa_policy_info;
1722 break;
1723 default:
1724 return NT_STATUS_INVALID_LEVEL;
1725 break;
1728 return NT_STATUS_OK;
1733 netr_ServerPasswordGet
1735 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1736 struct netr_ServerPasswordGet *r)
1738 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1743 netr_NETRLOGONSENDTOSAM
1745 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1746 struct netr_NETRLOGONSENDTOSAM *r)
1748 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1753 netr_DsRGetDCNameEx2
1755 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1756 TALLOC_CTX *mem_ctx,
1757 struct netr_DsRGetDCNameEx2 *r)
1759 struct ldb_context *sam_ctx;
1760 struct netr_DsRGetDCNameInfo *info;
1761 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1762 const struct tsocket_address *remote_address;
1763 char *addr = NULL;
1764 const char *server_site_name;
1765 char *guid_str;
1766 struct netlogon_samlogon_response response;
1767 NTSTATUS status;
1768 const char *dc_name = NULL;
1769 const char *domain_name = NULL;
1770 struct interface *ifaces;
1771 const char *pdc_ip;
1773 ZERO_STRUCTP(r->out.info);
1775 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1776 dce_call->conn->auth_state.session_info, 0);
1777 if (sam_ctx == NULL) {
1778 return WERR_DS_UNAVAILABLE;
1781 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1782 if (tsocket_address_is_inet(remote_address, "ip")) {
1783 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1784 W_ERROR_HAVE_NO_MEMORY(addr);
1787 /* "server_unc" is ignored by w2k3 */
1789 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1790 return WERR_INVALID_FLAGS;
1793 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1794 r->in.flags & DS_PDC_REQUIRED &&
1795 r->in.flags & DS_KDC_REQUIRED) {
1796 return WERR_INVALID_FLAGS;
1798 if (r->in.flags & DS_IS_FLAT_NAME &&
1799 r->in.flags & DS_IS_DNS_NAME) {
1800 return WERR_INVALID_FLAGS;
1802 if (r->in.flags & DS_RETURN_DNS_NAME &&
1803 r->in.flags & DS_RETURN_FLAT_NAME) {
1804 return WERR_INVALID_FLAGS;
1806 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1807 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1808 return WERR_INVALID_FLAGS;
1811 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1812 r->in.flags &
1813 (DS_DIRECTORY_SERVICE_REQUIRED |
1814 DS_DIRECTORY_SERVICE_PREFERRED |
1815 DS_GC_SERVER_REQUIRED |
1816 DS_PDC_REQUIRED |
1817 DS_KDC_REQUIRED)) {
1818 return WERR_INVALID_FLAGS;
1821 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1822 r->in.site_name) {
1823 return WERR_INVALID_FLAGS;
1826 /* Proof server site parameter "site_name" if it was specified */
1827 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1828 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1829 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1830 server_site_name) != 0)) {
1831 return WERR_NO_SUCH_DOMAIN;
1834 guid_str = r->in.domain_guid != NULL ?
1835 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1837 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1838 r->in.domain_name,
1839 r->in.domain_name,
1840 NULL, guid_str,
1841 r->in.client_account,
1842 r->in.mask, addr,
1843 NETLOGON_NT_VERSION_5EX_WITH_IP,
1844 lp_ctx, &response, true);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 return ntstatus_to_werror(status);
1850 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1851 * (O) flag when the returned forest name is in DNS format. This is here
1852 * always the case (see below).
1854 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1856 if (r->in.flags & DS_RETURN_DNS_NAME) {
1857 dc_name = response.data.nt5_ex.pdc_dns_name;
1858 domain_name = response.data.nt5_ex.dns_domain;
1860 * According to MS-NRPC 2.2.1.2.1 we should set the
1861 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1862 * the returned information is in DNS form.
1864 response.data.nt5_ex.server_type |=
1865 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1866 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1867 dc_name = response.data.nt5_ex.pdc_name;
1868 domain_name = response.data.nt5_ex.domain_name;
1869 } else {
1872 * TODO: autodetect what we need to return
1873 * based on the given arguments
1875 dc_name = response.data.nt5_ex.pdc_name;
1876 domain_name = response.data.nt5_ex.domain_name;
1879 if (!dc_name || !dc_name[0]) {
1880 return WERR_NO_SUCH_DOMAIN;
1883 if (!domain_name || !domain_name[0]) {
1884 return WERR_NO_SUCH_DOMAIN;
1887 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1888 W_ERROR_HAVE_NO_MEMORY(info);
1889 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1890 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1892 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1893 pdc_ip = iface_list_best_ip(ifaces, addr);
1894 if (pdc_ip == NULL) {
1895 pdc_ip = "127.0.0.1";
1897 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1898 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1899 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1900 info->domain_guid = response.data.nt5_ex.domain_uuid;
1901 info->domain_name = domain_name;
1902 info->forest_name = response.data.nt5_ex.forest;
1903 info->dc_flags = response.data.nt5_ex.server_type;
1904 info->dc_site_name = response.data.nt5_ex.server_site;
1905 info->client_site_name = response.data.nt5_ex.client_site;
1907 *r->out.info = info;
1909 return WERR_OK;
1913 netr_DsRGetDCNameEx
1915 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1916 struct netr_DsRGetDCNameEx *r)
1918 struct netr_DsRGetDCNameEx2 r2;
1919 WERROR werr;
1921 ZERO_STRUCT(r2);
1923 r2.in.server_unc = r->in.server_unc;
1924 r2.in.client_account = NULL;
1925 r2.in.mask = 0;
1926 r2.in.domain_guid = r->in.domain_guid;
1927 r2.in.domain_name = r->in.domain_name;
1928 r2.in.site_name = r->in.site_name;
1929 r2.in.flags = r->in.flags;
1930 r2.out.info = r->out.info;
1932 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1934 return werr;
1938 netr_DsRGetDCName
1940 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1941 struct netr_DsRGetDCName *r)
1943 struct netr_DsRGetDCNameEx2 r2;
1944 WERROR werr;
1946 ZERO_STRUCT(r2);
1948 r2.in.server_unc = r->in.server_unc;
1949 r2.in.client_account = NULL;
1950 r2.in.mask = 0;
1951 r2.in.domain_name = r->in.domain_name;
1952 r2.in.domain_guid = r->in.domain_guid;
1954 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1955 r2.in.flags = r->in.flags;
1956 r2.out.info = r->out.info;
1958 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1960 return werr;
1963 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1965 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1966 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1968 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1973 netr_NetrEnumerateTrustedDomainsEx
1975 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1976 struct netr_NetrEnumerateTrustedDomainsEx *r)
1978 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1983 netr_DsRAddressToSitenamesExW
1985 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1986 struct netr_DsRAddressToSitenamesExW *r)
1988 struct ldb_context *sam_ctx;
1989 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1990 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1991 sa_family_t sin_family;
1992 struct sockaddr_in *addr;
1993 #ifdef HAVE_IPV6
1994 struct sockaddr_in6 *addr6;
1995 char addr_str[INET6_ADDRSTRLEN];
1996 #else
1997 char addr_str[INET_ADDRSTRLEN];
1998 #endif
1999 char *subnet_name;
2000 const char *res;
2001 uint32_t i;
2003 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2004 dce_call->conn->auth_state.session_info, 0);
2005 if (sam_ctx == NULL) {
2006 return WERR_DS_UNAVAILABLE;
2009 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2010 W_ERROR_HAVE_NO_MEMORY(ctr);
2012 *r->out.ctr = ctr;
2014 ctr->count = r->in.count;
2015 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2016 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2017 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2018 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2020 for (i=0; i<ctr->count; i++) {
2021 ctr->sitename[i].string = NULL;
2022 ctr->subnetname[i].string = NULL;
2024 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2025 continue;
2027 /* The first two byte of the buffer are reserved for the
2028 * "sin_family" but for now only the first one is used. */
2029 sin_family = r->in.addresses[i].buffer[0];
2031 switch (sin_family) {
2032 case AF_INET:
2033 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2034 continue;
2036 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2037 res = inet_ntop(AF_INET, &addr->sin_addr,
2038 addr_str, sizeof(addr_str));
2039 break;
2040 #ifdef HAVE_IPV6
2041 case AF_INET6:
2042 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2043 continue;
2045 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2046 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2047 addr_str, sizeof(addr_str));
2048 break;
2049 #endif
2050 default:
2051 continue;
2054 if (res == NULL) {
2055 continue;
2058 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2059 mem_ctx,
2060 addr_str,
2061 &subnet_name);
2062 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2063 ctr->subnetname[i].string = subnet_name;
2066 return WERR_OK;
2071 netr_DsRAddressToSitenamesW
2073 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2074 struct netr_DsRAddressToSitenamesW *r)
2076 struct netr_DsRAddressToSitenamesExW r2;
2077 struct netr_DsRAddressToSitenamesWCtr *ctr;
2078 uint32_t i;
2079 WERROR werr;
2081 ZERO_STRUCT(r2);
2083 r2.in.server_name = r->in.server_name;
2084 r2.in.count = r->in.count;
2085 r2.in.addresses = r->in.addresses;
2087 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2088 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2090 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2091 W_ERROR_HAVE_NO_MEMORY(ctr);
2093 *r->out.ctr = ctr;
2095 ctr->count = r->in.count;
2096 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2097 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2099 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2101 for (i=0; i<ctr->count; i++) {
2102 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2105 return werr;
2110 netr_DsrGetDcSiteCoverageW
2112 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2113 struct netr_DsrGetDcSiteCoverageW *r)
2115 struct ldb_context *sam_ctx;
2116 struct DcSitesCtr *ctr;
2117 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2119 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2120 dce_call->conn->auth_state.session_info, 0);
2121 if (sam_ctx == NULL) {
2122 return WERR_DS_UNAVAILABLE;
2125 ctr = talloc(mem_ctx, struct DcSitesCtr);
2126 W_ERROR_HAVE_NO_MEMORY(ctr);
2128 *r->out.ctr = ctr;
2130 /* For now only return our default site */
2131 ctr->num_sites = 1;
2132 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2133 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2134 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2135 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2137 return WERR_OK;
2141 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2142 struct ldb_context *sam_ctx,
2143 struct netr_DomainTrustList *trusts,
2144 uint32_t trust_flags)
2146 struct ldb_dn *system_dn;
2147 struct ldb_message **dom_res = NULL;
2148 const char *trust_attrs[] = { "flatname", "trustPartner",
2149 "securityIdentifier", "trustDirection",
2150 "trustType", "trustAttributes", NULL };
2151 uint32_t n;
2152 int i;
2153 int ret;
2155 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2156 NETR_TRUST_FLAG_OUTBOUND))) {
2157 return WERR_INVALID_FLAGS;
2160 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2161 ldb_get_default_basedn(sam_ctx),
2162 "(&(objectClass=container)(cn=System))");
2163 if (!system_dn) {
2164 return WERR_GENERAL_FAILURE;
2167 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2168 &dom_res, trust_attrs,
2169 "(objectclass=trustedDomain)");
2171 for (i = 0; i < ret; i++) {
2172 unsigned int trust_dir;
2173 uint32_t flags = 0;
2175 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2176 "trustDirection", 0);
2178 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2179 flags |= NETR_TRUST_FLAG_INBOUND;
2181 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2182 flags |= NETR_TRUST_FLAG_OUTBOUND;
2185 if (!(flags & trust_flags)) {
2186 /* this trust direction was not requested */
2187 continue;
2190 n = trusts->count;
2191 trusts->array = talloc_realloc(trusts, trusts->array,
2192 struct netr_DomainTrust,
2193 n + 1);
2194 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2196 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2197 if (!trusts->array[n].netbios_name) {
2198 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2199 "without flatname\n",
2200 ldb_dn_get_linearized(dom_res[i]->dn)));
2203 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2205 trusts->array[n].trust_flags = flags;
2206 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2207 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2208 /* TODO: find if we have parent in the list */
2209 trusts->array[n].parent_index = 0;
2212 trusts->array[n].trust_type =
2213 ldb_msg_find_attr_as_uint(dom_res[i],
2214 "trustType", 0);
2215 trusts->array[n].trust_attributes =
2216 ldb_msg_find_attr_as_uint(dom_res[i],
2217 "trustAttributes", 0);
2219 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2220 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2221 struct dom_sid zero_sid;
2222 ZERO_STRUCT(zero_sid);
2223 trusts->array[n].sid =
2224 dom_sid_dup(trusts, &zero_sid);
2225 } else {
2226 trusts->array[n].sid =
2227 samdb_result_dom_sid(trusts, dom_res[i],
2228 "securityIdentifier");
2230 trusts->array[n].guid = GUID_zero();
2232 trusts->count = n + 1;
2235 talloc_free(dom_res);
2236 return WERR_OK;
2240 netr_DsrEnumerateDomainTrusts
2242 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2243 TALLOC_CTX *mem_ctx,
2244 struct netr_DsrEnumerateDomainTrusts *r)
2246 struct netr_DomainTrustList *trusts;
2247 struct ldb_context *sam_ctx;
2248 int ret;
2249 struct ldb_message **dom_res;
2250 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2251 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2252 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2253 const char *p;
2254 WERROR werr;
2256 if (r->in.trust_flags & 0xFFFFFE00) {
2257 return WERR_INVALID_FLAGS;
2260 /* TODO: turn to hard check once we are sure this is 100% correct */
2261 if (!r->in.server_name) {
2262 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2263 "But received NULL!\n", dnsdomain));
2264 } else {
2265 p = strchr(r->in.server_name, '.');
2266 if (!p) {
2267 DEBUG(3, ("Invalid domain! Expected name in domain "
2268 "[%s]. But received [%s]!\n",
2269 dnsdomain, r->in.server_name));
2270 p = r->in.server_name;
2271 } else {
2272 p++;
2274 if (strcasecmp(p, dnsdomain)) {
2275 DEBUG(3, ("Invalid domain! Expected name in domain "
2276 "[%s]. But received [%s]!\n",
2277 dnsdomain, r->in.server_name));
2281 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2282 W_ERROR_HAVE_NO_MEMORY(trusts);
2284 trusts->count = 0;
2285 r->out.trusts = trusts;
2287 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2288 dce_call->conn->auth_state.session_info, 0);
2289 if (sam_ctx == NULL) {
2290 return WERR_GENERAL_FAILURE;
2293 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2294 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2296 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2297 trusts, r->in.trust_flags);
2298 W_ERROR_NOT_OK_RETURN(werr);
2301 /* NOTE: we currently are always the root of the forest */
2302 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2303 uint32_t n = trusts->count;
2305 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2306 &dom_res, dom_attrs);
2307 if (ret != 1) {
2308 return WERR_GENERAL_FAILURE;
2311 trusts->count = n + 1;
2312 trusts->array = talloc_realloc(trusts, trusts->array,
2313 struct netr_DomainTrust,
2314 trusts->count);
2315 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2317 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2318 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2319 trusts->array[n].trust_flags =
2320 NETR_TRUST_FLAG_NATIVE |
2321 NETR_TRUST_FLAG_TREEROOT |
2322 NETR_TRUST_FLAG_IN_FOREST |
2323 NETR_TRUST_FLAG_PRIMARY;
2324 /* we are always the root domain for now */
2325 trusts->array[n].parent_index = 0;
2326 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2327 trusts->array[n].trust_attributes = 0;
2328 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2329 dom_res[0],
2330 "objectSid");
2331 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2332 "objectGUID");
2333 talloc_free(dom_res);
2336 return WERR_OK;
2341 netr_DsrDeregisterDNSHostRecords
2343 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2344 struct netr_DsrDeregisterDNSHostRecords *r)
2346 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2351 netr_ServerTrustPasswordsGet
2353 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2354 struct netr_ServerTrustPasswordsGet *r)
2356 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2360 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2361 struct ldb_context *sam_ctx,
2362 struct loadparm_context *lp_ctx,
2363 struct lsa_ForestTrustInformation *info)
2365 struct lsa_ForestTrustDomainInfo *domain_info;
2366 struct lsa_ForestTrustRecord *e;
2367 struct ldb_message **dom_res;
2368 const char * const dom_attrs[] = { "objectSid", NULL };
2369 int ret;
2371 /* we need to provide 2 entries:
2372 * 1. the Root Forest name
2373 * 2. the Domain Information
2376 info->count = 2;
2377 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2378 W_ERROR_HAVE_NO_MEMORY(info->entries);
2380 /* Forest root info */
2381 e = talloc(info, struct lsa_ForestTrustRecord);
2382 W_ERROR_HAVE_NO_MEMORY(e);
2384 e->flags = 0;
2385 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2386 e->time = 0; /* so far always 0 in trces. */
2387 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2388 mem_ctx);
2389 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2391 info->entries[0] = e;
2393 /* Domain info */
2394 e = talloc(info, struct lsa_ForestTrustRecord);
2395 W_ERROR_HAVE_NO_MEMORY(e);
2397 /* get our own domain info */
2398 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2399 if (ret != 1) {
2400 return WERR_GENERAL_FAILURE;
2403 /* TODO: check if disabled and set flags accordingly */
2404 e->flags = 0;
2405 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2406 e->time = 0; /* so far always 0 in traces. */
2408 domain_info = &e->forest_trust_data.domain_info;
2409 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2410 "objectSid");
2411 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2412 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2414 info->entries[1] = e;
2416 talloc_free(dom_res);
2418 return WERR_OK;
2422 netr_DsRGetForestTrustInformation
2424 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2425 TALLOC_CTX *mem_ctx,
2426 struct netr_DsRGetForestTrustInformation *r)
2428 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2429 struct lsa_ForestTrustInformation *info, **info_ptr;
2430 struct ldb_context *sam_ctx;
2431 WERROR werr;
2433 if (r->in.flags & 0xFFFFFFFE) {
2434 return WERR_INVALID_FLAGS;
2437 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2438 dce_call->conn->auth_state.session_info, 0);
2439 if (sam_ctx == NULL) {
2440 return WERR_GENERAL_FAILURE;
2443 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2444 if (!samdb_is_pdc(sam_ctx)) {
2445 return WERR_NERR_NOTPRIMARY;
2448 if (r->in.trusted_domain_name == NULL) {
2449 return WERR_INVALID_FLAGS;
2452 /* TODO: establish an schannel connection with
2453 * r->in.trusted_domain_name and perform a
2454 * netr_GetForestTrustInformation call against it */
2456 /* for now return not implementd */
2457 return WERR_CALL_NOT_IMPLEMENTED;
2460 /* TODO: check r->in.server_name is our name */
2462 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2463 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2465 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2466 W_ERROR_HAVE_NO_MEMORY(info);
2468 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2469 W_ERROR_NOT_OK_RETURN(werr);
2471 *info_ptr = info;
2472 r->out.forest_trust_info = info_ptr;
2474 return WERR_OK;
2479 netr_GetForestTrustInformation
2481 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2482 TALLOC_CTX *mem_ctx,
2483 struct netr_GetForestTrustInformation *r)
2485 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2486 struct netlogon_creds_CredentialState *creds;
2487 struct lsa_ForestTrustInformation *info, **info_ptr;
2488 struct ldb_context *sam_ctx;
2489 NTSTATUS status;
2490 WERROR werr;
2492 status = dcesrv_netr_creds_server_step_check(dce_call,
2493 mem_ctx,
2494 r->in.computer_name,
2495 r->in.credential,
2496 r->out.return_authenticator,
2497 &creds);
2498 if (!NT_STATUS_IS_OK(status)) {
2499 return status;
2502 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2503 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2504 return NT_STATUS_NOT_IMPLEMENTED;
2507 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2508 dce_call->conn->auth_state.session_info, 0);
2509 if (sam_ctx == NULL) {
2510 return NT_STATUS_INTERNAL_ERROR;
2513 /* TODO: check r->in.server_name is our name */
2515 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2516 if (!info_ptr) {
2517 return NT_STATUS_NO_MEMORY;
2519 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2520 if (!info) {
2521 return NT_STATUS_NO_MEMORY;
2524 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2525 if (!W_ERROR_IS_OK(werr)) {
2526 return werror_to_ntstatus(werr);
2529 *info_ptr = info;
2530 r->out.forest_trust_info = info_ptr;
2532 return NT_STATUS_OK;
2537 netr_ServerGetTrustInfo
2539 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2540 struct netr_ServerGetTrustInfo *r)
2542 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2546 netr_Unused47
2548 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2549 struct netr_Unused47 *r)
2551 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2555 struct netr_dnsupdate_RODC_state {
2556 struct dcesrv_call_state *dce_call;
2557 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2558 struct dnsupdate_RODC *r2;
2562 called when the forwarded RODC dns update request is finished
2564 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2566 struct netr_dnsupdate_RODC_state *st =
2567 tevent_req_callback_data(subreq,
2568 struct netr_dnsupdate_RODC_state);
2569 NTSTATUS status;
2571 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2572 TALLOC_FREE(subreq);
2573 if (!NT_STATUS_IS_OK(status)) {
2574 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2575 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2578 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2580 status = dcesrv_reply(st->dce_call);
2581 if (!NT_STATUS_IS_OK(status)) {
2582 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2587 netr_DsrUpdateReadOnlyServerDnsRecords
2589 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2590 TALLOC_CTX *mem_ctx,
2591 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2593 struct netlogon_creds_CredentialState *creds;
2594 NTSTATUS nt_status;
2595 struct dcerpc_binding_handle *binding_handle;
2596 struct netr_dnsupdate_RODC_state *st;
2597 struct tevent_req *subreq;
2599 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2600 mem_ctx,
2601 r->in.computer_name,
2602 r->in.credential,
2603 r->out.return_authenticator,
2604 &creds);
2605 NT_STATUS_NOT_OK_RETURN(nt_status);
2607 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2608 return NT_STATUS_ACCESS_DENIED;
2611 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2612 NT_STATUS_HAVE_NO_MEMORY(st);
2614 st->dce_call = dce_call;
2615 st->r = r;
2616 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2617 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2619 st->r2->in.dom_sid = creds->sid;
2620 st->r2->in.site_name = r->in.site_name;
2621 st->r2->in.dns_ttl = r->in.dns_ttl;
2622 st->r2->in.dns_names = r->in.dns_names;
2623 st->r2->out.dns_names = r->out.dns_names;
2625 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2626 "dnsupdate", &ndr_table_irpc);
2627 if (binding_handle == NULL) {
2628 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2629 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2630 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2633 /* forward the call */
2634 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2635 binding_handle, st->r2);
2636 NT_STATUS_HAVE_NO_MEMORY(subreq);
2638 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2640 /* setup the callback */
2641 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2643 return NT_STATUS_OK;
2647 /* include the generated boilerplate */
2648 #include "librpc/gen_ndr/ndr_netlogon_s.c"