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 "../lib/util/memcache.h"
31 #include "../libcli/auth/schannel.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_c.h"
36 #include "../libcli/ldap/ldap_ndr.h"
37 #include "dsdb/samdb/ldb_modules/util.h"
38 #include "lib/tsocket/tsocket.h"
39 #include "librpc/gen_ndr/ndr_netlogon.h"
40 #include "librpc/gen_ndr/ndr_lsa.h"
41 #include "librpc/gen_ndr/ndr_samr.h"
42 #include "librpc/gen_ndr/ndr_irpc.h"
43 #include "lib/socket/netif.h"
45 static struct memcache
*global_challenge_table
;
47 struct netlogon_server_pipe_state
{
48 struct netr_Credential client_challenge
;
49 struct netr_Credential server_challenge
;
52 static NTSTATUS
dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
53 struct netr_ServerReqChallenge
*r
)
55 struct netlogon_server_pipe_state
*pipe_state
=
56 talloc_get_type(dce_call
->context
->private_data
, struct netlogon_server_pipe_state
);
59 ZERO_STRUCTP(r
->out
.return_credentials
);
61 if (global_challenge_table
== NULL
) {
63 * We maintain a global challenge table
64 * with a fixed size (8k)
66 * This is required for the strange clients
67 * which use different connections for
68 * netr_ServerReqChallenge() and netr_ServerAuthenticate3()
71 global_challenge_table
= memcache_init(talloc_autofree_context(),
73 if (global_challenge_table
== NULL
) {
74 return NT_STATUS_NO_MEMORY
;
78 /* destroyed on pipe shutdown */
81 talloc_free(pipe_state
);
82 dce_call
->context
->private_data
= NULL
;
85 pipe_state
= talloc(dce_call
->context
, struct netlogon_server_pipe_state
);
86 NT_STATUS_HAVE_NO_MEMORY(pipe_state
);
88 pipe_state
->client_challenge
= *r
->in
.credentials
;
90 generate_random_buffer(pipe_state
->server_challenge
.data
,
91 sizeof(pipe_state
->server_challenge
.data
));
93 *r
->out
.return_credentials
= pipe_state
->server_challenge
;
95 dce_call
->context
->private_data
= pipe_state
;
97 key
= data_blob_string_const(r
->in
.computer_name
);
98 val
= data_blob_const(pipe_state
, sizeof(*pipe_state
));
100 memcache_add(global_challenge_table
, SINGLETON_CACHE
, key
, val
);
105 static NTSTATUS
dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
106 struct netr_ServerAuthenticate3
*r
)
108 struct netlogon_server_pipe_state
*pipe_state
=
109 talloc_get_type(dce_call
->context
->private_data
, struct netlogon_server_pipe_state
);
110 DATA_BLOB challenge_key
;
111 bool challenge_valid
= false;
112 struct netlogon_server_pipe_state challenge
;
113 struct netlogon_creds_CredentialState
*creds
;
114 struct ldb_context
*sam_ctx
;
115 struct samr_Password
*curNtHash
= NULL
;
116 struct samr_Password
*prevNtHash
= NULL
;
117 uint32_t user_account_control
;
119 struct ldb_message
**msgs
;
121 const char *attrs
[] = {"unicodePwd", "userAccountControl",
123 const char *account_name
;
124 uint32_t server_flags
= 0;
125 uint32_t negotiate_flags
= 0;
126 bool allow_nt4_crypto
= lpcfg_allow_nt4_crypto(dce_call
->conn
->dce_ctx
->lp_ctx
);
127 bool reject_des_client
= !allow_nt4_crypto
;
128 bool reject_md5_client
= lpcfg_reject_md5_clients(dce_call
->conn
->dce_ctx
->lp_ctx
);
130 ZERO_STRUCTP(r
->out
.return_credentials
);
133 challenge_key
= data_blob_string_const(r
->in
.computer_name
);
134 if (pipe_state
!= NULL
) {
135 dce_call
->context
->private_data
= NULL
;
138 * If we had a challenge remembered on the connection
139 * consider this for usage. This can't be cleanup
142 * This is the default code path for typical clients
143 * which call netr_ServerReqChallenge() and
144 * netr_ServerAuthenticate3() on the same dcerpc connection.
146 challenge
= *pipe_state
;
147 TALLOC_FREE(pipe_state
);
148 challenge_valid
= true;
154 * Fallback and try to get the challenge from
157 * If too many clients are using this code path,
158 * they may destroy their cache entries as the
159 * global_challenge_table memcache has a fixed size.
161 * Note: this handles global_challenge_table == NULL fine
163 ok
= memcache_lookup(global_challenge_table
, SINGLETON_CACHE
,
164 challenge_key
, &val
);
165 if (ok
&& val
.length
== sizeof(challenge
)) {
166 memcpy(&challenge
, val
.data
, sizeof(challenge
));
167 challenge_valid
= true;
169 ZERO_STRUCT(challenge
);
174 * At this point we can cleanup the cache entry,
175 * if we fail the client needs to call netr_ServerReqChallenge
178 * Note: this handles global_challenge_table == NULL
179 * and also a non existing record just fine.
181 memcache_delete(global_challenge_table
,
182 SINGLETON_CACHE
, challenge_key
);
184 server_flags
= NETLOGON_NEG_ACCOUNT_LOCKOUT
|
185 NETLOGON_NEG_PERSISTENT_SAMREPL
|
186 NETLOGON_NEG_ARCFOUR
|
187 NETLOGON_NEG_PROMOTION_COUNT
|
188 NETLOGON_NEG_CHANGELOG_BDC
|
189 NETLOGON_NEG_FULL_SYNC_REPL
|
190 NETLOGON_NEG_MULTIPLE_SIDS
|
192 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL
|
193 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC
|
194 NETLOGON_NEG_GENERIC_PASSTHROUGH
|
195 NETLOGON_NEG_CONCURRENT_RPC
|
196 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL
|
197 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL
|
198 NETLOGON_NEG_STRONG_KEYS
|
199 NETLOGON_NEG_TRANSITIVE_TRUSTS
|
200 NETLOGON_NEG_DNS_DOMAIN_TRUSTS
|
201 NETLOGON_NEG_PASSWORD_SET2
|
202 NETLOGON_NEG_GETDOMAININFO
|
203 NETLOGON_NEG_CROSS_FOREST_TRUSTS
|
204 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION
|
205 NETLOGON_NEG_RODC_PASSTHROUGH
|
206 NETLOGON_NEG_SUPPORTS_AES
|
207 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS
|
208 NETLOGON_NEG_AUTHENTICATED_RPC
;
210 negotiate_flags
= *r
->in
.negotiate_flags
& server_flags
;
212 if (negotiate_flags
& NETLOGON_NEG_STRONG_KEYS
) {
213 reject_des_client
= false;
216 if (negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
217 reject_des_client
= false;
218 reject_md5_client
= false;
221 if (reject_des_client
|| reject_md5_client
) {
223 * Here we match Windows 2012 and return no flags.
225 *r
->out
.negotiate_flags
= 0;
226 return NT_STATUS_DOWNGRADE_DETECTED
;
230 * According to Microsoft (see bugid #6099)
231 * Windows 7 looks at the negotiate_flags
232 * returned in this structure *even if the
233 * call fails with access denied!
235 *r
->out
.negotiate_flags
= negotiate_flags
;
237 switch (r
->in
.secure_channel_type
) {
239 case SEC_CHAN_DNS_DOMAIN
:
240 case SEC_CHAN_DOMAIN
:
245 return NT_STATUS_INVALID_PARAMETER
;
247 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
248 r
->in
.secure_channel_type
));
249 return NT_STATUS_INVALID_PARAMETER
;
252 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, dce_call
->conn
->dce_ctx
->lp_ctx
,
253 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
), 0);
254 if (sam_ctx
== NULL
) {
255 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
258 if (r
->in
.secure_channel_type
== SEC_CHAN_DOMAIN
||
259 r
->in
.secure_channel_type
== SEC_CHAN_DNS_DOMAIN
)
261 struct ldb_message
*tdo_msg
= NULL
;
262 const char * const tdo_attrs
[] = {
268 char *encoded_name
= NULL
;
270 const char *flatname
= NULL
;
272 bool require_trailer
= true;
273 const char *netbios
= NULL
;
274 const char *dns
= NULL
;
276 if (r
->in
.secure_channel_type
== SEC_CHAN_DNS_DOMAIN
) {
278 require_trailer
= false;
281 encoded_name
= ldb_binary_encode_string(mem_ctx
,
283 if (encoded_name
== NULL
) {
284 return NT_STATUS_NO_MEMORY
;
287 len
= strlen(encoded_name
);
289 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
292 if (require_trailer
&& encoded_name
[len
- 1] != trailer
) {
293 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
295 encoded_name
[len
- 1] = '\0';
297 if (r
->in
.secure_channel_type
== SEC_CHAN_DNS_DOMAIN
) {
300 netbios
= encoded_name
;
303 nt_status
= dsdb_trust_search_tdo(sam_ctx
,
305 tdo_attrs
, mem_ctx
, &tdo_msg
);
306 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
307 DEBUG(2, ("Client asked for a trusted domain secure channel, "
308 "but there's no tdo for [%s] => [%s] \n",
309 r
->in
.account_name
, encoded_name
));
310 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
312 if (!NT_STATUS_IS_OK(nt_status
)) {
316 nt_status
= dsdb_trust_get_incoming_passwords(tdo_msg
, mem_ctx
,
319 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_ACCOUNT_DISABLED
)) {
320 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
322 if (!NT_STATUS_IS_OK(nt_status
)) {
326 flatname
= ldb_msg_find_attr_as_string(tdo_msg
, "flatName", NULL
);
327 if (flatname
== NULL
) {
328 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
331 account_name
= talloc_asprintf(mem_ctx
, "%s$", flatname
);
332 if (account_name
== NULL
) {
333 return NT_STATUS_NO_MEMORY
;
336 account_name
= r
->in
.account_name
;
339 /* pull the user attributes */
340 num_records
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &msgs
, attrs
,
341 "(&(sAMAccountName=%s)(objectclass=user))",
342 ldb_binary_encode_string(mem_ctx
, account_name
));
344 if (num_records
== 0) {
345 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
346 r
->in
.account_name
));
347 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
350 if (num_records
> 1) {
351 DEBUG(0,("Found %d records matching user [%s]\n", num_records
, r
->in
.account_name
));
352 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
355 user_account_control
= ldb_msg_find_attr_as_uint(msgs
[0], "userAccountControl", 0);
357 if (user_account_control
& UF_ACCOUNTDISABLE
) {
358 DEBUG(1, ("Account [%s] is disabled\n", r
->in
.account_name
));
359 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
362 if (r
->in
.secure_channel_type
== SEC_CHAN_WKSTA
) {
363 if (!(user_account_control
& UF_WORKSTATION_TRUST_ACCOUNT
)) {
364 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control
));
365 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
367 } else if (r
->in
.secure_channel_type
== SEC_CHAN_DOMAIN
||
368 r
->in
.secure_channel_type
== SEC_CHAN_DNS_DOMAIN
) {
369 if (!(user_account_control
& UF_INTERDOMAIN_TRUST_ACCOUNT
)) {
370 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control
));
372 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
374 } else if (r
->in
.secure_channel_type
== SEC_CHAN_BDC
) {
375 if (!(user_account_control
& UF_SERVER_TRUST_ACCOUNT
)) {
376 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control
));
377 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
379 } else if (r
->in
.secure_channel_type
== SEC_CHAN_RODC
) {
380 if (!(user_account_control
& UF_PARTIAL_SECRETS_ACCOUNT
)) {
381 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control
));
382 return NT_STATUS_NO_TRUST_SAM_ACCOUNT
;
385 /* we should never reach this */
386 return NT_STATUS_INTERNAL_ERROR
;
389 if (!(user_account_control
& UF_INTERDOMAIN_TRUST_ACCOUNT
)) {
390 nt_status
= samdb_result_passwords_no_lockout(mem_ctx
,
391 dce_call
->conn
->dce_ctx
->lp_ctx
,
392 msgs
[0], NULL
, &curNtHash
);
393 if (!NT_STATUS_IS_OK(nt_status
)) {
394 return NT_STATUS_ACCESS_DENIED
;
398 if (curNtHash
== NULL
) {
399 return NT_STATUS_ACCESS_DENIED
;
402 if (!challenge_valid
) {
403 DEBUG(1, ("No challenge requested by client [%s/%s], "
404 "cannot authenticate\n",
406 r
->in
.account_name
));
407 return NT_STATUS_ACCESS_DENIED
;
410 creds
= netlogon_creds_server_init(mem_ctx
,
413 r
->in
.secure_channel_type
,
414 &challenge
.client_challenge
,
415 &challenge
.server_challenge
,
418 r
->out
.return_credentials
,
420 if (creds
== NULL
&& prevNtHash
!= NULL
) {
422 * We fallback to the previous password for domain trusts.
424 * Note that lpcfg_old_password_allowed_period() doesn't
427 creds
= netlogon_creds_server_init(mem_ctx
,
430 r
->in
.secure_channel_type
,
431 &challenge
.client_challenge
,
432 &challenge
.server_challenge
,
435 r
->out
.return_credentials
,
439 return NT_STATUS_ACCESS_DENIED
;
442 creds
->sid
= samdb_result_dom_sid(creds
, msgs
[0], "objectSid");
444 nt_status
= schannel_save_creds_state(mem_ctx
,
445 dce_call
->conn
->dce_ctx
->lp_ctx
,
447 if (!NT_STATUS_IS_OK(nt_status
)) {
448 ZERO_STRUCTP(r
->out
.return_credentials
);
452 *r
->out
.rid
= samdb_result_rid_from_sid(mem_ctx
, msgs
[0],
458 static NTSTATUS
dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
459 struct netr_ServerAuthenticate
*r
)
461 struct netr_ServerAuthenticate3 a
;
464 * negotiate_flags is used as an [in] parameter
465 * so it need to be initialised.
467 * (I think ... = 0; seems wrong here --metze)
469 uint32_t negotiate_flags_in
= 0;
470 uint32_t negotiate_flags_out
= 0;
472 a
.in
.server_name
= r
->in
.server_name
;
473 a
.in
.account_name
= r
->in
.account_name
;
474 a
.in
.secure_channel_type
= r
->in
.secure_channel_type
;
475 a
.in
.computer_name
= r
->in
.computer_name
;
476 a
.in
.credentials
= r
->in
.credentials
;
477 a
.in
.negotiate_flags
= &negotiate_flags_in
;
479 a
.out
.return_credentials
= r
->out
.return_credentials
;
481 a
.out
.negotiate_flags
= &negotiate_flags_out
;
483 return dcesrv_netr_ServerAuthenticate3(dce_call
, mem_ctx
, &a
);
486 static NTSTATUS
dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
487 struct netr_ServerAuthenticate2
*r
)
489 struct netr_ServerAuthenticate3 r3
;
492 r3
.in
.server_name
= r
->in
.server_name
;
493 r3
.in
.account_name
= r
->in
.account_name
;
494 r3
.in
.secure_channel_type
= r
->in
.secure_channel_type
;
495 r3
.in
.computer_name
= r
->in
.computer_name
;
496 r3
.in
.credentials
= r
->in
.credentials
;
497 r3
.out
.return_credentials
= r
->out
.return_credentials
;
498 r3
.in
.negotiate_flags
= r
->in
.negotiate_flags
;
499 r3
.out
.negotiate_flags
= r
->out
.negotiate_flags
;
502 return dcesrv_netr_ServerAuthenticate3(dce_call
, mem_ctx
, &r3
);
506 * NOTE: The following functions are nearly identical to the ones available in
507 * source3/rpc_server/srv_nelog_nt.c
508 * The reason we keep 2 copies is that they use different structures to
509 * represent the auth_info and the decrpc pipes.
513 * If schannel is required for this call test that it actually is available.
515 static NTSTATUS
schannel_check_required(struct dcerpc_auth
*auth_info
,
516 const char *computer_name
,
517 bool integrity
, bool privacy
)
520 if (auth_info
&& auth_info
->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
521 if (!privacy
&& !integrity
) {
525 if ((!privacy
&& integrity
) &&
526 auth_info
->auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
) {
530 if ((privacy
|| integrity
) &&
531 auth_info
->auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
536 /* test didn't pass */
537 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
540 return NT_STATUS_ACCESS_DENIED
;
543 static NTSTATUS
dcesrv_netr_creds_server_step_check(struct dcesrv_call_state
*dce_call
,
545 const char *computer_name
,
546 struct netr_Authenticator
*received_authenticator
,
547 struct netr_Authenticator
*return_authenticator
,
548 struct netlogon_creds_CredentialState
**creds_out
)
551 struct dcerpc_auth
*auth_info
= dce_call
->conn
->auth_state
.auth_info
;
552 bool schannel_global_required
= false; /* Should be lpcfg_schannel_server() == true */
554 if (schannel_global_required
) {
555 nt_status
= schannel_check_required(auth_info
,
558 if (!NT_STATUS_IS_OK(nt_status
)) {
563 nt_status
= schannel_check_creds_state(mem_ctx
,
564 dce_call
->conn
->dce_ctx
->lp_ctx
,
566 received_authenticator
,
567 return_authenticator
,
573 Change the machine account password for the currently connected
574 client. Supplies only the NT#.
577 static NTSTATUS
dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
578 struct netr_ServerPasswordSet
*r
)
580 struct netlogon_creds_CredentialState
*creds
;
581 struct ldb_context
*sam_ctx
;
582 const char * const attrs
[] = { "unicodePwd", NULL
};
583 struct ldb_message
**res
;
584 struct samr_Password
*oldNtHash
;
588 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
591 r
->in
.credential
, r
->out
.return_authenticator
,
593 NT_STATUS_NOT_OK_RETURN(nt_status
);
595 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);
596 if (sam_ctx
== NULL
) {
597 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
600 netlogon_creds_des_decrypt(creds
, r
->in
.new_password
);
602 /* fetch the old password hashes (the NT hash has to exist) */
604 ret
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &res
, attrs
,
605 "(&(objectClass=user)(objectSid=%s))",
606 ldap_encode_ndr_dom_sid(mem_ctx
, creds
->sid
));
608 return NT_STATUS_WRONG_PASSWORD
;
611 nt_status
= samdb_result_passwords_no_lockout(mem_ctx
,
612 dce_call
->conn
->dce_ctx
->lp_ctx
,
613 res
[0], NULL
, &oldNtHash
);
614 if (!NT_STATUS_IS_OK(nt_status
) || !oldNtHash
) {
615 return NT_STATUS_WRONG_PASSWORD
;
618 /* Using the sid for the account as the key, set the password */
619 nt_status
= samdb_set_password_sid(sam_ctx
, mem_ctx
,
621 NULL
, /* Don't have version */
622 NULL
, /* Don't have plaintext */
623 NULL
, r
->in
.new_password
,
624 NULL
, oldNtHash
, /* Password change */
630 Change the machine account password for the currently connected
631 client. Supplies new plaintext.
633 static NTSTATUS
dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
634 struct netr_ServerPasswordSet2
*r
)
636 struct netlogon_creds_CredentialState
*creds
;
637 struct ldb_context
*sam_ctx
;
638 const char * const attrs
[] = { "dBCSPwd", "unicodePwd", NULL
};
639 struct ldb_message
**res
;
640 struct samr_Password
*oldLmHash
, *oldNtHash
;
641 struct NL_PASSWORD_VERSION version
= {};
642 const uint32_t *new_version
= NULL
;
644 DATA_BLOB new_password
;
646 struct samr_CryptPassword password_buf
;
648 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
651 r
->in
.credential
, r
->out
.return_authenticator
,
653 NT_STATUS_NOT_OK_RETURN(nt_status
);
655 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);
656 if (sam_ctx
== NULL
) {
657 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
660 memcpy(password_buf
.data
, r
->in
.new_password
->data
, 512);
661 SIVAL(password_buf
.data
, 512, r
->in
.new_password
->length
);
663 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
664 netlogon_creds_aes_decrypt(creds
, password_buf
.data
, 516);
666 netlogon_creds_arcfour_crypt(creds
, password_buf
.data
, 516);
669 switch (creds
->secure_channel_type
) {
670 case SEC_CHAN_DOMAIN
:
671 case SEC_CHAN_DNS_DOMAIN
: {
672 uint32_t len
= IVAL(password_buf
.data
, 512);
674 uint32_t ofs
= 500 - len
;
677 p
= password_buf
.data
+ ofs
;
679 version
.ReservedField
= IVAL(p
, 0);
680 version
.PasswordVersionNumber
= IVAL(p
, 4);
681 version
.PasswordVersionPresent
= IVAL(p
, 8);
683 if (version
.PasswordVersionPresent
== NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT
) {
684 new_version
= &version
.PasswordVersionNumber
;
692 if (!extract_pw_from_buffer(mem_ctx
, password_buf
.data
, &new_password
)) {
693 DEBUG(3,("samr: failed to decode password buffer\n"));
694 return NT_STATUS_WRONG_PASSWORD
;
697 /* fetch the old password hashes (at least one of both has to exist) */
699 ret
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &res
, attrs
,
700 "(&(objectClass=user)(objectSid=%s))",
701 ldap_encode_ndr_dom_sid(mem_ctx
, creds
->sid
));
703 return NT_STATUS_WRONG_PASSWORD
;
706 nt_status
= samdb_result_passwords_no_lockout(mem_ctx
,
707 dce_call
->conn
->dce_ctx
->lp_ctx
,
708 res
[0], &oldLmHash
, &oldNtHash
);
709 if (!NT_STATUS_IS_OK(nt_status
) || (!oldLmHash
&& !oldNtHash
)) {
710 return NT_STATUS_WRONG_PASSWORD
;
713 /* Using the sid for the account as the key, set the password */
714 nt_status
= samdb_set_password_sid(sam_ctx
, mem_ctx
,
717 &new_password
, /* we have plaintext */
719 oldLmHash
, oldNtHash
, /* Password change */
728 static WERROR
dcesrv_netr_LogonUasLogon(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
729 struct netr_LogonUasLogon
*r
)
731 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
738 static WERROR
dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
739 struct netr_LogonUasLogoff
*r
)
741 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
745 static NTSTATUS
dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx
*r
)
747 switch (r
->in
.logon_level
) {
748 case NetlogonInteractiveInformation
:
749 case NetlogonServiceInformation
:
750 case NetlogonInteractiveTransitiveInformation
:
751 case NetlogonServiceTransitiveInformation
:
752 if (r
->in
.logon
->password
== NULL
) {
753 return NT_STATUS_INVALID_PARAMETER
;
756 switch (r
->in
.validation_level
) {
757 case NetlogonValidationSamInfo
: /* 2 */
758 case NetlogonValidationSamInfo2
: /* 3 */
759 case NetlogonValidationSamInfo4
: /* 6 */
762 return NT_STATUS_INVALID_INFO_CLASS
;
766 case NetlogonNetworkInformation
:
767 case NetlogonNetworkTransitiveInformation
:
768 if (r
->in
.logon
->network
== NULL
) {
769 return NT_STATUS_INVALID_PARAMETER
;
772 switch (r
->in
.validation_level
) {
773 case NetlogonValidationSamInfo
: /* 2 */
774 case NetlogonValidationSamInfo2
: /* 3 */
775 case NetlogonValidationSamInfo4
: /* 6 */
778 return NT_STATUS_INVALID_INFO_CLASS
;
783 case NetlogonGenericInformation
:
784 if (r
->in
.logon
->generic
== NULL
) {
785 return NT_STATUS_INVALID_PARAMETER
;
788 switch (r
->in
.validation_level
) {
789 /* TODO: case NetlogonValidationGenericInfo: 4 */
790 case NetlogonValidationGenericInfo2
: /* 5 */
793 return NT_STATUS_INVALID_INFO_CLASS
;
798 return NT_STATUS_INVALID_PARAMETER
;
805 netr_LogonSamLogon_base
807 This version of the function allows other wrappers to say 'do not check the credentials'
809 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
811 static NTSTATUS
dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
812 struct netr_LogonSamLogonEx
*r
, struct netlogon_creds_CredentialState
*creds
)
814 struct auth4_context
*auth_context
;
815 struct auth_usersupplied_info
*user_info
;
816 struct auth_user_info_dc
*user_info_dc
;
818 struct netr_SamBaseInfo
*sam
;
819 struct netr_SamInfo2
*sam2
;
820 struct netr_SamInfo3
*sam3
;
821 struct netr_SamInfo6
*sam6
;
823 *r
->out
.authoritative
= 1;
825 user_info
= talloc_zero(mem_ctx
, struct auth_usersupplied_info
);
826 NT_STATUS_HAVE_NO_MEMORY(user_info
);
828 netlogon_creds_decrypt_samlogon_logon(creds
,
832 switch (r
->in
.logon_level
) {
833 case NetlogonInteractiveInformation
:
834 case NetlogonServiceInformation
:
835 case NetlogonInteractiveTransitiveInformation
:
836 case NetlogonServiceTransitiveInformation
:
838 /* TODO: we need to deny anonymous access here */
839 nt_status
= auth_context_create(mem_ctx
,
840 dce_call
->event_ctx
, dce_call
->msg_ctx
,
841 dce_call
->conn
->dce_ctx
->lp_ctx
,
843 NT_STATUS_NOT_OK_RETURN(nt_status
);
845 user_info
->logon_parameters
= r
->in
.logon
->password
->identity_info
.parameter_control
;
846 user_info
->client
.account_name
= r
->in
.logon
->password
->identity_info
.account_name
.string
;
847 user_info
->client
.domain_name
= r
->in
.logon
->password
->identity_info
.domain_name
.string
;
848 user_info
->workstation_name
= r
->in
.logon
->password
->identity_info
.workstation
.string
;
850 user_info
->flags
|= USER_INFO_INTERACTIVE_LOGON
;
851 user_info
->password_state
= AUTH_PASSWORD_HASH
;
853 user_info
->password
.hash
.lanman
= talloc(user_info
, struct samr_Password
);
854 NT_STATUS_HAVE_NO_MEMORY(user_info
->password
.hash
.lanman
);
855 *user_info
->password
.hash
.lanman
= r
->in
.logon
->password
->lmpassword
;
857 user_info
->password
.hash
.nt
= talloc(user_info
, struct samr_Password
);
858 NT_STATUS_HAVE_NO_MEMORY(user_info
->password
.hash
.nt
);
859 *user_info
->password
.hash
.nt
= r
->in
.logon
->password
->ntpassword
;
862 case NetlogonNetworkInformation
:
863 case NetlogonNetworkTransitiveInformation
:
865 /* TODO: we need to deny anonymous access here */
866 nt_status
= auth_context_create(mem_ctx
,
867 dce_call
->event_ctx
, dce_call
->msg_ctx
,
868 dce_call
->conn
->dce_ctx
->lp_ctx
,
870 NT_STATUS_NOT_OK_RETURN(nt_status
);
872 nt_status
= auth_context_set_challenge(auth_context
, r
->in
.logon
->network
->challenge
, "netr_LogonSamLogonWithFlags");
873 NT_STATUS_NOT_OK_RETURN(nt_status
);
875 user_info
->logon_parameters
= r
->in
.logon
->network
->identity_info
.parameter_control
;
876 user_info
->client
.account_name
= r
->in
.logon
->network
->identity_info
.account_name
.string
;
877 user_info
->client
.domain_name
= r
->in
.logon
->network
->identity_info
.domain_name
.string
;
878 user_info
->workstation_name
= r
->in
.logon
->network
->identity_info
.workstation
.string
;
880 user_info
->password_state
= AUTH_PASSWORD_RESPONSE
;
881 user_info
->password
.response
.lanman
= data_blob_talloc(mem_ctx
, r
->in
.logon
->network
->lm
.data
, r
->in
.logon
->network
->lm
.length
);
882 user_info
->password
.response
.nt
= data_blob_talloc(mem_ctx
, r
->in
.logon
->network
->nt
.data
, r
->in
.logon
->network
->nt
.length
);
887 case NetlogonGenericInformation
:
889 if (creds
->negotiate_flags
& NETLOGON_NEG_SUPPORTS_AES
) {
891 } else if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
894 /* Using DES to verify kerberos tickets makes no sense */
895 return NT_STATUS_INVALID_PARAMETER
;
898 if (strcmp(r
->in
.logon
->generic
->package_name
.string
, "Kerberos") == 0) {
900 struct dcerpc_binding_handle
*irpc_handle
;
901 struct kdc_check_generic_kerberos check
;
902 struct netr_GenericInfo2
*generic
= talloc_zero(mem_ctx
, struct netr_GenericInfo2
);
903 NT_STATUS_HAVE_NO_MEMORY(generic
);
904 *r
->out
.authoritative
= 1;
906 /* TODO: Describe and deal with these flags */
909 r
->out
.validation
->generic
= generic
;
911 irpc_handle
= irpc_binding_handle_by_name(mem_ctx
,
915 if (irpc_handle
== NULL
) {
916 return NT_STATUS_NO_LOGON_SERVERS
;
919 check
.in
.generic_request
=
920 data_blob_const(r
->in
.logon
->generic
->data
,
921 r
->in
.logon
->generic
->length
);
924 * TODO: make this async and avoid
925 * dcerpc_binding_handle_set_sync_ev()
927 dcerpc_binding_handle_set_sync_ev(irpc_handle
,
928 dce_call
->event_ctx
);
929 status
= dcerpc_kdc_check_generic_kerberos_r(irpc_handle
,
932 if (!NT_STATUS_IS_OK(status
)) {
935 generic
->length
= check
.out
.generic_reply
.length
;
936 generic
->data
= check
.out
.generic_reply
.data
;
940 /* Until we get an implemetnation of these other packages */
941 return NT_STATUS_INVALID_PARAMETER
;
944 return NT_STATUS_INVALID_PARAMETER
;
947 nt_status
= auth_check_password(auth_context
, mem_ctx
, user_info
, &user_info_dc
);
948 /* TODO: set *r->out.authoritative = 0 on specific errors */
949 NT_STATUS_NOT_OK_RETURN(nt_status
);
951 switch (r
->in
.validation_level
) {
953 nt_status
= auth_convert_user_info_dc_sambaseinfo(mem_ctx
, user_info_dc
, &sam
);
954 NT_STATUS_NOT_OK_RETURN(nt_status
);
956 sam2
= talloc_zero(mem_ctx
, struct netr_SamInfo2
);
957 NT_STATUS_HAVE_NO_MEMORY(sam2
);
960 /* And put into the talloc tree */
961 talloc_steal(sam2
, sam
);
962 r
->out
.validation
->sam2
= sam2
;
968 nt_status
= auth_convert_user_info_dc_saminfo3(mem_ctx
,
971 NT_STATUS_NOT_OK_RETURN(nt_status
);
973 r
->out
.validation
->sam3
= sam3
;
979 nt_status
= auth_convert_user_info_dc_saminfo3(mem_ctx
,
982 NT_STATUS_NOT_OK_RETURN(nt_status
);
984 sam6
= talloc_zero(mem_ctx
, struct netr_SamInfo6
);
985 NT_STATUS_HAVE_NO_MEMORY(sam6
);
986 sam6
->base
= sam3
->base
;
988 sam6
->sidcount
= sam3
->sidcount
;
989 sam6
->sids
= sam3
->sids
;
991 sam6
->dns_domainname
.string
= lpcfg_dnsdomain(dce_call
->conn
->dce_ctx
->lp_ctx
);
992 sam6
->principle
.string
= talloc_asprintf(mem_ctx
, "%s@%s",
993 sam
->account_name
.string
, sam6
->dns_domainname
.string
);
994 NT_STATUS_HAVE_NO_MEMORY(sam6
->principle
.string
);
995 /* And put into the talloc tree */
996 talloc_steal(sam6
, sam3
);
998 r
->out
.validation
->sam6
= sam6
;
1002 return NT_STATUS_INVALID_INFO_CLASS
;
1005 netlogon_creds_encrypt_samlogon_validation(creds
,
1006 r
->in
.validation_level
,
1009 /* TODO: Describe and deal with these flags */
1012 return NT_STATUS_OK
;
1015 static NTSTATUS
dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1016 struct netr_LogonSamLogonEx
*r
)
1019 struct netlogon_creds_CredentialState
*creds
;
1021 *r
->out
.authoritative
= 1;
1023 nt_status
= dcesrv_netr_LogonSamLogon_check(r
);
1024 if (!NT_STATUS_IS_OK(nt_status
)) {
1028 nt_status
= schannel_get_creds_state(mem_ctx
,
1029 dce_call
->conn
->dce_ctx
->lp_ctx
,
1030 r
->in
.computer_name
, &creds
);
1031 if (!NT_STATUS_IS_OK(nt_status
)) {
1035 if (!dce_call
->conn
->auth_state
.auth_info
||
1036 dce_call
->conn
->auth_state
.auth_info
->auth_type
!= DCERPC_AUTH_TYPE_SCHANNEL
) {
1037 return NT_STATUS_ACCESS_DENIED
;
1039 return dcesrv_netr_LogonSamLogon_base(dce_call
, mem_ctx
, r
, creds
);
1043 netr_LogonSamLogonWithFlags
1046 static NTSTATUS
dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1047 struct netr_LogonSamLogonWithFlags
*r
)
1050 struct netlogon_creds_CredentialState
*creds
;
1051 struct netr_LogonSamLogonEx r2
;
1053 struct netr_Authenticator
*return_authenticator
;
1057 r2
.in
.server_name
= r
->in
.server_name
;
1058 r2
.in
.computer_name
= r
->in
.computer_name
;
1059 r2
.in
.logon_level
= r
->in
.logon_level
;
1060 r2
.in
.logon
= r
->in
.logon
;
1061 r2
.in
.validation_level
= r
->in
.validation_level
;
1062 r2
.in
.flags
= r
->in
.flags
;
1063 r2
.out
.validation
= r
->out
.validation
;
1064 r2
.out
.authoritative
= r
->out
.authoritative
;
1065 r2
.out
.flags
= r
->out
.flags
;
1067 *r
->out
.authoritative
= 1;
1069 nt_status
= dcesrv_netr_LogonSamLogon_check(&r2
);
1070 if (!NT_STATUS_IS_OK(nt_status
)) {
1074 return_authenticator
= talloc(mem_ctx
, struct netr_Authenticator
);
1075 NT_STATUS_HAVE_NO_MEMORY(return_authenticator
);
1077 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
1079 r
->in
.computer_name
,
1080 r
->in
.credential
, return_authenticator
,
1082 NT_STATUS_NOT_OK_RETURN(nt_status
);
1084 nt_status
= dcesrv_netr_LogonSamLogon_base(dce_call
, mem_ctx
, &r2
, creds
);
1086 r
->out
.return_authenticator
= return_authenticator
;
1094 static NTSTATUS
dcesrv_netr_LogonSamLogon(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1095 struct netr_LogonSamLogon
*r
)
1097 struct netr_LogonSamLogonWithFlags r2
;
1103 r2
.in
.server_name
= r
->in
.server_name
;
1104 r2
.in
.computer_name
= r
->in
.computer_name
;
1105 r2
.in
.credential
= r
->in
.credential
;
1106 r2
.in
.return_authenticator
= r
->in
.return_authenticator
;
1107 r2
.in
.logon_level
= r
->in
.logon_level
;
1108 r2
.in
.logon
= r
->in
.logon
;
1109 r2
.in
.validation_level
= r
->in
.validation_level
;
1110 r2
.in
.flags
= &flags
;
1111 r2
.out
.validation
= r
->out
.validation
;
1112 r2
.out
.authoritative
= r
->out
.authoritative
;
1113 r2
.out
.flags
= &flags
;
1115 status
= dcesrv_netr_LogonSamLogonWithFlags(dce_call
, mem_ctx
, &r2
);
1117 r
->out
.return_authenticator
= r2
.out
.return_authenticator
;
1126 static NTSTATUS
dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1127 struct netr_LogonSamLogoff
*r
)
1129 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1137 static NTSTATUS
dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1138 struct netr_DatabaseDeltas
*r
)
1140 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1147 static NTSTATUS
dcesrv_netr_DatabaseSync2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1148 struct netr_DatabaseSync2
*r
)
1150 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1151 return NT_STATUS_NOT_IMPLEMENTED
;
1158 static NTSTATUS
dcesrv_netr_DatabaseSync(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1159 struct netr_DatabaseSync
*r
)
1161 struct netr_DatabaseSync2 r2
;
1166 r2
.in
.logon_server
= r
->in
.logon_server
;
1167 r2
.in
.computername
= r
->in
.computername
;
1168 r2
.in
.credential
= r
->in
.credential
;
1169 r2
.in
.database_id
= r
->in
.database_id
;
1170 r2
.in
.restart_state
= SYNCSTATE_NORMAL_STATE
;
1171 r2
.in
.sync_context
= r
->in
.sync_context
;
1172 r2
.out
.sync_context
= r
->out
.sync_context
;
1173 r2
.out
.delta_enum_array
= r
->out
.delta_enum_array
;
1174 r2
.in
.preferredmaximumlength
= r
->in
.preferredmaximumlength
;
1176 status
= dcesrv_netr_DatabaseSync2(dce_call
, mem_ctx
, &r2
);
1185 static NTSTATUS
dcesrv_netr_AccountDeltas(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1186 struct netr_AccountDeltas
*r
)
1188 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1189 return NT_STATUS_NOT_IMPLEMENTED
;
1196 static NTSTATUS
dcesrv_netr_AccountSync(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1197 struct netr_AccountSync
*r
)
1199 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1200 return NT_STATUS_NOT_IMPLEMENTED
;
1207 static WERROR
dcesrv_netr_GetDcName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1208 struct netr_GetDcName
*r
)
1210 const char * const attrs
[] = { NULL
};
1211 struct ldb_context
*sam_ctx
;
1212 struct ldb_message
**res
;
1213 struct ldb_dn
*domain_dn
;
1218 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1219 * that the domainname needs to be a valid netbios domain
1220 * name, if it is not NULL.
1222 if (r
->in
.domainname
) {
1223 const char *dot
= strchr(r
->in
.domainname
, '.');
1224 size_t len
= strlen(r
->in
.domainname
);
1226 if (dot
|| len
> 15) {
1227 return WERR_DCNOTFOUND
;
1231 * TODO: Should we also varify that only valid
1232 * netbios name characters are used?
1236 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
1237 dce_call
->conn
->dce_ctx
->lp_ctx
,
1238 dce_call
->conn
->auth_state
.session_info
, 0);
1239 if (sam_ctx
== NULL
) {
1240 return WERR_DS_UNAVAILABLE
;
1243 domain_dn
= samdb_domain_to_dn(sam_ctx
, mem_ctx
,
1245 if (domain_dn
== NULL
) {
1246 return WERR_NO_SUCH_DOMAIN
;
1249 ret
= gendb_search_dn(sam_ctx
, mem_ctx
,
1250 domain_dn
, &res
, attrs
);
1252 return WERR_NO_SUCH_DOMAIN
;
1255 /* TODO: - return real IP address
1256 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1258 dcname
= talloc_asprintf(mem_ctx
, "\\\\%s",
1259 lpcfg_netbios_name(dce_call
->conn
->dce_ctx
->lp_ctx
));
1260 W_ERROR_HAVE_NO_MEMORY(dcname
);
1262 *r
->out
.dcname
= dcname
;
1268 netr_LogonControl2Ex
1270 static WERROR
dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1271 struct netr_LogonControl2Ex
*r
)
1273 return WERR_NOT_SUPPORTED
;
1280 static WERROR
dcesrv_netr_LogonControl(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1281 struct netr_LogonControl
*r
)
1283 struct netr_LogonControl2Ex r2
;
1286 if (r
->in
.level
== 0x00000001) {
1289 r2
.in
.logon_server
= r
->in
.logon_server
;
1290 r2
.in
.function_code
= r
->in
.function_code
;
1291 r2
.in
.level
= r
->in
.level
;
1293 r2
.out
.query
= r
->out
.query
;
1295 werr
= dcesrv_netr_LogonControl2Ex(dce_call
, mem_ctx
, &r2
);
1296 } else if (r
->in
.level
== 0x00000002) {
1297 werr
= WERR_NOT_SUPPORTED
;
1299 werr
= WERR_UNKNOWN_LEVEL
;
1309 static WERROR
dcesrv_netr_LogonControl2(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1310 struct netr_LogonControl2
*r
)
1312 struct netr_LogonControl2Ex r2
;
1317 r2
.in
.logon_server
= r
->in
.logon_server
;
1318 r2
.in
.function_code
= r
->in
.function_code
;
1319 r2
.in
.level
= r
->in
.level
;
1320 r2
.in
.data
= r
->in
.data
;
1321 r2
.out
.query
= r
->out
.query
;
1323 werr
= dcesrv_netr_LogonControl2Ex(dce_call
, mem_ctx
, &r2
);
1328 static WERROR
fill_trusted_domains_array(TALLOC_CTX
*mem_ctx
,
1329 struct ldb_context
*sam_ctx
,
1330 struct netr_DomainTrustList
*trusts
,
1331 uint32_t trust_flags
);
1336 static WERROR
dcesrv_netr_GetAnyDCName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1337 struct netr_GetAnyDCName
*r
)
1339 struct netr_DomainTrustList
*trusts
;
1340 struct ldb_context
*sam_ctx
;
1341 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1345 *r
->out
.dcname
= NULL
;
1347 if ((r
->in
.domainname
== NULL
) || (r
->in
.domainname
[0] == '\0')) {
1348 /* if the domainname parameter wasn't set assume our domain */
1349 r
->in
.domainname
= lpcfg_workgroup(lp_ctx
);
1352 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1353 dce_call
->conn
->auth_state
.session_info
, 0);
1354 if (sam_ctx
== NULL
) {
1355 return WERR_DS_UNAVAILABLE
;
1358 if (strcasecmp(r
->in
.domainname
, lpcfg_workgroup(lp_ctx
)) == 0) {
1359 /* well we asked for a DC of our own domain */
1360 if (samdb_is_pdc(sam_ctx
)) {
1361 /* we are the PDC of the specified domain */
1362 return WERR_NO_SUCH_DOMAIN
;
1365 *r
->out
.dcname
= talloc_asprintf(mem_ctx
, "\\%s",
1366 lpcfg_netbios_name(lp_ctx
));
1367 W_ERROR_HAVE_NO_MEMORY(*r
->out
.dcname
);
1372 /* Okay, now we have to consider the trusted domains */
1374 trusts
= talloc_zero(mem_ctx
, struct netr_DomainTrustList
);
1375 W_ERROR_HAVE_NO_MEMORY(trusts
);
1379 werr
= fill_trusted_domains_array(mem_ctx
, sam_ctx
, trusts
,
1380 NETR_TRUST_FLAG_INBOUND
1381 | NETR_TRUST_FLAG_OUTBOUND
);
1382 W_ERROR_NOT_OK_RETURN(werr
);
1384 for (i
= 0; i
< trusts
->count
; i
++) {
1385 if (strcasecmp(r
->in
.domainname
, trusts
->array
[i
].netbios_name
) == 0) {
1386 /* FIXME: Here we need to find a DC for the specified
1387 * trusted domain. */
1389 /* return WERR_OK; */
1390 return WERR_NO_SUCH_DOMAIN
;
1394 return WERR_NO_SUCH_DOMAIN
;
1401 static NTSTATUS
dcesrv_netr_DatabaseRedo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1402 struct netr_DatabaseRedo
*r
)
1404 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1409 netr_NetrEnumerateTrustedDomains
1411 static NTSTATUS
dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1412 struct netr_NetrEnumerateTrustedDomains
*r
)
1414 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1419 netr_LogonGetCapabilities
1421 static NTSTATUS
dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1422 struct netr_LogonGetCapabilities
*r
)
1424 struct netlogon_creds_CredentialState
*creds
;
1427 status
= dcesrv_netr_creds_server_step_check(dce_call
,
1429 r
->in
.computer_name
,
1431 r
->out
.return_authenticator
,
1433 if (!NT_STATUS_IS_OK(status
)) {
1434 DEBUG(0,(__location__
" Bad credentials - error\n"));
1436 NT_STATUS_NOT_OK_RETURN(status
);
1438 if (r
->in
.query_level
!= 1) {
1439 return NT_STATUS_NOT_SUPPORTED
;
1442 r
->out
.capabilities
->server_capabilities
= creds
->negotiate_flags
;
1444 return NT_STATUS_OK
;
1449 netr_NETRLOGONSETSERVICEBITS
1451 static WERROR
dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1452 struct netr_NETRLOGONSETSERVICEBITS
*r
)
1454 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1459 netr_LogonGetTrustRid
1461 static WERROR
dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1462 struct netr_LogonGetTrustRid
*r
)
1464 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1469 netr_NETRLOGONCOMPUTESERVERDIGEST
1471 static WERROR
dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1472 struct netr_NETRLOGONCOMPUTESERVERDIGEST
*r
)
1474 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1479 netr_NETRLOGONCOMPUTECLIENTDIGEST
1481 static WERROR
dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1482 struct netr_NETRLOGONCOMPUTECLIENTDIGEST
*r
)
1484 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1492 static WERROR
dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1493 struct netr_DsRGetSiteName
*r
)
1495 struct ldb_context
*sam_ctx
;
1496 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1498 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1499 dce_call
->conn
->auth_state
.session_info
, 0);
1500 if (sam_ctx
== NULL
) {
1501 return WERR_DS_UNAVAILABLE
;
1505 * We assume to be a DC when we get called over NETLOGON. Hence we
1506 * get our site name always by using "samdb_server_site_name()"
1507 * and not "samdb_client_site_name()".
1509 *r
->out
.site
= samdb_server_site_name(sam_ctx
, mem_ctx
);
1510 W_ERROR_HAVE_NO_MEMORY(*r
->out
.site
);
1517 fill in a netr_OneDomainInfo from a ldb search result
1519 static NTSTATUS
fill_one_domain_info(TALLOC_CTX
*mem_ctx
,
1520 struct loadparm_context
*lp_ctx
,
1521 struct ldb_context
*sam_ctx
,
1522 struct ldb_message
*res
,
1523 struct netr_OneDomainInfo
*info
,
1524 bool is_local
, bool is_trust_list
)
1528 if (is_trust_list
) {
1529 /* w2k8 only fills this on trusted domains */
1530 info
->trust_extension
.info
= talloc_zero(mem_ctx
, struct netr_trust_extension
);
1531 info
->trust_extension
.length
= 16;
1532 info
->trust_extension
.info
->flags
=
1533 NETR_TRUST_FLAG_TREEROOT
|
1534 NETR_TRUST_FLAG_IN_FOREST
|
1535 NETR_TRUST_FLAG_PRIMARY
|
1536 NETR_TRUST_FLAG_NATIVE
;
1538 info
->trust_extension
.info
->parent_index
= 0; /* should be index into array
1540 info
->trust_extension
.info
->trust_type
= LSA_TRUST_TYPE_UPLEVEL
; /* should be based on ldb search for trusts */
1541 info
->trust_extension
.info
->trust_attributes
= 0; /* TODO: base on ldb search? */
1544 if (is_trust_list
) {
1545 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1546 info
->dns_forestname
.string
= NULL
;
1548 info
->dns_forestname
.string
= samdb_forest_name(sam_ctx
, mem_ctx
);
1549 NT_STATUS_HAVE_NO_MEMORY(info
->dns_forestname
.string
);
1550 info
->dns_forestname
.string
= talloc_asprintf(mem_ctx
, "%s.", info
->dns_forestname
.string
);
1551 NT_STATUS_HAVE_NO_MEMORY(info
->dns_forestname
.string
);
1555 info
->domainname
.string
= lpcfg_workgroup(lp_ctx
);
1556 info
->dns_domainname
.string
= lpcfg_dnsdomain(lp_ctx
);
1557 info
->domain_guid
= samdb_result_guid(res
, "objectGUID");
1558 info
->domain_sid
= samdb_result_dom_sid(mem_ctx
, res
, "objectSid");
1560 info
->domainname
.string
= ldb_msg_find_attr_as_string(res
, "flatName", NULL
);
1561 info
->dns_domainname
.string
= ldb_msg_find_attr_as_string(res
, "trustPartner", NULL
);
1562 info
->domain_guid
= samdb_result_guid(res
, "objectGUID");
1563 info
->domain_sid
= samdb_result_dom_sid(mem_ctx
, res
, "securityIdentifier");
1565 if (!is_trust_list
) {
1566 info
->dns_domainname
.string
= talloc_asprintf(mem_ctx
, "%s.", info
->dns_domainname
.string
);
1569 return NT_STATUS_OK
;
1573 netr_LogonGetDomainInfo
1574 this is called as part of the ADS domain logon procedure.
1576 It has an important role in convaying details about the client, such
1577 as Operating System, Version, Service Pack etc.
1579 static NTSTATUS
dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state
*dce_call
,
1580 TALLOC_CTX
*mem_ctx
, struct netr_LogonGetDomainInfo
*r
)
1582 struct netlogon_creds_CredentialState
*creds
;
1583 const char * const attrs
[] = { "objectSid", "objectGUID", "flatName",
1584 "securityIdentifier", "trustPartner", NULL
};
1585 const char * const attrs2
[] = { "sAMAccountName", "dNSHostName",
1586 "msDS-SupportedEncryptionTypes", NULL
};
1587 const char *sam_account_name
, *old_dns_hostname
, *prefix1
, *prefix2
;
1588 struct ldb_context
*sam_ctx
;
1589 struct ldb_message
**res1
, **res2
, **res3
, *new_msg
;
1590 struct ldb_dn
*workstation_dn
;
1591 struct netr_DomainInformation
*domain_info
;
1592 struct netr_LsaPolicyInformation
*lsa_policy_info
;
1593 uint32_t default_supported_enc_types
= 0xFFFFFFFF;
1594 bool update_dns_hostname
= true;
1598 status
= dcesrv_netr_creds_server_step_check(dce_call
,
1600 r
->in
.computer_name
,
1602 r
->out
.return_authenticator
,
1604 if (!NT_STATUS_IS_OK(status
)) {
1605 DEBUG(0,(__location__
" Bad credentials - error\n"));
1607 NT_STATUS_NOT_OK_RETURN(status
);
1609 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
,
1610 dce_call
->conn
->dce_ctx
->lp_ctx
,
1611 system_session(dce_call
->conn
->dce_ctx
->lp_ctx
), 0);
1612 if (sam_ctx
== NULL
) {
1613 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
1616 switch (r
->in
.level
) {
1617 case 1: /* Domain information */
1619 if (r
->in
.query
->workstation_info
== NULL
) {
1620 return NT_STATUS_INVALID_PARAMETER
;
1623 /* Prepares the workstation DN */
1624 workstation_dn
= ldb_dn_new_fmt(mem_ctx
, sam_ctx
, "<SID=%s>",
1625 dom_sid_string(mem_ctx
, creds
->sid
));
1626 NT_STATUS_HAVE_NO_MEMORY(workstation_dn
);
1628 /* Lookup for attributes in workstation object */
1629 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, workstation_dn
, &res1
,
1632 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1635 /* Gets the sam account name which is checked against the DNS
1636 * hostname parameter. */
1637 sam_account_name
= ldb_msg_find_attr_as_string(res1
[0],
1640 if (sam_account_name
== NULL
) {
1641 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1645 * Checks that the sam account name without a possible "$"
1646 * matches as prefix with the DNS hostname in the workstation
1649 prefix1
= talloc_strndup(mem_ctx
, sam_account_name
,
1650 strcspn(sam_account_name
, "$"));
1651 NT_STATUS_HAVE_NO_MEMORY(prefix1
);
1652 if (r
->in
.query
->workstation_info
->dns_hostname
!= NULL
) {
1653 prefix2
= talloc_strndup(mem_ctx
,
1654 r
->in
.query
->workstation_info
->dns_hostname
,
1655 strcspn(r
->in
.query
->workstation_info
->dns_hostname
, "."));
1656 NT_STATUS_HAVE_NO_MEMORY(prefix2
);
1658 if (strcasecmp(prefix1
, prefix2
) != 0) {
1659 update_dns_hostname
= false;
1662 update_dns_hostname
= false;
1665 /* Gets the old DNS hostname */
1666 old_dns_hostname
= ldb_msg_find_attr_as_string(res1
[0],
1671 * Updates the DNS hostname when the client wishes that the
1672 * server should handle this for him
1673 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1674 * obviously only checked when we do already have a
1676 * See MS-NRPC section 3.5.4.3.9
1678 if ((old_dns_hostname
!= NULL
) &&
1679 (r
->in
.query
->workstation_info
->workstation_flags
1680 & NETR_WS_FLAG_HANDLES_SPN_UPDATE
) != 0) {
1681 update_dns_hostname
= false;
1684 /* Gets host information and put them into our directory */
1686 new_msg
= ldb_msg_new(mem_ctx
);
1687 NT_STATUS_HAVE_NO_MEMORY(new_msg
);
1689 new_msg
->dn
= workstation_dn
;
1691 /* Sets the OS name */
1693 if (r
->in
.query
->workstation_info
->os_name
.string
== NULL
) {
1694 return NT_STATUS_INVALID_PARAMETER
;
1697 ret
= ldb_msg_add_string(new_msg
, "operatingSystem",
1698 r
->in
.query
->workstation_info
->os_name
.string
);
1699 if (ret
!= LDB_SUCCESS
) {
1700 return NT_STATUS_NO_MEMORY
;
1704 * Sets information from "os_version". On an empty structure
1705 * the values are cleared.
1707 if (r
->in
.query
->workstation_info
->os_version
.os
!= NULL
) {
1708 struct netr_OsVersionInfoEx
*os_version
;
1709 const char *os_version_str
;
1711 os_version
= &r
->in
.query
->workstation_info
->os_version
.os
->os
;
1713 if (os_version
->CSDVersion
== NULL
) {
1714 return NT_STATUS_INVALID_PARAMETER
;
1717 os_version_str
= talloc_asprintf(new_msg
, "%u.%u (%u)",
1718 os_version
->MajorVersion
,
1719 os_version
->MinorVersion
,
1720 os_version
->BuildNumber
);
1721 NT_STATUS_HAVE_NO_MEMORY(os_version_str
);
1723 ret
= ldb_msg_add_string(new_msg
,
1724 "operatingSystemServicePack",
1725 os_version
->CSDVersion
);
1726 if (ret
!= LDB_SUCCESS
) {
1727 return NT_STATUS_NO_MEMORY
;
1730 ret
= ldb_msg_add_string(new_msg
,
1731 "operatingSystemVersion",
1733 if (ret
!= LDB_SUCCESS
) {
1734 return NT_STATUS_NO_MEMORY
;
1737 ret
= samdb_msg_add_delete(sam_ctx
, mem_ctx
, new_msg
,
1738 "operatingSystemServicePack");
1739 if (ret
!= LDB_SUCCESS
) {
1740 return NT_STATUS_NO_MEMORY
;
1743 ret
= samdb_msg_add_delete(sam_ctx
, mem_ctx
, new_msg
,
1744 "operatingSystemVersion");
1745 if (ret
!= LDB_SUCCESS
) {
1746 return NT_STATUS_NO_MEMORY
;
1751 * If the boolean "update_dns_hostname" remained true, then we
1752 * are fine to start the update.
1754 if (update_dns_hostname
) {
1755 ret
= ldb_msg_add_string(new_msg
,
1757 r
->in
.query
->workstation_info
->dns_hostname
);
1758 if (ret
!= LDB_SUCCESS
) {
1759 return NT_STATUS_NO_MEMORY
;
1762 /* This manual "servicePrincipalName" generation is
1763 * still needed! Since the update in the samldb LDB
1764 * module does only work if the entries already exist
1765 * which isn't always the case. */
1766 ret
= ldb_msg_add_string(new_msg
,
1767 "servicePrincipalName",
1768 talloc_asprintf(new_msg
, "HOST/%s",
1769 r
->in
.computer_name
));
1770 if (ret
!= LDB_SUCCESS
) {
1771 return NT_STATUS_NO_MEMORY
;
1774 ret
= ldb_msg_add_string(new_msg
,
1775 "servicePrincipalName",
1776 talloc_asprintf(new_msg
, "HOST/%s",
1777 r
->in
.query
->workstation_info
->dns_hostname
));
1778 if (ret
!= LDB_SUCCESS
) {
1779 return NT_STATUS_NO_MEMORY
;
1783 if (dsdb_replace(sam_ctx
, new_msg
, 0) != LDB_SUCCESS
) {
1784 DEBUG(3,("Impossible to update samdb: %s\n",
1785 ldb_errstring(sam_ctx
)));
1788 talloc_free(new_msg
);
1790 /* Writes back the domain information */
1792 /* We need to do two searches. The first will pull our primary
1793 domain and the second will pull any trusted domains. Our
1794 primary domain is also a "trusted" domain, so we need to
1795 put the primary domain into the lists of returned trusts as
1797 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, ldb_get_default_basedn(sam_ctx
),
1800 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1803 ret3
= gendb_search(sam_ctx
, mem_ctx
, NULL
, &res3
, attrs
,
1804 "(objectClass=trustedDomain)");
1806 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1809 domain_info
= talloc(mem_ctx
, struct netr_DomainInformation
);
1810 NT_STATUS_HAVE_NO_MEMORY(domain_info
);
1812 ZERO_STRUCTP(domain_info
);
1814 /* Informations about the local and trusted domains */
1816 status
= fill_one_domain_info(mem_ctx
,
1817 dce_call
->conn
->dce_ctx
->lp_ctx
,
1818 sam_ctx
, res2
[0], &domain_info
->primary_domain
,
1820 NT_STATUS_NOT_OK_RETURN(status
);
1822 domain_info
->trusted_domain_count
= ret3
+ 1;
1823 domain_info
->trusted_domains
= talloc_array(mem_ctx
,
1824 struct netr_OneDomainInfo
,
1825 domain_info
->trusted_domain_count
);
1826 NT_STATUS_HAVE_NO_MEMORY(domain_info
->trusted_domains
);
1828 for (i
=0;i
<ret3
;i
++) {
1829 status
= fill_one_domain_info(mem_ctx
,
1830 dce_call
->conn
->dce_ctx
->lp_ctx
,
1832 &domain_info
->trusted_domains
[i
],
1834 NT_STATUS_NOT_OK_RETURN(status
);
1837 status
= fill_one_domain_info(mem_ctx
,
1838 dce_call
->conn
->dce_ctx
->lp_ctx
, sam_ctx
, res2
[0],
1839 &domain_info
->trusted_domains
[i
], true, true);
1840 NT_STATUS_NOT_OK_RETURN(status
);
1842 /* Sets the supported encryption types */
1843 domain_info
->supported_enc_types
= ldb_msg_find_attr_as_uint(res1
[0],
1844 "msDS-SupportedEncryptionTypes",
1845 default_supported_enc_types
);
1847 /* Other host domain information */
1849 lsa_policy_info
= talloc(mem_ctx
,
1850 struct netr_LsaPolicyInformation
);
1851 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info
);
1852 ZERO_STRUCTP(lsa_policy_info
);
1854 domain_info
->lsa_policy
= *lsa_policy_info
;
1856 /* The DNS hostname is only returned back when there is a chance
1858 if ((r
->in
.query
->workstation_info
->workstation_flags
1859 & NETR_WS_FLAG_HANDLES_SPN_UPDATE
) != 0) {
1860 domain_info
->dns_hostname
.string
= old_dns_hostname
;
1862 domain_info
->dns_hostname
.string
= NULL
;
1865 domain_info
->workstation_flags
=
1866 r
->in
.query
->workstation_info
->workstation_flags
& (
1867 NETR_WS_FLAG_HANDLES_SPN_UPDATE
| NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS
);
1869 r
->out
.info
->domain_info
= domain_info
;
1871 case 2: /* LSA policy information - not used at the moment */
1872 lsa_policy_info
= talloc(mem_ctx
,
1873 struct netr_LsaPolicyInformation
);
1874 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info
);
1875 ZERO_STRUCTP(lsa_policy_info
);
1877 r
->out
.info
->lsa_policy_info
= lsa_policy_info
;
1880 return NT_STATUS_INVALID_LEVEL
;
1884 return NT_STATUS_OK
;
1889 netr_ServerPasswordGet
1891 static NTSTATUS
dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1892 struct netr_ServerPasswordGet
*r
)
1894 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1899 netr_NETRLOGONSENDTOSAM
1901 static WERROR
dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
1902 struct netr_NETRLOGONSENDTOSAM
*r
)
1904 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
1909 netr_DsRGetDCNameEx2
1911 static WERROR
dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state
*dce_call
,
1912 TALLOC_CTX
*mem_ctx
,
1913 struct netr_DsRGetDCNameEx2
*r
)
1915 struct ldb_context
*sam_ctx
;
1916 struct netr_DsRGetDCNameInfo
*info
;
1917 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
1918 const struct tsocket_address
*local_address
;
1919 char *local_addr
= NULL
;
1920 const struct tsocket_address
*remote_address
;
1921 char *remote_addr
= NULL
;
1922 const char *server_site_name
;
1924 struct netlogon_samlogon_response response
;
1926 const char *dc_name
= NULL
;
1927 const char *domain_name
= NULL
;
1930 ZERO_STRUCTP(r
->out
.info
);
1932 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
1933 dce_call
->conn
->auth_state
.session_info
, 0);
1934 if (sam_ctx
== NULL
) {
1935 return WERR_DS_UNAVAILABLE
;
1938 local_address
= dcesrv_connection_get_local_address(dce_call
->conn
);
1939 if (tsocket_address_is_inet(local_address
, "ip")) {
1940 local_addr
= tsocket_address_inet_addr_string(local_address
, mem_ctx
);
1941 W_ERROR_HAVE_NO_MEMORY(local_addr
);
1944 remote_address
= dcesrv_connection_get_remote_address(dce_call
->conn
);
1945 if (tsocket_address_is_inet(remote_address
, "ip")) {
1946 remote_addr
= tsocket_address_inet_addr_string(remote_address
, mem_ctx
);
1947 W_ERROR_HAVE_NO_MEMORY(remote_addr
);
1950 /* "server_unc" is ignored by w2k3 */
1952 if (r
->in
.flags
& ~(DSGETDC_VALID_FLAGS
)) {
1953 return WERR_INVALID_FLAGS
;
1956 if (r
->in
.flags
& DS_GC_SERVER_REQUIRED
&&
1957 r
->in
.flags
& DS_PDC_REQUIRED
&&
1958 r
->in
.flags
& DS_KDC_REQUIRED
) {
1959 return WERR_INVALID_FLAGS
;
1961 if (r
->in
.flags
& DS_IS_FLAT_NAME
&&
1962 r
->in
.flags
& DS_IS_DNS_NAME
) {
1963 return WERR_INVALID_FLAGS
;
1965 if (r
->in
.flags
& DS_RETURN_DNS_NAME
&&
1966 r
->in
.flags
& DS_RETURN_FLAT_NAME
) {
1967 return WERR_INVALID_FLAGS
;
1969 if (r
->in
.flags
& DS_DIRECTORY_SERVICE_REQUIRED
&&
1970 r
->in
.flags
& DS_DIRECTORY_SERVICE_6_REQUIRED
) {
1971 return WERR_INVALID_FLAGS
;
1974 if (r
->in
.flags
& DS_GOOD_TIMESERV_PREFERRED
&&
1976 (DS_DIRECTORY_SERVICE_REQUIRED
|
1977 DS_DIRECTORY_SERVICE_PREFERRED
|
1978 DS_GC_SERVER_REQUIRED
|
1981 return WERR_INVALID_FLAGS
;
1984 if (r
->in
.flags
& DS_TRY_NEXTCLOSEST_SITE
&&
1986 return WERR_INVALID_FLAGS
;
1989 /* Proof server site parameter "site_name" if it was specified */
1990 server_site_name
= samdb_server_site_name(sam_ctx
, mem_ctx
);
1991 W_ERROR_HAVE_NO_MEMORY(server_site_name
);
1992 if ((r
->in
.site_name
!= NULL
) && (strcasecmp(r
->in
.site_name
,
1993 server_site_name
) != 0)) {
1994 return WERR_NO_SUCH_DOMAIN
;
1997 guid_str
= r
->in
.domain_guid
!= NULL
?
1998 GUID_string(mem_ctx
, r
->in
.domain_guid
) : NULL
;
2000 status
= fill_netlogon_samlogon_response(sam_ctx
, mem_ctx
,
2004 r
->in
.client_account
,
2005 r
->in
.mask
, remote_addr
,
2006 NETLOGON_NT_VERSION_5EX_WITH_IP
,
2007 lp_ctx
, &response
, true);
2008 if (!NT_STATUS_IS_OK(status
)) {
2009 return ntstatus_to_werror(status
);
2013 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2014 * (O) flag when the returned forest name is in DNS format. This is here
2015 * always the case (see below).
2017 response
.data
.nt5_ex
.server_type
|= DS_DNS_FOREST_ROOT
;
2019 if (r
->in
.flags
& DS_RETURN_DNS_NAME
) {
2020 dc_name
= response
.data
.nt5_ex
.pdc_dns_name
;
2021 domain_name
= response
.data
.nt5_ex
.dns_domain
;
2023 * According to MS-NRPC 2.2.1.2.1 we should set the
2024 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2025 * the returned information is in DNS form.
2027 response
.data
.nt5_ex
.server_type
|=
2028 DS_DNS_CONTROLLER
| DS_DNS_DOMAIN
;
2029 } else if (r
->in
.flags
& DS_RETURN_FLAT_NAME
) {
2030 dc_name
= response
.data
.nt5_ex
.pdc_name
;
2031 domain_name
= response
.data
.nt5_ex
.domain_name
;
2035 * TODO: autodetect what we need to return
2036 * based on the given arguments
2038 dc_name
= response
.data
.nt5_ex
.pdc_name
;
2039 domain_name
= response
.data
.nt5_ex
.domain_name
;
2042 if (!dc_name
|| !dc_name
[0]) {
2043 return WERR_NO_SUCH_DOMAIN
;
2046 if (!domain_name
|| !domain_name
[0]) {
2047 return WERR_NO_SUCH_DOMAIN
;
2050 info
= talloc(mem_ctx
, struct netr_DsRGetDCNameInfo
);
2051 W_ERROR_HAVE_NO_MEMORY(info
);
2052 info
->dc_unc
= talloc_asprintf(mem_ctx
, "%s%s",
2053 dc_name
[0] != '\\'? "\\\\":"",
2054 talloc_strdup(mem_ctx
, dc_name
));
2055 W_ERROR_HAVE_NO_MEMORY(info
->dc_unc
);
2057 pdc_ip
= local_addr
;
2058 if (pdc_ip
== NULL
) {
2059 pdc_ip
= "127.0.0.1";
2061 info
->dc_address
= talloc_asprintf(mem_ctx
, "\\\\%s", pdc_ip
);
2062 W_ERROR_HAVE_NO_MEMORY(info
->dc_address
);
2063 info
->dc_address_type
= DS_ADDRESS_TYPE_INET
;
2064 info
->domain_guid
= response
.data
.nt5_ex
.domain_uuid
;
2065 info
->domain_name
= domain_name
;
2066 info
->forest_name
= response
.data
.nt5_ex
.forest
;
2067 info
->dc_flags
= response
.data
.nt5_ex
.server_type
;
2068 if (r
->in
.flags
& DS_RETURN_DNS_NAME
) {
2069 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2070 * returned if we are returning info->dc_unc containing a FQDN.
2071 * This attribute is called DomainControllerName in the specs,
2072 * it seems that we decide to return FQDN or netbios depending on
2073 * DS_RETURN_DNS_NAME.
2075 info
->dc_flags
|= DS_DNS_CONTROLLER
;
2077 info
->dc_site_name
= response
.data
.nt5_ex
.server_site
;
2078 info
->client_site_name
= response
.data
.nt5_ex
.client_site
;
2080 *r
->out
.info
= info
;
2088 static WERROR
dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2089 struct netr_DsRGetDCNameEx
*r
)
2091 struct netr_DsRGetDCNameEx2 r2
;
2096 r2
.in
.server_unc
= r
->in
.server_unc
;
2097 r2
.in
.client_account
= NULL
;
2099 r2
.in
.domain_guid
= r
->in
.domain_guid
;
2100 r2
.in
.domain_name
= r
->in
.domain_name
;
2101 r2
.in
.site_name
= r
->in
.site_name
;
2102 r2
.in
.flags
= r
->in
.flags
;
2103 r2
.out
.info
= r
->out
.info
;
2105 werr
= dcesrv_netr_DsRGetDCNameEx2(dce_call
, mem_ctx
, &r2
);
2113 static WERROR
dcesrv_netr_DsRGetDCName(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2114 struct netr_DsRGetDCName
*r
)
2116 struct netr_DsRGetDCNameEx2 r2
;
2121 r2
.in
.server_unc
= r
->in
.server_unc
;
2122 r2
.in
.client_account
= NULL
;
2124 r2
.in
.domain_name
= r
->in
.domain_name
;
2125 r2
.in
.domain_guid
= r
->in
.domain_guid
;
2127 r2
.in
.site_name
= NULL
; /* this is correct, we should ignore site GUID */
2128 r2
.in
.flags
= r
->in
.flags
;
2129 r2
.out
.info
= r
->out
.info
;
2131 werr
= dcesrv_netr_DsRGetDCNameEx2(dce_call
, mem_ctx
, &r2
);
2136 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2138 static WERROR
dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2139 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
*r
)
2141 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2146 netr_NetrEnumerateTrustedDomainsEx
2148 static WERROR
dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2149 struct netr_NetrEnumerateTrustedDomainsEx
*r
)
2151 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2156 netr_DsRAddressToSitenamesExW
2158 static WERROR
dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2159 struct netr_DsRAddressToSitenamesExW
*r
)
2161 struct ldb_context
*sam_ctx
;
2162 struct netr_DsRAddressToSitenamesExWCtr
*ctr
;
2163 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
2164 sa_family_t sin_family
;
2165 struct sockaddr_in
*addr
;
2167 struct sockaddr_in6
*addr6
;
2168 char addr_str
[INET6_ADDRSTRLEN
];
2170 char addr_str
[INET_ADDRSTRLEN
];
2176 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
2177 dce_call
->conn
->auth_state
.session_info
, 0);
2178 if (sam_ctx
== NULL
) {
2179 return WERR_DS_UNAVAILABLE
;
2182 ctr
= talloc(mem_ctx
, struct netr_DsRAddressToSitenamesExWCtr
);
2183 W_ERROR_HAVE_NO_MEMORY(ctr
);
2187 ctr
->count
= r
->in
.count
;
2188 ctr
->sitename
= talloc_array(ctr
, struct lsa_String
, ctr
->count
);
2189 W_ERROR_HAVE_NO_MEMORY(ctr
->sitename
);
2190 ctr
->subnetname
= talloc_array(ctr
, struct lsa_String
, ctr
->count
);
2191 W_ERROR_HAVE_NO_MEMORY(ctr
->subnetname
);
2193 for (i
=0; i
<ctr
->count
; i
++) {
2194 ctr
->sitename
[i
].string
= NULL
;
2195 ctr
->subnetname
[i
].string
= NULL
;
2197 if (r
->in
.addresses
[i
].size
< sizeof(sa_family_t
)) {
2200 /* The first two byte of the buffer are reserved for the
2201 * "sin_family" but for now only the first one is used. */
2202 sin_family
= r
->in
.addresses
[i
].buffer
[0];
2204 switch (sin_family
) {
2206 if (r
->in
.addresses
[i
].size
< sizeof(struct sockaddr_in
)) {
2209 addr
= (struct sockaddr_in
*) r
->in
.addresses
[i
].buffer
;
2210 res
= inet_ntop(AF_INET
, &addr
->sin_addr
,
2211 addr_str
, sizeof(addr_str
));
2215 if (r
->in
.addresses
[i
].size
< sizeof(struct sockaddr_in6
)) {
2218 addr6
= (struct sockaddr_in6
*) r
->in
.addresses
[i
].buffer
;
2219 res
= inet_ntop(AF_INET6
, &addr6
->sin6_addr
,
2220 addr_str
, sizeof(addr_str
));
2231 ctr
->sitename
[i
].string
= samdb_client_site_name(sam_ctx
,
2235 W_ERROR_HAVE_NO_MEMORY(ctr
->sitename
[i
].string
);
2236 ctr
->subnetname
[i
].string
= subnet_name
;
2244 netr_DsRAddressToSitenamesW
2246 static WERROR
dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2247 struct netr_DsRAddressToSitenamesW
*r
)
2249 struct netr_DsRAddressToSitenamesExW r2
;
2250 struct netr_DsRAddressToSitenamesWCtr
*ctr
;
2256 r2
.in
.server_name
= r
->in
.server_name
;
2257 r2
.in
.count
= r
->in
.count
;
2258 r2
.in
.addresses
= r
->in
.addresses
;
2260 r2
.out
.ctr
= talloc(mem_ctx
, struct netr_DsRAddressToSitenamesExWCtr
*);
2261 W_ERROR_HAVE_NO_MEMORY(r2
.out
.ctr
);
2263 ctr
= talloc(mem_ctx
, struct netr_DsRAddressToSitenamesWCtr
);
2264 W_ERROR_HAVE_NO_MEMORY(ctr
);
2268 ctr
->count
= r
->in
.count
;
2269 ctr
->sitename
= talloc_array(ctr
, struct lsa_String
, ctr
->count
);
2270 W_ERROR_HAVE_NO_MEMORY(ctr
->sitename
);
2272 werr
= dcesrv_netr_DsRAddressToSitenamesExW(dce_call
, mem_ctx
, &r2
);
2274 for (i
=0; i
<ctr
->count
; i
++) {
2275 ctr
->sitename
[i
].string
= (*r2
.out
.ctr
)->sitename
[i
].string
;
2283 netr_DsrGetDcSiteCoverageW
2285 static WERROR
dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2286 struct netr_DsrGetDcSiteCoverageW
*r
)
2288 struct ldb_context
*sam_ctx
;
2289 struct DcSitesCtr
*ctr
;
2290 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
2292 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
2293 dce_call
->conn
->auth_state
.session_info
, 0);
2294 if (sam_ctx
== NULL
) {
2295 return WERR_DS_UNAVAILABLE
;
2298 ctr
= talloc(mem_ctx
, struct DcSitesCtr
);
2299 W_ERROR_HAVE_NO_MEMORY(ctr
);
2303 /* For now only return our default site */
2305 ctr
->sites
= talloc_array(ctr
, struct lsa_String
, ctr
->num_sites
);
2306 W_ERROR_HAVE_NO_MEMORY(ctr
->sites
);
2307 ctr
->sites
[0].string
= samdb_server_site_name(sam_ctx
, mem_ctx
);
2308 W_ERROR_HAVE_NO_MEMORY(ctr
->sites
[0].string
);
2314 static WERROR
fill_trusted_domains_array(TALLOC_CTX
*mem_ctx
,
2315 struct ldb_context
*sam_ctx
,
2316 struct netr_DomainTrustList
*trusts
,
2317 uint32_t trust_flags
)
2319 struct ldb_dn
*system_dn
;
2320 struct ldb_message
**dom_res
= NULL
;
2321 const char *trust_attrs
[] = { "flatname", "trustPartner",
2322 "securityIdentifier", "trustDirection",
2323 "trustType", "trustAttributes", NULL
};
2328 if (!(trust_flags
& (NETR_TRUST_FLAG_INBOUND
|
2329 NETR_TRUST_FLAG_OUTBOUND
))) {
2330 return WERR_INVALID_FLAGS
;
2333 system_dn
= samdb_search_dn(sam_ctx
, mem_ctx
,
2334 ldb_get_default_basedn(sam_ctx
),
2335 "(&(objectClass=container)(cn=System))");
2337 return WERR_GENERAL_FAILURE
;
2340 ret
= gendb_search(sam_ctx
, mem_ctx
, system_dn
,
2341 &dom_res
, trust_attrs
,
2342 "(objectclass=trustedDomain)");
2344 for (i
= 0; i
< ret
; i
++) {
2345 unsigned int trust_dir
;
2348 trust_dir
= ldb_msg_find_attr_as_uint(dom_res
[i
],
2349 "trustDirection", 0);
2351 if (trust_dir
& LSA_TRUST_DIRECTION_INBOUND
) {
2352 flags
|= NETR_TRUST_FLAG_INBOUND
;
2354 if (trust_dir
& LSA_TRUST_DIRECTION_OUTBOUND
) {
2355 flags
|= NETR_TRUST_FLAG_OUTBOUND
;
2358 if (!(flags
& trust_flags
)) {
2359 /* this trust direction was not requested */
2364 trusts
->array
= talloc_realloc(trusts
, trusts
->array
,
2365 struct netr_DomainTrust
,
2367 W_ERROR_HAVE_NO_MEMORY(trusts
->array
);
2369 trusts
->array
[n
].netbios_name
= talloc_steal(trusts
->array
, ldb_msg_find_attr_as_string(dom_res
[i
], "flatname", NULL
));
2370 if (!trusts
->array
[n
].netbios_name
) {
2371 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2372 "without flatname\n",
2373 ldb_dn_get_linearized(dom_res
[i
]->dn
)));
2376 trusts
->array
[n
].dns_name
= talloc_steal(trusts
->array
, ldb_msg_find_attr_as_string(dom_res
[i
], "trustPartner", NULL
));
2378 trusts
->array
[n
].trust_flags
= flags
;
2379 if ((trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) &&
2380 !(flags
& NETR_TRUST_FLAG_TREEROOT
)) {
2381 /* TODO: find if we have parent in the list */
2382 trusts
->array
[n
].parent_index
= 0;
2385 trusts
->array
[n
].trust_type
=
2386 ldb_msg_find_attr_as_uint(dom_res
[i
],
2388 trusts
->array
[n
].trust_attributes
=
2389 ldb_msg_find_attr_as_uint(dom_res
[i
],
2390 "trustAttributes", 0);
2392 if ((trusts
->array
[n
].trust_type
== LSA_TRUST_TYPE_MIT
) ||
2393 (trusts
->array
[n
].trust_type
== LSA_TRUST_TYPE_DCE
)) {
2394 struct dom_sid zero_sid
;
2395 ZERO_STRUCT(zero_sid
);
2396 trusts
->array
[n
].sid
=
2397 dom_sid_dup(trusts
, &zero_sid
);
2399 trusts
->array
[n
].sid
=
2400 samdb_result_dom_sid(trusts
, dom_res
[i
],
2401 "securityIdentifier");
2403 trusts
->array
[n
].guid
= GUID_zero();
2405 trusts
->count
= n
+ 1;
2408 talloc_free(dom_res
);
2413 netr_DsrEnumerateDomainTrusts
2415 static WERROR
dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state
*dce_call
,
2416 TALLOC_CTX
*mem_ctx
,
2417 struct netr_DsrEnumerateDomainTrusts
*r
)
2419 struct netr_DomainTrustList
*trusts
;
2420 struct ldb_context
*sam_ctx
;
2422 struct ldb_message
**dom_res
;
2423 const char * const dom_attrs
[] = { "objectSid", "objectGUID", NULL
};
2424 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
2425 const char *dnsdomain
= lpcfg_dnsdomain(lp_ctx
);
2429 if (r
->in
.trust_flags
& 0xFFFFFE00) {
2430 return WERR_INVALID_FLAGS
;
2433 /* TODO: turn to hard check once we are sure this is 100% correct */
2434 if (!r
->in
.server_name
) {
2435 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2436 "But received NULL!\n", dnsdomain
));
2438 p
= strchr(r
->in
.server_name
, '.');
2440 DEBUG(3, ("Invalid domain! Expected name in domain "
2441 "[%s]. But received [%s]!\n",
2442 dnsdomain
, r
->in
.server_name
));
2443 p
= r
->in
.server_name
;
2447 if (strcasecmp(p
, dnsdomain
)) {
2448 DEBUG(3, ("Invalid domain! Expected name in domain "
2449 "[%s]. But received [%s]!\n",
2450 dnsdomain
, r
->in
.server_name
));
2454 trusts
= talloc_zero(mem_ctx
, struct netr_DomainTrustList
);
2455 W_ERROR_HAVE_NO_MEMORY(trusts
);
2458 r
->out
.trusts
= trusts
;
2460 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
2461 dce_call
->conn
->auth_state
.session_info
, 0);
2462 if (sam_ctx
== NULL
) {
2463 return WERR_GENERAL_FAILURE
;
2466 if ((r
->in
.trust_flags
& NETR_TRUST_FLAG_INBOUND
) ||
2467 (r
->in
.trust_flags
& NETR_TRUST_FLAG_OUTBOUND
)) {
2469 werr
= fill_trusted_domains_array(mem_ctx
, sam_ctx
,
2470 trusts
, r
->in
.trust_flags
);
2471 W_ERROR_NOT_OK_RETURN(werr
);
2474 /* NOTE: we currently are always the root of the forest */
2475 if (r
->in
.trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) {
2476 uint32_t n
= trusts
->count
;
2478 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, NULL
,
2479 &dom_res
, dom_attrs
);
2481 return WERR_GENERAL_FAILURE
;
2484 trusts
->count
= n
+ 1;
2485 trusts
->array
= talloc_realloc(trusts
, trusts
->array
,
2486 struct netr_DomainTrust
,
2488 W_ERROR_HAVE_NO_MEMORY(trusts
->array
);
2490 trusts
->array
[n
].netbios_name
= lpcfg_workgroup(lp_ctx
);
2491 trusts
->array
[n
].dns_name
= lpcfg_dnsdomain(lp_ctx
);
2492 trusts
->array
[n
].trust_flags
=
2493 NETR_TRUST_FLAG_NATIVE
|
2494 NETR_TRUST_FLAG_TREEROOT
|
2495 NETR_TRUST_FLAG_IN_FOREST
|
2496 NETR_TRUST_FLAG_PRIMARY
;
2497 /* we are always the root domain for now */
2498 trusts
->array
[n
].parent_index
= 0;
2499 trusts
->array
[n
].trust_type
= LSA_TRUST_TYPE_UPLEVEL
;
2500 trusts
->array
[n
].trust_attributes
= 0;
2501 trusts
->array
[n
].sid
= samdb_result_dom_sid(mem_ctx
,
2504 trusts
->array
[n
].guid
= samdb_result_guid(dom_res
[0],
2506 talloc_free(dom_res
);
2514 netr_DsrDeregisterDNSHostRecords
2516 static WERROR
dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2517 struct netr_DsrDeregisterDNSHostRecords
*r
)
2519 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2524 netr_ServerTrustPasswordsGet
2526 static NTSTATUS
dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2527 struct netr_ServerTrustPasswordsGet
*r
)
2529 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2533 static WERROR
fill_forest_trust_array(TALLOC_CTX
*mem_ctx
,
2534 struct ldb_context
*sam_ctx
,
2535 struct loadparm_context
*lp_ctx
,
2536 struct lsa_ForestTrustInformation
*info
)
2538 struct lsa_ForestTrustDomainInfo
*domain_info
;
2539 struct lsa_ForestTrustRecord
*e
;
2540 struct ldb_message
**dom_res
;
2541 const char * const dom_attrs
[] = { "objectSid", NULL
};
2544 /* we need to provide 2 entries:
2545 * 1. the Root Forest name
2546 * 2. the Domain Information
2550 info
->entries
= talloc_array(info
, struct lsa_ForestTrustRecord
*, 2);
2551 W_ERROR_HAVE_NO_MEMORY(info
->entries
);
2553 /* Forest root info */
2554 e
= talloc(info
, struct lsa_ForestTrustRecord
);
2555 W_ERROR_HAVE_NO_MEMORY(e
);
2558 e
->type
= LSA_FOREST_TRUST_TOP_LEVEL_NAME
;
2559 e
->time
= 0; /* so far always 0 in trces. */
2560 e
->forest_trust_data
.top_level_name
.string
= samdb_forest_name(sam_ctx
,
2562 W_ERROR_HAVE_NO_MEMORY(e
->forest_trust_data
.top_level_name
.string
);
2564 info
->entries
[0] = e
;
2567 e
= talloc(info
, struct lsa_ForestTrustRecord
);
2568 W_ERROR_HAVE_NO_MEMORY(e
);
2570 /* get our own domain info */
2571 ret
= gendb_search_dn(sam_ctx
, mem_ctx
, NULL
, &dom_res
, dom_attrs
);
2573 return WERR_GENERAL_FAILURE
;
2576 /* TODO: check if disabled and set flags accordingly */
2578 e
->type
= LSA_FOREST_TRUST_DOMAIN_INFO
;
2579 e
->time
= 0; /* so far always 0 in traces. */
2581 domain_info
= &e
->forest_trust_data
.domain_info
;
2582 domain_info
->domain_sid
= samdb_result_dom_sid(info
, dom_res
[0],
2584 domain_info
->dns_domain_name
.string
= lpcfg_dnsdomain(lp_ctx
);
2585 domain_info
->netbios_domain_name
.string
= lpcfg_workgroup(lp_ctx
);
2587 info
->entries
[1] = e
;
2589 talloc_free(dom_res
);
2595 netr_DsRGetForestTrustInformation
2597 static WERROR
dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state
*dce_call
,
2598 TALLOC_CTX
*mem_ctx
,
2599 struct netr_DsRGetForestTrustInformation
*r
)
2601 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
2602 struct lsa_ForestTrustInformation
*info
, **info_ptr
;
2603 struct ldb_context
*sam_ctx
;
2606 if (r
->in
.flags
& 0xFFFFFFFE) {
2607 return WERR_INVALID_FLAGS
;
2610 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
2611 dce_call
->conn
->auth_state
.session_info
, 0);
2612 if (sam_ctx
== NULL
) {
2613 return WERR_GENERAL_FAILURE
;
2616 if (r
->in
.flags
& DS_GFTI_UPDATE_TDO
) {
2617 if (!samdb_is_pdc(sam_ctx
)) {
2618 return WERR_NERR_NOTPRIMARY
;
2621 if (r
->in
.trusted_domain_name
== NULL
) {
2622 return WERR_INVALID_FLAGS
;
2625 /* TODO: establish an schannel connection with
2626 * r->in.trusted_domain_name and perform a
2627 * netr_GetForestTrustInformation call against it */
2629 /* for now return not implementd */
2630 return WERR_CALL_NOT_IMPLEMENTED
;
2633 /* TODO: check r->in.server_name is our name */
2635 info_ptr
= talloc(mem_ctx
, struct lsa_ForestTrustInformation
*);
2636 W_ERROR_HAVE_NO_MEMORY(info_ptr
);
2638 info
= talloc_zero(info_ptr
, struct lsa_ForestTrustInformation
);
2639 W_ERROR_HAVE_NO_MEMORY(info
);
2641 werr
= fill_forest_trust_array(mem_ctx
, sam_ctx
, lp_ctx
, info
);
2642 W_ERROR_NOT_OK_RETURN(werr
);
2645 r
->out
.forest_trust_info
= info_ptr
;
2652 netr_GetForestTrustInformation
2654 static NTSTATUS
dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state
*dce_call
,
2655 TALLOC_CTX
*mem_ctx
,
2656 struct netr_GetForestTrustInformation
*r
)
2658 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
2659 struct netlogon_creds_CredentialState
*creds
;
2660 struct lsa_ForestTrustInformation
*info
, **info_ptr
;
2661 struct ldb_context
*sam_ctx
;
2665 status
= dcesrv_netr_creds_server_step_check(dce_call
,
2667 r
->in
.computer_name
,
2669 r
->out
.return_authenticator
,
2671 if (!NT_STATUS_IS_OK(status
)) {
2675 if ((creds
->secure_channel_type
!= SEC_CHAN_DNS_DOMAIN
) &&
2676 (creds
->secure_channel_type
!= SEC_CHAN_DOMAIN
)) {
2677 return NT_STATUS_NOT_IMPLEMENTED
;
2680 sam_ctx
= samdb_connect(mem_ctx
, dce_call
->event_ctx
, lp_ctx
,
2681 dce_call
->conn
->auth_state
.session_info
, 0);
2682 if (sam_ctx
== NULL
) {
2683 return NT_STATUS_INTERNAL_ERROR
;
2686 /* TODO: check r->in.server_name is our name */
2688 info_ptr
= talloc(mem_ctx
, struct lsa_ForestTrustInformation
*);
2690 return NT_STATUS_NO_MEMORY
;
2692 info
= talloc_zero(info_ptr
, struct lsa_ForestTrustInformation
);
2694 return NT_STATUS_NO_MEMORY
;
2697 werr
= fill_forest_trust_array(mem_ctx
, sam_ctx
, lp_ctx
, info
);
2698 if (!W_ERROR_IS_OK(werr
)) {
2699 return werror_to_ntstatus(werr
);
2703 r
->out
.forest_trust_info
= info_ptr
;
2705 return NT_STATUS_OK
;
2710 netr_ServerGetTrustInfo
2712 static NTSTATUS
dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2713 struct netr_ServerGetTrustInfo
*r
)
2715 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2721 static NTSTATUS
dcesrv_netr_Unused47(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
2722 struct netr_Unused47
*r
)
2724 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR
);
2728 struct netr_dnsupdate_RODC_state
{
2729 struct dcesrv_call_state
*dce_call
;
2730 struct netr_DsrUpdateReadOnlyServerDnsRecords
*r
;
2731 struct dnsupdate_RODC
*r2
;
2735 called when the forwarded RODC dns update request is finished
2737 static void netr_dnsupdate_RODC_callback(struct tevent_req
*subreq
)
2739 struct netr_dnsupdate_RODC_state
*st
=
2740 tevent_req_callback_data(subreq
,
2741 struct netr_dnsupdate_RODC_state
);
2744 status
= dcerpc_dnsupdate_RODC_r_recv(subreq
, st
->dce_call
);
2745 TALLOC_FREE(subreq
);
2746 if (!NT_STATUS_IS_OK(status
)) {
2747 DEBUG(0,(__location__
": IRPC callback failed %s\n", nt_errstr(status
)));
2748 st
->dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
2751 st
->r
->out
.dns_names
= talloc_steal(st
->dce_call
, st
->r2
->out
.dns_names
);
2753 status
= dcesrv_reply(st
->dce_call
);
2754 if (!NT_STATUS_IS_OK(status
)) {
2755 DEBUG(0,(__location__
": dcesrv_reply() failed - %s\n", nt_errstr(status
)));
2760 netr_DsrUpdateReadOnlyServerDnsRecords
2762 static NTSTATUS
dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state
*dce_call
,
2763 TALLOC_CTX
*mem_ctx
,
2764 struct netr_DsrUpdateReadOnlyServerDnsRecords
*r
)
2766 struct netlogon_creds_CredentialState
*creds
;
2768 struct dcerpc_binding_handle
*binding_handle
;
2769 struct netr_dnsupdate_RODC_state
*st
;
2770 struct tevent_req
*subreq
;
2772 nt_status
= dcesrv_netr_creds_server_step_check(dce_call
,
2774 r
->in
.computer_name
,
2776 r
->out
.return_authenticator
,
2778 NT_STATUS_NOT_OK_RETURN(nt_status
);
2780 if (creds
->secure_channel_type
!= SEC_CHAN_RODC
) {
2781 return NT_STATUS_ACCESS_DENIED
;
2784 st
= talloc_zero(mem_ctx
, struct netr_dnsupdate_RODC_state
);
2785 NT_STATUS_HAVE_NO_MEMORY(st
);
2787 st
->dce_call
= dce_call
;
2789 st
->r2
= talloc_zero(st
, struct dnsupdate_RODC
);
2790 NT_STATUS_HAVE_NO_MEMORY(st
->r2
);
2792 st
->r2
->in
.dom_sid
= creds
->sid
;
2793 st
->r2
->in
.site_name
= r
->in
.site_name
;
2794 st
->r2
->in
.dns_ttl
= r
->in
.dns_ttl
;
2795 st
->r2
->in
.dns_names
= r
->in
.dns_names
;
2796 st
->r2
->out
.dns_names
= r
->out
.dns_names
;
2798 binding_handle
= irpc_binding_handle_by_name(st
, dce_call
->msg_ctx
,
2799 "dnsupdate", &ndr_table_irpc
);
2800 if (binding_handle
== NULL
) {
2801 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2802 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
2803 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2806 /* forward the call */
2807 subreq
= dcerpc_dnsupdate_RODC_r_send(st
, dce_call
->event_ctx
,
2808 binding_handle
, st
->r2
);
2809 NT_STATUS_HAVE_NO_MEMORY(subreq
);
2811 dce_call
->state_flags
|= DCESRV_CALL_STATE_FLAG_ASYNC
;
2813 /* setup the callback */
2814 tevent_req_set_callback(subreq
, netr_dnsupdate_RODC_callback
, st
);
2816 return NT_STATUS_OK
;
2820 /* include the generated boilerplate */
2821 #include "librpc/gen_ndr/ndr_netlogon_s.c"