s4-rpc_server: support AES decryption in netr_ServerPasswordSet2 server.
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob5db4fd120121a479893a808372d24524547a0b1d
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_ARCFOUR) {
639 netlogon_creds_arcfour_crypt(creds,
640 r->in.logon->password->lmpassword.hash,
641 sizeof(r->in.logon->password->lmpassword.hash));
642 netlogon_creds_arcfour_crypt(creds,
643 r->in.logon->password->ntpassword.hash,
644 sizeof(r->in.logon->password->ntpassword.hash));
645 } else {
646 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
647 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
650 /* TODO: we need to deny anonymous access here */
651 nt_status = auth_context_create(mem_ctx,
652 dce_call->event_ctx, dce_call->msg_ctx,
653 dce_call->conn->dce_ctx->lp_ctx,
654 &auth_context);
655 NT_STATUS_NOT_OK_RETURN(nt_status);
657 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
658 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
659 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
660 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
662 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
663 user_info->password_state = AUTH_PASSWORD_HASH;
665 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
666 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
667 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
669 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
670 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
671 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
673 break;
674 case NetlogonNetworkInformation:
675 case NetlogonNetworkTransitiveInformation:
677 /* TODO: we need to deny anonymous access here */
678 nt_status = auth_context_create(mem_ctx,
679 dce_call->event_ctx, dce_call->msg_ctx,
680 dce_call->conn->dce_ctx->lp_ctx,
681 &auth_context);
682 NT_STATUS_NOT_OK_RETURN(nt_status);
684 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
685 NT_STATUS_NOT_OK_RETURN(nt_status);
687 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
688 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
689 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
690 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
692 user_info->password_state = AUTH_PASSWORD_RESPONSE;
693 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
694 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
696 break;
699 case NetlogonGenericInformation:
701 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
702 netlogon_creds_arcfour_crypt(creds,
703 r->in.logon->generic->data, r->in.logon->generic->length);
704 } else {
705 /* Using DES to verify kerberos tickets makes no sense */
706 return NT_STATUS_INVALID_PARAMETER;
709 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
710 NTSTATUS status;
711 struct dcerpc_binding_handle *irpc_handle;
712 struct kdc_check_generic_kerberos check;
713 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
714 NT_STATUS_HAVE_NO_MEMORY(generic);
715 *r->out.authoritative = 1;
717 /* TODO: Describe and deal with these flags */
718 *r->out.flags = 0;
720 r->out.validation->generic = generic;
722 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
723 dce_call->msg_ctx,
724 "kdc_server",
725 &ndr_table_irpc);
726 if (irpc_handle == NULL) {
727 return NT_STATUS_NO_LOGON_SERVERS;
730 check.in.generic_request =
731 data_blob_const(r->in.logon->generic->data,
732 r->in.logon->generic->length);
734 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
735 mem_ctx,
736 &check);
737 if (!NT_STATUS_IS_OK(status)) {
738 return status;
740 generic->length = check.out.generic_reply.length;
741 generic->data = check.out.generic_reply.data;
742 return NT_STATUS_OK;
745 /* Until we get an implemetnation of these other packages */
746 return NT_STATUS_INVALID_PARAMETER;
748 default:
749 return NT_STATUS_INVALID_PARAMETER;
752 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
753 /* TODO: set *r->out.authoritative = 0 on specific errors */
754 NT_STATUS_NOT_OK_RETURN(nt_status);
756 switch (r->in.validation_level) {
757 case 2:
758 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
759 NT_STATUS_NOT_OK_RETURN(nt_status);
761 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
762 NT_STATUS_HAVE_NO_MEMORY(sam2);
763 sam2->base = *sam;
765 /* And put into the talloc tree */
766 talloc_steal(sam2, sam);
767 r->out.validation->sam2 = sam2;
769 sam = &sam2->base;
770 break;
772 case 3:
773 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
774 user_info_dc,
775 &sam3);
776 NT_STATUS_NOT_OK_RETURN(nt_status);
778 r->out.validation->sam3 = sam3;
780 sam = &sam3->base;
781 break;
783 case 6:
784 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
785 user_info_dc,
786 &sam3);
787 NT_STATUS_NOT_OK_RETURN(nt_status);
789 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
790 NT_STATUS_HAVE_NO_MEMORY(sam6);
791 sam6->base = sam3->base;
792 sam = &sam6->base;
793 sam6->sidcount = sam3->sidcount;
794 sam6->sids = sam3->sids;
796 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
797 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
798 sam->account_name.string, sam6->dns_domainname.string);
799 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
800 /* And put into the talloc tree */
801 talloc_steal(sam6, sam3);
803 r->out.validation->sam6 = sam6;
804 break;
806 default:
807 return NT_STATUS_INVALID_INFO_CLASS;
810 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
811 /* It appears that level 6 is not individually encrypted */
812 if ((r->in.validation_level != 6) &&
813 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
814 /* This key is sent unencrypted without the ARCFOUR flag set */
815 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
816 netlogon_creds_arcfour_crypt(creds,
817 sam->key.key,
818 sizeof(sam->key.key));
822 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
823 /* It appears that level 6 is not individually encrypted */
824 if ((r->in.validation_level != 6) &&
825 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
826 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
827 netlogon_creds_arcfour_crypt(creds,
828 sam->LMSessKey.key,
829 sizeof(sam->LMSessKey.key));
830 } else {
831 netlogon_creds_des_encrypt_LMKey(creds,
832 &sam->LMSessKey);
836 /* TODO: Describe and deal with these flags */
837 *r->out.flags = 0;
839 return NT_STATUS_OK;
842 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
843 struct netr_LogonSamLogonEx *r)
845 NTSTATUS nt_status;
846 struct netlogon_creds_CredentialState *creds;
848 *r->out.authoritative = 1;
850 nt_status = dcesrv_netr_LogonSamLogon_check(r);
851 if (!NT_STATUS_IS_OK(nt_status)) {
852 return nt_status;
855 nt_status = schannel_get_creds_state(mem_ctx,
856 dce_call->conn->dce_ctx->lp_ctx,
857 r->in.computer_name, &creds);
858 if (!NT_STATUS_IS_OK(nt_status)) {
859 return nt_status;
862 if (!dce_call->conn->auth_state.auth_info ||
863 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
864 return NT_STATUS_ACCESS_DENIED;
866 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
870 netr_LogonSamLogonWithFlags
873 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
874 struct netr_LogonSamLogonWithFlags *r)
876 NTSTATUS nt_status;
877 struct netlogon_creds_CredentialState *creds;
878 struct netr_LogonSamLogonEx r2;
880 struct netr_Authenticator *return_authenticator;
882 ZERO_STRUCT(r2);
884 r2.in.server_name = r->in.server_name;
885 r2.in.computer_name = r->in.computer_name;
886 r2.in.logon_level = r->in.logon_level;
887 r2.in.logon = r->in.logon;
888 r2.in.validation_level = r->in.validation_level;
889 r2.in.flags = r->in.flags;
890 r2.out.validation = r->out.validation;
891 r2.out.authoritative = r->out.authoritative;
892 r2.out.flags = r->out.flags;
894 *r->out.authoritative = 1;
896 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
897 if (!NT_STATUS_IS_OK(nt_status)) {
898 return nt_status;
901 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
902 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
904 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
905 mem_ctx,
906 r->in.computer_name,
907 r->in.credential, return_authenticator,
908 &creds);
909 NT_STATUS_NOT_OK_RETURN(nt_status);
911 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
913 r->out.return_authenticator = return_authenticator;
915 return nt_status;
919 netr_LogonSamLogon
921 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
922 struct netr_LogonSamLogon *r)
924 struct netr_LogonSamLogonWithFlags r2;
925 uint32_t flags = 0;
926 NTSTATUS status;
928 ZERO_STRUCT(r2);
930 r2.in.server_name = r->in.server_name;
931 r2.in.computer_name = r->in.computer_name;
932 r2.in.credential = r->in.credential;
933 r2.in.return_authenticator = r->in.return_authenticator;
934 r2.in.logon_level = r->in.logon_level;
935 r2.in.logon = r->in.logon;
936 r2.in.validation_level = r->in.validation_level;
937 r2.in.flags = &flags;
938 r2.out.validation = r->out.validation;
939 r2.out.authoritative = r->out.authoritative;
940 r2.out.flags = &flags;
942 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
944 r->out.return_authenticator = r2.out.return_authenticator;
946 return status;
951 netr_LogonSamLogoff
953 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
954 struct netr_LogonSamLogoff *r)
956 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
962 netr_DatabaseDeltas
964 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
965 struct netr_DatabaseDeltas *r)
967 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
972 netr_DatabaseSync2
974 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
975 struct netr_DatabaseSync2 *r)
977 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
978 return NT_STATUS_NOT_IMPLEMENTED;
983 netr_DatabaseSync
985 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
986 struct netr_DatabaseSync *r)
988 struct netr_DatabaseSync2 r2;
989 NTSTATUS status;
991 ZERO_STRUCT(r2);
993 r2.in.logon_server = r->in.logon_server;
994 r2.in.computername = r->in.computername;
995 r2.in.credential = r->in.credential;
996 r2.in.database_id = r->in.database_id;
997 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
998 r2.in.sync_context = r->in.sync_context;
999 r2.out.sync_context = r->out.sync_context;
1000 r2.out.delta_enum_array = r->out.delta_enum_array;
1001 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1003 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1005 return status;
1010 netr_AccountDeltas
1012 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1013 struct netr_AccountDeltas *r)
1015 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1016 return NT_STATUS_NOT_IMPLEMENTED;
1021 netr_AccountSync
1023 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1024 struct netr_AccountSync *r)
1026 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1027 return NT_STATUS_NOT_IMPLEMENTED;
1032 netr_GetDcName
1034 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1035 struct netr_GetDcName *r)
1037 const char * const attrs[] = { NULL };
1038 struct ldb_context *sam_ctx;
1039 struct ldb_message **res;
1040 struct ldb_dn *domain_dn;
1041 int ret;
1042 const char *dcname;
1045 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1046 * that the domainname needs to be a valid netbios domain
1047 * name, if it is not NULL.
1049 if (r->in.domainname) {
1050 const char *dot = strchr(r->in.domainname, '.');
1051 size_t len = strlen(r->in.domainname);
1053 if (dot || len > 15) {
1054 return WERR_DCNOTFOUND;
1058 * TODO: Should we also varify that only valid
1059 * netbios name characters are used?
1063 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1064 dce_call->conn->dce_ctx->lp_ctx,
1065 dce_call->conn->auth_state.session_info, 0);
1066 if (sam_ctx == NULL) {
1067 return WERR_DS_UNAVAILABLE;
1070 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1071 r->in.domainname);
1072 if (domain_dn == NULL) {
1073 return WERR_NO_SUCH_DOMAIN;
1076 ret = gendb_search_dn(sam_ctx, mem_ctx,
1077 domain_dn, &res, attrs);
1078 if (ret != 1) {
1079 return WERR_NO_SUCH_DOMAIN;
1082 /* TODO: - return real IP address
1083 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1085 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1086 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1087 W_ERROR_HAVE_NO_MEMORY(dcname);
1089 *r->out.dcname = dcname;
1090 return WERR_OK;
1095 netr_LogonControl2Ex
1097 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1098 struct netr_LogonControl2Ex *r)
1100 return WERR_NOT_SUPPORTED;
1105 netr_LogonControl
1107 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1108 struct netr_LogonControl *r)
1110 struct netr_LogonControl2Ex r2;
1111 WERROR werr;
1113 if (r->in.level == 0x00000001) {
1114 ZERO_STRUCT(r2);
1116 r2.in.logon_server = r->in.logon_server;
1117 r2.in.function_code = r->in.function_code;
1118 r2.in.level = r->in.level;
1119 r2.in.data = NULL;
1120 r2.out.query = r->out.query;
1122 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1123 } else if (r->in.level == 0x00000002) {
1124 werr = WERR_NOT_SUPPORTED;
1125 } else {
1126 werr = WERR_UNKNOWN_LEVEL;
1129 return werr;
1134 netr_LogonControl2
1136 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1137 struct netr_LogonControl2 *r)
1139 struct netr_LogonControl2Ex r2;
1140 WERROR werr;
1142 ZERO_STRUCT(r2);
1144 r2.in.logon_server = r->in.logon_server;
1145 r2.in.function_code = r->in.function_code;
1146 r2.in.level = r->in.level;
1147 r2.in.data = r->in.data;
1148 r2.out.query = r->out.query;
1150 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1152 return werr;
1155 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1156 struct ldb_context *sam_ctx,
1157 struct netr_DomainTrustList *trusts,
1158 uint32_t trust_flags);
1161 netr_GetAnyDCName
1163 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1164 struct netr_GetAnyDCName *r)
1166 struct netr_DomainTrustList *trusts;
1167 struct ldb_context *sam_ctx;
1168 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1169 uint32_t i;
1170 WERROR werr;
1172 *r->out.dcname = NULL;
1174 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1175 /* if the domainname parameter wasn't set assume our domain */
1176 r->in.domainname = lpcfg_workgroup(lp_ctx);
1179 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1180 dce_call->conn->auth_state.session_info, 0);
1181 if (sam_ctx == NULL) {
1182 return WERR_DS_UNAVAILABLE;
1185 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1186 /* well we asked for a DC of our own domain */
1187 if (samdb_is_pdc(sam_ctx)) {
1188 /* we are the PDC of the specified domain */
1189 return WERR_NO_SUCH_DOMAIN;
1192 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1193 lpcfg_netbios_name(lp_ctx));
1194 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1196 return WERR_OK;
1199 /* Okay, now we have to consider the trusted domains */
1201 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1202 W_ERROR_HAVE_NO_MEMORY(trusts);
1204 trusts->count = 0;
1206 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1207 NETR_TRUST_FLAG_INBOUND
1208 | NETR_TRUST_FLAG_OUTBOUND);
1209 W_ERROR_NOT_OK_RETURN(werr);
1211 for (i = 0; i < trusts->count; i++) {
1212 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1213 /* FIXME: Here we need to find a DC for the specified
1214 * trusted domain. */
1216 /* return WERR_OK; */
1217 return WERR_NO_SUCH_DOMAIN;
1221 return WERR_NO_SUCH_DOMAIN;
1226 netr_DatabaseRedo
1228 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1229 struct netr_DatabaseRedo *r)
1231 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1236 netr_NetrEnumerateTrustedDomains
1238 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1239 struct netr_NetrEnumerateTrustedDomains *r)
1241 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1246 netr_LogonGetCapabilities
1248 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1249 struct netr_LogonGetCapabilities *r)
1251 struct netlogon_creds_CredentialState *creds;
1252 NTSTATUS status;
1254 status = dcesrv_netr_creds_server_step_check(dce_call,
1255 mem_ctx,
1256 r->in.computer_name,
1257 r->in.credential,
1258 r->out.return_authenticator,
1259 &creds);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 DEBUG(0,(__location__ " Bad credentials - error\n"));
1263 NT_STATUS_NOT_OK_RETURN(status);
1265 if (r->in.query_level != 1) {
1266 return NT_STATUS_NOT_SUPPORTED;
1269 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1271 return NT_STATUS_OK;
1276 netr_NETRLOGONSETSERVICEBITS
1278 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1279 struct netr_NETRLOGONSETSERVICEBITS *r)
1281 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1286 netr_LogonGetTrustRid
1288 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1289 struct netr_LogonGetTrustRid *r)
1291 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1296 netr_NETRLOGONCOMPUTESERVERDIGEST
1298 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1299 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1301 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1306 netr_NETRLOGONCOMPUTECLIENTDIGEST
1308 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1309 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1311 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1317 netr_DsRGetSiteName
1319 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1320 struct netr_DsRGetSiteName *r)
1322 struct ldb_context *sam_ctx;
1323 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1325 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1326 dce_call->conn->auth_state.session_info, 0);
1327 if (sam_ctx == NULL) {
1328 return WERR_DS_UNAVAILABLE;
1332 * We assume to be a DC when we get called over NETLOGON. Hence we
1333 * get our site name always by using "samdb_server_site_name()"
1334 * and not "samdb_client_site_name()".
1336 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1337 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1339 return WERR_OK;
1344 fill in a netr_OneDomainInfo from a ldb search result
1346 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1347 struct loadparm_context *lp_ctx,
1348 struct ldb_context *sam_ctx,
1349 struct ldb_message *res,
1350 struct netr_OneDomainInfo *info,
1351 bool is_local, bool is_trust_list)
1353 ZERO_STRUCTP(info);
1355 if (is_trust_list) {
1356 /* w2k8 only fills this on trusted domains */
1357 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1358 info->trust_extension.length = 16;
1359 info->trust_extension.info->flags =
1360 NETR_TRUST_FLAG_TREEROOT |
1361 NETR_TRUST_FLAG_IN_FOREST |
1362 NETR_TRUST_FLAG_PRIMARY |
1363 NETR_TRUST_FLAG_NATIVE;
1365 info->trust_extension.info->parent_index = 0; /* should be index into array
1366 of parent */
1367 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1368 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1371 if (is_trust_list) {
1372 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1373 info->dns_forestname.string = NULL;
1374 } else {
1375 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1376 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1377 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1378 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1381 if (is_local) {
1382 info->domainname.string = lpcfg_workgroup(lp_ctx);
1383 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1384 info->domain_guid = samdb_result_guid(res, "objectGUID");
1385 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1386 } else {
1387 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1388 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1389 info->domain_guid = samdb_result_guid(res, "objectGUID");
1390 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1392 if (!is_trust_list) {
1393 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1396 return NT_STATUS_OK;
1400 netr_LogonGetDomainInfo
1401 this is called as part of the ADS domain logon procedure.
1403 It has an important role in convaying details about the client, such
1404 as Operating System, Version, Service Pack etc.
1406 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1407 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1409 struct netlogon_creds_CredentialState *creds;
1410 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1411 "securityIdentifier", "trustPartner", NULL };
1412 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1413 "msDS-SupportedEncryptionTypes", NULL };
1414 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1415 struct ldb_context *sam_ctx;
1416 struct ldb_message **res1, **res2, **res3, *new_msg;
1417 struct ldb_dn *workstation_dn;
1418 struct netr_DomainInformation *domain_info;
1419 struct netr_LsaPolicyInformation *lsa_policy_info;
1420 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1421 bool update_dns_hostname = true;
1422 int ret, ret3, i;
1423 NTSTATUS status;
1425 status = dcesrv_netr_creds_server_step_check(dce_call,
1426 mem_ctx,
1427 r->in.computer_name,
1428 r->in.credential,
1429 r->out.return_authenticator,
1430 &creds);
1431 if (!NT_STATUS_IS_OK(status)) {
1432 DEBUG(0,(__location__ " Bad credentials - error\n"));
1434 NT_STATUS_NOT_OK_RETURN(status);
1436 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1437 dce_call->conn->dce_ctx->lp_ctx,
1438 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1439 if (sam_ctx == NULL) {
1440 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1443 switch (r->in.level) {
1444 case 1: /* Domain information */
1446 if (r->in.query->workstation_info == NULL) {
1447 return NT_STATUS_INVALID_PARAMETER;
1450 /* Prepares the workstation DN */
1451 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1452 dom_sid_string(mem_ctx, creds->sid));
1453 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1455 /* Lookup for attributes in workstation object */
1456 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1457 attrs2);
1458 if (ret != 1) {
1459 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1462 /* Gets the sam account name which is checked against the DNS
1463 * hostname parameter. */
1464 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1465 "sAMAccountName",
1466 NULL);
1467 if (sam_account_name == NULL) {
1468 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1472 * Checks that the sam account name without a possible "$"
1473 * matches as prefix with the DNS hostname in the workstation
1474 * info structure.
1476 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1477 strcspn(sam_account_name, "$"));
1478 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1479 if (r->in.query->workstation_info->dns_hostname != NULL) {
1480 prefix2 = talloc_strndup(mem_ctx,
1481 r->in.query->workstation_info->dns_hostname,
1482 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1483 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1485 if (strcasecmp(prefix1, prefix2) != 0) {
1486 update_dns_hostname = false;
1488 } else {
1489 update_dns_hostname = false;
1492 /* Gets the old DNS hostname */
1493 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1494 "dNSHostName",
1495 NULL);
1498 * Updates the DNS hostname when the client wishes that the
1499 * server should handle this for him
1500 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1501 * obviously only checked when we do already have a
1502 * "dNSHostName".
1503 * See MS-NRPC section 3.5.4.3.9
1505 if ((old_dns_hostname != NULL) &&
1506 (r->in.query->workstation_info->workstation_flags
1507 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1508 update_dns_hostname = false;
1511 /* Gets host information and put them into our directory */
1513 new_msg = ldb_msg_new(mem_ctx);
1514 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1516 new_msg->dn = workstation_dn;
1518 /* Sets the OS name */
1520 if (r->in.query->workstation_info->os_name.string == NULL) {
1521 return NT_STATUS_INVALID_PARAMETER;
1524 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1525 r->in.query->workstation_info->os_name.string);
1526 if (ret != LDB_SUCCESS) {
1527 return NT_STATUS_NO_MEMORY;
1531 * Sets information from "os_version". On an empty structure
1532 * the values are cleared.
1534 if (r->in.query->workstation_info->os_version.os != NULL) {
1535 struct netr_OsVersionInfoEx *os_version;
1536 const char *os_version_str;
1538 os_version = &r->in.query->workstation_info->os_version.os->os;
1540 if (os_version->CSDVersion == NULL) {
1541 return NT_STATUS_INVALID_PARAMETER;
1544 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1545 os_version->MajorVersion,
1546 os_version->MinorVersion,
1547 os_version->BuildNumber);
1548 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1550 ret = ldb_msg_add_string(new_msg,
1551 "operatingSystemServicePack",
1552 os_version->CSDVersion);
1553 if (ret != LDB_SUCCESS) {
1554 return NT_STATUS_NO_MEMORY;
1557 ret = ldb_msg_add_string(new_msg,
1558 "operatingSystemVersion",
1559 os_version_str);
1560 if (ret != LDB_SUCCESS) {
1561 return NT_STATUS_NO_MEMORY;
1563 } else {
1564 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1565 "operatingSystemServicePack");
1566 if (ret != LDB_SUCCESS) {
1567 return NT_STATUS_NO_MEMORY;
1570 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1571 "operatingSystemVersion");
1572 if (ret != LDB_SUCCESS) {
1573 return NT_STATUS_NO_MEMORY;
1578 * If the boolean "update_dns_hostname" remained true, then we
1579 * are fine to start the update.
1581 if (update_dns_hostname) {
1582 ret = ldb_msg_add_string(new_msg,
1583 "dNSHostname",
1584 r->in.query->workstation_info->dns_hostname);
1585 if (ret != LDB_SUCCESS) {
1586 return NT_STATUS_NO_MEMORY;
1589 /* This manual "servicePrincipalName" generation is
1590 * still needed! Since the update in the samldb LDB
1591 * module does only work if the entries already exist
1592 * which isn't always the case. */
1593 ret = ldb_msg_add_string(new_msg,
1594 "servicePrincipalName",
1595 talloc_asprintf(new_msg, "HOST/%s",
1596 r->in.computer_name));
1597 if (ret != LDB_SUCCESS) {
1598 return NT_STATUS_NO_MEMORY;
1601 ret = ldb_msg_add_string(new_msg,
1602 "servicePrincipalName",
1603 talloc_asprintf(new_msg, "HOST/%s",
1604 r->in.query->workstation_info->dns_hostname));
1605 if (ret != LDB_SUCCESS) {
1606 return NT_STATUS_NO_MEMORY;
1610 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1611 DEBUG(3,("Impossible to update samdb: %s\n",
1612 ldb_errstring(sam_ctx)));
1615 talloc_free(new_msg);
1617 /* Writes back the domain information */
1619 /* We need to do two searches. The first will pull our primary
1620 domain and the second will pull any trusted domains. Our
1621 primary domain is also a "trusted" domain, so we need to
1622 put the primary domain into the lists of returned trusts as
1623 well. */
1624 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1625 &res2, attrs);
1626 if (ret != 1) {
1627 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1630 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1631 "(objectClass=trustedDomain)");
1632 if (ret3 == -1) {
1633 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1636 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1637 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1639 ZERO_STRUCTP(domain_info);
1641 /* Informations about the local and trusted domains */
1643 status = fill_one_domain_info(mem_ctx,
1644 dce_call->conn->dce_ctx->lp_ctx,
1645 sam_ctx, res2[0], &domain_info->primary_domain,
1646 true, false);
1647 NT_STATUS_NOT_OK_RETURN(status);
1649 domain_info->trusted_domain_count = ret3 + 1;
1650 domain_info->trusted_domains = talloc_array(mem_ctx,
1651 struct netr_OneDomainInfo,
1652 domain_info->trusted_domain_count);
1653 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1655 for (i=0;i<ret3;i++) {
1656 status = fill_one_domain_info(mem_ctx,
1657 dce_call->conn->dce_ctx->lp_ctx,
1658 sam_ctx, res3[i],
1659 &domain_info->trusted_domains[i],
1660 false, true);
1661 NT_STATUS_NOT_OK_RETURN(status);
1664 status = fill_one_domain_info(mem_ctx,
1665 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1666 &domain_info->trusted_domains[i], true, true);
1667 NT_STATUS_NOT_OK_RETURN(status);
1669 /* Sets the supported encryption types */
1670 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1671 "msDS-SupportedEncryptionTypes",
1672 default_supported_enc_types);
1674 /* Other host domain information */
1676 lsa_policy_info = talloc(mem_ctx,
1677 struct netr_LsaPolicyInformation);
1678 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1679 ZERO_STRUCTP(lsa_policy_info);
1681 domain_info->lsa_policy = *lsa_policy_info;
1683 /* The DNS hostname is only returned back when there is a chance
1684 * for a change. */
1685 if ((r->in.query->workstation_info->workstation_flags
1686 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1687 domain_info->dns_hostname.string = old_dns_hostname;
1688 } else {
1689 domain_info->dns_hostname.string = NULL;
1692 domain_info->workstation_flags =
1693 r->in.query->workstation_info->workstation_flags & (
1694 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1696 r->out.info->domain_info = domain_info;
1697 break;
1698 case 2: /* LSA policy information - not used at the moment */
1699 lsa_policy_info = talloc(mem_ctx,
1700 struct netr_LsaPolicyInformation);
1701 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1702 ZERO_STRUCTP(lsa_policy_info);
1704 r->out.info->lsa_policy_info = lsa_policy_info;
1705 break;
1706 default:
1707 return NT_STATUS_INVALID_LEVEL;
1708 break;
1711 return NT_STATUS_OK;
1716 netr_ServerPasswordGet
1718 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1719 struct netr_ServerPasswordGet *r)
1721 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1726 netr_NETRLOGONSENDTOSAM
1728 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1729 struct netr_NETRLOGONSENDTOSAM *r)
1731 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1736 netr_DsRGetDCNameEx2
1738 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1739 TALLOC_CTX *mem_ctx,
1740 struct netr_DsRGetDCNameEx2 *r)
1742 struct ldb_context *sam_ctx;
1743 struct netr_DsRGetDCNameInfo *info;
1744 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1745 const struct tsocket_address *remote_address;
1746 char *addr = NULL;
1747 const char *server_site_name;
1748 char *guid_str;
1749 struct netlogon_samlogon_response response;
1750 NTSTATUS status;
1751 const char *dc_name = NULL;
1752 const char *domain_name = NULL;
1753 struct interface *ifaces;
1754 const char *pdc_ip;
1756 ZERO_STRUCTP(r->out.info);
1758 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1759 dce_call->conn->auth_state.session_info, 0);
1760 if (sam_ctx == NULL) {
1761 return WERR_DS_UNAVAILABLE;
1764 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1765 if (tsocket_address_is_inet(remote_address, "ip")) {
1766 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1767 W_ERROR_HAVE_NO_MEMORY(addr);
1770 /* "server_unc" is ignored by w2k3 */
1772 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1773 return WERR_INVALID_FLAGS;
1776 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1777 r->in.flags & DS_PDC_REQUIRED &&
1778 r->in.flags & DS_KDC_REQUIRED) {
1779 return WERR_INVALID_FLAGS;
1781 if (r->in.flags & DS_IS_FLAT_NAME &&
1782 r->in.flags & DS_IS_DNS_NAME) {
1783 return WERR_INVALID_FLAGS;
1785 if (r->in.flags & DS_RETURN_DNS_NAME &&
1786 r->in.flags & DS_RETURN_FLAT_NAME) {
1787 return WERR_INVALID_FLAGS;
1789 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1790 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1791 return WERR_INVALID_FLAGS;
1794 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1795 r->in.flags &
1796 (DS_DIRECTORY_SERVICE_REQUIRED |
1797 DS_DIRECTORY_SERVICE_PREFERRED |
1798 DS_GC_SERVER_REQUIRED |
1799 DS_PDC_REQUIRED |
1800 DS_KDC_REQUIRED)) {
1801 return WERR_INVALID_FLAGS;
1804 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1805 r->in.site_name) {
1806 return WERR_INVALID_FLAGS;
1809 /* Proof server site parameter "site_name" if it was specified */
1810 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1811 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1812 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1813 server_site_name) != 0)) {
1814 return WERR_NO_SUCH_DOMAIN;
1817 guid_str = r->in.domain_guid != NULL ?
1818 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1820 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1821 r->in.domain_name,
1822 r->in.domain_name,
1823 NULL, guid_str,
1824 r->in.client_account,
1825 r->in.mask, addr,
1826 NETLOGON_NT_VERSION_5EX_WITH_IP,
1827 lp_ctx, &response, true);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 return ntstatus_to_werror(status);
1833 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1834 * (O) flag when the returned forest name is in DNS format. This is here
1835 * always the case (see below).
1837 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1839 if (r->in.flags & DS_RETURN_DNS_NAME) {
1840 dc_name = response.data.nt5_ex.pdc_dns_name;
1841 domain_name = response.data.nt5_ex.dns_domain;
1843 * According to MS-NRPC 2.2.1.2.1 we should set the
1844 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1845 * the returned information is in DNS form.
1847 response.data.nt5_ex.server_type |=
1848 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1849 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1850 dc_name = response.data.nt5_ex.pdc_name;
1851 domain_name = response.data.nt5_ex.domain_name;
1852 } else {
1855 * TODO: autodetect what we need to return
1856 * based on the given arguments
1858 dc_name = response.data.nt5_ex.pdc_name;
1859 domain_name = response.data.nt5_ex.domain_name;
1862 if (!dc_name || !dc_name[0]) {
1863 return WERR_NO_SUCH_DOMAIN;
1866 if (!domain_name || !domain_name[0]) {
1867 return WERR_NO_SUCH_DOMAIN;
1870 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1871 W_ERROR_HAVE_NO_MEMORY(info);
1872 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1873 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1875 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1876 pdc_ip = iface_list_best_ip(ifaces, addr);
1877 if (pdc_ip == NULL) {
1878 pdc_ip = "127.0.0.1";
1880 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1881 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1882 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1883 info->domain_guid = response.data.nt5_ex.domain_uuid;
1884 info->domain_name = domain_name;
1885 info->forest_name = response.data.nt5_ex.forest;
1886 info->dc_flags = response.data.nt5_ex.server_type;
1887 info->dc_site_name = response.data.nt5_ex.server_site;
1888 info->client_site_name = response.data.nt5_ex.client_site;
1890 *r->out.info = info;
1892 return WERR_OK;
1896 netr_DsRGetDCNameEx
1898 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1899 struct netr_DsRGetDCNameEx *r)
1901 struct netr_DsRGetDCNameEx2 r2;
1902 WERROR werr;
1904 ZERO_STRUCT(r2);
1906 r2.in.server_unc = r->in.server_unc;
1907 r2.in.client_account = NULL;
1908 r2.in.mask = 0;
1909 r2.in.domain_guid = r->in.domain_guid;
1910 r2.in.domain_name = r->in.domain_name;
1911 r2.in.site_name = r->in.site_name;
1912 r2.in.flags = r->in.flags;
1913 r2.out.info = r->out.info;
1915 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1917 return werr;
1921 netr_DsRGetDCName
1923 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1924 struct netr_DsRGetDCName *r)
1926 struct netr_DsRGetDCNameEx2 r2;
1927 WERROR werr;
1929 ZERO_STRUCT(r2);
1931 r2.in.server_unc = r->in.server_unc;
1932 r2.in.client_account = NULL;
1933 r2.in.mask = 0;
1934 r2.in.domain_name = r->in.domain_name;
1935 r2.in.domain_guid = r->in.domain_guid;
1937 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1938 r2.in.flags = r->in.flags;
1939 r2.out.info = r->out.info;
1941 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1943 return werr;
1946 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1948 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1949 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1951 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1956 netr_NetrEnumerateTrustedDomainsEx
1958 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1959 struct netr_NetrEnumerateTrustedDomainsEx *r)
1961 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1966 netr_DsRAddressToSitenamesExW
1968 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1969 struct netr_DsRAddressToSitenamesExW *r)
1971 struct ldb_context *sam_ctx;
1972 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1973 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1974 sa_family_t sin_family;
1975 struct sockaddr_in *addr;
1976 #ifdef HAVE_IPV6
1977 struct sockaddr_in6 *addr6;
1978 char addr_str[INET6_ADDRSTRLEN];
1979 #else
1980 char addr_str[INET_ADDRSTRLEN];
1981 #endif
1982 char *subnet_name;
1983 const char *res;
1984 uint32_t i;
1986 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1987 dce_call->conn->auth_state.session_info, 0);
1988 if (sam_ctx == NULL) {
1989 return WERR_DS_UNAVAILABLE;
1992 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1993 W_ERROR_HAVE_NO_MEMORY(ctr);
1995 *r->out.ctr = ctr;
1997 ctr->count = r->in.count;
1998 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1999 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2000 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2001 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2003 for (i=0; i<ctr->count; i++) {
2004 ctr->sitename[i].string = NULL;
2005 ctr->subnetname[i].string = NULL;
2007 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2008 continue;
2010 /* The first two byte of the buffer are reserved for the
2011 * "sin_family" but for now only the first one is used. */
2012 sin_family = r->in.addresses[i].buffer[0];
2014 switch (sin_family) {
2015 case AF_INET:
2016 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2017 continue;
2019 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2020 res = inet_ntop(AF_INET, &addr->sin_addr,
2021 addr_str, sizeof(addr_str));
2022 break;
2023 #ifdef HAVE_IPV6
2024 case AF_INET6:
2025 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2026 continue;
2028 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2029 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2030 addr_str, sizeof(addr_str));
2031 break;
2032 #endif
2033 default:
2034 continue;
2037 if (res == NULL) {
2038 continue;
2041 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2042 mem_ctx,
2043 addr_str,
2044 &subnet_name);
2045 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2046 ctr->subnetname[i].string = subnet_name;
2049 return WERR_OK;
2054 netr_DsRAddressToSitenamesW
2056 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2057 struct netr_DsRAddressToSitenamesW *r)
2059 struct netr_DsRAddressToSitenamesExW r2;
2060 struct netr_DsRAddressToSitenamesWCtr *ctr;
2061 uint32_t i;
2062 WERROR werr;
2064 ZERO_STRUCT(r2);
2066 r2.in.server_name = r->in.server_name;
2067 r2.in.count = r->in.count;
2068 r2.in.addresses = r->in.addresses;
2070 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2071 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2073 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2074 W_ERROR_HAVE_NO_MEMORY(ctr);
2076 *r->out.ctr = ctr;
2078 ctr->count = r->in.count;
2079 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2080 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2082 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2084 for (i=0; i<ctr->count; i++) {
2085 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2088 return werr;
2093 netr_DsrGetDcSiteCoverageW
2095 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2096 struct netr_DsrGetDcSiteCoverageW *r)
2098 struct ldb_context *sam_ctx;
2099 struct DcSitesCtr *ctr;
2100 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2102 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2103 dce_call->conn->auth_state.session_info, 0);
2104 if (sam_ctx == NULL) {
2105 return WERR_DS_UNAVAILABLE;
2108 ctr = talloc(mem_ctx, struct DcSitesCtr);
2109 W_ERROR_HAVE_NO_MEMORY(ctr);
2111 *r->out.ctr = ctr;
2113 /* For now only return our default site */
2114 ctr->num_sites = 1;
2115 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2116 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2117 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2118 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2120 return WERR_OK;
2124 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2125 struct ldb_context *sam_ctx,
2126 struct netr_DomainTrustList *trusts,
2127 uint32_t trust_flags)
2129 struct ldb_dn *system_dn;
2130 struct ldb_message **dom_res = NULL;
2131 const char *trust_attrs[] = { "flatname", "trustPartner",
2132 "securityIdentifier", "trustDirection",
2133 "trustType", "trustAttributes", NULL };
2134 uint32_t n;
2135 int i;
2136 int ret;
2138 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2139 NETR_TRUST_FLAG_OUTBOUND))) {
2140 return WERR_INVALID_FLAGS;
2143 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2144 ldb_get_default_basedn(sam_ctx),
2145 "(&(objectClass=container)(cn=System))");
2146 if (!system_dn) {
2147 return WERR_GENERAL_FAILURE;
2150 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2151 &dom_res, trust_attrs,
2152 "(objectclass=trustedDomain)");
2154 for (i = 0; i < ret; i++) {
2155 unsigned int trust_dir;
2156 uint32_t flags = 0;
2158 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2159 "trustDirection", 0);
2161 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2162 flags |= NETR_TRUST_FLAG_INBOUND;
2164 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2165 flags |= NETR_TRUST_FLAG_OUTBOUND;
2168 if (!(flags & trust_flags)) {
2169 /* this trust direction was not requested */
2170 continue;
2173 n = trusts->count;
2174 trusts->array = talloc_realloc(trusts, trusts->array,
2175 struct netr_DomainTrust,
2176 n + 1);
2177 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2179 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2180 if (!trusts->array[n].netbios_name) {
2181 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2182 "without flatname\n",
2183 ldb_dn_get_linearized(dom_res[i]->dn)));
2186 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2188 trusts->array[n].trust_flags = flags;
2189 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2190 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2191 /* TODO: find if we have parent in the list */
2192 trusts->array[n].parent_index = 0;
2195 trusts->array[n].trust_type =
2196 ldb_msg_find_attr_as_uint(dom_res[i],
2197 "trustType", 0);
2198 trusts->array[n].trust_attributes =
2199 ldb_msg_find_attr_as_uint(dom_res[i],
2200 "trustAttributes", 0);
2202 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2203 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2204 struct dom_sid zero_sid;
2205 ZERO_STRUCT(zero_sid);
2206 trusts->array[n].sid =
2207 dom_sid_dup(trusts, &zero_sid);
2208 } else {
2209 trusts->array[n].sid =
2210 samdb_result_dom_sid(trusts, dom_res[i],
2211 "securityIdentifier");
2213 trusts->array[n].guid = GUID_zero();
2215 trusts->count = n + 1;
2218 talloc_free(dom_res);
2219 return WERR_OK;
2223 netr_DsrEnumerateDomainTrusts
2225 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2226 TALLOC_CTX *mem_ctx,
2227 struct netr_DsrEnumerateDomainTrusts *r)
2229 struct netr_DomainTrustList *trusts;
2230 struct ldb_context *sam_ctx;
2231 int ret;
2232 struct ldb_message **dom_res;
2233 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2234 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2235 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2236 const char *p;
2237 WERROR werr;
2239 if (r->in.trust_flags & 0xFFFFFE00) {
2240 return WERR_INVALID_FLAGS;
2243 /* TODO: turn to hard check once we are sure this is 100% correct */
2244 if (!r->in.server_name) {
2245 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2246 "But received NULL!\n", dnsdomain));
2247 } else {
2248 p = strchr(r->in.server_name, '.');
2249 if (!p) {
2250 DEBUG(3, ("Invalid domain! Expected name in domain "
2251 "[%s]. But received [%s]!\n",
2252 dnsdomain, r->in.server_name));
2253 p = r->in.server_name;
2254 } else {
2255 p++;
2257 if (strcasecmp(p, dnsdomain)) {
2258 DEBUG(3, ("Invalid domain! Expected name in domain "
2259 "[%s]. But received [%s]!\n",
2260 dnsdomain, r->in.server_name));
2264 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2265 W_ERROR_HAVE_NO_MEMORY(trusts);
2267 trusts->count = 0;
2268 r->out.trusts = trusts;
2270 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2271 dce_call->conn->auth_state.session_info, 0);
2272 if (sam_ctx == NULL) {
2273 return WERR_GENERAL_FAILURE;
2276 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2277 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2279 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2280 trusts, r->in.trust_flags);
2281 W_ERROR_NOT_OK_RETURN(werr);
2284 /* NOTE: we currently are always the root of the forest */
2285 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2286 uint32_t n = trusts->count;
2288 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2289 &dom_res, dom_attrs);
2290 if (ret != 1) {
2291 return WERR_GENERAL_FAILURE;
2294 trusts->count = n + 1;
2295 trusts->array = talloc_realloc(trusts, trusts->array,
2296 struct netr_DomainTrust,
2297 trusts->count);
2298 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2300 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2301 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2302 trusts->array[n].trust_flags =
2303 NETR_TRUST_FLAG_NATIVE |
2304 NETR_TRUST_FLAG_TREEROOT |
2305 NETR_TRUST_FLAG_IN_FOREST |
2306 NETR_TRUST_FLAG_PRIMARY;
2307 /* we are always the root domain for now */
2308 trusts->array[n].parent_index = 0;
2309 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2310 trusts->array[n].trust_attributes = 0;
2311 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2312 dom_res[0],
2313 "objectSid");
2314 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2315 "objectGUID");
2316 talloc_free(dom_res);
2319 return WERR_OK;
2324 netr_DsrDeregisterDNSHostRecords
2326 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2327 struct netr_DsrDeregisterDNSHostRecords *r)
2329 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2334 netr_ServerTrustPasswordsGet
2336 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2337 struct netr_ServerTrustPasswordsGet *r)
2339 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2343 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2344 struct ldb_context *sam_ctx,
2345 struct loadparm_context *lp_ctx,
2346 struct lsa_ForestTrustInformation *info)
2348 struct lsa_ForestTrustDomainInfo *domain_info;
2349 struct lsa_ForestTrustRecord *e;
2350 struct ldb_message **dom_res;
2351 const char * const dom_attrs[] = { "objectSid", NULL };
2352 int ret;
2354 /* we need to provide 2 entries:
2355 * 1. the Root Forest name
2356 * 2. the Domain Information
2359 info->count = 2;
2360 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2361 W_ERROR_HAVE_NO_MEMORY(info->entries);
2363 /* Forest root info */
2364 e = talloc(info, struct lsa_ForestTrustRecord);
2365 W_ERROR_HAVE_NO_MEMORY(e);
2367 e->flags = 0;
2368 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2369 e->time = 0; /* so far always 0 in trces. */
2370 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2371 mem_ctx);
2372 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2374 info->entries[0] = e;
2376 /* Domain info */
2377 e = talloc(info, struct lsa_ForestTrustRecord);
2378 W_ERROR_HAVE_NO_MEMORY(e);
2380 /* get our own domain info */
2381 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2382 if (ret != 1) {
2383 return WERR_GENERAL_FAILURE;
2386 /* TODO: check if disabled and set flags accordingly */
2387 e->flags = 0;
2388 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2389 e->time = 0; /* so far always 0 in traces. */
2391 domain_info = &e->forest_trust_data.domain_info;
2392 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2393 "objectSid");
2394 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2395 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2397 info->entries[1] = e;
2399 talloc_free(dom_res);
2401 return WERR_OK;
2405 netr_DsRGetForestTrustInformation
2407 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2408 TALLOC_CTX *mem_ctx,
2409 struct netr_DsRGetForestTrustInformation *r)
2411 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2412 struct lsa_ForestTrustInformation *info, **info_ptr;
2413 struct ldb_context *sam_ctx;
2414 WERROR werr;
2416 if (r->in.flags & 0xFFFFFFFE) {
2417 return WERR_INVALID_FLAGS;
2420 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2421 dce_call->conn->auth_state.session_info, 0);
2422 if (sam_ctx == NULL) {
2423 return WERR_GENERAL_FAILURE;
2426 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2427 if (!samdb_is_pdc(sam_ctx)) {
2428 return WERR_NERR_NOTPRIMARY;
2431 if (r->in.trusted_domain_name == NULL) {
2432 return WERR_INVALID_FLAGS;
2435 /* TODO: establish an schannel connection with
2436 * r->in.trusted_domain_name and perform a
2437 * netr_GetForestTrustInformation call against it */
2439 /* for now return not implementd */
2440 return WERR_CALL_NOT_IMPLEMENTED;
2443 /* TODO: check r->in.server_name is our name */
2445 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2446 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2448 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2449 W_ERROR_HAVE_NO_MEMORY(info);
2451 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2452 W_ERROR_NOT_OK_RETURN(werr);
2454 *info_ptr = info;
2455 r->out.forest_trust_info = info_ptr;
2457 return WERR_OK;
2462 netr_GetForestTrustInformation
2464 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2465 TALLOC_CTX *mem_ctx,
2466 struct netr_GetForestTrustInformation *r)
2468 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2469 struct netlogon_creds_CredentialState *creds;
2470 struct lsa_ForestTrustInformation *info, **info_ptr;
2471 struct ldb_context *sam_ctx;
2472 NTSTATUS status;
2473 WERROR werr;
2475 status = dcesrv_netr_creds_server_step_check(dce_call,
2476 mem_ctx,
2477 r->in.computer_name,
2478 r->in.credential,
2479 r->out.return_authenticator,
2480 &creds);
2481 if (!NT_STATUS_IS_OK(status)) {
2482 return status;
2485 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2486 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2487 return NT_STATUS_NOT_IMPLEMENTED;
2490 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2491 dce_call->conn->auth_state.session_info, 0);
2492 if (sam_ctx == NULL) {
2493 return NT_STATUS_INTERNAL_ERROR;
2496 /* TODO: check r->in.server_name is our name */
2498 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2499 if (!info_ptr) {
2500 return NT_STATUS_NO_MEMORY;
2502 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2503 if (!info) {
2504 return NT_STATUS_NO_MEMORY;
2507 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2508 if (!W_ERROR_IS_OK(werr)) {
2509 return werror_to_ntstatus(werr);
2512 *info_ptr = info;
2513 r->out.forest_trust_info = info_ptr;
2515 return NT_STATUS_OK;
2520 netr_ServerGetTrustInfo
2522 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2523 struct netr_ServerGetTrustInfo *r)
2525 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2529 netr_Unused47
2531 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2532 struct netr_Unused47 *r)
2534 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2538 struct netr_dnsupdate_RODC_state {
2539 struct dcesrv_call_state *dce_call;
2540 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2541 struct dnsupdate_RODC *r2;
2545 called when the forwarded RODC dns update request is finished
2547 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2549 struct netr_dnsupdate_RODC_state *st =
2550 tevent_req_callback_data(subreq,
2551 struct netr_dnsupdate_RODC_state);
2552 NTSTATUS status;
2554 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2555 TALLOC_FREE(subreq);
2556 if (!NT_STATUS_IS_OK(status)) {
2557 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2558 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2561 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2563 status = dcesrv_reply(st->dce_call);
2564 if (!NT_STATUS_IS_OK(status)) {
2565 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2570 netr_DsrUpdateReadOnlyServerDnsRecords
2572 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2573 TALLOC_CTX *mem_ctx,
2574 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2576 struct netlogon_creds_CredentialState *creds;
2577 NTSTATUS nt_status;
2578 struct dcerpc_binding_handle *binding_handle;
2579 struct netr_dnsupdate_RODC_state *st;
2580 struct tevent_req *subreq;
2582 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2583 mem_ctx,
2584 r->in.computer_name,
2585 r->in.credential,
2586 r->out.return_authenticator,
2587 &creds);
2588 NT_STATUS_NOT_OK_RETURN(nt_status);
2590 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2591 return NT_STATUS_ACCESS_DENIED;
2594 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2595 NT_STATUS_HAVE_NO_MEMORY(st);
2597 st->dce_call = dce_call;
2598 st->r = r;
2599 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2600 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2602 st->r2->in.dom_sid = creds->sid;
2603 st->r2->in.site_name = r->in.site_name;
2604 st->r2->in.dns_ttl = r->in.dns_ttl;
2605 st->r2->in.dns_names = r->in.dns_names;
2606 st->r2->out.dns_names = r->out.dns_names;
2608 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2609 "dnsupdate", &ndr_table_irpc);
2610 if (binding_handle == NULL) {
2611 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2612 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2613 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2616 /* forward the call */
2617 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2618 binding_handle, st->r2);
2619 NT_STATUS_HAVE_NO_MEMORY(subreq);
2621 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2623 /* setup the callback */
2624 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2626 return NT_STATUS_OK;
2630 /* include the generated boilerplate */
2631 #include "librpc/gen_ndr/ndr_netlogon_s.c"