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/>.
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"
41 struct netlogon_server_pipe_state
{
42 struct netr_Credential client_challenge
;
43 struct netr_Credential server_challenge
;
46 static NTSTATUS
dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
47 struct netr_ServerReqChallenge
*r
)
49 struct netlogon_server_pipe_state
*pipe_state
=
50 talloc_get_type(dce_call
->context
->private_data
, struct netlogon_server_pipe_state
);
52 ZERO_STRUCTP(r
->out
.return_credentials
);
54 /* destroyed on pipe shutdown */
57 talloc_free(pipe_state
);
58 dce_call
->context
->private_data
= NULL
;
61 pipe_state
= talloc(dce_call
->context
, struct netlogon_server_pipe_state
);
62 NT_STATUS_HAVE_NO_MEMORY(pipe_state
);
64 pipe_state
->client_challenge
= *r
->in
.credentials
;
66 generate_random_buffer(pipe_state
->server_challenge
.data
,
67 sizeof(pipe_state
->server_challenge
.data
));
69 *r
->out
.return_credentials
= pipe_state
->server_challenge
;
71 dce_call
->context
->private_data
= pipe_state
;
76 static NTSTATUS
dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
77 struct netr_ServerAuthenticate3
*r
)
79 struct netlogon_server_pipe_state
*pipe_state
=
80 talloc_get_type(dce_call
->context
->private_data
, struct netlogon_server_pipe_state
);
81 struct netlogon_creds_CredentialState
*creds
;
82 struct ldb_context
*sam_ctx
;
83 struct samr_Password
*mach_pwd
;
84 uint32_t user_account_control
;
86 struct ldb_message
**msgs
;
88 const char *attrs
[] = {"unicodePwd", "userAccountControl",
91 const char *trust_dom_attrs
[] = {"flatname", NULL
};
92 const char *account_name
;
94 ZERO_STRUCTP(r
->out
.return_credentials
);
98 * According to Microsoft (see bugid #6099)
99 * Windows 7 looks at the negotiate_flags
100 * returned in this structure *even if the
101 * call fails with access denied!
103 *r
->out
.negotiate_flags
= NETLOGON_NEG_ACCOUNT_LOCKOUT
|
104 NETLOGON_NEG_PERSISTENT_SAMREPL
|
105 NETLOGON_NEG_ARCFOUR
|
106 NETLOGON_NEG_PROMOTION_COUNT
|
107 NETLOGON_NEG_CHANGELOG_BDC
|
108 NETLOGON_NEG_FULL_SYNC_REPL
|
109 NETLOGON_NEG_MULTIPLE_SIDS
|
111 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL
|
112 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC
|
113 NETLOGON_NEG_GENERIC_PASSTHROUGH
|
114 NETLOGON_NEG_CONCURRENT_RPC
|
115 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL
|
116 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL
|
117 NETLOGON_NEG_STRONG_KEYS
|
118 NETLOGON_NEG_TRANSITIVE_TRUSTS
|
119 NETLOGON_NEG_DNS_DOMAIN_TRUSTS
|
120 NETLOGON_NEG_PASSWORD_SET2
|
121 NETLOGON_NEG_GETDOMAININFO
|
122 NETLOGON_NEG_CROSS_FOREST_TRUSTS
|
123 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
|
124 NETLOGON_NEG_RODC_PASSTHROUGH
|
125 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS
|
126 NETLOGON_NEG_AUTHENTICATED_RPC
;
128 switch (r
->in
.secure_channel_type
) {
130 case SEC_CHAN_DNS_DOMAIN
:
131 case SEC_CHAN_DOMAIN
:
136 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
137 r
->in
.secure_channel_type
));
138 return NT_STATUS_INVALID_PARAMETER
;
141 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
,
142 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
), 0);
143 if (sam_ctx
== NULL
) {
144 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
147 if (r
->in
.secure_channel_type
== SEC_CHAN_DNS_DOMAIN
) {
148 char *encoded_account
= ldb_binary_encode_string(mem_ctx
, r
->in
.account_name
);
149 const char *flatname
;
150 if (!encoded_account
) {
151 return NT_STATUS_NO_MEMORY
;
154 /* Kill the trailing dot */
155 if (encoded_account
[strlen(encoded_account
)-1] == '.') {
156 encoded_account
[strlen(encoded_account
)-1] = '\0';
159 /* pull the user attributes */
160 num_records
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &msgs
,
162 "(&(trustPartner=%s)(objectclass=trustedDomain))",
165 if (num_records
== 0) {
166 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
168 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
171 if (num_records
> 1) {
172 DEBUG(0,("Found %d records matching user [%s]\n", num_records
, r
->in
.account_name
));
173 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
176 flatname
= ldb_msg_find_attr_as_string(msgs
[0], "flatname", NULL
);
178 /* No flatname for this trust - we can't proceed */
179 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
181 account_name
= talloc_asprintf(mem_ctx
, "%s$", flatname
);
184 return NT_STATUS_NO_MEMORY
;
188 account_name
= r
->in
.account_name
;
191 /* pull the user attributes */
192 num_records
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &msgs
, attrs
,
193 "(&(sAMAccountName=%s)(objectclass=user))",
194 ldb_binary_encode_string(mem_ctx
, account_name
));
196 if (num_records
== 0) {
197 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
198 r
->in
.account_name
));
199 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
202 if (num_records
> 1) {
203 DEBUG(0,("Found %d records matching user [%s]\n", num_records
, r
->in
.account_name
));
204 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
207 user_account_control
= ldb_msg_find_attr_as_uint(msgs
[0], "userAccountControl", 0);
209 if (user_account_control
& UF_ACCOUNTDISABLE
) {
210 DEBUG(1, ("Account [%s] is disabled\n", r
->in
.account_name
));
211 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
214 if (r
->in
.secure_channel_type
== SEC_CHAN_WKSTA
) {
215 if (!(user_account_control
& UF_WORKSTATION_TRUST_ACCOUNT
)) {
216 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control
));
217 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
219 } else if (r
->in
.secure_channel_type
== SEC_CHAN_DOMAIN
||
220 r
->in
.secure_channel_type
== SEC_CHAN_DNS_DOMAIN
) {
221 if (!(user_account_control
& UF_INTERDOMAIN_TRUST_ACCOUNT
)) {
222 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control
));
224 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
226 } else if (r
->in
.secure_channel_type
== SEC_CHAN_BDC
) {
227 if (!(user_account_control
& UF_SERVER_TRUST_ACCOUNT
)) {
228 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control
));
229 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
231 } else if (r
->in
.secure_channel_type
== SEC_CHAN_RODC
) {
232 if (!(user_account_control
& UF_PARTIAL_SECRETS_ACCOUNT
)) {
233 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control
));
234 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
237 /* we should never reach this */
238 return NT_STATUS_INTERNAL_ERROR
;
241 *r
->out
.rid
= samdb_result_rid_from_sid(mem_ctx
, msgs
[0],
244 mach_pwd
= samdb_result_hash(mem_ctx
, msgs
[0], "unicodePwd");
245 if (mach_pwd
== NULL
) {
246 return NT_STATUS_ACCESS_DENIED
;
250 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
251 return NT_STATUS_ACCESS_DENIED
;
254 creds
= netlogon_creds_server_init(mem_ctx
,
257 r
->in
.secure_channel_type
,
258 &pipe_state
->client_challenge
,
259 &pipe_state
->server_challenge
,
262 r
->out
.return_credentials
,
263 *r
->in
.negotiate_flags
);
266 return NT_STATUS_ACCESS_DENIED
;
269 creds
->sid
= samdb_result_dom_sid(creds
, msgs
[0], "objectSid");
271 nt_status
= schannel_save_creds_state(mem_ctx
,
272 lpcfg_private_dir(dce_call
->conn
->dce_ctx
->lp_ctx
),
278 static NTSTATUS
dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
279 struct netr_ServerAuthenticate
*r
)
281 struct netr_ServerAuthenticate3 a
;
284 * negotiate_flags is used as an [in] parameter
285 * so it need to be initialised.
287 * (I think ... = 0; seems wrong here --metze)
289 uint32_t negotiate_flags_in
= 0;
290 uint32_t negotiate_flags_out
= 0;
292 a
.in
.server_name
= r
->in
.server_name
;
293 a
.in
.account_name
= r
->in
.account_name
;
294 a
.in
.secure_channel_type
= r
->in
.secure_channel_type
;
295 a
.in
.computer_name
= r
->in
.computer_name
;
296 a
.in
.credentials
= r
->in
.credentials
;
297 a
.in
.negotiate_flags
= &negotiate_flags_in
;
299 a
.out
.return_credentials
= r
->out
.return_credentials
;
301 a
.out
.negotiate_flags
= &negotiate_flags_out
;
303 return dcesrv_netr_ServerAuthenticate3(dce_call
, mem_ctx
, &a
);
306 static NTSTATUS
dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
307 struct netr_ServerAuthenticate2
*r
)
309 struct netr_ServerAuthenticate3 r3
;
312 r3
.in
.server_name
= r
->in
.server_name
;
313 r3
.in
.account_name
= r
->in
.account_name
;
314 r3
.in
.secure_channel_type
= r
->in
.secure_channel_type
;
315 r3
.in
.computer_name
= r
->in
.computer_name
;
316 r3
.in
.credentials
= r
->in
.credentials
;
317 r3
.out
.return_credentials
= r
->out
.return_credentials
;
318 r3
.in
.negotiate_flags
= r
->in
.negotiate_flags
;
319 r3
.out
.negotiate_flags
= r
->out
.negotiate_flags
;
322 return dcesrv_netr_ServerAuthenticate3(dce_call
, mem_ctx
, &r3
);
326 * NOTE: The following functions are nearly identical to the ones available in
327 * source3/rpc_server/srv_nelog_nt.c
328 * The reason we keep 2 copies is that they use different structures to
329 * represent the auth_info and the decrpc pipes.
333 * If schannel is required for this call test that it actually is available.
335 static NTSTATUS
schannel_check_required(struct dcerpc_auth
*auth_info
,
336 const char *computer_name
,
337 bool integrity
, bool privacy
)
340 if (auth_info
&& auth_info
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
341 if (!privacy
&& !integrity
) {
345 if ((!privacy
&& integrity
) &&
346 auth_info
->auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
) {
350 if ((privacy
|| integrity
) &&
351 auth_info
->auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
356 /* test didn't pass */
357 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
360 return NT_STATUS_ACCESS_DENIED
;
363 static NTSTATUS
dcesrv_netr_creds_server_step_check(struct dcesrv_call_state
*dce_call
,
365 const char *computer_name
,
366 struct netr_Authenticator
*received_authenticator
,
367 struct netr_Authenticator
*return_authenticator
,
368 struct netlogon_creds_CredentialState
**creds_out
)
371 struct dcerpc_auth
*auth_info
= dce_call
->conn
->auth_state
.auth_info
;
372 bool schannel_global_required
= false; /* Should be lpcfg_schannel_server() == true */
374 if (schannel_global_required
) {
375 nt_status
= schannel_check_required(auth_info
,
378 if (!NT_STATUS_IS_OK(nt_status
)) {
383 nt_status
= schannel_check_creds_state(mem_ctx
,
384 lpcfg_private_dir(dce_call
->conn
->dce_ctx
->lp_ctx
),
386 received_authenticator
,
387 return_authenticator
,
393 Change the machine account password for the currently connected
394 client. Supplies only the NT#.
397 static NTSTATUS
dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
398 struct netr_ServerPasswordSet
*r
)
400 struct netlogon_creds_CredentialState
*creds
;
401 struct ldb_context
*sam_ctx
;
402 const char * const attrs
[] = { "unicodePwd", NULL
};
403 struct ldb_message
**res
;
404 struct samr_Password
*oldNtHash
;
408 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
411 r
->in
.credential
, r
->out
.return_authenticator
,
413 NT_STATUS_NOT_OK_RETURN(nt_status
);
415 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);
416 if (sam_ctx
== NULL
) {
417 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
420 netlogon_creds_des_decrypt(creds
, r
->in
.new_password
);
422 /* fetch the old password hashes (the NT hash has to exist) */
424 ret
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &res
, attrs
,
425 "(&(objectClass=user)(objectSid=%s))",
426 ldap_encode_ndr_dom_sid(mem_ctx
, creds
->sid
));
428 return NT_STATUS_WRONG_PASSWORD
;
431 nt_status
= samdb_result_passwords(mem_ctx
,
432 dce_call
->conn
->dce_ctx
->lp_ctx
,
433 res
[0], NULL
, &oldNtHash
);
434 if (!NT_STATUS_IS_OK(nt_status
) || !oldNtHash
) {
435 return NT_STATUS_WRONG_PASSWORD
;
438 /* Using the sid for the account as the key, set the password */
439 nt_status
= samdb_set_password_sid(sam_ctx
, mem_ctx
,
441 NULL
, /* Don't have plaintext */
442 NULL
, r
->in
.new_password
,
443 NULL
, oldNtHash
, /* Password change */
449 Change the machine account password for the currently connected
450 client. Supplies new plaintext.
452 static NTSTATUS
dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
453 struct netr_ServerPasswordSet2
*r
)
455 struct netlogon_creds_CredentialState
*creds
;
456 struct ldb_context
*sam_ctx
;
457 const char * const attrs
[] = { "dBCSPwd", "unicodePwd", NULL
};
458 struct ldb_message
**res
;
459 struct samr_Password
*oldLmHash
, *oldNtHash
;
461 DATA_BLOB new_password
;
464 struct samr_CryptPassword password_buf
;
466 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
469 r
->in
.credential
, r
->out
.return_authenticator
,
471 NT_STATUS_NOT_OK_RETURN(nt_status
);
473 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);
474 if (sam_ctx
== NULL
) {
475 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
478 memcpy(password_buf
.data
, r
->in
.new_password
->data
, 512);
479 SIVAL(password_buf
.data
, 512, r
->in
.new_password
->length
);
480 netlogon_creds_arcfour_crypt(creds
, password_buf
.data
, 516);
482 if (!extract_pw_from_buffer(mem_ctx
, password_buf
.data
, &new_password
)) {
483 DEBUG(3,("samr: failed to decode password buffer\n"));
484 return NT_STATUS_WRONG_PASSWORD
;
487 /* fetch the old password hashes (at least one of both has to exist) */
489 ret
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &res
, attrs
,
490 "(&(objectClass=user)(objectSid=%s))",
491 ldap_encode_ndr_dom_sid(mem_ctx
, creds
->sid
));
493 return NT_STATUS_WRONG_PASSWORD
;
496 nt_status
= samdb_result_passwords(mem_ctx
,
497 dce_call
->conn
->dce_ctx
->lp_ctx
,
498 res
[0], &oldLmHash
, &oldNtHash
);
499 if (!NT_STATUS_IS_OK(nt_status
) || (!oldLmHash
&& !oldNtHash
)) {
500 return NT_STATUS_WRONG_PASSWORD
;
503 /* Using the sid for the account as the key, set the password */
504 nt_status
= samdb_set_password_sid(sam_ctx
, mem_ctx
,
506 &new_password
, /* we have plaintext */
508 oldLmHash
, oldNtHash
, /* Password change */
517 static WERROR
dcesrv_netr_LogonUasLogon(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
518 struct netr_LogonUasLogon
*r
)
520 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
527 static WERROR
dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
528 struct netr_LogonUasLogoff
*r
)
530 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
534 static NTSTATUS
dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx
*r
)
536 switch (r
->in
.logon_level
) {
537 case NetlogonInteractiveInformation
:
538 case NetlogonServiceInformation
:
539 case NetlogonInteractiveTransitiveInformation
:
540 case NetlogonServiceTransitiveInformation
:
541 if (r
->in
.logon
->password
== NULL
) {
542 return NT_STATUS_INVALID_PARAMETER
;
545 switch (r
->in
.validation_level
) {
546 case NetlogonValidationSamInfo
: /* 2 */
547 case NetlogonValidationSamInfo2
: /* 3 */
548 case NetlogonValidationSamInfo4
: /* 6 */
551 return NT_STATUS_INVALID_INFO_CLASS
;
555 case NetlogonNetworkInformation
:
556 case NetlogonNetworkTransitiveInformation
:
557 if (r
->in
.logon
->network
== NULL
) {
558 return NT_STATUS_INVALID_PARAMETER
;
561 switch (r
->in
.validation_level
) {
562 case NetlogonValidationSamInfo
: /* 2 */
563 case NetlogonValidationSamInfo2
: /* 3 */
564 case NetlogonValidationSamInfo4
: /* 6 */
567 return NT_STATUS_INVALID_INFO_CLASS
;
572 case NetlogonGenericInformation
:
573 if (r
->in
.logon
->generic
== NULL
) {
574 return NT_STATUS_INVALID_PARAMETER
;
577 switch (r
->in
.validation_level
) {
578 /* TODO: case NetlogonValidationGenericInfo: 4 */
579 case NetlogonValidationGenericInfo2
: /* 5 */
582 return NT_STATUS_INVALID_INFO_CLASS
;
587 return NT_STATUS_INVALID_PARAMETER
;
594 netr_LogonSamLogon_base
596 This version of the function allows other wrappers to say 'do not check the credentials'
598 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
600 static NTSTATUS
dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
601 struct netr_LogonSamLogonEx
*r
, struct netlogon_creds_CredentialState
*creds
)
603 struct auth_context
*auth_context
;
604 struct auth_usersupplied_info
*user_info
;
605 struct auth_user_info_dc
*user_info_dc
;
607 static const char zeros
[16];
608 struct netr_SamBaseInfo
*sam
;
609 struct netr_SamInfo2
*sam2
;
610 struct netr_SamInfo3
*sam3
;
611 struct netr_SamInfo6
*sam6
;
613 *r
->out
.authoritative
= 1;
615 user_info
= talloc_zero(mem_ctx
, struct auth_usersupplied_info
);
616 NT_STATUS_HAVE_NO_MEMORY(user_info
);
618 switch (r
->in
.logon_level
) {
619 case NetlogonInteractiveInformation
:
620 case NetlogonServiceInformation
:
621 case NetlogonInteractiveTransitiveInformation
:
622 case NetlogonServiceTransitiveInformation
:
623 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
624 netlogon_creds_arcfour_crypt(creds
,
625 r
->in
.logon
->password
->lmpassword
.hash
,
626 sizeof(r
->in
.logon
->password
->lmpassword
.hash
));
627 netlogon_creds_arcfour_crypt(creds
,
628 r
->in
.logon
->password
->ntpassword
.hash
,
629 sizeof(r
->in
.logon
->password
->ntpassword
.hash
));
631 netlogon_creds_des_decrypt(creds
, &r
->in
.logon
->password
->lmpassword
);
632 netlogon_creds_des_decrypt(creds
, &r
->in
.logon
->password
->ntpassword
);
635 /* TODO: we need to deny anonymous access here */
636 nt_status
= auth_context_create(mem_ctx
,
637 dce_call
->event_ctx
, dce_call
->msg_ctx
,
638 dce_call
->conn
->dce_ctx
->lp_ctx
,
640 NT_STATUS_NOT_OK_RETURN(nt_status
);
642 user_info
->logon_parameters
= r
->in
.logon
->password
->identity_info
.parameter_control
;
643 user_info
->client
.account_name
= r
->in
.logon
->password
->identity_info
.account_name
.string
;
644 user_info
->client
.domain_name
= r
->in
.logon
->password
->identity_info
.domain_name
.string
;
645 user_info
->workstation_name
= r
->in
.logon
->password
->identity_info
.workstation
.string
;
647 user_info
->flags
|= USER_INFO_INTERACTIVE_LOGON
;
648 user_info
->password_state
= AUTH_PASSWORD_HASH
;
650 user_info
->password
.hash
.lanman
= talloc(user_info
, struct samr_Password
);
651 NT_STATUS_HAVE_NO_MEMORY(user_info
->password
.hash
.lanman
);
652 *user_info
->password
.hash
.lanman
= r
->in
.logon
->password
->lmpassword
;
654 user_info
->password
.hash
.nt
= talloc(user_info
, struct samr_Password
);
655 NT_STATUS_HAVE_NO_MEMORY(user_info
->password
.hash
.nt
);
656 *user_info
->password
.hash
.nt
= r
->in
.logon
->password
->ntpassword
;
659 case NetlogonNetworkInformation
:
660 case NetlogonNetworkTransitiveInformation
:
662 /* TODO: we need to deny anonymous access here */
663 nt_status
= auth_context_create(mem_ctx
,
664 dce_call
->event_ctx
, dce_call
->msg_ctx
,
665 dce_call
->conn
->dce_ctx
->lp_ctx
,
667 NT_STATUS_NOT_OK_RETURN(nt_status
);
669 nt_status
= auth_context_set_challenge(auth_context
, r
->in
.logon
->network
->challenge
, "netr_LogonSamLogonWithFlags");
670 NT_STATUS_NOT_OK_RETURN(nt_status
);
672 user_info
->logon_parameters
= r
->in
.logon
->network
->identity_info
.parameter_control
;
673 user_info
->client
.account_name
= r
->in
.logon
->network
->identity_info
.account_name
.string
;
674 user_info
->client
.domain_name
= r
->in
.logon
->network
->identity_info
.domain_name
.string
;
675 user_info
->workstation_name
= r
->in
.logon
->network
->identity_info
.workstation
.string
;
677 user_info
->password_state
= AUTH_PASSWORD_RESPONSE
;
678 user_info
->password
.response
.lanman
= data_blob_talloc(mem_ctx
, r
->in
.logon
->network
->lm
.data
, r
->in
.logon
->network
->lm
.length
);
679 user_info
->password
.response
.nt
= data_blob_talloc(mem_ctx
, r
->in
.logon
->network
->nt
.data
, r
->in
.logon
->network
->nt
.length
);
684 case NetlogonGenericInformation
:
686 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
687 netlogon_creds_arcfour_crypt(creds
,
688 r
->in
.logon
->generic
->data
, r
->in
.logon
->generic
->length
);
690 /* Using DES to verify kerberos tickets makes no sense */
691 return NT_STATUS_INVALID_PARAMETER
;
694 if (strcmp(r
->in
.logon
->generic
->package_name
.string
, "Kerberos") == 0) {
696 struct dcerpc_binding_handle
*irpc_handle
;
697 struct kdc_check_generic_kerberos check
;
698 struct netr_GenericInfo2
*generic
= talloc_zero(mem_ctx
, struct netr_GenericInfo2
);
699 NT_STATUS_HAVE_NO_MEMORY(generic
);
700 *r
->out
.authoritative
= 1;
702 /* TODO: Describe and deal with these flags */
705 r
->out
.validation
->generic
= generic
;
707 irpc_handle
= irpc_binding_handle_by_name(mem_ctx
,
711 if (irpc_handle
== NULL
) {
712 return NT_STATUS_NO_LOGON_SERVERS
;
715 check
.in
.generic_request
=
716 data_blob_const(r
->in
.logon
->generic
->data
,
717 r
->in
.logon
->generic
->length
);
719 status
= dcerpc_kdc_check_generic_kerberos_r(irpc_handle
,
722 if (!NT_STATUS_IS_OK(status
)) {
725 generic
->length
= check
.out
.generic_reply
.length
;
726 generic
->data
= check
.out
.generic_reply
.data
;
730 /* Until we get an implemetnation of these other packages */
731 return NT_STATUS_INVALID_PARAMETER
;
734 return NT_STATUS_INVALID_PARAMETER
;
737 nt_status
= auth_check_password(auth_context
, mem_ctx
, user_info
, &user_info_dc
);
738 /* TODO: set *r->out.authoritative = 0 on specific errors */
739 NT_STATUS_NOT_OK_RETURN(nt_status
);
741 switch (r
->in
.validation_level
) {
743 nt_status
= auth_convert_user_info_dc_sambaseinfo(mem_ctx
, user_info_dc
, &sam
);
744 NT_STATUS_NOT_OK_RETURN(nt_status
);
746 sam2
= talloc_zero(mem_ctx
, struct netr_SamInfo2
);
747 NT_STATUS_HAVE_NO_MEMORY(sam2
);
750 /* And put into the talloc tree */
751 talloc_steal(sam2
, sam
);
752 r
->out
.validation
->sam2
= sam2
;
758 nt_status
= auth_convert_user_info_dc_saminfo3(mem_ctx
,
761 NT_STATUS_NOT_OK_RETURN(nt_status
);
763 r
->out
.validation
->sam3
= sam3
;
769 nt_status
= auth_convert_user_info_dc_saminfo3(mem_ctx
,
772 NT_STATUS_NOT_OK_RETURN(nt_status
);
774 sam6
= talloc_zero(mem_ctx
, struct netr_SamInfo6
);
775 NT_STATUS_HAVE_NO_MEMORY(sam6
);
776 sam6
->base
= sam3
->base
;
778 sam6
->sidcount
= sam3
->sidcount
;
779 sam6
->sids
= sam3
->sids
;
781 sam6
->dns_domainname
.string
= lpcfg_dnsdomain(dce_call
->conn
->dce_ctx
->lp_ctx
);
782 sam6
->principle
.string
= talloc_asprintf(mem_ctx
, "%s@%s",
783 sam
->account_name
.string
, sam6
->dns_domainname
.string
);
784 NT_STATUS_HAVE_NO_MEMORY(sam6
->principle
.string
);
785 /* And put into the talloc tree */
786 talloc_steal(sam6
, sam3
);
788 r
->out
.validation
->sam6
= sam6
;
792 return NT_STATUS_INVALID_INFO_CLASS
;
795 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
796 /* It appears that level 6 is not individually encrypted */
797 if ((r
->in
.validation_level
!= 6) &&
798 memcmp(sam
->key
.key
, zeros
, sizeof(sam
->key
.key
)) != 0) {
799 /* This key is sent unencrypted without the ARCFOUR flag set */
800 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
801 netlogon_creds_arcfour_crypt(creds
,
803 sizeof(sam
->key
.key
));
807 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
808 /* It appears that level 6 is not individually encrypted */
809 if ((r
->in
.validation_level
!= 6) &&
810 memcmp(sam
->LMSessKey
.key
, zeros
, sizeof(sam
->LMSessKey
.key
)) != 0) {
811 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
812 netlogon_creds_arcfour_crypt(creds
,
814 sizeof(sam
->LMSessKey
.key
));
816 netlogon_creds_des_encrypt_LMKey(creds
,
821 /* TODO: Describe and deal with these flags */
827 static NTSTATUS
dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
828 struct netr_LogonSamLogonEx
*r
)
831 struct netlogon_creds_CredentialState
*creds
;
833 *r
->out
.authoritative
= 1;
835 nt_status
= dcesrv_netr_LogonSamLogon_check(r
);
836 if (!NT_STATUS_IS_OK(nt_status
)) {
840 nt_status
= schannel_get_creds_state(mem_ctx
,
841 lpcfg_private_dir(dce_call
->conn
->dce_ctx
->lp_ctx
),
842 r
->in
.computer_name
, &creds
);
843 if (!NT_STATUS_IS_OK(nt_status
)) {
847 if (!dce_call
->conn
->auth_state
.auth_info
||
848 dce_call
->conn
->auth_state
.auth_info
->auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
849 return NT_STATUS_ACCESS_DENIED
;
851 return dcesrv_netr_LogonSamLogon_base(dce_call
, mem_ctx
, r
, creds
);
855 netr_LogonSamLogonWithFlags
858 static NTSTATUS
dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
859 struct netr_LogonSamLogonWithFlags
*r
)
862 struct netlogon_creds_CredentialState
*creds
;
863 struct netr_LogonSamLogonEx r2
;
865 struct netr_Authenticator
*return_authenticator
;
869 r2
.in
.server_name
= r
->in
.server_name
;
870 r2
.in
.computer_name
= r
->in
.computer_name
;
871 r2
.in
.logon_level
= r
->in
.logon_level
;
872 r2
.in
.logon
= r
->in
.logon
;
873 r2
.in
.validation_level
= r
->in
.validation_level
;
874 r2
.in
.flags
= r
->in
.flags
;
875 r2
.out
.validation
= r
->out
.validation
;
876 r2
.out
.authoritative
= r
->out
.authoritative
;
877 r2
.out
.flags
= r
->out
.flags
;
879 *r
->out
.authoritative
= 1;
881 nt_status
= dcesrv_netr_LogonSamLogon_check(&r2
);
882 if (!NT_STATUS_IS_OK(nt_status
)) {
886 return_authenticator
= talloc(mem_ctx
, struct netr_Authenticator
);
887 NT_STATUS_HAVE_NO_MEMORY(return_authenticator
);
889 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
892 r
->in
.credential
, return_authenticator
,
894 NT_STATUS_NOT_OK_RETURN(nt_status
);
896 nt_status
= dcesrv_netr_LogonSamLogon_base(dce_call
, mem_ctx
, &r2
, creds
);
898 r
->out
.return_authenticator
= return_authenticator
;
906 static NTSTATUS
dcesrv_netr_LogonSamLogon(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
907 struct netr_LogonSamLogon
*r
)
909 struct netr_LogonSamLogonWithFlags r2
;
915 r2
.in
.server_name
= r
->in
.server_name
;
916 r2
.in
.computer_name
= r
->in
.computer_name
;
917 r2
.in
.credential
= r
->in
.credential
;
918 r2
.in
.return_authenticator
= r
->in
.return_authenticator
;
919 r2
.in
.logon_level
= r
->in
.logon_level
;
920 r2
.in
.logon
= r
->in
.logon
;
921 r2
.in
.validation_level
= r
->in
.validation_level
;
922 r2
.in
.flags
= &flags
;
923 r2
.out
.validation
= r
->out
.validation
;
924 r2
.out
.authoritative
= r
->out
.authoritative
;
925 r2
.out
.flags
= &flags
;
927 status
= dcesrv_netr_LogonSamLogonWithFlags(dce_call
, mem_ctx
, &r2
);
929 r
->out
.return_authenticator
= r2
.out
.return_authenticator
;
938 static NTSTATUS
dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
939 struct netr_LogonSamLogoff
*r
)
941 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
949 static NTSTATUS
dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
950 struct netr_DatabaseDeltas
*r
)
952 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
959 static NTSTATUS
dcesrv_netr_DatabaseSync2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
960 struct netr_DatabaseSync2
*r
)
962 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
963 return NT_STATUS_NOT_IMPLEMENTED
;
970 static NTSTATUS
dcesrv_netr_DatabaseSync(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
971 struct netr_DatabaseSync
*r
)
973 struct netr_DatabaseSync2 r2
;
978 r2
.in
.logon_server
= r
->in
.logon_server
;
979 r2
.in
.computername
= r
->in
.computername
;
980 r2
.in
.credential
= r
->in
.credential
;
981 r2
.in
.database_id
= r
->in
.database_id
;
982 r2
.in
.restart_state
= SYNCSTATE_NORMAL_STATE
;
983 r2
.in
.sync_context
= r
->in
.sync_context
;
984 r2
.out
.sync_context
= r
->out
.sync_context
;
985 r2
.out
.delta_enum_array
= r
->out
.delta_enum_array
;
986 r2
.in
.preferredmaximumlength
= r
->in
.preferredmaximumlength
;
988 status
= dcesrv_netr_DatabaseSync2(dce_call
, mem_ctx
, &r2
);
997 static NTSTATUS
dcesrv_netr_AccountDeltas(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
998 struct netr_AccountDeltas
*r
)
1000 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1001 return NT_STATUS_NOT_IMPLEMENTED
;
1008 static NTSTATUS
dcesrv_netr_AccountSync(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1009 struct netr_AccountSync
*r
)
1011 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1012 return NT_STATUS_NOT_IMPLEMENTED
;
1019 static WERROR
dcesrv_netr_GetDcName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1020 struct netr_GetDcName
*r
)
1022 const char * const attrs
[] = { NULL
};
1023 struct ldb_context
*sam_ctx
;
1024 struct ldb_message
**res
;
1025 struct ldb_dn
*domain_dn
;
1030 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1031 * that the domainname needs to be a valid netbios domain
1032 * name, if it is not NULL.
1034 if (r
->in
.domainname
) {
1035 const char *dot
= strchr(r
->in
.domainname
, '.');
1036 size_t len
= strlen(r
->in
.domainname
);
1038 if (dot
|| len
> 15) {
1039 return WERR_DCNOTFOUND
;
1043 * TODO: Should we also varify that only valid
1044 * netbios name characters are used?
1048 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
1049 dce_call
->conn
->dce_ctx
->lp_ctx
,
1050 dce_call
->conn
->auth_state
.session_info
, 0);
1051 if (sam_ctx
== NULL
) {
1052 return WERR_DS_UNAVAILABLE
;
1055 domain_dn
= samdb_domain_to_dn(sam_ctx
, mem_ctx
,
1057 if (domain_dn
== NULL
) {
1058 return WERR_DS_UNAVAILABLE
;
1061 ret
= gendb_search_dn(sam_ctx
, mem_ctx
,
1062 domain_dn
, &res
, attrs
);
1064 return WERR_NO_SUCH_DOMAIN
;
1067 /* TODO: - return real IP address
1068 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1070 dcname
= talloc_asprintf(mem_ctx
, "\\\\%s",
1071 lpcfg_netbios_name(dce_call
->conn
->dce_ctx
->lp_ctx
));
1072 W_ERROR_HAVE_NO_MEMORY(dcname
);
1074 *r
->out
.dcname
= dcname
;
1080 netr_LogonControl2Ex
1082 static WERROR
dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1083 struct netr_LogonControl2Ex
*r
)
1085 return WERR_NOT_SUPPORTED
;
1092 static WERROR
dcesrv_netr_LogonControl(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1093 struct netr_LogonControl
*r
)
1095 struct netr_LogonControl2Ex r2
;
1098 if (r
->in
.level
== 0x00000001) {
1101 r2
.in
.logon_server
= r
->in
.logon_server
;
1102 r2
.in
.function_code
= r
->in
.function_code
;
1103 r2
.in
.level
= r
->in
.level
;
1105 r2
.out
.query
= r
->out
.query
;
1107 werr
= dcesrv_netr_LogonControl2Ex(dce_call
, mem_ctx
, &r2
);
1108 } else if (r
->in
.level
== 0x00000002) {
1109 werr
= WERR_NOT_SUPPORTED
;
1111 werr
= WERR_UNKNOWN_LEVEL
;
1121 static WERROR
dcesrv_netr_LogonControl2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1122 struct netr_LogonControl2
*r
)
1124 struct netr_LogonControl2Ex r2
;
1129 r2
.in
.logon_server
= r
->in
.logon_server
;
1130 r2
.in
.function_code
= r
->in
.function_code
;
1131 r2
.in
.level
= r
->in
.level
;
1132 r2
.in
.data
= r
->in
.data
;
1133 r2
.out
.query
= r
->out
.query
;
1135 werr
= dcesrv_netr_LogonControl2Ex(dce_call
, mem_ctx
, &r2
);
1140 static WERROR
fill_trusted_domains_array(TALLOC_CTX
*mem_ctx
,
1141 struct ldb_context
*sam_ctx
,
1142 struct netr_DomainTrustList
*trusts
,
1143 uint32_t trust_flags
);
1148 static WERROR
dcesrv_netr_GetAnyDCName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1149 struct netr_GetAnyDCName
*r
)
1151 struct netr_DomainTrustList
*trusts
;
1152 struct ldb_context
*sam_ctx
;
1153 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1157 *r
->out
.dcname
= NULL
;
1159 if ((r
->in
.domainname
== NULL
) || (r
->in
.domainname
[0] == '\0')) {
1160 /* if the domainname parameter wasn't set assume our domain */
1161 r
->in
.domainname
= lpcfg_workgroup(lp_ctx
);
1164 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1165 dce_call
->conn
->auth_state
.session_info
, 0);
1166 if (sam_ctx
== NULL
) {
1167 return WERR_DS_UNAVAILABLE
;
1170 if (strcasecmp(r
->in
.domainname
, lpcfg_workgroup(lp_ctx
)) == 0) {
1171 /* well we asked for a DC of our own domain */
1172 if (samdb_is_pdc(sam_ctx
)) {
1173 /* we are the PDC of the specified domain */
1174 return WERR_NO_SUCH_DOMAIN
;
1177 *r
->out
.dcname
= talloc_asprintf(mem_ctx
, "\\%s",
1178 lpcfg_netbios_name(lp_ctx
));
1179 W_ERROR_HAVE_NO_MEMORY(*r
->out
.dcname
);
1184 /* Okay, now we have to consider the trusted domains */
1186 trusts
= talloc_zero(mem_ctx
, struct netr_DomainTrustList
);
1187 W_ERROR_HAVE_NO_MEMORY(trusts
);
1191 werr
= fill_trusted_domains_array(mem_ctx
, sam_ctx
, trusts
,
1192 NETR_TRUST_FLAG_INBOUND
1193 | NETR_TRUST_FLAG_OUTBOUND
);
1194 W_ERROR_NOT_OK_RETURN(werr
);
1196 for (i
= 0; i
< trusts
->count
; i
++) {
1197 if (strcasecmp(r
->in
.domainname
, trusts
->array
[i
].netbios_name
) == 0) {
1198 /* FIXME: Here we need to find a DC for the specified
1199 * trusted domain. */
1201 /* return WERR_OK; */
1202 return WERR_NO_SUCH_DOMAIN
;
1206 return WERR_NO_SUCH_DOMAIN
;
1213 static NTSTATUS
dcesrv_netr_DatabaseRedo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1214 struct netr_DatabaseRedo
*r
)
1216 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1221 netr_NetrEnumerateTrustedDomains
1223 static NTSTATUS
dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1224 struct netr_NetrEnumerateTrustedDomains
*r
)
1226 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1231 netr_LogonGetCapabilities
1233 static NTSTATUS
dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1234 struct netr_LogonGetCapabilities
*r
)
1236 /* we don't support AES yet */
1237 return NT_STATUS_NOT_IMPLEMENTED
;
1242 netr_NETRLOGONSETSERVICEBITS
1244 static WERROR
dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1245 struct netr_NETRLOGONSETSERVICEBITS
*r
)
1247 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1252 netr_LogonGetTrustRid
1254 static WERROR
dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1255 struct netr_LogonGetTrustRid
*r
)
1257 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1262 netr_NETRLOGONCOMPUTESERVERDIGEST
1264 static WERROR
dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1265 struct netr_NETRLOGONCOMPUTESERVERDIGEST
*r
)
1267 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1272 netr_NETRLOGONCOMPUTECLIENTDIGEST
1274 static WERROR
dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1275 struct netr_NETRLOGONCOMPUTECLIENTDIGEST
*r
)
1277 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1285 static WERROR
dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1286 struct netr_DsRGetSiteName
*r
)
1288 struct ldb_context
*sam_ctx
;
1289 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1291 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1292 dce_call
->conn
->auth_state
.session_info
, 0);
1293 if (sam_ctx
== NULL
) {
1294 return WERR_DS_UNAVAILABLE
;
1297 *r
->out
.site
= samdb_server_site_name(sam_ctx
, mem_ctx
);
1298 W_ERROR_HAVE_NO_MEMORY(*r
->out
.site
);
1305 fill in a netr_OneDomainInfo from a ldb search result
1307 static NTSTATUS
fill_one_domain_info(TALLOC_CTX
*mem_ctx
,
1308 struct loadparm_context
*lp_ctx
,
1309 struct ldb_context
*sam_ctx
,
1310 struct ldb_message
*res
,
1311 struct netr_OneDomainInfo
*info
,
1312 bool is_local
, bool is_trust_list
)
1316 if (is_trust_list
) {
1317 /* w2k8 only fills this on trusted domains */
1318 info
->trust_extension
.info
= talloc_zero(mem_ctx
, struct netr_trust_extension
);
1319 info
->trust_extension
.length
= 16;
1320 info
->trust_extension
.info
->flags
=
1321 NETR_TRUST_FLAG_TREEROOT
|
1322 NETR_TRUST_FLAG_IN_FOREST
|
1323 NETR_TRUST_FLAG_PRIMARY
|
1324 NETR_TRUST_FLAG_NATIVE
;
1326 info
->trust_extension
.info
->parent_index
= 0; /* should be index into array
1328 info
->trust_extension
.info
->trust_type
= LSA_TRUST_TYPE_UPLEVEL
; /* should be based on ldb search for trusts */
1329 info
->trust_extension
.info
->trust_attributes
= 0; /* TODO: base on ldb search? */
1332 if (is_trust_list
) {
1333 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1334 info
->dns_forestname
.string
= NULL
;
1336 info
->dns_forestname
.string
= samdb_forest_name(sam_ctx
, mem_ctx
);
1337 NT_STATUS_HAVE_NO_MEMORY(info
->dns_forestname
.string
);
1338 info
->dns_forestname
.string
= talloc_asprintf(mem_ctx
, "%s.", info
->dns_forestname
.string
);
1339 NT_STATUS_HAVE_NO_MEMORY(info
->dns_forestname
.string
);
1343 info
->domainname
.string
= lpcfg_workgroup(lp_ctx
);
1344 info
->dns_domainname
.string
= lpcfg_dnsdomain(lp_ctx
);
1345 info
->domain_guid
= samdb_result_guid(res
, "objectGUID");
1346 info
->domain_sid
= samdb_result_dom_sid(mem_ctx
, res
, "objectSid");
1348 info
->domainname
.string
= ldb_msg_find_attr_as_string(res
, "flatName", NULL
);
1349 info
->dns_domainname
.string
= ldb_msg_find_attr_as_string(res
, "trustPartner", NULL
);
1350 info
->domain_guid
= samdb_result_guid(res
, "objectGUID");
1351 info
->domain_sid
= samdb_result_dom_sid(mem_ctx
, res
, "securityIdentifier");
1353 if (!is_trust_list
) {
1354 info
->dns_domainname
.string
= talloc_asprintf(mem_ctx
, "%s.", info
->dns_domainname
.string
);
1357 return NT_STATUS_OK
;
1361 netr_LogonGetDomainInfo
1362 this is called as part of the ADS domain logon procedure.
1364 It has an important role in convaying details about the client, such
1365 as Operating System, Version, Service Pack etc.
1367 static NTSTATUS
dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state
*dce_call
,
1368 TALLOC_CTX
*mem_ctx
, struct netr_LogonGetDomainInfo
*r
)
1370 struct netlogon_creds_CredentialState
*creds
;
1371 const char * const attrs
[] = { "objectSid", "objectGUID", "flatName",
1372 "securityIdentifier", "trustPartner", NULL
};
1373 const char * const attrs2
[] = { "sAMAccountName", "dNSHostName",
1374 "msDS-SupportedEncryptionTypes", NULL
};
1375 const char *sam_account_name
, *old_dns_hostname
, *prefix1
, *prefix2
;
1376 struct ldb_context
*sam_ctx
;
1377 struct ldb_message
**res1
, **res2
, **res3
, *new_msg
;
1378 struct ldb_dn
*workstation_dn
;
1379 struct netr_DomainInformation
*domain_info
;
1380 struct netr_LsaPolicyInformation
*lsa_policy_info
;
1381 uint32_t default_supported_enc_types
= 0xFFFFFFFF;
1382 bool update_dns_hostname
= true;
1386 status
= dcesrv_netr_creds_server_step_check(dce_call
,
1388 r
->in
.computer_name
,
1390 r
->out
.return_authenticator
,
1392 if (!NT_STATUS_IS_OK(status
)) {
1393 DEBUG(0,(__location__
" Bad credentials - error\n"));
1395 NT_STATUS_NOT_OK_RETURN(status
);
1397 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
1398 dce_call
->conn
->dce_ctx
->lp_ctx
,
1399 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
), 0);
1400 if (sam_ctx
== NULL
) {
1401 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
1404 switch (r
->in
.level
) {
1405 case 1: /* Domain information */
1407 if (r
->in
.query
->workstation_info
== NULL
) {
1408 return NT_STATUS_INVALID_PARAMETER
;
1411 /* Prepares the workstation DN */
1412 workstation_dn
= ldb_dn_new_fmt(mem_ctx
, sam_ctx
, "<SID=%s>",
1413 dom_sid_string(mem_ctx
, creds
->sid
));
1414 NT_STATUS_HAVE_NO_MEMORY(workstation_dn
);
1416 /* Lookup for attributes in workstation object */
1417 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, workstation_dn
, &res1
,
1420 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1423 /* Gets the sam account name which is checked against the DNS
1424 * hostname parameter. */
1425 sam_account_name
= ldb_msg_find_attr_as_string(res1
[0],
1428 if (sam_account_name
== NULL
) {
1429 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1433 * Checks that the sam account name without a possible "$"
1434 * matches as prefix with the DNS hostname in the workstation
1437 prefix1
= talloc_strndup(mem_ctx
, sam_account_name
,
1438 strcspn(sam_account_name
, "$"));
1439 NT_STATUS_HAVE_NO_MEMORY(prefix1
);
1440 if (r
->in
.query
->workstation_info
->dns_hostname
!= NULL
) {
1441 prefix2
= talloc_strndup(mem_ctx
,
1442 r
->in
.query
->workstation_info
->dns_hostname
,
1443 strcspn(r
->in
.query
->workstation_info
->dns_hostname
, "."));
1444 NT_STATUS_HAVE_NO_MEMORY(prefix2
);
1446 if (strcasecmp(prefix1
, prefix2
) != 0) {
1447 update_dns_hostname
= false;
1450 update_dns_hostname
= false;
1453 /* Gets the old DNS hostname */
1454 old_dns_hostname
= ldb_msg_find_attr_as_string(res1
[0],
1459 * Updates the DNS hostname when the client wishes that the
1460 * server should handle this for him
1461 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1462 * obviously only checked when we do already have a
1464 * See MS-NRPC section 3.5.4.3.9
1466 if ((old_dns_hostname
!= NULL
) &&
1467 (r
->in
.query
->workstation_info
->workstation_flags
1468 & NETR_WS_FLAG_HANDLES_SPN_UPDATE
) != 0) {
1469 update_dns_hostname
= false;
1472 /* Gets host information and put them into our directory */
1474 new_msg
= ldb_msg_new(mem_ctx
);
1475 NT_STATUS_HAVE_NO_MEMORY(new_msg
);
1477 new_msg
->dn
= workstation_dn
;
1479 /* Sets the OS name */
1481 if (r
->in
.query
->workstation_info
->os_name
.string
== NULL
) {
1482 return NT_STATUS_INVALID_PARAMETER
;
1485 ret
= ldb_msg_add_string(new_msg
, "operatingSystem",
1486 r
->in
.query
->workstation_info
->os_name
.string
);
1487 if (ret
!= LDB_SUCCESS
) {
1488 return NT_STATUS_NO_MEMORY
;
1492 * Sets information from "os_version". On an empty structure
1493 * the values are cleared.
1495 if (r
->in
.query
->workstation_info
->os_version
.os
!= NULL
) {
1496 struct netr_OsVersionInfoEx
*os_version
;
1497 const char *os_version_str
;
1499 os_version
= &r
->in
.query
->workstation_info
->os_version
.os
->os
;
1501 if (os_version
->CSDVersion
== NULL
) {
1502 return NT_STATUS_INVALID_PARAMETER
;
1505 os_version_str
= talloc_asprintf(new_msg
, "%u.%u (%u)",
1506 os_version
->MajorVersion
,
1507 os_version
->MinorVersion
,
1508 os_version
->BuildNumber
);
1509 NT_STATUS_HAVE_NO_MEMORY(os_version_str
);
1511 ret
= ldb_msg_add_string(new_msg
,
1512 "operatingSystemServicePack",
1513 os_version
->CSDVersion
);
1514 if (ret
!= LDB_SUCCESS
) {
1515 return NT_STATUS_NO_MEMORY
;
1518 ret
= ldb_msg_add_string(new_msg
,
1519 "operatingSystemVersion",
1521 if (ret
!= LDB_SUCCESS
) {
1522 return NT_STATUS_NO_MEMORY
;
1525 ret
= samdb_msg_add_delete(sam_ctx
, mem_ctx
, new_msg
,
1526 "operatingSystemServicePack");
1527 if (ret
!= LDB_SUCCESS
) {
1528 return NT_STATUS_NO_MEMORY
;
1531 ret
= samdb_msg_add_delete(sam_ctx
, mem_ctx
, new_msg
,
1532 "operatingSystemVersion");
1533 if (ret
!= LDB_SUCCESS
) {
1534 return NT_STATUS_NO_MEMORY
;
1539 * If the boolean "update_dns_hostname" remained true, then we
1540 * are fine to start the update.
1542 if (update_dns_hostname
) {
1543 ret
= ldb_msg_add_string(new_msg
,
1545 r
->in
.query
->workstation_info
->dns_hostname
);
1546 if (ret
!= LDB_SUCCESS
) {
1547 return NT_STATUS_NO_MEMORY
;
1550 /* This manual "servicePrincipalName" generation is
1551 * still needed! Since the update in the samldb LDB
1552 * module does only work if the entries already exist
1553 * which isn't always the case. */
1554 ret
= ldb_msg_add_string(new_msg
,
1555 "servicePrincipalName",
1556 talloc_asprintf(new_msg
, "HOST/%s",
1557 r
->in
.computer_name
));
1558 if (ret
!= LDB_SUCCESS
) {
1559 return NT_STATUS_NO_MEMORY
;
1562 ret
= ldb_msg_add_string(new_msg
,
1563 "servicePrincipalName",
1564 talloc_asprintf(new_msg
, "HOST/%s",
1565 r
->in
.query
->workstation_info
->dns_hostname
));
1566 if (ret
!= LDB_SUCCESS
) {
1567 return NT_STATUS_NO_MEMORY
;
1571 if (dsdb_replace(sam_ctx
, new_msg
, 0) != LDB_SUCCESS
) {
1572 DEBUG(3,("Impossible to update samdb: %s\n",
1573 ldb_errstring(sam_ctx
)));
1576 talloc_free(new_msg
);
1578 /* Writes back the domain information */
1580 /* We need to do two searches. The first will pull our primary
1581 domain and the second will pull any trusted domains. Our
1582 primary domain is also a "trusted" domain, so we need to
1583 put the primary domain into the lists of returned trusts as
1585 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, ldb_get_default_basedn(sam_ctx
),
1588 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1591 ret3
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &res3
, attrs
,
1592 "(objectClass=trustedDomain)");
1594 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1597 domain_info
= talloc(mem_ctx
, struct netr_DomainInformation
);
1598 NT_STATUS_HAVE_NO_MEMORY(domain_info
);
1600 ZERO_STRUCTP(domain_info
);
1602 /* Informations about the local and trusted domains */
1604 status
= fill_one_domain_info(mem_ctx
,
1605 dce_call
->conn
->dce_ctx
->lp_ctx
,
1606 sam_ctx
, res2
[0], &domain_info
->primary_domain
,
1608 NT_STATUS_NOT_OK_RETURN(status
);
1610 domain_info
->trusted_domain_count
= ret3
+ 1;
1611 domain_info
->trusted_domains
= talloc_array(mem_ctx
,
1612 struct netr_OneDomainInfo
,
1613 domain_info
->trusted_domain_count
);
1614 NT_STATUS_HAVE_NO_MEMORY(domain_info
->trusted_domains
);
1616 for (i
=0;i
<ret3
;i
++) {
1617 status
= fill_one_domain_info(mem_ctx
,
1618 dce_call
->conn
->dce_ctx
->lp_ctx
,
1620 &domain_info
->trusted_domains
[i
],
1622 NT_STATUS_NOT_OK_RETURN(status
);
1625 status
= fill_one_domain_info(mem_ctx
,
1626 dce_call
->conn
->dce_ctx
->lp_ctx
, sam_ctx
, res2
[0],
1627 &domain_info
->trusted_domains
[i
], true, true);
1628 NT_STATUS_NOT_OK_RETURN(status
);
1630 /* Sets the supported encryption types */
1631 domain_info
->supported_enc_types
= ldb_msg_find_attr_as_uint(res1
[0],
1632 "msDS-SupportedEncryptionTypes",
1633 default_supported_enc_types
);
1635 /* Other host domain information */
1637 lsa_policy_info
= talloc(mem_ctx
,
1638 struct netr_LsaPolicyInformation
);
1639 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info
);
1640 ZERO_STRUCTP(lsa_policy_info
);
1642 domain_info
->lsa_policy
= *lsa_policy_info
;
1644 /* The DNS hostname is only returned back when there is a chance
1646 if ((r
->in
.query
->workstation_info
->workstation_flags
1647 & NETR_WS_FLAG_HANDLES_SPN_UPDATE
) != 0) {
1648 domain_info
->dns_hostname
.string
= old_dns_hostname
;
1650 domain_info
->dns_hostname
.string
= NULL
;
1653 domain_info
->workstation_flags
=
1654 r
->in
.query
->workstation_info
->workstation_flags
;
1656 r
->out
.info
->domain_info
= domain_info
;
1658 case 2: /* LSA policy information - not used at the moment */
1659 lsa_policy_info
= talloc(mem_ctx
,
1660 struct netr_LsaPolicyInformation
);
1661 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info
);
1662 ZERO_STRUCTP(lsa_policy_info
);
1664 r
->out
.info
->lsa_policy_info
= lsa_policy_info
;
1667 return NT_STATUS_INVALID_LEVEL
;
1671 return NT_STATUS_OK
;
1676 netr_ServerPasswordGet
1678 static WERROR
dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1679 struct netr_ServerPasswordGet
*r
)
1681 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1686 netr_NETRLOGONSENDTOSAM
1688 static WERROR
dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1689 struct netr_NETRLOGONSENDTOSAM
*r
)
1691 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1696 netr_DsRGetDCNameEx2
1698 static WERROR
dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state
*dce_call
,
1699 TALLOC_CTX
*mem_ctx
,
1700 struct netr_DsRGetDCNameEx2
*r
)
1702 struct ldb_context
*sam_ctx
;
1703 struct netr_DsRGetDCNameInfo
*info
;
1704 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1705 const struct tsocket_address
*remote_address
;
1707 const char *server_site_name
;
1709 struct netlogon_samlogon_response response
;
1711 const char *dc_name
= NULL
;
1712 const char *domain_name
= NULL
;
1714 ZERO_STRUCTP(r
->out
.info
);
1716 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1717 dce_call
->conn
->auth_state
.session_info
, 0);
1718 if (sam_ctx
== NULL
) {
1719 return WERR_DS_UNAVAILABLE
;
1722 remote_address
= dcesrv_connection_get_remote_address(dce_call
->conn
);
1723 if (tsocket_address_is_inet(remote_address
, "ip")) {
1724 addr
= tsocket_address_inet_addr_string(remote_address
, mem_ctx
);
1725 W_ERROR_HAVE_NO_MEMORY(addr
);
1728 /* "server_unc" is ignored by w2k3 */
1730 if (r
->in
.flags
& ~(DSGETDC_VALID_FLAGS
)) {
1731 return WERR_INVALID_FLAGS
;
1734 if (r
->in
.flags
& DS_GC_SERVER_REQUIRED
&&
1735 r
->in
.flags
& DS_PDC_REQUIRED
&&
1736 r
->in
.flags
& DS_KDC_REQUIRED
) {
1737 return WERR_INVALID_FLAGS
;
1739 if (r
->in
.flags
& DS_IS_FLAT_NAME
&&
1740 r
->in
.flags
& DS_IS_DNS_NAME
) {
1741 return WERR_INVALID_FLAGS
;
1743 if (r
->in
.flags
& DS_RETURN_DNS_NAME
&&
1744 r
->in
.flags
& DS_RETURN_FLAT_NAME
) {
1745 return WERR_INVALID_FLAGS
;
1747 if (r
->in
.flags
& DS_DIRECTORY_SERVICE_REQUIRED
&&
1748 r
->in
.flags
& DS_DIRECTORY_SERVICE_6_REQUIRED
) {
1749 return WERR_INVALID_FLAGS
;
1752 if (r
->in
.flags
& DS_GOOD_TIMESERV_PREFERRED
&&
1754 (DS_DIRECTORY_SERVICE_REQUIRED
|
1755 DS_DIRECTORY_SERVICE_PREFERRED
|
1756 DS_GC_SERVER_REQUIRED
|
1759 return WERR_INVALID_FLAGS
;
1762 if (r
->in
.flags
& DS_TRY_NEXTCLOSEST_SITE
&&
1764 return WERR_INVALID_FLAGS
;
1767 /* Proof server site parameter "site_name" if it was specified */
1768 server_site_name
= samdb_server_site_name(sam_ctx
, mem_ctx
);
1769 W_ERROR_HAVE_NO_MEMORY(server_site_name
);
1770 if ((r
->in
.site_name
!= NULL
) && (strcasecmp(r
->in
.site_name
,
1771 server_site_name
) != 0)) {
1772 return WERR_NO_SUCH_DOMAIN
;
1775 guid_str
= r
->in
.domain_guid
!= NULL
?
1776 GUID_string(mem_ctx
, r
->in
.domain_guid
) : NULL
;
1778 status
= fill_netlogon_samlogon_response(sam_ctx
, mem_ctx
,
1782 r
->in
.client_account
,
1784 NETLOGON_NT_VERSION_5EX_WITH_IP
,
1785 lp_ctx
, &response
, true);
1786 if (!NT_STATUS_IS_OK(status
)) {
1787 return ntstatus_to_werror(status
);
1790 if (r
->in
.flags
& DS_RETURN_DNS_NAME
) {
1791 dc_name
= response
.data
.nt5_ex
.pdc_dns_name
;
1792 domain_name
= response
.data
.nt5_ex
.dns_domain
;
1793 } else if (r
->in
.flags
& DS_RETURN_FLAT_NAME
) {
1794 dc_name
= response
.data
.nt5_ex
.pdc_name
;
1795 domain_name
= response
.data
.nt5_ex
.domain_name
;
1799 * TODO: autodetect what we need to return
1800 * based on the given arguments
1802 dc_name
= response
.data
.nt5_ex
.pdc_name
;
1803 domain_name
= response
.data
.nt5_ex
.domain_name
;
1806 if (!dc_name
|| !dc_name
[0]) {
1807 return WERR_NO_SUCH_DOMAIN
;
1810 if (!domain_name
|| !domain_name
[0]) {
1811 return WERR_NO_SUCH_DOMAIN
;
1814 info
= talloc(mem_ctx
, struct netr_DsRGetDCNameInfo
);
1815 W_ERROR_HAVE_NO_MEMORY(info
);
1816 info
->dc_unc
= talloc_asprintf(mem_ctx
, "\\\\%s", dc_name
);
1817 W_ERROR_HAVE_NO_MEMORY(info
->dc_unc
);
1818 info
->dc_address
= talloc_asprintf(mem_ctx
, "\\\\%s",
1819 response
.data
.nt5_ex
.sockaddr
.pdc_ip
);
1820 W_ERROR_HAVE_NO_MEMORY(info
->dc_address
);
1821 info
->dc_address_type
= DS_ADDRESS_TYPE_INET
; /* TODO: make this dynamic? for ipv6 */
1822 info
->domain_guid
= response
.data
.nt5_ex
.domain_uuid
;
1823 info
->domain_name
= domain_name
;
1824 info
->forest_name
= response
.data
.nt5_ex
.forest
;
1825 info
->dc_flags
= response
.data
.nt5_ex
.server_type
;
1826 info
->dc_site_name
= response
.data
.nt5_ex
.server_site
;
1827 info
->client_site_name
= response
.data
.nt5_ex
.client_site
;
1829 *r
->out
.info
= info
;
1837 static WERROR
dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1838 struct netr_DsRGetDCNameEx
*r
)
1840 struct netr_DsRGetDCNameEx2 r2
;
1845 r2
.in
.server_unc
= r
->in
.server_unc
;
1846 r2
.in
.client_account
= NULL
;
1848 r2
.in
.domain_guid
= r
->in
.domain_guid
;
1849 r2
.in
.domain_name
= r
->in
.domain_name
;
1850 r2
.in
.site_name
= r
->in
.site_name
;
1851 r2
.in
.flags
= r
->in
.flags
;
1852 r2
.out
.info
= r
->out
.info
;
1854 werr
= dcesrv_netr_DsRGetDCNameEx2(dce_call
, mem_ctx
, &r2
);
1862 static WERROR
dcesrv_netr_DsRGetDCName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1863 struct netr_DsRGetDCName
*r
)
1865 struct netr_DsRGetDCNameEx2 r2
;
1870 r2
.in
.server_unc
= r
->in
.server_unc
;
1871 r2
.in
.client_account
= NULL
;
1873 r2
.in
.domain_name
= r
->in
.domain_name
;
1874 r2
.in
.domain_guid
= r
->in
.domain_guid
;
1876 r2
.in
.site_name
= NULL
; /* this is correct, we should ignore site GUID */
1877 r2
.in
.flags
= r
->in
.flags
;
1878 r2
.out
.info
= r
->out
.info
;
1880 werr
= dcesrv_netr_DsRGetDCNameEx2(dce_call
, mem_ctx
, &r2
);
1885 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1887 static WERROR
dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1888 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
*r
)
1890 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1895 netr_NetrEnumerateTrustedDomainsEx
1897 static WERROR
dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1898 struct netr_NetrEnumerateTrustedDomainsEx
*r
)
1900 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1905 netr_DsRAddressToSitenamesExW
1907 static WERROR
dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1908 struct netr_DsRAddressToSitenamesExW
*r
)
1910 struct ldb_context
*sam_ctx
;
1911 struct netr_DsRAddressToSitenamesExWCtr
*ctr
;
1912 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1913 sa_family_t sin_family
;
1914 struct sockaddr_in
*addr
;
1916 struct sockaddr_in6
*addr6
;
1917 char addr_str
[INET6_ADDRSTRLEN
];
1919 char addr_str
[INET_ADDRSTRLEN
];
1925 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1926 dce_call
->conn
->auth_state
.session_info
, 0);
1927 if (sam_ctx
== NULL
) {
1928 return WERR_DS_UNAVAILABLE
;
1931 ctr
= talloc(mem_ctx
, struct netr_DsRAddressToSitenamesExWCtr
);
1932 W_ERROR_HAVE_NO_MEMORY(ctr
);
1936 ctr
->count
= r
->in
.count
;
1937 ctr
->sitename
= talloc_array(ctr
, struct lsa_String
, ctr
->count
);
1938 W_ERROR_HAVE_NO_MEMORY(ctr
->sitename
);
1939 ctr
->subnetname
= talloc_array(ctr
, struct lsa_String
, ctr
->count
);
1940 W_ERROR_HAVE_NO_MEMORY(ctr
->subnetname
);
1942 for (i
=0; i
<ctr
->count
; i
++) {
1943 ctr
->sitename
[i
].string
= NULL
;
1944 ctr
->subnetname
[i
].string
= NULL
;
1946 if (r
->in
.addresses
[i
].size
< sizeof(sa_family_t
)) {
1949 /* The first two byte of the buffer are reserved for the
1950 * "sin_family" but for now only the first one is used. */
1951 sin_family
= r
->in
.addresses
[i
].buffer
[0];
1953 switch (sin_family
) {
1955 if (r
->in
.addresses
[i
].size
< sizeof(struct sockaddr_in
)) {
1958 addr
= (struct sockaddr_in
*) r
->in
.addresses
[i
].buffer
;
1959 res
= inet_ntop(AF_INET
, &addr
->sin_addr
,
1960 addr_str
, sizeof(addr_str
));
1964 if (r
->in
.addresses
[i
].size
< sizeof(struct sockaddr_in6
)) {
1967 addr6
= (struct sockaddr_in6
*) r
->in
.addresses
[i
].buffer
;
1968 res
= inet_ntop(AF_INET6
, &addr6
->sin6_addr
,
1969 addr_str
, sizeof(addr_str
));
1980 ctr
->sitename
[i
].string
= samdb_client_site_name(sam_ctx
,
1984 W_ERROR_HAVE_NO_MEMORY(ctr
->sitename
[i
].string
);
1985 ctr
->subnetname
[i
].string
= subnet_name
;
1993 netr_DsRAddressToSitenamesW
1995 static WERROR
dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1996 struct netr_DsRAddressToSitenamesW
*r
)
1998 struct netr_DsRAddressToSitenamesExW r2
;
1999 struct netr_DsRAddressToSitenamesWCtr
*ctr
;
2005 r2
.in
.server_name
= r
->in
.server_name
;
2006 r2
.in
.count
= r
->in
.count
;
2007 r2
.in
.addresses
= r
->in
.addresses
;
2009 r2
.out
.ctr
= talloc(mem_ctx
, struct netr_DsRAddressToSitenamesExWCtr
*);
2010 W_ERROR_HAVE_NO_MEMORY(r2
.out
.ctr
);
2012 ctr
= talloc(mem_ctx
, struct netr_DsRAddressToSitenamesWCtr
);
2013 W_ERROR_HAVE_NO_MEMORY(ctr
);
2017 ctr
->count
= r
->in
.count
;
2018 ctr
->sitename
= talloc_array(ctr
, struct lsa_String
, ctr
->count
);
2019 W_ERROR_HAVE_NO_MEMORY(ctr
->sitename
);
2021 werr
= dcesrv_netr_DsRAddressToSitenamesExW(dce_call
, mem_ctx
, &r2
);
2023 for (i
=0; i
<ctr
->count
; i
++) {
2024 ctr
->sitename
[i
].string
= (*r2
.out
.ctr
)->sitename
[i
].string
;
2032 netr_DsrGetDcSiteCoverageW
2034 static WERROR
dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2035 struct netr_DsrGetDcSiteCoverageW
*r
)
2037 struct ldb_context
*sam_ctx
;
2038 struct DcSitesCtr
*ctr
;
2039 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
2041 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
2042 dce_call
->conn
->auth_state
.session_info
, 0);
2043 if (sam_ctx
== NULL
) {
2044 return WERR_DS_UNAVAILABLE
;
2047 ctr
= talloc(mem_ctx
, struct DcSitesCtr
);
2048 W_ERROR_HAVE_NO_MEMORY(ctr
);
2052 /* For now only return our default site */
2054 ctr
->sites
= talloc_array(ctr
, struct lsa_String
, ctr
->num_sites
);
2055 W_ERROR_HAVE_NO_MEMORY(ctr
->sites
);
2056 ctr
->sites
[0].string
= samdb_server_site_name(sam_ctx
, mem_ctx
);
2057 W_ERROR_HAVE_NO_MEMORY(ctr
->sites
[0].string
);
2063 #define GET_CHECK_STR(dest, mem, msg, attr) \
2066 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
2068 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
2069 "without flatname\n", \
2070 ldb_dn_get_linearized(msg->dn))); \
2073 dest = talloc_strdup(mem, s); \
2074 W_ERROR_HAVE_NO_MEMORY(dest); \
2078 static WERROR
fill_trusted_domains_array(TALLOC_CTX
*mem_ctx
,
2079 struct ldb_context
*sam_ctx
,
2080 struct netr_DomainTrustList
*trusts
,
2081 uint32_t trust_flags
)
2083 struct ldb_dn
*system_dn
;
2084 struct ldb_message
**dom_res
= NULL
;
2085 const char *trust_attrs
[] = { "flatname", "trustPartner",
2086 "securityIdentifier", "trustDirection",
2087 "trustType", "trustAttributes", NULL
};
2092 if (!(trust_flags
& (NETR_TRUST_FLAG_INBOUND
|
2093 NETR_TRUST_FLAG_OUTBOUND
))) {
2094 return WERR_INVALID_FLAGS
;
2097 system_dn
= samdb_search_dn(sam_ctx
, mem_ctx
,
2098 ldb_get_default_basedn(sam_ctx
),
2099 "(&(objectClass=container)(cn=System))");
2101 return WERR_GENERAL_FAILURE
;
2104 ret
= gendb_search(sam_ctx
, mem_ctx
, system_dn
,
2105 &dom_res
, trust_attrs
,
2106 "(objectclass=trustedDomain)");
2108 for (i
= 0; i
< ret
; i
++) {
2109 unsigned int trust_dir
;
2112 trust_dir
= ldb_msg_find_attr_as_uint(dom_res
[i
],
2113 "trustDirection", 0);
2115 if (trust_dir
& LSA_TRUST_DIRECTION_INBOUND
) {
2116 flags
|= NETR_TRUST_FLAG_INBOUND
;
2118 if (trust_dir
& LSA_TRUST_DIRECTION_OUTBOUND
) {
2119 flags
|= NETR_TRUST_FLAG_OUTBOUND
;
2122 if (!(flags
& trust_flags
)) {
2123 /* this trust direction was not requested */
2128 trusts
->array
= talloc_realloc(trusts
, trusts
->array
,
2129 struct netr_DomainTrust
,
2131 W_ERROR_HAVE_NO_MEMORY(trusts
->array
);
2133 GET_CHECK_STR(trusts
->array
[n
].netbios_name
, trusts
,
2134 dom_res
[i
], "flatname");
2135 GET_CHECK_STR(trusts
->array
[n
].dns_name
, trusts
,
2136 dom_res
[i
], "trustPartner");
2138 trusts
->array
[n
].trust_flags
= flags
;
2139 if ((trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) &&
2140 !(flags
& NETR_TRUST_FLAG_TREEROOT
)) {
2141 /* TODO: find if we have parent in the list */
2142 trusts
->array
[n
].parent_index
= 0;
2145 trusts
->array
[n
].trust_type
=
2146 ldb_msg_find_attr_as_uint(dom_res
[i
],
2148 trusts
->array
[n
].trust_attributes
=
2149 ldb_msg_find_attr_as_uint(dom_res
[i
],
2150 "trustAttributes", 0);
2152 if ((trusts
->array
[n
].trust_type
== NETR_TRUST_TYPE_MIT
) ||
2153 (trusts
->array
[n
].trust_type
== NETR_TRUST_TYPE_DCE
)) {
2154 struct dom_sid zero_sid
;
2155 ZERO_STRUCT(zero_sid
);
2156 trusts
->array
[n
].sid
=
2157 dom_sid_dup(trusts
, &zero_sid
);
2159 trusts
->array
[n
].sid
=
2160 samdb_result_dom_sid(trusts
, dom_res
[i
],
2161 "securityIdentifier");
2163 trusts
->array
[n
].guid
= GUID_zero();
2165 trusts
->count
= n
+ 1;
2168 talloc_free(dom_res
);
2173 netr_DsrEnumerateDomainTrusts
2175 static WERROR
dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state
*dce_call
,
2176 TALLOC_CTX
*mem_ctx
,
2177 struct netr_DsrEnumerateDomainTrusts
*r
)
2179 struct netr_DomainTrustList
*trusts
;
2180 struct ldb_context
*sam_ctx
;
2182 struct ldb_message
**dom_res
;
2183 const char * const dom_attrs
[] = { "objectSid", "objectGUID", NULL
};
2184 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
2185 const char *dnsdomain
= lpcfg_dnsdomain(lp_ctx
);
2189 if (r
->in
.trust_flags
& 0xFFFFFE00) {
2190 return WERR_INVALID_FLAGS
;
2193 /* TODO: turn to hard check once we are sure this is 100% correct */
2194 if (!r
->in
.server_name
) {
2195 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2196 "But received NULL!\n", dnsdomain
));
2198 p
= strchr(r
->in
.server_name
, '.');
2200 DEBUG(3, ("Invalid domain! Expected name in domain "
2201 "[%s]. But received [%s]!\n",
2202 dnsdomain
, r
->in
.server_name
));
2203 p
= r
->in
.server_name
;
2207 if (strcasecmp(p
, dnsdomain
)) {
2208 DEBUG(3, ("Invalid domain! Expected name in domain "
2209 "[%s]. But received [%s]!\n",
2210 dnsdomain
, r
->in
.server_name
));
2214 trusts
= talloc_zero(mem_ctx
, struct netr_DomainTrustList
);
2215 W_ERROR_HAVE_NO_MEMORY(trusts
);
2218 r
->out
.trusts
= trusts
;
2220 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
2221 dce_call
->conn
->auth_state
.session_info
, 0);
2222 if (sam_ctx
== NULL
) {
2223 return WERR_GENERAL_FAILURE
;
2226 if ((r
->in
.trust_flags
& NETR_TRUST_FLAG_INBOUND
) ||
2227 (r
->in
.trust_flags
& NETR_TRUST_FLAG_OUTBOUND
)) {
2229 werr
= fill_trusted_domains_array(mem_ctx
, sam_ctx
,
2230 trusts
, r
->in
.trust_flags
);
2231 W_ERROR_NOT_OK_RETURN(werr
);
2234 /* NOTE: we currently are always the root of the forest */
2235 if (r
->in
.trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) {
2236 uint32_t n
= trusts
->count
;
2238 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, NULL
,
2239 &dom_res
, dom_attrs
);
2241 return WERR_GENERAL_FAILURE
;
2244 trusts
->count
= n
+ 1;
2245 trusts
->array
= talloc_realloc(trusts
, trusts
->array
,
2246 struct netr_DomainTrust
,
2248 W_ERROR_HAVE_NO_MEMORY(trusts
->array
);
2250 trusts
->array
[n
].netbios_name
= lpcfg_workgroup(lp_ctx
);
2251 trusts
->array
[n
].dns_name
= lpcfg_dnsdomain(lp_ctx
);
2252 trusts
->array
[n
].trust_flags
=
2253 NETR_TRUST_FLAG_NATIVE
|
2254 NETR_TRUST_FLAG_TREEROOT
|
2255 NETR_TRUST_FLAG_IN_FOREST
|
2256 NETR_TRUST_FLAG_PRIMARY
;
2257 /* we are always the root domain for now */
2258 trusts
->array
[n
].parent_index
= 0;
2259 trusts
->array
[n
].trust_type
= NETR_TRUST_TYPE_UPLEVEL
;
2260 trusts
->array
[n
].trust_attributes
= 0;
2261 trusts
->array
[n
].sid
= samdb_result_dom_sid(mem_ctx
,
2264 trusts
->array
[n
].guid
= samdb_result_guid(dom_res
[0],
2266 talloc_free(dom_res
);
2274 netr_DsrDeregisterDNSHostRecords
2276 static WERROR
dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2277 struct netr_DsrDeregisterDNSHostRecords
*r
)
2279 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2284 netr_ServerTrustPasswordsGet
2286 static NTSTATUS
dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2287 struct netr_ServerTrustPasswordsGet
*r
)
2289 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2293 static WERROR
fill_forest_trust_array(TALLOC_CTX
*mem_ctx
,
2294 struct ldb_context
*sam_ctx
,
2295 struct loadparm_context
*lp_ctx
,
2296 struct lsa_ForestTrustInformation
*info
)
2298 struct lsa_ForestTrustDomainInfo
*domain_info
;
2299 struct lsa_ForestTrustRecord
*e
;
2300 struct ldb_message
**dom_res
;
2301 const char * const dom_attrs
[] = { "objectSid", NULL
};
2304 /* we need to provide 2 entries:
2305 * 1. the Root Forest name
2306 * 2. the Domain Information
2310 info
->entries
= talloc_array(info
, struct lsa_ForestTrustRecord
*, 2);
2311 W_ERROR_HAVE_NO_MEMORY(info
->entries
);
2313 /* Forest root info */
2314 e
= talloc(info
, struct lsa_ForestTrustRecord
);
2315 W_ERROR_HAVE_NO_MEMORY(e
);
2318 e
->type
= LSA_FOREST_TRUST_TOP_LEVEL_NAME
;
2319 e
->time
= 0; /* so far always 0 in trces. */
2320 e
->forest_trust_data
.top_level_name
.string
= samdb_forest_name(sam_ctx
,
2322 W_ERROR_HAVE_NO_MEMORY(e
->forest_trust_data
.top_level_name
.string
);
2324 info
->entries
[0] = e
;
2327 e
= talloc(info
, struct lsa_ForestTrustRecord
);
2328 W_ERROR_HAVE_NO_MEMORY(e
);
2330 /* get our own domain info */
2331 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, NULL
, &dom_res
, dom_attrs
);
2333 return WERR_GENERAL_FAILURE
;
2336 /* TODO: check if disabled and set flags accordingly */
2338 e
->type
= LSA_FOREST_TRUST_DOMAIN_INFO
;
2339 e
->time
= 0; /* so far always 0 in traces. */
2341 domain_info
= &e
->forest_trust_data
.domain_info
;
2342 domain_info
->domain_sid
= samdb_result_dom_sid(info
, dom_res
[0],
2344 domain_info
->dns_domain_name
.string
= lpcfg_dnsdomain(lp_ctx
);
2345 domain_info
->netbios_domain_name
.string
= lpcfg_workgroup(lp_ctx
);
2347 info
->entries
[1] = e
;
2349 talloc_free(dom_res
);
2355 netr_DsRGetForestTrustInformation
2357 static WERROR
dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state
*dce_call
,
2358 TALLOC_CTX
*mem_ctx
,
2359 struct netr_DsRGetForestTrustInformation
*r
)
2361 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
2362 struct lsa_ForestTrustInformation
*info
, **info_ptr
;
2363 struct ldb_context
*sam_ctx
;
2366 if (r
->in
.flags
& 0xFFFFFFFE) {
2367 return WERR_INVALID_FLAGS
;
2370 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
2371 dce_call
->conn
->auth_state
.session_info
, 0);
2372 if (sam_ctx
== NULL
) {
2373 return WERR_GENERAL_FAILURE
;
2376 if (r
->in
.flags
& DS_GFTI_UPDATE_TDO
) {
2377 if (!samdb_is_pdc(sam_ctx
)) {
2378 return WERR_NERR_NOTPRIMARY
;
2381 if (r
->in
.trusted_domain_name
== NULL
) {
2382 return WERR_INVALID_FLAGS
;
2385 /* TODO: establish an schannel connection with
2386 * r->in.trusted_domain_name and perform a
2387 * netr_GetForestTrustInformation call against it */
2389 /* for now return not implementd */
2390 return WERR_CALL_NOT_IMPLEMENTED
;
2393 /* TODO: check r->in.server_name is our name */
2395 info_ptr
= talloc(mem_ctx
, struct lsa_ForestTrustInformation
*);
2396 W_ERROR_HAVE_NO_MEMORY(info_ptr
);
2398 info
= talloc_zero(info_ptr
, struct lsa_ForestTrustInformation
);
2399 W_ERROR_HAVE_NO_MEMORY(info
);
2401 werr
= fill_forest_trust_array(mem_ctx
, sam_ctx
, lp_ctx
, info
);
2402 W_ERROR_NOT_OK_RETURN(werr
);
2405 r
->out
.forest_trust_info
= info_ptr
;
2412 netr_GetForestTrustInformation
2414 static NTSTATUS
dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state
*dce_call
,
2415 TALLOC_CTX
*mem_ctx
,
2416 struct netr_GetForestTrustInformation
*r
)
2418 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
2419 struct netlogon_creds_CredentialState
*creds
;
2420 struct lsa_ForestTrustInformation
*info
, **info_ptr
;
2421 struct ldb_context
*sam_ctx
;
2425 status
= dcesrv_netr_creds_server_step_check(dce_call
,
2427 r
->in
.computer_name
,
2429 r
->out
.return_authenticator
,
2431 if (!NT_STATUS_IS_OK(status
)) {
2435 if ((creds
->secure_channel_type
!= SEC_CHAN_DNS_DOMAIN
) &&
2436 (creds
->secure_channel_type
!= SEC_CHAN_DOMAIN
)) {
2437 return NT_STATUS_NOT_IMPLEMENTED
;
2440 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
2441 dce_call
->conn
->auth_state
.session_info
, 0);
2442 if (sam_ctx
== NULL
) {
2443 return NT_STATUS_UNSUCCESSFUL
;
2446 /* TODO: check r->in.server_name is our name */
2448 info_ptr
= talloc(mem_ctx
, struct lsa_ForestTrustInformation
*);
2450 return NT_STATUS_NO_MEMORY
;
2452 info
= talloc_zero(info_ptr
, struct lsa_ForestTrustInformation
);
2454 return NT_STATUS_NO_MEMORY
;
2457 werr
= fill_forest_trust_array(mem_ctx
, sam_ctx
, lp_ctx
, info
);
2458 if (!W_ERROR_IS_OK(werr
)) {
2459 return werror_to_ntstatus(werr
);
2463 r
->out
.forest_trust_info
= info_ptr
;
2465 return NT_STATUS_OK
;
2470 netr_ServerGetTrustInfo
2472 static NTSTATUS
dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2473 struct netr_ServerGetTrustInfo
*r
)
2475 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2481 static NTSTATUS
dcesrv_netr_Unused47(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2482 struct netr_Unused47
*r
)
2484 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2488 struct netr_dnsupdate_RODC_state
{
2489 struct dcesrv_call_state
*dce_call
;
2490 struct netr_DsrUpdateReadOnlyServerDnsRecords
*r
;
2491 struct dnsupdate_RODC
*r2
;
2495 called when the forwarded RODC dns update request is finished
2497 static void netr_dnsupdate_RODC_callback(struct tevent_req
*subreq
)
2499 struct netr_dnsupdate_RODC_state
*st
=
2500 tevent_req_callback_data(subreq
,
2501 struct netr_dnsupdate_RODC_state
);
2504 status
= dcerpc_dnsupdate_RODC_r_recv(subreq
, st
->dce_call
);
2505 TALLOC_FREE(subreq
);
2506 if (!NT_STATUS_IS_OK(status
)) {
2507 DEBUG(0,(__location__
": IRPC callback failed %s\n", nt_errstr(status
)));
2508 st
->dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
2511 st
->r
->out
.dns_names
= talloc_steal(st
->dce_call
, st
->r2
->out
.dns_names
);
2513 status
= dcesrv_reply(st
->dce_call
);
2514 if (!NT_STATUS_IS_OK(status
)) {
2515 DEBUG(0,(__location__
": dcesrv_reply() failed - %s\n", nt_errstr(status
)));
2520 netr_DsrUpdateReadOnlyServerDnsRecords
2522 static NTSTATUS
dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state
*dce_call
,
2523 TALLOC_CTX
*mem_ctx
,
2524 struct netr_DsrUpdateReadOnlyServerDnsRecords
*r
)
2526 struct netlogon_creds_CredentialState
*creds
;
2528 struct dcerpc_binding_handle
*binding_handle
;
2529 struct netr_dnsupdate_RODC_state
*st
;
2530 struct tevent_req
*subreq
;
2532 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
2534 r
->in
.computer_name
,
2536 r
->out
.return_authenticator
,
2538 NT_STATUS_NOT_OK_RETURN(nt_status
);
2540 if (creds
->secure_channel_type
!= SEC_CHAN_RODC
) {
2541 return NT_STATUS_ACCESS_DENIED
;
2544 st
= talloc_zero(mem_ctx
, struct netr_dnsupdate_RODC_state
);
2545 NT_STATUS_HAVE_NO_MEMORY(st
);
2547 st
->dce_call
= dce_call
;
2549 st
->r2
= talloc_zero(st
, struct dnsupdate_RODC
);
2550 NT_STATUS_HAVE_NO_MEMORY(st
->r2
);
2552 st
->r2
->in
.dom_sid
= creds
->sid
;
2553 st
->r2
->in
.site_name
= r
->in
.site_name
;
2554 st
->r2
->in
.dns_ttl
= r
->in
.dns_ttl
;
2555 st
->r2
->in
.dns_names
= r
->in
.dns_names
;
2556 st
->r2
->out
.dns_names
= r
->out
.dns_names
;
2558 binding_handle
= irpc_binding_handle_by_name(st
, dce_call
->msg_ctx
,
2559 "dnsupdate", &ndr_table_irpc
);
2560 if (binding_handle
== NULL
) {
2561 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2562 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
2563 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2566 /* forward the call */
2567 subreq
= dcerpc_dnsupdate_RODC_r_send(st
, dce_call
->event_ctx
,
2568 binding_handle
, st
->r2
);
2569 NT_STATUS_HAVE_NO_MEMORY(subreq
);
2571 dce_call
->state_flags
|= DCESRV_CALL_STATE_FLAG_ASYNC
;
2573 /* setup the callback */
2574 tevent_req_set_callback(subreq
, netr_dnsupdate_RODC_callback
, st
);
2576 return NT_STATUS_OK
;
2580 /* include the generated boilerplate */
2581 #include "librpc/gen_ndr/ndr_netlogon_s.c"