ctdb-tests: Update statd-callout tests to handle both modes
[samba4-gss.git] / source3 / winbindd / winbindd_util.c
blob9515692b5fe390dee341493c2d121db899a86565
1 /*
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/>.
23 #include "includes.h"
24 #include "winbindd.h"
25 #include "lib/util_unixsids.h"
26 #include "secrets.h"
27 #include "../libcli/security/security.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "passdb/machine_sid.h"
30 #include "passdb.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"
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_WINBIND
44 /**
45 * @file winbindd_util.c
47 * Winbind daemon for NT domain authentication nss module.
48 **/
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)
59 /* Initialise list */
61 if ((!_domain_list) && (!init_domain_list())) {
62 smb_panic("Init_domain_list failed");
65 return _domain_list;
68 /* Free all entries in the trusted domain list */
70 static void free_domain_list(void)
72 struct winbindd_domain *domain = _domain_list;
74 while(domain) {
75 struct winbindd_domain *next = domain->next;
77 DLIST_REMOVE(_domain_list, domain);
78 TALLOC_FREE(domain);
79 domain = next;
83 /**
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)
89 if (domain == NULL) {
90 domain = domain_list();
91 } else {
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;
102 return domain;
105 static bool is_internal_domain(const struct dom_sid *sid)
107 if (sid == NULL)
108 return False;
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,
120 uint32_t trust_type,
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)) {
146 break;
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) {
158 continue;
161 if (dom_sid_equal(&check_domain->sid, sid)) {
162 break;
166 if (check_domain != NULL) {
167 DBG_ERR("SID [%s] already used by domain [%s], "
168 "expected [%s]\n",
169 dom_sid_str_buf(sid, &buf),
170 check_domain->name,
171 domain->name);
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) {
184 continue;
187 if (strequal(check_domain->alt_name, dns_name)) {
188 break;
192 if (check_domain != NULL) {
193 DBG_ERR("DNS name [%s] used by domain [%s], "
194 "expected [%s]\n",
195 dns_name, check_domain->name,
196 domain->name);
197 return NT_STATUS_INVALID_PARAMETER;
201 if (domain != NULL) {
202 *_d = domain;
203 return NT_STATUS_OK;
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) {
216 TALLOC_FREE(domain);
217 return NT_STATUS_NO_MEMORY;
220 domain->queue = tevent_queue_create(domain, "winbind_domain");
221 if (domain->queue == NULL) {
222 TALLOC_FREE(domain);
223 return NT_STATUS_NO_MEMORY;
226 domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
227 if (domain->binding_handle == NULL) {
228 TALLOC_FREE(domain);
229 return NT_STATUS_NO_MEMORY;
232 domain->name = talloc_strdup(domain, domain_name);
233 if (domain->name == NULL) {
234 TALLOC_FREE(domain);
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) {
241 TALLOC_FREE(domain);
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());
262 } else {
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
285 * completely.
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));
301 *_d = domain;
302 return NT_STATUS_OK;
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;
310 return true;
312 if (domain->routing_domain != routing_domain) {
313 return false;
315 return true;
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;
325 NTSTATUS status;
326 bool ok;
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.
335 if (IS_DC) {
336 return true;
339 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
340 if (!ok) {
341 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
342 return false;
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,
352 dns_domainname,
353 &domain_sid,
355 NETR_TRUST_FLAG_OUTBOUND,
357 SEC_CHAN_NULL,
358 find_default_route_domain(),
359 &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);
365 return false;
368 return true;
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;
398 pid_t client_pid;
400 state = talloc_zero(NULL, struct trustdom_state);
401 if (state == NULL) {
402 DEBUG(0, ("talloc failed\n"));
403 return;
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),
414 client_name,
415 client_pid,
416 &state->trusts);
417 if (req == NULL) {
418 DBG_ERR("dcerpc_wbint_ListTrustedDomains_send failed\n");
419 TALLOC_FREE(state);
420 return;
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;
431 uint32_t i;
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),
450 nt_errstr(result));
451 TALLOC_FREE(state);
452 return;
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
471 * domains.
473 status = add_trusted_domain(trust->netbios_name,
474 trust->dns_name,
475 trust->sid,
476 trust->trust_type,
477 trust->trust_flags,
478 trust->trust_attributes,
479 SEC_CHAN_NULL,
480 find_default_route_domain(),
481 &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",
486 nt_errstr(status));
487 return;
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
496 && !forest_root)
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();
505 else
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();
515 TALLOC_FREE(state);
517 return;
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;
528 size_t i;
529 NTSTATUS status;
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 ) )
538 return;
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) ) {
548 continue;
551 /* Here's the forest root */
553 d = find_domain_from_name_noinit( dom_list[i].domain_name );
554 if (d == NULL) {
555 status = add_trusted_domain(dom_list[i].domain_name,
556 dom_list[i].dns_name,
557 &dom_list[i].sid,
558 dom_list[i].trust_type,
559 dom_list[i].trust_flags,
560 dom_list[i].trust_attribs,
561 SEC_CHAN_NULL,
562 find_default_route_domain(),
563 &d);
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",
569 nt_errstr(status));
570 return;
573 if (d == NULL) {
574 continue;
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 );
587 break;
590 TALLOC_FREE( dom_list );
592 return;
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;
605 size_t i;
606 NTSTATUS status;
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 ) )
615 return;
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 ) )
627 continue;
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
634 about it */
636 if (d == NULL) {
637 status = add_trusted_domain(
638 dom_list[i].domain_name,
639 dom_list[i].dns_name,
640 &dom_list[i].sid,
641 type,
642 flags,
643 attribs,
644 SEC_CHAN_NULL,
645 find_default_route_domain(),
646 &d);
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",
652 nt_errstr(status));
653 return;
657 if (d == NULL) {
658 continue;
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 );
669 return;
672 /*********************************************************************
673 The process of updating the trusted domain list is a three step
674 async process:
675 (a) ask our domain
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)
683 TALLOC_FREE(te);
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.
706 return;
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,
713 struct timeval now,
714 void *private_data)
716 struct winbindd_domain *domain = NULL;
718 TALLOC_FREE(te);
720 for (domain = domain_list(); domain != NULL; domain = domain->next) {
721 DBG_DEBUG("Domain %s is %s\n",
722 domain->name,
723 domain->online ? "online" : "offline");
725 if (get_global_winbindd_state_offline()) {
726 DBG_DEBUG("We are globally offline, do nothing.\n");
727 break;
730 if (domain->online ||
731 domain->check_online_event != NULL ||
732 domain->secure_channel_type == SEC_CHAN_NULL) {
733 continue;
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");
745 continue;
748 tevent_req_set_callback(domain->check_online_event,
749 wbd_ping_dc_done, domain);
752 te = tevent_add_timer(ev,
753 NULL,
754 timeval_current_ofs(lp_winbind_reconnect_delay(),
756 winbindd_ping_offline_domains,
757 NULL);
758 if (te == NULL) {
759 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
762 return;
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);
776 TALLOC_FREE(subreq);
777 if (any_nt_status_not_ok(status, result, &status)) {
778 DBG_WARNING("dcerpc_wbint_PingDc_recv failed for domain: "
779 "%s - %s\n",
780 domain->name,
781 nt_errstr(status));
782 return;
785 DBG_DEBUG("dcerpc_wbint_PingDc_recv() succeeded, "
786 "domain: %s, dc-name: %s\n",
787 domain->name,
788 domain->ping_dcname);
790 talloc_free(discard_const(domain->ping_dcname));
791 domain->ping_dcname = NULL;
793 return;
796 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
797 void *private_data,
798 uint32_t msg_type,
799 struct server_id server_id,
800 size_t num_fds,
801 int *fds,
802 DATA_BLOB *data)
804 bool ok;
806 if (num_fds != 0) {
807 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
808 return;
811 DBG_NOTICE("Rescanning trusted domains\n");
813 ok = add_trusted_domains_dc();
814 if (!ok) {
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)
825 bool ok;
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)));
834 return false;
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),
843 NULL /* oldpass */,
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 */
848 &domain->sid,
849 cli_credentials_get_password_last_changed_time(creds),
850 cli_credentials_get_secure_channel_type(creds),
851 false /* do_delete: Do not delete */);
852 TALLOC_FREE(creds);
853 if (ok == false) {
854 DEBUG(0, ("Failed to write our own "
855 "local AD domain join password for "
856 "winbindd's internal use into secrets.tdb\n"));
857 return false;
859 return true;
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;
867 uint32_t i;
868 NTSTATUS status;
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",
876 nt_errstr(status));
877 return false;
880 for (i = 0; i < num_domains; i++) {
881 status = add_trusted_domain(ti[i]->name,
882 NULL,
883 &ti[i]->sid,
884 LSA_TRUST_TYPE_DOWNLEVEL,
885 NETR_TRUST_FLAG_OUTBOUND,
887 SEC_CHAN_DOMAIN,
888 NULL,
889 &domain);
890 if (!NT_STATUS_IS_OK(status)) {
891 DBG_NOTICE("add_trusted_domain returned %s\n",
892 nt_errstr(status));
893 return false;
897 return true;
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",
903 nt_errstr(status));
904 return false;
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 "
934 "domain[%s/%s]\n",
935 domains[i]->netbios_name,
936 domains[i]->domain_name);
937 continue;
940 status = add_trusted_domain(domains[i]->netbios_name,
941 domains[i]->domain_name,
942 &domains[i]->security_identifier,
943 domains[i]->trust_type,
944 trust_flags,
945 domains[i]->trust_attributes,
946 sec_chan_type,
947 NULL,
948 &domain);
949 if (!NT_STATUS_IS_OK(status)) {
950 DBG_NOTICE("add_trusted_domain returned %s\n",
951 nt_errstr(status));
952 return false;
956 for (i = 0; i < num_domains; i++) {
957 struct ForestTrustInfo fti;
958 uint32_t fi;
959 enum ndr_err_code ndr_err;
960 struct winbindd_domain *routing_domain = NULL;
962 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
963 continue;
966 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
967 continue;
970 if (domains[i]->trust_forest_trust_info.length == 0) {
971 continue;
974 routing_domain = find_domain_from_name_noinit(
975 domains[i]->netbios_name);
976 if (routing_domain == NULL) {
977 DBG_ERR("Can't find winbindd domain [%s]\n",
978 domains[i]->netbios_name);
979 return false;
982 ndr_err = ndr_pull_struct_blob_all(
983 &domains[i]->trust_forest_trust_info,
984 talloc_tos(), &fti,
985 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
986 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
987 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
988 domains[i]->netbios_name,
989 ndr_map_error2string(ndr_err));
990 return false;
993 for (fi = 0; fi < fti.count; fi++) {
994 struct ForestTrustInfoRecord *rec =
995 &fti.records[fi].record;
996 struct ForestTrustDataDomainInfo *drec = NULL;
998 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
999 continue;
1001 drec = &rec->data.info;
1003 if (rec->flags & LSA_NB_DISABLED_MASK) {
1004 continue;
1007 if (rec->flags & LSA_SID_DISABLED_MASK) {
1008 continue;
1012 * TODO:
1013 * also try to find a matching
1014 * LSA_TLN_DISABLED_MASK ???
1017 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1018 if (domain != NULL) {
1019 continue;
1022 status = add_trusted_domain(drec->netbios_name.string,
1023 drec->dns_name.string,
1024 &drec->sid,
1025 LSA_TRUST_TYPE_UPLEVEL,
1026 NETR_TRUST_FLAG_OUTBOUND,
1028 SEC_CHAN_NULL,
1029 routing_domain,
1030 &domain);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 DBG_NOTICE("add_trusted_domain returned %s\n",
1033 nt_errstr(status));
1034 return false;
1036 if (domain == NULL) {
1037 continue;
1042 return true;
1046 /* Look up global info for the winbind daemon */
1047 bool init_domain_list(void)
1049 int role = lp_server_role();
1050 struct pdb_domain_info *pdb_domain_info = NULL;
1051 struct winbindd_domain *domain = NULL;
1052 NTSTATUS status;
1053 bool ok;
1055 /* Free existing list */
1056 free_domain_list();
1058 /* BUILTIN domain */
1060 status = add_trusted_domain("BUILTIN",
1061 NULL,
1062 &global_sid_Builtin,
1063 LSA_TRUST_TYPE_DOWNLEVEL,
1064 0, /* trust_flags */
1065 0, /* trust_attribs */
1066 SEC_CHAN_LOCAL,
1067 NULL,
1068 &domain);
1069 if (!NT_STATUS_IS_OK(status)) {
1070 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1071 nt_errstr(status));
1072 return false;
1075 /* Local SAM */
1078 * In case the passdb backend is passdb_dsdb the domain SID comes from
1079 * dsdb, not from secrets.tdb. As we use the domain SID in various
1080 * places, we must ensure the domain SID is migrated from dsdb to
1081 * secrets.tdb before get_global_sam_sid() is called the first time.
1083 * The migration is done as part of the passdb_dsdb initialisation,
1084 * calling pdb_get_domain_info() triggers it.
1086 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1088 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1089 uint32_t trust_flags;
1090 bool is_root;
1091 enum netr_SchannelType sec_chan_type;
1092 const char *account_name;
1093 struct samr_Password current_nt_hash;
1095 if (pdb_domain_info == NULL) {
1096 DEBUG(0, ("Failed to fetch our own local AD "
1097 "domain info from sam.ldb\n"));
1098 return false;
1101 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1102 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1103 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1104 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1106 is_root = strequal(pdb_domain_info->dns_domain,
1107 pdb_domain_info->dns_forest);
1108 if (is_root) {
1109 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1112 status = add_trusted_domain(pdb_domain_info->name,
1113 pdb_domain_info->dns_domain,
1114 &pdb_domain_info->sid,
1115 LSA_TRUST_TYPE_UPLEVEL,
1116 trust_flags,
1117 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1118 SEC_CHAN_BDC,
1119 NULL,
1120 &domain);
1121 TALLOC_FREE(pdb_domain_info);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 DBG_ERR("Failed to add our own local AD "
1124 "domain to winbindd's internal list\n");
1125 return false;
1129 * We need to call this to find out if we are an RODC
1131 ok = get_trust_pw_hash(domain->name,
1132 current_nt_hash.hash,
1133 &account_name,
1134 &sec_chan_type);
1135 if (!ok) {
1137 * If get_trust_pw_hash() fails, then try and
1138 * fetch the password from the more recent of
1139 * secrets.{ldb,tdb} using the
1140 * pdb_get_trust_credentials()
1142 ok = migrate_secrets_tdb_to_ldb(domain);
1144 if (!ok) {
1145 DEBUG(0, ("Failed to migrate our own "
1146 "local AD domain join password for "
1147 "winbindd's internal use into "
1148 "secrets.tdb\n"));
1149 return false;
1151 ok = get_trust_pw_hash(domain->name,
1152 current_nt_hash.hash,
1153 &account_name,
1154 &sec_chan_type);
1155 if (!ok) {
1156 DEBUG(0, ("Failed to find our own just "
1157 "written local AD domain join "
1158 "password for winbindd's internal "
1159 "use in secrets.tdb\n"));
1160 return false;
1164 domain->secure_channel_type = sec_chan_type;
1165 if (sec_chan_type == SEC_CHAN_RODC) {
1166 domain->rodc = true;
1169 } else {
1170 uint32_t trust_flags;
1171 enum netr_SchannelType secure_channel_type;
1173 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1174 if (role != ROLE_DOMAIN_MEMBER) {
1175 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1178 if (role > ROLE_DOMAIN_MEMBER) {
1179 secure_channel_type = SEC_CHAN_BDC;
1180 } else {
1181 secure_channel_type = SEC_CHAN_LOCAL;
1184 if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) {
1185 /* This is IPA DC that presents itself as
1186 * an Active Directory domain controller to trusted AD
1187 * forests but in fact is a classic domain controller.
1189 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1190 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1191 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1192 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1193 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1194 status = add_trusted_domain(pdb_domain_info->name,
1195 pdb_domain_info->dns_domain,
1196 &pdb_domain_info->sid,
1197 LSA_TRUST_TYPE_UPLEVEL,
1198 trust_flags,
1199 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1200 secure_channel_type,
1201 NULL,
1202 &domain);
1203 TALLOC_FREE(pdb_domain_info);
1204 } else {
1205 status = add_trusted_domain(get_global_sam_name(),
1206 NULL,
1207 get_global_sam_sid(),
1208 LSA_TRUST_TYPE_DOWNLEVEL,
1209 trust_flags,
1210 0, /* trust_attribs */
1211 secure_channel_type,
1212 NULL,
1213 &domain);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 DBG_ERR("Failed to add local SAM to "
1217 "domain to winbindd's internal list\n");
1218 return false;
1222 if (IS_DC) {
1223 ok = add_trusted_domains_dc();
1224 if (!ok) {
1225 DBG_ERR("init_domain_list_dc failed\n");
1226 return false;
1230 if ( role == ROLE_DOMAIN_MEMBER ) {
1231 struct dom_sid our_sid;
1232 uint32_t trust_type;
1234 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1235 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1236 return False;
1239 if (lp_realm() != NULL) {
1240 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1241 } else {
1242 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1245 status = add_trusted_domain(lp_workgroup(),
1246 lp_realm(),
1247 &our_sid,
1248 trust_type,
1249 NETR_TRUST_FLAG_PRIMARY|
1250 NETR_TRUST_FLAG_OUTBOUND,
1251 0, /* trust_attribs */
1252 SEC_CHAN_WKSTA,
1253 NULL,
1254 &domain);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 DBG_ERR("Failed to add local SAM to "
1257 "domain to winbindd's internal list\n");
1258 return false;
1262 status = imessaging_register(winbind_imessaging_context(), NULL,
1263 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1264 wb_imsg_new_trusted_domain);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1267 return false;
1270 return True;
1274 * Given a domain name, return the struct winbindd domain info for it
1276 * @note Do *not* pass lp_workgroup() to this function. domain_list
1277 * may modify it's value, and free that pointer. Instead, our local
1278 * domain may be found by calling find_our_domain().
1279 * directly.
1282 * @return The domain structure for the named domain, if it is working.
1285 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1287 struct winbindd_domain *domain;
1289 /* Search through list */
1291 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1292 if (strequal(domain_name, domain->name)) {
1293 return domain;
1295 if (domain->alt_name == NULL) {
1296 continue;
1298 if (strequal(domain_name, domain->alt_name)) {
1299 return domain;
1303 /* Not found */
1305 return NULL;
1309 * Given a domain name, return the struct winbindd domain if it's a direct
1310 * outgoing trust
1312 * @return The domain structure for the named domain, if it is a direct outgoing trust
1314 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1316 struct winbindd_domain *domain = NULL;
1318 domain = find_domain_from_name_noinit(domain_name);
1319 if (domain == NULL) {
1320 return NULL;
1323 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1324 return domain;
1327 return NULL;
1330 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1332 struct winbindd_domain *domain;
1334 domain = find_domain_from_name_noinit(domain_name);
1336 if (domain == NULL)
1337 return NULL;
1339 if (!domain->initialized)
1340 init_dc_connection(domain, false);
1342 return domain;
1345 /* Given a domain sid, return the struct winbindd domain info for it */
1347 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1349 struct winbindd_domain *domain;
1351 /* Search through list */
1353 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1354 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1355 return domain;
1358 /* Not found */
1360 return NULL;
1364 * Given a domain sid, return the struct winbindd domain if it's a direct
1365 * outgoing trust
1367 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1369 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1371 struct winbindd_domain *domain = NULL;
1373 domain = find_domain_from_sid_noinit(sid);
1374 if (domain == NULL) {
1375 return NULL;
1378 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1379 return domain;
1382 return NULL;
1385 /* Given a domain sid, return the struct winbindd domain info for it */
1387 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1389 struct winbindd_domain *domain;
1391 domain = find_domain_from_sid_noinit(sid);
1393 if (domain == NULL)
1394 return NULL;
1396 if (!domain->initialized)
1397 init_dc_connection(domain, false);
1399 return domain;
1402 struct winbindd_domain *find_our_domain(void)
1404 struct winbindd_domain *domain;
1406 /* Search through list */
1408 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1409 if (domain->primary)
1410 return domain;
1413 smb_panic("Could not find our domain");
1414 return NULL;
1417 struct winbindd_domain *find_default_route_domain(void)
1419 if (!IS_DC) {
1420 return find_our_domain();
1422 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1423 return NULL;
1426 /* Find the appropriate domain to lookup a name or SID */
1428 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1430 struct dom_sid_buf buf;
1432 DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid, &buf));
1435 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1436 * by our passdb.
1439 if ( sid_check_is_in_unix_groups(sid) ||
1440 sid_check_is_unix_groups(sid) ||
1441 sid_check_is_in_unix_users(sid) ||
1442 sid_check_is_unix_users(sid) ||
1443 sid_check_is_our_sam(sid) ||
1444 sid_check_is_in_our_sam(sid) )
1446 return find_domain_from_sid(get_global_sam_sid());
1449 if ( sid_check_is_builtin(sid) ||
1450 sid_check_is_in_builtin(sid) ||
1451 sid_check_is_wellknown_domain(sid, NULL) ||
1452 sid_check_is_in_wellknown_domain(sid) )
1454 return find_domain_from_sid(&global_sid_Builtin);
1457 if (IS_DC) {
1458 struct winbindd_domain *domain = NULL;
1460 domain = find_domain_from_sid_noinit(sid);
1461 if (domain == NULL) {
1462 return NULL;
1465 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1466 return domain;
1469 return domain->routing_domain;
1472 /* On a member server a query for SID or name can always go to our
1473 * primary DC. */
1475 DEBUG(10, ("calling find_our_domain\n"));
1476 return find_our_domain();
1479 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1481 bool predefined;
1483 if ( strequal(domain_name, unix_users_domain_name() ) ||
1484 strequal(domain_name, unix_groups_domain_name() ) )
1487 * The "Unix User" and "Unix Group" domain are handled by
1488 * passdb
1490 return find_domain_from_name_noinit( get_global_sam_name() );
1493 if (strequal(domain_name, "BUILTIN") ||
1494 strequal(domain_name, get_global_sam_name())) {
1495 return find_domain_from_name_noinit(domain_name);
1498 predefined = dom_sid_lookup_is_predefined_domain(domain_name);
1499 if (predefined) {
1500 return find_domain_from_name_noinit(builtin_domain_name());
1503 if (IS_DC) {
1504 struct winbindd_domain *domain = NULL;
1506 domain = find_domain_from_name_noinit(domain_name);
1507 if (domain == NULL) {
1508 return NULL;
1511 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1512 return domain;
1515 return domain->routing_domain;
1518 return find_our_domain();
1521 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1523 static bool assume_domain(const char *domain)
1525 /* never assume the domain on a standalone server */
1527 if ( lp_server_role() == ROLE_STANDALONE )
1528 return False;
1530 /* domain member servers may possibly assume for the domain name */
1532 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1533 if ( !strequal(lp_workgroup(), domain) )
1534 return False;
1536 if ( lp_winbind_use_default_domain() )
1537 return True;
1540 /* only left with a domain controller */
1542 if ( strequal(get_global_sam_name(), domain) ) {
1543 return True;
1546 return False;
1549 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1550 bool parse_domain_user(TALLOC_CTX *ctx,
1551 const char *domuser,
1552 char **pnamespace,
1553 char **pdomain,
1554 char **puser)
1556 char *p = NULL;
1557 char *namespace = NULL;
1558 char *domain = NULL;
1559 char *user = NULL;
1561 if (strlen(domuser) == 0) {
1562 return false;
1565 p = strchr(domuser, *lp_winbind_separator());
1566 if (p != NULL) {
1567 user = talloc_strdup(ctx, p + 1);
1568 if (user == NULL) {
1569 goto fail;
1571 domain = talloc_strdup(ctx,
1572 domuser);
1573 if (domain == NULL) {
1574 goto fail;
1576 domain[PTR_DIFF(p, domuser)] = '\0';
1577 namespace = talloc_strdup(ctx, domain);
1578 if (namespace == NULL) {
1579 goto fail;
1581 } else {
1582 user = talloc_strdup(ctx, domuser);
1583 if (user == NULL) {
1584 goto fail;
1586 p = strchr(domuser, '@');
1587 if (p != NULL) {
1588 /* upn */
1589 namespace = talloc_strdup(ctx, p + 1);
1590 if (namespace == NULL) {
1591 goto fail;
1593 domain = talloc_strdup(ctx, "");
1594 if (domain == NULL) {
1595 goto fail;
1598 } else if (assume_domain(lp_workgroup())) {
1599 domain = talloc_strdup(ctx, lp_workgroup());
1600 if (domain == NULL) {
1601 goto fail;
1603 namespace = talloc_strdup(ctx, domain);
1604 if (namespace == NULL) {
1605 goto fail;
1607 } else {
1608 namespace = talloc_strdup(ctx, lp_netbios_name());
1609 if (namespace == NULL) {
1610 goto fail;
1612 domain = talloc_strdup(ctx, "");
1613 if (domain == NULL) {
1614 goto fail;
1619 if (!strupper_m(domain)) {
1620 goto fail;
1623 *pnamespace = namespace;
1624 *pdomain = domain;
1625 *puser = user;
1626 return true;
1627 fail:
1628 TALLOC_FREE(user);
1629 TALLOC_FREE(domain);
1630 TALLOC_FREE(namespace);
1631 return false;
1634 bool canonicalize_username(TALLOC_CTX *mem_ctx,
1635 char **pusername_inout,
1636 char **pnamespace,
1637 char **pdomain,
1638 char **puser)
1640 bool ok;
1641 char *namespace = NULL;
1642 char *domain = NULL;
1643 char *user = NULL;
1644 char *username_inout = NULL;
1646 ok = parse_domain_user(mem_ctx,
1647 *pusername_inout,
1648 &namespace, &domain, &user);
1650 if (!ok) {
1651 return False;
1654 username_inout = talloc_asprintf(mem_ctx, "%s%c%s",
1655 domain, *lp_winbind_separator(),
1656 user);
1658 if (username_inout == NULL) {
1659 goto fail;
1662 *pnamespace = namespace;
1663 *puser = user;
1664 *pdomain = domain;
1665 *pusername_inout = username_inout;
1666 return True;
1667 fail:
1668 TALLOC_FREE(username_inout);
1669 TALLOC_FREE(namespace);
1670 TALLOC_FREE(domain);
1671 TALLOC_FREE(user);
1672 return false;
1676 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1677 'winbind separator' options.
1678 This means:
1679 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1680 lp_workgroup()
1682 If we are a PDC or BDC, and this is for our domain, do likewise.
1684 On an AD DC we always fill DOMAIN\\USERNAME.
1686 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1689 * talloc version of fill_domain_username()
1690 * return NULL on talloc failure.
1692 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1693 const char *domain,
1694 const char *user,
1695 bool can_assume)
1697 char *tmp_user, *name;
1699 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1700 can_assume = false;
1703 if (user == NULL) {
1704 return NULL;
1707 tmp_user = talloc_strdup(mem_ctx, user);
1708 if (tmp_user == NULL) {
1709 return NULL;
1711 if (!strlower_m(tmp_user)) {
1712 TALLOC_FREE(tmp_user);
1713 return NULL;
1716 if (can_assume && assume_domain(domain)) {
1717 name = tmp_user;
1718 } else {
1719 name = talloc_asprintf(mem_ctx, "%s%c%s",
1720 domain,
1721 *lp_winbind_separator(),
1722 tmp_user);
1723 TALLOC_FREE(tmp_user);
1726 return name;
1730 * Client list accessor functions
1733 static struct winbindd_cli_state *_client_list;
1734 static int _num_clients;
1736 /* Return list of all connected clients */
1738 struct winbindd_cli_state *winbindd_client_list(void)
1740 return _client_list;
1743 /* Return list-tail of all connected clients */
1745 struct winbindd_cli_state *winbindd_client_list_tail(void)
1747 return DLIST_TAIL(_client_list);
1750 /* Return previous (read:newer) client in list */
1752 struct winbindd_cli_state *
1753 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1755 return DLIST_PREV(cli);
1758 /* Add a connection to the list */
1760 void winbindd_add_client(struct winbindd_cli_state *cli)
1762 cli->last_access = time(NULL);
1763 DLIST_ADD(_client_list, cli);
1764 _num_clients++;
1767 /* Remove a client from the list */
1769 void winbindd_remove_client(struct winbindd_cli_state *cli)
1771 DLIST_REMOVE(_client_list, cli);
1772 _num_clients--;
1775 /* Move a client to head or list */
1777 void winbindd_promote_client(struct winbindd_cli_state *cli)
1779 cli->last_access = time(NULL);
1780 DLIST_PROMOTE(_client_list, cli);
1783 /* Return number of open clients */
1785 int winbindd_num_clients(void)
1787 return _num_clients;
1790 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1791 const struct dom_sid *user_sid,
1792 uint32_t *p_num_groups, struct dom_sid **user_sids)
1794 struct netr_SamInfo3 *info3 = NULL;
1795 NTSTATUS status = NT_STATUS_NO_MEMORY;
1796 uint32_t num_groups = 0;
1798 DEBUG(3,(": lookup_usergroups_cached\n"));
1800 *user_sids = NULL;
1801 *p_num_groups = 0;
1803 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1805 if (info3 == NULL) {
1806 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1810 * Before bug #7843 the "Domain Local" groups were added with a
1811 * lookupuseraliases call, but this isn't done anymore for our domain
1812 * so we need to resolve resource groups here.
1814 * When to use Resource Groups:
1815 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1817 status = sid_array_from_info3(mem_ctx, info3,
1818 user_sids,
1819 &num_groups,
1820 false);
1822 if (!NT_STATUS_IS_OK(status)) {
1823 TALLOC_FREE(info3);
1824 return status;
1827 TALLOC_FREE(info3);
1828 *p_num_groups = num_groups;
1829 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1831 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1833 return status;
1836 /*********************************************************************
1837 We use this to remove spaces from user and group names
1838 ********************************************************************/
1840 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1841 const char *domain_name,
1842 const char *name,
1843 char **normalized)
1845 struct winbindd_domain *domain = NULL;
1846 NTSTATUS nt_status;
1848 if (!name || !normalized) {
1849 return NT_STATUS_INVALID_PARAMETER;
1852 if (!lp_winbind_normalize_names()) {
1853 return NT_STATUS_PROCEDURE_NOT_FOUND;
1856 domain = find_domain_from_name_noinit(domain_name);
1857 if (domain == NULL) {
1858 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1859 return NT_STATUS_NO_SUCH_DOMAIN;
1862 /* Alias support and whitespace replacement are mutually
1863 exclusive */
1865 nt_status = resolve_username_to_alias(mem_ctx, domain,
1866 name, normalized );
1867 if (NT_STATUS_IS_OK(nt_status)) {
1868 /* special return code to let the caller know we
1869 mapped to an alias */
1870 return NT_STATUS_FILE_RENAMED;
1873 /* check for an unreachable domain */
1875 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1876 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1877 domain->name));
1878 set_domain_offline(domain);
1879 return nt_status;
1882 /* deal with whitespace */
1884 *normalized = talloc_strdup(mem_ctx, name);
1885 if (!(*normalized)) {
1886 return NT_STATUS_NO_MEMORY;
1889 all_string_sub( *normalized, " ", "_", 0 );
1891 return NT_STATUS_OK;
1894 /*********************************************************************
1895 We use this to do the inverse of normalize_name_map()
1896 ********************************************************************/
1898 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1899 const char *name,
1900 char **normalized)
1902 NTSTATUS nt_status;
1903 struct winbindd_domain *domain = find_our_domain();
1905 if (!name || !normalized) {
1906 return NT_STATUS_INVALID_PARAMETER;
1909 if (!lp_winbind_normalize_names()) {
1910 return NT_STATUS_PROCEDURE_NOT_FOUND;
1913 /* Alias support and whitespace replacement are mutally
1914 exclusive */
1916 /* When mapping from an alias to a username, we don't know the
1917 domain. But we only need a domain structure to cache
1918 a successful lookup , so just our own domain structure for
1919 the seqnum. */
1921 nt_status = resolve_alias_to_username(mem_ctx, domain,
1922 name, normalized);
1923 if (NT_STATUS_IS_OK(nt_status)) {
1924 /* Special return code to let the caller know we mapped
1925 from an alias */
1926 return NT_STATUS_FILE_RENAMED;
1929 /* check for an unreachable domain */
1931 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1932 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1933 domain->name));
1934 set_domain_offline(domain);
1935 return nt_status;
1938 /* deal with whitespace */
1940 *normalized = talloc_strdup(mem_ctx, name);
1941 if (!(*normalized)) {
1942 return NT_STATUS_NO_MEMORY;
1945 all_string_sub(*normalized, "_", " ", 0);
1947 return NT_STATUS_OK;
1950 /*********************************************************************
1951 ********************************************************************/
1953 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1955 struct winbindd_tdc_domain *tdc = NULL;
1956 TALLOC_CTX *frame = talloc_stackframe();
1957 bool ret = false;
1959 /* We can contact the domain if it is our primary domain */
1961 if (domain->primary) {
1962 ret = true;
1963 goto done;
1966 /* Trust the TDC cache and not the winbindd_domain flags */
1968 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1969 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1970 domain->name));
1971 ret = false;
1972 goto done;
1975 /* Can always contact a domain that is in out forest */
1977 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1978 ret = true;
1979 goto done;
1983 * On a _member_ server, we cannot contact the domain if it
1984 * is running AD and we have no inbound trust.
1987 if (!IS_DC &&
1988 domain->active_directory &&
1989 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1991 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1992 "and we have no inbound trust.\n", domain->name));
1993 goto done;
1996 /* Assume everything else is ok (probably not true but what
1997 can you do?) */
1999 ret = true;
2001 done:
2002 talloc_destroy(frame);
2004 return ret;
2007 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
2009 /*********************************************************************
2010 ********************************************************************/
2012 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
2014 char *var = NULL;
2015 char addr[INET6_ADDRSTRLEN];
2016 const char *kdc = NULL;
2017 int lvl = 11;
2019 if (!domain || !domain->alt_name || !*domain->alt_name) {
2020 return;
2023 if (domain->initialized && !domain->active_directory) {
2024 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2025 domain->alt_name));
2026 return;
2029 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2030 kdc = addr;
2031 if (!*kdc) {
2032 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2033 domain->alt_name));
2034 kdc = domain->dcname;
2037 if (!kdc || !*kdc) {
2038 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2039 domain->alt_name));
2040 return;
2043 var = talloc_asprintf_strupper_m(
2044 talloc_tos(),
2045 "%s_%s",
2046 WINBINDD_LOCATOR_KDC_ADDRESS,
2047 domain->alt_name);
2048 if (var == NULL) {
2049 return;
2052 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2053 var, kdc));
2055 setenv(var, kdc, 1);
2056 TALLOC_FREE(var);
2059 /*********************************************************************
2060 ********************************************************************/
2062 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2064 struct winbindd_domain *our_dom = find_our_domain();
2066 winbindd_set_locator_kdc_env(domain);
2068 if (domain != our_dom) {
2069 winbindd_set_locator_kdc_env(our_dom);
2073 /*********************************************************************
2074 ********************************************************************/
2076 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2078 char *var = NULL;
2080 if (!domain || !domain->alt_name || !*domain->alt_name) {
2081 return;
2084 var = talloc_asprintf_strupper_m(
2085 talloc_tos(),
2086 "%s_%s",
2087 WINBINDD_LOCATOR_KDC_ADDRESS,
2088 domain->alt_name);
2089 if (var == NULL) {
2090 return;
2093 unsetenv(var);
2094 TALLOC_FREE(var);
2096 #else
2098 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2100 return;
2103 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2105 return;
2108 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2110 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2113 * Make sure we start with authoritative=true,
2114 * it will only set to false if we don't know the
2115 * domain.
2117 resp->data.auth.authoritative = true;
2119 resp->data.auth.nt_status = NT_STATUS_V(result);
2120 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2122 /* we might have given a more useful error above */
2123 if (*resp->data.auth.error_string == '\0')
2124 fstrcpy(resp->data.auth.error_string,
2125 get_friendly_nt_error_msg(result));
2126 resp->data.auth.pam_error = nt_status_to_pam(result);
2129 bool is_domain_offline(const struct winbindd_domain *domain)
2131 if (get_global_winbindd_state_offline()) {
2132 return true;
2134 return !domain->online;
2137 bool is_domain_online(const struct winbindd_domain *domain)
2139 return !is_domain_offline(domain);
2143 * Parse an char array into a list of sids.
2145 * The input sidstr should consist of 0-terminated strings
2146 * representing sids, separated by newline characters '\n'.
2147 * The list is terminated by an empty string, i.e.
2148 * character '\0' directly following a character '\n'
2149 * (or '\0' right at the start of sidstr).
2151 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2152 struct dom_sid **sids, uint32_t *num_sids)
2154 const char *p;
2156 p = sidstr;
2157 if (p == NULL)
2158 return False;
2160 while (p[0] != '\0') {
2161 struct dom_sid sid;
2162 const char *q = NULL;
2164 if (!dom_sid_parse_endp(p, &sid, &q)) {
2165 DEBUG(1, ("Could not parse sid %s\n", p));
2166 return false;
2168 if (q[0] != '\n') {
2169 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2170 return false;
2172 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2173 num_sids)))
2175 return False;
2177 p = q+1;
2179 return True;
2182 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2183 struct unixid **pxids, uint32_t *pnum_xids)
2185 const char *p;
2186 struct unixid *xids = NULL;
2187 uint32_t num_xids = 0;
2189 p = xidstr;
2190 if (p == NULL) {
2191 return false;
2194 while (p[0] != '\0') {
2195 struct unixid *tmp;
2196 struct unixid xid;
2197 unsigned long long id;
2198 char *endp;
2199 int error = 0;
2201 switch (p[0]) {
2202 case 'U':
2203 xid = (struct unixid) { .type = ID_TYPE_UID };
2204 break;
2205 case 'G':
2206 xid = (struct unixid) { .type = ID_TYPE_GID };
2207 break;
2208 default:
2209 return false;
2212 p += 1;
2214 id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
2215 if (error != 0) {
2216 goto fail;
2218 if (*endp != '\n') {
2219 goto fail;
2221 p = endp+1;
2223 xid.id = id;
2224 if ((unsigned long long)xid.id != id) {
2225 goto fail;
2228 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2229 if (tmp == NULL) {
2230 return 0;
2232 xids = tmp;
2234 xids[num_xids] = xid;
2235 num_xids += 1;
2238 *pxids = xids;
2239 *pnum_xids = num_xids;
2240 return true;
2242 fail:
2243 TALLOC_FREE(xids);
2244 return false;