ctdb-scripts: Move connection tracking to 10.interface
[samba4-gss.git] / source3 / winbindd / winbindd_util.c
blob681d4194127d504031d9c8278038f2ba7f33642e
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;
955 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
956 domain->active_directory = true;
958 domain->domain_type = domains[i]->trust_type;
959 domain->domain_trust_attribs = domains[i]->trust_attributes;
962 for (i = 0; i < num_domains; i++) {
963 struct ForestTrustInfo fti;
964 uint32_t fi;
965 enum ndr_err_code ndr_err;
966 struct winbindd_domain *routing_domain = NULL;
968 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
969 continue;
972 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
973 continue;
976 if (domains[i]->trust_forest_trust_info.length == 0) {
977 continue;
980 routing_domain = find_domain_from_name_noinit(
981 domains[i]->netbios_name);
982 if (routing_domain == NULL) {
983 DBG_ERR("Can't find winbindd domain [%s]\n",
984 domains[i]->netbios_name);
985 return false;
988 ndr_err = ndr_pull_struct_blob_all(
989 &domains[i]->trust_forest_trust_info,
990 talloc_tos(), &fti,
991 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
992 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
993 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
994 domains[i]->netbios_name,
995 ndr_map_error2string(ndr_err));
996 return false;
999 for (fi = 0; fi < fti.count; fi++) {
1000 struct ForestTrustInfoRecord *rec =
1001 &fti.records[fi].record;
1002 struct ForestTrustDataDomainInfo *drec = NULL;
1004 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1005 continue;
1007 drec = &rec->data.info;
1009 if (rec->flags & LSA_NB_DISABLED_MASK) {
1010 continue;
1013 if (rec->flags & LSA_SID_DISABLED_MASK) {
1014 continue;
1018 * TODO:
1019 * also try to find a matching
1020 * LSA_TLN_DISABLED_MASK ???
1023 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1024 if (domain != NULL) {
1025 continue;
1028 status = add_trusted_domain(drec->netbios_name.string,
1029 drec->dns_name.string,
1030 &drec->sid,
1031 LSA_TRUST_TYPE_UPLEVEL,
1032 NETR_TRUST_FLAG_OUTBOUND,
1034 SEC_CHAN_NULL,
1035 routing_domain,
1036 &domain);
1037 if (!NT_STATUS_IS_OK(status)) {
1038 DBG_NOTICE("add_trusted_domain returned %s\n",
1039 nt_errstr(status));
1040 return false;
1042 if (domain == NULL) {
1043 continue;
1048 return true;
1052 /* Look up global info for the winbind daemon */
1053 bool init_domain_list(void)
1055 int role = lp_server_role();
1056 struct pdb_domain_info *pdb_domain_info = NULL;
1057 struct winbindd_domain *domain = NULL;
1058 NTSTATUS status;
1059 bool ok;
1061 /* Free existing list */
1062 free_domain_list();
1064 /* BUILTIN domain */
1066 status = add_trusted_domain("BUILTIN",
1067 NULL,
1068 &global_sid_Builtin,
1069 LSA_TRUST_TYPE_DOWNLEVEL,
1070 0, /* trust_flags */
1071 0, /* trust_attribs */
1072 SEC_CHAN_LOCAL,
1073 NULL,
1074 &domain);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1077 nt_errstr(status));
1078 return false;
1081 /* Local SAM */
1084 * In case the passdb backend is passdb_dsdb the domain SID comes from
1085 * dsdb, not from secrets.tdb. As we use the domain SID in various
1086 * places, we must ensure the domain SID is migrated from dsdb to
1087 * secrets.tdb before get_global_sam_sid() is called the first time.
1089 * The migration is done as part of the passdb_dsdb initialisation,
1090 * calling pdb_get_domain_info() triggers it.
1092 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1094 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1095 uint32_t trust_flags;
1096 bool is_root;
1097 enum netr_SchannelType sec_chan_type;
1098 const char *account_name;
1099 struct samr_Password current_nt_hash;
1101 if (pdb_domain_info == NULL) {
1102 DEBUG(0, ("Failed to fetch our own local AD "
1103 "domain info from sam.ldb\n"));
1104 return false;
1107 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1108 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1109 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1110 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1112 is_root = strequal(pdb_domain_info->dns_domain,
1113 pdb_domain_info->dns_forest);
1114 if (is_root) {
1115 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1118 status = add_trusted_domain(pdb_domain_info->name,
1119 pdb_domain_info->dns_domain,
1120 &pdb_domain_info->sid,
1121 LSA_TRUST_TYPE_UPLEVEL,
1122 trust_flags,
1123 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1124 SEC_CHAN_BDC,
1125 NULL,
1126 &domain);
1127 TALLOC_FREE(pdb_domain_info);
1128 if (!NT_STATUS_IS_OK(status)) {
1129 DBG_ERR("Failed to add our own local AD "
1130 "domain to winbindd's internal list\n");
1131 return false;
1135 * We need to call this to find out if we are an RODC
1137 ok = get_trust_pw_hash(domain->name,
1138 current_nt_hash.hash,
1139 &account_name,
1140 &sec_chan_type);
1141 if (!ok) {
1143 * If get_trust_pw_hash() fails, then try and
1144 * fetch the password from the more recent of
1145 * secrets.{ldb,tdb} using the
1146 * pdb_get_trust_credentials()
1148 ok = migrate_secrets_tdb_to_ldb(domain);
1150 if (!ok) {
1151 DEBUG(0, ("Failed to migrate our own "
1152 "local AD domain join password for "
1153 "winbindd's internal use into "
1154 "secrets.tdb\n"));
1155 return false;
1157 ok = get_trust_pw_hash(domain->name,
1158 current_nt_hash.hash,
1159 &account_name,
1160 &sec_chan_type);
1161 if (!ok) {
1162 DEBUG(0, ("Failed to find our own just "
1163 "written local AD domain join "
1164 "password for winbindd's internal "
1165 "use in secrets.tdb\n"));
1166 return false;
1170 domain->secure_channel_type = sec_chan_type;
1171 if (sec_chan_type == SEC_CHAN_RODC) {
1172 domain->rodc = true;
1175 } else {
1176 uint32_t trust_flags;
1177 enum netr_SchannelType secure_channel_type;
1179 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1180 if (role != ROLE_DOMAIN_MEMBER) {
1181 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1184 if (role > ROLE_DOMAIN_MEMBER) {
1185 secure_channel_type = SEC_CHAN_BDC;
1186 } else {
1187 secure_channel_type = SEC_CHAN_LOCAL;
1190 if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) {
1191 /* This is IPA DC that presents itself as
1192 * an Active Directory domain controller to trusted AD
1193 * forests but in fact is a classic domain controller.
1195 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1196 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1197 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1198 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1199 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1200 status = add_trusted_domain(pdb_domain_info->name,
1201 pdb_domain_info->dns_domain,
1202 &pdb_domain_info->sid,
1203 LSA_TRUST_TYPE_UPLEVEL,
1204 trust_flags,
1205 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1206 secure_channel_type,
1207 NULL,
1208 &domain);
1209 TALLOC_FREE(pdb_domain_info);
1210 } else {
1211 status = add_trusted_domain(get_global_sam_name(),
1212 NULL,
1213 get_global_sam_sid(),
1214 LSA_TRUST_TYPE_DOWNLEVEL,
1215 trust_flags,
1216 0, /* trust_attribs */
1217 secure_channel_type,
1218 NULL,
1219 &domain);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 DBG_ERR("Failed to add local SAM to "
1223 "domain to winbindd's internal list\n");
1224 return false;
1228 if (IS_DC) {
1229 ok = add_trusted_domains_dc();
1230 if (!ok) {
1231 DBG_ERR("init_domain_list_dc failed\n");
1232 return false;
1236 if ( role == ROLE_DOMAIN_MEMBER ) {
1237 struct dom_sid our_sid;
1238 uint32_t trust_type;
1240 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1241 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1242 return False;
1245 if (lp_realm() != NULL) {
1246 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1247 } else {
1248 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1251 status = add_trusted_domain(lp_workgroup(),
1252 lp_realm(),
1253 &our_sid,
1254 trust_type,
1255 NETR_TRUST_FLAG_PRIMARY|
1256 NETR_TRUST_FLAG_OUTBOUND,
1257 0, /* trust_attribs */
1258 SEC_CHAN_WKSTA,
1259 NULL,
1260 &domain);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 DBG_ERR("Failed to add local SAM to "
1263 "domain to winbindd's internal list\n");
1264 return false;
1268 status = imessaging_register(winbind_imessaging_context(), NULL,
1269 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1270 wb_imsg_new_trusted_domain);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1273 return false;
1276 return True;
1280 * Given a domain name, return the struct winbindd domain info for it
1282 * @note Do *not* pass lp_workgroup() to this function. domain_list
1283 * may modify it's value, and free that pointer. Instead, our local
1284 * domain may be found by calling find_our_domain().
1285 * directly.
1288 * @return The domain structure for the named domain, if it is working.
1291 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1293 struct winbindd_domain *domain;
1295 /* Search through list */
1297 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1298 if (strequal(domain_name, domain->name)) {
1299 return domain;
1301 if (domain->alt_name == NULL) {
1302 continue;
1304 if (strequal(domain_name, domain->alt_name)) {
1305 return domain;
1309 /* Not found */
1311 return NULL;
1315 * Given a domain name, return the struct winbindd domain if it's a direct
1316 * outgoing trust
1318 * @return The domain structure for the named domain, if it is a direct outgoing trust
1320 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1322 struct winbindd_domain *domain = NULL;
1324 domain = find_domain_from_name_noinit(domain_name);
1325 if (domain == NULL) {
1326 return NULL;
1329 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1330 return domain;
1333 return NULL;
1336 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1338 struct winbindd_domain *domain;
1340 domain = find_domain_from_name_noinit(domain_name);
1342 if (domain == NULL)
1343 return NULL;
1345 if (!domain->initialized)
1346 init_dc_connection(domain, false);
1348 return domain;
1351 /* Given a domain sid, return the struct winbindd domain info for it */
1353 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1355 struct winbindd_domain *domain;
1357 /* Search through list */
1359 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1360 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1361 return domain;
1364 /* Not found */
1366 return NULL;
1370 * Given a domain sid, return the struct winbindd domain if it's a direct
1371 * outgoing trust
1373 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1375 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1377 struct winbindd_domain *domain = NULL;
1379 domain = find_domain_from_sid_noinit(sid);
1380 if (domain == NULL) {
1381 return NULL;
1384 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1385 return domain;
1388 return NULL;
1391 /* Given a domain sid, return the struct winbindd domain info for it */
1393 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1395 struct winbindd_domain *domain;
1397 domain = find_domain_from_sid_noinit(sid);
1399 if (domain == NULL)
1400 return NULL;
1402 if (!domain->initialized)
1403 init_dc_connection(domain, false);
1405 return domain;
1408 struct winbindd_domain *find_our_domain(void)
1410 struct winbindd_domain *domain;
1412 /* Search through list */
1414 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1415 if (domain->primary)
1416 return domain;
1419 smb_panic("Could not find our domain");
1420 return NULL;
1423 struct winbindd_domain *find_default_route_domain(void)
1425 if (!IS_DC) {
1426 return find_our_domain();
1428 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1429 return NULL;
1432 /* Find the appropriate domain to lookup a name or SID */
1434 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1436 struct dom_sid_buf buf;
1438 DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid, &buf));
1441 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1442 * by our passdb.
1445 if ( sid_check_is_in_unix_groups(sid) ||
1446 sid_check_is_unix_groups(sid) ||
1447 sid_check_is_in_unix_users(sid) ||
1448 sid_check_is_unix_users(sid) ||
1449 sid_check_is_our_sam(sid) ||
1450 sid_check_is_in_our_sam(sid) )
1452 return find_domain_from_sid(get_global_sam_sid());
1455 if ( sid_check_is_builtin(sid) ||
1456 sid_check_is_in_builtin(sid) ||
1457 sid_check_is_wellknown_domain(sid, NULL) ||
1458 sid_check_is_in_wellknown_domain(sid) )
1460 return find_domain_from_sid(&global_sid_Builtin);
1463 if (IS_DC) {
1464 struct winbindd_domain *domain = NULL;
1466 domain = find_domain_from_sid_noinit(sid);
1467 if (domain == NULL) {
1468 return NULL;
1471 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1472 return domain;
1475 return domain->routing_domain;
1478 /* On a member server a query for SID or name can always go to our
1479 * primary DC. */
1481 DEBUG(10, ("calling find_our_domain\n"));
1482 return find_our_domain();
1485 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1487 bool predefined;
1489 if ( strequal(domain_name, unix_users_domain_name() ) ||
1490 strequal(domain_name, unix_groups_domain_name() ) )
1493 * The "Unix User" and "Unix Group" domain are handled by
1494 * passdb
1496 return find_domain_from_name_noinit( get_global_sam_name() );
1499 if (strequal(domain_name, "BUILTIN") ||
1500 strequal(domain_name, get_global_sam_name())) {
1501 return find_domain_from_name_noinit(domain_name);
1504 predefined = dom_sid_lookup_is_predefined_domain(domain_name);
1505 if (predefined) {
1506 return find_domain_from_name_noinit(builtin_domain_name());
1509 if (IS_DC) {
1510 struct winbindd_domain *domain = NULL;
1512 domain = find_domain_from_name_noinit(domain_name);
1513 if (domain == NULL) {
1514 return NULL;
1517 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1518 return domain;
1521 return domain->routing_domain;
1524 return find_our_domain();
1527 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1529 static bool assume_domain(const char *domain)
1531 /* never assume the domain on a standalone server */
1533 if ( lp_server_role() == ROLE_STANDALONE )
1534 return False;
1536 /* domain member servers may possibly assume for the domain name */
1538 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1539 if ( !strequal(lp_workgroup(), domain) )
1540 return False;
1542 if ( lp_winbind_use_default_domain() )
1543 return True;
1546 /* only left with a domain controller */
1548 if ( strequal(get_global_sam_name(), domain) ) {
1549 return True;
1552 return False;
1555 /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
1556 bool parse_domain_user(TALLOC_CTX *ctx,
1557 const char *domuser,
1558 char **pnamespace,
1559 char **pdomain,
1560 char **puser)
1562 char *p = NULL;
1563 char *namespace = NULL;
1564 char *domain = NULL;
1565 char *user = NULL;
1567 if (strlen(domuser) == 0) {
1568 return false;
1571 p = strchr(domuser, *lp_winbind_separator());
1572 if (p != NULL) {
1573 user = talloc_strdup(ctx, p + 1);
1574 if (user == NULL) {
1575 goto fail;
1577 domain = talloc_strdup(ctx,
1578 domuser);
1579 if (domain == NULL) {
1580 goto fail;
1582 domain[PTR_DIFF(p, domuser)] = '\0';
1583 namespace = talloc_strdup(ctx, domain);
1584 if (namespace == NULL) {
1585 goto fail;
1587 } else {
1588 user = talloc_strdup(ctx, domuser);
1589 if (user == NULL) {
1590 goto fail;
1592 p = strchr(domuser, '@');
1593 if (p != NULL) {
1594 /* upn */
1595 namespace = talloc_strdup(ctx, p + 1);
1596 if (namespace == NULL) {
1597 goto fail;
1599 domain = talloc_strdup(ctx, "");
1600 if (domain == NULL) {
1601 goto fail;
1604 } else if (assume_domain(lp_workgroup())) {
1605 domain = talloc_strdup(ctx, lp_workgroup());
1606 if (domain == NULL) {
1607 goto fail;
1609 namespace = talloc_strdup(ctx, domain);
1610 if (namespace == NULL) {
1611 goto fail;
1613 } else {
1614 namespace = talloc_strdup(ctx, lp_netbios_name());
1615 if (namespace == NULL) {
1616 goto fail;
1618 domain = talloc_strdup(ctx, "");
1619 if (domain == NULL) {
1620 goto fail;
1625 if (!strupper_m(domain)) {
1626 goto fail;
1629 *pnamespace = namespace;
1630 *pdomain = domain;
1631 *puser = user;
1632 return true;
1633 fail:
1634 TALLOC_FREE(user);
1635 TALLOC_FREE(domain);
1636 TALLOC_FREE(namespace);
1637 return false;
1640 bool canonicalize_username(TALLOC_CTX *mem_ctx,
1641 char **pusername_inout,
1642 char **pnamespace,
1643 char **pdomain,
1644 char **puser)
1646 bool ok;
1647 char *namespace = NULL;
1648 char *domain = NULL;
1649 char *user = NULL;
1650 char *username_inout = NULL;
1652 ok = parse_domain_user(mem_ctx,
1653 *pusername_inout,
1654 &namespace, &domain, &user);
1656 if (!ok) {
1657 return False;
1660 username_inout = talloc_asprintf(mem_ctx, "%s%c%s",
1661 domain, *lp_winbind_separator(),
1662 user);
1664 if (username_inout == NULL) {
1665 goto fail;
1668 *pnamespace = namespace;
1669 *puser = user;
1670 *pdomain = domain;
1671 *pusername_inout = username_inout;
1672 return True;
1673 fail:
1674 TALLOC_FREE(username_inout);
1675 TALLOC_FREE(namespace);
1676 TALLOC_FREE(domain);
1677 TALLOC_FREE(user);
1678 return false;
1682 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1683 'winbind separator' options.
1684 This means:
1685 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1686 lp_workgroup()
1688 If we are a PDC or BDC, and this is for our domain, do likewise.
1690 On an AD DC we always fill DOMAIN\\USERNAME.
1692 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1695 * talloc version of fill_domain_username()
1696 * return NULL on talloc failure.
1698 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1699 const char *domain,
1700 const char *user,
1701 bool can_assume)
1703 char *tmp_user, *name;
1705 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1706 can_assume = false;
1709 if (user == NULL) {
1710 return NULL;
1713 tmp_user = talloc_strdup(mem_ctx, user);
1714 if (tmp_user == NULL) {
1715 return NULL;
1717 if (!strlower_m(tmp_user)) {
1718 TALLOC_FREE(tmp_user);
1719 return NULL;
1722 if (can_assume && assume_domain(domain)) {
1723 name = tmp_user;
1724 } else {
1725 name = talloc_asprintf(mem_ctx, "%s%c%s",
1726 domain,
1727 *lp_winbind_separator(),
1728 tmp_user);
1729 TALLOC_FREE(tmp_user);
1732 return name;
1736 * Client list accessor functions
1739 static struct winbindd_cli_state *_client_list;
1740 static int _num_clients;
1742 /* Return list of all connected clients */
1744 struct winbindd_cli_state *winbindd_client_list(void)
1746 return _client_list;
1749 /* Return list-tail of all connected clients */
1751 struct winbindd_cli_state *winbindd_client_list_tail(void)
1753 return DLIST_TAIL(_client_list);
1756 /* Return previous (read:newer) client in list */
1758 struct winbindd_cli_state *
1759 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1761 return DLIST_PREV(cli);
1764 /* Add a connection to the list */
1766 void winbindd_add_client(struct winbindd_cli_state *cli)
1768 cli->last_access = time(NULL);
1769 DLIST_ADD(_client_list, cli);
1770 _num_clients++;
1773 /* Remove a client from the list */
1775 void winbindd_remove_client(struct winbindd_cli_state *cli)
1777 DLIST_REMOVE(_client_list, cli);
1778 _num_clients--;
1781 /* Move a client to head or list */
1783 void winbindd_promote_client(struct winbindd_cli_state *cli)
1785 cli->last_access = time(NULL);
1786 DLIST_PROMOTE(_client_list, cli);
1789 /* Return number of open clients */
1791 int winbindd_num_clients(void)
1793 return _num_clients;
1796 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1797 const struct dom_sid *user_sid,
1798 uint32_t *p_num_groups, struct dom_sid **user_sids)
1800 struct netr_SamInfo3 *info3 = NULL;
1801 NTSTATUS status = NT_STATUS_NO_MEMORY;
1802 uint32_t num_groups = 0;
1804 DEBUG(3,(": lookup_usergroups_cached\n"));
1806 *user_sids = NULL;
1807 *p_num_groups = 0;
1809 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1811 if (info3 == NULL) {
1812 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1816 * Before bug #7843 the "Domain Local" groups were added with a
1817 * lookupuseraliases call, but this isn't done anymore for our domain
1818 * so we need to resolve resource groups here.
1820 * When to use Resource Groups:
1821 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1823 status = sid_array_from_info3(mem_ctx, info3,
1824 user_sids,
1825 &num_groups,
1826 false);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 TALLOC_FREE(info3);
1830 return status;
1833 TALLOC_FREE(info3);
1834 *p_num_groups = num_groups;
1835 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1837 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1839 return status;
1842 /*********************************************************************
1843 We use this to remove spaces from user and group names
1844 ********************************************************************/
1846 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1847 const char *domain_name,
1848 const char *name,
1849 char **normalized)
1851 struct winbindd_domain *domain = NULL;
1852 NTSTATUS nt_status;
1854 if (!name || !normalized) {
1855 return NT_STATUS_INVALID_PARAMETER;
1858 if (!lp_winbind_normalize_names()) {
1859 return NT_STATUS_PROCEDURE_NOT_FOUND;
1862 domain = find_domain_from_name_noinit(domain_name);
1863 if (domain == NULL) {
1864 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1865 return NT_STATUS_NO_SUCH_DOMAIN;
1868 /* Alias support and whitespace replacement are mutually
1869 exclusive */
1871 nt_status = resolve_username_to_alias(mem_ctx, domain,
1872 name, normalized );
1873 if (NT_STATUS_IS_OK(nt_status)) {
1874 /* special return code to let the caller know we
1875 mapped to an alias */
1876 return NT_STATUS_FILE_RENAMED;
1879 /* check for an unreachable domain */
1881 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1882 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1883 domain->name));
1884 set_domain_offline(domain);
1885 return nt_status;
1888 /* deal with whitespace */
1890 *normalized = talloc_strdup(mem_ctx, name);
1891 if (!(*normalized)) {
1892 return NT_STATUS_NO_MEMORY;
1895 all_string_sub( *normalized, " ", "_", 0 );
1897 return NT_STATUS_OK;
1900 /*********************************************************************
1901 We use this to do the inverse of normalize_name_map()
1902 ********************************************************************/
1904 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1905 const char *name,
1906 char **normalized)
1908 NTSTATUS nt_status;
1909 struct winbindd_domain *domain = find_our_domain();
1911 if (!name || !normalized) {
1912 return NT_STATUS_INVALID_PARAMETER;
1915 if (!lp_winbind_normalize_names()) {
1916 return NT_STATUS_PROCEDURE_NOT_FOUND;
1919 /* Alias support and whitespace replacement are mutally
1920 exclusive */
1922 /* When mapping from an alias to a username, we don't know the
1923 domain. But we only need a domain structure to cache
1924 a successful lookup , so just our own domain structure for
1925 the seqnum. */
1927 nt_status = resolve_alias_to_username(mem_ctx, domain,
1928 name, normalized);
1929 if (NT_STATUS_IS_OK(nt_status)) {
1930 /* Special return code to let the caller know we mapped
1931 from an alias */
1932 return NT_STATUS_FILE_RENAMED;
1935 /* check for an unreachable domain */
1937 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1938 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1939 domain->name));
1940 set_domain_offline(domain);
1941 return nt_status;
1944 /* deal with whitespace */
1946 *normalized = talloc_strdup(mem_ctx, name);
1947 if (!(*normalized)) {
1948 return NT_STATUS_NO_MEMORY;
1951 all_string_sub(*normalized, "_", " ", 0);
1953 return NT_STATUS_OK;
1956 /*********************************************************************
1957 ********************************************************************/
1959 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1961 struct winbindd_tdc_domain *tdc = NULL;
1962 TALLOC_CTX *frame = talloc_stackframe();
1963 bool ret = false;
1965 /* We can contact the domain if it is our primary domain */
1967 if (domain->primary) {
1968 ret = true;
1969 goto done;
1972 /* Trust the TDC cache and not the winbindd_domain flags */
1974 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1975 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1976 domain->name));
1977 ret = false;
1978 goto done;
1981 /* Can always contact a domain that is in out forest */
1983 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1984 ret = true;
1985 goto done;
1989 * On a _member_ server, we cannot contact the domain if it
1990 * is running AD and we have no inbound trust.
1993 if (!IS_DC &&
1994 domain->active_directory &&
1995 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1997 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1998 "and we have no inbound trust.\n", domain->name));
1999 goto done;
2002 /* Assume everything else is ok (probably not true but what
2003 can you do?) */
2005 ret = true;
2007 done:
2008 talloc_destroy(frame);
2010 return ret;
2013 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
2015 /*********************************************************************
2016 ********************************************************************/
2018 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
2020 char *var = NULL;
2021 char addr[INET6_ADDRSTRLEN];
2022 const char *kdc = NULL;
2023 int lvl = 11;
2025 if (!domain || !domain->alt_name || !*domain->alt_name) {
2026 return;
2029 if (domain->initialized && !domain->active_directory) {
2030 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2031 domain->alt_name));
2032 return;
2035 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2036 kdc = addr;
2037 if (!*kdc) {
2038 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2039 domain->alt_name));
2040 kdc = domain->dcname;
2043 if (!kdc || !*kdc) {
2044 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2045 domain->alt_name));
2046 return;
2049 var = talloc_asprintf_strupper_m(
2050 talloc_tos(),
2051 "%s_%s",
2052 WINBINDD_LOCATOR_KDC_ADDRESS,
2053 domain->alt_name);
2054 if (var == NULL) {
2055 return;
2058 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2059 var, kdc));
2061 setenv(var, kdc, 1);
2062 TALLOC_FREE(var);
2065 /*********************************************************************
2066 ********************************************************************/
2068 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2070 struct winbindd_domain *our_dom = find_our_domain();
2072 winbindd_set_locator_kdc_env(domain);
2074 if (domain != our_dom) {
2075 winbindd_set_locator_kdc_env(our_dom);
2079 /*********************************************************************
2080 ********************************************************************/
2082 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2084 char *var = NULL;
2086 if (!domain || !domain->alt_name || !*domain->alt_name) {
2087 return;
2090 var = talloc_asprintf_strupper_m(
2091 talloc_tos(),
2092 "%s_%s",
2093 WINBINDD_LOCATOR_KDC_ADDRESS,
2094 domain->alt_name);
2095 if (var == NULL) {
2096 return;
2099 unsetenv(var);
2100 TALLOC_FREE(var);
2102 #else
2104 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2106 return;
2109 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2111 return;
2114 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2116 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2119 * Make sure we start with authoritative=true,
2120 * it will only set to false if we don't know the
2121 * domain.
2123 resp->data.auth.authoritative = true;
2125 resp->data.auth.nt_status = NT_STATUS_V(result);
2126 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2128 /* we might have given a more useful error above */
2129 if (*resp->data.auth.error_string == '\0')
2130 fstrcpy(resp->data.auth.error_string,
2131 get_friendly_nt_error_msg(result));
2132 resp->data.auth.pam_error = nt_status_to_pam(result);
2135 bool is_domain_offline(const struct winbindd_domain *domain)
2137 if (get_global_winbindd_state_offline()) {
2138 return true;
2140 return !domain->online;
2143 bool is_domain_online(const struct winbindd_domain *domain)
2145 return !is_domain_offline(domain);
2149 * Parse an char array into a list of sids.
2151 * The input sidstr should consist of 0-terminated strings
2152 * representing sids, separated by newline characters '\n'.
2153 * The list is terminated by an empty string, i.e.
2154 * character '\0' directly following a character '\n'
2155 * (or '\0' right at the start of sidstr).
2157 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2158 struct dom_sid **sids, uint32_t *num_sids)
2160 const char *p;
2162 p = sidstr;
2163 if (p == NULL)
2164 return False;
2166 while (p[0] != '\0') {
2167 struct dom_sid sid;
2168 const char *q = NULL;
2170 if (!dom_sid_parse_endp(p, &sid, &q)) {
2171 DEBUG(1, ("Could not parse sid %s\n", p));
2172 return false;
2174 if (q[0] != '\n') {
2175 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2176 return false;
2178 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2179 num_sids)))
2181 return False;
2183 p = q+1;
2185 return True;
2188 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2189 struct unixid **pxids, uint32_t *pnum_xids)
2191 const char *p;
2192 struct unixid *xids = NULL;
2193 uint32_t num_xids = 0;
2195 p = xidstr;
2196 if (p == NULL) {
2197 return false;
2200 while (p[0] != '\0') {
2201 struct unixid *tmp;
2202 struct unixid xid;
2203 unsigned long long id;
2204 char *endp;
2205 int error = 0;
2207 switch (p[0]) {
2208 case 'U':
2209 xid = (struct unixid) { .type = ID_TYPE_UID };
2210 break;
2211 case 'G':
2212 xid = (struct unixid) { .type = ID_TYPE_GID };
2213 break;
2214 default:
2215 return false;
2218 p += 1;
2220 id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
2221 if (error != 0) {
2222 goto fail;
2224 if (*endp != '\n') {
2225 goto fail;
2227 p = endp+1;
2229 xid.id = id;
2230 if ((unsigned long long)xid.id != id) {
2231 goto fail;
2234 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2235 if (tmp == NULL) {
2236 return 0;
2238 xids = tmp;
2240 xids[num_xids] = xid;
2241 num_xids += 1;
2244 *pxids = xids;
2245 *pnum_xids = num_xids;
2246 return true;
2248 fail:
2249 TALLOC_FREE(xids);
2250 return false;