2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) Tim Potter 2000-2001
7 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "lib/util_unixsids.h"
27 #include "../libcli/security/security.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "passdb/machine_sid.h"
31 #include "source4/lib/messaging/messaging.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "auth/credentials/credentials.h"
35 #include "libsmb/samlogon_cache.h"
36 #include "lib/util/smb_strtox.h"
37 #include "lib/util/string_wrappers.h"
38 #include "lib/global_contexts.h"
39 #include "librpc/gen_ndr/ndr_winbind_c.h"
42 #define DBGC_CLASS DBGC_WINBIND
45 * @file winbindd_util.c
47 * Winbind daemon for NT domain authentication nss module.
50 /* The list of trusted domains. Note that the list can be deleted and
51 recreated using the init_domain_list() function so pointers to
52 individual winbindd_domain structures cannot be made. Keep a copy of
53 the domain name instead. */
55 static struct winbindd_domain
*_domain_list
= NULL
;
57 struct winbindd_domain
*domain_list(void)
61 if ((!_domain_list
) && (!init_domain_list())) {
62 smb_panic("Init_domain_list failed");
68 /* Free all entries in the trusted domain list */
70 static void free_domain_list(void)
72 struct winbindd_domain
*domain
= _domain_list
;
75 struct winbindd_domain
*next
= domain
->next
;
77 DLIST_REMOVE(_domain_list
, domain
);
84 * Iterator for winbindd's domain list.
85 * To be used (e.g.) in tevent based loops.
87 struct winbindd_domain
*wb_next_domain(struct winbindd_domain
*domain
)
90 domain
= domain_list();
92 domain
= domain
->next
;
95 if ((domain
!= NULL
) &&
96 (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC
) &&
97 sid_check_is_our_sam(&domain
->sid
))
99 domain
= domain
->next
;
105 static bool is_internal_domain(const struct dom_sid
*sid
)
110 return (sid_check_is_our_sam(sid
) || sid_check_is_builtin(sid
));
113 /* Add a trusted domain to our list of domains.
114 If the domain already exists in the list,
115 return it and don't re-initialize. */
117 static NTSTATUS
add_trusted_domain(const char *domain_name
,
118 const char *dns_name
,
119 const struct dom_sid
*sid
,
121 uint32_t trust_flags
,
122 uint32_t trust_attribs
,
123 enum netr_SchannelType secure_channel_type
,
124 struct winbindd_domain
*routing_domain
,
125 struct winbindd_domain
**_d
)
127 struct winbindd_domain
*domain
= NULL
;
128 int role
= lp_server_role();
129 struct dom_sid_buf buf
;
131 if (is_null_sid(sid
)) {
132 DBG_ERR("Got null SID for domain [%s]\n", domain_name
);
133 return NT_STATUS_INVALID_PARAMETER
;
136 if (secure_channel_type
== SEC_CHAN_NULL
&& !is_allowed_domain(domain_name
)) {
137 return NT_STATUS_NO_SUCH_DOMAIN
;
141 * We can't call domain_list() as this function is called from
142 * init_domain_list() and we'll get stuck in a loop.
144 for (domain
= _domain_list
; domain
; domain
= domain
->next
) {
145 if (strequal(domain_name
, domain
->name
)) {
150 if (domain
!= NULL
) {
151 struct winbindd_domain
*check_domain
= NULL
;
153 for (check_domain
= _domain_list
;
154 check_domain
!= NULL
;
155 check_domain
= check_domain
->next
)
157 if (check_domain
== domain
) {
161 if (dom_sid_equal(&check_domain
->sid
, sid
)) {
166 if (check_domain
!= NULL
) {
167 DBG_ERR("SID [%s] already used by domain [%s], "
169 dom_sid_str_buf(sid
, &buf
),
172 return NT_STATUS_INVALID_PARAMETER
;
176 if ((domain
!= NULL
) && (dns_name
!= NULL
)) {
177 struct winbindd_domain
*check_domain
= NULL
;
179 for (check_domain
= _domain_list
;
180 check_domain
!= NULL
;
181 check_domain
= check_domain
->next
)
183 if (check_domain
== domain
) {
187 if (strequal(check_domain
->alt_name
, dns_name
)) {
192 if (check_domain
!= NULL
) {
193 DBG_ERR("DNS name [%s] used by domain [%s], "
195 dns_name
, check_domain
->name
,
197 return NT_STATUS_INVALID_PARAMETER
;
201 if (domain
!= NULL
) {
206 /* Create new domain entry */
207 domain
= talloc_zero(NULL
, struct winbindd_domain
);
208 if (domain
== NULL
) {
209 return NT_STATUS_NO_MEMORY
;
212 domain
->children
= talloc_zero_array(domain
,
213 struct winbindd_child
,
214 lp_winbind_max_domain_connections());
215 if (domain
->children
== NULL
) {
217 return NT_STATUS_NO_MEMORY
;
220 domain
->queue
= tevent_queue_create(domain
, "winbind_domain");
221 if (domain
->queue
== NULL
) {
223 return NT_STATUS_NO_MEMORY
;
226 domain
->binding_handle
= wbint_binding_handle(domain
, domain
, NULL
);
227 if (domain
->binding_handle
== NULL
) {
229 return NT_STATUS_NO_MEMORY
;
232 domain
->name
= talloc_strdup(domain
, domain_name
);
233 if (domain
->name
== NULL
) {
235 return NT_STATUS_NO_MEMORY
;
238 if (dns_name
!= NULL
) {
239 domain
->alt_name
= talloc_strdup(domain
, dns_name
);
240 if (domain
->alt_name
== NULL
) {
242 return NT_STATUS_NO_MEMORY
;
246 domain
->backend
= NULL
;
247 domain
->internal
= is_internal_domain(sid
);
248 domain
->secure_channel_type
= secure_channel_type
;
249 domain
->sequence_number
= DOM_SEQUENCE_NONE
;
250 domain
->last_seq_check
= 0;
251 domain
->initialized
= false;
252 domain
->online
= is_internal_domain(sid
);
253 domain
->domain_flags
= trust_flags
;
254 domain
->domain_type
= trust_type
;
255 domain
->domain_trust_attribs
= trust_attribs
;
256 domain
->routing_domain
= routing_domain
;
257 sid_copy(&domain
->sid
, sid
);
259 /* Is this our primary domain ? */
260 if (role
== ROLE_DOMAIN_MEMBER
) {
261 domain
->primary
= strequal(domain_name
, lp_workgroup());
263 domain
->primary
= strequal(domain_name
, get_global_sam_name());
266 if (domain
->primary
) {
267 if (role
== ROLE_ACTIVE_DIRECTORY_DC
) {
268 domain
->active_directory
= true;
270 if (lp_security() == SEC_ADS
) {
271 domain
->active_directory
= true;
273 } else if (!domain
->internal
) {
274 if (domain
->domain_type
== LSA_TRUST_TYPE_UPLEVEL
) {
275 domain
->active_directory
= true;
279 domain
->can_do_ncacn_ip_tcp
= domain
->active_directory
;
281 if (secure_channel_type
!= SEC_CHAN_NULL
) {
283 * If we loaded the domain from
284 * our config it is initialized
287 domain
->initialized
= true;
290 /* Link to domain list */
291 DLIST_ADD_END(_domain_list
, domain
);
293 wcache_tdc_add_domain( domain
);
295 setup_domain_child(domain
);
297 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
298 domain
->name
, domain
->alt_name
,
299 dom_sid_str_buf(&domain
->sid
, &buf
));
305 bool set_routing_domain(struct winbindd_domain
*domain
,
306 struct winbindd_domain
*routing_domain
)
308 if (domain
->routing_domain
== NULL
) {
309 domain
->routing_domain
= routing_domain
;
312 if (domain
->routing_domain
!= routing_domain
) {
318 bool add_trusted_domain_from_auth(uint16_t validation_level
,
319 struct info3_text
*info3
,
320 struct info6_text
*info6
)
322 struct winbindd_domain
*domain
= NULL
;
323 struct dom_sid domain_sid
;
324 const char *dns_domainname
= NULL
;
329 * We got a successful auth from a domain that might not yet be in our
330 * domain list. If we're a member we trust our DC who authenticated the
331 * user from that domain and add the domain to our list on-the-fly. If
332 * we're a DC we rely on configured trusts and don't add on-the-fly.
339 ok
= dom_sid_parse(info3
->dom_sid
, &domain_sid
);
341 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3
->dom_sid
);
345 if (validation_level
== 6) {
346 if (!strequal(info6
->dns_domainname
, "")) {
347 dns_domainname
= info6
->dns_domainname
;
351 status
= add_trusted_domain(info3
->logon_dom
,
355 NETR_TRUST_FLAG_OUTBOUND
,
358 find_default_route_domain(),
360 if (!NT_STATUS_IS_OK(status
) &&
361 !NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_DOMAIN
))
363 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
364 info3
->logon_dom
, info3
->dom_sid
);
371 bool domain_is_forest_root(const struct winbindd_domain
*domain
)
373 const uint32_t fr_flags
=
374 (NETR_TRUST_FLAG_TREEROOT
|NETR_TRUST_FLAG_IN_FOREST
);
376 return ((domain
->domain_flags
& fr_flags
) == fr_flags
);
379 /********************************************************************
380 rescan our domains looking for new trusted domains
381 ********************************************************************/
383 struct trustdom_state
{
384 struct winbindd_domain
*domain
;
385 struct netr_DomainTrustList trusts
;
388 static void trustdom_list_done(struct tevent_req
*req
);
389 static void rescan_forest_root_trusts( void );
390 static void rescan_forest_trusts( void );
392 static void add_trusted_domains( struct winbindd_domain
*domain
)
394 struct tevent_context
*ev
= global_event_context();
395 struct trustdom_state
*state
;
396 struct tevent_req
*req
;
397 const char *client_name
= NULL
;
400 state
= talloc_zero(NULL
, struct trustdom_state
);
402 DEBUG(0, ("talloc failed\n"));
405 state
->domain
= domain
;
407 /* Called from timer, not from a real client */
408 client_name
= getprogname();
409 client_pid
= getpid();
411 req
= dcerpc_wbint_ListTrustedDomains_send(state
,
413 dom_child_handle(domain
),
418 DBG_ERR("dcerpc_wbint_ListTrustedDomains_send failed\n");
422 tevent_req_set_callback(req
, trustdom_list_done
, state
);
425 static void trustdom_list_done(struct tevent_req
*req
)
427 struct trustdom_state
*state
= tevent_req_callback_data(
428 req
, struct trustdom_state
);
429 bool within_forest
= false;
430 NTSTATUS status
, result
;
434 * Only when we enumerate our primary domain
435 * or our forest root domain, we should keep
436 * the NETR_TRUST_FLAG_IN_FOREST flag, in
437 * all other cases we need to clear it as the domain
438 * is not part of our forest.
440 if (state
->domain
->primary
) {
441 within_forest
= true;
442 } else if (domain_is_forest_root(state
->domain
)) {
443 within_forest
= true;
446 status
= dcerpc_wbint_ListTrustedDomains_recv(req
, state
, &result
);
447 if (any_nt_status_not_ok(status
, result
, &status
)) {
448 DBG_WARNING("Could not receive trusts for domain %s: %s-%s\n",
449 state
->domain
->name
, nt_errstr(status
),
455 for (i
=0; i
<state
->trusts
.count
; i
++) {
456 struct netr_DomainTrust
*trust
= &state
->trusts
.array
[i
];
457 struct winbindd_domain
*domain
= NULL
;
459 if (!within_forest
) {
460 trust
->trust_flags
&= ~NETR_TRUST_FLAG_IN_FOREST
;
463 if (!state
->domain
->primary
) {
464 trust
->trust_flags
&= ~NETR_TRUST_FLAG_PRIMARY
;
468 * We always call add_trusted_domain() cause on an existing
469 * domain structure, it will update the SID if necessary.
470 * This is important because we need the SID for sibling
473 status
= add_trusted_domain(trust
->netbios_name
,
478 trust
->trust_attributes
,
480 find_default_route_domain(),
482 if (!NT_STATUS_IS_OK(status
) &&
483 !NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_DOMAIN
))
485 DBG_NOTICE("add_trusted_domain returned %s\n",
492 Cases to consider when scanning trusts:
493 (a) we are calling from a child domain (primary && !forest_root)
494 (b) we are calling from the root of the forest (primary && forest_root)
495 (c) we are calling from a trusted forest domain (!primary
499 if (state
->domain
->primary
) {
500 /* If this is our primary domain and we are not in the
501 forest root, we have to scan the root trusts first */
503 if (!domain_is_forest_root(state
->domain
))
504 rescan_forest_root_trusts();
506 rescan_forest_trusts();
508 } else if (domain_is_forest_root(state
->domain
)) {
509 /* Once we have done root forest trust search, we can
510 go on to search the trusted forests */
512 rescan_forest_trusts();
520 /********************************************************************
521 Scan the trusts of our forest root
522 ********************************************************************/
524 static void rescan_forest_root_trusts( void )
526 struct winbindd_tdc_domain
*dom_list
= NULL
;
527 size_t num_trusts
= 0;
531 /* The only transitive trusts supported by Windows 2003 AD are
532 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
533 first two are handled in forest and listed by
534 DsEnumerateDomainTrusts(). Forest trusts are not so we
535 have to do that ourselves. */
537 if ( !wcache_tdc_fetch_list( &dom_list
, &num_trusts
) )
540 for ( i
=0; i
<num_trusts
; i
++ ) {
541 struct winbindd_domain
*d
= NULL
;
543 /* Find the forest root. Don't necessarily trust
544 the domain_list() as our primary domain may not
545 have been initialized. */
547 if ( !(dom_list
[i
].trust_flags
& NETR_TRUST_FLAG_TREEROOT
) ) {
551 /* Here's the forest root */
553 d
= find_domain_from_name_noinit( dom_list
[i
].domain_name
);
555 status
= add_trusted_domain(dom_list
[i
].domain_name
,
556 dom_list
[i
].dns_name
,
558 dom_list
[i
].trust_type
,
559 dom_list
[i
].trust_flags
,
560 dom_list
[i
].trust_attribs
,
562 find_default_route_domain(),
565 if (!NT_STATUS_IS_OK(status
) &&
566 NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_DOMAIN
))
568 DBG_ERR("add_trusted_domain returned %s\n",
577 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
578 "for domain tree root %s (%s)\n",
579 d
->name
, d
->alt_name
));
581 d
->domain_flags
= dom_list
[i
].trust_flags
;
582 d
->domain_type
= dom_list
[i
].trust_type
;
583 d
->domain_trust_attribs
= dom_list
[i
].trust_attribs
;
585 add_trusted_domains( d
);
590 TALLOC_FREE( dom_list
);
595 /********************************************************************
596 scan the transitive forest trusts (not our own)
597 ********************************************************************/
600 static void rescan_forest_trusts( void )
602 struct winbindd_domain
*d
= NULL
;
603 struct winbindd_tdc_domain
*dom_list
= NULL
;
604 size_t num_trusts
= 0;
608 /* The only transitive trusts supported by Windows 2003 AD are
609 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
610 first two are handled in forest and listed by
611 DsEnumerateDomainTrusts(). Forest trusts are not so we
612 have to do that ourselves. */
614 if ( !wcache_tdc_fetch_list( &dom_list
, &num_trusts
) )
617 for ( i
=0; i
<num_trusts
; i
++ ) {
618 uint32_t flags
= dom_list
[i
].trust_flags
;
619 uint32_t type
= dom_list
[i
].trust_type
;
620 uint32_t attribs
= dom_list
[i
].trust_attribs
;
622 d
= find_domain_from_name_noinit( dom_list
[i
].domain_name
);
624 /* ignore our primary and internal domains */
626 if ( d
&& (d
->internal
|| d
->primary
) )
629 if ( (flags
& NETR_TRUST_FLAG_INBOUND
) &&
630 (type
== LSA_TRUST_TYPE_UPLEVEL
) &&
631 (attribs
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) )
633 /* add the trusted domain if we don't know
637 status
= add_trusted_domain(
638 dom_list
[i
].domain_name
,
639 dom_list
[i
].dns_name
,
645 find_default_route_domain(),
647 if (!NT_STATUS_IS_OK(status
) &&
648 NT_STATUS_EQUAL(status
,
649 NT_STATUS_NO_SUCH_DOMAIN
))
651 DBG_ERR("add_trusted_domain: %s\n",
661 DEBUG(10,("Following trust path for domain %s (%s)\n",
662 d
->name
, d
->alt_name
));
663 add_trusted_domains( d
);
667 TALLOC_FREE( dom_list
);
672 /*********************************************************************
673 The process of updating the trusted domain list is a three step
676 (b) ask the root domain in our forest
677 (c) ask a DC in any Win2003 trusted forests
678 *********************************************************************/
680 void rescan_trusted_domains(struct tevent_context
*ev
, struct tevent_timer
*te
,
681 struct timeval now
, void *private_data
)
685 /* I used to clear the cache here and start over but that
686 caused problems in child processes that needed the
687 trust dom list early on. Removing it means we
688 could have some trusted domains listed that have been
689 removed from our primary domain's DC until a full
690 restart. This should be ok since I think this is what
691 Windows does as well. */
693 /* this will only add new domains we didn't already know about
694 in the domain_list()*/
696 add_trusted_domains( find_our_domain() );
698 te
= tevent_add_timer(
699 ev
, NULL
, timeval_current_ofs(WINBINDD_RESCAN_FREQ
, 0),
700 rescan_trusted_domains
, NULL
);
702 * If te == NULL, there's not much we can do here. Don't fail, the
703 * only thing we miss is new trusted domains.
709 static void wbd_ping_dc_done(struct tevent_req
*subreq
);
711 void winbindd_ping_offline_domains(struct tevent_context
*ev
,
712 struct tevent_timer
*te
,
716 struct winbindd_domain
*domain
= NULL
;
720 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
721 DBG_DEBUG("Domain %s is %s\n",
723 domain
->online
? "online" : "offline");
725 if (get_global_winbindd_state_offline()) {
726 DBG_DEBUG("We are globally offline, do nothing.\n");
730 if (domain
->online
||
731 domain
->check_online_event
!= NULL
||
732 domain
->secure_channel_type
== SEC_CHAN_NULL
) {
736 winbindd_flush_negative_conn_cache(domain
);
738 domain
->check_online_event
=
739 dcerpc_wbint_PingDc_send(domain
,
741 dom_child_handle(domain
),
742 &domain
->ping_dcname
);
743 if (domain
->check_online_event
== NULL
) {
744 DBG_WARNING("Failed to schedule ping, no-memory\n");
748 tevent_req_set_callback(domain
->check_online_event
,
749 wbd_ping_dc_done
, domain
);
752 te
= tevent_add_timer(ev
,
754 timeval_current_ofs(lp_winbind_reconnect_delay(),
756 winbindd_ping_offline_domains
,
759 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
765 static void wbd_ping_dc_done(struct tevent_req
*subreq
)
767 struct winbindd_domain
*domain
=
768 tevent_req_callback_data(subreq
,
769 struct winbindd_domain
);
770 NTSTATUS status
, result
;
772 SMB_ASSERT(subreq
== domain
->check_online_event
);
773 domain
->check_online_event
= NULL
;
775 status
= dcerpc_wbint_PingDc_recv(subreq
, domain
, &result
);
777 if (any_nt_status_not_ok(status
, result
, &status
)) {
778 DBG_WARNING("dcerpc_wbint_PingDc_recv failed for domain: "
785 DBG_DEBUG("dcerpc_wbint_PingDc_recv() succeeded, "
786 "domain: %s, dc-name: %s\n",
788 domain
->ping_dcname
);
790 talloc_free(discard_const(domain
->ping_dcname
));
791 domain
->ping_dcname
= NULL
;
796 static void wb_imsg_new_trusted_domain(struct imessaging_context
*msg
,
799 struct server_id server_id
,
807 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds
);
811 DBG_NOTICE("Rescanning trusted domains\n");
813 ok
= add_trusted_domains_dc();
815 DBG_ERR("Failed to reload trusted domains\n");
820 * We did not get the secret when we queried secrets.tdb, so read it
821 * from secrets.tdb and re-sync the databases
823 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain
*domain
)
826 struct cli_credentials
*creds
;
827 NTSTATUS can_migrate
= pdb_get_trust_credentials(domain
->name
,
828 NULL
, domain
, &creds
);
829 if (!NT_STATUS_IS_OK(can_migrate
)) {
830 DEBUG(0, ("Failed to fetch our own local AD domain join "
831 "password for winbindd's internal use, both from "
832 "secrets.tdb and secrets.ldb: %s\n",
833 nt_errstr(can_migrate
)));
838 * NOTE: It is very unlikely we end up here if there is an
839 * oldpass, because a new password is created at
840 * classicupgrade, so this is not a concern.
842 ok
= secrets_store_machine_pw_sync(cli_credentials_get_password(creds
),
844 cli_credentials_get_domain(creds
),
845 cli_credentials_get_realm(creds
),
846 cli_credentials_get_salt_principal(creds
, creds
),
847 0, /* Supported enc types, unused */
849 cli_credentials_get_password_last_changed_time(creds
),
850 cli_credentials_get_secure_channel_type(creds
),
851 false /* do_delete: Do not delete */);
854 DEBUG(0, ("Failed to write our own "
855 "local AD domain join password for "
856 "winbindd's internal use into secrets.tdb\n"));
862 bool add_trusted_domains_dc(void)
864 struct winbindd_domain
*domain
= NULL
;
865 struct pdb_trusted_domain
**domains
= NULL
;
866 uint32_t num_domains
= 0;
870 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX
)) {
871 struct trustdom_info
**ti
= NULL
;
873 status
= pdb_enum_trusteddoms(talloc_tos(), &num_domains
, &ti
);
874 if (!NT_STATUS_IS_OK(status
)) {
875 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
880 for (i
= 0; i
< num_domains
; i
++) {
881 status
= add_trusted_domain(ti
[i
]->name
,
884 LSA_TRUST_TYPE_DOWNLEVEL
,
885 NETR_TRUST_FLAG_OUTBOUND
,
890 if (!NT_STATUS_IS_OK(status
)) {
891 DBG_NOTICE("add_trusted_domain returned %s\n",
900 status
= pdb_enum_trusted_domains(talloc_tos(), &num_domains
, &domains
);
901 if (!NT_STATUS_IS_OK(status
)) {
902 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
907 for (i
= 0; i
< num_domains
; i
++) {
908 enum netr_SchannelType sec_chan_type
= SEC_CHAN_DOMAIN
;
909 uint32_t trust_flags
= 0;
911 if (domains
[i
]->trust_type
== LSA_TRUST_TYPE_UPLEVEL
) {
912 sec_chan_type
= SEC_CHAN_DNS_DOMAIN
;
915 if (!(domains
[i
]->trust_direction
& LSA_TRUST_DIRECTION_OUTBOUND
)) {
916 sec_chan_type
= SEC_CHAN_NULL
;
919 if (domains
[i
]->trust_direction
& LSA_TRUST_DIRECTION_INBOUND
) {
920 trust_flags
|= NETR_TRUST_FLAG_INBOUND
;
922 if (domains
[i
]->trust_direction
& LSA_TRUST_DIRECTION_OUTBOUND
) {
923 trust_flags
|= NETR_TRUST_FLAG_OUTBOUND
;
925 if (domains
[i
]->trust_attributes
& LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
) {
926 trust_flags
|= NETR_TRUST_FLAG_IN_FOREST
;
929 if (domains
[i
]->trust_attributes
& LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION
) {
931 * We don't support selective authentication yet.
933 DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
935 domains
[i
]->netbios_name
,
936 domains
[i
]->domain_name
);
940 status
= add_trusted_domain(domains
[i
]->netbios_name
,
941 domains
[i
]->domain_name
,
942 &domains
[i
]->security_identifier
,
943 domains
[i
]->trust_type
,
945 domains
[i
]->trust_attributes
,
949 if (!NT_STATUS_IS_OK(status
)) {
950 DBG_NOTICE("add_trusted_domain returned %s\n",
955 if (domains
[i
]->trust_type
== LSA_TRUST_TYPE_UPLEVEL
) {
956 domain
->active_directory
= true;
958 domain
->domain_type
= domains
[i
]->trust_type
;
959 domain
->domain_trust_attribs
= domains
[i
]->trust_attributes
;
962 for (i
= 0; i
< num_domains
; i
++) {
963 struct ForestTrustInfo fti
;
965 enum ndr_err_code ndr_err
;
966 struct winbindd_domain
*routing_domain
= NULL
;
968 if (domains
[i
]->trust_type
!= LSA_TRUST_TYPE_UPLEVEL
) {
972 if (!(domains
[i
]->trust_attributes
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
)) {
976 if (domains
[i
]->trust_forest_trust_info
.length
== 0) {
980 routing_domain
= find_domain_from_name_noinit(
981 domains
[i
]->netbios_name
);
982 if (routing_domain
== NULL
) {
983 DBG_ERR("Can't find winbindd domain [%s]\n",
984 domains
[i
]->netbios_name
);
988 ndr_err
= ndr_pull_struct_blob_all(
989 &domains
[i
]->trust_forest_trust_info
,
991 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
);
992 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
993 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
994 domains
[i
]->netbios_name
,
995 ndr_map_error2string(ndr_err
));
999 for (fi
= 0; fi
< fti
.count
; fi
++) {
1000 struct ForestTrustInfoRecord
*rec
=
1001 &fti
.records
[fi
].record
;
1002 struct ForestTrustDataDomainInfo
*drec
= NULL
;
1004 if (rec
->type
!= FOREST_TRUST_DOMAIN_INFO
) {
1007 drec
= &rec
->data
.info
;
1009 if (rec
->flags
& LSA_NB_DISABLED_MASK
) {
1013 if (rec
->flags
& LSA_SID_DISABLED_MASK
) {
1019 * also try to find a matching
1020 * LSA_TLN_DISABLED_MASK ???
1023 domain
= find_domain_from_name_noinit(drec
->netbios_name
.string
);
1024 if (domain
!= NULL
) {
1028 status
= add_trusted_domain(drec
->netbios_name
.string
,
1029 drec
->dns_name
.string
,
1031 LSA_TRUST_TYPE_UPLEVEL
,
1032 NETR_TRUST_FLAG_OUTBOUND
,
1037 if (!NT_STATUS_IS_OK(status
)) {
1038 DBG_NOTICE("add_trusted_domain returned %s\n",
1042 if (domain
== NULL
) {
1052 /* Look up global info for the winbind daemon */
1053 bool init_domain_list(void)
1055 int role
= lp_server_role();
1056 struct pdb_domain_info
*pdb_domain_info
= NULL
;
1057 struct winbindd_domain
*domain
= NULL
;
1061 /* Free existing list */
1064 /* BUILTIN domain */
1066 status
= add_trusted_domain("BUILTIN",
1068 &global_sid_Builtin
,
1069 LSA_TRUST_TYPE_DOWNLEVEL
,
1070 0, /* trust_flags */
1071 0, /* trust_attribs */
1075 if (!NT_STATUS_IS_OK(status
)) {
1076 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1084 * In case the passdb backend is passdb_dsdb the domain SID comes from
1085 * dsdb, not from secrets.tdb. As we use the domain SID in various
1086 * places, we must ensure the domain SID is migrated from dsdb to
1087 * secrets.tdb before get_global_sam_sid() is called the first time.
1089 * The migration is done as part of the passdb_dsdb initialisation,
1090 * calling pdb_get_domain_info() triggers it.
1092 pdb_domain_info
= pdb_get_domain_info(talloc_tos());
1094 if ( role
== ROLE_ACTIVE_DIRECTORY_DC
) {
1095 uint32_t trust_flags
;
1097 enum netr_SchannelType sec_chan_type
;
1098 const char *account_name
;
1099 struct samr_Password current_nt_hash
;
1101 if (pdb_domain_info
== NULL
) {
1102 DEBUG(0, ("Failed to fetch our own local AD "
1103 "domain info from sam.ldb\n"));
1107 trust_flags
= NETR_TRUST_FLAG_PRIMARY
;
1108 trust_flags
|= NETR_TRUST_FLAG_IN_FOREST
;
1109 trust_flags
|= NETR_TRUST_FLAG_NATIVE
;
1110 trust_flags
|= NETR_TRUST_FLAG_OUTBOUND
;
1112 is_root
= strequal(pdb_domain_info
->dns_domain
,
1113 pdb_domain_info
->dns_forest
);
1115 trust_flags
|= NETR_TRUST_FLAG_TREEROOT
;
1118 status
= add_trusted_domain(pdb_domain_info
->name
,
1119 pdb_domain_info
->dns_domain
,
1120 &pdb_domain_info
->sid
,
1121 LSA_TRUST_TYPE_UPLEVEL
,
1123 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
,
1127 TALLOC_FREE(pdb_domain_info
);
1128 if (!NT_STATUS_IS_OK(status
)) {
1129 DBG_ERR("Failed to add our own local AD "
1130 "domain to winbindd's internal list\n");
1135 * We need to call this to find out if we are an RODC
1137 ok
= get_trust_pw_hash(domain
->name
,
1138 current_nt_hash
.hash
,
1143 * If get_trust_pw_hash() fails, then try and
1144 * fetch the password from the more recent of
1145 * secrets.{ldb,tdb} using the
1146 * pdb_get_trust_credentials()
1148 ok
= migrate_secrets_tdb_to_ldb(domain
);
1151 DEBUG(0, ("Failed to migrate our own "
1152 "local AD domain join password for "
1153 "winbindd's internal use into "
1157 ok
= get_trust_pw_hash(domain
->name
,
1158 current_nt_hash
.hash
,
1162 DEBUG(0, ("Failed to find our own just "
1163 "written local AD domain join "
1164 "password for winbindd's internal "
1165 "use in secrets.tdb\n"));
1170 domain
->secure_channel_type
= sec_chan_type
;
1171 if (sec_chan_type
== SEC_CHAN_RODC
) {
1172 domain
->rodc
= true;
1176 uint32_t trust_flags
;
1177 enum netr_SchannelType secure_channel_type
;
1179 trust_flags
= NETR_TRUST_FLAG_OUTBOUND
;
1180 if (role
!= ROLE_DOMAIN_MEMBER
) {
1181 trust_flags
|= NETR_TRUST_FLAG_PRIMARY
;
1184 if (role
> ROLE_DOMAIN_MEMBER
) {
1185 secure_channel_type
= SEC_CHAN_BDC
;
1187 secure_channel_type
= SEC_CHAN_LOCAL
;
1190 if ((pdb_domain_info
!= NULL
) && (role
== ROLE_IPA_DC
)) {
1191 /* This is IPA DC that presents itself as
1192 * an Active Directory domain controller to trusted AD
1193 * forests but in fact is a classic domain controller.
1195 trust_flags
= NETR_TRUST_FLAG_PRIMARY
;
1196 trust_flags
|= NETR_TRUST_FLAG_IN_FOREST
;
1197 trust_flags
|= NETR_TRUST_FLAG_NATIVE
;
1198 trust_flags
|= NETR_TRUST_FLAG_OUTBOUND
;
1199 trust_flags
|= NETR_TRUST_FLAG_TREEROOT
;
1200 status
= add_trusted_domain(pdb_domain_info
->name
,
1201 pdb_domain_info
->dns_domain
,
1202 &pdb_domain_info
->sid
,
1203 LSA_TRUST_TYPE_UPLEVEL
,
1205 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
,
1206 secure_channel_type
,
1209 TALLOC_FREE(pdb_domain_info
);
1211 status
= add_trusted_domain(get_global_sam_name(),
1213 get_global_sam_sid(),
1214 LSA_TRUST_TYPE_DOWNLEVEL
,
1216 0, /* trust_attribs */
1217 secure_channel_type
,
1221 if (!NT_STATUS_IS_OK(status
)) {
1222 DBG_ERR("Failed to add local SAM to "
1223 "domain to winbindd's internal list\n");
1229 ok
= add_trusted_domains_dc();
1231 DBG_ERR("init_domain_list_dc failed\n");
1236 if ( role
== ROLE_DOMAIN_MEMBER
) {
1237 struct dom_sid our_sid
;
1238 uint32_t trust_type
;
1240 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid
)) {
1241 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1245 if (lp_realm() != NULL
) {
1246 trust_type
= LSA_TRUST_TYPE_UPLEVEL
;
1248 trust_type
= LSA_TRUST_TYPE_DOWNLEVEL
;
1251 status
= add_trusted_domain(lp_workgroup(),
1255 NETR_TRUST_FLAG_PRIMARY
|
1256 NETR_TRUST_FLAG_OUTBOUND
,
1257 0, /* trust_attribs */
1261 if (!NT_STATUS_IS_OK(status
)) {
1262 DBG_ERR("Failed to add local SAM to "
1263 "domain to winbindd's internal list\n");
1268 status
= imessaging_register(winbind_imessaging_context(), NULL
,
1269 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS
,
1270 wb_imsg_new_trusted_domain
);
1271 if (!NT_STATUS_IS_OK(status
)) {
1272 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status
));
1280 * Given a domain name, return the struct winbindd domain info for it
1282 * @note Do *not* pass lp_workgroup() to this function. domain_list
1283 * may modify it's value, and free that pointer. Instead, our local
1284 * domain may be found by calling find_our_domain().
1288 * @return The domain structure for the named domain, if it is working.
1291 struct winbindd_domain
*find_domain_from_name_noinit(const char *domain_name
)
1293 struct winbindd_domain
*domain
;
1295 /* Search through list */
1297 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
1298 if (strequal(domain_name
, domain
->name
)) {
1301 if (domain
->alt_name
== NULL
) {
1304 if (strequal(domain_name
, domain
->alt_name
)) {
1315 * Given a domain name, return the struct winbindd domain if it's a direct
1318 * @return The domain structure for the named domain, if it is a direct outgoing trust
1320 struct winbindd_domain
*find_trust_from_name_noinit(const char *domain_name
)
1322 struct winbindd_domain
*domain
= NULL
;
1324 domain
= find_domain_from_name_noinit(domain_name
);
1325 if (domain
== NULL
) {
1329 if (domain
->secure_channel_type
!= SEC_CHAN_NULL
) {
1336 struct winbindd_domain
*find_domain_from_name(const char *domain_name
)
1338 struct winbindd_domain
*domain
;
1340 domain
= find_domain_from_name_noinit(domain_name
);
1345 if (!domain
->initialized
)
1346 init_dc_connection(domain
, false);
1351 /* Given a domain sid, return the struct winbindd domain info for it */
1353 struct winbindd_domain
*find_domain_from_sid_noinit(const struct dom_sid
*sid
)
1355 struct winbindd_domain
*domain
;
1357 /* Search through list */
1359 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
1360 if (dom_sid_compare_domain(sid
, &domain
->sid
) == 0)
1370 * Given a domain sid, return the struct winbindd domain if it's a direct
1373 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1375 struct winbindd_domain
*find_trust_from_sid_noinit(const struct dom_sid
*sid
)
1377 struct winbindd_domain
*domain
= NULL
;
1379 domain
= find_domain_from_sid_noinit(sid
);
1380 if (domain
== NULL
) {
1384 if (domain
->secure_channel_type
!= SEC_CHAN_NULL
) {
1391 /* Given a domain sid, return the struct winbindd domain info for it */
1393 struct winbindd_domain
*find_domain_from_sid(const struct dom_sid
*sid
)
1395 struct winbindd_domain
*domain
;
1397 domain
= find_domain_from_sid_noinit(sid
);
1402 if (!domain
->initialized
)
1403 init_dc_connection(domain
, false);
1408 struct winbindd_domain
*find_our_domain(void)
1410 struct winbindd_domain
*domain
;
1412 /* Search through list */
1414 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
1415 if (domain
->primary
)
1419 smb_panic("Could not find our domain");
1423 struct winbindd_domain
*find_default_route_domain(void)
1426 return find_our_domain();
1428 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1432 /* Find the appropriate domain to lookup a name or SID */
1434 struct winbindd_domain
*find_lookup_domain_from_sid(const struct dom_sid
*sid
)
1436 struct dom_sid_buf buf
;
1438 DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid
, &buf
));
1441 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1445 if ( sid_check_is_in_unix_groups(sid
) ||
1446 sid_check_is_unix_groups(sid
) ||
1447 sid_check_is_in_unix_users(sid
) ||
1448 sid_check_is_unix_users(sid
) ||
1449 sid_check_is_our_sam(sid
) ||
1450 sid_check_is_in_our_sam(sid
) )
1452 return find_domain_from_sid(get_global_sam_sid());
1455 if ( sid_check_is_builtin(sid
) ||
1456 sid_check_is_in_builtin(sid
) ||
1457 sid_check_is_wellknown_domain(sid
, NULL
) ||
1458 sid_check_is_in_wellknown_domain(sid
) )
1460 return find_domain_from_sid(&global_sid_Builtin
);
1464 struct winbindd_domain
*domain
= NULL
;
1466 domain
= find_domain_from_sid_noinit(sid
);
1467 if (domain
== NULL
) {
1471 if (domain
->secure_channel_type
!= SEC_CHAN_NULL
) {
1475 return domain
->routing_domain
;
1478 /* On a member server a query for SID or name can always go to our
1481 DEBUG(10, ("calling find_our_domain\n"));
1482 return find_our_domain();
1485 struct winbindd_domain
*find_lookup_domain_from_name(const char *domain_name
)
1489 if ( strequal(domain_name
, unix_users_domain_name() ) ||
1490 strequal(domain_name
, unix_groups_domain_name() ) )
1493 * The "Unix User" and "Unix Group" domain are handled by
1496 return find_domain_from_name_noinit( get_global_sam_name() );
1499 if (strequal(domain_name
, "BUILTIN") ||
1500 strequal(domain_name
, get_global_sam_name())) {
1501 return find_domain_from_name_noinit(domain_name
);
1504 predefined
= dom_sid_lookup_is_predefined_domain(domain_name
);
1506 return find_domain_from_name_noinit(builtin_domain_name());
1510 struct winbindd_domain
*domain
= NULL
;
1512 domain
= find_domain_from_name_noinit(domain_name
);
1513 if (domain
== NULL
) {
1517 if (domain
->secure_channel_type
!= SEC_CHAN_NULL
) {
1521 return domain
->routing_domain
;
1524 return find_our_domain();
1527 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1529 static bool assume_domain(const char *domain
)
1531 /* never assume the domain on a standalone server */
1533 if ( lp_server_role() == ROLE_STANDALONE
)
1536 /* domain member servers may possibly assume for the domain name */
1538 if ( lp_server_role() == ROLE_DOMAIN_MEMBER
) {
1539 if ( !strequal(lp_workgroup(), domain
) )
1542 if ( lp_winbind_use_default_domain() )
1546 /* only left with a domain controller */
1548 if ( strequal(get_global_sam_name(), domain
) ) {
1555 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1556 bool parse_domain_user(TALLOC_CTX
*ctx
,
1557 const char *domuser
,
1563 char *namespace = NULL
;
1564 char *domain
= NULL
;
1567 if (strlen(domuser
) == 0) {
1571 p
= strchr(domuser
, *lp_winbind_separator());
1573 user
= talloc_strdup(ctx
, p
+ 1);
1577 domain
= talloc_strdup(ctx
,
1579 if (domain
== NULL
) {
1582 domain
[PTR_DIFF(p
, domuser
)] = '\0';
1583 namespace = talloc_strdup(ctx
, domain
);
1584 if (namespace == NULL
) {
1588 user
= talloc_strdup(ctx
, domuser
);
1592 p
= strchr(domuser
, '@');
1595 namespace = talloc_strdup(ctx
, p
+ 1);
1596 if (namespace == NULL
) {
1599 domain
= talloc_strdup(ctx
, "");
1600 if (domain
== NULL
) {
1604 } else if (assume_domain(lp_workgroup())) {
1605 domain
= talloc_strdup(ctx
, lp_workgroup());
1606 if (domain
== NULL
) {
1609 namespace = talloc_strdup(ctx
, domain
);
1610 if (namespace == NULL
) {
1614 namespace = talloc_strdup(ctx
, lp_netbios_name());
1615 if (namespace == NULL
) {
1618 domain
= talloc_strdup(ctx
, "");
1619 if (domain
== NULL
) {
1625 if (!strupper_m(domain
)) {
1629 *pnamespace
= namespace;
1635 TALLOC_FREE(domain
);
1636 TALLOC_FREE(namespace);
1640 bool canonicalize_username(TALLOC_CTX
*mem_ctx
,
1641 char **pusername_inout
,
1647 char *namespace = NULL
;
1648 char *domain
= NULL
;
1650 char *username_inout
= NULL
;
1652 ok
= parse_domain_user(mem_ctx
,
1654 &namespace, &domain
, &user
);
1660 username_inout
= talloc_asprintf(mem_ctx
, "%s%c%s",
1661 domain
, *lp_winbind_separator(),
1664 if (username_inout
== NULL
) {
1668 *pnamespace
= namespace;
1671 *pusername_inout
= username_inout
;
1674 TALLOC_FREE(username_inout
);
1675 TALLOC_FREE(namespace);
1676 TALLOC_FREE(domain
);
1682 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1683 'winbind separator' options.
1685 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1688 If we are a PDC or BDC, and this is for our domain, do likewise.
1690 On an AD DC we always fill DOMAIN\\USERNAME.
1692 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1695 * talloc version of fill_domain_username()
1696 * return NULL on talloc failure.
1698 char *fill_domain_username_talloc(TALLOC_CTX
*mem_ctx
,
1703 char *tmp_user
, *name
;
1705 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
1713 tmp_user
= talloc_strdup(mem_ctx
, user
);
1714 if (tmp_user
== NULL
) {
1717 if (!strlower_m(tmp_user
)) {
1718 TALLOC_FREE(tmp_user
);
1722 if (can_assume
&& assume_domain(domain
)) {
1725 name
= talloc_asprintf(mem_ctx
, "%s%c%s",
1727 *lp_winbind_separator(),
1729 TALLOC_FREE(tmp_user
);
1736 * Client list accessor functions
1739 static struct winbindd_cli_state
*_client_list
;
1740 static int _num_clients
;
1742 /* Return list of all connected clients */
1744 struct winbindd_cli_state
*winbindd_client_list(void)
1746 return _client_list
;
1749 /* Return list-tail of all connected clients */
1751 struct winbindd_cli_state
*winbindd_client_list_tail(void)
1753 return DLIST_TAIL(_client_list
);
1756 /* Return previous (read:newer) client in list */
1758 struct winbindd_cli_state
*
1759 winbindd_client_list_prev(struct winbindd_cli_state
*cli
)
1761 return DLIST_PREV(cli
);
1764 /* Add a connection to the list */
1766 void winbindd_add_client(struct winbindd_cli_state
*cli
)
1768 cli
->last_access
= time(NULL
);
1769 DLIST_ADD(_client_list
, cli
);
1773 /* Remove a client from the list */
1775 void winbindd_remove_client(struct winbindd_cli_state
*cli
)
1777 DLIST_REMOVE(_client_list
, cli
);
1781 /* Move a client to head or list */
1783 void winbindd_promote_client(struct winbindd_cli_state
*cli
)
1785 cli
->last_access
= time(NULL
);
1786 DLIST_PROMOTE(_client_list
, cli
);
1789 /* Return number of open clients */
1791 int winbindd_num_clients(void)
1793 return _num_clients
;
1796 NTSTATUS
lookup_usergroups_cached(TALLOC_CTX
*mem_ctx
,
1797 const struct dom_sid
*user_sid
,
1798 uint32_t *p_num_groups
, struct dom_sid
**user_sids
)
1800 struct netr_SamInfo3
*info3
= NULL
;
1801 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1802 uint32_t num_groups
= 0;
1804 DEBUG(3,(": lookup_usergroups_cached\n"));
1809 info3
= netsamlogon_cache_get(mem_ctx
, user_sid
);
1811 if (info3
== NULL
) {
1812 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1816 * Before bug #7843 the "Domain Local" groups were added with a
1817 * lookupuseraliases call, but this isn't done anymore for our domain
1818 * so we need to resolve resource groups here.
1820 * When to use Resource Groups:
1821 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1823 status
= sid_array_from_info3(mem_ctx
, info3
,
1828 if (!NT_STATUS_IS_OK(status
)) {
1834 *p_num_groups
= num_groups
;
1835 status
= (user_sids
!= NULL
) ? NT_STATUS_OK
: NT_STATUS_NO_MEMORY
;
1837 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1842 /*********************************************************************
1843 We use this to remove spaces from user and group names
1844 ********************************************************************/
1846 NTSTATUS
normalize_name_map(TALLOC_CTX
*mem_ctx
,
1847 const char *domain_name
,
1851 struct winbindd_domain
*domain
= NULL
;
1854 if (!name
|| !normalized
) {
1855 return NT_STATUS_INVALID_PARAMETER
;
1858 if (!lp_winbind_normalize_names()) {
1859 return NT_STATUS_PROCEDURE_NOT_FOUND
;
1862 domain
= find_domain_from_name_noinit(domain_name
);
1863 if (domain
== NULL
) {
1864 DBG_ERR("Failed to find domain '%s'\n", domain_name
);
1865 return NT_STATUS_NO_SUCH_DOMAIN
;
1868 /* Alias support and whitespace replacement are mutually
1871 nt_status
= resolve_username_to_alias(mem_ctx
, domain
,
1873 if (NT_STATUS_IS_OK(nt_status
)) {
1874 /* special return code to let the caller know we
1875 mapped to an alias */
1876 return NT_STATUS_FILE_RENAMED
;
1879 /* check for an unreachable domain */
1881 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
)) {
1882 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1884 set_domain_offline(domain
);
1888 /* deal with whitespace */
1890 *normalized
= talloc_strdup(mem_ctx
, name
);
1891 if (!(*normalized
)) {
1892 return NT_STATUS_NO_MEMORY
;
1895 all_string_sub( *normalized
, " ", "_", 0 );
1897 return NT_STATUS_OK
;
1900 /*********************************************************************
1901 We use this to do the inverse of normalize_name_map()
1902 ********************************************************************/
1904 NTSTATUS
normalize_name_unmap(TALLOC_CTX
*mem_ctx
,
1909 struct winbindd_domain
*domain
= find_our_domain();
1911 if (!name
|| !normalized
) {
1912 return NT_STATUS_INVALID_PARAMETER
;
1915 if (!lp_winbind_normalize_names()) {
1916 return NT_STATUS_PROCEDURE_NOT_FOUND
;
1919 /* Alias support and whitespace replacement are mutally
1922 /* When mapping from an alias to a username, we don't know the
1923 domain. But we only need a domain structure to cache
1924 a successful lookup , so just our own domain structure for
1927 nt_status
= resolve_alias_to_username(mem_ctx
, domain
,
1929 if (NT_STATUS_IS_OK(nt_status
)) {
1930 /* Special return code to let the caller know we mapped
1932 return NT_STATUS_FILE_RENAMED
;
1935 /* check for an unreachable domain */
1937 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
)) {
1938 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1940 set_domain_offline(domain
);
1944 /* deal with whitespace */
1946 *normalized
= talloc_strdup(mem_ctx
, name
);
1947 if (!(*normalized
)) {
1948 return NT_STATUS_NO_MEMORY
;
1951 all_string_sub(*normalized
, "_", " ", 0);
1953 return NT_STATUS_OK
;
1956 /*********************************************************************
1957 ********************************************************************/
1959 bool winbindd_can_contact_domain(struct winbindd_domain
*domain
)
1961 struct winbindd_tdc_domain
*tdc
= NULL
;
1962 TALLOC_CTX
*frame
= talloc_stackframe();
1965 /* We can contact the domain if it is our primary domain */
1967 if (domain
->primary
) {
1972 /* Trust the TDC cache and not the winbindd_domain flags */
1974 if ((tdc
= wcache_tdc_fetch_domain(frame
, domain
->name
)) == NULL
) {
1975 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1981 /* Can always contact a domain that is in out forest */
1983 if (tdc
->trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) {
1989 * On a _member_ server, we cannot contact the domain if it
1990 * is running AD and we have no inbound trust.
1994 domain
->active_directory
&&
1995 ((tdc
->trust_flags
& NETR_TRUST_FLAG_INBOUND
) != NETR_TRUST_FLAG_INBOUND
))
1997 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1998 "and we have no inbound trust.\n", domain
->name
));
2002 /* Assume everything else is ok (probably not true but what
2008 talloc_destroy(frame
);
2013 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
2015 /*********************************************************************
2016 ********************************************************************/
2018 static void winbindd_set_locator_kdc_env(const struct winbindd_domain
*domain
)
2021 char addr
[INET6_ADDRSTRLEN
];
2022 const char *kdc
= NULL
;
2025 if (!domain
|| !domain
->alt_name
|| !*domain
->alt_name
) {
2029 if (domain
->initialized
&& !domain
->active_directory
) {
2030 DEBUG(lvl
,("winbindd_set_locator_kdc_env: %s not AD\n",
2035 print_sockaddr(addr
, sizeof(addr
), &domain
->dcaddr
);
2038 DEBUG(lvl
,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2040 kdc
= domain
->dcname
;
2043 if (!kdc
|| !*kdc
) {
2044 DEBUG(lvl
,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2049 var
= talloc_asprintf_strupper_m(
2052 WINBINDD_LOCATOR_KDC_ADDRESS
,
2058 DEBUG(lvl
,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2061 setenv(var
, kdc
, 1);
2065 /*********************************************************************
2066 ********************************************************************/
2068 void winbindd_set_locator_kdc_envs(const struct winbindd_domain
*domain
)
2070 struct winbindd_domain
*our_dom
= find_our_domain();
2072 winbindd_set_locator_kdc_env(domain
);
2074 if (domain
!= our_dom
) {
2075 winbindd_set_locator_kdc_env(our_dom
);
2079 /*********************************************************************
2080 ********************************************************************/
2082 void winbindd_unset_locator_kdc_env(const struct winbindd_domain
*domain
)
2086 if (!domain
|| !domain
->alt_name
|| !*domain
->alt_name
) {
2090 var
= talloc_asprintf_strupper_m(
2093 WINBINDD_LOCATOR_KDC_ADDRESS
,
2104 void winbindd_set_locator_kdc_envs(const struct winbindd_domain
*domain
)
2109 void winbindd_unset_locator_kdc_env(const struct winbindd_domain
*domain
)
2114 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2116 void set_auth_errors(struct winbindd_response
*resp
, NTSTATUS result
)
2119 * Make sure we start with authoritative=true,
2120 * it will only set to false if we don't know the
2123 resp
->data
.auth
.authoritative
= true;
2125 resp
->data
.auth
.nt_status
= NT_STATUS_V(result
);
2126 fstrcpy(resp
->data
.auth
.nt_status_string
, nt_errstr(result
));
2128 /* we might have given a more useful error above */
2129 if (*resp
->data
.auth
.error_string
== '\0')
2130 fstrcpy(resp
->data
.auth
.error_string
,
2131 get_friendly_nt_error_msg(result
));
2132 resp
->data
.auth
.pam_error
= nt_status_to_pam(result
);
2135 bool is_domain_offline(const struct winbindd_domain
*domain
)
2137 if (get_global_winbindd_state_offline()) {
2140 return !domain
->online
;
2143 bool is_domain_online(const struct winbindd_domain
*domain
)
2145 return !is_domain_offline(domain
);
2149 * Parse an char array into a list of sids.
2151 * The input sidstr should consist of 0-terminated strings
2152 * representing sids, separated by newline characters '\n'.
2153 * The list is terminated by an empty string, i.e.
2154 * character '\0' directly following a character '\n'
2155 * (or '\0' right at the start of sidstr).
2157 bool parse_sidlist(TALLOC_CTX
*mem_ctx
, const char *sidstr
,
2158 struct dom_sid
**sids
, uint32_t *num_sids
)
2166 while (p
[0] != '\0') {
2168 const char *q
= NULL
;
2170 if (!dom_sid_parse_endp(p
, &sid
, &q
)) {
2171 DEBUG(1, ("Could not parse sid %s\n", p
));
2175 DEBUG(1, ("Got invalid sidstr: %s\n", p
));
2178 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx
, &sid
, sids
,
2188 bool parse_xidlist(TALLOC_CTX
*mem_ctx
, const char *xidstr
,
2189 struct unixid
**pxids
, uint32_t *pnum_xids
)
2192 struct unixid
*xids
= NULL
;
2193 uint32_t num_xids
= 0;
2200 while (p
[0] != '\0') {
2203 unsigned long long id
;
2209 xid
= (struct unixid
) { .type
= ID_TYPE_UID
};
2212 xid
= (struct unixid
) { .type
= ID_TYPE_GID
};
2220 id
= smb_strtoull(p
, &endp
, 10, &error
, SMB_STR_STANDARD
);
2224 if (*endp
!= '\n') {
2230 if ((unsigned long long)xid
.id
!= id
) {
2234 tmp
= talloc_realloc(mem_ctx
, xids
, struct unixid
, num_xids
+1);
2240 xids
[num_xids
] = xid
;
2245 *pnum_xids
= num_xids
;