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
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 "auth/gensec/schannel_state.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "lib/messaging/irpc.h"
35 #include "librpc/gen_ndr/ndr_irpc.h"
37 struct netlogon_server_pipe_state
{
38 struct netr_Credential client_challenge
;
39 struct netr_Credential server_challenge
;
42 static NTSTATUS
dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
43 struct netr_ServerReqChallenge
*r
)
45 struct netlogon_server_pipe_state
*pipe_state
=
46 talloc_get_type(dce_call
->context
->private_data
, struct netlogon_server_pipe_state
);
48 ZERO_STRUCTP(r
->out
.return_credentials
);
50 /* destroyed on pipe shutdown */
53 talloc_free(pipe_state
);
54 dce_call
->context
->private_data
= NULL
;
57 pipe_state
= talloc(dce_call
->context
, struct netlogon_server_pipe_state
);
58 NT_STATUS_HAVE_NO_MEMORY(pipe_state
);
60 pipe_state
->client_challenge
= *r
->in
.credentials
;
62 generate_random_buffer(pipe_state
->server_challenge
.data
,
63 sizeof(pipe_state
->server_challenge
.data
));
65 *r
->out
.return_credentials
= pipe_state
->server_challenge
;
67 dce_call
->context
->private_data
= pipe_state
;
72 static NTSTATUS
dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
73 struct netr_ServerAuthenticate3
*r
)
75 struct netlogon_server_pipe_state
*pipe_state
=
76 talloc_get_type(dce_call
->context
->private_data
, struct netlogon_server_pipe_state
);
77 struct netlogon_creds_CredentialState
*creds
;
78 struct ldb_context
*schannel_ldb
;
79 struct ldb_context
*sam_ctx
;
80 struct samr_Password
*mach_pwd
;
81 uint32_t user_account_control
;
83 struct ldb_message
**msgs
;
85 const char *attrs
[] = {"unicodePwd", "userAccountControl",
88 const char *trust_dom_attrs
[] = {"flatname", NULL
};
89 const char *account_name
;
91 ZERO_STRUCTP(r
->out
.return_credentials
);
95 * According to Microsoft (see bugid #6099)
96 * Windows 7 looks at the negotiate_flags
97 * returned in this structure *even if the
98 * call fails with access denied!
100 *r
->out
.negotiate_flags
= NETLOGON_NEG_ACCOUNT_LOCKOUT
|
101 NETLOGON_NEG_PERSISTENT_SAMREPL
|
102 NETLOGON_NEG_ARCFOUR
|
103 NETLOGON_NEG_PROMOTION_COUNT
|
104 NETLOGON_NEG_CHANGELOG_BDC
|
105 NETLOGON_NEG_FULL_SYNC_REPL
|
106 NETLOGON_NEG_MULTIPLE_SIDS
|
108 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL
|
109 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC
|
110 NETLOGON_NEG_GENERIC_PASSTHROUGH
|
111 NETLOGON_NEG_CONCURRENT_RPC
|
112 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL
|
113 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL
|
114 NETLOGON_NEG_STRONG_KEYS
|
115 NETLOGON_NEG_TRANSITIVE_TRUSTS
|
116 NETLOGON_NEG_DNS_DOMAIN_TRUSTS
|
117 NETLOGON_NEG_PASSWORD_SET2
|
118 NETLOGON_NEG_GETDOMAININFO
|
119 NETLOGON_NEG_CROSS_FOREST_TRUSTS
|
120 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
|
121 NETLOGON_NEG_RODC_PASSTHROUGH
|
122 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS
|
123 NETLOGON_NEG_AUTHENTICATED_RPC
;
126 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
127 return NT_STATUS_ACCESS_DENIED
;
130 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
,
131 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
));
132 if (sam_ctx
== NULL
) {
133 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
136 if (r
->in
.secure_channel_type
== SEC_CHAN_DNS_DOMAIN
) {
137 char *encoded_account
= ldb_binary_encode_string(mem_ctx
, r
->in
.account_name
);
138 const char *flatname
;
139 if (!encoded_account
) {
140 return NT_STATUS_NO_MEMORY
;
143 /* Kill the trailing dot */
144 if (encoded_account
[strlen(encoded_account
)-1] == '.') {
145 encoded_account
[strlen(encoded_account
)-1] = '\0';
148 /* pull the user attributes */
149 num_records
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &msgs
,
151 "(&(trustPartner=%s)(objectclass=trustedDomain))",
154 if (num_records
== 0) {
155 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
157 return NT_STATUS_ACCESS_DENIED
;
160 if (num_records
> 1) {
161 DEBUG(0,("Found %d records matching user [%s]\n", num_records
, r
->in
.account_name
));
162 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
165 flatname
= ldb_msg_find_attr_as_string(msgs
[0], "flatname", NULL
);
167 /* No flatname for this trust - we can't proceed */
168 return NT_STATUS_ACCESS_DENIED
;
170 account_name
= talloc_asprintf(mem_ctx
, "%s$", flatname
);
173 return NT_STATUS_NO_MEMORY
;
177 account_name
= r
->in
.account_name
;
180 /* pull the user attributes */
181 num_records
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &msgs
, attrs
,
182 "(&(sAMAccountName=%s)(objectclass=user))",
183 ldb_binary_encode_string(mem_ctx
, account_name
));
185 if (num_records
== 0) {
186 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
187 r
->in
.account_name
));
188 return NT_STATUS_ACCESS_DENIED
;
191 if (num_records
> 1) {
192 DEBUG(0,("Found %d records matching user [%s]\n", num_records
, r
->in
.account_name
));
193 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
196 user_account_control
= ldb_msg_find_attr_as_uint(msgs
[0], "userAccountControl", 0);
198 if (user_account_control
& UF_ACCOUNTDISABLE
) {
199 DEBUG(1, ("Account [%s] is disabled\n", r
->in
.account_name
));
200 return NT_STATUS_ACCESS_DENIED
;
203 if (r
->in
.secure_channel_type
== SEC_CHAN_WKSTA
) {
204 if (!(user_account_control
& UF_WORKSTATION_TRUST_ACCOUNT
)) {
205 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control
));
206 return NT_STATUS_ACCESS_DENIED
;
208 } else if (r
->in
.secure_channel_type
== SEC_CHAN_DOMAIN
||
209 r
->in
.secure_channel_type
== SEC_CHAN_DNS_DOMAIN
) {
210 if (!(user_account_control
& UF_INTERDOMAIN_TRUST_ACCOUNT
)) {
211 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control
));
213 return NT_STATUS_ACCESS_DENIED
;
215 } else if (r
->in
.secure_channel_type
== SEC_CHAN_BDC
) {
216 if (!(user_account_control
& UF_SERVER_TRUST_ACCOUNT
)) {
217 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control
));
218 return NT_STATUS_ACCESS_DENIED
;
221 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
222 r
->in
.secure_channel_type
));
223 return NT_STATUS_ACCESS_DENIED
;
226 *r
->out
.rid
= samdb_result_rid_from_sid(mem_ctx
, msgs
[0],
229 mach_pwd
= samdb_result_hash(mem_ctx
, msgs
[0], "unicodePwd");
230 if (mach_pwd
== NULL
) {
231 return NT_STATUS_ACCESS_DENIED
;
234 creds
= netlogon_creds_server_init(mem_ctx
,
237 r
->in
.secure_channel_type
,
238 &pipe_state
->client_challenge
,
239 &pipe_state
->server_challenge
,
242 r
->out
.return_credentials
,
243 *r
->in
.negotiate_flags
);
246 return NT_STATUS_ACCESS_DENIED
;
249 creds
->sid
= samdb_result_dom_sid(creds
, msgs
[0], "objectSid");
251 schannel_ldb
= schannel_db_connect(mem_ctx
, dce_call
->event_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
);
253 return NT_STATUS_ACCESS_DENIED
;
256 nt_status
= schannel_store_session_key_ldb(schannel_ldb
, mem_ctx
, creds
);
257 talloc_unlink(mem_ctx
, schannel_ldb
);
262 static NTSTATUS
dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
263 struct netr_ServerAuthenticate
*r
)
265 struct netr_ServerAuthenticate3 a
;
268 * negotiate_flags is used as an [in] parameter
269 * so it need to be initialised.
271 * (I think ... = 0; seems wrong here --metze)
273 uint32_t negotiate_flags_in
= 0;
274 uint32_t negotiate_flags_out
= 0;
276 a
.in
.server_name
= r
->in
.server_name
;
277 a
.in
.account_name
= r
->in
.account_name
;
278 a
.in
.secure_channel_type
= r
->in
.secure_channel_type
;
279 a
.in
.computer_name
= r
->in
.computer_name
;
280 a
.in
.credentials
= r
->in
.credentials
;
281 a
.in
.negotiate_flags
= &negotiate_flags_in
;
283 a
.out
.return_credentials
= r
->out
.return_credentials
;
285 a
.out
.negotiate_flags
= &negotiate_flags_out
;
287 return dcesrv_netr_ServerAuthenticate3(dce_call
, mem_ctx
, &a
);
290 static NTSTATUS
dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
291 struct netr_ServerAuthenticate2
*r
)
293 struct netr_ServerAuthenticate3 r3
;
296 r3
.in
.server_name
= r
->in
.server_name
;
297 r3
.in
.account_name
= r
->in
.account_name
;
298 r3
.in
.secure_channel_type
= r
->in
.secure_channel_type
;
299 r3
.in
.computer_name
= r
->in
.computer_name
;
300 r3
.in
.credentials
= r
->in
.credentials
;
301 r3
.out
.return_credentials
= r
->out
.return_credentials
;
302 r3
.in
.negotiate_flags
= r
->in
.negotiate_flags
;
303 r3
.out
.negotiate_flags
= r
->out
.negotiate_flags
;
306 return dcesrv_netr_ServerAuthenticate3(dce_call
, mem_ctx
, &r3
);
310 Validate an incoming authenticator against the credentials for the remote machine.
312 The credentials are (re)read and from the schannel database, and
313 written back after the caclulations are performed.
315 The creds_out parameter (if not NULL) returns the credentials, if
316 the caller needs some of that information.
319 static NTSTATUS
dcesrv_netr_creds_server_step_check(struct dcesrv_call_state
*dce_call
,
321 const char *computer_name
,
322 struct netr_Authenticator
*received_authenticator
,
323 struct netr_Authenticator
*return_authenticator
,
324 struct netlogon_creds_CredentialState
**creds_out
)
327 struct ldb_context
*ldb
;
328 bool schannel_global_required
= false; /* Should be lp_schannel_server() == true */
329 bool schannel_in_use
= dce_call
->conn
->auth_state
.auth_info
330 && dce_call
->conn
->auth_state
.auth_info
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
331 && (dce_call
->conn
->auth_state
.auth_info
->auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
332 || dce_call
->conn
->auth_state
.auth_info
->auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
);
334 ldb
= schannel_db_connect(mem_ctx
, dce_call
->event_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
);
336 return NT_STATUS_ACCESS_DENIED
;
338 nt_status
= schannel_creds_server_step_check_ldb(ldb
, mem_ctx
,
340 schannel_global_required
,
342 received_authenticator
,
343 return_authenticator
, creds_out
);
344 talloc_unlink(mem_ctx
, ldb
);
349 Change the machine account password for the currently connected
350 client. Supplies only the NT#.
353 static NTSTATUS
dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
354 struct netr_ServerPasswordSet
*r
)
356 struct netlogon_creds_CredentialState
*creds
;
357 struct ldb_context
*sam_ctx
;
360 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
363 r
->in
.credential
, r
->out
.return_authenticator
,
365 NT_STATUS_NOT_OK_RETURN(nt_status
);
367 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
));
368 if (sam_ctx
== NULL
) {
369 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
372 netlogon_creds_des_decrypt(creds
, r
->in
.new_password
);
374 /* Using the sid for the account as the key, set the password */
375 nt_status
= samdb_set_password_sid(sam_ctx
, mem_ctx
,
377 NULL
, /* Don't have plaintext */
378 NULL
, r
->in
.new_password
,
379 true, /* Password change */
385 Change the machine account password for the currently connected
386 client. Supplies new plaintext.
388 static NTSTATUS
dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
389 struct netr_ServerPasswordSet2
*r
)
391 struct netlogon_creds_CredentialState
*creds
;
392 struct ldb_context
*sam_ctx
;
394 DATA_BLOB new_password
;
396 struct samr_CryptPassword password_buf
;
398 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
401 r
->in
.credential
, r
->out
.return_authenticator
,
403 NT_STATUS_NOT_OK_RETURN(nt_status
);
405 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
));
406 if (sam_ctx
== NULL
) {
407 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
410 memcpy(password_buf
.data
, r
->in
.new_password
->data
, 512);
411 SIVAL(password_buf
.data
, 512, r
->in
.new_password
->length
);
412 netlogon_creds_arcfour_crypt(creds
, password_buf
.data
, 516);
414 if (!extract_pw_from_buffer(mem_ctx
, password_buf
.data
, &new_password
)) {
415 DEBUG(3,("samr: failed to decode password buffer\n"));
416 return NT_STATUS_WRONG_PASSWORD
;
419 /* Using the sid for the account as the key, set the password */
420 nt_status
= samdb_set_password_sid(sam_ctx
, mem_ctx
,
422 &new_password
, /* we have plaintext */
424 true, /* Password change */
433 static WERROR
dcesrv_netr_LogonUasLogon(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
434 struct netr_LogonUasLogon
*r
)
436 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
443 static WERROR
dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
444 struct netr_LogonUasLogoff
*r
)
446 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
451 netr_LogonSamLogon_base
453 This version of the function allows other wrappers to say 'do not check the credentials'
455 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
457 static NTSTATUS
dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
458 struct netr_LogonSamLogonEx
*r
, struct netlogon_creds_CredentialState
*creds
)
460 struct auth_context
*auth_context
;
461 struct auth_usersupplied_info
*user_info
;
462 struct auth_serversupplied_info
*server_info
;
464 static const char zeros
[16];
465 struct netr_SamBaseInfo
*sam
;
466 struct netr_SamInfo2
*sam2
;
467 struct netr_SamInfo3
*sam3
;
468 struct netr_SamInfo6
*sam6
;
470 user_info
= talloc(mem_ctx
, struct auth_usersupplied_info
);
471 NT_STATUS_HAVE_NO_MEMORY(user_info
);
473 user_info
->flags
= 0;
474 user_info
->mapped_state
= false;
475 user_info
->remote_host
= NULL
;
477 switch (r
->in
.logon_level
) {
478 case NetlogonInteractiveInformation
:
479 case NetlogonServiceInformation
:
480 case NetlogonInteractiveTransitiveInformation
:
481 case NetlogonServiceTransitiveInformation
:
482 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
483 netlogon_creds_arcfour_crypt(creds
,
484 r
->in
.logon
->password
->lmpassword
.hash
,
485 sizeof(r
->in
.logon
->password
->lmpassword
.hash
));
486 netlogon_creds_arcfour_crypt(creds
,
487 r
->in
.logon
->password
->ntpassword
.hash
,
488 sizeof(r
->in
.logon
->password
->ntpassword
.hash
));
490 netlogon_creds_des_decrypt(creds
, &r
->in
.logon
->password
->lmpassword
);
491 netlogon_creds_des_decrypt(creds
, &r
->in
.logon
->password
->ntpassword
);
494 /* TODO: we need to deny anonymous access here */
495 nt_status
= auth_context_create(mem_ctx
,
496 dce_call
->event_ctx
, dce_call
->msg_ctx
,
497 dce_call
->conn
->dce_ctx
->lp_ctx
,
499 NT_STATUS_NOT_OK_RETURN(nt_status
);
501 user_info
->logon_parameters
= r
->in
.logon
->password
->identity_info
.parameter_control
;
502 user_info
->client
.account_name
= r
->in
.logon
->password
->identity_info
.account_name
.string
;
503 user_info
->client
.domain_name
= r
->in
.logon
->password
->identity_info
.domain_name
.string
;
504 user_info
->workstation_name
= r
->in
.logon
->password
->identity_info
.workstation
.string
;
506 user_info
->flags
|= USER_INFO_INTERACTIVE_LOGON
;
507 user_info
->password_state
= AUTH_PASSWORD_HASH
;
509 user_info
->password
.hash
.lanman
= talloc(user_info
, struct samr_Password
);
510 NT_STATUS_HAVE_NO_MEMORY(user_info
->password
.hash
.lanman
);
511 *user_info
->password
.hash
.lanman
= r
->in
.logon
->password
->lmpassword
;
513 user_info
->password
.hash
.nt
= talloc(user_info
, struct samr_Password
);
514 NT_STATUS_HAVE_NO_MEMORY(user_info
->password
.hash
.nt
);
515 *user_info
->password
.hash
.nt
= r
->in
.logon
->password
->ntpassword
;
518 case NetlogonNetworkInformation
:
519 case NetlogonNetworkTransitiveInformation
:
521 /* TODO: we need to deny anonymous access here */
522 nt_status
= auth_context_create(mem_ctx
,
523 dce_call
->event_ctx
, dce_call
->msg_ctx
,
524 dce_call
->conn
->dce_ctx
->lp_ctx
,
526 NT_STATUS_NOT_OK_RETURN(nt_status
);
528 nt_status
= auth_context_set_challenge(auth_context
, r
->in
.logon
->network
->challenge
, "netr_LogonSamLogonWithFlags");
529 NT_STATUS_NOT_OK_RETURN(nt_status
);
531 user_info
->logon_parameters
= r
->in
.logon
->network
->identity_info
.parameter_control
;
532 user_info
->client
.account_name
= r
->in
.logon
->network
->identity_info
.account_name
.string
;
533 user_info
->client
.domain_name
= r
->in
.logon
->network
->identity_info
.domain_name
.string
;
534 user_info
->workstation_name
= r
->in
.logon
->network
->identity_info
.workstation
.string
;
536 user_info
->password_state
= AUTH_PASSWORD_RESPONSE
;
537 user_info
->password
.response
.lanman
= data_blob_talloc(mem_ctx
, r
->in
.logon
->network
->lm
.data
, r
->in
.logon
->network
->lm
.length
);
538 user_info
->password
.response
.nt
= data_blob_talloc(mem_ctx
, r
->in
.logon
->network
->nt
.data
, r
->in
.logon
->network
->nt
.length
);
543 case NetlogonGenericInformation
:
545 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
546 netlogon_creds_arcfour_crypt(creds
,
547 r
->in
.logon
->generic
->data
, r
->in
.logon
->generic
->length
);
549 /* Using DES to verify kerberos tickets makes no sense */
550 return NT_STATUS_INVALID_PARAMETER
;
553 if (strcmp(r
->in
.logon
->generic
->package_name
.string
, "Kerberos") == 0) {
555 struct server_id
*kdc
;
556 struct kdc_check_generic_kerberos check
;
557 struct netr_GenericInfo2
*generic
= talloc_zero(mem_ctx
, struct netr_GenericInfo2
);
558 NT_STATUS_HAVE_NO_MEMORY(generic
);
559 *r
->out
.authoritative
= 1;
561 /* TODO: Describe and deal with these flags */
564 r
->out
.validation
->generic
= generic
;
566 kdc
= irpc_servers_byname(dce_call
->msg_ctx
, mem_ctx
, "kdc_server");
567 if ((kdc
== NULL
) || (kdc
[0].id
== 0)) {
568 return NT_STATUS_NO_LOGON_SERVERS
;
571 check
.in
.generic_request
=
572 data_blob_const(r
->in
.logon
->generic
->data
,
573 r
->in
.logon
->generic
->length
);
575 status
= irpc_call(dce_call
->msg_ctx
, kdc
[0],
576 &ndr_table_irpc
, NDR_KDC_CHECK_GENERIC_KERBEROS
,
578 if (!NT_STATUS_IS_OK(status
)) {
581 generic
->length
= check
.out
.generic_reply
.length
;
582 generic
->data
= check
.out
.generic_reply
.data
;
586 /* Until we get an implemetnation of these other packages */
587 return NT_STATUS_INVALID_PARAMETER
;
590 return NT_STATUS_INVALID_PARAMETER
;
593 nt_status
= auth_check_password(auth_context
, mem_ctx
, user_info
, &server_info
);
594 NT_STATUS_NOT_OK_RETURN(nt_status
);
596 nt_status
= auth_convert_server_info_sambaseinfo(mem_ctx
, server_info
, &sam
);
597 NT_STATUS_NOT_OK_RETURN(nt_status
);
599 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
600 /* It appears that level 6 is not individually encrypted */
601 if ((r
->in
.validation_level
!= 6) &&
602 memcmp(sam
->key
.key
, zeros
, sizeof(sam
->key
.key
)) != 0) {
603 /* This key is sent unencrypted without the ARCFOUR flag set */
604 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
605 netlogon_creds_arcfour_crypt(creds
,
607 sizeof(sam
->key
.key
));
611 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
612 /* It appears that level 6 is not individually encrypted */
613 if ((r
->in
.validation_level
!= 6) &&
614 memcmp(sam
->LMSessKey
.key
, zeros
, sizeof(sam
->LMSessKey
.key
)) != 0) {
615 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
616 netlogon_creds_arcfour_crypt(creds
,
618 sizeof(sam
->LMSessKey
.key
));
620 netlogon_creds_des_encrypt_LMKey(creds
,
625 switch (r
->in
.validation_level
) {
627 sam2
= talloc_zero(mem_ctx
, struct netr_SamInfo2
);
628 NT_STATUS_HAVE_NO_MEMORY(sam2
);
630 r
->out
.validation
->sam2
= sam2
;
634 sam3
= talloc_zero(mem_ctx
, struct netr_SamInfo3
);
635 NT_STATUS_HAVE_NO_MEMORY(sam3
);
637 r
->out
.validation
->sam3
= sam3
;
641 sam6
= talloc_zero(mem_ctx
, struct netr_SamInfo6
);
642 NT_STATUS_HAVE_NO_MEMORY(sam6
);
644 sam6
->forest
.string
= lp_dnsdomain(dce_call
->conn
->dce_ctx
->lp_ctx
);
645 sam6
->principle
.string
= talloc_asprintf(mem_ctx
, "%s@%s",
646 sam
->account_name
.string
, sam6
->forest
.string
);
647 NT_STATUS_HAVE_NO_MEMORY(sam6
->principle
.string
);
648 r
->out
.validation
->sam6
= sam6
;
655 *r
->out
.authoritative
= 1;
657 /* TODO: Describe and deal with these flags */
663 static NTSTATUS
dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
664 struct netr_LogonSamLogonEx
*r
)
667 struct netlogon_creds_CredentialState
*creds
;
668 struct ldb_context
*ldb
= schannel_db_connect(mem_ctx
, dce_call
->event_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
);
670 return NT_STATUS_ACCESS_DENIED
;
673 nt_status
= schannel_fetch_session_key_ldb(ldb
, mem_ctx
, r
->in
.computer_name
, &creds
);
674 if (!NT_STATUS_IS_OK(nt_status
)) {
678 if (!dce_call
->conn
->auth_state
.auth_info
||
679 dce_call
->conn
->auth_state
.auth_info
->auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
680 return NT_STATUS_ACCESS_DENIED
;
682 return dcesrv_netr_LogonSamLogon_base(dce_call
, mem_ctx
, r
, creds
);
686 netr_LogonSamLogonWithFlags
689 static NTSTATUS
dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
690 struct netr_LogonSamLogonWithFlags
*r
)
693 struct netlogon_creds_CredentialState
*creds
;
694 struct netr_LogonSamLogonEx r2
;
696 struct netr_Authenticator
*return_authenticator
;
698 return_authenticator
= talloc(mem_ctx
, struct netr_Authenticator
);
699 NT_STATUS_HAVE_NO_MEMORY(return_authenticator
);
701 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
704 r
->in
.credential
, return_authenticator
,
706 NT_STATUS_NOT_OK_RETURN(nt_status
);
710 r2
.in
.server_name
= r
->in
.server_name
;
711 r2
.in
.computer_name
= r
->in
.computer_name
;
712 r2
.in
.logon_level
= r
->in
.logon_level
;
713 r2
.in
.logon
= r
->in
.logon
;
714 r2
.in
.validation_level
= r
->in
.validation_level
;
715 r2
.in
.flags
= r
->in
.flags
;
716 r2
.out
.validation
= r
->out
.validation
;
717 r2
.out
.authoritative
= r
->out
.authoritative
;
718 r2
.out
.flags
= r
->out
.flags
;
720 nt_status
= dcesrv_netr_LogonSamLogon_base(dce_call
, mem_ctx
, &r2
, creds
);
722 r
->out
.return_authenticator
= return_authenticator
;
730 static NTSTATUS
dcesrv_netr_LogonSamLogon(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
731 struct netr_LogonSamLogon
*r
)
733 struct netr_LogonSamLogonWithFlags r2
;
739 r2
.in
.server_name
= r
->in
.server_name
;
740 r2
.in
.computer_name
= r
->in
.computer_name
;
741 r2
.in
.credential
= r
->in
.credential
;
742 r2
.in
.return_authenticator
= r
->in
.return_authenticator
;
743 r2
.in
.logon_level
= r
->in
.logon_level
;
744 r2
.in
.logon
= r
->in
.logon
;
745 r2
.in
.validation_level
= r
->in
.validation_level
;
746 r2
.in
.flags
= &flags
;
747 r2
.out
.validation
= r
->out
.validation
;
748 r2
.out
.authoritative
= r
->out
.authoritative
;
749 r2
.out
.flags
= &flags
;
751 status
= dcesrv_netr_LogonSamLogonWithFlags(dce_call
, mem_ctx
, &r2
);
753 r
->out
.return_authenticator
= r2
.out
.return_authenticator
;
762 static NTSTATUS
dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
763 struct netr_LogonSamLogoff
*r
)
765 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
773 static NTSTATUS
dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
774 struct netr_DatabaseDeltas
*r
)
776 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
783 static NTSTATUS
dcesrv_netr_DatabaseSync2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
784 struct netr_DatabaseSync2
*r
)
786 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
787 return NT_STATUS_NOT_IMPLEMENTED
;
794 static NTSTATUS
dcesrv_netr_DatabaseSync(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
795 struct netr_DatabaseSync
*r
)
797 struct netr_DatabaseSync2 r2
;
802 r2
.in
.logon_server
= r
->in
.logon_server
;
803 r2
.in
.computername
= r
->in
.computername
;
804 r2
.in
.credential
= r
->in
.credential
;
805 r2
.in
.database_id
= r
->in
.database_id
;
806 r2
.in
.restart_state
= SYNCSTATE_NORMAL_STATE
;
807 r2
.in
.sync_context
= r
->in
.sync_context
;
808 r2
.out
.sync_context
= r
->out
.sync_context
;
809 r2
.out
.delta_enum_array
= r
->out
.delta_enum_array
;
810 r2
.in
.preferredmaximumlength
= r
->in
.preferredmaximumlength
;
812 status
= dcesrv_netr_DatabaseSync2(dce_call
, mem_ctx
, &r2
);
821 static NTSTATUS
dcesrv_netr_AccountDeltas(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
822 struct netr_AccountDeltas
*r
)
824 /* w2k3 returns "NOT IMPLEMENTED" for this call */
825 return NT_STATUS_NOT_IMPLEMENTED
;
832 static NTSTATUS
dcesrv_netr_AccountSync(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
833 struct netr_AccountSync
*r
)
835 /* w2k3 returns "NOT IMPLEMENTED" for this call */
836 return NT_STATUS_NOT_IMPLEMENTED
;
843 static WERROR
dcesrv_netr_GetDcName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
844 struct netr_GetDcName
*r
)
846 const char * const attrs
[] = { NULL
};
847 struct ldb_context
*sam_ctx
;
848 struct ldb_message
**res
;
849 struct ldb_dn
*domain_dn
;
853 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
854 dce_call
->conn
->dce_ctx
->lp_ctx
,
855 dce_call
->conn
->auth_state
.session_info
);
856 if (sam_ctx
== NULL
) {
857 return WERR_DS_UNAVAILABLE
;
860 domain_dn
= samdb_domain_to_dn(sam_ctx
, mem_ctx
,
862 if (domain_dn
== NULL
) {
863 return WERR_DS_UNAVAILABLE
;
866 ret
= gendb_search_dn(sam_ctx
, mem_ctx
,
867 domain_dn
, &res
, attrs
);
869 return WERR_NO_SUCH_DOMAIN
;
872 /* TODO: - return real IP address
873 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
875 dcname
= talloc_asprintf(mem_ctx
, "\\\\%s",
876 lp_netbios_name(dce_call
->conn
->dce_ctx
->lp_ctx
));
877 W_ERROR_HAVE_NO_MEMORY(dcname
);
879 *r
->out
.dcname
= dcname
;
887 static WERROR
dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
888 struct netr_LogonControl2Ex
*r
)
890 return WERR_NOT_SUPPORTED
;
897 static WERROR
dcesrv_netr_LogonControl(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
898 struct netr_LogonControl
*r
)
900 struct netr_LogonControl2Ex r2
;
903 if (r
->in
.level
== 0x00000001) {
906 r2
.in
.logon_server
= r
->in
.logon_server
;
907 r2
.in
.function_code
= r
->in
.function_code
;
908 r2
.in
.level
= r
->in
.level
;
910 r2
.out
.query
= r
->out
.query
;
912 werr
= dcesrv_netr_LogonControl2Ex(dce_call
, mem_ctx
, &r2
);
913 } else if (r
->in
.level
== 0x00000002) {
914 werr
= WERR_NOT_SUPPORTED
;
916 werr
= WERR_UNKNOWN_LEVEL
;
926 static WERROR
dcesrv_netr_LogonControl2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
927 struct netr_LogonControl2
*r
)
929 struct netr_LogonControl2Ex r2
;
934 r2
.in
.logon_server
= r
->in
.logon_server
;
935 r2
.in
.function_code
= r
->in
.function_code
;
936 r2
.in
.level
= r
->in
.level
;
937 r2
.in
.data
= r
->in
.data
;
938 r2
.out
.query
= r
->out
.query
;
940 werr
= dcesrv_netr_LogonControl2Ex(dce_call
, mem_ctx
, &r2
);
949 static WERROR
dcesrv_netr_GetAnyDCName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
950 struct netr_GetAnyDCName
*r
)
952 struct netr_GetDcName r2
;
957 r2
.in
.logon_server
= r
->in
.logon_server
;
958 r2
.in
.domainname
= r
->in
.domainname
;
959 r2
.out
.dcname
= r
->out
.dcname
;
961 werr
= dcesrv_netr_GetDcName(dce_call
, mem_ctx
, &r2
);
970 static NTSTATUS
dcesrv_netr_DatabaseRedo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
971 struct netr_DatabaseRedo
*r
)
973 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
978 netr_NetrEnumerateTurstedDomains
980 static WERROR
dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
981 struct netr_NetrEnumerateTrustedDomains
*r
)
983 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
988 netr_LogonGetCapabilities
990 static NTSTATUS
dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
991 struct netr_LogonGetCapabilities
*r
)
993 /* we don't support AES yet */
994 return NT_STATUS_NOT_IMPLEMENTED
;
999 netr_NETRLOGONSETSERVICEBITS
1001 static WERROR
dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1002 struct netr_NETRLOGONSETSERVICEBITS
*r
)
1004 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1009 netr_LogonGetTrustRid
1011 static WERROR
dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1012 struct netr_LogonGetTrustRid
*r
)
1014 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1019 netr_NETRLOGONCOMPUTESERVERDIGEST
1021 static WERROR
dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1022 struct netr_NETRLOGONCOMPUTESERVERDIGEST
*r
)
1024 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1029 netr_NETRLOGONCOMPUTECLIENTDIGEST
1031 static WERROR
dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1032 struct netr_NETRLOGONCOMPUTECLIENTDIGEST
*r
)
1034 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1042 static WERROR
dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1043 struct netr_DsRGetSiteName
*r
)
1045 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1050 fill in a netr_OneDomainInfo from a ldb search result
1052 static NTSTATUS
fill_one_domain_info(TALLOC_CTX
*mem_ctx
,
1053 struct loadparm_context
*lp_ctx
,
1054 struct ldb_context
*sam_ctx
,
1055 struct ldb_message
*res
,
1056 struct netr_OneDomainInfo
*info
,
1057 bool is_local
, bool is_trust_list
)
1061 if (is_trust_list
) {
1062 /* w2k8 only fills this on trusted domains */
1063 info
->trust_extension
.info
= talloc_zero(mem_ctx
, struct netr_trust_extension
);
1064 info
->trust_extension
.length
= 16;
1065 info
->trust_extension
.info
->flags
=
1066 NETR_TRUST_FLAG_TREEROOT
|
1067 NETR_TRUST_FLAG_IN_FOREST
|
1068 NETR_TRUST_FLAG_PRIMARY
|
1069 NETR_TRUST_FLAG_NATIVE
;
1071 info
->trust_extension
.info
->parent_index
= 0; /* should be index into array
1073 info
->trust_extension
.info
->trust_type
= LSA_TRUST_TYPE_UPLEVEL
; /* should be based on ldb search for trusts */
1074 info
->trust_extension
.info
->trust_attributes
= 0; /* TODO: base on ldb search? */
1077 if (is_trust_list
) {
1078 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1079 info
->dns_forestname
.string
= NULL
;
1082 /* TODO: we need a common function for pulling the forest */
1083 info
->dns_forestname
.string
= ldb_dn_canonical_string(info
, ldb_get_root_basedn(sam_ctx
));
1084 if (!info
->dns_forestname
.string
) {
1085 return NT_STATUS_NO_SUCH_DOMAIN
;
1087 p
= strchr(info
->dns_forestname
.string
, '/');
1091 info
->dns_forestname
.string
= talloc_asprintf(mem_ctx
, "%s.", info
->dns_forestname
.string
);
1096 info
->domainname
.string
= lp_sam_name(lp_ctx
);
1097 info
->dns_domainname
.string
= lp_dnsdomain(lp_ctx
);
1098 info
->domain_guid
= samdb_result_guid(res
, "objectGUID");
1099 info
->domain_sid
= samdb_result_dom_sid(mem_ctx
, res
, "objectSid");
1101 info
->domainname
.string
= samdb_result_string(res
, "flatName", NULL
);
1102 info
->dns_domainname
.string
= samdb_result_string(res
, "trustPartner", NULL
);
1103 info
->domain_guid
= samdb_result_guid(res
, "objectGUID");
1104 info
->domain_sid
= samdb_result_dom_sid(mem_ctx
, res
, "securityIdentifier");
1106 if (!is_trust_list
) {
1107 info
->dns_domainname
.string
= talloc_asprintf(mem_ctx
, "%s.", info
->dns_domainname
.string
);
1110 return NT_STATUS_OK
;
1114 netr_LogonGetDomainInfo
1115 this is called as part of the ADS domain logon procedure.
1117 It has an important role in convaying details about the client, such
1118 as Operating System, Version, Service Pack etc.
1120 static NTSTATUS
dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state
*dce_call
,
1121 TALLOC_CTX
*mem_ctx
, struct netr_LogonGetDomainInfo
*r
)
1123 struct netlogon_creds_CredentialState
*creds
;
1124 const char * const attrs
[] = { "objectSid", "objectGUID", "flatName",
1125 "securityIdentifier", "trustPartner", NULL
};
1126 const char * const attrs2
[] = { "dNSHostName",
1127 "msDS-SupportedEncryptionTypes", NULL
};
1128 const char *temp_str
;
1129 const char *old_dns_hostname
;
1130 struct ldb_context
*sam_ctx
;
1131 struct ldb_message
**res1
, **res2
, **res3
, *new_msg
;
1132 struct ldb_dn
*workstation_dn
;
1133 struct netr_DomainInformation
*domain_info
;
1134 struct netr_LsaPolicyInformation
*lsa_policy_info
;
1135 struct netr_OsVersionInfoEx
*os_version
;
1136 uint32_t default_supported_enc_types
= 0xFFFFFFFF;
1137 int ret1
, ret2
, ret3
, i
;
1140 status
= dcesrv_netr_creds_server_step_check(dce_call
,
1142 r
->in
.computer_name
,
1144 r
->out
.return_authenticator
,
1146 if (!NT_STATUS_IS_OK(status
)) {
1147 DEBUG(0,(__location__
" Bad credentials - error\n"));
1149 NT_STATUS_NOT_OK_RETURN(status
);
1151 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
1152 dce_call
->conn
->dce_ctx
->lp_ctx
,
1153 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
));
1154 if (sam_ctx
== NULL
) {
1155 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
1158 switch (r
->in
.level
) {
1159 case 1: /* Domain information */
1161 /* TODO: check NTSTATUS results - and fail also on SAMDB
1162 * errors (needs some testing against Windows Server 2008) */
1165 * Check that the computer name parameter matches as prefix with
1166 * the DNS hostname in the workstation info structure.
1168 temp_str
= strndup(r
->in
.query
->workstation_info
->dns_hostname
,
1169 strcspn(r
->in
.query
->workstation_info
->dns_hostname
,
1171 if (strcasecmp(r
->in
.computer_name
, temp_str
) != 0)
1172 return NT_STATUS_INVALID_PARAMETER
;
1174 workstation_dn
= ldb_dn_new_fmt(mem_ctx
, sam_ctx
, "<SID=%s>",
1175 dom_sid_string(mem_ctx
, creds
->sid
));
1176 NT_STATUS_HAVE_NO_MEMORY(workstation_dn
);
1178 /* Lookup for attributes in workstation object */
1179 ret1
= gendb_search_dn(sam_ctx
, mem_ctx
, workstation_dn
,
1182 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1185 /* Gets the old DNS hostname */
1186 old_dns_hostname
= samdb_result_string(res1
[0], "dNSHostName",
1189 /* Gets host informations and put them in our directory */
1190 new_msg
= ldb_msg_new(mem_ctx
);
1191 NT_STATUS_HAVE_NO_MEMORY(new_msg
);
1193 new_msg
->dn
= workstation_dn
;
1195 /* Deletes old OS version values */
1196 samdb_msg_add_delete(sam_ctx
, mem_ctx
, new_msg
,
1197 "operatingSystemServicePack");
1198 samdb_msg_add_delete(sam_ctx
, mem_ctx
, new_msg
,
1199 "operatingSystemVersion");
1201 if (dsdb_replace(sam_ctx
, new_msg
, 0) != LDB_SUCCESS
) {
1202 DEBUG(3,("Impossible to update samdb: %s\n",
1203 ldb_errstring(sam_ctx
)));
1206 talloc_free(new_msg
);
1208 new_msg
= ldb_msg_new(mem_ctx
);
1209 NT_STATUS_HAVE_NO_MEMORY(new_msg
);
1211 new_msg
->dn
= workstation_dn
;
1213 /* Sets the OS name */
1214 samdb_msg_set_string(sam_ctx
, mem_ctx
, new_msg
,
1216 r
->in
.query
->workstation_info
->os_name
.string
);
1219 * Sets informations from "os_version". On a empty structure
1220 * the values are cleared.
1222 if (r
->in
.query
->workstation_info
->os_version
.os
!= NULL
) {
1223 os_version
= &r
->in
.query
->workstation_info
->os_version
.os
->os
;
1225 samdb_msg_set_string(sam_ctx
, mem_ctx
, new_msg
,
1226 "operatingSystemServicePack",
1227 os_version
->CSDVersion
);
1229 samdb_msg_set_string(sam_ctx
, mem_ctx
, new_msg
,
1230 "operatingSystemVersion",
1231 talloc_asprintf(mem_ctx
, "%d.%d (%d)",
1232 os_version
->MajorVersion
,
1233 os_version
->MinorVersion
,
1234 os_version
->BuildNumber
1240 * Updates the "dNSHostname" and the "servicePrincipalName"s
1241 * since the client wishes that the server should handle this
1242 * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1243 * See MS-NRPC section 3.5.4.3.9
1245 if ((r
->in
.query
->workstation_info
->workstation_flags
1246 & NETR_WS_FLAG_HANDLES_SPN_UPDATE
) == 0) {
1247 samdb_msg_set_string(sam_ctx
, mem_ctx
, new_msg
,
1249 r
->in
.query
->workstation_info
->dns_hostname
);
1251 samdb_msg_add_string(sam_ctx
, mem_ctx
, new_msg
,
1252 "servicePrincipalName",
1253 talloc_asprintf(mem_ctx
, "HOST/%s",
1254 r
->in
.computer_name
)
1256 samdb_msg_add_string(sam_ctx
, mem_ctx
, new_msg
,
1257 "servicePrincipalName",
1258 talloc_asprintf(mem_ctx
, "HOST/%s",
1259 r
->in
.query
->workstation_info
->dns_hostname
)
1263 if (dsdb_replace(sam_ctx
, new_msg
, 0) != LDB_SUCCESS
) {
1264 DEBUG(3,("Impossible to update samdb: %s\n",
1265 ldb_errstring(sam_ctx
)));
1268 talloc_free(new_msg
);
1270 /* Writes back the domain information */
1272 /* We need to do two searches. The first will pull our primary
1273 domain and the second will pull any trusted domains. Our
1274 primary domain is also a "trusted" domain, so we need to
1275 put the primary domain into the lists of returned trusts as
1277 ret2
= gendb_search_dn(sam_ctx
, mem_ctx
, samdb_base_dn(sam_ctx
),
1280 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1283 ret3
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &res3
, attrs
,
1284 "(objectClass=trustedDomain)");
1286 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1289 domain_info
= talloc(mem_ctx
, struct netr_DomainInformation
);
1290 NT_STATUS_HAVE_NO_MEMORY(domain_info
);
1292 ZERO_STRUCTP(domain_info
);
1294 /* Informations about the local and trusted domains */
1296 status
= fill_one_domain_info(mem_ctx
,
1297 dce_call
->conn
->dce_ctx
->lp_ctx
,
1298 sam_ctx
, res2
[0], &domain_info
->primary_domain
,
1300 NT_STATUS_NOT_OK_RETURN(status
);
1302 domain_info
->trusted_domain_count
= ret3
+ 1;
1303 domain_info
->trusted_domains
= talloc_array(mem_ctx
,
1304 struct netr_OneDomainInfo
,
1305 domain_info
->trusted_domain_count
);
1306 NT_STATUS_HAVE_NO_MEMORY(domain_info
->trusted_domains
);
1308 for (i
=0;i
<ret3
;i
++) {
1309 status
= fill_one_domain_info(mem_ctx
,
1310 dce_call
->conn
->dce_ctx
->lp_ctx
,
1312 &domain_info
->trusted_domains
[i
],
1314 NT_STATUS_NOT_OK_RETURN(status
);
1317 status
= fill_one_domain_info(mem_ctx
,
1318 dce_call
->conn
->dce_ctx
->lp_ctx
, sam_ctx
, res2
[0],
1319 &domain_info
->trusted_domains
[i
], true, true);
1320 NT_STATUS_NOT_OK_RETURN(status
);
1322 /* Sets the supported encryption types */
1323 domain_info
->supported_enc_types
= samdb_result_uint(res1
[0],
1324 "msDS-SupportedEncryptionTypes",
1325 default_supported_enc_types
);
1327 /* Other host domain informations */
1329 lsa_policy_info
= talloc(mem_ctx
,
1330 struct netr_LsaPolicyInformation
);
1331 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info
);
1332 ZERO_STRUCTP(lsa_policy_info
);
1334 domain_info
->lsa_policy
= *lsa_policy_info
;
1336 domain_info
->dns_hostname
.string
= old_dns_hostname
;
1337 domain_info
->workstation_flags
=
1338 r
->in
.query
->workstation_info
->workstation_flags
;
1340 r
->out
.info
->domain_info
= domain_info
;
1342 case 2: /* LSA policy information - not used at the moment */
1343 lsa_policy_info
= talloc(mem_ctx
,
1344 struct netr_LsaPolicyInformation
);
1345 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info
);
1346 ZERO_STRUCTP(lsa_policy_info
);
1348 r
->out
.info
->lsa_policy_info
= lsa_policy_info
;
1351 return NT_STATUS_INVALID_LEVEL
;
1355 return NT_STATUS_OK
;
1361 netr_ServerPasswordGet
1363 static WERROR
dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1364 struct netr_ServerPasswordGet
*r
)
1366 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1371 netr_NETRLOGONSENDTOSAM
1373 static WERROR
dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1374 struct netr_NETRLOGONSENDTOSAM
*r
)
1376 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1381 netr_DsRAddressToSitenamesW
1383 static WERROR
dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1384 struct netr_DsRAddressToSitenamesW
*r
)
1386 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1391 netr_DsRGetDCNameEx2
1393 static WERROR
dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state
*dce_call
,
1394 TALLOC_CTX
*mem_ctx
,
1395 struct netr_DsRGetDCNameEx2
*r
)
1397 const char * const attrs
[] = { "objectGUID", NULL
};
1398 struct ldb_context
*sam_ctx
;
1399 struct ldb_message
**res
;
1400 struct ldb_dn
*domain_dn
;
1402 struct netr_DsRGetDCNameInfo
*info
;
1403 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1405 ZERO_STRUCTP(r
->out
.info
);
1407 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1408 dce_call
->conn
->auth_state
.session_info
);
1409 if (sam_ctx
== NULL
) {
1410 return WERR_DS_UNAVAILABLE
;
1413 /* Windows 7 sends the domain name in the form the user typed, so we
1414 * have to cope with both the short and long form here */
1415 if (r
->in
.domain_name
!= NULL
&&
1416 !lp_is_my_domain_or_realm(lp_ctx
, r
->in
.domain_name
)) {
1417 return WERR_NO_SUCH_DOMAIN
;
1420 domain_dn
= ldb_get_default_basedn(sam_ctx
);
1421 if (domain_dn
== NULL
) {
1422 return WERR_DS_UNAVAILABLE
;
1425 ret
= gendb_search_dn(sam_ctx
, mem_ctx
,
1426 domain_dn
, &res
, attrs
);
1428 return WERR_GENERAL_FAILURE
;
1431 info
= talloc(mem_ctx
, struct netr_DsRGetDCNameInfo
);
1432 W_ERROR_HAVE_NO_MEMORY(info
);
1434 /* TODO: - return real IP address
1435 * - check all r->in.* parameters
1436 * (server_unc is ignored by w2k3!)
1438 info
->dc_unc
= talloc_asprintf(mem_ctx
, "\\\\%s.%s",
1439 lp_netbios_name(lp_ctx
),
1440 lp_dnsdomain(lp_ctx
));
1441 W_ERROR_HAVE_NO_MEMORY(info
->dc_unc
);
1443 info
->dc_address
= talloc_strdup(mem_ctx
, "\\\\0.0.0.0");
1444 W_ERROR_HAVE_NO_MEMORY(info
->dc_address
);
1446 info
->dc_address_type
= DS_ADDRESS_TYPE_INET
;
1447 info
->domain_guid
= samdb_result_guid(res
[0], "objectGUID");
1448 info
->domain_name
= lp_dnsdomain(lp_ctx
);
1449 info
->forest_name
= lp_dnsdomain(lp_ctx
);
1450 info
->dc_flags
= DS_DNS_FOREST_ROOT
|
1453 DS_SERVER_WRITABLE
|
1455 DS_SERVER_TIMESERV
|
1462 info
->dc_site_name
= samdb_server_site_name(sam_ctx
, mem_ctx
);
1463 W_ERROR_HAVE_NO_MEMORY(info
->dc_site_name
);
1465 /* FIXME: Hardcoded site name */
1466 info
->client_site_name
= talloc_strdup(mem_ctx
,
1467 "Default-First-Site-Name");
1468 W_ERROR_HAVE_NO_MEMORY(info
->client_site_name
);
1470 *r
->out
.info
= info
;
1478 static WERROR
dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1479 struct netr_DsRGetDCNameEx
*r
)
1481 struct netr_DsRGetDCNameEx2 r2
;
1486 r2
.in
.server_unc
= r
->in
.server_unc
;
1487 r2
.in
.client_account
= NULL
;
1489 r2
.in
.domain_guid
= r
->in
.domain_guid
;
1490 r2
.in
.domain_name
= r
->in
.domain_name
;
1491 r2
.in
.site_name
= r
->in
.site_name
;
1492 r2
.in
.flags
= r
->in
.flags
;
1493 r2
.out
.info
= r
->out
.info
;
1495 werr
= dcesrv_netr_DsRGetDCNameEx2(dce_call
, mem_ctx
, &r2
);
1503 static WERROR
dcesrv_netr_DsRGetDCName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1504 struct netr_DsRGetDCName
*r
)
1506 struct netr_DsRGetDCNameEx2 r2
;
1511 r2
.in
.server_unc
= r
->in
.server_unc
;
1512 r2
.in
.client_account
= NULL
;
1514 r2
.in
.domain_name
= r
->in
.domain_name
;
1515 r2
.in
.domain_guid
= r
->in
.domain_guid
;
1517 r2
.in
.site_name
= NULL
; /* should fill in from site GUID */
1518 r2
.in
.flags
= r
->in
.flags
;
1519 r2
.out
.info
= r
->out
.info
;
1521 werr
= dcesrv_netr_DsRGetDCNameEx2(dce_call
, mem_ctx
, &r2
);
1526 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1528 static WERROR
dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1529 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
*r
)
1531 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1536 netr_NetrEnumerateTrustedDomainsEx
1538 static WERROR
dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1539 struct netr_NetrEnumerateTrustedDomainsEx
*r
)
1541 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1546 netr_DsRAddressToSitenamesExW
1548 static WERROR
dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1549 struct netr_DsRAddressToSitenamesExW
*r
)
1551 struct netr_DsRAddressToSitenamesExWCtr
*ctr
;
1554 /* we should map the provided IPs to site names, once we have
1557 ctr
= talloc(mem_ctx
, struct netr_DsRAddressToSitenamesExWCtr
);
1558 W_ERROR_HAVE_NO_MEMORY(ctr
);
1562 ctr
->count
= r
->in
.count
;
1563 ctr
->sitename
= talloc_array(ctr
, struct lsa_String
, ctr
->count
);
1564 W_ERROR_HAVE_NO_MEMORY(ctr
->sitename
);
1565 ctr
->subnetname
= talloc_array(ctr
, struct lsa_String
, ctr
->count
);
1566 W_ERROR_HAVE_NO_MEMORY(ctr
->subnetname
);
1568 for (i
=0; i
<ctr
->count
; i
++) {
1569 /* FIXME: Hardcoded site name */
1570 ctr
->sitename
[i
].string
= "Default-First-Site-Name";
1571 ctr
->subnetname
[i
].string
= NULL
;
1579 netr_DsrGetDcSiteCoverageW
1581 static WERROR
dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1582 struct netr_DsrGetDcSiteCoverageW
*r
)
1584 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1588 #define GET_CHECK_STR(dest, mem, msg, attr) \
1591 s = samdb_result_string(msg, attr, NULL); \
1593 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1594 "without flatname\n", \
1595 ldb_dn_get_linearized(msg->dn))); \
1598 dest = talloc_strdup(mem, s); \
1599 W_ERROR_HAVE_NO_MEMORY(dest); \
1603 static WERROR
fill_trusted_domains_array(TALLOC_CTX
*mem_ctx
,
1604 struct ldb_context
*sam_ctx
,
1605 struct netr_DomainTrustList
*trusts
,
1606 uint32_t trust_flags
)
1608 struct ldb_dn
*system_dn
;
1609 struct ldb_message
**dom_res
= NULL
;
1610 const char *trust_attrs
[] = { "flatname", "trustPartner",
1611 "securityIdentifier", "trustDirection",
1612 "trustType", "trustAttributes", NULL
};
1616 if (!(trust_flags
& (NETR_TRUST_FLAG_INBOUND
|
1617 NETR_TRUST_FLAG_OUTBOUND
))) {
1618 return WERR_INVALID_FLAGS
;
1621 system_dn
= samdb_search_dn(sam_ctx
, mem_ctx
,
1622 ldb_get_default_basedn(sam_ctx
),
1623 "(&(objectClass=container)(cn=System))");
1625 return WERR_GENERAL_FAILURE
;
1628 ret
= gendb_search(sam_ctx
, mem_ctx
, system_dn
,
1629 &dom_res
, trust_attrs
,
1630 "(objectclass=trustedDomain)");
1632 for (i
= 0; i
< ret
; i
++) {
1633 unsigned int trust_dir
;
1636 trust_dir
= samdb_result_uint(dom_res
[i
],
1637 "trustDirection", 0);
1639 if (trust_dir
& LSA_TRUST_DIRECTION_INBOUND
) {
1640 flags
|= NETR_TRUST_FLAG_INBOUND
;
1642 if (trust_dir
& LSA_TRUST_DIRECTION_OUTBOUND
) {
1643 flags
|= NETR_TRUST_FLAG_OUTBOUND
;
1646 if (!(flags
& trust_flags
)) {
1647 /* this trust direction was not requested */
1652 trusts
->array
= talloc_realloc(trusts
, trusts
->array
,
1653 struct netr_DomainTrust
,
1655 W_ERROR_HAVE_NO_MEMORY(trusts
->array
);
1657 GET_CHECK_STR(trusts
->array
[n
].netbios_name
, trusts
,
1658 dom_res
[i
], "flatname");
1659 GET_CHECK_STR(trusts
->array
[n
].dns_name
, trusts
,
1660 dom_res
[i
], "trustPartner");
1662 trusts
->array
[n
].trust_flags
= flags
;
1663 if ((trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) &&
1664 !(flags
& NETR_TRUST_FLAG_TREEROOT
)) {
1665 /* TODO: find if we have parent in the list */
1666 trusts
->array
[n
].parent_index
= 0;
1669 trusts
->array
[n
].trust_type
=
1670 samdb_result_uint(dom_res
[i
],
1672 trusts
->array
[n
].trust_attributes
=
1673 samdb_result_uint(dom_res
[i
],
1674 "trustAttributes", 0);
1676 if ((trusts
->array
[n
].trust_type
== NETR_TRUST_TYPE_MIT
) ||
1677 (trusts
->array
[n
].trust_type
== NETR_TRUST_TYPE_DCE
)) {
1678 struct dom_sid zero_sid
;
1679 ZERO_STRUCT(zero_sid
);
1680 trusts
->array
[n
].sid
=
1681 dom_sid_dup(trusts
, &zero_sid
);
1683 trusts
->array
[n
].sid
=
1684 samdb_result_dom_sid(trusts
, dom_res
[i
],
1685 "securityIdentifier");
1687 trusts
->array
[n
].guid
= GUID_zero();
1689 trusts
->count
= n
+ 1;
1692 talloc_free(dom_res
);
1697 netr_DsrEnumerateDomainTrusts
1699 static WERROR
dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state
*dce_call
,
1700 TALLOC_CTX
*mem_ctx
,
1701 struct netr_DsrEnumerateDomainTrusts
*r
)
1703 struct netr_DomainTrustList
*trusts
;
1704 struct ldb_context
*sam_ctx
;
1706 struct ldb_message
**dom_res
;
1707 const char * const dom_attrs
[] = { "objectSid", "objectGUID", NULL
};
1708 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1709 const char *dnsdomain
= lp_dnsdomain(lp_ctx
);
1713 if (r
->in
.trust_flags
& 0xFFFFFE00) {
1714 return WERR_INVALID_FLAGS
;
1717 /* TODO: turn to hard check once we are sure this is 100% correct */
1718 if (!r
->in
.server_name
) {
1719 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1720 "But received NULL!\n", dnsdomain
));
1722 p
= strchr(r
->in
.server_name
, '.');
1724 DEBUG(3, ("Invalid domain! Expected name in domain "
1725 "[%s]. But received [%s]!\n",
1726 dnsdomain
, r
->in
.server_name
));
1727 p
= r
->in
.server_name
;
1731 if (strcasecmp(p
, dnsdomain
)) {
1732 DEBUG(3, ("Invalid domain! Expected name in domain "
1733 "[%s]. But received [%s]!\n",
1734 dnsdomain
, r
->in
.server_name
));
1738 ZERO_STRUCT(r
->out
);
1740 trusts
= talloc_zero(mem_ctx
, struct netr_DomainTrustList
);
1741 W_ERROR_HAVE_NO_MEMORY(trusts
);
1744 r
->out
.trusts
= trusts
;
1746 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1747 dce_call
->conn
->auth_state
.session_info
);
1748 if (sam_ctx
== NULL
) {
1749 return WERR_GENERAL_FAILURE
;
1752 if ((r
->in
.trust_flags
& NETR_TRUST_FLAG_INBOUND
) ||
1753 (r
->in
.trust_flags
& NETR_TRUST_FLAG_OUTBOUND
)) {
1755 werr
= fill_trusted_domains_array(mem_ctx
, sam_ctx
,
1756 trusts
, r
->in
.trust_flags
);
1757 W_ERROR_NOT_OK_RETURN(werr
);
1760 /* NOTE: we currently are always the root of the forest */
1761 if (r
->in
.trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) {
1762 int n
= trusts
->count
;
1764 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, NULL
,
1765 &dom_res
, dom_attrs
);
1767 return WERR_GENERAL_FAILURE
;
1770 trusts
->count
= n
+ 1;
1771 trusts
->array
= talloc_realloc(trusts
, trusts
->array
,
1772 struct netr_DomainTrust
,
1774 W_ERROR_HAVE_NO_MEMORY(trusts
->array
);
1776 trusts
->array
[n
].netbios_name
= lp_workgroup(lp_ctx
);
1777 trusts
->array
[n
].dns_name
= lp_dnsdomain(lp_ctx
);
1778 trusts
->array
[n
].trust_flags
=
1779 NETR_TRUST_FLAG_NATIVE
|
1780 NETR_TRUST_FLAG_TREEROOT
|
1781 NETR_TRUST_FLAG_IN_FOREST
|
1782 NETR_TRUST_FLAG_PRIMARY
;
1783 /* we are always the root domain for now */
1784 trusts
->array
[n
].parent_index
= 0;
1785 trusts
->array
[n
].trust_type
= NETR_TRUST_TYPE_UPLEVEL
;
1786 trusts
->array
[n
].trust_attributes
= 0;
1787 trusts
->array
[n
].sid
= samdb_result_dom_sid(mem_ctx
,
1790 trusts
->array
[n
].guid
= samdb_result_guid(dom_res
[0],
1792 talloc_free(dom_res
);
1800 netr_DsrDeregisterDNSHostRecords
1802 static WERROR
dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1803 struct netr_DsrDeregisterDNSHostRecords
*r
)
1805 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1810 netr_ServerTrustPasswordsGet
1812 static NTSTATUS
dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1813 struct netr_ServerTrustPasswordsGet
*r
)
1815 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1819 static WERROR
fill_forest_trust_array(TALLOC_CTX
*mem_ctx
,
1820 struct ldb_context
*sam_ctx
,
1821 struct loadparm_context
*lp_ctx
,
1822 struct lsa_ForestTrustInformation
*info
)
1824 struct lsa_ForestTrustDomainInfo
*domain_info
;
1825 struct lsa_ForestTrustRecord
*e
;
1826 struct ldb_message
**dom_res
;
1827 const char * const dom_attrs
[] = { "objectSid", NULL
};
1830 /* we need to provide 2 entries:
1831 * 1. the Root Forest name
1832 * 2. the Domain Information
1836 info
->entries
= talloc_array(info
, struct lsa_ForestTrustRecord
*, 2);
1837 W_ERROR_HAVE_NO_MEMORY(info
->entries
);
1839 /* Forest root info */
1840 e
= talloc(info
, struct lsa_ForestTrustRecord
);
1841 W_ERROR_HAVE_NO_MEMORY(e
);
1844 e
->level
= LSA_FOREST_TRUST_TOP_LEVEL_NAME
;
1845 e
->time
= 0; /* so far always 0 in trces. */
1846 e
->forest_trust_data
.top_level_name
.string
= lp_dnsdomain(lp_ctx
);
1848 info
->entries
[0] = e
;
1851 e
= talloc(info
, struct lsa_ForestTrustRecord
);
1852 W_ERROR_HAVE_NO_MEMORY(e
);
1854 /* get our own domain info */
1855 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, NULL
, &dom_res
, dom_attrs
);
1857 return WERR_GENERAL_FAILURE
;
1860 /* TODO: check if disabled and set flags accordingly */
1862 e
->level
= LSA_FOREST_TRUST_DOMAIN_INFO
;
1863 e
->time
= 0; /* so far always 0 in traces. */
1865 domain_info
= &e
->forest_trust_data
.domain_info
;
1866 domain_info
->domain_sid
= samdb_result_dom_sid(info
, dom_res
[0],
1868 domain_info
->dns_domain_name
.string
= lp_dnsdomain(lp_ctx
);
1869 domain_info
->netbios_domain_name
.string
= lp_workgroup(lp_ctx
);
1871 info
->entries
[1] = e
;
1873 talloc_free(dom_res
);
1879 netr_DsRGetForestTrustInformation
1881 static WERROR
dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state
*dce_call
,
1882 TALLOC_CTX
*mem_ctx
,
1883 struct netr_DsRGetForestTrustInformation
*r
)
1885 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1886 struct lsa_ForestTrustInformation
*info
, **info_ptr
;
1887 struct ldb_context
*sam_ctx
;
1890 ZERO_STRUCT(r
->out
);
1892 if (lp_server_role(lp_ctx
) != ROLE_DOMAIN_CONTROLLER
) {
1893 return WERR_CALL_NOT_IMPLEMENTED
;
1896 if (r
->in
.flags
& 0xFFFFFFFE) {
1897 return WERR_INVALID_FLAGS
;
1900 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1901 dce_call
->conn
->auth_state
.session_info
);
1902 if (sam_ctx
== NULL
) {
1903 return WERR_GENERAL_FAILURE
;
1906 if (r
->in
.flags
& DS_GFTI_UPDATE_TDO
) {
1907 if (!samdb_is_pdc(sam_ctx
)) {
1908 return WERR_NERR_NOTPRIMARY
;
1911 if (r
->in
.trusted_domain_name
== NULL
) {
1912 return WERR_INVALID_FLAGS
;
1915 /* TODO: establish an schannel connection with
1916 * r->in.trusted_domain_name and perform a
1917 * netr_GetForestTrustInformation call against it */
1919 /* for now return not implementd */
1920 return WERR_CALL_NOT_IMPLEMENTED
;
1923 /* TODO: check r->in.server_name is our name */
1925 info_ptr
= talloc(mem_ctx
, struct lsa_ForestTrustInformation
*);
1926 W_ERROR_HAVE_NO_MEMORY(info_ptr
);
1928 info
= talloc_zero(info_ptr
, struct lsa_ForestTrustInformation
);
1929 W_ERROR_HAVE_NO_MEMORY(info
);
1931 werr
= fill_forest_trust_array(mem_ctx
, sam_ctx
, lp_ctx
, info
);
1932 W_ERROR_NOT_OK_RETURN(werr
);
1935 r
->out
.forest_trust_info
= info_ptr
;
1942 netr_GetForestTrustInformation
1944 static NTSTATUS
dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state
*dce_call
,
1945 TALLOC_CTX
*mem_ctx
,
1946 struct netr_GetForestTrustInformation
*r
)
1948 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1949 struct netlogon_creds_CredentialState
*creds
;
1950 struct lsa_ForestTrustInformation
*info
, **info_ptr
;
1951 struct ldb_context
*sam_ctx
;
1955 if (lp_server_role(lp_ctx
) != ROLE_DOMAIN_CONTROLLER
) {
1956 return NT_STATUS_NOT_IMPLEMENTED
;
1959 ZERO_STRUCT(r
->out
);
1961 status
= dcesrv_netr_creds_server_step_check(dce_call
,
1963 r
->in
.computer_name
,
1965 r
->out
.return_authenticator
,
1967 if (!NT_STATUS_IS_OK(status
)) {
1971 if ((creds
->secure_channel_type
!= SEC_CHAN_DNS_DOMAIN
) &&
1972 (creds
->secure_channel_type
!= SEC_CHAN_DOMAIN
)) {
1973 return NT_STATUS_NOT_IMPLEMENTED
;
1976 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1977 dce_call
->conn
->auth_state
.session_info
);
1978 if (sam_ctx
== NULL
) {
1979 return NT_STATUS_UNSUCCESSFUL
;
1982 /* TODO: check r->in.server_name is our name */
1984 info_ptr
= talloc(mem_ctx
, struct lsa_ForestTrustInformation
*);
1986 return NT_STATUS_NO_MEMORY
;
1988 info
= talloc_zero(info_ptr
, struct lsa_ForestTrustInformation
);
1990 return NT_STATUS_NO_MEMORY
;
1993 werr
= fill_forest_trust_array(mem_ctx
, sam_ctx
, lp_ctx
, info
);
1994 if (!W_ERROR_IS_OK(werr
)) {
1995 return werror_to_ntstatus(werr
);
1999 r
->out
.forest_trust_info
= info_ptr
;
2001 return NT_STATUS_OK
;
2006 netr_ServerGetTrustInfo
2008 static NTSTATUS
dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2009 struct netr_ServerGetTrustInfo
*r
)
2011 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2015 /* include the generated boilerplate */
2016 #include "librpc/gen_ndr/ndr_netlogon_s.c"