smbXsrv_session: Remove a "can't happen" NULL check
[Samba.git] / source3 / winbindd / winbindd_util.c
blob2234efeed542ec82258b7ccaaf0da0d18c9cd267
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->secure_channel_type = secure_channel_type;
257 domain->routing_domain = routing_domain;
258 sid_copy(&domain->sid, sid);
260 /* Is this our primary domain ? */
261 if (role == ROLE_DOMAIN_MEMBER) {
262 domain->primary = strequal(domain_name, lp_workgroup());
263 } else {
264 domain->primary = strequal(domain_name, get_global_sam_name());
267 if (domain->primary) {
268 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
269 domain->active_directory = true;
271 if (lp_security() == SEC_ADS) {
272 domain->active_directory = true;
274 } else if (!domain->internal) {
275 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
276 domain->active_directory = true;
280 domain->can_do_ncacn_ip_tcp = domain->active_directory;
282 /* Link to domain list */
283 DLIST_ADD_END(_domain_list, domain);
285 wcache_tdc_add_domain( domain );
287 setup_domain_child(domain);
289 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
290 domain->name, domain->alt_name,
291 dom_sid_str_buf(&domain->sid, &buf));
293 *_d = domain;
294 return NT_STATUS_OK;
297 bool set_routing_domain(struct winbindd_domain *domain,
298 struct winbindd_domain *routing_domain)
300 if (domain->routing_domain == NULL) {
301 domain->routing_domain = routing_domain;
302 return true;
304 if (domain->routing_domain != routing_domain) {
305 return false;
307 return true;
310 bool add_trusted_domain_from_auth(uint16_t validation_level,
311 struct info3_text *info3,
312 struct info6_text *info6)
314 struct winbindd_domain *domain = NULL;
315 struct dom_sid domain_sid;
316 const char *dns_domainname = NULL;
317 NTSTATUS status;
318 bool ok;
321 * We got a successful auth from a domain that might not yet be in our
322 * domain list. If we're a member we trust our DC who authenticated the
323 * user from that domain and add the domain to our list on-the-fly. If
324 * we're a DC we rely on configured trusts and don't add on-the-fly.
327 if (IS_DC) {
328 return true;
331 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
332 if (!ok) {
333 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
334 return false;
337 if (validation_level == 6) {
338 if (!strequal(info6->dns_domainname, "")) {
339 dns_domainname = info6->dns_domainname;
343 status = add_trusted_domain(info3->logon_dom,
344 dns_domainname,
345 &domain_sid,
347 NETR_TRUST_FLAG_OUTBOUND,
349 SEC_CHAN_NULL,
350 find_default_route_domain(),
351 &domain);
352 if (!NT_STATUS_IS_OK(status) &&
353 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
355 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
356 info3->logon_dom, info3->dom_sid);
357 return false;
360 return true;
363 bool domain_is_forest_root(const struct winbindd_domain *domain)
365 const uint32_t fr_flags =
366 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
368 return ((domain->domain_flags & fr_flags) == fr_flags);
371 /********************************************************************
372 rescan our domains looking for new trusted domains
373 ********************************************************************/
375 struct trustdom_state {
376 struct winbindd_domain *domain;
377 struct netr_DomainTrustList trusts;
380 static void trustdom_list_done(struct tevent_req *req);
381 static void rescan_forest_root_trusts( void );
382 static void rescan_forest_trusts( void );
384 static void add_trusted_domains( struct winbindd_domain *domain )
386 struct tevent_context *ev = global_event_context();
387 struct trustdom_state *state;
388 struct tevent_req *req;
389 const char *client_name = NULL;
390 pid_t client_pid;
392 state = talloc_zero(NULL, struct trustdom_state);
393 if (state == NULL) {
394 DEBUG(0, ("talloc failed\n"));
395 return;
397 state->domain = domain;
399 /* Called from timer, not from a real client */
400 client_name = getprogname();
401 client_pid = getpid();
403 req = dcerpc_wbint_ListTrustedDomains_send(state,
405 dom_child_handle(domain),
406 client_name,
407 client_pid,
408 &state->trusts);
409 if (req == NULL) {
410 DBG_ERR("dcerpc_wbint_ListTrustedDomains_send failed\n");
411 TALLOC_FREE(state);
412 return;
414 tevent_req_set_callback(req, trustdom_list_done, state);
417 static void trustdom_list_done(struct tevent_req *req)
419 struct trustdom_state *state = tevent_req_callback_data(
420 req, struct trustdom_state);
421 bool within_forest = false;
422 NTSTATUS status, result;
423 uint32_t i;
426 * Only when we enumerate our primary domain
427 * or our forest root domain, we should keep
428 * the NETR_TRUST_FLAG_IN_FOREST flag, in
429 * all other cases we need to clear it as the domain
430 * is not part of our forest.
432 if (state->domain->primary) {
433 within_forest = true;
434 } else if (domain_is_forest_root(state->domain)) {
435 within_forest = true;
438 status = dcerpc_wbint_ListTrustedDomains_recv(req, state, &result);
439 if (any_nt_status_not_ok(status, result, &status)) {
440 DBG_WARNING("Could not receive trusts for domain %s: %s-%s\n",
441 state->domain->name, nt_errstr(status),
442 nt_errstr(result));
443 TALLOC_FREE(state);
444 return;
447 for (i=0; i<state->trusts.count; i++) {
448 struct netr_DomainTrust *trust = &state->trusts.array[i];
449 struct winbindd_domain *domain = NULL;
451 if (!within_forest) {
452 trust->trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
455 if (!state->domain->primary) {
456 trust->trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
460 * We always call add_trusted_domain() cause on an existing
461 * domain structure, it will update the SID if necessary.
462 * This is important because we need the SID for sibling
463 * domains.
465 status = add_trusted_domain(trust->netbios_name,
466 trust->dns_name,
467 trust->sid,
468 trust->trust_type,
469 trust->trust_flags,
470 trust->trust_attributes,
471 SEC_CHAN_NULL,
472 find_default_route_domain(),
473 &domain);
474 if (!NT_STATUS_IS_OK(status) &&
475 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
477 DBG_NOTICE("add_trusted_domain returned %s\n",
478 nt_errstr(status));
479 return;
484 Cases to consider when scanning trusts:
485 (a) we are calling from a child domain (primary && !forest_root)
486 (b) we are calling from the root of the forest (primary && forest_root)
487 (c) we are calling from a trusted forest domain (!primary
488 && !forest_root)
491 if (state->domain->primary) {
492 /* If this is our primary domain and we are not in the
493 forest root, we have to scan the root trusts first */
495 if (!domain_is_forest_root(state->domain))
496 rescan_forest_root_trusts();
497 else
498 rescan_forest_trusts();
500 } else if (domain_is_forest_root(state->domain)) {
501 /* Once we have done root forest trust search, we can
502 go on to search the trusted forests */
504 rescan_forest_trusts();
507 TALLOC_FREE(state);
509 return;
512 /********************************************************************
513 Scan the trusts of our forest root
514 ********************************************************************/
516 static void rescan_forest_root_trusts( void )
518 struct winbindd_tdc_domain *dom_list = NULL;
519 size_t num_trusts = 0;
520 size_t i;
521 NTSTATUS status;
523 /* The only transitive trusts supported by Windows 2003 AD are
524 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
525 first two are handled in forest and listed by
526 DsEnumerateDomainTrusts(). Forest trusts are not so we
527 have to do that ourselves. */
529 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
530 return;
532 for ( i=0; i<num_trusts; i++ ) {
533 struct winbindd_domain *d = NULL;
535 /* Find the forest root. Don't necessarily trust
536 the domain_list() as our primary domain may not
537 have been initialized. */
539 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
540 continue;
543 /* Here's the forest root */
545 d = find_domain_from_name_noinit( dom_list[i].domain_name );
546 if (d == NULL) {
547 status = add_trusted_domain(dom_list[i].domain_name,
548 dom_list[i].dns_name,
549 &dom_list[i].sid,
550 dom_list[i].trust_type,
551 dom_list[i].trust_flags,
552 dom_list[i].trust_attribs,
553 SEC_CHAN_NULL,
554 find_default_route_domain(),
555 &d);
557 if (!NT_STATUS_IS_OK(status) &&
558 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
560 DBG_ERR("add_trusted_domain returned %s\n",
561 nt_errstr(status));
562 return;
565 if (d == NULL) {
566 continue;
569 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
570 "for domain tree root %s (%s)\n",
571 d->name, d->alt_name ));
573 d->domain_flags = dom_list[i].trust_flags;
574 d->domain_type = dom_list[i].trust_type;
575 d->domain_trust_attribs = dom_list[i].trust_attribs;
577 add_trusted_domains( d );
579 break;
582 TALLOC_FREE( dom_list );
584 return;
587 /********************************************************************
588 scan the transitive forest trusts (not our own)
589 ********************************************************************/
592 static void rescan_forest_trusts( void )
594 struct winbindd_domain *d = NULL;
595 struct winbindd_tdc_domain *dom_list = NULL;
596 size_t num_trusts = 0;
597 size_t i;
598 NTSTATUS status;
600 /* The only transitive trusts supported by Windows 2003 AD are
601 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
602 first two are handled in forest and listed by
603 DsEnumerateDomainTrusts(). Forest trusts are not so we
604 have to do that ourselves. */
606 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
607 return;
609 for ( i=0; i<num_trusts; i++ ) {
610 uint32_t flags = dom_list[i].trust_flags;
611 uint32_t type = dom_list[i].trust_type;
612 uint32_t attribs = dom_list[i].trust_attribs;
614 d = find_domain_from_name_noinit( dom_list[i].domain_name );
616 /* ignore our primary and internal domains */
618 if ( d && (d->internal || d->primary ) )
619 continue;
621 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
622 (type == LSA_TRUST_TYPE_UPLEVEL) &&
623 (attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
625 /* add the trusted domain if we don't know
626 about it */
628 if (d == NULL) {
629 status = add_trusted_domain(
630 dom_list[i].domain_name,
631 dom_list[i].dns_name,
632 &dom_list[i].sid,
633 type,
634 flags,
635 attribs,
636 SEC_CHAN_NULL,
637 find_default_route_domain(),
638 &d);
639 if (!NT_STATUS_IS_OK(status) &&
640 NT_STATUS_EQUAL(status,
641 NT_STATUS_NO_SUCH_DOMAIN))
643 DBG_ERR("add_trusted_domain: %s\n",
644 nt_errstr(status));
645 return;
649 if (d == NULL) {
650 continue;
653 DEBUG(10,("Following trust path for domain %s (%s)\n",
654 d->name, d->alt_name ));
655 add_trusted_domains( d );
659 TALLOC_FREE( dom_list );
661 return;
664 /*********************************************************************
665 The process of updating the trusted domain list is a three step
666 async process:
667 (a) ask our domain
668 (b) ask the root domain in our forest
669 (c) ask a DC in any Win2003 trusted forests
670 *********************************************************************/
672 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
673 struct timeval now, void *private_data)
675 TALLOC_FREE(te);
677 /* I used to clear the cache here and start over but that
678 caused problems in child processes that needed the
679 trust dom list early on. Removing it means we
680 could have some trusted domains listed that have been
681 removed from our primary domain's DC until a full
682 restart. This should be ok since I think this is what
683 Windows does as well. */
685 /* this will only add new domains we didn't already know about
686 in the domain_list()*/
688 add_trusted_domains( find_our_domain() );
690 te = tevent_add_timer(
691 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
692 rescan_trusted_domains, NULL);
694 * If te == NULL, there's not much we can do here. Don't fail, the
695 * only thing we miss is new trusted domains.
698 return;
701 static void wbd_ping_dc_done(struct tevent_req *subreq);
703 void winbindd_ping_offline_domains(struct tevent_context *ev,
704 struct tevent_timer *te,
705 struct timeval now,
706 void *private_data)
708 struct winbindd_domain *domain = NULL;
710 TALLOC_FREE(te);
712 for (domain = domain_list(); domain != NULL; domain = domain->next) {
713 DBG_DEBUG("Domain %s is %s\n",
714 domain->name,
715 domain->online ? "online" : "offline");
717 if (get_global_winbindd_state_offline()) {
718 DBG_DEBUG("We are globally offline, do nothing.\n");
719 break;
722 if (domain->online ||
723 domain->check_online_event != NULL ||
724 domain->secure_channel_type == SEC_CHAN_NULL) {
725 continue;
728 winbindd_flush_negative_conn_cache(domain);
730 domain->check_online_event =
731 dcerpc_wbint_PingDc_send(domain,
733 dom_child_handle(domain),
734 &domain->ping_dcname);
735 if (domain->check_online_event == NULL) {
736 DBG_WARNING("Failed to schedule ping, no-memory\n");
737 continue;
740 tevent_req_set_callback(domain->check_online_event,
741 wbd_ping_dc_done, domain);
744 te = tevent_add_timer(ev,
745 NULL,
746 timeval_current_ofs(lp_winbind_reconnect_delay(),
748 winbindd_ping_offline_domains,
749 NULL);
750 if (te == NULL) {
751 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
754 return;
757 static void wbd_ping_dc_done(struct tevent_req *subreq)
759 struct winbindd_domain *domain =
760 tevent_req_callback_data(subreq,
761 struct winbindd_domain);
762 NTSTATUS status, result;
764 SMB_ASSERT(subreq == domain->check_online_event);
765 domain->check_online_event = NULL;
767 status = dcerpc_wbint_PingDc_recv(subreq, domain, &result);
768 TALLOC_FREE(subreq);
769 if (any_nt_status_not_ok(status, result, &status)) {
770 DBG_WARNING("dcerpc_wbint_PingDc_recv failed for domain: "
771 "%s - %s\n",
772 domain->name,
773 nt_errstr(status));
774 return;
777 DBG_DEBUG("dcerpc_wbint_PingDc_recv() succeeded, "
778 "domain: %s, dc-name: %s\n",
779 domain->name,
780 domain->ping_dcname);
782 talloc_free(discard_const(domain->ping_dcname));
783 domain->ping_dcname = NULL;
785 return;
788 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
789 void *private_data,
790 uint32_t msg_type,
791 struct server_id server_id,
792 size_t num_fds,
793 int *fds,
794 DATA_BLOB *data)
796 bool ok;
798 if (num_fds != 0) {
799 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
800 return;
803 DBG_NOTICE("Rescanning trusted domains\n");
805 ok = add_trusted_domains_dc();
806 if (!ok) {
807 DBG_ERR("Failed to reload trusted domains\n");
812 * We did not get the secret when we queried secrets.tdb, so read it
813 * from secrets.tdb and re-sync the databases
815 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
817 bool ok;
818 struct cli_credentials *creds;
819 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
820 NULL, domain, &creds);
821 if (!NT_STATUS_IS_OK(can_migrate)) {
822 DEBUG(0, ("Failed to fetch our own local AD domain join "
823 "password for winbindd's internal use, both from "
824 "secrets.tdb and secrets.ldb: %s\n",
825 nt_errstr(can_migrate)));
826 return false;
830 * NOTE: It is very unlikely we end up here if there is an
831 * oldpass, because a new password is created at
832 * classicupgrade, so this is not a concern.
834 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
835 NULL /* oldpass */,
836 cli_credentials_get_domain(creds),
837 cli_credentials_get_realm(creds),
838 cli_credentials_get_salt_principal(creds, creds),
839 0, /* Supported enc types, unused */
840 &domain->sid,
841 cli_credentials_get_password_last_changed_time(creds),
842 cli_credentials_get_secure_channel_type(creds),
843 false /* do_delete: Do not delete */);
844 TALLOC_FREE(creds);
845 if (ok == false) {
846 DEBUG(0, ("Failed to write our own "
847 "local AD domain join password for "
848 "winbindd's internal use into secrets.tdb\n"));
849 return false;
851 return true;
854 bool add_trusted_domains_dc(void)
856 struct winbindd_domain *domain = NULL;
857 struct pdb_trusted_domain **domains = NULL;
858 uint32_t num_domains = 0;
859 uint32_t i;
860 NTSTATUS status;
862 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
863 struct trustdom_info **ti = NULL;
865 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
866 if (!NT_STATUS_IS_OK(status)) {
867 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
868 nt_errstr(status));
869 return false;
872 for (i = 0; i < num_domains; i++) {
873 status = add_trusted_domain(ti[i]->name,
874 NULL,
875 &ti[i]->sid,
876 LSA_TRUST_TYPE_DOWNLEVEL,
877 NETR_TRUST_FLAG_OUTBOUND,
879 SEC_CHAN_DOMAIN,
880 NULL,
881 &domain);
882 if (!NT_STATUS_IS_OK(status)) {
883 DBG_NOTICE("add_trusted_domain returned %s\n",
884 nt_errstr(status));
885 return false;
889 return true;
892 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
893 if (!NT_STATUS_IS_OK(status)) {
894 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
895 nt_errstr(status));
896 return false;
899 for (i = 0; i < num_domains; i++) {
900 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
901 uint32_t trust_flags = 0;
903 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
904 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
907 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
908 sec_chan_type = SEC_CHAN_NULL;
911 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
912 trust_flags |= NETR_TRUST_FLAG_INBOUND;
914 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
915 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
917 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
918 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
921 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
923 * We don't support selective authentication yet.
925 DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
926 "domain[%s/%s]\n",
927 domains[i]->netbios_name,
928 domains[i]->domain_name);
929 continue;
932 status = add_trusted_domain(domains[i]->netbios_name,
933 domains[i]->domain_name,
934 &domains[i]->security_identifier,
935 domains[i]->trust_type,
936 trust_flags,
937 domains[i]->trust_attributes,
938 sec_chan_type,
939 NULL,
940 &domain);
941 if (!NT_STATUS_IS_OK(status)) {
942 DBG_NOTICE("add_trusted_domain returned %s\n",
943 nt_errstr(status));
944 return false;
947 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
948 domain->active_directory = true;
950 domain->domain_type = domains[i]->trust_type;
951 domain->domain_trust_attribs = domains[i]->trust_attributes;
954 for (i = 0; i < num_domains; i++) {
955 struct ForestTrustInfo fti;
956 uint32_t fi;
957 enum ndr_err_code ndr_err;
958 struct winbindd_domain *routing_domain = NULL;
960 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
961 continue;
964 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
965 continue;
968 if (domains[i]->trust_forest_trust_info.length == 0) {
969 continue;
972 routing_domain = find_domain_from_name_noinit(
973 domains[i]->netbios_name);
974 if (routing_domain == NULL) {
975 DBG_ERR("Can't find winbindd domain [%s]\n",
976 domains[i]->netbios_name);
977 return false;
980 ndr_err = ndr_pull_struct_blob_all(
981 &domains[i]->trust_forest_trust_info,
982 talloc_tos(), &fti,
983 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
984 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
985 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
986 domains[i]->netbios_name,
987 ndr_map_error2string(ndr_err));
988 return false;
991 for (fi = 0; fi < fti.count; fi++) {
992 struct ForestTrustInfoRecord *rec =
993 &fti.records[fi].record;
994 struct ForestTrustDataDomainInfo *drec = NULL;
996 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
997 continue;
999 drec = &rec->data.info;
1001 if (rec->flags & LSA_NB_DISABLED_MASK) {
1002 continue;
1005 if (rec->flags & LSA_SID_DISABLED_MASK) {
1006 continue;
1010 * TODO:
1011 * also try to find a matching
1012 * LSA_TLN_DISABLED_MASK ???
1015 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1016 if (domain != NULL) {
1017 continue;
1020 status = add_trusted_domain(drec->netbios_name.string,
1021 drec->dns_name.string,
1022 &drec->sid,
1023 LSA_TRUST_TYPE_UPLEVEL,
1024 NETR_TRUST_FLAG_OUTBOUND,
1026 SEC_CHAN_NULL,
1027 routing_domain,
1028 &domain);
1029 if (!NT_STATUS_IS_OK(status)) {
1030 DBG_NOTICE("add_trusted_domain returned %s\n",
1031 nt_errstr(status));
1032 return false;
1034 if (domain == NULL) {
1035 continue;
1040 return true;
1044 /* Look up global info for the winbind daemon */
1045 bool init_domain_list(void)
1047 int role = lp_server_role();
1048 struct pdb_domain_info *pdb_domain_info = NULL;
1049 struct winbindd_domain *domain = NULL;
1050 NTSTATUS status;
1051 bool ok;
1053 /* Free existing list */
1054 free_domain_list();
1056 /* BUILTIN domain */
1058 status = add_trusted_domain("BUILTIN",
1059 NULL,
1060 &global_sid_Builtin,
1061 LSA_TRUST_TYPE_DOWNLEVEL,
1062 0, /* trust_flags */
1063 0, /* trust_attribs */
1064 SEC_CHAN_LOCAL,
1065 NULL,
1066 &domain);
1067 if (!NT_STATUS_IS_OK(status)) {
1068 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1069 nt_errstr(status));
1070 return false;
1073 /* Local SAM */
1076 * In case the passdb backend is passdb_dsdb the domain SID comes from
1077 * dsdb, not from secrets.tdb. As we use the domain SID in various
1078 * places, we must ensure the domain SID is migrated from dsdb to
1079 * secrets.tdb before get_global_sam_sid() is called the first time.
1081 * The migration is done as part of the passdb_dsdb initialisation,
1082 * calling pdb_get_domain_info() triggers it.
1084 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1086 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1087 uint32_t trust_flags;
1088 bool is_root;
1089 enum netr_SchannelType sec_chan_type;
1090 const char *account_name;
1091 struct samr_Password current_nt_hash;
1093 if (pdb_domain_info == NULL) {
1094 DEBUG(0, ("Failed to fetch our own local AD "
1095 "domain info from sam.ldb\n"));
1096 return false;
1099 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1100 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1101 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1102 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1104 is_root = strequal(pdb_domain_info->dns_domain,
1105 pdb_domain_info->dns_forest);
1106 if (is_root) {
1107 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1110 status = add_trusted_domain(pdb_domain_info->name,
1111 pdb_domain_info->dns_domain,
1112 &pdb_domain_info->sid,
1113 LSA_TRUST_TYPE_UPLEVEL,
1114 trust_flags,
1115 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1116 SEC_CHAN_BDC,
1117 NULL,
1118 &domain);
1119 TALLOC_FREE(pdb_domain_info);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 DBG_ERR("Failed to add our own local AD "
1122 "domain to winbindd's internal list\n");
1123 return false;
1127 * We need to call this to find out if we are an RODC
1129 ok = get_trust_pw_hash(domain->name,
1130 current_nt_hash.hash,
1131 &account_name,
1132 &sec_chan_type);
1133 if (!ok) {
1135 * If get_trust_pw_hash() fails, then try and
1136 * fetch the password from the more recent of
1137 * secrets.{ldb,tdb} using the
1138 * pdb_get_trust_credentials()
1140 ok = migrate_secrets_tdb_to_ldb(domain);
1142 if (!ok) {
1143 DEBUG(0, ("Failed to migrate our own "
1144 "local AD domain join password for "
1145 "winbindd's internal use into "
1146 "secrets.tdb\n"));
1147 return false;
1149 ok = get_trust_pw_hash(domain->name,
1150 current_nt_hash.hash,
1151 &account_name,
1152 &sec_chan_type);
1153 if (!ok) {
1154 DEBUG(0, ("Failed to find our own just "
1155 "written local AD domain join "
1156 "password for winbindd's internal "
1157 "use in secrets.tdb\n"));
1158 return false;
1162 domain->secure_channel_type = sec_chan_type;
1163 if (sec_chan_type == SEC_CHAN_RODC) {
1164 domain->rodc = true;
1167 } else {
1168 uint32_t trust_flags;
1169 enum netr_SchannelType secure_channel_type;
1171 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1172 if (role != ROLE_DOMAIN_MEMBER) {
1173 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1176 if (role > ROLE_DOMAIN_MEMBER) {
1177 secure_channel_type = SEC_CHAN_BDC;
1178 } else {
1179 secure_channel_type = SEC_CHAN_LOCAL;
1182 if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) {
1183 /* This is IPA DC that presents itself as
1184 * an Active Directory domain controller to trusted AD
1185 * forests but in fact is a classic domain controller.
1187 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1188 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1189 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1190 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1191 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1192 status = add_trusted_domain(pdb_domain_info->name,
1193 pdb_domain_info->dns_domain,
1194 &pdb_domain_info->sid,
1195 LSA_TRUST_TYPE_UPLEVEL,
1196 trust_flags,
1197 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1198 secure_channel_type,
1199 NULL,
1200 &domain);
1201 TALLOC_FREE(pdb_domain_info);
1202 } else {
1203 status = add_trusted_domain(get_global_sam_name(),
1204 NULL,
1205 get_global_sam_sid(),
1206 LSA_TRUST_TYPE_DOWNLEVEL,
1207 trust_flags,
1208 0, /* trust_attribs */
1209 secure_channel_type,
1210 NULL,
1211 &domain);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 DBG_ERR("Failed to add local SAM to "
1215 "domain to winbindd's internal list\n");
1216 return false;
1220 if (IS_DC) {
1221 ok = add_trusted_domains_dc();
1222 if (!ok) {
1223 DBG_ERR("init_domain_list_dc failed\n");
1224 return false;
1228 if ( role == ROLE_DOMAIN_MEMBER ) {
1229 struct dom_sid our_sid;
1230 uint32_t trust_type;
1232 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1233 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1234 return False;
1237 if (lp_realm() != NULL) {
1238 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1239 } else {
1240 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1243 status = add_trusted_domain(lp_workgroup(),
1244 lp_realm(),
1245 &our_sid,
1246 trust_type,
1247 NETR_TRUST_FLAG_PRIMARY|
1248 NETR_TRUST_FLAG_OUTBOUND,
1249 0, /* trust_attribs */
1250 SEC_CHAN_WKSTA,
1251 NULL,
1252 &domain);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 DBG_ERR("Failed to add local SAM to "
1255 "domain to winbindd's internal list\n");
1256 return false;
1260 status = imessaging_register(winbind_imessaging_context(), NULL,
1261 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1262 wb_imsg_new_trusted_domain);
1263 if (!NT_STATUS_IS_OK(status)) {
1264 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1265 return false;
1268 return True;
1272 * Given a domain name, return the struct winbindd domain info for it
1274 * @note Do *not* pass lp_workgroup() to this function. domain_list
1275 * may modify it's value, and free that pointer. Instead, our local
1276 * domain may be found by calling find_our_domain().
1277 * directly.
1280 * @return The domain structure for the named domain, if it is working.
1283 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1285 struct winbindd_domain *domain;
1287 /* Search through list */
1289 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1290 if (strequal(domain_name, domain->name)) {
1291 return domain;
1293 if (domain->alt_name == NULL) {
1294 continue;
1296 if (strequal(domain_name, domain->alt_name)) {
1297 return domain;
1301 /* Not found */
1303 return NULL;
1307 * Given a domain name, return the struct winbindd domain if it's a direct
1308 * outgoing trust
1310 * @return The domain structure for the named domain, if it is a direct outgoing trust
1312 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1314 struct winbindd_domain *domain = NULL;
1316 domain = find_domain_from_name_noinit(domain_name);
1317 if (domain == NULL) {
1318 return NULL;
1321 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1322 return domain;
1325 return NULL;
1328 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1330 struct winbindd_domain *domain;
1332 domain = find_domain_from_name_noinit(domain_name);
1334 if (domain == NULL)
1335 return NULL;
1337 if (!domain->initialized)
1338 init_dc_connection(domain, false);
1340 return domain;
1343 /* Given a domain sid, return the struct winbindd domain info for it */
1345 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1347 struct winbindd_domain *domain;
1349 /* Search through list */
1351 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1352 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1353 return domain;
1356 /* Not found */
1358 return NULL;
1362 * Given a domain sid, return the struct winbindd domain if it's a direct
1363 * outgoing trust
1365 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1367 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1369 struct winbindd_domain *domain = NULL;
1371 domain = find_domain_from_sid_noinit(sid);
1372 if (domain == NULL) {
1373 return NULL;
1376 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1377 return domain;
1380 return NULL;
1383 /* Given a domain sid, return the struct winbindd domain info for it */
1385 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1387 struct winbindd_domain *domain;
1389 domain = find_domain_from_sid_noinit(sid);
1391 if (domain == NULL)
1392 return NULL;
1394 if (!domain->initialized)
1395 init_dc_connection(domain, false);
1397 return domain;
1400 struct winbindd_domain *find_our_domain(void)
1402 struct winbindd_domain *domain;
1404 /* Search through list */
1406 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1407 if (domain->primary)
1408 return domain;
1411 smb_panic("Could not find our domain");
1412 return NULL;
1415 struct winbindd_domain *find_default_route_domain(void)
1417 if (!IS_DC) {
1418 return find_our_domain();
1420 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1421 return NULL;
1424 /* Find the appropriate domain to lookup a name or SID */
1426 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1428 struct dom_sid_buf buf;
1430 DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid, &buf));
1433 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1434 * by our passdb.
1437 if ( sid_check_is_in_unix_groups(sid) ||
1438 sid_check_is_unix_groups(sid) ||
1439 sid_check_is_in_unix_users(sid) ||
1440 sid_check_is_unix_users(sid) ||
1441 sid_check_is_our_sam(sid) ||
1442 sid_check_is_in_our_sam(sid) )
1444 return find_domain_from_sid(get_global_sam_sid());
1447 if ( sid_check_is_builtin(sid) ||
1448 sid_check_is_in_builtin(sid) ||
1449 sid_check_is_wellknown_domain(sid, NULL) ||
1450 sid_check_is_in_wellknown_domain(sid) )
1452 return find_domain_from_sid(&global_sid_Builtin);
1455 if (IS_DC) {
1456 struct winbindd_domain *domain = NULL;
1458 domain = find_domain_from_sid_noinit(sid);
1459 if (domain == NULL) {
1460 return NULL;
1463 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1464 return domain;
1467 return domain->routing_domain;
1470 /* On a member server a query for SID or name can always go to our
1471 * primary DC. */
1473 DEBUG(10, ("calling find_our_domain\n"));
1474 return find_our_domain();
1477 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1479 bool predefined;
1481 if ( strequal(domain_name, unix_users_domain_name() ) ||
1482 strequal(domain_name, unix_groups_domain_name() ) )
1485 * The "Unix User" and "Unix Group" domain are handled by
1486 * passdb
1488 return find_domain_from_name_noinit( get_global_sam_name() );
1491 if (strequal(domain_name, "BUILTIN") ||
1492 strequal(domain_name, get_global_sam_name())) {
1493 return find_domain_from_name_noinit(domain_name);
1496 predefined = dom_sid_lookup_is_predefined_domain(domain_name);
1497 if (predefined) {
1498 return find_domain_from_name_noinit(builtin_domain_name());
1501 if (IS_DC) {
1502 struct winbindd_domain *domain = NULL;
1504 domain = find_domain_from_name_noinit(domain_name);
1505 if (domain == NULL) {
1506 return NULL;
1509 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1510 return domain;
1513 return domain->routing_domain;
1516 return find_our_domain();
1519 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1521 static bool assume_domain(const char *domain)
1523 /* never assume the domain on a standalone server */
1525 if ( lp_server_role() == ROLE_STANDALONE )
1526 return False;
1528 /* domain member servers may possibly assume for the domain name */
1530 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1531 if ( !strequal(lp_workgroup(), domain) )
1532 return False;
1534 if ( lp_winbind_use_default_domain() )
1535 return True;
1538 /* only left with a domain controller */
1540 if ( strequal(get_global_sam_name(), domain) ) {
1541 return True;
1544 return False;
1547 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1548 bool parse_domain_user(TALLOC_CTX *ctx,
1549 const char *domuser,
1550 char **pnamespace,
1551 char **pdomain,
1552 char **puser)
1554 char *p = NULL;
1555 char *namespace = NULL;
1556 char *domain = NULL;
1557 char *user = NULL;
1559 if (strlen(domuser) == 0) {
1560 return false;
1563 p = strchr(domuser, *lp_winbind_separator());
1564 if (p != NULL) {
1565 user = talloc_strdup(ctx, p + 1);
1566 if (user == NULL) {
1567 goto fail;
1569 domain = talloc_strdup(ctx,
1570 domuser);
1571 if (domain == NULL) {
1572 goto fail;
1574 domain[PTR_DIFF(p, domuser)] = '\0';
1575 namespace = talloc_strdup(ctx, domain);
1576 if (namespace == NULL) {
1577 goto fail;
1579 } else {
1580 user = talloc_strdup(ctx, domuser);
1581 if (user == NULL) {
1582 goto fail;
1584 p = strchr(domuser, '@');
1585 if (p != NULL) {
1586 /* upn */
1587 namespace = talloc_strdup(ctx, p + 1);
1588 if (namespace == NULL) {
1589 goto fail;
1591 domain = talloc_strdup(ctx, "");
1592 if (domain == NULL) {
1593 goto fail;
1596 } else if (assume_domain(lp_workgroup())) {
1597 domain = talloc_strdup(ctx, lp_workgroup());
1598 if (domain == NULL) {
1599 goto fail;
1601 namespace = talloc_strdup(ctx, domain);
1602 if (namespace == NULL) {
1603 goto fail;
1605 } else {
1606 namespace = talloc_strdup(ctx, lp_netbios_name());
1607 if (namespace == NULL) {
1608 goto fail;
1610 domain = talloc_strdup(ctx, "");
1611 if (domain == NULL) {
1612 goto fail;
1617 if (!strupper_m(domain)) {
1618 goto fail;
1621 *pnamespace = namespace;
1622 *pdomain = domain;
1623 *puser = user;
1624 return true;
1625 fail:
1626 TALLOC_FREE(user);
1627 TALLOC_FREE(domain);
1628 TALLOC_FREE(namespace);
1629 return false;
1632 bool canonicalize_username(TALLOC_CTX *mem_ctx,
1633 char **pusername_inout,
1634 char **pnamespace,
1635 char **pdomain,
1636 char **puser)
1638 bool ok;
1639 char *namespace = NULL;
1640 char *domain = NULL;
1641 char *user = NULL;
1642 char *username_inout = NULL;
1644 ok = parse_domain_user(mem_ctx,
1645 *pusername_inout,
1646 &namespace, &domain, &user);
1648 if (!ok) {
1649 return False;
1652 username_inout = talloc_asprintf(mem_ctx, "%s%c%s",
1653 domain, *lp_winbind_separator(),
1654 user);
1656 if (username_inout == NULL) {
1657 goto fail;
1660 *pnamespace = namespace;
1661 *puser = user;
1662 *pdomain = domain;
1663 *pusername_inout = username_inout;
1664 return True;
1665 fail:
1666 TALLOC_FREE(username_inout);
1667 TALLOC_FREE(namespace);
1668 TALLOC_FREE(domain);
1669 TALLOC_FREE(user);
1670 return false;
1674 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1675 'winbind separator' options.
1676 This means:
1677 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1678 lp_workgroup()
1680 If we are a PDC or BDC, and this is for our domain, do likewise.
1682 On an AD DC we always fill DOMAIN\\USERNAME.
1684 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1687 * talloc version of fill_domain_username()
1688 * return NULL on talloc failure.
1690 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1691 const char *domain,
1692 const char *user,
1693 bool can_assume)
1695 char *tmp_user, *name;
1697 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1698 can_assume = false;
1701 if (user == NULL) {
1702 return NULL;
1705 tmp_user = talloc_strdup(mem_ctx, user);
1706 if (tmp_user == NULL) {
1707 return NULL;
1709 if (!strlower_m(tmp_user)) {
1710 TALLOC_FREE(tmp_user);
1711 return NULL;
1714 if (can_assume && assume_domain(domain)) {
1715 name = tmp_user;
1716 } else {
1717 name = talloc_asprintf(mem_ctx, "%s%c%s",
1718 domain,
1719 *lp_winbind_separator(),
1720 tmp_user);
1721 TALLOC_FREE(tmp_user);
1724 return name;
1728 * Client list accessor functions
1731 static struct winbindd_cli_state *_client_list;
1732 static int _num_clients;
1734 /* Return list of all connected clients */
1736 struct winbindd_cli_state *winbindd_client_list(void)
1738 return _client_list;
1741 /* Return list-tail of all connected clients */
1743 struct winbindd_cli_state *winbindd_client_list_tail(void)
1745 return DLIST_TAIL(_client_list);
1748 /* Return previous (read:newer) client in list */
1750 struct winbindd_cli_state *
1751 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1753 return DLIST_PREV(cli);
1756 /* Add a connection to the list */
1758 void winbindd_add_client(struct winbindd_cli_state *cli)
1760 cli->last_access = time(NULL);
1761 DLIST_ADD(_client_list, cli);
1762 _num_clients++;
1765 /* Remove a client from the list */
1767 void winbindd_remove_client(struct winbindd_cli_state *cli)
1769 DLIST_REMOVE(_client_list, cli);
1770 _num_clients--;
1773 /* Move a client to head or list */
1775 void winbindd_promote_client(struct winbindd_cli_state *cli)
1777 cli->last_access = time(NULL);
1778 DLIST_PROMOTE(_client_list, cli);
1781 /* Return number of open clients */
1783 int winbindd_num_clients(void)
1785 return _num_clients;
1788 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1789 const struct dom_sid *user_sid,
1790 uint32_t *p_num_groups, struct dom_sid **user_sids)
1792 struct netr_SamInfo3 *info3 = NULL;
1793 NTSTATUS status = NT_STATUS_NO_MEMORY;
1794 uint32_t num_groups = 0;
1796 DEBUG(3,(": lookup_usergroups_cached\n"));
1798 *user_sids = NULL;
1799 *p_num_groups = 0;
1801 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1803 if (info3 == NULL) {
1804 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1808 * Before bug #7843 the "Domain Local" groups were added with a
1809 * lookupuseraliases call, but this isn't done anymore for our domain
1810 * so we need to resolve resource groups here.
1812 * When to use Resource Groups:
1813 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1815 status = sid_array_from_info3(mem_ctx, info3,
1816 user_sids,
1817 &num_groups,
1818 false);
1820 if (!NT_STATUS_IS_OK(status)) {
1821 TALLOC_FREE(info3);
1822 return status;
1825 TALLOC_FREE(info3);
1826 *p_num_groups = num_groups;
1827 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1829 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1831 return status;
1834 /*********************************************************************
1835 We use this to remove spaces from user and group names
1836 ********************************************************************/
1838 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1839 const char *domain_name,
1840 const char *name,
1841 char **normalized)
1843 struct winbindd_domain *domain = NULL;
1844 NTSTATUS nt_status;
1846 if (!name || !normalized) {
1847 return NT_STATUS_INVALID_PARAMETER;
1850 if (!lp_winbind_normalize_names()) {
1851 return NT_STATUS_PROCEDURE_NOT_FOUND;
1854 domain = find_domain_from_name_noinit(domain_name);
1855 if (domain == NULL) {
1856 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1857 return NT_STATUS_NO_SUCH_DOMAIN;
1860 /* Alias support and whitespace replacement are mutually
1861 exclusive */
1863 nt_status = resolve_username_to_alias(mem_ctx, domain,
1864 name, normalized );
1865 if (NT_STATUS_IS_OK(nt_status)) {
1866 /* special return code to let the caller know we
1867 mapped to an alias */
1868 return NT_STATUS_FILE_RENAMED;
1871 /* check for an unreachable domain */
1873 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1874 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1875 domain->name));
1876 set_domain_offline(domain);
1877 return nt_status;
1880 /* deal with whitespace */
1882 *normalized = talloc_strdup(mem_ctx, name);
1883 if (!(*normalized)) {
1884 return NT_STATUS_NO_MEMORY;
1887 all_string_sub( *normalized, " ", "_", 0 );
1889 return NT_STATUS_OK;
1892 /*********************************************************************
1893 We use this to do the inverse of normalize_name_map()
1894 ********************************************************************/
1896 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1897 const char *name,
1898 char **normalized)
1900 NTSTATUS nt_status;
1901 struct winbindd_domain *domain = find_our_domain();
1903 if (!name || !normalized) {
1904 return NT_STATUS_INVALID_PARAMETER;
1907 if (!lp_winbind_normalize_names()) {
1908 return NT_STATUS_PROCEDURE_NOT_FOUND;
1911 /* Alias support and whitespace replacement are mutally
1912 exclusive */
1914 /* When mapping from an alias to a username, we don't know the
1915 domain. But we only need a domain structure to cache
1916 a successful lookup , so just our own domain structure for
1917 the seqnum. */
1919 nt_status = resolve_alias_to_username(mem_ctx, domain,
1920 name, normalized);
1921 if (NT_STATUS_IS_OK(nt_status)) {
1922 /* Special return code to let the caller know we mapped
1923 from an alias */
1924 return NT_STATUS_FILE_RENAMED;
1927 /* check for an unreachable domain */
1929 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1930 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1931 domain->name));
1932 set_domain_offline(domain);
1933 return nt_status;
1936 /* deal with whitespace */
1938 *normalized = talloc_strdup(mem_ctx, name);
1939 if (!(*normalized)) {
1940 return NT_STATUS_NO_MEMORY;
1943 all_string_sub(*normalized, "_", " ", 0);
1945 return NT_STATUS_OK;
1948 /*********************************************************************
1949 ********************************************************************/
1951 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1953 struct winbindd_tdc_domain *tdc = NULL;
1954 TALLOC_CTX *frame = talloc_stackframe();
1955 bool ret = false;
1957 /* We can contact the domain if it is our primary domain */
1959 if (domain->primary) {
1960 ret = true;
1961 goto done;
1964 /* Trust the TDC cache and not the winbindd_domain flags */
1966 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1967 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1968 domain->name));
1969 ret = false;
1970 goto done;
1973 /* Can always contact a domain that is in out forest */
1975 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1976 ret = true;
1977 goto done;
1981 * On a _member_ server, we cannot contact the domain if it
1982 * is running AD and we have no inbound trust.
1985 if (!IS_DC &&
1986 domain->active_directory &&
1987 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1989 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1990 "and we have no inbound trust.\n", domain->name));
1991 goto done;
1994 /* Assume everything else is ok (probably not true but what
1995 can you do?) */
1997 ret = true;
1999 done:
2000 talloc_destroy(frame);
2002 return ret;
2005 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
2007 /*********************************************************************
2008 ********************************************************************/
2010 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
2012 char *var = NULL;
2013 char addr[INET6_ADDRSTRLEN];
2014 const char *kdc = NULL;
2015 int lvl = 11;
2017 if (!domain || !domain->alt_name || !*domain->alt_name) {
2018 return;
2021 if (domain->initialized && !domain->active_directory) {
2022 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2023 domain->alt_name));
2024 return;
2027 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2028 kdc = addr;
2029 if (!*kdc) {
2030 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2031 domain->alt_name));
2032 kdc = domain->dcname;
2035 if (!kdc || !*kdc) {
2036 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2037 domain->alt_name));
2038 return;
2041 var = talloc_asprintf_strupper_m(
2042 talloc_tos(),
2043 "%s_%s",
2044 WINBINDD_LOCATOR_KDC_ADDRESS,
2045 domain->alt_name);
2046 if (var == NULL) {
2047 return;
2050 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2051 var, kdc));
2053 setenv(var, kdc, 1);
2054 TALLOC_FREE(var);
2057 /*********************************************************************
2058 ********************************************************************/
2060 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2062 struct winbindd_domain *our_dom = find_our_domain();
2064 winbindd_set_locator_kdc_env(domain);
2066 if (domain != our_dom) {
2067 winbindd_set_locator_kdc_env(our_dom);
2071 /*********************************************************************
2072 ********************************************************************/
2074 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2076 char *var = NULL;
2078 if (!domain || !domain->alt_name || !*domain->alt_name) {
2079 return;
2082 var = talloc_asprintf_strupper_m(
2083 talloc_tos(),
2084 "%s_%s",
2085 WINBINDD_LOCATOR_KDC_ADDRESS,
2086 domain->alt_name);
2087 if (var == NULL) {
2088 return;
2091 unsetenv(var);
2092 TALLOC_FREE(var);
2094 #else
2096 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2098 return;
2101 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2103 return;
2106 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2108 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2111 * Make sure we start with authoritative=true,
2112 * it will only set to false if we don't know the
2113 * domain.
2115 resp->data.auth.authoritative = true;
2117 resp->data.auth.nt_status = NT_STATUS_V(result);
2118 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2120 /* we might have given a more useful error above */
2121 if (*resp->data.auth.error_string == '\0')
2122 fstrcpy(resp->data.auth.error_string,
2123 get_friendly_nt_error_msg(result));
2124 resp->data.auth.pam_error = nt_status_to_pam(result);
2127 bool is_domain_offline(const struct winbindd_domain *domain)
2129 if (get_global_winbindd_state_offline()) {
2130 return true;
2132 return !domain->online;
2135 bool is_domain_online(const struct winbindd_domain *domain)
2137 return !is_domain_offline(domain);
2141 * Parse an char array into a list of sids.
2143 * The input sidstr should consist of 0-terminated strings
2144 * representing sids, separated by newline characters '\n'.
2145 * The list is terminated by an empty string, i.e.
2146 * character '\0' directly following a character '\n'
2147 * (or '\0' right at the start of sidstr).
2149 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2150 struct dom_sid **sids, uint32_t *num_sids)
2152 const char *p;
2154 p = sidstr;
2155 if (p == NULL)
2156 return False;
2158 while (p[0] != '\0') {
2159 struct dom_sid sid;
2160 const char *q = NULL;
2162 if (!dom_sid_parse_endp(p, &sid, &q)) {
2163 DEBUG(1, ("Could not parse sid %s\n", p));
2164 return false;
2166 if (q[0] != '\n') {
2167 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2168 return false;
2170 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2171 num_sids)))
2173 return False;
2175 p = q+1;
2177 return True;
2180 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2181 struct unixid **pxids, uint32_t *pnum_xids)
2183 const char *p;
2184 struct unixid *xids = NULL;
2185 uint32_t num_xids = 0;
2187 p = xidstr;
2188 if (p == NULL) {
2189 return false;
2192 while (p[0] != '\0') {
2193 struct unixid *tmp;
2194 struct unixid xid;
2195 unsigned long long id;
2196 char *endp;
2197 int error = 0;
2199 switch (p[0]) {
2200 case 'U':
2201 xid = (struct unixid) { .type = ID_TYPE_UID };
2202 break;
2203 case 'G':
2204 xid = (struct unixid) { .type = ID_TYPE_GID };
2205 break;
2206 default:
2207 return false;
2210 p += 1;
2212 id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
2213 if (error != 0) {
2214 goto fail;
2216 if (*endp != '\n') {
2217 goto fail;
2219 p = endp+1;
2221 xid.id = id;
2222 if ((unsigned long long)xid.id != id) {
2223 goto fail;
2226 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2227 if (tmp == NULL) {
2228 return 0;
2230 xids = tmp;
2232 xids[num_xids] = xid;
2233 num_xids += 1;
2236 *pxids = xids;
2237 *pnum_xids = num_xids;
2238 return true;
2240 fail:
2241 TALLOC_FREE(xids);
2242 return false;